原理

损失函数:

a 是用来调解正负样本,根据不同的比例来减少正负样本loss的比例,从而提高模型学习能力,一般情况下正样本远远小于负样本,所以设置a=0.25,负样本为0.75就能缩小loss的比例。

γ 负责降低简单样本的损失值, 以解决加总后负样本loss值很大,这样可以让模型学习的时候多学习到困难样本的特征来达到更好的识别效果。

(1-pt)这里可以代表预测的分值越高则值越小,pt越小值越大,这种的好处是一旦分很低,造成的loss更大,让模型学习效果更好。

特点:

在模型学习的时候注意力集中在分值很低的预测来降低loss。在进行梯度下降的时候,模型通过训练只是为了loss的降低,这样就专门针对导致loss大的值进行修改来降低loss,就能获得好的模型。

代码实现

重要的是loss公式实现,以及一些tensor函数使用。

# focal loss是retinanet网络提出的新型损失函数,重点就是当正负样本差距过大,导致训练效果低下时,
# 该如何减少负样本的loss,增加正样本占全部loss的比重,从而有效的控制样本差距带来的好的模型学习能力。from torch import nn
import torch
from torch.nn import functional as F  # 必要class focal_loss(nn.Module):def __init__(self, alpha=0.25, gamma=2, num_classes=5, size_average=True):super(focal_loss, self).__init__()self.size_average = size_average  # 是否将每一个batch的loss加总后平均if isinstance(alpha, (float, int)):  # 仅仅设置第一类别的权重self.alpha = torch.zeros(num_classes)  # [0.,0.,0.,0.,...,0.]self.alpha[0] += alpha  # [alpha,0.,0.,0.,...,0.]# [alpha,1 - alpha,1 - alpha,1 - alpha,...,1 - alpha]self.alpha[1:] += (1 - alpha)if isinstance(alpha, list):  # 全部权重自己设置self.alpha = torch.Tensor(alpha)self.gamma = gammadef forward(self, inputs, targets):alpha = self.alpha# tensor([0.2500, 0.7500, 0.7500, 0.7500, 0.7500])print('aaaaaaa', alpha)N = inputs.size(0)print('nnnnnnnnnnn', N)  # 5C = inputs.size(1)print('ccccccccccc', C)  # 5P = F.softmax(inputs, dim=1)  # 将inputs进行softmax,杂乱的数据映射到0-1区间内print('ppppppppppp', P)# tensor([[0.0635, 0.2920, 0.4117, 0.1595, 0.0734],#         [0.4445, 0.1057, 0.0810, 0.1186, 0.2501],#         [0.1678, 0.2101, 0.0960, 0.1782, 0.3480],#         [0.2171, 0.2126, 0.3949, 0.1447, 0.0306],#         [0.0577, 0.1277, 0.5094, 0.1682, 0.1370]], grad_fn=<SoftmaxBackward>)# ---------one hot start--------------## .data取出数据部分  .new生成和input一样shape的tensor,且无内容  .fill_(0)填充为0class_mask = inputs.data.new(N, C).fill_(0)print('依照input shape制作:class_mask\n', class_mask)# tensor([[0., 0., 0., 0., 0.],#         [0., 0., 0., 0., 0.],#         [0., 0., 0., 0., 0.],#         [0., 0., 0., 0., 0.],#         [0., 0., 0., 0., 0.]])class_mask = class_mask.requires_grad_()  # 需要更新, 所以加入梯度计算# requires_grad=True 的作用是让 backward 可以追踪这个参数并且计算它的梯度# 最开始定义你的输入是 requires_grad=True ,那么后续对应的输出也自动具有 requires_grad=True# 只有 requires_grad=True 的参数才会参与求导# 如果你想取的参数是由 torch.tensor(requires_grad=True) 定义的,可以直接取它的 grad# 如果你的参数是如 y 和 z 这样计算出来的,那么根据编译器警告,需要定义 y.retain_grad() 就可以取得 y 的 grad# 还有一个方法是使用钩子可以保存计算的中间梯度# 梯度的计算会在计算完成后遗弃,并且 requires_grad=False 的参数不计算它的梯度,如此可以减少内存使用和降低计算量# 在使用 Pytorch 的 nn.Module 建立网络时,其内部的参数都自动的设置为了 requires_grad=True ,故可以直接取梯度# 叶子节点:只有定义的 Tensor 参数才是叶子节点;只有 requires_grad=True 和叶子节点 is_leaf=True 才有 grad 的值'''使用backward()函数反向传播计算tensor的梯度时,并不计算所有tensor的梯度,而是只计算满足这几个条件的tensor的梯度:1.类型为叶子节点、2.requires_grad=True、3.依赖该tensor的所有tensor的requires_grad=True。在pytorch中,神经网络层中的权值w的tensor均为叶子节点;自己定义的tensor例如a=torch.tensor([1.0])定义的节点是叶子节点'''ids = targets.view(-1, 1)  # 展开一维  取得标签的索引print('取得targets的索引\n', ids)# tensor([[4],#         [4],#         [4],#         [4],#         [4]])class_mask.data.scatter_(dim=1, index=ids.data, value=1.)  # 利用scatter将索引丢给mask# scatter_(input,dim,index,value) 将value对应的值按照index确定的索引写入input张量中,其中索引是根据给定的dim(维度)来确定的。"""Args: input.scatter_(dim, index, value)input:要进行scatter_填充的tensordim:在input张量进行scatter_填充的维度index:input对应dim的填充索引,要小于对应填充维度的长度,且index维度要与input张量维度一致value:填充值"""# scatter() 不会直接修改原来的 Tensor# scatter_() 会在原来的基础上对Tensor进行修改print('targets的one_hot形式\n', class_mask)  # one-hot target生成 在最后一列填充了1.# tensor([[0., 0., 0., 0., 1.],#         [0., 0., 0., 0., 1.],#         [0., 0., 0., 0., 1.],#         [0., 0., 0., 0., 1.],#         [0., 0., 0., 0., 1.]], requires_grad=True)# ---------one hot end-------------------#probs = (P * class_mask).sum(1).view(-1, 1)  # 求和 展开print('留下targets的概率(1的部分),0的部分消除\n', probs)# 将softmax * one_hot 格式,P中的0的部分被消除 留下1的概率, shape = (5, 1), 5就是每个target的概率# tensor([[0.0734],#         [0.2501],#         [0.3480],#         [0.0306],#         [0.1370]], grad_fn=<ViewBackward>)log_p = probs.log()  # 取得对数print('取得对数\n', log_p)# tensor([[-2.6114],#         [-1.3858],#         [-1.0556],#         [-3.4873],#         [-1.9875]], grad_fn=<LogBackward>)loss = torch.pow((1 - probs), self.gamma) * log_p  # 公式(1-p)^gamma * log_pbatch_loss = -alpha * loss.t()  # 公式 .t()是转置print('每一个batch的loss\n', batch_loss)# batch_loss就是取每一个batch的loss值# 最终将每一个batch的loss加总后平均if self.size_average:  # 默认loss = batch_loss.mean()  # 平均else:loss = batch_loss.sum()  # 求和print('loss值为\n', loss)return lossif __name__ == '__main__':torch.manual_seed(50)  # 随机种子确保每次input tensor值是一样的input = torch.randn(5, 5, dtype=torch.float32,requires_grad=True)  # [5,5] 浮点型数据 有梯度计算的需要print('input值为\n', input)# tensor([[-1.1588,  0.3673,  0.7110, -0.2373, -1.0129],#         [ 0.5580, -0.8784, -1.1446, -0.7629, -0.0170],#         [-0.0477,  0.1770, -0.6058,  0.0125,  0.6818],#         [ 0.4508,  0.4299,  1.0491,  0.0453, -1.5092],#         [-1.5502, -0.7564,  0.6274, -0.4808, -0.6856]], requires_grad=True)targets = torch.randint(5, (5, ))targets[:] = 4print('targets值为\n', targets)  # tensor([4, 4, 4, 4, 4])criterion = focal_loss()  # 实例化focal_loss 使用默认init参数# 实例化后,调用net(x)或者net(x,y),就是调用net里重载的forward函数loss = criterion(input, targets)loss.backward()  # 反传 只需调用.backward()不需重载a = F.cross_entropy(input, targets)  # 交叉熵损失 对比print('CE loss', a)

