IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 【损失函数】NLLLoss损失、CrossEntropy_Loss交叉熵损失以及Label Smoothing示例与代码 -> 正文阅读

[人工智能]【损失函数】NLLLoss损失、CrossEntropy_Loss交叉熵损失以及Label Smoothing示例与代码

??机缘巧合下,近期又详细学习了一遍各损失函数的计算,特此记录以便后续回顾。

??为了公式表示更加清晰,我们设 y n ∈ { 1 , 2 , … , K } {{y_n} \in \{ 1,2, \ldots ,K\} } yn?{1,2,,K} 为样本 n {n} n 的真实标签, v = ( v 1 , v 2 , … v K ) {v = ({v_1},{v_2}, \ldots {v_K})} v=(v1?,v2?,vK?) 为网络的输出,即样本 n {n} n 的预测结果,设 N {N} N 为一批样本的数目(即Batch size), K {K} K 为分类任务的类别数目。

??为了本文例子的统一展示,我们为网络的输出 p r e d s {preds} preds 和标签 t a r g e t {target} target 赋值,即只有两个样本,一个标签为 2 {2} 2,另一个标签为 3 {3} 3
?? p r e d s = [ [ 0.1 , 0.2 , 0.3 , 0.4 ] , [ 0.1 , 0.1 , 0.1 , 0.1 ] ] {preds = [[0.1, 0.2, 0.3, 0.4], [0.1, 0.1, 0.1, 0.1]]} preds=[[0.1,0.2,0.3,0.4],[0.1,0.1,0.1,0.1]]
?? t a r g e t = [ 2 , 3 ] {target = [2, 3]} target=[2,3]

一、NLLLoss损失与CrossEntropy_Loss交叉熵损失

1. Softmax

??Softmax是网络输出后第一步操作,其公式可表示为:
e v y n ∑ m = 1 K e v m {\frac{{{e^{{v_{{y_n}}}}}}}{{\sum\nolimits_{m = 1}^K {{e^{{v_m}}}} }}} m=1K?evm?evyn?????由于网络的输出有正有负,有大有小,Softmax主要是将输出概率标准化到 [ 0 , 1 ] {[0,1]} [0,1] 之间,方便比较,示例计算如下:
[ 0.1 , 0.2 , 0.3 , 0.4 ] → s o f t m a x [ e 0.1 S 1 , e 0.2 S 1 , e 0.3 S 1 , e 0.4 S 1 ] = [ 0.2138 , 0.2363 , 0.2612 , 0.2887 ] {[0.1,0.2,0.3,0.4]\mathop \to \limits^{{\mathop{\rm softmax}\nolimits} } \left[ {\frac{{{e^{0.1}}}}{{{S_1}}},\frac{{{e^{0.2}}}}{{{S_1}}},\frac{{{e^{0.3}}}}{{{S_1}}},\frac{{{e^{0.4}}}}{{{S_1}}}} \right] = [0.2138,0.2363,0.2612,0.2887]} [0.1,0.2,0.3,0.4]softmax[S1?e0.1?,S1?e0.2?,S1?e0.3?,S1?e0.4?]=[0.2138,0.2363,0.2612,0.2887] [ 0.1 , 0.1 , 0.1 , 0.1 ] → s o f t m a x [ e 0.1 S 2 , e 0.1 S 2 , e 0.1 S 2 , e 0.1 S 2 ] = [ 0.2500 , 0.2500 , 0.2500 , 0.2500 ] {[0.1,0.1,0.1,0.1]\mathop \to \limits^{{\mathop{\rm softmax}\nolimits} } \left[ {\frac{{{e^{0.1}}}}{{{S_2}}},\frac{{{e^{0.1}}}}{{{S_2}}},\frac{{{e^{0.1}}}}{{{S_2}}},\frac{{{e^{0.1}}}}{{{S_2}}}} \right] = [0.2500,0.2500,0.2500,0.2500]} [0.1,0.1,0.1,0.1]softmax[S2?e0.1?,S2?e0.1?,S2?e0.1?,S2?e0.1?]=[0.2500,0.2500,0.2500,0.2500]??其中, S 1 = e 0.1 + e 0.2 + e 0.3 + e 0.4 {{S_1} = {e^{0.1}} + {e^{0.2}} + {e^{0.3}} + {e^{0.4}}} S1?=e0.1+e0.2+e0.3+e0.4 S 2 = e 0.1 + e 0.1 + e 0.1 + e 0.1 {{S_2} = {e^{0.1}} + {e^{0.1}} + {e^{0.1}} + {e^{0.1}}} S2?=e0.1+e0.1+e0.1+e0.1

