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 = \frac{1}{mini\_batch\_size}\sum_i loss(x_i, class_i)$$size_average=False
:
$$all\_loss = \sum_i loss(x_i, class_i)$$
CrossEntropyLoss
使用
1
torch.nn.CrossEntropyLoss()
具体操作
- 等价于
log_softmax
+torch.nn.NLLLoss()
- 先对网络输出做对数似然, 然后再
- 等价于
softmax的定义
$$softmax(x_{i}) = \frac{e^{x_{i}}}{\sum_{j=1}x_{j}}$$log_softmax的定义
$$log(softmax(x_{i}))$$- 注意: 这里的
log
是以e
为底的对数
- 注意: 这里的
为什么是这种实现方式?
- 为什么是
log_softmax
+torch.nn.NLLLoss()
的方式而不是普通的计算方式- 普通的计算方式是直接对每个概率求出log值, 然后相加, 本质上是一样的
CrossEntropyLoss
中多了个softmax是为了保证输入都是概率值
log(softmax(x))
的优化- 实际上使用的是
log_softmax(x)
log_softmax(x)
的运算速度比单独计算softmax
+log
的速度快- 同时二者的运算结果相同
- 文档中没有提到, 但是一种可能的优化方法是
$$
\begin{align}
log_sofmax(x) &= log \frac{e^{x_{i}}}{\sum_{j=1}x_{j}} \\
&= log e^{x_i} - log \sum_{j=1}x_{j} \\
&= x_i - log \sum_{j=1}x_{j}
\end{align}
$$ - 上面的式子中,只需要计算一次 \(log \sum_{j=1}x_{j}\)即可(且不同维度可重用该值), 其他的都是加减法运算
- 实际上使用的是
相关损失函数 BCELoss
使用
1
torch.nn.BCELoss()
具体操作
- 就是实现了书上定义的二分类交叉熵定义
计算公式:
- 单个样本的计算公式:
- 普通样本计算公式:
$$ loss(o,t)=-\frac{1}{n}\sum_i(t[i] log(o[i])+(1-t[i]) log(1-o[i])) $$ - 带有权重的单个样本计算公式:
$$ loss(o,t)=-\frac{1}{n}\sum_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 = \frac{1}{mini\_batch\_size}\sum_i loss(o_i, t_i)$$size_average=False
:
$$all\_loss = \sum_i loss(o_i, t_i)$$
BCELoss vs CrossEntropyLoss
BCELoss
对应的网络只有一个输出值CrossEntropyLoss
对应的网络有两个输出值- 可以证明, 二分类时
BCELoss
与CrossEntropyLoss
等价- 证明时, 将每个
CrossEntropyLoss
的计算公式中的softmax
函数分子分母同时除以shift
, 即可得到为下面的定义, 进一步可得到BCELoss
的计算公式
$$f_i(x) = \frac{e^{(x_i - shift)}} { \sum^j e^{(x_j - shift)}},shift = max (x_i)$$
- 证明时, 将每个
相关损失函数 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自带的计算器中