NLLLoss
使用
1
torch.nn.NLLLoss()
具体操作
- 返回负对数似然损失(The negative log likelihood loss)
- 虽然命名是负对数自然损失, 但是实际上本函数不含有
log
操作,本函数假设log
操作在输入前已经完成了
常用于分类问题的损失函数
一般适用于网络最后一层为
log_softmax
的时候
计算公式
- 单个样本的计算公式:
- 普通样本计算公式:
loss(x,class)=−x[class] - 带有权重的单个样本计算公式:
loss(x,class)=−weights[class]∗x[class] - 因为多类别分类中,类别中只有一个维度是1, 其他维度都是0, 所以在计算时只考虑为1的维度就行, 为0的维度与当前类别值相乘为0
- (在这里我们存储的不是向量,而是该为1的维度的索引,所以使用-x[class]即可直接取出该样本对应的对数似然损失,其中,取对数的操作在输入前已经完成了)
- 普通样本计算公式:
- 批量样本的计算公式:
size_average=True
(default):
all_loss=1mini_batch_size∑iloss(xi,classi)size_average=False
:
all_loss=∑iloss(xi,classi)
CrossEntropyLoss
使用
1
torch.nn.CrossEntropyLoss()
具体操作
- 等价于
log_softmax
+torch.nn.NLLLoss()
- 先对网络输出做对数似然, 然后再
- 等价于
softmax的定义
softmax(xi)=exi∑j=1xjlog_softmax的定义
log(softmax(xi))- 注意: 这里的
log
是以e
为底的对数
- 注意: 这里的
为什么是这种实现方式?
- 为什么是
log_softmax
+torch.nn.NLLLoss()
的方式而不是普通的计算方式- 普通的计算方式是直接对每个概率求出log值, 然后相加, 本质上是一样的
CrossEntropyLoss
中多了个softmax是为了保证输入都是概率值
log(softmax(x))
的优化- 实际上使用的是
log_softmax(x)
log_softmax(x)
的运算速度比单独计算softmax
+log
的速度快- 同时二者的运算结果相同
- 文档中没有提到, 但是一种可能的优化方法是
logsofmax(x)=logexi∑j=1xj=logexi−log∑j=1xj=xi−log∑j=1xj - 上面的式子中,只需要计算一次 log∑j=1xj即可(且不同维度可重用该值), 其他的都是加减法运算
- 实际上使用的是
相关损失函数 BCELoss
使用
1
torch.nn.BCELoss()
具体操作
- 就是实现了书上定义的二分类交叉熵定义
计算公式:
- 单个样本的计算公式:
- 普通样本计算公式:
loss(o,t)=−1n∑i(t[i]log(o[i])+(1−t[i])log(1−o[i])) - 带有权重的单个样本计算公式:
loss(o,t)=−1n∑iweights[i] (t[i]log(o[i])+(1−t[i])∗log(1−o[i])) - 因为多类别分类中,类别中只有一个维度是1, 其他维度都是0, 所以在计算时只考虑为1的维度就行, 为0的维度与当前类别值相乘为0
- (在这里我们存储的不是向量,而是该为1的维度的索引,所以使用-x[class]即可直接取出该样本对应的对数似然损失,其中,取对数的操作在输入前已经完成了)
- 普通样本计算公式:
- 批量样本的计算公式:
size_average=True
(default):
all_loss=1mini_batch_size∑iloss(oi,ti)size_average=False
:
all_loss=∑iloss(oi,ti)
BCELoss vs CrossEntropyLoss
BCELoss
对应的网络只有一个输出值CrossEntropyLoss
对应的网络有两个输出值- 可以证明, 二分类时
BCELoss
与CrossEntropyLoss
等价- 证明时, 将每个
CrossEntropyLoss
的计算公式中的softmax
函数分子分母同时除以shift
, 即可得到为下面的定义, 进一步可得到BCELoss
的计算公式
fi(x)=e(xi−shift)∑je(xj−shift),shift=max(xi)
- 证明时, 将每个
相关损失函数 MultiLabelMarginLoss
使用
1
torch.nn.MultiLabelMarginLoss()
用于多标签分类的损失函数
总结
- 一般来说直接使用
CrossEntropyLoss
即可- 二分类时还可以使用
nn.BCELoss
- 二分类时使用
nn.BCELoss
的话,输入的input
和target
维度都为n * 1
的维度 - 二分类时使用
CrossEntropyLoss
则输入的input
为n * 2
的维度
- 二分类时还可以使用
- 如果使用
NLLLoss
则一定记得在输出层最后加一层log_softmax
层 - 注意,
log
指的是以e
为底的对数函数,而不是以10
为底的- Mac自带的计算器中
log
是以10
为底的,ln
才是以e
为底的
- Mac自带的计算器中