add finetune doc
parent
e33baa2b7c
commit
1d3b8e71c9
|
@ -3,21 +3,26 @@ import numpy as np
|
|||
import os
|
||||
import sys
|
||||
|
||||
"""
|
||||
Usage: python generate_flower_list.py ./jpg train > train_list.txt
|
||||
python generate_flower_list.py ./jpg valid > val_list.txt
|
||||
"""
|
||||
""".mat files data format
|
||||
imagelabel.mat
|
||||
jpg_name 1 2 3 ...
|
||||
label 32 12 66 ...
|
||||
|
||||
setid.mat
|
||||
jpg_name(10 records in a class) 24 6 100 65 32 ...
|
||||
label 4 ...
|
||||
"""
|
||||
"""
|
||||
Usage:
|
||||
python generate_flower_list.py prefix_folder mode
|
||||
|
||||
python generate_flower_list.py jpg train > train_list.txt
|
||||
python generate_flower_list.py jpg valid > val_list.txt
|
||||
"""
|
||||
data_path = sys.argv[1]
|
||||
imagelabels_path='./imagelabels.mat'
|
||||
setid_path='./setid.mat'
|
||||
|
||||
"""
|
||||
imagelabel.mat
|
||||
jpg_name 1 2 3 ...
|
||||
label 32 12 66 ...
|
||||
"""
|
||||
labels = scipy.io.loadmat(imagelabels_path)
|
||||
labels = np.array(labels['labels'][0])
|
||||
setid = scipy.io.loadmat(setid_path)
|
||||
|
@ -27,13 +32,6 @@ d['train'] = np.array(setid['trnid'][0])
|
|||
d['valid'] = np.array(setid['valid'][0])
|
||||
d['test']=np.array(setid['tstid'][0])
|
||||
|
||||
"""
|
||||
setid.mat
|
||||
jpg_name 24 6 100 65 32 ...
|
||||
label 4 ...
|
||||
"""
|
||||
|
||||
|
||||
for id in d[sys.argv[2]]:
|
||||
message = str(data_path)+"/image_"+str(id).zfill(5)+" "+str(labels[id-1])
|
||||
message = str(data_path)+"/image_"+str(id).zfill(5)+".jpg "+str(labels[id-1])
|
||||
print(message)
|
|
@ -3,23 +3,25 @@
|
|||
---
|
||||
|
||||
## 1.简介
|
||||
PaddleClas支持ImageNet1000和Flower数据分类任务。
|
||||
本文档介绍ImageNet1k和Flower102数据准备过程。
|
||||
PaddleClas提供了丰富的预训练模型,支持的模型列表请参考[模型库](../models/models_intro.md)
|
||||
|
||||
## 2.数据集准备
|
||||
|
||||
数据集 | 训练集大小 | 测试集大小 | 类别数 | 备注|
|
||||
:------:|:---------------:|:---------------------:|:-----------:|:-----------:
|
||||
Flowers|1k | 6k | 102 |
|
||||
[ImageNet](http://www.image-net.org/challenges/LSVRC/2012/)|1.2M| 50k | 1000 |
|
||||
[Flower102](https://www.robots.ox.ac.uk/~vgg/data/flowers/102/)|1k | 6k | 102 |
|
||||
[ImageNet1k](http://www.image-net.org/challenges/LSVRC/2012/)|1.2M| 50k | 1000 |
|
||||
|
||||
数据格式
|
||||
PaddleClas加载PaddleClas/dataset/中的数据,通过指定data_dir和file_list来进行加载
|
||||
|
||||
PaddleClas加载PaddleClas/dataset/中的数据,请将下载后的数据按下面格式组织放置到PaddleClas/dataset/中。
|
||||
### ImageNet1k
|
||||
从官方下载数据后,按如下组织数据
|
||||
|
||||
```bash
|
||||
PaddleClas/dataset/imagenet
|
||||
|_ train
|
||||
PaddleClas/dataset/imagenet/
|
||||
|_ train/
|
||||
| |_ n01440764
|
||||
| | |_ n01440764_10026.JPEG
|
||||
| | |_ ...
|
||||
|
@ -28,29 +30,39 @@ PaddleClas/dataset/imagenet
|
|||
| |_ n15075141
|
||||
| |_ ...
|
||||
| |_ n15075141_9993.JPEG
|
||||
|_ val
|
||||
|_ val/
|
||||
| |_ ILSVRC2012_val_00000001.JPEG
|
||||
| |_ ...
|
||||
| |_ ILSVRC2012_val_00050000.JPEG
|
||||
|_ train_list.txt
|
||||
|_ val_list.txt
|
||||
```
|
||||
### Flower
|
||||
从VGG官方网站下载后的数据,解压后包括
|
||||
jpg/
|
||||
setid.mat
|
||||
imagelabels.mat
|
||||
将以上文件放置在PaddleClas/dataset/flower102/下
|
||||
|
||||
通过运行generate_flower_list.py生成train_list.txt和val_list.txt
|
||||
|
||||
```bash
|
||||
PaddleClas/dataset/flower
|
||||
|_ train
|
||||
python generate_flower_list.py jpg train > train_list.txt
|
||||
python generate_flower_list.py jpg valid > val_list.txt
|
||||
|
||||
```
|
||||
按照如下结构组织数据:
|
||||
|
||||
```bash
|
||||
PaddleClas/dataset/flower102/
|
||||
|_ jpg/
|
||||
| |_ image_03601.jpg
|
||||
| |_ ...
|
||||
| |_ image_07073.jpg
|
||||
|_ val
|
||||
| |_ image_04121.jpg
|
||||
| |_ ...
|
||||
| |_ image_02355.jpg
|
||||
|_ train_list.txt
|
||||
|_ val_list.txt
|
||||
```
|
||||
|
||||
|
||||
或是通过软链接将数据从实际地址链接到PaddleClas/dataset/下
|
||||
|
||||
```bash
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
# 模型微调
|
||||
|
||||
本文档将介绍如何使用PaddleClas进行模型微调(finetune)
|
||||
模型微调使用PaddleClas提供的预训练模型,可以节省从头训练的计算资源和时间,并提高准确率。
|
||||
|
||||
> 在使用ResNet50_vd_ssld蒸馏模型对flower102数据进行模型微调,仅需要3分钟(V100 单卡)top1即可达到94.96%
|
||||
|
||||
|
||||
模型微调大致包括如下四个步骤:
|
||||
- 初始化预训练模型
|
||||
- 剔除FC层
|
||||
- 更新参数
|
||||
- 新的训练策略
|
||||
|
||||
|
||||
## 初始化预训练模型
|
||||
|
||||
这里我们以ResNet50_vd和ResNet50_vd_ssld预训练模型对flower102数据集进行微调
|
||||
|
||||
ResNet50_vd: 在ImageNet1k数据集上训练 top1 acc:79.1% 模型详细信息参考[模型库](https://paddleclas.readthedocs.io/zh_CN/latest/models/ResNet_and_vd.html)
|
||||
|
||||
ResNet50_vd_ssld: 在ImageNet1k数据集训练的蒸馏模型 top1: 82.4% 模型详细信息参考[模型库](https://paddleclas.readthedocs.io/zh_CN/latest/models/ResNet_and_vd.html)
|
||||
|
||||
flower数据集相关信息参考[数据文档](data.md)
|
||||
|
||||
指定pretrained_model参数初始化预训练模型
|
||||
ResNet50_vd:
|
||||
|
||||
```bash
|
||||
python -m paddle.distributed.launch \
|
||||
--selected_gpus="0" \
|
||||
tools/train.py \
|
||||
-c ./configs/finetune/ResNet50_vd_finetune.yaml
|
||||
-o pretrained_model= ResNet50_vd预训练模型
|
||||
```
|
||||
|
||||
ResNet50_vd_ssld:
|
||||
|
||||
```bash
|
||||
python -m paddle.distributed.launch \
|
||||
--selected_gpus="0" \
|
||||
tools/train.py \
|
||||
-c ./configs/finetune/ResNet50_vd_ssld_finetune.yaml
|
||||
-o pretrained_model= ResNet50_vd_ssld预训练模型
|
||||
```
|
||||
|
||||
|
||||
##剔除FC层
|
||||
|
||||
由于新的数据集类别数(Flower102:102类)和ImgaeNet1k数据(1000类)不一致,一般需要对分类网络的最后FC层进行调整,PaddleClas默认剔除所有形状不一样的层
|
||||
|
||||
```python
|
||||
#excerpt from PaddleClas/ppcls/utils/save_load.py
|
||||
|
||||
def load_params(exe, prog, path):
|
||||
# ...
|
||||
|
||||
ignore_set = set()
|
||||
state = _load_state(path)
|
||||
|
||||
# 剔除预训练模型和模型间形状不一致的参数
|
||||
|
||||
all_var_shape = {}
|
||||
for block in prog.blocks:
|
||||
for param in block.all_parameters():
|
||||
all_var_shape[param.name] = param.shape
|
||||
ignore_set.update([
|
||||
name for name, shape in all_var_shape.items()
|
||||
if name in state and shape != state[name].shape
|
||||
])
|
||||
|
||||
# 用于迁移学习的代码段已被省略 ...
|
||||
|
||||
if len(ignore_set) > 0:
|
||||
for k in ignore_set:
|
||||
if k in state:
|
||||
# 剔除参数
|
||||
del state[k]
|
||||
fluid.io.set_program_state(prog, state)
|
||||
```
|
||||
在将shape不一致的层进行剔除正确加载预训练模型后,我们要选择需要更新的参数来让优化器进行参数更新。
|
||||
|
||||
## 更新参数
|
||||
|
||||
首先,分类网络中的卷积层大致可以分为
|
||||
|
||||
- ```浅层卷积层```:用于提取基础特征
|
||||
- ```深层卷积层```:用于提取抽象特征
|
||||
- ```FC层```:进行特征组合
|
||||
|
||||
其次,在衡量数据集大小差别和数据集的相似程度后,我们一般遵循如下的规则进行参数更新:
|
||||
|
||||
- 1. 新的数据集很小,在类别,具体种类上和原数据很像。由于新数据集很小,这里可能出现过拟合的问题;由于数据很像,可以认为预训练模型的深层特征仍然会起作用,只需要训练一个最终的```FC层```即可。
|
||||
- 2. 新的数据集很大,在类别,具体种类上和原数据很像。推荐训练网络中全部层的参数。
|
||||
- 3. 新的数据集很小但是和原数据不相像,可以冻结网络中初始层的参数更新```stop_gradient=True```,对较高层进行重新训练。
|
||||
- 4. 新的数据集很大但是和原数据不相像,这时候预训练模型可能不会生效,需要从头训练。
|
||||
|
||||
PaddleClas模型微调默认更新所有层参数。
|
||||
|
||||
## 新的训练策略
|
||||
|
||||
1. 学习率
|
||||
由于已经加载了预训练模型,对于从头训练的随机初始化参数来讲,模型中的参数已经具备了一定的分类能力,所以建议使用与从头训练相比更小的学习率,例如减小10倍。
|
||||
2. 类别数和总图片数调整为新数据集数据
|
||||
3. 调整训练轮数,由于不需要从头开始训练,一般相对减少模型微调的训练轮数
|
||||
|
||||
## 模型微调结果
|
||||
|
||||
在使用ResNet50_vd预训练模型对flower102数据进行模型微调后,top1 acc 达到 92.71%
|
||||
在使用ResNet50_vd_ssld预训练模型对flower102数据进行模型微调后,top1 acc 达到94.96%
|
|
@ -16,15 +16,17 @@ export PYTHONPATH=path_to_PaddleClas:$PYTHONPATH
|
|||
PaddleClas 提供模型训练与评估脚本:tools/train.py和tools/eval.py
|
||||
|
||||
### 2.1 模型训练
|
||||
以flower102数据为例按如下方式启动模型训练,flower数据集准备请参考[数据集准备](./data.md)
|
||||
|
||||
```bash
|
||||
# PaddleClas通过launch方式启动多卡多进程训练
|
||||
# 通过设置FLAGS_selected_gpus 指定GPU运行卡号
|
||||
|
||||
python -m paddle.distributed.launch \
|
||||
--selected_gpus="0,1,2,3" \
|
||||
--log_dir=log_ResNet50 \
|
||||
--log_dir=log_ResNet50_vd \
|
||||
tools/train.py \
|
||||
-c ./configs/ResNet/ResNet50.yaml
|
||||
-c ./configs/flower.yaml
|
||||
```
|
||||
|
||||
- 输出日志示例如下:
|
||||
|
@ -40,7 +42,7 @@ python -m paddle.distributed.launch \
|
|||
--selected_gpus="0,1,2,3" \
|
||||
--log_dir=log_ResNet50_vd \
|
||||
tools/train.py \
|
||||
-c ./configs/ResNet/ResNet50_vd.yaml \
|
||||
-c ./configs/flower.yaml \
|
||||
-o use_mix=1
|
||||
|
||||
```
|
||||
|
@ -54,18 +56,8 @@ epoch:0 train step:522 loss:1.6330 lr:0.100000 elapse:0.210
|
|||
或是直接修改模型对应的yaml配置文件,具体配置参数参考[配置文档](config.md)。
|
||||
|
||||
### 2.3 模型微调
|
||||
模型微调请参照[模型微调文档](./finetune.md)
|
||||
|
||||
您可以通过如下命令进行模型微调,通过指定--pretrained_model参数加载预训练模型
|
||||
|
||||
```bash
|
||||
python -m paddle.distributed.launch \
|
||||
--selected_gpus="0,1,2,3" \
|
||||
--log_dir=log_ResNet50_vd \
|
||||
train.py \
|
||||
-c ../configs/ResNet/ResNet50_vd.yaml \
|
||||
-o pretrained_model= 预训练模型路径\
|
||||
|
||||
```
|
||||
|
||||
### 2.2 模型评估
|
||||
|
||||
|
|
Loading…
Reference in New Issue