无法将 y 截距添加到线性模型?

Posted

技术标签:

【中文标题】无法将 y 截距添加到线性模型?【英文标题】:Can't add y-intercept to linear model? 【发布时间】:2019-11-19 04:16:08 【问题描述】:

我正在尝试使用 statsmodels 构建多元线性回归模型。我希望模型包含一个常数,但它没有正确添加。我使用了一个不同的、较小的数据集,它可以工作,但我现在的数据集不行。我当前的数据集大约是 1000 个观测值 x 2000 个变量。

# Multiple Linear Regression

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import statsmodels.api as sm

# Importing the dataset, y value is last column, other columns are X
dataset = pd.read_excel('sheet.xlsx')
X = dataset.iloc[:, :-1]
y = dataset.iloc[:, -1]

#Stats
X2 = sm.add_constant(X)
test = sm.OLS(y, X2)
test2 = test.fit()
print(test2.summary())

我的输出如下所示:

/home/chasel88/.local/lib/python3.7/site-packages/statsmodels/regression/linear_model.py:1648: RuntimeWarning: divide by zero encountered in true_divide
  return 1 - (np.divide(self.nobs - self.k_constant, self.df_resid)
/home/chasel88/.local/lib/python3.7/site-packages/statsmodels/regression/linear_model.py:1649: RuntimeWarning: invalid value encountered in double_scalars
  * (1 - self.rsquared))
/home/chasel88/.local/lib/python3.7/site-packages/statsmodels/regression/linear_model.py:1665: RuntimeWarning: divide by zero encountered in double_scalars
  return self.s-s-r/self.df_resid
/home/chasel88/.local/lib/python3.7/site-packages/statsmodels/regression/linear_model.py:1578: RuntimeWarning: divide by zero encountered in double_scalars
  return np.dot(wresid, wresid) / self.df_resid
                            OLS Regression Results                            
==============================================================================
Dep. Variable:            Reverse Log   R-squared:                       1.000
Model:                            OLS   Adj. R-squared:                    nan
Method:                 Least Squares   F-statistic:                     0.000
Date:                 Di, 09 Jul 2019   Prob (F-statistic):                nan
Time:                        16:36:58   Log-Likelihood:                 31546.
No. Observations:                1097   AIC:                        -6.090e+04
Df Residuals:                       0   BIC:                        -5.541e+04
Df Model:                        1096                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Measurement1      2.1712        inf          0        nan         nan         nan
Measurement2    -0.1254        inf         -0        nan         nan         nan
Measurement3     -1.0199        inf         -0        nan         nan         nan
Measurement4      2.4232        inf          0        nan         nan         nan
Measurement5      0.7925        inf          0        nan         nan         nan
Measurement6     -0.6553        inf         -0        nan         nan         nan

它没有显示 y 截距,但是当我在 sklearn 中运行这些数据时,我得到了截距。我只是想使用 statsmodels 以便我可以获得系数的 p 值。除了丢失的截距外,到处都写着“nan”,它表示除以零错误。有谁知道问题出在哪里?

【问题讨论】:

您有 1097 个观察值,但有 2000 个看似不共线的变量。完美的 1 和 0 Df 残差的 R 平方应该让你眼前一亮;您的数据严重过度拟合。 我想知道哪些预测变量对我的响应变量影响最大,p 值不错。我不需要它来很好地预测新数据。但我是新手,所以我不确定这是否是正确的方向。 基本上,我试图找出我的 2000 个变量中最有影响力和最重要的变量。我不确定这是否会导致过度拟合,但这是一个方面。 在这种情况下,您可能需要查看LASSO 回归。这是变量选择的一种方法。这可以通过statsmodels 或sklearn 来完成 【参考方案1】:

为您的sklearnstatsmodels 回归提供mcve 会有很大帮助。

撇开使用 2,000 个变量进行回归的优点不谈,您的输入数据似乎可能包含一列常量。 sm.add_constant() 的帮助页面指出:

has_constant : str 'raise', 'add', 'skip'
    Behavior if ``data`` already has a constant. The default will return
    data without adding another constant. If 'raise', will raise an
    error if a constant is present. Using 'add' will duplicate the
    constant, if one is present.

正常行为

np.random.seed(42)
df = pd.DataFrame('x1':np.random.rand(20) // .1,
                  'x2':np.random.rand(20) // .01,
                  'x3':np.random.rand(20) // .01,
                  'y':np.random.rand(20) // .01)

X = df.iloc[:, :-1]
y = df.iloc[:, -1]

X2 = sm.add_constant(X)
model = sm.OLS(y, X2).fit()
print(model.summary())

返回

const         23.7669     24.751      0.960      0.351     -28.702      76.236
x1             1.1993      2.943      0.408      0.689      -5.039       7.438
x2             0.4973      0.327      1.523      0.147      -0.195       1.190
x3            -0.1122      0.231     -0.486      0.634      -0.602       0.377

数据集中已有常数

如果数据集中已经存在常数项,sm.add_constant() 运行,不返回任何消息,并且不添加常数。在下面的例子中,常数是1以外的值,所以回归输出中k的参数与上面的正常情况不同。

np.random.seed(42)
df = pd.DataFrame('x1':np.random.rand(20) // .1,
                  'x2':np.random.rand(20) // .01,
                  'x3':np.random.rand(20) // .01,
                  'k':list([15])*20,
                  'y':np.random.rand(20) // .01)

X = df.iloc[:, :-1]
y = df.iloc[:, -1]

X2 = sm.add_constant(X)
model = sm.OLS(y, X2).fit()
print(model.summary())

返回

                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
x1             1.1993      2.943      0.408      0.689      -5.039       7.438
x2             0.4973      0.327      1.523      0.147      -0.195       1.190
x3            -0.1122      0.231     -0.486      0.634      -0.602       0.377
k              1.5845      1.650      0.960      0.351      -1.913       5.082

【讨论】:

我使用了 has_constant='raise' 参数,它引发了一个错误,并说已经存在一个常量。这是否意味着它将我的列之一解释为常数?如果已经有一个常数,那么没有显示常数是否有意义?有没有办法确保没有任何列被用作常量? 实际上,我的问题可能是变量多于观察值吗?当我使用 800 个 ish 变量与 1000 个 ish 观察值相比时,它有效,但当我使用 1200 个或更多 ish 变量时就不行了。 @ChaseLewis 是的,如果您已经有一个所有值都相同的列,sm.add_constant 会将 该列 解释为常量,如我上面的示例所示。和示例一样,它不会显示名为const 的参数,但显示常量列(在上面的第二个示例中,k)。 特别是考虑到您使用has_constant='raise' 进行的测试,我怀疑具有常量值的列是您在第二条评论中描述的测试中未包含的“400-ish”变量之一。您可以使用 df.nunique() == 1 进行测试 没有一列具有完全相同的值,尽管所有列都用 1 或 0 填充。但我认为当我添加第 1038 个变量时,问题就发生了。我可以阻止程序选择一列作为常数吗?此外,当变量超过我的 1097 个观察值时,许多统计数据都会变成“nan”。

以上是关于无法将 y 截距添加到线性模型?的主要内容,如果未能解决你的问题,请参考以下文章

怎样用SPSS做一元线性回归?具体怎么检验相关性

线性模型-分类模型

R线性回归模型构建示例

如何在 polr 有序 logit 模型的截距上测试线性假设?

线性回归训练数据的负R2

Python Sklearn 线性回归产生不正确的系数值