こしあん
2020-04-03

物体検出で使うMean Average PrecisionをNumpyで実装する


5.6k{icon} {views}


物体検出でよく使われる評価指標・Mean Average Precision(mAP)をNumpyで実装しました。計算に癖があるので注意が必要です。

目次

参考記事

こちらの記事がとてもわかりやすいので参考にしました。これをもとに実装しました。

【物体検出】mAP ( mean Average Precision ) の算出方法

コード

import numpy as np

def mean_average_precision(y_true, y_pred):
    average_precisions = []
    # クラス単位でAPを計算
    for i in range(len(y_true)):
        sort_idx = np.argsort(y_pred[i])[::-1]
        y_true_sorted = y_true[i][sort_idx]

        cumsum = np.cumsum(y_true_sorted)
        recall = cumsum / np.max(cumsum)
        precision = cumsum / np.arange(1, 1 + y_true[i].shape[0])

        # 代表点
        points_x = np.arange(11) / 10
        points_y = np.zeros(points_x.shape[0])
        for i in range(points_x.shape[0]-1, -1, -1):
            points_y[i] = np.max(precision[recall >= points_x[i]])

        average_precision = np.mean(points_y)
        average_precisions.append(average_precision)
    return average_precisions

if __name__ == "__main__":
    # 1クラスの場合
    # Correct or not
    y_true = [np.array([1, 1, 0, 0, 0, 1, 1, 0, 0, 1], dtype=np.float32)]
    # Confidence score
    y_pred = [np.array([.96, .92, .89, .88, .84, .83, .80, .78, .74, .72], dtype=np.float32)]
    # クラス単位のAverage Precision
    class_ap = mean_average_precision(y_true, y_pred)

参考記事と同じ例を使っています。y_trueは該当のBounding Boxが与えられたクラスなのかどうか(Yesなら1、Noなら0)、y_predは信頼度(Confidence Score)を示します。y_predは画像分類でいうところのソフトマックスの確率にあたるでしょう。y_predはソートされていなくてもOKです。

物体検出のMean Average Precisionは、普通のRecision-Recallカーブから計算するもの(例えば、sklearn.metrics.average_precision_score)と異なり、Max precision to the rightというようなPrecision-Recallカーブのジグザクの補完処理が入ります。そのため、Sklearnの当該関数とは異なった値が出てきます。ソートされたものに対して累積和を取ればいいですね。

この結果は、次のようになります。

[0.7532467532467532]

これはクラス単位(この例では1クラス)のAverage Precisionなので、最終的にこのリストに対して平均を取ればMean Average Precisionになります。



Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です