Pipeline
构造器规则:需要一个定义步骤顺序的 (名字, 估计器)对的列表。除了最后一个是估计器(estimator),其余都要是转换器(transformer,即要有fit_transform()
方法),名字可以随意取。
名词解释:可参考【Scikit-Learn | 自定义转换器(transformer)】【 fit()、transform()、fit_transform() 三者联系与区别】
所有的转换器都是估计器,但估计器不一定是转换器
一般,当你调用Pipeline的fit()
方法时,就会对所有转换器按顺序调用fit_transform()
方法,将每次调用的输出作为参数传递给下一个调用,一直到最后一个估计器,它只执行fit()
方法。
code 1 :探索执行方法
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
import pandas as pd
data_num = pd.read_csv("filename.csv")
num_pipeline = Pipeline([
('imputer', Imputer(strategy="median")),
('std_scaler', StandardScaler()),
])
data_num_tr = num_pipeline.fit_transform(housing_num)
在code 1中,最后的估计器是一个StandardScaler
,它是一个转换器,因此这个pipeline有一个transform()
方法,可以按顺序对数据做转换。由于它还有一个fit_transform()
方法可以使用,就不必先调用fit()
再进行transform()
。
构建的pipeline可以以一个选择转换器开始,其作用是选择该数据集中要处理的属性(可以是数值变量或分类变量),丢弃其他无用的属性,进而进行下一步操作。尤其是构建处理数值属性和类别属性的pipeline。
我们需要将选择转换器输出值的类别由DataFrame
转变为一个NumPy数组。而Scikit-Learn库没有module来处理Pandas的DataFrame
,因此我们需要写一个简单的自定义转换器来做这项工作。
code 2:搭建一个选择转换器
from sklearn.base import BaseEstimator, TransformerMixin
class DataFrameSelector(BaseEstimator, TransformerMixin):
def __init__(self, attribute_name):
self.attribute_names = attribute_names
def fit(self, X, y=None):
return self
def transform(self, X):
return X[self.attribute_names].values
code 3: 构建pipeline
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
# 建立一个处理数据值中含数值变量(处理残缺值和特征标准化)的列的pipeline
num_pipeline = Pipeline([
('selector', DataFrameSelector(num_attribs)),
('imputer', Imputer(strategy="median")),
('std_scaler', StandardScaler())
])
# 建立一个处理数据集中含类别变量(标签编码)的列的pipeline
cat_pipeline = Pipeline([
('selector', DataFrameSelector(cat_attribs)),
('onehot', OneHotEncoder(handle_unknown='ignore')),
])
名词解释: 可参考【处理残缺值(Missing value)python-sklearn实现| 三种常用方法】【处理类别变量(categorical variable)python-sklearn实现 | 三种常用方法】
Scikit-Learnti提供一个类FeatureUnion
来将不同的pipeline连接在一起。当调用合并后的pipeline的transform()
方法时,每个转换器的transform()
会被并行执行,等待输出,然后将输出合并起来,并返回结果(当然,调用它的fit()
方法就会调用每个转换器的fit()
方法)。
code 4: 连接pipeline
from sklearn.pipeline import FeatureUnion
# 一个能处理数据集中含数值属性和类别属性的列的pipeline
full_pipeline = FeatureUnion(transformer_list=[
('num_pipeline', num_pipeline),
('cat_pipeline', cat_pipeline),
])
code 5: 运行pipeline
import pandas as pd
# 读取数据
data = pd.read_csv('filename.csv')
# 数据预处理,处理数据集中含有数值属性和类别属性的列
data_prepared = full_pipeline.fit_transform(data)
在Scikit-Learn 0.20中,ColumnTransformer
类同时具有DataFrameSelector
类和FeatureUnion
类的功能。
Code 6
try:
from sklearn.compose import ColumnTransformer
except ImportError:
from future_encoders import ColumnTransformer # Scikit-Learn < 0.20
# 分别获得数据集data中数值属性和类别属性的列名
num_attribs = ['num_1', 'num_2']
cat_attribs = ['cat_1', 'cat_2']
full_pipeline = ColumnTransformer([
("num", num_pipeline, num_attribs),
("cat", OneHotEncoder(), cat_attribs),
])
data_prepared = full_pipeline.fit_transform(data)
参考资料:
《Hands-on Machine Learning with Scikit-Learn and TensorFlow》