Merge branch 'PaddlePaddle:develop' into develop
commit
f64188e4ea
|
@ -8,7 +8,7 @@
|
|||
|
||||
**近期更新**
|
||||
|
||||
- 2021.07.08、07.27 添加26个[FAQ](docs/zh_CN/faq_series/faq_2021_s2.md)
|
||||
- 2021.08.11 更新7个[FAQ](docs/zh_CN/faq_series/faq_2021_s2.md)。
|
||||
- 2021.06.29 添加Swin-transformer系列模型,ImageNet1k数据集上Top1 acc最高精度可达87.2%;支持训练预测评估与whl包部署,预训练模型可以从[这里](docs/zh_CN/models/models_intro.md)下载。
|
||||
- 2021.06.22,23,24 PaddleClas官方研发团队带来技术深入解读三日直播课。课程回放:[https://aistudio.baidu.com/aistudio/course/introduce/24519](https://aistudio.baidu.com/aistudio/course/introduce/24519)
|
||||
- 2021.06.16 PaddleClas v2.2版本升级,集成Metric learning,向量检索等组件。新增商品识别、动漫人物识别、车辆识别和logo识别等4个图像识别应用。新增LeViT、Twins、TNT、DLA、HarDNet、RedNet系列30个预训练模型。
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -167,4 +167,22 @@ python tools/export_model.py -c configs/ppyolo/ppyolov2_r50vd_dcn_365e_coco.yml
|
|||
|
||||
更多模型导出教程,请参考:[EXPORT_MODEL](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/deploy/EXPORT_MODEL.md)
|
||||
|
||||
导出模型之后,在主体检测与识别任务中,就可以将检测模型的路径更改为该inference模型路径,完成预测。图像识别快速体验可以参考:[图像识别快速开始教程](../tutorials/quick_start_recognition.md)。
|
||||
最终,目录`inference/ppyolov2_r50vd_dcn_365e_coco`中包含`inference.pdiparams`, `inference.pdiparams.info` 以及 `inference.pdmodel` 文件,其中`inference.pdiparams`为保存的inference模型权重文件,`inference.pdmodel`为保存的inference模型结构文件。
|
||||
|
||||
|
||||
导出模型之后,在主体检测与识别任务中,就可以将检测模型的路径更改为该inference模型路径,完成预测。
|
||||
|
||||
以商品识别为例,其配置文件为[inference_product.yaml](../../../deploy/configs/inference_product.yaml),修改其中的`Global.det_inference_model_dir`字段为导出的主体检测inference模型目录,参考[图像识别快速开始教程](../tutorials/quick_start_recognition.md),即可完成商品检测与识别过程。
|
||||
|
||||
|
||||
### FAQ
|
||||
|
||||
#### Q:可以使用其他的主体检测模型结构吗?
|
||||
|
||||
* A:可以的,但是目前的检测预处理过程仅适配yolo系列的预处理,因此在使用的时候,建议优先使用yolo系列的模型进行训练,如果希望使用faster rcnn等其他系列的模型,需要按照PaddleDetection的数据预处理,修改下预处理逻辑,这块如果您有需求或者有问题的话,欢迎提issue或者在群里反馈。
|
||||
|
||||
#### Q:可以修改主体检测的预测尺度吗?
|
||||
|
||||
* A:可以的,但是需要注意2个地方
|
||||
* PaddleClas中提供的主体检测模型是基于640x640的分辨率去训练的,因此预测的时候也是默认使用640x640的分辨率进行预测,使用其他分辨率预测的话,精度会有所降低。
|
||||
* 在模型导出的时候,建议也修改下模型导出的分辨率,保持模型导出、模型预测的分辨率一致。
|
||||
|
|
|
@ -1,124 +1,269 @@
|
|||
# 图像识别常见问题汇总 - 2021 第2季
|
||||
# PaddleClas 相关常见问题汇总 - 2021 第2季
|
||||
|
||||
## 写在前面
|
||||
|
||||
* 我们收集整理了开源以来在issues和用户群中的常见问题并且给出了简要解答,旨在为广大用户提供一些参考,也希望帮助大家少走一些弯路。
|
||||
|
||||
* 图像分类、识别、检索领域大佬众多,模型和论文更新速度也很快,本文档回答主要依赖有限的项目实践,难免挂一漏万,如有遗漏和不足,也希望有识之士帮忙补充和修正,万分感谢。
|
||||
|
||||
## 目录
|
||||
* [第1期](#第1期)(2021.07.08)
|
||||
* [第2期](#第2期)(2021.07.27)
|
||||
* [近期更新](#近期更新)(2021.08.11)
|
||||
* [精选](#精选)
|
||||
* [1. 理论篇](#1.理论篇)
|
||||
* [1.1 PaddleClas基础知识](#1.1PaddleClas基础知识)
|
||||
* [1.2 骨干网络和预训练模型库](#1.2骨干网络和预训练模型库)
|
||||
* [1.3 图像分类](#1.3图像分类)
|
||||
* [1.4 通用检测模块](#1.4通用检测模块)
|
||||
* [1.5 图像识别模块](#1.5图像识别模块)
|
||||
* [1.6 检索模块](#1.6检索模块)
|
||||
* [2. 实战篇](#2.实战篇)
|
||||
* [2.1 训练与评估共性问题](#2.1训练与评估共性问题)
|
||||
* [2.2 图像分类](#2.2图像分类)
|
||||
* [2.3 通用检测模块](#2.3通用检测模块)
|
||||
* [2.4 图像识别模块](#2.4图像识别模块)
|
||||
* [2.5 检索模块](#2.5检索模块)
|
||||
* [2.6 模型预测部署](#2.6模型预测部署)
|
||||
|
||||
<a name="第1期"></a>
|
||||
## 第1期
|
||||
<a name="近期更新"></a>
|
||||
## 近期更新
|
||||
|
||||
### Q1.1: 目前使用的主体检测模型检测在某些场景中会有误检?
|
||||
#### Q2.6.2: 导出inference模型进行预测部署,准确率异常,为什么呢?
|
||||
**A**: 该问题通常是由于在导出时未能正确加载模型参数导致的,首先检查模型导出时的日志,是否存在类似下述内容:
|
||||
```
|
||||
UserWarning: Skip loading for ***. *** is not found in the provided dict.
|
||||
```
|
||||
如果存在,则说明模型权重未能加载成功,请进一步检查配置文件中的 `Global.pretrained_model` 字段,是否正确配置了模型权重文件的路径。模型权重文件后缀名通常为 `pdparams`,注意在配置该路径时无需填写文件后缀名。
|
||||
|
||||
**A**:目前的主体检测模型训练时使用了COCO、Object365、RPC、LogoDet等公开数据集,如果被检测数据是类似工业质检等于常见类别差异较大的数据,需要基于目前的检测模型重新微调训练。
|
||||
#### Q2.1.4: 数据预处理中,不想对输入数据进行裁剪,该如何设置?或者如何设置剪裁的尺寸。
|
||||
**A**: PaddleClas 支持的数据预处理算子可在这里查看:`ppcls/data/preprocess/__init__.py`,所有支持的算子均可在配置文件中进行配置,配置的算子名称需要和算子类名一致,参数与对应算子类的构造函数参数一致。如不需要对图像裁剪,则可去掉 `CropImage`、`RandCropImage`,使用 `ResizeImage` 替换即可,可通过其参数设置不同的resize方式, 使用 `size` 参数则直接将图像缩放至固定大小,使用`resize_short` 参数则会维持图像宽高比进行缩放。设置裁剪尺寸时,可通过 `CropImage` 算子的 `size` 参数,或 `RandCropImage` 算子的 `size` 参数。
|
||||
|
||||
### Q1.2: 添加图片后建索引报`assert text_num >= 2`错?
|
||||
#### Q1.1.3: Momentum 优化器中的 momentum 参数是什么意思呢?
|
||||
**A**: Momentum 优化器是在 SGD 优化器的基础上引入了“动量”的概念。在 SGD 优化器中,在 `t+1` 时刻,参数 `w` 的更新可表示为:
|
||||
```latex
|
||||
w_t+1 = w_t - lr * grad
|
||||
```
|
||||
其中,`lr` 为学习率,`grad` 为此时参数 `w` 的梯度。在引入动量的概念后,参数 `w` 的更新可表示为:
|
||||
```latex
|
||||
v_t+1 = m * v_t + lr * grad
|
||||
w_t+1 = w_t - v_t+1
|
||||
```
|
||||
其中,`m` 即为动量 `momentum`,表示累积动量的加权值,一般取 `0.9`,当取值小于 `1` 时,则越早期的梯度对当前的影响越小,例如,当动量参数 `m` 取 `0.9` 时,在 `t` 时刻,`t-5` 的梯度加权值为 `0.9 ^ 5 = 0.59049`,而 `t-2` 时刻的梯度加权值为 `0.9 ^ 2 = 0.81`。因此,太过“久远”的梯度信息对当前的参考意义很小,而“最近”的历史梯度信息对当前影响更大,这也是符合直觉的。
|
||||
|
||||
**A**:请确保data_file.txt中图片路径和图片名称中间的间隔为单个table,而不是空格。
|
||||
<div align="center">
|
||||
<img src="../../images/faq/momentum.jpeg" width="400">
|
||||
</div>
|
||||
|
||||
### Q1.3: 识别模块预测时报`Illegal instruction`错?
|
||||
*该图来自 `https://blog.csdn.net/tsyccnh/article/details/76270707`*
|
||||
|
||||
**A**:可能是编译生成的库文件与您的环境不兼容,导致程序报错,如果报错,推荐参考[向量检索教程](../../../deploy/vector_search/README.md)重新编译库文件。
|
||||
通过引入动量的概念,在参数更新时考虑了历史更新的影响,因此可以加快收敛速度,也改善了 `SGD` 优化器带来的损失(cost、loss)震荡问题。
|
||||
|
||||
### Q1.4 主体检测是每次只输出一个主体检测框吗?
|
||||
#### Q1.1.4: PaddleClas 是否有 `Fixing the train-test resolution discrepancy` 这篇论文的实现呢?
|
||||
**A**: 目前 PaddleClas 没有实现。如果需要,可以尝试自己修改代码。简单来说,该论文所提出的思想是使用较大分辨率作为输入,对已经训练好的模型最后的FC层进行fine-tune。具体操作上,首先在较低分辨率的数据集上对模型网络进行训练,完成训练后,对网络除最后的FC层外的其他层的权重设置参数 `stop_gradient=True`,然后使用较大分辨率的输入对网络进行fine-tune训练。
|
||||
|
||||
**A**:主体检测这块的输出数量是可以通过配置文件配置的。在配置文件中Global.threshold控制检测的阈值,小于该阈值的检测框被舍弃,Global.max_det_results控制最大返回的结果数,这两个参数共同决定了输出检测框的数量。
|
||||
#### Q1.6.2: PaddleClas 图像识别用于 Eval 的配置文件中,`Query` 和 `Gallery` 配置具体是用于做什么呢?
|
||||
**A**: `Query` 与 `Gallery` 均为数据集配置,其中 `Gallery` 用于配置底库数据,`Query` 用于配置验证集。在进行 Eval 时,首先使用模型对 `Gallery` 底库数据进行前向计算特征向量,特征向量用于构建底库,然后模型对 `Query` 验证集中的数据进行前向计算特征向量,再与底库计算召回率等指标。
|
||||
|
||||
### Q1.5 训练主体检测模型的数据是如何选择的?换成更小的模型会有损精度吗?
|
||||
#### Q2.1.5: PaddlePaddle 安装后,使用报错,无法导入 paddle 下的任何模块(import paddle.xxx),是为什么呢?
|
||||
**A**: 首先可以使用以下代码测试 Paddle 是否安装正确:
|
||||
```python
|
||||
import paddle
|
||||
paddle.utils.install_check.run_check()
|
||||
```
|
||||
正确安装时,通常会有如下提示:
|
||||
```
|
||||
PaddlePaddle is installed successfully! Let's start deep learning with PaddlePaddle now.
|
||||
```
|
||||
如未能安装成功,则会有相应问题的提示。
|
||||
另外,在同时安装CPU版本和GPU版本Paddle后,由于两个版本存在冲突,需要将两个版本全部卸载,然后重新安装所需要的版本。
|
||||
|
||||
**A**:训练数据是在COCO、Object365、RPC、LogoDet等公开数据集中随机抽取的子集,小模型精度可能会有一些损失,后续我们也会尝试下更小的检测模型。关于主体检测模型的更多信息请参考[主体检测](../application/mainbody_detection.md)。
|
||||
#### Q2.1.6: 使用PaddleClas训练时,如何设置仅保存最优模型?不想保存中间模型。
|
||||
**A**: PaddleClas在训练过程中,会保存/更新以下三类模型:
|
||||
1. 最新的模型(`latest.pdopt`, `latest.pdparams`,`latest.pdstates`),当训练意外中断时,可使用最新保存的模型恢复训练;
|
||||
2. 最优的模型(`best_model.pdopt`,`best_model.pdparams`,`best_model.pdstates`);
|
||||
3. 训练过程中,一个epoch结束时的断点(`epoch_xxx.pdopt`,`epoch_xxx.pdparams`,`epoch_xxx.pdstates`)。训练配置文件中 `Global.save_interval` 字段表示该模型的保存间隔。将该字段设置大于总epochs数,则不再保存中间断点模型。
|
||||
|
||||
### Q1.6 识别模型怎么在预训练模型的基础上进行微调训练?
|
||||
<a name="精选"></a>
|
||||
## 精选
|
||||
|
||||
**A**:识别模型的微调训练和分类模型的微调训练类似,识别模型可以加载商品的预训练模型],训练过程可以参考[识别模型训练](../tutorials/getting_started_retrieval.md),后续我们也会持续细化这块的文档。
|
||||
<a name="1.理论篇"></a>
|
||||
## 1. 理论篇
|
||||
|
||||
### Q1.7 PaddleClas和PaddleDetection区别
|
||||
<a name="1.1PaddleClas基础知识"></a>
|
||||
### 1.1 PaddleClas基础知识
|
||||
|
||||
#### Q1.1.1 PaddleClas和PaddleDetection区别
|
||||
**A**:PaddleClas是一个兼主体检测、图像分类、图像检索于一体的图像识别repo,用于解决大部分图像识别问题,用户可以很方便的使用PaddleClas来解决小样本、多类别的图像识别问题。PaddleDetection提供了目标检测、关键点检测、多目标跟踪等能力,方便用户定位图像中的感兴趣的点和区域,被广泛应用于工业质检、遥感图像检测、无人巡检等项目。
|
||||
|
||||
### Q1.8 PaddleClas 2.2和PaddleClas 2.1完全兼容吗?
|
||||
|
||||
#### Q1.1.2 PaddleClas 2.2和PaddleClas 2.1完全兼容吗?
|
||||
**A**:PaddleClas2.2相对PaddleClas2.1新增了metric learning模块,主体检测模块、向量检索模块。另外,也提供了商品识别、车辆识别、logo识别和动漫人物识别等4个场景应用示例。用户可以基于PaddleClas 2.2快速构建图像识别系统。在图像分类模块,二者的使用方法类似,可以参考[图像分类示例](../tutorials/getting_started.md)快速迭代和评估。新增的metric learning模块,可以参考[metric learning示例](../tutorials/getting_started_retrieval.md)。另外,新版本暂时还不支持fp16、dali训练,也暂时不支持多标签训练,这块内容将在不久后支持。
|
||||
|
||||
### Q1.9 训练metric learning时,每个epoch中,无法跑完所有mini-batch,为什么?
|
||||
#### Q1.1.3: Momentum 优化器中的 momentum 参数是什么意思呢?
|
||||
**A**: Momentum 优化器是在 SGD 优化器的基础上引入了“动量”的概念。在 SGD 优化器中,在 `t+1` 时刻,参数 `w` 的更新可表示为:
|
||||
```latex
|
||||
w_t+1 = w_t - lr * grad
|
||||
```
|
||||
其中,`lr` 为学习率,`grad` 为此时参数 `w` 的梯度。在引入动量的概念后,参数 `w` 的更新可表示为:
|
||||
```latex
|
||||
v_t+1 = m * v_t + lr * grad
|
||||
w_t+1 = w_t - v_t+1
|
||||
```
|
||||
其中,`m` 即为动量 `momentum`,表示累积动量的加权值,一般取 `0.9`,当取值小于 `1` 时,则越早期的梯度对当前的影响越小,例如,当动量参数 `m` 取 `0.9` 时,在 `t` 时刻,`t-5` 的梯度加权值为 `0.9 ^ 5 = 0.59049`,而 `t-2` 时刻的梯度加权值为 `0.9 ^ 2 = 0.81`。因此,太过“久远”的梯度信息对当前的参考意义很小,而“最近”的历史梯度信息对当前影响更大,这也是符合直觉的。
|
||||
|
||||
**A**:在训练metric learning时,使用的Sampler是DistributedRandomIdentitySampler,该Sampler不会采样全部的图片,导致会让每一个epoch采样的数据不是所有的数据,所以无法跑完显示的mini-batch是正常现象。后续我们会优化下打印的信息,尽可能减少给大家带来的困惑。
|
||||
<div align="center">
|
||||
<img src="../../images/faq/momentum.jpeg" width="400">
|
||||
</div>
|
||||
|
||||
### Q1.10 有些图片没有识别出结果,为什么?
|
||||
通过引入动量的概念,在参数更新时考虑了历史更新的影响,因此可以加快收敛速度,也改善了 `SGD` 优化器带来的损失(cost、loss)震荡问题。
|
||||
|
||||
**A**:在配置文件(如inference_product.yaml)中,`IndexProcess.score_thres`中会控制被识别的图片与库中的图片的余弦相似度的最小值。当余弦相似度小于该值时,不会打印结果。您可以根据自己的实际数据调整该值。
|
||||
#### Q1.1.4: PaddleClas 是否有 `Fixing the train-test resolution discrepancy` 这篇论文的实现呢?
|
||||
**A**: 目前 PaddleClas 没有实现。如果需要,可以尝试自己修改代码。简单来说,该论文所提出的思想是使用较大分辨率作为输入,对已经训练好的模型最后的FC层进行fine-tune。具体操作上,首先在较低分辨率的数据集上对模型网络进行训练,完成训练后,对网络除最后的FC层外的其他层的权重设置参数 `stop_gradient=True`,然后使用较大分辨率的输入对网络进行fine-tune训练。
|
||||
|
||||
### Q1.11 为什么有一些图片检测出的结果就是原图?
|
||||
<a name="1.2骨干网络和预训练模型库"></a>
|
||||
### 1.2 骨干网络和预训练模型库
|
||||
|
||||
**A**:主体检测模型会返回检测框,但事实上为了让后续的识别模型更加准确,在返回检测框的同时也返回了原图。后续会根据原图或者检测框与库中的图片的相似度排序,相似度最高的库中图片的标签即为被识别图片的标签。
|
||||
<a name="1.3图像分类"></a>
|
||||
### 1.3 图像分类
|
||||
|
||||
### Q1.12 使用`circle loss`还需加`triplet loss`吗?
|
||||
#### Q1.3.1: PaddleClas有提供调整图片亮度,对比度,饱和度,色调等方面的数据增强吗?
|
||||
**A**:PaddleClas提供了多种数据增广方式, 可分为3类:
|
||||
1. 图像变换类: AutoAugment, RandAugment;
|
||||
2. 图像裁剪类: CutOut、RandErasing、HideAndSeek、GridMask;
|
||||
3. 图像混叠类:Mixup, Cutmix.
|
||||
|
||||
其中,Randangment提供了多种数据增强方式的随机组合,可以满足亮度、对比度、饱和度、色调等多方面的数据增广需求
|
||||
|
||||
<a name="1.4通用检测模块"></a>
|
||||
### 1.4 通用检测模块
|
||||
|
||||
#### Q1.4.1 主体检测是每次只输出一个主体检测框吗?
|
||||
**A**:主体检测这块的输出数量是可以通过配置文件配置的。在配置文件中Global.threshold控制检测的阈值,小于该阈值的检测框被舍弃,Global.max_det_results控制最大返回的结果数,这两个参数共同决定了输出检测框的数量。
|
||||
|
||||
#### Q1.4.2 训练主体检测模型的数据是如何选择的?换成更小的模型会有损精度吗?
|
||||
**A**:训练数据是在COCO、Object365、RPC、LogoDet等公开数据集中随机抽取的子集,小模型精度可能会有一些损失,后续我们也会尝试下更小的检测模型。关于主体检测模型的更多信息请参考[主体检测](../application/mainbody_detection.md)。
|
||||
|
||||
#### Q1.4.3: 目前使用的主体检测模型检测在某些场景中会有误检?
|
||||
**A**:目前的主体检测模型训练时使用了COCO、Object365、RPC、LogoDet等公开数据集,如果被检测数据是类似工业质检等于常见类别差异较大的数据,需要基于目前的检测模型重新微调训练。
|
||||
|
||||
<a name="1.5图像识别模块"></a>
|
||||
### 1.5 图像识别模块
|
||||
|
||||
#### Q1.5.1 使用`circle loss`还需加`triplet loss`吗?
|
||||
**A**:`circle loss`是统一了样本对学习和分类学习的两种形式,如果是分类学习的形式的话,可以增加`triplet loss`。
|
||||
|
||||
### Q1.13 hub serving方式启动某个模块,怎么添加该模块的参数呢?
|
||||
|
||||
**A**:具体可以参考[hub serving参数](../../../deploy/hubserving/clas/params.py)。
|
||||
|
||||
### Q1.14 模型训练出nan,为什么?
|
||||
|
||||
**A**:
|
||||
|
||||
1.确保正确加载预训练模型, 最简单的加载方式添加参数`-o Arch.pretrained=True`即可;
|
||||
|
||||
2.模型微调时,学习率不要太大,如设置0.001就好。
|
||||
|
||||
|
||||
### Q1.15 SSLD中,大模型在500M数据上预训练后蒸馏小模型,然后在1M数据上蒸馏finetune小模型?
|
||||
|
||||
**A**:步骤如下:
|
||||
|
||||
1.基于facebook开源的`ResNeXt101-32x16d-wsl`模型 去蒸馏得到了`ResNet50-vd`模型;
|
||||
|
||||
2.用这个`ResNet50-vd`,在500W数据集上去蒸馏`MobilNetV3`;
|
||||
|
||||
3.考虑到500W的数据集的分布和100W的数据分布不完全一致,所以这块,在100W上的数据上又finetune了一下,精度有微弱的提升。
|
||||
|
||||
|
||||
### Q1.16 如果不是识别开源的四个方向的图片,该使用哪个识别模型?
|
||||
|
||||
#### Q1.5.2 如果不是识别开源的四个方向的图片,该使用哪个识别模型?
|
||||
**A**:建议使用商品识别模型,一来是因为商品覆盖的范围比较广,被识别的图片是商品的概率更大,二来是因为商品识别模型的训练数据使用了5万类别的数据,泛化能力更好,特征会更鲁棒一些。
|
||||
|
||||
### Q1.17 最后使用512维的向量,为什么不用1024或者其他维度的呢?
|
||||
|
||||
#### Q1.5.3 最后使用512维的向量,为什么不用1024或者其他维度的呢?
|
||||
**A**:使用维度小的向量,为了加快计算,在实际使用过程中,可能使用128甚至更小。一般来说,512的维度已经够大,能充分表示特征了。
|
||||
|
||||
### Q1.18 训练SwinTransformer,loss出现nan
|
||||
|
||||
**A**:训练SwinTransformer的话,需要使用paddle-dev去训练,安装方式参考[paddlepaddle安装方式](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/develop/install/pip/linux-pip.html),后续paddlepaddle-2.1也会同时支持。
|
||||
|
||||
### Q1.19 新增底库数据需要重新构建索引吗?
|
||||
|
||||
**A**:这一版需要重新构建索引,未来版本会支持只构建新增图片的索引。
|
||||
|
||||
### Q1.20 PaddleClas 的`train_log`文件在哪里?
|
||||
|
||||
**A**:在保存权重的路径中存放了`train.log`。
|
||||
|
||||
|
||||
<a name="第2期"></a>
|
||||
## 第2期
|
||||
|
||||
### Q2.1 PaddleClas目前使用的Möbius向量检索算法支持类似于faiss的那种index.add()的功能吗? 另外,每次构建新的图都要进行train吗?这里的train是为了检索加速还是为了构建相似的图?
|
||||
<a name="1.6检索模块"></a>
|
||||
### 1.6 检索模块
|
||||
|
||||
#### Q1.6.1 PaddleClas目前使用的Möbius向量检索算法支持类似于faiss的那种index.add()的功能吗? 另外,每次构建新的图都要进行train吗?这里的train是为了检索加速还是为了构建相似的图?
|
||||
**A**:Mobius提供的检索算法是一种基于图的近似最近邻搜索算法,目前支持两种距离计算方式:inner product和L2 distance. faiss中提供的index.add功能暂时不支持,如果需要增加检索库的内容,需要从头重新构建新的index. 在每次构建index时,检索算法内部执行的操作是一种类似于train的过程,不同于faiss提供的train接口,我们命名为build, 主要的目的是为了加速检索的速度。
|
||||
|
||||
### Q2.2 可以对视频中每一帧画面进行逐帧预测吗?
|
||||
#### Q1.6.2: PaddleClas 图像识别用于 Eval 的配置文件中,`Query` 和 `Gallery` 配置具体是用于做什么呢?
|
||||
**A**: `Query` 与 `Gallery` 均为数据集配置,其中 `Gallery` 用于配置底库数据,`Query` 用于配置验证集。在进行 Eval 时,首先使用模型对 `Gallery` 底库数据进行前向计算特征向量,特征向量用于构建底库,然后模型对 `Query` 验证集中的数据进行前向计算特征向量,再与底库计算召回率等指标。
|
||||
|
||||
<a name="2.实战篇"></a>
|
||||
## 2. 实战篇
|
||||
|
||||
<a name="2.1训练与评估共性问题"></a>
|
||||
### 2.1 训练与评估共性问题
|
||||
|
||||
#### Q2.1.1 PaddleClas 的`train_log`文件在哪里?
|
||||
**A**:在保存权重的路径中存放了`train.log`。
|
||||
|
||||
#### Q2.1.2 模型训练出nan,为什么?
|
||||
**A**:
|
||||
1.确保正确加载预训练模型, 最简单的加载方式添加参数`-o Arch.pretrained=True`即可;
|
||||
2.模型微调时,学习率不要太大,如设置0.001就好。
|
||||
|
||||
#### Q2.1.3 可以对视频中每一帧画面进行逐帧预测吗?
|
||||
**A**:可以,但目前PaddleClas并不支持视频输入。可以尝试修改一下PaddleClas代码,或者预先将视频逐帧转为图像存储,再使用PaddleClas进行预测。
|
||||
|
||||
### Q2.3:在直播场景中,需要提供一个直播即时识别画面,能够在延迟几秒内找到特征目标物并用框圈起,这个可以实现吗?
|
||||
**A**:要达到实时的检测效果,需要检测速度达到实时性的要求;PPyolo是Paddle团队提供的轻量级目标检测模型,检测速度和精度达到了很好的平衡,可以试试ppyolo来做检测. 关于ppyolo的使用,可以参照: https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/configs/ppyolo/README_cn.md
|
||||
#### Q2.1.4: 数据预处理中,不想对输入数据进行裁剪,该如何设置?或者如何设置剪裁的尺寸。
|
||||
**A**: PaddleClas 支持的数据预处理算子可在这里查看:`ppcls/data/preprocess/__init__.py`,所有支持的算子均可在配置文件中进行配置,配置的算子名称需要和算子类名一致,参数与对应算子类的构造函数参数一致。如不需要对图像裁剪,则可去掉 `CropImage`、`RandCropImage`,使用 `ResizeImage` 替换即可,可通过其参数设置不同的resize方式, 使用 `size` 参数则直接将图像缩放至固定大小,使用`resize_short` 参数则会维持图像宽高比进行缩放。设置裁剪尺寸时,可通过 `CropImage` 算子的 `size` 参数,或 `RandCropImage` 算子的 `size` 参数。
|
||||
|
||||
### Q2.4: 对于未知的标签,加入gallery dataset可以用于后续的分类识别(无需训练),但是如果前面的检测模型对于未知的标签无法定位检测出来,是否还是要训练前面的检测模型?
|
||||
#### Q2.1.5: PaddlePaddle 安装后,使用报错,无法导入 paddle 下的任何模块(import paddle.xxx),是为什么呢?
|
||||
**A**: 首先可以使用以下代码测试 Paddle 是否安装正确:
|
||||
```python
|
||||
import paddle
|
||||
paddle.utils.install_check.run_check()
|
||||
```
|
||||
正确安装时,通常会有如下提示:
|
||||
```
|
||||
PaddlePaddle is installed successfully! Let's start deep learning with PaddlePaddle now.
|
||||
```
|
||||
如未能安装成功,则会有相应问题的提示。
|
||||
另外,在同时安装CPU版本和GPU版本Paddle后,由于两个版本存在冲突,需要将两个版本全部卸载,然后重新安装所需要的版本。
|
||||
|
||||
#### Q2.1.6: 使用PaddleClas训练时,如何设置仅保存最优模型?不想保存中间模型。
|
||||
**A**: PaddleClas在训练过程中,会保存/更新以下三类模型:
|
||||
1. 最新的模型(`latest.pdopt`, `latest.pdparams`,`latest.pdstates`),当训练意外中断时,可使用最新保存的模型恢复训练;
|
||||
2. 最优的模型(`best_model.pdopt`,`best_model.pdparams`,`best_model.pdstates`);
|
||||
3. 训练过程中,一个epoch结束时的断点(`epoch_xxx.pdopt`,`epoch_xxx.pdparams`,`epoch_xxx.pdstates`)。训练配置文件中 `Global.save_interval` 字段表示该模型的保存间隔。将该字段设置大于总epochs数,则不再保存中间断点模型。
|
||||
|
||||
<a name="2.2图像分类"></a>
|
||||
### 2.2 图像分类
|
||||
|
||||
#### Q2.2.1 SSLD中,大模型在500M数据上预训练后蒸馏小模型,然后在1M数据上蒸馏finetune小模型?
|
||||
**A**:步骤如下:
|
||||
1. 基于facebook开源的`ResNeXt101-32x16d-wsl`模型 去蒸馏得到了`ResNet50-vd`模型;
|
||||
2. 用这个`ResNet50-vd`,在500W数据集上去蒸馏`MobilNetV3`;
|
||||
3. 考虑到500W的数据集的分布和100W的数据分布不完全一致,所以这块,在100W上的数据上又finetune了一下,精度有微弱的提升。
|
||||
|
||||
#### Q2.2.2 训练SwinTransformer,loss出现nan
|
||||
**A**:训练SwinTransformer时,请使用版本大于等于 `2.1.1` 的 `Paddle`,并且加载我们提供的预训练模型,学习率也不宜过大。
|
||||
|
||||
<a name="2.3通用检测模块"></a>
|
||||
### 2.3 通用检测模块
|
||||
|
||||
#### Q2.3.1 为什么有一些图片检测出的结果就是原图?
|
||||
**A**:主体检测模型会返回检测框,但事实上为了让后续的识别模型更加准确,在返回检测框的同时也返回了原图。后续会根据原图或者检测框与库中的图片的相似度排序,相似度最高的库中图片的标签即为被识别图片的标签。
|
||||
|
||||
#### Q2.3.2:在直播场景中,需要提供一个直播即时识别画面,能够在延迟几秒内找到特征目标物并用框圈起,这个可以实现吗?
|
||||
**A**:要达到实时的检测效果,需要检测速度达到实时性的要求;PP-YOLO是Paddle团队提供的轻量级目标检测模型,检测速度和精度达到了很好的平衡,可以试试PP-YOLO来做检测. 关于PP-YOLO的使用,可以参照:[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.1/configs/ppyolo/README_cn.md)。
|
||||
|
||||
#### Q2.3.3: 对于未知的标签,加入gallery dataset可以用于后续的分类识别(无需训练),但是如果前面的检测模型对于未知的标签无法定位检测出来,是否还是要训练前面的检测模型?
|
||||
**A**:如果检测模型在自己的数据集上表现不佳,需要在自己的检测数据集上再finetune下
|
||||
|
||||
### Q2.5: Mac重新编译index.so时报错如下:clang: error: unsupported option '-fopenmp', 该如何处理?
|
||||
**A**:该问题已经解决。Mac编译index.so,可以参照文档: https://github.com/PaddlePaddle/PaddleClas/blob/develop/deploy/vector_search/README.md
|
||||
<a name="2.4图像识别模块"></a>
|
||||
### 2.4 图像识别模块
|
||||
|
||||
### Q2.6: PaddleClas有提供调整图片亮度,对比度,饱和度,色调等方面的数据增强吗?
|
||||
**A**:PaddleClas提供了多种数据增广方式, 可分为3类:1. 图像变换类: AutoAugment, RandAugment; 2. 图像裁剪类: CutOut、RandErasing、HideAndSeek、GridMask;3. 图像混叠类:Mixup, Cutmix. 其中,Randangment提供了多种数据增强方式的随机组合,可以满足亮度、对比度、饱和度、色调等多方面的数据增广需求
|
||||
#### Q2.4.1: 识别模块预测时报`Illegal instruction`错?
|
||||
**A**:可能是编译生成的库文件与您的环境不兼容,导致程序报错,如果报错,推荐参考[向量检索教程](../../../deploy/vector_search/README.md)重新编译库文件。
|
||||
|
||||
#### Q2.4.2: 识别模型怎么在预训练模型的基础上进行微调训练?
|
||||
**A**:识别模型的微调训练和分类模型的微调训练类似,识别模型可以加载商品的预训练模型,训练过程可以参考[识别模型训练](../tutorials/getting_started_retrieval.md),后续我们也会持续细化这块的文档。
|
||||
|
||||
#### Q2.4.3: 训练metric learning时,每个epoch中,无法跑完所有mini-batch,为什么?
|
||||
**A**:在训练metric learning时,使用的Sampler是DistributedRandomIdentitySampler,该Sampler不会采样全部的图片,导致会让每一个epoch采样的数据不是所有的数据,所以无法跑完显示的mini-batch是正常现象。后续我们会优化下打印的信息,尽可能减少给大家带来的困惑。
|
||||
|
||||
#### Q2.4.4: 有些图片没有识别出结果,为什么?
|
||||
**A**:在配置文件(如inference_product.yaml)中,`IndexProcess.score_thres`中会控制被识别的图片与库中的图片的余弦相似度的最小值。当余弦相似度小于该值时,不会打印结果。您可以根据自己的实际数据调整该值。
|
||||
|
||||
<a name="2.5检索模块"></a>
|
||||
### 2.5 检索模块
|
||||
|
||||
#### Q2.5.1: 添加图片后建索引报`assert text_num >= 2`错?
|
||||
**A**:请确保data_file.txt中图片路径和图片名称中间的间隔为单个table,而不是空格。
|
||||
|
||||
#### Q2.5.2: 新增底库数据需要重新构建索引吗?
|
||||
**A**:这一版需要重新构建索引,未来版本会支持只构建新增图片的索引。
|
||||
|
||||
#### Q2.5.3: Mac重新编译index.so时报错如下:clang: error: unsupported option '-fopenmp', 该如何处理?
|
||||
**A**:该问题已经解决。可以参照[文档](../../../develop/deploy/vector_search/README.md)重新编译 index.so。
|
||||
|
||||
<a name="2.6模型预测部署"></a>
|
||||
### 2.6 模型预测部署
|
||||
|
||||
#### Q2.6.1: hub serving方式启动某个模块,怎么添加该模块的参数呢?
|
||||
**A**:具体可以参考[hub serving参数](../../../deploy/hubserving/clas/params.py)。
|
||||
|
||||
#### Q2.6.2: 导出inference模型进行预测部署,准确率异常,为什么呢?
|
||||
**A**: 该问题通常是由于在导出时未能正确加载模型参数导致的,首先检查模型导出时的日志,是否存在类似下述内容:
|
||||
```
|
||||
UserWarning: Skip loading for ***. *** is not found in the provided dict.
|
||||
```
|
||||
如果存在,则说明模型权重未能加载成功,请进一步检查配置文件中的 `Global.pretrained_model` 字段,是否正确配置了模型权重文件的路径。模型权重文件后缀名通常为 `pdparams`,注意在配置该路径时无需填写文件后缀名。
|
||||
|
|
|
@ -244,7 +244,7 @@ python3 python/predict_cls.py \
|
|||
-c configs/inference_cls.yaml \
|
||||
-o Global.infer_imgs=../dataset/flowers102/jpg/image_00001.jpg \
|
||||
-o Global.inference_model_dir=../inference/ \
|
||||
-o PostProcess.class_id_map_file=None
|
||||
-o PostProcess.Topk.class_id_map_file=None
|
||||
|
||||
|
||||
其中:
|
||||
|
|
|
@ -128,7 +128,7 @@ python3 -m paddle.distributed.launch \
|
|||
PaddleClas包含了自研的SSLD知识蒸馏方案,具体的内容可以参考[知识蒸馏章节](../advanced_tutorials/distillation/distillation.md), 本小节将尝试使用知识蒸馏技术对MobileNetV3_large_x1_0模型进行训练,使用`2.1.2小节`训练得到的ResNet50_vd模型作为蒸馏所用的教师模型,首先将`2.1.2小节`训练得到的ResNet50_vd模型保存到指定目录,脚本如下。
|
||||
|
||||
```shell
|
||||
mkdir pretrained
|
||||
mkdir pretrained
|
||||
cp -r output_CIFAR/ResNet50_vd/best_model.pdparams ./pretrained/
|
||||
```
|
||||
|
||||
|
@ -256,5 +256,5 @@ PreProcess:
|
|||
python3 python/predict_cls.py \
|
||||
-c configs/inference_cls.yaml \
|
||||
-o Global.infer_imgs=../dataset/CIFAR100/test/0/0001.png \
|
||||
-o PostProcess.class_id_map_file=None
|
||||
-o PostProcess.Topk.class_id_map_file=None
|
||||
```
|
||||
|
|
|
@ -12,15 +12,9 @@ class Identity(nn.Layer):
|
|||
|
||||
|
||||
class TheseusLayer(nn.Layer):
|
||||
def __init__(self, *args, return_patterns=None, **kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TheseusLayer, self).__init__()
|
||||
self.res_dict = None
|
||||
if return_patterns is not None:
|
||||
self._update_res(return_patterns)
|
||||
|
||||
def forward(self, *input, res_dict=None, **kwargs):
|
||||
if res_dict is not None:
|
||||
self.res_dict = res_dict
|
||||
self.res_dict = {}
|
||||
|
||||
# stop doesn't work when stop layer has a parallel branch.
|
||||
def stop_after(self, stop_layer_name: str):
|
||||
|
@ -38,33 +32,43 @@ class TheseusLayer(nn.Layer):
|
|||
stop_layer_name)
|
||||
return after_stop
|
||||
|
||||
def _update_res(self, return_layers):
|
||||
def update_res(self, return_patterns):
|
||||
if not return_patterns or isinstance(self, WrapLayer):
|
||||
return
|
||||
for layer_i in self._sub_layers:
|
||||
layer_name = self._sub_layers[layer_i].full_name()
|
||||
for return_pattern in return_layers:
|
||||
if return_layers is not None and re.match(return_pattern,
|
||||
layer_name):
|
||||
self._sub_layers[layer_i].register_forward_post_hook(
|
||||
self._save_sub_res_hook)
|
||||
if isinstance(self._sub_layers[layer_i], (nn.Sequential, nn.LayerList)):
|
||||
self._sub_layers[layer_i] = wrap_theseus(self._sub_layers[layer_i])
|
||||
self._sub_layers[layer_i].res_dict = self.res_dict
|
||||
self._sub_layers[layer_i].update_res(return_patterns)
|
||||
else:
|
||||
for return_pattern in return_patterns:
|
||||
if re.match(return_pattern, layer_name):
|
||||
if not isinstance(self._sub_layers[layer_i], TheseusLayer):
|
||||
self._sub_layers[layer_i] = wrap_theseus(self._sub_layers[layer_i])
|
||||
self._sub_layers[layer_i].register_forward_post_hook(
|
||||
self._sub_layers[layer_i]._save_sub_res_hook)
|
||||
self._sub_layers[layer_i].res_dict = self.res_dict
|
||||
if isinstance(self._sub_layers[layer_i], TheseusLayer):
|
||||
self._sub_layers[layer_i].res_dict = self.res_dict
|
||||
self._sub_layers[layer_i].update_res(return_patterns)
|
||||
|
||||
def replace_sub(self, layer_name_pattern, replace_function,
|
||||
recursive=True):
|
||||
for k in self._sub_layers.keys():
|
||||
layer_name = self._sub_layers[k].full_name()
|
||||
def _save_sub_res_hook(self, layer, input, output):
|
||||
self.res_dict[layer.full_name()] = output
|
||||
|
||||
def replace_sub(self, layer_name_pattern, replace_function, recursive=True):
|
||||
for layer_i in self._sub_layers:
|
||||
layer_name = self._sub_layers[layer_i].full_name()
|
||||
if re.match(layer_name_pattern, layer_name):
|
||||
self._sub_layers[k] = replace_function(self._sub_layers[k])
|
||||
self._sub_layers[layer_i] = replace_function(self._sub_layers[layer_i])
|
||||
if recursive:
|
||||
if isinstance(self._sub_layers[k], TheseusLayer):
|
||||
self._sub_layers[k].replace_sub(
|
||||
if isinstance(self._sub_layers[layer_i], TheseusLayer):
|
||||
self._sub_layers[layer_i].replace_sub(
|
||||
layer_name_pattern, replace_function, recursive)
|
||||
elif isinstance(self._sub_layers[k],
|
||||
nn.Sequential) or isinstance(
|
||||
self._sub_layers[k], nn.LayerList):
|
||||
for kk in self._sub_layers[k]._sub_layers.keys():
|
||||
self._sub_layers[k]._sub_layers[kk].replace_sub(
|
||||
elif isinstance(self._sub_layers[layer_i], (nn.Sequential, nn.LayerList)):
|
||||
for layer_j in self._sub_layers[layer_i]._sub_layers:
|
||||
self._sub_layers[layer_i]._sub_layers[layer_j].replace_sub(
|
||||
layer_name_pattern, replace_function, recursive)
|
||||
else:
|
||||
pass
|
||||
|
||||
'''
|
||||
example of replace function:
|
||||
|
@ -78,3 +82,40 @@ class TheseusLayer(nn.Layer):
|
|||
return new_conv
|
||||
|
||||
'''
|
||||
|
||||
|
||||
class WrapLayer(TheseusLayer):
|
||||
def __init__(self, sub_layer):
|
||||
super(WrapLayer, self).__init__()
|
||||
self.sub_layer = sub_layer
|
||||
self.name = sub_layer.full_name()
|
||||
|
||||
def full_name(self):
|
||||
return self.name
|
||||
|
||||
def forward(self, *inputs, **kwargs):
|
||||
return self.sub_layer(*inputs, **kwargs)
|
||||
|
||||
def update_res(self, return_patterns):
|
||||
if not return_patterns or not isinstance(self.sub_layer, (nn.Sequential, nn.LayerList)):
|
||||
return
|
||||
for layer_i in self.sub_layer._sub_layers:
|
||||
if isinstance(self.sub_layer._sub_layers[layer_i], (nn.Sequential, nn.LayerList)):
|
||||
self.sub_layer._sub_layers[layer_i] = wrap_theseus(self.sub_layer._sub_layers[layer_i])
|
||||
self.sub_layer._sub_layers[layer_i].res_dict = self.res_dict
|
||||
self.sub_layer._sub_layers[layer_i].update_res(return_patterns)
|
||||
|
||||
layer_name = self.sub_layer._sub_layers[layer_i].full_name()
|
||||
for return_pattern in return_patterns:
|
||||
if re.match(return_pattern, layer_name):
|
||||
self.sub_layer._sub_layers[layer_i].res_dict = self.res_dict
|
||||
self.sub_layer._sub_layers[layer_i].register_forward_post_hook(
|
||||
self._sub_layers[layer_i]._save_sub_res_hook)
|
||||
|
||||
if isinstance(self.sub_layer._sub_layers[layer_i], TheseusLayer):
|
||||
self.sub_layer._sub_layers[layer_i].update_res(return_patterns)
|
||||
|
||||
|
||||
def wrap_theseus(sub_layer):
|
||||
wrapped_layer = WrapLayer(sub_layer)
|
||||
return wrapped_layer
|
||||
|
|
|
@ -111,7 +111,7 @@ class VGGNet(TheseusLayer):
|
|||
model: nn.Layer. Specific VGG model depends on args.
|
||||
"""
|
||||
|
||||
def __init__(self, config, stop_grad_layers=0, class_num=1000):
|
||||
def __init__(self, config, stop_grad_layers=0, class_num=1000, return_patterns=None):
|
||||
super().__init__()
|
||||
|
||||
self.stop_grad_layers = stop_grad_layers
|
||||
|
@ -138,7 +138,7 @@ class VGGNet(TheseusLayer):
|
|||
self.fc2 = Linear(4096, 4096)
|
||||
self.fc3 = Linear(4096, class_num)
|
||||
|
||||
def forward(self, inputs):
|
||||
def forward(self, inputs, res_dict=None):
|
||||
x = self.conv_block_1(inputs)
|
||||
x = self.conv_block_2(x)
|
||||
x = self.conv_block_3(x)
|
||||
|
@ -152,6 +152,9 @@ class VGGNet(TheseusLayer):
|
|||
x = self.relu(x)
|
||||
x = self.drop(x)
|
||||
x = self.fc3(x)
|
||||
if self.res_dict and res_dict is not None:
|
||||
for res_key in list(self.res_dict):
|
||||
res_dict[res_key] = self.res_dict.pop(res_key)
|
||||
return x
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ MODEL_URLS = {
|
|||
"ResNeXt101_32x8d_wsl":
|
||||
"https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x8d_wsl_pretrained.pdparams",
|
||||
"ResNeXt101_32x16d_wsl":
|
||||
"https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x816_wsl_pretrained.pdparams",
|
||||
"https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x16_wsl_pretrained.pdparams",
|
||||
"ResNeXt101_32x32d_wsl":
|
||||
"https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNeXt101_32x32d_wsl_pretrained.pdparams",
|
||||
"ResNeXt101_32x48d_wsl":
|
||||
|
|
|
@ -24,6 +24,7 @@ Loss:
|
|||
Train:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
epsilon: 0.1
|
||||
Eval:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
|
@ -35,9 +36,10 @@ Optimizer:
|
|||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.8
|
||||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -24,6 +24,7 @@ Loss:
|
|||
Train:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
epsilon: 0.1
|
||||
Eval:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
|
@ -35,9 +36,10 @@ Optimizer:
|
|||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.8
|
||||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -24,6 +24,7 @@ Loss:
|
|||
Train:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
epsilon: 0.1
|
||||
Eval:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
|
@ -35,9 +36,10 @@ Optimizer:
|
|||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.8
|
||||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -41,7 +41,7 @@ Optimizer:
|
|||
values: [0.1, 0.01, 0.001, 0.0001]
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -39,7 +39,7 @@ Optimizer:
|
|||
values: [0.1, 0.01, 0.001, 0.0001]
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -39,7 +39,7 @@ Optimizer:
|
|||
values: [0.1, 0.01, 0.001, 0.0001]
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -39,7 +39,7 @@ Optimizer:
|
|||
values: [0.1, 0.01, 0.001, 0.0001]
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -39,7 +39,7 @@ Optimizer:
|
|||
learning_rate: 0.045
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -37,7 +37,7 @@ Optimizer:
|
|||
learning_rate: 0.045
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -37,7 +37,7 @@ Optimizer:
|
|||
learning_rate: 0.045
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -37,7 +37,7 @@ Optimizer:
|
|||
learning_rate: 0.045
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -37,7 +37,7 @@ Optimizer:
|
|||
learning_rate: 0.045
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -37,7 +37,7 @@ Optimizer:
|
|||
learning_rate: 0.045
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
# global configs
|
||||
Global:
|
||||
checkpoints: null
|
||||
pretrained_model: null
|
||||
output_dir: ./output/
|
||||
device: gpu
|
||||
save_interval: 1
|
||||
eval_during_train: True
|
||||
eval_interval: 1
|
||||
epochs: 240
|
||||
print_batch_step: 10
|
||||
use_visualdl: False
|
||||
# used for static mode and model export
|
||||
image_shape: [3, 224, 224]
|
||||
save_inference_dir: ./inference
|
||||
|
||||
# model architecture
|
||||
Arch:
|
||||
name: ShuffleNetV2_swish
|
||||
class_num: 1000
|
||||
|
||||
# loss function config for traing/eval process
|
||||
Loss:
|
||||
Train:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
Eval:
|
||||
- CELoss:
|
||||
weight: 1.0
|
||||
|
||||
|
||||
Optimizer:
|
||||
name: Momentum
|
||||
momentum: 0.9
|
||||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.5
|
||||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
DataLoader:
|
||||
Train:
|
||||
dataset:
|
||||
name: ImageNetDataset
|
||||
image_root: ./dataset/ILSVRC2012/
|
||||
cls_label_path: ./dataset/ILSVRC2012/train_list.txt
|
||||
transform_ops:
|
||||
- DecodeImage:
|
||||
to_rgb: True
|
||||
channel_first: False
|
||||
- RandCropImage:
|
||||
size: 224
|
||||
- RandFlipImage:
|
||||
flip_code: 1
|
||||
- NormalizeImage:
|
||||
scale: 1.0/255.0
|
||||
mean: [0.485, 0.456, 0.406]
|
||||
std: [0.229, 0.224, 0.225]
|
||||
order: ''
|
||||
|
||||
sampler:
|
||||
name: DistributedBatchSampler
|
||||
batch_size: 256
|
||||
drop_last: False
|
||||
shuffle: True
|
||||
loader:
|
||||
num_workers: 4
|
||||
use_shared_memory: True
|
||||
|
||||
Eval:
|
||||
dataset:
|
||||
name: ImageNetDataset
|
||||
image_root: ./dataset/ILSVRC2012/
|
||||
cls_label_path: ./dataset/ILSVRC2012/val_list.txt
|
||||
transform_ops:
|
||||
- DecodeImage:
|
||||
to_rgb: True
|
||||
channel_first: False
|
||||
- ResizeImage:
|
||||
resize_short: 256
|
||||
- CropImage:
|
||||
size: 224
|
||||
- NormalizeImage:
|
||||
scale: 1.0/255.0
|
||||
mean: [0.485, 0.456, 0.406]
|
||||
std: [0.229, 0.224, 0.225]
|
||||
order: ''
|
||||
sampler:
|
||||
name: DistributedBatchSampler
|
||||
batch_size: 64
|
||||
drop_last: False
|
||||
shuffle: False
|
||||
loader:
|
||||
num_workers: 4
|
||||
use_shared_memory: True
|
||||
|
||||
Infer:
|
||||
infer_imgs: docs/images/whl/demo.jpg
|
||||
batch_size: 10
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
to_rgb: True
|
||||
channel_first: False
|
||||
- ResizeImage:
|
||||
resize_short: 256
|
||||
- CropImage:
|
||||
size: 224
|
||||
- NormalizeImage:
|
||||
scale: 1.0/255.0
|
||||
mean: [0.485, 0.456, 0.406]
|
||||
std: [0.229, 0.224, 0.225]
|
||||
order: ''
|
||||
- ToCHWImage:
|
||||
PostProcess:
|
||||
name: Topk
|
||||
topk: 5
|
||||
class_id_map_file: ppcls/utils/imagenet1k_label_list.txt
|
||||
|
||||
Metric:
|
||||
Train:
|
||||
- TopkAcc:
|
||||
topk: [1, 5]
|
||||
Eval:
|
||||
- TopkAcc:
|
||||
topk: [1, 5]
|
|
@ -38,7 +38,7 @@ Optimizer:
|
|||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -38,7 +38,7 @@ Optimizer:
|
|||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -38,7 +38,7 @@ Optimizer:
|
|||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0003
|
||||
coeff: 0.00003
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -38,7 +38,7 @@ Optimizer:
|
|||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -38,7 +38,7 @@ Optimizer:
|
|||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -38,7 +38,7 @@ Optimizer:
|
|||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: 'L2'
|
||||
coeff: 0.0004
|
||||
coeff: 0.00004
|
||||
|
||||
|
||||
# data loader for train and eval
|
||||
|
|
|
@ -588,7 +588,7 @@ class Trainer(object):
|
|||
if len(batch) == 3:
|
||||
has_unique_id = True
|
||||
batch[2] = batch[2].reshape([-1, 1]).astype("int64")
|
||||
out = self.model(batch[0], batch[1])
|
||||
out = self.forward(batch)
|
||||
batch_feas = out["features"]
|
||||
|
||||
# do norm
|
||||
|
@ -653,7 +653,7 @@ class Trainer(object):
|
|||
image_file_list.append(image_file)
|
||||
if len(batch_data) >= batch_size or idx == len(image_list) - 1:
|
||||
batch_tensor = paddle.to_tensor(batch_data)
|
||||
out = self.model(batch_tensor)
|
||||
out = self.forward([batch_tensor])
|
||||
if isinstance(out, list):
|
||||
out = out[0]
|
||||
result = postprocess_func(out, image_file_list)
|
||||
|
|
|
@ -185,7 +185,7 @@ function func_inference(){
|
|||
elif [ ${use_gpu} = "True" ] || [ ${use_gpu} = "gpu" ]; then
|
||||
for use_trt in ${use_trt_list[*]}; do
|
||||
for precision in ${precision_list[*]}; do
|
||||
if [ ${precision} = "False" ] && [ ${use_trt} = "False" ]; then
|
||||
if [ ${precision} = "True" ] && [ ${use_trt} = "False" ]; then
|
||||
continue
|
||||
fi
|
||||
if [[ ${use_trt} = "False" || ${precision} =~ "int8" ]] && [ ${_flag_quant} = "True" ]; then
|
||||
|
|
Loading…
Reference in New Issue