首先像下面这样读入数据
\\spambase.data中包含实际数据,spambase.names中包含变量的信息
> spambase <- read.csv("spambase.data",header=F)
由于该数据文件中不包含变量信息,因此令header=F,使第1行不为变量名。像下面通过read.table()函数读入数据,并通过colnames()函数指定数据框spambase的变量名。
> colnames(spambase) <- read.table("spambase.names",skip=33,
+ sep=":",comment.char=" ")[,1]
> colnames(spambase)[ncol(spambase)] <- "spam"
先来考虑用一个解释变量预测目标变量的情形。解释变量设为word_freq_your,目标变量spam。首先我们观察word_freq_your和spam的散点图。
> library(ggplot2)
> qplot(word_freq_your,spam,data=spambase,alpha=I(0.03))
alpha参数设置了透明度,点较多的地方显示较浓,可以看到word_freq_your的值较大,则越容易判定为垃圾邮件。根据垃圾邮件判定的真伪,向下面这样输出中位数、平均值、标准差。
> library(dplyr)
> spambase %>%
> group_by(spam) %>%
> summarise(count=n(),
+ med=median(word_freq_your),
+ mean=mean(word_freq_your),
+ sd=sd(word_freq_your))
然后用一元回归模型套用到该模型上:
> spam.your.lm <- lm(spam~word_freq_your,data=spambase)
> summary(spam.your.lm)
> qplot(word_freq_your,spam,data=spambase,alpha=I(0.03))+
+ geom_smooth(method="lm")
目标变量取值只能为0或1,以该回归直线为模型的话,对于较大的word_freq_your的值,会得到比1大的预测值。对于某些数据,有时会得到负的预测值。为了发生这种情况,我们利用Logistic函数取代y=ax+b。该模型被称为广义线性模型(GLM)的统计模型,通过执行glm()函数,可以推导出该模型的参数。
> spam.your.lst <- glm(spam~word_freq_your,
+ data=spambase,family="binomial")
> spam.your.lst
\\可以推出模型的表达式。
用散点图表示上述模型:
> a <-coef(spam.your.lst)[2]
> b <-coef(spam.your.lst)[1]
> lst.fun <- function(x){
+ 1/(1+exp(-(a*x+b)))
+ }
> qplot(word_freq_your,spam,data=spambase,
+ alpha=I(0.03),xlim=c(-5,15)) +
+ stat_function(fun=lst.fun,geom="line")
接着可以使用predict()函数和residuals()函数分别计算使用了该模型的预测值和残差。由于预测值在0和1之间,因此这里根据预测值为0.5及以上判定为垃圾邮件的规则,来看看预测有多大的准确性。
> spam.your.pred <- predict(spam.your.lst,type="resp")
> (tb <- table(spam=spambase$spam,pred=round(spam.your.pred)))
\\下面结果是混淆矩阵
pred
spam 0 1
0 2478 310
1 998 815
\\由上述结果我们可以求出误分率,如下:
> 1-sum(diag(tb))/sum(tb)
[1] 0.284286
\\上述是利用一个变量来预测,可以看出误分率是很大的,并不准确。
下面我们利用几个变量进行预测。
\\首先我们使用全部变量来拟合Logistic回归模型。
> spam.glm <- glm(spam~.,data=spambase,family="binomial")
> summary(spam.glm)
\\可以看到很多效果不显著的系数。
接下来,我们执行变量选择,获取最优预测模型。
> library(MASS)
> (spam.glm.best <- stepAIC(spam.glm))
> summary(spam.glm.best)
下面我们来确认一下,和只使用word_freq_your为解释变量时相比,使用该模型后预测有了多大程度的改善。
> spam.best.pred <- predict(spam.glm.best,type="resp")
> (tb.best <- table(spam=spambase$spam,
+ pred=round(spam.best.pred)))
pred
spam FALSE TRUE
0 2669 119
1 193 1620
> 1-sum(diag(tb.best))/sum(tb.best)
[1] 0.06781135