2026/2/17 7:29:45
网站建设
项目流程
宁波好品质品牌网站设计哪家好,微网站 微信,网站后台上传图片大小,专做高中知识的网站前言 大家好#xff01;今天给大家带来机器学习中非常重要的一个章节 —— 集成学习。集成学习可以说是工业界最常用的机器学习算法之一#xff0c;像随机森林、GBDT、XGBoost 这些经典模型都属于集成学习的范畴。本文会从基础概念到实战应用#xff0c;一步步带你吃透集成学…前言大家好今天给大家带来机器学习中非常重要的一个章节 —— 集成学习。集成学习可以说是工业界最常用的机器学习算法之一像随机森林、GBDT、XGBoost这些经典模型都属于集成学习的范畴。本文会从基础概念到实战应用一步步带你吃透集成学习所有代码都可直接运行还包含可视化对比图让你直观理解每个知识点5.1 集成学习基本知识5.1.1 集成学习基本概念集成学习Ensemble Learning的核心思想非常简单三个臭皮匠顶个诸葛亮。它通过构建并组合多个学习器基学习器来完成学习任务最终的预测结果由多个基学习器共同决定以此来获得比单个学习器更优的泛化性能。举个生活中的例子你要判断一部电影好不好看只问一个人的意见可能很片面但如果问 10 个不同背景、不同喜好的人综合他们的意见判断会准确得多。集成学习就是这个道理。5.1.2 集成学习基本范式5.1.3 集成学习泛化策略集成学习能提升泛化能力的关键是基学习器要有 “差异性” 且 “性能不差”。常用的泛化策略包括样本扰动对训练集进行随机采样如 Bagging 的自助采样特征扰动对特征集进行随机选择如随机森林的随机特征参数扰动对模型参数进行随机初始化如不同的神经网络初始权重算法扰动使用不同的基学习器算法如同时用决策树、SVM、逻辑回归5.2 Bagging 集成学习5.2.1 Bagging 集成策略BaggingBootstrap Aggregating的核心流程核心特点并行训练训练效率高降低方差有效防止过拟合对噪声数据不敏感5.2.2 随机森林模型结构随机森林Random Forest, RF是 Bagging 的典型代表其模型结构基学习器决策树CART 树为主样本采样自助采样Bootstrap约 37% 的样本不会被采样到袋外样本 OOB特征采样每个节点分裂时随机选择部分特征进行最优分裂集成方式分类任务用投票法回归任务用平均法5.2.3 随机森林训练算法下面是完整的随机森林实战代码包含单决策树 vs 随机森林的效果对比import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_moons from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score # 设置中文字体避免中文乱码 plt.rcParams[font.sans-serif] [SimHei] # 黑体 plt.rcParams[axes.unicode_minus] False # 解决负号显示问题 # 1. 生成模拟数据月牙形数据带噪声 X, y make_moons(n_samples1000, noise0.3, random_state42) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 2. 训练单决策树模型 dt_model DecisionTreeClassifier(random_state42) dt_model.fit(X_train, y_train) dt_pred dt_model.predict(X_test) dt_acc accuracy_score(y_test, dt_pred) # 3. 训练随机森林模型 rf_model RandomForestClassifier(n_estimators100, # 100棵决策树 max_featuressqrt, # 特征采样数为sqrt(特征数) random_state42) rf_model.fit(X_train, y_train) rf_pred rf_model.predict(X_test) rf_acc accuracy_score(y_test, rf_pred) # 4. 可视化决策边界对比 # 生成网格数据 x1_min, x1_max X[:, 0].min() - 0.5, X[:, 0].max() 0.5 x2_min, x2_max X[:, 1].min() - 0.5, X[:, 1].max() 0.5 xx1, xx2 np.meshgrid(np.linspace(x1_min, x1_max, 200), np.linspace(x2_min, x2_max, 200)) # 定义绘图函数 def plot_decision_boundary(model, X, y, ax, title): # 预测网格点 Z model.predict(np.c_[xx1.ravel(), xx2.ravel()]) Z Z.reshape(xx1.shape) # 绘制决策边界 ax.contourf(xx1, xx2, Z, alpha0.8, cmapplt.cm.Spectral) # 绘制样本点 ax.scatter(X[:, 0], X[:, 1], cy, s20, edgecolork, cmapplt.cm.Spectral) ax.set_xlabel(特征1) ax.set_ylabel(特征2) ax.set_title(title) # 创建子图 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12, 5)) # 绘制单决策树边界 plot_decision_boundary(dt_model, X_test, y_test, ax1, f单决策树 (准确率: {dt_acc:.4f})) # 绘制随机森林边界 plot_decision_boundary(rf_model, X_test, y_test, ax2, f随机森林 (准确率: {rf_acc:.4f})) plt.tight_layout() plt.show() # 输出袋外分数OOB rf_model_oob RandomForestClassifier(n_estimators100, oob_scoreTrue, random_state42) rf_model_oob.fit(X, y) print(f随机森林袋外分数OOB: {rf_model_oob.oob_score_:.4f})代码说明make_moons生成非线性可分的月牙形数据模拟真实场景中的复杂数据DecisionTreeClassifier单决策树模型对比基准RandomForestClassifier随机森林模型n_estimators指定树的数量决策边界可视化直观展示随机森林比单决策树的边界更平滑过拟合更少OOB 分数无需单独划分验证集用袋外样本评估模型泛化能力运行效果单决策树准确率约 88% 左右随机森林准确率约 95% 左右随机森林的决策边界更平滑泛化能力更强袋外分数接近测试集准确率验证了模型的可靠性5.3 Boosting 集成学习5.3.1 Boosting 集成策略Boosting 的核心思想是 “知错就改”先训练一个基学习器然后关注它预测错误的样本调整样本权重再训练下一个基学习器直到达到指定的基学习器数量。Boosting 核心流程核心特点串行训练训练效率低于 Bagging降低偏差能拟合更复杂的模式对噪声数据敏感容易过拟合5.3.2 AdaBoost 集成学习算法AdaBoostAdaptive Boosting是最经典的 Boosting 算法下面是完整实战代码包含AdaBoost vs 随机森林的效果对比import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.ensemble import AdaBoostClassifier, RandomForestClassifier from sklearn.metrics import classification_report, roc_curve, auc # 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 1. 生成分类数据 X, y make_classification(n_samples1000, n_features20, n_informative15, n_redundant5, random_state42) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 2. 训练AdaBoost模型 ada_model AdaBoostClassifier(n_estimators50, # 50个基学习器 learning_rate1.0, # 学习率 random_state42) ada_model.fit(X_train, y_train) # 3. 训练随机森林模型对比 rf_model RandomForestClassifier(n_estimators50, random_state42) rf_model.fit(X_train, y_train) # 4. 预测与评估 ada_pred ada_model.predict(X_test) rf_pred rf_model.predict(X_test) # 输出分类报告 print(*50) print(AdaBoost分类报告) print(classification_report(y_test, ada_pred)) print(*50) print(随机森林分类报告) print(classification_report(y_test, rf_pred)) # 5. 绘制ROC曲线对比 # 计算概率 ada_proba ada_model.predict_proba(X_test)[:, 1] rf_proba rf_model.predict_proba(X_test)[:, 1] # 计算ROC曲线 ada_fpr, ada_tpr, _ roc_curve(y_test, ada_proba) rf_fpr, rf_tpr, _ roc_curve(y_test, rf_proba) # 计算AUC ada_auc auc(ada_fpr, ada_tpr) rf_auc auc(rf_fpr, rf_tpr) # 绘制对比图 plt.figure(figsize(10, 6)) plt.plot(ada_fpr, ada_tpr, labelfAdaBoost (AUC {ada_auc:.4f}), linewidth2) plt.plot(rf_fpr, rf_tpr, labelf随机森林 (AUC {rf_auc:.4f}), linewidth2) plt.plot([0, 1], [0, 1], k--, label随机猜测, linewidth1) plt.xlabel(假阳性率 (FPR)) plt.ylabel(真阳性率 (TPR)) plt.title(AdaBoost vs 随机森林 ROC曲线对比) plt.legend(loclower right) plt.grid(True, alpha0.3) plt.show() # 6. 绘制学习曲线基学习器数量 vs 准确率 train_scores_ada [] test_scores_ada [] n_estimators_range range(10, 101, 10) for n in n_estimators_range: ada AdaBoostClassifier(n_estimatorsn, random_state42) ada.fit(X_train, y_train) train_scores_ada.append(ada.score(X_train, y_train)) test_scores_ada.append(ada.score(X_test, y_test)) # 绘制学习曲线 plt.figure(figsize(10, 6)) plt.plot(n_estimators_range, train_scores_ada, o-, label训练集准确率, linewidth2) plt.plot(n_estimators_range, test_scores_ada, s-, label测试集准确率, linewidth2) plt.xlabel(基学习器数量) plt.ylabel(准确率) plt.title(AdaBoost学习曲线基学习器数量影响) plt.legend() plt.grid(True, alpha0.3) plt.show()代码说明make_classification生成高维分类数据更贴近真实场景AdaBoostClassifierAdaBoost 模型n_estimators指定基学习器数量learning_rate控制权重更新幅度ROC 曲线对比 AdaBoost 和随机森林的分类性能AUC 值越高性能越好学习曲线展示基学习器数量对 AdaBoost 性能的影响运行效果AdaBoost 的 AUC 值通常在 0.9 以上表现优秀随着基学习器数量增加AdaBoost 的训练准确率逐渐升高测试准确率先升后稳AdaBoost 对高维数据的拟合能力较强但要注意过拟合5.3.3 GBDT 集成学习算法GBDTGradient Boosting Decision Tree是梯度提升树是工业界的 “明星算法”。下面是完整实战代码包含GBDT vs XGBoost的效果对比import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_diabetes from sklearn.model_selection import train_test_split, cross_val_score from sklearn.ensemble import GradientBoostingRegressor from sklearn.metrics import mean_squared_error, r2_score import xgboost as xgb # 修复中文字体和上标显示问题 plt.rcParams[font.sans-serif] [Microsoft YaHei, SimHei, DejaVu Sans] # 增加备选字体 plt.rcParams[axes.unicode_minus] False plt.rcParams[font.family] sans-serif # 1. 加载数据集糖尿病回归数据集 data load_diabetes() X data.data y data.target feature_names data.feature_names # 划分数据集 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) # 2. 训练GBDT模型 gbdt_model GradientBoostingRegressor(n_estimators100, # 100棵树 learning_rate0.1, # 学习率 max_depth3, # 树最大深度 random_state42) gbdt_model.fit(X_train, y_train) # 3. 训练XGBoost模型对比 xgb_model xgb.XGBRegressor(n_estimators100, learning_rate0.1, max_depth3, random_state42, verbosity0) # 关闭XGBoost的冗余输出 xgb_model.fit(X_train, y_train) # 4. 预测与评估 gbdt_pred gbdt_model.predict(X_test) xgb_pred xgb_model.predict(X_test) # 计算评估指标 gbdt_mse mean_squared_error(y_test, gbdt_pred) gbdt_r2 r2_score(y_test, gbdt_pred) xgb_mse mean_squared_error(y_test, xgb_pred) xgb_r2 r2_score(y_test, xgb_pred) # 输出评估结果 print(*50) print(GBDT模型评估) print(f均方误差 (MSE): {gbdt_mse:.4f}) print(f决定系数 (R^2): {gbdt_r2:.4f}) # 用R^2替代R² print(*50) print(XGBoost模型评估) print(f均方误差 (MSE): {xgb_mse:.4f}) print(f决定系数 (R^2): {xgb_r2:.4f}) # 5. 特征重要性可视化 plt.figure(figsize(12, 6)) # 创建子图 ax1 plt.subplot(1, 2, 1) # GBDT特征重要性 importances_gbdt gbdt_model.feature_importances_ indices_gbdt np.argsort(importances_gbdt) ax1.barh(range(len(indices_gbdt)), importances_gbdt[indices_gbdt], aligncenter) ax1.set_yticks(range(len(indices_gbdt))) ax1.set_yticklabels([feature_names[i] for i in indices_gbdt]) ax1.set_xlabel(特征重要性) ax1.set_title(GBDT 特征重要性) # XGBoost特征重要性 ax2 plt.subplot(1, 2, 2) importances_xgb xgb_model.feature_importances_ indices_xgb np.argsort(importances_xgb) ax2.barh(range(len(indices_xgb)), importances_xgb[indices_xgb], aligncenter) ax2.set_yticks(range(len(indices_xgb))) ax2.set_yticklabels([feature_names[i] for i in indices_xgb]) ax2.set_xlabel(特征重要性) ax2.set_title(XGBoost 特征重要性) plt.tight_layout() plt.show() # 6. 预测值 vs 真实值对比图 plt.figure(figsize(12, 6)) # GBDT对比 ax1 plt.subplot(1, 2, 1) ax1.scatter(y_test, gbdt_pred, alpha0.6, cblue, label预测值) ax1.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], r--, label完美预测线) ax1.set_xlabel(真实值) ax1.set_ylabel(预测值) ax1.set_title(fGBDT 预测值 vs 真实值 (R^2{gbdt_r2:.4f})) # 替换R²为R^2 ax1.legend() ax1.grid(True, alpha0.3) # XGBoost对比 ax2 plt.subplot(1, 2, 2) ax2.scatter(y_test, xgb_pred, alpha0.6, cgreen, label预测值) ax2.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], r--, label完美预测线) ax2.set_xlabel(真实值) ax2.set_ylabel(预测值) ax2.set_title(fXGBoost 预测值 vs 真实值 (R^2{xgb_r2:.4f})) # 替换R²为R^2 ax2.legend() ax2.grid(True, alpha0.3) plt.tight_layout() plt.show() # 7. 交叉验证对比 cv_gbdt cross_val_score(gbdt_model, X, y, cv5, scoringr2) cv_xgb cross_val_score(xgb_model, X, y, cv5, scoringr2) print(*50) print(5折交叉验证结果) print(fGBDT平均R^2: {cv_gbdt.mean():.4f} (±{cv_gbdt.std():.4f})) print(fXGBoost平均R^2: {cv_xgb.mean():.4f} (±{cv_xgb.std():.4f}))代码说明load_diabetes糖尿病回归数据集适合展示回归模型的效果GradientBoostingRegressorGBDT 回归模型max_depth控制树的复杂度XGBRegressorXGBoost 回归模型GBDT 的优化版特征重要性展示模型认为哪些特征对预测结果影响最大预测值 vs 真实值散点图直观展示模型的预测效果越接近对角线预测越准运行效果XGBoost 的 MSE 略低于 GBDTR² 略高于 GBDT性能更优特征重要性图展示了不同模型对特征的关注度差异交叉验证结果验证了模型的稳定性5.4 集成学习应用5.4.1 房价预测分析下面是完整的房价预测实战代码使用随机森林和 GBDT 进行房价预测并可视化对比import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor from sklearn.metrics import mean_absolute_error, r2_score from sklearn.preprocessing import StandardScaler # 修复中文字体和上标显示问题彻底解决R²警告 plt.rcParams[font.sans-serif] [Microsoft YaHei, SimHei, DejaVu Sans] plt.rcParams[axes.unicode_minus] False plt.rcParams[font.family] sans-serif # 1. 生成模拟加州房价数据集修复isin方法问题 print(正在生成模拟加州房价数据集...) np.random.seed(42) # 固定随机种子保证结果可复现 # 模拟8个核心特征对应真实加州房价数据集特征 n_samples 20000 # 样本数量 median_income np.random.normal(3.8, 1.5, n_samples) # 人均收入关键特征 housing_median_age np.random.randint(1, 50, n_samples) # 房屋年龄 total_rooms np.random.poisson(2000, n_samples) # 总房间数 total_bedrooms np.random.poisson(500, n_samples) # 总卧室数 population np.random.poisson(1500, n_samples) # 人口数 households np.random.poisson(500, n_samples) # 家庭数 latitude np.random.uniform(32, 42, n_samples) # 纬度 longitude np.random.uniform(-124, -114, n_samples) # 经度 # 模拟类别特征距离海洋的距离先生成numpy数组后续转为pandas Series ocean_proximity np.random.choice([1H OCEAN, INLAND, NEAR OCEAN, NEAR BAY], n_samples, p[0.4, 0.3, 0.2, 0.1]) # 修复用numpy的in1d方法替代pandas的isin解决AttributeError # 计算距离海洋近的样本的房价加成 ocean_bonus np.where(np.in1d(ocean_proximity, [1H OCEAN, NEAR OCEAN]), 50000, 0) # 模拟目标变量房价中位数基于特征计算加入随机噪声 median_house_value (median_income * 50000 # 收入对房价影响最大 (50 - housing_median_age) * 1000 (total_rooms / households) * 100 ocean_bonus # 距离海洋近的房价加成 np.random.normal(0, 30000, n_samples)) # 构建DataFrame将所有特征整合 housing_df pd.DataFrame({ median_income: median_income, housing_median_age: housing_median_age, total_rooms: total_rooms, total_bedrooms: total_bedrooms, population: population, households: households, latitude: latitude, longitude: longitude, ocean_proximity: ocean_proximity, median_house_value: median_house_value # 目标变量房价中位数 }) # 处理异常值确保房价为正符合实际意义 housing_df[median_house_value] housing_df[median_house_value].clip(lower10000) print(f模拟数据集生成成功样本数量{housing_df.shape[0]}, 特征数量{housing_df.shape[1]-1}) # 2. 数据预处理 # 处理缺失值模拟数据无缺失此处为兼容真实数据逻辑 housing_df housing_df.dropna(subset[total_bedrooms]) # 分离特征X和目标变量y X housing_df.drop(median_house_value, axis1) y housing_df[median_house_value] # 处理类别特征对ocean_proximity做独热编码转为数值特征 X pd.get_dummies(X, columns[ocean_proximity], drop_firstTrue) # 提取特征名用于后续可视化 feature_names X.columns.tolist() # 转换为numpy数组适配sklearn模型输入格式 X X.values y y.values # 数据标准化消除量纲影响提升模型训练稳定性 scaler StandardScaler() X_scaled scaler.fit_transform(X) # 划分训练集和测试集8:2拆分random_state固定确保结果可复现 X_train, X_test, y_train, y_test train_test_split(X_scaled, y, test_size0.2, random_state42) # 3. 模型调参与训练随机森林 GBDT # 3.1 随机森林调参用GridSearchCV找最优参数 rf_params { n_estimators: [50, 100], # 决策树数量越多通常效果越好但速度越慢 max_depth: [10, None], # 树最大深度None表示不限制可能过拟合 min_samples_split: [2, 5] # 节点分裂的最小样本数越大越防止过拟合 } # 初始化随机森林模型n_jobs-1用所有CPU核心加速 rf RandomForestRegressor(random_state42, n_jobs-1) # 网格搜索cv3表示3折交叉验证scoringr2用决定系数评估 rf_grid GridSearchCV(rf, rf_params, cv3, scoringr2, n_jobs-1) rf_grid.fit(X_train, y_train) # 获取最优模型 best_rf rf_grid.best_estimator_ # 3.2 GBDT调参Gradient Boosting Decision Tree gbdt_params { n_estimators: [50, 100], # 弱学习器数量迭代次数 learning_rate: [0.05, 0.1],# 学习率步长越小需要越多迭代次数 max_depth: [3, 5] # 树最大深度控制模型复杂度 } # 初始化GBDT模型 gbdt GradientBoostingRegressor(random_state42) # 网格搜索 gbdt_grid GridSearchCV(gbdt, gbdt_params, cv3, scoringr2, n_jobs-1) gbdt_grid.fit(X_train, y_train) # 获取最优模型 best_gbdt gbdt_grid.best_estimator_ # 4. 模型预测与评估 # 用测试集做预测 rf_pred best_rf.predict(X_test) gbdt_pred best_gbdt.predict(X_test) # 计算评估指标 # MAE平均绝对误差预测值与真实值的平均绝对差越小越好 rf_mae mean_absolute_error(y_test, rf_pred) gbdt_mae mean_absolute_error(y_test, gbdt_pred) # R²决定系数衡量模型解释目标变量的能力越接近1越好 rf_r2 r2_score(y_test, rf_pred) gbdt_r2 r2_score(y_test, gbdt_pred) # 输出评估结果 print(\n *60) print(【随机森林模型结果】) print(f最优参数{rf_grid.best_params_}) print(f平均绝对误差MAE{rf_mae:.2f} 美元) print(f决定系数R^2{rf_r2:.4f}) print(\n *60) print(【GBDT模型结果】) print(f最优参数{gbdt_grid.best_params_}) print(f平均绝对误差MAE{gbdt_mae:.2f} 美元) print(f决定系数R^2{gbdt_r2:.4f}) # 5. 可视化预测结果4个子图直观对比模型性能 plt.figure(figsize(14, 10)) # 设置画布大小 # 子图1预测误差分布直方图看误差是否接近正态分布 ax1 plt.subplot(2, 2, 1) rf_error y_test - rf_pred # 随机森林误差 gbdt_error y_test - gbdt_pred # GBDT误差 ax1.hist(rf_error, bins50, alpha0.6, color#1f77b4, label随机森林误差) ax1.hist(gbdt_error, bins50, alpha0.6, color#2ca02c, labelGBDT误差) ax1.set_xlabel(预测误差真实值 - 预测值, fontsize10) ax1.set_ylabel(频次, fontsize10) ax1.set_title(模型预测误差分布, fontsize12, fontweightbold) ax1.legend() ax1.grid(True, alpha0.3) # 显示网格方便读数 # 子图2随机森林预测值vs真实值看预测是否贴合真实值 ax2 plt.subplot(2, 2, 2) ax2.scatter(y_test, rf_pred, alpha0.5, s15, color#1f77b4) # 散点图 # 绘制完美预测线yx ax2.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], r--, linewidth2) ax2.set_xlabel(真实房价美元, fontsize10) ax2.set_ylabel(预测房价美元, fontsize10) ax2.set_title(f随机森林预测值vs真实值R^2{rf_r2:.4f}, fontsize12, fontweightbold) ax2.grid(True, alpha0.3) # 子图3GBDT预测值vs真实值 ax3 plt.subplot(2, 2, 3) ax3.scatter(y_test, gbdt_pred, alpha0.5, s15, color#2ca02c) # 散点图 ax3.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], r--, linewidth2) ax3.set_xlabel(真实房价美元, fontsize10) ax3.set_ylabel(预测房价美元, fontsize10) ax3.set_title(fGBDT预测值vs真实值R^2{gbdt_r2:.4f}, fontsize12, fontweightbold) ax3.grid(True, alpha0.3) # 子图4GBDT特征重要性看哪些特征对房价影响最大 ax4 plt.subplot(2, 2, 4) importances best_gbdt.feature_importances_ # 获取特征重要性 indices np.argsort(importances) # 按重要性升序排序方便横向柱状图显示 # 处理长特征名避免显示重叠 short_names [name[:12] ... if len(name) 12 else name for name in feature_names] ax4.barh(range(len(indices)), importances[indices], color#2ca02c, alpha0.8) ax4.set_yticks(range(len(indices))) ax4.set_yticklabels([short_names[i] for i in indices], fontsize9) ax4.set_xlabel(特征重要性, fontsize10) ax4.set_title(GBDT模型特征重要性, fontsize12, fontweightbold) # 调整子图间距避免重叠 plt.tight_layout() # 显示图片无需保存直接弹出窗口 plt.show()代码说明fetch_california_housing加州房价数据集包含 8 个特征贴近真实房价预测场景GridSearchCV网格搜索调参自动寻找最优参数组合标准化处理提升模型收敛速度和性能多维度可视化误差分布、预测值对比、特征重要性全面评估模型效果5.4.2 自动人脸检测下面是使用集成学习随机森林进行人脸检测的完整代码import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix from sklearn.decomposition import PCA import warnings warnings.filterwarnings(ignore) # 设置中文字体解决中文显示问题 plt.rcParams[font.sans-serif] [Microsoft YaHei, SimHei, DejaVu Sans] plt.rcParams[axes.unicode_minus] False plt.rcParams[font.family] sans-serif # 1. 模拟生成人脸数据集和LFW结构一致 print(正在模拟生成人脸数据集...) np.random.seed(42) # 固定随机种子结果可复现 # 模拟参数贴合LFW数据集特性 n_classes 7 # 7个人物类别和LFW一致 target_names [George W Bush, Tony Blair, Hugo Chavez, Colin Powell, Donald Rumsfeld, Jean Chretien, Ariel Sharon] # 人物名称和LFW一致 h, w 50, 37 # 人脸图像尺寸LFW resize0.4后的尺寸 n_samples_per_class [130, 77, 71, 121, 88, 71, 73] # 每个类别的样本数贴近LFW真实分布 n_samples sum(n_samples_per_class) # 总样本数 n_features h * w # 特征数像素数50x371850 # 生成模拟人脸数据基于高斯分布模拟灰度图像像素值0-255 X np.zeros((n_samples, n_features)) # 特征矩阵样本数×像素数 y np.zeros(n_samples, dtypeint) # 标签矩阵 start_idx 0 for i in range(n_classes): # 为每个人物生成独特的人脸特征不同均值的高斯分布模拟面部差异 class_mean np.random.normal(120, 30, n_features) # 该人物的像素均值 class_std np.random.normal(40, 5, n_features) # 该人物的像素标准差 class_samples np.random.normal(class_mean, class_std, (n_samples_per_class[i], n_features)) # 像素值裁剪到0-255符合灰度图像规范 class_samples np.clip(class_samples, 0, 255) # 填充到总数据中 X[start_idx:start_idx n_samples_per_class[i]] class_samples y[start_idx:start_idx n_samples_per_class[i]] i start_idx n_samples_per_class[i] # 输出数据集信息 print(*60) print(模拟数据集基本信息) print(f样本数量: {n_samples}) print(f特征数量: {n_features} (人脸像素尺寸{h}x{w})) print(f类别数量: {n_classes}) print(f人物列表: {target_names}) for i in range(n_classes): print(f {target_names[i]}: {n_samples_per_class[i]}张照片) # 2. 划分数据集8:2拆分保证类别分布均衡 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.25, random_state42, stratifyy ) # 3. PCA特征降维减少计算量提取核心特征 n_components 150 print(f\n{-*60}) print(f使用PCA降维{n_features}维像素 → {n_components}维主成分) pca PCA(n_componentsn_components, svd_solverrandomized, whitenTrue, random_state42) pca.fit(X_train) # 转换训练集和测试集 X_train_pca pca.transform(X_train) X_test_pca pca.transform(X_test) # 4. 训练随机森林分类器 print(f\n{-*60}) print(训练随机森林分类器200棵决策树...) rf_model RandomForestClassifier( n_estimators200, max_depth20, n_jobs-1, random_state42, class_weightbalanced ) rf_model.fit(X_train_pca, y_train) # 5. 预测与评估 y_pred rf_model.predict(X_test_pca) # 输出分类报告 print(f\n{-*60}) print(模型分类报告Precision精确率Recall召回率F1综合得分) print(classification_report(y_test, y_pred, target_namestarget_names)) # 6. 可视化1混淆矩阵 cm confusion_matrix(y_test, y_pred, labelsrange(n_classes)) plt.figure(figsize(10, 8)) plt.imshow(cm, interpolationnearest, cmapplt.cm.Blues) plt.title(随机森林人脸分类 - 混淆矩阵, fontsize14, fontweightbold) plt.colorbar(label样本数量) tick_marks np.arange(n_classes) plt.xticks(tick_marks, target_names, rotation45, haright) plt.yticks(tick_marks, target_names) plt.xlabel(预测标签, fontsize12) plt.ylabel(真实标签, fontsize12) # 混淆矩阵中显示数字 thresh cm.max() / 2. for i in range(cm.shape[0]): for j in range(cm.shape[1]): plt.text(j, i, format(cm[i, j], d), hacenter, vacenter, fontsize10, colorwhite if cm[i, j] thresh else black) plt.tight_layout() plt.savefig(模拟数据_混淆矩阵.png, dpi300, bbox_inchestight) plt.show() # 定义可视化函数绘制人脸图像 def plot_gallery(images, titles, h, w, n_row3, n_col4, titleNone): plt.figure(figsize(1.8 * n_col, 2.4 * n_row)) if title: plt.suptitle(title, fontsize14, fontweightbold) plt.subplots_adjust(bottom0, left.01, right.99, top.90, hspace.35) for i in range(n_row * n_col): if i len(images): break plt.subplot(n_row, n_col, i 1) plt.imshow(images[i].reshape((h, w)), cmapplt.cm.gray) plt.title(titles[i], size11) plt.xticks(()) plt.yticks(()) # 生成预测结果标题 def get_pred_title(y_pred, y_test, target_names, i): pred_name target_names[y_pred[i]].split()[-1] # 只显示姓氏简化显示 true_name target_names[y_test[i]].split()[-1] return f预测: {pred_name}\n真实: {true_name} # 可视化2预测结果前12张人脸 print(f\n{-*60}) print(可视化预测结果绿色正确红色错误) prediction_titles [] correct_count 0 for i in range(min(12, len(y_pred))): pred_name target_names[y_pred[i]].split()[-1] true_name target_names[y_test[i]].split()[-1] prediction_titles.append(get_pred_title(y_pred, y_test, target_names, i)) # 终端彩色输出 if pred_name true_name: correct_count 1 print(f样本{i1}: 预测{pred_name:6s} | 真实{true_name:6s} | \033[32m正确\033[0m) else: print(f样本{i1}: 预测{pred_name:6s} | 真实{true_name:6s} | \033[31m错误\033[0m) # 绘制预测结果图 plot_gallery(X_test, prediction_titles, h, w, title人脸分类预测结果前12张) plt.savefig(模拟数据_预测结果.png, dpi300, bbox_inchestight) plt.show() # 可视化3PCA特征脸核心特征 print(f\n{-*60}) print(可视化PCA特征脸人脸核心轮廓特征) eigenfaces pca.components_.reshape((n_components, h, w)) eigenface_titles [f特征脸 {i1} for i in range(min(12, n_components))] plot_gallery(eigenfaces, eigenface_titles, h, w, titlePCA提取的特征脸前12个) plt.savefig(模拟数据_特征脸.png, dpi300, bbox_inchestight) plt.show() # 输出核心指标总结 accuracy np.mean(y_pred y_test) variance_ratio np.sum(pca.explained_variance_ratio_) print(f\n{-*60}) print(模型核心指标总结) print(f整体准确率: {accuracy:.4f} ({accuracy*100:.2f}%)) print(fPCA降维保留方差比例: {variance_ratio:.4f} ({variance_ratio*100:.2f}%)) print(f前12张样本预测正确率: {correct_count/12:.4f} ({correct_count}/12))代码说明fetch_lfw_people加载 LFW 人脸数据集包含多位知名人物的人脸照片PCA 降维将高维的人脸像素特征降维到 150 维减少计算量提升模型性能随机森林分类对降维后的特征进行分类识别不同的人脸混淆矩阵展示模型在不同人物上的分类准确率特征脸可视化展示 PCA 提取的关键人脸特征5.5 习题基础题简述集成学习的核心思想Bagging 和 Boosting 的主要区别是什么随机森林相比单决策树有哪些改进为什么能有效防止过拟合AdaBoost 的样本权重更新规则是什么学习率对模型有什么影响编程题基于鸢尾花数据集分别使用 Bagging、AdaBoost、GBDT 构建分类模型对比它们的准确率和训练时间。基于波士顿房价数据集或加州房价数据集使用 XGBoost 构建回归模型并通过网格搜索优化参数。尝试使用 Stacking 集成策略第一层用随机森林、GBDT第二层用逻辑回归在任意分类数据集上验证效果。总结集成学习核心通过组合多个基学习器提升模型性能关键是保证基学习器的 “差异性” 和 “基本性能”。Bagging vs BoostingBagging 并行训练、降低方差代表随机森林Boosting 串行训练、降低偏差代表AdaBoost、GBDT。实战要点随机森林适合处理高维数据、噪声数据调参重点是树的数量和特征采样数。GBDT/XGBoost 适合回归和分类任务调参重点是学习率、树深度和迭代次数。集成学习在实际应用中房价预测、人脸检测表现优于单个模型是工业界的首选算法之一。总结本文所有代码均可直接运行需安装 scikit-learn、xgboost、matplotlib 等库建议大家动手实操加深对集成学习的理解。如果有任何问题欢迎在评论区交流