Keras迁移学习中如何给Xception的BatchNorm层设training=False且不改动模型结构
解决方法
首先明确两个容易混淆的参数区别:
trainable:控制层的权重是否在训练过程中更新training:控制层在前向传播时使用训练模式还是推理模式的逻辑,BatchNorm层的这个参数直接决定用批次统计量还是预训练的移动均值/方差
你现有代码里首先存在语法错误:循环中的bn_layer.trainable=False引用了未定义变量,直接删掉即可。
接下来直接在遍历baseModel层的逻辑里加BatchNorm层的特殊处理就行,不需要调整你现有模型的整体构建逻辑,不会把Xception打包成单个层:
from tensorflow.keras.layers import BatchNormalization def build_model(): # 加载ImageNet预训练权重的Xception模型 baseModel = Xception(weights= 'imagenet', include_top = False, input_shape=(224, 224, 3)) for layer in baseModel.layers: layer.trainable = False # 仅对BatchNorm层做特殊设置 if isinstance(layer, BatchNormalization): layer.trainable = False # 核心设置:强制该层始终运行在推理模式 layer.training = False headModel = baseModel.output headModel = Flatten()(headModel) headModel = Dense(64,activation="LeakyReLU")(headModel) headModel = Dropout(0.5)(headModel) headModel = Dense(32,activation="LeakyReLU")(headModel) headModel = Dropout(0.4)(headModel) headModel = Dense(16, activation="LeakyReLU")(headModel) headModel = Dropout(0.3)(headModel) headModel = Dense(8, activation="LeakyReLU")(headModel) headModel = Dropout(0.2)(headModel) headModel = Dense(3, activation="softmax")(headModel) x = Model(baseModel.inputs, outputs=headModel) optimizers = Adam(learning_rate=0.001) x.compile(loss = 'categorical_crossentropy', optimizer = optimizers, metrics = ['accuracy']) return x x = build_model() x.summary()
效果验证
- 运行
summary()仍然会展示Xception的所有内部层级,不会将其合并为单个层 - Grad-CAM可以正常获取Xception内部层的输出计算梯度,不受影响
- BatchNorm层在训练全程都会使用预训练得到的移动均值和方差,不会用当前批次的统计量更新
如果后续需要解冻部分层做微调,只需要调整遍历条件,仅把需要解冻的非BatchNorm层的trainable设为True,BatchNorm层保持training=False和trainable=False即可。
内容的提问来源于stack exchange,提问作者TensorMind
相关产品推荐
相关产品推荐

