Softmax函数的性质

本文瀏覽次數19

发布日期

2024年1月9日

Softmax是深度学习模型中常用的一种函数,常常用在分类模型的最后一层。向量经过softmax函数后,其总和等于1,因此能够作为分类模型的输出,用来逼近一个真实的概率分布。

1 数学定义

softmax函数的定义为: σ(z)i=ezijezj,(1) 其中,z为输入向量。

下面的代码展示了softmax函数的一种简单的实现方式。

import torch 

def my_softmax(z, dim):
    # z.shape == bn, n
    z = torch.exp(z)
    z = z / torch.sum(z, dim=dim)
    return z 

tensor_test = torch.rand(10, 100)
diff = (my_softmax(tensor_test, 0) - torch.softmax(tensor_test, 0)).abs().mean().item()
assert diff < 1e-6, diff
print('Difference: ', diff)
Difference:  6.180256750809576e-09

2 Softmax的上溢和下溢问题

softmax在计算机的实际运算过程中,容易遇到上溢和下溢问题。 设z是softmax函数的输入。假如z中的数值都极小(趋于负无穷大),这时公式 1的分母接近0,容易导致产生的数超出浮点型的上限,这被称为下溢;反之,若z中存在特别大的数,由于函数ex增长极快,输出的数也很可能超出浮点型的上限,这被称为上溢

下面的代码展示了softmax的计算中出现上溢出和下溢出的情形。

out = my_softmax(tensor_test + 1e5, 0)
if torch.any(torch.isnan(out)):
    print('检测到上溢!')

out = my_softmax(tensor_test - 1e5, 0)
if torch.any(torch.isnan(out)):
    print('检测到下溢!')

out = torch.softmax(tensor_test + 1e5, 0)
out2 = torch.softmax(tensor_test - 1e5, 0)
if not (
    torch.any(torch.isnan(out)) or 
    torch.any(torch.isnan(out2))
):
    print('torch.softmax函数没有出现上溢下溢问题。')
检测到上溢!
检测到下溢!
torch.softmax函数没有出现上溢下溢问题。

尽管我们实现的简单的softmax函数会发生上溢和下溢,但torch的softmax函数没有出现问题。torch是如何做到的呢?

2.1 上溢和下溢问题的应对方法

softmax函数有这样的特性:softmax(z+y)=softmax(z),yR,即对输入向量随意加上任意一个数,输出都不会变。

选取y=zk,其中k=maxj(zj),可以解决这一问题。这时,j,ezj+yj=k时取得最大值,最大值为1,于是不存在上溢。同时,由于分母必然大于等于1,因此也不存在下溢。

改进后的softmax函数如下:

def my_softmax_2(z, dim):
    # z.shape == bn, n

    # 减去最大值
    z -= z.max(dim=dim)[0]

    z = torch.exp(z)
    z = z / torch.sum(z, dim=dim)
    return z 

out = my_softmax_2(tensor_test + 1e5, 0)
if torch.any(torch.isnan(out)):
    print('检测到上溢!')

out = my_softmax_2(tensor_test - 1e5, 0)
if torch.any(torch.isnan(out)):
    print('检测到下溢!')

diff = (my_softmax_2(tensor_test, 0) - torch.softmax(tensor_test, 0)).abs().mean().item()
assert diff < 1e-6, diff
print('Difference: ', diff)
Difference:  9.164214387347158e-10

3 Softmax函数求导

softmax是一个将向量映射为向量的函数。求其输出对输入的导数得到一个雅克比矩阵。为了方便,记si:=σ(z)i. 计算该雅克比矩阵要分两种情况讨论。一是sizi(雅克比矩阵的对角线),二是sizk,ik的情况。

第一种情况的导数计算如下: si=ezijezj=1j,jiezjzi+1sizi=ezijezj(jezj)2eziezi(jezj)2=sisi2=si(1si), 第二种情况的导数sizk(ik)计算如下: sizk=eziezk(jezj)2=sisk 因此对softmax函数求导,其雅可比矩阵为: (s1(1s1)s1s2s1s3s1sns2s1s2(1s2)s2s3s2snsns1sns2sns3sn(1sn))

观察该矩阵,我们可以发现在两种情况下,矩阵的将会接近0矩阵。一是 当softmax函数的输出为one hot时(即si=1ji,sj=0),得到的雅克比矩阵为0矩阵;另一种情况是softmax的输出维度较多,且个维度的值都较为均等的情况,此时s1s2s3sn0。训练中,这两种情况将导致梯度消失,可能影响训练,因此是我们要提前了解的。

4 结语

记得在读硕士的最后一学期时,有一回面试一家公司。这家公司是国内小有名气的中厰。面试官问了softmax函数的问题,我便以上面所述的内容对之。结束时,面试官笑著说,记得几年前,我问同样的问题,几乎没几个人答得上来。但是,今年同样的问题,居然人人都能回答上来呢。

听到面试官的话,我也不禁感慨。看来这几年时间过去,深度学习/人工智能的赛道确实是越来越卷了。作为一名准备面试的学生,这个问题在我看来确实是常识。再过几年,它会不会成为一般本科生,甚至中小学生的常识呢。笑。

By @執迷 in
Tags : #深度學習,