代码实现为:

import torch
import torch.nn.functional as F

preds = torch.tensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.1, 0.1, 0.1]])

exp = torch.exp(preds)
sum_ = torch.sum(exp, dim=1).reshape(-1, 1)
softmax = exp / sum_
print('手动计算softmax:\n', softmax)

softmax_ = F.softmax(preds, dim=1)
print('函数计算softmax:\n', softmax_)

输出是一样的:

手动计算softmax:
 tensor([[0.2138, 0.2363, 0.2612, 0.2887],
        [0.2500, 0.2500, 0.2500, 0.2500]])
函数计算softmax:
 tensor([[0.2138, 0.2363, 0.2612, 0.2887],
        [0.2500, 0.2500, 0.2500, 0.2500]])

2. Log_Softmax

??Log_Softmax,算如其名,就是在Softmax之后进行 L o g {Log} Log,其公式可表示为:
log ? ( e v y n ∑ m = 1 K e v m ) {\log (\frac{{{e^{{v_{{y_n}}}}}}}{{\sum\nolimits_{m = 1}^K {{e^{{v_m}}}} }})} log(m=1K?evm?evyn???)
??值得注意的是,这里的 L o g {Log} Log是以 e {e} e 为底的,即数学中的 I n {In} In,示例计算如下:
[ 0.2138 , 0.2363 , 0.2612 , 0.2887 ] → [ I n ( 0.2138 ) , I n ( 0.2363 ) , I n ( 0.2612 ) , I n ( 0.2887 ) ] {[0.2138,0.2363,0.2612,0.2887] \to [In(0.2138),In(0.2363),In(0.2612),In(0.2887)]} [0.2138,0.2363,0.2612,0.2887][In(0.2138),In(0.2363),In(0.2612),In(0.2887)] [ 0.2500 , 0.2500 , 0.2500 , 0.2500 ] → [ I n ( 0.2500 ) , I n ( 0.2500 ) , I n ( 0.2500 ) , I n ( 0.2500 ) ] {[0.2500,0.2500,0.2500,0.2500] \to [In(0.2500),In(0.2500),In(0.2500),In(0.2500)]} [0.2500,0.2500,0.2500,0.2500][In(0.2500),In(0.2500),In(0.2500),In(0.2500)]??此处手动计算与代码计算会由于保留小数问题存在微小的差异,保留小数更多时,就一样了。

代码实现为:

import torch
import torch.nn.functional as F

preds = torch.tensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.1, 0.1, 0.1]])

exp = torch.exp(preds)
sum_ = torch.sum(exp, dim=1).reshape(-1, 1)
softmax = exp / sum_
log_softmax = torch.log(softmax) 
print('手动计算log_softmax:\n', log_softmax)

softmax_ = F.log_softmax(preds, dim=1)
print('函数计算log_softmax:\n', softmax_)

输出是一样的:

手动计算log_softmax:
 tensor([[-1.5425, -1.4425, -1.3425, -1.2425],
        [-1.3863, -1.3863, -1.3863, -1.3863]])
函数计算log_softmax:
 tensor([[-1.5425, -1.4425, -1.3425, -1.2425],
        [-1.3863, -1.3863, -1.3863, -1.3863]])

3. NLLLoss

??NLLLoss损失,即对Log_Softmax之后的结果,将样本标签对应位置的数值进行相加,再除以样本量,最后再去负号,因为 L o g {Log} Log之后是负数,损失需要转换为正值。在我们的示例中:
??对 [ ? 1.5425 , ? 1.4425 , ? 1.3425 , ? 1.2425 ] {[ - 1.5425, - 1.4425, - 1.3425, - 1.2425]} [?1.5425,?1.4425,?1.3425,?1.2425] [ ? 1.3863 , ? 1.3863 , ? 1.3863 , ? 1.3863 ] {[-1.3863, -1.3863, -1.3863, -1.3863]} [?1.3863,?1.3863,?1.3863,?1.3863] 标签对应位置 t a r g e t = [ 2 , 3 ] {target = [2, 3]} target=[2,3] 上的数值相加除 2 {2} 2 再取负,即:
? ( ? 1.3425 ) + ( ? 1.3863 ) 2 = 1.3644 { - \frac{{( - 1.3425) + ( - 1.3863)}}{2}{\rm{ = }}1.3644} ?2(?1.3425)+(?1.3863)?=1.3644代码实现为:

