Neural network 非线性神经网络回归-未正确估计二次函数

Neural network 非线性神经网络回归-未正确估计二次函数,neural-network,keras,non-linear-regression,nonlinear-functions,Neural Network,Keras,Non Linear Regression,Nonlinear Functions,我主要使用人工神经网络进行分类,直到最近才开始尝试对连续变量进行建模。作为练习,我生成了一组简单的(x,y)对,其中y=x^2,并尝试训练ANN学习这个二次函数 人工神经网络模型: 该ANN有1个输入节点(即x),2个隐藏层,每个层中有2个节点,以及1个输出节点。所有四个隐藏节点都使用非线性tanh激活函数,而输出节点没有激活函数(因为它是回归) 数据: 对于训练集,我随机生成了100个介于-20,20(x)和计算y=x^2之间的数字。对于测试集,我随机生成了100个介于(-30,30)之间的数

我主要使用人工神经网络进行分类,直到最近才开始尝试对连续变量进行建模。作为练习,我生成了一组简单的(x,y)对,其中y=x^2,并尝试训练ANN学习这个二次函数

人工神经网络模型:

该ANN有1个输入节点(即x),2个隐藏层,每个层中有2个节点,以及1个输出节点。所有四个隐藏节点都使用非线性tanh激活函数,而输出节点没有激活函数(因为它是回归)

数据:

对于训练集,我随机生成了100个介于-20,20(x)和计算y=x^2之间的数字。对于测试集,我随机生成了100个介于(-30,30)之间的数字,也计算了y=x^2。然后我变换了所有x,使它们以0为中心,最小值和最大值分别约为-1.5和1.5。我同样变换了所有y,但使它们的最小值和最大值分别为-0.9和0.9。这样,所有数据都在tanh激活函数的中间范围内,而不是在极端情况下

问题:

在Keras中训练ANN后,我发现只有多项式函数的右半部分被学习,而左半部分是完全平坦的。有人知道为什么会这样吗?我尝试过使用不同的缩放选项,以及隐藏层规范,但在左侧没有运气

谢谢

附件是我用于一切的代码,图像显示了缩放训练x与预测y的曲线图。正如你所看到的,只有抛物线的一半被恢复

import numpy as np, pandas as pd
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import matplotlib.pyplot as plt

seed = 10
n = 100
X_train = np.random.uniform(-20, 20, n)
Y_train = X_train ** 2
X_test = np.random.uniform(-30, 30, n)
Y_test = X_test ** 2

#### Scale the data

x_cap = max(abs(np.array(list(X_train) + list(X_test))))
y_cap = max(abs(np.array(list(Y_train) + list(Y_test))))
x_mean = np.mean(np.array(list(X_train) + list(X_test)))
y_mean = np.mean(np.array(list(Y_train) + list(Y_test)))

X_train2 = (X_train-x_mean) / x_cap
X_test2 = (X_test-x_mean) / x_cap
Y_train2 = (Y_train-y_mean) / y_cap
Y_test2 = (Y_test-y_mean) / y_cap

X_train2 = X_train2 * (1.5 / max(X_train2))
Y_train2 = Y_train2 * (0.9 / max(Y_train2))

# define base model
def baseline_model1():
# create model
model1 = Sequential()
model1.add(Dense(2, input_dim=1, kernel_initializer='normal', activation='tanh'))
model1.add(Dense(2, input_dim=1, kernel_initializer='normal', activation='tanh'))
model1.add(Dense(1, kernel_initializer='normal'))
# Compile model
model1.compile(loss='mean_squared_error', optimizer='adam')
return model1

np.random.seed(seed)
estimator1 = KerasRegressor(build_fn=baseline_model1, epochs=100, batch_size=5, verbose=0)

estimator1.fit(X_train2, Y_train2)
prediction = estimator1.predict(X_train2)
plt.scatter(X_train2, prediction)

您的网络对初始参数非常敏感。以下内容将有所帮助:

  • kernel\u初始值设定项更改为
    glorot\u uniform
    。您的网络非常小,
    glorot_uniform
    将与tanh激活相协调,工作得更好。这将鼓励你的体重最初在一个更合理的范围内(因为它考虑了每层的扇入和扇出)

  • 训练您的模型以适应更多时代(即1000年)


你也应该考虑给隐藏层添加更多的宽度。我从2号换到5号,非常合身。我还使用了rvinas建议的更多纪元