-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathcategorical_loss_function.py
More file actions
207 lines (192 loc) · 8.77 KB
/
Copy pathcategorical_loss_function.py
File metadata and controls
207 lines (192 loc) · 8.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import tensorflow as tf
def categorical_crossentropy(Y_pred, Y_gt):
"""
Categorical crossentropy between an output and a target
loss=-y*log(y')
:param Y_pred: A tensor resulting from a softmax
:param Y_gt: A tensor of the same shape as `output`
:return:categorical_crossentropy loss
"""
epsilon = 1.e-5
# scale preds so that the class probas of each sample sum to 1
output = Y_pred / tf.reduce_sum(Y_pred, axis=- 1, keep_dims=True)
# manual computation of crossentropy
output = tf.clip_by_value(output, epsilon, 1. - epsilon)
loss = -Y_gt * tf.log(output)
loss = tf.reduce_sum(loss, axis=(1, 2, 3))
loss = tf.reduce_mean(loss, axis=0)
loss = tf.reduce_mean(loss)
return loss
def weighted_categorical_crossentropy(Y_pred, Y_gt, weights):
"""
weighted_categorical_crossentropy between an output and a target
loss=-weight*y*log(y')
:param Y_pred:A tensor resulting from a softmax
:param Y_gt:A tensor of the same shape as `output`
:param weights:numpy array of shape (C,) where C is the number of classes
:return:categorical_crossentropy loss
Usage:
weights = np.array([0.5,2,10]) # Class one at 0.5, class 2 twice the normal weights, class 3 10x.
"""
weights = np.array(weights)
epsilon = 1.e-5
# scale preds so that the class probas of each sample sum to 1
output = Y_pred / tf.reduce_sum(Y_pred, axis=- 1, keep_dims=True)
# manual computation of crossentropy
output = tf.clip_by_value(output, epsilon, 1. - epsilon)
loss = - Y_gt * tf.log(output)
loss = tf.reduce_sum(loss, axis=(1, 2, 3))
loss = tf.reduce_mean(loss, axis=0)
loss = tf.reduce_mean(weights * loss)
return loss
def categorical_dice(Y_pred, Y_gt, weight_loss):
"""
multi label dice loss with weighted
WDL=1-2*(sum(w*sum(r&p))/sum((w*sum(r+p)))),w=array of shape (C,)
:param Y_pred: [None, self.image_depth, self.image_height, self.image_width,
self.numclass],Y_pred is softmax result
:param Y_gt:[None, self.image_depth, self.image_height, self.image_width,
self.numclass],Y_gt is one hot result
:param weight_loss: numpy array of shape (C,) where C is the number of classes
:return:
"""
weight_loss = np.array(weight_loss)
smooth = 1.e-5
smooth_tf = tf.constant(smooth, tf.float32)
Y_pred = tf.cast(Y_pred, tf.float32)
Y_gt = tf.cast(Y_gt, tf.float32)
# Compute gen dice coef:
numerator = Y_gt * Y_pred
numerator = tf.reduce_sum(numerator, axis=(1, 2, 3))
denominator = Y_gt + Y_pred
denominator = tf.reduce_sum(denominator, axis=(1, 2, 3))
gen_dice_coef = tf.reduce_mean(2. * (numerator + smooth_tf) / (denominator + smooth_tf), axis=0)
loss = -tf.reduce_mean(weight_loss * gen_dice_coef)
return loss
def categorical_focal_loss(Y_pred, Y_gt, gamma, alpha):
"""
Categorical focal_loss between an output and a target
:param Y_pred: A tensor of the same shape as `y_pred`
:param Y_gt: A tensor resulting from a softmax(-1,z,h,w,numclass)
:param alpha: Sample category weight,which is shape (C,) where C is the number of classes
:param gamma: Difficult sample weight
:return:
"""
weight_loss = np.array(alpha)
epsilon = 1.e-5
# Scale predictions so that the class probas of each sample sum to 1
output = Y_pred / tf.reduce_sum(Y_pred, axis=- 1, keepdims=True)
# Clip the prediction value to prevent NaN's and Inf's
output = tf.clip_by_value(output, epsilon, 1. - epsilon)
# Calculate Cross Entropy
cross_entropy = -Y_gt * tf.log(output)
# Calculate Focal Loss
loss = tf.pow(1 - output, gamma) * cross_entropy
loss = tf.reduce_sum(loss, axis=(1, 2, 3))
loss = tf.reduce_mean(loss, axis=0)
loss = tf.reduce_mean(weight_loss * loss)
return loss
def categorical_dicePcrossentroy(Y_pred, Y_gt, weight, lamda=0.5):
"""
hybrid loss function from dice loss and crossentroy
loss=Ldice+lamda*Lfocalloss
:param Y_pred:A tensor resulting from a softmax(-1,z,h,w,numclass)
:param Y_gt: A tensor of the same shape as `y_pred`
:param gamma:Difficult sample weight
:param alpha:Sample category weight,which is shape (C,) where C is the number of classes
:param lamda:trade-off between dice loss and focal loss,can set 0.1,0.5,1
:return:diceplusfocalloss
"""
weight_loss = np.array(weight)
smooth = 1.e-5
smooth_tf = tf.constant(smooth, tf.float32)
Y_pred = tf.cast(Y_pred, tf.float32)
Y_gt = tf.cast(Y_gt, tf.float32)
# Compute gen dice coef:
numerator = Y_gt * Y_pred
numerator = tf.reduce_sum(numerator, axis=(1, 2, 3))
denominator = Y_gt + Y_pred
denominator = tf.reduce_sum(denominator, axis=(1, 2, 3))
gen_dice_coef = tf.reduce_sum(2. * (numerator + smooth_tf) / (denominator + smooth_tf), axis=0)
loss1 = tf.reduce_mean(weight_loss * gen_dice_coef)
epsilon = 1.e-5
# scale preds so that the class probas of each sample sum to 1
output = Y_pred / tf.reduce_sum(Y_pred, axis=- 1, keep_dims=True)
# manual computation of crossentropy
output = tf.clip_by_value(output, epsilon, 1. - epsilon)
loss = -Y_gt * tf.log(output)
loss = tf.reduce_mean(loss, axis=(1, 2, 3))
loss = tf.reduce_mean(loss, axis=0)
loss2 = tf.reduce_mean(weight_loss * loss)
total_loss = (1 - lamda) * (1 - loss1) + lamda * loss2
return total_loss
def categorical_dicePfocalloss(Y_pred, Y_gt, alpha, lamda=0.5, gamma=2.):
"""
hybrid loss function from dice loss and focalloss
loss=Ldice+lamda*Lfocalloss
:param Y_pred:A tensor resulting from a softmax(-1,z,h,w,numclass)
:param Y_gt: A tensor of the same shape as `y_pred`
:param gamma:Difficult sample weight
:param alpha:Sample category weight,which is shape (C,) where C is the number of classes
:param lamda:trade-off between dice loss and focal loss,can set 0.1,0.5,1
:return:dicePfocalloss
"""
weight_loss = np.array(alpha)
smooth = 1.e-5
smooth_tf = tf.constant(smooth, tf.float32)
Y_pred = tf.cast(Y_pred, tf.float32)
Y_gt = tf.cast(Y_gt, tf.float32)
# Compute gen dice coef:
numerator = Y_gt * Y_pred
numerator = tf.reduce_sum(numerator, axis=(1, 2, 3))
denominator = Y_gt + Y_pred
denominator = tf.reduce_sum(denominator, axis=(1, 2, 3))
gen_dice_coef = tf.reduce_sum(2. * (numerator + smooth_tf) / (denominator + smooth_tf), axis=0)
loss1 = tf.reduce_mean(weight_loss * gen_dice_coef)
epsilon = 1.e-5
# Scale predictions so that the class probas of each sample sum to 1
output = Y_pred / tf.reduce_sum(Y_pred, axis=- 1, keepdims=True)
# Clip the prediction value to prevent NaN's and Inf's
output = tf.clip_by_value(output, epsilon, 1. - epsilon)
# Calculate Cross Entropy
cross_entropy = -Y_gt * tf.log(output)
# Calculate Focal Loss
loss = tf.pow(1 - output, gamma) * cross_entropy
loss = tf.reduce_mean(loss, axis=(1, 2, 3))
loss = tf.reduce_mean(loss, axis=0)
loss2 = tf.reduce_mean(weight_loss * loss)
total_loss = (1 - lamda) * (1 - loss1) + lamda * loss2
return total_loss
def ssim2d_loss(Y_pred, Y_gt, maxlabel):
"""
Computes SSIM index between Y_pred and Y_gt.only calculate 2d image,3d image can use it,but not actual ssim3d
:param Y_pred:A tensor resulting from a softmax(-1,z,h,w,numclass)
:param Y_gt:A tensor of the same shape as `y_pred`
:param maxlabel:maxlabelvalue
:return:ssim_loss
"""
loss = tf.image.ssim(Y_pred, Y_gt, maxlabel)
loss = tf.reduce_mean(loss)
return loss
def multiscalessim2d_loss(Y_pred, Y_gt, maxlabel, downsampledfactor=4):
"""
Computes the MS-SSIM between Y_pred and Y_gt.only calculate 2d image,3d image can use it,but not actual multiscalessim3d
:param Y_pred:A tensor resulting from a softmax(-1,z,h,w,numclass)
:param Y_gt:A tensor of the same shape as `y_pred`
:param maxlabel:maxlabelvalue
:param downsampledfactor:downsample factor depend on input imagesize
:return:multiscalessim_loss
"""
if downsampledfactor >= 5:
_MSSSIM_WEIGHTS = (0.0448, 0.2856, 0.3001, 0.2363, 0.1333)
if downsampledfactor == 4:
_MSSSIM_WEIGHTS = (0.0448, 0.2856, 0.3001, 0.2363)
if downsampledfactor == 3:
_MSSSIM_WEIGHTS = (0.0448, 0.2856, 0.3001)
if downsampledfactor == 2:
_MSSSIM_WEIGHTS = (0.0448, 0.2856)
if downsampledfactor <= 1:
_MSSSIM_WEIGHTS = (0.0448)
loss = tf.image.ssim_multiscale(Y_pred, Y_gt, maxlabel, power_factors=_MSSSIM_WEIGHTS)
loss = tf.reduce_mean(loss)
return loss