在参加Coursera的“可重复研究”课程时,我无法理解教师用于对数回归的代码。
此代码使用kernlab库的垃圾数据集中的数据。此数据将4601封电子邮件归类为垃圾邮件或非垃圾邮件。除了这个类标签外,还有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)]
答案 0 :(得分:1)
解释如下。我花了大约2-3个小时才包好 整个事情围绕着我的头,但我的解释就在这里。
目标:找到一个“简单模型” (二项式回归)
当我们使用“简单模型”进行预测时,“错误” (交叉验证错误)。
数据集,我们仅使用trainSpam
数据集来设置
预测模型。每个单元格的数值代表
给定电子邮件(行)的单词(按列给出)的出现。对于
例如,charDollar
列的第2行的a为0.054。这表示
该第二封邮件在邮件中具有0.054 $
个符号。
数据本质上是二项式的,即非垃圾邮件为0,非垃圾邮件为1 垃圾邮件。通过以下方式将其数字化:
trainSpam$numType = as.numeric(trainSpam$type)-1
二项式回归由于数据为二项式,因此我们拟合了一条曲线,
~~二项回归~~预测邮件出现的可能性
垃圾邮件取决于值。例如,查看列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个模型中的哪个正在预测 “最好”。为此,我们使用交叉验证...
cv.glm或CrossValidation
交叉验证的工作原理如下:进一步划分trainData 进入训练和测试。 TRAIN数据用于计算glm,并且 此glm用于预测TEST数据的结果。这个做完了 多次“ in a particular way”,并将结果平均。
简历使用成本函数来计算错误。
cost function
(在这种情况下)计算失败次数
预测。 TEST数据用于此目的。它需要两个参数
这是X(观察到的TEST数据)和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)
PS 非常有益的是查看glm binomial fitting
(including timestamp)的完成方式以及对
coefficients that come from glm
以及获得的含义
cross-validated error。当然,我同意这是一个艰难的过程
在这方面跳转,而不必费心解释任何与
这个,曾经如此。希望这会有所帮助。
答案 1 :(得分:0)
在演讲的7:13,数据分析第2部分的结构,彭教授解释说他将循环遍历spam
数据集中的所有自变量。 kernlab
包。然后,他在预测数据集中的特定电子邮件是否为垃圾邮件时运行一组线性模型,以查看哪个变量具有最低的交叉验证错误率。
在costFunction()
中使用cv.glm()
函数将numType
的实际值与预测值进行比较。它将实际值不等于predicted
&gt;的逻辑比较结果的计数求和。 0.5。
lmformula = reformulate(...)
行创建一个线性模型公式,该公式随for()
循环的每次迭代而变化,将因变量设置为numType
。
for()
循环的输出是一个计数向量,其中每个numType
的{{1}}的实际值与垃圾邮件与垃圾邮件的实际分类不匹配。最后一行代码glm()
计算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)]
...意味着电子邮件中的美元符号数是在预测测试数据集中的垃圾邮件时具有最低交叉验证错误率的自变量。