使用 dill 库保存和加载 neupy 算法可以 return 同一时间段的不同预测?

Saving and loading neupy algorithm with dill library can return different predictions for the same time period?

首先感谢您阅读本文,如果您能提供帮助,在此先感谢您。 这是我用于监督学习的算法:

   # Define neural network
cgnet = algorithms.LevenbergMarquardt(
    connection=[
        layers.Input(XTrain.shape[1]),
        layers.Relu(6),
        layers.Linear(1)
    ],
    mu_update_factor=2,
    mu=0.1,
    shuffle_data=True,
    verbose=True,
    decay_rate=0.1,
    addons=[algorithms.WeightElimination]
)

交叉验证结果良好 (k=10):

[0.16767815652364237, 0.13396493112368024, 0.19033966833586402, 0.12023567250054788, 0.11826824035439124, 0.13115856672872392, 0.14250003819441104, 0.12729442202775898, 0.31073760721487326, 0.19299511349686768]
[0.9395976956178138, 0.9727526340820827, 0.9410503161549465, 0.9740922179654977, 0.9764171089773663, 0.9707258917808179, 0.9688830174583372, 0.973160633351555, 0.8551738446276884, 0.936661707991699]
MEA: 0.16 (+/- 0.11)
R2: 0.95 (+/- 0.07)

训练后我用 dill 保存了算法:

with open('network-storage.dill', 'wb') as f:
    dill.dump(cgnet, f)

然后,如果我用 dill 加载网络并考虑整个训练集的 X 值,我得到相同的 R2 (0.9691),直到现在一切正常。这是结果:

如果我尝试做同样的事情但只在最近几年 [2018-2022] 我得到这个(用 X 训练值(2018 到 2022)预测 y):

而不是这个(用 X 训练值(1992 到 2022)预测 y):

