Mercurial > hg > camir-aes2014
comparison toolboxes/distance_learning/mlr/separationOracle/separationOracleNDCG.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function [Y, Loss] = separationOracleNDCG(q, D, pos, neg, k) | |
2 % | |
3 % [Y,Loss] = separationOracleNDCG(q, D, pos, neg, k) | |
4 % | |
5 % q = index of the query point | |
6 % D = the current distance matrix | |
7 % pos = indices of relevant results for q | |
8 % neg = indices of irrelevant results for q | |
9 % k = length of the list to consider | |
10 % | |
11 % Y is a permutation 1:n corresponding to the maximally | |
12 % violated constraint | |
13 % | |
14 % Loss is the loss for Y, in this case, 1-NDCG(Y) | |
15 | |
16 | |
17 % First, sort the documents in descending order of W'Phi(q,x) | |
18 % Phi = - (X(q) - X(x)) * (X(q) - X(x))' | |
19 | |
20 % Sort the positive documents | |
21 ScorePos = - D(pos, q); | |
22 [Vpos, Ipos] = sort(full(ScorePos'), 'descend'); | |
23 Ipos = pos(Ipos); | |
24 | |
25 % Sort the negative documents | |
26 ScoreNeg = - D(neg, q); | |
27 [Vneg, Ineg] = sort(full(ScoreNeg'), 'descend'); | |
28 Ineg = neg(Ineg); | |
29 | |
30 % Now, solve the DP for the interleaving | |
31 | |
32 numPos = length(pos); | |
33 numNeg = length(neg); | |
34 n = numPos + numNeg; | |
35 | |
36 % From Chakrabarti (KDD08) | |
37 k = min(k, numPos); | |
38 | |
39 cVneg = cumsum(Vneg); | |
40 | |
41 Discount = zeros(k, 1); | |
42 Discount(1:2) = 1; | |
43 Discount(3:k) = 1./ log2(3:k); | |
44 | |
45 DCGstar = sum(Discount); | |
46 | |
47 | |
48 % Pre-compute the loss table | |
49 LossTab = padarray( hankel(- Discount / DCGstar), ... | |
50 max(0, [numNeg numPos] - k), 0, 'post'); | |
51 if sum(size(LossTab) > [numNeg, numPos]) | |
52 LossTab = LossTab(1:numNeg, 1:numPos); | |
53 end | |
54 | |
55 % 2010-01-17 09:13:41 by Brian McFee <bmcfee@cs.ucsd.edu> | |
56 % initialize the score table | |
57 | |
58 pcVneg = [0 cVneg]; | |
59 % Pre-compute cellScore | |
60 cellValue = bsxfun(@times, Vpos / (numPos * numNeg), numNeg - 2 * ((1:numNeg)-1)'); | |
61 cellValue = bsxfun(@plus, (2 * pcVneg(1:numNeg) - cVneg(end))' / (numPos * numNeg), cellValue); | |
62 cellValue = cellValue + LossTab; | |
63 | |
64 S = zeros(numNeg, numPos); | |
65 P = zeros(numNeg, numPos); | |
66 | |
67 % Initialize first column | |
68 P(:,1) = 1; | |
69 S(:,1) = cellValue(:,1); | |
70 | |
71 % Initialize first row | |
72 P(1,:) = 1; | |
73 S(1,:) = cumsum(cellValue(1,:)); | |
74 | |
75 % For the rest, use the recurrence | |
76 | |
77 for g = 2:numPos | |
78 [m, pointer] = cummax(S(:,g-1)); | |
79 P(:,g) = pointer; | |
80 S(:,g) = m' + cellValue(:,g); | |
81 end | |
82 | |
83 % Now reconstruct the permutation from the DP table | |
84 Y = nan * ones(n,1); | |
85 [m,p] = max(S(:,numPos)); | |
86 | |
87 Loss = 1 + LossTab(p,numPos); | |
88 | |
89 NegsBefore = zeros(numPos,1); | |
90 NegsBefore(numPos) = p-1; | |
91 | |
92 for a = numPos:-1:2 | |
93 p = P(p,a); | |
94 NegsBefore(a-1) = p-1; | |
95 Loss = Loss + LossTab(p,a-1); | |
96 end | |
97 Y((1:numPos)' + NegsBefore) = Ipos; | |
98 Y(isnan(Y)) = Ineg; | |
99 | |
100 end |