在不少關於醫學圖像分割的競賽、論文和項目中,發現 Dice 係數(Dice coefficient) 損失函數出現的頻率較多,這裏整理一下。使用圖像分割,繞不開Dice損失,這個就比如在目標檢測中繞不開IoU同樣。python
1 概述
Dice損失和Dice係數(Dice coefficient)是同一個東西,他們的關係是:網絡
DiceLoss=1−DiceCoefficientDiceLoss = 1-DiceCoefficientDiceLoss=1−DiceCoefficient機器學習
1.2 Dice 定義
- Dice係數, 根據 Lee Raymond Dice命名,是一種集合類似度度量函數,一般用於計算兩個樣本的類似度(值範圍爲 [0, 1])。
DiceCoefficient=2∣X⋂Y∣∣X∣+∣Y∣DiceCoefficient = \frac{2|X \bigcap Y|}{|X| + |Y|}DiceCoefficient=∣X∣+∣Y∣2∣X⋂Y∣函數
其中∣X∣⋂∣Y∣|X| \bigcap |Y|∣X∣⋂∣Y∣表示X和Y集合的交集,|X|和|Y|表示其元素個數,對於分割任務而言,|X|和|Y|表示分割的ground truth和predict_mask。學習
此外,咱們能夠獲得Dice Loss的公式:this
DiceLoss=1−2∣X⋂Y∣∣X∣+∣Y∣DiceLoss = 1- \frac{2|X \bigcap Y|}{|X| + |Y|}DiceLoss=1−∣X∣+∣Y∣2∣X⋂Y∣url
2 手推案例
這個Dice網上有一個很是好二分類的Dice Loss的手推的案例,很是好理解,過程分紅兩個部分:spa
- 先計算∣X∣⋂∣Y∣|X|\bigcap|Y|∣X∣⋂∣Y∣
- 再計算∣X∣|X|∣X∣和∣Y∣|Y|∣Y∣
計算loss咱們必然已經有了這兩個參數,模型給出的output,也就是預測的mask;數據集中的ground truth(GT),也就是真實的mask。.net
在不少關於醫學圖像分割的競賽、論文和項目中,發現 Dice 係數(Dice coefficient) 損失函數出現的頻率較多,這裏整理一下。使用圖像分割,繞不開Dice損失,這個就比如在目標檢測中繞不開IoU同樣。code
1 概述
Dice損失和Dice係數(Dice coefficient)是同一個東西,他們的關係是:
DiceLoss=1−DiceCoefficientDiceLoss = 1-DiceCoefficientDiceLoss=1−DiceCoefficient
1.2 Dice 定義
- Dice係數, 根據 Lee Raymond Dice命名,是一種集合類似度度量函數,一般用於計算兩個樣本的類似度(值範圍爲 [0, 1])。
DiceCoefficient=2∣X⋂Y∣∣X∣+∣Y∣DiceCoefficient = \frac{2|X \bigcap Y|}{|X| + |Y|}DiceCoefficient=∣X∣+∣Y∣2∣X⋂Y∣
其中∣X∣⋂∣Y∣|X| \bigcap |Y|∣X∣⋂∣Y∣表示X和Y集合的交集,|X|和|Y|表示其元素個數,對於分割任務而言,|X|和|Y|表示分割的ground truth和predict_mask。
此外,咱們能夠獲得Dice Loss的公式:
DiceLoss=1−2∣X⋂Y∣∣X∣+∣Y∣DiceLoss = 1- \frac{2|X \bigcap Y|}{|X| + |Y|}DiceLoss=1−∣X∣+∣Y∣2∣X⋂Y∣
2 手推案例
這個Dice網上有一個很是好二分類的Dice Loss的手推的案例,很是好理解,過程分紅兩個部分:
- 先計算∣X∣⋂∣Y∣|X|\bigcap|Y|∣X∣⋂∣Y∣
- 再計算∣X∣|X|∣X∣和∣Y∣|Y|∣Y∣
計算loss咱們必然已經有了這兩個參數,模型給出的output,也就是預測的mask;數據集中的ground truth(GT),也就是真實的mask。
固然還沒完,還要把結果加和:
對於二分類問題,GT分割圖是隻有 0, 1 兩個值的,所以能夠有效的將在 Pred 分割圖中未在 GT 分割圖中激活的全部像素清零. 對於激活的像素,主要是懲罰低置信度的預測,較高值會獲得更好的 Dice 係數.
關於計算∣X∣|X|∣X∣和∣Y∣|Y|∣Y∣,以下:
其中須要注意的是,一半狀況下,這個是直接對全部元素求和,固然有對全部元素先平方再求和的作法。總之就這麼多,很是的簡單好用。不過上面的內容是針對分割二分類的狀況,對於多分類的狀況和二分類基本相同。
3 二分類代碼實現
在實現的時候,每每會加上一個smooth,防止分母爲0的狀況出現。因此公式變成:
DiceLoss=1−2∣X⋂Y∣+smooth∣X∣+∣Y∣+smoothDiceLoss = 1- \frac{2|X \bigcap Y|+smooth}{|X| + |Y|+smooth}DiceLoss=1−∣X∣+∣Y∣+smooth2∣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=TPTP+FP+FNIoU = \frac{TP}{TP+FP+FN}IoU=TP+FP+FNTP
Dice的算式,結合咱們以前講的內容,能夠推導出,∣X∣⋂∣Y∣|X|\bigcap|Y|∣X∣⋂∣Y∣就是TP,∣X∣|X|∣X∣假設是GT的話就是FN+TP,∣Y∣|Y|∣Y∣假設是預測的mask,就是TP+FP,因此:
Dicecoefficient=2×TPTP+FN+TP+FPDice_coefficient = \frac{2\times TP}{TP+FN + TP + FP}Dicecoefficient=TP+FN+TP+FP2×TP
因此咱們能夠獲得Dice和IoU之間的關係了,這裏的以後的Dice默認表示Dice Coefficient:
IoU=Dice2−DiceIoU = \frac{Dice}{2-Dice}IoU=2−DiceDice
這個函數圖像以下圖,咱們只關注0~1這個區間就行了,能夠發現:
- IoU和Dice同時爲0,同時爲1;這很好理解,就是全預測正確和所有預測錯誤
- 假設在相同的預測狀況下,能夠發現Dice給出的評價會比IoU高一些,哈哈哈。因此Dice的數據會更加好看一些。