我正在研究不同场景下线性回归的一些例子,比较使用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和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)然后,我创建了三个单独的数据框架来比较每个模型的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]
})下面是我如何创建dataframe来比较每个模型的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)))下面是生成的数据文件:
COEFFICIENTS:

分数:

PREDICTIONS:

我有三个我无法调和的问题:
normalize=False似乎没有任何作用。我能理解有相同的预测值和R^2值,但是我的特性有不同的数值尺度,所以我不知道为什么正常化会没有任何影响。当您考虑到使用StandardScaler会显着地改变系数时,这是双重混淆的。Normalizer的模型会导致与其他模型完全不同的系数值,特别是当带有LinearRegression(normalize=True)的模型完全没有变化的时候。如果要查看每个文档,它们似乎非常相似,如果不是完全相同的话。
规范化:布尔、可选、默认的假 当fit_intercept设置为False时,将忽略此参数。如果为真,则在回归之前,通过减去均值,再除以L2-范数,将回归量X归一化。
同时,sklearn.preprocessing.Normalizer 默认情况下,它将规范为l2规范。上的文档。
我看不出这两个选项之间有什么区别,我也不明白为什么其中一个在系数值上会与另一个有如此大的差别。
StandardScaler的模型的结果对我来说是一致的,但是我不明白为什么使用StandardScaler和设置set_intercept=False的模型表现这么差。从线性回归模上的文档
fit_intercept :布尔值,可选,默认的真 是否计算此模型的截距。如果设置为False,则不 拦截将用于计算(例如,数据预计已经被使用)。 中心)。
StandardScaler将您的数据作为中心,所以我不明白为什么将它与fit_intercept=False一起使用会产生不一致的结果。
发布于 2020-08-06 17:39:13
关于fit_intercept=0和标准化数据不一致结果的最后一个问题(3)还没有得到充分的回答。
OP很可能期望StandardScaler将X和y标准化,这将使拦截必须达到0 (证明 1/3的下行方式)。
然而,StandardScaler忽略y。参见api接口。
TransformedTargetRegressor提供了一个解决方案。这种方法对于因变量的非线性转换也很有用,例如y的日志转换(但考虑这)。
下面是一个解决OP问题#3的例子:
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import make_pipeline
from sklearn.datasets import make_regression
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
import numpy as np
# define a custom transformer
class stdY(BaseEstimator,TransformerMixin):
def __init__(self):
pass
def fit(self,Y):
self.std_err_=np.std(Y)
self.mean_=np.mean(Y)
return self
def transform(self,Y):
return (Y-self.mean_)/self.std_err_
def inverse_transform(self,Y):
return Y*self.std_err_+self.mean_
# standardize X and no intercept pipeline
no_int_pipe=make_pipeline(StandardScaler(),LinearRegression(fit_intercept=0)) # only standardizing X, so not expecting a great fit by itself.
# standardize y pipeline
std_lin_reg=TransformedTargetRegressor(regressor=no_int_pipe, transformer=stdY()) # transforms y, estimates the model, then reverses the transformation for evaluating loss.
#after returning to re-read my answer, there's an even easier solution, use StandardScaler as the transfromer:
std_lin_reg_easy=TransformedTargetRegressor(regressor=no_int_pipe, transformer=StandardScaler())
# generate some simple data
X, y, w = make_regression(n_samples=100,
n_features=3, # x variables generated and returned
n_informative=3, # x variables included in the actual model of y
effective_rank=3, # make less than n_informative for multicollinearity
coef=True,
noise=0.1,
random_state=0,
bias=10)
std_lin_reg.fit(X,y)
print('custom transformer on y and no intercept r2_score: ',std_lin_reg.score(X,y))
std_lin_reg_easy.fit(X,y)
print('standard scaler on y and no intercept r2_score: ',std_lin_reg_easy.score(X,y))
no_int_pipe.fit(X,y)
print('\nonly standard scalar and no intercept r2_score: ',no_int_pipe.score(X,y))回传
custom transformer on y and no intercept r2_score: 0.9999343800041816
standard scaler on y and no intercept r2_score: 0.9999343800041816
only standard scalar and no intercept r2_score: 0.3319175799267782https://stackoverflow.com/questions/54067474
复制相似问题