BCELoss、crossentropyLoss、NLLLoss的使用(pytorch)
BCELoss
用于二分类问题,计算loss值,与sigmoid函数一起使用(就是逻辑回归的那个公式,线性外面套一个sigmoid函数)
参考文档
理解
看它的参数说明大概能知道:
参数
- weight(张量*,*可选)–对每个批次元素的损失赋予的手动重新缩放重量。如果给定,则必须是大小为nbatch的张量。
- size_average(bool*,*可选)–已弃用(请参阅
reduction
)。默认情况下,损失是批次中每个损失元素的平均数。请注意,对于某些损失,每个样本有多个元素。如果该字段size_average
设置为False
,则每个小批量的损失总和。何时reduce
被忽略False
。默认:True
- reduce(bool*,*可选)–不推荐使用(请参阅
reduction
)。默认情况下,根据,对每个小批量的损失进行平均或求和size_average
。当reduce
为is时False
,则返回每批元素的损失,然后忽略size_average
。默认:True
- reduction(字符串*,*可选)–指定要应用于输出的减少量:
'none'
|'mean'
|'sum'
。'none'
:不应用缩减,'mean'
:输出的总和除以输出中元素的数量,'sum'
:输出的总和。注意:size_average
和reduce
正在弃用的过程中,同时,指定这两个args中的任何一个将覆盖reduction
。默认:'mean'
**理解:**我们一般只用reduction这个参数,有两个选择:
-
'mean'
:输出的总和 除以 输出中元素的数量 【以batch为单位进行计算】 -
'sum'
:输出的总和【以样本个体为单位进行计算】
demo
import torch
import torch.nn as nn
epoch = 4
batch_size = 3
m = nn.Sigmoid()
loss = nn.BCELoss(reduction="mean")
loss1 = nn.BCELoss(reduction="sum")
input = torch.randn(epoch, batch_size, requires_grad=True)
target = torch.empty(epoch, batch_size, ).random_(2)
print(input)
print(target)
"""
the way of mean
"""
i = 0
total_loss = 0
while i < epoch:
out = m(input[i])
output = loss(out, target[i])
output.backward()
total_loss += output.item()
# print(f"input[{i}]:", input[i])
# print(f"target[{i}]:", target[i])
print("output:", output)
i += 1
print("total_loss:", total_loss)
print("loss:", total_loss / epoch) # 这里除的是epoch,也可以是你的迭代次数
"""
the way of sum
"""
i = 0
total_loss = 0
while i < epoch:
out = m(input[i])
output1 = loss1(out, target[i])
output1.backward()
total_loss += output1.item()
# print(f"input[{i}]:", input[i])
# print(f"target[{i}]:", target[i])
print("output1:", output1)
i += 1
print("total_loss:", total_loss)
print("loss:", total_loss / (epoch * batch_size)) # 这里除以了样本总数
# 输出结果:
tensor([[ 0.5393, 0.8473, -0.3530],
[-0.6885, 0.5141, -0.0987],
[ 0.4177, 0.2554, -1.7657],
[-0.5285, 0.9502, 0.1078]], requires_grad=True)
tensor([[0., 1., 0.],
[0., 0., 1.],
[0., 1., 1.],
[0., 1., 0.]])
output: tensor(0.6292, grad_fn=<BinaryCrossEntropyBackward>)
output: tensor(0.7112, grad_fn=<BinaryCrossEntropyBackward>)
output: tensor(1.1403, grad_fn=<BinaryCrossEntropyBackward>)
output: tensor(0.5129, grad_fn=<BinaryCrossEntropyBackward>)
total_loss: 2.993612587451935
loss: 0.7484031468629837
output1: tensor(1.8875, grad_fn=<BinaryCrossEntropyBackward>)
output1: tensor(2.1336, grad_fn=<BinaryCrossEntropyBackward>)
output1: tensor(3.4209, grad_fn=<BinaryCrossEntropyBackward>)
output1: tensor(1.5388, grad_fn=<BinaryCrossEntropyBackward>)
total_loss: 8.98083770275116
loss: 0.7484031418959299
应用
我们需要查看其loss,一般在一个epoch中,要么每个batch输出一次,要么隔n个batch输出一次,因此,
如果使用mean
(默认为mean
),表示已经做了均值处理,只需要total_loss除以n(迭代次数)就可以;
如果使用sum
,表示没有除以该batch中的样本数,则需要total_loss除以(n*batch_size)【最后一下如果不能整除,自然也就不会进行这一步的total_loss转loss计算】
代码如下:
total_loss += loss.item()
if i % 3 == 0:
# print("len(trainLoader):", len(trainLoader))
# print("len(x)", len(x))
print(f'[{time_since(start)}] Epoch {epoch} ', end='')
print(f'[{i * len(x[0])}/{len(trainSet)}] ', end='')
print(f'loss = {total_loss / (i * len(x[0]))} ', end='')
print(f'loss = {total_loss / (i)} ', end='')
print(f'[{total_loss} / {(i )}]')
crossentropyLoss、NLLLoss
CrossEntropyLoss,它就是计算交叉熵损失函数
NLLLoss(Negative Log Likelihood Loss)是计算负log似然损失
参考文档
crossEntropyLoss
import torch
import torch.nn as nn
batch_size = 3
criterion = nn.CrossEntropyLoss()
y_pred = torch.randn(batch_size, 5)
y = torch.empty(batch_size, dtype=torch.long).random_(5)
print(y_pred)
# soft = nn.Softmax(dim=1) # 这里用的softmax
# y_pred = soft(y_pred) # 但是crossEntropy会自动添加一个Softmax,所以不用自己加
# print(y_pred)
print(y)
loss = criterion(y_pred, y)
print(loss)
"""
tensor([[-0.9051, -0.4489, -0.5590, -0.1007, 1.1984],
[-0.0395, 0.4527, 0.0423, -0.1724, 0.4925],
[ 0.4064, 1.5080, 1.1995, 0.1651, 0.2300]])
tensor([[0.0693, 0.1094, 0.0980, 0.1550, 0.5682],
[0.1588, 0.2597, 0.1723, 0.1390, 0.2703],
[0.1275, 0.3836, 0.2818, 0.1002, 0.1069]])
tensor([2, 1, 3])
tensor(1.6658)
"""
直观解析:这里是5分类
- y_pred:生成一个Batch_size x 5(classify number)的矩阵,每行是每个分类的概率
- y:直接是分类的代号
- crossEntropy会自动添加一个Softmax,所以不用自己加
NLLLoss
import torch
import torch.nn as nn
batch_size = 4
m = nn.LogSoftmax(dim=1)
criterion = nn.NLLLoss()
y_pred = torch.randn(batch_size, 5)
print(y_pred)
y = torch.empty(batch_size, dtype=torch.long).random_(5)
y_pred = m(y_pred) # 注意:这里用的是LogSoftmax 负log似然
loss = criterion(y_pred, y)
print(y_pred)
print(y)
print(loss)
"""
tensor([[-0.0823, -1.9247, -0.0603, 0.1532, -1.3969],
[ 0.4716, 1.2842, -0.9967, 1.2505, -0.5792],
[ 0.1119, 1.1941, -0.9118, 2.0806, -0.1346],
[ 0.2026, 0.6298, -0.2217, 0.7229, -0.1681]])
tensor([[-1.3123, -3.1547, -1.2903, -1.0768, -2.6269],
[-1.7939, -0.9813, -3.2621, -1.0150, -2.8447],
[-2.5058, -1.4236, -3.5295, -0.5371, -2.7523],
[-1.7156, -1.2884, -2.1399, -1.1953, -2.0863]])
tensor([3, 1, 1, 3])
tensor(1.1692)
"""
NLLLoss这里,y_pred需要经过LogSoftmax才行
版权声明:本文为qq_37774098原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END