目录
文章性质:学习笔记 📖
主要内容:根据 视频教程 中提供的 LR-ASPP?源代码(PyTorch),对 train.py、lraspp_model.py 文件进行具体讲解。
? ├── src: 模型的backbone以及LRASPP的搭建
? ├── train_utils: 训练、验证以及多GPU训练相关模块
? ├── my_dataset.py: 自定义dataset用于读取VOC数据集
? ├── train.py: 单GPU训练脚本
? ├── train_multi_GPU.py: 针对使用多GPU的用户使用
? ├── predict.py: 简易的预测脚本,使用训练好的权重进行预测测试
? ├── validation.py: 利用训练好的权重验证/测试数据的mIoU等指标,并生成record_mAP.txt文件
? └── pascal_voc_classes.json: pascal_voc标签文件?
在对 PyTorch 官方实现的 LR-ASPP 源代码进行解析的过程中,最好能够结合对应的 LR-ASPP 网络结构图:
LR-ASPP 的 train.py 和 predict.py 都和 PyTorch 官方实现的 FCN 源代码类似,只有 train.py 中的?create_model 函数不同。
【说明】通过 lraspp_mobilenetv3_large 函数来实例化 LR-ASPP 模型,传入参数包括:
在 lraspp_mobilenetv3_large 函数中,使用?mobilenet_v3_large 构建?backbone ,传入的?dilated=True 说明使用了膨胀卷积,如下图所示:
【拓展】如果小伙伴们想了解?mobilenet_v3_large 网络结构以及如何用 PyTorch 实现这个网络结构,可学习下面这些视频:
关于 create_model 函数的 pretrain 参数取值:
【情况1】需要提前下载对应权重 lraspp_mobilenet_v3_large_coco :
在 train.py 文件中将 create_model 函数传入的 pretrain 设置为 True ,其使用的 lraspp_mobilenetv3_large 函数默认将 pretrain_backbone 设置为 False,这时使用的是 PyTorch 官方使用 LR-ASPP 模型在 COCO 数据集上的预训练权重,载入 backbone 的预训练权重。
【情况2】需要提取下载对应权重 mobilenetv3_large_imagenet :
在 train.py 文件中将 create_model 函数传入的?pretrain 设置为 False ,其使用的 lraspp_mobilenetv3_large 函数需要将 pretrain_backbone 设置为 True,这时就只使用 mobilenetv3 的 backbone 权重,而不载入整个模型的权重。
【彩蛋】为了更加直观地说明 create_model 的?pretrain、lraspp_mobilenetv3_large 的 pretrain_backbone、
[ train.py ] create_model 函数 | [ lraspp_model.py ] lraspp_mobilenetv3_large 函数 | 载入权重 |
---|---|---|
pretrain = True | pretrain_backbone = False | 使用 PyTorch 官方使用 LR-ASPP 模型在 COCO 数据集上的预训练权重,需下载对应权重 lraspp_mobilenet_v3_large_coco |
pretrain = False | pretrain_backbone = True | 使用 mobilenetv3 的 backbone 权重,而不是载入整个模型的权重,需下载对应权重 mobilenetv3_large_imagenet |
【补充】权重文件的下载链接(下载后记得重命名):
在 lraspp_mobilenetv3_large 函数中,stage_indices 由三部分组成:stage_indices 第一个值为 0 ;然后遍历 backbone ,也就是 mobilemetv3 中对应的所有层结构 ,通过 getattr 方法去取得层结构的 is_strided 参数数值,若 is_strided 为 True,则将对应层的索引 i 添加到 stage_indices 列表中,若 is_strided 为False 或者没有 is_strided 这个参数,则不添加索引;stage_indices 最后一个值对应 backbone 最后一个模块的索引 。
Question:如何判定?is_strided 为 False 还是 True 呢?
在 mobilenet_backbone.py 中,回顾 mobilenet 中 bottleneck 的实现,在 InvertedResidual 类,当 cnf.stride > 1 时 is_strided 为 True 。
Question:为什么 stage_indices 得到的层索引就相当于层名称?
在 mobilenet_backbone.py 的 MobileNetV3 类中,features 是通过 Sequential 方法搭建的,其每一个子模块的名称与其在 Sequential 中的索引是对应的,因此 stage_indices 得到的层索引就相当于层名称 ,它的第一个索引 0 对应第一个 3x3 的 conv2d 卷积层,它中间遍历得到的索引对应 bottleneck 中 stride 步距为 2 的层,最后一个索引对应 1x1 的 conv2d 卷积层。
关于 low_pos、high_pos、low_channels、high_channels 的理解:
【代码解析】对?lraspp_mobilenetv3_large 函数的具体解析(结合上图):
【注意】LR-ASPP 网络模型使用的 backbone 是 MobileNetV3 !
?LRASPP 类在?__init__ 初始化函数中,构建 LRASPPHead,结合结构图:
【说明】在 LRASPP 类的 forward 函数中:x 是图像数据,x.shape[-2:] 是图像的宽高,out = self.classfier(features) 是 FCNHead 的输出。?