Pytorch中常见的损失函数的原理

Pytorch中常见的损失函数的原理及代码示例

本文介绍在pytorch中常用的几种损失函数的原理及代码示例,以方便后续自查,但本文未对其中的数学原理进行详细介绍,后续有需要可再进行补充。

1. MSE Loss

均方损失函数,适用于回归任务。一般损失函数都是计算一个 batch 数据总的损失,而不是计算单个样本的损失。

计算公式:
ℓ ( x , y ) = L = { l 1 , … , l N } ⊤ , l n = ( x n − y n ) 2 \begin{equation} \ell(x, y)=L=\left\{l_{1}, \ldots, l_{N}\right\}^{\top}, \quad l_{n}=\left(x_{n}-y_{n}\right)^{2} \end{equation} (x,y)=L={l1,,lN},ln=(xnyn)2
其中x是Input,y表示target

参数说明:

CLASS torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')

reduce与size_average:

reduce = False,损失函数返回的是向量形式的 loss,这种情况下参数 size_average 失效

reduce = True, 损失函数返回的是标量形式的 loss,这种情况下:
1)当 size_average = True 时,返回 loss.mean(),即所有向量元素求和后再除以向量长度
2)当 size_average = False 时,返回 loss.sum(),即所有向量元素只求和

reduction:默认是mean,还可以是sum

代码示例:

import torch
import torch.nn as nn
import torch.nn.functional as F
# 1.调用MSELoss
mse_loss_fn = torch.nn.MSELoss()   # 默认输出标量并求均值
input = torch.randn(2, 4, requires_grad=True)
target = torch.randn(2, 4)
output =  mse_loss_fn(input, target)
print(output.item())
2.2671520709991455

2. BCE Loss

只适用与二分类任务,且神经网络的输出是一个概率分布,一般输出层的激活函数是 Sigmod 函数(返回一个概率数值,那么可以理解为某一类的概率),因为只有两类,所以输出没必要归一化,直接就是一个概率分布。

计算公式:

一个batch数据的损失为:
L b a t c h = − w ⋅ [ y ln ⁡ y ^ + ( 1 − y ) ln ⁡ ( 1 − y ^ ) ] \begin{equation} L_{b a t c h}=-w \cdot[y \ln \hat{y}+(1-y) \ln (1-\hat{y})] \end{equation} Lbatch=w[ylny^+(1y)ln(1y^)]
一个样本的损失为:
L one  = − [ y ln ⁡ y ^ + ( 1 − y ) ln ⁡ ( 1 − y ^ ) ] \begin{equation} L_{\text {one }}=-[y \ln \hat{y}+(1-y) \ln (1-\hat{y})] \end{equation} Lone =[ylny^+(1y)ln(1y^)]
参数说明:

CLASS torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')

weight:weight 必须和 target 的 shape 一致

reduce与size_average:

reduce = False,损失函数返回的是向量形式的 loss,这种情况下参数 size_average 失效

reduce = True, 损失函数返回的是标量形式的 loss,这种情况下:
1)当 size_average = True 时,返回 loss.mean(),即所有向量元素求和后再除以向量长度
2)当 size_average = False 时,返回 loss.sum(),即所有向量元素只求和

reduction:默认是mean,还可以是sum

输入值与目标值说明:

input:可以是任意维度,保证是log的一个概率

target:与input一致,默认情况是线性的概率

outputz:一般是一个张量

代码示例:

# logits shape:[BS,NC] Logits可以理解为输出的一个概率分布
# 定义一些通用的
batch_size = 2
num_class = 4

logits = torch.randn(batch_size,num_class) # 未归一化分数,作为损失函数的输入

target_indices = torch.randint(num_class,size = (batch_size,)) # 形成的是[0,num_class-1]范围的索引的目标分布 
target_logits = torch.randn(batch_size,num_class) # 形成的是目标概率分布
## 2. 调用Binary Cross Entropy loss (BCE Loss)
bce_loss_fn = torch.nn.BCELoss()
logits = torch.randn(batch_size) # 这是logits
prob_1 = torch.sigmoid(logits) # 这是概率
# 如果神经网络输出的是logits,那么就用BCEwithlogitsloss这个方法
target = torch.randint(2,size=(batch_size,))
bce_loss = bce_loss_fn(prob_1,target.float())
print(f"binary cross entropy loss:{bce_loss}")

