常见的损失函数在pytorch框架的应用(持续更新)

前言

目前在比较流行的深度框架tensorflow、pytorch中损失函数都已经被封装的很好了,大家在使用的过程中直接调用就可以了,但是时间长了,大家就可能不记得函数内部的数学逻辑了,在这里写这一片文章的主要的原因就是方便忘记的时候来进行回忆。

二分类损失函数

二分类损失函数主要是用在分类任务中,对应的激活函数是sigmoid函数,下面我们来进行展开二分类损失函数的公式、意义和与之对应的sigmoid函数。
以神经元来进行举例子,通常一个神经元的输出表达形式为:
在这里插入图片描述
x表示特征,w表示的是神经元里面的参数,b表示的是偏置,和h(w)表示的一个神经元的输出。
在深度学习中神经元后面跟的是激活函数,激活函数主要作用是在模型中引入非线性因素来让模型能够拟合任何问题,避免模型成为一个线性组合的过程,这里就不在这里进行赘述了,感兴趣的可以自己搜索学习,网上的资料很多。二分类任务中一般用的是sigmoid函数,但是任何事情不是绝对的,也有softmax函数的,这个在以后会进行介绍,sigmoid函数函数的数学表达式:
在这里插入图片描述
公式中的和h(w)表示的神经网络的输出,sigmoid函数的输出值域范围是(0,1),sigmoid函数激活函数很少放在神经网络中来充当激活函数,这是由于该函数的导数范围所决定的,其导数的取值范围在(0,0.25],正是这个导数的取值范围很小导致的结果就是很容易造成网络反向链式传播的过程中梯度消失,这个现象不利于网络的加深换句话说就是不利于用在网络很深的神经网络中。sigmoid函数目前是用在二分类任务中的末端也就是放在输出端。计算方式如下:
在这里插入图片描述
上图就是把这个函数的计算过程解释的很明白了,感兴趣的可以看一下。

咱们言归正传,下面进入主题,正式解释一下二分类任务中的损失函数-二分类交叉熵函数。下面我们看一个公式:
在这里插入图片描述
上面的公式有一种叫法是对数释然损失,关于这个公式里面的y=1、y=0表示的是分类的类别,二分类任务中标签值一般设置为0和1,h(x)表示的是神经元经过激活函数的输出值,根据目标值来选择将sigmoid输出带入到相应的公式中来求损失值。下面我们来论证一下h(x)和损失值的关系,如下图:
在这里插入图片描述
上面是目标值y=1的时候输出与损失之间的关系,可以看出当输入越大对应的损失值越小,也就是损失值和和sigmoid的输出成反比。当目标值为0的时候我们可以看到就是当sigmoid的输出越小对应的损失函数的值也就小。以上解释就很好诠释了深度学习中二分类的模型的训练过程。
上面的对数释然损失是个分段函数,下面我们将这个分段函数整合到一块,方便大家学习,公式如下:
在这里插入图片描述
接下来我们呢就带入上面那个例子来计算一遍,就能理解意义了。
在这里插入图片描述
我们已经知道,-log§, P值越大,结果越小,所以我们可以对着这个损失的式子去分析,以上就是关于sigmoi和对应的损失函数的相关理解,为了方便理解,下面我写一个例子,方便大家的理解。
首先我写一个简单的模型例子,然后观察输出:

import  torch.nn as nn
# 随机生成的图片
x=torch.randn([3,3,512,512],requires_grad=True)
class model(nn.Module):
    def __init__(self,F_g=3,F_int=10,img_size=512,num_classes=2):
        super(model, self).__init__()
        self.conv1= nn.Conv2d(in_channels=F_g, out_channels=F_int, kernel_size=3, stride=1, padding=1, bias=True)
        pool_kernel = int(img_size)
        # 全局平均池化,输出(n,c,1,1)的特征图
        self.avgpool = nn.AvgPool2d(pool_kernel, stride=1, ceil_mode=True)
        self.fc1 = nn.Linear(F_int, 50)
        self.fc2 = nn.Linear(50,1 )
        # sigmoid损失函数
        
    def run(self,x):
        x=self.conv1(x)
        x=self.avgpool(x)
        x=x.view(x.size(0),-1)
        x=self.fc1(x)
        x=self.fc2(x)
        print(x)
        return x
