关于dice, miou, loss计算的细节

1. loss

两种方式:

1. 按batch等权平均:

python 复制代码
    for batch_idx, (inputs, target_masks) in enumerate(progress_bar):
        outputs = lora_model(**inputs)
        loss, loss_focal, loss_dice = process_outputs(outputs, target_masks)  # 此时得到的loss是一个batch内的平均loss
        ...
        epoch_loss += loss.item()

    avg_train_loss = epoch_loss / len(train_dataloader)

特点 :每个batch权重相同。 ----> 1. 如果data_loader的最后一个batch不满,那么这个batch对loss做出的贡献和其他满batch对loss做出的贡献是相同的。 2. 某些batch里有效像素/正样本特别少(比如很多 GT=0),但它仍占同等权重。

对第一个问题举个例子:

假设 batch_size=4,但最后一个 batch 只有 1 张:

  • Batch1(4张图)loss=0.10
  • Batch2(1张图)loss=1.00

loss=(0.10+1.00)/2=0.55

让只有1张图的 batch占了50%的权重。第二个问题同理。

2. 按样本数加权:

python 复制代码
sum_loss = 0.0
sum_n = 0
for ...:
    n = target_masks.size(0)   # batch size
    sum_loss += loss.item() * n
    sum_n += n
avg = sum_loss / sum_n

特点:每张图权重相同(样本级平均)。

按照上面的例子,计算出来的loss如下:

(0.10⋅4+1.00⋅1)/(4+1)=(0.4+1)/5=0.28

什么情况下二者可以认为近似相同

没有单独更小的batch: drop_last=True 或者 数据量刚好能整除 batch_size。

补充:在第一点提到"某些batch里有效像素/正样本特别少"的问题,要解决这个问题,loss计算需要考虑按有效像素数或正样本数加权(取决于loss归一化的方式),但这属于更高级的对齐问题,如果各个batch内的GT分布不是很极端,可以不考虑这种情况。

2. Dice 和 MIou

1. 关于Miou的说明

  • Iou_fg: 只算前景
  • mean over classes: 平均iou_fg和iou_bg
  • mean over images: 对每张图的iou的平均

2. 两种方法

A 使用混淆矩阵

  • Dice = (2TP/(2TP+FP+FN))
  • IoU = (TP/(TP+FP+FN))
python 复制代码
def _confusion_from_binary(pred01: np.ndarray, gt01: np.ndarray):
    """
    pred01, gt01: ndarray, values in {0,1}
    """
    pred = (pred01 > 0).astype(np.bool_)
    gt = (gt01 > 0).astype(np.bool_)

    tp = np.logical_and(pred, gt).sum(dtype=np.int64)
    fp = np.logical_and(pred, np.logical_not(gt)).sum(dtype=np.int64)
    fn = np.logical_and(np.logical_not(pred), gt).sum(dtype=np.int64)
    tn = np.logical_and(np.logical_not(pred), np.logical_not(gt)).sum(dtype=np.int64)
    return tp, fp, fn, tn

def dice_iou(pred: np.ndarray, gt: np.ndarray, eps: float = 1e-7):
    """
    pred, gt: ndarray shape (P, X, Y, Z), values {0,1}
    """
    pred=pred[0]
    gt=gt[0]

    tp, fp, fn, tn = _confusion_from_binary(pred, gt)

    dice = (2 * tp + eps) / (2 * tp + fp + fn + eps)
    iou = (tp + eps) / (tp + fp + fn + eps)

    return float(dice), float(iou)

B 用intersection/union推

  • intersection = sum(pred * gt)
  • union_dice = sum(pred) + sum(gt)
  • union_iou = sum(pred) + sum(gt) − intersection
