其他分享
首页 > 其他分享> > 共线性系列故事

共线性系列故事

作者:互联网

我们经常听说,建模时应当尽量避免共线性(collinearity),会导致参数估计不稳定、模型不可靠等等。那么共线性究竟有多可怕?共线性具体会带来什么问题?共线性得到的模型是否真的不行?笔者通过自己的一些思考,结合模拟数据的测试,对共线性的问题进行了些探讨。笔者拙见,如有纰漏,烦请指教。

其实很多变量都存在少量的共线性关系,但是对建模基本没有造成影响。本文主要探讨的是共线性较严重的情况。

问题引入

现在模拟一个情景:现在需要建立一个关于消费水平的预测模型,对于每个消费者收集了3个变量:月收入 x_1,存款 x_2,所在地区的经济水平 x_3 ,假设月收入与存款之间存在线性关系,这里为了简化问题,假设是2倍的关系(当然实际情况不是2倍,而且不是严格线性关系),即 x_2=2x_1,并且假定消费水平与这3个变量之间的关系为:y=8x_1+8x_2+6x_3。当然这些是假定的理想情况,实际关系要复杂很多。因果关系是存在的,月收入、存款或当地经济水平,任意一个因素都确实可能影响消费者的消费水平。

很明显,如果直接建模,变量之间存在严重的共线性关系。我们来看看具体会产生哪些现象。

代码测试

为了解答这个问题,我用 R 和 Python 做了些测试,下面以R 代码为例:

# Test the influence of collinearity

# add random effect for the variable
add_random<-function(x, sd){
  # generate random effect on the full data, using sd=sd
  len<-length(x)
  y=x+rnorm(len, mean = 0, sd = sd*1)
  # generate random effect on the random 20% of data, using sd=sd*1.6
  len1<-round(len*0.2)
  index<-sample(1:len,len1,replace = FALSE)
  y[index]<-y[index]+rnorm(len1,mean = 0, sd = sd*1.6)
  # generate random effect on the random 16% of data, using sd=sd*1.8
  len2<-round(len*0.16)
  index<-sample(1:len,len2,replace = FALSE)
  y[index]<-y[index]+rnorm(len2,mean = 0, sd = sd*1.8)
  return(y)
}

# x1, x2, x3 are the true factor that generate the event (result varaiable, Y)
x1<-rnorm(100, mean = 16, sd = 1)
x2<-2*x1
x3<-rnorm(100, mean = 18, sd = 3)

# add random effect for x1, x2, x3, using sd=0.001.
# to guarantee the collinearity, the random effect should be small.
x1<-add_random(x1, sd=0.001)
x2<-add_random(x2, sd=0.001)
x3<-add_random(x3, sd=0.001)

# validate the relationship between x1 and x2.
cor(x1, x2)
# [1] 0.9999981

# if the cause-effect relationship is: y=8*x1+8*x2+6*x3
y<-8*x1 + 8*x2 + 6*x3
y<-add_random(y, sd=1)

# validate the relationship between y and (8*x1 + 8*x2 + 6*x3).
cor(y, 8*x1 + 8*x2 + 6*x3)
# [1] 0.9990227

# x4 is the combination of x1 and x2 with the same weight.
x4<-x1+x2

# fit the model using x1 and x3
model_A<-lm(y~x1+x3)
summary(model_A)
# Coefficients:
#             Estimate  Std.Error   t value  Pr(>|t|)    
# (Intercept)  0.14680    2.42208   0.061    0.952    
# x1          24.03943    0.15005 160.207   <2e-16 ***
# x3           5.94959    0.04482 132.745   <2e-16 ***
# Multiple R-squared:  0.9981,	Adjusted R-squared:  0.998 

# fit the model using x2 and x3
model_B<-lm(y~x2+x3)
summary(model_B)
# Coefficients:
#             Estimate   Std.Error  t value  Pr(>|t|)    
# (Intercept)  0.16278    2.42378   0.067    0.947    
# x2          12.01916    0.07508 160.088   <2e-16 ***
# x3           5.94944    0.04485 132.643   <2e-16 ***
# Multiple R-squared:  0.9981,	Adjusted R-squared:  0.998

# fit the model using x4 and x3
model_C<-lm(y~x4+x3)
summary(model_C)
# Coefficients:
#             Estimate   Std.Error  t value  Pr(>|t|)    
# (Intercept)  0.15712    2.42293   0.065    0.948    
# x4           8.01290    0.05003 160.146   <2e-16 ***
# x3           5.94949    0.04484 132.692   <2e-16 ***
# Multiple R-squared:  0.9981,	Adjusted R-squared:  0.998 

