集成学习 集成学习通过组合多个基学习器来获得更好的预测性能

集成学习详解

学习目标

完成本节后,你将能够:

  • 理解集成学习的基本原理
  • 掌握主要集成方法的特点
  • 实现常用的集成算法
  • 优化集成模型的性能
  • 处理实际的集成学习问题

先修知识

学习本节内容需要:

  • Python编程基础
  • 机器学习基础算法
  • 基本的统计学知识
  • 模型评估方法

集成学习基础

基本原理

集成学习通过组合多个基学习器来提高模型性能。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 生成示例数据
X, y = make_classification(n_samples=1000, n_features=20,
                         n_informative=15, n_redundant=5,
                         random_state=42)

# 数据分割
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42)

投票法

from sklearn.ensemble import VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC

def create_voting_classifier():
    """
    创建投票分类器
    """
    # 定义基分类器
    clf1 = LogisticRegression(random_state=42)
    clf2 = RandomForestClassifier(n_estimators=50, random_state=42)
    clf3 = SVC(probability=True, random_state=42)
    
    # 创建投票分类器
    voting_clf = VotingClassifier(
        estimators=[('lr', clf1), ('rf', clf2), ('svc', clf3)],
        voting='soft'
    )
    
    return voting_clf

# 训练和评估
voting_clf = create_voting_classifier()
voting_clf.fit(X_train, y_train)
y_pred = voting_clf.predict(X_test)
print(f'投票分类器准确率: {accuracy_score(y_test, y_pred):.4f}')

Bagging方法

随机森林

def analyze_random_forest():
    """
    分析随机森林的性能
    """
    # 创建随机森林
    rf = RandomForestClassifier(n_estimators=100, random_state=42)
    rf.fit(X_train, y_train)
    
    # 特征重要性分析
    importances = rf.feature_importances_
    indices = np.argsort(importances)[::-1]
    
    plt.figure(figsize=(10, 6))
    plt.title("随机森林特征重要性")
    plt.bar(range(X.shape[1]), importances[indices])
    plt.xticks(range(X.shape[1]), [f'feature {i}' for i in indices], rotation=45)
    plt.tight_layout()
    plt.show()
    
    return rf

# 分析随机森林
rf_clf = analyze_random_forest()

袋外误差估计

def analyze_oob_error():
    """
    分析袋外误差随树数量的变化
    """
    n_estimators = range(1, 100, 5)
    oob_errors = []
    
    for n in n_estimators:
        rf = RandomForestClassifier(n_estimators=n,
                                  oob_score=True,
                                  random_state=42)
        rf.fit(X_train, y_train)
        oob_errors.append(1 - rf.oob_score_)
    
    plt.plot(n_estimators, oob_errors)
    plt.xlabel('树的数量')
    plt.ylabel('OOB错误率')
    plt.title('随机森林OOB错误率分析')
    plt.show()

Boosting方法

AdaBoost

from sklearn.ensemble import AdaBoostClassifier

def analyze_adaboost():
    """
    分析AdaBoost的性能
    """
    # 创建基分类器
    base_clf = DecisionTreeClassifier(max_depth=1)
    
    # 创建AdaBoost分类器
    ada = AdaBoostClassifier(base_estimator=base_clf,
                            n_estimators=100,
                            random_state=42)
    
    # 训练模型
    ada.fit(X_train, y_train)
    
    # 分析学习曲线
    train_scores = []
    test_scores = []
    
    for i in range(1, len(ada.estimators_) + 1):
        ada.n_estimators = i
        ada.fit(X_train, y_train)
        train_scores.append(ada.score(X_train, y_train))
        test_scores.append(ada.score(X_test, y_test))
    
    plt.plot(range(1, len(ada.estimators_) + 1),
             train_scores, label='训练集')
    plt.plot(range(1, len(ada.estimators_) + 1),
             test_scores, label='测试集')
    plt.xlabel('迭代次数')
    plt.ylabel('准确率')
    plt.title('AdaBoost学习曲线')
    plt.legend()
    plt.show()
    
    return ada

梯度提升

from sklearn.ensemble import GradientBoostingClassifier

def analyze_gradient_boosting():
    """
    分析梯度提升的性能
    """
    # 创建梯度提升分类器
    gb = GradientBoostingClassifier(n_estimators=100,
                                  learning_rate=0.1,
                                  max_depth=3,
                                  random_state=42)
    
    # 训练模型
    gb.fit(X_train, y_train)
    
    # 分析特征重要性
    importances = gb.feature_importances_
    indices = np.argsort(importances)[::-1]
    
    plt.figure(figsize=(10, 6))
    plt.title("梯度提升特征重要性")
    plt.bar(range(X.shape[1]), importances[indices])
    plt.xticks(range(X.shape[1]), [f'feature {i}' for i in indices], rotation=45)
    plt.tight_layout()
    plt.show()
    
    return gb

XGBoost

基本使用

import xgboost as xgb

