简单梳理一下推荐场景常见的一些loss和,以及一些随笔
Binary Cross-Entropy Loss(BCE Loss):用于度量二元分类任务(即每个样本都只有两个类别)中的预测概率与实际标签之间的差异。BCE Loss 的计算公式如下:
其中,y 是实际的标签(0 或 1),p 是预测概率。当 y=1 时,损失计算为 -log(p);当 y=0 时,损失计算为 -log(1-p)。模型的目标是最小化损失,这将使预测的概率接近实际标签。
import tensorflow as tf
# 假设我们有一个二分类问题
labels = [1, 0, 1] # 实际标签
logits = [0.8, 0.3, 0.6] # 模型预测的概率
labels = tf.constant(labels, dtype=tf.float32)
logits = tf.constant(logits, dtype=tf.float32)
# 计算二元交叉熵损失
loss = tf.keras.losses.binary_crossentropy(labels, logits, from_logits=False)
print("Loss: ", loss.numpy())其中,from_logits=False表示我们的输出已经是概率分布(经过了softmax或sigmoid函数),如果from_logits=True,则表示输出是原始的logits,还没有经过softmax或sigmoid函数。
如果扩展成CE Loss,那么需要注意,输入的label需要是one-hot形式:
import tensorflow as tf
# 假设我们有一个二分类问题,且标签是one-hot编码的
labels = [[1, 0], [0, 1], [1, 0]] # 实际标签
logits = [[0.6, 0.4], [0.4, 0.6], [0.7, 0.3]] # 模型预测的概率
labels = tf.constant(labels, dtype=tf.float32)
logits = tf.constant(logits, dtype=tf.float32)
# 计算交叉熵损失
loss = tf.keras.losses.categorical_crossentropy(labels, logits, from_logits=False)
print("Loss: ", loss.numpy())注意,如果标签不是one-hot编码的,而是类别的整数编码,那么应该使用tf.keras.losses.sparse_categorical_crossentropy函数来计算交叉熵损失。
关于BCE 梯度消失:
《Understanding the Ranking Loss for Recommendation with Sparse User Feedback SIGKDD‘2024》
提到:在正样本稀疏的场景下BCE loss存在负样本导致梯度消失问题。
实证方法:BCE方法产生的负样本的梯度norms相比于Combined-Pair方法小的许多
解决方法:负样本会产生较大的梯度,因此引入排序loss(LTR)能够减轻仅使用BCE loss的优化困难,从而产生更好的效果。
梯度范数(Gradient Norms)是指梯度向量的范数(通常是L2范数),它衡量的是梯度向量的大小。具体来说,给定一个梯度向量 \mathbf{g} = [g_1, g_2, \ldots, g_n] ,其L2范数定义为:
梯度范数在深度学习中有重要的意义,因为它反映了梯度的整体大小。梯度范数的大小直接影响到参数更新的幅度,从而影响模型的训练过程。
为什么梯度范数可以衡量梯度消失
梯度消失问题是指在深度神经网络中,随着网络层数的增加,梯度在反向传播过程中逐渐变小,最终可能接近于零。这会导致参数更新非常缓慢,甚至停止更新,从而使得模型难以训练。通过观察梯度范数的变化,可以衡量梯度消失问题的严重程度:

Focal Loss是一种针对分类问题中类别不平衡的损失函数,在2017年的论文《Focal Loss for Dense Object Detection》中提出。Focal Loss如下:
其中:
简单说就是在CE的基础上加了-\alpha_t (1 - p_t)^{\gamma} 用来控制loss的权重,预测离label越近的样本(简单label),权重越低;反之则权重越重。从而实现让模型更加关注难样本。
注意:这里需要注意的是\alpha_t ,通常情况下,正样本是负样本少的,所以默认值是给0.25,但是有些时候如果正样本比负样本多了,这里要做相应的调整。
import tensorflow as tf
def focal_loss(labels, logits, alpha=0.25, gamma=2.0):
labels = tf.cast(labels, dtype=tf.float32)
logits = tf.cast(logits, dtype=tf.float32)
# 计算二元交叉熵损失
ce_loss = tf.keras.losses.binary_crossentropy(labels, logits, from_logits=True)
# 计算预测概率
pred_prob = tf.sigmoid(logits)
# 计算Focal Loss中的调制因子
modulating_factor = tf.pow(tf.abs(labels - pred_prob), gamma)
# 计算Focal Loss
loss = tf.reduce_mean(alpha * modulating_factor * ce_loss)
return loss
# 假设我们有一个二分类问题
labels = [1, 0, 1] # 实际标签
logits = [2.0, -1.0, 1.0] # 模型预测的logits
labels = tf.constant(labels, dtype=tf.float32)
logits = tf.constant(logits, dtype=tf.float32)
# 计算Focal Loss
loss = focal_loss(labels, logits)
print("Loss: ", loss.numpy())它用于对比学习(contrastive learning)任务,特别是在自监督学习(self-supervised learning)中。InfoNCE Loss 显示了两个随机变量之间的互信息估计。其计算公式如下:
其中,x_i 是输入样本,y_i 和 y_j分别是正样本(相似样本)和负样本(不相似样本)。函数 f(x, y) 表示 x 和 y 之间的相似度分数。τ 是温度系数,用于调节 softmax 函数的稀疏程度。上式分母中的sum是在1个正样本和k个负样本上做的,从0到k,所以共k+1个样本。
恺明大佬在MoCo里提到,InfoNCE loss其实就是一个cross entropy loss,做的是一个k+1类的分类任务,目的就是想把这个q图片分到K+这个类。
和CE区别:1. 加了一个温度系数τ。2. 分母不一样,CE是所有分类(K个),InfoNCE是所有负样本还加一个正样本(K+1)
和NCE区别:NCE是BCE形式,只区分噪声和非噪声数据。但是噪声不一定都是一个类,所以改成多分类就有了InfoNCE。类似于BCE和CE的区别,也就是二分类还是多分类。
Bayesian Personalized Ranking Loss(BPR Loss):它用于处理隐式反馈(例如用户与某个物品的交互记录)的推荐系统。BPR 旨在学习用户和物品之间的相对排序,通常用于pair-wise推荐。BPR Loss具有以下形式:
其中:
目标就是希望每一对正负样本中的正样本预估值要大于负样本的预估值。从公式看就是x_{ui} (正反馈)越大越好, x_{uj}(负反馈)越小越好。
Hinge Loss和BPR Loss差不多,一般都是用于pair-wise的任务中。其目标是最大化正确分类与错误分类之间的间隔。在多类别分类问题中,在二分类问题中,Hinge Loss 的定义如下:
在多类别分类问题中,Multiclass Hinge Loss 的计算公式如下:
其中:
Loss期望是正样本的分数高于负样本的分数至少一个固定的margin,这个margin大小是超参数,不太好拍,一般还是用BPR Loss叭~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。