LogisticRegression scikit学习协变量(列)顺序对训练很重要

Posted

技术标签:

【中文标题】LogisticRegression scikit学习协变量(列)顺序对训练很重要【英文标题】:LogisticRegression scikit learn covariate (column) order matters on training 【发布时间】:2018-06-01 06:00:09 【问题描述】:

由于某种原因,协变量的顺序似乎与 scikit-learn 中的 LogisticRegression 分类器有关,这对我来说似乎很奇怪。我有 9 个协变量和一个二进制输出,当我更改列的顺序并调用 fit() 然后调用 predict_proba() 时,输出是不同的。下面的玩具示例

logit_model = LogisticRegression(C=1e9, tol=1e-15)

以下

logit_model.fit(df['column_2','column_1'],df['target'])
logit_model.predict_proba(df['column_2','column_1'])

array([[ 0.27387109,  0.72612891] ..])

给出不同的结果:

logit_model.fit(df['column_1','column_2'],df['target'])
logit_model.predict_proba(df['column_1','column_2'])

array([[ 0.26117794,  0.73882206], ..])

这对我来说似乎令人惊讶,但也许这只是我对算法的内部结构和拟合方法缺乏了解。

我错过了什么?

编辑:这是完整的代码和数据

数据:https://s3-us-west-2.amazonaws.com/gjt-personal/test_model.csv

import pandas as pd
from sklearn.linear_model import LogisticRegression

df = pd.read_csv('test_model.csv',index_col=False)

columns1 =['col_1','col_2','col_3','col_4','col_5','col_6','col_7','col_8','col_9']
columns2 =['col_2','col_1','col_3','col_4','col_5','col_6','col_7','col_8','col_9']

logit_model = LogisticRegression(C=1e9, tol=1e-15)

logit_model.fit(df[columns1],df['target'])
logit_model.predict_proba(df[columns1])

logit_model.fit(df[columns2],df['target'])
logit_model.predict_proba(df[columns2])

原来它与 tol=1e-15 有关,因为这会产生不同的结果。

LogisticRegression(C=1e9, tol=1e-15)

但这给出了相同的结果。

LogisticRegression(C=1e9)

【问题讨论】:

【参考方案1】:

这是在两个代码示例中测量相同的东西。

当我们将 DataFrame 提供给 sklearn 中的分类器时,它会在数据帧的每一行上进行训练(每一行对应一个观察值)

所以行的顺序无关紧要,因为您得到的输出是特定行对应于每个可能的类的概率。

例如:

array([[ 0.26117794, 0.73882206], ..]) 的输出意味着我们提供给分类器的行有约 26% 的机会属于第 0 类,有约 74% 的机会属于第 1 类。这个测量并没有说明什么各个列。只是整个行。

让我知道这是否有帮助,如果我能澄清我的答案。

【讨论】:

所以我的问题不是关于输出的解释或者不同行的不同,而是当fit上的列顺序不同时同一行的不同/跨度> 根据代码,输出完全相同。您能否提供一个示例,说明同一行数据的输出不同? 输出完全相同是什么意思?这不一样。你的意思是应该完全一样吗? 天哪,我完全错过了。我觉得自己很愚蠢。 实际的答案是逻辑回归使用梯度下降来达到其最终形式,这意味着涉及一些随机性。无论行的顺序如何,重新拟合模型都会改变预测。您可以通过在 train_test_split() 中设置随机种子来测试这一点【参考方案2】:

感谢您添加示例数据。

更深入地查看您的数据显然不是标准化的。如果您将StandardScaler 应用于数据集并再次尝试拟合,您会发现预测差异消失了。

虽然这个结果至少是一致的,但它引发LineSearchWarningConvergenceWarning 仍然令人不安。对此,我想说您在1e-15 的容忍度确实非常低。考虑到您应用的非常高的正则化惩罚率(1e9),将tol 降低到默认的1e-4 将不会产生任何影响。这使得模型能够正确收敛并仍然产生相同的结果(运行时间更快)。

我的整个过程如下所示:

import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

ss = StandardScaler()
cols1 = np.arange(9)
cols2 = np.array([1,0,2,3,4,5,6,7,8])
X = ss.fit_transform(df.drop('target', axis=1))

lr = LogisticRegression(solver='newton-cg', tol=1e-4, C=1e9)
lr.fit(X[:, cols1], df['target'])
preds_1 = lr.predict_proba(X[:, cols1])

lr.fit(X[:, cols2], df['target'])
preds_2 = lr.predict_proba(X[:, cols2])

preds_1 
array([[  0.00000000e+00,   1.00000000e+00],
       [  0.00000000e+00,   1.00000000e+00],
       [  0.00000000e+00,   1.00000000e+00],
       ...,
       [  1.00000000e+00,   9.09277801e-31],
       [  1.00000000e+00,   3.52079327e-35],
       [  1.00000000e+00,   5.99607407e-30]])

preds_2
array([[  0.00000000e+00,   1.00000000e+00],
       [  0.00000000e+00,   1.00000000e+00],
       [  0.00000000e+00,   1.00000000e+00],
       ...,
       [  1.00000000e+00,   9.09277801e-31],
       [  1.00000000e+00,   3.52079327e-35],
       [  1.00000000e+00,   5.99607407e-30]])

断言preds_1 == preds_2 将失败,但每个值的差异在 1e-40 + 的数量级上,我想说这远远超出了任何合理的重要性水平。

【讨论】:

Grr 是的,这就是我的想法,但在文档中它说:“在求解器 == ‘sag’ 或 ‘liblinear’ 时使用。”这就是为什么我使用newton-cg scikit-learn.org/stable/modules/generated/… 嗯,如果我用logit_model = LogisticRegression(random_state=0) 重新运行,输出是相等的,但是如果我运行,LogisticRegression(fit_intercept=True, C=1e9,tol=1e-15, solver='newton-cg',random_state=0) 仍然不同,即使运行LogisticRegression() 也是一样的 那么在这种情况下,您不再使用 newton-cg 了,这是有道理的 所以它与tol 属性有关。 LogisticRegression(fit_intercept=True, C=1e9,tol=1e-15) 不同但LogisticRegression(fit_intercept=True, C=1e9) 相同,知道为什么会这样吗? ah "注意:底层 C 实现在拟合模型时使用随机数生成器来选择特征。因此,对于相同的输入数据,结果略有不同的情况并不少见。如果发生这种情况,尝试使用较小的 tol 参数。”

以上是关于LogisticRegression scikit学习协变量(列)顺序对训练很重要的主要内容,如果未能解决你的问题,请参考以下文章

scikit-learn 中 LogisticRegression 上的 GridSearchCV

LogisticRegression scikit学习协变量(列)顺序对训练很重要

如何评估 scikit learn LogisticRegression 的成本函数?

在 scikit-learn 库中使用 sgd 求解器的 SGDClassifier 与 LogisticRegression

SciKit LogisticRegression 无法准确预测

逻辑回归模型中的内核 LogisticRegression scikit-learn sklearn