【问题标题】:Question About Dropout Layer and Batch Normalization Layer in DNN model关于DNN模型中Dropout Layer和Batch Normalization Layer的问题
【发布时间】:2021-04-20 13:28:57
【问题描述】:

我对 Dropout 层和 Batch 标准化层有一些疑问。基本上,我已经做了一个简单的 DNN 结构,带有一个 Dropout 层和 Batch 归一化层,并对其进行训练就可以了。

DNN模型的简单结构举例:

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential([
    layers.Dense(10, activation='relu', input_shape=[11]),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(8, activation='relu'),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(6, activation='relu'),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1,activation='softmax'),
])

model.compile(
    optimizer='adam',
    loss='mae',
)

history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=256,
    epochs=100,
    verbose=0,
)

但现在我想在我的自定义预测模型中使用训练模型的所有层的权重和偏差(忘记其他方式)。

# Predictions for test
test_logits_1 = tf.matmul(tf_test_dataset, weights_1) + biases_1
test_relu_1 = tf.nn.relu(test_logits_1)

test_logits_2 = tf.matmul(test_relu_1, weights_2) + biases_2
test_relu_2 = tf.nn.relu(test_logits_2)

test_logits_3 = tf.matmul(test_relu_2, weights_3) + biases_3
test_relu_3 = tf.nn.relu(test_logits_3)

test_logits_4 = tf.matmul(test_logits_3 , weights_4) + biases_4
test_prediction = tf.nn.softmax(test_relu_4)

现在问题来了:必须要在预测模型中添加dropout层和batch normalized层,batch size吗?如果是,那么为什么要这样做?如何提取层的所有细节并将它们用于我的自定义预测模型?

【问题讨论】:

  • 您不需要添加 dropout 层,因为 dropout 层是 meant 仅在训练期间而不是在推理期间起作用。我相信需要添加批量标准化,您可以从here轻松获得公式
  • 能解释一下为什么它需要在预测时间以及我应该取哪些参数??
  • 你绝对需要使用 dropout 层。在训练期间,dropout 层将所有剩余的值乘以1/(1-p),否则网络将接收到测试时输入的两倍。看到这个:stackoverflow.com/questions/59003985/…
  • @Nicolas Gervais 我知道 dropout 层会规范其余未设置为零的值,但这里的 OP 不是在询问仅使用经过训练的权重进行推理吗?
  • 批量归一化层没有任何参数,它只是一个归一化过程(即只是一些数据操作),类似于softmax层没有任何参数。

标签: python tensorflow keras


【解决方案1】:

@博士。 Snoopy 感谢您指出 BatchNormalization 有参数,但据我所知,它们不是基于我从文档和少量研究中推断出来的归一化权重(权重被归一化)。

doc 说了以下内容(下面引用了文本),根据描述,很明显 betagamma 值是可训练的变量,与输出一致来自张量流。

在训练期间(即使用 fit() 或使用参数 training=True 调用层/模型时),层使用当前批次输入的均值和标准差对其输出进行归一化。也就是说,对于每个被归一化的通道,该层返回 (batch - mean(batch)) / (var(batch) + epsilon) * gamma + beta,其中:

  • epsilon 是一个小常数(可配置为构造函数参数的一部分)
  • gamma 是一个学习的缩放因子(初始化为 1),可以通过将 scale=False 传递给构造函数来禁用它。
  • beta 是一个学习的偏移因子(初始化为 0),可以通过将 center=False 传递给构造函数来禁用它。

但这并不是故事的结局,因为模型摘要表明参数数量超过了 betagamma 所包含的参数数量。

可以在此处观察到 4 的因子,即 BatchNormalization 层中的参数数量是该层操作的输入形状的 4 倍。

这些附加参数是 moving_meanmoving_variance 值,可以在以下输出中看到

回到OP最初的问题和关心,“我应该担心什么参数?”,推理需要的参数是moving_meanmoving_variancebetagamma 值。

使用这些值/参数的方式很容易从我在这里再次引用的文档中推断出来-

在推理期间(即使用 evaluate() 或 predict() 或使用参数 training=False(这是默认值)调用层/模型时,层使用均值和标准的移动平均值对其输出进行归一化它在训练过程中看到的批次的偏差。也就是说,它返回 (batch - self.movi​​ng_mean) / (self.movi​​ng_var + epsilon) * gamma + beta。

self.movi​​ng_mean 和 self.movi​​ng_var 是不可训练的变量,每次在训练模式下调用层时都会更新,如下所示:

  • moving_mean = Moving_mean * 动量 + 平均值(批次)*(1 - 动量)
  • moving_var = Moving_var * 动量 + var(batch) * (1 - 动量)

因此,只有在对具有与推理数据相似统计数据的数据进行训练后,该层才会在推理期间对其输入进行归一化。

所以假设 moving_meanmoving_variancebetagamma 值可用于每个 BatchNormalization 层,我认为第一次激活后需要添加以下代码-

# epsilon is just to avoid ZeroDivisionError, so the default value should be okay
test_BN_1 = (test_relu_1 - moving_mean_1) / (moving_var_1 + epsilon_1) * gamma_1 + beta_1

编辑:

事实证明文档似乎是错误的,但根据我可以从 github 上的源代码推断出的内容,实现似乎是正确的。

如果您点击以下链接,您会看到BatchNormalization 类的call 方法在这里https://github.com/keras-team/keras/blob/master/keras/layers/normalization.py#L1227 计算实际上是由keras 后端规范化函数batch_normalization 这里https://github.com/keras-team/keras/blob/35146d00b44ca645fbf4ad0b007faa07632c6f9e/keras/backend.py#L2963 完成的。后端函数doc字符串似乎与参考论文中提到的内容以及您发布的图片一致。

也就是说,您应该只使用方差的平方根。

【讨论】:

  • 是的,我们需要在推理过程中使用小批量统计信息,就像您提到的实现一样。在原始方程中,他们使用方差脉冲ε的平方根。但是 Keras 包避免了平方根方差脉冲 epsilon。应该采用哪个等式?
  • 你能告诉我你在说哪个“原始方程”吗?
  • 请检查这个等式:i.stack.imgur.com/BiPHy.png
猜你喜欢
  • 2018-09-02
  • 1970-01-01
  • 2018-01-15
  • 1970-01-01
  • 2020-12-13
  • 1970-01-01
  • 2020-12-04
  • 2021-08-15
  • 2019-08-10
相关资源
最近更新 更多