用 VIF 方法消除多维数据中的多重共线性

多元线性回归是我们在数据分析中经常用到的一个方法,很多人在遇到多维数据时基本上无脑使用该方法,而在用多元线性回归之后所得到的结果又并不总是完美的,其问题实际上并不出在方法上,而是出在数据上。当数据涉及的维度过多时,我们就很难保证维度之间互不相关,而这些维度又都对结果产生一定影响,当一组维度或者变量之间有较强的相关性时,就认为是一种违背多元线性回归模型基本假设的情形。今天我们就讲解一下如何用VIF方法消除多维数据中多重共线性的问题。

首先介绍一下多重共线性。

多元回归模型有一个基本假设,就是要求设计矩阵X的秩rank(X)=p+1,其中p是维度数,即要求X中的列向量之间线性无关。如果存在不全为零的p+1个数c0、c1、c2、...、cp,使得c0 + c1xi1 + c2xi2 + ... + cpxip = 0i=1, 2, 3, ..., n,则自变量x1、x2、...、xp之间存在多重共线性(multi-collinearity),因为实际问题中,完全多重共线性不太常见,所以上式中的等号经常用约等号。多重共线性到底会带来什么问题呢,笔者下面就用一个实际例子来告诉大家。

这个例子来自1994年统计摘要,是一个中国民航客运量的回归模型,统计了1978至1993年的各年数据。该模型以民航客运量为因变量y,以国民收入、消费额、民航航线里程、来华旅游入境人数作为影响客运量的主要因素,其中y的单位是万人,x1表示国民收入(亿元),x2表示消费额(亿元),x3表示铁路客运量(万人),x4表示民航航线里程(万公里),x5表示来华旅游入境人数(万人)。该数据集如图1所示,一共16行、7列(包括前面的year,虽然这一列用不到)。

图1. 数据集截图

我们用该数据集来做一个多元线性回归模型,主要使用statsmodels,代码如下。首先是导入各种库。

import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.stats.outliers_influence import variance_inflation_factor

接下来是读取数据,并生成自变量X和因变量y

file = r'C:\Users\Desktop\data.xlsx'
data = pd.read_excel(file) #读取数据
y = data['y'] #因变量数据
X = data.loc[:, 'x1':] #自变量数据

然后是生成多元回归模型,并输出结果,结果如图2所示。

X = sm.add_constant(X) #加上一列常数1,这是回归模型中的常数项
reg = sm.OLS(y, X) #生成回归模型
model = reg.fit() #拟合数据
model.summary() #生成结果

图2. 原数据的多元回归模型结果

图2中的参数较多,如果大家对这个结果不太明白,可以参考笔者之前给公众号写的文章《详解用statsmodels进行回归分析》。从图2中可以得出,我们的模型的回归方程为y = 450.9 + 0.354x1 - 0.561x2 - 0.0073x3 + 21.578x4 + 0.435x5,看到这里,估计很多人就看出一些问题了。这个回归模型从表面上看没有什么太大的问题,但是仔细分析一下其实际意义,就能看出一些问题,x2是消费额,从经济学角度分析,消费额与民航客运量之间的关系应该是正相关的,也就是x2前面的系数应该是正的,但这里却是负值,问题出在哪?这就是变量之间的多重共线性造成的。

多重共线性的影响就在于此,我们的模型结果中每一个参数都能通过检验,而且模型整体的线性显著性也很好(比如该例中R-squared值为0.998,效果非常好),但其部分参数的实际意义却和我们的常识是相违背的,而这种情况我们往往很难察觉,很多人看到自己的模型在数学角度上没有任何问题,就直接拿去用了,结果总是得到错误的结论。

那么如何来诊断多重共线性呢?笔者今天就介绍一下VIF方法。VIF全称是Variance Inflation Factor,即方差扩大因子,我们对自变量X作中心标准化,则X变为Xs,然后可以得到Xs’ Xs = (rij),这个就是自变量的相关阵。如图3所示,式(1)中C的主对角线元素VIFj=cjj,就是自变量xj的方差扩大因子,式(2)中的Rj^2是自变量xj对其余p-1个自变量的复决定系数,式(2)也可以作为方差扩大因子VIFj的定义,可知VIFj是大于等于1的。

图3. VIF方法部分公式

Rj^2度量了自变量xj与其余p-1个自变量的线性相关程度,这种相关程度越强,说明自变量之间的多重共线性就越严重,Rj^2越接近1,VIFj就越大。反之,xj与其余p-1个自变量之间的线性相关程度越弱,多重共线性就越弱,Rj^2就越接近于0,VIFj就约接近于1。由此可见,VIFj的大小反映了自变量之间是否存在多重共线性,可由它来度量多重共线性的严重程度,那么VIFj多大才算是有严重的多重共线性呢?根据统计学中的使用经验,当VIFj大于等于10的时候,就说明自变量xj与其余自变量之间存在严重的多重共线性,且这种多重共线性会过度地影响最小二乘估计值。

在了解了VIF的概念之后,我们就用代码来展示一下如何诊断并消除多重共线性。这里笔者依然使用前面的数据,但加入了VIF检测,同时给出消除多重共线性后的结果,全部代码如下。

file = r'C:\Users\Desktop\data.xlsx'
data = pd.read_excel(file)
y = data['y']
X = data.loc[:, 'x1':]
X = sm.add_constant(X)

def process(data, col):
    data = data.loc[:, col] #读取对应列标数据
    vif = [variance_inflation_factor(data.values, i) for i in range(data.shape[1])][1:] 
    if max(vif) >= 10:
        index = np.argmax(vif)+1 #得到最大值的标号
        del col[index] #删除vif值最大的一项
        return process(data, col) #递归过程
    else:
        vif = [variance_inflation_factor(data.values, i) for i in range(data.shape[1])][1:]
        return col, vif
          
