# Kaggle 官方教程：机器学习中级4 Pipeline
> 原文：[Intermediate Machine Learning](https://www.kaggle.com/learn/intermediate-machine-learning) > [Pipelines](https://www.kaggle.com/alexisbcook/pipelines)
> 
> 译者：[Leytton](https://github.com/Leytton)
> 
> 协议：[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)

PS：水平有限，欢迎交流指正（Leytton@126.com）

在本教程中，你将学习如何使用`pipeline`来清理你的建模代码。

## 1、介绍
`Pipeline`是一种简单的方法，能让你的数据预处理和建模步骤一步到位。

很多数据科学家没有使用`pipeline`来建模，但`pipeline`有很多重要好处。包含：

 1. 更精简的代码：考虑到数据处理时会造成混乱，使用`pipeline`不需要在每个步骤都特别注意训练和验证数据。
 2. 更少的Bug：错误应用和忘记处理步骤的概率更小。
 3. 更易产品化：把模型转化成规模化发布原型是比较难的，再此我们不做过多讨论，但`pipeline`对这个有帮助。
 4. 模型验证更加多样化：你将会在下一个课程中看到`交叉验证`的案例。

## 2、案例
跟前面教程一样，我们将会使用 [Melbourne Housing 数据集](https://www.kaggle.com/dansbecker/melbourne-housing-snapshot/home)

我们不会关注数据加载步骤。假设你已经拥有了`X_train`、`X_valid`、`y_train`和`y_valid`中的训练和验证数据。

我们先使用`head()`方法瞄一眼训练数据。注意这些数据保护分类数据和缺失数据。使用pipelines将会很方便处理这两者。
```python
X_train.head()
```
输出结果：
```
	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
```
我们通过三个步骤来使用pipelines：

**步骤1：定义处理步骤**

与`pipeline`将预处理与建模步骤打包一样，我们使用`ColumnTransformer`类来将不同的步骤打包在一起。下面的代码做了两件事情：

 - 填充缺失数据为`数值`类型（用均值等方法填充数值类型数据）
 - 用`one-hot`编码来填充`分类`缺失数据

```python
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder

# 预处理数值类型数据
numerical_transformer = SimpleImputer(strategy='constant')

# 预处理分类数据
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])

# 将处理步骤打包
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numerical_transformer, numerical_cols),
        ('cat', categorical_transformer, categorical_cols)
    ])
```

**步骤2：定义模型**

接下来我们使用熟悉的`RandomForestRegressor`类定义一个`随机森林`模型。

```python
from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=100, random_state=0)
```
**步骤3：创建和评估Pipeline**

最后，我们使用`Pipeline`类来定义一个打包预处理和建模步骤的pipeline。这里有些重点需要注意：

 - 使用pipeline，我们预处理训练数据以及拟合模型只有了一行代码。（相反，如果不使用pipeline，我们需要做填充、编码、和模型训练的步骤。如果我们需要同时处理数值和分类变量，这将非常繁琐！）
 - 我们在调用`predict()`指令时使用的`X_valid`中包含未经处理的特征值，pipeline会在预测前自动进行预处理。（然而，如果不使用pipeline，在预测前，我们需要记住对验证数据进行预处理）。

```python
from sklearn.metrics import mean_absolute_error

# 在pipeline中打包预处理和建模代码
my_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                              ('model', model)
                             ])

# 预处理训练数据，拟合模型 
my_pipeline.fit(X_train, y_train)

# 预处理验证数据, 获取预测值
preds = my_pipeline.predict(X_valid)

# 评估模型
score = mean_absolute_error(y_valid, preds)
print('MAE:', score)
```
输出结果：
```
MAE: 160679.18917034855
```
## 3、结论
`Pipeline`在机器学习代码清理和规避错误中，尤其是复杂数据预处理的工作流，非常实用。 

## 4、去吧，皮卡丘
在接下来的[练习](https://www.kaggle.com/kernels/fork/3370278)中，使用`pipeline`来体验高级数据预处理技术并改善你的预测！

