【0】推荐系统中评价指标

1、离线评估

在推荐系统的评估过程中,离线评估往往被当做最常用也是最基本的评估方法。顾名思义,离线评估是指在将模型部署于线上环境之前,在离线环境中进行的评估。由于不用部署到生产环境,离线评估没有线上部署的工程风险,也无须浪费宝贵的线上流量资源,而且具有测试时间短,同时进行多组并行测试、能够利用丰富的线下计算资源等诸多优点。

一个好的推荐系统,除了准确度外,还需要对内容的覆盖度,推荐的内容的多样性,新颖性,是否能给用户带来惊喜等。这些标准之间不一定是相互正向作用,有些标准之间存在一定的矛盾性,比如新颖性和惊喜可能会带来覆盖度的提升,但对准确度可能有一定损耗。有些标准,如新颖性和惊喜度,量化指标需根据具体业务场景制定,而准确度的度量,业绩基本使用AUC这个指标,或者是基于AUC优化后的指标。

2、评估指标

2.1、图表

注意P=TP+FN表示实际为正例的样本个数,N=FP+TN表示实际为负例的样本个数。 

2.2、几个指标的定义:

正确率是一个很好很直观的评价指标,但是有时候正确率高并不能代表一个算法就好。比如某个地区某天地震的预测,假设我们有一堆的特征作为地震分类的属性,类别只有两个:0:不发生地震、1:发生地震。一个不加思考的分类器,对每一个测试用例都将类别划分为0,那那么它就可能达到99%的正确率,但真的地震来临时,这个分类器毫无察觉,这个分类带来的损失是巨大的。为什么99%的正确率的分类器却不是我们想要的,因为这里数据分布不均衡,类别1的数据太少,完全错分类别1依然可以达到很高的正确率却忽视了我们关注的东西。

(1)正确率/准确率(accuracy) = 所有预测正确的样本数量 /总样本数量,即 (TP+TN) / (P+N)。就是被分对的样本数除以所有的样本数,通常来说,正确率越高,分类器越好;Accuracy = (TP + TN) / (TP + TN + FP + FN)

(2)精确率(precision) = 预测正确的正类样本数量 / 预测为正类的样本数量 ,TP/(TP+FP),即预测为正的样本中,真正的正类占比。表示被分为正例的示例中实际为正例的比例。Precision = TP / (TP + FP)        

(3)召回率(recall) = 预测正确的正类样本数量 / 实际为正类的样本数量 TP/(TP+FN),即所有正类中,正确预测的占比。召回率是覆盖面的度量,度量有多个正例被分为正例。Recall = TP / (TP + FN)

精确率是分类正确的正样本个数占分类器判定为正样本的样本个数的比例。召回率是分类正确的正样本个数占真正的正样本个数的比例。排序模型中,通常没有一个确定的阈值把预测结果直接判定为正样本或负样本,而是采用TopN排序结果的精确率和召回率来衡量排序模型的性能,即认为模型排序的TopN的结果即是模型判定的正样本,然后计算Precision@N和Recall@N。

(4)F1值 = 精确率 * 召回率 * 2 / (精确率 + 召回率) (F 值即为精确率和召回率的调和均值)。精确率和召回率是矛盾统一的两个指标,为提高精确率,分类器需要尽量在“更有把握时”才把样本预测为正样本,但往往会因过于保守而漏掉很多“没有把握”的正样本导致召回率降低。F1 = 2 * (Precision * Recall) / (Precision + Recall)

(5)对数损失

 

2.3 AUC和ROC

AUC是ROC曲线下面积(Area Under roc Curve)的简称,顾名思义,AUC的值就是处于ROC curve下方的那部分面积的大小。通常,AUC的值介于0.5到1.0之间,AUC越大,诊断准确性越高。在ROC曲线上,最靠近坐标图左上方的点为敏感性和特异性均较高的临界值。

(1)ROC曲线

ROC曲线的横坐标为False Positive Rate(FPR,假阳性率);纵坐标为True Positive Rate(TPR,真阳性率)。FPR和TPR的计算方法如下:

 (2)AUC

1、 AUC作为指标衡量模型时,不依赖于分类阈值的选取,而准确率、精确率、召回率、F1值对阈值的选取依赖大,不同的阈值会带来不同的结果,而从AUC的定义(ROC的生成)知道,AUC是根据所有分类阈值得到的,因此比单独依赖一个分类阈值的指标更有优势。AUC体现的是对样本的排序能力,与具体的分值无关,和推荐系统中的大多数业务场景更贴合,因为大多数业务场景关心item之间的相对序而不关心item的预测分。AUC对正负样本比例不敏感,也是它在业界被广泛使用的原因。公式如下:

2、举例说明

在给出的例子中,包含有2个正样本(A, B)和3个负样本(C, D, E),因此一共有6个(2*3)正负样本对,即公式中分母为6。接下来计算公式中的分子,即每个正负样本对的指示函数值:以A为正样本形成的正负样本对为(A, C), (A, D), (A, E),指示函数值分别为1,0.5,0;以B为正样本形成的正负样本对为(B, C), (B, D), (B, E),指示函数值分别为1,1,1。

 3、代码实现

import numpy as np
from sklearn.metrics import roc_auc_score


def get_auc(y_lables, y_scores):
    auc = roc_auc_score(y_lables, y_scores)
    print('AUC calculated by sklearn tools is {}'.format(auc))
    return auc


