【机器学习实战】逻辑回归----digits手写数字分类

【导入库和数据集】

和线性回归一样,首先导入所需要用到的库和数据集。
导入库:

##用于可视化图表
import matplotlib.pyplot as plt
##用于做科学计算
import numpy as np
##用于做数据分析
import pandas as pd
##用于加载数据或生成数据等
from sklearn import datasets
##加载线性模型
from sklearn import linear_model
###用于交叉验证以及训练集和测试集的划分
from sklearn.cross_validation import train_test_split
from sklearn.model_selection import cross_val_predict
#from sklearn.cross_validation import cross_val_score
###这个模块中含有评分函数,性能度量,距离计算等
from sklearn import metrics
###用于做数据预处理
from sklearn import preprocessing

数据集:
这次数据集还是选用sklearn中提供的小数据集——digits手写字体数据集。先看一下官方介绍:
这里写图片描述
通过官方的数据集介绍我们可以知道,这个digits手写数据集其实是1797组8*8的手写数字图像的像素点集合。有10个分类,代表了“0,1,2,…,9”这是个数字。特征维度为64,对应了每组数据的8*8个像素点。大概知道了这些,我们可以具体查看一下。

digits = datasets.load_digits()#导入digits数据集
print(digits.keys())#查看digits中有哪些属性
输出为:dict_keys(['images', 'target_names', 'DESCR', 'data', 'target'])
(1797, 64)
[0 1 2 3 4 5 6 7 8 9]
0
[[  0.   0.   5.  13.   9.   1.   0.   0.]
 [  0.   0.  13.  15.  10.  15.   5.   0.]
 [  0.   3.  15.   2.   0.  11.   8.   0.]
 [  0.   4.  12.   0.   0.   8.   8.   0.]
 [  0.   5.   8.   0.   0.   9.   8.   0.]
 [  0.   4.  11.   0.   1.  12.   7.   0.]
 [  0.   2.  14.   5.  10.  12.   0.   0.]
 [  0.   0.   6.  13.  10.   0.   0.   0.]]
1
[[  0.   0.   0.  12.  13.   5.   0.   0.]
 [  0.   0.   0.  11.  16.   9.   0.   0.]
 [  0.   0.   3.  15.  16.   6.   0.   0.]
 [  0.   7.  15.  16.  16.   2.   0.   0.]
 [  0.   0.   1.  16.  16.   3.   0.   0.]
 [  0.   0.   1.  16.  16.   6.   0.   0.]
 [  0.   0.   1.  16.  16.   6.   0.   0.]
 [  0.   0.   0.  11.  16.  10.   0.   0.]]

digits数据集中有1797个数据,分类标签为0~9,打印第一和第二个图像的标签和数据看看,可以发现每一个像素点在0~16之间。不过这个看起来感觉不够直观,可以画图来看。

plt.gray()
for i in range(0,2):
    plt.matshow(digits.images[i])
    plt.show()
    print(digits.target[i])

输出为:
这里写图片描述

大概能看出数字的样子。我们可以将这些图像和它的标签打印到一起来看。

fig=plt.figure(figsize=(8,8))
fig.subplots_adjust(left=0,right=1,bottom=0,top=1,hspace=0.05,wspace=0.05)
for i in range(30):
    ax=fig.add_subplot(6,5,i+1,xticks=[],yticks=[])
    ax.imshow(digits.images[i],cmap=plt.cm.binary,interpolation='nearest')
    ax.text(0,7,str(digits.target[i]))
plt.show()

输出为:
这里写图片描述

【二分类问题】

从上面对数据集的分析,我们知道digits数据集有10个分类,我们将0~4当做一类,5~9当做另一类,问题就变为了二分类问题。
导入数据:
获得数据集的输入和输出,并且划分训练集和测试集。

digits_X = digits.data   ##获得数据集中的输入
digits_y = digits.target ##获得数据集中的输出,即标签(也就是类别)
### test_size:测试数据大小
X_train,X_test,y_train,y_test = train_test_split(digits_X, digits_y, test_size = 0.1)
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
##输出为:
(1617, 64)
(180, 64)
(1617,)
(180,)

训练集有1617个样本,测试集有180个样本。

