无法训练keras模型来逼近简单函数

时间:2018-06-10 19:59:49

标签: python machine-learning keras deep-learning

我刚从机器学习开始,我试着编写一个简单的程序,其中nn将学习简单函数y = f(x)= 2x。

以下是代码:

#x is a 1D array of 1 to 1000
x = np.arange(1,1000, 1)
y = x*2

xtrain = x[:750]
ytrain = y[:750]
xtest = x[750:]
ytest = y[750:]

from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten, Conv2D

model = Sequential()

model.add(Dense(128, input_dim=1, activation='relu'))

model.add(Dense(1, activation='relu'))

model.compile(loss='mean_squared_error', 
          optimizer='sgd', 
          metrics=['accuracy'])

model.summary()

history = model.fit(xtrain, ytrain, 
                batch_size=100, 
                epochs=20, 
                verbose=1, 
                validation_split=0.2)

无论我如何更改架构或超参数,我都会得到以下输出:

79999/79999 [==============================] - 1s 13us/step - loss: 8533120007.8465 - acc: 0.0000e+00 - val_loss: 32532613324.8000 - val_acc: 0.0000e+00

精度始终为0。我做错了什么?

2 个答案:

答案 0 :(得分:1)

实际上,如果你盲目地运行并期望渐变下降方法学习任何功能,你会期望的。您观察到的行为源于两个原因:

  1. SGD用来更新权重的衍生物实际上取决于输入。采用一个非常简单的案例y = f(wx + b),使用链规则y相对于w的派生f'(wx + b)*xw' = w - alpha*gradient。因此,当存在非常大/非标准化的输入的更新时,它会爆炸。现在更新基本上是relu,所以重量突然变得非常小,实际上是负面的。
  2. 在单次渐变更新后,输出变为负值,因为SGD刚刚超过。由于您在最后一层中再次拥有relu,因此只输出0并且训练停止,因为当输出为np.arange(1, 10)的负导数时为0。
  3. 您可以将数据大小减少到$(document).ready(function(){ $.getJSON("https://api.blockchain.info/pools?timespan=5days&callback=?", function(result){ }); }); 并减少隐藏神经元的数量,比如12(更多神经元在单次更新后使输出更加负面,因为它们的所有权重也变为负数)并且您将能够训练网络。

答案 1 :(得分:0)

我认为它可以解决这个问题。我使用randn代替arange。其他事情几乎相同。

x = np.random.randn(1000)
y = x*2

xtrain = x[0:750]
ytrain = y[0:750]


model = Sequential()

model.add(Dense(128, input_dim=1, activation='relu'))
model.add(Dense(1))
model.summary()
sgd = optimizers.SGD(lr=0.01, decay=1e-6)
model.compile(loss='mean_squared_error', 
          optimizer=sgd, 
          metrics=['mae'])

history = model.fit(xtrain, ytrain,
                batch_size=100, 
                epochs=20, 
                verbose=1, 
                validation_split=0.2)

如果要使用较早的数据集(即arange)。这是随附的代码。

x = np.arange(1,1000, 1)
y = x*2

xtrain = x[0:750]
ytrain = y[0:750]


model = Sequential()

model.add(Dense(128, input_dim=1, activation='relu'))
model.add(Dense(1))
model.summary()
sgd = optimizers.Adam(lr=0.0001)
model.compile(loss='mean_squared_error', 
          optimizer=sgd, 
          metrics=['mae'])

history = model.fit(xtrain, ytrain,
                batch_size=100, 
                epochs=200, 
                verbose=1, 
                validation_split=0.2)