为什么当我加载不同的X值范围时,同一时期得到不同的预测? (1992 年到 2022 年的 X 输入:1992 年到 2022 年的 y 预测是可以的。 (X input from 2018 to 2022: y prediction for 2018 to 2022 is not ok.

这是代码:

import numpy as np
import pandas as pd
import datetime as dt
import matplotlib.pyplot as plt
import dill
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
from sklearn.model_selection import KFold
from scipy.interpolate import Rbf
from scipy import stats
from neupy import layers, environment, algorithms
from neupy import plots


# Import data 
data = pd.read_excel('DataAL_Incremento.xlsx', index_col=0, header=1).iloc[:,[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,-1]]
data.columns = ['PPO4L(in)','PPO4(in)','NH4L(in)','NH4(in)','NO3L(in)','NNO3(in)','CBOL(in)', 'CBO(in)','Temp(In)','Temp(alb)','Tair ','Tdew',
                'Wvel','Cl_aL(in)','Cl_a(in)','ODL(in)','OD(in)','Qin(in)','ODalb','PPO4(alb)','NNO3(alb)']


# Add filtered data
tmp0 = data.iloc[:,[9, 6, 14]].rolling(9, center=False, axis=0).mean()
tmp0.columns = ['Temp(alb)_09','CBOL(in)_09','Cl_a(in)_09']
tmp1 = data.iloc[:,[9, 6, 14]].rolling(15, center=False, axis=0).mean()
tmp1.columns = ['Temp(alb)_15', 'CBOL(in)_15','Cl_a(in)_15']
tmp2 = data.iloc[:,[9, 6, 14]].rolling(31, center=False, axis=0).mean()
tmp2.columns = ['Temp(alb)_31', 'CBOL(in)_31','Cl_a(in)_31']
data = pd.concat((data, tmp0, tmp1, tmp2), axis=1)

# Drop empty records
data = data.dropna()

# Define data
X = data.loc[:, ['CBOL(in)', 'CBO(in)','Temp(In)','Temp(alb)','Tair ','Cl_aL(in)','Cl_a(in)','OD(in)','Temp(alb)_31', 'CBOL(in)_31','Cl_a(in)_31']]

y = data.loc[:, ['ODalb']]


years = data.index.year
yearsTrain = range(1992,2022)
yearsTest = 2019,2020,2021

#yearsTrain, yearsTest = train_test_split(np.unique(years), test_size=0.2, train_size=0.8, random_state=None)

XTrain = X.query('@years in @yearsTrain')
yTrain = y.query('@years in @yearsTrain').values.ravel()
XTest = X.query('@years in @yearsTest')
yTest = y.query('@years in @yearsTest').values.ravel()

results = y.query('@years in @yearsTest')


#===============================================================================
# Neural network
#===============================================================================

# Define neural network
cgnet = algorithms.LevenbergMarquardt(
    connection=[
        layers.Input(XTrain.shape[1]),
        layers.Relu(6),
        layers.Linear(1)
    ],
    mu_update_factor=2,
    mu=0.1,
    shuffle_data=True,
    verbose=True,
    decay_rate=0.1,
    addons=[algorithms.WeightElimination]
)

# Scale
XScaler = StandardScaler()
XScaler.fit(XTrain)
XTrainScaled = XScaler.transform(XTrain)
XTestScaled = XScaler.transform(XTest)

yScaler = StandardScaler()
yScaler.fit(yTrain.reshape(-1, 1))
yTrainScaled = yScaler.transform(yTrain.reshape(-1, 1)).ravel()
yTestScaled = yScaler.transform(yTest.reshape(-1, 1)).ravel()

# Train 
cgnet.train(XTrainScaled, yTrainScaled, XTestScaled, yTestScaled, epochs=30)

yEstTrain = yScaler.inverse_transform(cgnet.predict(XTrainScaled).reshape(-1, 1)).ravel()
mae = np.mean(np.abs(yTrain-yEstTrain))
results['ANN'] = yScaler.inverse_transform(cgnet.predict(XTestScaled).reshape(-1, 1)).ravel()

# Metrics
mse  = np.mean((yTrain-yEstTrain)**2)
mseTes = np.mean((yTest-results['ANN'])**2)
maeTes = np.mean(np.abs(yTest-results['ANN']))
meantrain = np.mean(yTrain)
ssTest = (yTrain-meantrain)**2
r2=(1-(mse/(np.mean(ssTest))))
meantest = np.mean(yTest)
ssTrain = (yTest-meantest)**2
r2Tes=(1-(mseTes/(np.mean(ssTrain))))


# Plot results
print("NN MAE: %f (All), %f (Test) " % (mae, maeTes))
print ("NN MSE: %f (All), %f (Test) " % (mse, mseTes))
print ("NN R2: %f (All), %f (Test) " % (r2, r2Tes))

results.plot()
plt.show(block=True)

plots.error_plot(cgnet)
plt.show(block=True)

plt.scatter(yTest,results['ANN'])
plt.xlabel('True Values')
plt.ylabel('Predictions')

plt.show(block=True)


#===============================================================================
# Save algorithms - Neural network
#===============================================================================

with open('network-storage.dill', 'wb') as f:
    dill.dump(cgnet, f)

#===============================================================================
# Load algorithms - Neural network
#===============================================================================

#Prepare data

dataVal = pd.read_excel('DataAL_IncrementoTeste.xlsx', index_col=0, header=1).iloc[:,[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,-1]]

dataVal.columns = ['PPO4L(in)','PPO4(in)','NH4L(in)','NH4(in)','NO3L(in)','NNO3(in)','CBOL(in)', 'CBO(in)','Temp(In)','Temp(alb)','Tair ','Tdew',
                   'Wvel','Cl_aL(in)','Cl_a(in)','ODL(in)','OD(in)','Qin(in)','ODalb','PPO4(alb)','NNO3(alb)']


# Add filtered data
tmp0 = dataVal.iloc[:,[9, 6, 14]].rolling(9, center=False, axis=0).mean()
tmp0.columns = ['Temp(alb)_09','CBOL(in)_09','Cl_a(in)_09']
tmp1 = dataVal.iloc[:,[9, 6, 14]].rolling(15, center=False, axis=0).mean()
tmp1.columns = ['Temp(alb)_15', 'CBOL(in)_15','Cl_a(in)_15']
tmp2 = dataVal.iloc[:,[9, 6, 14]].rolling(31, center=False, axis=0).mean()
tmp2.columns = ['Temp(alb)_31', 'CBOL(in)_31','Cl_a(in)_31']
dataVal = pd.concat((dataVal, tmp0, tmp1, tmp2), axis=1)

# Drop empty records (removes adjacent columns)
dataVal = dataVal.dropna()

# Define data
Xval = dataVal.loc[:, ['CBOL(in)', 'CBO(in)','Temp(In)','Temp(alb)','Tair ','Cl_aL(in)','Cl_a(in)','OD(in)','Temp(alb)_31', 'CBOL(in)_31','Cl_a(in)_31']]
yval = dataVal.loc[:, ['ODalb']]

years = dataVal.index.year
yearsTrain = range(2018,2022)

XFinalVal = Xval.query('@years in @yearsTrain')
yFinalVal = yval.query('@years in @yearsTrain').values.ravel()
resultsVal = yval.query('@years in @yearsTrain')


# Load algorithms 
with open('network-storage.dill', 'rb') as f:
    cgnet = dill.load(f)
# Scale X
    XScaler = StandardScaler()
    XScaler.fit(XFinalVal)
    XFinalScaled = XScaler.transform(XFinalVal)

# Scale y  
    yScaler = StandardScaler()
    yScaler.fit(yFinalVal.reshape(-1, 1))
    yTrainScaled = yScaler.transform(yFinalVal.reshape(-1, 1)).ravel()
# Predict
    y_predicted = yScaler.inverse_transform(cgnet.predict(XFinalScaled).reshape(-1, 1)).ravel()

    resultsVal['ANN'] = y_predicted
    scoreMean = metrics.mean_absolute_error(yFinalVal, y_predicted)
    scoreR2 = metrics.r2_score(yFinalVal, y_predicted)


print(scoreMean)
print(scoreR2)


plt.scatter(yFinalVal,y_predicted)

plt.xlabel('True Values')
plt.ylabel('Predictions')

plt.show(block=True)

resultsVal.plot()
plt.show(block=True)


#===============================================================================
# Cross validation - Neural network
#===============================================================================
XScaler = StandardScaler()
XScaler.fit(XTrain)
XTrainScaled = XScaler.transform(XTrain)
XTestScaled = XScaler.transform(XTest)

yScaler = StandardScaler()
yScaler.fit(yTrain.reshape(-1, 1))
yTrainScaled = yScaler.transform(yTrain.reshape(-1, 1)).ravel()
yTestScaled = yScaler.transform(yTest.reshape(-1, 1)).ravel()

kfold = KFold(n_splits=10, shuffle=True, random_state=None)
scoresMean = []   
scoresR2 = [] 

for train, test in kfold.split(XTrainScaled):
    x_train, x_test = XTrainScaled[train], XTrainScaled[test]
    y_train, y_test = yTrainScaled[train], yTrainScaled[test]

    cgnet = algorithms.LevenbergMarquardt(
        connection=[
            layers.Input(XTrain.shape[1]),
            layers.Relu(6),
            layers.Linear(1)
        ],
        mu_update_factor=2,
        mu=0.1,
        shuffle_data=True,
        verbose=True,
        decay_rate=0.1,
        addons=[algorithms.WeightElimination]
    )

    cgnet.train(x_train, y_train, epochs=100)
    y_predicted = cgnet.predict(x_test)

    scoreMean = metrics.mean_absolute_error(y_test, y_predicted)
    scoreR2 = metrics.r2_score(y_test, y_predicted)
    scoresMean.append(scoreMean)
    scoresR2.append(scoreR2)

print(scoresMean)
print(scoresR2)
scoresMean = np.array(scoresMean)
scoresR2 = np.array(scoresR2)

print("MEA: %0.2f (+/- %0.2f)" % (scoresMean.mean(), scoresMean.std() * 2))

print("R2: %0.2f (+/- %0.2f)" % (scoresR2.mean(), scoresR2.std() * 2))

我认为问题之一可能与您在训练前应用的缩放有关。在训练阶段,你使用训练数据拟合缩放函数

XScaler = StandardScaler()
XScaler.fit(XTrain)

但是在使用 dill 加载网络后,您已经为缩放器安装了不同的数据(特别是验证数据)

XScaler = StandardScaler()
XScaler.fit(XFinalVal)

在第二种情况下,您对网络在训练期间未见过的预测使用不同的缩放比例。与网络预期的样本相比,新的缩放比例可能会产生不同的样本分布。

为了使训练效果可重现,您还需要保存 XScaler 并在加载网络时同时加载它。

我所描述的一切也适用于 yScaler