def _focal(y_true, y_pred): # y_true [batch_size, num_anchor, num_classes+1] # y_pred [batch_size, num_anchor, num_classes] labels = y_true[:, :, :-1] anchor_state = y_true[:, :, -1] # -1 是需要忽略的, 0 是背景, 1 是存在目标 classification = y_pred # 找出存在目标的先验框 indices_for_object = backend.where(keras.backend.equal( anchor_state, 1)) labels_for_object = backend.gather_nd(labels, indices_for_object) classification_for_object = backend.gather_nd(classification, indices_for_object) # 计算每一个先验框应该有的权重 alpha_factor_for_object = keras.backend.ones_like( labels_for_object) * alpha alpha_factor_for_object = backend.where( keras.backend.equal(labels_for_object, 1), alpha_factor_for_object, 1 - alpha_factor_for_object) focal_weight_for_object = backend.where( keras.backend.equal(labels_for_object, 1), 1 - classification_for_object, classification_for_object) focal_weight_for_object = alpha_factor_for_object * focal_weight_for_object**gamma # 将权重乘上所求得的交叉熵 cls_loss_for_object = focal_weight_for_object * keras.backend.binary_crossentropy( labels_for_object, classification_for_object) # 找出实际上为背景的先验框 indices_for_back = backend.where(keras.backend.equal(anchor_state, 0)) labels_for_back = backend.gather_nd(labels, indices_for_back) classification_for_back = backend.gather_nd(classification, indices_for_back) # 计算每一个先验框应该有的权重 alpha_factor_for_back = keras.backend.ones_like(labels_for_back) * ( 1 - alpha) focal_weight_for_back = classification_for_back focal_weight_for_back = alpha_factor_for_back * focal_weight_for_back**gamma # 将权重乘上所求得的交叉熵 cls_loss_for_back = focal_weight_for_back * keras.backend.binary_crossentropy( labels_for_back, classification_for_back) # 标准化,实际上是正样本的数量 normalizer = tf.where(keras.backend.equal(anchor_state, 1)) normalizer = keras.backend.cast( keras.backend.shape(normalizer)[0], keras.backend.floatx()) normalizer = keras.backend.maximum(keras.backend.cast_to_floatx(1.0), normalizer) # 将所获得的loss除上正样本的数量 cls_loss_for_object = keras.backend.sum(cls_loss_for_object) cls_loss_for_back = keras.backend.sum(cls_loss_for_back) # 总的loss loss = (cls_loss_for_object + cls_loss_for_back) / normalizer return loss
def _smooth_l1(y_true, y_pred): #---------------------------------------------------# # y_true [batch_size, num_anchor, 4+1] # y_pred [batch_size, num_anchor, 4] #---------------------------------------------------# regression = y_pred regression_target = y_true[:, :, :-1] anchor_state = y_true[:, :, -1] # 找出存在目标的先验框 indices = backend.where(keras.backend.equal(anchor_state, 1)) regression = backend.gather_nd(regression, indices) regression_target = backend.gather_nd(regression_target, indices) # 计算smooth L1损失 regression_diff = regression - regression_target regression_diff = keras.backend.abs(regression_diff) regression_loss = backend.where( keras.backend.less(regression_diff, 1.0 / sigma_squared), 0.5 * sigma_squared * keras.backend.pow(regression_diff, 2), regression_diff - 0.5 / sigma_squared) # 将所获得的loss除上正样本的数量 normalizer = keras.backend.maximum(1, keras.backend.shape(indices)[0]) normalizer = keras.backend.cast(normalizer, dtype=keras.backend.floatx()) return keras.backend.sum(regression_loss) / normalizer / 4
def _smooth_l1(y_true, y_pred): regression = y_pred regression_target = y_true[:, :, :-1] anchor_state = y_true[:, :, -1] indices = backend.where(keras.backend.equal(anchor_state, 1)) regression = backend.gather_nd(regression, indices) regression_target = backend.gather_nd(regression_target, indices) # compute smooth L1 loss # f(x) = 0.5 * (sigma * x)^2 if |x| < 1 / sigma / sigma # |x| - 0.5 / sigma / sigma otherwise regression_diff = regression - regression_target regression_diff = keras.backend.abs(regression_diff) regression_loss = backend.where( keras.backend.less(regression_diff, 1.0 / sigma_squared), 0.5 * sigma_squared * keras.backend.pow(regression_diff, 2), regression_diff - 0.5 / sigma_squared) # compute the normalizer: the number of positive anchors normalizer = keras.backend.maximum(1, keras.backend.shape(indices)[0]) normalizer = keras.backend.cast(normalizer, dtype=keras.backend.floatx()) return keras.backend.sum(regression_loss) / normalizer / 4