【问题标题】:OLS using statsmodel.formula.api versus statsmodel.apiOLS 使用 statsmodel.formula.api 与 statsmodel.api
【发布时间】:2015-08-19 10:38:39
【问题描述】:

谁能向我解释一下 statsmodel.formula.api 中的 ols 与 statsmodel.api 中的 ols 之间的区别?

使用 ISLR 文本中的广告数据,我使用两者运行了一个 ols,得到了不同的结果。然后我与 scikit-learn 的 LinearRegression 进行了比较。

import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
import statsmodels.api as sm
from sklearn.linear_model import LinearRegression

df = pd.read_csv("C:\...\Advertising.csv")

x1 = df.loc[:,['TV']]
y1 = df.loc[:,['Sales']]

print "Statsmodel.Formula.Api Method"
model1 = smf.ols(formula='Sales ~ TV', data=df).fit()
print model1.params

print "\nStatsmodel.Api Method"
model2 = sm.OLS(y1, x1)
results = model2.fit()
print results.params

print "\nSci-Kit Learn Method"
model3 = LinearRegression()
model3.fit(x1, y1)
print model3.coef_
print model3.intercept_

输出如下:

Statsmodel.Formula.Api Method
Intercept    7.032594
TV           0.047537
dtype: float64

Statsmodel.Api Method
TV    0.08325
dtype: float64

Sci-Kit Learn Method
[[ 0.04753664]]
[ 7.03259355]

statsmodel.api 方法返回的 TV 参数与 statsmodel.formula.api 和 scikit-learn 方法不同。

statsmodel.api 运行什么样的 ols 算法会产生不同的结果?有没有人有可以帮助回答这个问题的文档链接?

【问题讨论】:

标签: python linear-regression


【解决方案1】:

我在使用 Logit 函数时遇到了类似的问题。 (我使用 patsy 创建矩阵,所以截距就在那里。) 我的 sm.logit 没有收敛。 然而,我的 sm.formula.logit 正在收敛。

输入的数据完全相同。 我将求解器方法更改为“牛顿”,并且 sm.logit 也收敛了。 这两个版本是否可能具有不同的默认求解器方法。

【讨论】:

    【解决方案2】:

    今天遇到这个问题,想详细说明@stellasia 的答案,因为 statsmodels 文档可能有点模棱两可。

    除非您在实例化OLS 时使用actual R-style string-formulas,否则您需要在statsmodels.formulas.api 和普通statsmodels.api 下添加一个常量(字面意思是一列1)。 @Chetan 在这里使用 R 风格的格式 (formula='Sales ~ TV'),所以他不会遇到这种微妙之处,但对于有一些 Python 知识但没有 R 背景的人来说,这可能会非常混乱。

    此外,在构建模型时,是否指定hasconst 参数无关紧要。 (这有点傻。)换句话说,除非您使用 R 风格的字符串公式,否则 hasconst 会被忽略,即使它应该这样做

    [指示] RHS 是否包含用户提供的常量

    因为,在脚注中

    除非您使用公式,否则模型不会添加任何常数。

    下面的示例显示,如果不使用 R 样式的字符串公式,.formulas.api.api 都需要用户添加的列向量 1。

    # Generate some relational data
    np.random.seed(123)
    nobs = 25 
    x = np.random.random((nobs, 2)) 
    x_with_ones = sm.add_constant(x, prepend=False)
    beta = [.1, .5, 1] 
    e = np.random.random(nobs)
    y = np.dot(x_with_ones, beta) + e
    

    现在将xy 输入Excel 并运行数据>数据分析>回归,确保未选中“常数为零”。你会得到以下系数:

    Intercept       1.497761024
    X Variable 1    0.012073045
    X Variable 2    0.623936056
    

    现在,尝试在x 而非x_with_ones 上运行此回归,在statsmodels.formula.apistatsmodels.api 中将hasconst 设置为NoneTrueFalse。您会看到,在这 6 个场景中的每一个场景中,都没有返回截距。 (只有两个参数。)

    import statsmodels.formula.api as smf
    import statsmodels.api as sm
    
    print('smf models')
    print('-' * 10)
    for hc in [None, True, False]:
        model = smf.OLS(endog=y, exog=x, hasconst=hc).fit()
        print(model.params)
    
    # smf models
    # ----------
    # [ 1.46852293  1.8558273 ]
    # [ 1.46852293  1.8558273 ]
    # [ 1.46852293  1.8558273 ]
    

    现在,将1.0s 的列向量添加到x 可以正确运行。您可以在此处使用smf,但如果您不使用公式,则实际上没有必要。

    print('sm models')
    print('-' * 10)
    for hc in [None, True, False]:
        model = sm.OLS(endog=y, exog=x_with_ones, hasconst=hc).fit()
        print(model.params)
    
    # sm models
    # ----------
    # [ 0.01207304  0.62393606  1.49776102]
    # [ 0.01207304  0.62393606  1.49776102]
    # [ 0.01207304  0.62393606  1.49776102]
    

    【讨论】:

    • 非常好的答案,从 stellasia 的回答中澄清了许多事情。在我看来,你的答案应该被勾选为正确。 (由于 stellasia 的回答,我花了几个小时才明白,如果您不使用使用公式,即使 statsmodels.formula.api 也不会添加截距)
    【解决方案3】:

    区别在于是否存在截距:

    • statsmodels.formula.api 中,与 R 方法类似,常量会自动添加到您的数据中,并在拟合时截距
    • statsmodels.api 中,您必须自己添加一个常量(请参阅the documentation here)。尝试使用来自 statsmodels.api 的add_constant

      x1 = sm.add_constant(x1)
      

    【讨论】:

    • 我会补充一点,如果你想运行固定效应回归,statsmodels.formula.api 会更容易
    • 我的印象是这个答案现在已经过时了。请在此处查看更多详细信息:stackoverflow.com/questions/51126928/…。如果我说错了,请提前道歉。
    猜你喜欢
    • 1970-01-01
    • 2022-07-24
    • 2014-12-19
    • 2017-11-16
    • 2019-08-21
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    相关资源
    最近更新 更多