含max函数的Contrastive loss梯度计算方法咨询
含max函数的对比损失函数梯度计算方法
给定对比损失函数:
L = y*d**2 + (1-y)*max(margin-d,0)**2
完全可以计算该损失的梯度。max函数虽在分段点(margin-d=0即d=margin)处不可导,但实际训练中取次梯度(通常选用单侧导数即可,不影响优化过程)即可,其余分段区域均为可导状态,下面分情况推导并给出numpy实现:
梯度推导(对d求导)
损失函数中y为二分类标签(取值0或1),d是样本对的距离,margin为预设超参数,分情况讨论梯度∂L/∂d:
当
y=1时:
损失简化为L = d²,直接求导得:∂L/∂d = 2*d当
y=0时:
损失简化为L = max(margin - d, 0)²,再细分两种场景:- 若
d ≤ margin:max(margin-d,0) = margin-d,损失为(margin-d)²,求导得:∂L/∂d = -2*(margin - d) - 若
d > margin:max(margin-d,0) = 0,损失为0,梯度为:∂L/∂d = 0
- 若
Numpy实现示例
针对批量样本场景,用numpy实现损失和梯度的计算:
import numpy as np def compute_contrastive_loss_and_grad(d, y, margin): # 计算批量损失 loss = y * d**2 + (1 - y) * np.maximum(margin - d, 0)**2 # 初始化梯度数组,形状与d一致 grad = np.zeros_like(d) # 处理y=1的样本 y1_indices = y == 1 grad[y1_indices] = 2 * d[y1_indices] # 处理y=0的样本 y0_indices = y == 0 # 子场景:d <= margin y0_d_le_margin = y0_indices & (d <= margin) grad[y0_d_le_margin] = -2 * (margin - d[y0_d_le_margin]) # 子场景:d > margin,梯度保持0即可,无需额外操作 return loss, grad
该函数支持批量输入(比如d是形状为(N,)的数组,对应N个样本对的距离;y是同形状的标签数组),输出对应批量的损失和梯度,和你之前用numpy计算简单函数梯度的逻辑一致。
内容的提问来源于stack exchange,提问作者parth percy
相关产品推荐
相关产品推荐