import torch
import torch.nn.functional as F

preds = torch.tensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.1, 0.1, 0.1]])
target = torch.tensor([2, 3])

exp = torch.exp(preds)
sum_ = torch.sum(exp, dim=1).reshape(-1, 1)
softmax = exp / sum_
log_softmax = torch.log(softmax) 

one_hot = F.one_hot(target).float() 
nllloss = -torch.sum(one_hot * log_softmax) / target.shape[0]
print('手动计算nllloss:\n', nllloss)

Log_Softmax = F.log_softmax(preds, dim=1)  
Nllloss = F.nll_loss(Log_Softmax, target)  
print('函数计算nllloss:\n', Nllloss)

输出是一样的:

手动计算nllloss:
 tensor(1.3644)
函数计算nllloss:
 tensor(1.3644)

4. CrossEntropy_Loss

??有了对Softmax、Log_Softmax和NLLLoss损失的了解,交叉熵损失CrossEntropy_Loss就是他们的齐活:
?? C r o s s E n t r o p y _ L o s s = S o f t m a x + L o g + N L L L o s s {CrossEntropy\_Loss = Softmax + Log + NLLLoss} CrossEntropy_Loss=Softmax+Log+NLLLoss = L o g _ S o f t m a x + N L L L o s s {Log\_Softmax + NLLLoss} Log_Softmax+NLLLoss
??公式可表示为:
? 1 N ∑ n = 1 N log ? ( e v y n ∑ m = 1 K e v m ) { - \frac{1}{N}\sum\limits_{n = 1}^N {\log (\frac{{{e^{{v_{{y_n}}}}}}}{{\sum\nolimits_{m = 1}^K {{e^{{v_m}}}} }})}} ?N1?n=1N?log(m=1K?evm?evyn???)
??CrossEntropy_Loss与NLLLoss计算结果是一致的,因为NLLLoss的输入一般也是Log_Softmax之后的结果。

完整代码实现为:

import torch
import torch.nn.functional as F

preds = torch.tensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.1, 0.1, 0.1]])
target = torch.tensor([2, 3])

one_hot = F.one_hot(target).float() # 对标签作 one_hot 编码
print('[1]one_hot编码target:\n', one_hot)
exp = torch.exp(preds)
print('[2]对网络预测preds求指数:\n', exp)
sum_ = torch.sum(exp, dim=1).reshape(-1, 1)  # 按行求和
softmax = exp / sum_  # 计算 softmax()
print('[3]softmax操作:\n', softmax)
log_softmax = torch.log(softmax) # 计算 log_softmax()
print('[4]softmax后取对数:\n', log_softmax)
nllloss = -torch.sum(one_hot * log_softmax) / target.shape[0]  # 标签乘以激活后的数据,求平均值,取反
print("[5]手动使用nllloss计算交叉熵:", nllloss)

print('----------------------------------------------')
# 调用 NLLLoss() 函数计算
Log_Softmax = F.log_softmax(preds, dim=1)  # log_softmax() 激活
Nllloss = F.nll_loss(Log_Softmax, target)  # 无需对标签作 one_hot 编码
print("函数使用Nllloss计算交叉熵:", Nllloss)
# 直接使用交叉熵损失函数 CrossEntropy_Loss()
cross_entropy = F.cross_entropy(preds, target)  # 无需对标签作 one_hot 编码
print('函数交叉熵cross_entropy:', cross_entropy)

输出为:

[1]one_hot编码target:
 tensor([[0., 0., 1., 0.],
        [0., 0., 0., 1.]])
[2]对网络预测preds求指数:
 tensor([[1.1052, 1.2214, 1.3499, 1.4918],
        [1.1052, 1.1052, 1.1052, 1.1052]])
[3]softmax操作:
 tensor([[0.2138, 0.2363, 0.2612, 0.2887],
        [0.2500, 0.2500, 0.2500, 0.2500]])
[4]softmax后取对数:
 tensor([[-1.5425, -1.4425, -1.3425, -1.2425],
        [-1.3863, -1.3863, -1.3863, -1.3863]])
[5]手动使用nllloss计算交叉熵: tensor(1.3644)
----------------------------------------------
函数使用Nllloss计算交叉熵: tensor(1.3644)
函数交叉熵cross_entropy: tensor(1.3644)

二、交叉熵损失的Label Smoothing

