Source code for deepr.layers.click_rank

"""Rank Layer"""

import tensorflow as tf

from deepr.layers import base
from deepr.utils.broadcasting import make_same_shape


[docs]class ClickRank(base.Layer): """Click Rank Layer"""
[docs] def __init__(self, **kwargs): super().__init__(n_in=3, n_out=1, **kwargs)
[docs] def forward(self, tensors, mode: str = None): """Forward method of the layer Parameters ---------- tensors : Tuple[tf.Tensor] - positives: shape = (batch, num_events) - negatives: shape = (batch, num_events, num_negatives) - mask: shape = (batch, num_events, num_negatives) Returns ------- tf.Tensor ClickRank """ positives, negatives, mask = tensors # One score per negative : (batch, num_events, num_negative) positives, negatives = make_same_shape([positives, negatives], broadcast=False) positives_greater_negatives = tf.greater(positives, negatives) # One score per event, average of ranks : (batch, num_events) eps = 1e-8 mask_float = tf.to_float(mask) negatives_sum = tf.reduce_sum(tf.to_float(positives_greater_negatives) * mask_float, axis=-1) # In case no negatives, click rank would be 0.5 (random). # Events with no negatives are then removed via masking, so it # should not impact the final loss in any way. event_ranks = 1.0 - (negatives_sum + eps) / (tf.reduce_sum(mask_float, axis=-1) + eps * 2) # Each event contributes according to it weight event_mask = tf.to_float(tf.reduce_any(mask, axis=-1)) event_ranks = event_ranks * event_mask return tf.reduce_sum(event_ranks) / tf.reduce_sum(event_mask)