本文包含代码案例和讲解,建议收藏,也顺便点个赞吧。欢迎各路朋友爱好者加我的微信讨论问题:cyx645016617.

在很多关于医学图像分割的竞赛、论文和项目中,发现 Dice 系数(Dice coefficient) 损失函数出现的频率较多,这里整理一下。使用图像分割,绕不开Dice损失,这个就好比在目标检测中绕不开IoU一样

1 概述

Dice损失和Dice系数(Dice coefficient)是同一个东西,他们的关系是:

\[DiceLoss = 1-DiceCoefficient
\]

1.2 Dice 定义

  • Dice系数, 根据 Lee Raymond Dice命名,是一种集合相似度度量函数,通常用于计算两个样本的相似度(值范围为 [0, 1])。
\[DiceCoefficient = \frac{2|X \bigcap Y|}{|X| + |Y|}
\]

其中\(|X| \bigcap |Y|\)表示X和Y集合的交集,|X|和|Y|表示其元素个数,对于分割任务而言,|X|和|Y|表示分割的ground truth和predict_mask

此外,我们可以得到Dice Loss的公式:

\[DiceLoss = 1- \frac{2|X \bigcap Y|}{|X| + |Y|}
\]

2 手推案例

这个Dice网上有一个非常好二分类的Dice Loss的手推的案例,非常好理解,过程分成两个部分:

  1. 先计算\(|X|\bigcap|Y|\)
  2. 再计算\(|X|\)和\(|Y|\)

    计算loss我们必然已经有了这两个参数,模型给出的output,也就是预测的mask;数据集中的ground truth(GT),也就是真实的mask。

在很多关于医学图像分割的竞赛、论文和项目中,发现 Dice 系数(Dice coefficient) 损失函数出现的频率较多,这里整理一下。使用图像分割,绕不开Dice损失,这个就好比在目标检测中绕不开IoU一样

1 概述

Dice损失和Dice系数(Dice coefficient)是同一个东西,他们的关系是:

\[DiceLoss = 1-DiceCoefficient
\]

1.2 Dice 定义

  • Dice系数, 根据 Lee Raymond Dice命名,是一种集合相似度度量函数,通常用于计算两个样本的相似度(值范围为 [0, 1])。
\[DiceCoefficient = \frac{2|X \bigcap Y|}{|X| + |Y|}
\]

其中\(|X| \bigcap |Y|\)表示X和Y集合的交集,|X|和|Y|表示其元素个数,对于分割任务而言,|X|和|Y|表示分割的ground truth和predict_mask

此外,我们可以得到Dice Loss的公式:

\[DiceLoss = 1- \frac{2|X \bigcap Y|}{|X| + |Y|}
\]

2 手推案例

这个Dice网上有一个非常好二分类的Dice Loss的手推的案例,非常好理解,过程分成两个部分:

  1. 先计算\(|X|\bigcap|Y|\)
  2. 再计算\(|X|\)和\(|Y|\)

    计算loss我们必然已经有了这两个参数,模型给出的output,也就是预测的mask;数据集中的ground truth(GT),也就是真实的mask。

当然还没完,还要把结果加和:

对于二分类问题,GT分割图是只有 0, 1 两个值的,因此可以有效的将在 Pred 分割图中未在 GT 分割图中激活的所有像素清零. 对于激活的像素,主要是惩罚低置信度的预测,较高值会得到更好的 Dice 系数.

关于计算\(|X|\)和\(|Y|\),如下:

其中需要注意的是,一半情况下,这个是直接对所有元素求和,当然有对所有元素先平方再求和的做法。总之就这么多,非常的简单好用。不过上面的内容是针对分割二分类的情况,对于多分类的情况和二分类基本相同

3 二分类代码实现

在实现的时候,往往会加上一个smooth,防止分母为0的情况出现。所以公式变成:

\[DiceLoss = 1- \frac{2|X \bigcap Y|+smooth}{|X| + |Y|+smooth}
\]

一般smooth为1

3.1 PyTorch实现

先是dice coefficient的实现,pred和target的shape为【batch_size,channels,...】,2D和3D的都可以用这个。

def dice_coeff(pred, target):
smooth = 1.
num = pred.size(0)
m1 = pred.view(num, -1) # Flatten
m2 = target.view(num, -1) # Flatten
intersection = (m1 * m2).sum() return (2. * intersection + smooth) / (m1.sum() + m2.sum() + smooth)

当然dice loss就是1-dice ceofficient,所以可以写成:

def dice_coeff(pred, target):
smooth = 1.
num = pred.size(0)
m1 = pred.view(num, -1) # Flatten
m2 = target.view(num, -1) # Flatten
intersection = (m1 * m2).sum() return 1-(2. * intersection + smooth) / (m1.sum() + m2.sum() + smooth)

