|
|
|
@ -110,6 +110,7 @@ __all__ = [
|
|
|
|
|
'relu',
|
|
|
|
|
'log',
|
|
|
|
|
'crop',
|
|
|
|
|
'rank_loss',
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -5282,3 +5283,74 @@ def crop(x, shape=None, offsets=None, name=None):
|
|
|
|
|
outputs={'Out': out},
|
|
|
|
|
attrs=None if len(attrs) == 0 else attrs)
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rank_loss(label, left, right, name=None):
|
|
|
|
|
"""
|
|
|
|
|
**Rank loss layer for RankNet**
|
|
|
|
|
|
|
|
|
|
RankNet(http://icml.cc/2015/wp-content/uploads/2015/06/icml_ranking.pdf)
|
|
|
|
|
is a pairwise ranking model with a training sample consisting of a pair
|
|
|
|
|
of documents, A and B. Label P indicates whether A is ranked higher than B
|
|
|
|
|
or not:
|
|
|
|
|
|
|
|
|
|
P = {0, 1} or {0, 0.5, 1}, where 0.5 means that there is no information
|
|
|
|
|
about the rank of the input pair.
|
|
|
|
|
|
|
|
|
|
Rank loss layer takes three inputs: left (o_i), right (o_j) and
|
|
|
|
|
label (P_{i,j}). The inputs respectively represent RankNet's output scores
|
|
|
|
|
for documents A and B and the value of label P. The following equation
|
|
|
|
|
computes rank loss C_{i,j} from the inputs:
|
|
|
|
|
|
|
|
|
|
$$
|
|
|
|
|
C_{i,j} = -\tilde{P_{ij}} * o_{i,j} + \log(1 + e^{o_{i,j}}) \\
|
|
|
|
|
o_{i,j} = o_i - o_j \\
|
|
|
|
|
\tilde{P_{i,j}} = \left \{0, 0.5, 1 \right \} \ or \ \left \{0, 1 \right \}
|
|
|
|
|
$$
|
|
|
|
|
|
|
|
|
|
Rank loss layer takes batch inputs with size batch_size (batch_size >= 1).
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
label (Variable): Indicats whether A ranked higher than B or not.
|
|
|
|
|
left (Variable): RankNet's output score for doc A.
|
|
|
|
|
right (Variable): RankNet's output score for doc B.
|
|
|
|
|
name(str|None): A name for this layer(optional). If set None, the layer
|
|
|
|
|
will be named automatically.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
list: The value of rank loss.
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
ValueError: Any of label, left, and right is not a variable.
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
|
|
label = fluid.layers.data(name="label", shape=[4, 1], dtype="float32")
|
|
|
|
|
left = fluid.layers.data(name="left", shape=[4, 1], dtype="float32")
|
|
|
|
|
right = fluid.layers.data(name="right", shape=[4, 1], dtype="float32")
|
|
|
|
|
out = fluid.layers.rank_loss(label, left, right)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
helper = LayerHelper('rank_loss', **locals())
|
|
|
|
|
|
|
|
|
|
if not (isinstance(label, Variable)):
|
|
|
|
|
raise ValueError("The label should be a Variable")
|
|
|
|
|
|
|
|
|
|
if not (isinstance(left, Variable)):
|
|
|
|
|
raise ValueError("The left should be a Variable")
|
|
|
|
|
|
|
|
|
|
if not (isinstance(right, Variable)):
|
|
|
|
|
raise ValueError("The right should be a Variable")
|
|
|
|
|
|
|
|
|
|
out = helper.create_tmp_variable("float32")
|
|
|
|
|
|
|
|
|
|
helper.append_op(
|
|
|
|
|
type='rank_loss',
|
|
|
|
|
inputs={"Label": label,
|
|
|
|
|
"Left": left,
|
|
|
|
|
"Right": right},
|
|
|
|
|
outputs={'Out': out})
|
|
|
|
|
return out
|
|
|
|
|