Tensorflow:批归一化和l1l2正则化
Posted -柚子皮-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tensorflow:批归一化和l1l2正则化相关的知识,希望对你有一定的参考价值。
Batch Nomalization
tf.nn.batch_normalization()是一个低级的操作函数,调用者需要自己处理张量的平均值和方差。
tf.nn.fused_batch_norm是另一个低级的操作函数,和前者十分相似,不同之处在于它针对4维输入张量进行了优化,这是卷积神经网络中常见的情况,而前者tf.nn.batch_normalization则接受任何等级大于1的张量。
tf.nn.batch_norm_with_global_normalization是另一个被弃用的操作,现在这个函数会委托给tf.nn.batch_normalization执行,在未来这个函数会被放弃。
tf.contrib.layers.batch_norm是batch_norm的早期实现,其升级的核心api版本为(tf.layers.batch_normalization),不推荐使用它,因为它可能会在未来的版本中丢失。
tf.layers.batch_normalization是对先前操作的高级封装,最大的不同在于它负责创建和管理运行张量的均值和方差,并尽可可能地快速融合计算,通常,这个函数应该是你的默认选择。
tf.keras.layers.BatchNormalization是BN算法的keras实现,这个函数在后端会调用tensorflow的tf.nn.batch_normalization函数。
Note:
1 tf.nn.batch_normalization(),tf.layers.batch_normalization和tensorflow.contrib.layers.batch_norm()这三个batch normal函数的封装程度逐渐递增,都会自动将 update_ops 添加到tf.GraphKeys.UPDATE_OPS这个collection中。[TensorFlow踩坑指南]
2 tf.keras.layers.BatchNormalization 不会自动将 update_ops 添加到 tf.GraphKeys.UPDATE_OPS 这个 collection 中。所以在 TensorFlow 训练 session 中使用 tf.keras.layers.BatchNormalization 时,需要手动将 keras.BatchNormalization 层的 updates 添加到 tf.GraphKeys.UPDATE_OPS 中。[TensorFlow 中 Batch Normalization API 的一些坑]
[tensorflow中Batch Normalization的不同实现]
BN头号大坑:没有调用 update_ops
Batch Normalization 中需要计算移动平均值,所以 BN 中有一些 update_ops,在训练中需要通过 tf.control_dependencies() 来添加对 update_ops 的调用:
1update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
train_op = tf.train.AdamOptimizer(lrn_rate).minimize(cost)
在使用 update_ops 前,需要将 BN 层的 update_ops 添加到 tf.GraphKeys.UPDATE_OPS 这个 collection 中。
tf.layers.BatchNormalization 和 tf.layers.batch_normalization 会自动将 update_ops 添加到 tf.GraphKeys.UPDATE_OPS 这个 collection 中(注:training 参数为 True 时,才会添加,False 时不添加)。
检测是否添加了 updates 的方法:
print(tf.get_collection(tf.GraphKeys.UPDATE_OPS))
Note: 要生效,在优化时,都需要加(下面的所有示例没写出来)
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) with tf.control_dependencies(update_ops): self.train_op = layers.optimize_loss(self.loss, tf.train.get_global_step(), optimizer=self.optimizer, learning_rate=self.learning_rate, clip_gradients=self.clip_norm)
[TensorFlow 中 Batch Normalization API 的一些坑]
tensorflow Batch Normalization使用示例
示例1:高阶kpi,先定义再使用
self.bn_layers = [ tf.layers.BatchNormalization(name='bn' + str(i), trainable=self.is_training, _reuse=tf.AUTO_REUSE) for i in range(layers_cnt)] #_reuse=tf.AUTO_REUSE是用于再次定义(不是再次使用时)的参数共享,再次使用应该不需要此参数就是直接用的,参数当然一样 fc = self.bn_layers[i](fc, training=training)
Note: tf.keras.layers.BatchNormalization应该和这个差不多。
示例2:老版本示例,不太建议
import tensorflow.contrib.layers as layers x = layers.batch_norm( x, center=True, scale=True, reuse=tf.AUTO_REUSE, scope=scope, is_training=is_training )
BN中的变量
定义tf.layers.BatchNormalization后,
Trainable Variable:
<tf.Variable 'bn0/gamma:0' shape=(64,) dtype=float32_ref>
<tf.Variable 'bn0/beta:0' shape=(64,) dtype=float32_ref>
非Trainable的Global Variable:
<tf.Variable 'bn0/moving_mean:0' shape=(64,) dtype=float32_ref>
<tf.Variable 'bn0/moving_variance:0' shape=(64,) dtype=float32_ref>
[深度学习:批归一化和层归一化Batch Normalization、Layer Normalization]
L2正则化
tensorflow实现
示例1:
from tensorflow.python.keras.regularizers import l2 self.kernels = [self.add_weight(name='kernel' + str(i), shape=(hidden_units[i], hidden_units[i + 1]), initializer=glorot_normal(seed=self.seed), regularizer=l2(self.l2_reg), trainable=self.is_training, getter=tf.get_variable) for i in range(layers_cnt)] #self.bias不需要正则 self.reg_loss = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) self.reg_loss = tf.reduce_sum(self.reg_loss) self.loss = self.loss + self.reg_loss
示例2:
from tensorflow.contrib.layers.python.layers import regularizers x = layers.fully_connected( x, activation_fn=activation, num_outputs=out_size, weights_initializer=initializer_map.get(initializer)(), weights_regularizer=regularizers.l1_l2_regularizer(scale_l1=l1_reg, scale_l2=l2_reg), biases_initializer=init_ops.zeros_initializer(), scope=scope ) loss部分同示例1
示例3:
weight_decay=0.1 tmp=tf.constant([0,1,2,3],dtype=tf.float32) l2_reg=tf.contrib.layers.l2_regularizer(weight_decay) a=tf.get_variable("I_am_a",regularizer=l2_reg,initializer=tmp) #上面代码的等价代码 ''' a=tf.get_variable("I_am_a",initializer=tmp) a2=tf.reduce_sum(a*a)*weight_decay/2; tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,a2) ''' loss部分同示例1
等价代码的说明:
首先定义a变量:a=tf.get_variable("I_am_a",initializer=tmp)
然后将a进行正则化处理:a2=tf.reduce_sum(a*a)*weight_decay/2,最后将处理后的变量加入tf.GraphKeys.REGULARIZATION_LOSSES集合,所有经过正则化处理的变量都会加入这个集合:tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,a2)。
对变量执行完L2正则化后,利用tf.get_collection()函数将所有正则化后的变量取出来放入一个列表:keys = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES),将该列表中的值加起来,再加到loss上,就完成了整个正则化过程:l2_loss=loss + tf.add_n(keys)。
解释[Tensorflow中实现正则化]
Note: L2正则化的预处理数据是平方和除以2,这是方便处理加的一个系数,因为w平方求导之后会多出来一个系数2,有没有系数,优化过程都是一样进行的,减小a和减小10a是一样的训练目标。如果说正则化和主loss的比例不同,还有衰减系数可以调。
[tensorflow使用L2 regularization正则化修正overfitting过拟合]
L2正则化衰减系数
如 [Tensorflow中实现正则化]中的0.1
如 [tensorflow使用L2 regularization正则化修正overfitting过拟合]中的0.004
第一次尝试的话,lz一般设置成0.001
from: -柚子皮-
ref:
以上是关于Tensorflow:批归一化和l1l2正则化的主要内容,如果未能解决你的问题,请参考以下文章