当前位置: 首页 > article >正文

机器学习周报(11.18-11.24)

文章目录

摘要

本文总结了 PyTorch 中常见的损失函数与相似度度量的理论基础和实现方法,重点分析了交叉熵、信息熵、负对数似然(NLL)、KL 散度和余弦相似度的数学原理及其在深度学习中的应用场景。通过示例代码详细阐述了这些概念的 PyTorch 实现方式,帮助读者在理论与实践之间建立联系。

Abstract

This article summarizes the theoretical foundations and implementation methods of commonly used loss functions and similarity metrics in PyTorch, focusing on the mathematical principles of cross-entropy, entropy, negative log-likelihood (NLL), KL divergence, and cosine similarity, as well as their applications in deep learning. By presenting detailed example code, the article bridges the gap between theory and practice, helping readers gain a comprehensive understanding.

1 Corss Entropy Loss

1.1 介绍

参数:

在这里插入图片描述

  • weight:指定权重,(dim),可选参数,可以给每个类指定一个权重。通常在训练数据中不同类别的样本数量差别较大时,可以使用权重来平衡。
  • ignore_index:指定忽略一个真实值,(int),也就是手动忽略一个真实值。
  • reduction:在[none, mean, sum]中选,string型。none表示不降维,返回和target相同形状;mean表示对一个batch的损失求均值;sum表示对一个batch的损失求和

输入:
在这里插入图片描述
可以看到对于Target,是有两种情况的。如果Target是类别的索引,那么Target的shape是比Input的shape少了通道维;如果Target是类别的概率值,那么Target的shape是与Input的shape相同。具体可以看官网。

1.2 代码举例

import torch
import torch.nn as nn
import torch.nn.functional as F

# logits shape:[BS, NC]
batch_size = 2
num_class = 7

logits = torch.randn(batch_size, num_class)  # input unnormalized score
target_indices = torch.randint(num_class, size=(batch_size,))  # delta目标分布,是整形的索引 shape:(2,)
target_logits = torch.randn(batch_size, num_class)  # 非delta目标分布,概率分布 shape:[2,7]


ce_loss_fn = nn.CrossEntropyLoss()  # 实例化

## method 1 for CE loss
ce_loss = ce_loss_fn(logits, target_indices) 
print(f"cross entropy loss1: {ce_loss}")

## method 2 for CE loss
ce_loss = ce_loss_fn(logits, torch.softmax(target_logits, dim=-1))  
# 将target_logits 进行softmax在通道维上进行归一化成概率分布,和为1
print(f"cross entropy loss2: {ce_loss}")

输出结果均为标量:

cross entropy loss1: 3.269336700439453
cross entropy loss2: 2.0783615112304688

2 Negative Log Likelihood loss (NLL loss)

2.1 介绍

在这里插入图片描述
对于负对数似然Negative Log Likelihood loss(NLL loss)来说,input是每个类别的log-probabilities,而target只能为类别索引。实际上,能用cross entropy loss的地方就能用negative log-likelihood loss,这在后面的代码部分进行进一步验证。

2.2 代码举例

nll_fn = nn.NLLLoss()
nll_loss = nll_fn(torch.log(torch.softmax(logits, dim=-1)), target_indices)
print(f"negative log-likelihood loss: {nll_loss}")

​沿用上面初始化的logits,对其在通道维上进行softmax得到归一化概率值,再取对数,从而获得batch_size个样本的每个class的log-probabilities。target_indices是类别索引。

输出结果为标量:

negative log-likelihood loss: 3.269336700439453

​ 如果沿用上面CELoss的logitstarget_indices的初始化值,可以看到cross entropy loss1和negative log-likelihood loss的输出结果是相同的。说明cross entropy loss = s o f t m a x + l o g + n l l l o s s =softmax+log+nll loss =softmax+log+nllloss

3 Kullback-Leibler divergence loss (KL loss)

3.1 介绍

P、Q相当于两个系统,KL距离的定义为:

D K L ( P ∣ ∣ Q ) = ∑ x ∈ X P ( x ) l o g ( P ( x ) Q ( x ) ) D_{KL}(P||Q)=\sum_{x\in X}P(x)log(\frac{P(x)}{Q(x)}) DKL(P∣∣Q)=xXP(x)log(Q(x)P(x))

其中,P在前,即以P为基准,衡量Q相对于P来说的差距。如果P、Q两个系统分布相同,则 D K L ( P ∣ ∣ Q ) = 0 D_{KL}(P||Q)=0 DKL(P∣∣Q)=0。所以KL散度具有非负性。