3.2 keras实现

smooth = 1. # 用于防止分母为0.
def dice_coef(y_true, y_pred):
y_true_f = K.flatten(y_true) # 将 y_true 拉伸为一维.
y_pred_f = K.flatten(y_pred)
intersection = K.sum(y_true_f * y_pred_f)
return (2. * intersection + smooth) / (K.sum(y_true_f * y_true_f) + K.sum(y_pred_f * y_pred_f) + smooth) def dice_coef_loss(y_true, y_pred):
return 1. - dice_coef(y_true, y_pred)

3.3 tensorflow实现

def dice_coe(output, target, loss_type='jaccard', axis=(1, 2, 3), smooth=1e-5):
"""
Soft dice (Sørensen or Jaccard) coefficient for comparing the similarity of two batch of data,
usually be used for binary image segmentation
i.e. labels are binary.
The coefficient between 0 to 1, 1 means totally match. Parameters
-----------
output : Tensor
A distribution with shape: [batch_size, ....], (any dimensions).
target : Tensor
The target distribution, format the same with `output`.
loss_type : str
``jaccard`` or ``sorensen``, default is ``jaccard``.
axis : tuple of int
All dimensions are reduced, default ``[1,2,3]``.
smooth : float
This small value will be added to the numerator and denominator.
- If both output and target are empty, it makes sure dice is 1.
- If either output or target are empty (all pixels are background), dice = ```smooth/(small_value + smooth)``, then if smooth is very small, dice close to 0 (even the image values lower than the threshold), so in this case, higher smooth can have a higher dice. Examples
---------
>>> outputs = tl.act.pixel_wise_softmax(network.outputs)
>>> dice_loss = 1 - tl.cost.dice_coe(outputs, y_) References
-----------
- `Wiki-Dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`__ """
inse = tf.reduce_sum(output * target, axis=axis)
if loss_type == 'jaccard':
l = tf.reduce_sum(output * output, axis=axis)
r = tf.reduce_sum(target * target, axis=axis)
elif loss_type == 'sorensen':
l = tf.reduce_sum(output, axis=axis)
r = tf.reduce_sum(target, axis=axis)
else:
raise Exception("Unknow loss_type")
dice = (2. * inse + smooth) / (l + r + smooth)
dice = tf.reduce_mean(dice)
return dice

4 多分类

假设是一个10分类的任务,那么我们应该会有一个这样的模型预测结果:[batch_size,10,width,height],然后我们的ground truth需要改成one hot的形式,也变成[batch_size,10,width,height]。剩下的和二分类的代码基本相同了,先ground truth和预测结果对应元素相乘,然后对相乘的结果求和。就是最后需要对每一个类别和每一个样本都求一次平均就行了。

5 深入探讨Dice,IoU



上图就是我们常见的IoU方法,假设分子的两个集合,一个集合是Ground Truth,另外一个集合是神经网络给出的预测值。不要被图中的正方形的形状限制了想想,对于分割任务来说,一般是像素级的不规则图案

如果预测正确,也就是分子中的蓝色交汇的部分,称之为True Positive,属于True Positive的像素的数量就是分子的值。分母的值是Ground Truth的所有像素的数量和预测结果中所有像素的数量的和再减去重叠的部分的像素数量。

直接学过recall,precision,混淆矩阵,f1score的朋友一定对FN,TP,TN,FP这些不陌生:

  • 黄色区域:预测为negative,但是GT中是positive的False Negative区域;
  • 红色区域:预测为positive,但是GT中是Negative的False positive区域;

对于IoU的预测好坏的直观理解就是:



简单的说就是,重叠的越多,IoU越接近1,预测效果越好

现在让我们更好的从IoU过渡到Dice,我们先把IoU的算式写出来:

\[IoU = \frac{TP}{TP+FP+FN}
\]

Dice的算式,结合我们之前讲的内容,可以推导出,\(|X|\bigcap|Y|\)就是TP,\(|X|\)假设是GT的话就是FN+TP,\(|Y|\)假设是预测的mask,就是TP+FP,所以:

\[Dice_coefficient = \frac{2\times TP}{TP+FN + TP + FP}
\]

所以我们可以得到Dice和IoU之间的关系了,这里的之后的Dice默认表示Dice Coefficient

\[IoU = \frac{Dice}{2-Dice}
\]

这个函数图像如下图,我们只关注0~1这个区间就好了,可以发现:

  • IoU和Dice同时为0,同时为1;这很好理解,就是全预测正确和全部预测错误
  • 假设在相同的预测情况下,可以发现Dice给出的评价会比IoU高一些,哈哈哈。所以Dice的数据会更加好看一些。

参考文章:

  1. https://www.aiuai.cn/aifarm1159.html
  2. https://blog.csdn.net/py184473894/article/details/90383618

