来自 Coursera "Reproducible Research" class 的日志回归代码解释

log regression code explanation from Coursera's "Reproducible Research" class

在学习 Coursera 的 "Reproducible Research" class 时,我无法理解讲师用于对数回归的代码。

此代码使用的是来自 kernlab 库的垃圾邮件数据集的数据。此数据 class 将 4601 封电子邮件确定为垃圾邮件或非垃圾邮件。除了这个 class 标签之外,还有 57 个变量表示电子邮件中某些单词和字符的出现频率。数据已在测试数据集和训练数据集之间拆分。

此代码特别采用训练数据集 ("trainSpam")。它应该做的是遍历数据集中的每个变量,并尝试拟合一个泛化模型(在本例中为逻辑回归),以仅使用一个变量来预测电子邮件是否为垃圾邮件。

我真的不明白代码中的某些行在做什么。有人可以向我解释一下吗?谢谢。

trainSpam$numType = as.numeric(trainSpam$type) - 1 ## here a new column is just being created assigning 0 and 1 for spam and nonspam emails

costFunction = function(x,y) sum(x != (y > 0.5)) ## I understand a function is being created but I really don't understand what the function "costFunction" is supposed to do. I could really use and explanation for this

cvError = rep(NA,55)
library(boot)
for (i in 1:55){
    lmFormula = reformulate(names(trainSpam)[i], response = "numType") ## I really don't understand this line of code either

    glmFit = glm(lmFormula, family = "binomial", data = trainSpam)

    cvError[i] = cv.glm(trainSpam, glmFit, costFunction, 2)$delta[2]
}
names(trainSpam)[which.min(cvError)]

在 7:13 讲座中,数据分析的结构第 2 部分,彭教授解释说他将遍历[中的所有自变量=12=] 数据集来自 kernlab 包。然后,他运行一组线性模型,以查看在预测数据集中的特定电子邮件是否为垃圾邮件时哪个变量具有最低的交叉验证错误率。

costFunction() 函数用于 cv.glm() 以将 numType 的实际值与预测值进行比较。它对实际值不等于 predicted > 0.5 的逻辑比较结果的计数求和。

lmformula = reformulate(...) 行创建了一个线性模型公式,该公式随 for() 循环的每次迭代而变化,将因变量设置为 numType

for() 循环的输出是一个计数向量,其中每个 glm()numType 的实际值与垃圾邮件与非垃圾邮件的实际分类不匹配。最后一行代码 names(trainSpam)[which.min(cvError)] 计算进入 cvError 向量的索引具有最低值,并使用它从 trainSpam 数据框中提取自变量名称。

这个例子的完整代码是:

library(kernlab)

data(spam)
set.seed(3435)
trainIndicator = rbinom(4601,size=1,prob=0.5)
table(trainIndicator)
trainSpam = spam[trainIndicator==1,]
testSpam = spam[trainIndicator==0,]

trainSpam$numType = as.numeric(trainSpam$type)-1
costFunction = function(x,y) sum(x!=(y > 0.5)) 
cvError = rep(NA,55)
library(boot)
for(i in 1:55){
     lmFormula = reformulate(names(trainSpam)[i], response = "numType")
     glmFit = glm(lmFormula,family="binomial",data=trainSpam)
     cvError[i] = cv.glm(trainSpam,glmFit,costFunction,2)$delta[2]
}

## Which predictor has minimum cross-validated error?
names(trainSpam)[which.min(cvError)]

...输出:

> names(trainSpam)[which.min(cvError)]
[1] "charDollar"
>

...意味着在测试数据集中预测垃圾邮件时,电子邮件中美元符号的数量是具有最低交叉验证错误率的自变量。

解释如下。我花了大约 2-3 小时来包装 整件事都在我脑海里,但这是我的解释。

目标

目标:找到一个"simple model"(二项回归) "error" (交叉验证错误),当我们使用 "simple model" 进行预测时。

数据集我们只使用trainSpam数据集来制作 预测模型。每个单元格都有代表的数值 给定电子邮件(行)出现的单词(按列给出)。为了 例如,charDollar 列的第 2 行的 a 为 0.054。这表示 第二封邮件在邮件中有 0.054 $ 个符号。

数据本质上是二项式的,即 0 表示非垃圾邮件,1 表示 垃圾邮件。这是用以下数字制成的:

trainSpam$numType = as.numeric(trainSpam$type)-1

曲线拟合

二项式回归 由于数据是二项式的,我们拟合一条曲线, ~~二项式回归~~预测邮件的概率 垃圾邮件取决于 Value 。例如,查看列 charDollar

png(filename="glm.png")
lmFormula=numType~charDollar
plot(lmFormula,data=trainSpam, ylab="probability")
g=glm(lmFormula,family=binomial, data=trainSpam)
curve(predict(g,data.frame(charDollar=x),type="resp"),add=TRUE)
dev.off()

在这里你看到 charDollar 值 > 0.5 几乎是 100% 它是垃圾邮件的概率。二项式回归就是这样用的。

作者查看每一列,进行二项式回归 合身。这是通过 for loop 完成的。所以作者现在有55个模型。

误差估计

作者想看看这55个模型中的哪个在预测 "BEST"。为此,我们使用交叉验证...

cv.glm 或交叉验证

交叉验证的工作原理如下:它进一步划分了 trainData 进入训练和测试。 TRAIN 数据用于计算 glm,并且 此 glm 用于预测 TEST 数据的结果。这个做完了 "in a particular way" 多次,结果取平均值。

CV 使用成本函数计算误差。

cost function(在本例中)计算失败的次数 预测。测试数据用于此。它需要两个参数 这是 X(观察到的测试数据)和 Y(基于 glm 的预测数据) 并检查在这种情况下它失败了多少次:

costFunction = function(x,y) sum(x!=(y > 0.5))

Y>0.5 提供一个截止值来决定一个值是否是垃圾邮件。因此,如果 预测值为 0.6 则预测为 SPAM(或 1)。如果 预测值为 <=0.5 那么它不是垃圾邮件(或 0)。

通过 for 循环,我们遍历每一列并在最后一张图片 预测错误最少的列:

which.min(cvError)

P.S 看看glm二项式拟合如何 (包括timestamp)就搞定了,解释了 coefficients that come from glm以及获得的意义 cross-validated error。当然,我同意但是陡峭 跳到这方面,懒得解释任何相关的东西 这,什么都没有。希望这对您有所帮助。