【機器學習】Rank 中使用的指標及示例代碼

作者:LogM

本文原載於 https://segmentfault.com/u/logm/articles ,不允許轉載~

1. P@K

P@K,代表前 K 個預測值中有多少的準確率 (Precision)。

比如,一個模型輸出了一組排序,其輸出的好壞依次爲:好、壞、好、壞、好。

那麼,

Prec@3 = 2/3

Prec@4 = 2/4

Prec@5 = 3/5

def precision(gt, pred, K):
    """ Computes the average precision.
        gt: list, ground truth, all relevant docs' index
        pred: list, prediction
    """
    hit_num = len(gt & set(pred[:K]))
    return float(1.0 * hit_num / K)

2. MAP

AP 是 average precision 的縮寫,計算方式是把所有相關文檔的 P@K 求平均。

借用上面的例子,一個模型輸出了一組排序,依次爲:好的結果、壞的結果、好的結果、壞的結果、好的結果。

那麼,

AP = (1/1 + 2/3 + 3/5) / 3 = 0.76

注意,不是 (1/1 + 1/2 + 2/3 + 2/4 + 3/5) / 5。因爲在實際情況中,總有一些"好的結果"是模型漏召回的,指標的計算公式應該怎麼處理這部分漏召回?

AP 會把所有"好的結果"都算上,但是排序模型可能會對某些"好的結果"漏召回,這些"漏召回"的 P@K 視爲0。

MAP 是 mean average precision 的縮寫,就是把所有的 AP 求平均。

def average_precision(gt, pred):
    """ Computes the average precision.
        gt: list, ground truth, all relevant docs' index
        pred: list, prediction
    """
    if not gt:
        return 0.0

    score = 0.0
    num_hits = 0.0
    for i, p in enumerate(pred):
        if p in gt and p not in pred[:i]:
            num_hits += 1.0
            score += num_hits / (i + 1.0)

    return score / max(1.0, len(gt))

3. MRR

某些場景下,每個問題只有一個標準答案,我們只關心標準答案的排序位置。此時,我們是把標準答案在模型輸出結果中的排序取倒數作爲它的 RR (Reciprocal Rank)。

比如,模型的輸出一組排序,依次爲:非標準答案,標準答案,非標準答案,非標準答案

那麼:

RR = 1/2

對所有的問題取平均,得到 MRR (Mean Reciprocal Rank)。

def reciprocal_rank(gt, pred):
    """ Computes the reciprocal rank.
        gt: list, ground truth, all relevant docs' index
        pred: list, prediction
    """
    if not gt:
        return 0.0

    score = 0.0
    for rank, item in enumerate(pred):
        if item in gt:
            score = 1.0 / (rank + 1.0)
            break
    return score

4. NDCG

這塊涉及到一些數學公式,我懶得打了,可以谷歌到。直接看下面的代碼來理解估計會更清楚一些。

DCG: Discounted Cumulative Gain

IDCG: ideal DCG,是 ground truth 情況下的 DCG

NDCG: normalized DCG,是 DCG 和 IDCG 相除

NDCG = DCG / IDCG

def NDCG(gt, pred, use_graded_scores=False):
    """ Computes the NDCG.
        gt: list, ground truth, all relevant docs' index
        pred: list, prediction
    """
    score = 0.0
    for rank, item in enumerate(pred):
        if item in gt:
            if use_graded_scores:
                grade = 1.0 / (gt.index(item) + 1)
            else:
                grade = 1.0
            score += grade / np.log2(rank + 2)

    norm = 0.0
    for rank in range(len(gt)):
        if use_graded_scores:
            grade = 1.0 / (rank + 1)
        else:
            grade = 1.0
        norm += grade / np.log2(rank + 2)
    return score / max(0.3, norm)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章