[机器学习]pipeline(模型训练实战)

302 阅读3分钟

以下是一个完整的随机森林算法 Pipeline 示例代码,涵盖数据预处理、特征工程、模型训练和评估的全流程。

代码使用 scikit-learnPipelineColumnTransformer,并处理混合类型(数值型 + 分类型)特征。


import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.metrics import accuracy_score

# 生成示例数据集(包含数值型和分类型特征)
data = {
    'age': [25, 30, np.nan, 45, 35, 28, 50, 31],
    'income': [50000, 80000, 60000, np.nan, 120000, 45000, 95000, 77000],
    'gender': ['M', 'F', 'F', 'M', 'M', 'F', np.nan, 'M'],
    'education': ['Bachelor', 'Master', 'PhD', 'Bachelor', np.nan, 'Master', 'PhD', 'Bachelor'],
    'purchased': [1, 0, 1, 0, 1, 0, 1, 1]  # 目标变量
}
df = pd.DataFrame(data)

# 划分特征和目标列
X = df.drop('purchased', axis=1)
y = df['purchased']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义数值型和分类型特征列
numeric_features = ['age', 'income']
categorical_features = ['gender', 'education']

# 数值型特征处理管道
numeric_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='median')),  # 填充缺失值
    ('scaler', StandardScaler())                    # 标准化(虽然随机森林不必须,但展示用法)
])

# 分类型特征处理管道
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),  # 填充缺失值
    ('onehot', OneHotEncoder(handle_unknown='ignore'))     # 独热编码
])

# 组合特征处理器
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numeric_transformer, numeric_features),
        ('cat', categorical_transformer, categorical_features)
    ])

# 完整Pipeline(特征处理 + 随机森林)
pipeline = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier(
        n_estimators=100,
        max_depth=5,
        random_state=42
    ))
])

# 训练模型
pipeline.fit(X_train, y_train)

# 预测并评估
y_pred = pipeline.predict(X_test)
print(f"Test Accuracy: {accuracy_score(y_test, y_pred):.2f}")

# 输出特征重要性(需要从Pipeline中提取预处理后的特征名)
onehot_columns = pipeline.named_steps['preprocessor'].named_transformers_['cat'].named_steps['onehot'].get_feature_names_out(categorical_features)
all_features = numeric_features + list(onehot_columns)

importances = pipeline.named_steps['classifier'].feature_importances_
print("\nFeature Importances:")
for feature, importance in zip(all_features, importances):
    print(f"{feature}: {importance:.4f}")

代码解析

1. 数据准备

  • 创建包含混合类型特征的示例数据:

    • 数值型age(含缺失值)、income(含缺失值)
    • 分类型gender(含缺失值)、education(含缺失值)
    • 目标变量purchased(二分类)

2. 特征处理

  • 数值型特征

    • 使用 SimpleImputer 用中位数填充缺失值
    • 使用 StandardScaler 标准化(尽管随机森林不需要,但展示通用写法)
  • 分类型特征

    • 使用 SimpleImputer 用众数填充缺失值
    • 使用 OneHotEncoder 进行独热编码

3. Pipeline 结构


Pipeline(
    # 特征预处理
    preprocessor = ColumnTransformer([
        num → [Imputer → Scaler],
        cat → [Imputer → OneHotEncoder]
    ]),
    
    # 随机森林模型
    classifier = RandomForestClassifier()
)

4. 核心优势

  • 自动化流程:从原始数据到预测结果的全流程自动化处理
  • 避免数据泄露:确保预处理仅基于训练数据统计量
  • 可维护性:清晰的步骤分离,便于修改和调试
  • 特征重要性:支持提取预处理后的特征名称与重要性对应

输出示例

Test Accuracy: 0.50

Feature Importances:
age: 0.3250
income: 0.2500
gender_F: 0.0250
gender_M: 0.1250
education_Bachelor: 0.1000
education_Master: 0.0500
education_PhD: 0.1250

扩展使用

  1. 超参数调优(使用 GridSearchCV):
from sklearn.model_selection import GridSearchCV

param_grid = {
    'classifier__n_estimators': [50, 100, 200],
    'classifier__max_depth': [3, 5, None]
}

search = GridSearchCV(pipeline, param_grid, cv=3)
search.fit(X_train, y_train)
print(f"Best params: {search.best_params_}")
  1. 处理更复杂数据
  • 添加 FunctionTransformer 自定义特征工程
  • 使用 OrdinalEncoder 处理有序分类特征
  • 集成特征选择组件(如 SelectKBest
  1. 部署模型

# 保存模型
import joblib
joblib.dump(pipeline, 'rf_pipeline.pkl')

# 加载模型
loaded_pipeline = joblib.load('rf_pipeline.pkl')
loaded_pipeline.predict(X_new)