【问题标题】:How to prevent a lazy Convolutional Neural Network?如何防止惰性卷积神经网络?
【发布时间】:2018-05-30 12:26:50
【问题描述】:

如何防止懒惰的卷积神经网络?在用 KERAS 训练后,我以“懒惰的 CNN”结束。无论输入是什么,输出都是恒定的。你认为问题是什么?

我尝试重复 NVIDIA 的自动驾驶汽车端到端学习实验the paper。当然,我没有真正的汽车,而是 Udacity 的simulator。模拟器生成关于汽车前景的图形。

CNN 接收到该数字,并提供转向角度以使汽车保持在轨道上。游戏规则是让模拟汽车在赛道上安全运行。这不是很困难。

奇怪的是,有时我在用 KERAS 训练后以一个懒惰的 CNN 结束,它给出了恒定的转向角。模拟汽车会成功,但 CNN 的输出没有变化。特别是层变得更深,例如CNN the paper

如果我使用这样的 CNN,我可以在训练后得到一个有用的模型。

model = Sequential()
model.add(Lambda(lambda x: x/255.0 - 0.5, input_shape = (160,320,3)))
model.add(Cropping2D(cropping=((70,25),(0,0))))
model.add(Conv2D(24, 5, strides=(2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(36, 5, strides=(2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(48, 5, strides=(2, 2)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(50))
model.add(Activation('sigmoid'))
model.add(Dense(10))
model.add(Activation('sigmoid'))
model.add(Dense(1))

但是,如果我使用更深的 CNN,我就有更多机会接收到惰性 CNN。 具体来说,如果我使用喜欢 NVIDIA 的 CNN,每次训练后我几乎都会收到一个懒惰的 CNN。

model = Sequential()
model.add(Lambda(lambda x: x/255.0 - 0.5, input_shape = (160,320,3)))
model.add(Cropping2D(cropping=((70,25),(0,0))))
model.add(Conv2D(24, 5, strides=(2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(36, 5, strides=(2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(48, 5, strides=(2, 2)))
model.add(Activation('relu'))
model.add(Conv2D(64, 3, strides=(1, 1)))
model.add(Activation('relu'))
model.add(Conv2D(64, 3, strides=(1, 1)))
model.add(Activation('relu'))
model.add(Flatten())
model.add(Dense(1164))
model.add(Activation('sigmoid'))
model.add(Dense(100))
model.add(Activation('sigmoid'))
model.add(Dense(50))
model.add(Activation('sigmoid'))
model.add(Dense(10))
model.add(Activation('sigmoid'))
model.add(Dense(1))

我对卷积层使用“relu”,全连接层的激活函数是“sigmoid”。我尝试更改激活函数,但没有效果。

这是我的分析。我不同意我的程序中的错误,因为我可以使用相同的代码和更简单的 CNN 成功驾驶汽车。我认为原因是模拟器或神经网络的结构。在真正的自动驾驶汽车中,训练信号,即转向角,应该包含噪声;因此,驾驶员永远不会在真正的道路上握住方向盘。但在模拟器中,训练信号非常干净。几乎 60% 的转向角为零。优化器可以通过使 CNN 的输出接近零来轻松完成这项工作。优化器似乎也很懒惰。然而,当我们真的想要这个 CNN 输出一些东西时,它也会给出零。因此,我为这些零转向角添加了小噪音。我得到一个懒惰的 CNN 的机会更小,但它并没有消失。

你觉得我的分析怎么样?我可以使用其他策略吗?我想知道在 CNN 研究的悠久历史中是否已经解决了类似的问题。

资源

相关文件已上传至GitHub。您可以使用这些文件重复整个实验。

【问题讨论】:

标签: machine-learning computer-vision keras conv-neural-network robotics


【解决方案1】:

我无法运行您的模型,因为问题和 GitHub 存储库都不包含数据。这就是为什么我对我的答案有 90% 的把握。

但我认为你的网络的主要问题是密集层之后的sigmoid 激活函数。我想,当只有两个时它会训练得很好,但是四个太多了。

不幸的是,NVidia 的 End to End Learning for Self-Driving Cars 论文没有明确指定它,但现在默认激活不再是 sigmoid(就像以前一样),而是 relu。如果您对为什么会这样感兴趣,请参阅this discussion。所以我提出的解决方案是试试这个模型:

model = Sequential()
model.add(Lambda(lambda x: x/255.0 - 0.5, input_shape = (160,320,3)))
model.add(Cropping2D(cropping=((70,25),(0,0))))
model.add(Conv2D(24, (5, 5), strides=(2, 2), activation="relu"))
model.add(Conv2D(36, (5, 5), strides=(2, 2), activation="relu"))
model.add(Conv2D(48, (5, 5), strides=(2, 2), activation="relu"))
model.add(Conv2D(64, (3, 3), strides=(1, 1), activation="relu"))
model.add(Conv2D(64, (3, 3), strides=(1, 1), activation="relu"))
model.add(Flatten())
model.add(Dense(1164, activation="relu"))
model.add(Dense(100, activation="relu"))
model.add(Dense(50, activation="relu"))
model.add(Dense(10, activation="relu"))
model.add(Dense(1))

它模仿 NVidia 的网络架构,不受梯度消失的影响。

【讨论】:

  • 非常感谢您的建议。这些天我正在研究另一个可悲的问题。在某些文化中,忽视他人是非常严重的。我没有忽略,但我的小脑袋无法处理这么多信息。我会回来的。
  • 您 90% 的信心是正确的。懒惰的卷积神经网络已经消失了。谢谢你。看来我有一个消失的梯度问题。如果梯度无法通过网络,优化器必须通过提供惰性 CNN 来完成工作!有可能,但我认为详细原因值得研究。
猜你喜欢
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
  • 2020-10-07
  • 2020-10-19
  • 2020-10-19
相关资源
最近更新 更多