【发布时间】:2017-03-17 06:20:11
【问题描述】:
我正在尝试使用 5 个卷积层 - 2 个隐藏层 - 1 个 Softmax 的 CNN。
架构是:
cv0->relu->cv1->relu-cv2->relu->cv3->relu->cv4->relu->cv5->hid1->relu->hid2->relu->logistic softmax
通过使用图像中的 66 个补丁标记应用随机梯度。训练仅应用于具有 20 个 epoch 的单个图像以进行测试。
从网络中识别出的错误在每次迭代中都在爆炸,因此梯度在第 4 个 epoch 的第 3 个之后计算 nan。
- epoch 1 学习成本:
4.702012 - epoch 2 学习成本:
45338036.000000 - epoch 3 学习成本:
74726722389225987403008805175296.000000 - epoch 4 学习成本:
nan
正如您所见,在错误被分解为非常高的值后,梯度产生的 nan 传播到了所有网络中。
查看来自不同层权重值的单个节点以了解发生了什么:
layer8 (softmax):
- 初始值
[ 0.05436778 0.02379715] - 纪元 1
[ 0.28402206 -0.20585714] - 第二纪元
[ -5.27361184e-02 9.52038541e-02] - 第三纪元
[-7330.04199219 7330.12011719] - 第四纪元
[ nan nan]
layer6 (hid1):
- 初始值
[-0.0254469 0.00760095 ..., -0.00587915 0.02619855 0.03809309] - 纪元 1
[-0.0254469 0.00760095 ..., -0.00587915 0.02619855 0.03809309] - 第二纪元
[-0.0254469 0.00760095 ..., -0.00587915 0.02619855 0.03809309 - 第三纪元
[ -2.54468974e-02 1.79247314e+16 ..., -5.87915350e-03 2.61985492e-02 -2.06307964e+19] - 第四纪元
[ nan nan ..., nan nan nan]
layer0 (cv0):
关于初始化是
[[-0.01704694 -0.01683052 -0.0894756 ]
[ 0.12275343 -0.05518051 -0.09202443]
[-0.11599202 -0.04718829 -0.04359322]]
而在第三个纪元是
[[-24165.15234375 -26490.89257812 -24820.1484375 ]
[-27381.8203125 -26653.3359375 -24762.28710938]
[-23120.56835938 -21189.44921875 -24513.65039062]]
很明显,权重值正在爆炸式增长。
学习率为 0.01 所以为了解决这个问题,我将学习率改为 0.001,Nan 有时会消失,网络会收敛,有时不会收敛,网络会被 NaN 饱和。再次尝试使用 0.0001 的较小学习率,但我还没有看到 NaN。我从每次重新运行代码时得到的结果中看到的结果确实不同,我认为这首先与权重初始化有关。
所以我尝试了不同的权重初始化:
对于带有relu的Conv层
W_bound_6 = numpy.sqrt(6. / (fan_in + fan_out))
W_bound_2 = numpy.sqrt(2. / (fan_in + fan_out))
W_values = numpy.asarray(
numpy.random.randn(filter_shape[0], filter_shape[1], filter_shape[2], filter_shape[3]) * W_bound_2,
dtype=theano.config.floatX)
对于隐藏层和softamx层
W_bound_2 = numpy.sqrt(2. / (filter_shape[0] + filter_shape[1]))
W_values = numpy.asarray(
numpy.random.randn(filter_shape[0], filter_shape[1]) * W_bound_2,
dtype=theano.config.floatX
)
并将 b 全部初始化为零。
差异并不大,我仍然看不出结果有什么不同。
我将我的问题发布到:
- disccuess 如果我正在做的权重初始化是 正确编码
- 看看我们是否可以避免让学习率变得非常小,并至少在前几次迭代中保持较高,因为在我的例子中,它是在第 4 次迭代中传播 Nan。
- 我想知道是 L1,L2 正则化,因为我正在使用 Theano,我应该在哪里实现成本函数中的代码,或者我应该更改更新函数。
成本函数
-T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])
更新功能
updates = [
(param_i, param_i - learning_rate * grad_i)
for param_i, grad_i in zip(classifier.params, grads)
]
- 在我的结构中每一层之后的 relu 实现是否正确,但在 softmax 中不正确?
【问题讨论】:
-
我对 CNN 了解不多,但您尝试过剪裁渐变吗?在某些时候,您可能拥有
grads = T.grad(cost, classifier.params)。尝试使用grads_clipped = [T.clip(g, -2, 2] for g in grads)添加一个新行并将更新中的grads替换为grads_clipped,即zip(classifier.params, grads_clipped) -
我在 google group 上看到了这项工作,以避免梯度爆炸。我不记得到底在讨论什么是好技术还是不好。
-
值得一试。关于 L1、L2 正则化,您只需将其粘贴在损失函数的末尾即可
cost = -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y] + L1 + L2)
标签: python machine-learning deep-learning theano convolution