载入一个数据集用例

scikit-learn包含一些标准数据集,如:作为分类用的iris(虹膜)和digits(数字)数据集,以及用于回归的boston house prices数据集。
载入数据:

>>> from sklearn import datasets
>>> iris = datasets.load_iris()
>>> digits = datasets.load_digits()

一个数据集dataset是一个类似字典类型的对象,对象包含所有data以及这些data的元数据metadatadata是一个n_samples行、n_features列的数组,保存在对象的.data成员中。对于监督学习,还有一个或多个response variables存储在.target成员中。不同数据集的更多细节在dedicated section中。

digits数据集为例,digits.data给出了用于分类这些数字(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则给出这些数字的图像数据集所对应的真实的值。

>>> digits.target
array([0, 1, 2, ..., 8, 9, 8])

关于data数组的维度shape

data数组一般都是 (n_samples, n_features)的2维数组,尽管一些原始数据可能会有不同维度,如digits中,每一个原始图像的样本维度都是8*8,获取其中一个图像数据:

>>> digits.images[0]
array([[  0.,   0.,   5.,  13.,   9.,   1.,   0.,   0.],
       [  0.,   0.,  13.,  15.,  10.,  15.,   5.,   0.],
       [  0.,   3.,  15.,   2.,   0.,  11.,   8.,   0.],
       [  0.,   4.,  12.,   0.,   0.,   8.,   8.,   0.],
       [  0.,   5.,   8.,   0.,   0.,   9.,   8.,   0.],
       [  0.,   4.,  11.,   0.,   1.,  12.,   7.,   0.],
       [  0.,   2.,  14.,   5.,  10.,  12.,   0.,   0.],
       [  0.,   0.,   6.,  13.,  10.,   0.,   0.,   0.]])

simple example on this dataset 阐述了如何从原始数据改变到scikit-learn要求的维度:

>>> digits = datasets.load_digits()
>>> digits.images.shape
(1797, 8, 8)
>>> n_samples = len(digits.images)  #1797个examples
>>> data = digits.images.reshape((n_samples, -1))

这一用例中,digits.data是2维的,可以直接用。

从外部数据集载入数据

参见loading external datasets.

学习和预测

在“数字”数据集中,算法的任务是给定一个图像,预测它代表哪个数字,“数字”有10个类别(0-9),每个类别都有一些样本,基于这些样本拟合一个能预测出新样本类别的估计器estimator
使用sklearn.svm.SVC 实现支持向量机分类器:

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

这个例子是手动设置gamma. 也可以使用grid searchcross validation等工具自动寻找更好的参数。
要调用估计器实例clfclf这里是一个SVM分类器),必须先拟合到一个模型,也就是必须先从模型中学习(也就是训练train)。

>>> clf.fit(digits.data[:-1], digits.target[:-1])  #保留最后一个样本作为测试集
SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma=0.001, kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

现在可以用分类器进行预测了

>>> clf.predict(digits.data[-1:])#最后一个样本代表数字8
array([8])

模型保存

可以使用python内置模块pickle保存scikit中的模型

>>> 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)  
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

>>> import pickle
>>> s = pickle.dumps(clf)    # 保存模型
>>> clf2 = pickle.loads(s)
>>> clf2.predict(X[0:1])
array([0])
>>> y[0]
0

也可以使用 joblib保存,joblib在保存大量数据时更有效率,但只能保存在磁盘而不是在字符串(如上例的s中)中

>>> from sklearn.externals import joblib
>>> joblib.dump(clf, 'filename.pkl')

此后可以再重新载入保存的模型(尤其在其它python程序中)

>>> clf = joblib.load('filename.pkl')

除了函数名filename.pkl外,joblib.dumpjoblib.load函数同样可以接收文件对象 functions also accept file-like object instead of filenames. 关于Joblib的数据保存在这里

惯例

为了预测的准确性,scikit-learn估计器也遵循一些规则:

