淘先锋技术网

首页 1 2 3 4 5 6 7

PyTorch学习笔记:nn.CrossEntropyLoss——交叉熵损失

功能:创建一个交叉熵损失函数:
l ( x , y ) = L = { l 1 , … , l N } T , l n = − ∑ c = 1 C w c log ⁡ e x n , c ∑ i = 1 C e x n , i ⋅ y n , c l(x,y)=L=\{l_1,\dots,l_N\}^T,l_n=-\sum^C_{c=1}w_c\log\frac{e^{x_{n,c}}}{\sum^C_{i=1}e^{x_{n,i}}}· y_{n,c} l(x,y)=L={l1,,lN}Tln=c=1Cwclogi=1Cexn,iexn,cyn,c
其中 x x x是输入, y n , c y_{n,c} yn,c是标签向量元素(来自经过独热编码后的标签向量), w w w是类别权重, C C C是类别总数, N N N表示batch size。

输入:

注意:

  • 输入应该包含原始、未经过标准化的预测值,CrossEntropyLoss函数已经内置softmax处理
  • 对于输入张量 x x x,尺寸必须为 ( m i n i b a t c h , C ) (minibatch,C) (minibatch,C)或者 ( m i n i b a t c h , C , d 1 , … , d K ) (minibatch,C,d_1,\dots,d_K) (minibatch,C,d1,,dK),后者对于计算高维输入时很有用,如计算二维图像中每个像素点的交叉熵损失,注意: K ≥ 1 K≥1 K1
  • 输入的张量 y y y,尺寸必须为 ( m i n i b a t c h ) (minibatch) (minibatch)或者 ( m i n i b a t c h , d 1 , … , d K ) (minibatch,d_1,\dots,d_K) (minibatch,d1,,dK),与 x x x的尺寸相对应,后者也是用于高维数据的计算
  • 注意 x x x的第二维度尺寸与类别数量一一对应,并且 y y y只需要输入物体类别序号即可,无需输入独热编码(该函数会自动对 y y y做独热编码), y y y里面数据的大小不能超过 x x x第二维度尺寸的大小减一(减一是因为标签 y y y是从 0 0 0开始计算)

代码案例

一般用法

import torch.nn as nn
import torch

x = torch.randn((2, 8))
# 在0-7范围内,随机生成两个数,当做标签
y = torch.randint(0, 8, [2])
ce = nn.CrossEntropyLoss()
out = ce(x, y)
print(x)
print(y)
print(out)

输出

# x
tensor([[ 1.3712,  0.4903, -1.3202,  0.1297, -1.6004, -0.1809, -2.8812, -0.3088],
        [ 0.5855, -0.4926,  0.7647, -0.1717, -1.0418, -0.0381, -0.1307, -0.6390]])
# y
tensor([5, 0])
# 得到的交叉熵损失,默认返回损失的平均值
tensor(1.9324)

参数weight的用法

import torch.nn as nn
import torch

x = torch.randn((2, 2))
y = torch.tensor([0, 1])
# 不添加weight
ce = nn.CrossEntropyLoss(reduction='none')
# 添加weight
ce_w = nn.CrossEntropyLoss(weight=torch.tensor([0.5, 1.5]), reduction='none')
out = ce(x, y)
out_w = ce_w(x, y)
print(x)
print(y)
print(out)
print(out_w)

输出

# x
tensor([[-1.1011,  0.6231],
        [ 0.2384, -0.3223]])
# y
tensor([0, 1])
# 不添加weight时的损失输出
tensor([1.8883, 1.0123])
# weight定义为[0.5, 1.5]时的损失
# 第一个数据(batch中第一个元素)由于标签为0
# 因此对应的损失乘以weight中第一个权重
# 第二个数据类似
tensor([0.9441, 1.5184])

参数ignore_index的用法

import torch.nn as nn
import torch

x = torch.randn((2, 2))
y = torch.tensor([0, 1])
# 不添加ignore_index
ce = nn.CrossEntropyLoss(reduction='none')
# 添加ignore_index
ce_i = nn.CrossEntropyLoss(ignore_index = 0, reduction='none')
out = ce(x, y)
out_i = ce_i(x, y)
print(x)
print(y)
print(out)
print(out_i)

输出

# x
tensor([[-0.9390, -0.6169],
        [-0.7700,  0.3602]])
# y
tensor([0, 1])
# 不添加ignore_index时的损失输出
tensor([0.8671, 0.2799])
# ignore_index设置为0,表示忽略类别序号为0的损失
# 这里第一个数据标签设置为0,因此第一个损失清零
tensor([0.0000, 0.2799])

输入高维数据时

这里以对二维的预测图做损失为例

import torch.nn as nn
import torch
# 这里表示随机生成batch为1,图片尺寸为3*3
# 并且每个点有两个类别的预测图
x = torch.randn((1, 2, 3, 3))
# 这里表示预测图x对应的标签y
# 预测图x每个位置都会对应一个标签值
# x删去第二维度后的尺寸,就是标签y的尺寸
y = torch.randint(0, 2, [1, 3, 3])
ce = nn.CrossEntropyLoss(reduction='none')
out = ce(x, y)
print(x)
print(y)
print(out)

输出

# 输入的高维数据x
tensor([[[[ 0.8859, -2.0889, -0.6026],
          [-1.6448,  0.7807,  0.9609],
          [-0.0646,  0.2204, -0.7471]],

         [[ 0.7075, -0.7013, -0.9280],
          [-0.6913,  2.1507, -0.0758],
          [ 0.2139,  0.8387,  0.3743]]]])
# 对应的标签,预测图x长宽为多少,标签y的长宽就为多少
tensor([[[0, 0, 1],
         [0, 0, 0],
         [1, 0, 1]]])
# 输出的损失
# 函数会为预测图x上每个位置都生成一个损失,这里一共生成3*3个损失(对应长乘宽)
tensor([[[0.6079, 1.6105, 0.8690],
         [1.2794, 1.5964, 0.3035],
         [0.5635, 1.0493, 0.2820]]])

官方文档

nn.CrossEntropyLoss:https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss

初步完稿于:2022年1月29日