Pipeline类不但可以用于预处理和分类,实际上还可以将任意数量的估计器链接在一起。如:可以构建一个包含特征提取、特征选择、缩放和分类的管道,同时也可以使用归回或聚类替代分类。而该使用管道中的估计器唯一的要求就是除了最后一步之外的所有步骤都具有transform方法,这样它可以生成新的数据表示,以提供下一个步骤使用。
在调用Pipeline的过程中,管道内部一次对每个步骤调用fit和transform(或者fit_transform),其输入是前一个步骤中transform方法的输出,对于管道中的最后一步,则仅调用fit(或fit_transform)。
这里需要注意的是,pipeline.steps是由元组组成的列表,所以pipeline.steps[0][1]是一个估计器,pipeline.steps[1][1]是第二个估计器,以此类推(具体过程fit和fit_transform如下):
def fit(self, x, y):
x_transformed = x
for name, estimator in self.steps[:,-1]:
#遍历除最后一步之外的所有步骤
#对数据进行拟合交换
x_transformed = estimator.fit_transform(x_transformed, y)
#对最后一步进行拟合
self.steps[-1][1].fit(x_transformed, y)
return self
#使用Pipeline进行预测时,我们同样利用除最后一步以外的所有步骤对数据进行变换(transform),
#最后一步调用predict
def predict(self, x):
x_transformed = x
for step in self.steps[:,-1]:
#遍历除最后一步之外的所有步骤
#对数据进行拟合交换
x_transformed = step[1].fit_transform(x_transformed)
#对最后一步进行拟合
return self.steps[-1][1].fit(x_transformed)
上述是构造管道训练和预测的一般过程展示,不过管道实际上最后一步不需要具有predict函数,就如我们可以创建一个只包含一个缩放器和一个PCA的管道,由于最后一步PCA具有transform方法,所以我们可以对管道调用transform,以得到PCA.transform应用于前一个步骤处理过的数据后得到的输出。所以管道的最后一步只需要具有fit方法。
利用make_pipeline更加方便地创建管道:利用上述方法创建管道相对比较麻烦,我们一般不需要为每一个步骤提供用户指定的名称,所以可以通过make_pipeline很快捷的为我们创建管道并根据每个步骤所属的类为其自动命名,make_pipeline的具体语法如下所示:
from sklearn.pipeline import make_pipeline
#标准与法
pipe_long = Pipeline([("scaler", MinMaxScaler()), ("svm", SVC(C=100))])
#缩写语法
pipe_short = make_pipeline(MinMaxScaler(), SVC(C=100))
上述两个管道对象pipe_long和pipe_short作用完全相同,但pipe_short的步骤是自动命名的,我们可以通过steps属性来查看步骤名称:
print("Pipeline steps:{}".format(pipe_short.steps))
运行后可以查看到其对应的步骤名称为:
这两个步骤被命名为minmaxscaler和svc,一般来说,步骤名称是类名称的小写版本,如果多个步骤属于同一个类,则会附加一个数字,如下:
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
pipe = make_pipeline(StandardScaler(), PCA(n_components=2), StandardScaler())
print("Pipeline steps of the same classes:{}".format(pipe.steps))
运行后其对应的steps内容如下:
由运行结果可见,第一个standardscaler步骤被命名为standardscaler-1,第二个被命名为standardscaler-2.在这种情况下,使用具有具体名称的pipeline构建可能会更好(即直接使用Pipeline函数来创建管道,手动指定对应的名称),以便于为每个步骤提供更具有实际意义的名称。
访问步骤属性:通常来说,我们希望检查管道中某一步骤的属性——比如线性模型的系数或PCA提供的成分,要想访问管道中的步骤,最简单的方法是通过named_steps属性,它是一个字典,将步骤名称映射为估计器:
#用前面定义的管道对cancer数据集进行拟合
pipe.fit(cancer.data)
#从“pca“步骤中提取两个主成分
components = pipe.named_steps["pca"].components_
print("components shape is: {}".format(components.shape))
运行后得到的步骤属性字典为:
components shape is: (2, 30)