机器学习中级教程
在本教程中,您将学习如何使用管道来优化建模代码。
正文
介绍
管道是保持数据预处理和建模代码井然有序的一种简单方法。具体来说,管道将预处理和建模步骤捆绑在一起,这样您就可以像使用单个步骤一样使用整个包。
许多数据科学家在没有管道的情况下拼凑模型,但管道有一些重要的好处。这些措施包括:
- 更干净的代码:在预处理的每一步计算数据可能会变得混乱。有了管道,你不需要在每一步都手动跟踪你的训练和验证数据。
- 更少的bug:误用步骤或忘记预处理步骤的机会更少。
- 产品化更容易:将模型从原型转换为可大规模部署的模型可能会出人意料地困难。我们不会在这里讨论很多相关的问题,但管道可以提供帮助。
- 模型验证的更多选项:您将在下一个教程中看到一个例子,其中涉及交叉验证。
举例
与上一篇教程一样,我们将使用墨尔本住房数据集。
我们将不关注数据加载步骤。相反,您可以想象,您已经在X_train、X_valid、y_train和y_valid中拥有了训练和验证数据。
我们用下面的head()方法查看一下训练数据。请注意,数据既包含分类数据,也包含缺少值的列。有了管道,两者都很容易处理!
X_train.head()
我们分三个步骤构建完整的管道。
第1步:定义预处理步骤
与管道将预处理步骤和建模步骤捆绑在一起的方式类似,我们使用 ColumnTransformer
类将不同的预处理步骤捆绑在一起。下面的代码:
- 在数值数据中计算缺失的值
- 估算缺失值,并对分类数据应用热编码。
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)
])
MAE: 17621.3197260274
如果不是以上这个值,系统会提示你做进一步修改,修改A部分的内容
第2步骤:生成测试预测
现在,您将使用经过训练的模型,用测试数据生成预测。
# Preprocessing of test data, fit model
# 预处理测试数据进行预测
preds_test = ____ # Your code here
# Check your answer
step_2.check()
第3步:创建并评估管道
最后,我们使用Pipeline类定义一个管道,该管道将预处理和建模步骤捆绑在一起。有几件重要的事情需要注意:
- 通过管道,我们对训练数据进行预处理,并在一行代码中拟合模型。(相比之下,如果没有管道,我们必须在单独的步骤中进行插补、一次热编码和模型训练。如果我们必须同时处理数字和分类变量,这会变得特别混乱!)
- 通过管道,我们在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
结论
管道对于清理机器学习代码和避免错误很有价值,对于具有复杂数据预处理的工作流尤其有用。
轮到你了
在下一个练习中使用管道来使用先进的数据预处理技术并改进您的预测!
练习部分
在本练习中,您将使用管道来提高机器学习代码的效率。
设置
下面的问题将为你的工作提供反馈。运行以下单元格设置反馈系统。
# Set up code checking
import os
if not os.path.exists("../input/train.csv"):
os.symlink("../input/home-data-for-ml-course/train.csv", "../input/train.csv")
os.symlink("../input/home-data-for-ml-course/test.csv", "../input/test.csv")
from learntools.core import binder
binder.bind(globals())
from learntools.ml_intermediate.ex4 import *
print("Setup Complete")
Setup Complete
您将使用来自 Housing Prices Competition for Kaggle Learn Users 案例.
。
在不做任何更改的情况下运行以下代码单元,以加载X_train、X_valid、y_train和y_valid中的训练集和验证集。测试集在X_test中加载。
import pandas as pd
from sklearn.model_selection import train_test_split
# Read the data
X_full = pd.read_csv('../input/train.csv', index_col='Id')
X_test_full = pd.read_csv('../input/test.csv', index_col='Id')
# Remove rows with missing target, separate target from predictors
X_full.dropna(axis=0, subset=['SalePrice'], inplace=True)
y = X_full.SalePrice
X_full.drop(['SalePrice'], axis=1, inplace=True)
# Break off validation set from training data
X_train_full, X_valid_full, y_train, y_valid = train_test_split(X_full, 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()
X_test = X_test_full[my_cols].copy()
X_train.head()
下一个代码单元使用教程中的代码预处理数据并训练模型。运行此代码,不做任何更改。
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_error
# 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)
])
# Define model
# 定义模型
model = RandomForestRegressor(n_estimators=100, random_state=0)
# Bundle preprocessing and modeling code in a pipeline
# 将预处理和建立模型打包成一个管道
clf = Pipeline(steps=[('preprocessor', preprocessor),
('model', model)
])
# Preprocessing of training data, fit model
# 预处理训练数据,拟合模型
clf.fit(X_train, y_train)
# Preprocessing of validation data, get predictions
# 预处理验证数据,预测结果
preds = clf.predict(X_valid)
print('MAE:', mean_absolute_error(y_valid, preds))
MAE: 17861.780102739725
代码生成的平均绝对误差(MAE)值约为17862。在下一步中,您将修改代码以做得更好。
第1步:提高绩效
A 部分
现在轮到你了!在下面的代码单元中,定义自己的预处理步骤和随机林模型。填写以下变量的值:
- 数值型转换
- 分类型转换
- 模型
要通过这部分练习,只需定义有效的预处理步骤和随机林模型。
# Preprocessing for numerical data
# 预处理数值型数据
numerical_transformer = ____ # Your code here
# Preprocessing for categorical data
# 预处理分类型数据
categorical_transformer = ____ # Your code here
# Bundle preprocessing for numerical and categorical data
# 将数值型和分类型捆绑一起进行预处理
preprocessor = ColumnTransformer(
transformers=[
('num', numerical_transformer, numerical_cols),
('cat', categorical_transformer, categorical_cols)
])
# Define model
# 定义模型
model = ____ # Your code here
# Check your answer
step_1.a.check()
B 部分
运行下面的代码单元格,不做任何更改。
要通过这一步,您需要在a部分中定义一个管道,该管道的MAE低于上述代码。我们鼓励你在这里慢慢来,尝试许多不同的方法,看看你能得到多低的MAE!(如果您的代码没有通过,请修改A部分中的预处理步骤和模型。)
运行下一个代码单元以获取此方法的MAE。
# 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)
# Check your answer
step_1.b.check()
MAE: 17621.3197260274
第2步:生成测试预测
现在,您将使用经过训练的模型,用测试数据生成预测。
# Preprocessing of test data, fit model
preds_test = ____ # Your code here
# Check your answer
step_2.check()
运行下一个代码单元,不做任何更改,将结果保存到CSV文件中,该文件可以直接提交给竞赛。
# Save test predictions to file
output = pd.DataFrame({'Id': X_test.index,
'SalePrice': preds_test})
output.to_csv('submission.csv', index=False)
提交结果
一旦你成功完成了第二步,你就可以将结果提交到排行榜了!如果您选择这样做,请单击此链接上的“加入竞争”按钮,确保您已加入竞争。
首先单击窗口右上角的“保存版本”按钮。这将生成一个弹出窗口。
确保选择了“全部保存并运行”选项,然后单击“保存”按钮。
这将在笔记本的左下角生成一个窗口。完成运行后,单击“保存版本”按钮右侧的数字。这会在屏幕右侧显示一个版本列表。点击省略号(…)在最新版本的右侧,选择“在查看器中打开”。这将使您进入同一页面的查看模式。您需要向下滚动才能返回这些说明。
单击屏幕右侧的“输出”选项卡。然后,点击你想提交的文件,点击提交按钮,将结果提交到排行榜。
您现在已成功提交竞赛!
如果您想继续工作以提高性能,请选择屏幕右上角的编辑按钮。然后您可以更改代码并重复该过程。还有很大的改进空间,你将在工作中登上排行榜。
继续前进
继续学习交叉验证,这是一种可以用来获得更准确的模型性能估计的技术!
答案
### step 1_a
# Preprocessing for numerical data
numerical_transformer = SimpleImputer(strategy='constant')
# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant')),
('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)
])
# Define model
model = RandomForestRegressor(n_estimators=100, random_state=0)
# step 1_b
# Preprocessing of test data, fit model
preds_test = my_pipeline.predict(X_test)
# step 2
# Preprocessing of test data, fit model
preds_test = my_pipeline.predict(X_test)