def calculate_auc_func1(y_labels, y_scores):
    pos_sample_ids = [i for i in range(len(y_labels)) if y_labels[i] == 1]
    neg_sample_ids = [i for i in range(len(y_labels)) if y_labels[i] == 0]

    sum_indicator_value = 0
    for i in pos_sample_ids:
        for j in neg_sample_ids:
            if y_scores[i] > y_scores[j]:
                sum_indicator_value += 1
            elif y_scores[i] == y_scores[j]:
                sum_indicator_value += 0.5

    auc = sum_indicator_value / (len(pos_sample_ids) * len(neg_sample_ids))
    print("AUC calculated by func1 is {}".format(auc))
    return auc


def calculate_auc_func2(y_labels, y_scores):
    samples = list(zip(y_scores, y_labels))
    rank = [(label, score) for label, score in sorted(samples, key=lambda x: x[0])]
    pos_rank = [i + 1 for i in range(len(rank)) if rank[i][1] == 1]
    pos_cnt = np.sum(y_labels == 1)
    neg_cnt = np.sum(y_labels == 0)
    auc = (np.sum(pos_rank) - (pos_cnt * (pos_cnt + 1) / 2)) / (pos_cnt * neg_cnt)
    print("AUC calculated by func2 is {}".format(auc))
    return auc


if __name__ == '__main__':
    y_labels = np.array([1, 1, 0, 0, 0])
    y_scores = np.array([0.4, 0.8, 0.2, 0.4, 0.5])
    get_auc(y_labels, y_scores)
    calculate_auc_func1(y_labels, y_scores)
    calculate_auc_func2(y_labels, y_scores)

2.4、举例 

1、准确率和召回率

2.5、二分类准确率/正确率

公式:accuracy = (正确预测的样本数量) / (总样本数量)

# 二分类准确率pytorch代码和公式
# accuracy = (正确预测的样本数量) / (总样本数量)

import torch


def binary_accuracy(y_pred, y_true):
    rounded_preds = torch.round(torch.sigmoid(y_pred))
    correct = (rounded_preds == y_true).float().sum()
    accuracy = correct / y_true.size(0)
    return accuracy


# 示例数据
y_pred = torch.tensor([0.2, 0.8, 0.6, 0.3])  # 模型的预测概率
y_true = torch.tensor([0, 1, 1, 0])  # 真实的目标标签

accuracy = binary_accuracy(y_pred, y_true)
print("Binary Accuracy:", accuracy.item())

2.6、召回率

import torch
from sklearn.metrics import recall_score


def recall_score_fun(y_pred, y_true):
    rounded_preds = torch.round(torch.sigmoid(y_pred))
    true_positives = torch.sum((rounded_preds == 1) & (y_true == 1)).float()
    false_negatives = torch.sum((rounded_preds == 0) & (y_true == 1)).float()
    recall = true_positives / (true_positives + false_negatives)
    return recall


# todo 方式一(一直为1)
y_pred = torch.tensor([0.8, 0.1, 0.6, 0.8])  # 模型的预测概率
y_true = torch.tensor([0, 1, 1, 1])  # 真实的目标标签

recall = recall_score_fun(y_pred, y_true)
print("Recall:", recall.item())

# 将张量转换为NumPy数组,方式二
y_pred_np = y_pred.numpy()
y_true_np = y_true.numpy()

recall = recall_score(y_true_np, y_pred_np.round())
print("Recall:", recall)

2.7、精确率

import torch
from sklearn.metrics import precision_score


def precision_score_fun(y_pred, y_true):
    rounded_preds = torch.round(torch.sigmoid(y_pred))
    true_positives = torch.sum((rounded_preds == 1) & (y_true == 1)).float()
    false_positives = torch.sum((rounded_preds == 1) & (y_true == 0)).float()
    precision = true_positives / (true_positives + false_positives) if (true_positives + false_positives) != 0 else 0.0
    return precision


# 方式一
y_pred = torch.tensor([0.2, 0.8, 0.6, 0.3])  # 模型的预测概率
y_true = torch.tensor([1, 0, 1, 1])  # 真实的目标标签

precision = precision_score_fun(y_pred, y_true)
print("Precision:", precision.item())

# 方式二
y_pred_np = y_pred.numpy()
y_true_np = y_true.numpy()

precision = precision_score(y_true_np, y_pred_np.round())
print("Precision:", precision)

2.8、F1

import torch
from sklearn.metrics import f1_score


def f1_score_fun(y_pred, y_true):
    rounded_preds = torch.round(torch.sigmoid(y_pred))
    true_positives = torch.sum((rounded_preds == 1) & (y_true == 1)).float()
    false_positives = torch.sum((rounded_preds == 1) & (y_true == 0)).float()
    false_negatives = torch.sum((rounded_preds == 0) & (y_true == 1)).float()

    precision = true_positives / (true_positives + false_positives) if (true_positives + false_positives) != 0 else 0.0
    recall = true_positives / (true_positives + false_negatives) if (true_positives + false_negatives) != 0 else 0.0

    f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) != 0 else 0.0
    return f1


# 方式一
y_pred = torch.tensor([0.2, 0.8, 0.6, 0.3])  # 模型的预测概率
y_true = torch.tensor([0, 1, 1, 0])  # 真实的目标标签

f1 = f1_score_fun(y_pred, y_true)
print("F1 Score:", f1.item())

# 方式二
y_pred_np = y_pred.numpy()
y_true_np = y_true.numpy()

f1 = f1_score(y_true_np, y_pred_np.round())
print("F1 Score:", f1)

参考:

推荐系统评测指标—准确率(Precision)、召回率(Recall)、F值(F-Measure) - 茄子_2008 - 博客园

CTR预估和auc的渊源 - 知乎

分类指标准确率(Precision)和正确率(Accuracy)的区别_青椒炒代码的博客-CSDN博客_precision分类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值