图像分割必备知识点 | Dice损失 理论+代码的更多相关文章

  1. 图像分割必备知识点 | Unet详解 理论+ 代码

    文章转自:微信公众号[机器学习炼丹术].文章转载或者交流联系作者微信:cyx645016617 喜欢的话可以参与文中的讨论.在文章末尾点赞.在看点一下呗. 0 概述 语义分割(Semantic Seg ...

  2. 图像分割必备知识点 | Unet++超详解+注解

    文章来自周纵苇大佬的知乎,是Unet++模型的一作大佬,其在2019年底详细剖析了Unet++模型,讲解的非常好.所以在此做一个搬运+个人的理解. 文中加粗部分为个人做的注解.需要讨论交流的朋友可以加 ...

  3. Hybrid App 应用开发中 9 个必备知识点复习(WebView / 调试 等)

    前言 我们大前端团队内部 ?每周一练 的知识复习计划继续加油,本篇文章是 <Hybrid APP 混合应用专题> 主题的第二期和第三期的合集. 这一期共整理了 10 个问题,和相应的参考答 ...

  4. Web前端-CSS必备知识点

    Web前端-CSS必备知识点 css基本内容,类选择符,id选择符,伪类,伪元素,结构,继承,特殊性,层叠,元素分类,颜色,长度,url,文本,字体,边框,块级元素,浮动元素,内联元素,定位. 链接: ...

  5. 软件测试就业必备知识点&自学软件测试-Dotest-2019

    软件测试就业必备知识点&自学测试&教学大纲-Dotest-2019

  6. ASP.NET MVC开发:Web项目开发必备知识点

    最近加班加点完成一个Web项目,使用Asp.net MVC开发.很久以前接触的Asp.net开发还是Aspx形式,什么Razor引擎,什么MVC还是这次开发才明白,可以算是新手. 对新手而言,那进行A ...

  7. Microsoft Dynamics CRM2011 必备知识点

    一.CRM基本知识 1.CRM2001 有几个服务端点? 答:对外公开的服务,如Web服务,WCF,Restful API 2.一个ERP系统,要访问CRM的数据,CRM2011有哪些现有的服务入口提 ...

  8. 使用html5中video自定义播放器必备知识点总结以及JS全屏API介绍

    一.video的js知识点: controls(控制器).autoplay(自动播放).loop(循环)==video默认的: 自定义播放器中一些JS中提供的方法和属性的记录: 1.play()控制视 ...

  9. MVC中权限的知识点及具体实现代码

    一:知识点部分 权限是做网页经常要涉及到的一个知识点,在使用MVC做权限设计时需要先了解以下知识: MVC中Url的执行是按照Controller->Action->View页面,但是我们 ...

随机推荐

  1. C++学习---队列的构建及操作

    一.循环队列 #include <iostream> using namespace std; #define MAXQSIZE 100 typedef struct { int* bas ...

  2. redis过期事件,swoole监听

    $serv = new Swoole\Server('0.0.0.0', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP); $serv->set(array( 'work ...

  3. Cocos2d-x extensions库使用问题解决方法

    需要在加入头文件#include "cocos-ext.h" 1>e:\cocos\cocos2d-x\cocos2d-x-3.10\extensions\gui\cccon ...

  4. viewpage轮播图

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com ...

  5. JQuery如何实现统计图表

    EEP JQuery如何实现统计图表 讯光科技 前言 在ERP项目开发过程中,统计图表(chart)普遍应用于各种统计和报表中,其形象直观,内容清晰.EEP的JQuery网站项目使用了Easyui 插 ...

  6. hello world .net core 微服务框架 Viper

    1.Viper是什么? Viper 是.NET平台下的Anno微服务框架的一个示例项目.入门简单.安全.稳定.高可用.全平台可监控.底层通讯可以随意切换thrift grpc. 自带服务发现.调用链追 ...

  7. SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂)

    SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂) 在实际开发过程中,经常会碰见一些比如系统启动初始化信息.统计在线人数.在线用户数.过滤敏/高词汇.访问权限控制(URL级别 ...

  8. Java中的(String args[])

    1. DOS下运行 首先,String args[] 这个形式可以直接看出它就是一个字符串数组充当main函数形式参数,args是arguments的缩写,不是关键字(就是一个数组名),可以改但没必要 ...

  9. 如何将别人Google云端硬盘中的数据进行保存

    查了好久终于知道! 如何将别人Google云端硬盘中的数据进行copy,而不是右键发现只有添加快捷方式 只要shift+z就可以保存了! 之后等我弄清楚怎么将别人家的云盘中的数据集导到colab再来详 ...

  10. 【SpringCloud】04.SpringCloud Eureka Server与Client的创建

    Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的.SpringCloud将它集成在其子项 ...