scikit-learn 机器学习

Python,机器学习 2017-01-15

起步

scikit-learn 是一个比较流行的开源机器学习库。它支持许多分类,回归,聚类算法,包括支持向量机,逻辑回归,朴素贝叶斯,随机森林,梯度boosting,k-means 和 DBSCAN,并且可以与 Numpy 与 SciPy 库进行交互。

本文参考: http://www.scipy-lectures.org/packages/scikit-learn/index.html http://scikit-learn.org/stable/tutorial/basic/tutorial.html

scikit-learn的基本功能主要被分为六个部分,分类,回归,聚类,数据降维,模型选择,数据预处理,具体可以参考官方网站上的文档。

依赖

Numpy,Scipy
IPython
matplotlib
scikit(http://scikit-learn.org)

实例数据

机器学习问题通常是考虑如何通过一组数据的样本来预测未知数据的一些特性。如果每个样本自身含有多个变量,我们管变量叫做特征。

首先,我们将加载一些数据来玩。我们将使用的数据是一个非常简单的花数据库,称为Iris数据集。

Virginia_Iris.png

我们有鸢尾花的150观察指定一些测量:萼片长,萼片宽度,花瓣长度和宽度花瓣与它一起亚型:山鸢尾,变色鸢尾,菖蒲锦葵。

# coding: utf-8
from sklearn import datasets
iris = datasets.load_iris()

数据存储在 .data 成员中,它是一个 (n_samples, n_features) numpy 数组

print iris.data.shape
# output:(150L, 4L)

每一个样本的类别存储在 .target 属性中,它是一个一维数组:

print iris.target.shape
#output:(150L,)

显示数据集中有哪些类别:

np.unique(iris.target)
#output: array([0, 1, 2])

手写数字数据集

手写数字数据集由1797个图像组成,其中每个图像是表示手写数字的8x8像素图像

digits_first_image.png

加载数据集:

digits = datasets.load_digits()

查看底层数据:

print(digits.data)  
"""
[[  0.   0.   5. ...,   0.   0.   0.]
 [  0.   0.   0. ...,  10.   0.   0.]
 [  0.   0.   0. ...,  16.   9.   0.]
 ..., 
 [  0.   0.   1. ...,   6.   0.   0.]
 [  0.   0.   2. ...,  12.   0.   0.]
 [  0.   0.  10. ...,  12.   1.   0.]]
"""

查看数据目标值:

digits.target
#output: array([0, 1, 2, ..., 8, 9, 8])

学习与预测

这里我们使用手写数字数据集做数字识别。我们需要将评估函数与数据进行拟合来进行预测。

在 scikit-learn 中,评估函数(estimator)是一个 Python 对象,它实现了 fit(X, y)predict(T) 方法。

sklearn.svm.SVC 就是一个实现了支持向量分类的评估函数,这里仅是做一个简单的例子,不深究算法的细节与参数的选择,我们仅把它当作一个黑盒:

from sklearn import svm
clf = svm.SVC(gamma=0.001, C=100.)

# 或者
clf = svm.LinearSVC()
clf.fit(iris.data, iris.target)
"""
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
     intercept_scaling=1, loss='squared_hinge', max_iter=1000,
     multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
     verbose=0)
"""

关于模型参数的选择

这里我们手动地设置了 gamma 的值,使用格点搜索与交叉验证的方法可以自动帮我们找到较好的参数

评估函数实例的变量名取作 clf ,说明它是一个分类器(classifier)。将训练集传递给 fit 方法进行数据拟合之后就可以做预测了。这里我们取数据集的最后一张图最为预测图,前面的数据都作为训练数据。

clf.fit(digits.data[:-1], digits.target[:-1]) 
"""
SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape=None, degree=3, gamma=0.001, kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)
"""

我们需要预测的图:

document-uid8834labid1235timestamp1438078290923.png

感觉它。。好像是个8!用排除法看!

clf.predict(digits.data[-1])
#output: array([8])

线性回归模型

在回归的模型中,目标值是输入值的线性组合,假设y此处输入图片的描述是预测值,那么

document-uid8834labid1235timestamp1438078996859.png

其中 w = (w_1,..., w_p) 作为 coef_(因数),w_0 作为 intercept_(截距)

线性回归拟合一个线性模型,根据最小二乘法最小化样本与模型的残差。

from sklearn import linear_model
clf = linear_model.LinearRegression()
clf.fit ([[0, 0], [1, 1], [2, 2]], [0, 1, 2])
clf.coef_
# array([ 0.5,  0.5])

分类

最简单的分类算法就是最近邻居算法:给一个新的数据,取在n维空间中离它最近的样本的标签作为它的标签,这里的 n 由样本的特征数量决定。k-最近邻分类器在内部使用基于球树的算法来表示其训练的样本。

iris_knn.png

knn分类器(k-nearest neighbors)示例:

from sklearn import neighbors
knn = neighbors.KNeighborsClassifier()
knn.fit(iris.data, iris.target) 
knn.predict([[0.1, 0.2, 0.3, 0.4]])
#output:array([0])

训练集和测试集

当使用学习算法进行实验时,重要的是不要测试估计量对用于拟合估计量的数据的预测。实际上,使用kNN估计器,我们将总是在训练集上获得完美的预测。

perm = np.random.permutation(iris.target.size)
iris.data = iris.data[perm]
iris.target = iris.target[perm]
knn.fit(iris.data[:100], iris.target[:100]) 
"""
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform'
"""
knn.score(iris.data[100:], iris.target[100:])
# output: 0.95999999999999996

K-means聚类

如果鸢尾花卉数据样本并没有包括它的目标值在里面,而我们只知道有三种鸢尾花而已,那么就可以使用无监督算法来对样本进行聚类分组。

kmeans.jpg

最简单的聚类算法是 k-means 算法,它将数据分成 k 类,将一个样本分配到一个类中时,分配依据是该样本与所分配类中已有样本的均值(可以想象该类中已分配样本的质心的位置)的距离。同时因为新加入了一个样本,均值也会更新(质心的位置发生变化)。这类操作会持续几轮直至类收敛,持续的轮数由 max_iter 决定。

from sklearn import cluster, datasets
iris = datasets.load_iris()
k_means = cluster.KMeans(n_clusters=3)
k_means.fit(iris.data) 
"""
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
    n_clusters=3, n_init=10, n_jobs=1, precompute_distances='auto',
    random_state=None, tol=0.0001, verbose=0)
"""

分别抽取打印 k-means 的分类结果与数据的实际结果:

print k_means.labels_[::10]
=> [1 1 1 1 1 0 0 0 0 0 2 2 2 2 2]

print iris.target[::10]
=> [0 0 0 0 0 1 1 1 1 1 2 2 2 2 2]

图像压缩

聚类的一个典型应用就是对图片进行色调分离,聚类可以被看作是从观察结果中选择少量信息的方式(如在较小空间上的投影)。例如,这可以用于后置图像(将色调的连续层次转换成具有较少色调的几个区域):

from scipy import misc
lena = misc.face(gray=True).astype(np.float32)
X = lena.reshape((-1, 1)) # We need an (n_sample, n_feature) array
k_means = cluster.KMeans(n_clusters=5)
k_means.fit(X)
# output: KMeans(...)
values = k_means.cluster_centers_.squeeze()
labels = k_means.labels_
lena_compressed = np.choose(labels, values)
lena_compressed.shape = lena.shape

image_zip.jpg

降维

pca_3d_axis.jpg

空间中的数据点看上去几乎就在一个平面上,这意味着数据的某一个特征几乎可以由另两个特征计算得到,这种时候我们就可以进行数据降维了。这里使用主成分分析(PCA:Principal Component Analysis)。

from sklearn import decomposition
pca = decomposition.PCA(n_components=2)
pca.fit(iris.data)
# output: PCA(copy=True, iterated_power='auto', n_components=2, whiten=False,...)

数据可视化:

import pylab as pl
X = pca.transform(iris.data)
pl.scatter(X[:, 0], X[:, 1], c=iris.target) 

pca_iris.png

降维除了可以用在数据可视化上,还可以通过对数据进行预处理提高监督学习处理数据的效率。

文档

官方文档:http://scikit-learn.org/stable/tutorial/basic/tutorial.html


本文由 hongweipeng 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

赏个馒头吧