0


【深度学习】4-梯度确认时遇bug:写了个糟糕的softmax函数

🚩 前言

活动地址:CSDN21天学习挑战赛
🚀 博主主页:阿阿阿阿锋的主页_CSDN
🌊 希望和大家一起加油,一起进步!

今天学习《深度学习入门:基于python的理论与实践》时,被梯度确认的问题卡了很久。具体过程就不赘述,最终发现是我写的 softmax 函数的问题,导致的数值微分与反向传播求得的梯度总对不上。
softmax 问题在于我这里没有考虑好不同维度数据的情况。


文章目录


1. softmax函数代码

import numpy as np

defsoftmax(a): 
    a -= np.max(a)
    exp_a = np.exp(a)return exp_a / np.sum(exp_a)

2. 不能正确处理批量样本

我们对比一下处理单个样本和批量样本的情况:

a = np.array([1,2,3])
b = np.array([[1,2,3],[1,2,3]])
softmax(a), softmax(b)
输出:
(array([0.09003057, 0.24472847, 0.66524096]),
 array([[0.04501529, 0.12236424, 0.33262048],
        [0.04501529, 0.12236424, 0.33262048]]))

容易发现,对应的值,后者的结果都是前者的一半。问题就在

np.sum(exp_a)

这里:
在批量数据(矩阵)情况下,我们本意是每个样本求得一个和值,即按行求和。它却将所有数据相加而仅得到一个和值。

再验证一下:

a = np.array([1,2,3])
b = np.array([[1,2,3],[1,2,3],[1,2,3]])
softmax(a), softmax(b)
输出:
(array([0.09003057, 0.24472847, 0.66524096]),
 array([[0.03001019, 0.08157616, 0.22174699],
        [0.03001019, 0.08157616, 0.22174699],
        [0.03001019, 0.08157616, 0.22174699]]))

可以看到,样本数增加为 3 个时,后者的输出也相应地变成了前者的三分之一。此时前者输出的 3 个数和为 1 ,而后者是输出的 9 个数和为 1。

现在单样本和批量的输出之间还具有倍数关系,如果每个样本是数据不同,那么将会更加乱套:

a = np.array([1,2,3])
b = np.array([[1,2,3],[4,5,6]])
softmax(a), softmax(b)
输出:
(array([0.09003057, 0.24472847, 0.66524096]),
 array([[0.00426978, 0.01160646, 0.03154963],
        [0.08576079, 0.23312201, 0.63369132]]))

3. 解决方案

分情况处理即可:

defsoftmax(x):if x.ndim ==2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x)/ np.sum(np.exp(x), axis=0)return y.T 

    x = x - np.max(x)return np.exp(x)/ np.sum(np.exp(x))
注:此代码来自前言提到的书本

我们之前分析了,其实就是求和函数的问题,因此我尝试着能不能写得更加简洁和统一些。

但是我没有成功,因为会遇到一些细节处理上的问题,例如批量情况下:最大值 max 也应当是按行求得;

np.sum

得到的是一维数组,为了最后相除时能够进行广播,进行转置是有必要的。

不过修改代码的尝试倒是加深了我对它的理解。


感谢阅读

标签: 深度学习 bug python

本文转载自: https://blog.csdn.net/m0_63238256/article/details/126411411
版权归原作者 阿阿阿阿锋 所有, 如有侵权,请联系我们删除。

“【深度学习】4-梯度确认时遇bug:写了个糟糕的softmax函数”的评论:

还没有评论