feat: add the doc and demo about gallery2fc
add description doc and demo configpull/1714/head
parent
1020f41899
commit
4fc82eef5a
|
@ -2,7 +2,7 @@
|
|||
|
||||
本教程将介绍基于[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) 在移动端部署PaddleClas PP-ShiTu模型的详细步骤。
|
||||
|
||||
Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。
|
||||
Paddle Lite是飞桨轻量化推理引擎,为手机、IoT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。
|
||||
|
||||
## 1. 准备环境
|
||||
|
||||
|
@ -216,3 +216,6 @@ A1:如果已经走通了上述步骤,更换模型只需要替换 `.nb` 模
|
|||
|
||||
Q2:换一个图测试怎么做?
|
||||
A2:替换 deploy 下的测试图像为你想要测试的图像,并重新生成json配置文件(或者直接修改图像路径),使用 ADB 再次 push 到手机上即可。
|
||||
|
||||
Q3:如果需要更换模型/预训练模型/底库数据集,需要怎么做:
|
||||
A:请参考文档 [基于分类方法的 PP-Shitu 移动端部署方案说明](./gallery2fc.md)。
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# 识别模型转分类模型
|
||||
|
||||
PaddleClas 提供了 `gallery2fc.py` 工具,帮助大家将识别模型转为分类模型。
|
||||
|
||||
## 一、模型转换说明
|
||||
|
||||
### 1.1 准备底库数据、预训练模型
|
||||
|
||||
#### 1. 底库数据集
|
||||
|
||||
首先需要准备好底库数据,下面以 PaddleClas 提供饮料数据集(drink_dataset_v1.0)为例进行说明,饮料数据集获取方法:
|
||||
|
||||
```shell
|
||||
cd PaddleClas/
|
||||
wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/data/drink_dataset_v1.0.tar
|
||||
tar -xf drink_dataset_v1.0.tar
|
||||
```
|
||||
|
||||
饮料数据集的底库图片路径为 `drink_dataset_v1.0/gallery/`,底库图片列表可在 `drink_dataset_v1.0/gallery/drink_label.txt` 中查看,关于底库数据格式说明,请参考文档[数据集格式说明](../data_preparation/recognition_dataset.md#1-数据集格式说明)。
|
||||
|
||||
#### 2. 预训练模型
|
||||
|
||||
在开始转换模型前,需要准备好预训练模型,下面以量化后的 `general_PPLCNet_x2_5` 模型为例,下载预训练模型:
|
||||
|
||||
```shell
|
||||
cd PaddleClas/pretrained/
|
||||
wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/general_PPLCNet_x2_5_pretrained_v1.0_quant.pdparams
|
||||
```
|
||||
|
||||
### 1.2 准备配置文件
|
||||
|
||||
在进行模型转换时,需要通过配置文件定义所需参数,本例中所用配置文件为 `ppcls/configs/GeneralRecognition/Gallery2FC_PPLCNet_x2_5.yaml`,对于配置文件字段的说明,如下所示:
|
||||
|
||||
* Global:
|
||||
* pretrained_model: 预训练模型路径,无需包含 `.pdparams` 后缀名;
|
||||
* image_shape: 模型输入数据尺寸,无需包含 batch size 维度;
|
||||
* save_inference_dir: 转换后模型的保存路径;
|
||||
* Arch: 模型结构相关定义,可参考 [配置说明](../models_training/config_description.md#3-%E8%AF%86%E5%88%AB%E6%A8%A1%E5%9E%8B);
|
||||
* IndexProcess: 底库数据集相关定义
|
||||
* image_root: 底库数据集路径;
|
||||
* data_file: 底库数据集列表文件路径;
|
||||
|
||||
### 1.3 转换特征提取模型
|
||||
|
||||
在完成上述准备工作后,即可进行模型转换,命令如下所示:
|
||||
|
||||
```python
|
||||
python ppcls/utils/gallery2fc.py -c ppcls/configs/GeneralRecognition/Gallery2FC_PPLCNet_x2_5.yaml
|
||||
```
|
||||
|
||||
在上述命令执行完成后,转换并导出的模型保存在目录 `./inference/general_PPLCNet_x2_5_quant/` 下。在推理部署时,需要注意的是,模型的输出结果通常有多个,应选取分类结果作为模型输出,需要注意区分。
|
|
@ -0,0 +1,51 @@
|
|||
# global configs
|
||||
Global:
|
||||
pretrained_model: ./pretrained/general_PPLCNet_x2_5_pretrained_v1.0_quant
|
||||
# used for static mode and model export
|
||||
image_shape: [3, 224, 224]
|
||||
save_inference_dir: ./inference/general_PPLCNet_x2_5_quant/inference
|
||||
|
||||
# for quantizaiton or prune model
|
||||
Slim:
|
||||
## for prune
|
||||
quant:
|
||||
name: pact
|
||||
|
||||
# model architecture
|
||||
Arch:
|
||||
name: RecModel
|
||||
|
||||
Backbone:
|
||||
name: PPLCNet_x2_5
|
||||
pretrained: False
|
||||
use_ssld: True
|
||||
BackboneStopLayer:
|
||||
name: "flatten"
|
||||
Neck:
|
||||
name: FC
|
||||
embedding_size: 1280
|
||||
class_num: 512
|
||||
Head:
|
||||
name: ArcMargin
|
||||
embedding_size: 512
|
||||
class_num: 185341
|
||||
margin: 0.2
|
||||
scale: 30
|
||||
|
||||
# indexing engine config
|
||||
IndexProcess:
|
||||
image_root: "./drink_dataset_v1.0/gallery/"
|
||||
data_file: "./drink_dataset_v1.0/gallery/drink_label.txt"
|
||||
delimiter: "\t"
|
||||
batch_size: 2
|
||||
transform_ops:
|
||||
- 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:
|
|
@ -12,10 +12,14 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import paddle
|
||||
import cv2
|
||||
|
||||
import os
|
||||
import sys
|
||||
__dir__ = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(os.path.abspath(os.path.join(__dir__, '../../')))
|
||||
|
||||
from ppcls.arch import build_model
|
||||
from ppcls.utils.config import parse_config, parse_args
|
||||
from ppcls.utils.save_load import load_dygraph_pretrain
|
||||
|
@ -51,12 +55,17 @@ class GalleryLayer(paddle.nn.Layer):
|
|||
self.gallery_images.append(image_file)
|
||||
gallery_docs.append(ori_line.strip())
|
||||
gallery_labels.append(line[1].strip())
|
||||
self.gallery_layer = paddle.nn.Linear(embedding_size, len(self.gallery_images), bias_attr=False)
|
||||
self.gallery_layer = paddle.nn.Linear(
|
||||
embedding_size, len(self.gallery_images), bias_attr=False)
|
||||
self.gallery_layer.skip_quant = True
|
||||
output_label_str = ""
|
||||
for i, label_i in enumerate(gallery_labels):
|
||||
output_label_str += "{} {}\n".format(i, label_i)
|
||||
output_path = configs["Global"]["save_inference_dir"] + "_label.txt"
|
||||
|
||||
save_dir = os.path.dirname(configs["Global"]["save_inference_dir"])
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
with open(output_path, "w") as f:
|
||||
f.write(output_label_str)
|
||||
|
||||
|
@ -71,19 +80,23 @@ class GalleryLayer(paddle.nn.Layer):
|
|||
embedding_size = self.configs["Arch"]["Head"]["embedding_size"]
|
||||
batch_index = 0
|
||||
input_tensor = paddle.zeros(self.image_shape)
|
||||
gallery_feature = paddle.zeros((len(self.gallery_images), embedding_size))
|
||||
gallery_feature = paddle.zeros(
|
||||
(len(self.gallery_images), embedding_size))
|
||||
for i, image_path in enumerate(self.gallery_images):
|
||||
image = cv2.imread(image_path)[:, :, ::-1]
|
||||
for op in preprocess_ops:
|
||||
image = op(image)
|
||||
input_tensor[batch_index] = image
|
||||
batch_index += 1
|
||||
if batch_index == self.batch_size or i == len(self.gallery_images) - 1:
|
||||
if batch_index == self.batch_size or i == len(
|
||||
self.gallery_images) - 1:
|
||||
batch_feature = feature_extractor(input_tensor)["features"]
|
||||
for j in range(batch_index):
|
||||
feature = batch_feature[j]
|
||||
norm_feature = paddle.nn.functional.normalize(feature, axis=0)
|
||||
norm_feature = paddle.nn.functional.normalize(
|
||||
feature, axis=0)
|
||||
gallery_feature[i - batch_index + j + 1] = norm_feature
|
||||
batch_index = 0
|
||||
self.gallery_layer.set_state_dict({"_layer.weight": gallery_feature.T})
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue