forked from naver/cgd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevaluator.py
67 lines (56 loc) · 2.48 KB
/
evaluator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# -*- coding: utf-8 -*-
# Copyright 2019-present NAVER Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from tqdm import tqdm
import mxnet as mx
import numpy as np
class Evaluator(object):
def __init__(self, model, data_loader, ctx):
self.model = model
self.data_loader = data_loader
self.ctx = ctx
# Reference from Apache MXNet example code
# (https://github.com/apache/incubator-mxnet/blob/master/example/gluon/embedding_learning/train.py#L123)
def _evaluate_recall_at_k(self, d_mat, labels, ranks):
recall_at_ranks = []
for k in ranks:
correct, cnt = 0.0, 0.0
for i in range(d_mat.shape[0]):
d_mat[i, i] = 1e10
nns = np.argpartition(d_mat[i], k)[:k]
if any(labels[i] == labels[nn] for nn in nns):
correct += 1
cnt += 1
recall_at_ranks.append(correct/cnt)
return recall_at_ranks
def evaluate(self, ranks):
print('Extracting features...')
test_features, test_class_ids = [], []
for i, inputs in tqdm(enumerate(self.data_loader), total=len(self.data_loader)):
images, class_ids = inputs
features = self.model(images.as_in_context(self.ctx))
test_features.append(features.asnumpy())
test_class_ids.extend(class_ids.asnumpy())
test_features = np.concatenate(test_features)
test_class_ids = np.asarray(test_class_ids)
print('Computing distance matrix...')
sum_of_squares = np.sum(test_features ** 2.0, axis=1, keepdims=True)
d_mat = sum_of_squares + sum_of_squares.transpose() - (2.0 * np.dot(test_features, test_features.transpose()))
print('Evaluating...')
recall_at_ranks = self._evaluate_recall_at_k(d_mat, test_class_ids, ranks)
return recall_at_ranks