在这里插入图片描述

​ 对于官网上的公式来说,P等价于 y t r u e y_{true} ytrue,Q等价于 y p r e d y_{pred} ypred

这里需要注意的是inputtarget的shape应该相同。而且,为了避免下溢的一些问题,期望 input是在log的空间传入进来的,而target可以是 log 空间,也可以是线性空间。

3.2 代码举例

kld_loss_fn = nn.KLDivLoss(reduction='mean')
kld_loss = kld_loss_fn(torch.log(torch.softmax(logits, dim=-1)), torch.softmax(target_logits, dim=-1))
print(f"Kullback-Leibler divergence loss : {kld_loss}")

输出结果为标量:

Kullback-Leibler divergence loss : 0.07705999910831451

4 验证 D K L ( P ∣ ∣ Q ) = H ( p , q ) − H ( p ) D_{KL}(P||Q)=H(p,q)-H(p) DKL(P∣∣Q)=H(p,q)H(p)

4.1 介绍

​ 首先从公式的角度来说明这个式子的正确性:

在这里插入图片描述
​ 这个公式的意思是p、q的KL散度=p、q的交叉熵 - p的信息熵。其中 p 的信息熵就是目标分布的信息熵。

4.2 代码验证

# 4.验证 CE = IE + KLD  交叉熵=信息熵+KL散度
# 交叉熵
ce_loss_fn_smaple = nn.CrossEntropyLoss(reduction="none")  # 能够输出每一个样本的loss,不进行平均
ce_loss_sample = ce_loss_fn_smaple(logits, torch.softmax(target_logits, dim=-1))  # (b,)
print(f"cross entropy loss sample: {ce_loss_sample}")

# KL散度
kld_loss_fn_sample = nn.KLDivLoss(reduction="none")
kld_loss_sample = kld_loss_fn_sample(torch.log(torch.softmax(logits, dim=-1)), torch.softmax(target_logits, dim=-1)).sum(-1)
print(f"Kullback-Leibler divergence loss sample: {kld_loss_sample}")

# 计算目标分布的信息熵
target_information_entropy = torch.distributions.Categorical(probs=torch.softmax(target_logits, dim=-1)).entropy()
print(f"information entropy sample: {target_information_entropy}")  # IE为常数,如果目标分布是delta分布,IE=0

# 验证 CE = IE + KLD 是否成立
print(torch.allclose(ce_loss_sample, kld_loss_sample + target_information_entropy))  # 比较两个浮点数

​ 输出结果如下

cross entropy loss sample: tensor([1.7736, 2.5585])
Kullback-Leibler divergence loss sample: tensor([0.1108, 1.1138])
information entropy sample: tensor([1.6628, 1.4447])
True

​可以看到,最终的输出结果为True,说明公式成立。值得一提的是,由于在数据集中的target是确定的,所以其信息熵也是确定的,为常数。所以优化交叉熵损失和KL散度损失是等价的,只是在数值上相差一个常数。

5 Binary Cross Entropy loss (BCE loss)

5.1 介绍

​以上所介绍的都常使用于多分类问题,BCE loss二项交叉熵适用于二分类问题。API中的公式如下:

l n = − w n [ y n ⋅ l o g ( x n ) + ( 1 − y n ) ⋅ l o g ( 1 − x n ) ] l_n = -w_n[y_n·log(x_n)+(1-y_n)·log(1-x_n)] ln=wn[ynlog(xn)+(1yn)log(1xn)]

要求TargetInput是相同的维度,对于target,数值应该在0-1之间。

5.2代码举例

# 5.调用Binary Cross Entropy loss (BCE loss) 二分类的损失函数

bce_loss_fn = nn.BCELoss()
logits = torch.randn(batch_size)
prob_1 = torch.sigmoid(logits)  # 使用sigmoid求出概率值
target = torch.randint(2, size=(batch_size,))  # 二分类,只有0和1
bce_loss = bce_loss_fn(prob_1, target.float())
print(f"binary Cross Entropy loss: {bce_loss}")


# 1) BCEWithLogitsLoss = sigmoid + BCELoss ,传入的未归一化的logits
bce_logits_loss_fn = nn.BCEWithLogitsLoss()
bce_logits_loss = bce_logits_loss_fn(logits, target.float())
print(f"binary Cross Entropy with logits loss: {bce_logits_loss}")
print(torch.allclose(bce_logits_loss, bce_loss))  # 比较两个浮点数


