web-dev-qa-db-ja.com

Pythonの混同行列から適合率、再現率、およびf-measureを取得する方法

Pythonを使用していて、いくつかの混同行列があります。多クラス分類の混同行列によって精度と再現率、およびf-measureを計算したいと思います。結果ログにy_truey_predが含まれていません。 、混同行列を含めるだけです。

マルチクラス分類の混同行列からこれらのスコアを取得する方法を教えてください。

6
ryo

MNISTデータ分類(10クラス)の場合を考えてみましょう。10,000サンプルのテストセットに対して、次の混同行列cm(Numpy配列)が得られます。

array([[ 963,    0,    0,    1,    0,    2,   11,    1,    2,    0],
       [   0, 1119,    3,    2,    1,    0,    4,    1,    4,    1],
       [  12,    3,  972,    9,    6,    0,    6,    9,   13,    2],
       [   0,    0,    8,  975,    0,    2,    2,   10,   10,    3],
       [   0,    2,    3,    0,  953,    0,   11,    2,    3,    8],
       [   8,    1,    0,   21,    2,  818,   17,    2,   15,    8],
       [   9,    3,    1,    1,    4,    2,  938,    0,    0,    0],
       [   2,    7,   19,    2,    2,    0,    0,  975,    2,   19],
       [   8,    5,    4,    8,    6,    4,   14,   11,  906,    8],
       [  11,    7,    1,   12,   16,    1,    1,    6,    5,  949]])

適合率と再現率(クラスごと)を取得するには、クラスごとにTP、FP、およびFNを計算する必要があります。 TNは必要ありませんが、サニティチェックに役立つため、TNも計算します。

真のポジティブは、単に対角要素です。

# numpy should have already been imported as np
TP = np.diag(cm)
TP
# array([ 963, 1119,  972,  975,  953,  818,  938,  975,  906,  949])

誤検知は、それぞれの列の合計から対角要素(つまり、TP要素)を引いたものです。

FP = np.sum(cm, axis=0) - TP
FP
# array([50, 28, 39, 56, 37, 11, 66, 42, 54, 49])

同様に、False Negativesは、それぞれの行の合計から対角(つまり、TP)要素を引いたものです。

FN = np.sum(cm, axis=1) - TP
FN
# array([17, 16, 60, 35, 29, 74, 20, 53, 68, 60])

さて、真のネガティブは少しトリッキーです。まず、クラス0に関して、True Negativeが正確に何を意味するかを考えてみましょう。これは、0ではないとして正しく識別されたすべてのサンプルを意味します。したがって、基本的には、対応する行と列を混同行列から削除してから、残りのすべての要素を合計する必要があります。

num_classes = 10
TN = []
for i in range(num_classes):
    temp = np.delete(cm, i, 0)    # delete ith row
    temp = np.delete(temp, i, 1)  # delete ith column
    TN.append(sum(sum(temp)))
TN
# [8970, 8837, 8929, 8934, 8981, 9097, 8976, 8930, 8972, 8942]

サニティチェックを行いましょう:各クラスの場合、TP、FP、FN、およびTNの合計はテストセットのサイズ(ここでは10,000)と等しくなければなりません):これが実際に当てはまることを確認しましょう:

l = 10000
for i in range(num_classes):
    print(TP[i] + FP[i] + FN[i] + TN[i] == l)

結果は

True
True
True
True
True
True
True
True
True
True

これらの数量を計算すると、クラスごとの適合率と再現率を簡単に取得できるようになります。

precision = TP/(TP+FP)
recall = TP/(TP+FN)

この例では、

precision
# array([ 0.95064166,  0.97558849,  0.96142433,  0.9456838 ,  0.96262626,
#         0.986731  ,  0.93426295,  0.95870206,  0.94375   ,  0.9509018])

recall
# array([ 0.98265306,  0.98590308,  0.94186047,  0.96534653,  0.97046843,
#         0.91704036,  0.97912317,  0.94844358,  0.9301848 ,  0.94053518])

これで、混同行列の任意のサイズに対してこれらの量を仮想的に計算できるようになります。

13
desertnaut

次の形式の混同行列がある場合:

cmat = [[ 5,  7], 
        [25, 37]]

以下の簡単な関数を作成できます。

def myscores(smat): 
    tp = smat[0][0] 
    fp = smat[0][1] 
    fn = smat[1][0] 
    tn = smat[1][1] 
    return tp/(tp+fp), tp/(tp+fn)

テスト:

print("precision and recall:", myscores(cmat))

出力:

precision and recall: (0.4166666666666667, 0.16666666666666666)

上記の関数を拡張して他のスコアを生成することもできます。その式は https://en.wikipedia.org/wiki/Confusion_matrix に記載されています。

4
rnso