Learning to Rank

Learning to rank [1] treats predict-then-optimize training as ranking a pool of feasible solutions. Predicted costs assign scores to solutions, and the loss encourages the optimal solution to rank highest. Each variant scores the ranking differently. Like contrastive methods, LTR uses solve_ratio and dataset to manage the pool.

The training loops on this page build on the Common Setup from Training Methods.

  • Pointwise regresses each predicted score \(\hat{\mathbf{c}}^\top \mathbf{w}\) toward the true value \(\mathbf{c}^\top \mathbf{w}\) for every \(\mathbf{w} \in \Gamma\).

  • Pairwise enforces a margin between the optimal solution and each suboptimal one.

  • Listwise models the entire ranking distribution with a SoftMax over the negative predicted costs (for a minimization problem, so the lowest-cost solution gets the highest probability),

    \[P(\mathbf{w}' \mid \hat{\mathbf{c}}) = \frac{\exp(-\hat{\mathbf{c}}^\top \mathbf{w}')}{\sum_{\mathbf{w} \in \Gamma} \exp(-\hat{\mathbf{c}}^\top \mathbf{w})},\]

    and minimizes the cross-entropy against the true ranking distribution,

    \[\mathcal{L}_{\mathrm{LTR}}^{\mathrm{list}}(\hat{\mathbf{c}}, \mathbf{c}) = - \sum_{\mathbf{w} \in \Gamma} P(\mathbf{w} \mid \mathbf{c}) \log P(\mathbf{w} \mid \hat{\mathbf{c}}).\]

    The gradient has a closed form,

    \[\frac{\partial \mathcal{L}_{\mathrm{LTR}}^{\mathrm{list}}(\hat{\mathbf{c}}, \mathbf{c})}{\partial \hat{\mathbf{c}}} = \sum_{\mathbf{w} \in \Gamma} P(\mathbf{w} \mid \mathbf{c})\, \mathbf{w} - \sum_{\mathbf{w} \in \Gamma} P(\mathbf{w} \mid \hat{\mathbf{c}})\, \mathbf{w}.\]

Pointwise LTR

pyepo.func.ptLTR

alias of pointwiseLearningToRank

Training loop:

ltr = pyepo.func.ptLTR(optmodel, processes=1, solve_ratio=0.05, dataset=dataset)

for epoch in range(20):
    for x, c, w, z in dataloader:
        cp = predmodel(x)
        loss = ltr(cp, c)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Pairwise LTR

pyepo.func.prLTR

alias of pairwiseLearningToRank

Training loop:

ltr = pyepo.func.prLTR(optmodel, processes=1, solve_ratio=0.05, dataset=dataset)

for epoch in range(20):
    for x, c, w, z in dataloader:
        cp = predmodel(x)
        loss = ltr(cp, c)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Listwise LTR

pyepo.func.lsLTR

alias of listwiseLearningToRank

Training loop:

ltr = pyepo.func.lsLTR(optmodel, processes=1, solve_ratio=0.05, dataset=dataset)

for epoch in range(20):
    for x, c, w, z in dataloader:
        cp = predmodel(x)
        loss = ltr(cp, c)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Footnotes