介绍
Keras中的 层(layer) 通常用参数trainable来控制该层的 权重是否可以更新。
在使用 keras 预训练模型时,用模型的属性trainable来控制各个层的 权重是否可以更新。
但是,tf.keras.layers.BatchNormalization不受上面的控制,即:无法通过上面2种方式冻结bn层
引发的问题
keras预训练模型中,包含bn层的,都会发生 过拟合、验证集的准确率不变 等问题,如:ResNet系列
详见:
https://www.malaoshi.top/show_1EF5JUYBib4t.html
解决方法
方法1
通过Keras的K.learning_phase冻结bn层参数
函数解释参见:
https://www.malaoshi.top/show_1EF5JTbvJ50y.html
demo代码
import tensorflow.keras.backend as K
# 冻结bn层
K.set_learning_phase(0)
# 预训练模型代码
.....
# 解冻bn层
K.set_learning_phase(1)
x = layerNp1(...)(x)
x = tf.keras.layers.BatchNormalization(...)(x)
案例:
keras resnet50过拟合导致验证集准确率不变的解决方法
方法2
tf.keras.layers.BatchNormalization的参数training,控制归一化时用的是当前Batch的均值和方差(训练模式)还是移动均值和方差(测试模式)。
代码:
x = BatchNormalization()(y, training=False)
注意
keras的不同版本,可能bn层会有不同的行为,也就是说,不要一味的使用K.set_learning_phase冻结、解冻bn层
当发现过拟合,验证集准确率不变时,再用K.set_learning_phase(0)进行测试
感谢:
https://zhuanlan.zhihu.com/p/56225304