OpenMMLab 实战营打卡 - 第 三 课
Posted 苦瓜汤补钙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenMMLab 实战营打卡 - 第 三 课相关的知识,希望对你有一定的参考价值。
图像分类代码实战与超算平台介绍
目录
(1)加载 anaconda ,创建⼀个 python 3.8 的环境。
(4)安装 openmmlab/mmclassification 模块
前言
第三堂课:计算机视觉之图像分类代码教学,你想了解的环境配置和代码实操都在链接里啦!第三堂课程链接:3 图像分类代码实战与超算平台介绍_哔哩哔哩_bilibili
一、图像分类工具包MMClassification
1.MMClassification介绍
MMClassification实际上是专门针对图像分类做的代码库,所有代码都放在github上面(代码仓库:open-mmlab/mmclassification: OpenMMLab Image Classification Toolbox and Benchmark (github.com)),也有对应的文档(文档教程:Welcome to MMClassification’s documentation! — MMClassification 0.25.0 documentation)。MMClassification提供丰富的模型,也支持很多数据集以及训练的策略,同时提供大量应用的工具以及预训练的模型。我们可以拿一些预训练的模型做推理的任务,比如实现预测图像的信息,集成到系统。也可以定义自己的网络或者数据,基于MMClassification里面的工具或策略去训练自己的模型。当然MMClassification还有其他的辅助功能,比如包括对模型可解释性的分析。整个代码库遵循MMClassification体系的模块化设计,可以按照模块找寻相应代码去定制、debug,可以抠代码出来放入自己的代码库。
(1)Python推理API
一行代码可以下载一个预训练的模型和权重$ mim download mmcls --config mobilenet-v2_8xb32_in1k --dest,然后写几行Python实现简单的图像分类的推理,如下图所示会告诉我们图像内容是什么、对应预测的概率。
(2)推理工具&训练工具
推理工具和训练工具都需要源码安装。
推理工具使用说明:Getting Started — MMClassification 0.25.0 documentation
#单张图推理
python demo/image_demo.py $IMAGE_FILE $CONFIG_FILE $CHECKPOINT_FILE
#在测试集上测试
#单卡
python tools/test.py $CONFIG_FILE $CHECKPOINT_FILE [--metrics $METRICS] [--out
$RESULT_FILE]
#多机多卡
./tools/dist_test.sh $CONFIG_FILE $CHECKPOINT_FILE $GPU_NUM [--metrics $METRICS] [--out
$RESULT_FILE]
训练工具使用说明:Getting Started — MMClassification 0.25.0 documentation
#单卡训练
python tools/train.py $CONFIG_FILE [optional arguments]
#单机、多机多卡训练
./tools/dist_train.sh $CONFIG_FILE $GPU_NUM [optional arguments]
#使用任务调度器 Slurm 启动任务
[GPUS=$GPUS] ./tools/slurm_train.sh $PARTITION $JOB_NAME $CONFIG_FILE $WORK_DIR
#从 checkpoint 恢复训练
增加 --resume-from $CHECKPOINT_FILE 参数
(3)使用MIM工具实现训练和测试
MIM 为所有 OpenMMLab 工具提供了统一的命令行接口。
下载配置文件和预训练模型:
mim download mmcls --config mobilenet-v2_8xb32_in1k --dest .
mim train mmcls 参数同 mmcls 自己的 train.py
mim train mmcls 参数同 mmcls 自己的 train.py -G 4 –g 4 –p $PARTITION --launcher slurm
测试
mim test mmcls 参数同 mmcls 自己的 test.py --gpus 4 --launcher pytorch
2.软件环境
通常这个软件的环境底层是我们的硬件,可以支持在CPU、GPU,然后操作系统支持Windows和Linux,基于python和pytorch(一定要安装)。OpenMMLab自己的东西主要是最底层的基础库MMCV,基于MMCV搭建了不同任务的库,以及MIM工具(用于管理)三部分。
二、北京超级云计算中心
1.中心介绍
北京超级云计算中心(简称“北京超算”),2011年11月在北京怀柔综合性国家科学中心—怀柔科学城奠基成立,是由北京市人民政府主导、院市共建的“北京超级云计算和国家重要信息化基础平台”。是一家面向科学计算、工业仿真、气象海洋、新能源、生物医药、人工智能等重点行业应用领域,提供随需供应的超级云计算服务提供商。
北龙超云负责运营的北京超级云计算中心于2020年、2021年、2022年连续三年获得中国HPCTOP100排行榜“通用CPU算力性能第一名”。同时在2021年AI Perf5O0榜单中,北京超级云计算中心共计10套AI算力系统上榜,获得总量份额第一名。
2.平台简介
北京超算网站:北京超级云计算中心 (blsc.cn)
下载客户端并登录,可以看见云桌面有许多应用。快传,平台与本地的一个传输通道。SSH,在Linux上使用的一种终端工具。
三、花卉分类
1.环境搭建
打开北京超算SSH,根据 mmclassification 的环境要求,需要⽤ anaconda、cuda、gcc 等基础环境模块。在 N26分区(因为我的超算账号在26分区,也可使用30分区),可以使⽤ module avail 命令可以使⽤模块信息。
(1)加载 anaconda ,创建⼀个 python 3.8 的环境。
由于我在26分区,所以anaconda只有2020.11这个版本,人工你是在30分区那么你还可以选择加载anaconda2021.05。
# 加载 anaconda/2020.11
module load anaconda/2020.11
# 创建 python=3.8 的环境
conda create --name opennmmlab_mmclassification python=3.8
# 激活环境
source activate opennmmlab_mmclassification
激活环境后,安装torch。
(2)torch安装
torch 参考官⽹需求。注意在 RTX3090 的GPU上,cuda 版本需要 ≥ 11.1 。 如下安装的 torch 是 1.10.0+cu111 。
# 加载 cuda/11.1
module load cuda/11.1
# 安装 torch
pip install torch==1.10.0+cu111 torchvision==0.11.0+cu111 torchaudio==0.10.0 -f
https://download.pytorch.org/whl/torch_stable.html
使⽤ pip 安装的torch 不包括 cuda,所以需要使⽤ module 加载 cuda/11.1 模块。安装时间根据不同网络情况有所不同。
(3)安装mmcv-full模块
mmcv-full 模块安装时候需要注意 torch 和 cuda 版本,参考这⾥ 。
pip install mmcv-full==1.7.0 -f
https://download.openmmlab.com/mmcv/dist/cu111/torch1.10/index.html
(4)安装 openmmlab/mmclassification 模块
建议通过下载编译的⽅式进⾏安装;安装该模块需要 gcc ≥ 5, 使⽤ module 加载⼀个 gcc ,例如 module load gcc/7.3 。
# 加载 gcc/7.3 模块
module load gcc/7.3
# git 下载 mmclassification 代码
git clone https://github.com/open-mmlab/mmclassification.git
# 编译安装
cd mmclassification
pip install -e .
(5)总结环境信息
可以使⽤ module list 查看当前环境中加载的依赖模块。
$ module list
(6)准备shell脚本,将环境预先保存在脚本中。
#!/bin/bash
# 加载模块
module load anaconda/2020.11
module load cuda/11.1
module load gcc/7.3
# 激活环境
source activate opennmmlab_mmclassification
2.数据集
flower 数据集包含 5 种类别的花卉图像:雏菊 daisy 588张,蒲公英 dandelion 556张,玫瑰 rose 583张,向⽇葵 sunflower 536张,郁⾦⾹ tulip 585张。由于某些原因我是在本地跑的程序,下图为本地运行截图,后续介绍为课程上N30分区的讲解。
(1)将数据集按照 8:2 的⽐例划分成训练和验证⼦数据集,并将数据集整理成ImageNet的格式将训练⼦集和验证⼦集放到 train 和 val ⽂件夹下。
1 flower_dataset
2 |--- classes.txt
3 |--- train.txt
4 |--- val.txt
5 | |--- train
6 | | |--- daisy
7 | | | |--- NAME1.jpg
8 | | | |--- NAME2.jpg
9 | | | |--- ...
10 | | |--- dandelion
11 | | | |--- NAME1.jpg
12 | | | |--- NAME2.jpg
13 | | | |--- ...
14 | | |--- rose
15 | | | |--- NAME1.jpg
16 | | | |--- NAME2.jpg
17 | | | |--- ...
18 | | |--- sunflower
19 | | | |--- NAME1.jpg
20 | | | |--- NAME2.jpg
21 | | | |--- ...
22 | | |--- tulip
23 | | | |--- NAME1.jpg
24 | | | |--- NAME2.jpg
25 | | | |--- ...
26 | |--- val
27 | | |--- daisy
28 | | | |--- NAME1.jpg
29 | | | |--- NAME2.jpg
30 | | | |--- ...
31 | | |--- dandelion
32 | | | |--- NAME1.jpg
33 | | | |--- NAME2.jpg
34 | | | |--- ...
35 | | |--- rose
36 | | | |--- NAME1.jpg
37 | | | |--- NAME2.jpg
38 | | | |--- ...
39 | | |--- sunflower
40 | | | |--- NAME1.jpg
41 | | | |--- NAME2.jpg
42 | | | |--- ...
43 | | |--- tulip
44 | | | |--- NAME1.jpg
45 | | | |--- NAME2.jpg
46 | | | |--- ...
- 创建并编辑标注⽂件将所有类别的名称写到 classes.txt 中,每⾏代表⼀个类别。
1 tulip
2 dandelion
3 daisy
4 sunflower
5 rose
- ⽣成训练(可选)和验证⼦集标注列表 train.txt 和 val.txt ,每⾏应包含⼀个⽂件名和其对应的标签。如下,可将处理好的数据集迁移到 mmclassification/data ⽂件夹下。
1 ...
2 daisy/NAME**.jpg 0
3 daisy/NAME**.jpg 0
4 ...
5 dandelion/NAME**.jpg 1
6 dandelion/NAME**.jpg 1
7 ...
8 rose/NAME**.jpg 2
9 rose/NAME**.jpg 2
10 ...
11 sunflower/NAME**.jpg 3
12 sunflower/NAME**.jpg 3
13 ...
14 tulip/NAME**.jpg 4
15 tulip/NAME**.jpg 4
- 数据集划分代码 split_data.py 如下,执⾏:python split_data.py [源数据集路径] [⽬标数据集路径]
1 import os
2 import sys
3 import shutil
4 import numpy as np
5
6
7 def load_data(data_path):
8 count = 0
9 data =
10 for dir_name in os.listdir(data_path):
11 dir_path = os.path.join(data_path, dir_name)
12 if not os.path.isdir(dir_path):
13 continue
14
15 data[dir_name] = []
16 for file_name in os.listdir(dir_path):
17 file_path = os.path.join(dir_path, file_name)
18 if not os.path.isfile(file_path):
19 continue
20 data[dir_name].append(file_path)
21
22 count += len(data[dir_name])
23 print(" :".format(dir_name, len(data[dir_name])))
24
25 print("total of image : ".format(count))
26 return data
27
28
29 def copy_dataset(src_img_list, data_index, target_path):
30 target_img_list = []
31 for index in data_index:
32 src_img = src_img_list[index]
33 img_name = os.path.split(src_img)[-1]
34
35 shutil.copy(src_img, target_path)
36 target_img_list.append(os.path.join(target_path, img_name))
37 return target_img_list
38
39
40 def write_file(data, file_name):
41 if isinstance(data, dict):
42 write_data = []
43 for lab, img_list in data.items():
44 for img in img_list:
45 write_data.append(" ".format(img, lab))
46 else:
47 write_data = data
48
49 with open(file_name, "w") as f:
50 for line in write_data:
51 f.write(line + "\\n")
52
53 print(" write over!".format(file_name))
54
55
56 def split_data(src_data_path, target_data_path, train_rate=0.8):
57 src_data_dict = load_data(src_data_path)
58
59 classes = []
60 train_dataset, val_dataset = ,
61 train_count, val_count = 0, 0
62 for i, (cls_name, img_list) in enumerate(src_data_dict.items()):
63 img_data_size = len(img_list)
random_index = np.random.choice(img_data_size, img_data_size,
replace=False)
64
65
66 train_data_size = int(img_data_size * train_rate)
67 train_data_index = random_index[:train_data_size]
68 val_data_index = random_index[train_data_size:]
69
70 train_data_path = os.path.join(target_data_path, "train", cls_name)
71 val_data_path = os.path.join(target_data_path, "val", cls_name)
72 os.makedirs(train_data_path, exist_ok=True)
73 os.makedirs(val_data_path, exist_ok=True)
74
75 classes.append(cls_name)
train_dataset[i] = copy_dataset(img_list, train_data_index,
train_data_path)
76
77 val_dataset[i] = copy_dataset(img_list, val_data_index, val_data_path)
78
print("target train:, val:".format(cls_name,
len(train_dataset[i]), len(val_dataset[i])))
79
80 train_count += len(train_dataset[i])
81 val_count += len(val_dataset[i])
82
print("train size:, val size:, total:".format(train_count, val_count,
train_count + val_count))
83
84
85 write_file(classes, os.path.join(target_data_path, "classes.txt"))
86 write_file(train_dataset, os.path.join(target_data_path, "train.txt"))
87 write_file(val_dataset, os.path.join(target_data_path, "val.txt"))
88
89
90 def main():
91 src_data_path = sys.argv[1]
92 target_data_path = sys.argv[2]
93 split_data(src_data_path, target_data_path, train_rate=0.8)
94
95
96 if __name__ == '__main__':
97 main()
3.MMCls配置文件
构建配置⽂件可以使⽤继承机制,从 configs/base 中继承 ImageNet 预训练的任何模型,ImageNet 的数据集配置,学习率策略等。
在 mmclassification/configs 下创建 resnet18 ⽬录,放入resnet18_b32_flower.py。
_base_ = ['../_base_/models/resnet18.py', '../_base_/datasets/imagenet_bs32.py', '../_base_/default_runtime.py']
model = dict(
head=dict(
num_classes=5,
topk = (1, )
))
data = dict(
samples_per_gpu = 32,
workers_per_gpu = 2,
train = dict(
data_prefix = '/HOME/yourname/run/mmclassification/data/flower/train',
ann_file = '/HOME/yourname/run/mmclassification/data/flower/train.txt',
classes = '/HOME/yourname/run/mmclassification/data/flower/classes.txt'
),
val = dict(
data_prefix = '/HOME/yourname/run/mmclassification/data/flower/val',
ann_file = '/HOME/yourname/run/mmclassification/data/flower/val.txt',
classes = '/HOME/yourname/run/mmclassification/data/flower/classes.txt'
)
)
optimizer = dict(type='SGD', lr=0.001, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
policy='step',
step=[1])
runner = dict(type='EpochBasedRunner', max_epochs=100)
# 预训练模型
load_from ='/HOME/yourname/run/mmclassification/checkpoints/resnet18_batch256_imagenet_20200708-34ab8f90.pth'
4.提交计算
单卡计算,在环境、数据集、MMCls 配置⽂件准备完成之后就可以提交计算。在 N30 提交计算可以通过作业脚本的⽅式,操作步骤如下:
(1)新建⼀个作业脚本 run.sh,脚本的解释器可以是 /bin/sh、/bin/bash、/bin/csh 脚本内容如下:########注意–work-dir 指定的work就是最后模型存放的空间########
#!/bin/bash
# 加载模块
module load anaconda/2021.05
module load cuda/11.1
module load gcc/7.3
# 激活环境
source activate opennmmlab_mmclassification
# 刷新⽇志缓存
export PYTHONUNBUFFERED=1
# 训练模型
python tools/train.py \\
configs/resnet/resnet18_b32_flower.py \\
--work-dir work/resnet18_b32_flower
(2)使⽤ sbatch 命令提交作业脚本。
sbatch --gpus=1 run.sh
–gpus 可以指定申请 GPU 的卡数,在 N30 分区可以申请的 GPU 卡数范围为 1~8,默认每卡配置 6核CPU、60GB 内存。 执⾏ sbatch --gpus=1 run.sh 命令之后可申请到 1 GPU、6 核 CPU、60GB 内存。
提交成功之后会输出作业信息 “Submitted batch job xxxx” 其中 xxxx为作业ID,可以通过作业ID查看⽇志信息。
(3)使⽤ squeue 或 parajobs 查看提交的作业。
(4)查看作业输出⽇志。默认标准输出和标准出错都定向到⼀个 slurm-%j.log (“%j” 为作业ID)⽂件中,当作业状态是 R 的时候,可在当前提交的路径下看到。可以通过 tail 等命令查看⽇志输出。
总结
以上就是今天笔记打卡的内容,本文仅仅简单介绍了图像分类代码实战和北京超算的使用。
以上是关于OpenMMLab 实战营打卡 - 第 三 课的主要内容,如果未能解决你的问题,请参考以下文章