[ML] Pipeline无法缩放目标之解决方法

本偏示範了如何将Pipeline与TransformedTargetRegressor结合,前者负责处理输入特徵的缩放;后者针对目标输出作缩放。若有更进一步需求,建议可以建立两个Pipeline(代码如下)或者详读TransformedTargetRegressor手册

# (修正2)快捷:利用2*Pipeline减化过程,需要汇出2个模型# 输出model41 = Pipeline([('scaler', StandardScaler())])model41.fit(target)# 输入model42 = Pipeline([('scaler', StandardScaler()),                    ('model', LinearRegression())])model42.fit(feature_set, model41.fit_transform(target))std = np.std(model41.inverse_transform(model42.predict(feature_set)))print(std)print(model42.steps[1][1].coef_, '\n')#------------------------------------------------------------------------------

最近要把训练完毕的模型供其他同事使用,早期方法是用查表法进行数据处理,但随着方法的堆叠,查表法已经肥胖到一个不忍直视的地步了。

每次都会输入16个讯号,根据规则表中不同的设定参数对每一个讯号作相应处理
http://img2.58codes.com/2024/20124766zvVORKrz6h.png

然后我想到前阵子在特徵工程不再难这本书中看到Pipeline,由于Pipeline是将重複性质高的工作转为自动化(简单来讲就是省略了fit、fit_transform、transform、inverse_transform),因此我尝试利用它来取代规则表大部分的功能。

但是在测试Pipeline过程中我发现目标没有办法被缩放,而网路上的Pipeline教学几乎都是关于分类问题(目标不需要缩放),但终于让我在[1]找到解法,感谢他!!!

汇入相关函式库

# 汇入库import numpy as npimport pandas as pdfrom sklearn.linear_model import LinearRegressionfrom sklearn.preprocessing import StandardScalerfrom sklearn.pipeline import Pipelinefrom sklearn.compose import TransformedTargetRegressorimport matplotlib.pyplot as pltnp.random.seed(42)

建立测试数据

# 建立测试数据# behchmark参考自https://xinzhe.blog.csdn.net/article/details/85036849size = 750feature_set = np.random.uniform(0, 1, (size, 5))target = 10 * np.sin(np.pi*feature_set[:,0]*feature_set[:,1]) + \         20*(feature_set[:,2] - .5)**2 + \         10*feature_set[:,3] + \         5*feature_set[:,4]         feature_set = pd.DataFrame(feature_set)              target = pd.DataFrame(target.reshape(-1, 1)) 

先用最直接的方法取得一个预测值,目的在确认后面的Pipeline输出是否正确

# 一般方法:建立两个scaler,一个model。需要汇出2+1个模型# 预测输出标準差 [ 4.24940990558225 ]# 模型系数[ 0.39987264  0.42860665 -0.04726804  0.55697928  0.31174619 ]scaler_x, scaler_y = StandardScaler(), StandardScaler()model1 = LinearRegression()X, y = scaler_x.fit_transform(feature_set), scaler_y.fit_transform(target)model1.fit(X, y)std = np.std(scaler_y.inverse_transform(model1.predict(X)))print(std)print(model1.coef_, '\n')# ------------------------------------------------------------------------------

用Pipeline重新改写上面的代码,但模型系数与一般方法不符合

# 快捷:利用Pipeline减化过程,需要汇出1个模型# 预测输出标準差 [ 4.249409905582251 ]# 模型系数[ 1.94451238  2.08424096 -0.22985641  2.70849516  1.51596848 ]model2 = Pipeline([('scaler', StandardScaler()),                   ('model', LinearRegression())])model2.fit(feature_set, target)std = np.std(model2.predict(feature_set))print(std)print(model2.steps[1][1].coef_, '\n')

先检查一下这两个线性回归模型的係数,很明显两者差异甚大,看来式在作数据缩放时出了问题。

model1的係数为[ 0.39987264 0.42860665 -0.04726804 0.55697928 0.31174619 ]
http://img2.58codes.com/2024/201247660EMQWTKiMB.png

model2的係数为[ 1.94451238 2.08424096 -0.22985641 2.70849516 1.51596848 ]
http://img2.58codes.com/2024/20124766VM8JaEllgP.png

确认一下这两个数据缩放的最大值最小值,发现case2只对输入特徵进行缩放,所以两者回归模型的係数,导致预测值也有所不同,但差异不大。

model1的scaler1和scaler2参数
http://img2.58codes.com/2024/20124766ahnheEKQvj.png

model2的Pipeline只有一个缩放器,对应model1的scaler_x
http://img2.58codes.com/2024/20124766pY1rFNcY6U.png

既然知道问题了,基于Pipeline为框架的限制下,如何让目标也进行缩放呢?

参考于[1],结合了sklearn的TransformedTargetRegressor,这样不但目标也可以被缩放,而且仅需汇出一个模型。

# (修正)快捷:利用Pipeline将输入处理自动化;TransformedTargetRegressor转换目标,需要汇出1个模型# 预测输出标準差 [ 4.24940990558225 ]# 模型系数 [ 0.39987264  0.42860665 -0.04726804  0.55697928  0.31174619 ] pipeline = Pipeline(steps=[('normalize', StandardScaler()),                             ('model', LinearRegression())])model3 = TransformedTargetRegressor(regressor=pipeline, transformer=StandardScaler())model3.fit(feature_set, target)std = np.std(model3.predict(feature_set))print(std)print(model3.regressor_[1].coef_, '\n')#------------------------------------------------------------------------------

model3的係数,与model1相符合
http://img2.58codes.com/2024/2012476620d2V07u9q.png
model3内部Pipeline的scaler,与scaler_x对应
http://img2.58codes.com/2024/201247668rfCyV450i.png
model3的scaler,与scaler_y对应
http://img2.58codes.com/2024/20124766i0sL3mNUXd.png

然后就可以将wrapped_model汇出噜

import joblibjoblib.dump(wrapped_model, 'model.h5')# 汇出external_model = joblib.load('model.h5')# 汇入

参考资料

[1] How to Transform Target Variables for Regression in Python
[2] 机器学习】Selecting good features – Part IV: stability selection, RFE and everything side by side


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章