【导入库和数据集】
和线性回归一样,首先导入所需要用到的库和数据集。
导入库:
##用于可视化图表
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,因此导致模型判断为
9≥5
9
≥
5
,所以预测值输出为1。而第6个的7比较像1,因此导致模型判断为
1≤4
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个样本预测错误,
1−12180≈0.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个,
1−8180≈0.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