机器学习是人工智能的一个分支,主要是设计和分析一些让计算机可以自动“学习”的算法,这些算法可以从数据中自动分析获得规律,并利用规律对未知数据进行预测。当前,机器学习已广泛应用于计算机视觉、自然语言处理、生物特征识别、战略游戏和机器人等领域。
本课程首先简单介绍了什么是机器学习、什么是Scikit-learn以及如何安装Scikit-learn;然后讲解了如何选择合适的机器学习方法,并以iris数据集为例展示了Scikit-learn的通用学习模式,同时分享了一些有用的数据集及其用法;接着是Scikit-learn模型的讲解,包括其常用属性和功能;最后结合案例详细讲解了如何进行数据标准化,以及如何通过交叉验证选择合适的模型。
【课程目标】
了解开源机器学习库Scikit-learn
熟悉常用的机器学习方法
使用Scikit-learn实现数据标准化和交叉验证
【适用对象】
AI开发者、学生
【课程大纲】
知识模块 | 简介 |
---|---|
机器学习 Scikit-Learn | 什么是Scikit-Learn Scikit-Learn安装 Scikit-Learn如何选择机器学习方法 Scikit-Learn通用学习模式 Scikit-Learn sklearn的datasets数据库 Scikit-Learn model常用属性和功能 Scikit-Learn normalization标准化数据 Scikit-Learn cross validation交叉验证 Scikit-Learn保存model |
腾讯云旗下面向云生态用户的一站式学习成长平台
在这里我们介绍了什么是机器学习, 还有机器学习包含了哪些方法. 通常来说, 机器学习的方法包括:
Scikit-learn 也简称 sklearn, 是机器学习领域当中最知名的 python 模块之一.
Sklearn 包含了很多种机器学习的方式:
我们总能够从这些方法中挑选出一个适合于自己问题的, 然后解决自己的问题.
安装 Scikit-learn (sklearn) 最简单的方法就是使用 pip 安装它.
首先确认自己电脑中有安装
如果还不确定如何安装 Numpy 请查看这个 安装 Numpy 教程. 如果能顺利安装 Numpy 那 Scipy 的安装就没有问题了.
然后找到你的 Terminal (MacOS or Linux), 或者 CMD (Windows). 输入以下语句:
# python 2+ 版本复制:
pip install -U scikit-learn
# python 3+ 版本复制:
pip3 install -U scikit-learn
安装完 Sklearn 后,不要直接去用,先了解一下都有什么模型方法,然后选择适当的方法,来达到你的目标。
Sklearn 官网提供了一个流程图, 蓝色圆圈内是判断条件,绿色方框内是可以选择的算法:
从 START 开始,首先看数据的样本是否 >50
,小于则需要收集更多的数据。
由图中,可以看到算法有四类,分类,回归,聚类,降维。
其中 分类和回归是监督式学习,即每个数据对应一个 label。 聚类 是非监督式学习,即没有 label。 另外一类是 降维,当数据集有很多很多属性的时候,可以通过 降维 算法把属性归纳起来。例如 20 个属性只变成 2 个,注意,这不是挑出 2 个,而是压缩成为 2 个,它们集合了 20 个属性的所有特征,相当于把重要的信息提取的更好,不重要的信息就不要了。
然后看问题属于哪一类问题,是分类还是回归,还是聚类,就选择相应的算法。 当然还要考虑数据的大小,例如 100K
是一个阈值。
可以发现有些方法是既可以作为分类,也可以作为回归,例如 SGD
。
Sklearn 把所有机器学习的模式整合统一起来了,学会了一个模式就可以通吃其他不同类型的学习模式。
例如,分类器,
Sklearn 本身就有很多数据库,可以用来练习。 以 Iris 的数据为例,这种花有四个属性,花瓣的长宽,茎的长宽,根据这些属性把花分为三类。
我们要用 分类器 去把四种类型的花分开。
今天用KNN classifier
,就是选择几个临近点,综合它们做个平均来作为预测值。
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
加载iris
的数据,把属性存在X
,类别标签存在y
:
iris = datasets.load_iris()
iris_X = iris.data
iris_y = iris.target
观察一下数据集,X
有四个属性,y
有 0,1,2 三类:
print(iris_X[:2, :])
print(iris_y)
"""
[[ 5.1 3.5 1.4 0.2]
[ 4.9 3. 1.4 0.2]]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
"""
把数据集分为训练集和测试集,其中 test_size=0.3
,即测试集占总数据的 30%:
X_train, X_test, y_train, y_test = train_test_split(
iris_X, iris_y, test_size=0.3)
可以看到分开后的数据集,顺序也被打乱,这样更有利于学习模型:
print(y_train)
"""
[2 1 0 1 0 0 1 1 1 1 0 0 1 2 1 1 1 0 2 2 1 1 1 1 0 2 2 0 2 2 2 2 2 0 1 2 2
2 2 2 2 0 1 2 2 1 1 1 0 0 1 2 0 1 0 1 0 1 2 2 0 1 2 2 2 1 1 1 1 2 2 2 1 0
1 1 0 0 0 2 0 1 0 0 1 2 0 2 2 0 0 2 2 2 1 2 0 0 2 1 2 0 0 1 2]
"""
定义模块方式 KNeighborsClassifier()
, 用 fit
来训练 training data
,这一步就完成了训练的所有步骤, 后面的 knn
就已经是训练好的模型,可以直接用来 predict
测试集的数据, 对比用模型预测的值与真实的值,可以看到大概模拟出了数据,但是有误差,是不会完完全全预测正确的。
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
print(knn.predict(X_test))
print(y_test)
"""
[2 0 0 1 2 2 0 0 0 1 2 2 1 1 2 1 2 1 0 0 0 2 1 2 0 0 0 0 1 0 2 0 0 2 1 0 1
0 0 1 0 1 2 0 1]
[2 0 0 1 2 1 0 0 0 1 2 2 1 1 2 1 2 1 0 0 0 2 1 2 0 0 0 0 1 0 2 0 0 2 1 0 1
0 0 1 0 1 2 0 1]
"""
Sklearn
中的 data sets
,很多而且有用,可以用来学习算法模型。
数据案例: boston 房价, 糖尿病, 数字, Iris 花。
也可以生成虚拟的数据,例如用来训练线性回归模型的数据,可以用函数来生成。
可以看到sample
的总数,属性,以及label
等信息
如果是自己生成数据,按照函数的形式,输入 sample,feature,target
的个数等等。
sklearn.datasets.make_regression(n_samples=100, n_features=100, n_informative=10, n_targets=1, bias=0.0, effective_rank=None, tail_strength=0.5, noise=0.0, shuffle=True, coef=False, random_state=None)[source]
导入 datasets
包,以 Linear Regression
为例。
from __future__ import print_function
from sklearn import datasets
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
用 datasets.load_boston()
的形式加载数据,并给 X
和 y
赋值,这种形式在 Sklearn
中都是高度统一的。
loaded_data = datasets.load_boston()
data_X = loaded_data.data
data_y = loaded_data.target
定义模型。
可以直接用默认值去建立 model
,默认值也不错,也可以自己改变参数使模型更好。 然后用 training data
去训练模型。
model = LinearRegression()
model.fit(data_X, data_y)
再打印出预测值,这里用 X
的前 4 个来预测,同时打印真实值,作为对比,可以看到是有些误差的。
print(model.predict(data_X[:4, :]))
print(data_y[:4])
"""
[ 30.00821269 25.0298606 30.5702317 28.60814055]
[ 24. 21.6 34.7 33.4]
"""
为了提高准确度,可以通过尝试不同的model
,不同的参数,不同的预处理等方法,入门的话可以直接用默认值。
下面是创造数据的例子。
用函数来建立 100 个 sample
,有一个 feature
,和一个 target
,这样比较方便可视化。
X, y = datasets.make_regression(n_samples=100, n_features=1, n_targets=1, noise=10)
用 scatter
的形式来输出结果。
plt.scatter(X, y)
plt.show()
可以看到用函数生成的 Linear Regression
用的数据。
noise
越大的话,点就会越来越离散,例如 noise
由 10 变为 50.
X, y = datasets.make_regression(n_samples=100, n_features=1, n_targets=1, noise=50)
plt.scatter(X, y)
plt.show()
以 LinearRegressor
为例,所以先导入包,数据,还有模型。
from sklearn import datasets
from sklearn.linear_model import LinearRegression
loaded_data = datasets.load_boston()
data_X = loaded_data.data
data_y = loaded_data.target
model = LinearRegression()
接下来 model.fit
和 model.predict
就属于 Model 的功能,用来训练模型,用训练好的模型预测。
model.fit(data_X, data_y)
print(model.predict(data_X[:4, :]))
"""
[ 30.00821269 25.0298606 30.5702317 28.60814055]
"""
然后,model.coef_
和 model.intercept_
属于 Model 的属性, 例如对于 LinearRegressor
这个模型,这两个属性分别输出模型的斜率和截距(与y轴的交点)。
print(model.coef_)
print(model.intercept_)
"""
[ -1.07170557e-01 4.63952195e-02 2.08602395e-02 2.68856140e+00
-1.77957587e+01 3.80475246e+00 7.51061703e-04 -1.47575880e+00
3.05655038e-01 -1.23293463e-02 -9.53463555e-01 9.39251272e-03
-5.25466633e-01]
36.4911032804
"""
model.get_params()
也是功能,它可以取出之前定义的参数。
print(model.get_params())
"""
{'copy_X': True, 'normalize': False, 'n_jobs': 1, 'fit_intercept': True}
"""
model.score(data_X, data_y)
它可以对 Model 用 R^2
的方式进行打分,输出精确度。关于 R^2 coefficient of determination
可以查看 wiki
print(model.score(data_X, data_y)) # R^2 coefficient of determination
"""
0.740607742865
"""
from sklearn import preprocessing #标准化数据模块
import numpy as np
#建立Array
a = np.array([[10, 2.7, 3.6],
[-100, 5, -2],
[120, 20, 40]], dtype=np.float64)
#将normalized后的a打印出
print(preprocessing.scale(a))
# [[ 0. -0.85170713 -0.55138018]
# [-1.22474487 -0.55187146 -0.852133 ]
# [ 1.22474487 1.40357859 1.40351318]]
加载模块
# 标准化数据模块
from sklearn import preprocessing
import numpy as np
# 将资料分割成train与test的模块
from sklearn.model_selection import train_test_split
# 生成适合做classification资料的模块
from sklearn.datasets.samples_generator import make_classification
# Support Vector Machine中的Support Vector Classifier
from sklearn.svm import SVC
# 可视化数据的模块
import matplotlib.pyplot as plt
生成适合做Classification数据
#生成具有2种属性的300笔数据
X, y = make_classification(
n_samples=300, n_features=2,
n_redundant=0, n_informative=2,
random_state=22, n_clusters_per_class=1,
scale=100)
#可视化数据
plt.scatter(X[:, 0], X[:, 1], c=y)
plt.show()
数据标准化前
标准化前的预测准确率只有0.477777777778
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
clf = SVC()
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))
# 0.477777777778
数据标准化后
数据的单位发生了变化, X
数据也被压缩到差不多大小范围.
标准化后的预测准确率提升至0.9
X = preprocessing.scale(X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
clf = SVC()
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))
# 0.9
Sklearn 中的 Cross Validation (交叉验证)对于我们选择正确的 Model 和 Model 的参数是非常有帮助的, 有了他的帮助,我们能直观的看出不同 Model 或者参数对结构准确度的影响。
from sklearn.datasets import load_iris # iris数据集
from sklearn.model_selection import train_test_split # 分割数据模块
from sklearn.neighbors import KNeighborsClassifier # K最近邻(kNN,k-NearestNeighbor)分类算法
#加载iris数据集
iris = load_iris()
X = iris.data
y = iris.target
#分割数据并
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=4)
#建立模型
knn = KNeighborsClassifier()
#训练模型
knn.fit(X_train, y_train)
#将准确率打印出
print(knn.score(X_test, y_test))
# 0.973684210526
可以看到基础验证的准确率为0.973684210526
from sklearn.cross_validation import cross_val_score # K折交叉验证模块
#使用K折交叉验证模块
scores = cross_val_score(knn, X, y, cv=5, scoring='accuracy')
#将5次的预测准确率打印出
print(scores)
# [ 0.96666667 1. 0.93333333 0.96666667 1. ]
#将5次的预测准确平均率打印出
print(scores.mean())
# 0.973333333333
可以看到交叉验证的准确平均率为0.973333333333
一般来说准确率(accuracy)
会用于判断分类(Classification)模型的好坏。
import matplotlib.pyplot as plt #可视化模块
#建立测试参数集
k_range = range(1, 31)
k_scores = []
#藉由迭代的方式来计算不同参数对模型的影响,并返回交叉验证后的平均准确率
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy')
k_scores.append(scores.mean())
#可视化数据
plt.plot(k_range, k_scores)
plt.xlabel('Value of K for KNN')
plt.ylabel('Cross-Validated Accuracy')
plt.show()
从图中可以得知,选择12~18
的k
值最好。高过18
之后,准确率开始下降则是因为过拟合(Over fitting)的问题。
一般来说平均方差(Mean squared error)
会用于判断回归(Regression)模型的好坏。
import matplotlib.pyplot as plt
k_range = range(1, 31)
k_scores = []
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
loss = -cross_val_score(knn, X, y, cv=10, scoring='mean_squared_error')
k_scores.append(loss.mean())
plt.plot(k_range, k_scores)
plt.xlabel('Value of K for KNN')
plt.ylabel('Cross-Validated MSE')
plt.show()
sklearn.learning_curve
中的 learning curve 可以很直观的看出我们的 model 学习的进度, 对比发现有没有 overfitting 的问题. 然后我们可以对我们的 model 进行调整, 克服 overfitting 的问题.
加载对应模块:
from sklearn.learning_curve import learning_curve #学习曲线模块
from sklearn.datasets import load_digits #digits数据集
from sklearn.svm import SVC #Support Vector Classifier
import matplotlib.pyplot as plt #可视化模块
import numpy as np
加载digits数据集,其包含的是手写体的数字,从0到9。数据集总共有1797个样本,每个样本由64个特征组成, 分别为其手写体对应的8×8像素表示,每个特征取值0~16。
digits = load_digits()
X = digits.data
y = digits.target
观察样本由小到大的学习曲线变化, 采用K折交叉验证 cv=10
, 选择平均方差检视模型效能 scoring='mean_squared_error'
, 样本由小到大分成5轮检视学习曲线(10%, 25%, 50%, 75%, 100%)
:
可视化图形:
plt.plot(train_sizes, train_loss_mean, 'o-', color="r",
label="Training")
plt.plot(train_sizes, test_loss_mean, 'o-', color="g",
label="Cross-validation")
plt.xlabel("Training examples")
plt.ylabel("Loss")
plt.legend(loc="best")
plt.show()
连续三节的交叉验证(cross validation)让我们知道在机器学习中验证是有多么的重要, 这一次的 sklearn 中我们用到了sklearn.learning_curve
当中的另外一种, 叫做validation_curve
,用这一种曲线我们就能更加直观看出改变模型中的参数的时候有没有过拟合(overfitting)的问题了. 这也是可以让我们更好的选择参数的方法.
继续上一节的例子,并稍作小修改即可画出图形。这次我们来验证SVC
中的一个参数 gamma
在什么范围内能使 model 产生好的结果. 以及过拟合和 gamma
取值的关系.
from sklearn.learning_curve import validation_curve #validation_curve模块
from sklearn.datasets import load_digits
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
#digits数据集
digits = load_digits()
X = digits.data
y = digits.target
#建立参数测试集
param_range = np.logspace(-6, -2.3, 5)
#使用validation_curve快速找出参数对模型的影响
train_loss, test_loss = validation_curve(
SVC(), X, y, param_name='gamma', param_range=param_range, cv=10, scoring='mean_squared_error')
#平均每一轮的平均方差
train_loss_mean = -np.mean(train_loss, axis=1)
test_loss_mean = -np.mean(test_loss, axis=1)
#可视化图形
plt.plot(param_range, train_loss_mean, 'o-', color="r",
label="Training")
plt.plot(param_range, test_loss_mean, 'o-', color="g",
label="Cross-validation")
plt.xlabel("gamma")
plt.ylabel("Loss")
plt.legend(loc="best")
plt.show()
由图中可以明显看到gamma值大于0.001
,模型就会有过拟合(Overfitting)的问题。
总算到了最后一次的课程了,我们训练好了一个Model 以后总需要保存和再次预测, 所以保存和读取我们的sklearn model也是同样重要的一步。这次主要介绍两种保存Model的模块pickle
与joblib
。
首先简单建立与训练一个SVC
Model。
from sklearn import svm
from sklearn import datasets
clf = svm.SVC()
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf.fit(X,y)
使用pickle
来保存与读取训练好的Model。 (若忘记什么是pickle
,可以回顾13.8 pickle 保存数据视频。)
import pickle #pickle模块
#保存Model(注:save文件夹要预先建立,否则会报错)
with open('save/clf.pickle', 'wb') as f:
pickle.dump(clf, f)
#读取Model
with open('save/clf.pickle', 'rb') as f:
clf2 = pickle.load(f)
#测试读取后的Model
print(clf2.predict(X[0:1]))
# [0]
joblib
是sklearn
的外部模块。
from sklearn.externals import joblib #jbolib模块
#保存Model(注:save文件夹要预先建立,否则会报错)
joblib.dump(clf, 'save/clf.pkl')
#读取Model
clf3 = joblib.load('save/clf.pkl')
#测试读取后的Model
print(clf3.predict(X[0:1]))
# [0]
最后可以知道joblib
在使用上比较容易,读取速度也相对pickle
快。
课程学习交流
请扫码关注腾讯产业互联网学堂微信公众号