1.使用ipdb在终端调试
2.PyTorch ResNet 使用与源码解析
3.torchvision应用与源码分析
4.PyTorch - DataLoader 源码解析(一)
5.detectron2安装及微软最新state of the art目标检测模型DynamicHead训练自己数据全程指南
6.nn.MaxPool2d 中使用 ceil_mode 和 padding的码分区别
使用ipdb在终端调试
在训练网络模型过程中,调试是码分提高模型性能的关键步骤。Python的码分默认调试器pdb,被IPython的码分增强版ipdb所优化,特别适合在无图形界面的码分终端环境中进行调试工作。
首先,码分6间房源码确保你的码分IPython版本低于7..1,因为高版本可能会在导入torchvision时出现错误。码分一旦遇到这个问题,码分可以参考解决方案,码分调整版本或在特定场景下使用ipdb。码分
ipdb提供了两种使用方法。码分一是码分直接在源代码中插入断点,通过`ipdb.set_trace()`在执行到指定代码行时暂停,码分如`PATH = './unet.pt'`后。码分这种方法的优点是直观,但缺点是频繁修改源代码,可能影响代码整洁度。
另一种是命令行调试,无需修改源代码。只需在终端输入特定命令,如`ipdb`,即可进入调试环境。在调试过程中,你可以使用`b`命令设置断点,如`b 9`表示在第9行设置断点。`tbreak`则创建一次性的断点。
管理断点有多种方式,如`disable`禁用,`enable`重新启用,`delete`删除。执行`c`或`continue`命令可以运行到下一个断点,`n`和`s`用于逐行执行,`a`查看当前函数参数,`r`执行至`return`,`l`和`ll`用于查看源代码。
调试过程中,可以利用`restart`或`run`命令重启调试器,保持设置;如果需要全新的环境,`q`或`exit`退出后重新开始。生鲜批发 源码`h`或`help`命令则提供了所有可用功能的详细说明。
通过ipdb,终端调试变得更加直观和高效,帮助我们逐步优化模型,找出并修复问题。
PyTorch ResNet 使用与源码解析
在PyTorch中,我们可以通过torchvision.model库轻松使用预训练的图像分类模型,如ResNet。本文将重点讲解ResNet的使用和源码解析。模型介绍与ResNet应用
torchvision.model库提供了多种预训练模型,包括ResNet,其特点是层深度的残差网络。首先,我们需要加载预训练的模型参数: 模型加载代码: pythonmodel = torchvision.models.resnet(pretrained=True)
接着,将模型放置到GPU上,并设置为评估模式: GPU和评估模式设置: pythonmodel = model.to(device='cuda')
model.eval()
Inference流程
在进行预测时,主要步骤包括数据预处理和网络前向传播: 关键代码: pythonwith torch.no_grad():
output = model(input_data)
残差连接详解
ResNet的核心是残差块,包含两个路径:一个是拟合残差的路径(称为残差路径),另一个是恒等映射(称为shortcut)。通过element-wise addition将两者连接: 残差块结构: 1. 残差路径: [公式] 2. 短路路径: [公式] (通常为identity mapping)网络结构与变种
ResNet有不同深度的变种,如ResNet、ResNet、ResNet等,网络结构根据层数和块的数量有所不同: 不同ResNet的结构图: ...源码分析
构造函数中,例如ResNet的构造过程是通过_resnet()方法逐步构建网络,涉及BasicBlock或Bottleneck的使用: ResNet构造函数: ... 源码的深入解析包括forward()方法的执行流程,以及_make_layer()方法定义网络层: forward()方法和_make_layer()方法: ...图解示例
ResNet和ResNet的不同层结构,如layer1的升维与shortcut处理: ResNet和ResNet的图解: ... 希望这些内容对理解ResNet在PyTorch中的应用有所帮助。如果你从中受益,别忘了分享或支持作者继续创作。torchvision应用与源码分析
torchvision是PyTorch库中的一部分,用于计算机视觉任务,它包含了一系列的预训练模型和数据集。
一:torchvision应用
在计算机视觉领域,torchvision提供了方便的API,用于加载和处理图像数据,训练模型和进行预测。它通常与PyTorch深度学习框架结合使用,为用户提供了一个完整的公祭 php 源码框架来开发和部署计算机视觉应用。
二:torchvision源码分析
1. setup.py分析
setup.py是Python包的配置文件,用于描述包的元数据和安装步骤。在torchvision中,setup.py文件被用来编译和安装包的依赖库。
1.1 导入依赖的模块
1.2 从配置文件中获取当前torchvision的版本信息
1.3 获取依赖的torch版本信息
1.4 获取编译扩展信息,然后传递给setup函数,启动编译
1.5 重点:get_extensions分析
在torchvision的setup.py文件中,get_extensions函数是核心部分,它负责编译torchvision自身的源码以及一些第三方库,如jpeg和codec等。
1.5.1 获取ccsrc下面的cpp源码
1.5.2 获取环境变量中配置的编译选项
1.5.3 判断是AMD的HIP还是nVidia的CUDA,来获取到最终的cuda文件
1.5.4:依据环境上是否支持cuda来确定编译扩展
1.5.5 添加扩展
至此,torchvision就将整个版本包编译出来了,会调用torch的cpp和cuda编译扩展(即:通过gcc+nvcc来编译ccsrc下面的源码,而不用torchvision自行再来设置各种编译环境信息了)。
整个编译核心流程总结如下:
2. torchvision新增算子流程
以torchvision.ops.DeformConv2d为例
2.1 基础用法与模型结构
通过Netron工具打开模型结构,可以看到torchvision的deform_conv2d是单独的IR定义的算子
2.2 python侧实现分析
deform_conv2d定义在Python侧,实际上做了参数初始化后,将转交给了C++侧对应的接口
2.3 C++侧分析:torch.ops.torchvision.deform_conv2d
2.3.1 接口定义
2.3.2 接口实现
关键在于这两个接口的注册
算子的具体实现和如何向pytorch完成注册呢?
该算子有C++和CUDA实现方式,C++方式可以在纯CPU版本中运行,cuda实现则依赖于GPU和CUDA
2.3.2.1 C++实现
2.3.2.2 CUDA实现
这种方式实现的算子,trace出来的模型中,为单个算子
总结:自定义算子向torch集成分为两步
三:基于torchvision新增一个算子
实现一个算子:my_add = 2*x + y
3.1 环境准备
PyTorch - DataLoader 源码解析(一)
本文为作者基于个人经验进行的初步解析,由于能力有限,可能存在遗漏或错误,敬请各位批评指正。
本文并未全面解析 DataLoader 的全部源码,仅对 DataLoader 与 Sampler 之间的联系进行了分析。以下内容均基于单线程迭代器代码展开,多线程情况将在后续文章中阐述。
以一个简单的数据集遍历代码为例,在循环中,数据是如何从 loader 中被取出的?通过断点调试,我们发现循环时,代码进入了 torch.utils.data.DataLoader 类的 __iter__() 方法,具体内容如下:
可以看到,该函数返回了一个迭代器,主要由 self._get_iterator() 和 self._iterator._reset(self) 提供。接下来,uuid生成源码我们进入 self._get_iterator() 方法查看迭代器的产生过程。
在此方法中,根据 self.num_workers 的数量返回了不同的迭代器,主要区别在于多线程处理方式不同,但这两种迭代器都是继承自 _BaseDataLoaderIter 类。这里我们先看单线程下的例子,进入 _SingleProcessDataLoaderIter(self)。
构造函数并不复杂,在父类的构造器中执行了大量初始化属性,然后在自己的构造器中获得了一个 self._dataset_fetcher。此时继续单步前进断点,发现程序进入到了父类的 __next__() 方法中。
在分析代码之前,我们先整理一下目前得到的信息:
下面是 __next__() 方法的内容:
可以看到最后返回的是变量 data,而 data 是由 self._next_data() 生成的,进入这个方法,我们发现这个方法由子类负责实现。
在这个方法中,我们可以看到数据从 self._dataset_fecther.fetch() 中得到,需要依赖参数 index,而这个 index 由 self._next_index() 提供。进入这个方法可以发现它是由父类实现的。
而前面的 index 实际上是由这个 self._sampler_iter 迭代器提供的。查找 self._sampler_iter 的定义,我们发现其在构造函数中。
仔细观察,我们可以在倒数第 4 行发现 self._sampler_iter = iter(self._index_sampler),这个迭代器就是这里的 self._index_sampler 提供的,而 self._index_sampler 来自 loader._index_sampler。这个 loader 就是最外层的 DataLoader。因此我们回到 DataLoader 类中查看这个 _index_sampler 是如何得到的。
我们可以发现 _index_sampler 是一个由 @property 装饰得到的属性,会根据 self._auto_collation 来返回 self.batch_sampler 或者 self.sampler。再次整理已知信息,我们可以得到:
因此,只要知道 batch_sampler 和 sampler 如何返回 index,就能了解整个流程。
首先发现这两个属性来自 DataLoader 的构造函数,因此下面先分析构造函数。微分享源码
由于构造函数代码量较大,因此这里只关注与 Sampler 相关的部分,代码如下:
在这里我们只关注以下部分:
代码首先检查了参数的合法性,然后进行了一轮初始化属性,接着判断了 dataset 的类型,处理完特殊情况。接下来,函数对参数冲突进行了判断,共判断了 3 种参数冲突:
检查完参数冲突后,函数开始创建 sampler 和 batch_sampler,如下图所示:
注意,仅当未指定 sampler 时才会创建 sampler;同理,仅在未指定 batch_sampler 且存在 batch_size 时才会创建 batch_sampler。
在 DataLoader 的构造函数中,如果不指定参数 batch_sampler,则默认创建 BatchSampler 对象。该对象需要一个 Sampler 对象作为参数参与构造。这也是在构造函数中,batch_sampler 与 sampler 冲突的原因之一。因为传入一个 batch_sampler 时,说明 sampler 已经作为参数完成了 batch_sampler 的构造,若再将 sampler 传入 DataLoader 是多余的。
以第一节中的简单代码为例,此时并未指定 Sampler 和 batch_sampler,也未指定 batch_size,默认为 1,因此在 DataLoader 构造时,创建了一个 SequencialSampler,并传入了 BatchSampler 进行构建。继续第一节中的断点,可以发现:
具体使用 sampler 还是 batch_sampler 来生成 index,取决于 _auto_collation,而从上面的代码发现,只要存在 self.batch_sampler 就永远使用 batch_sampler 来生成。batch_sampler 与 sampler 冲突的原因之二:若不设置冲突,那么使用者试图同时指定 batch_sampler 与 sampler 后,尤其是在使用者继承了新的 Sampler 子类后, sampler 在获取数据的时候完全没有被使用,这对开发者来说是一个困惑的现象,容易引起不易察觉的 BUG。
继续断点发现程序进入了 BatchSampler 的 __iter__() 方法,代码如下:
从代码中可以发现,程序不停地从 self.sampler 中获取 idx 加入列表,直到填满一个 batch 的量,并将这一整个 batch 的 index 返回到迭代器的 _next_data()。
此处由 self._dataset_fetcher.fetch(index) 来获取真正的数据,进入函数后看到:
这里依然根据 self.auto_collation(来自 DataLoader._auto_collation)进行分别处理,但是总体逻辑都是通过 self.dataset[] 来调用 Dataset 对象的 __getitem__() 方法。
此处的 Dataset 是来自 torchvision 的 DatasetFolder 对象,这里读取文件路径中的后,经过转换变为 Tensor 对象,与标签 target 一起返回。参数中的 index 是由迭代器的 self._dataset_fetcher.fetch() 传入。
整个获取数据的流程可以用以下流程图简略表示:
注意:
另附:
对于一条循环语句,在执行过程中发生了以下事件:
detectron2安装及微软最新state of the art目标检测模型DynamicHead训练自己数据全程指南
首先,您需要从github.com/microsoft/Dy...仓库下载代码。
同时,下载并安装detectron2源码。
在Win系统中安装Detectron2时,有一些要点和避坑指南需要注意。
安装命令为:python setup.py build develop。
执行该命令可能会报错,提示找不到vc++ .0。这时,您需要在VS中安装C++组件。
接下来,需要安装依赖库,如torch、torchvision、pycocotools和fvcore等。
安装过程中,在Win上运行安装命令可能会遇到错误:nvcc.exe failed with exit status 1。
要解决此错误,需要修改detectron2\layers\csrc ms_rotated ms_rotated_cuda.cu代码前几行,将条件编译#ifdef WITH_CUDA和#ifdef WITH_HIP全部注释掉,只保留#include "box_iou_rotated/box_iou_rotated_utils.h"。
修改完成后,再次运行python setup.py build develop,并等待一段时间,就可以顺利编译并安装了。
DynamicHead训练代码原版不包含注册数据集的代码,需要修改train_net.py文件,将注册数据集的代码加入其中。修改后的完整代码如下所示。
请确保您的训练数据集符合coco格式,如果不是,需要编写代码将其转换为coco格式。
修改数据集路径的代码如下,其中coco文件夹是训练和验证集json文件所在路径,train_path和val_path是训练和验证集所在路径。
在以下代码中,需要修改数据集的类别信息和注册的训练验证集名字。
训练的脚本命令是:python train_net.py --config configs/dyhead_swint_atss_fpn_2x_ms.yaml --num-gpus 1。
命令中出现的configs文件夹中的yaml文件也需要修改,将其中的datasets修改为您代码中注册的数据集名字,并在代码中重写或覆盖选项。
运行上述训练脚本可能会遇到的问题及解决方案如下:
遇到"broken pipe"错误,即多进程数据加载错误,将加载进程数修改为1即可解决。
如果训练报错weights_decay是none,打印cfg查看哪些是none,发现weight_decay_bias是none,将weight_decay_bias设置为0而不是none即可成功训练。
Github上提供的预训练权重是在coco数据集上训练的,类别数与您的数据集不同,不能作为weights初始化。
最后,成功训练的图示。
nn.MaxPool2d 中使用 ceil_mode 和 padding的区别
nn.MaxPool2d在处理池化操作时,有两个关键参数:ceil_mode和padding,它们在处理边界时有所不同。默认情况下,ceil_mode为False,意味着窗口超出边界时会直接舍弃。如果设置ceil_mode为True,窗口可以超出但不超过一半,这相当于在边缘处做了半步的填充。
而padding则是直接在输入数据周围添加指定数量的像素。通常,池化操作用来降低图像分辨率,如设置stride为2,kernel_size为3,以达到每步降低一半的效果。例如,对于输入分辨率n,不使用padding时,输出分辨率为n/2(向下取整)。
当n为偶数时,ceil_mode的作用显现,如n=4,3/2=1,不满足期望的2x2分辨率。这时,开启ceil_mode会向上取整至2,或者设置padding为1,都能达到目标。以3x3窗口池化4x4图像为例,ceil_mode会向右下方填充,采样点偏左上;而padding则偏右下方。
虽然两种方式都能得到期望的特征图形状,但视觉上存在细微差别。实践中,两者在PyTorch的 torchvision 源码中都被使用,具体选择哪种取决于具体任务的需求和性能考虑。总的来说,两者影响不大,可以根据个人偏好或者特定场景来决定使用哪种模式。
NVIDIA Jetson NX安装torchvision教程
安装 torchvision 前,先确保已安装 pytorch,参考相关教程进行操作。
首先,切换至国内软件源,执行更新操作。
安装 torchvision 所需依赖。
使用 dpkg 手动安装时,注意到 libpython3-dev 未有候选版本,需手动安装。安装其他依赖已满足。
下载 arm 架构的 libpython3-dev_3.6.7-1~._arm.deb 包,确保版本与当前 python3(3.6.9)兼容。
使用 dpkg -i 安装 deb 包,若遇到依赖问题,直接在网页中查找所有依赖的下载链接。
安装 libpython3-dev 的依赖 libpython3.6-dev 时,出现版本不正确的错误。分析后发现 libpython3.6-dev 需要的版本为 3.6.9-1~.ubuntu1.4,已有的版本为 3.6.9-1~.,因此安装 libpython3.6-dev 的候选版本 libpython3.6-stdlib 中最后一个版本,即为所需版本 3.6.9-1~.ubuntu1.4。
安装 torchvision 源码,确保 pytorch 和 torchvision 版本匹配,如 torch 1.6 版本对应 torchvision 0.7.0 版本。
使用码云账号注册并导入 torchvision 仓库,完成代码下载。
进入 torchvision 目录,使用命令编译,通常需时约十分钟。
当出现 pillow 报错时,说明 torchvision 近于安装成功。返回上一级目录,使用 pip/pip3 安装 pillow。
若下载速度慢,可使用国内豆瓣源下载安装 pillow。
安装 pillow 后,再次尝试导入 torch 仍报错,需再次进入 torchvision 目录进行编译安装。这次配置完成迅速。
使用 pip3 list 查看已安装包及版本,确认 torchvision 安装完成。
执行卷积神经网络训练,速度比本地快四倍。使用 jtop 监控 CPU、GPU 运行情况,观察在 Jetson Nano 上使用 pytorch 并设置 CUDA 进行训练时,主要由 GPU 执行计算,W 功率能达到的算力相当不错。
mmdetection源码阅读笔记:ResNet
ResNet,作为mmdetection中backbone的基石,其重要性不言而喻,它是人工智能领域引用最频繁的论文之一,微软亚洲研究院的杰作。自年提出以来,ResNet一直是目标检测领域最流行的backbone之一,其核心是通过残差结构实现更深的网络,解决深度网络退化的问题。
ResNet的基本原理是利用残差结构,通过1×1、3×3和1×1的卷积单元,如BasicBlock和BottleneckBlock,来构建不同版本的网络,如resnet-到resnet-,它们在基本单元和层数上有所区别。在mmdetection的实现中,从conv2到conv5主要由res_layer构成,其中下采样策略是关键,不同版本的网络在layer1之后的下采样位置有所不同。
ResLayer的构造函数是理解mmdetection中ResNet的关键,它涉及内存优化技术,如torch.utils.checkpoint,通过控制函数的运行方式来节省内存,但可能增加反向传播计算时间。此外,对norm层的处理也体现了与torchvision预训练模型的兼容性。
最后,ResNet的make_stage_plugins方法允许在核心结构中插入拓展组件,这增加了模型的灵活性。总的来说,ResNet的源码阅读揭示了其设计的巧妙和灵活性,是理解深度学习模型架构的重要一步。