python 复制代码
def compute_metrics(pred, target, smooth=1e-6):
    """
    pred:   [B,H,W] logits (NOT sigmoid)
    target: [B,H,W] 0/1

    empty_policy:(GT empty & Pred empty) => score=1, (GT empty & Pred non-empty) => score=0
    """
    prob = torch.sigmoid(pred).detach()
    pred_bin = (prob > 0.5).float()
    target = target.float()

    # flatten per image
    pred_f = pred_bin.flatten(1)
    tgt_f  = target.flatten(1)

    inter = (pred_f * tgt_f).sum(1)                # [B]
    pred_sum = pred_f.sum(1)                       # [B]
    tgt_sum  = tgt_f.sum(1)                        # [B]
    union_iou = pred_sum + tgt_sum - inter
    union_dice = pred_sum + tgt_sum

    iou = (inter + smooth) / (union_iou + smooth)
    dice = (2 * inter + smooth) / (union_dice + smooth)

    gt_empty = (tgt_sum == 0)
    pred_empty = (pred_sum == 0)

    # set empty-gt images score based on whether prediction is also empty
    iou = torch.where(gt_empty, pred_empty.float(), iou)
    dice = torch.where(gt_empty, pred_empty.float(), dice)
    return iou.mean().item(), dice.mean().item()

这两种在二值预测且同一阈值下是等价的。

3. 对谁求和

A micro

先把所有像素 (跨多张图/多batch)汇总TP/FP/FN,再算 Dice/IoU。适用于更关心整体像素表现(比如器官分割、前景占比相对稳定)的情况。
特点

  • 大目标/大图权重大,小目标权重小
  • 数值通常更"乐观",波动更小
  • Dice 和 IoU 的对应关系在同一汇总口径下是稳定的

对GT=0多的影响:空图如果预测也空,会贡献大量TN,但TN不进 Dice/IoU;空图对micro的影响相对间接。如果空图预测出 FP,会显著拉低。

B macro over images

每张图 先算一个 Dice/IoU,然后对图做平均。适用于更希望每个病例同等重要的情况。
特点

  • 每张图权重相同,小目标图不再被"淹没"
  • 对"哪些图失败了"更敏感
  • 通常比 micro 更低、更接近"最差情况"

对GT=0多的影响:如果要把空GT图也纳入平均,必须定义空图得分。

C macro over classes

定义 :分别算背景 IoU、前景 IoU,然后对类别平均。二分类时就是 (IoU_bg + IoU_fg)/2。适用于多分类语义分割,要求类别公平。
特点

  • 强制同时关注背景和前景
  • 但对分割来说很多时候"背景 IoU"意义不大

对GT=0多的影响:若某类在某张图里不存在,"是否计入该类 IoU"的策略会影响巨大(同样会出现空集问题)

4. GT=0如何处理

A perfect-empty

空图预测空给满分,空图有FP给0。目标是希望模型"遇到没有目标的图就不要分出东西"。但如果空图占比非常高,指标可能看起来很好。

B ignore-empty

空 GT 的图不计入前景IoU/Dice平均,适用于只想评估"有前景时分割得如何"。并且空图数量很多,担心指标被空图主导

C eps-approx

例如 (tp+eps)/(tp+fp+fn+eps)。当 tp=fp=fn=0 时会得到1,但当GT空且pred有少量FP时,会得到接近0。

相关推荐
老刘说AI1 小时前
WorkFlow Agent案例:auto_document_agent(文件自动处理)
开发语言·数据库·人工智能·python·神经网络·自然语言处理
AI成长日志2 小时前
【强化学习专栏】深度强化学习技术演进:DQN、PPO、SAC的架构设计与训练优化
人工智能·算法·架构
云烟成雨TD2 小时前
Spring AI 1.x 系列【15】AI Agent 基石:Tool Calling 标准与 Spring AI 集成
java·人工智能·spring
科学创新前沿2 小时前
逆向设计新范式:深度学习驱动的声学超材料智能优化!
人工智能·python·深度学习·声学·逆向设计·声学超材料
铮铭2 小时前
上海交大 RoboClaw VS EmbodiedAgentsSys 两个框架对比分析
人工智能·机器人·ai编程·具身智能·vla
rgb2gray2 小时前
论文详解:基于POI数据的城市功能区动态演化分析——以北京为例
人工智能·算法·机器学习·回归·gwr
不懂网络的坤坤2 小时前
2026中关村论坛AI主题日深度解读
人工智能
产业家2 小时前
“龙虾思想”背后:把AI战火正式推向软件层
人工智能
新缸中之脑2 小时前
将Autoresearch转化为通用技能
人工智能