类型投递

除非特别指定,输入将被投递(cast)成float64

>>> import numpy as np
>>> from sklearn import random_projection

>>> rng = np.random.RandomState(0)
>>> X = rng.rand(10, 2000)
>>> X = np.array(X, dtype='float32')
>>> X.dtype
dtype('float32')

>>> transformer = random_projection.GaussianRandomProjection()
>>> X_new = transformer.fit_transform(X)
>>> X_new.dtype
dtype('float64')

fit_transform(X)Xfloat32投递成float64.
回归目标Regression targets 投递成float64,分类目标保持不变.

>>> from sklearn import datasets
>>> from sklearn.svm import SVC
>>> iris = datasets.load_iris()
>>> clf = SVC()
>>> clf.fit(iris.data, iris.target)  
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

>>> list(clf.predict(iris.data[:3]))
[0, 0, 0]

>>> clf.fit(iris.data, iris.target_names[iris.target])  
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

>>> list(clf.predict(iris.data[:3]))  
['setosa', 'setosa', 'setosa']

第一个predict() 返回一个整形数组,保持iris.target 的类型不变;第二个predict()返回字符串数组, 同样保持iris.target_names的string类型。

重拟合、更新参数

通过sklearn.pipeline.Pipeline.set_params构造的参数可以被更新。多次调用fit()能将之前学习的参数覆盖。

>>> import numpy as np
>>> from sklearn.svm import SVC

>>> rng = np.random.RandomState(0)
>>> X = rng.rand(100, 10)
>>> y = rng.binomial(1, 0.5, 100)
>>> X_test = rng.rand(5, 10)

>>> clf = SVC()
>>> clf.set_params(kernel='linear').fit(X, y)  
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)
>>> clf.predict(X_test)
array([1, 0, 1, 1, 0])

>>> clf.set_params(kernel='rbf').fit(X, y)  
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)
>>> clf.predict(X_test)
array([0, 0, 0, 1, 0])

创建估计器时默认核函数rbf首先被改为linear ,然后改回rbf重新拟合估计器并进行第二次预测。

多分类器和多标签拟合

使用多分类器时,学习和预测都是基于目标数据的格式

>>> from sklearn.svm import SVC
>>> from sklearn.multiclass import OneVsRestClassifier
>>> from sklearn.preprocessing import LabelBinarizer

>>> X = [[1, 2], [2, 4], [4, 5], [3, 2], [3, 1]]
>>> y = [0, 0, 1, 1, 2]

>>> classif = OneVsRestClassifier(estimator=SVC(random_state=0))
>>> classif.fit(X, y).predict(X)
array([0, 0, 1, 1, 2])

上例多分类器的标签是1维的,predict()则提供相应1维的多类预测。也可以基于2维二进制标签进行预测:

>>> y = LabelBinarizer().fit_transform(y)
>>> classif.fit(X, y).predict(X)
array([[1, 0, 0],
       [1, 0, 0],
       [0, 1, 0],
       [0, 0, 0],
       [0, 0, 0]])

这个分类器是使用LabelBinarizer基于2维二进制标签y拟合的,因此predict()返回相应的2维预测值。
注意到第4、5个实例返回的都是0,表示它们没有匹配到3个标签中的任意一个。

对于多标签输出,

>> from sklearn.preprocessing import MultiLabelBinarizer
>> y = [[0, 1], [0, 2], [1, 3], [0, 2, 3], [2, 4]]
>> y = MultiLabelBinarizer().fit_transform(y)
>> classif.fit(X, y).predict(X)
array([[1, 1, 0, 0, 0],
       [1, 0, 1, 0, 0],
       [0, 1, 0, 1, 0],
       [1, 0, 1, 1, 0],
       [0, 0, 1, 0, 1]])

使用MultiLabelBinarizer 将2维的多标签数组二进制化, predict() 返回一个2维数组,每个样本对应多个标签。