//  [python]
def get_discriminative_loss(self, features, labels):
        # feature:BxNxC, labels:BxN
        d_in = features.get_shape()[-1].value
        features = tf.reshape(features, [-1, d_in])  # NxC
        labels = tf.reshape(labels, [-1])  # N

        delta_v = 0.5
        delta_d = 1.5

        l_var = tf.zeros([0], tf.float32)
        mean_label_features_list = tf.zeros([0, d_in], tf.float32)
        for label_idx in range(self.config.num_classes):
            label_bool = tf.equal(labels, label_idx)
            label_num = tf.to_float(tf.count_nonzero(tf.to_float(label_bool)))
            def get_label_features(mean_label_features_list, l_var):
                label_features = tf.boolean_mask(features, label_bool)  # KxC
                mean_label_features = tf.reduce_mean(label_features, axis=0, keep_dims=True)  # 1xC
                mean_label_features_list = tf.concat([mean_label_features_list, mean_label_features], axis=0)
                dis = tf.sqrt(tf.reduce_sum(tf.square(label_features - mean_label_features), axis=-1))
                # close = tf.to_float(tf.less_equal(dis, delta_v))
                mid = tf.to_float(tf.logical_and(tf.greater(dis, delta_v), tf.less_equal(dis, delta_d)))
                far = tf.to_float(tf.greater(dis, delta_d))
                var = mid * tf.square(dis - delta_v)
                var = var + far * (dis - delta_d + (delta_d - delta_v)**2)
                var = tf.reduce_mean(var, keep_dims=True)
                # var = tf.reduce_mean(tf.sqrt(tf.reduce_sum(tf.square(label_features - mean_label_features), axis=-1)), keep_dims=True)
                l_var = tf.concat([l_var, var], axis=0)
                return mean_label_features_list, l_var
            def no_label_features(mean_label_features_list, l_var):
                return mean_label_features_list, l_var
            mean_label_features_list, l_var = tf.cond(tf.greater(label_num, 1),
                                               lambda: get_label_features(mean_label_features_list, l_var),
                                               lambda: no_label_features(mean_label_features_list, l_var))
        l_var = tf.reduce_mean(l_var)
        reg = tf.sqrt(tf.reduce_sum(tf.square(mean_label_features_list), axis=-1))  # NC
        l_reg = tf.reduce_mean(reg)

        l_dis = tf.zeros([0], tf.float32)
        i = tf.get_variable("ii", dtype=tf.int32, shape=[], initializer=tf.zeros_initializer())
        def cond2(j, mean_label_features_list, l_dis):
            return tf.less(j, tf.shape(mean_label_features_list)[0])
        def body2(j, mean_label_features_list, l_dis):
            mean_label_featuresi = tf.gather_nd(mean_label_features_list, tf.stack([i], axis=0))
            mean_label_featuresj = tf.gather_nd(mean_label_features_list, tf.stack([j], axis=0))
            dis = tf.sqrt(tf.reduce_sum(tf.square(mean_label_featuresi - mean_label_featuresj), axis=-1, keep_dims=True))
            close = tf.to_float(tf.less_equal(dis, 2*delta_d))
            l_dis = tf.concat([l_dis, close * tf.square(2*delta_d - dis)], axis=0)
            j = j + 1
            return j, mean_label_features_list, l_dis
        def cond1(i, mean_label_features_list, l_dis):
            return tf.less(i, tf.shape(mean_label_features_list)[0] - 1)
        def body1(i, mean_label_features_list, l_dis):
            j = i + 1
            j, mean_label_features_list, l_dis = tf.while_loop(cond2, body2, [j, mean_label_features_list, l_dis],
                                                               shape_invariants=[j.get_shape(),
                                                                                 mean_label_features_list.get_shape(),
                                                                                 tf.TensorShape([None])])
            i = i + 1
            return i, mean_label_features_list, l_dis
        i, mean_label_features_list, l_dis = tf.while_loop(cond1, body1, [i, mean_label_features_list, l_dis],
                                                           shape_invariants=[i.get_shape(),
                                                                             mean_label_features_list.get_shape(),
                                                                             tf.TensorShape([None])])
        l_dis = tf.reduce_mean(l_var)

        # l_dis = tf.constant(0, tf.float32)
        # l_reg = tf.constant(0, tf.float32)

        return l_var, l_dis, l_reg