我正在尝试使用神经网络(Keras)来逼近正弦函数。
是的,我已经阅读了相关的帖子 🙂
使用四个隐藏神经元和Sigmoid激活函数,以及一个使用线性激活函数的输出层,可以很好地工作。
但也有一些设置会产生对我来说看起来很奇怪的结果。
因为我刚开始使用神经网络,我对事情发生的原因和过程很感兴趣,但到目前为止我还没有弄明白。
# -*- coding: utf-8 -*-import numpy as npnp.random.seed(7)from keras.models import Sequentialfrom keras.layers import Denseimport pylab as plfrom sklearn.preprocessing import MinMaxScalerX = np.linspace(0.0 , 2.0 * np.pi, 10000).reshape(-1, 1)Y = np.sin(X)x_scaler = MinMaxScaler()#y_scaler = MinMaxScaler(feature_range=(-1.0, 1.0))y_scaler = MinMaxScaler()X = x_scaler.fit_transform(X)Y = y_scaler.fit_transform(Y)model = Sequential()model.add(Dense(4, input_dim=X.shape[1], kernel_initializer='uniform', activation='relu'))# model.add(Dense(4, input_dim=X.shape[1], kernel_initializer='uniform', activation='sigmoid'))# model.add(Dense(4, input_dim=X.shape[1], kernel_initializer='uniform', activation='tanh'))model.add(Dense(1, kernel_initializer='uniform', activation='linear'))model.compile(loss='mse', optimizer='adam', metrics=['mae'])model.fit(X, Y, epochs=500, batch_size=32, verbose=2)res = model.predict(X, batch_size=32)res_rscl = y_scaler.inverse_transform(res)Y_rscl = y_scaler.inverse_transform(Y)pl.subplot(211)pl.plot(res_rscl, label='ann')pl.plot(Y_rscl, label='train')pl.xlabel('#')pl.ylabel('value [arb.]')pl.legend()pl.subplot(212)pl.plot(Y_rscl - res_rscl, label='diff')pl.legend()pl.show()
这是使用四个隐藏神经元(ReLU)和线性输出激活函数的结果。
为什么结果呈现出ReLU的形状?
这是否与输出归一化有关?
回答:
这里有两点需要注意:
- 你的网络非常浅且小。只有4个使用
relu
的neurons很容易导致其中一些neurons完全饱和。这可能是你的网络结果看起来那样的原因。尝试使用he_normal
或he_uniform
作为初始化器来克服这个问题。 - 在我看来,你的网络对于这个任务来说太小了。我肯定会增加网络的深度和宽度,通过增加更多的neurons和layers。在使用形状类似于
sin
函数的sigmoid
时,这可能运作良好 – 但在使用relu
时,你真的需要一个更大的网络。