# fit the model using x1, x2 and x3. This is the case which existing the collinearity.
model_D<-lm(y~x1+x2+x3)
summary(model_D)
# Coefficients:
#             Estimate   Std.Error  t value  Pr(>|t|)    
# (Intercept)  0.14387    2.43502   0.059    0.953    
# x1          28.98087   75.73214   0.383    0.703    
# x2          -2.47062   37.86443  -0.065    0.948    
# x3           5.94962    0.04505 132.055   <2e-16 ***
# Multiple R-squared:  0.9981,	Adjusted R-squared:  0.998 

下面,我们对这些结果进行解读。

共线性对非共线性变量的影响

共线性对非共线性变量的影响。这句话有点拗口,具体来说,我想探讨的第一个问题是:如果保留共线性的变量,那么建模时,那些非公线性的变量的系数估计会不会受到影响?

由上述 model_D 可知,x_3 的系数的估计没有受到任何影响。并且,在增加变量数目或改变样本量后重新进行测试,都显示:非共线性的变量的系数估计都没有受到任何影响。

因此得出结论1:共线性对非共线性的变量的系数估计不产生影响。

 

共线性对模型拟合优度的影响

共线性对模型拟合优度的影响。这句话有点学术化,具体来说,我想探讨的第二个问题是:如果保留共线性的变量,那么建立的模型的预测能力是否受到影响?

由上述 model_D 可知,模型的 R^2 没有下降。并且,在增加变量数目或改变样本量后重新进行测试,都验证了这个现象。

因此得出结论2:共线性不会影响模型的拟合优度。

 

共线性对模型产生的具体影响

 

会使得共线性的变量的系数估计变得不可靠

 

原理解析

 

共线性影响模型泛化的一种情况

其实,有一种情况下,共线性建模会影响模型的泛化能力。当共线性的情况是由数据偶然所造成时,换一批数据后,共线性关系如果消失了,那么使用原先数据训练的模型,在新的数据中预测准确性会很差。

这种情况是存在的,仍然以刚刚的模拟情景为例。当我们用之前包含共线性变量的模型去测试这样一群消费者:刚刚毕业进入IT大厂的高收入程序员。高收入程序员,由于刚刚毕业,存款极少,那么存款与收入之间的共线性关系就消失了,那么之前保留共线性所训练的模型就有可能出现问题(因为系数的估计是不准的)。

更一般的情况是,当前选定的样本中,某些变量确实存在共线性,但是当扩大样本量后,共线性的关系消失了,那么原先保留共线性建模所得到的规律,在扩大样本量后就不再适用了。这种现象,笔者称之为“数据偶然造成的共线性”。这种共线性会导致模型变得不准确,此时需要对变量进行取舍。比如在某个小样本中,变量A和B存在共线性,且这种共线性时偶然造成的,那么我们需要考虑仅保留A或B(在当前数据上看,保留A或B似乎是差不多的),假定我们保留了A,并且系数有统计学意义。当换一批数据,AB的共线性关系消失时,AB中有一个和结局变量的关系有可能变得不显著。如果此时A变得不显著了,说明我们保留变量时没选对,人为造成了假阳性和假阴性。因此,在共线性时,挑选变量这一过程又变得没那么轻而易举,不是一个LASSO或者逐步回归能简单处理的。似乎,更明智的做法是,将所有变量保留下来,等待其他数据进行验证,经得起考验的变量就可以考虑纳入模型了。

 

人为消除共线性的好处

 

解释变量的意义解读

相比非线性模型,线性模型有一个好处,就是得到的模型参数(也就是变量的系数;非线性模型中的模型参数就不一定是系数了)是有实际意义的,模型本身也是基于概率和正态分布而推导的。因此,笔者习惯于优先使用广义线性模型拟合数据,如果效果不好,再使用非线性模型(如SVM、XGBoost、神经网络等)。

那么对于线性模型的解释变量的系数,究竟有怎样的意义呢?在没有共线性存在时,变量的系数的意义是确定的。在线性回归模型中,系数 w 的意义是:该变量每增加一个单位数值都会使结局变量增加 w。而在 Logistic 回归中,系数的意义可以从OR的角度来解释(此处不赘述,Logistic 回归中十分重要的基本知识)。在理想状态下(完全不存在任何共线性时),单变量建模所得的系数与多变量建模所得的系数是一致的(可以程序模拟验证这一结论),因此其解释意义是不变的。

