我通过不同情景下的线性回归的一些实例工作,使用Normalizer
和StandardScaler
比较结果,并将结果令人费解。
我使用的是波士顿住房数据集,并准备推出这样说:
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
VS使用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个独立dataframes比较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)))
下面是导致dataframes:
我有三个问题,我无法调和:
normalize=False
什么都不做。我可以理解预测和R ^ 2倍的值是相同的,但我的特点有不同的数值尺度,所以我不知道为什么正火没有任何作用的。当你考虑到使用StandardScaler
改变系数大大这是极为混乱。Normalizer
模型导致从其他诸如完全不同的系数值,特别是当与LinearRegression(normalize=True)
模型使得完全没有变化。如果你看看文档,每个,看来他们如果不是相同的非常相似。
从sklearn.linear_model.LinearRegression()文档:
标准化:布尔值,可选,默认为false
当fit_intercept设置为False忽略此参数。如果真,回归系数X将回归前通过减去平均值和由L2范数除以标准化。
同时,sklearn.preprocessing.Normalizer
states that it normalizes to the l2 norm by default的文档。
我看不出有什么之间这两个选项做一个区别,我不明白为什么一个会具有与其他的系数值这些激进的差异。
StandardScaler
的结果是一致的给我,但我不明白为什么使用StandardScaler
和设置set_intercept=False
模型进行如此糟糕。fit_intercept:布尔值,可选,默认为true
是否计算拦截此模型。如果设置为false,没有 截距将在计算中使用(例如,数据预期为已经 居中)。
该中心StandardScaler
你的数据,所以我不明白为什么使用它与fit_intercept=False
产生不连贯的结果。
Sklearn
反规范化计算:从标准的输入数据共同EFFS后的幕后共同efficients。 Reference这种去正常化已经这样做了,任何的测试数据,我们可以直接申请共同EFFS。并获得预测与标准化的测试数据。
因此,设置normalize=True
做有共同efficients的影响,但他们无论如何不影响最佳拟合线。
Normalizer
确实正常化相对于每个样品(意味着按行)。你看参考代码here。个别规范化样本单位规范。
而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()
你可以看到在图1,2的数据最佳拟合线和4将是相同的;表示该R2_分数不会改变由于柱/特征规格化或标准化的数据。只是,它有不同的合作EFFS结束。值。
注:fig3
最佳拟合线会有所不同。
与截距为零的prediction将预期对于其中目标变量不是缩放问题(平均= 0)执行坏。你可以看到22.532每一行,这意味着输出的影响,有差别。
我假设你的意思与第2款是reg1
和reg2
。让我们知道,如果事实并非如此。
线性回归具有相同的预测能力,如果你规范化数据或没有。因此,使用normalize=True
对预测没有影响。理解这一点的一种方式是看到正常化(列方向)是在各列((x-a)/b
)和一个线性回归的数据不影响系数估计的线性变换的线性操作中,仅改变它们的值。请注意,这种说法是不正确的套索/里奇/ ElasticNet。
那么,为什么不系数不同?那么,normalize=True
还考虑什么用户通常希望是在原有的特色,而不是标准化的特征系数。因此,它调整系数。检查,这是有道理的一种方法是使用一个简单的例子:
# two features, normal distributed with sigma=10
x1 = np.random.normal(0, 10, size=100)
x2 = np.random.normal(0, 10, size=100)
# y is related to each of them plus some noise
y = 3 + 2*x1 + 1*x2 + np.random.normal(0, 1, size=100)
X = np.array([x1, x2]).T # X has two columns
reg1 = LinearRegression().fit(X, y)
reg2 = LinearRegression(normalize=True).fit(X, y)
# check that coefficients are the same and equal to [2,1]
np.testing.assert_allclose(reg1.coef_, reg2.coef_)
np.testing.assert_allclose(reg1.coef_, np.array([2, 1]), rtol=0.01)
这证实了两种方法正确地捕获即,分别[X1,X2]和y,2位和1之间的实数信号。
Normalizer
是不是你所期望的。它正常化每一行逐行。那么,结果将发生巨大的变化,并有可能破坏要避免除特定情况下(例如,TF-IDF)的特点和目标之间的关系。
怎么看,假设上面的例子,但考虑到不同的功能,x3
,不与y
有关。使用Normalizer
导致x1
由x3
的值来修饰的,降低其与y
关系的实力。
系数之间的差异是,当你安装前规范,系数将是关于标准化的功能,同样的系数提到我在回答第一部分。它们可以被映射到使用reg4.coef_ / scaler.scale_
原来的参数:
x1 = np.random.normal(0, 10, size=100)
x2 = np.random.normal(0, 10, size=100)
y = 3 + 2*x1 + 1*x2 + np.random.normal(0, 1, size=100)
X = np.array([x1, x2]).T
reg1 = LinearRegression().fit(X, y)
reg2 = LinearRegression(normalize=True).fit(X, y)
scaler = StandardScaler()
reg4 = LinearRegression().fit(scaler.fit_transform(X), y)
np.testing.assert_allclose(reg1.coef_, reg2.coef_)
np.testing.assert_allclose(reg1.coef_, np.array([2, 1]), rtol=0.01)
# here
coefficients = reg4.coef_ / scaler.scale_
np.testing.assert_allclose(coefficients, np.array([2, 1]), rtol=0.01)
这是因为,在数学上,设置z = (x - mu)/sigma
,模型REG4是解决y = a1*z1 + a2*z2 + a0
。我们可以恢复通过简单的代数y和x之间的关系:y = a1*[(x1 - mu1)/sigma1] + a2*[(x2 - mu2)/sigma2] + a0
,这可以简化为y = (a1/sigma1)*x1 + (a2/sigma2)*x2 + (a0 - a1*mu1/sigma1 - a2*mu2/sigma2)
。
reg4.coef_ / scaler.scale_
代表[a1/sigma1, a2/sigma2]
在上面的符号,这是normalize=True
究竟是干什么的,以保证系数是相同的。
标准化的特点是零均值,但目标变量未必。因此,不fiting截距使模型无视目标的平均值。在我已经使用的例子中,“3”中y = 3 + ...
未安装,这自然降低了模型的预测能力。 :)