torch.nn.BCELoss用于计算二分类问题或多标签分类问题的交叉熵损失。
torch.nn.BCELoss需要配合Sigmoid函数使用。
二分类问题
对于二分类问题,若使用Softmax函数,则最后一层全连接层的神经元个数为2;若使用Sigmoid函数,则最后一层全连接层的神经元个数为1。假设有一猫狗二分类问题,经Sigmoid函数输出的值表示为猫的概率。
import torch
import torch.nn as nn
'''
对于一个2分类问题,通常使用0和1作为标签。这里假设猫的标签为0,狗的标签为1
当batch_size = 3时,这一个batch的标签是一个形状为[batch_size]的tensor,即shape为[5]
'''
# 一个batch(batch_size=3)的标签:[狗, 猫, 猫]
label = torch.tensor([1, 0, 0], dtype=torch.float32)
'''
对于一个2分类问题,当训练时batch_size为3,
则深度网络对每一个batch的预测值是一个形状为[batch_size]的tensor,即shape为[3]
以深度网络对第一个样本(狗)的预测值 -0.8 为例,经过Sigmoid层后,得到0.3100, 表示深度网络认为第一个样本属于猫的概率分别为0.3100。
'''
predict = torch.tensor([-0.8, 0.7, 0.5])
# 转为概率值
sigmoid = nn.Sigmoid()
print(sigmoid(predict)) # tensor([0.3100, 0.6682, 0.6225])
# 当reduction='none'时,输出是对每一个样本预测的损失
loss_func = torch.nn.BCELoss(reduction='none')
loss = loss_func(Sigmoid(predict), label)
print(loss) # tensor([1.1711, 1.1032, 0.9741])
# 当reduction='sum'时,输出是对这一个batch预测的损失之和
loss_func = torch.nn.BCELoss(reduction='sum')
loss = loss_func(Sigmoid(predict), label)
print(loss) # tensor(3.2484)
# 当reduction='mean'时,输出是对这一个batch预测的平均损失
loss_func = torch.nn.BCELoss(reduction='mean')
loss = loss_func(Sigmoid(predict), label)
print(loss) # tensor(1.0828)
torch.nn.BCEWithLogitsLoss
也可以直接使用torch.nn.BCEWithLogitsLoss,它内置了Sigmoid运算。
import torch
import torch.nn as nn
# 一个batch(batch_size=3)的标签:[狗, 猫, 猫]
label = torch.tensor([1, 0, 0], dtype=torch.float32)
# 深度网络对这一个batch的预测值
predict = torch.tensor([-0.8, 0.7, 0.5])
# 当reduction='none'时,输出是对每一个样本预测的损失
loss_func = torch.nn.BCEWithLogitsLoss(reduction='none')
print(loss_func(predict, label)) # tensor([1.1711, 1.1032, 0.9741])
# 当reduction='sum'时,输出是对这一个batch预测的损失之和
loss_func = torch.nn.BCEWithLogitsLoss(reduction='sum')
print(loss_func(predict, label)) # tensor(3.2484)
# 当reduction='mean'时,输出是对这一个batch预测的平均损失
loss_func = torch.nn.BCEWithLogitsLoss(reduction='mean')
print(loss_func(predict, label)) # tensor(1.0828)
多标签分类问题
假设一幅图像中可能有猫、狗或人,无记为0,有记为1。
比如一幅图像的标签为[1, 0, 0], 表示该图像中有猫,没有狗和人。
import torch
import torch.nn as nn
'''
对于一个3标签分类问题,
当batch_size = 2时,这一个batch的label是一个形状为[batch_size, label_classes]的tensor,即shape为[2, 3]
'''
# 一个batch(batch_size=2)的label
label = torch.tensor([[1, 0, 0],
[0, 1, 0]], dtype=torch.float32)
'''
对于一个3标签分类问题,当训练时batch_size为2,
则深度网络对每一个batch的预测值是一个形状为[batch_size, label_classes]的tensor,即shape为[2, 3]
以深度网络对第一个样本的预测值[-0.8, 0.7, 0.5]为例,经过Sigmoid层后,得到[0.7311, 0.5000, 0.5000],
表示深度网络认为第一个样本有猫、狗、人的概率分别为0.7311、0.5000、0.5000
'''
predict = torch.tensor([[-0.8, 0.7, 0.5],
[0.2, -0.4, 0.6]])
# 当reduction='mean'时,输出是对这一个batch预测的平均损失
loss_func = torch.nn.BCEWithLogitsLoss(reduction='mean')
loss = loss_func(predict, label)
print(loss) # tensor(0.9995)
torch.nn.MultiLabelSoftMarginLoss
也可以直接使用torch.nn.MultiLabelSoftMarginLoss
import torch
import torch.nn as nn
# 一个batch(batch_size=2)的label
label = torch.tensor([[1, 0, 0],
[0, 1, 0]], dtype=torch.float32)
predict = torch.tensor([[-0.8, 0.7, 0.5],
[0.2, -0.4, 0.6]])
# 当reduction='mean'时,输出是对这一个batch预测的平均损失
loss_func = torch.nn.MultiLabelSoftMarginLoss(reduction='mean')
loss = loss_func(predict, label)
print(loss) # tensor(0.9995)