捕获statsmodels中的高多重共线性

Ame*_*ina 23 python statistics scipy statsmodels

说我在statsmodels中适合模型

mod = smf.ols('dependent ~ first_category + second_category + other', data=df).fit()
Run Code Online (Sandbox Code Playgroud)

当我这样做时,mod.summary()我可能会看到以下内容:

Warnings:
[1] The condition number is large, 1.59e+05. This might indicate that there are
strong multicollinearity or other numerical problems.
Run Code Online (Sandbox Code Playgroud)

有时警告是不同的(例如,基于设计矩阵的特征值).如何在变量中捕获高多重共线性条件?此警告是否存储在模型对象的某处?

另外,我在哪里可以找到字段的描述summary()

beh*_*uri 48

可以通过检查检测的高多重共线性特征值相关矩阵.非常低的特征值表明数据是共线的,并且相应的特征向量显示哪些变量是共线的.

如果数据中没有共线性,则可以预期没有任何特征值接近零:

>>> xs = np.random.randn(100, 5)      # independent variables
>>> corr = np.corrcoef(xs, rowvar=0)  # correlation matrix
>>> w, v = np.linalg.eig(corr)        # eigen values & eigen vectors
>>> w
array([ 1.256 ,  1.1937,  0.7273,  0.9516,  0.8714])
Run Code Online (Sandbox Code Playgroud)

但是,如果说x[4] - 2 * x[0] - 3 * x[2] = 0,那么

>>> noise = np.random.randn(100)                      # white noise
>>> xs[:,4] = 2 * xs[:,0] + 3 * xs[:,2] + .5 * noise  # collinearity
>>> corr = np.corrcoef(xs, rowvar=0)
>>> w, v = np.linalg.eig(corr)
>>> w
array([ 0.0083,  1.9569,  1.1687,  0.8681,  0.9981])
Run Code Online (Sandbox Code Playgroud)

其中一个特征值(这里是第一个)接近于零.相应的特征向量是:

>>> v[:,0]
array([-0.4077,  0.0059, -0.5886,  0.0018,  0.6981])
Run Code Online (Sandbox Code Playgroud)

忽略几乎为零的系数,上面基本上说x[0],x[2]并且x[4]是共线的(如预期的那样).如果标准化xs值并乘以此特征向量,则结果将以小方差悬停在零附近:

>>> std_xs = (xs - xs.mean(axis=0)) / xs.std(axis=0)  # standardized values
>>> ys = std_xs.dot(v[:,0])
>>> ys.mean(), ys.var()
(0, 0.0083)
Run Code Online (Sandbox Code Playgroud)

注意,这ys.var()基本上是接近零的特征值.

因此,为了捕获高多线性,请查看相关矩阵的特征值.

  • @ user815423426这个理论比这里的理论要长,但请看[PCA`](https://en.wikipedia.org/wiki/Principal_component_analysis).基本上,每个特征向量解释了与其他特征向量正交的数据的变化,并且特征值表示在该方向上有多少变化.几乎为零的本征值表示零变化的方向,因此是共线性. (7认同)
  • @Jarad 是的。如果“特征值”*接近*零,则查看它们对应的“特征向量”以获取*不接近*零的值,并且这些值的索引表示共线的特征。作为旁注,您还可以先对数据进行标准化(例如,在“sklearn”中使用“StandardScaler”)并使用“np.cov”函数(代替“np.corrcoef”),这将返回协方差矩阵 (`cov_mat = np.cov(xs_standardized)` 并且您可以以上面演示的相同方式对其执行特征分解,并按照相同的程序确定共线特征。 (2认同)

elz*_*elz 5

基于R 的类似问题,还有其他一些可以帮助人们的选择。我正在寻找一个可以捕获共线性的数字,选项包括相关矩阵的行列式和条件数。

根据R个答案之一,相关矩阵的行列式将为“从0(完全共线性)到1(无共线性)”。我发现边界范围很有用。

行列式的翻译示例:

import numpy as np
import pandas as pd

# Create a sample random dataframe
np.random.seed(321)
x1 = np.random.rand(100)
x2 = np.random.rand(100)
x3 = np.random.rand(100)
df = pd.DataFrame({'x1': x1, 'x2': x2, 'x3': x3})

# Now create a dataframe with multicollinearity
multicollinear_df = df.copy()
multicollinear_df['x3'] = multicollinear_df['x1'] + multicollinear_df['x2']

# Compute both correlation matrices
corr = np.corrcoef(df, rowvar=0)
multicollinear_corr = np.corrcoef(multicollinear_df, rowvar=0)

# Compare the determinants
print np.linalg.det(corr) . # 0.988532159861
print np.linalg.det(multicollinear_corr) . # 2.97779797328e-16
Run Code Online (Sandbox Code Playgroud)

同样,协方差矩阵的条件数将趋近于无穷大且具有完美的线性依赖性。

print np.linalg.cond(corr) . # 1.23116253259
print np.linalg.cond(multicollinear_corr) . # 6.19985218873e+15
Run Code Online (Sandbox Code Playgroud)