def compute(self, y_true, y_pred): # y.shape (batches, priors, 4 x segment_offset + n x class_label) # TODO: negatives_for_hard? batch_size = tf.shape(y_true)[0] num_priors = tf.shape(y_true)[1] num_classes = tf.shape(y_true)[2] - 4 eps = K.epsilon() # confidence loss conf_true = tf.reshape(y_true[:,:,4:], [-1, num_classes]) conf_pred = tf.reshape(y_pred[:,:,4:], [-1, num_classes]) conf_loss = softmax_loss(conf_true, conf_pred) class_true = tf.argmax(conf_true, axis=1) class_pred = tf.argmax(conf_pred, axis=1) conf = tf.reduce_max(conf_pred, axis=1) neg_mask_float = conf_true[:,0] neg_mask = tf.cast(neg_mask_float, tf.bool) pos_mask = tf.logical_not(neg_mask) pos_mask_float = tf.cast(pos_mask, tf.float32) num_total = tf.cast(tf.shape(conf_true)[0], tf.float32) num_pos = tf.reduce_sum(pos_mask_float) num_neg = num_total - num_pos pos_conf_loss = tf.reduce_sum(conf_loss * pos_mask_float) pos_conf_loss = pos_conf_loss / (num_pos + eps) ## take only false positives for hard negative mining #false_pos_mask = tf.logical_and(neg_mask, tf.not_equal(class_pred, 0)) #num_false_pos = tf.reduce_sum(tf.cast(false_pos_mask, tf.float32)) #num_neg = tf.minimum(self.neg_pos_ratio * num_pos, num_false_pos) #neg_conf_loss = tf.boolean_mask(conf_loss, false_pos_mask) num_neg = tf.minimum(self.neg_pos_ratio * num_pos, num_neg) neg_conf_loss = tf.boolean_mask(conf_loss, neg_mask) neg_conf_loss = neg_conf_loss / (num_neg + eps) vals, idxs = tf.nn.top_k(neg_conf_loss, k=tf.cast(num_neg, tf.int32)) #neg_conf_loss = tf.reduce_sum(tf.gather(neg_conf_loss, idxs)) neg_conf_loss = tf.reduce_sum(vals) conf_loss = pos_conf_loss + neg_conf_loss # offset loss loc_true = tf.reshape(y_true[:,:,0:4], [-1, 4]) loc_pred = tf.reshape(y_pred[:,:,0:4], [-1, 4]) loc_loss = smooth_l1_loss(loc_true, loc_pred) pos_loc_loss = tf.reduce_sum(loc_loss * pos_mask_float) # only for positives loc_loss = pos_loc_loss / (num_pos + eps) # total loss loss = conf_loss + self.alpha * loc_loss # metrics precision, recall, accuracy, fmeasure = compute_metrics(class_true, class_pred, conf, top_k=100*batch_size) return eval('{'+' '.join(['"'+n+'": '+n+',' for n in self.metric_names])+'}')
def compute(self, y_true, y_pred): # y.shape (batches, segments, 2 x segment_label + 5 x segment_offset + 16 x inter_layer_links_label + 8 x cross_layer_links_label) batch_size = tf.shape(y_true)[0] eps = K.epsilon() # segment confidence loss seg_conf_true = tf.reshape(y_true[:, :, 0:2], [-1, 2]) seg_conf_pred = tf.reshape(y_pred[:, :, 0:2], [-1, 2]) seg_conf_loss = softmax_loss(seg_conf_true, seg_conf_pred) seg_class_pred = tf.argmax(seg_conf_pred, axis=1) neg_seg_mask_float = seg_conf_true[:, 0] neg_seg_mask = tf.cast(neg_seg_mask_float, tf.bool) pos_seg_mask = tf.logical_not(neg_seg_mask) pos_seg_mask_float = tf.cast(pos_seg_mask, tf.float32) num_seg = tf.cast(tf.shape(seg_conf_true)[0], tf.float32) num_pos_seg = tf.reduce_sum(pos_seg_mask_float) num_neg_seg = num_seg - num_pos_seg pos_seg_conf_loss = tf.reduce_sum(seg_conf_loss * pos_seg_mask_float) #false_pos_seg_mask = tf.logical_and(neg_seg_mask, tf.not_equal(seg_class_pred, 0)) #num_false_pos_seg = tf.reduce_sum(tf.cast(false_pos_seg_mask, tf.float32)) #num_neg_seg = tf.minimum(self.neg_pos_ratio * num_pos_seg, num_false_pos_seg) #neg_seg_conf_loss = tf.boolean_mask(seg_conf_loss, false_pos_seg_mask) num_neg_seg = tf.minimum(self.neg_pos_ratio * num_pos_seg, num_neg_seg) neg_seg_conf_loss = tf.boolean_mask(seg_conf_loss, neg_seg_mask) vals, idxs = tf.nn.top_k(neg_seg_conf_loss, k=tf.cast(num_neg_seg, tf.int32)) neg_seg_conf_loss = tf.reduce_sum(vals) pos_seg_conf_loss = pos_seg_conf_loss / (num_pos_seg + eps) neg_seg_conf_loss = neg_seg_conf_loss / (num_neg_seg + eps) seg_conf_loss = pos_seg_conf_loss + neg_seg_conf_loss seg_conf_loss = self.lambda_segments * seg_conf_loss # segment offset loss seg_loc_true = tf.reshape(y_true[:, :, 2:7], [-1, 5]) seg_loc_pred = tf.reshape(y_pred[:, :, 2:7], [-1, 5]) seg_loc_loss = smooth_l1_loss(seg_loc_true, seg_loc_pred) pos_seg_loc_loss = tf.reduce_sum(seg_loc_loss * pos_seg_mask_float) seg_loc_loss = pos_seg_loc_loss / (num_pos_seg + eps) seg_loc_loss = self.lambda_offsets * seg_loc_loss # link confidence loss inter_link_conf_true = y_true[:, :, 7:23] cross_link_conf_true = y_true[:, self.first_map_offset:, 23:31] link_conf_true = tf.concat([ tf.reshape(inter_link_conf_true, [-1, 2]), tf.reshape(cross_link_conf_true, [-1, 2]) ], 0) inter_link_conf_pred = y_pred[:, :, 7:23] cross_link_conf_pred = y_pred[:, self.first_map_offset:, 23:31] link_conf_pred = tf.concat([ tf.reshape(inter_link_conf_pred, [-1, 2]), tf.reshape(cross_link_conf_pred, [-1, 2]) ], 0) link_conf_loss = softmax_loss(link_conf_true, link_conf_pred) link_class_pred = tf.argmax(link_conf_pred, axis=1) neg_link_mask_float = link_conf_true[:, 0] neg_link_mask = tf.cast(neg_link_mask_float, tf.bool) pos_link_mask = tf.logical_not(neg_link_mask) pos_link_mask_float = tf.cast(pos_link_mask, tf.float32) num_link = tf.cast(tf.shape(link_conf_true)[0], tf.float32) num_pos_link = tf.reduce_sum(pos_link_mask_float) num_neg_link = num_link - num_pos_link pos_link_conf_loss = tf.reduce_sum(link_conf_loss * pos_link_mask_float) #false_pos_link_mask = tf.logical_and(neg_link_mask, tf.not_equal(link_class_pred, 0)) #num_false_pos_link = tf.reduce_sum(tf.cast(false_pos_link_mask, tf.float32)) #num_neg_link = tf.minimum(self.neg_pos_ratio * num_pos_link, num_false_pos_link) #neg_link_conf_loss = tf.boolean_mask(link_conf_loss, false_pos_link_mask) num_neg_link = tf.minimum(self.neg_pos_ratio * num_pos_link, num_neg_link) neg_link_conf_loss = tf.boolean_mask(link_conf_loss, neg_link_mask) vals, idxs = tf.nn.top_k(neg_link_conf_loss, k=tf.cast(num_neg_link, tf.int32)) neg_link_conf_loss = tf.reduce_sum(vals) pos_link_conf_loss = pos_link_conf_loss / (num_pos_link + eps) neg_link_conf_loss = neg_link_conf_loss / (num_neg_link + eps) link_conf_loss = pos_link_conf_loss + neg_link_conf_loss link_conf_loss = self.lambda_links * link_conf_loss # total loss total_loss = seg_conf_loss + seg_loc_loss + link_conf_loss seg_conf = tf.reduce_max(seg_conf_pred, axis=1) seg_class_true = tf.argmax(seg_conf_true, axis=1) seg_class_pred = tf.argmax(seg_conf_pred, axis=1) seg_precision, seg_recall, seg_accuracy, seg_fmeasure = compute_metrics( seg_class_true, seg_class_pred, seg_conf, top_k=100 * batch_size) link_conf = tf.reduce_max(link_conf_pred, axis=1) link_class_true = tf.argmax(link_conf_true, axis=1) link_class_pred = tf.argmax(link_conf_pred, axis=1) link_precision, link_recall, link_accuracy, link_fmeasure = compute_metrics( link_class_true, link_class_pred, link_conf, top_k=100 * batch_size) # metrics def make_fcn(t): return lambda y_true, y_pred: t for name in [ 'seg_conf_loss', 'seg_loc_loss', 'link_conf_loss', 'num_pos_seg', 'num_neg_seg', 'pos_seg_conf_loss', 'neg_seg_conf_loss', 'pos_link_conf_loss', 'neg_link_conf_loss', 'seg_precision', 'seg_recall', 'seg_accuracy', 'seg_fmeasure', 'link_precision', 'link_recall', 'link_accuracy', 'link_fmeasure', ]: f = make_fcn(eval(name)) f.__name__ = name self.metrics.append(f) return total_loss
def compute(self, y_true, y_pred): # y.shape (batches, priors, 4 x segment_offset + n x class_label) # TODO: negatives_for_hard? # mask based on y_true or y_pred? batch_size = tf.shape(y_true)[0] num_priors = tf.shape(y_true)[1] num_classes = tf.shape(y_true)[2] - 4 eps = K.epsilon() # confidence loss conf_true = tf.reshape(y_true[:, :, 4:], [-1, num_classes]) conf_pred = tf.reshape(y_pred[:, :, 4:], [-1, num_classes]) conf_loss = softmax_loss(conf_true, conf_pred) class_true = tf.argmax(conf_true, axis=1) class_pred = tf.argmax(conf_pred, axis=1) conf = tf.reduce_max(conf_pred, axis=1) neg_mask_float = conf_true[:, 0] neg_mask = tf.cast(neg_mask_float, tf.bool) pos_mask = tf.logical_not(neg_mask) pos_mask_float = tf.cast(pos_mask, tf.float32) num_total = tf.cast(tf.shape(conf_true)[0], tf.float32) num_pos = tf.reduce_sum(pos_mask_float) num_neg = num_total - num_pos pos_conf_loss = tf.reduce_sum(conf_loss * pos_mask_float) ## take only false positives for hard negative mining #false_pos_mask = tf.logical_and(neg_mask, tf.not_equal(class_pred, 0)) #num_false_pos = tf.reduce_sum(tf.cast(false_pos_mask, tf.float32)) #num_neg = tf.minimum(self.neg_pos_ratio * num_pos, num_false_pos) #neg_conf_loss = tf.boolean_mask(conf_loss, false_pos_mask) num_neg = tf.minimum(self.neg_pos_ratio * num_pos, num_neg) neg_conf_loss = tf.boolean_mask(conf_loss, neg_mask) vals, idxs = tf.nn.top_k(neg_conf_loss, k=tf.cast(num_neg, tf.int32)) #neg_conf_loss = tf.reduce_sum(tf.gather(neg_conf_loss, idxs)) neg_conf_loss = tf.reduce_sum(vals) conf_loss = (pos_conf_loss + neg_conf_loss) / (num_pos + num_neg + eps) # offset loss loc_true = tf.reshape(y_true[:, :, 0:4], [-1, 4]) loc_pred = tf.reshape(y_pred[:, :, 0:4], [-1, 4]) loc_loss = smooth_l1_loss(loc_true, loc_pred) pos_loc_loss = tf.reduce_sum(loc_loss * pos_mask_float) # only for positives loc_loss = pos_loc_loss / (num_pos + eps) # total loss total_loss = conf_loss + self.alpha * loc_loss # metrics pos_conf_loss = pos_conf_loss / (num_pos + eps) neg_conf_loss = neg_conf_loss / (num_neg + eps) pos_loc_loss = pos_loc_loss / (num_pos + eps) precision, recall, accuracy, fmeasure = compute_metrics(class_true, class_pred, conf, top_k=100 * batch_size) def make_fcn(t): return lambda y_true, y_pred: t for name in [ 'num_pos', 'num_neg', 'pos_conf_loss', 'neg_conf_loss', 'pos_loc_loss', 'precision', 'recall', 'accuracy', 'fmeasure', ]: f = make_fcn(eval(name)) f.__name__ = name self.metrics.append(f) return total_loss