关于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。

相关推荐
江畔柳前堤4 小时前
roLabelImg 详细安装教程
开发语言·人工智能·后端·云原生
阿里云大数据AI技术4 小时前
分链路差异化设计的DSP准实时数仓|钛动科技基于阿里云实时计算 Flink 版 + DLF Paimon + EMR Serverless StarRocks 的实践
人工智能·flink
陕西企来客4 小时前
2026年7月AI智能搜索曝光趋势研判
大数据·人工智能·机器学习·ai智能搜索曝光
阿里云大数据AI技术4 小时前
从算力到智能体,面向 Agentic AI 的基础设施演进
人工智能·agent
hangyuekejiGEO5 小时前
GEO技术服务选型指南
大数据·人工智能·python
阿里云大数据AI技术5 小时前
EMR Serverless Spark AI Function 的双维降本实践
人工智能·sql·spark
维基框架6 小时前
GitHub源码处理提速 一趟扫描反而更慢
人工智能·github
冬奇Lab6 小时前
代码库知识库系列(05):向量检索 vs 知识图谱——加了调用图并没有变更好
人工智能
AKAMAI6 小时前
你的源服务器可能是你做出的最昂贵决定
运维·人工智能·云计算
冬奇Lab6 小时前
【无标题】
人工智能·开源