MAP @ k вычисление - PullRequest
       79

MAP @ k вычисление

0 голосов
/ 03 марта 2019

Средняя средняя точность, вычисленная при k (для топ-k элементов в ответе), в соответствии с wiki , ml метриками в kaggle и этим ответом: Путаница в отношении (средней) средней точности следует рассчитывать как среднее значение средней точности при k, где средняя точность при k вычисляется как:

enter image description here

Где: P (i) - точность при отсечении i в списке;rel (i) - это индикаторная функция, равная 1, если элемент в ранге i является релевантным документом, в противном случае - ноль.

Делитель min(k, number of relevant documents) имеет значение максимально возможного количества соответствующих записей в ответе.

Является ли это понимание правильным?

Всегда ли MAP @ k всегда меньше, чем MAP, вычисляемая для всего ранжированного списка?

Меня беспокоит то, что MAP @ k не таквычислено во многих работах.

Как правило, делителем является не min(k, number of relevant documents), а количество относительных документов в top-k .Этот подход даст более высокое значение MAP@k.


HashNet: глубокое обучение хешированию по продолжению "(ICCV 2017)

Код: https://github.com/thuml/HashNet/blob/master/pytorch/src/test.py#L42-L51

    for i in range(query_num):
        label = validation_labels[i, :]
        label[label == 0] = -1
        idx = ids[:, i]
        imatch = np.sum(database_labels[idx[0:R], :] == label, axis=1) > 0
        relevant_num = np.sum(imatch)
        Lx = np.cumsum(imatch)
        Px = Lx.astype(float) / np.arange(1, R+1, 1)
        if relevant_num != 0:
            APx.append(np.sum(Px * imatch) / relevant_num)

Где relevant_num - это не min(k, number of relevant documents), а количество соответствующих документов в результате, которое не совпадает с общим количеством относительных документов или k .

Я неправильно читаю код?


Глубокое визуально-семантическое квантование эффективного поиска изображений CVPR 2017

Код: https://github.com/caoyue10/cvpr17-dvsq/blob/master/util.py#L155-L178

def get_mAPs_by_feature(self, database, query):
    ips = np.dot(query.output, database.output.T)
    #norms = np.sqrt(np.dot(np.reshape(np.sum(query.output ** 2, 1), [query.n_samples, 1]), np.reshape(np.sum(database.output ** 2, 1), [1, database.n_samples])))
    #self.all_rel = ips / norms
    self.all_rel = ips
    ids = np.argsort(-self.all_rel, 1)
    APx = []
    query_labels = query.label
    database_labels = database.label
    print "#calc mAPs# calculating mAPs"
    bar = ProgressBar(total=self.all_rel.shape[0])
    for i in xrange(self.all_rel.shape[0]):
        label = query_labels[i, :]
        label[label == 0] = -1
        idx = ids[i, :]
        imatch = np.sum(database_labels[idx[0: self.R], :] == label, 1) > 0
        rel = np.sum(imatch)
        Lx = np.cumsum(imatch)
        Px = Lx.astype(float) / np.arange(1, self.R+1, 1)
        if rel != 0:
            APx.append(np.sum(Px * imatch) / rel)
        bar.move()
    print "mAPs: ", np.mean(np.array(APx))
    return np.mean(np.array(APx))

Где делитель rel, который вычисляется как np.sum(imatch), где imatch - двоичный вектор, который указывает, является ли запись релевантнойили нет. Проблема в том, что требуется только сначала R: imatch = np.sum(database_labels[idx[0: self.R], :] == label, 1) > 0. Таким образом, np.sum(imatch) даст количество соответствующих записей в возвращенном списке размером R, но не min(R, number of relevant entries). И обратите внимание, что значенияR используется в документе меньше, чем количество записей в БД.


глубокое изучение двоичных хеш-кодов дляБыстрое получение изображений (CVPR 2015)

