更新 Python sklearn Lasso(normalize=True) 以使用管道

Posted

技术标签:

【中文标题】更新 Python sklearn Lasso(normalize=True) 以使用管道【英文标题】:Updating Python sklearn Lasso(normalize=True) to Use Pipeline 【发布时间】:2022-01-02 05:33:56 【问题描述】:

我是 Python 新手。我正在尝试通过使用此 CSV 进行 DataCamp 练习来练习基本的正则化: https://assets.datacamp.com/production/repositories/628/datasets/a7e65287ebb197b1267b5042955f27502ec65f31/gm_2008_region.csv

# Import numpy and pandas
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Read the CSV file into a DataFrame: df
df = pd.read_csv('gm_2008_region.csv')

# Create arrays for features and target variable
X = df.drop(['life','Region'], axis=1)
y = df['life'].values.reshape(-1,1)
df_columns = df.drop(['life','Region'], axis=1).columns

我用于 DataCamp 练习的代码如下:

# Import Lasso
from sklearn.linear_model import Lasso

# Instantiate a lasso regressor: lasso
lasso = Lasso(alpha=0.4, normalize=True)

# Fit the regressor to the data
lasso.fit(X, y)

# Compute and print the coefficients
lasso_coef = lasso.coef_
print(lasso_coef)

# Plot the coefficients
plt.plot(range(len(df_columns)), lasso_coef)
plt.xticks(range(len(df_columns)), df_columns.values, rotation=60)
plt.margins(0.02)
plt.show()

我得到上面的输出,表明 child_mortality 是预测预期寿命的最重要特征,但是由于使用了“normalize”,这段代码也导致了弃用警告。

我想使用当前的最佳做法更新此代码。我尝试了以下方法,但得到了不同的输出。我希望有人可以帮助确定我需要在更新的代码中修改什么以产生相同的输出。

# Modified based on https://scikit-learn.org/stable/modules/preprocessing.html#preprocessing-scaler
# and https://***.com/questions/28822756/getting-model-attributes-from-pipeline
# Import Lasso
from sklearn.linear_model import Lasso
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# Instantiate a lasso regressor: lasso
#lasso = Lasso(alpha=0.4, normalize=True)
pipe = Pipeline(steps=[    
('scaler',StandardScaler()),
('lasso',Lasso(alpha=0.4))
])

# Fit the regressor to the data
#lasso.fit(X, y)
pipe.fit(X, y)

# Compute and print the coefficients
#lasso_coef = lasso.coef_
#print(lasso_coef)
lasso_coef = pipe.named_steps['lasso'].coef_
print(lasso_coef)

# Plot the coefficients
plt.plot(range(len(df_columns)), lasso_coef)
plt.xticks(range(len(df_columns)), df_columns.values, rotation=60)
plt.margins(0.02)
plt.show()

如您所见,我得出了相同的结论,但如果输出图像更相似,我会更自在地正确执行此操作。我在管道上做错了什么?

【问题讨论】:

有趣的是intercept_ 也不同。顺便说一句,你不需要用lasso_coef = lasso.fit(X, y).coef_重新计算,lasso_coef = lasso.coef_就足够了。 【参考方案1】:

当您设置Lasso(..normalize=True) 时,标准化与StandardScaler() 中的不同。它除以 l2 范数而不是标准差。如果您阅读了help page:

normalize bool, default=False 时忽略此参数 fit_intercept 设置为 False。如果为真,回归量 X 将是 在回归前通过减去均值并除以归一化 l2范数。如果您想标准化,请使用 StandardScaler 在使用 normalize=False 调用 fit 之前。

自 1.0 版起已弃用:规范化在 1.0 版中已弃用 并将在 1.2 中删除。

post 中也提到了这一点。由于它将被弃用,我认为最好只使用 StandardScaler 规范化。只要您以相同的方式缩放它,您就可以看到它是可重现的:

lasso = Lasso(alpha=0.4,random_state=99)
lasso.fit(StandardScaler().fit_transform(X),y)
print(lasso.coef_)

[-0.         -0.30409556 -2.33203165 -0.          0.51040194  1.45942351
 -1.02516505 -4.57678764]

pipe = Pipeline(steps=[    
('scaler',StandardScaler()),
('lasso',Lasso(alpha=0.4,random_state=99))
])

pipe.fit(X, y)
lasso_coef = pipe.named_steps['lasso'].coef_
print(lasso_coef)

[-0.         -0.30409556 -2.33203165 -0.          0.51040194  1.45942351
 -1.02516505 -4.57678764]

【讨论】:

谢谢。我想我错误地假设将简单转换的变量标准化为“z-scores”。我只是尝试手动转换为 z-scores,并说服自己 Lasso 没有使用 normalize 选项这样做。 lasso_coef = [-0. -0. -0. 0. 0. 0. -0. -0.07] 如果我让自己正常化:X_normalized = ( X - np.mean(X) ) / np.std(X)y_normalized = ( y - np.mean(y) ) / np.std(y) --> lasso2_coef = [-0. -0. -0.02 0. 0. 0. -0. -0.47] 我需要继续思考这个问题。【参考方案2】:

我已经实现了一个自定义规范化函数来完成这项工作。另外,请注意 L2 范数对系数的缩放。

# Import Lasso
from sklearn.linear_model import Lasso

def L2Normalizer(X) :
    X = X - np.mean(X, axis=0)
    X = X / np.linalg.norm(X, axis=0)
    return X

# Instantiate a lasso regressor: lasso
lasso = Lasso(alpha=0.4)

# Fit the regressor to the data
reg = lasso.fit(L2Normalizer(X), y)

# Compute and print the coefficients
lasso_coef = reg.coef_ / np.linalg.norm(X-np.mean(X, axis=0), axis=0)
print(lasso_coef)

# Plot the coefficients
plt.grid(color="#E5E5E5")
plt.plot(range(len(df_columns)), lasso_coef)
plt.xticks(range(len(df_columns)), df_columns.values, rotation=60)
plt.margins(0.02)

plt.show()

【讨论】:

以上是关于更新 Python sklearn Lasso(normalize=True) 以使用管道的主要内容,如果未能解决你的问题,请参考以下文章

手写算法-python代码实现Lasso回归

sklearn中正则化的Lasso问题

sklearn中正则化的Lasso问题

sklearn.linear_model.Lasso

Sklearn Lasso Regression 比 Ridge Regression 差几个数量级?

sklearn—LinearRegression,Ridge,RidgeCV,Lasso线性回归模型简单使用