pairwisecosface.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from __future__ import absolute_import
  15. from __future__ import division
  16. from __future__ import print_function
  17. import math
  18. import paddle
  19. import paddle.nn as nn
  20. import paddle.nn.functional as F
  21. class PairwiseCosface(nn.Layer):
  22. def __init__(self, margin, gamma):
  23. super(PairwiseCosface, self).__init__()
  24. self.margin = margin
  25. self.gamma = gamma
  26. def forward(self, embedding, targets):
  27. if isinstance(embedding, dict):
  28. embedding = embedding['features']
  29. # Normalize embedding features
  30. embedding = F.normalize(embedding, axis=1)
  31. dist_mat = paddle.matmul(embedding, embedding, transpose_y=True)
  32. N = dist_mat.shape[0]
  33. is_pos = targets.reshape([N, 1]).expand([N, N]).equal(
  34. paddle.t(targets.reshape([N, 1]).expand([N, N]))).astype('float')
  35. is_neg = targets.reshape([N, 1]).expand([N, N]).not_equal(
  36. paddle.t(targets.reshape([N, 1]).expand([N, N]))).astype('float')
  37. # Mask scores related to itself
  38. is_pos = is_pos - paddle.eye(N, N)
  39. s_p = dist_mat * is_pos
  40. s_n = dist_mat * is_neg
  41. logit_p = -self.gamma * s_p + (-99999999.) * (1 - is_pos)
  42. logit_n = self.gamma * (s_n + self.margin) + (-99999999.) * (1 - is_neg
  43. )
  44. loss = F.softplus(
  45. paddle.logsumexp(
  46. logit_p, axis=1) + paddle.logsumexp(
  47. logit_n, axis=1)).mean()
  48. return {"PairwiseCosface": loss}