python - 在线性回归中比较 StandardScaler 与 Normalizer 的结果

标签 python machine-learning scikit-learn linear-regression

我正在研究不同场景下的一些线性回归示例,比较使用 NormalizerStandardScaler 的结果,结果令人费解。

我正在使用波士顿住房数据集,并以这种方式准备它:

import numpy as np
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.preprocessing import Normalizer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression

#load the data
df = pd.DataFrame(boston.data)
df.columns = boston.feature_names
df['PRICE'] = boston.target

我目前正在尝试推理我从以下场景中得到的结果:

  • 使用参数 normalize=True 初始化线性回归与使用 Normalizer
  • 使用参数 fit_intercept = False 初始化线性回归,有和没有标准化。

总的来说,我发现结果令人困惑。

以下是我设置所有内容的方式:

# Prep the data
X = df.iloc[:, :-1]
y = df.iloc[:, -1:]
normal_X = Normalizer().fit_transform(X)
scaled_X = StandardScaler().fit_transform(X)

#now prepare some of the models
reg1 = LinearRegression().fit(X, y)
reg2 = LinearRegression(normalize=True).fit(X, y)
reg3 = LinearRegression().fit(normal_X, y)
reg4 = LinearRegression().fit(scaled_X, y)
reg5 = LinearRegression(fit_intercept=False).fit(scaled_X, y)

然后,我创建了 3 个单独的数据帧来比较每个模型的 R_score、系数值和预测。

为了创建数据框来比较每个模型的系数值,我执行了以下操作:

#Create a dataframe of the coefficients
coef = pd.DataFrame({
    'coeff':                       reg1.coef_[0],
    'coeff_normalize_true':        reg2.coef_[0],
    'coeff_normalizer':            reg3.coef_[0],
    'coeff_scaler':                reg4.coef_[0],
    'coeff_scaler_no_int':         reg5.coef_[0]
})

下面是我如何创建数据框来比较每个模型的 R^2 值:

scores = pd.DataFrame({
    'score':                        reg1.score(X, y),
    'score_normalize_true':         reg2.score(X, y),
    'score_normalizer':             reg3.score(normal_X, y),
    'score_scaler':                 reg4.score(scaled_X, y),
    'score_scaler_no_int':          reg5.score(scaled_X, y)
    }, index=range(1)
)

最后,这是比较每个预测的数据框:

predictions = pd.DataFrame({
    'pred':                        reg1.predict(X).ravel(),
    'pred_normalize_true':         reg2.predict(X).ravel(),
    'pred_normalizer':             reg3.predict(normal_X).ravel(),
    'pred_scaler':                 reg4.predict(scaled_X).ravel(),
    'pred_scaler_no_int':          reg5.predict(scaled_X).ravel()
}, index=range(len(y)))

这是生成的数据帧:

系数: Dataframe comparing the coefficients from different models

分数: Dataframe comparing the R^2 values from different models

预测: Dataframe comparing the prediction values from different models

我有三个无法调和的问题:

  1. 为什么前两个模型完全没有区别?似乎设置 normalize=False 什么都不做。我可以理解具有相同的预测值和 R^2 值,但我的特征具有不同的数值尺度,所以我不确定为什么归一化根本没有效果。当您认为使用 StandardScaler 会显着改变系数时,这会更加令人困惑。
  2. 我不明白为什么使用 Normalizer 的模型会导致与其他模型截然不同的系数值,尤其是当使用 LinearRegression(normalize=True) 的模型没有完全改变。

如果您查看每个文档,就会发现它们即使不完全相同也非常相似。

来自 sklearn.linear_model.LinearRegression() 上的文档:

normalize : boolean, optional, default False

This parameter is ignored when fit_intercept is set to False. If True, the regressors X will be normalized before regression by subtracting the mean and dividing by the l2-norm.

与此同时,sklearn.preprocessing.Normalizer 上的文档 states that it normalizes to the l2 norm by default .