参考文章:

叶子节点和tensor的requires_grad参数 - 知乎

pytorch 深入理解 tensor.scatter_ ()用法_aoi997的博客-CSDN博客_tensor.scatter

Pytorch中的scatter_函数_.我心永恒_的博客-CSDN博客_pytorch scatter_函数

pytorch 实现Focal loss 详细讲解 代码简洁易懂_视觉盛宴的博客-CSDN博客_focal loss pytorch

经典神经网络 -- RetinaNet的Focal_Loss : 设计原理与pytorch实现相关推荐

  1. 《不只是美:信息图表设计原理与经典案例》—— 2.5 功能限制形式

    本节书摘来异步社区<不只是美:信息图表设计原理与经典案例>一书中的第2章,第2.5节,作者:[美]Alberto Cairo,更多章节内容可以访问云栖社区"异步社区"公 ...

  2. PrivacyIN Week2 | 张宇鹏博导开讲经典零知识证明协议设计原理

    前言 隐私研究院[PrivacyIN]第一期ZK训练营课程精讲内容上线,本期课堂邀请到美国德州农工大学(Texas A&M University)计算机科学与工程学院的助理教授张宇鹏,主要介绍 ...

  3. 《不只是美:信息图表设计原理与经典案例》—— 第2章 形式与功能:可视是一种技术...

    本节书摘来异步社区<不只是美:信息图表设计原理与经典案例>一书中的第2章,作者:[美]Alberto Cairo,更多章节内容可以访问云栖社区"异步社区"公众号查看. ...

  4. 《不只是美:信息图表设计原理与经典案例》—— 1.1 理性乐观派观派

    本节书摘来异步社区<不只是美:信息图表设计原理与经典案例>一书中的第1章,第1.1节,作者:[美]Alberto Cairo,更多章节内容可以访问云栖社区"异步社区"公 ...

  5. 神经网络处理器设计原理,神经网络控制系统设计

    谷歌发布tpu研究论文,神经网络专用处理器是怎样炼成的 TPU的需求大约真正出现在6年之前,那时我们在所有产品之中越来越多的地方已开始使用消耗大量计算资源的深度学习模型:昂贵的计算令人担忧. 假如存在 ...

  6. 神经网络反向传播梯度计算数学原理

    [神经网络]反向传播梯度计算数学原理 1 文章概述 本文通过一段来自于Pytorch官方的warm-up的例子:使用numpy来实现一个简单的神经网络.使用基本的数学原理,对其计算过程进行理论推导,以 ...

  7. 经典神经网络论文超详细解读(三)——GoogLeNet InceptionV1学习笔记(翻译+精读+代码复现)

    前言 在上一期中介绍了VGG,VGG在2014年ImageNet 中获得了定位任务第1名和分类任务第2名的好成绩,而今天要介绍的就是同年分类任务的第一名--GoogLeNet . 作为2014年Ima ...

  8. 深度学习入门笔记(二十):经典神经网络(LeNet-5、AlexNet和VGGNet)

    欢迎关注WX公众号:[程序员管小亮] 专栏--深度学习入门笔记 声明 1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献. 2)本文仅供学术交流,非商用.所以每一部分具 ...

  9. 卷积神经网络(CNN)的原理

    https://blog.csdn.net/weixin_42278173/article/details/81776807 卷积神经网络(CNN)的原理 本文主要内容: CNN的定义 CNN的构成 ...

  10. quartz 分布式_后端必备分布式技术之-调度系统Quartz设计原理

    调度系统作为分布式系统技术中重要的一环,了解其技术原理必不可少,不同系统内部采用的调度系统叫法不一样,但大致功能都类似,而Quartz作为经典的开源企业级调度系统,怎么能不研究一下呢? 为什么要学习q ...