Model=model()
output=Model.run(x)
output1=torch.sigmoid(output)
# output1=output1.reshape(-1)
target=torch.tensor([1.,1.,0.])
Loss1=nn.BCELoss()
loss1=Loss1(output1.reshape(-1),target)
print("loss1",loss1)
Loss2=nn.BCEWithLogitsLoss()
loss2=Loss2(output.reshape(-1),target)
print("loss2",loss2)

运行输出:

tensor([[-0.0381],
        [-0.0381],
        [-0.0382]], grad_fn=<AddmmBackward>)
loss1 tensor(0.6997, grad_fn=<BinaryCrossEntropyBackward>)
loss2 tensor(0.6997, grad_fn=<BinaryCrossEntropyWithLogitsBackward>)

上面就是自己随机写的一个小网络,针对输出的图片进行分类,使用两种求二分类交叉熵的办法,具体的使用方法可以自己认真看一下。
pytorch中二分类损失函数有两种,它们分别是:

torch.nn.BCELoss() 和 torch.nn.BCEWithLogitsLoss()

BCE这三个字母其实就是binary cross entropy的缩写

他们的区别是:
(1)BCELoss:需要先将最后一层经过sigmoid进行缩放然后再通过该函数
(2)BCEWithLogitsLoss:BCEWithLogitsLoss就是把Sigmoid-BCELoss合成一步,不再需要在最后经过sigmoid进行缩放,直接对最后得到的logits进行处理。
备注:logits,指的是还没有经过sigmoid和softmax缩放的结果哦!

多分类损失函数

我们知道卷积神经网络(CNN)在图像领域的应用已经非常广泛了,一般一个CNN网络主要包含卷积层,池化层(pooling),全连接层,损失层等。虽然现在已经开源了很多深度学习框架(比如MxNet,Caffe等),训练一个模型变得非常简单,但是你对这些层具体是怎么实现的了解吗?你对softmax,softmax loss,cross entropy了解吗?相信很多人不一定清楚。虽然网上的资料很多,但是质量参差不齐,常常看得眼花缭乱。为了让大家少走弯路,特地整理了下这些知识点的来龙去脉,希望不仅帮助自己巩固知识,也能帮到他人理解这些内容。

这一篇主要介绍全连接层和损失层的内容,算是网络里面比较基础的一块内容。先理清下从全连接层到损失层之间的计算。来看下面这张图,来自参考资料1(自己实在懒得画图了)。

这张图的等号左边部分就是全连接层做的事,W是全连接层的参数,我们也称为权值,X是全连接层的输入,也就是特征。从图上可以看出特征X是N1的向量,这是怎么得到的呢?这个特征就是由全连接层前面多个卷积层和池化层处理后得到的,假设全连接层前面连接的是一个卷积层,这个卷积层的输出是100个特征(也就是我们常说的feature map的channel为100),每个特征的大小是44,那么在将这些特征输入给全连接层之前会将这些特征flat成N1的向量(这个时候N就是10044=1600)。解释完X,再来看W,W是全连接层的参数,是个TN的矩阵,这个N和X的N对应,T表示类别数,比如你是7分类,那么T就是7。我们所说的训练一个网络,对于全连接层而言就是寻找最合适的W矩阵。因此全连接层就是执行WX得到一个T1的向量(也就是图中的logits[T1]),这个向量里面的每个数都没有大小限制的,也就是从负无穷大到正无穷大。然后如果你是多分类问题,一般会在全连接层后面接一个softmax层,这个softmax的输入是T1的向量,输出也是T1的向量(也就是图中的prob[T*1],这个向量的每个值表示这个样本属于每个类的概率),只不过输出的向量的每个值的大小范围为0到1。

现在你知道softmax的输出向量是什么意思了,就是概率,该样本属于各个类的概率!

那么softmax执行了什么操作可以得到0到1的概率呢?先来看看softmax的公式(以前自己看这些内容时候对公式也很反感,不过静下心来看就好了):