我看不出这两个选项的作用有何不同,我也不明白为什么一个选项的系数值会与另一个选项有如此大的差异。

  1. 使用 StandardScaler 的模型的结果与我一致,但我不明白为什么模型使用 StandardScaler 并设置 set_intercept=False 表现很差。

来自 Linear Regression module 上的文档:

fit_intercept : boolean, optional, default True

whether to calculate the intercept for this model. If set to False, no
intercept will be used in calculations (e.g. data is expected to be already
centered).

StandardScaler 将您的数据居中,所以我不明白为什么将它与 fit_intercept=False 一起使用会产生不连贯的结果。

最佳答案

  1. 前两个模型之间系数没有差异的原因是 Sklearn 在根据标准化输入数据计算系数后,在幕后对系数进行反标准化。 Reference

之所以进行反规范化,是因为对于测试数据,我们可以直接应用协效应。并在不标准化测试数据的情况下获得预测。

因此,设置 normalize=True 确实会影响系数,但无论如何它们不会影响最佳拟合线。

  1. Normalizer 对每个样本进行标准化(意味着按行)。你看引用码here .

From documentation:

Normalize samples individually to unit norm.

normalize=True 对每个列/特征进行规范化。 Reference

了解规范化对数据不同维度的影响的示例。让我们取两个维度 x1 和 x2,y 作为目标变量。目标变量值在图中用颜色编码。

import matplotlib.pyplot as plt
from sklearn.preprocessing import Normalizer,StandardScaler
from sklearn.preprocessing.data import normalize

n=50
x1 = np.random.normal(0, 2, size=n)
x2 = np.random.normal(0, 2, size=n)
noise = np.random.normal(0, 1, size=n)
y = 5 + 0.5*x1 + 2.5*x2 + noise

fig,ax=plt.subplots(1,4,figsize=(20,6))

ax[0].scatter(x1,x2,c=y)
ax[0].set_title('raw_data',size=15)

X = np.column_stack((x1,x2))

column_normalized=normalize(X, axis=0)
ax[1].scatter(column_normalized[:,0],column_normalized[:,1],c=y)
ax[1].set_title('column_normalized data',size=15)

row_normalized=Normalizer().fit_transform(X)
ax[2].scatter(row_normalized[:,0],row_normalized[:,1],c=y)
ax[2].set_title('row_normalized data',size=15)

standardized_data=StandardScaler().fit_transform(X)
ax[3].scatter(standardized_data[:,0],standardized_data[:,1],c=y)
ax[3].set_title('standardized data',size=15)

plt.subplots_adjust(left=0.3, bottom=None, right=0.9, top=None, wspace=0.3, hspace=None)
plt.show()

enter image description here

您可以看到图 1,2 和图 4 中数据的最佳拟合线是相同的;表示 R2_-score 不会因列/特征规范化或标准化数据而改变。仅此而已,它最终会产生不同的协同效应。值(value)观。

注意:fig3 的最佳拟合线会有所不同。

  1. 当您设置 fit_intercept=False 时,将从预测中减去偏差项。 这意味着截距设置为零,否则将是目标变量的平均值。

prediction对于未缩放目标变量(均值 = 0)的问题,截距为零预计会表现不佳。您可以在每一行中看到 22.532 的差异,这表示输出的影响。

关于python - 在线性回归中比较 StandardScaler 与 Normalizer 的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54067474/

相关文章:

python - 使用 matplotlib 绘图函数绘制图形有时需要几分钟

python - 对象没有使用 argparse 的属性

python - 使用 Twisted 在 Python 中实现多进程服务器

python - 线性回归 : Cost function working independently, 但不在 scipy.optimize 函数内

machine-learning - Growing Neural Gas 如何用于聚类?

machine-learning - 验证聚类算法的输出

python - Databricks:如何从 R Dataframe 切换到 Pandas Dataframe(R 到 python 在同一笔记本中)

machine-learning - TensorFlow 学习率衰减 - 如何正确提供衰减的步数?

python - 值错误 : bad input shape (2835, 18)

python-3.x - 类型错误 : object of type 'numpy.int64' has no len()/TypeError: object of type 'int' has no len()/while using classification_report in scikitlearn