OLS回归:Scikit与Statsmodels?

时间:2014-02-26 22:34:32

标签: python scikit-learn linear-regression statsmodels

短版:我在某些数据上使用了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(这对社会科学有益)。这可能是一个好兆头或只是巧合。

这些数据是对魔兽世界(来自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. 我可以在不问这里的情况下解决这个问题,如果是这样的话怎么样?
  4. 我知道这个问题有一些相当模糊的部分(没有代码,没有数据,没有输出),但我认为它更多的是关于两个包的一般过程。当然,一个似乎更多的统计数据,似乎更多的机器学习,但他们都是OLS所以我不明白为什么输出不一样。

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

    谢谢!

3 个答案:

答案 0 :(得分:31)

听起来你没有向两个程序提供相同的回归量矩阵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

答案 1 :(得分:2)

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

答案 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,这是基本的线性代数。