运用逻辑回归进行手写数字识别(基于R语言)

理论基础

手写数字识别的本质是把手写数字灰度图片的256个特征作为预测变量,利用这256个特征判断这张图片写的是什么数字,即把该图片归入0、1、2…9这总共十个类中。根据《统计学习导论》4.3.5响应分类数超过2的逻辑回归里的表述,当响应变量的水平数量大于2时,依然可以把二分类的逻辑回归推广到多分类,例如当Y可取1、2、3时,可利用概率的性质P(Y=1|X)=1-P(Y=2|X)-P(Y=3|X)算出已知预测变量X后Y=1的概率,同理也可以算出Y=2、Y=3的概率,哪个概率大就把Y归入哪类,当然也可以根据实际需要规定归类的阈值。但是书上说这种方法并不常用,所以不做过多介绍,包括此章的R语言演示中也没有涉及多分类逻辑回归的具体做法。
通过上网查询,找到一种叫oneVsAll的方法,可以通过建立多个二分类逻辑回归模型来解决多分类逻辑回归的问题。于是决定采用此法进行多分类逻辑回归建模。
具体做法:①把Y=0算作一类,Y≠0算作另一类,然后建立二分类逻辑回归模型;同理把Y=1算作一类,把Y≠1算作另一类,然后建立二分类逻辑回归模型;同理把Y=2算作一类,把Y≠2算作另一类,然后建立二分类逻辑回归模型……以此类推总共建立10个二分类逻辑回归模型。②可以根据上述模型的模型响应值依次得到P(Y=0|X)、P(Y=1|X)、P(Y=2|X)…P(Y=9|X)。③根据上一步得到的10个概率值,比较出最大的概率值,把Y归入最大概率值相应的那一类。

R语言建模实现(完整代码及注释放在附录)

以下①②③点对应上述具体步骤的①②③点。


利用fread()函数导入训练集、测试集,分别记作trainset、testset.
将训练集第一列非零数字变为0,第一列的零变为1:
在这里插入图片描述

具体效果如图:
运用逻辑回归进行手写数字识别(基于R语言)_第1张图片

由此可见一个多分类问题的数据集被转换成了二分类问题的数据集,所以可用glm函数进行二分类逻辑回归建模,把模型记作glm.fit0:
在这里插入图片描述

依次类推建立glm.fit1到glm.fit9


利用这十个模型依次算出P(Y=0|X)到P(Y=9|X):
运用逻辑回归进行手写数字识别(基于R语言)_第2张图片


用cbind函数把P(Y=0|X)到P(Y=9|X)按列组合成一个概率矩阵,记作glm.probs:
运用逻辑回归进行手写数字识别(基于R语言)_第3张图片

从图中显然看出,按照归类到最大概率的类的原则,第一个图片应该识别为6,第二个图片应该识别为5,第三个图片应该识别为4,这可以利用apply函数实现:
可以得到训练集的预测结果:
在这里插入图片描述
运用逻辑回归进行手写数字识别(基于R语言)_第4张图片

到此建模完成。

实验结果:

训练集结果:

运用逻辑回归进行手写数字识别(基于R语言)_第5张图片
从混淆矩阵看出,数字零的错误分类出现得最多,这是算法的一个优化方向。
正确率高达95%,说明该模型在训练集的表现很好,但是训练集的正确率太高可能会出现过拟合。

测试集结果:

运用逻辑回归进行手写数字识别(基于R语言)_第6张图片

从混淆矩阵看,与训练集显示的情况一样,数字零的错分情况总是发生。
正确率为82%,说明该模型在训练集上的表现也比较好,没有出现过拟合的情况。

R代码

trainset<-fread("C:\\Users\\39291\\Desktop\\data_mining-master\\training.csv",data.table = FALSE)#载入数据
testset<-fread("C:\\Users\\39291\\Desktop\\data_mining-master\\test.csv",data.table = FALSE)#载入数据


train.num0<-trainset$V1
train.num0[train.num0==0]<-10
train.num0[train.num0<10]<-0#将Y≠0作为一类,记作0
train.num0[train.num0==10]<-1#将Y=0作为另一类,记作1
train.factor0<-as.factor(train.num0)#将数值型对象转成因子型对象
dataframe0<-cbind(train.factor0,trainset[,-1])#得到可用于二分类的数据集dataframe0
glm.fit0<-glm(formula = dataframe0$train.factor0~.,family=binomial,data=dataframe0,control=list(maxit=100))#建立二分类逻辑回归模型glm.fit0
#运用同样的方法继续建立glm.fit1到glm.fit9
train.num1<-trainset$V1
train.num1[train.num1==1]<-10
train.num1[train.num1<10]<-0
train.num1[train.num1==10]

你可能感兴趣的:(机器学习,人工智能,数据挖掘,算法,r语言)