载入一个数据集用例
scikit-learn包含一些标准数据集,如:作为分类用的iris
(虹膜)和digits
(数字)数据集,以及用于回归的boston house prices
数据集。
载入数据:
>>> from sklearn import datasets
>>> iris = datasets.load_iris()
>>> digits = datasets.load_digits()
一个数据集dataset
是一个类似字典类型的对象,对象包含所有data
以及这些data
的元数据metadata
。data
是一个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维的,可以直接用。
从外部数据集载入数据
学习和预测
在“数字”数据集中,算法的任务是给定一个图像,预测它代表哪个数字,“数字”有10个类别(0-9),每个类别都有一些样本,基于这些样本拟合一个能预测出新样本类别的估计器estimator
使用sklearn.svm.SVC
实现支持向量机分类器:
>>> from sklearn import svm
>>> clf = svm.SVC(gamma=0.001, C=100.)
这个例子是手动设置gamma. 也可以使用grid search
或cross validation
等工具自动寻找更好的参数。
要调用估计器实例clf
(clf
这里是一个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.dump
和joblib.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)
将X
由float32
投递成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维数组,每个样本对应多个标签。