# 2) BCE Loss 是特殊的 NLL Loss
nll_fn = nn.NLLLoss()
prob_0 = 1 - prob_1.unsqueeze(-1)  # 在通道维升维 [BS, 1]
prob = torch.cat([prob_0, prob_1.unsqueeze(-1)], dim=-1)  # [BS, 2]
nll_loss_binary = nll_fn(torch.log(prob), target)
print(f"negative likelihood loss binary: {nll_loss_binary}")
print(torch.allclose(bce_loss, nll_loss_binary))  # 比较两个浮点数

输出结果如下:

binary Cross Entropy loss: 0.963399350643158
binary Cross Entropy with logits loss: 0.963399350643158
True
negative likelihood loss binary: 0.963399350643158
True

从输出结果中可以看出:

1)BCEWithLogitsLoss = sigmoid+BCELoss;
2)BCE Loss 是特殊的 NLL Loss,NLL Loss可以处理多分类问题,当目标只有0、1两个索引时,也可以处理二分类的情况。

6 Cosine Similarity Loss

6.1 介绍

Cosine Embedding Loss基于余弦相似度,从而评估两个输入的量是相似的还是不相似的。在对比学习、自监督学习、学习图片或文本的相似度、搜索引擎图片搜索等中大量应用。
在这里插入图片描述
​ 要求input1input2的shape相同,target的值为1或者-1。

6.2 代码举例

cosine_loss_fn = nn.CosineEmbeddingLoss()
v1 = torch.randn(batch_size, 512)
v2 = torch.randn(batch_size, 512)
target = torch.randint(2, size=(batch_size, )) * 2 - 1  # 只能是-1~1
cosine_loss = cosine_loss_fn(v1, v2, target)
print(f"cosine similarity loss: {cosine_loss}")

​ 输出结果为标量:

cosine similarity loss: 0.07631295919418335

总结

交叉熵 是多分类任务中最常用的损失函数,其核心是评估真实分布和预测分布的匹配程度。信息熵 衡量了分布的不确定性,通常用于分析概率分布的性质。负对数似然 专注于正确类别的预测概率,是交叉熵的重要组成部分,常与 log_softmax 配合使用。KL 散度 是两个分布之间的相对熵,用于知识蒸馏或分布匹配,能够有效衡量目标分布与预测分布的差异。余弦相似度 关注向量间的方向相似性,适用于特征匹配和相似性计算任务


http://www.kler.cn/a/411720.html

相关文章:

  • day05(单片机高级)PCB基础
  • 警钟长鸣,防微杜渐,遨游防爆手机如何护航安全生产?
  • 【CANOE】【Capl】【RS232】控制串口设备
  • D80【 python 接口自动化学习】- python基础之HTTP
  • 0BB定位胶具有优异的焊带粘接性和可靠性,助力客户降本增效
  • uniapp+vue2重新进入小程序就清除缓存,设备需要重新扫码
  • C++:final 关键字用于阻止类被继承或阻止虚函数被进一步重写
  • Node.js笔记(三)局域网聊天室构建1
  • 在 Taro 中实现系统主题适配:亮/暗模式
  • 自动驾驶系统研发系列—智能驾驶倒车盲区终结者:智能侧向警告与制动技术解析
  • MATLAB支持的距离度量
  • 【大数据技术基础】 课程 第8章 数据仓库Hive的安装和使用 大数据基础编程、实验和案例教程(第2版)
  • uniapp定义new plus.nativeObj.View实现APP端全局弹窗
  • MDETR - Modulated Detection for End-to-End Multi-Modal Understanding
  • STM32的AFIO讲解
  • Java 爬虫深度解析销量和商品详情数据获取
  • MongoDB 和 Redis 是两种不同类型的数据库比较
  • 探索Python的HTTP之旅:揭秘Requests库的神秘面纱
  • 【leetcode】全排列 回溯法
  • 高效制作定期Excel报表:自动化与模板化的策略
  • OpenCV 计算图像清晰度
  • 2024年第15届蓝桥杯C/C++组蓝桥杯JAVA实现
  • JavaApi.JDBC( 重点 )
  • 数据结构——用数组实现栈和队列
  • 鸿蒙操作系统(HarmonyOS)
  • html select下拉多选 修改yselect.js插件实现下拉多选,搜索,限制选中,默认回显等操作