tensorflow-sphereface-asoftmax
tensorflow-sphereface-asoftmax copied to clipboard
m=3 hasn't been implemented
Since m=3 hasn't been implemented, will you please provide the formula for that.
`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