天天看点

softmax杂谈

softmax杂谈

在多分类问题中,我们可以使用 softmax 函数,对输出的值归一化为概率值。下面举个例子:

softmax杂谈

上图转换为表达式:

????(0)=(????(0)0,????(0)1,⋯,????(0)9)????????(1)=(????(1)0,????(1)1,⋯,????(1)6)????????(2)=(????(2)0,????(2)1,⋯,????(2)4)????a(0)=(a0(0),a1(0),⋯,a9(0))Ta(1)=(a0(1),a1(1),⋯,a6(1))Ta(2)=(a0(2),a1(2),⋯,a4(2))T

对于任意的 0≤????≤20≤i≤2, 有前向传播的表达式:

????(????+1)=????(????)????(????)+????(????)????(????+1)=????(????+1)(????(????+1))z(i+1)=W(i)a(i)+b(i)a(i+1)=f(i+1)(z(i+1))

其中,????(????)f(j) 表示激活函数,除了输出层外,一般使用 ReLU 函数;????(????),????(????)W(i),b(i) 为模型参数。

如若我们有 ????m 个样本 {????(????)}????????=1{x(j)}j=1m 组成的数据集 ????D, 称 ????=(????(1),????(2),⋯,????(????))????X=(x(1),x(2),⋯,x(m))T 为数据集 ????D 的设计矩阵。

这样,前向传播可以改写为:

{????(1+????)=????(????)????(0)+(????(????))????????(1+????)=????(1+????)(????(1+????)){Z(1+i)=Z(i)W(0)+(b(i))TA(1+i)=f(1+i)(Z(1+i))

????(????)=(????(????)1,????(????)2,⋯,????(????)????)????Z(i)=(z1(i),z2(i),⋯,zm(i))T, 这里对 ????(????)z(i) 添加下标以区别不同的样本;

这里对列向量 ????(????)b(i) 进行了 broadcast 操作;

且 ????(0)=????Z(0)=X.

softmax杂谈

对于多分类问题,一般输出层对应的激活函数的 softmax 函数:

求解 ????(2)A(2):

计算 ????????????=exp(????(1))exp=exp⁡(Z(1));

对 ????????????exp 按列做归一化, 便可得到 softmax(????(1))softmax(A(1)).

但如果输入值较大或较小时,会出现内存溢出的现象:

一种简单有效避免该问题的方法就是让 exp(????????)exp⁡(zj) 中的 ????????zj 替换为 ????????−max????{????????}zj−maxi{zi}, 由于 max????maxi 是个固定的常数,所以 exp(????????)exp⁡(zj)的值没有改变。但是,此时避免了溢出现象的出现。

当然这种做法也不是最完美的,因为 softmax 函数不可能产生 <code>0</code> 值,但这总比出现 <code>nan</code> 的结果好,并且真实的结果也是非常接近 00 的。

除此之外,还有一个问题:如果我们计算 logsoftmax(????????)log⁡softmax(zj) 时,先计算 softmaxsoftmax 再将其传递给 loglog,会错误的得到 −∞−∞

最简单的处理方式是直接加一个很小的常数:

为了解决此数值计算的不稳定,MXNet 提供了:

解决计算交叉熵时出现的数值不稳定的问题。