为了账号安全,请及时绑定邮箱和手机立即绑定

逻辑回归 scikit-learn 与 statsmodels 的系数

逻辑回归 scikit-learn 与 statsmodels 的系数

慕沐林林 2022-12-06 16:41:42
当使用这两个 API 执行逻辑回归时,它们会给出不同的系数。即使是这个简单的例子,它在系数方面也不会产生相同的结果。我遵循关于同一主题的旧建议的建议,例如在 sklearn 中为参数 C 设置一个大值,因为它使惩罚几乎消失(或设置 penalty="none")。import pandas as pdimport numpy as npimport sklearn as skfrom sklearn.linear_model import LogisticRegressionimport statsmodels.api as smn = 200x = np.random.randint(0, 2, size=n)y = (x > (0.5 + np.random.normal(0, 0.5, n))).astype(int)display(pd.crosstab( y, x ))max_iter = 100#### Statsmodelsres_sm = sm.Logit(y, x).fit(method="ncg", maxiter=max_iter)print(res_sm.params)#### Scikit-Learnres_sk = LogisticRegression( solver='newton-cg', multi_class='multinomial', max_iter=max_iter, fit_intercept=True, C=1e8 )res_sk.fit( x.reshape(n, 1), y )print(res_sk.coef_)例如,我只是运行上面的代码并获得 1.72276655 的 statsmodels 和 1.86324749 的 sklearn。当多次运行时,它总是给出不同的系数(有时比其他系数更接近,但无论如何)。因此,即使使用那个玩具示例,两个 API 也会给出不同的系数(因此比值比),并且对于真实数据(此处未显示),它几乎会“失控”......我错过了什么吗?我怎样才能产生相似的系数,例如至少在逗号后的一两个数字?
查看完整描述

1 回答

?
翻阅古今

TA贡献1780条经验 获得超5个赞

您的代码存在一些问题。

首先,您在此处显示的两个模型并不相同:尽管您适合 scikit-learn LogisticRegressionfit_intercept=True这是默认设置),但您不会使用 statsmodels 模型;来自 statsmodels文档

默认情况下不包含拦截,应由用户添加。看statsmodels.tools.add_constant

这似乎是一个常见的混淆点 - 例如scikit-learn 和 statsmodels - 哪个 R 平方是正确的?(也有自己的答案)。

另一个问题是,尽管您处于二元分类设置中,但您要求multi_class='multinomial'在您的 中LogisticRegression,但事实并非如此。

第三个问题是,正如相关的交叉验证线程逻辑回归:Scikit Learn vs Statsmodels中所解释的那样:

没有办法在 scikit-learn 中关闭正则化,但是您可以通过将调整参数 C 设置为较大的数字来使其无效。

这使得这两个模型在原则上再次不可比,但您已经通过设置在此处成功解决了这个问题C=1e8。事实上,从那时起(2016 年),scikit-learn 确实添加了一种关闭正则化的方法penalty='none',根据文档,通过设置 since :

如果为“无”(liblinear 求解器不支持),则不应用正则化。

现在应该将其视为关闭正则化的规范方法。

因此,将这些更改合并到您的代码中,我们有:

np.random.seed(42) # for reproducibility


#### Statsmodels

# first artificially add intercept to x, as advised in the docs:

x_ = sm.add_constant(x)

res_sm = sm.Logit(y, x_).fit(method="ncg", maxiter=max_iter) # x_ here

print(res_sm.params)

这给出了结果:


Optimization terminated successfully.

         Current function value: 0.403297

         Iterations: 5

         Function evaluations: 6

         Gradient evaluations: 10

         Hessian evaluations: 5

[-1.65822763  3.65065752]

数组的第一个元素是截距,第二个元素是 的系数x。而对于 scikit 学习,我们有:


#### Scikit-Learn


res_sk = LogisticRegression(solver='newton-cg', max_iter=max_iter, fit_intercept=True, penalty='none')

res_sk.fit( x.reshape(n, 1), y )

print(res_sk.intercept_, res_sk.coef_)

结果是:


[-1.65822806] [[3.65065707]]

在机器的数字精度范围内,这些结果实际上是相同的。


对不同的值重复该过程np.random.seed()不会改变上面显示的结果的本质。


查看完整回答
反对 回复 2022-12-06
  • 1 回答
  • 0 关注
  • 170 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信