python - 关于DNN模型中Dropout Layer和Batch Normalization Layer的问题
问题描述
我对 Dropout 层和 Batch 标准化层有一些疑问。基本上,我制作了一个带有 Dropout 层和 Batch 归一化层的简单 DNN 结构,并对其进行训练就可以了。
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??如果是,那么为什么要这样做以及如何提取图层的所有细节并将它们用于我的自定义预测模型中?
解决方案
@博士。史努比感谢您指出 BatchNormalization 具有参数,但据我所知,它们不是基于我从文档和少量研究中得出的归一化权重(归一化的权重)。
该文档说了以下内容(下面引用了文本),并且根据描述,很明显beta和gamma值是可训练的变量,与 tensorflow 的输出相符。
在训练期间(即使用 fit() 或使用参数 training=True 调用层/模型时),层使用当前批次输入的均值和标准差对其输出进行归一化。也就是说,对于每个被归一化的通道,该层返回 (batch - mean(batch)) / (var(batch) + epsilon) * gamma + beta,其中:
- epsilon 是一个小常数(可配置为构造函数参数的一部分)
- gamma 是一个学习的比例因子(初始化为 1),可以通过将 scale=False 传递给构造函数来禁用它。
- beta 是一个学习的偏移因子(初始化为 0),可以通过将 center=False 传递给构造函数来禁用它。
但这并不是故事的结局,因为模型摘要表明参数数量超过了beta和gamma所包含的参数数量。
这里可以观察到因子4 ,即 BatchNormalization 层中的参数数量是该层操作的输入形状的 4 倍。
这些附加参数是moving_mean和moving_variance值,可以在以下输出中看到
回到 OP 最初的问题和关注点,“我应该担心哪些参数?”,推理所需的参数是move_mean、Moving_variance、beta和gamma值。
使用这些值/参数的方式很容易从我在这里再次引用的文档中推断出来-
在推理过程中(即使用 evaluate() 或 predict() 或使用参数 training=False(这是默认值)调用层/模型时,层使用均值和标准差的移动平均值对其输出进行归一化。它在训练期间看到的批次。也就是说,它返回 (batch - self.moving_mean) / (self.moving_var + epsilon) * gamma + beta。
self.moving_mean 和 self.moving_var 是不可训练的变量,每次在训练模式下调用层时都会更新,如下所示:
- 移动均值 = 移动均值 * 动量 + 均值(批次)*(1 - 动量)
- 移动变量 = 移动变量 * 动量 + var(batch) * (1 - 动量)
因此,该层仅在对具有与推理数据相似统计数据的数据进行训练后,才会在推理期间对其输入进行归一化。
因此,假设每个 BatchNormalization 层都可以使用Moving_mean、Moving_variance、beta和gamma值,我认为需要在第一次激活后添加以下代码 -
# 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 上的源代码推断出的内容,实现似乎是正确的。
如果您按照以下链接,您会看到这里的类call
方法https://github.com/keras-team/keras/blob/master/keras/layers/normalization.py#L1227计算实际上是由keras 后端规范化功能在这里https://github.com/keras-team/keras/blob/35146d00b44ca645fbf4ad0b007faa07632c6f9e/keras/backend.py#L2963。后端函数文档字符串似乎与参考论文中提到的内容和您发布的图片一致。BatchNormalization
batch_normalization
这意味着,您应该只使用方差的平方根。
推荐阅读
- linux - 将东西放在 docker 容器中的什么位置?
- python - 无法在 Windows Server 2019 上加载 dll
- python - Flask Security 在 where 子句中使用 id 而不是 email
- google-apps-script - Google Sheet Cell 执行 Google 搜索
- artifactory - Jfrog Artifactory OSS - 路由器服务错误 - UpCloud
- java - 在我的 sortedLinkedList 中跟踪前一个节点的最佳方法是什么?
- python - 在python中使用正则表达式转义颜色字符串
- sql - 在 Hive SQL 中按可变时间窗口对行号进行分区
- c# - 如何访问任何 TwoPaneView 的 ScrollViewers
- git - 配置 git 代理