def train_xgboost():
    """
    训练XGBoost模型
    """
    # 创建DMatrix数据格式
    dtrain = xgb.DMatrix(X_train, label=y_train)
    dtest = xgb.DMatrix(X_test, label=y_test)
    
    # 设置参数
    params = {
        'max_depth': 3,
        'eta': 0.1,
        'objective': 'binary:logistic',
        'eval_metric': 'logloss'
    }
    
    # 训练模型
    num_round = 100
    evallist = [(dtrain, 'train'), (dtest, 'test')]
    bst = xgb.train(params, dtrain, num_round, evallist)
    
    return bst

# 训练XGBoost模型
xgb_model = train_xgboost()

参数调优

from sklearn.model_selection import GridSearchCV
from xgboost import XGBClassifier

def tune_xgboost():
    """
    XGBoost参数调优
    """
    xgb_clf = XGBClassifier()
    
    param_grid = {
        'max_depth': [3, 5, 7],
        'learning_rate': [0.01, 0.1, 0.3],
        'n_estimators': [100, 200],
        'subsample': [0.8, 1.0]
    }
    
    grid_search = GridSearchCV(xgb_clf, param_grid, cv=5,
                             scoring='accuracy', n_jobs=-1)
    grid_search.fit(X_train, y_train)
    
    print("最佳参数:", grid_search.best_params_)
    print("最佳得分:", grid_search.best_score_)
    
    return grid_search.best_estimator_

LightGBM

基本使用

import lightgbm as lgb

def train_lightgbm():
    """
    训练LightGBM模型
    """
    # 创建数据集
    train_data = lgb.Dataset(X_train, label=y_train)
    test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)
    
    # 设置参数
    params = {
        'objective': 'binary',
        'metric': 'binary_logloss',
        'num_leaves': 31,
        'learning_rate': 0.05
    }
    
    # 训练模型
    num_round = 100
    bst = lgb.train(params, train_data, num_round,
                    valid_sets=[test_data])
    
    return bst

# 训练LightGBM模型
lgb_model = train_lightgbm()

堆叠集成

实现堆叠

from sklearn.ensemble import StackingClassifier

def create_stacking_classifier():
    """
    创建堆叠集成分类器
    """
    # 定义基分类器
    estimators = [
        ('rf', RandomForestClassifier(n_estimators=100, random_state=42)),
        ('gb', GradientBoostingClassifier(n_estimators=100, random_state=42)),
        ('xgb', XGBClassifier(random_state=42))
    ]
    
    # 定义最终分类器
    final_estimator = LogisticRegression()
    
    # 创建堆叠分类器
    stacking_clf = StackingClassifier(
        estimators=estimators,
        final_estimator=final_estimator,
        cv=5
    )
    
    return stacking_clf

# 训练堆叠分类器
stacking_clf = create_stacking_classifier()
stacking_clf.fit(X_train, y_train)

实战项目:信用卡欺诈检测

数据准备

# 加载信用卡交易数据
from sklearn.preprocessing import StandardScaler

def prepare_fraud_detection_data():
    """
    准备欺诈检测数据
    """
    # 假设我们有信用卡交易数据
    # 实际项目中需要加载真实数据
    X, y = make_classification(n_samples=10000,
                             n_features=30,
                             n_classes=2,
                             weights=[0.98, 0.02],  # 模拟欺诈率2%
                             random_state=42)
    
    # 数据标准化
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    return train_test_split(X_scaled, y, test_size=0.2,
                          random_state=42, stratify=y)

# 准备数据
X_train, X_test, y_train, y_test = prepare_fraud_detection_data()

模型训练与评估

from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns

def train_fraud_detection_model():
    """
    训练欺诈检测模型
    """
    # 创建模型
    model = XGBClassifier(
        max_depth=5,
        learning_rate=0.1,
        n_estimators=200,
        scale_pos_weight=50  # 处理类别不平衡
    )
    
    # 训练模型
    model.fit(X_train, y_train)
    
    # 预测
    y_pred = model.predict(X_test)
    
    # 评估结果
    print("\n分类报告:")
    print(classification_report(y_test, y_pred))
    
    # 绘制混淆矩阵
    plt.figure(figsize=(8, 6))
    sns.heatmap(confusion_matrix(y_test, y_pred), annot=True, fmt='d')
    plt.title('混淆矩阵')
    plt.ylabel('真实标签')
    plt.xlabel('预测标签')
    plt.show()
    
    return model

# 训练欺诈检测模型
fraud_detection_model = train_fraud_detection_model()

练习与作业

  1. 基础练习:

    • 实现简单的Bagging算法
    • 使用不同的基分类器
    • 分析集成大小的影响
  2. 进阶练习:

    • 实现完整的Stacking框架
    • 比较不同集成方法的性能
    • 处理不平衡数据集
  3. 项目实践:

    • 选择一个真实数据集
    • 实现多个集成模型
    • 分析和比较性能

常见问题

Q1: 如何选择合适的集成方法? A1: 需要考虑以下因素:

  • 数据规模和特征数量
  • 计算资源限制
  • 模型可解释性要求
  • 是否存在类别不平衡
  • 是否需要特征重要性分析

Q2: 如何避免过拟合? A2: 可以采用以下方法:

  • 控制基学习器的复杂度
  • 使用交叉验证
  • 调整学习率
  • 使用早停
  • 增加正则化

扩展阅读

下一步学习

  • 深度学习基础
  • 神经网络集成
  • 在线学习
  • 强化学习