# 模型训练流程

本文档基于开源数据集VOC0712训练person、car、dog三个类别的检测模型

## 准备VOC0712数据集

```shell
cd vnne_dev_tools
mkdir ./datasets
ln -s /path/to/your/VOCdevkit ./datasets/VOCdevkit
```


数据集存放结构如下

```
datasets/
  VOCdevkit/
    VOC2007/
      Annotations/
      ImageSets/
      JPEGImages/
      ...
    VOC2012/
      Annotations/
      ImageSets/
      JPEGImages/
      ...
```

## 参考[训练配置注释](training_params.md)调整训练参数


## 第一步 训练浮点模型

```shell
cd vnne_dev_tools
YOLOX_DATADIR="./datasets" python scripts/model_train.py --config configs.sa6920_npu_3classes_voc_float_600e_185k_trainset_rgb \
                                                                --devices 8 --batch-size 64 \
                                                                --ckpt checkpoint/SA6921/coco_pretrain_185k.pth
# 参数含义:
# config: 模型配置文件，定义模型结构、量化参数、后处理等
# devices: 模型训练使用GPU个数
# batch-size: 单卡batchsize 大小
# ckpt: 预训练模型路径
```


## 第二步 训练量化模型

量化模型需要浮点模型进行初始化，更改量化配置文件中的如下配置

```
    'float_pretrain': 'docs/training_sample_data/sa6920_npu_3classes_voc_float_600e_185k_rgb_best_ckpt.pth'
```

```shell
cd vnne_dev_tools
YOLOX_DATADIR="./datasets" python scripts/model_train.py --config configs.sa6920_npu_3classes_voc_quant_a8w8_120e_185k_trainset_fusebn_ranger_simple_rgb \
                                                                --devices 8 --batch-size 64 
# 参数含义:
# config: 模型配置文件，定义模型结构、量化参数、后处理等
# devices: 模型训练使用GPU个数
# batch-size: 单卡batchsize 大小
```

新增量化配置相比之前增加如下方法稳定量化训练：
1. 浮点模型量化前融合BN

```shell
    def get_model(self):
        model = YOLOXTrainer(**config['model_config'])
        model.apply(init_yolo)
        model.yolox.head0.initialized_params(1e-2)
        load_checkpoint(model, config['float_pretrain'])
        model.yolox = absorb_bn(model.yolox, min_var=1e-10)
        model_nobn = YOLOXTrainer(**config['model_config_nobn'])
        model_nobn.yolox.load_state_dict(model.yolox.state_dict())
        model = model_nobn
```

2. 使用ranger优化器

```
    def get_optimizer(self, batch_size):
        if "optimizer" not in self.__dict__:
            if self.warmup_epochs > 0:
                lr = self.warmup_lr
            else:
                lr = self.basic_lr_per_img * batch_size

            pg0, pg1, pg2 = [], [], []  # optimizer parameter groups

            for k, v in self.model.named_modules():
                if hasattr(v, "bias") and isinstance(v.bias, nn.Parameter):
                    pg2.append(v.bias)  # biases
                if isinstance(v, nn.BatchNorm2d):
                    pg0.append(v.weight)  # no decay
                elif hasattr(v, "weight") and isinstance(v.weight, nn.Parameter):
                    pg1.append(v.weight)  # apply decay

            optimizer = Ranger(
                pg1, lr=lr, weight_decay=self.weight_decay
            )
```

3. 更小学习率微调QAT

```
        # --------------  training config --------------------- #
        # epoch number used for warmup
        self.warmup_epochs = 0
        # max training epoch
        self.max_epoch = 600
        # minimum learning rate during warmup
        self.warmup_lr = 0
        self.min_lr_ratio = 0.05
        # learning rate for one image. During training, lr will multiply batchsize.
        self.basic_lr_per_img = 0.002 / 64.0
        # name of LRScheduler
        self.scheduler = "warmcos"
        # last #epoch to close augmention like mosaic
        self.no_aug_epochs = 400
        # apply EMA during training
        self.ema = False
```

## 示例配置训练结果

|Model| Params |size |Mean AP<sup>0.5 |AP<sup>0.5<br>person | AP<sup>0.5<br>car | AP<sup>0.5<br>dog |training log| weights |
| ------ | ------       |:---: | :---:    | :---:       |:---:     |:---:  | :---: | :----: |
|[voc_3classes_float_185k](../configs/sa6920_npu_3classes_voc_float_600e_185k_trainset_rgb.py) | 185k    |416  |53.85 |63.31      |56.98      |41.27 | [float_log](training_sample_data/sa6920_npu_3classes_voc_float_600e_185k_train_log.txt) | [float_ckpt](training_sample_data/sa6920_npu_3classes_voc_float_600e_185k_rgb_best_ckpt.pth) |
|[voc_3classes_185k_a8w4_fusebn_ranger](../configs/sa6920_npu_3classes_voc_quant_a8w8_120e_185k_trainset_fusebn_ranger_simple_rgb.py) | 185k    |416  |56.21 |65.42      |58.75    |44.46 |[qat_log](training_sample_data/sa6920_npu_3classes_voc_quant_a8w8_185k_fusebn_ranger_simple_rgb_train_log.txt)| [qat_ckpt](training_sample_data/sa6920_npu_3classes_voc_quant_a8w8_185k_fusebn_ranger_simple_rgb_best_ckpt.pth) |