annotate toolboxes/distance_learning/mlr/separationOracle/separationOracleMAP.m @ 0:cc4b1211e677 tip

initial commit to HG from Changeset: 646 (e263d8a21543) added further path and more save "camirversion.m"
author Daniel Wolff
date Fri, 19 Aug 2016 13:07:06 +0200
parents
children
rev   line source
Daniel@0 1 function [Y, Loss] = separationOracleMAP(q, D, pos, neg, k)
Daniel@0 2 %
Daniel@0 3 % [Y,Loss] = separationOracleMAP(q, D, pos, neg, k)
Daniel@0 4 %
Daniel@0 5 % q = index of the query point
Daniel@0 6 % D = the current distance matrix
Daniel@0 7 % pos = indices of relevant results for q
Daniel@0 8 % neg = indices of irrelevant results for q
Daniel@0 9 % k = length of the list to consider (unused in MAP)
Daniel@0 10 %
Daniel@0 11 % Y is a permutation 1:n corresponding to the maximally
Daniel@0 12 % violated constraint
Daniel@0 13 %
Daniel@0 14 % Loss is the loss for Y, in this case, 1-AP(Y)
Daniel@0 15
Daniel@0 16
Daniel@0 17 % First, sort the documents in descending order of W'Phi(q,x)
Daniel@0 18 % Phi = - (X(q) - X(x)) * (X(q) - X(x))'
Daniel@0 19
Daniel@0 20 % Sort the positive documents
Daniel@0 21 ScorePos = - D(pos,q);
Daniel@0 22 [Vpos, Ipos] = sort(full(ScorePos'), 'descend');
Daniel@0 23 Ipos = pos(Ipos);
Daniel@0 24
Daniel@0 25 % Sort the negative documents
Daniel@0 26 ScoreNeg = - D(neg,q);
Daniel@0 27 [Vneg, Ineg] = sort(full(ScoreNeg'), 'descend');
Daniel@0 28 Ineg = neg(Ineg);
Daniel@0 29
Daniel@0 30 % Now, solve the DP for the interleaving
Daniel@0 31
Daniel@0 32 numPos = length(pos);
Daniel@0 33 numNeg = length(neg);
Daniel@0 34 n = numPos + numNeg;
Daniel@0 35
Daniel@0 36
Daniel@0 37 % Pre-generate the precision scores
Daniel@0 38 % H = triu(1./bsxfun(@minus, (0:(numPos-1))', 1:n));
Daniel@0 39 H = tril(1./bsxfun(@minus, 0:(numPos-1), (1:n)'));
Daniel@0 40
Daniel@0 41 % Padded cumulative Vneg
Daniel@0 42 pcVneg = cumsum([0 Vneg]);
Daniel@0 43
Daniel@0 44 % Generate the discriminant scores
Daniel@0 45 H = H + scoreChangeMatrix(Vpos, Vneg, n, pcVneg);
Daniel@0 46
Daniel@0 47 % Cost of inserting the first + at position b
Daniel@0 48 P = zeros(size(H));
Daniel@0 49
Daniel@0 50 % Now recurse
Daniel@0 51 for a = 2:numPos
Daniel@0 52
Daniel@0 53 % Fill in the back-pointers
Daniel@0 54 [m,p] = cummax(H(:,a-1));
Daniel@0 55 % The best point is the previous row, up to b-1
Daniel@0 56 H(a:n,a) = H(a:n,a) + (a-1)/a .* m(a-1:n-1)';
Daniel@0 57 P(a+1:n,a) = p(a:n-1);
Daniel@0 58 P(a,a) = a-1;
Daniel@0 59 end
Daniel@0 60
Daniel@0 61 % Now reconstruct the permutation from the DP table
Daniel@0 62 Y = nan * ones(n,1);
Daniel@0 63 [m,p] = max(H(:,numPos));
Daniel@0 64 Y(p) = Ipos(numPos);
Daniel@0 65
Daniel@0 66 for a = numPos:-1:2
Daniel@0 67 p = P(p,a);
Daniel@0 68 Y(p) = Ipos(a-1);
Daniel@0 69 end
Daniel@0 70 Y(isnan(Y)) = Ineg;
Daniel@0 71
Daniel@0 72 % Compute loss for this list
Daniel@0 73 Loss = 1 - AP(Y, pos);
Daniel@0 74 end
Daniel@0 75
Daniel@0 76 function C = scoreChangeMatrix(Vpos, Vneg, n, pcVneg)
Daniel@0 77 numNeg = length(Vneg);
Daniel@0 78 numPos = length(Vpos);
Daniel@0 79
Daniel@0 80 % Inserting the a'th relevant document at position b
Daniel@0 81 % There are (b - (a - 1)) negative docs before a
Daniel@0 82 % And (numNeg - (b - (a - 1))) negative docs after
Daniel@0 83 %
Daniel@0 84 % The change in score is proportional to:
Daniel@0 85 %
Daniel@0 86 % sum_{negative j} (Vpos(a) - Vneg(j)) * y_{aj}
Daniel@0 87 %
Daniel@0 88 % = (numNeg - (b - (a - 1))) * Vpos(a) # Negatives after a
Daniel@0 89 % - (cVneg(end) - cVneg(b - (a - 1))) Weight of negs after a
Daniel@0 90 % - (b - (a - 1)) * Vpos(a) # Negatives before a
Daniel@0 91 % + cVneg(b - (a - 1)) Weight of negs before a
Daniel@0 92 %
Daniel@0 93 % Rearrange:
Daniel@0 94 %
Daniel@0 95 % (numNeg - 2 * (b - a + 1)) * Vpos(a)
Daniel@0 96 % - cVneg(end) + 2 * cVneg(b - a + 1)
Daniel@0 97 %
Daniel@0 98 % Valid range of a: 1:numPos
Daniel@0 99 % Valid range of b: a:n
Daniel@0 100
Daniel@0 101 D = bsxfun(@plus, 1-(1:numPos), (1:n)');
Daniel@0 102 C = numNeg - 2 * D;
Daniel@0 103 C = bsxfun(@times, Vpos, C);
Daniel@0 104
Daniel@0 105 D(D < 1) = 1;
Daniel@0 106 D(D > length(pcVneg)) = length(pcVneg);
Daniel@0 107
Daniel@0 108 % FIXME: 2011-01-28 21:13:37 by Brian McFee <bmcfee@cs.ucsd.edu>
Daniel@0 109 % brutal hack to get around matlab's screwy matrix reshaping
Daniel@0 110 if numPos == 1
Daniel@0 111 pcVneg = pcVneg';
Daniel@0 112 end
Daniel@0 113
Daniel@0 114 C = C + 2 * pcVneg(D) - pcVneg(end);
Daniel@0 115
Daniel@0 116 % Normalize
Daniel@0 117 C = bsxfun(@ldivide, (1:numPos) * numNeg, C);
Daniel@0 118
Daniel@0 119 % -Inf out the infeasible regions
Daniel@0 120 C = C - triu(Inf * bsxfun(@gt, (1:numPos), (1:n)'),1);
Daniel@0 121
Daniel@0 122
Daniel@0 123 end
Daniel@0 124
Daniel@0 125 function x = AP(Y, pos)
Daniel@0 126 % Indicator for relevant documents
Daniel@0 127 rel = ismember(Y, pos);
Daniel@0 128
Daniel@0 129 % Prec@k for all k
Daniel@0 130 Prec = cumsum(rel)' ./ (1:length(Y));
Daniel@0 131
Daniel@0 132 % Prec@k averaged over relevant positions
Daniel@0 133 x = mean(Prec(rel));
Daniel@0 134 end