然而,当存在共线性时,情况就不一样了。若直接包含共线性建模,则所得系数无法收敛(系数取值有无数种可能),无法解释。若只保留共线性变量中的一个变量进行建模,则得到的系数的解释意义,就不再应该是该系数原本的解释意义了,严格来说应该是共线性变量群体的综合意义。或者说,保留的变量是一群变量的“代表”。因此在选择性保留变量时,我们实际上已经赋予这个变量新的含义了,这一点值得注意。这一点有点像主成分分析(PCA)的哲学,保留的变量其实是一个复合含义的变量(虽然表明上没有做成分映射、就只是单纯保留了这个变量)。比如,上述 model_A。仅保留了月收入和当地经济水平这两个变量,但是此时对于月收入的系数(w1=24)的解读,应该是:由月收入和存款构成新的变量(我们称之为“个人经济能力”),该变量采用的数据暂时仍然是月收入的数据,该变量带来的效应可以用 w1来衡量的。

我们常说,变量的系数代表着变量的重要性或者贡献。但其实这个说法是有问题的。第一,变量的系数会受到数据方差和尺度的影响,不同方差和尺度的变量,比较其系数大小是不公平的。第二,变量的系数并非就反应了这个变量的真实意义(存在共线性时,其代表的是共线性变量群体的综合意义)。

基于此,我们需要更好的办法去评估各个变量的重要性。在线性回归中,我们可以评估各个变量的R^2 贡献,在 Logistic 回归中我们可以使用似然比检验中的卡方值(或Wald检验近似替代的卡方值,Wald检验的卡方值就等于“系数/系数标准差”。Frank Harrell 教授很推荐使用Wald检验的卡方值来表示变量的重要性。不过个人对Wald检验的卡方值仍然持保守态度)。

进行多变量建模,我们一般会先对变量进行标准化处理(normalization,先中心化再尺度化),这样应该也是可以让各个变量在比较系数时变得公平。此外,标准化处理还有个好处,就是可以加快梯度下降的效率(当各个变量方差差别较大时,各个变量对应的系数的收敛速度差别很大,在CNN训练时也有这个问题,可以采用不同的学习率对各个参数更新迭代,也可以采用标准化的策略)。大概,BatchNormalization有助于训练深度模型,是有这个原因在里面的吧。

 

更广泛的场景

实际建模中,情况要比刚刚的讨论复杂很多,我们甚至不考虑“因果关系”,甚至试图建立“表型与表型之间关系”的模型,这将很可能引入更多的共线性变量!典型的案例是代谢组学研究,比如探索代谢物与疾病疗效之间的关系(代谢物是表型、疗效也是表型)的问题中,因变量(各个代谢物)之间存在高度的共线性。

因此,我们甚至会发现,共线性的情况变得更加普遍了。我们可以找到很多存在线性关系的特征,这就使得建模更加费劲了。当然,如果没有“因果关系”,建模时也就不那么关注系数的解释意义了(机器学习的黑箱也是如此,各个变量的解释意义被忽视)。那么,既然如此,参数是否收敛也就变得不那么重要,只要预测能力强且泛化能力强(外推性好),那就行啦。具体参数是啥不重要了,当作“黑箱模型”啦。

 

规律的简单性与复杂性

规律(模型)是简单的。我们可以利用少量关键的信息建立模型,能保证模型相对稳定。因为使用的特征是极其关键的特征,甚至是整个研究群体的普遍特征(比如模拟情景中的“当地经济水平与消费水平存在普遍的相关规律”),所以模型能保证稳定性、广泛适用性。

规律(模型)是复杂的。我们常常对简单的模型表示不满足(总是希望追求完美),因为预测结果相对粗糙,不够精准,我们希望能更精准地实现预测。那么就需要找出更多有用的信息,加入更多的特征进行建模。理想状态下,当我们找到所有有用的信息,建立因果作用网络模型,那么预测能力可以接近完美。但是我们找到的规律总是不全面的,由于规律的不全面,导致某些规律只适用于部分亚群体。尤其是存在共线性关系时,这将使得建立的模型变得不可靠(我们很难反推出各个共线性变量的真实系数);这时大家往往宁愿舍弃共线性的变量,来谋得模型的稳定。但是,如果我们能够挖掘到更多有用的信息(比如建立更复杂的理论或者加入更多的先验知识,推导出各个共线性变量的真实系数,甚至建立各种非线性关系、网络关系等),有可能可以模拟出真实的规律。

不同的规律,复杂性是不同的。有的规律本身就很简单,那么就很容易模拟得很接近真实(比如根据身高体重来预测合适的衣服尺寸)。而有的规律本身就很复杂(比如预测任意一个人得癌症的风险),则模型是复杂的(当然我们常常会根据少数关键信息建立简单的模型)。

 

 

 

 

 

标签:共线性,系数,系列,变量,故事,模型,保留,建模
来源: https://blog.csdn.net/fjsd155/article/details/94852770