OLS回归:Scikit vs.状态模型?

问题描述 投票:21回答:2

简短版本:我在一些数据上使用了scikit LinearRegression,但是我习惯了p值,所以将数据放入statsmodels OLS,尽管R ^ 2大致相同,但变量系数都大不相同。这让我很担心,因为最可能的问题是我在某个地方犯了错误,现在我对这两个输出都没有信心(因为我可能错误地制作了一个模型,但不知道哪个模型)。

更长的版本:因为我不知道问题出在哪里,我不确切地知道要包括哪些细节,包括一切可能都太多了。我也不确定包含代码或数据。

我的印象是scikit的LR和statsmodels OLS都应该做OLS,据我所知OLS是OLS所以结果应该是相同的。

对于scikit的LR,结果是(统计上)相同,无论我是否设置normalize = True或= False,我觉得有点奇怪。

对于statsmodels OLS,我使用来自sklearn的StandardScaler来规范化数据。我添加了一列,因此它包含一个拦截(因为scikit的输出包括一个拦截)。更多关于这一点:http://statsmodels.sourceforge.net/devel/examples/generated/example_ols.html(添加此列没有将变量系数更改为任何显着的程度,并且截距非常接近于零。)StandardScaler不喜欢我的int不是浮点数,所以我试过这个:https://github.com/scikit-learn/scikit-learn/issues/1709那个使警告消失但结果完全相同。

当然,我使用5倍cv进行sklearn方法(每次R ^ 2对于测试和训练数据都是一致的),对于statsmodels我只是把它全部丢弃。

sklearn和statsmodels的R ^ 2约为0.41(这对社会科学有益)。这可能是一个好兆头或只是巧合。

这些数据是对WoW(来自http://mmnet.iis.sinica.edu.tw/dl/wowah/)中的化身的观察,我每周都要用它来制作一些具有不同特征的化身。最初这是一个数据科学课的课程项目。

独立变量包括一周中观察的数量(int),角色等级(int),如果在公会中(布尔),当看到时(工作日的布尔,平日前夕,工作日晚,周末相同的三个),对于字符类的虚拟(在数据收集时,在WoW中只有8个类,因此有7个虚拟变量并且原始字符串分类变量被删除),以及其他类。

因变量是每个字符在该周(int)中获得的级别数。

有趣的是,类似变量中的一些相对顺序在statsmodels和sklearn之间保持不变。因此,尽管负载非常不同,但“看到”的等级顺序是相同的,并且角色类假人的等级顺序是相同的,尽管负载是非常不同的。

我认为这个问题类似于这个问题:Difference in Python statsmodels OLS and R's lm

我在Python和统计数据方面做得很好,但是还不够好,无法想象这样的东西。我试着阅读sklearn docs和statsmodels docs,但是如果答案就在那里,我不理解它。

我会很高兴知道:

  1. 哪个输出可能准确? (当然,如果我错过了一个小兵,他们可能都会。)
  2. 如果我弄错了,它是什么以及如何解决它?
  3. 我可以在没有问这里的情况下想出来,如果是这样的话怎么样?

我知道这个问题有一些相当模糊的部分(没有代码,没有数据,没有输出),但我认为它更多的是关于两个包的一般过程。当然,一个似乎更多的统计数据,似乎更多的机器学习,但他们都是OLS所以我不明白为什么输出不一样。

(我甚至尝试了一些其他的OLS调用三角测量,一个给了一个低得多的R ^ 2,一个循环了五分钟而我杀了它,一个崩溃了。)

谢谢!

python scikit-learn linear-regression statsmodels
2个回答
32
投票

听起来你没有向两个程序提供相同的回归量X矩阵(但见下文)。下面是一个示例,向您展示需要使用哪些选项来生成相同结果的sklearn和statsmodel。

import numpy as np
import statsmodels.api as sm
from sklearn.linear_model import LinearRegression

# Generate artificial data (2 regressors + constant)
nobs = 100 
X = np.random.random((nobs, 2)) 
X = sm.add_constant(X)
beta = [1, .1, .5] 
e = np.random.random(nobs)
y = np.dot(X, beta) + e 

# Fit regression model
sm.OLS(y, X).fit().params
>> array([ 1.4507724 ,  0.08612654,  0.60129898])

LinearRegression(fit_intercept=False).fit(X, y).coef_
>> array([ 1.4507724 ,  0.08612654,  0.60129898])

正如一位评论者建议的那样,即使你给两个程序提供相同的X,X也可能没有完整的列级别,并且他们可以在幕后进行(不同的)动作以使OLS计算通过(即丢弃不同的列)。

我建议你使用pandaspatsy来处理这个问题:

import pandas as pd
from patsy import dmatrices

dat = pd.read_csv('wow.csv')
y, X = dmatrices('levels ~ week + character + guild', data=dat)

或者,或者,statsmodels公式界面:

import statsmodels.formula.api as smf
dat = pd.read_csv('wow.csv')
mod = smf.ols('levels ~ week + character + guild', data=dat).fit()

编辑:这个例子可能很有用:http://statsmodels.sourceforge.net/devel/example_formulas.html


2
投票

我只想在这里添加,就sklearn而言,它并没有使用OLS方法进行线性回归。由于sklearn来自数据挖掘/机器学习领域,他们喜欢使用Steepest Descent Gradient算法。这是一种对初始条件等敏感的数值方法,而OLS是一种分析闭合形式方法,因此应该预期差异。因此,statsmodels来自经典统计领域,因此他们将使用OLS技术。因此,来自2个不同库的两个线性回归之间存在差异


0
投票

如果你使用statsmodels,我强烈建议使用statsmodels公式接口。您将使用statsmodels公式接口从OLS获得与sklearn.linear_model.LinearRegression或R,或SAS或Excel相同的旧结果。

smod = smf.ols(formula ='y~ x', data=df)
result = smod.fit()
print(result.summary())

如有疑问,请

  1. 尝试阅读源代码
  2. 尝试使用不同语言进行基准测试,或者
  3. 从头开始尝试OLS,这是基本的线性代数。
© www.soinside.com 2019 - 2024. All rights reserved.