0. 前言

  • 文章来源:CSDN@LawsonAbs
  • log_softmax计算损失的时候常用的一个函数,那么这个函数的内部到底是怎么做到的呢?这里详细的解释一下。

1. 代码

写代码前,回忆一下log_softmax的公式 − l o g e x p ( p j ) ∑ i e x p ( p i ) -log\frac{exp(p_j)}{\sum_{i}exp(p_i)} logiexp(pi)exp(pj),其实就是 log + softmax。 下面就来实现一下这个函数。

'''自己实现log_softmax 函数
(1)使用torch.exp()函数计算各个logit的e次幂
(2)使用torch.sum()函数计算求和
(3)使用torch.log对比例求对数
可以发现,二者最终的结果是相同的
'''
import torch as t
import torch.nn.functional as F
logit = t.tensor([0.1,0.1,0.1,0.7])
a = t.exp(logit)
print("a=",a)
b = t.sum(a,dim=0,keepdim=True)
print("b=",b)
c=t.log(a/b)
print(c)
print(F.log_softmax(logit)) 

执行结果:
在这里插入图片描述

2. 思考

尽管二者输出一致,但是二者实现过程是相同的吗?可以肯定的回答:不相同!
这里实现的log + softmax 还是有很多bug的,比如存在上溢出的风险,从而得到nan 的结果。 ∑ e x p ( x i ) \sum exp(x_i) exp(xi) 是很容易上溢出的,那么有什么办法解决这个问题呢?如下所述就是一种简单的方法,这里就不展开叙述了。
l o g _ s o f t m a x = l o g e x p ( x j ) ∑ i e x p ( x i ) = l o g e x p ( x j ) / e x p ( c ) ∑ i e x p ( x i ) / e x p ( c ) = l o g e x p ( x j − c ) ∑ i e x p ( x i − c ) \begin{aligned} log\_softmax &= log \frac{exp(x_j)}{\sum _i exp_(x_i)} \\ &= log \frac{exp(x_j)/exp(c)}{\sum _i exp_(x_i)/exp(c)} \\ &= log \frac{exp(x_j-c)}{\sum _i exp_(x_i-c)} \\ \end{aligned} log_softmax=logiexp(xi)exp(xj)=logiexp(xi)/exp(c)exp(xj)/exp(c)=logiexp(xic)exp(xjc)
其中 c = m a x ( x i ) c = max(x_i) c=max(xi)
我想说的只有一点:以后想用log_softmax的话,可以直接使用pytorch中的log_softmax()函数即可,如果想自己分开搞大概率会出错。

要对论文中的公式非常敏感。很多损失其实就是 log_softmax 的变形而已。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