Mercurial > hg > camir-ismir2012
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 |