由于digits数据集的输入数据在不同维度上的特征的尺度(单位)不一致,需要标准化步骤对数据进行预处理(针对的是每一个特征上的数据)。我们看看经过预处理后的数据变成了什么样。

digits_X = digits.data   ##获得数据集中的输入
digits_y = digits.target ##获得数据集中的输出,即标签(也就是类别)
### test_size:测试数据大小
X_train,X_test,y_train,y_test = train_test_split(digits_X, digits_y, test_size = 0.1)
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
plt.gray()
plt.matshow(np.abs(X_train[0].reshape(8, 8)))
plt.show()
X_train=preprocessing.StandardScaler().fit_transform(X_train)

plt.gray()
plt.matshow(np.abs(X_train[0].reshape(8, 8)))
plt.show()

print(X_train[0])
print("第一个特征的均值为",X_train[0].mean())
print("第一个特征的方差为",X_train[0].var()) 

输出为:
这里写图片描述

[ 0.         -0.33114795 -1.08393502 -1.60706168  0.96486852  0.57531019
 -0.40894927 -0.11573126 -0.05788529 -0.61731417 -1.71250427  0.25255752
  1.19287415 -0.34182745 -0.51285157 -0.12578097 -0.04311306 -0.72760443
  0.55376957  1.52982569  1.43339513 -0.60237557 -0.54488676 -0.11662057
 -0.02487593  0.80537163  0.94404281  1.23094941  0.9929394  -0.42889005
 -0.63114251 -0.0497981   0.         -0.67552341 -1.22434888  0.14582454
  0.96358366 -0.3042967  -0.82781514  0.         -0.06468145 -0.53108301
 -1.06144103  0.26953149  1.32170303 -0.04757315 -0.8012934  -0.09359159
 -0.03735601 -0.40118922 -1.33164946 -0.1055701   1.23816962  0.69686567
 -0.75764252 -0.22004476 -0.02487593 -0.29910251 -1.08083868 -1.61483653
  0.44573836  0.38372346 -0.50824622 -0.19897474]
第一个特征的均值为 -0.0993004141872
第一个特征的方差为 0.579330788574

上图第一个是未经过标准化时的图形,第二个是标准化后的图形。

由于我们这里是要实现二分类问题。因此将标签从0~9的十分类变为0或1的二分类。

print(y_train[0:20])
y_train = (y_train > 4).astype(np.int)
print(y_train[0:20])
###输出为:
[1 0 1 3 8 8 0 3 4 1 9 1 9 7 9 4 3 8 0 5]
[0 0 0 0 1 1 0 0 0 0 1 0 1 1 1 0 0 1 0 1]

上面是没有变换时十分类的,下面是变换后二分类的,我们将小于等于4的类别作为0类,大于等于5的类别作为1类。

加载模型并训练:

##加载逻辑回归模型并使用L1正则化,正则化参数C选0.5
model_LR_l1=linear_model.LogisticRegression(C=0.5, penalty='l1', tol=0.01)
##将训练数据传入开始训练
model_LR_l1.fit(X_train,y_train)
##准备测试数据
X_test_scale=preprocessing.StandardScaler().fit_transform(X_test)
y_test_trans = (y_test>4).astype(np.int)
##将测试数据传入训练好的模型,进行评分
print(model_LR_l1.score(X_test_scale,y_test_trans))
##将测试集的输入数据传入训练好的模型,得到预测值。
y_pred = model_LR_l1.predict(X_test_scale)

评分为:0.933333333333

图形显示:
我们可以看看测试集中这180个样本的预测情况(以前30个为例)

fig1=plt.figure(figsize=(8,8))
fig1.subplots_adjust(left=0,right=1,bottom=0,top=1,hspace=0.05,wspace=0.05)
for i in range(30):
    ax=fig1.add_subplot(6,5,i+1,xticks=[],yticks=[])
    ax.imshow(np.abs(X_test[i].reshape(8, 8)),cmap=plt.cm.binary,interpolation='nearest')
    ax.text(0,1,str(y_test[i]))
    ax.text(0,7,str(y_pred[i]))
plt.show()

上面为真实标签(是未变为二分类的标签,即十分类的标签),下面为预测值(已变为二分类标签,0代表真实标签小于等于4,1代表真实标签大于等于5)
这里写图片描述
我们可以发现第5个,第6个,第26个的预测错误,根据我的想法,应该是第5个和第26个的4比较像9,因此导致模型判断为 95 9 ≥ 5 ,所以预测值输出为1。而第6个的7比较像1,因此导致模型判断为 14 1 ≤ 4 ,所以预测值输出为0。

