多重共线性问题在机器学习中的典型场景与应对技巧

文摘   2025-01-08 20:00   湖北  

背景

多重共线性是回归分析中一种统计现象,指的是自变量(预测变量)之间存在较高的相关性。当多个自变量之间高度相关时,它们会携带相似的信息,从而导致模型难以区分这些变量对因变量的独立贡献

  • 完美共线性:当一个特征是其他特征的完全线性组合时,称为完美共线性(极少见)

  • 强共线性:当特征之间有较强但不完全的线性相关性时,称为强共线性(更常见)

多重共线性会导致:

  • 不稳定的模型系数:特别是在回归模型中,某些特征的系数可能变得非常大,方向甚至会发生翻转

  • 特征贡献难以解释:在高度相关的特征中,很难区分哪个特征对目标变量贡献更大

  • 数值计算问题:对一些算法来说,共线性可能导致矩阵不可逆或病态,使计算过程变得不稳定

  • 过拟合风险:多重共线性可能让模型捕捉到不必要的噪声
机器学习模型是否需要关注多重共线性?

主要取决于具体的模型和目标任务

对共线性敏感的模型:线性回归、逻辑回归、广义线性模型(GLM)等

对共线性不敏感的模型:树模型(决策树、随机森林、梯度提升树等)、神经网络等

具体应用场景的影响:解释性任务如果需要从模型中提取特征的重要性或解释其系数(如线性回归中的系数),就必须关注多重共线性。因为高共线性会让系数变得难以解释、预测任务如果模型的目标是纯预测,而非解释,那么对于决策树等鲁棒性强的模型,共线性可能并不会显著降低性能

如何检测多重共线性?

  • 简单相关系数矩阵:计算特征之间的相关系数,如果两个特征之间的相关系数接近±1,说明它们可能存在共线性

  • 方差膨胀因子(VIF):VIF<5多重共线性较弱、VIF>10多重共线性较强,可能需要处理

  • 特征选择的条件数:当条件数较高(如 >30)时,表明共线性较严重

应对多重共线性的方法包括删除冗余特征、正则化(如岭回归)、降维(如PCA)、或选择对共线性不敏感的模型(如树模型)

代码实现

数据读取

import pandas as pdimport numpy as npimport matplotlib.pyplot as pltplt.rcParams['font.family'] = 'Times New Roman'plt.rcParams['axes.unicode_minus'] = Falsefrom sklearn.model_selection import train_test_splitdf = pd.read_excel('2025-1-5公众号Python机器学习AI.xlsx')

相关系数矩阵检测

import seaborn as sns
# 计算相关系数矩阵corr = df.corr()
# 创建图形fig, ax = plt.subplots(figsize=(108), dpi=1200)cmap = plt.cm.viridisnorm = plt.Normalize(vmin=-1, vmax=1)
# 初始化一个空的可绘制对象用于颜色条scatter_handles = []
# 循环绘制气泡图和数值for i in range(len(corr.columns)):    for j in range(len(corr.columns)):        if i > j:  # 对角线左下部分,只显示气泡            color = cmap(norm(corr.iloc[i, j]))  # 根据相关系数获取颜色            scatter = ax.scatter(i, j, s=np.abs(corr.iloc[i, j]) * 1000, color=color, alpha=0.75)            scatter_handles.append(scatter)  # 保存scatter对象用于颜色条        elif i < j:  # 对角线右上部分,只显示数值            color = cmap(norm(corr.iloc[i, j]))  # 数值的颜色同样基于相关系数            ax.text(i, j, f'{corr.iloc[i, j]:.2f}', ha='center', va='center', color=color, fontsize=10)        else:  # 对角线部分,显示空白            ax.scatter(i, j, s=1, color='white')
# 设置坐标轴标签ax.set_xticks(range(len(corr.columns)))ax.set_xticklabels(corr.columns, rotation=45, ha='right', fontsize=10)ax.set_yticks(range(len(corr.columns)))ax.set_yticklabels(corr.columns, fontsize=10)sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)sm.set_array([])  # 仅用于显示颜色条fig.colorbar(sm, ax=ax, label='Correlation Coefficient')plt.savefig("1.png", format='png', bbox_inches='tight')plt.tight_layout()plt.show()
def detect_high_multicollinearity(df, threshold=0.8):    # 计算相关系数矩阵    corr_matrix = df.corr()        # 提取上三角矩阵(排除对角线)    upper_triangle = np.triu(np.ones(corr_matrix.shape), k=1)    high_corr_indices = np.where(np.abs(corr_matrix.values) * upper_triangle > threshold)        # 转换为特征对列表    high_corr_pairs = [        (df.columns[i], df.columns[j], corr_matrix.iloc[i, j])        for i, j in zip(*high_corr_indices)    ]        return high_corr_pairs

