推薦算法評估:precision ,recall,mrr,NDCG

ground_true 爲1 的情況:

recall=hit_rate

這時值的計算與你推薦個數多少無關,recall 又叫查全率,只要押中了,那就認爲單用戶命中率爲100%。

precision 和 topk 有關,單個用戶爲 命中個數/topk,與recall 成正比。

計算平均值時用,命中的用戶個數 / 總的用戶個數。

 

ground_truth 爲 多個 的情況:

recall:每個用戶的命中率爲,在你的候選推薦中,命中了多少個。單個用戶計算爲,命中個數(hitrate)/ 該用戶ground_truth個數

precision:爲查準率。單個用戶計算爲 命中個數 / topk .

計算平均值則將所有單個用戶相加 / user總個數

 

實現:

def precision_at_k_per_sample(actual, predicted, topk):
    num_hits = 0
    for place in predicted:
        if place in actual:
            num_hits += 1
    return num_hits / (topk + 0.0)
    # 一個準確率是,推薦的命中個數/topk

 

 


def precision_at_k(actual, predicted, topk):
    sum_precision = 0.0
    num_users = len(predicted) #用戶總個數
    for i in range(num_users):
        act_set = set(actual[i]) # ground truth 爲1,或者多個 
        pred_set = set(predicted[i][:topk])
        sum_precision += len(act_set & pred_set) / float(topk) # ground——truth 爲1或者多個 狀態下的準確率,求兩個set的交集即命中個數,除topk

    return sum_precision / num_users

 

 


def recall_at_k(actual, predicted, topk):
    sum_recall = 0.0
    num_users = len(predicted)
    true_users = 0
    for i in range(num_users):
        act_set = set(actual[i])
        pred_set = set(predicted[i][:topk])
        if len(act_set) != 0:
            sum_recall += len(act_set & pred_set) / float(len(act_set)) #也是命中個數 除以 ground-truth 的個數 求和後再除以用戶個數。
            true_users += 1
    return sum_recall / true_users

 

 


# 平均倒數排名, 即在第一個命中,得分爲1,第二個爲1/2, 第三個命中爲1/3,最後/topk,即推薦的個數
def mrr_at_k(actual, predicted, topk): # 這個只是考慮了一個用戶的狀況
    if len(predicted) > topk:
        predicted = predicted[:topk]

    score = 0.0

    for i, p in enumerate(predicted):  # i 是 p 的下標, p是 預測的值
        if p in actual and p not in predicted[:i]: # p在 ground truth 中,但在預測集中之前沒出現過,即去重。
            score += 1 / (i+1.0)  # 因爲下標所以要+1.0

    if not actual:
        return 0.0

    return score / min(len(actual), topk)

 

 


# 也只考慮了一個用戶的情況, 和mrr的區別僅在排序增益上, 分母取 ground truth 和topk 的較小值
def ndcg_at_k(actual, predicted, topk):
    if len(predicted) > topk:
        predicted = predicted[:topk]

    score = 0.0

    for i, p in enumerate(predicted):
        if p in actual and p not in predicted[:i]:
            score +=  1.0 / np.log2(i + 2.0)

    if not actual:
        return 0.0

    return score / min(len(actual), topk)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章