bpr_loss.py 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. ## @package bpr_loss
  2. # Module caffe2.python.layers.bpr_loss
  3. from caffe2.python import schema
  4. from caffe2.python.layers.layers import (
  5. ModelLayer,
  6. )
  7. from caffe2.python.layers.tags import (
  8. Tags
  9. )
  10. import numpy as np
  11. # ref: https://arxiv.org/pdf/1205.2618.pdf
  12. class BPRLoss(ModelLayer):
  13. def __init__(self, model, input_record, name='bpr_loss', **kwargs):
  14. super(BPRLoss, self).__init__(model, name, input_record, **kwargs)
  15. assert schema.is_schema_subset(
  16. schema.Struct(
  17. ('pos_prediction', schema.Scalar()),
  18. ('neg_prediction', schema.List(np.float32)),
  19. ),
  20. input_record
  21. )
  22. self.tags.update([Tags.EXCLUDE_FROM_PREDICTION])
  23. self.output_schema = schema.Scalar(
  24. np.float32,
  25. self.get_next_blob_reference('output'))
  26. def add_ops(self, net):
  27. # formula:
  28. # loss = - SUM(Ln(Sigmoid(Simlarity(u, pos) - Simlarity(u, neg))))
  29. neg_score = self.input_record.neg_prediction['values']()
  30. pos_score = net.LengthsTile(
  31. [
  32. self.input_record.pos_prediction(),
  33. self.input_record.neg_prediction['lengths']()
  34. ],
  35. net.NextScopedBlob('pos_score_repeated')
  36. )
  37. # https://www.tensorflow.org/api_docs/python/tf/math/log_sigmoid
  38. softplus = net.Softplus([net.Sub([neg_score, pos_score])])
  39. net.ReduceFrontSum(softplus, self.output_schema.field_blobs())