├── README.md ├── examples ├── README.md ├── fig_01.png └── fig_02.png └── tf_angular_loss.py /README.md: -------------------------------------------------------------------------------- 1 | ## Angular loss for deep metric learning 2 | 3 | Tensorflow Implemenation of Deep Metric Learning with Angular Loss. 4 | https://arxiv.org/abs/1708.01682 5 | 6 | 7 | 8 | 9 | ## NOTE: 10 | + All classes in an input batch should be different. 11 | + All embeddings should not be l2 normalized. 12 | + When you guys use this angular loss with [N-pair loss](https://www.tensorflow.org/api_docs/python/tf/contrib/losses/metric_learning/npairs_loss), let ```with_l2_reg``` be ```False```. If not, let it be ```True```. 13 | + I implemented only an angular mc loss. triplet version will be updated. 14 | 15 | ## Reference 16 | ``` 17 | @inproceedings{wang2017deep, 18 | title={Deep metric learning with angular loss}, 19 | author={Wang, Jian and Zhou, Feng and Wen, Shilei and Liu, Xiao and Lin, Yuanqing}, 20 | booktitle={2017 IEEE International Conference on Computer Vision (ICCV)}, 21 | pages={2612--2620}, 22 | year={2017}, 23 | organization={IEEE} 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | examples 2 | -------------------------------------------------------------------------------- /examples/fig_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geonm/tf_angular_loss/485f4f748d57b9206e2b392e440248d0cd790fc3/examples/fig_01.png -------------------------------------------------------------------------------- /examples/fig_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geonm/tf_angular_loss/485f4f748d57b9206e2b392e440248d0cd790fc3/examples/fig_02.png -------------------------------------------------------------------------------- /tf_angular_loss.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import numpy as np 4 | import tensorflow as tf 5 | 6 | 7 | def get_angular_loss(input_labels, anchor_features, pos_features, degree=45, batch_size=10, with_l2reg=False): 8 | ''' 9 | #NOTE: degree is degree!!! not radian value 10 | ''' 11 | if with_l2reg: 12 | reg_anchor = tf.reduce_mean(tf.reduce_sum(tf.square(anchor_features), 1)) 13 | reg_positive = tf.reduce_mean(tf.reduce_sum(tf.square(pos_features), 1)) 14 | l2loss = tf.multiply(0.25 * 0.002, reg_anchor + reg_positive, name='l2loss_angular') 15 | else: 16 | l2loss = 0.0 17 | 18 | alpha = np.deg2rad(degree) 19 | sq_tan_alpha = np.tan(alpha) ** 2 20 | 21 | #anchor_features = tf.nn.l2_normalize(anchor_features) 22 | #pos_features = tf.nn.l2_normalize(pos_features) 23 | 24 | # 2(1+(tan(alpha))^2 * xaTxp) 25 | #batch_size = 10 26 | xaTxp = tf.matmul(anchor_features, pos_features, transpose_a=False, transpose_b=True) 27 | sim_matrix_1 = tf.multiply(2.0 * (1.0 + sq_tan_alpha) * xaTxp, tf.eye(batch_size, dtype=tf.float32)) 28 | 29 | # 4((tan(alpha))^2(xa + xp)Txn 30 | xaPxpTxn = tf.matmul((anchor_features + pos_features), pos_features, transpose_a=False, transpose_b=True) 31 | sim_matrix_2 = tf.multiply(4.0 * sq_tan_alpha * xaPxpTxn, tf.ones_like(xaPxpTxn, dtype=tf.float32) - tf.eye(batch_size, dtype=tf.float32)) 32 | 33 | # similarity_matrix 34 | similarity_matrix = sim_matrix_1 + sim_matrix_2 35 | 36 | # do softmax cross-entropy 37 | lshape = tf.shape(input_labels) 38 | #assert lshape.shape == 1 39 | labels = tf.reshape(input_labels, [lshape[0], 1]) 40 | 41 | labels_remapped = tf.to_float(tf.equal(labels, tf.transpose(labels))) 42 | labels_remapped /= tf.reduce_sum(labels_remapped, 1, keepdims=True) 43 | 44 | xent_loss = tf.nn.softmax_cross_entropy_with_logits(logits=similarity_matrix, labels=labels_remapped) 45 | xent_loss = tf.reduce_mean(xent_loss, name='xentropy_angular') 46 | 47 | return l2loss + xent_loss 48 | 49 | if __name__ == '__main__': 50 | ## test 51 | os.environ['CUDA_VISIBLE_DEVICES'] = '' 52 | dims_vector = 256 53 | np_anchor = np.random.rand(10, dims_vector)#np.array([[1,2,3,4,5],[6,7,8,9,10]]) 54 | np_pos = np.random.rand(10, dims_vector)#np.array([[1.5, 2.5, 3.5, 4.5, 5.5], [6.5, 7.5, 8.5, 9.5, 10.5]]) 55 | np_pos_same = np_anchor.copy() 56 | 57 | anchor = tf.convert_to_tensor(np_anchor, dtype=tf.float32) 58 | pos = tf.convert_to_tensor(np_pos, dtype=tf.float32) 59 | pos_same = tf.convert_to_tensor(np_pos_same, dtype=tf.float32) 60 | 61 | real_labels = tf.convert_to_tensor(np.arange(start=0, stop=10, dtype='int32')) 62 | 63 | degree = 30 64 | 65 | angular_loss = get_angular_loss(real_labels, anchor, pos, degree=degree) 66 | angular_loss_same = get_angular_loss(real_labels, anchor, pos_same, degree=degree) 67 | 68 | npairs_loss = tf.contrib.losses.metric_learning.npairs_loss(real_labels, anchor, pos) 69 | npairs_loss_same = tf.contrib.losses.metric_learning.npairs_loss(real_labels, anchor, pos_same) 70 | ##### show outputs 71 | sess = tf.Session() 72 | 73 | #print(sess.run(labels), np_anchor.shape) 74 | 75 | out_angular_loss, out_angular_loss_same, out_npairs_loss, out_npairs_loss_same = sess.run([angular_loss, angular_loss_same, npairs_loss, npairs_loss_same]) 76 | 77 | print('\nangular_loss: \n', out_angular_loss, out_angular_loss_same) 78 | print('\nnpairs_loss: \n', out_npairs_loss, out_npairs_loss_same) 79 | print('') 80 | --------------------------------------------------------------------------------