此前小天分享了PyTorc干货的Scikit-Learn上篇(点击蓝字可直接阅读),看完下篇希望你能马上学溜PyTorch!(万一这回就学以致用了呢,我先收藏为敬)
讲完Scikit-Learn的数据表示和评估器API的基础知识、简单线性回归,小天将在本文中为大家带来鸢尾花数据的分类、降维和聚类,还有手写数据的探索,耐心往下看吧~
Scikit-Learn·下篇
有监督学习示例:鸢尾花数据分类
如何为鸢尾花数据集建立模型,先用一部分数据进行训练,再用模型预测出其他样本的标签?
我们将使用非常简单的高斯朴素贝叶斯(Gaussian naive Bayes)方法完成这个任务,这个方法假设每个特征中属于每一类的观测值都符合高斯分布。因为高斯朴素贝叶斯方法速度很快,而且不需要选择超参数,所以通常很适合作为初步分类手段,再借助更复杂的模型进行优化之前使用。
先将数据分割成训练集(training set)和测试集(testing set),借助train_test_split 函数
from sklearn.cross_validation import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(X_iris, y_iris,
random_state=1)
用下面的模型来预测标签
from sklearn.naive_bayes import GaussianNB #1.选择模型类
model = GaussianNB() #2.初始化模型
model.fit(Xtrain, ytrain) #3.用模型拟合数据
y_model = model.predict(Xtest) #4.对新数据进行预测
用accuracy_score 工具验证模型预测结果的准确率(预测的所有结果中,正确结果占总预测样本数的比例)
from sklearn.metrics import accuracy_score
accuracy_score(ytest, y_model)
准确率竟然高达97%,常简单的分类算法也可以有效地学习这个数据集!
无监督学习示例:鸢尾花数据降维
无监督学习问题——对鸢尾花数据集进行降维,以便能更方便地对数据进行可视化。鸢尾花数据集由四个维度构成,即每个样本都有四个维度。
降维的任务是要找到一个可以保留数据本质特征的低维矩阵来表示高维数据。降维通常用于辅助数据可视化的工作,毕竟用二维数据画图比用四维甚至更高维的数据画图更方便!
使用主成分分析(principal component analysis,PCA)方法,这是一种快速线性降维技术。
from sklearn.decomposition import PCA # 1.选择模型类
model = PCA(n_components=2) # 2.设置超参数,初始化模型
model.fit(X_iris) # 3.拟合数据,注意这里不用y变量
X_2D = model.transform(X_iris) # 4. 将数据转换为二维
画出结果,将二维数据插入到鸢尾花的DataFrame 中,然后用 Seaborn 的lmplot 方法画图。
iris['PCA1'] = X_2D[:, 0]
iris['PCA2'] = X_2D[:, 1]
sns.lmplot("PCA1", "PCA2", hue='species', data=iris, fit_reg=False);
二维数据表示图可以看出,虽然PCA 算法根本不知道花的种类标签,但不同种类的花还是被很清晰地区分开来。
无监督学习示例:鸢尾花数据聚类
对鸢尾花数据进行聚类。聚类算法是要对没有任何标签的数据集进行分组。我们将用一个强大的聚类方法——高斯混合模型(Gaussian mixture model,GMM)
from sklearn.mixture import GaussianMixture #1.选择模型类
model = GaussianMixture(n_components=3,
covariance_type='full')
#SK-Learn 0.18
#model = GMM(n_components=3,
# covariance_type='full') #2.设置超参数,初始化模型
model.fit(X_iris) #3.拟合数据,注意不需要y变量
y_gmm = model.predict(X_iris) #4. 确定簇标签
用Seaborn画出结果
iris['cluster'] = y_gmm
sns.lmplot("PCA1", "PCA2", data=iris, hue='species',
col='cluster', fit_reg=False);
GMM 算法的训练效果:setosa(山鸢尾花)类的花在簇0 中被完美地区分出来,唯一的遗憾是第三幅图中versicolor(变色鸢尾 花)和virginicaI(维吉尼亚鸢尾花)还有一点混淆。
1.3 应用:手写数字探索
手写数字识别:简单点说,这个问题包括图像中字符的定位和识别两部分。为了演示方便,我们选择使用Scikit-Learn 中自带的手写数字数据集。
加载并可视化手写数字
from sklearn.datasets import load_digits
digits = load_digits()
digits.images.shape
图像数据是一个三维矩阵:共有1797个样本,每张图像都是8像素×8像素
import matplotlib.pyplot as plt
fig, axes = plt.subplots(10, 10, figsize=(8, 8),
subplot_kw={'xticks':[], 'yticks':[]},
gridspec_kw=dict(hspace=0.1, wspace=0.1))
for i, ax in enumerate(axes.flat):
ax.imshow(digits.images[i], cmap='binary', interpolation='nearest')
ax.text(0.05, 0.05, str(digits.target[i]),
transform=ax.transAxes, color='green')
在Scikit-Learn 中使用数据,需要一个维度为[n_samples, n_features] 的二维特征矩阵——可以将每个样本图像的所有像素都作为特征,也就是将每个数字的8 像素×8 像素平铺成长度为64 的一维数组。另外,还需要一个目标数组,用来表示每个数字的真实值(标签)。这两份数据已经放在手写数字数据集的data 与target 属性中,直接使用即可:
X = digits.data
X.shape
y = digits.target
y.shape
无监督学习:降维
想对具有64 维参数空间的样本进行可视化,但是在如此高维度的空间中进行可视化十分困难;借助无监督学习方法将维度降到二维。这次试试流形学习算法中的Isomap算法对数据进行降维。
from sklearn.manifold import Isomap
iso = Isomap(n_components=2)
iso.fit(digits.data)
data_projected = iso.transform(digits.data)
data_projected.shape
数据已经投影到二维,把数据画出来;
plt.scatter(data_projected[:, 0], data_projected[:, 1], c=digits.target, s=20,
edgecolor='none', alpha=0.5,
cmap=plt.cm.get_cmap('Spectral', 10))
plt.colorbar(label='digit label', ticks=range(10))
plt.clim(-0.5, 9.5);
这幅图呈现出了非常直观的效果,让我们知道数字在64 维空间中的分离(可识别)程度。
例如,在参数空间中,数字0和数字1基本不会重叠。根据常识也是如此:数字0 是中间一片空白,而数字1 是中间一片黑。另外,从图中会发现,数字1 和数字4 好像有点儿混淆——也许是有些人写数字1 的时候喜欢在上面加个“帽子”,因此看起来就像是数字4。
数字分类
我们需要找到一个分类算法,对手写数字进行分类。
将数据分成训练集和测试集,然后用高斯朴素贝叶斯模型来拟合:
Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, random_state=0)
from sklearn.naive_bayes import GaussianNB
model = GaussianNB()
model.fit(Xtrain, ytrain)
y_model = model.predict(Xtest)
获得模型的准确率
from sklearn.metrics import accuracy_score
accuracy_score(ytest, y_model)
一个非常简单的模型,数字识别率就可以达到80%以上!但仅依靠这个指标,我们无法知道模型哪里做得不够好,解决这个问题的办法就是用混淆矩阵(confusionmatrix)。可以用Scikit-Learn 计算混淆矩阵,然后用Seaborn画出来。
from sklearn.metrics import confusion_matrix
mat = confusion_matrix(ytest, y_model)
sns.heatmap(mat, square=True, annot=True, cbar=False)
plt.xlabel('predicted value')
plt.ylabel('true value');
从图中可以看出,误判的主要原因在于许多数字2 被误判成了数字1或数字8。另一种显示模型特征的直观方式是将样本画出来,然后把预测标签放在左下角,用绿色表示预测正确,用红色表示预测错误
fig, axes = plt.subplots(10, 10, figsize=(8, 8),
subplot_kw={'xticks':[], 'yticks':[]},
gridspec_kw=dict(hspace=0.1, wspace=0.1))
test_images = Xtest.reshape(-1, 8, 8)
for i, ax in enumerate(axes.flat):
ax.imshow(test_images[i], cmap='binary', interpolation='nearest')
ax.text(0.05, 0.05, str(y_model[i]),
transform=ax.transAxes,
color='green' if (ytest[i] == y_model[i]) else 'red')
通过观察这部分样本数据,我们能知道模型哪里的学习不够好。如果希望分类准确率达到80% 以上,可能需要借助更加复杂的算法,例如支持向量机、随机森林,或者其他分类算法。
1.4 小结
本节介绍了Scikit-Learn 中数据表示方法和评估器API 的基本特征。除了评估器的类型不同,导入模型/ 初始化模型/ 拟合数据/ 预测数据的步骤是完全相同的。对评估器API 有了基本认识之后,你可以参考Scikit-Learn 文档继续学习更多知识,并在你的数据上尝试不同的模型哦~