├── 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 |
--------------------------------------------------------------------------------