putting-it-all-together-with-pipelines

用管线命令连接多个转换方法

下面,让我们用管线命令连接多个转换方法,来演示一个复杂点儿的例子。

Getting ready

本主题将再度释放管线命令的光芒。之前我们用它处理缺失数据,只是牛刀小试罢了。下面我们用管线命令把多个预处理步骤连接起来处理,会非常方便。

首先,我们加载带缺失值的iris数据集:

In [1]:
from sklearn.datasets import load_iris
import numpy as np

iris = load_iris()
iris_data = iris.data

mask = np.random.binomial(1, .25, iris_data.shape).astype(bool)
iris_data[mask] = np.nan

iris_data[:5]
Out[1]:
array([[ nan,  3.5,  1.4,  0.2],
       [ 4.9,  3. ,  1.4,  0.2],
       [ 4.7,  3.2,  1.3,  0.2],
       [ 4.6,  nan,  1.5,  nan],
       [ 5. ,  3.6,  1.4,  0.2]])

How to do it...

本主题的目标是首先补全iris_data的缺失值,然后对补全的数据集用PCA。可以看出这个流程需要一个训练数据集和一个对照集(holdout set);管线命令会让事情更简单,不过之前我们做一些准备工作。

首先加载需要的模块:

In [2]:
from sklearn import pipeline, preprocessing, decomposition

然后,建立ImputerPCA类:

In [3]:
pca = decomposition.PCA()
imputer = preprocessing.Imputer()

有了两个类之后,我们就可以用管线命令处理:

In [4]:
pipe = pipeline.Pipeline([('imputer', imputer), ('pca', pca)])
np.set_printoptions(2)
iris_data_transformed = pipe.fit_transform(iris_data)
iris_data_transformed[:5]
Out[4]:
array([[-2.44, -0.79, -0.12, -0.1 ],
       [-2.67,  0.2 , -0.21,  0.15],
       [-2.83,  0.31, -0.19, -0.08],
       [-2.35,  0.66,  0.67, -0.06],
       [-2.68, -0.06, -0.2 , -0.4 ]])

如果我们用单独的步骤分别处理,每个步骤都要用一次fit_transform,而这里只需要用一次,而且只需要一个对象。

How it works...

管线命令的每个步骤都是用一个元组表示,元组的第一个元素是对象的名称,第二个元素是对象。

本质上,这些步骤都是在管线命令调用时依次执行fit_transform方法。还有一种快速但不太简洁的管线命令建立方法,就像我们快速建立标准化调整模型一样,只不过用StandardScaler会获得更多功能。pipeline函数将自动创建管线命令的名称:

In [5]:
pipe2 = pipeline.make_pipeline(imputer, pca)
pipe2.steps
Out[5]:
[('imputer',
  Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)),
 ('pca', PCA(copy=True, n_components=None, whiten=False))]

这和前面的模型结果一样:

In [6]:
iris_data_transformed2 = pipe2.fit_transform(iris_data)
iris_data_transformed2[:5]
Out[6]:
array([[-2.44, -0.79, -0.12, -0.1 ],
       [-2.67,  0.2 , -0.21,  0.15],
       [-2.83,  0.31, -0.19, -0.08],
       [-2.35,  0.66,  0.67, -0.06],
       [-2.68, -0.06, -0.2 , -0.4 ]])

There's more...

管线命令连接内部每个对象的属性是通过set_params方法实现,其参数用<对象名称>__<对象参数>表示。例如,我们设置PCA的主成份数量为2:

In [8]:
pipe2.set_params(pca__n_components=2)
Out[8]:
Pipeline(steps=[('imputer', Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)), ('pca', PCA(copy=True, n_components=2, whiten=False))])

__标识在Python社区读作dunder

这里n_components=2pca本身的参数。我们再演示一下,输出将是一个$N \times 2$维矩阵:

In [9]:
iris_data_transformed3 = pipe2.fit_transform(iris_data)
iris_data_transformed3[:5]
Out[9]:
array([[-2.44, -0.79],
       [-2.67,  0.2 ],
       [-2.83,  0.31],
       [-2.35,  0.66],
       [-2.68, -0.06]])