交叉熵和mse_Softmax与交叉熵损失的实现及求导

softmax函数

它接受一个向量(或者一组变量)作为输入,每个变量指数化后除以所有指数化变量之和,(顺便说一下,sigmoid函数就是其输入数为2时的特例),有点类似于对输入进行归一化,事实上它就叫做归一化指数函数

为了更直观的理解先来看一个栗子,现有一个向量如下

将其作为softamax的输入,先对其进行指数化:

最后就是:

得到的向量所有元素之和为1,每一个元素表示其概率。例如,在MNIST识别手写数字(0到9)的任务中,

就是一个包含10个元素的向量,

计算的结果的每个元素的值表示所要识别的数字为该数字的概率,取概率最高的作为结果

基本上的原理和功能都说明白了,不过在实际计算过程中有事会遇到一些问题,比如遇到

为这种情况:

碰到这种情况再计算

的话就可能因为数字过大而导致溢出,所以在进行计算之前需要读输入

进行一些处理,将

的每个元素都减上

的最大值,再进行Softmax计算:

可以看到,将所有元素都减去同一个值并不会改变最后的结果。以上,是softmax是计算过程

交叉熵损失函数(CrossEntropyLoss)

网络的训练需要有损失函数,而softmax对应的损失函数就是交叉熵损失函数,它多作做分类任务中,计算公式如下:

上式中,

是softmax的计算结果;

是训练样本的标签,表示该样本正确的分类类型,如果以向量表示的话,其中只有一个元素为1,其余元素都为0:

基于这个特性,所以损失大小只与网络判断正确分类的概率有关。举个栗子,一个样本的正确分类是第t类,即

,所以损失的公式可以简化为:

来看看对数函数的图像:

因为

是网络判断该样本属于第t类的概率,

,所以

的值越接近1,损失越小(趋近0),所以

的值越接近0,损失越大(趋近无穷大)

梯度计算

首先是损失关于

的梯度。因为损失是一个标量(数值),而

是一个向量,所以损失关于

的梯度也是一个向量

因为公式损失的计算公式很简单,所以梯度推导也不复杂,下面直接写公式:

最后得到:

接下来是是softmax梯度的推导,先回顾下softmax函数的公式:

将其计算路径如下图所示:

观察上图中的计算路径,可以将

看作

的多元复合函数

所以,该函数的导数偏导计算公式如下:

(1)

为了方便理解,顺便贴一下求导路径:

式(1)分为两部分,分别来计算:

整理得到:

(2)

然后是另一部分:

(3)

将(2),(3)的结果带入(1)中,得到:

(4)

在实现中,如果是将softmax实现为独立的层(Layer)的话,根据到这一步为止的讨论已经可以写出softmax的代码了:

class Softmax:

def forward(self, x):

v = np.exp(x - x.max(axis=-1, keepdims=True))

self.a = v / v.sum(axis=-1, keepdims=True)

return self.a

def backward(self, y):

return self.a * (eta - np.einsum('ij,ij->i', eta, self.a, optimize=True))

上面代码中反向计算的实现使用了爱因斯坦求和约定,不太了解的可以参考这个链接

然而在一些网络的实现中,softmax层并不包含在其中,例如,有一个分类任务,所有的样本分别属于三类,假设对于某个样本,网络的最后一层的输出为:

显然,现在已经知道网络对该样本类别的推断了(softmax不过是进一步计算各个类别的概率而已)

所以,交叉熵损失的梯度计算中会包含softmax的这部分,所以把

的具体值代入到(4)中:

因为

只有一个元素为1,其余都为0,所以

,最终得到:

最后,是交叉熵损失函数的实现代码:

class CrossEntropyLoss:

def __init__(self):

# 内置一个softmax作为分类器

self.classifier = Softmax()

def backward(self):

return self.classifier.a - self.y

def __call__(self, a, y):

'''a: 批量的样本输出y: 批量的样本真值return: 该批样本的平均损失'''

a = self.classifier.forward(a) # 得到各个类别的概率

self.y = y

loss = np.einsum('ij,ij->', y, np.log(a), optimize=True) / y.shape[0]

return -loss

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值