让我们来看看一共有多少个样本是判断错误的。

fig2=plt.figure(figsize=(8,8))
fig2.subplots_adjust(left=0,right=1,bottom=0,top=1,hspace=0.05,wspace=0.05)
num=0
for i in range(180):
    if(y_test_trans[i]!=y_pred[i]):
        num=num+1
        ax=fig2.add_subplot(12,5,num,xticks=[],yticks=[])
        ax.imshow(np.abs(X_test[i].reshape(8, 8)),cmap=plt.cm.binary,interpolation='nearest')
        ax.text(0,1,str(y_test[i]))
        ax.text(0,7,str(y_pred[i]))
plt.show()
print(num)

这里写图片描述
一共有12个样本预测错误, 1121800.9333 1 − 12 180 ≈ 0.9333

【多分类】

多分类可以选择“ovr”或者“multinomial”(即mvm)
使用OvR方法:

##加载逻辑回归模型,选择随机平均梯度下降,最大迭代次数选择5000
model_LR_mult=linear_model.LogisticRegression(solver='sag',max_iter=5000,random_state=42,multi_class='ovr')
##将训练数据传入开始训练
model_LR_mult.fit(X_train,y_train)

这里max_iter选择小了可能会出现下面这样的情况
这里写图片描述

X_test_scale=preprocessing.StandardScaler().fit_transform(X_test)
print(model_LR_mult.score(X_test_scale,y_test))
y_pred = model_LR_mult.predict(X_test_scale)
输出为:0.955555555556

用图像来看看预测情况,上面数字为真实标签,下面数字为预测值。
这里写图片描述

找出测试集中预测错误的样本:
这里写图片描述
一共有8个, 181800.95556 1 − 8 180 ≈ 0.95556

使用MvM方法:
和上面的代码没什么区别,只是multi_class参数选择multinomial。

##加载逻辑回归模型,选择随机平均梯度下降,多分类方法用many vs many
model_LR_mult=linear_model.LogisticRegression(solver='sag',max_iter=5000,random_state=42,multi_class='multinomial')
##将训练数据传入开始训练
model_LR_mult.fit(X_train,y_train)
X_test_scale=preprocessing.StandardScaler().fit_transform(X_test)
print(model_LR_mult.score(X_test_scale,y_test))
y_pred = model_LR_mult.predict(X_test_scale)
##显示前30个样本的真实标签和预测值,用图显示
fig5=plt.figure(figsize=(8,8))
fig5.subplots_adjust(left=0,right=1,bottom=0,top=1,hspace=0.05,wspace=0.05)
for i in range(30):
    ax=fig5.add_subplot(6,5,i+1,xticks=[],yticks=[])
    ax.imshow(np.abs(X_test[i].reshape(8, 8)),cmap=plt.cm.binary,interpolation='nearest')
    ax.text(0,1,str(y_test[i]))
    ax.text(0,7,str(y_pred[i]))
plt.show()
fig6=plt.figure(figsize=(8,8))
fig6.subplots_adjust(left=0,right=1,bottom=0,top=1,hspace=0.05,wspace=0.05)
##找出分类错误的样本,用图显示
num=0
for i in range(180):
    if(y_test[i]!=y_pred[i]):
        num=num+1
        ax=fig6.add_subplot(6,5,num,xticks=[],yticks=[])
        ax.imshow(np.abs(X_test[i].reshape(8, 8)),cmap=plt.cm.binary,interpolation='nearest')
        #用目标值标记图像
        ax.text(0,1,str(y_test[i]))
        ax.text(0,7,str(y_pred[i]))
plt.show()
print(num)

参考:
http://scikit-learn.org/stable/auto_examples/linear_model/plot_logistic_l1_l2_sparsity.html#sphx-glr-auto-examples-linear-model-plot-logistic-l1-l2-sparsity-py
http://scikit-learn.org/stable/auto_examples/linear_model/plot_logistic_multinomial.html#sphx-glr-auto-examples-linear-model-plot-logistic-multinomial-py

代码保存于:
https://github.com/htshinichi/ML_practice

  • 8
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值