【问题标题】:Capturing high multi-collinearity in statsmodels在 statsmodels 中捕获高度多重共线性
【发布时间】:2014-10-29 19:59:07
【问题描述】:

假设我在 statsmodels 中拟合了一个模型

mod = smf.ols('dependent ~ first_category + second_category + other', data=df).fit()

当我执行mod.summary() 时,我可能会看到以下内容:

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

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

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

【问题讨论】:

    标签: python statistics scipy statsmodels


    【解决方案1】:

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

    根据 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
    

    同样,协方差矩阵的条件数将接近无穷大,具有完美的线性相关性。

    print np.linalg.cond(corr) . # 1.23116253259
    print np.linalg.cond(multicollinear_corr) . # 6.19985218873e+15
    

    【讨论】:

      【解决方案2】:

      您可以通过检查相关矩阵特征值来检测高度多重共线性。极低的特征值表明数据是共线的,对应的特征向量显示哪些变量是共线的。

      如果数据中不存在共线性,您会认为没有一个特征值接近于零:

      >>> 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])
      

      但是,如果说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])
      

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

      >>> v[:,0]
      array([-0.4077,  0.0059, -0.5886,  0.0018,  0.6981])
      

      忽略几乎为零的系数,上面基本上说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)
      

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

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

      【讨论】:

      • 谢谢。这种方法isn't mentioned in Wikipedia。您介意解释一下吗,或者您是否知道任何可以解释为什么相关矩阵的小特征值表示多重共线性的来源?
      • @user815423426 这个理论比这里适合的要长,但是看看PCA。基本上,每个特征向量解释了与其他特征向量正交的数据的变化,特征值显示了该方向的变化量。一个几乎为零的特征值表示一个变化为零的方向,因此是共线性的。
      • 我很困惑。特征值接近于零指示共线性。第一个特征值接近于零,因此您可以检查特征向量。从[-0.4077, 0.0059, -0.5886, 0.0018, 0.6981],您确定x[0]x[2]x[4] 是共线的。所以在特征向量中,我们正在寻找接近零的数字?
      • @Jarad 是的。如果eigenvalues 接近为零,请查看它们对应的eigenvectors不接近为零的值,这些值的索引表示共线的特征.作为旁注,您还可以首先标准化数据(例如,在sklearn 中使用StandardScaler)并使用np.cov 函数(代替np.corrcoef),这将返回一个协方差矩阵(@987654344 @ 并且您可以按照上面演示的相同方式对其进行特征分解,并按照相同的步骤确定共线特征。
      猜你喜欢
      • 2019-06-13
      • 1970-01-01
      • 2016-10-05
      • 2018-01-13
      • 2013-07-16
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      相关资源
      最近更新 更多