在机器学习项目中,经常遇到数据不一致、缺失值和杂质等问题,这些都需要进行预处理。预处理数据不仅耗时,而且过程复杂。为了简化这一过程,机器学习中引入了流水线(Pipeline)的概念,它允许将所有的预处理步骤串联起来,一步接一步地执行。
在数据预处理的各个步骤中,单独处理看起来对于初学者或参加竞赛是可行的,但当目标是构建一个用于生产的端到端机器学习项目时,就需要在将新数据传递给模型之前先进行预处理,这会耗费大量的重复工作。为了节省这一繁琐的工作,使用流水线。
列转换器是scikit-learn中的一个类,用于为数值和分类数据创建并应用不同的转换器。要创建转换器,需要指定转换器对象,并将转换列表与要应用转换的列一起作为元组传递。
import pandas as pd
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder
from sklearn.model_selection import train_test_split
df = pd.read_csv('covid_toy.csv')
X_train, X_test, y_train, y_test = train_test_split(df.drop(columns=['has_covid']), df['has_covid'], test_size=0.2)
# 创建转换器
from sklearn.compose import ColumnTransformer
transformer = ColumnTransformer(transformers=[
('impute_fever', SimpleImputer(), ['fever']),
('encode_cough', OrdinalEncoder(categories=[['Mild', 'Strong']]), ['cough']),
('encode_gender_city', OneHotEncoder(sparse=False, drop='first'), ['gender', 'city'])
], remainder='passthrough')
x_train_transform = transformer.fit_transform(X_train)
print(x_train_transform[:5])
应用转换后,将得到一个Numpy数组,总共转换了七个列,因为城市列将扩展成四个不同的列。结果数据框将如下所示。
机器学习流水线是一种将多个步骤串联起来,使得每个步骤的输出作为下一个步骤的输入的机制。这意味着它执行一系列步骤,其中第一个转换器的输出成为下一个转换器的输入。
例如,如果正在处理一个包含缺失值和分类变量的混乱数据集的机器学习项目,将首先处理这些问题,然后训练模型。但是使用流水线,可以将这三个步骤串联在一个步骤中,使项目工作流程更加平滑和简单。
# 导入必要的库
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, MinMaxScaler
from sklearn.pipeline import Pipeline
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.tree import DecisionTreeClassifier
df = pd.read_csv('titanic.csv')
# 训练测试集分割
df.drop(columns=['PassengerId', 'Name', 'Ticket', 'Cabin'], inplace=True)
X_train, X_test, y_train, y_test = train_test_split(df.drop(columns=['Survived']), df['Survived'], test_size=0.2, random_state=42)
# 创建转换器
trf1 = ColumnTransformer([
('impute_age', SimpleImputer(), [2]),
('impute_embarked', SimpleImputer(strategy='most_frequent'), [6])
], remainder='passthrough')
trf2 = ColumnTransformer([
('ohe_sex_embarked', OneHotEncoder(sparse=False, handle_unknown='ignore'), [1, 6])
], remainder='passthrough')
trf3 = ColumnTransformer([
('scale', MinMaxScaler(), slice(0, 10))
])
trf4 = SelectKBest(score_func=chi2, k=8)
trf5 = DecisionTreeClassifier()
# 创建流水线
pipe = Pipeline([
('trf1', trf1),
('trf2', trf2),
('trf3', trf3),
('trf4', trf4),
('trf5', trf5)
])
# 拟合数据
pipe.fit(X_train, y_train)