在CNN中,全连接层后会加上softmax函数,并且一般用交叉熵函数作为损失函数。这篇文章主要记录softmax把CNN的输出变成概率的过程以及交叉熵如何为优化过程提供度量,并且用python实现。
softmax函数
softmax函数将一个N维向量的输入的每一维都转换成区间维(0,1)之间的一个实数,公式如下:
pi=eai∑Nk=1eak p i = e a i ∑ k = 1 N e k a
softmax可以将全连接层的输出映射成一个概率分布,我们的训练目标是让属于第k类的样本经过softmax函数之后,第k类概率越大越好。
下面是使用python实现softmax函数:
def softmax(x):
exps = np.exp(x)
return exps / np.sum(exps)
由于numpy中浮点类型是有数值上的限制的,对于指数函数来说很容易打破上线返回nan。
为了避免出现nan这种情况,通常在分子和分母上同时乘一个常数C,表达式如下:
pj=eai∑Nk=1eak=CeaiC∑Nk=1eak=eai+log(C)∑Nk=1eak+log(C) p j = e a i ∑ k = 1 N e a k = C e a i C ∑ k = 1 N e a k = e a i + l o g ( C ) ∑ k = 1 N e a k + l o g ( C )
理论上我们可以选择任何一个值作为log(C),但是一般我们会选择log(C)=-max(a),通过这种方法可以使得原来非常大的指数结果变成0,避免出现nan的情况。
下面是用python实现改进后的softmax函数:
def stable_softmax(x):
exps = np.exp(x-np.max(x))
return exps / np.sum(exps)
softmax函数的导数推倒过程
softmax函数可以将样本输出变成概率密度函数,由于这一特性我们可以把它放到神经网络最后一层,最理想的输出就是样本类别one-hot的表现形式。我们接下来了解一下如何计算softmax函数的梯度,首先对softmax函数求导:
∂pj∂aj=∂eai∑Nk=1eak∂aj ∂ p j ∂ a j = ∂ e a i ∑ k = 1 N e a k ∂ a j
根据求导法则 f(x)=g(x)h(x) f ( x ) = g ( x ) h ( x ) 的导数为 f′(x)=g′(x)h(x)−