### 用NLLLoss(本文后面会讲到)代替BCE LOSS做二分类
prob_0 = 1 - prob_1.unsqueeze(-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 is:{nll_loss_binary}")
binary cross entropy loss:0.4194680452346802
negative likelihood loss binary is0.4194680452346802

3. CrossEntropyLoss

用于分类任务中,常用于多分类

当使用 CrossEntropyLoss 损失函数的时候,神经网络的输出就不用再接 softmax 层了,因为这个损失函数内部会做这个归一化,同时它还会根据对应的输出标签 y 生成 one−hot向量。如下图所示:

CrossEntropyLoss

交叉熵计算公式:
H ( p , q ) = − ∑ i = 1 N p ( x i ) ln ⁡ q ( x i ) \begin{equation} H(p, q)=-\sum_{i=1}^{N} p\left(x_{i}\right) \ln q\left(x_{i}\right) \end{equation} H(p,q)=i=1Np(xi)lnq(xi)
其中p表示真实分布,q表示预测分布

参数说明:

CLASS torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean', label_smoothing=0.0

weight:分类类别明显不均衡的话,会设置weight来使得更均衡

ignore_index:类似padding的操作,一般设置ingnore_index = 0,传入之后,如果目标为ingnore_index,就不会考虑那个位置

reduction:默认是mean,还可以是sum

label_smoothing:把目标的概率值降低点,相当于平滑化的操作

输入值与目标值说明:

input:输入(在模型中,也就是模型的输出值,放入损失中作为输入)是未归一化的一个分数。(N,C) or (C,),where C = number of classes, or (N, C, d_1, d_2, …, d_K)(N,C,d1,d2,…,d**K) with K≥1 in the case of K-dimensional loss.(这些d可理解为时空维度,如d1为视频高度;d2为视频宽度;d3为视频通道数目;d4为视频时间维度)

target:传入的是类别标签,如果input是©的话,那么target形状就是();如果input是(N,C)的话,那么target形状就是(N);如果input是(N, C, d_1, d_2, …, d_K)的话,那么target形状就是(N, d_1, d_2, …, d_K)。总之就是少了C这一维,每一个值范围是[0,C)

output:If reduction is none,那么就与targe一致,反之就是标量

代码示例:

## 3. 调用Cross Entropy loss (CE Loss)
### method1 for CE Loss
ce_loss_fn = torch.nn.CrossEntropyLoss()
ce_loss1 = ce_loss_fn(logits,target_indices)
print(f"cross entropy loss is {ce_loss1}")

### method2 for CE Loss
ce_loss2 = ce_loss_fn(logits,torch.softmax(target_logits,dim=-1))
print(f"cross entropy loss is {ce_loss2}")
cross entropy loss1 is 1.4498498439788818
cross entropy loss2 is 1.7070740461349487

4. NLLLoss(负对数似然Loss)

交叉熵就是负对数似然

CLASS torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean')

参数说明:

weight:分类类别明显不均衡的话,会设置weight来使得更均衡

ignore_index:类似padding的操作,一般设置ingnore_index = 0,传入之后,如果目标为ingnore_index,就不会考虑那个位置

reduction:默认是mean,还可以是sum

label_smoothing:把目标的概率值降低点,相当于平滑化的操作

输入值与目标值说明:

input:输入(在模型中,也就是模型的输出值,放入损失中作为输入)必须是每个类别的对数概率,并且是做了对数化的。(N,C) or (C,),where C = number of classes, or (N, C, d_1, d_2, …, d_K) with K≥1 in the case of K-dimensional loss.

target:是一个索引,范围是[0,C-1],其中C为类别的数目。形状是 (N) or 一个标量 or (N, C, d_1, d_2, …, d_K) with K≥1 in the case of K-dimensional loss.

ouput:If reduction is none, shape (N) or (N, C, d_1, d_2, …, d_K) with K≥1 in the case of K-dimensional loss.否则就是标量。

代码示例:

## 4. 调用Negative Log Likelihood loss (NLL Loss)
nll_fn = torch.nn.NLLLoss()
nll_loss = nll_fn(torch.log(torch.softmax(logits,dim=-1)),target_indices)
print(f"negative log likelihood loss is {nll_loss}")
## 重要结论:cross entropy value = NLL value
negative log likelihood loss is 1.4498497247695923

5. KL散度 Loss

KL散度计算公式:
D K L ( p ∥ q ) = H ( p , q ) − H ( p ) \begin{equation} D_{K L}(p \| q)=H(p, q)-H(p) \end{equation} DKL(pq)=H(p,q)H(p)
参数说明:

CLASS torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)

reduce与size_average:

reduce = False,损失函数返回的是向量形式的 loss,这种情况下参数 size_average 失效

reduce = True, 损失函数返回的是标量形式的 loss,这种情况下:
1)当 size_average = True 时,返回 loss.mean(),即所有向量元素求和后再除以向量长度
2)当 size_average = False 时,返回 loss.sum(),即所有向量元素只求和

reduction:默认是mean,还可以是sum

log_target:表示是否对目标值求log

