LogisticRegression scikit 学习协变量(列)顺序对训练很重要
LogisticRegression scikit learn covariate (column) order matters on training
出于某种原因,协变量的顺序似乎与 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)
这是在两个代码示例中测量相同的东西。
当我们将 DataFrame
馈送到 sklearn 中的 classifier 时,它会在数据帧的每一行上进行训练(每一行对应一个观察值)
所以行的顺序并不重要,因为您得到的输出是特定行对应于每个可能的 classes 的概率。
例如:
array([[ 0.26117794, 0.73882206], ..])
的输出意味着我们提供给 classifier 的行有大约 26% 的机会在 class 0 和大约 74% 的机会在 class 中 1. 此测量值并未说明各个列的任何信息。只是整行。
让我知道这是否有帮助,以及我是否可以澄清我的答案。
感谢您添加示例数据。
深入了解您的数据,显然没有标准化。如果您将 StandardScaler
应用于数据集并再次尝试拟合,您会发现预测差异消失了。
虽然这个结果至少是一致的,但仍然令人不安的是它引发了 LineSearchWarning
和 ConvergenceWarning
。对此我会说你在 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 +,我认为这远远超出了任何合理的显着性水平。
出于某种原因,协变量的顺序似乎与 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)
这是在两个代码示例中测量相同的东西。
当我们将 DataFrame
馈送到 sklearn 中的 classifier 时,它会在数据帧的每一行上进行训练(每一行对应一个观察值)
所以行的顺序并不重要,因为您得到的输出是特定行对应于每个可能的 classes 的概率。
例如:
array([[ 0.26117794, 0.73882206], ..])
的输出意味着我们提供给 classifier 的行有大约 26% 的机会在 class 0 和大约 74% 的机会在 class 中 1. 此测量值并未说明各个列的任何信息。只是整行。
让我知道这是否有帮助,以及我是否可以澄清我的答案。
感谢您添加示例数据。
深入了解您的数据,显然没有标准化。如果您将 StandardScaler
应用于数据集并再次尝试拟合,您会发现预测差异消失了。
虽然这个结果至少是一致的,但仍然令人不安的是它引发了 LineSearchWarning
和 ConvergenceWarning
。对此我会说你在 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 +,我认为这远远超出了任何合理的显着性水平。