scikit-learn 介绍
以手写数字识别为例机器学习任务的步骤要经过以下步骤:
1.数据的采集和标记
如果我们从头训练一个数字手写识别的程序,需要先采集数据,即让尽量多不同书写习惯的用户,写出0~9的所有数字,然后把用户写出来的数据进行标记。
在scikit-learn 中自带一些训练数据,其中一个就是熟悉数字识别的数据,可以用以下代码来加载数据。
from sklearn import datasets
digits = datasets.load_digits() # 加载数据
可以在Jupiter notebook中将图片用mathplotlib现实出来
# 把数据所代表的图片显示出来
images_and_labels = list(zip(digits.images, digits.target)) # zip把图片和类型组成一个元祖(digits.images,digits.target)
plt.figure(figsize=(8, 6), dpi=50)
for index, (image, label) in enumerate(images_and_labels[:8]):
plt.subplot(2, 4, index + 1) # 将画布分成两行四列第几个子图
plt.axis('off') # 不使用坐标轴
plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest') # 用来展示2维图像,设置图片的色彩和间距
plt.title('Digit: %i' % label, fontsize=20)
2.特征选择
scikit-learn
scikit-learn 使用Numpy 的array对象来表示数据,所有的图片数据都保存在digits.images 里,每一个元素都是一个8*8尺寸的灰阶照片。在进行机器学习时,需要把数据保存为样本个数*特征个数 。
通过 digits. data.shape查看数据格式为:
print("shape of raw image data: {0}".format(digits.images.shape))
print("shape of data: {0}".format(digits.data.shape))
输出为:
shape of raw image data: (1797, 8, 8)
shape of data: (1797, 64)
一共有1797个样本,原始数据是8*8的图片,而用来训练的数据是把图片的64个像素点都转为特征。
3.数据清洗
在采集的数据时候,图片的分别率是200✖️200,那么一个样例就有200 ✖️200个特征,计算量是巨大的,为了减少计算量,也为了模型的稳定性,我们需要把200✖️200的数据缩小到8*8的图片。这个过程就是数据清洗。
4.模型选择
不同的机器学习算法对特定的机器学习应用有不同的效率,此处选择支持向量机来作为手写识别的算法的模型,
5.模型训练
在训练模型之前,需要先把数据集分为训练数据集和测试数据集。
# 把数据分成训练数据集和测试数据集
from sklearn.cross_validation import train_test_split
Xtrain, Xtest, Ytrain, Ytest = train_test_split(digits.data, digits.target, test_size=0.20, random_state=2);
接着,使用训练数据集Xtrain 和Ytrain 来训练模型。
# 使用支持向量机来训练模型
from sklearn import svm
clf = svm.SVC(gamma=0.001, C=100., probability=True)
clf.fit(Xtrain, Ytrain);
训练完成之后,clf 对象会包含我们训练出来的模型。我们可以使用这个模型对象来进行预测。
6.模型测试
测试模型的准确度的方式,直观的方法是我们用训练出来的模型clf 预测测试数据集,然后把预测结果Ypred和真正的结果Ytest比较。看有多少个是正确的,就能评估模型的准确度。
# 评估模型的准确度
from sklearn.metrics import accuracy_score
Ypred = clf.predict(Xtest);
accuracy_score(Ytest, Ypred)
输出结果为:0.97777777777777775
可以看出有97.8%的准确度
还可以把测试数据集里的部分图片显示出来,并且在图片的左下角显示预测值,右下角显示真是值。
# 查看预测的情况
fig, axes = plt.subplots(4, 4, figsize=(8, 8))
fig.subplots_adjust(hspace=0.1, wspace=0.1)
for i, ax in enumerate(axes.flat):
ax.imshow(Xtest[i].reshape(8, 8), cmap=plt.cm.gray_r, interpolation='nearest')
ax.text(0.05, 0.05, str(Ypred[i]), fontsize=32,
transform=ax.transAxes,
color='green' if Ypred[i] == Ytest[i] else 'red')
ax.text(0.8, 0.05, str(Ytest[i]), fontsize=32,
transform=ax.transAxes,
color='black')
ax.set_xticks([])
ax.set_yticks([])
7.模型的保存与加载
# 保存模型参数
from sklearn.externals import joblib
joblib.dump(clf, 'digits_svm.pkl');
当我们需要这个模型来进行预测的时候,直接加载模型即可。
# 导入模型参数,直接进行预测
clf = joblib.load('digits_svm.pkl')
Ypred = clf.predict(Xtest);
clf.score(Xtest, Ytest)
输出结果为:0.97777777777777775
scikit-learn 一般性的原理和通用规则
scikit-learn 包含大部分流行的有监督学习算法(分类和回归)和无监督学习算法(聚类和数据降维)的实现。
1.评估模型对象
sklearn 中所有的算法都是以一个评估模型对象的方式向外提供接口。创建评估对象的时,可以指定不通的参数,这个称为评估对象参数。直接影响模型训练的效率和准确性。
我们学习机器学习算法的原理,其中一项重要的任务就是了解不同的机器学习算法有哪些可调参数。
2.模型接口
sklearn 所有的评估模型对象多有fit()这个接口,这是用来训练模型的接口,针对有监督的学习算法。使用fit(x,y)来进行训练,其中y是标记数据,针对无监督学习的机器学习算法,使用fit(x)来训练,因为无监督学习的算法的数据集是没有标记的,不需要传入y.
针对所有有监督的学习算法,sklearn 的模型对象提供了predict()接口,用来输出一个带预测的数据。属于各种类型的可能行,而predict()接口直接返回可能性中最高的那个类别。
几乎所有模型都体都提供了score()接口来评价一个模型的好坏。