Код: https://github.com/kevinlin311tw/caffe-cvprw15/blob/master/analysis/precision.m#L30-L55

    buffer_yes = zeros(K,1);
    buffer_total = zeros(K,1);
    total_relevant = 0;

    for j = 1:K
        retrieval_label = trn_label(y2(j));

        if (query_label==retrieval_label)
            buffer_yes(j,1) = 1;
            total_relevant = total_relevant + 1;
        end
        buffer_total(j,1) = 1;
    end

    % compute precision
    P = cumsum(buffer_yes) ./ Ns';

    if (sum(buffer_yes) == 0)
        AP(i) = 0;
    else
        AP(i) = sum(P.*buffer_yes) / sum(buffer_yes);
    end

Здесь делителем является sum(buffer_yes), который является числом относительных документов в возвращенномсписок размеров k , а не min(k, number of relevant documents).


«Контролируемое изучение семантики, сохраняющей глубокое хеширование» (TPAMI 2017)

Код: https://github.com/kevinlin311tw/Caffe-DeepBinaryCode/blob/master/analysis/precision.m

Код такой же, как и в предыдущей статье.


Обучение компактным двоичным дескрипторам с неконтролируемой глубинойНейронные сети (CVPR 2016)

Тот же код: https://github.com/kevinlin311tw/cvpr16-deepbit/blob/master/analysis/precision.m#L32-L55



Я что-то упустил?Правильно ли указан код в приведенных выше документах?Почему он не совпадает с https://github.com/benhamner/Metrics/blob/master/Python/ml_metrics/average_precision.py#L25-L39?


Обновление

Я обнаружил эту закрытую проблему, ссылаясь на ту же проблему: https://github.com/thuml/HashNet/issues/2

Isутверждать, что следующая заявка верна?

AP является метрикой рейтинга.Если 2 верхних поиска в ранжированном списке являются релевантными (и только 2 верхними), AP составляет 100%.Вы говорите о Recall, который в данном случае действительно равен 0,2%.

Насколько я понимаю, если мы рассматриваем AP как область под кривой PR, приведенное выше утверждение неверно.


PS Я сомневался, стоит ли переходить к перекрестной проверке или к StackOverflow.Если вы думаете, что лучше поместить его в Cross Validated, я не возражаю.Мое рассуждение состояло в том, что это не теоретический вопрос, а вопрос реализации со ссылкой на реальный код.

1 Ответ

0 голосов
/ 03 марта 2019

Вы совершенно правы и молодцы, что нашли это.Учитывая сходство кода, я предполагаю, что есть одна ошибка в исходном коде, а затем бумаги после того, как бумаги скопировали плохую реализацию, не рассматривая ее внимательно.

Средство определения проблемы "akturtle" также совершенно верно, я собиралсяприведи тот же пример.Я не уверен, что «кунхэ» понял аргумент, конечно, при вычислении средней точности имеет значение отзыв.

Да, ошибка должна увеличивать цифры.Я просто надеюсь, что рейтинговые списки достаточно длинные и что методы достаточно разумны, так что они достигают 100% отзыва в ранжированном списке, и в этом случае ошибка не повлияет на результаты.

К сожалению, это трудно длярецензенты поймут это, как правило, никто не рецензирует код статьи. Стоит связаться с авторами, чтобы попытаться заставить их обновить код, обновить их статьи правильными номерами или, по крайней мере, не продолжать повторять ошибку в своих будущих работах.,Если вы планируете написать статью, сравнивающую различные методы, вы можете указать на проблему и сообщить правильные цифры (а также, возможно, те, которые содержат ошибку, только для того, чтобы сделать яблоки для сравнения яблок).

Чтобы ответитьВаш дополнительный вопрос:

Всегда ли MAP @ k всегда меньше, чем MAP, вычисляемая для всего ранжированного списка?

Не обязательно, MAP @ k по существу вычисляет MAP при нормализациидля потенциального случая, когда вы не можете сделать что-либо лучше, учитывая только k поисков.Например, рассмотрите возвращенный ранжированный список с релевантностями: 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 и предположите, что в общей сложности 6 соответствующих документов.MAP должен быть немного выше, чем 50%, в то время как MAP @ 3 = 100%, потому что вы не можете сделать ничего лучше, чем извлечь 1 1 1. Но это не связано с обнаруженной вами ошибкой, так как с их ошибкой MAP @ k гарантируетсябыть как минимум таким же большим, как истинный MAP@k.

...