本偏示範了如何将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个讯号,根据规则表中不同的设定参数对每一个讯号作相应处理
然后我想到前阵子在特徵工程不再难这本书中看到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 ]
model2的係数为[ 1.94451238 2.08424096 -0.22985641 2.70849516 1.51596848 ]
确认一下这两个数据缩放的最大值最小值,发现case2只对输入特徵进行缩放,所以两者回归模型的係数,导致预测值也有所不同,但差异不大。
model1的scaler1和scaler2参数
model2的Pipeline只有一个缩放器,对应model1的scaler_x
既然知道问题了,基于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相符合
model3内部Pipeline的scaler,与scaler_x对应
model3的scaler,与scaler_y对应
然后就可以将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