python - 无法训练 keras 模型来逼近一个简单的函数
问题描述
我刚开始学习机器学习,我尝试编写一个简单的程序,其中 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。我究竟做错了什么?
解决方案
如果您盲目地运行并期望梯度下降方法学习任何功能,这实际上就是您所期望的。您观察到的行为源于两个原因:
- SGD 用于更新权重的导数实际上取决于输入。举一个很简单的例子,关于
y = f(wx + b)
的导数是使用链式法则。因此,当有一个非常大/非标准化的输入更新时,它会爆炸。现在更新基本是,所以权重突然变小了,实际上是负数。y
w
f'(wx + b)*x
w' = w - alpha*gradient
- 在单次梯度更新后,输出变为负数,因为 SGD 刚刚过冲。由于您再次
relu
在最后一层,它只输出 0 并且训练停止,因为当输出为负导数时relu
为 0。
您可以将数据大小减少到np.arange(1, 10)
并将隐藏神经元的数量减少到 12 个(更多的神经元使输出在单次更新后变得更加负,因为它们的所有权重也变为负),您将能够训练网络。
推荐阅读
- excel - 有没有办法在 Excel 中将长日期转换为短日期?
- math - 什么是渐近符号的松散界限?
- amazon-web-services - CloudFormation 和私有子网
- javascript - 使用条件渲染反应嵌套地图和过滤器不起作用
- python - Django:将多个保存组合到一个数据库操作中
- python - 如何在 python 中使用 .format 设置打印条件?
- asp.net - 是否可以将 BitBucket 用作云存储?
- php - 表单提交后新鲜的 Laravel Nova 返回 419 过期
- python - 高效的 Python 脚本开发
- ios - 无法重新排序 tableView 单元格图像