You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用smp.Unet配置aux_params时出现AttributeError: 'tuple'无size属性

问题:smp.Unet添加aux_params后触发AttributeError: 'tuple' object has no attribute 'size'

错误现象

使用segmentation_models_pytorch(简称smp)的Unet模型并传入aux_params参数后,训练时出现如下错误:

File .../python3.11/site-packages/segmentation_models_pytorch/utils/train.py:51, in Epoch.run(self, dataloader)
     49 for x, y in iterator:
     50     x, y = x.to(self.device), y.to(self.device)
---> 51     loss, y_pred = self.batch_update(x, y)
     53     # update loss logs
     54     loss_value = loss.cpu().detach().numpy()
...
-> 3162 if not (target.size() == input.size()):
   3163     raise ValueError("Target size ({}) must be the same as input size ({})".format(target.size(), input.size()))
   3165 return torch.binary_cross_entropy_with_logits(input, target, weight, pos_weight, reduction_enum)
File ".../train_model.py", line 153, in train
    train_logs = self.train_epoch.run(self.train_loader)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../train_model.py", line 173, in main
    water_seg_model.train(epoch_number=100)
  File ".../train_model.py", line 176, in <module>
    main()
AttributeError: 'tuple' object has no attribute 'size'

错误原因

当给smp.Unet传入aux_params时,模型的输出不再是单个张量,而是元组(主分割输出, 辅助分类输出)。但默认的smp.utils.train.TrainEpoch和损失函数只会处理单个输出张量,直接将元组传入损失函数时,损失函数会尝试调用tuple.size()方法,而元组没有这个属性,因此触发错误。

解决方法

需要自定义损失函数来处理模型的双输出,同时调整指标计算逻辑只针对主分割输出:

1. 自定义组合损失函数

编写损失函数,拆分模型输出的元组,分别计算主损失和辅助损失后加权求和:

def combined_loss(y_pred, y_true):
    # 拆分模型输出:主分割输出、辅助分支输出
    main_output, aux_output = y_pred
    # 计算主分割任务损失
    main_loss = smp.losses.SoftBCEWithLogitsLoss()(main_output, y_true)
    # 计算辅助分支损失(若辅助分支是全局分类,需调整目标格式适配输出尺寸)
    aux_loss = smp.losses.SoftBCEWithLogitsLoss()(aux_output, y_true)
    # 加权求和,辅助损失权重可根据需求调整
    return main_loss + 0.3 * aux_loss

# 给损失函数命名,方便TrainEpoch记录训练日志
combined_loss.__name__ = 'CombinedLoss'

2. 自定义指标处理逻辑

默认指标会接收模型的元组输出,需要修改指标只使用主分割输出计算:

class CustomIoU(smp.utils.metrics.IoU):
    def __call__(self, y_pred, y_true):
        # 只取主分割输出计算IoU指标
        main_output, _ = y_pred
        return super().__call__(main_output, y_true)

3. 更新模型初始化代码

将自定义的损失和指标替换原有的配置:

class SegmentationModel():
    def __init__(self):
        # ... 原有模型初始化代码保持不变 ...
        
        # 替换为自定义组合损失
        self.loss = combined_loss
        
        # 替换为自定义IoU指标
        self.metrics = [
            CustomIoU(threshold=THRESHOLD),
        ]
        
        # ... 其余代码保持不变 ...

补充说明

如果辅助分支是全局分类任务(而非与主输出同尺寸的分割),还需要修改数据集返回的目标,添加全局分类标签,或者调整辅助损失的计算逻辑适配输出尺寸。


内容的提问来源于stack exchange,提问作者Tema Sysoev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:01:10