输入值与目标值说明:

input:可以是任意维度,保证是log的一个概率

target:与input一致,默认情况是线性的概率

output:默认是一个标量,如果redution为"none",那么与输入具有相同形状

代码示例:

## 4. 调用Kullback-Leibler divergence loss(KL Loss)
kid_loss_fn = torch.nn.KLDivLoss()
kid_loss = kid_loss_fn(torch.softmax(logits,dim=-1),torch.softmax(target_logits,dim=-1))
print(f"Kullback-Leibler divergence  loss is {kid_loss}")
Kullback-Leibler divergence  loss is -0.3704858124256134

验证CE = IE + KLD(交叉熵 = 信息熵 + KL散度)

# 验证的时候就按样本了
ce_loss_fn_sample = torch.nn.CrossEntropyLoss(reduction="none")
ce_loss_sample = ce_loss_fn_sample(logits,torch.softmax(target_logits,dim=-1))
print(f"cross entropy loss sample is {ce_loss_sample}")

kid_loss_fn_sample = torch.nn.KLDivLoss(reduction="none")
kid_loss_sample = kid_loss_fn_sample(torch.log(torch.softmax(logits,dim=-1)),torch.softmax(target_logits,dim=-1)).sum(dim=-1)
print(f"Kullback-Leibler divergence loss sample is {kid_loss_sample}")

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

print(torch.allclose(ce_loss_sample,kid_loss_sample+target_information_entropy))
cross entropy loss sample is tensor([1.4442, 1.9700])
Kullback-Leibler divergence loss sample is tensor([0.2811, 0.7337])
information entropy sample is tensor([1.1631, 1.2363])
True

6. 余弦相似度 Loss

根据余弦相似度来判断输入的两个数是相似还是不相似的(在对比学习、自监督学习、文本相似度、图片相似度、图片检索中比较常用)

CLASS torch.nn.CosineEmbeddingLoss(margin=0.0, size_average=None, reduce=None, reduction='mean')

参数说明:

margin:是一个-1 到 1 ,0 到 0.5 的数,默认为0

reduce与size_average:

reduce = False,损失函数返回的是向量形式的 loss,这种情况下参数 size_average 失效

reduce = True, 损失函数返回的是标量形式的 loss,这种情况下:
1)当 size_average = True 时,返回 loss.mean(),即所有向量元素求和后再除以向量长度
2)当 size_average = False 时,返回 loss.sum(),即所有向量元素只求和

reduction:默认是mean,还可以是sum

输入值与目标值说明:

input1:(N,D)或(D),其中N是batch_size,D是embedding dimension

input2:与input1一致

target:(N) 或 () -1或1

output:如果redution为"none",那么就是(N),否则就是标量

代码示例:

## 6.调用Cosine Similarity loss
cosine_loss_fn = torch.nn.CosineEmbeddingLoss()
v1 = torch.randn(batch_size,512)
v2 = torch.randn(batch_size,512)
target = torch.randint(2,size = (batch_size,))*2 - 1 # torch.randint(2是 0,1 *2 是0,2 -1 就是 -1,1
cosine_loss = cosine_loss_fn(v1,v2,target)
print(f"Cosine Similarity loss is:{cosine_loss}")
Cosine Similarity loss is0.942288875579834

参考:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch,可以使用最大似然估计(Maximum Likelihood Estimation,MLE)来选择合适的损失函数。最大似然估计是一种常用的参数估计方法,通过最大化观测数据的似然函数来估计模型参数。 PyTorch提供了各种损失函数,可以根据具体的任务和数据类型选择适当的损失函数进行最大似然估计。以下是一些常用的损失函数示例: 1. 对于分类任务: - 交叉熵损失函数(CrossEntropyLoss):适用于多分类任务,将模型预测的概率分布与真实标签之间的差异最小化。 - 二元交叉熵损失函数(BCELoss):适用于二分类任务,将模型预测的概率与真实标签之间的差异最小化。 2. 对于回归任务: - 均方误差损失函数(MSELoss):将模型预测的值与真实值之间的差异平方和最小化。 - 平均绝对误差损失函数(L1Loss):将模型预测的值与真实值之间的差异绝对值平均化。 这些损失函数都是基于最大似然估计的原理,通过最小化或最大化特定的目标函数来估计模型的参数。根据具体的问题和数据类型,选择合适的损失函数非常重要。 需要注意的是,PyTorch损失函数通常是对一个批次(batch)的样本进行计算的,因此在使用时需要将模型预测值与真实标签对齐,并考虑合适的维度和权重设置。 总之,PyTorch提供了多种损失函数,可以用于最大似然估计的模型训练。选择合适的损失函数取决于具体的任务和数据类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值