多重共线性是指线性回归模型中的自变量之间存在精确相关关系或高度相关关系。其数学描述如下:如果存在不全为0的 p + 1 p+1 p+1个数 c 0 , c 1 , c 2 , … , c p c_{0},c_{1},c_{2},\dots,c_{p} c0,c1,c2,…,cp使得 c 0 + c 1 x 1 + c 2 x 2 + ⋯ + c p x p = 0 c_{0}+c_{1}\boldsymbol{x_{1}}+c_{2}\boldsymbol{x_{2}}+\dots+c_{p}\boldsymbol{x_{p}}=0 c0+c1x1+c2x2+⋯+cpxp=0则称自变量 x 1 , x 2 , … , x p \boldsymbol{x_{1}},\boldsymbol{x_{2}},\dots,\boldsymbol{x_{p}} x1,x2,…,xp之间存在着完全多重共线性。在完全共线性的情况下,某一个自变量可以完全由其他自变量线性表示。但是这种情况并不常见,常见的是上述等式近似成立的情况。即存在不全为0的 p + 1 p+1 p+1个数 c 0 , c 1 , c 2 , … , c p c_{0},c_{1},c_{2},\dots,c_{p} c0,c1,c2,…,cp使得 c 0 + c 1 x 1 + c 2 x 2 + ⋯ + c p x p ≈ 0 c_{0}+c_{1}\boldsymbol{x_{1}}+c_{2}\boldsymbol{x_{2}}+\dots+c_{p}\boldsymbol{x_{p}}\approx0 c0+c1x1+c2x2+⋯+cpxp≈0则称自变量 x 1 , x 2 , … , x p \boldsymbol{x_{1}},\boldsymbol{x_{2}},\dots,\boldsymbol{x_{p}} x1,x2,…,xp之间存在近似共线性。
最小二乘法(Ordinary Least Squares, OLS)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。
多元线性回归模型可以使用最小二乘法进行求解。其具体的推导过程在参考资料2中已经详细列出,这里不再赘述。回归模型参数的最小二乘估计的表达式为:
w ^ = ( X T X ) − 1 X T Y \hat{w}=(\boldsymbol{X^{T}}\boldsymbol{X})^{-1}\boldsymbol{X^{T}}\boldsymbol{Y} w^=(XTX)−1XTY
当多重线性回归模型的自变量之间存在完全多重共现性时,上述公式中的矩阵 X \boldsymbol{X} X的秩 r a n k ( X ) < p + 1 rank(\boldsymbol{X}) rank(X)<p+1
而对于近似共线性,此时矩阵 X X X的秩 r a n k ( X ) = p + 1 rank(X)=p+1 rank(X)=p+1,但此时估计量的方差非常大。即 v a r ( w ^ ∣ X ) = σ 2 ( X T X ) − 1 = σ 2 ∑ i = 1 p 1 λ i var(\hat{w}|X)=\sigma^{2}(\boldsymbol{X^{T}X})^{-1}=\sigma^{2}\sum_{i=1}^{p}\frac{1}{\lambda{i}} var(w^∣X)=σ2(XTX)−1=σ2i=1∑pλi1当为近似共线性时, λ i \lambda_{i} λi( λ 1 , λ 2 , … , λ p \lambda_{1},\lambda_{2},\dots,\lambda_{p} λ1,λ2,…,λp为 X T X \boldsymbol{X^{T}X} XTX的特征根)必然有趋向于0的,此时 w ^ \hat{w} w^的方差会非常大,导致 w ^ \hat{w} w^有效性降低。
另外,多重共线性会导致变量的显著性检验失去意义,有可能将重要的解释变量排除在模型之外;多重共线性可能会导致模型的预测功能失效,变大的方差容易使区间预测的“区间”变大,使预测失去意义。
一般使用方差膨胀系数(Variance Inflation Factor, VIF)和相关系数来检测多重共线性,这里只介绍前者。方差膨胀系数表示回归系数估计量的方差与假设自变量间不线性相关时方差的比值。其计算公式为: V I F i = 1 1 − R i 2 VIF_{i}=\frac{1}{1-R_{i}^{2}} VIFi=1−Ri21其中 R i R_{i} Ri为自变量 x i x_{i} xi对其他自变量做回归分析时的R_squared值( 1 − R 2 1-R^{2} 1−R2称为容忍度)。方差膨胀系数VIF越大,说明自变量之间存在共线性的可能性越大。一般来讲,如果方差膨胀因子超过10,则回归模型存在严重的多重共线性。
from sklearn.datasets import make_regression
from sklearn.linear_model import LinearRegression
import pandas as pd
import numpy as np
from sklearn.metrics import mean_squared_error
from statsmodels.stats.outliers_influence import variance_inflation_factor
import seaborn as sns
from matplotlib import pyplot as plt
from patsy.highlevel import dmatrices
X,y=make_regression(n_samples=100,n_features=2,noise=1,n_targets=1)
X=pd.DataFrame(X,columns=['feat1','feat2'])
X['feat3']=4*X['feat2']+np.random.randn(X.shape[0]) #人为制造多重共线性
#1.计算自变量之间的相关性并可视化
X_corr=X.corr()
sns.heatmap(X_corr,annot=True)
plt.show()
#2.计算各个变量的方差膨胀因子
data=X.copy()
data['target']=y
Y,X_matrix=dmatrices('target~feat1+feat2+feat3',data=data,return_type='dataframe')
#X_matrix会比X多一个常数列
vif=pd.DataFrame()
vif['feature']=X_matrix.columns
vif['VIF']=[variance_inflation_factor(X_matrix.values,i) for i in range(X_matrix.shape[1])]
#3-1.先对无共线性的数据进行OLS求解
X_1=X[['feat1','feat2']]
lr=LinearRegression()
lr.fit(X_1,y)
y_pred=lr.predict(X_1)
print("无共线性字段时模型效果:MSE={:.3f}".format(mean_squared_error(y, y_pred)))
print("无共线性字段时模型参数:{:.3f}、{:.3f}".format(lr.coef_[0],lr.coef_[1]))
print("无共线性字段时模型参数:{:.3f}".format(lr.intercept_))
#3-2.对有共线性的数据进行OLS求解
X_2=X[['feat1','feat2','feat3']]
lr1=LinearRegression()
lr1.fit(X_2,y)
y_pred1=lr1.predict(X_2)
print("有共线性字段时模型效果:MSE={:.3f}".format(mean_squared_error(y, y_pred1)))
print("有共线性字段时模型参数:{:.3f}、{:.3f}、{:.3f}".format(lr1.coef_[0],lr1.coef_[1],lr1.coef_[2]))
print("有共线性字段时模型参数:{:.3f}".format(lr1.intercept_))
结果如下:
(1)热力图:可以看出feat2和feat3之间存在较高的相关性。
(2) VIF矩阵: 特征feat2和feat3的VIF指数都大于10,说明原数据中有与其存在线性关系的特征。
(3)模型结果:从试验结果中可以看出,数据中存在共线性并不会对模型的效果产生太大影响(目前还不太清楚什么情况下会使模型预测失效)。从代码中可以知道,feat3与feat2之间存在共线性,理论上这两个参数的重要性应该相当。但从共线性数据训练的模型结果中可以看出,feat3对于模型的影响微乎其微(这就是前面说的使变量的显著性检验失去意义)。
无共线性字段时模型效果:MSE=0.861
无共线性字段时模型参数:91.748、29.889
无共线性字段时模型参数:0.169
有共线性字段时模型效果:MSE=0.852
有共线性字段时模型参数:91.771、29.467、0.102
有共线性字段时模型参数:0.176
当数据中存在多重共线性时,可以选择删除变量、PCA方法处理或者使用Lasso等带有正则化项的模型。