欢迎访问集智主站:集智,通向智能时代的引擎
注意!
本文所有代码均可在集智原贴中运行调试(无需安装环境),请点击这里前往原贴
机器学习解决的问题
有监督学习从两个数据集中发现关联:观察到的数据X和我们想要预测的数据y(称为“目标”或“标签”)。通常情况下,y是长度为n_samples的一维数组。 Scikit-learn中所有的有监督预测器都提供:fit(X,y)方法来建立拟合模型;predict(X)方法,输入无标签采样X,返回预测标签y。
术语:分类与回归
如果预测目的是分类带有有限多个标签的采样,换言之即“命名”采样对象,那么这就是一个分类任务。相对地,如果目的是预测连续目标变量,则是回归任务。
在Scikit-learn的分类中,y是整数或字符组成的矢量。
近邻分类与维数灾难
分类鸢尾花
鸢尾花数据集用于分类任务:根据花瓣/萼片的长/宽识别3种不同的鸢尾花(Setosa, Versicolour, Virginica)。
# 导入数值计算库Numpy,以及Scikit-learn中的数据集
import numpy as np
from sklearn import datasets
# 从数据集中导入鸢尾花
iris = datasets.load_iris()
# 将特征数据赋值给iris_X,标签数据赋值给iris_y
iris_X = iris.data
iris_y = iris.target
# 输出iris_y的不重复元素
np.unique(iris_y)
# 导入数值计算库Numpy,以及Scikit-learn中的数据集
import numpy as np
from sklearn import datasets
# 从数据集中导入鸢尾花
iris = datasets.load_iris()
# 将特征数据赋值给iris_X,标签数据赋值给iris_y
iris_X = iris.data
iris_y = iris.target
# 输出iris_y的不重复元素
np.unique(iris_y)
len(np.unique(iris_y)) == 3
k近邻算法
近邻算法是最简单的实用分类器:针对每个新采样X_test,在训练集(用于训练预测器的数据)中寻找特征向量最为接近的采样。
训练集与测试集
对于任何学习算法来说,都不能用已经参与过训练的数据再去校验预测器的预测结果,因为这并不能衡量预测器对新数据的适用性。这就是为什么数据集要分为训练集和测试集。 当然了如果你的Python基础还不牢固,也欢迎到集智课堂里巩固一下基础
import numpy as np
from sklearn import datasets
iris = datasets.load_iris()
iris_X = iris.data
iris_y = iris.target
# 将数据集随机划分为训练集合测试集
np.random.seed(0)
indices = np.random.permutation(len(iris_X))
iris_X_train = iris_X[indices[:-10]]
iris_y_train = iris_y[indices[:-10]]
iris_X_test = iris_X[indices[-10:]]
iris_y_test = iris_y[indices[-10:]]
# 从Scikit-learn库中导入分类器并创建对象knn
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier()
# 用训练集拟合数据
knn.fit(iris_X_train, iris_y_train)
# 用测试集进行实地预测
iris_y_predict = knn.predict(iris_X_test)
print('iris_y_predict = ')
print(iris_y_predict)
# 与测试集标签进行对比
iris_y_test
print('iris_y_test = ')
print(iris_y_test)
# 将数据集随机划分为训练集合测试集
np.random.seed(0)
indices = np.random.permutation(len(iris_X))
iris_X_train = iris_X[indices[:-10]]
iris_y_train = iris_y[indices[:-10]]
iris_X_test = iris_X[indices[-10:]]
iris_y_test = iris_y[indices[-10:]]
# 从Scikit-learn库中导入分类器并创建对象knn
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier()
# 用训练集拟合数据
knn.fit(iris_X_train, iris_y_train)
# 用测试集进行实地预测
iris_y_predict = knn.predict(iris_X_test)
print('iris_y_predict = ')
print(iris_y_predict)
# 与测试集标签进行对比
iris_y_test
print('iris_y_test = ')
print(iris_y_test)
用K近邻分类器做分类,并将结果赋值予变量iris_y_predict
维数灾难
对于一个有效的预测器而言,你需要使相邻采样点之间的距离小于特定值d,d的值因问题而异。在一维情况下,我们需要平均的点。在上述的KNN例子中,如果数据只有一个值为0到1的特征,且有n个采样点,那么新数据总能落在与相邻点不到1/n的距离内。因而当1/n相比异类特征偏差很小的时候,最近邻算法总是有效的。
假设特征的数量不是1,而是,此时你就需要
个点。比如在一维情况下我们需要10个点,那么
维情况下就需要
个点来填充[0,1]空间。随着
的增大,支撑有效预测器的训练点数量将呈指数增长。
例如,若每个点是一个8bytes的数字,那么仅仅p~20个维度的KNN预测器所需的训练点便已经超过了当前互联网的总数据量(约1000Exabytes)。 这就是维数灾难,也是机器学习面临的核心问题之一。
线性模型:从回归到稀疏
糖尿病数据集
该数据集包含来自442名病人的10个体征变量(年龄,性别,体重,血压)以及一年后的病情发展指标。
现在的任务是根据当前的体征变量预测病情的变化。
from sklearn import datasets
# 导入diabetes数据集并赋值予同名变量
diabetes = datasets.load_diabetes()
# 划分训练集与测试集,测试集样本量为20
diabetes_X_train = diabetes.data[:-20]
diabetes_X_test = diabetes.data[-20:]
diabetes_y_train = diabetes.target[:-20]
diabetes_y_test = diabetes.target[-20:]
# 导入diabetes数据集并赋值予同名变量
diabetes = datasets.load_diabetes()
# 划分训练集与测试集,测试集样本量为20
diabetes_X_train = diabetes.data[:-20]
diabetes_X_test = diabetes.data[-20:]
diabetes_y_train = diabetes.target[:-20]
diabetes_y_test = diabetes.target[-20:]
len(diabetes_X_train) == 20
导入diabetes数据集并赋值予同名变量。
划分训练集与测试集,测试集样本量为20。
线性回归
最简单的线性回归拟合了一个线性模型,通过调整一系列参数以使得偏差平方和最小(最小二乘法)。
线性模型:
数据
目标变量
系数
采样噪音
diabetes = datasets.load_diabetes()
diabetes_X_train = diabetes.data[:-20]
diabetes_X_test = diabetes.data[-20:]
diabetes_y_train = diabetes.target[:-20]
diabetes_y_test = diabetes.target[-20:]
from sklearn import linear_model
# 建立线性回归模型对象
regr = linear_model.LinearRegression()
regr.fit(diabetes_X_train, diabetes_y_train)
print(regr.coef_)
# 偏差平方和
np.mean((regr.predict(diabetes_X_test)-diabetes_y_test)**2)
# 偏差解释:1代表完美预测,0表示X和y毫无线性关系E
score = regr.score(diabetes_X_test, diabetes_y_test)
print(score)
from sklearn import linear_model
# 建立线性回归模型对象
regr = linear_model.LinearRegression()
regr.fit(diabetes_X_train, diabetes_y_train)
print(regr.coef_)
# 偏差平方和
np.mean((regr.predict(diabetes_X_test)-diabetes_y_test)**2)
# 偏差解释:1代表完美预测,0表示X和y毫无线性关系E
score = regr.score(diabetes_X_test, diabetes_y_test)
print(score)
score > 0.5
用线性回归模型对糖尿病数据集做预测并输出测试得分
支持向量机(SVM)
线性支持向量机
支持向量机属于判别式模型:试图寻找一组例子来建立一个平面,使两个类别之间的空间最大。参数设置了正则化:值较小的
说明”空间“由更多甚至分界线周围的全部采样点计算得出(更加正则);较大的
说明”空间“仅由分界线附近的采样点计算而来(正则程度低)。
支持向量机可用于回归——SVR(Support Vector Regression)或分类——SVC(Support Vector Classification)。
from sklearn import svm
# 创建SVC对象,并使用线性核函数
svc = svm.SVC(kernel='linear')
svc.fit(iris_X_train, iris_y_train)
from sklearn import svm
# 创建SVC对象,并使用线性核函数
svc = svm.SVC(kernel='linear')
svc.fit(iris_X_train, iris_y_train)
创建SVC对象,并使用线性核函数
提示: 归一化数据 对于包括SVM的很多预测器在内,使数据集的每个特征具有单位标准差有助于获得良好的预测效果。
使用核函数(kernel)
在特征空间内,不同类别并不总是线性可分。解决方案便是建立非线性决策函数如多项式函数,这可通过核函数技巧实现:对采样使用核函数来分配不同的决策权重。
svc = svm.SVC(kernel='linear')
svc = svm.SVC(kernel='poly', degree=3)
svc = svm.SVC(kernel='rbf')
练习
尝试只用前两个特征,通过支持向量机将鸢尾花数据集的类别1、2分类出来。每个类别留出10%作为测试集。
警告: 类别经过排序,不要留出最后10%,那样会导致测试只在单独一个类别上进行。
提示: 可以在网格上使用decision_function方法获得直观信息。
from sklearn import datasets
%matplotlib inline
iris = datasets.load_iris()
X = iris.data
y = iris.target
X = X[y != 0, :2]
y = y[y != 0]
# 以下由读者完成整个程序
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets, svm
# 样本容量
n_sample = len(X)
# 产生随机序列用于划分训练集/测试集
np.random.seed(0)
order = np.random.permutation(n_sample)
X = X[order]
y = y[order].astype(np.float)
X_train = X[:.9 * n_sample]
y_train = y[:.9 * n_sample]
X_test = X[.9 * n_sample:]
y_test = y[.9 * n_sample:]
# 对不同kernel分别训练模型
for fig_num, kernel in enumerate(('linear', 'rbf', 'poly')):
clf = svm.SVC(kernel=kernel, gamma=10)
clf.fit(X_train, y_train)
plt.figure(fig_num)
plt.clf()
plt.scatter(X[:, 0], X[:, 1], c=y, zorder=10, cmap=plt.cm.Paired)
# 输出测试数据图表
plt.scatter(X_test[:, 0], X_test[:, 1], s=80, facecolors='none', zorder=10)
plt.axis('tight')
x_min = X[:, 0].min()
x_max = X[:, 0].max()
y_min = X[:, 1].min()
y_max = X[:, 1].max()
XX, YY = np.mgrid[x_min:x_max:200j, y_min:y_max:200j]
Z = clf.decision_function(np.c_[XX.ravel(), YY.ravel()])
# 将计算结果加入图表
Z = Z.reshape(XX.shape)
plt.pcolormesh(XX, YY, Z > 0, cmap=plt.cm.Paired)
plt.contour(XX, YY, Z, colors=['k', 'k', 'k'], linestyles=['--', '-', '--'],
levels=[-.5, 0, .5])
plt.title(kernel)
plt.show()
随机划分训练/测试集,对三种不同的kernel分别训练模型。