Softmax是深度学习模型中常用的一种函数,常常用在分类模型的最后一层。向量经过softmax函数后,其总和等于1,因此能够作为分类模型的输出,用来逼近一个真实的概率分布。
1 数学定义
softmax函数的定义为:
下面的代码展示了softmax函数的一种简单的实现方式。
import torch
def my_softmax(z, dim):
# z.shape == bn, n
= torch.exp(z)
z = z / torch.sum(z, dim=dim)
z return z
= torch.rand(10, 100)
tensor_test = (my_softmax(tensor_test, 0) - torch.softmax(tensor_test, 0)).abs().mean().item()
diff assert diff < 1e-6, diff
print('Difference: ', diff)
Difference: 6.180256750809576e-09
2 Softmax的上溢和下溢问题
softmax在计算机的实际运算过程中,容易遇到上溢和下溢问题。 设
下面的代码展示了softmax的计算中出现上溢出和下溢出的情形。
= my_softmax(tensor_test + 1e5, 0)
out if torch.any(torch.isnan(out)):
print('检测到上溢!')
= my_softmax(tensor_test - 1e5, 0)
out if torch.any(torch.isnan(out)):
print('检测到下溢!')
= torch.softmax(tensor_test + 1e5, 0)
out = torch.softmax(tensor_test - 1e5, 0)
out2 if not (
any(torch.isnan(out)) or
torch.any(torch.isnan(out2))
torch.
):print('torch.softmax函数没有出现上溢下溢问题。')
检测到上溢!
检测到下溢!
torch.softmax函数没有出现上溢下溢问题。
尽管我们实现的简单的softmax函数会发生上溢和下溢,但torch的softmax函数没有出现问题。torch是如何做到的呢?
2.1 上溢和下溢问题的应对方法
softmax函数有这样的特性:
选取
改进后的softmax函数如下:
def my_softmax_2(z, dim):
# z.shape == bn, n
# 减去最大值
-= z.max(dim=dim)[0]
z
= torch.exp(z)
z = z / torch.sum(z, dim=dim)
z return z
= my_softmax_2(tensor_test + 1e5, 0)
out if torch.any(torch.isnan(out)):
print('检测到上溢!')
= my_softmax_2(tensor_test - 1e5, 0)
out if torch.any(torch.isnan(out)):
print('检测到下溢!')
= (my_softmax_2(tensor_test, 0) - torch.softmax(tensor_test, 0)).abs().mean().item()
diff assert diff < 1e-6, diff
print('Difference: ', diff)
Difference: 9.164214387347158e-10
3 Softmax函数求导
softmax是一个将向量映射为向量的函数。求其输出对输入的导数得到一个雅克比矩阵。为了方便,记
第一种情况的导数计算如下:
观察该矩阵,我们可以发现在两种情况下,矩阵的将会接近0矩阵。一是 当softmax函数的输出为one hot时(即
4 结语
记得在读硕士的最后一学期时,有一回面试一家公司。这家公司是国内小有名气的中厰。面试官问了softmax函数的问题,我便以上面所述的内容对之。结束时,面试官笑著说,记得几年前,我问同样的问题,几乎没几个人答得上来。但是,今年同样的问题,居然人人都能回答上来呢。
听到面试官的话,我也不禁感慨。看来这几年时间过去,深度学习/人工智能的赛道确实是越来越卷了。作为一名准备面试的学生,这个问题在我看来确实是常识。再过几年,它会不会成为一般本科生,甚至中小学生的常识呢。笑。