我的问题在最后。
一个示例 CNN 使用迷你批量 GD 进行训练,并在最后一个全连接层(第60行)使用了 dropout,如下所示:
fc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training)
起初我以为 tf.layers.dropout
或 tf.nn.dropout
会随机将列中的神经元设为零。但最近我发现事实并非如此。下面的代码片段展示了 dropout
的作用。我使用 fc0
作为一个 4 个样本 x 10 个特征的矩阵,而 fc
作为 dropout 后的版本。
import tensorflow as tfimport numpy as npfc0 = tf.random_normal([4, 10])fc = tf.nn.dropout(fc0, 0.5)sess = tf.Session()sess.run(tf.global_variables_initializer())a, b = sess.run([fc0, fc])np.savetxt("oo.txt", np.vstack((a, b)), fmt="%.2f", delimiter=",")
在输出文件 oo.txt
中(原始矩阵:第1-4行,dropout 后的矩阵:第5-8行):
0.10,1.69,0.36,-0.53,0.89,0.71,-0.84,0.24,-0.72,-0.440.88,0.32,0.58,-0.18,1.57,0.04,0.58,-0.56,-0.66,0.59-1.65,-1.68,-0.26,-0.09,-1.35,-0.21,1.78,-1.69,-0.47,1.26-1.52,0.52,-0.99,0.35,0.90,1.17,-0.92,-0.68,-0.27,0.680.20,0.00,0.71,-0.00,0.00,0.00,-0.00,0.47,-0.00,-0.870.00,0.00,0.00,-0.00,3.15,0.07,1.16,-0.00,-1.32,0.00-0.00,-3.36,-0.00,-0.17,-0.00,-0.42,3.57,-3.37,-0.00,2.53-0.00,1.05,-1.99,0.00,1.80,0.00,-0.00,-0.00,-0.55,1.35
我对 正确? 的 dropout 理解是,在迷你批量或批量梯度下降阶段,对每个样本敲出 p% 的 相同 单元,反向传播更新 “稀疏网络” 的权重和偏置。然而,在 示例 的实现中,一个批次中每个样本的神经元被 随机 丢弃,如 oo.txt
第5到8行所示,并且对于每个样本,”稀疏网络” 是 不同的。
相比之下,在随机梯度下降的情况下,样本逐个输入神经网络,并且在每次迭代中,每个 tf.layers.dropout
引入的”稀疏网络”的权重都会被更新。
我的问题是,在迷你批量或批量训练中,是不是应该实现为在一个批次中对所有样本敲出相同的neurons?也许可以通过在每次迭代中对所有输入批次样本应用一个掩码?类似于这样:
# ones: 一个1xN全1张量# mask: 一个1xN的0-1张量,通过广播沿样本轴将fc1乘以maskmask = tf.layers.dropout(ones, rate=dropout, training=is_training)fc1 = tf.multiply(fc1, mask)
现在我在想,示例 中的 dropout 策略可能是更新某个神经元权重的一种 加权 方式,如果一个神经元在一个迷你批次中在10个样本中的1个被保留,其权重将通过 alpha * 1/10 * (y_k_hat-y_k) * x_k
更新,与另一个在所有10个样本中都被保留的神经元的权重通过 alpha * 1/10 * sum[(y_k_hat-y_k) * x_k]
更新相比?
截图来自 这里
回答:
Dropout 通常用于防止过拟合。在这种情况下,它会对某个神经元施加巨大的权重。通过随机将其设为0,你迫使网络在确定结果时使用更多的神经元。为了使其效果更好,你应该对每个样本丢弃不同的神经元,这样你计算的梯度会更接近没有dropout时的梯度。
如果你对批次中的每个样本丢弃相同的neurons,我猜测你的梯度会变得不那么稳定(这可能对你的应用无关紧要)。
此外,dropout 会上调其余值以保持平均激活水平大致相同。如果没有它,网络将学习错误的偏置或在关闭dropout时过饱和。
如果你仍然希望在批次中丢弃相同的neurons,那么可以对一个形状为 (1, num_neurons) 的全1张量应用dropout,然后将其与激活值相乘。