??Label Smoothing (论文传送) 是一种正则化手段,在一定程度上可以避免模型的过拟合。在交叉熵损失CrossEntropy_Loss中,非标签对应位置的预测信息是没有被使用的,而Label Smoothing使用了这种信息,宏观上讲,也是略微改变了标签的分布,使得标签不在是非0即1了,故而称为标签平滑。
??Label Smoothing的公式可表示为:
( 1 ? ε ) ? [ ? 1 N ∑ n = 1 N log ? ( e v y n ∑ m = 1 K e v m ) ] + ε ? [ ? 1 N K ∑ n = 1 N ∑ k = 1 K log ? ( e v k ∑ m = 1 K e v m ) ] {(1 - \varepsilon ) \cdot [ - \frac{1}{N}\sum\limits_{n = 1}^N {\log (\frac{{{e^{{v_{{y_n}}}}}}}{{\sum\nolimits_{m = 1}^K {{e^{{v_m}}}} }})} ] + \varepsilon \cdot [ - \frac{1}{{NK}}\sum\limits_{n = 1}^N {\sum\limits_{k = 1}^K {\log (\frac{{{e^{{v_k}}}}}{{\sum\nolimits_{m = 1}^K {{e^{{v_m}}}} }})} } ]} (1?ε)?[?N1?n=1N?log(m=1K?evm?evyn???)]+ε?[?NK1?n=1N?k=1K?log(m=1K?evm?evk??)]??从公式可以看出,系数为 ( 1 ? ε ) {(1 - \varepsilon )} (1?ε) 的前一部分就是交叉熵损失,后一部分,涵盖了非标签对应位置上的预测信息,在我们的示例中,后一部分的计算为:
[ ? 1.5425 , ? 1.4425 , ? 1.3425 , ? 1.2425 ] → s u m ? 5.5700 {[ - 1.5425, - 1.4425, - 1.3425, - 1.2425]\mathop \to \limits^{{\rm{sum}}} - 5.5700} [?1.5425,?1.4425,?1.3425,?1.2425]sum?5.5700 [ ? 1.3863 , ? 1.3863 , ? 1.3863 , ? 1.3863 ] → s u m ? 5.5452 {[ - 1.3863, - 1.3863, - 1.3863, - 1.3863]\mathop \to \limits^{{\rm{sum}}} - 5.5452} [?1.3863,?1.3863,?1.3863,?1.3863]sum?5.5452??对Log_Softmax之后的结果求和,取负数,再除以样本量 2 {2} 2 和 分类类别数 4 {4} 4,得到:
? ( ? 5.5700 ) + ( ? 5.5452 ) 2 × 4 = 1 . 3894 { - \frac{{( - 5.5700) + ( - 5.5452)}}{{2 \times 4}} = {\rm{1}}{\rm{.3894}}} ?2×4(?5.5700)+(?5.5452)?=1.3894??最后以 ε {\varepsilon} ε 系数与交叉熵损失进行加权,设 ε = 0.1 {\varepsilon}=0.1 ε=0.1 ,得到:
( 1 ? 0.1 ) × 1.3644 + 0.1 × 1.3894 = 1.3669 {(1 - 0.1) \times 1.3644 + 0.1 \times 1.3894 = 1.3669} (1?0.1)×1.3644+0.1×1.3894=1.3669代码实现为:

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

def linear_combination(x, y, epsilon):
    return epsilon * x + (1 - epsilon) * y

def reduce_loss(loss, reduction='mean'):
    return loss.mean() if reduction == 'mean' else loss.sum() if reduction == 'sum' else loss

class LabelSmoothing_CrossEntropy(nn.Module):
    def __init__(self, epsilon: float = 0.1, reduction='mean'):
        super().__init__()
        self.epsilon = epsilon
        self.reduction = reduction

    def forward(self, preds, target):
        n = preds.size()[-1]    
        log_preds = F.log_softmax(preds, dim=-1)    
        loss = reduce_loss(-log_preds.sum(dim=-1), self.reduction)      
        nll = F.nll_loss(log_preds, target, reduction=self.reduction)   
        return linear_combination(loss / n, nll, self.epsilon)

preds = torch.tensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.1, 0.1, 0.1]])
target = torch.tensor([2, 3])

ls = LabelSmoothing_CrossEntropy()
lsloss = ls(preds, target)
print('Label smoothing损失:', lsloss)

输出为:

Label smoothing损失: tensor(1.3669)
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 11:56:46  更:2022-10-31 11:59:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:28:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码