简介
许多数据科学家在没有管道的情况下拼凑模型,但管道有一些重要的好处。其中包括
- 更简洁的代码:在预处理的每个步骤中计算数据可能会变得混乱。使用管道,您将不需要在每个步骤手动跟踪您的训练和验证数据。
- 更少的bug:错误应用步骤或忘记预处理步骤的机会更少。
- 更容易生产:将模型从原型转换为可大规模部署的东西可能非常困难。我们不会在这里讨论许多相关的问题,但管道可以提供帮助。
- 模型验证的更多选项:您将在下一个教程中看到一个示例,它涵盖了交叉验证。
例子
我们继续使用Melbourne Housing 数据集.
我们将不关注数据加载步骤。相反,您可以想象自己已经有了 X_train
, X_valid
, y_train
, 和 y_valid
. 中的训练和验证数据。
import pandas as pd from sklearn.model_selection import train_test_split # Read the data data = pd.read_csv('melbourne-housing-snapshot/melb_data.csv') # Separate target from predictors y = data.Price X = data.drop(['Price'], axis=1) # Divide data into training and validation subsets X_train_full, X_valid_full, y_train, y_valid = train_test_split(X, y, train_size=0.8, test_size=0.2, random_state=0) # "Cardinality" means the number of unique values in a column # Select categorical columns with relatively low cardinality (convenient but arbitrary) categorical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].nunique() < 10 and X_train_full[cname].dtype == "object"] # Select numerical columns numerical_cols = [cname for cname in X_train_full.columns if X_train_full[cname].dtype in ['int64', 'float64']] # Keep selected columns only my_cols = categorical_cols + numerical_cols X_train = X_train_full[my_cols].copy() X_valid = X_valid_full[my_cols].copy()
我们用下面的head()方法查看一下训练数据。注意,数据既包含类别数据,也包含缺少值的列。使用管道,可以很容易地处理这两个问题!
X_train.head()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
Type | Method | Regionname | Rooms | Distance | Postcode | Bedroom2 | Bathroom | Car | Landsize | BuildingArea | YearBuilt | Lattitude | Longtitude | Propertycount | |
12167 | u | S | Southern Metropolitan | 1 | 5.0 | 3182.0 | 1.0 | 1.0 | 1.0 | 0.0 | NaN | 1940.0 | -37.85984 | 144.9867 | 13240.0 |
6524 | h | SA | Western Metropolitan | 2 | 8.0 | 3016.0 | 2.0 | 2.0 | 1.0 | 193.0 | NaN | NaN | -37.85800 | 144.9005 | 6380.0 |
8413 | h | S | Western Metropolitan | 3 | 12.6 | 3020.0 | 3.0 | 1.0 | 1.0 | 555.0 | NaN | NaN | -37.79880 | 144.8220 | 3755.0 |
2919 | u | SP | Northern Metropolitan | 3 | 13.0 | 3046.0 | 3.0 | 1.0 | 1.0 | 265.0 | NaN | 1995.0 | -37.70830 | 144.9158 | 8870.0 |
6043 | h | S | Western Metropolitan | 3 | 13.3 | 3020.0 | 3.0 | 1.0 | 2.0 | 673.0 | 673.0 | 1970.0 | -37.76230 | 144.8272 | 4217.0 |
分三步构建完整的管道。
步骤1:定义预处理
与管道将预处理和建模步骤捆绑在一起的方式类似,我们使用“ColumnTransformer”类将不同的预处理步骤捆绑在一起。下面的代码
- 在数值数据中计算缺失值,并且
- 计算缺失值并对分类数据应用one-hot编码。
from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import OneHotEncoder # Preprocessing for numerical data numerical_transformer = SimpleImputer(strategy='constant') # Preprocessing for categorical data categorical_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='most_frequent')), ('onehot', OneHotEncoder(handle_unknown='ignore')) ]) # Bundle preprocessing for numerical and categorical data preprocessor = ColumnTransformer( transformers=[ ('num', numerical_transformer, numerical_cols), ('cat', categorical_transformer, categorical_cols) ])
步骤3:定义模型
接下来,我们定义一个随机森林模型RandomForestRegressor
。
from sklearn.ensemble import RandomForestRegressor model = RandomForestRegressor(n_estimators=100, random_state=0)
步骤3:创建和评估管道
最后,我们使用 Pipeline
类,定义一个将预处理和建模步骤捆绑在一起的管道。有几件重要的事情需要注意:
- 使用管道,我们预处理训练数据并在一行代码中拟合模型。(相比之下,如果没有管道,我们必须在单独的步骤中进行imputation, one-hot编码和模型训练。如果我们必须同时处理数值变量和分类变量,这会变得特别混乱!)
- 使用管道,我们将' X_valid '中未处理的特征提供给' predict() '命令,并且管道在生成预测之前自动预处理特征。(但是,如果没有管道,我们必须记住在进行预测之前对验证数据进行预处理。)
from sklearn.metrics import mean_absolute_error # Bundle preprocessing and modeling code in a pipeline my_pipeline = Pipeline(steps=[('preprocessor', preprocessor), ('model', model) ]) # Preprocessing of training data, fit model my_pipeline.fit(X_train, y_train) # Preprocessing of validation data, get predictions preds = my_pipeline.predict(X_valid) # Evaluate the model score = mean_absolute_error(y_valid, preds) print('MAE:', score)
MAE: 160679.18917034855
结论
管道对于清理机器学习代码和避免错误很有价值,对于具有复杂数据预处理的工作流尤其有用。