# 测试函数high_corr_features = detect_high_multicollinearity(df, threshold=0.8)
print("高度多重共线性的特征对及其相关系数:")for pair in high_corr_features:    print(f"{pair[0]} 和 {pair[1]} 的相关系数为 {pair[2]:.2f}")

绘制气泡图可视化相关系数矩阵,并使用阈值0.8检测数据集中高度多重共线性的特征对及其相关系数

方差膨胀因子(VIF)

from statsmodels.stats.outliers_influence import variance_inflation_factorfrom patsy import dmatrix
def vif_analysis(df, high_threshold=10, low_threshold=5):    # 确保只处理数值型特征    df_numeric = df.select_dtypes(include=[np.number])
    # 添加常数项,保证VIF计算正确    X = dmatrix(" + ".join(df_numeric.columns), data=df_numeric, return_type='dataframe')
    # 计算每个特征的VIF    vif_data = pd.DataFrame()    vif_data["Feature"] = X.columns    vif_data["VIF"] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]        # 去掉常数项的VIF    vif_data = vif_data[vif_data["Feature"] != "Intercept"]
    # 筛选出高共线性和低共线性特征    high_multicollinearity = vif_data[vif_data["VIF"] > high_threshold]["Feature"].tolist()    low_multicollinearity = vif_data[vif_data["VIF"] < low_threshold]["Feature"].tolist()        return {        "High Multicollinearity (VIF > {})".format(high_threshold): high_multicollinearity,        "Low Multicollinearity (VIF < {})".format(low_threshold): low_multicollinearity    }

# 测试函数vif_results = vif_analysis(df, high_threshold=10, low_threshold=5)
print("存在高共线性的特征 (VIF > 10):", vif_results["High Multicollinearity (VIF > 10)"])print("存在低共线性的特征 (VIF < 5):", vif_results["Low Multicollinearity (VIF < 5)"])

算方差膨胀因子(VIF)筛选出具有高共线性(VIF > 10)和低共线性(VIF < 5)的特征,以帮助分析多重共线性问题

特征选择的条件数

def calculate_condition_number(df, threshold=30):       # 确保只处理数值型特征    df_numeric = df.select_dtypes(include=[np.number])        # 标准化特征矩阵(均值为0,方差为1    X = (df_numeric - df_numeric.mean()) / df_numeric.std()        # 计算奇异值    singular_values = np.linalg.svd(X, compute_uv=False)        # 计算条件数    condition_number = max(singular_values) / min(singular_values)        # 检查是否存在多重共线性    multicollinearity = condition_number > threshold        return {        "Condition Number": condition_number,        "Multicollinearity Detected": multicollinearity,        "Threshold": threshold    }

# 测试函数condition_number_results = calculate_condition_number(df, threshold=30)
# 打印结果print(f"条件数: {condition_number_results['Condition Number']:.2f}")if condition_number_results["Multicollinearity Detected"]:    print(f"条件数大于阈值 {condition_number_results['Threshold']},表明存在多重共线性。")else:    print(f"条件数小于阈值 {condition_number_results['Threshold']},未发现显著的多重共线性。")

通过计算条件数判断数据集是否存在整体多重共线性,但无法具体识别哪些特征之间存在多重共线性

往期推荐

期刊配图:SHAP可视化改进依赖图+拟合线+边缘密度+分组对比
期刊配图:基于t-sne降维与模型预测概率的分类效果可视化
期刊配图:多种机器学习算法结合SHAP特征贡献在递归特征选择中的运用
置信区间+误差条:机器学习分类评价指标精美呈现
SCI图表:基于相关性和标准差的多模型评价——泰勒图解析
期刊文章配图:基于分组折线图的多机器学习模型表现评估对比
复现SCI文章 SHAP 依赖图可视化以增强机器学习模型的可解释性
SCI图表复现:优化SHAP特征贡献图展示更多模型细节
复现 Nature 图表——基于PCA的高维数据降维与可视化实践及其扩展
复现Nature图表——基于PCA降维与模型预测概率的分类效果可视化
SCI图表复现:特征相关性气泡热图展示
一图胜千言:回归预测模型训练集与测试集的进阶可视化
期刊文章配图:基于雷达图的多机器学习模型表现评估对比

期刊文章配图:斯皮尔曼相关系数热图反应非线性变量相关性

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参考

地学韦丰吉司长
绝佳地理学视角,地学韦丰吉司长为您呈现精选“地学”文章,为您提供权威的科普文章、学术资源和地学知识。探索地球之美,解读地理之奥秘。欢迎广大地学科研工作者、爱好者投稿和业务推广。请后台私信或加VX(XWFxwf7)联系韦丰小编!
 最新文章