《Learning scikit-learn Machine Learning in Python》chapter1
前言
由于实验原因,准备入坑 python 机器学习,而 python 机器学习常用的包就是 scikit-learn ,准备先了解一下这个工具。在这里搜了有 scikit-learn 关键字的书,找到了3本:《Learning scikit-learn: Machine Learning in Python》《Mastering Machine Learning With scikit-learn》《scikit-learn Cookbook》,第一本是2013年出版,后两本是2014年出版,都下下来看了下目录和页数,第一本只有118页,后两本分别为238页和214页,考虑到希望能够尽快看完一本,对整体 sklearn 有一定了解,最后选择了第一本进行阅读。
这本书上周看完了,但是笔记还没有整理,趁着写这个博客,重新复习一遍,加强理解,巩固记忆,如果有说错的地方,敬请指出。
本书概况
一共分为4个大章节:第一章是对机器学习的一个入门介绍;第二章和第三章分别介绍了监督学习和无监督学习在 sklearn 中的几种算法实现,每个算法用一个例子进行分别介绍,个人觉得很不错;第四章是对一些前面提到的高级技巧进行分类阐述,如果说前面的算法实现只是一个基本模型构建,第四章讲的内容,能够让模型进一步优化,达到如虎添翼的效果。
私以为这本书写得很不错,虽然页数不多,讲的内容也不是特别深入,但是对于一个机器学习小白来说,是一本很不错的入门书籍。看完这本书,能够对使用机器学习方法解决问题树立一个比较系统的思路和流程,而且由于页数不多,看完一本书基本也就花了大概一天半的时间,如果英语or有一定机器学习基础可能会更快。
但是这本书也有一个非常严重的缺陷——太老了。里面的代码都是用 python2 写的,而且一些函数接口,最新的 sklearn 快要不支持了,还有一些使用的数据集,链接下载的时候也遇到了一些问题,还有一些 typos 错误。这个读书笔记边整理的时候,也就边在对一些代码使用 python3 进行实现。
第一章读书笔记
前言
大多数用机器学习解决问题的过程可以简化成3个步骤:
- 给一个任务T
- 需要学习一些经验E(藏在数据集里)
- 有一个性能指标P(用来评估任务完成得怎么样)
安装
Scikit-learn 需要提前安装 Numpy 和 Scipy,参照后文的说法,最好还要安装 Pandas 和 Matplotlib。
windows 下建议直接安装 Anaconda,不错的集成工具,包含 Jupyter Notebook 和 Spyder,以及几乎所有的依赖包,如果没有再安装即可。
linux 下就直接安装 python 的虚拟环境,利用 pip 包管理工具一个一个进行安装,可以看这里,总结了一个非常简要的linux下搭建python机器学习环境的相关命令。
Mac 下也有类似的工具 MacPorts 和 HomeBrew。
数据集
sklearn 包含一些公开知名的数据集,只要引入相关的数据集包就可以。
这里引入了 1936 年鸢尾花的那个数据集,试一下代码(本文的代码都是基于python2实现的,但这个笔记都把代码转化成了 python 3的实现形式,后文就不一一赘述了)。
from sklearn import datasets
iris = datasets.load_iris()
X_iris, Y_iris = iris.data, iris.target
print(X_iris.shape, Y_iris.shape)
print(X_iris[0],Y_iris[0])
(150, 4) (150,)
[ 5.1 3.5 1.4 0.2] 0
shape表示矩阵的维度,行x列。
Numpy 会把数据按照类似 R 的数据框 or 矩阵的格式读取进来,数据一行表示一个实例,一列表示一个特征,基本后续的算法输入也是这种格式。
线性分类器模型构建、评估、可视化展示
这里举了个线性的例子,利用上面的数据集,用花萼的宽度和长度作为特征。随机选择了75%的作为训练集,剩下的作为测试集,来预测花的类别。
#数据集初步处理,构造训练集和验证集
from sklearn.cross_validation import train_test_split
from sklearn import preprocessing
X, y = X_iris[:,:2], Y_iris
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=33)
print(X_train.shape, y_train.shape)
(112, 2) (112,)
#对数据进行归一化
scaler = preprocessing.StandardScaler().fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
print(scaler)
StandardScaler(copy=True, with_mean=True, with_std=True)
#用横坐标为花萼长度,纵坐标为花萼宽度作图,不同种类的花用不同颜色表示,对数据结构进行可视化展示,可以指导后续的模型选择和建立
%matplotlib inline #这句话是在 jupyter 中展示图片必须写的命令,否则图片显示不出来
import matplotlib.pyplot as plt
colors = ['red','greenyellow','blue']
for i in range(len(colors)):
xs = X_train[:,0][y_train == i]
ys = X_train[:,1][y_train == i]
plt.scatter(xs, ys, c=colors[i])
plt.legend(iris.target_names)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
Text(0,0.5,'Sepal width')
#训练模型
from sklearn.linear_model import SGDClassifier
clf = SGDClassifier()
clf.fit(X_train, y_train)
print(clf.coef_)
print(clf.intercept_)
[[-38.1319044 4.82101696]
[ 0.74533565 -12.21001281]
[ 10.94046262 -9.35131933]]
[-11.9120138 -2.94008476 -17.30968766]
#开始作图
x_min, x_max = X_train[:,0].min() - .5, X_train[:,0].max() + .5
y_min, y_max = X_train[:,1].min() - .5, X_train[:,1].max() + .5
import numpy as np
xs = np.arange(x_min, x_max, 0.5)
fig, axes = plt.subplots(1,3)
fig.set_size_inches(10,6)
for i in [0, 1, 2]:
axes[i].set_aspect('equal')
axes[i].set_title('Class' + str(i) + ' versus the rest')
axes[i].set_xlabel('Sepal length')
axes[i].set_ylabel('Sepal width')
axes[i].set_xlim(x_min, x_max)
axes[i].set_ylim(y_min, y_max)
plt.sca(axes[i])
plt.scatter(X_train[:,0], X_train[:, 1], c=y_train, cmap=plt.cm.prism)
ys = (-clf.intercept_[i] - xs * clf.coef_[i, 0]) /clf.coef_[i, 1]
plt.plot(xs, ys, hold=True)
给一个实例,进行预测(训练集和测试集都要做同样的数据处理工作,如正则化等):
#预测
print(clf.predict(scaler.transform([[4.7, 3.1]])))
[0]
print(clf.decision_function(scaler.transform([[4.7, 3.1]])))
[[ 36.57038398 -5.03172599 -31.97218356]]
模型构建完毕,但是还需要评定性能:
#在训练集上的性能评估
from sklearn import metrics
y_train_pred = clf.predict(X_train)
print(metrics.accuracy_score(y_train, y_train_pred))
0.776785714286
#在测试集上的性能评估
y_pred = clf.predict(X_test)
print(metrics.accuracy_score(y_test, y_pred))
0.526315789474
算法在训练集上的效果肯定比测试集上要好,所以是一个检测算法性能上限的方法。
F1值的计算是一个结合精确率和召回率的评估指标,值为 2* presion * recall/(precision + recall)
#整体的分析报告
print(metrics.classification_report(y_test, y_pred, target_names=iris.target_names))
precision recall f1-score support
setosa 1.00 1.00 1.00 8
versicolor 0.38 1.00 0.55 11
virginica 1.00 0.05 0.10 19
avg / total 0.82 0.53 0.42 38
#看混淆矩阵,可以看出到底是哪些判错影响了性能
print(metrics.confusion_matrix(y_test, y_pred))
[[ 8 0 0]
[ 0 11 0]
[ 0 18 1]]
常用的交叉验证方法来评估模型:
#采用5折交叉验证的方法对模型进行评估
from sklearn.cross_validation import cross_val_score, KFold
from sklearn.pipeline import Pipeline
clf = Pipeline([
('scaler', preprocessing.StandardScaler()),
('linear_model', SGDClassifier())
])
cv = KFold(X.shape[0], 5, shuffle=True, random_state=33)
scores = cross_val_score(clf, X, y, cv=cv)
print(scores)
[ 0.66666667 0.63333333 0.6 0.83333333 0.86666667]
#计算5折的平均分值,即为模型的性能
from scipy.stats import sem
def mean_score(scores):
return ("Mean score: {0:.3f} (+/-{1:.3f})").format(np.mean(scores), sem(scores))
print(mean_score(scores))
Mean score: 0.720 (+/-0.054)
英语生词总结
sepal:花萼;
petal:花瓣;
setosa:刺芒野古草;
versicolor:杂色的;
virginica:维尔吉尼卡;
harmonic:和谐的,和声的;
intuitively:直观的,直觉的;
adequately:充分的,足够的,适当的;
instantiation:实例化;
annotated:有注释的,带注释的。
小结
整体来说,第一章用一个简单的线性分类器的例子,走了一遍简要的机器学习的流程,介绍了一些相关概念,能够对机器学习有一个简要的认识。
机器学习的一些分类:
- 监督学习(分类)
- 回归(其实也是一种分类,只不过不是离散型的类别,而是连续型的数字)
- 非监督学习(聚类)
机器学习的一些重要概念:
- 维数爆炸
- 过拟合/欠拟合
- 泛化能力
- 偏差和方差(其实和上面的过拟合和欠拟合是对应的)
- 线性分类器高偏差低方差,KNN低偏差高方差,偏差高对应欠拟合,方差高对应过拟合
- 特征标准化和归一化(数据的处理)
- 特征工程(特征提取和特征选择)
- 模型选择(模型的参数设置)
欢迎转载本博客文章,转载请注明出处,十分感谢。