公式非常简单,前面说过softmax的输入是WX,假设模型的输入样本是I,讨论一个3分类问题(类别用1,2,3表示),样本I的真实类别是2,那么这个样本I经过网络所有层到达softmax层之前就得到了WX,也就是说WX是一个31的向量,那么上面公式中的aj就表示这个31的向量中的第j个值(最后会得到S1,S2,S3);而分母中的ak则表示31的向量中的3个值,所以会有个求和符号(这里求和是k从1到T,T和上面图中的T是对应相等的,也就是类别数的意思,j的范围也是1到T)。因为e^x恒大于0,所以分子永远是正数,分母又是多个正数的和,所以分母也肯定是正数,因此Sj是正数,而且范围是(0,1)。如果现在不是在训练模型,而是在测试模型,那么当一个样本经过softmax层并输出一个T1的向量时,就会取这个向量中值最大的那个数的index作为这个样本的预测标签。

因此我们训练全连接层的W的目标就是使得其输出的WX在经过softmax层计算后其对应于真实标签的预测概率要最高。

举个例子:假设你的WX=[1,2,3],那么经过softmax层后就会得到[0.09,0.24,0.67],这三个数字表示这个样本属于第1,2,3类的概率分别是0.09,0.24,0.67。

———————————–华丽的分割线——————————————

弄懂了softmax,就要来说说softmax loss了。
那softmax loss是什么意思呢?如下:

首先L是损失。Sj是softmax的输出向量S的第j个值,前面已经介绍过了,表示的是这个样本属于第j个类别的概率。yj前面有个求和符号,j的范围也是1到类别数T,因此y是一个1*T的向量,里面的T个值,而且只有1个值是1,其他T-1个值都是0。那么哪个位置的值是1呢?答案是真实标签对应的位置的那个值是1,其他都是0。所以这个公式其实有一个更简单的形式:

当然此时要限定j是指向当前样本的真实标签。

来举个例子吧。假设一个5分类问题,然后一个样本I的标签y=[0,0,0,1,0],也就是说样本I的真实标签是4,假设模型预测的结果概率(softmax的输出)p=[0.1,0.15,0.05,0.6,0.1],可以看出这个预测是对的,那么对应的损失L=-log(0.6),也就是当这个样本经过这样的网络参数产生这样的预测p时,它的损失是-log(0.6)。那么假设p=[0.15,0.2,0.4,0.1,0.15],这个预测结果就很离谱了,因为真实标签是4,而你觉得这个样本是4的概率只有0.1(远不如其他概率高,如果是在测试阶段,那么模型就会预测该样本属于类别3),对应损失L=-log(0.1)。那么假设p=[0.05,0.15,0.4,0.3,0.1],这个预测结果虽然也错了,但是没有前面那个那么离谱,对应的损失L=-log(0.3)。我们知道log函数在输入小于1的时候是个负数,而且log函数是递增函数,所以-log(0.6) < -log(0.3) < -log(0.1)。简单讲就是你预测错比预测对的损失要大,预测错得离谱比预测错得轻微的损失要大。

———————————–华丽的分割线———————————–

理清了softmax loss,就可以来看看cross entropy了。
corss entropy是交叉熵的意思,它的公式如下:

是不是觉得和softmax loss的公式很像。当cross entropy的输入P是softmax的输出时,cross entropy等于softmax loss。Pj是输入的概率向量P的第j个值,所以如果你的概率是通过softmax公式得到的,那么cross entropy就是softmax loss。这是我自己的理解,如果有误请纠正。

API详细解释:
https://blog.csdn.net/weixin_39850697/article/details/111081460?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%A4%9A%E5%88%86%E7%B1%BB%E4%BA%A4%E5%8F%89%E7%86%B5%E6%8D%9F%E5%A4%B1%E5%87%BD%E6%95%B0%E5%9C%A8pytorch%E4%B8%AD%E7%9A%84API&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-7-111081460.142v47pc_rank_34_ctr25,201v3add_ask&spm=1018.2226.3001.4187

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值