【问题标题】:Can I inverse transform the intercept and coefficients of LASSO regression after using Robust Scaler?使用 Robust Scaler 后,我可以对 LASSO 回归的截距和系数进行逆变换吗?
【发布时间】:2019-08-26 16:25:48
【问题描述】:

在使用 Robust Scaler 在缩放数据上拟合模型后,是否可以对 LASSO 回归中的截距和系数进行逆变换?

我正在使用 LASSO 回归来预测未标准化的数据值,并且除非事先进行缩放,否则 LASSO 的性能不佳。在缩放数据并拟合 LASSO 模型之后,理想情况下,我希望能够看到模型截距和系数是什么,但以原始单位(不是缩放版本)。我问了一个类似的问题here,看来这是不可能的。如果不是,为什么?谁可以给我解释一下这个?我正在努力扩大我对 LASSO 和 Robust Scaler 工作原理的理解。

下面是我使用的代码。在这里,我尝试使用transformer_x对系数进行逆变换,使用transformer_y对截距进行逆变换。但是,这听起来是不正确的。

import pandas as pd
from sklearn.preprocessing import RobustScaler
from sklearn.linear_model import Lasso

df = pd.DataFrame({'Y':[5, -10, 10, .5, 2.5, 15], 'X1':[1., -2.,  2., .1, .5, 3], 'X2':[1, 1, 2, 1, 1, 1], 
              'X3':[6, 6, 6, 5, 6, 4], 'X4':[6, 5, 4, 3, 2, 1]})

X = df[['X1','X2', 'X3' ,'X4']]
y = df[['Y']]

#Scaling 
transformer_x = RobustScaler().fit(X)
transformer_y = RobustScaler().fit(y) 
X_scal = transformer_x.transform(X)
y_scal = transformer_y.transform(y)

#LASSO
lasso = Lasso()
lasso = lasso.fit(X_scal, y_scal)

def pred_val(X1,X2,X3,X4): 

    print('X1 entered: ', X1)

    #Scale X value that user entered - by hand
    med_X = X.median()
    Q1_X = X.quantile(0.25)
    Q3_X = X.quantile(0.75)
    IQR_X = Q3_X - Q1_X
    X_scaled = (X1 - med_X)/IQR_X
    print('X1 scaled by hand: ', X_scaled[0].round(2))

    #Scale X value that user entered - by function
    X_scaled2 = transformer_x.transform(np.array([[X1,X2]]))
    print('X1 scaled by function: ', X_scaled2[0][0].round(2))

    #Intercept by hand
    med_y = y.median()
    Q1_y = y.quantile(0.25)
    Q3_y = y.quantile(0.75)
    IQR_y = Q3_y - Q1_y
    inv_int = med_y + IQR_y*lasso.intercept_[0]

    #Intercept by function
    inv_int2 = transformer_y.inverse_transform(lasso.intercept_.reshape(-1, 1))[0][0]

    #Coefficient by hand
    inv_coef = lasso.coef_[0]*IQR_y 

    #Coefficient by function 
    inv_coef2 = transformer_x.inverse_transform(reg.coef_.reshape(1,-1))[0]

    #Prediction by hand
    preds = inv_int + inv_coef*X_scaled[0]

    #Prediction by function 
    preds_inner = lasso.predict(X_scaled2)  
    preds_f = transformer_y.inverse_transform(preds_inner.reshape(-1, 1))[0][0]

    print('\nIntercept by hand: ', inv_int[0].round(2))
    print('Intercept by function: ', inv_int2.round(2))
    print('\nCoefficients by hand: ', inv_coef[0].round(2))
    print('Coefficients by function: ', inv_coef2[0].round(2))
    print('\nYour predicted value by hand is: ', preds[0].round(2))
    print('Your predicted value by function is: ', preds_f.round(2))
    print('Perfect Prediction would be 80')

pred_val(10,1,1,1)

更新:我更新了我的代码以显示我正在尝试创建的预测函数的类型。我只是想创建一个完全符合.predict 的函数,而且还以未缩放的单位显示截距和系数。

当前输出:

Out[1]:
X1 entered:  10
X1 scaled by hand:  5.97
X1 scaled by function:  5.97

Intercept by hand:  34.19
Intercept by function:  34.19

Coefficients by hand:  7.6
Coefficients by function:  8.5

Your predicted value by hand is:  79.54
Your predicted value by function is:  79.54
Perfect Prediction would be 80

理想输出:

Out[1]:
X1 entered:  10
X1 scaled by hand:  5.97
X1 scaled by function:  5.97

Intercept by hand:  34.19
Intercept by function:  34.19

Coefficients by hand:  7.6
Coefficients by function:  7.6

Your predicted value by hand is:  79.54
Your predicted value by function is:  79.54
Perfect Prediction would be 80

【问题讨论】:

  • 澄清一下:你想要原始单位中的系数和截距,还是想要原始单位中的预测(如 Stelgos 的回答)?
  • 我想要原始单位的系数和截距
  • 例如,如果您有以美元为单位的预测值,而 X 值以 [yr, m^2, USD] 为单位(例如),您需要以 USD/yr、USD/m^2 为单位的系数和纯数字,截取美元?
  • @Itamar Mushkin 对不起,我不太明白你的问题。我想要原始单位的系数,是的。

标签: python machine-learning lasso-regression


【解决方案1】:

基于链接的 SO 线程,您要做的就是获取未缩放的预测值。那正确吗?

如果是,那么你需要做的就是:

# Scale the test dataset
X_test_scaled = transformer_x.transform(X_test)

# Predict with the trained model
prediction = lasso.predict(X_test_scaled)

