Skip to content

Commit 84761f3

Browse files
committed
Update Soft/Hard Dice and IoU
1 parent 7f18518 commit 84761f3

File tree

1 file changed

+62
-30
lines changed

1 file changed

+62
-30
lines changed

tensorlayer/cost.py

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -121,43 +121,52 @@ def normalized_mean_square_error(output, target):
121121
return nmse
122122

123123

124-
def dice_coe(output, target, epsilon=1e-10):
125-
"""Sørensen–Dice coefficient for comparing the similarity of two distributions,
126-
usually be used for binary image segmentation i.e. labels are binary.
127-
The coefficient = [0, 1], 1 if totally match.
124+
def dice_coe(output, target, loss_type='jaccard', epsilon=1e-10):
125+
"""Soft dice (Sørensen or Jaccard) coefficient for comparing the similarity
126+
of two distributions, usually be used for binary image segmentation
127+
i.e. labels are binary. The coefficient in [0, 1], 1 means totally match.
128128
129129
Parameters
130130
-----------
131131
output : tensor
132132
A distribution with shape: [batch_size, ....], (any dimensions).
133133
target : tensor
134134
A distribution with shape: [batch_size, ....], (any dimensions).
135+
loss_type : string
136+
``jaccard`` or ``sorensen``, default is ``jaccard``.
135137
epsilon : float
136-
An optional name to attach to this layer.
138+
An small value be added to the numerator and denominator.
137139
138140
Examples
139141
---------
140142
>>> outputs = tl.act.pixel_wise_softmax(network.outputs)
141-
>>> dice_loss = 1 - tl.cost.dice_coe(outputs, y_, epsilon=1e-5)
143+
>>> dice_loss = 1 - tl.cost.dice_coe(outputs, y_)
142144
143145
References
144146
-----------
145-
- `wiki-dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_
147+
- `Wiki-Dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_
146148
"""
147149
# inse = tf.reduce_sum( tf.mul(output, target) )
148150
# l = tf.reduce_sum( tf.mul(output, output) )
149151
# r = tf.reduce_sum( tf.mul(target, target) )
150152
inse = tf.reduce_sum( output * target )
151-
l = tf.reduce_sum( output * output )
152-
r = tf.reduce_sum( target * target )
153-
dice = 2 * (inse) / (l + r)
154-
if epsilon == 0:
155-
return dice
153+
if loss_type == 'jaccard':
154+
l = tf.reduce_sum( output * output )
155+
r = tf.reduce_sum( target * target )
156+
elif loss_type == 'sorensen':
157+
l = tf.reduce_sum( output )
158+
r = tf.reduce_sum( target )
156159
else:
157-
return tf.clip_by_value(dice, 0, 1.0-epsilon)
158-
159-
160-
def dice_hard_coe(output, target, epsilon=1e-10):
160+
raise Exception("Unknow loss_type")
161+
dice = (2.*inse + epsilon) / (l + r + epsilon) # if both output and target are empty, dice is 1
162+
return dice
163+
# dice = 2 * (inse) / (l + r)
164+
# if epsilon == 0:
165+
# return dice
166+
# else:
167+
# return tf.clip_by_value(dice, 0, 1.0-epsilon)
168+
169+
def dice_hard_coe(output, target, threshold=0.5, epsilon=1e-10):
161170
"""Non-differentiable Sørensen–Dice coefficient for comparing the similarity of two distributions,
162171
usually be used for binary image segmentation i.e. labels are binary.
163172
The coefficient = [0, 1], 1 if totally match.
@@ -168,8 +177,10 @@ def dice_hard_coe(output, target, epsilon=1e-10):
168177
A distribution with shape: [batch_size, ....], (any dimensions).
169178
target : tensor
170179
A distribution with shape: [batch_size, ....], (any dimensions).
180+
threshold : float
181+
The threshold value to be true.
171182
epsilon : float
172-
An optional name to attach to this layer.
183+
An small value be added to the numerator and denominator.
173184
174185
Examples
175186
---------
@@ -178,21 +189,26 @@ def dice_hard_coe(output, target, epsilon=1e-10):
178189
179190
References
180191
-----------
181-
- `wiki-dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_
192+
- `Wiki-Dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_
182193
"""
183-
output = tf.cast(output > 0.5, dtype=tf.float32)
184-
target = tf.cast(target > 0.5, dtype=tf.float32)
194+
output = tf.cast(output > threshold, dtype=tf.float32)
195+
target = tf.cast(target > threshold, dtype=tf.float32)
185196
inse = tf.reduce_sum( output * target )
186-
l = tf.reduce_sum( output * output )
187-
r = tf.reduce_sum( target * target )
188-
dice = 2 * (inse) / (l + r)
189-
if epsilon == 0:
190-
return dice
191-
else:
192-
return tf.clip_by_value(dice, 0, 1.0-epsilon)
197+
l = tf.reduce_sum( output )
198+
r = tf.reduce_sum( target )
199+
# l = tf.reduce_sum( output * output )
200+
# r = tf.reduce_sum( target * target )
201+
dice = (2. * inse + epsilon) / (l + r + epsilon) # if both output and target are empty, it is 1
202+
return dice
203+
# dice = 2 * (inse) / (l + r)
204+
# if epsilon == 0:
205+
# return dice
206+
# else:
207+
# return tf.clip_by_value(dice, 0, 1.0-epsilon)
193208

194209
def iou_coe(output, target, threshold=0.5, epsilon=1e-10):
195-
"""Non-differentiable Intersection over Union, usually be used for evaluating binary image segmentation.
210+
"""Non-differentiable Intersection over Union, usually be used for
211+
evaluating binary image segmentation.
196212
The coefficient = [0, 1], 1 means totally match.
197213
198214
Parameters
@@ -204,7 +220,7 @@ def iou_coe(output, target, threshold=0.5, epsilon=1e-10):
204220
threshold : float
205221
The threshold value to be true.
206222
epsilon : float
207-
A small value to avoid zero denominator when both output and target output nothing.
223+
An small value be added to the numerator and denominator.
208224
209225
Examples
210226
---------
@@ -219,7 +235,23 @@ def iou_coe(output, target, threshold=0.5, epsilon=1e-10):
219235
truth = tf.cast(target > threshold, dtype=tf.float32)
220236
intersection = tf.reduce_sum(pre * truth)
221237
union = tf.reduce_sum(tf.cast((pre + truth) > threshold, dtype=tf.float32))
222-
return tf.reduce_sum(intersection) / (tf.reduce_sum(union) + epsilon)
238+
iou = (tf.reduce_sum(intersection) + epsilon) / (tf.reduce_sum(union) + epsilon)
239+
return iou
240+
# return tf.reduce_sum(intersection) / (tf.reduce_sum(union) + epsilon)
241+
242+
# ## test soft/hard dice and iou
243+
# import numpy as np
244+
# y = np.zeros((100,100,1))
245+
# y[0:10,0:10]=1
246+
# o = np.zeros((100,100,1))
247+
# # o[0:10,0:10]=1
248+
# o[5:15,5:15]=1
249+
# d = dice_coe(y, o)#, epsilon=1)
250+
# hd = dice_hard_coe(y, o)#, epsilon=1)
251+
# i = iou_coe(y, o)#, epsilon=1)
252+
# sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
253+
# print(sess.run([d,hd,i]))
254+
# exit()
223255

224256

225257
def cross_entropy_seq(logits, target_seqs, batch_size=None):#, batch_size=1, num_steps=None):

0 commit comments

Comments
 (0)