如何调整比例 scikit-learn 逻辑回归系数以对非比例数据集进行评分?

How to adjust scaled scikit-learn Logicistic Regression coeffs to score a non-scaled dataset?

我目前正在使用 Scikit-Learn 的 LogisticRegression 来构建模型。我用过

from sklearn import preprocessing
scaler=preprocessing.StandardScaler().fit(build)
build_scaled = scaler.transform(build)

在训练模型之前缩放我的所有输入变量。一切正常并产生了一个不错的模型,但我的理解是 LogisticRegression.coeff_ 产生的系数基于缩放变量。是否对那些可用于调整它们以产生可应用于非缩放数据的系数的系数进行转换?

我正在考虑在生产系统中实施模型,并尝试确定是否所有变量都需要在生产中以某种方式进行预处理以对模型进行评分。

注意:模型可能必须在生产环境中重新编码,而该环境未使用 python。

您可以通过两个步骤使用 pipeline:缩放和回归。它将原始数据作为输入并产生所需的回归。

或者如果您明确想要获取系数,您可以手动将 LogisticRegression 系数与定标器参数 scaler.mean_ 和 scaler.std_ 结合起来。

为此,请注意标准缩放器以这种方式标准化数据:v_norm = (v - M(v))/ sigma(v)。这里 M(v) 是原始变量 v 的平均值,sigma(v) 是它的标准偏差,分别存储在 scaler.mean_ 和 scaler.std_ 数组中。

然后 LogisticRegression 取这个归一化变量并将它们乘以 LogisticRegression.coef_ 并添加 intercept_。

简答,获取未缩放数据的 LogisticRegression 系数和截距(假设二元分类,并且 lr 是经过训练的 LogisticRegression 对象):

  1. 您必须将系数数组元素明智地除以(自 v0.17 起)scaler.scale_ 数组:coefficients = np.true_divide(lr.coeff_, scaler.scale_)

  2. 您必须从您的截距中减去所得系数(除法结果)数组与 scaler.mean_ 数组的内积:intercept = lr.intercept_ - np.dot(coefficients, scaler.mean_)

如果您认为每个特征都通过减去其均值(存储在 scaler.mean_ 数组中)然后除以其标准差(存储在 scaler.scale_ 数组中)。

您必须除以应用到标准化特征的缩放比例,还要乘以应用到目标的缩放比例。

假设

  • 每个特征变量 x_i 被缩放(除以)scale_x_i

  • 目标变量被缩放(除以)scale_y

然后

orig_coef_i = coef_i_found_on_scaled_data / scale_x_i * scale_y

这是一个使用 pandas 和 sklearn LinearRegression

的示例
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

import numpy as np
import pandas as pd

boston = load_boston()
# Looking at the description of the data tells us the target variable name
# print boston.DESCR
data = pd.DataFrame(
    data = np.c_[boston.data, boston.target],
    columns = list(boston.feature_names) + ['MVAL'],
)
data.head()

X = boston.data
y = boston.target

lr = LinearRegression()
lr.fit(X,y)

orig_coefs = lr.coef_

coefs1 = pd.DataFrame(
    data={
        'feature': boston.feature_names, 
        'orig_coef' : orig_coefs, 
    }
)
coefs1

这向我们展示了未应用缩放的线性回归系数。

#  | feature| orig_coef
# 0| CRIM   | -0.107171
# 1| ZN     |  0.046395
# 2| INDUS  |  0.020860
# etc

我们现在对所有变量进行归一化

# Now we normalise the data
scalerX = StandardScaler().fit(X)
scalery = StandardScaler().fit(y.reshape(-1,1)) # Have to reshape to avoid warnings

normed_X = scalerX.transform(X)
normed_y = scalery.transform(y.reshape(-1,1)) # Have to reshape to avoid warnings

normed_y = normed_y.ravel() # Turn y back into a vector again

# Check it's worked
# print np.mean(X, axis=0), np.mean(y, axis=0) # Should be 0s
# print np.std(X, axis=0), np.std(y, axis=0)   # Should be 1s

我们可以对这个归一化数据再次进行回归...

# Now we redo our regression
lr = LinearRegression()
lr.fit(normed_X, normed_y)

coefs2 = pd.DataFrame(
    data={
        'feature' : boston.feature_names,
        'orig_coef' : orig_coefs,
        'norm_coef' : lr.coef_,
        'scaleX' : scalerX.scale_,
        'scaley' : scalery.scale_[0],
    },
    columns=['feature', 'orig_coef', 'norm_coef', 'scaleX', 'scaley']
)
coefs2

...并应用缩放以取回我们的原始系数

# We can recreate our original coefficients by dividing by the
# scale of the feature (scaleX) and multiplying by the scale
# of the target (scaleY)
coefs2['rescaled_coef'] = coefs2.norm_coef / coefs2.scaleX * coefs2.scaley
coefs2

当我们这样做时,我们发现我们已经重新创建了原始系数。

#  | feature| orig_coef| norm_coef|    scaleX|   scaley| rescaled_coef
# 0| CRIM   | -0.107171| -0.100175|  8.588284| 9.188012| -0.107171
# 1| ZN     |  0.046395|  0.117651| 23.299396| 9.188012|  0.046395
# 2| INDUS  |  0.020860|  0.015560|  6.853571| 9.188012|  0.020860
# 3| CHAS   |  2.688561|  0.074249|  0.253743| 9.188012|  2.688561

对于某些机器学习方法,必须对目标变量 y 以及特征变量 x 进行归一化。如果你这样做了,你需要包括这个 "multiply by the scale of y" 步骤以及 "divide by the scale of X_i" 来取回原始回归系数。

希望对您有所帮助