【发布时间】:2018-10-07 10:17:18
【问题描述】:
我使用 TensorFlow 来训练 DNN。我了解到 Batch Normalization 对 DNN 很有帮助,所以我在 DNN 中使用了它。
我使用“tf.layers.batch_normalization”,按照API文档的说明搭建网络:training时,设置其参数“training=True” ,当 validate 时,设置“training=False”。并添加 tf.get_collection(tf.GraphKeys.UPDATE_OPS)。
这是我的代码:
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
input_node_num=257*7
output_node_num=257
tf_X = tf.placeholder(tf.float32,[None,input_node_num])
tf_Y = tf.placeholder(tf.float32,[None,output_node_num])
dropout_rate=tf.placeholder(tf.float32)
flag_training=tf.placeholder(tf.bool)
hid_node_num=2048
h1=tf.contrib.layers.fully_connected(tf_X, hid_node_num, activation_fn=None)
h1_2=tf.nn.relu(tf.layers.batch_normalization(h1,training=flag_training))
h1_3=tf.nn.dropout(h1_2,dropout_rate)
h2=tf.contrib.layers.fully_connected(h1_3, hid_node_num, activation_fn=None)
h2_2=tf.nn.relu(tf.layers.batch_normalization(h2,training=flag_training))
h2_3=tf.nn.dropout(h2_2,dropout_rate)
h3=tf.contrib.layers.fully_connected(h2_3, hid_node_num, activation_fn=None)
h3_2=tf.nn.relu(tf.layers.batch_normalization(h3,training=flag_training))
h3_3=tf.nn.dropout(h3_2,dropout_rate)
tf_Y_pre=tf.contrib.layers.fully_connected(h3_3, output_node_num, activation_fn=None)
loss=tf.reduce_mean(tf.square(tf_Y-tf_Y_pre))
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i1 in range(3000*num_batch):
train_feature=... # Some processing
train_label=... # Some processing
sess.run(train_step,feed_dict={tf_X:train_feature,tf_Y:train_label,flag_training:True,dropout_rate:1}) # when train , set "training=True" , when validate ,set "training=False" , get a bad result . However when train , set "training=False" ,when validate ,set "training=False" , get a better result .
if((i1+1)%277200==0):# print validate loss every 0.1 epoch
validate_feature=... # Some processing
validate_label=... # Some processing
validate_loss = sess.run(loss,feed_dict={tf_X:validate_feature,tf_Y:validate_label,flag_training:False,dropout_rate:1})
print(validate_loss)
我的代码有错误吗? 如果我的代码是正确的,我想我会得到一个奇怪的结果:
training时,我设置“training = True”,validate时,设置“training = False “,结果不好。我每 0.1 个 epoch 打印一次 validate loss ,第 1 到第 3 个 epoch 的 validate loss 是
0.929624
0.992692
0.814033
0.858562
1.042705
0.665418
0.753507
0.700503
0.508338
0.761886
0.787044
0.817034
0.726586
0.901634
0.633383
0.783920
0.528140
0.847496
0.804937
0.828761
0.802314
0.855557
0.702335
0.764318
0.776465
0.719034
0.678497
0.596230
0.739280
0.970555
但是,当我更改代码“sess.run(train_step,feed_dict={tf_X:train_feature,tf_Y:train_label,flag_training:True,dropout_rate:1})”时,即:设置“ training=False" 当 training 时设置 "training=False" 当 validate 时。结果是好的。第一个时期的验证损失是
0.474313
0.391002
0.369357
0.366732
0.383477
0.346027
0.336518
0.368153
0.330749
0.322070
0.335551
为什么会出现这个结果?训练时是否需要设置“training=True”,验证时设置“training=False”?
【问题讨论】:
-
你的 batch_size 有多大?
-
@Ishamael 我用于训练的数据是实时生成的。每个生成数据的batch_size是不固定的,每个batch通常有300到500个样本。 (我还有一个问题:在一般的DNN训练中,很常见将batch_size设置为固定值,比如设置batch_size = 1000,那么每个batch有1000个样本。我想知道是否DNN训练必须确保batch_size固定?比如第1批有300个样本,第2批有500个样本,第3批有400个样本……这种方式是否符合DNN理论?)
-
可变批量大小应该没问题。鉴于您的数据已生成,生成批次中的样本是否比生成批次中的样本更相似?如果是,这将是批量规范的问题
-
@Ishamael 是的,在生成的批次中的样本比跨生成的批次的样本更相似。我大概明白为什么在训练中设置“training=true”效果不好,而在训练中设置“training=false”效果很好:
-
@Ishamael 我认为原因是:因为使用了 tf.get_collection(tf.GraphKeys.UPDATE_OPS),所以全局均值 mean_global 和训练 DNN 时,全局方差 var_global 由批次均值 mean_batch 和批次方差 var_batch 更新,而不管“training= true”或“training=false”。
标签: python tensorflow deep-learning batch-normalization