如何为Keras下Segmentation_Models的ResNet34 U-Net添加Dropout层
错误原因
你遇到的AttributeError: 'KerasTensor' object has no attribute 'output'报错根源在于:循环第一次执行后,updated_model_layers已经变成Keras张量对象,不再是Keras层对象,没有output属性。除此之外你的实现逻辑还有一个更严重的问题:直接按顺序遍历模型层会完全丢失UNet的跳跃连接结构,最终生成的模型和原UNet结构完全不符,无法正常使用。
可行解决方案
import tensorflow as tf from tensorflow.keras.layers import Dropout from tensorflow.keras.models import Model import segmentation_models as sm # 配置参数 uncertain = True dropout_rate = 0.1 # 需要插入Dropout的卷积层名称 target_layers = ['decoder_stage0b_conv', 'decoder_stage0a_conv', 'decoder_stage1a_conv', 'decoder_stage1b_conv', 'decoder_stage2a_conv', 'decoder_stage2b_conv', 'decoder_stage3a_conv', 'decoder_stage3b_conv', 'decoder_stage4a_conv'] # 创建原模型 model = sm.Unet('resnet34', classes=1, activation='sigmoid', encoder_weights='imagenet') # 构建层输出映射字典 layer_outputs = {} # 按依赖关系遍历所有层重算输出 for layer in model.layers: # 获取当前层的输入张量 if isinstance(layer.input, list): inputs = [layer_outputs[inp.name] if inp.name in layer_outputs else inp for inp in layer.input] else: inputs = layer_outputs[layer.input.name] if layer.input.name in layer_outputs else layer.input # 计算当前层输出 cur_output = layer(inputs) # 目标卷积层后插入Dropout if layer.name in target_layers: if uncertain: # 推理阶段也开启Dropout用于不确定性估计 cur_output = Dropout(dropout_rate)(cur_output, training=True) else: cur_output = Dropout(dropout_rate)(cur_output) # 保存输出到映射字典 layer_outputs[layer.output.name] = cur_output # 构建新模型 new_model = Model(inputs=model.inputs, outputs=layer_outputs[model.output.name]) # 编译模型 optim = tf.keras.optimizers.Adam(0.001) total_loss = sm.losses.binary_focal_dice_loss metrics = ['accuracy', sm.metrics.IOUScore(threshold=0.5), sm.metrics.FScore(threshold=0.5)] new_model.compile(optimizer=optim, loss=total_loss, metrics=metrics)
关键说明
- 本方案通过层输出映射的方式完整保留了原UNet的跳跃连接结构,不会破坏原有特征传递逻辑
- 当
uncertain参数设为True时,Dropout层在推理阶段也会保持开启。做不确定性估计时,你只需要对同一个输入执行多次前向推理,计算多次输出结果的方差即可得到对应预测的不确定性 - 如果你只需要Dropout做训练正则化,不需要推理阶段开启,将
uncertain设为False即可
内容的提问来源于stack exchange,提问作者jwandscheer
相关产品推荐
相关产品推荐

