引言
在机器学习建模过程中,我们常常会遇到这样的困境:单分类器在测试集上的准确率始终徘徊不前,调参到极致也难以突破瓶颈;或者模型在部分样本上表现稳定,但对异常数据的鲁棒性极差。如果你也有过类似的困扰,那今天要聊的技术,或许能成为你的破局关键。
分类器集成并非什么高深莫测的黑科技,其核心思想简单又精妙——“三个臭皮匠顶个诸葛亮”。通过将多个性能一般的基分类器组合起来,形成一个强分类器,从而实现比单个基分类器更优的分类效果。今天这篇文章,我们就从原理、经典算法、实战代码到调优技巧,全方位拆解分类器集成,让你既能懂原理,又能上手用。
一、为什么需要分类器集成?先搞懂单分类器的“短板”
在聊集成之前,我们得先明白:单分类器的局限性是天生的。具体来说,主要有三个核心问题:
偏差与方差的矛盾:简单模型(如逻辑回归、决策树深度较浅时)往往偏差高、方差低,容易出现“欠拟合”;复杂模型(如深度神经网络、复杂决策树)则相反,方差高、偏差低,容易“过拟合”。单分类器很难同时兼顾低偏差和低方差。
泛化能力不足:单个模型对数据分布的敏感度较高,一旦测试集与训练集的分布有细微差异,性能就可能大幅下降。比如用单一决策树处理不平衡数据时,很容易偏向多数类样本。
局部最优陷阱:模型训练过程本质是寻找损失函数最小值的过程,但单分类器很容易陷入局部最优解,无法触及全局最优。
而分类器集成的核心价值,就是通过组合来弥补这些短板:通过选择多样化的基分类器,降低整体模型的方差;通过迭代优化或加权组合,降低偏差;最终实现“1+1>2”的泛化能力提升。
二、分类器集成的核心原理:两个关键要素
并非随便把几个分类器堆在一起就能叫“集成”,有效的集成必须满足两个核心条件,缺一不可:
1. 基分类器的“多样性”
这是集成的灵魂。如果所有基分类器的判断结果完全一致(即高度相关),那么集成后的结果和单个分类器没有区别。只有当基分类器之间存在“互补性”——有的擅长识别正样本,有的擅长排除负样本,有的对噪声不敏感,集成才能发挥作用。
实现多样性的常见方式有三种:
数据层面:对训练集进行抽样(如Bagging的自助抽样),让不同基分类器在不同的数据子集上训练。
模型层面:选择不同类型的基分类器(如逻辑回归+SVM+决策树),或同一类型但超参数不同的模型(如不同深度的决策树)。
特征层面:对特征进行抽样(如随机森林的特征随机选择),让不同基分类器关注不同的特征维度。
2. 合理的“组合策略”
有了多样化的基分类器,还需要一套规则将它们的预测结果组合起来。常见的组合策略分为「并行式」和「串行式」两类,分别对应不同的集成框架:
并行式组合:所有基分类器独立训练,组合时仅融合预测结果(如投票、平均),代表算法是Bagging。
串行式组合:基分类器按顺序训练,后一个分类器会根据前一个分类器的错误进行优化(如加权),代表算法是Boosting。
三、三大经典集成算法:从原理到适用场景
了解了核心原理后,我们来看工业界最常用的三大集成算法。这部分是重点,建议结合实际场景理解适用范围。
1. Bagging:并行集成的“稳定派”
核心思想:“自助抽样+并行训练+简单投票”。通过自助抽样(Bootstrap)从原始训练集中随机抽取多个子集,每个子集训练一个基分类器,最终通过投票(分类任务)或平均(回归任务)得到结果。
代表算法:随机森林(Random Forest)
随机森林在Bagging的基础上增加了“特征随机选择”:每个决策树节点分裂时,仅从随机选择的部分特征中挑选最优分裂点。这进一步增强了基分类器的多样性,也避免了单棵决策树过拟合的问题。
优势:
并行训练效率高,可充分利用多核CPU;
对噪声数据不敏感,鲁棒性强;
自带特征重要性评估,可用于特征选择。
适用场景:数据量较大、存在噪声、需要快速建模的场景,如用户行为分类、垃圾邮件识别。
注意点:对小样本数据效果一般,因为自助抽样可能导致样本代表性不足。
2. Boosting:串行集成的“优化派”
核心思想:“迭代优化+加权投票”。先训练一个简单的基分类器,然后根据其预测错误调整样本权重(错分样本权重提高,正确样本权重降低),再训练下一个基分类器,重复此过程,最终将所有基分类器加权组合(性能好的分类器权重高)。
代表算法:
AdaBoost:最基础的Boosting算法,通过样本权重调整实现优化,结构简单但对噪声敏感。
XGBoost/LightGBM/CatBoost:工业界主流的梯度提升树(GBDT)变种,通过梯度下降优化损失函数,支持正则化、缺失值处理,精度极高。
优势:
精度高,在 Kaggle 竞赛中常年霸榜;
对特征工程要求较低,可自动处理非线性关系。
适用场景:对精度要求高的场景,如信用风险评估、房价预测(回归)、疾病诊断。
注意点:串行训练效率较低,对噪声数据和异常值敏感,需要调参(如学习率、树深度)控制过拟合。
3. Stacking:集成中的“终极玩家”
核心思想:“分层集成+元分类器”。将多个基分类器的预测结果作为新的特征,输入到一个“元分类器”(Meta-Classifier)中,由元分类器给出最终预测。相当于用一个更高级的模型来学习“如何组合基分类器”。
结构分为两层:
第一层(基学习器):训练多个不同类型的基分类器(如随机森林+XGBoost+SVM),得到各自的预测概率。
第二层(元学习器):用基分类器的预测概率作为特征,训练一个简单模型(如逻辑回归、轻量GBDT),学习最优组合方式。
优势:灵活性极高,可融合不同类型模型的优势,理论上能达到更高精度。
适用场景:Kaggle 等竞赛的“冲榜”阶段,或对精度有极致要求的核心业务。
注意点:模型复杂度高,容易过拟合(需用交叉验证避免);训练成本高,不适合实时推理场景。
四、实战演练:用Python实现三大集成算法
光说不练假把式,接下来我们用 sklearn 实现随机森林(Bagging)、XGBoost(Boosting)和 Stacking,基于葡萄酒数据集(分类任务)对比性能。
环境准备:先安装必要的库
pip install sklearn xgboost pandas numpy1. 数据加载与预处理
import pandas as pd import numpy as np from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report # 加载数据集(葡萄酒分类:3类,13个特征) wine = load_wine() X = pd.DataFrame(wine.data, columns=wine.feature_names) y = pd.Series(wine.target, name='target') # 划分训练集/测试集(7:3) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y ) print(f"训练集规模:{X_train.shape},测试集规模:{X_test.shape}")2. 实现三大集成算法并对比
from sklearn.ensemble import RandomForestClassifier, StackingClassifier from xgboost import XGBClassifier from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC # 1. 随机森林(Bagging) rf = RandomForestClassifier( n_estimators=100, # 基分类器数量 max_depth=5, # 每棵树最大深度 random_state=42 ) rf.fit(X_train, y_train) rf_pred = rf.predict(X_test) rf_acc = accuracy_score(y_test, rf_pred) # 2. XGBoost(Boosting) xgb = XGBClassifier( n_estimators=100, learning_rate=0.1, # 学习率,控制每步权重更新幅度 max_depth=3, random_state=42, use_label_encoder=False, eval_metric='mlogloss' # 多分类损失函数 ) xgb.fit(X_train, y_train) xgb_pred = xgb.predict(X_test) xgb_acc = accuracy_score(y_test, rf_pred) # 3. Stacking(基分类器:随机森林+XGBoost+SVM;元分类器:逻辑回归) base_models = [ ('rf', RandomForestClassifier(n_estimators=50, random_state=42)), ('xgb', XGBClassifier(n_estimators=50, random_state=42, use_label_encoder=False, eval_metric='mlogloss')), ('svm', SVC(probability=True, random_state=42)) # SVM需开启概率预测 ] stack = StackingClassifier( estimators=base_models, final_estimator=LogisticRegression(random_state=42) ) stack.fit(X_train, y_train) stack_pred = stack.predict(X_test) stack_acc = accuracy_score(y_test, stack_pred) # 输出结果对比 print("=== 模型准确率对比 ===") print(f"随机森林:{rf_acc:.4f}") print(f"XGBoost:{xgb_acc:.4f}") print(f"Stacking:{stack_acc:.4f}") print("\n=== Stacking 分类报告 ===") print(classification_report(y_test, stack_pred))3. 结果分析
运行代码后,你会发现:
随机森林和 XGBoost 准确率都在 95% 以上,远超单分类器(如逻辑回归约 90%);
Stacking 准确率可能略高于前两者(或持平),但优势在复杂数据集上更明显;
XGBoost 的训练速度比随机森林慢,但精度更稳定;Stacking 训练最慢,但灵活性最高。
五、集成调优技巧:避开这些“坑”,性能再提升20%
集成不是“堆模型”,调优技巧直接决定最终效果。分享几个实战中总结的关键技巧:
基分类器选择:“弱而多样”优于“强而相似”:不要用多个复杂且高度相关的模型(如多个XGBoost),建议搭配“简单模型+复杂模型”(如逻辑回归+XGBoost+SVM),多样性更高。
控制基分类器数量:并非越多越好。n_estimators 增加到一定程度后,精度会饱和,反而增加训练成本。一般建议 100-500 之间,通过交叉验证确定。
防止过拟合的核心手段: Bagging:减小单棵树深度、增加特征抽样比例;
Boosting:降低学习率(如 0.01-0.1)、增加正则化项(如 XGBoost 的 reg_alpha);
Stacking:用交叉验证生成基分类器的预测结果(避免数据泄露)。
权重调整技巧:对 Boosting 类模型,可根据基分类器在验证集的性能动态调整权重,而非默认的迭代权重。
六、总结:集成算法的选型指南
最后,用一张表总结三大算法的选型逻辑,帮你快速决策:
算法类型 | 核心优势 | 训练效率 | 适用场景 | 代表工具 |
|---|---|---|---|---|
Bagging(随机森林) | 鲁棒性强、抗噪声 | 高(并行) | 快速建模、数据有噪声 | sklearn、Spark MLlib |
Boosting(XGBoost) | 精度高、支持正则化 | 中(串行) | 精度优先、结构化数据 | XGBoost、LightGBM |
Stacking | 融合多模型优势 | 低(多层训练) | 竞赛冲榜、极致精度 | sklearn、自定义实现 |
分类器集成的核心逻辑,是通过“多样性”和“组合策略”突破单模型的局限。在实际工作中,建议从简单的随机森林或XGBoost入手,再根据精度需求尝试Stacking。记住:没有最好的算法,只有最适合场景的算法。
七、项目源代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, roc_curve, auc from sklearn.preprocessing import label_binarize from sklearn.ensemble import RandomForestClassifier, StackingClassifier from xgboost import XGBClassifier from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC import warnings warnings.filterwarnings('ignore') # 设置图形样式 plt.rcParams['figure.figsize'] = [12, 8] plt.rcParams['font.size'] = 12 sns.set_style("whitegrid") # 加载数据集(葡萄酒分类:3类,13个特征) wine = load_wine() X = pd.DataFrame(wine.data, columns=wine.feature_names) y = pd.Series(wine.target, name='target') target_names = wine.target_names # 划分训练集/测试集(7:3) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y ) print(f"训练集规模:{X_train.shape},测试集规模:{X_test.shape}") print(f"类别分布 - 训练集: {np.bincount(y_train)},测试集: {np.bincount(y_test)}") # 1. 随机森林(Bagging) rf = RandomForestClassifier( n_estimators=100, max_depth=5, random_state=42 ) rf.fit(X_train, y_train) rf_pred = rf.predict(X_test) rf_acc = accuracy_score(y_test, rf_pred) # 2. XGBoost(Boosting) xgb = XGBClassifier( n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42, eval_metric='mlogloss' ) xgb.fit(X_train, y_train) xgb_pred = xgb.predict(X_test) xgb_acc = accuracy_score(y_test, xgb_pred) # 3. Stacking base_models = [ ('rf', RandomForestClassifier(n_estimators=50, random_state=42)), ('xgb', XGBClassifier(n_estimators=50, random_state=42, eval_metric='mlogloss')), ('svm', SVC(probability=True, random_state=42)) ] stack = StackingClassifier( estimators=base_models, final_estimator=LogisticRegression(random_state=42, max_iter=1000) ) stack.fit(X_train, y_train) stack_pred = stack.predict(X_test) stack_acc = accuracy_score(y_test, stack_pred) # 输出结果对比 print("\n" + "=" * 40) print("=== 模型准确率对比 ===") print("=" * 40) print(f"随机森林准确率:{rf_acc:.4f}") print(f"XGBoost准确率:{xgb_acc:.4f}") print(f"Stacking准确率:{stack_acc:.4f}") print("\n" + "=" * 40) print("=== Stacking 分类报告 ===") print("=" * 40) print(classification_report(y_test, stack_pred, target_names=target_names)) # ==================== 可视化部分 ==================== # 1. 创建综合可视化图表 fig, axes = plt.subplots(2, 3, figsize=(18, 12)) fig.suptitle('Wine Classification Model Performance Visualization', fontsize=16, fontweight='bold') # 1.1 准确率对比柱状图 ax1 = axes[0, 0] models = ['Random Forest', 'XGBoost', 'Stacking'] accuracies = [rf_acc, xgb_acc, stack_acc] colors = ['#FF6B6B', '#4ECDC4', '#45B7D1'] bars = ax1.bar(models, accuracies, color=colors, alpha=0.8) ax1.set_title('Model Accuracy Comparison', fontsize=14, fontweight='bold') ax1.set_ylabel('Accuracy', fontsize=12) ax1.set_ylim(0, 1.1) ax1.grid(True, alpha=0.3) for bar, acc in zip(bars, accuracies): height = bar.get_height() ax1.text(bar.get_x() + bar.get_width() / 2., height + 0.02, f'{acc:.3f}', ha='center', va='bottom', fontweight='bold') # 1.2 训练集特征分布箱线图 ax2 = axes[0, 1] # 选择前6个特征进行可视化 selected_features = X_train.columns[:6] data_to_plot = [] for feature in selected_features: data_to_plot.append(X_train[feature].values) box = ax2.boxplot(data_to_plot, patch_artist=True, labels=selected_features) colors_box = ['#FF9999', '#66B2FF', '#99FF99', '#FFCC99', '#FF99CC', '#99CCFF'] for patch, color in zip(box['boxes'], colors_box): patch.set_facecolor(color) patch.set_alpha(0.7) ax2.set_title('Feature Distribution (Training Set)', fontsize=14, fontweight='bold') ax2.set_ylabel('Value', fontsize=12) ax2.tick_params(axis='x', rotation=45) # 1.3 类别分布饼图 ax3 = axes[0, 2] class_counts = np.bincount(y_train) colors_pie = ['#FF6B6B', '#4ECDC4', '#45B7D1'] wedges, texts, autotexts = ax3.pie(class_counts, labels=target_names, colors=colors_pie, autopct='%1.1f%%', startangle=90, explode=(0.05, 0.05, 0.05)) ax3.set_title('Class Distribution (Training Set)', fontsize=14, fontweight='bold') for autotext in autotexts: autotext.set_color('white') autotext.set_fontweight('bold') # 1.4 随机森林特征重要性 ax4 = axes[1, 0] rf_importance = pd.DataFrame({ 'feature': wine.feature_names, 'importance': rf.feature_importances_ }).sort_values('importance', ascending=True) bars_rf = ax4.barh(rf_importance['feature'], rf_importance['importance'], color='#FF6B6B', alpha=0.7) ax4.set_title('Random Forest Feature Importance', fontsize=14, fontweight='bold') ax4.set_xlabel('Importance Score', fontsize=12) # 1.5 XGBoost特征重要性 ax5 = axes[1, 1] xgb_importance = pd.DataFrame({ 'feature': wine.feature_names, 'importance': xgb.feature_importances_ }).sort_values('importance', ascending=True) bars_xgb = ax5.barh(xgb_importance['feature'], xgb_importance['importance'], color='#4ECDC4', alpha=0.7) ax5.set_title('XGBoost Feature Importance', fontsize=14, fontweight='bold') ax5.set_xlabel('Importance Score', fontsize=12) # 1.6 混淆矩阵(Stacking模型) ax6 = axes[1, 2] cm = confusion_matrix(y_test, stack_pred) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=target_names, yticklabels=target_names, ax=ax6) ax6.set_title('Stacking Confusion Matrix', fontsize=14, fontweight='bold') ax6.set_xlabel('Predicted Label', fontsize=12) ax6.set_ylabel('True Label', fontsize=12) plt.tight_layout() plt.savefig('model_performance_visualization.png', dpi=300, bbox_inches='tight') plt.show() # 2. 创建ROC曲线图 fig2, ax_roc = plt.subplots(figsize=(10, 8)) # 将标签二值化 y_test_bin = label_binarize(y_test, classes=[0, 1, 2]) n_classes = y_test_bin.shape[1] # 为每个模型计算ROC曲线 models_info = [ ('Random Forest', rf, rf_pred, '#FF6B6B'), ('XGBoost', xgb, xgb_pred, '#4ECDC4'), ('Stacking', stack, stack_pred, '#45B7D1') ] for name, model, pred, color in models_info: # 获取预测概率 if hasattr(model, "predict_proba"): y_score = model.predict_proba(X_test) else: y_score = model.decision_function(X_test) # 计算微平均ROC曲线 fpr_micro, tpr_micro, _ = roc_curve(y_test_bin.ravel(), y_score.ravel()) roc_auc_micro = auc(fpr_micro, tpr_micro) # 绘制ROC曲线 ax_roc.plot(fpr_micro, tpr_micro, color=color, lw=2, label=f'{name} (AUC = {roc_auc_micro:.3f})') # 绘制对角线 ax_roc.plot([0, 1], [0, 1], 'k--', lw=1, alpha=0.6) ax_roc.set_xlim([0.0, 1.0]) ax_roc.set_ylim([0.0, 1.05]) ax_roc.set_xlabel('False Positive Rate', fontsize=12) ax_roc.set_ylabel('True Positive Rate', fontsize=12) ax_roc.set_title('ROC Curves (Micro-average)', fontsize=14, fontweight='bold') ax_roc.legend(loc="lower right") ax_roc.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('roc_curves.png', dpi=300, bbox_inches='tight') plt.show() # 3. 创建性能对比雷达图 fig3 = plt.figure(figsize=(10, 8)) ax_radar = fig3.add_subplot(111, projection='polar') # 获取分类指标 def get_metrics(y_true, y_pred): report = classification_report(y_true, y_pred, output_dict=True) return { 'precision': report['macro avg']['precision'], 'recall': report['macro avg']['recall'], 'f1': report['macro avg']['f1-score'], 'accuracy': report['accuracy'] } # 收集每个模型的指标 rf_metrics = get_metrics(y_test, rf_pred) xgb_metrics = get_metrics(y_test, xgb_pred) stack_metrics = get_metrics(y_test, stack_pred) # 准备雷达图数据 categories = ['Accuracy', 'Precision', 'Recall', 'F1-Score'] N = len(categories) # 将数据转为列表 def metrics_to_list(metrics): return [metrics['accuracy'], metrics['precision'], metrics['recall'], metrics['f1']] rf_values = metrics_to_list(rf_metrics) xgb_values = metrics_to_list(xgb_metrics) stack_values = metrics_to_list(stack_metrics) # 角度设置 angles = np.linspace(0, 2 * np.pi, N, endpoint=False).tolist() angles += angles[:1] # 闭合 rf_values += rf_values[:1] xgb_values += xgb_values[:1] stack_values += stack_values[:1] # 绘制雷达图 ax_radar.plot(angles, rf_values, 'o-', linewidth=2, label='Random Forest', color='#FF6B6B') ax_radar.fill(angles, rf_values, alpha=0.1, color='#FF6B6B') ax_radar.plot(angles, xgb_values, 'o-', linewidth=2, label='XGBoost', color='#4ECDC4') ax_radar.fill(angles, xgb_values, alpha=0.1, color='#4ECDC4') ax_radar.plot(angles, stack_values, 'o-', linewidth=2, label='Stacking', color='#45B7D1') ax_radar.fill(angles, stack_values, alpha=0.1, color='#45B7D1') # 设置标签 ax_radar.set_xticks(angles[:-1]) ax_radar.set_xticklabels(categories, fontsize=12) ax_radar.set_ylim(0, 1.1) ax_radar.set_title('Model Performance Radar Chart', fontsize=14, fontweight='bold', pad=20) ax_radar.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0)) ax_radar.grid(True) plt.tight_layout() plt.savefig('performance_radar_chart.png', dpi=300, bbox_inches='tight') plt.show() # 4. 特征相关性热图 fig4, ax_corr = plt.subplots(figsize=(12, 10)) correlation_matrix = X.corr() mask = np.triu(np.ones_like(correlation_matrix, dtype=bool)) sns.heatmap(correlation_matrix, mask=mask, annot=True, fmt='.2f', cmap='coolwarm', center=0, square=True, linewidths=0.5, cbar_kws={"shrink": 0.8}, ax=ax_corr) ax_corr.set_title('Feature Correlation Heatmap', fontsize=14, fontweight='bold') plt.tight_layout() plt.savefig('feature_correlation.png', dpi=300, bbox_inches='tight') plt.show() print("\n" + "=" * 50) print("Visualization Summary:") print("=" * 50) print("1. model_performance_visualization.png - Main performance dashboard") print("2. roc_curves.png - ROC curves for all models") print("3. performance_radar_chart.png - Performance comparison radar chart") print("4. feature_correlation.png - Feature correlation heatmap") print("\nAll charts have been saved to the current directory!")1.model_performance_visualization.png(模型性能综合可视化)
这张综合图表包含了6个子图,全面展示了模型的各个方面:
左上角:模型准确率对比柱状图,直观显示三个模型(随机森林、XGBoost、Stacking)在测试集上的准确率,柱状图高度代表准确率数值
右上角:训练集特征分布箱线图,展示了前6个特征的数值分布情况,箱体显示数据的四分位数,须线显示数据范围,异常值以点显示
中上:类别分布饼图,显示训练集中三个葡萄酒类别的比例分布,帮助了解数据是否均衡
左下角:随机森林特征重要性条形图,展示了随机森林模型认为最重要的特征,特征重要性越高表示该特征对分类贡献越大
中下:XGBoost特征重要性条形图,展示了XGBoost模型的特征重要性排序,可以与随机森林的结果进行对比
右下角:Stacking模型混淆矩阵热力图,显示Stacking模型的预测结果,对角线上的数值表示正确分类的样本数,非对角线表示误分类情况
2. roc_curves.png(ROC曲线图)
ROC曲线图是评估分类模型性能的重要工具:
图中展示了三个模型(随机森林、XGBoost、Stacking)的ROC曲线
横轴:假正率(False Positive Rate),即被错误分类为正类的负类样本比例
纵轴:真正率(True Positive Rate),即被正确分类的正类样本比例
对角线:随机分类器的性能基准(AUC=0.5)
每条曲线下的面积(AUC值)显示在标签中,AUC值越接近1表示模型性能越好
微平均:在多分类问题中,我们将所有类别的预测合并计算一个整体的ROC曲线
3. performance_radar_chart.png(性能雷达图)
雷达图以多边形形式对比三个模型在四个关键指标上的表现:
四个维度:
准确率:所有样本中被正确分类的比例
精确率:预测为正类的样本中实际为正类的比例
召回率:实际为正类的样本中被正确预测的比例
F1分数:精确率和召回率的调和平均数,综合衡量模型性能
越靠近外圈表示性能越好(最大值为1.0)
多边形面积越大表示模型综合性能越好
不同颜色代表不同模型,可以直观比较哪个模型在各方面都表现更优
4. feature_correlation.png(特征相关性热图)
这张热图展示了葡萄酒数据集中13个特征之间的相关性:
颜色深浅:红色表示正相关,蓝色表示负相关,白色表示无相关
数值范围:-1到+1,绝对值越大表示相关性越强
对角线:特征与自身的相关性为1(最深红色)
应用价值:
帮助识别高度相关的特征(可能包含冗余信息)
指导特征选择,避免多重共线性问题
理解数据集中特征之间的关系结构