comparison toolboxes/distance_learning/mlr/mlr_test.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
comparison
equal deleted inserted replaced
-1:000000000000 0:cc4b1211e677
1 function Perf = mlr_test(W, test_k, Xtrain, Ytrain, Xtest, Ytest, Testnorm)
2 % Perf = mlr_test(W, test_k, Xtrain, Ytrain, Xtest, Ytest)
3 %
4 % W = d-by-d positive semi-definite matrix
5 % test_k = vector of k-values to use for KNN/Prec@k/NDCG
6 % Xtrain = d-by-n matrix of training data
7 % Ytrain = n-by-1 vector of training labels
8 % OR
9 % n-by-2 cell array where
10 % Y{q,1} contains relevant indices (in 1..n) for point q
11 % Y{q,2} contains irrelevant indices (in 1..n) for point q
12 % Xtest = d-by-m matrix of testing data
13 % Ytest = m-by-1 vector of training labels, or m-by-2 cell array
14 %
15 %
16 % The output structure Perf contains the mean score for:
17 % AUC, KNN, Prec@k, MAP, MRR, NDCG,
18 % as well as the effective dimensionality of W, and
19 % the best-performing k-value for KNN, Prec@k, and NDCG.
20 %
21
22 % addpath('cuttingPlane', 'distance', 'feasible', 'initialize', 'loss', ...
23 % 'metricPsi', 'regularize', 'separationOracle', 'util');
24
25 Perf = struct( ...
26 'AUC', [], ...
27 'KNN', [], ...
28 'PrecAtK', [], ...
29 'MAP', [], ...
30 'MRR', [], ...
31 'NDCG', [], ...
32 'dimensionality', [], ...
33 'KNNk', [], ...
34 'PrecAtKk', [], ...
35 'NDCGk', [] ...
36 );
37
38 [d, nTrain, nKernel] = size(Xtrain);
39 nTest = length(Ytest);
40 test_k = min(test_k, nTrain);
41
42 if nargin < 7
43 Testnorm = [];
44 end
45
46 % Compute dimensionality of the learned metric
47 Perf.dimensionality = mlr_test_dimension(W, nTrain, nKernel);
48
49
50 % Build the distance matrix
51 [D, I] = mlr_test_distance(W, Xtrain, Xtest, Testnorm);
52
53
54 % Compute label agreement
55 if ~iscell(Ytest)
56 Labels = Ytrain(I);
57 Agree = bsxfun(@eq, Ytest', Labels);
58
59 % We only compute KNN error if Y are labels
60 [Perf.KNN, Perf.KNNk] = mlr_test_knn(Labels, Ytest, test_k);
61 else
62 Agree = zeros(nTrain, nTest);
63 for i = 1:nTest
64 Agree(:,i) = ismember(I(:,i), Ytest{i,1});
65 end
66 Agree = reduceAgreement(Agree);
67 end
68
69 % Compute AUC score
70 Perf.AUC = mlr_test_auc(Agree);
71
72 % Compute MAP score
73 Perf.MAP = mlr_test_map(Agree);
74
75 % Compute MRR score
76 Perf.MRR = mlr_test_mrr(Agree);
77
78 % Compute prec@k
79 [Perf.PrecAtK, Perf.PrecAtKk] = mlr_test_preck(Agree, test_k);
80
81 % Compute NDCG score
82 [Perf.NDCG, Perf.NDCGk] = mlr_test_ndcg(Agree, test_k);
83
84 end
85
86
87 function [D,I] = mlr_test_distance(W, Xtrain, Xtest, Testnorm)
88
89 % CASES:
90 % Raw: W = []
91
92 % Linear, full: W = d-by-d
93 % Single Kernel, full: W = n-by-n
94 % MKL, full: W = n-by-n-by-m
95
96 % Linear, diagonal: W = d-by-1
97 % Single Kernel, diagonal: W = n-by-1
98 % MKL, diag: W = n-by-m
99 % MKL, diag-off-diag: W = m-by-m-by-n
100
101 [d, nTrain, nKernel] = size(Xtrain);
102 nTest = size(Xtest, 2);
103
104 if isempty(W)
105 % W = [] => native euclidean distances
106 D = mlr_test_distance_raw(Xtrain, Xtest, Testnorm);
107
108 elseif size(W,1) == d && size(W,2) == d
109 % We're in a full-projection case
110 D = setDistanceFullMKL([Xtrain Xtest], W, nTrain + (1:nTest), 1:nTrain);
111
112 elseif size(W,1) == d && size(W,2) == nKernel
113 % We're in a simple diagonal case
114 D = setDistanceDiagMKL([Xtrain Xtest], W, nTrain + (1:nTest), 1:nTrain);
115
116 elseif size(W,1) == nKernel && size(W,2) == nKernel && size(W,3) == nTrain
117 % We're in DOD mode
118 D = setDistanceDODMKL([Xtrain Xtest], W, nTrain + (1:nTest), 1:nTrain);
119
120 else
121 % Error?
122 error('Cannot determine metric mode.');
123
124 end
125
126 D = full(D(1:nTrain, nTrain + (1:nTest)));
127 [v,I] = sort(D, 1);
128 end
129
130
131
132 function dimension = mlr_test_dimension(W, nTrain, nKernel)
133
134 % CASES:
135 % Raw: W = []
136
137 % Linear, full: W = d-by-d
138 % Single Kernel, full: W = n-by-n
139 % MKL, full: W = n-by-n-by-m
140
141 % Linear, diagonal: W = d-by-1
142 % Single Kernel, diagonal: W = n-by-1
143 % MKL, diag: W = n-by-m
144 % MKL, diag-off-diag: W = m-by-m-by-n
145
146
147 if size(W,2) == nTrain
148 dim = [];
149 for i = 1:nKernel
150 [v,d] = eig(0.5 * (W(:,:,i) + W(:,:,i)'));
151 dim = [dim ; abs(real(diag(d)))];
152 end
153 else
154 dim = W(:);
155 end
156
157 cd = cumsum(dim) / sum(dim);
158 dimension = find(cd >= 0.95, 1);
159 if isempty(dimension)
160 dimension = 0;
161 end
162 end
163
164 function [NDCG, NDCGk] = mlr_test_ndcg(Agree, test_k)
165
166 nTrain = size(Agree, 1);
167
168 Discount = zeros(1, nTrain);
169 Discount(1:2) = 1;
170
171 NDCG = -Inf;
172 NDCGk = 0;
173 for k = test_k
174
175 Discount(3:k) = 1 ./ log2(3:k);
176 Discount = Discount / sum(Discount);
177
178 b = mean(Discount * Agree);
179 if b > NDCG
180 NDCG = b;
181 NDCGk = k;
182 end
183 end
184 end
185
186 function [PrecAtK, PrecAtKk] = mlr_test_preck(Agree, test_k)
187
188 PrecAtK = -Inf;
189 PrecAtKk = 0;
190 for k = test_k
191 b = mean( mean( Agree(1:k, :), 1 ) );
192 if b > PrecAtK
193 PrecAtK = b;
194 PrecAtKk = k;
195 end
196 end
197 end
198
199 function [KNN, KNNk] = mlr_test_knn(Labels, Ytest, test_k)
200
201 KNN = -Inf;
202 KNNk = 0;
203 for k = test_k
204 b = mean( mode( Labels(1:k,:), 1 ) == Ytest');
205 if b > KNN
206 KNN = b;
207 KNNk = k;
208 end
209 end
210 end
211
212 function MAP = mlr_test_map(Agree);
213
214 nTrain = size(Agree, 1);
215 MAP = bsxfun(@ldivide, (1:nTrain)', cumsum(Agree, 1));
216 MAP = mean(sum(MAP .* Agree, 1)./ sum(Agree, 1));
217 end
218
219 function MRR = mlr_test_mrr(Agree);
220
221 nTest = size(Agree, 2);
222 MRR = 0;
223 for i = 1:nTest
224 MRR = MRR + (1 / find(Agree(:,i), 1));
225 end
226 MRR = MRR / nTest;
227 end
228
229 function AUC = mlr_test_auc(Agree)
230
231 TPR = cumsum(Agree, 1);
232 FPR = cumsum(~Agree, 1);
233
234 numPos = TPR(end,:);
235 numNeg = FPR(end,:);
236
237 TPR = mean(bsxfun(@rdivide, TPR, numPos),2);
238 FPR = mean(bsxfun(@rdivide, FPR, numNeg),2);
239 AUC = diff([0 FPR']) * TPR;
240 end
241
242
243 function D = mlr_test_distance_raw(Xtrain, Xtest, Testnorm)
244
245 [d, nTrain, nKernel] = size(Xtrain);
246 nTest = size(Xtest, 2);
247
248 if isempty(Testnorm)
249 % Not in kernel mode, compute distances directly
250 D = 0;
251 for i = 1:nKernel
252 D = D + setDistanceDiag([Xtrain(:,:,i) Xtest(:,:,i)], ones(d,1), ...
253 nTrain + (1:nTest), 1:nTrain);
254 end
255 else
256 % We are in kernel mode
257 D = sparse(nTrain + nTest, nTrain + nTest);
258 for i = 1:nKernel
259 Trainnorm = diag(Xtrain(:,:,i));
260 D(1:nTrain, nTrain + (1:nTest)) = D(1:nTrain, nTrain + (1:nTest)) ...
261 + bsxfun(@plus, Trainnorm, bsxfun(@plus, Testnorm(:,i)', -2 * Xtest(:,:,i)));
262 end
263 end
264 end
265
266 function A = reduceAgreement(Agree)
267 nPos = sum(Agree,1);
268 nNeg = sum(~Agree,1);
269
270 goodI = find(nPos > 0 & nNeg > 0);
271 A = Agree(:,goodI);
272 end