PaddleClas/docs/zh_CN/image_recognition_pipeline/feature_extraction.md

16 KiB
Raw Blame History

简体中文 | English

特征提取

目录

1. 摘要

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

2. 介绍

为了图像识别任务的灵活定制,我们将整个网络分为 Backbone、 Neck、 Head 以及 Loss 部分,整体结构如下图所示: 图中各个模块的功能为:

  • Backbone: 用于提取输入图像初步特征的骨干网络,一般由配置文件中的 Backbone 以及 BackboneStopLayer 字段共同指定。
  • Neck: 用以特征增强及特征维度变换。可以是一个简单的 FC Layer用来做特征维度变换也可以是较复杂的 FPN 结构,用以做特征增强,一般由配置文件中的 Neck 字段指定。
  • Head: 用来将 Neck 的输出 feature 转化为 logits让模型在训练阶段能以分类任务的形式进行训练。除了常用的 FC Layer 外,还可以替换为 CosMargin, ArcMargin, CircleMargin 等模块,一般由配置文件中的 Head 字段指定。
  • Loss: 指定所使用的 Loss 函数。我们将 Loss 设计为组合 loss 的形式,可以方便地将 Classification Loss 和 Metric learning Loss 组合在一起,一般由配置文件中的 Loss 字段指定。

3. 方法

3.1 Backbone

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

3.2 Neck

Neck 部分采用了 BN Neck,对 Backbone 抽取得到的特征的每个维度进行标准化操作,减少了同时优化度量学习损失和分类损失的难度。

3.3 Head

Head 部分选用 FC Layer,使用分类头将 feature 转换成 logits 供后续计算分类损失。

3.4 Loss

Loss 部分选用 Cross entropy lossTripletAngularMarginLoss,在训练时以分类损失和基于角度的三元组损失来指导网络进行优化。详细的配置文件见 GeneralRecognitionV2_PPLCNetV2_base.yaml

4. 实验部分

我们对原有的训练数据进行了合理扩充与优化,最终使用如下 16 个公开数据集的汇总:

数据集 数据量 类别数 场景 数据集地址
Aliproduct 2498771 50030 商品 地址
GLDv2 1580470 81313 地标 地址
VeRI-Wild 277797 30671 车辆 地址
LogoDet-3K 155427 3000 Logo 地址
SOP 59551 11318 商品 地址
Inshop 25882 3997 商品 地址
bird400 58388 400 鸟类 地址
104flows 12753 104 花类 地址
Cars 58315 112 车辆 地址
Fashion Product Images 44441 47 商品 地址
flowerrecognition 24123 59 花类 地址
food-101 101000 101 食物 地址
fruits-262 225639 262 水果 地址
inaturalist 265213 1010 自然 地址
indoor-scenes 15588 67 室内 地址
Products-10k 141931 9691 商品 地址
CompCars 16016 431 车辆 地址
Total 6M 192K - -

最终的模型精度指标如下表所示:

模型 Aliproduct VeRI-Wild LogoDet-3k iCartoonFace SOP Inshop
- recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%)
PP-ShiTuV2 84.2(83.3) 87.8(68.8) 88.0(63.2) 53.6(27.5) 77.6(55.3) 90.8(74.3)
模型 gldv2 imdb_face iNat instre sketch sop*
- recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%) recall@1%(mAP%)
PP-ShiTuV2 98.1(90.5) 35.9(11.2) 38.6(23.9) 87.7(71.4) 39.3(15.6) 98.3(90.9)
  • 预训练模型地址:general_PPLCNetV2_base_pretrained_v1.0.pdparams
  • 采用的评测指标为:Recall@1mAP
  • 速度评测机器的 CPU 具体信息为:Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
  • 速度指标的评测条件为: 开启 MKLDNN, 线程数设置为 10

5. 自定义特征提取

自定义特征提取,是指依据自己的任务,重新训练特征提取模型。

下面基于 GeneralRecognitionV2_PPLCNetV2_base.yaml 配置文件介绍主要的四个步骤1数据准备2模型训练3模型评估4模型推理

5.1 数据准备