最新文章

  1. Flutter配置好后,在Android Studio中找不到设备,no devices
  2. WGCNA | weighted correlation network analysis
  3. MongoDB的正确使用姿势
  4. Python学习之路day3-文件操作
  5. 拓端tecdat|用R语言模拟混合制排队随机服务排队系统
  6. 企业污染排放数据库、海关数据库
  7. 贪吃蛇c加加代码_C语言/C加加编程学习之贪吃蛇小游戏源代码
  8. html5 mp4在线播放器,HTML5 Web播放器-Video.js
  9. mysql主从配置master、slaver
  10. 一键加速索尼相机SD卡文件的复制操作,文件操作批处理教程
  11. 企业微信渠道二维码如何制作?
  12. 看巨人,学巨人,超巨人
  13. 微信不显示王者荣耀连接服务器,王者荣耀省级不显示,王者荣耀不用微信怎么登录...
  14. 8个游戏开发工具让你不懂编程也能做游戏
  15. photoshop是中文版怎么改成英文版!!
  16. 那些证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)【CSR文件 和 PEM 文件什么区别】
  17. 使用 ArcGIS Pro 对一幅没有空间参考的老照片进行配准
  18. 公司注册资本越高越好吗?公司注册资本为什么不能随便填?
  19. 【Excel】批量提取超链接中的链接地址
  20. Go+ 写文件方法教程(4.15)

热门文章

  1. HttpServlet请求重定向
  2. SSh三大框架的作用
  3. C#窗体控件简介ListBox
  4. 和商简智能CEO关于APS的聊后感
  5. 列向量互信息计算通用MATLAB代码
  6. 智能优化算法:阿基米德优化算法 -附代码
  7. GIS案例练习-----------第二天
  8. 《深度学习Python实践》附录——聚类分析
  9. Sentinel数据处理-基于snap软件
  10. Flutter之SemanticsBinding和WidgetsBindingObserver简析