# Inverse transform the prediction
prediction_in_dollars = transformer_y.inverse_transform(prediction)

更新:

假设训练数据只包含一个名为 X 的特征。下面是 RobustScaler 的作用:

X_scaled = (X - median(X))/IQR(X)
y_scaled = (y - median(y))/IQR(y)

然后,lasso 回归将给出如下预测:

a * X_scaled + b = y_scaled

您必须计算出方程式才能查看未缩放数据的模型系数:

# Substituting X_scaled and y_scaled from the 1st equation
# In this equation `median(X), IQR(X), median(y) and IQR(y) are plain numbers you already know from the training phase
a * (X - median(X))/IQR(X) + b = (y - median(y))/IQR(y)

如果您尝试从中得出类似a_new * x + b_new = y 的等式,您最终会得到:

a_new = (a * (X - median(X)) / (X * IQR(X))) * IQR(y)
b_new = b * IQR(y) + median(y)
a_new * X + b_new = y

您可以看到未缩放的系数 (a_new) 取决于 X。因此,您可以使用未缩放的 X 直接进行预测,但在这两者之间,您正在间接应用转换。

更新 2

我已经修改了您的代码,现在它显示了如何获得原始比例的系数。该脚本只是我上面显示的公式的实现。

import pandas as pd
import numpy as np
from sklearn.preprocessing import RobustScaler
from sklearn.linear_model import Lasso

df = pd.DataFrame({'Y':[5, -10, 10, .5, 2.5, 15], 'X1':[1., -2.,  2., .1, .5, 3], 'X2':[1, 1, 2, 1, 1, 1],
              'X3':[6, 6, 6, 5, 6, 4], 'X4':[6, 5, 4, 3, 2, 1]})

X = df[['X1','X2','X3','X4']]
y = df[['Y']]

#Scaling
transformer_x = RobustScaler().fit(X)
transformer_y = RobustScaler().fit(y)
X_scal = transformer_x.transform(X)
y_scal = transformer_y.transform(y)

#LASSO
lasso = Lasso()
lasso = lasso.fit(X_scal, y_scal)

def pred_val(X_test):

    print('X entered: ',)
    print (X_test.values[0])

    #Scale X value that user entered - by hand
    med_X = X.median()
    Q1_X = X.quantile(0.25)
    Q3_X = X.quantile(0.75)
    IQR_X = Q3_X - Q1_X
    X_scaled = ((X_test - med_X)/IQR_X).fillna(0).values
    print('X_test scaled by hand: ',)
    print (X_scaled[0])

    #Scale X value that user entered - by function
    X_scaled2 = transformer_x.transform(X_test)
    print('X_test scaled by function: ',)
    print (X_scaled2[0])

    #Intercept by hand
    med_y = y.median()
    Q1_y = y.quantile(0.25)
    Q3_y = y.quantile(0.75)
    IQR_y = Q3_y - Q1_y

    a = lasso.coef_
    coef_new = ((a * (X_test - med_X).values) / (X_test * IQR_X).values) * float(IQR_y)
    coef_new = np.nan_to_num(coef_new)[0]

    b = lasso.intercept_[0]
    intercept_new = b * float(IQR_y) + float(med_y)

    custom_pred = sum((coef_new * X_test.values)[0]) + intercept_new

    pred = lasso.predict(X_scaled2)
    final_pred = transformer_y.inverse_transform(pred.reshape(-1, 1))[0][0]


    print('Original intercept: ', lasso.intercept_[0].round(2))
    print('New intercept: ', intercept_new.round(2))
    print('Original coefficients: ', lasso.coef_.round(2))
    print('New coefficients: ', coef_new.round(2))
    print('Your predicted value by function is: ', final_pred.round(2))
    print('Your predicted value by hand is: ', custom_pred.round(2))


X_test = pd.DataFrame([10,1,1,1]).T
X_test.columns = ['X1', 'X2', 'X3', 'X4']

pred_val(X_test)

您可以看到自定义预测使用原始值 (X_test.values)。

结果:

X entered: 
[10  1  1  1]

X_test scaled by hand: 
[ 5.96774194  0.         -6.66666667 -1.        ]
X_test scaled by function: 
[ 5.96774194  0.         -6.66666667 -1.        ]

Original intercept:  0.01
New intercept:  3.83

Original coefficients:  [ 0.02  0.   -0.   -0.  ]
New coefficients:  [0.1 0.  0.  0. ]

Your predicted value by function is:  4.83
Your predicted value by hand is:  4.83

如上所述,新系数取决于X_test。这意味着您不能将它们的当前值用于另一个测试样本。对于不同的输入,它们的值会有所不同。

【讨论】:

  • 我正在寻找原始单位中的系数和截距,而不是预测值。
  • 一旦我得到未缩放的系数和截距,我可以通过 y = unscaled_intercept + (unscaled_coef * X_unscaled) 预测值吗?
  • 请查看我上面的回答,了解如何做到这一点。顺便说一句,为什么要反转系数?最终目标是什么?
  • 对不起,我检查了你的答案,但我仍然不确定如何取消系数。当我做 lasso.coef_*IQR_y 时,我得到的系数与我原来使用 inverse_transform 函数的 inverse_coeff_array 非常不同。为什么是这样? (另外,我在这里的最终目标是简单地了解 LASSO 是如何预测值的,这在同时使用 RobustScaler 时很难看到)
  • 如果我已经回答了你的问题,请接受我的回答。
猜你喜欢
  • 1970-01-01
  • 2018-03-05
  • 2023-03-16
  • 1970-01-01
  • 2022-08-06
  • 2018-05-11
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
相关资源
最近更新 更多