首先需要基于任务定制自己的数据集。数据集格式与文件结构详见 数据集格式说明

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

  • 修改类别数:
    Head:
      name: FC
      embedding_size: *feat_dim
      class_num: 192612  # 此处表示类别数
      weight_attr:
        initializer:
          name: Normal
          std: 0.001
      bias_attr: False
    
  • 修改训练数据集配置:
    Train:
      dataset:
        name: ImageNetDataset
        image_root: ./dataset/     # 此处表示train数据集所在的目录
        cls_label_path: ./dataset/train_reg_all_data_v2.txt  # 此处表示train数据集对应标注文件的地址
        relabel: True
    
  • 修改评估数据集中query数据配置
    Query:
      dataset:
        name: VeriWild
        image_root: ./dataset/Aliproduct/    # 此处表示query数据集所在的目录
        cls_label_path: ./dataset/Aliproduct/val_list.txt    # 此处表示query数据集对应标注文件的地址
    
  • 修改评估数据集中gallery数据配置
    Gallery:
      dataset:
        name: VeriWild
        image_root: ./dataset/Aliproduct/    # 此处表示gallery数据集所在的目录
        cls_label_path: ./dataset/Aliproduct/val_list.txt   # 此处表示gallery数据集对应标注文件的地址
    

5.2 模型训练

模型训练主要包括启动训练和断点恢复训练的功能

  • 单机单卡训练
    export CUDA_VISIBLE_DEVICES=0
    python3.7 tools/train.py \
    -c ./ppcls/configs/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml
    
  • 单机多卡训练
    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/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml
    

注意: 配置文件中默认采用在线评估的方式,如果你想加快训练速度,可以关闭在线评估功能,只需要在上述命令的后面,增加 -o Global.eval_during_train=False

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

  • 单机单卡断点恢复训练
    export CUDA_VISIBLE_DEVICES=0
    python3.7 tools/train.py \
    -c ./ppcls/configs/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml \
    -o Global.checkpoint="output/RecModel/latest"
    
  • 单机多卡断点恢复训练
    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/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml \
    -o Global.checkpoint="output/RecModel/latest"
    

5.3 模型评估

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

  • 单卡评估

    export CUDA_VISIBLE_DEVICES=0
    python3.7 tools/eval.py \
    -c ./ppcls/configs/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml \
    -o Global.pretrained_model="output/RecModel/best_model"
    
  • 多卡评估

    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/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml \
    -o  Global.pretrained_model="output/RecModel/best_model"
    

注: 建议使用多卡评估。该方式可以利用多卡并行计算快速得到全部数据的特征,能够加速评估的过程。

5.4 模型推理

推理过程包括两个步骤: 1导出推理模型2模型推理以获取特征向量

5.4.1 导出推理模型

首先需要将 *.pdparams 模型文件转换成 inference 格式,转换命令如下。

python3.7 tools/export_model.py \
-c ./ppcls/configs/GeneralRecognitionV2/GeneralRecognitionV2_PPLCNetV2_base.yaml \
-o Global.pretrained_model="output/RecModel/best_model"

生成的推理模型默认位于 PaddleClas/inference 目录,里面包含三个文件,分别为 inference.pdmodelinference.pdiparamsinference.pdiparams.info。 其中inference.pdmodel 用来存储推理模型的结构, inference.pdiparamsinference.pdiparams.info 用来存储推理模型相关的参数信息。

5.4.2 获取特征向量

使用上一步转换得到的 inference 格式模型,将输入图片转换为对应的特征向量,推理命令如下。

cd deploy
python3.7 python/predict_rec.py \
-c configs/inference_rec.yaml \
-o Global.rec_inference_model_dir="../inference"

得到的特征输出格式如下所示:

wangzai.jpg:    [-7.82453567e-02  2.55877394e-02 -3.66694555e-02  1.34572461e-02
  4.39076796e-02 -2.34078392e-02 -9.49947070e-03  1.28221214e-02
  5.53947650e-02  1.01355985e-02 -1.06436480e-02  4.97181974e-02
 -2.21862812e-02 -1.75557341e-02  1.55848479e-02 -3.33278324e-03
 ...
 -3.40284109e-02  8.35561901e-02  2.10910216e-02 -3.27066667e-02]

在实际使用过程中,仅仅得到特征可能并不能满足业务需求。如果想进一步通过特征检索来进行图像识别,可以参照文档 向量检索

6. 总结

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

7. 参考文献

  1. PP-LCNet: A Lightweight CPU Convolutional Neural Network
  2. Bag of Tricks and A Strong Baseline for Deep Person Re-identification