未验证 提交 c682043f 编写于 作者: D dyning 提交者: GitHub

updata ThesisReproduction_CV (#5355)

上级 d1dd17b7
......@@ -11,7 +11,7 @@
### 1.2 前序工作
基于本文规范复现论文过程中,建议开发者准备以下内容。
基于本指南复现论文过程中,建议开发者准备以下内容。
* 了解该模型输入输出格式。以AlexNet图像分类任务为例,通过阅读论文与参考代码,了解到模型输入为`[batch_size, 3, 224, 244]`的tensor,类型为`float32`或者`float16`,label为`[batch, ]`的label,类型为`int64`
* 准备好训练/验证数据集,用于模型训练与评估
......@@ -27,21 +27,21 @@
### 2.1 流程概览
基于通用的计算机视觉任务,论文复现整体流程图如下所示。
面对一篇计算机视觉论文,复现该论文的整体流程如下图所示。
![图片](images/framework.png)
总共包含11个步骤。为了高效复现论文,设置了5个验收节点。如上图中黄色框所示。后续章节会详细介绍上述步骤和验收节点,具体内容安排如下:
总共包含11个步骤,为了高效复现论文,设置了5个验收节点。如上图中黄色框所示。对应地,第3章到第5章的内容安排如下:
* 第3章:介绍11个复现步骤的理论知识以及操作方法
* 第3章:介绍11个复现步骤的理论知识以及实战
* 第4章:介绍5个验收节点的自查与验收方法
* 第5章:针对第3章在复现流程过程中可能出现的问题,在第5章会进行详细介绍。如果还是不能解决问题的话,可以进交流群讨论
* 第5章:针对复现流程过程中每个步骤可能出现的问题,本章会进行详细介绍。如果还是不能解决问题,可以提ISSUE或进交流群讨论
### 2.2 reprod_log whl包使用说明
### 2.2 reprod_log whl包
`reprod_log`是用于论文复现赛自动化测试和验收的工具,源代码地址在:[https://github.com/WenmuZhou/reprod_log](https://github.com/WenmuZhou/reprod_log)。主要功能包括:
#### 2.2.1 reprod_log工具简介
`reprod_log`是用于论文复现赛中辅助自查和验收工具。该工具源代码地址在:[https://github.com/WenmuZhou/reprod_log](https://github.com/WenmuZhou/reprod_log)。主要功能如下:
* 存取指定节点的输入输出tensor
* 基于文件的tensor读写
......@@ -96,9 +96,9 @@
* diff_threshold (float): 阈值,如果diff大于该阈值,则核验失败,默认为`1e-6`
* path (str): 日志保存的路径,默认为`./diff.txt`
### 2.3 使用demo
#### 2.2.2 reprod_log使用demo
下面基于代码:[https://github.com/littletomatodonkey/AlexNet-Prod/tree/master/pipeline/reprod_log_demo](https://github.com/littletomatodonkey/AlexNet-Prod/tree/master/pipeline/reprod_log_demo),给出详细的工具包API使用功能
下面基于代码:[https://github.com/littletomatodonkey/AlexNet-Prod/tree/master/pipeline/reprod_log_demo](https://github.com/littletomatodonkey/AlexNet-Prod/tree/master/pipeline/reprod_log_demo),给出如何使用该工具
文件夹中包含`write_log.py``check_log_diff.py`文件,其中`write_log.py`中给出了`ReprodLogger`类的使用方法,`check_log_diff.py`给出了`ReprodDiffHelper`类的使用方法,依次运行两个python文件,使用下面的方式运行代码。
......@@ -123,9 +123,9 @@ python3.7 check_log_diff.py
可以看出:对于key为`demo_test_1`的矩阵,由于diff为0,小于设置的阈值`1e-6`,核验成功;对于key为`demo_test_2`的矩阵,由于diff为0.33,大于设置的阈值`1e-6`,核验失败。
### 2.4 论文复现赛自动化测试
#### 2.2.3 reprod_log在论文复现中应用
假设基于上述工具的结果记录模块,产出下面若干文件
在论文复现中,基于reprod_log的结果记录模块,产出下面若干文件
```
log_reprod
├── forward_paddle.npy
......@@ -140,7 +140,7 @@ log_reprod
├── train_align_benchmark.npy # PaddlePaddle提供的参考评估指标
```
使用该工具中的`ReprodDiffHelper`模块,产出下面的日志文件。
基于reprod_log的`ReprodDiffHelper`模块,产出下面5个日志文件。
```
├── forward_diff.log # forward_paddle.npy与forward_torch.npy生成的diff结果文件
......@@ -150,79 +150,11 @@ log_reprod
├── train_align_diff.log # train_align_paddle.npy与train_align_benchmark.npy生成的diff结果文件
```
5个结果文件中,会显示基于`repod_log`的检查结果。
下面以后续的前向对齐为例,介绍下基于`repord_log`工具对齐的检查流程。其中与`reprod_log`工具有关的部分都是需要开发者需要去添加的部分。
具体代码地址为:[https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/Step1/AlexNet_paddle/forward_alexnet.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/Step1/AlexNet_paddle/forward_alexnet.py)
下载代码后,按照下面的步骤运行脚本。
```shell
# 进入文件夹
cd pipeline/Step1/
# 下载预训练模型
wget -P ../weights https://paddle-model-ecology.bj.bcebos.com/model/alexnet_reprod/alexnet_paddle.pdparams
wget -P ../weights https://paddle-model-ecology.bj.bcebos.com/model/alexnet_reprod/alexnet-owt-7be5be79.pth
# 生成paddle的前向数据
cd AlexNet_paddle/ && python3.7 forward_alexnet.py
# 生成torch的前向数据
cd ../AlexNet_torch && python3.7 forward_alexnet.py
# 对比生成log
cd ..
python3.7 check_step1.py
```
以PaddlePaddle为例,`forward_alexnet.py`的具体代码如下所示。
```python
import numpy as np
import paddle
# 导入模型
from paddlevision.models.alexnet import alexnet
# 导入reprod_log中的ReprodLogger类
from reprod_log import ReprodLogger
reprod_logger = ReprodLogger()
# 组网并初始化
model = alexnet(pretrained="../../weights/alexnet_paddle.pdparams" num_classes=1000)
model.eval()
# 读入fake data并转换为tensor,这里也可以固定seed在线生成fake data
fake_data = np.load("../../fake_data/fake_data.npy")
fake_data = paddle.to_tensor(fake_data)
# 模型前向
out = model(fake_data)
# 保存前向结果,对于不同的任务,需要开发者添加。
reprod_logger.add("logits", fake_data.cpu().detach().numpy())
reprod_logger.save("forward_paddle.npy")
```
diff检查的代码可以参考:[check_step1.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/Step1/check_step1.py),具体代码如下所示。
```python
# https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/Step1/check_step1.py
# 使用reprod_log排查diff
from reprod_log import ReprodDiffHelper
if __name__ == "__main__":
diff_helper = ReprodDiffHelper()
torch_info = diff_helper.load_info("AlexNet_torch/forward_torch.npy")
paddle_info = diff_helper.load_info("AlexNet_paddle/forward_paddle.npy")
diff_helper.compare_info(torch_info, paddle_info)
diff_helper.report(path="forward_diff.log")
```
产出日志如下。
```
2021-09-27 10:35:46,172 - reprod_log.utils - INFO - logits:
2021-09-27 10:35:46,173 - reprod_log.utils - INFO - mean diff: check passed: True, value: 0.0
2021-09-27 10:35:46,173 - reprod_log.utils - INFO - diff check passed
```
平均绝对误差为0,测试通过。
上述文件的生成代码都需要开发者进行开发,验收时需要提供上面罗列的所有文件(不需要提供产生这些文件的可运行程序)以及完整的模型训练评估程序和日志。
AlexNet-Prod项目提供了基于reprod_log的5个验收点对齐验收示例,具体代码地址为:[https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/)
每个文件夹中的README.md文档提供了使用说明。
## 3. 论文复现赛操作流程规范
## 3. 论文复现理论知识以及实战
### 3.1 模型结构对齐
......@@ -230,23 +162,40 @@ if __name__ == "__main__":
* 网络结构代码转换
* 权重转换
* 给定完全相同输入,生成tensor,验证模型的正确性
* 模型组网正确性验证
下面详细介绍这3个部分。
#### 3.1.1 网络结构代码转换
由于PyTorch的API和PaddlePaddle的API非常相似,所以组网部分代码直接手动转换即可。如果是PaddlePaddle没有的API,可以尝试用多种API来组合,高优的API如果希望获得支持,也可以提给PaddlePaddle团队提[ISSUE](https://github.com/PaddlePaddle/Paddle/issues)。API对应的列表也可以参考:[PyTorch-PaddlePaddle API映射表](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/08_api_mapping/pytorch_api_mapping_cn.html)
**【基本流程】**
由于PyTorch的API和PaddlePaddle的API非常相似,可以参考[PyTorch-PaddlePaddle API映射表](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/08_api_mapping/pytorch_api_mapping_cn.html)
,组网部分代码直接进行手动转换即可。
**【注意事项】**
对于AlexNet,PyTorch实现为: [alexnet-pytorch](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/AlexNet-torch/torchvision/models/alexnet.py), 复现的PaddlePaddle实现为: [alexnet-paddle](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/AlexNet-paddle/paddlevision/models/alexnet.py)
如果遇到PaddlePaddle没有的API,可以尝试用多种API来组合,也可以给PaddlePaddle团队提[ISSUE](https://github.com/PaddlePaddle/Paddle/issues),获得支持。
**【实战】**
对于AlexNet网络结构的PyTorch实现 [alexnet-pytorch](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/AlexNet-torch/torchvision/models/alexnet.py)[alexnet-paddle](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/AlexNet-paddle/paddlevision/models/alexnet.py) 提供了网络结构代码转换为PaddlePaddle的实现。
#### 3.1.2 权重转换
**【基本流程】**
组网代码转换完成之后,需要对模型权重进行转换,如果PyTorch repo中已经提供权重,那么可以直接下载并进行后续的转换;如果没有提供,则可以基于PyTorch代码,随机生成一个初始化权重(定义完model以后,使用`torch.save()` API保存模型权重),然后进行权重转换。
**【注意事项】**
在权重转换的时候,需要注意`paddle.nn.Linear`以及`paddle.nn.BatchNorm2D`等API的权重保存格式和名称等与PyTorch稍有diff,具体内容可以参考`5.1章节`
**【实战】**
AlexNet的代码转换脚本可以在这里查看:[https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/weights/torch2paddle.py](https://github.com/littletomatodonkey/AlexNet-Prod/blob/master/pipeline/weights/torch2paddle.py),核心函数如下所示。
注:运行该代码需要首先下载PyTorch的AlexNet预训练模型到该目录下,下载地址为:[https://download.pytorch.org/models/alexnet-owt-7be5be79.pth](https://download.pytorch.org/models/alexnet-owt-7be5be79.pth)
:运行该代码需要首先下载PyTorch的AlexNet预训练模型到该目录下,下载地址为:[https://download.pytorch.org/models/alexnet-owt-7be5be79.pth](https://download.pytorch.org/models/alexnet-owt-7be5be79.pth)
```python
# https://github.com/littletomatodonkey/AlexNet-Prod/blob/d7b1977c2043a346b3fee0039949d5334fb990a3/pipeline/weights/torch2paddle.py#L6
......@@ -277,27 +226,32 @@ transfer()
运行完成之后,会在这里生成`alexnet_paddle.pdparams`文件,为PaddlePaddle的预训练模型。
在权重转换的时候,需要注意`paddle.nn.Linear`以及`paddle.nn.BatchNorm2D`等API的权重保存格式和名称等与PyTorch稍有diff,具体内容可以参考`5.1章节`
#### 3.1.3 模型组网正确性验证
* 操作流程
**【基本流程】**
* 定义PyTorch模型,加载权重,固定seed,基于numpy生成随机数,转换为PyTorch可以处理的tensor,送入网络,获取输出,使用reprod_log保存结果。
* 定义PaddlePaddle模型,加载权重,固定seed,基于numpy生成随机数,转换为PaddlePaddle可以处理的tensor,送入网络,获取输出,使用reprod_log保存结果。
* 使用reprod_log排查diff,小于阈值,即可完成自测。
* 注意事项
**【注意事项】**
* 模型在前向对齐验证时,需要调用`model.eval()`方法,保证组网中的随机量被关闭,比如BatchNorm、Dropout等。
* 给定相同的输入数据,为保证可复现性,建议随机数生成时,固定seed进行生成。
* 输出diff可以使用`np.mean(np.abs(o1 - o2))`进行计算,一般小于1e-6的话,可以认为前向没有问题。
* 如果最终输出结果diff较大,可以使用二分的方法进行排查,比如说ResNet50,包含1个stem、4个res-stage、global avg-pooling以及最后的fc层,那么完成模型组网和权重转换之后,如果模型输出没有对齐,可以尝试输出中间某一个res-stage的tensor进行对比,如果相同,则向后进行排查;如果不同,则继续向前进行排查,以此类推,直到找到导致没有对齐的操作。
* 给定相同的输入数据,为保证可复现性,如果有随机数生成,固定相关的随机种子。
* 输出diff可以使用`np.mean(np.abs(o1 - o2))`进行计算,一般小于1e-6的话,可以认为前向没有问题。如果最终输出结果diff较大,可以使用二分的方法进行排查,比如说ResNet50,包含1个stem、4个res-stage、global avg-pooling以及最后的fc层,那么完成模型组网和权重转换之后,如果模型输出没有对齐,可以尝试输出中间某一个res-stage的tensor进行对比,如果相同,则向后进行排查;如果不同,则继续向前进行排查,以此类推,直到找到导致没有对齐的操作。
**【实战】**
### 3.2 验证/测试集数据读取对齐
AlexNet模型组网正确性验证可以参考如下示例代码:
[https://github.com/littletomatodonkey/AlexNet-Prod/tree/master/pipeline/Step1](https://github.com/littletomatodonkey/AlexNet-Prod/tree/master/pipeline/Step1)
### 3.2 验证/测试集数据读取对齐
#### 3.2.1 数据集类Dataset复现方法
**【基本流程】**
对于一个数据集,一般有以下一些信息需要重点关注
* 数据集名称、下载地址
......@@ -305,9 +259,11 @@ transfer()
* 数据集标注格式、标注信息
* 数据集通用的预处理方法
PaddlePaddle中数据集类为`paddle.io.Dataset`,PyTorch中对应为`torch.utils.data.Dataset`,二者功能一致,在绝大多数情况下,可以使用该类构建数据集。它是描述Dataset方法和行为的抽象类,在具体实现的时候,需要继承这个基类,实现其中的`__getitem__``__len__`方法。更多使用细节可以参考论文中的说明。
PaddlePaddle中数据集相关的API为`paddle.io.Dataset`,PyTorch中对应为`torch.utils.data.Dataset`,二者功能一致,在绝大多数情况下,可以使用该类构建数据集。它是描述Dataset方法和行为的抽象类,在具体实现的时候,需要继承这个基类,实现其中的`__getitem__``__len__`方法。除了参考代码中相关实现,也可以参考待复现论文中的说明。
论文中一般会提供数据集的名称以及基本信息。复现过程中,我们在下载完数据之后,建议先检查下是否和论文中描述一致,否则可能存在的问题有:
**【注意事项】**
此外,论文中一般会提供数据集的名称以及基本信息。复现过程中,我们在下载完数据之后,建议先检查下是否和论文中描述一致,否则可能存在的问题有:
* 数据集年份不同,比如论文中使用了MS-COCO2014数据集,但是我们下载的是MS-COCO2017数据集,如果不对其进行检查,可能会导致我们最终训练的数据量等与论文中有diff
* 数据集使用方式不同,有些论文中,可能只是抽取了该数据集的子集进行方法验证,此时需要注意抽取方法,需要保证抽取出的子集完全相同
......@@ -318,6 +274,9 @@ PaddlePaddle中数据集类为`paddle.io.Dataset`,PyTorch中对应为`torch.ut
* 有些自定义的数据处理方法,如果不涉及到深度学习框架的部分,可以直接复用。
* 对于特定任务中的数据预处理方法,比如说图像分类、检测、分割等,如果没有现成的API可以调用,可以参考官方模型套件中的一些实现方法,比如PaddleClas、PaddleDetection、PaddleSeg等。
**【实战】**
#### 3.2.2 数据加载器Dataloader复现方法
复现完Dataset之后,可以构建Dataloader,对数据进行组batch、批处理,送进网络进行计算。
......@@ -392,9 +351,6 @@ INFO:reprod_log.utils: mean diff: check passed: True, value: 0.0
INFO:reprod_log.utils:diff check passed
```
### 3.3 评估指标对齐
#### 3.3.1 复现方法
......@@ -751,7 +707,7 @@ python3.7 -m paddle.distributed.launch \
注意:这里8卡训练时,虽然单卡的batch size没有变化(32),但是总卡的batch size相当于是单卡的8倍,因此学习率也设置为了单卡时的8倍。
## 4. 验收与验收方法
## 4. 验收节点自查与验收方法
### 4.1 模型结构对齐验收方法
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册