tensorflow-sphereface-asoftmax icon indicating copy to clipboard operation
tensorflow-sphereface-asoftmax copied to clipboard

m=3 hasn't been implemented

Open ghost opened this issue 7 years ago • 1 comments

Since m=3 hasn't been implemented, will you please provide the formula for that.

ghost avatar Feb 19 '18 20:02 ghost

`def Loss_ASoftmax(x, y, l, num_cls, m = 2, name = 'asoftmax'):

# x: B x D - data shape of x is [batch, n_featrue]
# y: B x 1 - label shape of y is [batch,] one-hot = False
# l: 1 - lambda
# commented by Qi
# num_cls = num_classes, the Asoftmax act as a last FC layer to transform fearture x to finally out of size [batch,num_cls]

with tf.variable_scope(name) as scope:
    xs = x.get_shape()  #   num_cls = 10  x = tf.placeholder(tf.float32, [256, 2])  batch is 256
    w = tf.get_variable("asoftmax/W", [xs[1], num_cls], dtype=tf.float32,   # shape is [n_feature, num_cls] By Qi , xs[1] is the number of feature
            initializer=tf.contrib.layers.xavier_initializer())

    eps = 1e-8

    xw = tf.matmul(x,w)   # shape of xw is [batch,num_cls] commented by Qi

    if m == 0:
        return xw, tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=xw))

    w_norm = tf.norm(w, axis = 0) + eps  # calculate the L2 distance of w, the shape of w_norm is [num_cls] commented by Qi
    logits = xw/w_norm  # the shape of logits is [batch, num_cls], y / ||w|| =  ||x|| * cos(theta) commented by Qi

    if y is None:
        return logits, None

    ordinal = tf.constant(list(range(0, xs[0])), tf.int64)  # shape is [batch, ] creat a constant list with value [0,batch] commented by Qi
    ordinal_y = tf.stack([ordinal, y], axis = 1) # shape is [batch, 2], stack the indice and label commented by Qi

    x_norm = tf.norm(x, axis = 1) + eps  # shape is [batch, ], calculate the ||xi|| commented by Qi

    sel_logits = tf.gather_nd(logits, ordinal_y)  # shape is [batch, ], select the logit value yi from position of label
    # tf.gather_nd is a indice find function https://www.jianshu.com/p/dd2b8d290fa5
    cos_th = tf.div(sel_logits, x_norm) # sel_logits / x_norm = yi / ||xi|| = cos(thetai)
    #
    if m == 1:

        loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits))

    else:

        if m == 2:

            sign0 = tf.sign(cos_th)   # tf.sign : when x = >0, 0, <0 ,sign(x) = 1, 0, -1
            res = 2*tf.multiply(sign0, tf.square(cos_th)) - 1
        elif m == 3:
            cos_th3 = tf.pow(cos_th, 3)
            sign0 = tf.sign(cos_th)
            sign1 = tf.sign(tf.abs(cos_th) - 0.5)
            sign2 = sign0 * (1 + sign1) - 2
            res = sign1 * (4 * cos_th3 - 3 * cos_th) + sign2

        elif m == 4:

            cos_th2 = tf.square(cos_th)
            cos_th4 = tf.pow(cos_th, 4)
            sign0 = tf.sign(cos_th)
            sign3 = tf.multiply(tf.sign(2*cos_th2 - 1), sign0)
            sign4 = 2*sign0 + sign3 - 3
            res = sign3*(8*cos_th4 - 8*cos_th2 + 1) + sign4  
        else:
            raise ValueError('unsupported value of m')

        scaled_logits = tf.multiply(res, x_norm)  #

        f = 1.0/(1.0+l)
        ff = 1.0 - f
        comb_logits_diff = tf.add(logits, tf.scatter_nd(ordinal_y, tf.subtract(scaled_logits, sel_logits), logits.get_shape()))
        # tf.catter_nd is a update function with (indice, update, shape of zeros array)
        updated_logits = ff*logits + f*comb_logits_diff

        loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=updated_logits))

    return logits, loss`

Hello @zahra-anvari I add the m=3 into the function. If you find anything wrong please let me know

qiyang77 avatar Apr 16 '19 03:04 qiyang77