### Keras Sequential Model Non-linear Regression Model Bad Prediction

为了测试使用Keras的非线性序列模型,我创建了一些随机数据x1, x2, x3和y = a + b*x1 + c*x2^2 + d*x3^3 + e(a, b, c, d, e是常数)。损失值很快就降得很低,但模型的预测结果却相当错误。我之前用类似的代码做过线性模型,效果很好。可能是序列模型的设计有问题。以下是我的代码:

import numpy as npfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Input, Dense, Dropoutfrom tensorflow.keras import initializers# y = 3*x1 + 5*x2 + 10def gen_sequential_model():    model = Sequential([Input(3,name='input_layer')),    Dense(16, activation = 'relu', name = 'hidden_layer1', kernel_initializer=initializers.RandomNormal(mean = 0.0, stddev= 0.05, seed=42)),    Dense(16, activation = 'relu', name = 'hidden_layer2', kernel_initializer=initializers.RandomNormal(mean = 0.0, stddev= 0.05, seed=42)),    Dense(1, activation = 'relu', name = 'output_layer', kernel_initializer=initializers.RandomNormal(mean = 0.0, stddev= 0.05, seed=42)),    ])    model.summary()    model.compile(optimizer='adam',loss='mse')    return modeldef gen_linear_regression_dataset(numofsamples=500, a=3, b=5, c=7, d=9, e=11):    np.random.seed(42)    X = np.random.rand(numofsamples,3)    # y = a + bx1 + cx2^2 + dx3^3+ e    for idx in range(numofsamples):        X[idx][1] = X[idx][1]**2        X[idx][2] = X[idx][2]**3    coef = np.array([b,c,d])    bias = e    y = a + np.matmul(X,coef.transpose()) + bias    return X, ydef plot_loss_curve(history):    import matplotlib.pyplot as plt        plt.figure(figsize = (15,10))    plt.plot(history.history['loss'][1:])    plt.plot(history.history['val_loss'][1:])    plt.title('model loss')    plt.ylabel('loss')    plt.xlabel('epoch')    plt.legend(['train','test'],loc = 'upper right')    plt.show()def predict_new_sample(model, x, a=3, b=5, c=7, d=9, e=11):    x = x.reshape(1,3)    y_pred = model.predict(x)[0][0]    y_actual = a + b*x[0][0] + c*(x[0][1]**2) + d*(x[0][2]**3) + e    print("y actual value: ", y_actual)    print("y pred value: ", y_pred)model = gen_sequential_model()X,y = gen_linear_regression_dataset(numofsamples=2000)history = model.fit(X,y,epochs = 100, verbose=2, validation_split=0.3)plot_loss_curve(history)predict_new_sample(model, np.array([0.7,0.5,0.5]))

结果:

...Epoch 99/10044/44 - 0s - loss: 1.0631e-10 - val_loss: 9.9290e-11Epoch 100/10044/44 - 0s - loss: 1.0335e-10 - val_loss: 9.3616e-11y actual value:  20.375y pred value:  25.50001

为什么我的预测值与真实值相差这么大?


回答:

尽管在最后一层使用了不恰当的activation = 'relu',并且使用了不推荐的核初始化方法,你的模型运行良好,报告的指标是真实的,不是偶然的。

问题不在模型本身;问题在于你的数据生成函数没有返回你期望的内容。

首先,为了验证你的模型确实学会了你要求它学习的内容,让我们按原样运行你的代码,然后使用你的数据生成函数生成一个样本:

X, y_true = gen_linear_regression_dataset(numofsamples=1)print(X)print(y_true)

结果:

[[0.37454012 0.90385769 0.39221343]][25.72962531]

所以对于这个特定的X,真实输出是25.72962531;现在让我们将这个X传递给模型,使用你的predict_new_sample函数:

predict_new_sample(model, X)# result:y actual value:  22.134424269890232y pred value:  25.729633

嗯,预测的输出25.729633与上面计算的真实值(25.72962531)非常接近;问题是,你的函数认为真实输出应该是22.134424269890232,显然这不是正确的。

发生的情况是,你的gen_linear_regression_dataset函数在计算平方和立方成分之后返回数据X,这不是你想要的;你希望返回的数据X是在计算平方和立方成分之前的,这样你的模型可以自己学习如何做这些计算。

因此,你需要按以下方式更改函数:

def gen_linear_regression_dataset(numofsamples=500, a=3, b=5, c=7, d=9, e=11):    np.random.seed(42)    X_init = np.random.rand(numofsamples,3)  # 要返回的数据    # y = a + bx1 + cx2^2 + dx3^3+ e    X = X_init.copy()  # 临时数据    for idx in range(numofsamples):        X[idx][1] = X[idx][1]**2        X[idx][2] = X[idx][2]**3    coef = np.array([b,c,d])    bias = e    y = a + np.matmul(X,coef.transpose()) + bias    return X_init, y

修改函数并重新训练模型后(你会注意到验证误差最终会高一些,约为1.3),我们有

X, y_true = gen_linear_regression_dataset(numofsamples=1)print(X)print(y_true)

结果:

[[0.37454012 0.95071431 0.73199394]][25.72962531]

predict_new_sample(model, X)# result:y actual value:  25.729625308532768y pred value:  25.443237

这是一致的。当然,你仍然不会得到完美的预测,尤其是对未见过的数据(并且请记住,现在的误差更高):

predict_new_sample(model, np.array([0.07,0.6,0.5]))# result:y actual value:  17.995y pred value:  19.69147

如上所述,你应该更改模型以去除核初始化方法(即使用默认的、推荐的初始化方法)并为最后一层使用正确的激活函数:

def gen_sequential_model():    model = Sequential([Input(3,name='input_layer'),    Dense(16, activation = 'relu', name = 'hidden_layer1'),    Dense(16, activation = 'relu', name = 'hidden_layer2'),    Dense(1, activation = 'linear', name = 'output_layer'),    ])    model.summary()    model.compile(optimizer='adam',loss='mse')    return model

你会发现验证误差和预测结果会更好:

predict_new_sample(model, np.array([0.07,0.6,0.5]))# result:y actual value:  17.995y pred value:  18.272991

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注