@@ -121,7 +121,8 @@ def normalized_mean_square_error(output, target):
121121 return nmse
122122
123123
124- def dice_coe (output , target , loss_type = 'jaccard' , epsilon = 1e-10 ):
124+
125+ def dice_coe (output , target , loss_type = 'jaccard' , axis = [1 ,2 ,3 ], epsilon = 1e-5 ):
125126 """Soft dice (Sørensen or Jaccard) coefficient for comparing the similarity
126127 of two distributions, usually be used for binary image segmentation
127128 i.e. labels are binary. The coefficient in [0, 1], 1 means totally match.
@@ -134,39 +135,54 @@ def dice_coe(output, target, loss_type='jaccard', epsilon=1e-10):
134135 A distribution with shape: [batch_size, ....], (any dimensions).
135136 loss_type : string
136137 ``jaccard`` or ``sorensen``, default is ``jaccard``.
138+ axis : list of integer
139+ All dimensions are reduced, default ``[1,2,3]``.
137140 epsilon : float
138141 An small value be added to the numerator and denominator.
139142
140143 Examples
141144 ---------
142- >>> outputs = tf.nn.sigmoid (network.outputs)
145+ >>> outputs = tl.act.pixel_wise_softmax (network.outputs)
143146 >>> dice_loss = 1 - tl.cost.dice_coe(outputs, y_)
144147
145148 References
146149 -----------
147150 - `Wiki-Dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_
148151 """
149- # inse = tf.reduce_sum( tf.mul(output, target) )
150- # l = tf.reduce_sum( tf.mul(output, output) )
151- # r = tf.reduce_sum( tf.mul(target, target) )
152- inse = tf .reduce_sum ( output * target )
152+ # # inse = tf.reduce_sum( tf.mul(output, target) )
153+ # # l = tf.reduce_sum( tf.mul(output, output) )
154+ # # r = tf.reduce_sum( tf.mul(target, target) )
155+ # inse = tf.reduce_sum( output * target )
156+ # if loss_type == 'jaccard':
157+ # l = tf.reduce_sum( output * output )
158+ # r = tf.reduce_sum( target * target )
159+ # elif loss_type == 'sorensen':
160+ # l = tf.reduce_sum( output )
161+ # r = tf.reduce_sum( target )
162+ # else:
163+ # raise Exception("Unknow loss_type")
164+ # dice = (2. * inse + epsilon) / (l + r + epsilon) # if both output and target are empty, dice is 1
165+ # return dice
166+ # # dice = 2 * (inse) / (l + r)
167+ # # if epsilon == 0:
168+ # # return dice
169+ # # else:
170+ # # return tf.clip_by_value(dice, 0, 1.0-epsilon)
171+ inse = tf .reduce_sum (output * target , axis = axis )
153172 if loss_type == 'jaccard' :
154- l = tf .reduce_sum ( output * output )
155- r = tf .reduce_sum ( target * target )
173+ l = tf .reduce_sum (output * output , axis = axis )
174+ r = tf .reduce_sum (target * target , axis = axis )
156175 elif loss_type == 'sorensen' :
157- l = tf .reduce_sum ( output )
158- r = tf .reduce_sum ( target )
176+ l = tf .reduce_sum (output , axis = axis )
177+ r = tf .reduce_sum (target , axis = axis )
159178 else :
160179 raise Exception ("Unknow loss_type" )
161- dice = (2. * inse + epsilon ) / (l + r + epsilon ) # if both output and target are empty, dice is 1
180+ dice = (2. * inse + epsilon ) / (l + r + epsilon ) # if both output and target are empty, dice is 1
181+ dice = tf .reduce_mean (dice )
162182 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)
168183
169- def dice_hard_coe (output , target , threshold = 0.5 , epsilon = 1e-10 ):
184+
185+ def dice_hard_coe (output , target , threshold = 0.5 , axis = [1 ,2 ,3 ], epsilon = 1e-5 ):
170186 """Non-differentiable Sørensen–Dice coefficient for comparing the similarity of two distributions,
171187 usually be used for binary image segmentation i.e. labels are binary.
172188 The coefficient = [0, 1], 1 if totally match.
@@ -179,29 +195,41 @@ def dice_hard_coe(output, target, threshold=0.5, epsilon=1e-10):
179195 A distribution with shape: [batch_size, ....], (any dimensions).
180196 threshold : float
181197 The threshold value to be true.
198+ axis : list of integer
199+ All dimensions are reduced, default ``[1,2,3]``.
182200 epsilon : float
183201 An small value be added to the numerator and denominator.
184202
185203 References
186204 -----------
187205 - `Wiki-Dice <https://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_
188206 """
207+ # output = tf.cast(output > threshold, dtype=tf.float32)
208+ # target = tf.cast(target > threshold, dtype=tf.float32)
209+ # inse = tf.reduce_sum( output * target )
210+ # l = tf.reduce_sum( output )
211+ # r = tf.reduce_sum( target )
212+ # # l = tf.reduce_sum( output * output )
213+ # # r = tf.reduce_sum( target * target )
214+ # dice = (2. * inse + epsilon) / (l + r + epsilon) # if both output and target are empty, it is 1
215+ # return dice
216+ # # dice = 2 * (inse) / (l + r)
217+ # # if epsilon == 0:
218+ # # return dice
219+ # # else:
220+ # # return tf.clip_by_value(dice, 0, 1.0-epsilon)
189221 output = tf .cast (output > threshold , dtype = tf .float32 )
190222 target = tf .cast (target > threshold , dtype = tf .float32 )
191- inse = tf .reduce_sum ( output * target )
192- l = tf .reduce_sum ( output )
193- r = tf .reduce_sum ( target )
194- # l = tf.reduce_sum( output * output )
195- # r = tf.reduce_sum( target * target )
196- dice = (2. * inse + epsilon ) / (l + r + epsilon ) # if both output and target are empty, it is 1
197- return dice
198- # dice = 2 * (inse) / (l + r)
199- # if epsilon == 0:
200- # return dice
201- # else:
202- # return tf.clip_by_value(dice, 0, 1.0-epsilon)
223+ inse = tf .reduce_sum ( output * target , axis = axis )
224+ l = tf .reduce_sum (output , axis = axis )
225+ r = tf .reduce_sum (target , axis = axis )
226+ # hard_dice = (2. * inse ) / (l + r + epsilon)
227+ hard_dice = (2. * inse + epsilon ) / (l + r + epsilon )
228+ hard_dice = tf .reduce_mean (hard_dice )
229+ return hard_dice
230+
203231
204- def iou_coe (output , target , threshold = 0.5 , epsilon = 1e-10 ):
232+ def iou_coe (output , target , threshold = 0.5 , axis = [ 1 , 2 , 3 ], epsilon = 1e-5 ):
205233 """Non-differentiable Intersection over Union, usually be used for
206234 evaluating binary image segmentation.
207235 The coefficient = [0, 1], 1 means totally match.
@@ -214,39 +242,26 @@ def iou_coe(output, target, threshold=0.5, epsilon=1e-10):
214242 A distribution with shape: [batch_size, ....], (any dimensions).
215243 threshold : float
216244 The threshold value to be true.
245+ axis : list of integer
246+ All dimensions are reduced, default ``[1,2,3]``.
217247 epsilon : float
218248 An small value be added to the numerator and denominator.
219249
220- Examples
221- ---------
222- >>> outputs = tf.nn.sigmoid(network.outputs)
223- >>> iou = tl.cost.iou_coe(outputs, y_)
224-
225250 Notes
226251 ------
227252 - IOU cannot be used as training loss, people usually use dice coefficient for training, and IOU for evaluating.
228253 """
229254 pre = tf .cast (output > threshold , dtype = tf .float32 )
230255 truth = tf .cast (target > threshold , dtype = tf .float32 )
231- intersection = tf .reduce_sum (pre * truth )
232- union = tf .reduce_sum (tf .cast ((pre + truth ) > threshold , dtype = tf .float32 ))
233- iou = (tf .reduce_sum (intersection ) + epsilon ) / (tf .reduce_sum (union ) + epsilon )
234- return iou
235- # return tf.reduce_sum(intersection) / (tf.reduce_sum(union) + epsilon)
236-
237- # ## test soft/hard dice and iou
238- # import numpy as np
239- # y = np.zeros((100,100,1))
240- # y[0:10,0:10]=1
241- # o = np.zeros((100,100,1))
242- # # o[0:10,0:10]=1
243- # o[5:15,5:15]=1
244- # d = dice_coe(y, o)#, epsilon=1)
245- # hd = dice_hard_coe(y, o)#, epsilon=1)
246- # i = iou_coe(y, o)#, epsilon=1)
247- # sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
248- # print(sess.run([d,hd,i]))
249- # exit()
256+ inse = tf .reduce_sum (tf .multiply (pre , truth ), axis = axis ) # AND
257+ union = tf .reduce_sum (tf .cast (tf .add (pre ,truth )>= 1 , dtype = tf .float32 ), axis = axis ) # OR
258+ # iou = (tf.reduce_sum(inse) + epsilon) / (tf.reduce_sum(union) + epsilon)
259+ # it is incorrect as. if one empty, not inse==0 and union==0, it cannt be 1
260+ # iou = tf.reduce_sum(inse) / (tf.reduce_sum(union) + epsilon)
261+ # iou = inse / (union + epsilon) # bug: if one empty, iou=0 (correct), but if all empty, iou=0 (incorrect, it should be 1)
262+ batch_iou = (inse + epsilon ) / (union + epsilon )
263+ iou = tf .reduce_mean (batch_iou )
264+ return iou #, pre, truth, inse, union
250265
251266
252267def cross_entropy_seq (logits , target_seqs , batch_size = None ):#, batch_size=1, num_steps=None):
0 commit comments