cols = ['const', 'x1', 'x2', 'x3', 'x4', 'x5']
cols, vif = process(X, cols)
reg = sm.OLS(y, X[cols])
model = reg.fit()
model.summary()

这里我们从process这个函数开始讲起,process需要两个参数,一个是data,就是要输入的数据,另一个是col,就是数据的columns(即数据的列标题),我们这里默认使用的数据集是pandas.DataFrame格式的,所以数据都是有columns的。在process函数中,data = data.loc[:, col]就是读取只含有col列标的那些数据, vif = [variance_inflation_factor(data.values, i) for i in range(data.shape[1])][1:]这行代码就是计算vif的过程,variance_inflation_factor函数需要输入两个参数,分别是数据和每列数据的标号,这个标号也是从0开始的。而最终我们取得的vif结果是去掉第一项的,因为第一项对应数据集中const那一列,这一列因为都是1,所以在vif结果中要去掉,但在计算时要保留。而得到vif之后,我们要找出vif中数据最大的一项,判断其是否大于等于10。如果是,就找到其对应的标号,利用np.argmax即可,然后删除col中这一项,再把所得的结果带入到process函数中,形成递归;如果不是,则直接返回colvif这两个结果。

最终我们得到的cols['const', 'x3', 'x4', 'x5']const就是前面X = sm.add_constant(X)中加入的常数项一列,这个const列标是自动添加的,我们在这里仍沿用这个叫法,这列数据在VIF方法中只参与计算,但其值不用于比较大小。我们可以看到这里的结果去掉了x1x2这两列数据,消除多重共线性最好的方式就是把那些造成多重共线性的维度(自变量)直接去掉,vif[1.9836946236748652, 6.6499090855830225, 8.513876170172715]vif中所有数值都在10以内,说明目前已经消除了多重共线性。

然后用剩下的这些数据进行建模,得到多元回归模型,其结果如图4所示。该模型为y = 591.9 - 0.0104x3 + 26.4358x4 + 0.3174x5,该模型无论从数学上还是经济意义上,都能合理有效地进行解释。

图4. 用VIF法处理后的模型结果

判断数据是否具有多重共线性实际上有多种方法,比如特征根判定法、直接判断法等,本文主要讲解如何用VIF法来诊断多重共线性,有兴趣的读者也可以把此方法和其他方法进行一下对比学习。

作者简介:Mort,数据分析爱好者,擅长数据可视化,比较关注机器学习领域,希望能和业内朋友多学习交流。

赞赏作者

Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

长按扫码添加“Python小助手”

▼点击成为社区会员   喜欢就点个在看吧

  • 12
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 R Studio ,如果你使用的是 `lm()` 函数进行回归分析,那么通常会使用 `summary()` 函数来查看回归模型的结果。在 `summary()` 的输出,会有一个 `VIF` 列(即方差膨胀因子)。如果某个变量的 `VIF` 值大于 10,就可以认为存在多重共线性的风险。 所以,如果你想检查你的回归模型是否存在多重共线性,可以查看 `summary()` 输出的 `VIF` 值。如果有任何一个变量的 `VIF` 值大于 10,就可以认为存在多重共线性。 ### 回答2: 在RStudio进行多重共线性分析后,通常会得到一些统计数据以判断是否存在多重共线性问题。其,一个常用的指标是方差膨胀因子(VIF,Variance Inflation Factor)。VIF是通过计算自变量之间的相关程度,来评估其对多重共线性的贡献程度。 在多重共线性分析的结果,一般会列出各个自变量的VIF值。VIF值越高,表示对应的自变量与其他自变量之间存在较强的相关性,从而可能存在多重共线性问题。一般而言,当自变量的VIF值大于10或20时,可以认为存在较为严重的多重共线性。 值得注意的是,多重共线性只是用指标来衡量,在分析实际问题时,需要结合背景知识和具体情况来判断是否存在真正的多重共线性。此外,还有其他指标和方法可以用于检测多重共线性,如条件数(Condition Number)、特征值(Eigenvalue)等,也可以在分析结果找到这些指标的数值。 总之,在RStudio的多重共线性分析结果VIF值是用于判断存在多重共线性的一个重要指标。通过观察各个自变量的VIF值,可以初步判定是否存在多重共线性问题。 ### 回答3: 在RStudio进行多重共线性检验后,可以通过查看结果VIF(方差膨胀因子)来判断数据是否存在多重共线性VIF是判断多重共线性的指标之一,它衡量了某个自变量与其他自变量之间的相关性。VIF的计算公式为:VIF = 1 / (1 - R^2),其R^2是该自变量与其他自变量之间的线性相关性系数的平方。 通常而言,当某个自变量的VIF值超过10或者20时,就可以认为该变量存在较严重的多重共线性。这是因为,VIF值越大,表示自变量与其他自变量之间的相关性越高,进而说明了用户输入的自变量之间存在较强的共线性。 因此,在RStudio的多重共线性结果,我们可以通过查看各个自变量的VIF值来判断是否存在多重共线性。若某些自变量的VIF值超过了10或者20,就可以认为这些自变量之间存在较严重的多重共线性问题。 需要注意的是,多重共线性可能会导致模型的稳定性降低、系数估计不准确以及模型结果的不可靠性,因此在建立模型时需要警惕多重共线性存在,并采取相应的解决方法,如删除某些相关性较高的自变量、使用正则化技术等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值