前馈网络求导概论(一)·Softmax篇
Softmax是啥?
Hopfield网络的能量观点
1982年的Hopfiled网络首次将统计物理学的能量观点引入到神经网络中,
将神经网络的全局最小值求解,近似认为是求解热力学系统的能量最低点(最稳定点)。
为此,特地为神经网络定义了神经网络能量函数,其中为输入。
(省略Bias项)
值得注意的是,这套山寨牌能量函数只能求出局部最小值,SVM用二次规划函数替换掉之后才能求全局最小值。
唯一的败笔是,Hopfiled网络的输出仍然采用了阶跃函数Sign,走的还是Rosenblatt的老路子。
这个能量函数非常有趣,它在阶跃函数状态下永远是递减的,即便是W永远是正的。(错误的随机初始化也是OK的)。
原因如下:
I、当阶跃函数输出为1时,Wx为正,若产生Loss,,显然为负。
II、当阶跃函数输出为-1时,Wx为负,若产生Loss,,显然还是为负。
III、若无LOSS,或都为0,也为0。
概率与Boltzmann机
祖师爷Hinton在1985年创立了第一个随机神经网络,首次将概率引入神经网络这个大玄学中。
值得一提的是,在当时概率图模型也是被公认为玄学之一,很多研究者认为,信概率还不如信神经网络。(今天倒是反过来了)
Boltzmann机延续了Hopfiled能量函数的传统,但是用一个奇葩的归一化函数来产生概率,以取代相对不精确的阶跃函数。
这个归一化函数描述如下:
其中T为温度系数,超参数之一,需要调参。
看起来怎么那么眼熟呢,扔掉T之后,这不就是Sigmoid函数么。
可以看到,Boltzmann机为了表达概率,选用了Sigmoid函数作为神经网络的概率平滑产生器。
多变量概率与限制Boltzmann机
1986年由Smolensky创立的限制Boltzmann机将Hopfiled网络的输出部折回,这样就产生了多变量的输出。
如何去表达此时多变量情况下的概率,能量模型—配分函数(Partition Function)解决了这一点:
配分项Z是大家耳熟能详的恶心之物,它的求解让深度学习推迟了20年。
在深度学习被卡的20年间,配分项函数在多变量的判别模型中广泛推广,疑似是Softmax的雏形。
EBM(EnergyBased Model)
在LeCun的EBM教程Slides的介绍了配分判别函数,也就是今天的Softmax函数。
★The partition function ensures that undesired answers are given low probability
★For learning, we need to approximate the partition function (or its gradient with respect to the parameters)
顺便将其批判了一番:
★Max likelihood learning gives high probability to good answers
★Problem: there are too many bad answers!
这部分的观点可以参照PRML的序章关于贝叶斯拟合学习的讨论,采用配分判别的Loss、基于极大似然的频统方法
非常容易产生过拟合和弱泛化,贝叶斯学习和深度学习则引入先验Prior在极大似然的统计基础上做惩罚。
配分判别函数的定义如下:
其中为系数,扔掉之后就是Softmax函数。
SoftmaxLoss
不做过多介绍,见我的早期博文:Softmax回归
前向传播求Loss的时候只要记住一点区别:
I、在Logistic回归中,对每个样本,Loss-=或者Loss-=
II、在Softmax回归中,对每个样本,Loss只减去对应Label的
比较I、II也可以看出来,Logistic回归的二选一只是Softmax回归的N选一的特例。
泛型Softmax求导
尽管DeepLearning的基石是多样本与并行计算,但是在泛型章节中不考虑多样本情况。
求导描述将尽量与Caffe框架中的命名方式同步,以便于理解代码。
同时假定Softmax Axis上,命中Label的下标为k。
SoftmaxLoss
上图是在当单样本情况下,直接取Softmax Axis而画的,现在我们假设这是一个N=3的分类问题。(0,1,2)
同时取Class=2作为当前样本,命中的Label,即k=2。
由于Loss只和命中的分类有关,有:
则NLL (Negative-Log-Likelihood)为:
此时对于神经元,有如下两种求导方案:
I、
II、
其中,第一种是没有必要的,一般而言,Softmax的中间导数几乎不会用到。
除非我们让Softmax后面不接Loss,接其它的层,下一节会讲这种特殊情况,求导相当复杂。
现在考虑更一般的神经元,对NLL求导:
编程时:
对于①条件:先Copy一下Softmax的结果(即prob_data)到bottom_diff,再对k位置的unit减去1
对于②条件:直接Copy一下Softmax的结果(即prob_data)到bottom_diff
对于③条件:找到ignore位置的unit,强行置为0。
图示如下:
Softmax
在SoftmaxLayer中,我们将会遇到最普遍的反向传播任务:已知top_diff,求bottom_diff。
为了表述方便,设已知的top_diff的偏导表达式为:,则:
这是单独对Softmax求导的最麻烦之处,由于全连接性,输入神经元将被全部的输出神经元污染。
更一般的,我们将其写成:
。
考虑,有:
联合两部分后,有:
提取公共项部分:
Caffe中做了以下两点额外的优化:
I、由于对所有,都要计算相同的点积项,
一个简单优化是用GEMM做一次矩阵广播,这样,对每个样本的Softmax Axis轴上的多个单元,只需点积一次。
II、由于top_data与bottom_diff的shape相同,最外层top_data可基于全样本来乘,这在CUDA环境中,可以有效提升瞬时并行度。
空间Softmax求导
Fully Convolutional Networks for Semantic Segmentation
Caffe中将二轴Softmax(Batchsize/Softmax)扩展到了nD轴Softmax,用于全卷积网络。
这部分代码由此paper两位作者Jonathan Long&Evan Shelhamer加入,Github的History如下:
空间Soffmax是为了Dense Pixel Prediction(密集点预测)而生的,对于一张300x500的输入图像,
一次Softmax将产生300*500=15W个Loss,这属于神经网络——像素级理解,是目前最难的CV任务。
空间Softmax取消了Softmax前的InnerProduct做的Flatten,因为必须保证空间轴信息。
一个语义分割的图示如下:
GroundTruth、Outer_Num、Inner_Num
传统机器学习中的样本单数值Label,在ComputerVision中扩展为多数值Label后,即变成GroundTruth。
Caffe中采用以下格式来规范存储与读取:
对于GroundTruth的位置,即第个样本,空间位置的Label,对应的Softmax向量如下:
这样,对于outer_num数量的输入图像,就变成了outer_num*inner_num个像素样本。
值得注意的是,目前最新的研究表明,在像素级的理解中,batch_size大于1是没有意义的,会严重减慢收敛速度。
输入单张图像时,SGD做密集点预测,不会导致偏离最终的局部最值点,因为15W的Loss近似可以看成batch_size=15,0000
空间Softmax(without GroundTruth)
从上节可知,空间轴(e.g. Height/Width)的引入,可看成是倍化了batch_size轴。
故在SoftmaxLayer中,对单样本图像的输入,需要多引入一次循环模拟多样本,循环量即inner_num。
对于泛型Softmax中的点积运算,由计算单点积值,需要变化至求一组:
同样设,那么位置的两组点积向量分别如下:
由于点积的元素每次都要跳跃inner_num个位置,可利用BLAS库做StridedDot运算,点积增量设为inner_num即可。
I、在GEMM矩阵广播优化中,原来只需要将单点积值广播成[classes,1]的矩阵,顺次在Softmax-Axis轴上减去,即:
从的一段减去,由于无空间轴时,dim=classes,TopDiff的shape为[batch_size,classes],
矩阵的值恰好填充到下一样本的开头。
扩展空间轴时,则需要减去[classes,inner_num]个值,注意由于此时的shape为[batch_size,classes,inner_num],
如果你要线性覆盖,则需要先覆盖class=0的inner_num个值,所以一定要保证广播矩阵的shape为[classes,inner_num]。
然后再做一次向量减法。由于BLAS的GEMM运算支持,可一步完成。
II、在最外围的top_data乘算中,由于top_data与bottom_diff的shape相同,扩展空间轴无需调整代码。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)