From ec45b7798598201b3cefa519ffc5ad29851a071d Mon Sep 17 00:00:00 2001 From: yepei6 Date: Mon, 24 Aug 2020 22:01:35 +0800 Subject: [PATCH 1/3] add tutorials/source_zh_cn/mobilenetv2_finetune.md. --- .../advanced_use/mobilenetv2_finetune.md | 449 ++++++++++++++++++ 1 file changed, 449 insertions(+) create mode 100644 tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md diff --git a/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md b/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md new file mode 100644 index 0000000000..ba59537b06 --- /dev/null +++ b/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md @@ -0,0 +1,449 @@ +#
MobileNetV2 增量学习
+ +`CPU` `Ascend` `GPU` `模型开发` `中级` `高级` + + + +- [增量学习](#增量学习)- [概述](#概述) + - [任务描述及准备](#任务描述及准备) + - [环境配置](#环境配置) + - [克隆代码](#克隆代码) + - [准备预训练模型](#准备预训练模型) + - [准备数据](#准备数据) + - [预训练模型加载代码详解](#预训练模型加载代码详解) + - [训练参数简介](#训练参数简介) + - [加载训练](#加载训练) + - [开始增量训练](#开始增量训练) + - [调整节点数量](#调整节点数量) + - [训练结果](#训练结果) + - [验证增量训练模型](#验证增量训练模型) + - [验证结果](#验证结果) + + +   + +## 概述 + +计算机视觉任务中,从头开始训练一个网络耗时巨大,需要大量计算能力。预训练模型选择的常见的OpenImage、ImageNet、VOC、COCO等公开大型数据集,规模达到几十万甚至超过上百万张。大部分任务数据规模较大,训练网络模型时,如果不使用预训练模型,从头开始训练网络,需要消耗大量的时间与计算能力,模型容易陷入局部极小值和过拟合。因此大部分任务都会选择预训练模型,在其上做增量学习。 + +MindSpore是一个多元化的机器学习框架。既可以在手机等端侧和PC等设备上运行,也可以在云上的服务器集群上运行。目前MobileNetV2支持在windows系统中使用单核CPU做增量学习,在Euler系统中使用单个或者多个Ascend AI处理器和GPU中做增量学习,本教程将会介绍如何在不同系统与处理器下的MindSpore框架中做增量学习。 + +## 任务描述及准备 + +### 环境配置 + +若在华为云环境上运行,不需要安装MindSpore框架和配置Ascend AI处理器,可以跳过本小节。若在本地环境运行,需要安装MindSpore框架,配置CPU、Ascend AI处理器或GPU。 + +1. 安装MindSpore框架 + 在Euler、Ubuntu或者Windows等系统上需要系统和处理器架构[安装对应版本MindSporo框架](https://www.mindspore.cn/install)。 + +2. 配置CPU环境 + CPU环境只需按照系统和处理器架构暗安装对应版本的MinsSpore框架,无需其他特殊的配置。 + +3. 配置Ascend环境 + 以Ascend 910 AI处理器为例,1个8个处理器环境的json配置文件`hccl_config.json`示例如下。单/多处理器环境可以根据以下示例调整`"server_count"`与`device`: + + ```json + { + "version": "1.0", + "server_count": "1", + "server_list": [ + { + "server_id": "10.155.111.140", + "device": [ + {"device_id": "0","device_ip": "192.1.27.6","rank_id": "0"}, + {"device_id": "1","device_ip": "192.2.27.6","rank_id": "1"}, + {"device_id": "2","device_ip": "192.3.27.6","rank_id": "2"}, + {"device_id": "3","device_ip": "192.4.27.6","rank_id": "3"}, + {"device_id": "4","device_ip": "192.1.27.7","rank_id": "4"}, + {"device_id": "5","device_ip": "192.2.27.7","rank_id": "5"}, + {"device_id": "6","device_ip": "192.3.27.7","rank_id": "6"}, + {"device_id": "7","device_ip": "192.4.27.7","rank_id": "7"}], + "host_nic_ip": "reserve" + } + ], + "status": "completed" + } + ``` + + 使用Ascend AI处理器时,在代码中,需要在调用Ascend AI处理器开始训练或测试前,按照如下代码设置: + + ```python + import os + from mindspore import context + from mindspore.communication.management import init + + if __name__ == "__main__": + context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=int(os.environ["DEVICE_ID"])) + init() + ... + ``` + +4. 配置GPU环境 + 使用GPU时,在代码中,需要在调用GPU开始训练或测试前,按照如下代码设置: + + ```python + from mindspore import context + from mindspore.communication.management import init + + if __name__ == "__main__": + context.set_context(mode=context.GRAPH_MODE, device_target="GPU") + init("nccl") + ... + ``` + +### 克隆代码 + +CPU代码: + +```bash + +``` + +GPU与Ascend AI处理器代码: +在Gitee中克隆[MindSpore开源项目仓库](https://gitee.com/mindspore/mindspore.git),进入`./model_zoo/official/cv/mobilenetv2/`。 + +```bash +git clone git@gitee.com:/mindspore.git +cd ./mindspore/model_zoo/official/cv/mobilenetv2 +``` + +使用CPU进行增量训练时,运行`finetune.py`,使用训练好的模型进行验证与测试时,运行`finetune_eval.py`。 + +CPU代码结构如下: + +```python + ├── MobileNetV2 + ├── Readme.md # descriptions about MobileNetV2 + ├── src + │ ├──config.py # parameter configuration + │ ├──dataset.py # creating dataset + │ ├──launch.py # start python script + │ ├──lr_generator.py # learning rate config + │ ├──mobilenetV2.py # MobileNetV2 architecture + ├── finetune.py # finetune script + ├── finetune_eval.py # finetune eval script + ├── tools + │ ├──flatten_dir.py # script for private dataset process +``` + +使用GPU与Ascend AI处理器训练时,运行`run_train.sh`,该文件会将运行`launch.py`并且将参数传入`launch.py`, `launch.py`根据分配的Ascend AI处理器或GPU数量,启动多个进程运行`train.py`,每一个进程分配对应的一个处理器。 + +GPU与Ascend AI处理器代码结构如下: + +```python + ├── MobileNetV2 + ├── Readme.md # descriptions about MobileNetV2 + ├── scripts + │ ├──run_train.sh # shell script for train with Ascend or GPU + │ ├──run_eval.sh # shell script for evaluation with Ascend or GPU + ├── src + │ ├──config.py # parameter configuration + │ ├──dataset.py # creating dataset + │ ├──launch.py # start python script + │ ├──lr_generator.py # learning rate config + │ ├──mobilenetV2.py # MobileNetV2 architecture + │ ├──net_utils.py # net utils to load ckpt_file for fine tune or incremental learn + ├── train.py # training script + ├── eval.py # evaluation script +``` + +### 准备预训练模型 + +[下载预训练模型](https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite/mobilenetV2.ckpt)到以下目录: +`./pretrain_checkpoint/[pretrain_checkpoint_file]` + +```python +mkdir pretrain_checkpoint +wget -P ./pretrain_checkpoint https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite/mobilenetV2.ckpt +``` + +### 准备数据 + +准备ImageFolder格式管理的数据集,并且在运行`run_train.sh`时加入`[dataset_path]`参数: + +数据集结构如下: + + └─ImageFolder + ├─train + │ ├─class1Folder + │ ├─class2Folder + │ └─...... + └─eval + ├─class1Folder + ├─class2Folder + └─...... + +## 预训练模型加载代码详解 + +在增量学习时,需要加载预训练模型。不同数据集和任务中特征提取层(卷积层)分布趋于一致,但是特征向量的组合(全连接层)不相同,分类数量(全连接层output_size)通常也不一致。在增量学习时,只加载特征提取层参数,抛弃全连接层参数不加载。 + +### CPU加载模型 + +在增量学习时,构建只有特征提取层,没有全连接层的MobileNetV2,将经过预训练的模型参数权重加载入上述网络。另外构建一个只包含全局平均池化与全连接层的Head网络。在训练时,使用MobileNetV2提取的特征单独训练Head网络。 + +- 构建`MobileNetV2`特征提取网络(只有特征提取,不包括全连接层): + + ```python + class MobileNetV2(nn.Cell): + ... + def construct(self, x): + x = self.features(x) + return x + ... + ``` + +- 加载模型参数权重: + + ```python + net = MoblileNetV2(platform=args_ppt.platform) + if args_opt.pre_trained: + param_dict = load_checkpoint(args_opt.pre_trained) + load_param_into_net(net,param_dict) + ``` + +- 构建head网络: + + ```python + net = Head(last_channel, num_classes=config_cpu.numclasses) + model = Model(net, loss_fn=loss, optimizer=opt) + network=model._train_network + network.set_train() + ``` + +### GPU或Ascend AI处理器加载模型 + +在构建Network时,MindSpore会根据Python变量命名,自动隐式设置图结构中参数的命名。以如下MobileNetV2 head层初始化代码为例,全局平均池化、全连接层、Dropout层共同构成了head层,全局平均池化与Dropout层没有参数,head层中只有卷积层包含参数。全连接层的param.name是“head.1”,全连接层的权重和偏置分别为“head.1.weight”和“head.1.bias”。 + +- 全连接层 + + ```python + head = ([GlobalAvgPooling(), nn.Dense(self.out_channels, num_classes, has_bias=True)] if not has_dropout \ + else [GlobalAvgPooling(), nn.Dropout(0.2), nn.Dense(self.out_channels, num_classes, has_bias=True)]) + self.head = nn.SequentialCell(head) + self._initialize_weights() + ``` + +- 全连接层参数搜索 + + 若用户自定义Network,可以在初始化net后加入如下代码提取所有参数的命名,打印出来以方便查找全连接层参数命名,再使用`param_dict.pop(param.name)`来丢弃全连接层权重。 + + ```python + for param in net.get_parameters(): + print(param.name) + ``` + +- 加载模型权重 + 在模型加载之前,首先根据Network结构构建网络并且初始化网络权重。以如下MobileNetV2增量训练加载模型代码为例,代码第5-6行判断将pretrain_ckpt_path是否是用于增量学习或者调优,若不是这两种,将会报错。代码第7将`pretrain_ckpt_path`加载入`param_dict`;代码第9行与第19行判断pretrain_ckpt_path用于增量学习还是调优。若是增量学习,执行代码第10-13行,将`param_dict`中全连接层权重抛掉,执行代码第14行加载预训练模型中卷积、BN等特征提取层参数权重,执行代码第15-17行冻结`net`中全连接层之外的全部参数梯度,在后续训练过程中不再训练特征提取层权重,只训练全连接层权重。若是调优,执行代码第20行加载全部模型参数权重。 + + ```python + 1: def load_ckpt(network, pretrain_ckpt_path=None, ckpt_usage=None): + 2: """ + 3: incremental_learning or not + 4: """ + 5: if ckpt_usage not in ("incremental_learn", "fine_tune"): + 6: raise ValueError("Unsupported ckpt_usage. Only receive \"fine_tune\" or \"incremental_learn\"") + 7: param_dict = load_checkpoint(pretrain_ckpt_path) + 8: + 9: if ckpt_usage == "incremental_learn": + 10: param_dict.pop('head.1.weight') + 11: param_dict.pop('head.1.bias') + 12: param_dict.pop('moments.head.1.weight') + 13: param_dict.pop('moments.head.1.bias') + 14: load_param_into_net(network, param_dict) + 15: for param in network.get_parameters(): + 16: if param.name not in ("head.1.weight", "head.1.bias"): + 17: param.requires_grad = False + 18: + 19: elif ckpt_usage == "fine_tune": + 20: load_param_into_net(network, param_dict) + ``` + +## 训练参数简介 + +使用CPU训练时,运行`finetune.py`并且传入`dataset_path`、`pre_trained`与`platform`三个参数。使用GPU或Ascend AI处理器是,运行训练与验证脚本`./scripts/fun_train.sh`与`./scripts/infer.sh`时读取训练参数。 + +```shell +#CPU +python finetine.py --dataset_path [dataset_path] --pre_trained [pretrain_checkpoint_path] --platform [platform] + +#GPU or Ascend +sh run_train.sh [PLATFORM] [DEVICE_NUM] [VISIABLE_DEVICES(0,1,2,3,4,5,6,7)] [RANK_TABLE_FILE] [DATASET_PATH] [CKPT_PATH] [CKPT_USAGE] + +``` + +### CPU: + +- `--dataset_path`:训练与验证数据集地址,无默认值,用户训练/验证时必须输入。 +- `--pre_trained`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 +- `--platform`:芯片,默认为“Ascend”,可以设置为“GPU”。 + +### GPU: + +- `[PLATFORM]`:芯片,默认为“Ascend”,可以设置为“GPU”。 +- `[DEVICE_NUM]`:每个节点(一台服务器/PC相当于一个节点)进程数量,建议设置为机器上Ascend 芯片数量或GPU数量。 +- `[VISIABLE_DEVICES(0,1,2,3,4,5,6,7)]`:字符串格式的的设备ID,训练将会根据`[VISIABLE_DEVICES]`将进程绑定到对应ID的设备上,多个设备ID之间使用','分隔,建议ID数量与进程数量相同。 +- `[RANK_TABLE_FILE]`:platform选择Ascend时,需要配置Ascend的配置Json文件,。 +- `[DATASET_PATH]`:训练与验证数据集地址,无默认值,用户训练/验证时必须输入。 +- `[CKPT_PATH]`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 +- `[CKPT_USAGE]`:预训练模型使用用途,只有`fine_tune`或`incremental_learn`。 + +## 加载训练 + +### 开始增量训练 + +使用CPU和`MobileNetV2`做增量训练时,运行`finetine.py`[参数](#训练参数简介)。 +使用GPU或Ascend AI处理器和`MobileNetV2`做增量训练时,运行`run_train.sh`时传入[参数](#训练参数简介)。 + +CPU模式输出信息到交互式命令行,GPU与Ascend AI处理器模式运行`run_train.sh`时,命令行结尾使用`&> [log_file_path]`将标准输出与错误输出写入log文件。 增量训练成功开始训练,`./train/device*/log*.log`中会持续写入每一个epoch的训练时间与Loss等信息。若未成功,上述log文件会写入失败报错信息。 + +```shell +# CPU +python finetune.py CPU /store/dataset/OpenImage/train/ ./pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + +# GPU +sh run_train.sh GPU 8 0,1,2,3,4,5,6,7 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + +# Ascemd +sh run_train.sh Ascend 8 0,1,2,3,4,5,6,7 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn +``` + +### 调整节点数量 + +CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处理器平台上运行`run_train.sh`文件时,设置`[nproc_per_node]`为Ascend AI处理器/GPU数量, `[visible_devices]`为可使用的处理器编号,即Ascend AI处理器或GPU的ID,可以选择0-7中一个或多个设备ID。目前Ascend节点进程数量只能设置为1或者8。 + +- 使用样例1:使用1个CPU处理器。 + + ```shell + python finetune.py --platform CPU --dataset_path /store/dataset/OpenImage/train/ --pre_trained ./pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +- 使用样例2:使用1个GPU处理器,设备ID为“0”。 + + ```shell + sh run_train.sh GPU 1 0 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +- 使用样例3:使用1个GPU处理器,设备ID为“4”。 + + ```shell + sh run_train.sh GPU 1 4 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +- 使用样例4:使用8个GPU处理器,设备ID为“0,1,2,3,4,5,6,7”。 + + ```shell + sh run_train.sh GPU 8 0,1,2,3,4,5,6,7 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +- 使用样例5:使用1个Ascend AI处理器,设备ID为“0”。 + + ```shell + sh run_train.sh Ascend 1 0 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +- 使用样例6:使用1个Ascend AI处理器,设备ID为“4”。 + + ```shell + sh run_train.sh Ascend 1 4 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +- 使用样例7:使用8个Ascend AI处理器,设备ID为”0,1,2,3,4,5,6,7“。 + + ```shell + sh run_train.sh Ascend 8 0,1,2,3,4,5,6,7 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + ``` + +### 训练结果 + +- 查看运行结果。 + + - CPU: + 在交互式命令行中查看打印信息 + + 输出结果如下: + + ```shell + saved feature_0 + saved feature_1 + saved feature_2 + ... + saved feature_14 + saved feature_15 + saved feature_16 + epoch[1], iter[17] cost: 5494.584, per step time: 323.211, avg loss: 1.996, lr: 0.0300 + epoch[2], iter[17] cost: 5244.241, per step time: 308.485, avg loss: 1.047, lr: 0.0300 + epoch[3], iter[17] cost: 5270.173, per step time: 310.010, avg loss: 0.936, lr: 0.0300 + ... + epoch[13], iter[17] cost: 5243.293, per step time: 308.429, avg loss: 0.726, lr: 0.0300 + epoch[14], iter[17] cost: 5248.263, per step time: 308.721, avg loss: 0.721, lr: 0.0300 + epoch[15], iter[17] cost: 5263.191, per step time: 309.599, avg loss: 0.718, lr: 0.0300 + ``` + + - GPU: + + ```shell + cat ./train/device0/log0.log + ``` + + 输出结果如下: + + ```shell + + epoch: [ 0/200], step:[ 624/ 625], loss:[5.258/5.258], time:[140412.236], lr:[0.100] + epoch time: 140522.500, per step time: 224.836, avg loss: 5.258 + epoch: [ 1/200], step:[ 624/ 625], loss:[3.917/3.917], time:[138221.250], lr:[0.200] + epoch time: 138331.250, per step time: 221.330, avg loss: 3.917 + ``` + +- 查看保存的checkpoint文件。 + + - CPU: + + ```shell + dir checkpoint + 2020//0814 11:20 267,727 mobilenetv2_head_1.ckpt + 2020//0814 11:21 267,727 mobilenetv2_head_10.ckpt + 2020//0814 11:21 267,727 mobilenetv2_head_11.ckpt + ... + 2020//0814 11:21 267,727 mobilenetv2_head_7.ckpt + 2020//0814 11:21 267,727 mobilenetv2_head_8.ckpt + 2020//0814 11:21 267,727 mobilenetv2_head_9.ckpt + ``` + + - GPU: + + ```shell + ls ./train/device0/checkpoint/*.ckpt + mobilenetV2-100_625.ckpt mobilenetV2-191_625.ckpt + mobilenetV2-101_625.ckpt mobilenetV2-192_625.ckpt + ... + ``` + +### 验证增量训练模型 + +使用验证集测试模型性能,必须输入dataset_path和pretrain_checkpoint_path,platform默认为“Ascend”,可以自行设置为GPU,最终将标准输出与错误输出写入infer.log文件 + +```shell +#CPU +python finetune_eval.py --dataset_path \store\dataset\openimage\val\ .\checkpoint\mobilenetv2_head_15.ckpt +#GPU or Ascend +sh run_infer.sh [PLATFORM] /store/dataset/openimage/val/ ../checkpoint/mobilenet-200_625.ckpt +``` + +### 验证结果 + +- CPU模式 + CPU模式下在交互式命令行中输出 + + ```shell + result:{'acc':-.9466666666666666666667} ckpt = checkpoint\mobilenetv2_head_15.ckpt + ``` + +- GPU或Ascend模式 + GPU或Ascend AI处理器模式下将log信息写入`./infer.log`中 + + ```shell + cat ./infer.log + result: {'acc': 0.71976314102564111} ckpt=../checkpoint/mobilenet-200_625.ckpt + ``` -- Gitee From 7d06fc9e2e8ea11741399a21790a88eba1a57b7b Mon Sep 17 00:00:00 2001 From: Payne Date: Mon, 31 Aug 2020 17:53:01 +0800 Subject: [PATCH 2/3] change the button from device to train_method --- .../advanced_use/mobilenetv2_finetune.md | 304 ++++++++---------- 1 file changed, 136 insertions(+), 168 deletions(-) diff --git a/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md b/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md index ba59537b06..20be0b8cc5 100644 --- a/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md +++ b/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md @@ -11,7 +11,11 @@ - [准备预训练模型](#准备预训练模型) - [准备数据](#准备数据) - [预训练模型加载代码详解](#预训练模型加载代码详解) - - [训练参数简介](#训练参数简介) + - [增量学习加载模型](#增量学习加载模型) + - [微调加载模型](#微调加载模型) + - [参数简介](#参数简介) + - [运行python文件](#运行python文件) + - [运行shell脚本](#运行shell脚本) - [加载训练](#加载训练) - [开始增量训练](#开始增量训练) - [调整节点数量](#调整节点数量) @@ -32,15 +36,32 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 ### 环境配置 -若在华为云环境上运行,不需要安装MindSpore框架和配置Ascend AI处理器,可以跳过本小节。若在本地环境运行,需要安装MindSpore框架,配置CPU、Ascend AI处理器或GPU。 +若在华为云环境上运行,不需要安装MindSpore框架和配置Ascend AI处理器,可以跳过本小节。若在本地环境运行,需要安装MindSpore框架,配置CPU、GPU或Ascend AI处理器。 1. 安装MindSpore框架 在Euler、Ubuntu或者Windows等系统上需要系统和处理器架构[安装对应版本MindSporo框架](https://www.mindspore.cn/install)。 2. 配置CPU环境 - CPU环境只需按照系统和处理器架构暗安装对应版本的MinsSpore框架,无需其他特殊的配置。 + 使用CPU时,在代码中,需要在调用CPU开始训练或测试前,按照如下代码设置: -3. 配置Ascend环境 + ```python + if config.platform == "CPU": + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, save_graphs=False) + ``` + +3. 配置GPU环境 + 使用GPU时,在代码中,需要在调用GPU开始训练或测试前,按照如下代码设置: + + ```python + elif config.platform == "GPU": + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, save_graphs=False) + init("nccl") + context.set_auto_parallel_context(device_num=get_group_size(), + parallel_mode=ParallelMode.DATA_PARALLEL, + mirror_mean=True) + ``` + +4. 配置Ascend环境 以Ascend 910 AI处理器为例,1个8个处理器环境的json配置文件`hccl_config.json`示例如下。单/多处理器环境可以根据以下示例调整`"server_count"`与`device`: ```json @@ -50,7 +71,7 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 "server_list": [ { "server_id": "10.155.111.140", - "device": [ + "device": [ba {"device_id": "0","device_ip": "192.1.27.6","rank_id": "0"}, {"device_id": "1","device_ip": "192.2.27.6","rank_id": "1"}, {"device_id": "2","device_ip": "192.3.27.6","rank_id": "2"}, @@ -69,37 +90,20 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 使用Ascend AI处理器时,在代码中,需要在调用Ascend AI处理器开始训练或测试前,按照如下代码设置: ```python - import os - from mindspore import context - from mindspore.communication.management import init - - if __name__ == "__main__": - context.set_context(mode=context.GRAPH_MODE, device_target="Ascend", device_id=int(os.environ["DEVICE_ID"])) - init() - ... - ``` - -4. 配置GPU环境 - 使用GPU时,在代码中,需要在调用GPU开始训练或测试前,按照如下代码设置: - - ```python - from mindspore import context - from mindspore.communication.management import init - - if __name__ == "__main__": - context.set_context(mode=context.GRAPH_MODE, device_target="GPU") - init("nccl") - ... + elif config.platform == "Ascend": + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, device_id=config.device_id, + save_graphs=False) + if config.run_distribute: + context.set_auto_parallel_context(device_num=config.rank_size, + parallel_mode=ParallelMode.DATA_PARALLEL, + parameter_broadcast=True, mirror_mean=True) + auto_parallel_context().set_all_reduce_fusion_split_indices([140]) + init() + ... ``` ### 克隆代码 -CPU代码: - -```bash - -``` - GPU与Ascend AI处理器代码: 在Gitee中克隆[MindSpore开源项目仓库](https://gitee.com/mindspore/mindspore.git),进入`./model_zoo/official/cv/mobilenetv2/`。 @@ -108,28 +112,9 @@ git clone git@gitee.com:/mindspore.git cd ./mindspore/model_zoo/official/cv/mobilenetv2 ``` -使用CPU进行增量训练时,运行`finetune.py`,使用训练好的模型进行验证与测试时,运行`finetune_eval.py`。 +使用脚本文件`run_train.sh`时,该文件会将运行`launch.py`并且将参数传入`launch.py`, `launch.py`根据分配的CPU、GPU或Ascend AI处理器数量,启动单个/多个进程运行`train.py`,每一个进程分配对应的一个处理器。 -CPU代码结构如下: - -```python - ├── MobileNetV2 - ├── Readme.md # descriptions about MobileNetV2 - ├── src - │ ├──config.py # parameter configuration - │ ├──dataset.py # creating dataset - │ ├──launch.py # start python script - │ ├──lr_generator.py # learning rate config - │ ├──mobilenetV2.py # MobileNetV2 architecture - ├── finetune.py # finetune script - ├── finetune_eval.py # finetune eval script - ├── tools - │ ├──flatten_dir.py # script for private dataset process -``` - -使用GPU与Ascend AI处理器训练时,运行`run_train.sh`,该文件会将运行`launch.py`并且将参数传入`launch.py`, `launch.py`根据分配的Ascend AI处理器或GPU数量,启动多个进程运行`train.py`,每一个进程分配对应的一个处理器。 - -GPU与Ascend AI处理器代码结构如下: +代码结构如下: ```python ├── MobileNetV2 @@ -160,7 +145,7 @@ wget -P ./pretrain_checkpoint https://download.mindspore.cn/model_zoo/official/l ### 准备数据 -准备ImageFolder格式管理的数据集,并且在运行`run_train.sh`时加入`[dataset_path]`参数: +准备ImageFolder格式管理的数据集,运行`run_train.sh`时加入`[dataset_path]`参数,运行`train.py`时加入`--dataset_path [dataset_path]`参数: 数据集结构如下: @@ -176,109 +161,77 @@ wget -P ./pretrain_checkpoint https://download.mindspore.cn/model_zoo/official/l ## 预训练模型加载代码详解 -在增量学习时,需要加载预训练模型。不同数据集和任务中特征提取层(卷积层)分布趋于一致,但是特征向量的组合(全连接层)不相同,分类数量(全连接层output_size)通常也不一致。在增量学习时,只加载特征提取层参数,抛弃全连接层参数不加载。 - -### CPU加载模型 - -在增量学习时,构建只有特征提取层,没有全连接层的MobileNetV2,将经过预训练的模型参数权重加载入上述网络。另外构建一个只包含全局平均池化与全连接层的Head网络。在训练时,使用MobileNetV2提取的特征单独训练Head网络。 +在增量学习时,需要加载预训练模型。不同数据集和任务中特征提取层(卷积层)分布趋于一致,但是特征向量的组合(全连接层)不相同,分类数量(全连接层output_size)通常也不一致。在增量学习时,只加载与训练特征提取层参数,不加载与训练全连接层参数;在微调与初始训练,加载与训练特征提取层参数与全连接层参数。 -- 构建`MobileNetV2`特征提取网络(只有特征提取,不包括全连接层): +在训练与测试之前,首先按照代码第1行,构建MobileNetV2的backbone网络,head网络,并且构建包含这两个子网络的MobileNetV2网络。代码第4-21行展示了如何在`fine_tune`训练模式下,将预训练模型加载入`net`(MobileNetV2);在`incremental_learn`训练模式下,将预训练模型分别加载入backbone与head两个子网络,并且冻结住backbone子网络中的参数,不参与训练。代码第23-31行展示了如何冻结网络参数。 - ```python - class MobileNetV2(nn.Cell): - ... - def construct(self, x): - x = self.features(x) - return x - ... - ``` - -- 加载模型参数权重: - - ```python - net = MoblileNetV2(platform=args_ppt.platform) - if args_opt.pre_trained: - param_dict = load_checkpoint(args_opt.pre_trained) - load_param_into_net(net,param_dict) - ``` - -- 构建head网络: - - ```python - net = Head(last_channel, num_classes=config_cpu.numclasses) - model = Model(net, loss_fn=loss, optimizer=opt) - network=model._train_network - network.set_train() - ``` - -### GPU或Ascend AI处理器加载模型 - -在构建Network时,MindSpore会根据Python变量命名,自动隐式设置图结构中参数的命名。以如下MobileNetV2 head层初始化代码为例,全局平均池化、全连接层、Dropout层共同构成了head层,全局平均池化与Dropout层没有参数,head层中只有卷积层包含参数。全连接层的param.name是“head.1”,全连接层的权重和偏置分别为“head.1.weight”和“head.1.bias”。 - -- 全连接层 - - ```python - head = ([GlobalAvgPooling(), nn.Dense(self.out_channels, num_classes, has_bias=True)] if not has_dropout \ - else [GlobalAvgPooling(), nn.Dropout(0.2), nn.Dense(self.out_channels, num_classes, has_bias=True)]) - self.head = nn.SequentialCell(head) - self._initialize_weights() - ``` - -- 全连接层参数搜索 +```python + 1: # define network + 2: backbone_net, head_net, net = define_net(args_opt, config) + 3: ... + 4: # load the ckpt file to the network for fine tune, incremental leaning or train + 5: def define_net(args, config): + 6: backbone_net = MobileNetV2Backbone(platform=args.platform) + 7: head_net = MobileNetV2Head(input_channel=backbone_net.out_channels, num_classes=config.num_classes) + 8: net = mobilenet_v2(backbone_net, head_net) + 9: +10: # load the ckpt file to the network for fine tune or incremental leaning +11: if args.pretrain_ckpt: +12: if args.train_method == "fine_tune": +13: load_ckpt(net, args.pretrain_ckpt) +14: elif args.train_method == "incremental_learn": +15: load_ckpt(backbone_net, args.pretrain_ckpt, trainable=False) +16: elif args.train_method == "train": +17: pass +18: else: +19: raise ValueError("must input the usage of pretrain_ckpt when the pretrain_ckpt isn't None") +20: +21: return backbone_net, head_net, net +22: ... +23: def load_ckpt(network, pretrain_ckpt_path, trainable=True): +24: """ +25: incremental_learning or not +26: """ +27: param_dict = load_checkpoint(pretrain_ckpt_path) +28: load_param_into_net(network, param_dict) +29: if not trainable: +30: for param in network.get_parameters(): +31: param.requires_grad = False +``` - 若用户自定义Network,可以在初始化net后加入如下代码提取所有参数的命名,打印出来以方便查找全连接层参数命名,再使用`param_dict.pop(param.name)`来丢弃全连接层权重。 +## 参数简介 - ```python - for param in net.get_parameters(): - print(param.name) - ``` +使用CPU训练时,运行`finetune.py`并且传入`dataset_path`、`pre_trained`与`platform`三个参数。使用GPU或Ascend AI处理器是,运行训练与验证脚本`./scripts/fun_train.sh`与`./scripts/infer.sh`时读取训练参数。 -- 加载模型权重 - 在模型加载之前,首先根据Network结构构建网络并且初始化网络权重。以如下MobileNetV2增量训练加载模型代码为例,代码第5-6行判断将pretrain_ckpt_path是否是用于增量学习或者调优,若不是这两种,将会报错。代码第7将`pretrain_ckpt_path`加载入`param_dict`;代码第9行与第19行判断pretrain_ckpt_path用于增量学习还是调优。若是增量学习,执行代码第10-13行,将`param_dict`中全连接层权重抛掉,执行代码第14行加载预训练模型中卷积、BN等特征提取层参数权重,执行代码第15-17行冻结`net`中全连接层之外的全部参数梯度,在后续训练过程中不再训练特征提取层权重,只训练全连接层权重。若是调优,执行代码第20行加载全部模型参数权重。 +训练与验证时,可以根据系统支持直接运行``train.py``和``eval.py``,或者使用shell脚本``run_train.sh``和``run_eval.sh``调用``train.py``、``eval.py``运行训练与验证。 - ```python - 1: def load_ckpt(network, pretrain_ckpt_path=None, ckpt_usage=None): - 2: """ - 3: incremental_learning or not - 4: """ - 5: if ckpt_usage not in ("incremental_learn", "fine_tune"): - 6: raise ValueError("Unsupported ckpt_usage. Only receive \"fine_tune\" or \"incremental_learn\"") - 7: param_dict = load_checkpoint(pretrain_ckpt_path) - 8: - 9: if ckpt_usage == "incremental_learn": - 10: param_dict.pop('head.1.weight') - 11: param_dict.pop('head.1.bias') - 12: param_dict.pop('moments.head.1.weight') - 13: param_dict.pop('moments.head.1.bias') - 14: load_param_into_net(network, param_dict) - 15: for param in network.get_parameters(): - 16: if param.name not in ("head.1.weight", "head.1.bias"): - 17: param.requires_grad = False - 18: - 19: elif ckpt_usage == "fine_tune": - 20: load_param_into_net(network, param_dict) - ``` +```shell +# windows doesn't support shell +# windows/Linux train with python file +python train.py --dataset_path [dataset_path] --pretrain_ckpt [pretrain_checkpoint_path] --platform [platform] --train_method[("train", "fine_tune", "incremental_learn")] -## 训练参数简介 +# windows/Linux eval with python file +python eval.py --dataset_path [dataset_path] --pretrain_ckpt [pretrain_checkpoint_path] --platform [platform] -使用CPU训练时,运行`finetune.py`并且传入`dataset_path`、`pre_trained`与`platform`三个参数。使用GPU或Ascend AI处理器是,运行训练与验证脚本`./scripts/fun_train.sh`与`./scripts/infer.sh`时读取训练参数。 +# Linux train with shell script +sh run_train.sh [PLATFORM] [DEVICE_NUM] [VISIABLE_DEVICES(0,1,2,3,4,5,6,7)] [RANK_TABLE_FILE] [DATASET_PATH] [CKPT_PATH] [TRAIN_METHOD] -```shell -#CPU -python finetine.py --dataset_path [dataset_path] --pre_trained [pretrain_checkpoint_path] --platform [platform] +# Linux eval with shell script for train or fine_tune +sh run_eval.sh [PLATFORM] [DATASET_PATH] [CKPT_PATH] -#GPU or Ascend -sh run_train.sh [PLATFORM] [DEVICE_NUM] [VISIABLE_DEVICES(0,1,2,3,4,5,6,7)] [RANK_TABLE_FILE] [DATASET_PATH] [CKPT_PATH] [CKPT_USAGE] +# Linux eval with shell script for train or incremental learn +sh run_eval.sh [PLATFORM] [DATASET_PATH] [BACKBONE_CKPT_PATH] [HEAD_CKPT_PATH] ``` -### CPU: +### 运行python文件: - `--dataset_path`:训练与验证数据集地址,无默认值,用户训练/验证时必须输入。 -- `--pre_trained`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 -- `--platform`:芯片,默认为“Ascend”,可以设置为“GPU”。 +- `--pretrain_ckpt`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 +- `--platform`:芯片,默认为“Ascend”,可以设置为“CPU”或"GPU"。 +- `--train_method`:训练方法,必须输入“train"、"fine_tune"和incremental_learn"其中一个。 -### GPU: +### 运行shell脚本: - `[PLATFORM]`:芯片,默认为“Ascend”,可以设置为“GPU”。 - `[DEVICE_NUM]`:每个节点(一台服务器/PC相当于一个节点)进程数量,建议设置为机器上Ascend 芯片数量或GPU数量。 @@ -286,69 +239,84 @@ sh run_train.sh [PLATFORM] [DEVICE_NUM] [VISIABLE_DEVICES(0,1,2,3,4,5,6,7)] [RAN - `[RANK_TABLE_FILE]`:platform选择Ascend时,需要配置Ascend的配置Json文件,。 - `[DATASET_PATH]`:训练与验证数据集地址,无默认值,用户训练/验证时必须输入。 - `[CKPT_PATH]`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 -- `[CKPT_USAGE]`:预训练模型使用用途,只有`fine_tune`或`incremental_learn`。 +- `[TRAIN_METHOD]`:训练方法,必须输入`train`、`fine_tune`和`incremental_learn`其中一个。 +- `[BACKBONE_CKPT_PATH]`:针对增量学习的模型做验证时,需要输入主干网络层保存模型路径。 +- `[HEAD_CKPT_PATH]`:针对增量学习的模型做验证时,需要输入全连接层保存模型路径。 + ## 加载训练 ### 开始增量训练 -使用CPU和`MobileNetV2`做增量训练时,运行`finetine.py`[参数](#训练参数简介)。 -使用GPU或Ascend AI处理器和`MobileNetV2`做增量训练时,运行`run_train.sh`时传入[参数](#训练参数简介)。 +在windows系统上,`MobileNetV2`做增量训练时,只能运行`train.py`[参数](#训练参数简介)。 +在Linux系统时,使用`MobileNetV2`做增量训练时,可以运行`run_train.sh`, 并在在运行shell脚本文件时传入[参数](#训练参数简介)。 -CPU模式输出信息到交互式命令行,GPU与Ascend AI处理器模式运行`run_train.sh`时,命令行结尾使用`&> [log_file_path]`将标准输出与错误输出写入log文件。 增量训练成功开始训练,`./train/device*/log*.log`中会持续写入每一个epoch的训练时间与Loss等信息。若未成功,上述log文件会写入失败报错信息。 +Windows系统输出信息到交互式命令行,Linux系统环境下运行`run_train.sh`时,命令行结尾使用`&> [log_file_path]`将标准输出与错误输出写入log文件。 增量训练成功开始训练,`./train/device*/log*.log`中会持续写入每一个epoch的训练时间与Loss等信息。若未成功,上述log文件会写入失败报错信息。 ```shell -# CPU -python finetune.py CPU /store/dataset/OpenImage/train/ ./pretrain_checkpoint/mobilenetV2.ckpt incremental_learn +# windows +python train.py --platform CPU --dataset_path /store/dataset/OpenImage/train/ --pretrain_ckpt ./pretrain_checkpoint/mobilenetV2.ckpt -- train_method incremental_learn -# GPU +# windows or Linux: GPU sh run_train.sh GPU 8 0,1,2,3,4,5,6,7 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn -# Ascemd +# windows or Linux: Ascemd sh run_train.sh Ascend 8 0,1,2,3,4,5,6,7 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn ``` -### 调整节点数量 +### 调整节点数量 -CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处理器平台上运行`run_train.sh`文件时,设置`[nproc_per_node]`为Ascend AI处理器/GPU数量, `[visible_devices]`为可使用的处理器编号,即Ascend AI处理器或GPU的ID,可以选择0-7中一个或多个设备ID。目前Ascend节点进程数量只能设置为1或者8。 +目前运行`train.py`时仅支持单处理器,不需要调整节点数量。运行`run_train.sh`文件时,设置`[nproc_per_node]`为Ascend AI处理器/GPU数量, `[visible_devices]`为可使用的处理器编号,即Ascend AI处理器或GPU的ID,可以选择0-7中一个或多个设备ID。目前Ascend节点进程数量只能设置为1或者8。 -- 使用样例1:使用1个CPU处理器。 +- 使用样例1:通过python文件调用1个CPU处理器。 ```shell - python finetune.py --platform CPU --dataset_path /store/dataset/OpenImage/train/ --pre_trained ./pretrain_checkpoint/mobilenetV2.ckpt incremental_learn + python train.py --platform CPU --dataset_path /store/dataset/OpenImage/train/ --pre_trained ./pretrain_checkpoint/mobilenetV2.ckpt --train_method incremental_learn + ``` + +- 使用样例2:通过python文件调用1个GPU处理器。 + + ```shell + python train.py --platform GPU --dataset_path /store/dataset/OpenImage/train/ --pre_trained ./pretrain_checkpoint/mobilenetV2.ckpt --train_method incremental_learn + ``` + +- 使用样例3:通过python文件调用1个Ascend处理器。 + + ```shell + python train.py --platform Ascend --dataset_path /store/dataset/OpenImage/train/ --pre_trained ./pretrain_checkpoint/mobilenetV2.ckpt --train_method incremental_learn ``` -- 使用样例2:使用1个GPU处理器,设备ID为“0”。 +- 使用样例4:通过shell脚本调用1个GPU处理器,设备ID为“0”。 ```shell sh run_train.sh GPU 1 0 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn ``` -- 使用样例3:使用1个GPU处理器,设备ID为“4”。 +- 使用样例5:通过shell脚本调用1个GPU处理器,设备ID为“4”。 ```shell sh run_train.sh GPU 1 4 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn ``` -- 使用样例4:使用8个GPU处理器,设备ID为“0,1,2,3,4,5,6,7”。 +- 使用样例6:通过shell脚本调用8个GPU处理器,设备ID为“0,1,2,3,4,5,6,7”。 ```shell sh run_train.sh GPU 8 0,1,2,3,4,5,6,7 /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn ``` -- 使用样例5:使用1个Ascend AI处理器,设备ID为“0”。 +- 使用样例7:通过shell脚本调用1个Ascend AI处理器,设备ID为“0”。 ```shell sh run_train.sh Ascend 1 0 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn ``` -- 使用样例6:使用1个Ascend AI处理器,设备ID为“4”。 +- 使用样例8:通过shell脚本调用1个Ascend AI处理器,设备ID为“4”。 ```shell sh run_train.sh Ascend 1 4 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn ``` -- 使用样例7:使用8个Ascend AI处理器,设备ID为”0,1,2,3,4,5,6,7“。 +- 使用样例9:通过shell脚本调用8个Ascend AI处理器,设备ID为”0,1,2,3,4,5,6,7“。 ```shell sh run_train.sh Ascend 8 0,1,2,3,4,5,6,7 ~/rank_table.json /store/dataset/OpenImage/train/ ../pretrain_checkpoint/mobilenetV2.ckpt incremental_learn @@ -358,7 +326,7 @@ CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处 - 查看运行结果。 - - CPU: + - 运行python文件: 在交互式命令行中查看打印信息 输出结果如下: @@ -380,7 +348,7 @@ CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处 epoch[15], iter[17] cost: 5263.191, per step time: 309.599, avg loss: 0.718, lr: 0.0300 ``` - - GPU: + - 使用shell脚本: ```shell cat ./train/device0/log0.log @@ -398,7 +366,7 @@ CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处 - 查看保存的checkpoint文件。 - - CPU: + - 运行python文件: ```shell dir checkpoint @@ -411,7 +379,7 @@ CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处 2020//0814 11:21 267,727 mobilenetv2_head_9.ckpt ``` - - GPU: + - 使用shell脚本: ```shell ls ./train/device0/checkpoint/*.ckpt @@ -425,23 +393,23 @@ CPU目前支持单处理器,不需要调整节点数量。GPU和Ascend AI处 使用验证集测试模型性能,必须输入dataset_path和pretrain_checkpoint_path,platform默认为“Ascend”,可以自行设置为GPU,最终将标准输出与错误输出写入infer.log文件 ```shell -#CPU +#python python finetune_eval.py --dataset_path \store\dataset\openimage\val\ .\checkpoint\mobilenetv2_head_15.ckpt -#GPU or Ascend +#shell sh run_infer.sh [PLATFORM] /store/dataset/openimage/val/ ../checkpoint/mobilenet-200_625.ckpt ``` ### 验证结果 -- CPU模式 +- 运行python文件: CPU模式下在交互式命令行中输出 ```shell result:{'acc':-.9466666666666666666667} ckpt = checkpoint\mobilenetv2_head_15.ckpt ``` -- GPU或Ascend模式 - GPU或Ascend AI处理器模式下将log信息写入`./infer.log`中 +- 使用shell脚本: + shell脚本将把log信息写入`./infer.log`中 ```shell cat ./infer.log -- Gitee From 7bbfb496d620d7c8ddf16eabb19010cb3097a9a2 Mon Sep 17 00:00:00 2001 From: yepei6 Date: Mon, 31 Aug 2020 17:57:33 +0800 Subject: [PATCH 3/3] update tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md. --- .../advanced_use/mobilenetv2_finetune.md | 194 +++++++++--------- 1 file changed, 96 insertions(+), 98 deletions(-) diff --git a/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md b/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md index 20be0b8cc5..599992225a 100644 --- a/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md +++ b/tutorials/source_zh_cn/advanced_use/mobilenetv2_finetune.md @@ -4,15 +4,14 @@ -- [增量学习](#增量学习)- [概述](#概述) +- [增量学习](#增量学习) + - [概述](#概述) - [任务描述及准备](#任务描述及准备) - [环境配置](#环境配置) - [克隆代码](#克隆代码) - [准备预训练模型](#准备预训练模型) - [准备数据](#准备数据) - [预训练模型加载代码详解](#预训练模型加载代码详解) - - [增量学习加载模型](#增量学习加载模型) - - [微调加载模型](#微调加载模型) - [参数简介](#参数简介) - [运行python文件](#运行python文件) - [运行shell脚本](#运行shell脚本) @@ -39,14 +38,15 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 若在华为云环境上运行,不需要安装MindSpore框架和配置Ascend AI处理器,可以跳过本小节。若在本地环境运行,需要安装MindSpore框架,配置CPU、GPU或Ascend AI处理器。 1. 安装MindSpore框架 - 在Euler、Ubuntu或者Windows等系统上需要系统和处理器架构[安装对应版本MindSporo框架](https://www.mindspore.cn/install)。 + 在Euler、Ubuntu或者Windows等系统上需要根据系统和处理器架构[安装对应版本MindSpore框架](https://www.mindspore.cn/install)。 -2. 配置CPU环境 +2. 配置CPU环境 使用CPU时,在代码中,需要在调用CPU开始训练或测试前,按照如下代码设置: ```python if config.platform == "CPU": - context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, save_graphs=False) + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, \ + save_graphs=False) ``` 3. 配置GPU环境 @@ -54,7 +54,8 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 ```python elif config.platform == "GPU": - context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, save_graphs=False) + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, \ + save_graphs=False) init("nccl") context.set_auto_parallel_context(device_num=get_group_size(), parallel_mode=ParallelMode.DATA_PARALLEL, @@ -91,8 +92,8 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 ```python elif config.platform == "Ascend": - context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, device_id=config.device_id, - save_graphs=False) + context.set_context(mode=context.GRAPH_MODE, device_target=config.platform, \ + device_id=config.device_id, save_graphs=False) if config.run_distribute: context.set_auto_parallel_context(device_num=config.rank_size, parallel_mode=ParallelMode.DATA_PARALLEL, @@ -104,7 +105,6 @@ MindSpore是一个多元化的机器学习框架。既可以在手机等端侧 ### 克隆代码 -GPU与Ascend AI处理器代码: 在Gitee中克隆[MindSpore开源项目仓库](https://gitee.com/mindspore/mindspore.git),进入`./model_zoo/official/cv/mobilenetv2/`。 ```bash @@ -116,21 +116,22 @@ cd ./mindspore/model_zoo/official/cv/mobilenetv2 代码结构如下: -```python - ├── MobileNetV2 - ├── Readme.md # descriptions about MobileNetV2 - ├── scripts - │ ├──run_train.sh # shell script for train with Ascend or GPU - │ ├──run_eval.sh # shell script for evaluation with Ascend or GPU - ├── src - │ ├──config.py # parameter configuration - │ ├──dataset.py # creating dataset - │ ├──launch.py # start python script - │ ├──lr_generator.py # learning rate config - │ ├──mobilenetV2.py # MobileNetV2 architecture - │ ├──net_utils.py # net utils to load ckpt_file for fine tune or incremental learn - ├── train.py # training script - ├── eval.py # evaluation script +``` +├─MobileNetV2 + ├─Readme.md # descriptions about MobileNetV2 + ├─scripts + │ run_train.sh # shell script for train with Ascend or GPU + │ run_eval.sh # shell script for evaluation with Ascend or GPU + ├─src + │ config.py # parameter configuration + │ dataset.py # creating dataset + │ launch.py # start python script + │ lr_generator.py # learning rate config + │ mobilenetV2.py # MobileNetV2 architecture + │ models.py # net utils to load ckpt_file, define_net... + │ utils.py # net utils to switch precision, set_context and so on + ├─train.py # training script + └─eval.py # evaluation script ``` ### 准备预训练模型 @@ -149,61 +150,56 @@ wget -P ./pretrain_checkpoint https://download.mindspore.cn/model_zoo/official/l 数据集结构如下: - └─ImageFolder - ├─train - │ ├─class1Folder - │ ├─class2Folder - │ └─...... - └─eval - ├─class1Folder - ├─class2Folder - └─...... +``` +└─ImageFolder + ├─train + │ class1Folder + │ class2Folder + │ ...... + └─eval + class1Folder + class2Folder + ...... +``` ## 预训练模型加载代码详解 -在增量学习时,需要加载预训练模型。不同数据集和任务中特征提取层(卷积层)分布趋于一致,但是特征向量的组合(全连接层)不相同,分类数量(全连接层output_size)通常也不一致。在增量学习时,只加载与训练特征提取层参数,不加载与训练全连接层参数;在微调与初始训练,加载与训练特征提取层参数与全连接层参数。 +在增量学习时,需要加载预训练模型。不同数据集和任务中特征提取层(卷积层)分布趋于一致,但是特征向量的组合(全连接层)不相同,分类数量(全连接层output_size)通常也不一致。在增量学习时,只加载与训练特征提取层参数,不加载与训练全连接层参数;在微调与初始训练时,加载与训练特征提取层参数与全连接层参数。 在训练与测试之前,首先按照代码第1行,构建MobileNetV2的backbone网络,head网络,并且构建包含这两个子网络的MobileNetV2网络。代码第4-21行展示了如何在`fine_tune`训练模式下,将预训练模型加载入`net`(MobileNetV2);在`incremental_learn`训练模式下,将预训练模型分别加载入backbone与head两个子网络,并且冻结住backbone子网络中的参数,不参与训练。代码第23-31行展示了如何冻结网络参数。 ```python - 1: # define network - 2: backbone_net, head_net, net = define_net(args_opt, config) - 3: ... - 4: # load the ckpt file to the network for fine tune, incremental leaning or train - 5: def define_net(args, config): - 6: backbone_net = MobileNetV2Backbone(platform=args.platform) - 7: head_net = MobileNetV2Head(input_channel=backbone_net.out_channels, num_classes=config.num_classes) - 8: net = mobilenet_v2(backbone_net, head_net) - 9: -10: # load the ckpt file to the network for fine tune or incremental leaning -11: if args.pretrain_ckpt: -12: if args.train_method == "fine_tune": -13: load_ckpt(net, args.pretrain_ckpt) -14: elif args.train_method == "incremental_learn": -15: load_ckpt(backbone_net, args.pretrain_ckpt, trainable=False) -16: elif args.train_method == "train": -17: pass -18: else: -19: raise ValueError("must input the usage of pretrain_ckpt when the pretrain_ckpt isn't None") -20: -21: return backbone_net, head_net, net -22: ... -23: def load_ckpt(network, pretrain_ckpt_path, trainable=True): -24: """ -25: incremental_learning or not -26: """ -27: param_dict = load_checkpoint(pretrain_ckpt_path) -28: load_param_into_net(network, param_dict) -29: if not trainable: -30: for param in network.get_parameters(): -31: param.requires_grad = False + 1: backbone_net, head_net, net = define_net(args_opt, config) + 2: ... + 3: def define_net(args, config): + 4: backbone_net = MobileNetV2Backbone(platform=args.platform) + 5: head_net = MobileNetV2Head(input_channel=backbone_net.out_channels, num_classes=config.num_classes) + 6: net = mobilenet_v2(backbone_net, head_net) + 7: if args.pretrain_ckpt: + 8: if args.train_method == "fine_tune": + 9: load_ckpt(net, args.pretrain_ckpt) +10: elif args.train_method == "incremental_learn": +11: load_ckpt(backbone_net, args.pretrain_ckpt, trainable=False) +12: elif args.train_method == "train": +13: pass +14: else: +15: raise ValueError("must input the usage of pretrain_ckpt when the pretrain_ckpt isn't None") +16: return backbone_net, head_net, net +17: ... +18: def load_ckpt(network, pretrain_ckpt_path, trainable=True): +19: """ +20: incremental_learning or not +21: """ +22: param_dict = load_checkpoint(pretrain_ckpt_path) +23: load_param_into_net(network, param_dict) +24: if not trainable: +25: for param in network.get_parameters(): +26: param.requires_grad = False ``` ## 参数简介 -使用CPU训练时,运行`finetune.py`并且传入`dataset_path`、`pre_trained`与`platform`三个参数。使用GPU或Ascend AI处理器是,运行训练与验证脚本`./scripts/fun_train.sh`与`./scripts/infer.sh`时读取训练参数。 - -训练与验证时,可以根据系统支持直接运行``train.py``和``eval.py``,或者使用shell脚本``run_train.sh``和``run_eval.sh``调用``train.py``、``eval.py``运行训练与验证。 +在Windows与Linux系统上训练时,运行`train.py`并且传入`dataset_path`、`pretrain_ckpt`与`platform`三个参数。在Linux系统上时,还可以使用shell脚本文件`./scripts/fun_train.sh`与`./scripts/infer.sh`,运行时读取参数。 ```shell # windows doesn't support shell @@ -211,7 +207,7 @@ wget -P ./pretrain_checkpoint https://download.mindspore.cn/model_zoo/official/l python train.py --dataset_path [dataset_path] --pretrain_ckpt [pretrain_checkpoint_path] --platform [platform] --train_method[("train", "fine_tune", "incremental_learn")] # windows/Linux eval with python file -python eval.py --dataset_path [dataset_path] --pretrain_ckpt [pretrain_checkpoint_path] --platform [platform] +python eval.py --dataset_path [dataset_path] --pretrain_ckpt [pretrain_checkpoint_path] --head_ckpt [head_ckpt_path] --platform [platform] # Linux train with shell script sh run_train.sh [PLATFORM] [DEVICE_NUM] [VISIABLE_DEVICES(0,1,2,3,4,5,6,7)] [RANK_TABLE_FILE] [DATASET_PATH] [CKPT_PATH] [TRAIN_METHOD] @@ -220,7 +216,7 @@ sh run_train.sh [PLATFORM] [DEVICE_NUM] [VISIABLE_DEVICES(0,1,2,3,4,5,6,7)] [RAN sh run_eval.sh [PLATFORM] [DATASET_PATH] [CKPT_PATH] # Linux eval with shell script for train or incremental learn -sh run_eval.sh [PLATFORM] [DATASET_PATH] [BACKBONE_CKPT_PATH] [HEAD_CKPT_PATH] +sh run_eval.sh [PLATFORM] [DATASET_PATH] [PRETRAIN_CKPT_PATH] [HEAD_CKPT_PATH] ``` @@ -228,6 +224,7 @@ sh run_eval.sh [PLATFORM] [DATASET_PATH] [BACKBONE_CKPT_PATH] [HEAD_CKPT_PATH] - `--dataset_path`:训练与验证数据集地址,无默认值,用户训练/验证时必须输入。 - `--pretrain_ckpt`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 +- `--head_ckpt`:增量训练模型验证时,需要传入head_net预训练模型路径以加载预训练好的模型参数权重。 - `--platform`:芯片,默认为“Ascend”,可以设置为“CPU”或"GPU"。 - `--train_method`:训练方法,必须输入“train"、"fine_tune"和incremental_learn"其中一个。 @@ -240,7 +237,7 @@ sh run_eval.sh [PLATFORM] [DATASET_PATH] [BACKBONE_CKPT_PATH] [HEAD_CKPT_PATH] - `[DATASET_PATH]`:训练与验证数据集地址,无默认值,用户训练/验证时必须输入。 - `[CKPT_PATH]`:增量训练或调优时,需要传入checkpoint文件路径以加载预训练好的模型参数权重。 - `[TRAIN_METHOD]`:训练方法,必须输入`train`、`fine_tune`和`incremental_learn`其中一个。 -- `[BACKBONE_CKPT_PATH]`:针对增量学习的模型做验证时,需要输入主干网络层保存模型路径。 +- `[PRETRAIN_CKPT_PATH]`:针对增量学习的模型做验证时,需要输入主干网络层保存模型路径。 - `[HEAD_CKPT_PATH]`:针对增量学习的模型做验证时,需要输入全连接层保存模型路径。 @@ -248,8 +245,8 @@ sh run_eval.sh [PLATFORM] [DATASET_PATH] [BACKBONE_CKPT_PATH] [HEAD_CKPT_PATH] ### 开始增量训练 -在windows系统上,`MobileNetV2`做增量训练时,只能运行`train.py`[参数](#训练参数简介)。 -在Linux系统时,使用`MobileNetV2`做增量训练时,可以运行`run_train.sh`, 并在在运行shell脚本文件时传入[参数](#训练参数简介)。 +在windows系统上,`MobileNetV2`做增量训练时,只能运行`train.py`。 +在Linux系统时,使用`MobileNetV2`做增量训练时,也可以选择运行`run_train.sh`, 并在在运行shell脚本文件时传入[参数](#训练参数简介)。 Windows系统输出信息到交互式命令行,Linux系统环境下运行`run_train.sh`时,命令行结尾使用`&> [log_file_path]`将标准输出与错误输出写入log文件。 增量训练成功开始训练,`./train/device*/log*.log`中会持续写入每一个epoch的训练时间与Loss等信息。若未成功,上述log文件会写入失败报错信息。 @@ -332,20 +329,15 @@ sh run_train.sh Ascend 8 0,1,2,3,4,5,6,7 ~/rank_table.json /store/dataset/OpenIm 输出结果如下: ```shell - saved feature_0 - saved feature_1 - saved feature_2 - ... - saved feature_14 - saved feature_15 - saved feature_16 - epoch[1], iter[17] cost: 5494.584, per step time: 323.211, avg loss: 1.996, lr: 0.0300 - epoch[2], iter[17] cost: 5244.241, per step time: 308.485, avg loss: 1.047, lr: 0.0300 - epoch[3], iter[17] cost: 5270.173, per step time: 310.010, avg loss: 0.936, lr: 0.0300 - ... - epoch[13], iter[17] cost: 5243.293, per step time: 308.429, avg loss: 0.726, lr: 0.0300 - epoch[14], iter[17] cost: 5248.263, per step time: 308.721, avg loss: 0.721, lr: 0.0300 - epoch[15], iter[17] cost: 5263.191, per step time: 309.599, avg loss: 0.718, lr: 0.0300 + train args: Namespace(dataset_path='.\\dataset\\train', platform='CPU', \ + pretrain_ckpt='.\\pretrain_checkpoint\\mobilenetV2.ckpt', train_method='incremental_learn') + cfg: {'num_classes': 26, 'image_height': 224, 'image_width': 224, 'batch_size': 150, \ + 'epoch_size': 15, 'warmup_epochs': 0, 'lr_max': 0.03, 'lr_end': 0.03, 'momentum': 0.9, \ + 'weight_decay': 4e-05, 'label_smooth': 0.1, 'loss_scale': 1024, 'save_checkpoint': True, \ + 'save_checkpoint_epochs': 1, 'keep_checkpoint_max': 20, 'save_checkpoint_path': './checkpoint', \ + 'platform': 'CPU'} + Processing batch: 16: 100%|███████████████████████████████████████████ █████████████████████| 16/16 [00:00