feature_extraction.md 12.4 KB
Newer Older
H
HydrogenSulfate 已提交
1
简体中文|[English](../../en/image_recognition_pipeline/feature_extraction_en.md)
S
stephon 已提交
2
# 特征提取
S
sibo2rr 已提交
3 4 5

## 目录

H
HydrogenSulfate 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
- [1. 摘要](#1-摘要)
- [2. 介绍](#2-介绍)
- [3. 方法](#3-方法)
  - [3.1 Backbone](#31-backbone)
  - [3.2 Neck](#32-neck)
  - [3.3 Head](#33-head)
  - [3.4 Loss](#34-loss)
- [4. 实验部分](#4-实验部分)
- [5. 自定义特征提取](#5-自定义特征提取)
  - [5.1 数据准备](#51-数据准备)
  - [5.2 模型训练](#52-模型训练)
  - [5.3 模型评估](#53-模型评估)
  - [5.4 模型推理](#54-模型推理)
    - [5.4.1 导出推理模型](#541-导出推理模型)
    - [5.4.2 获取特征向量](#542-获取特征向量)
- [6. 总结](#6-总结)
- [7. 参考文献](#7-参考文献)
S
sibo2rr 已提交
23

S
stephon 已提交
24
<a name="1"></a>
S
sibo2rr 已提交
25

H
HydrogenSulfate 已提交
26
## 1. 摘要
S
sibo2rr 已提交
27

H
HydrogenSulfate 已提交
28
特征提取是图像识别中的关键一环,它的作用是将输入的图片转化为固定维度的特征向量,用于后续的[向量检索](./vector_search.md)。一个好的特征需要具备“相似度保持性”,即相似度高的图片对,其特征的相似度也比较高(特征空间中的距离比较近),相似度低的图片对,其特征相似度要比较低(特征空间中的距离比较远)。为此[Deep Metric Learning](../algorithm_introduction/metric_learning.md)领域内提出了不少方法用以研究如何通过深度学习来获得具有强表征能力的特征。
S
sibo2rr 已提交
29

S
stephon 已提交
30
<a name="2"></a>
S
stephon 已提交
31

H
HydrogenSulfate 已提交
32 33
## 2. 介绍

S
sibo2rr 已提交
34
为了图像识别任务的灵活定制,我们将整个网络分为 Backbone、 Neck、 Head 以及 Loss 部分,整体结构如下图所示:
S
stephon 已提交
35
![](../../images/feature_extraction_framework.png)
B
Bin Lu 已提交
36
图中各个模块的功能为:
S
sibo2rr 已提交
37

H
HydrogenSulfate 已提交
38 39
- **Backbone**: 用于提取输入图像初步特征的骨干网络,一般由配置文件中的 [`Backbone`](../../../ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml#L26-L29) 以及 [`BackboneStopLayer`](../../../ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml#L30-L31) 字段共同指定。
- **Neck**: 用以特征增强及特征维度变换。可以是一个简单的 FC Layer,用来做特征维度变换;也可以是较复杂的 FPN 结构,用以做特征增强,一般由配置文件中的 [`Neck`](../../../ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml#L32-L35)字段指定。
H
debug  
HydrogenSulfate 已提交
40 41
- **Head**: 用来将 feature 转化为 logits,让模型在训练阶段能以分类任务的形式进行训练。除了常用的 FC Layer 外,还可以替换为 cosmargin, arcmargin, circlemargin 等模块,一般由配置文件中的 [`Head`](../../../ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml#L36-L41)字段指定。
- **Loss**: 指定所使用的 Loss 函数。我们将 Loss 设计为组合 loss 的形式,可以方便地将 Classification Loss 和 Metric learning Loss 组合在一起,一般由配置文件中的 [`Loss`](../../../ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml#L44-L50)字段指定。
S
sibo2rr 已提交
42

S
stephon 已提交
43
<a name="3"></a>
S
stephon 已提交
44

H
HydrogenSulfate 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57
## 3. 方法

### 3.1 Backbone

Backbone 部分采用了 [PP_LCNet_x2_5](../models/PP-LCNet.md),其针对Intel CPU端的性能优化探索了多个有效的结构设计方案,最终实现了在不增加推理时间的情况下,进一步提升模型的性能,最终大幅度超越现有的 SOTA 模型。

### 3.2 Neck

Neck 部分采用了 [FC Layer](../../../ppcls/arch/gears/fc.py),对 Backbone 抽取得到的特征进行降维,减少了特征存储的成本与计算量。

### 3.3 Head

Head 部分选用 [ArcMargin](../../../ppcls/arch/gears/arcmargin.py),在训练时通过指定margin,增大同类特征之间的角度差异再进行分类,进一步提升抽取特征的表征能力。
S
sibo2rr 已提交
58

H
HydrogenSulfate 已提交
59
### 3.4 Loss
S
sibo2rr 已提交
60

H
HydrogenSulfate 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
Loss 部分选用 [Cross entropy loss](../../../ppcls/loss/celoss.py),在训练时以分类任务的损失函数来指导网络进行优化。详细的配置文件见[通用识别配置文件](../../../ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml)

<a name="4"></a>

## 4. 实验部分

训练数据为如下 7 个公开数据集的汇总:

|    数据集    | 数据量  |  类别数  |   场景   |                                  数据集地址                                  |
| :----------: | :-----: | :------: | :------: | :--------------------------------------------------------------------------: |
|  Aliproduct  | 2498771 |  50030   |   商品   |  [地址](https://retailvisionworkshop.github.io/recognition_challenge_2020/)  |
|    GLDv2     | 1580470 |  81313   |   地标   |           [地址](https://github.com/cvdfoundation/google-landmark)           |
|  VeRI-Wild   | 277797  |  30671   |   车辆   |                [地址](https://github.com/PKU-IMRE/VERI-Wild)                 |
|  LogoDet-3K  | 155427  |   3000   |   Logo   |          [地址](https://github.com/Wangjing1551/LogoDet-3K-Dataset)          |
| iCartoonFace | 389678  |   5013   | 动漫人物 | [地址](http://challenge.ai.iqiyi.com/detail?raceId=5def69ace9fcf68aef76a75d) |
|     SOP      |  59551  |  11318   |   商品   |          [地址](https://cvgl.stanford.edu/projects/lifted_struct/)           |
|    Inshop    |  25882  |   3997   |   商品   |        [地址](http://mmlab.ie.cuhk.edu.hk/projects/DeepFashion.html)         |
|  **Total**   | **5M**  | **185K** |   ----   |                                     ----                                     |
S
stephon 已提交
79

S
stephon 已提交
80
最终的模型效果如下表所示:
S
sibo2rr 已提交
81

H
HydrogenSulfate 已提交
82 83 84
|              模型               | Aliproduct | VeRI-Wild | LogoDet-3K | iCartoonFace |  SOP  | Inshop | Latency(ms) |
| :-----------------------------: | :--------: | :-------: | :--------: | :----------: | :---: | :----: | :---------: |
| GeneralRecognition_PPLCNet_x2_5 |   0.839    |   0.888   |   0.861    |    0.841     | 0.793 | 0.892  |     5.0     |
S
sibo2rr 已提交
85

H
HydrogenSulfate 已提交
86
* 预训练模型地址:[通用识别预训练模型](https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/rec/models/pretrain/general_PPLCNet_x2_5_pretrained_v1.0.pdparams)
B
Bin Lu 已提交
87
* 采用的评测指标为:`Recall@1`
S
sibo2rr 已提交
88
* 速度评测机器的 CPU 具体信息为:`Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz`
S
sibo2rr 已提交
89
* 速度指标的评测条件为: 开启 MKLDNN, 线程数设置为 10
S
stephon 已提交
90

H
HydrogenSulfate 已提交
91
<a name="5"></a>
S
sibo2rr 已提交
92

H
HydrogenSulfate 已提交
93
## 5. 自定义特征提取
S
sibo2rr 已提交
94

H
HydrogenSulfate 已提交
95
自定义特征提取,是指依据自己的任务,重新训练特征提取模型。
S
sibo2rr 已提交
96

H
HydrogenSulfate 已提交
97
下面基于`GeneralRecognition_PPLCNet_x2_5.yaml`配置文件,介绍主要的四个步骤:1)数据准备;2)模型训练;3)模型评估;4)模型推理
S
sibo2rr 已提交
98 99


H
HydrogenSulfate 已提交
100
<a name="5.1"></a>
B
Bin Lu 已提交
101

H
HydrogenSulfate 已提交
102
### 5.1 数据准备
S
sibo2rr 已提交
103

H
HydrogenSulfate 已提交
104
首先需要基于任务定制自己的数据集。数据集格式与文件结构详见[数据集格式说明](../data_preparation/recognition_dataset.md)
S
sibo2rr 已提交
105

H
HydrogenSulfate 已提交
106
准备完毕之后还需要在配置文件中修改数据配置相关的内容, 主要包括数据集的地址以及类别数量。对应到配置文件中的位置如下所示:
S
stephon 已提交
107

H
HydrogenSulfate 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
- 修改类别数:
  ```yaml
    Head:
      name: ArcMargin
      embedding_size: 512
      class_num: 185341    # 此处表示类别数
  ```
- 修改训练数据集配置:
  ```yaml
    Train:
      dataset:
        name: ImageNetDataset
        image_root: ./dataset/     # 此处表示train数据所在的目录
        cls_label_path: ./dataset/train_reg_all_data.txt  # 此处表示train数据集label文件的地址
  ```
- 修改评估数据集中query数据配置:
  ```yaml
      Query:
        dataset:
          name: VeriWild
          image_root: ./dataset/Aliproduct/    # 此处表示query数据集所在的目录
          cls_label_path: ./dataset/Aliproduct/val_list.txt    # 此处表示query数据集label文件的地址
  ```
- 修改评估数据集中gallery数据配置:
  ```yaml
      Gallery:
        dataset:
          name: VeriWild
          image_root: ./dataset/Aliproduct/    # 此处表示gallery数据集所在的目录
          cls_label_path: ./dataset/Aliproduct/val_list.txt   # 此处表示gallery数据集label文件的地址
  ```

<a name="5.2"></a>

### 5.2 模型训练

模型训练主要包括启动训练和断点恢复训练的功能
S
sibo2rr 已提交
145

H
HydrogenSulfate 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
- 单机单卡训练
  ```shell
  export CUDA_VISIBLE_DEVICES=0
  python3.7 tools/train.py \
  -c ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml
  ```
- 单机多卡训练
  ```shell
  export CUDA_VISIBLE_DEVICES=0,1,2,3
  python3.7 -m paddle.distributed.launch \
  --gpus="0,1,2,3" tools/train.py \
  -c ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml
  ```
**注意:**
配置文件中默认采用`在线评估`的方式,如果你想加快训练速度,可以关闭`在线评估`功能,只需要在上述命令的后面,增加 `-o Global.eval_during_train=False`

训练完毕后,在 output 目录下会生成最终模型文件 `latest.pdparams``best_model.pdarams` 和训练日志文件 `train.log`。其中,`best_model` 保存了当前评测指标下的最佳模型,`latest` 用来保存最新生成的模型, 方便在任务中断的情况下从断点位置恢复训练。通过在上述训练命令的末尾加上`-o Global.checkpoint="path_to_resume_checkpoint"`即可从断点恢复训练,示例如下。

- 单机单卡断点恢复训练
  ```shell
  export CUDA_VISIBLE_DEVICES=0
  python3.7 tools/train.py \
  -c ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml \
  -o Global.checkpoint="output/RecModel/latest"
  ```
- 单机多卡断点恢复训练
  ```shell
  export CUDA_VISIBLE_DEVICES=0,1,2,3
  python3.7 -m paddle.distributed.launch \
  --gpus="0,1,2,3" tools/train.py \
  -c ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml \
  -o Global.checkpoint="output/RecModel/latest"
  ```

<a name="5.3"></a>

### 5.3 模型评估

除了训练过程中对模型进行的在线评估,也可以手动启动评估程序来获得指定的模型的精度指标。
S
sibo2rr 已提交
185

B
Bin Lu 已提交
186
- 单卡评估
H
HydrogenSulfate 已提交
187 188 189 190 191 192
  ```shell
  export CUDA_VISIBLE_DEVICES=0
  python3.7 tools/eval.py \
  -c ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml \
  -o Global.pretrained_model="output/RecModel/best_model"
  ```
S
stephon 已提交
193

B
Bin Lu 已提交
194
- 多卡评估
H
HydrogenSulfate 已提交
195 196 197 198 199 200 201 202
  ```shell
  export CUDA_VISIBLE_DEVICES=0,1,2,3
  python3.7 -m paddle.distributed.launch \
  --gpus="0,1,2,3" tools/eval.py \
  -c  ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml \
  -o  Global.pretrained_model="output/RecModel/best_model"
  ```
**注:** 建议使用多卡评估。该方式可以利用多卡并行计算快速得到全部数据的特征,能够加速评估的过程。
S
stephon 已提交
203

H
HydrogenSulfate 已提交
204
<a name="5.4"></a>
S
sibo2rr 已提交
205

H
HydrogenSulfate 已提交
206
### 5.4 模型推理
S
sibo2rr 已提交
207

H
HydrogenSulfate 已提交
208
推理过程包括两个步骤: 1)导出推理模型;2)模型推理以获取特征向量
S
sibo2rr 已提交
209

H
HydrogenSulfate 已提交
210
#### 5.4.1 导出推理模型
S
sibo2rr 已提交
211

H
HydrogenSulfate 已提交
212 213 214
首先需要将 `*.pdparams` 模型文件转换成 inference 格式,转换命令如下。
```shell
python3.7 tools/export_model.py \
B
Bin Lu 已提交
215 216
-c ppcls/configs/GeneralRecognition/GeneralRecognition_PPLCNet_x2_5.yaml \
-o Global.pretrained_model="output/RecModel/best_model"
S
stephon 已提交
217
```
H
HydrogenSulfate 已提交
218 219
生成的推理模型默认位于 `PaddleClas/inference` 目录,里面包含三个文件,分别为 `inference.pdmodel``inference.pdiparams``inference.pdiparams.info`
其中`inference.pdmodel` 用来存储推理模型的结构, `inference.pdiparams``inference.pdiparams.info` 用来存储推理模型相关的参数信息。
S
sibo2rr 已提交
220

H
HydrogenSulfate 已提交
221
#### 5.4.2 获取特征向量
S
sibo2rr 已提交
222

H
HydrogenSulfate 已提交
223
使用上一步转换得到的 inference 格式模型,将输入图片转换为对应的特征向量,推理命令如下。
S
sibo2rr 已提交
224

H
HydrogenSulfate 已提交
225
```shell
S
stephon 已提交
226
cd deploy
H
HydrogenSulfate 已提交
227
python3.7 python/predict_rec.py \
B
Bin Lu 已提交
228 229
-c configs/inference_rec.yaml \
-o Global.rec_inference_model_dir="../inference"
B
Bin Lu 已提交
230
```
B
Bin Lu 已提交
231
得到的特征输出格式如下图所示:
B
Bin Lu 已提交
232
![](../../images/feature_extraction_output.png)
B
Bin Lu 已提交
233

H
HydrogenSulfate 已提交
234 235 236 237 238 239 240 241 242 243 244 245 246 247
在实际使用过程中,仅仅得到特征可能并不能满足业务需求。如果想进一步通过特征检索来进行图像识别,可以参照文档[向量检索](./vector_search.md)

<a name="6"></a>

## 6. 总结

特征提取模块作为图像识别中的关键一环,在网络结构的设计,损失函数的选取上有很大的改进空间。不同的数据集类型有各自不同的特点,如行人重识别、商品识别、人脸识别数据集的分布、图片内容都不尽相同。学术界根据这些特点提出了各种各样的方法,如PCB、MGN、ArcFace、CircleLoss、TripletLoss等,围绕的还是增大类间差异、减少类内差异的最终目标,从而有效地应对各种真实场景数据。

<a name="7"></a>

## 7. 参考文献

1. [PP-LCNet: A Lightweight CPU Convolutional Neural Network](https://arxiv.org/pdf/2109.15099.pdf)
2. [ArcFace: Additive Angular Margin Loss for Deep Face Recognition](https://arxiv.org/abs/1801.07698)