我很确定这是一个功能,而不是一个bug,但我想知道是否有一种方法可以使sklearn
和statsmodels
在他们的logit估计中匹配。一个非常简单的例子:
import numpy as np
import statsmodels.formula.api as sm
from sklearn.linear_model import LogisticRegression
np.random.seed(123)
n = 100
y = np.random.random_integers(0, 1, n)
x = np.random.random((n, 2))
# Constant term
x[:, 0] = 1.
statsmodels
的估计:
sm_lgt = sm.Logit(y, x).fit()
Optimization terminated successfully.
Current function value: 0.675320
Iterations 4
print sm_lgt.params
[ 0.38442 -1.1429183]
和sklearn
的估算值:
sk_lgt = LogisticRegression(fit_intercept=False).fit(x, y)
print sk_lgt.coef_
[[ 0.16546794 -0.72637982]]
我认为这与sklearn
中的实现有关,它使用了某种正则化。是否可以像statsmodels
那样估计一个barebones logit(它实际上更快,扩展得更好)。此外,sklearn
是否提供推理(标准误差)或边际效应?
是否可以像
那样估计一个准系统logit ?statsmodels
您可以将C
(反正则化强度)参数设置为任意高的常数,只要它是有限的:
>>> sk_lgt = LogisticRegression(fit_intercept=False, C=1e9).fit(x, y)
>>> print(sk_lgt.coef_)
[[ 0.38440594 -1.14287175]]
关闭正则化是不可能的,因为底层求解器Liblinear不支持这一点。
另外,
sklearn
是否提供推理(标准误差)或边际效应?
。有人建议添加这个,但它还没有在主代码库中。
作为额外的注意,当我的矩阵共线时,我正在努力解决结果的差异。显然,这意味着应该有一些额外的预处理,以获得可靠的结果,但我仍然希望找出为什么我得到了一个结果与sklearn,但统计模型错误。
简短的回答:在statmodels中调用fit
时设置solver='bfgs'
会给出与sklearn模型几乎相同的结果,即使在共线性变量的情况下(一旦考虑到sm的默认值没有拦截,而sklearn的默认值适合拦截)
示例(改编自OLS的类似问题):
import numpy as np
import statsmodels.api as sm
from sklearn.linear_model import LogisticRegression
np.random.seed = 237
num_samples=1000
X=np.random.random((num_samples, 2))
X[:, 1] = 2*X[:, 0]
X_sm = sm.add_constant(X)
beta = [1, -2, .5]
error = np.random.random(num_samples)
y = np.round(1/(1+np.exp( -(np.dot(X_sm, beta)) + error ))) # y = 1/(1+exp(-beta*x))
lr = LogisticRegression(C=1e9).fit(X, y)
print "sklearn:"
print lr.intercept_
print lr.coef_
print "statsmodels:"
print sm.Logit(y, X_sm).fit(method='bfgs').params # method='nm' or default method errors out
如果有人对这两个解算器背后的数学和结果的可靠性有什么评论,我很乐意听到!我发现有趣的是,sklearn甚至没有抛出一个警告…)