Bootstrap

OpenMMLab实战营打卡-第3课

一、配置环境

北京超算平台

参加openmmlab课程的同学可以通过给出的申请二维码扫描,完善信息问卷后等待几个工作日邮箱会发送回复,还可以自己搜索“北京超级云计算中心”微信公众号,关注后回复“2”即可获取申请试算通道

1.客户端安装

收到邮件回复后,邮件中会注明是哪个区的服务器

然后按照邮件要求,点击北京超算链接,下载客户端并登陆,如果不知道密码是啥也是可以在邮件中看到有重置密码的链接

2.创建环境

北京超算是用module来管理应用软件的,module的常用命令有

可以用 module avail 命令看平台支持的框架和工具:

我们使用cuda 11.6和anaconda 2021.05这2个作为基础。

在anaconda环境中新建名为 openmmlab ,Python3.8 版本的环境。

(1)加载cuda

module load cuda/11.6

(2)加载anaconda

module load anaconda/2021.05

(3)创建环境

conda create --name openmmlab python=3.8

(4)激活新建的openmmlab环境

source activate openmmlab

(5)安装pytorch:

打开pytorch链接:https://pytorch.org/get-started/locally/#start-locally

选择对应选项,底下会出来命令:

输入命令:

conda install pytorch torchvision torchaudio pytorch-cuda=11.6 -c pytorch -c nvidia

等待安装完成后,可以通过如下命令查看当前torch版本

python -c 'import torch;print(torch.__version__)'
1.13.1

查看pytorch版本:

import torch

print(torch.__version__)  # 查看torch当前版本号

print(torch.version.cuda)  # 编译当前版本的torch使用的cuda版本号

print(torch.cuda.is_available())  # 查看当前cuda是否可用于当前版本的Torch,如果输出True,则表示可用

注意:最好是把CUDA_HOME也设置好

CUDA_HOME='/data/apps/cuda/11.6'

3.利用SSH配置本地Vscode

1、在超算平台点击控制台

2、点击右边的SSH直连管理

3、点击“创建密码/公钥”

4、根据“如何查看/添加公钥”创建公钥,并复制到下面的公钥区

5、粘贴自己的公钥:

6、打开VSCode,左下角Open a Remote Window

选择Connect to Host->选择Add New SSH Host->粘贴->选择本地的配置文件->选择Linux然后点Continue,连接成功。

二、MMClassification初探

1 加载gcc/9.3

module load gcc/9.3

2 克隆mmclassification

git clone https://github.com/open-mmlab/mmclassification.git

3 编译安装

cd mmclassification
mim install mmcv-full

4 下载数据集

flower 数据集包含 5 种类别的花卉图像:雏菊 daisy 588张,蒲公英 dandelion 556张,玫瑰 rose 583张,向⽇ 葵 sunflower 536张,郁⾦⾹ tulip 585张。 数据集下载链接:

国际⽹:https://www.dropbox.com/s/snom6v4zfky0flx/flower_dataset.zip?dl=0
国内⽹:https://pan.baidu.com/s/1RJmAoxCD_aNPyTRX6w97xQ 提取码: 9x5u

5 划分数据集

将数据集按照 8:2 的⽐例划分成训练和验证⼦数据集,并将数据集整理成 ImageNet的格式 。将训练⼦集和验证⼦集放到 train 和 val ⽂件夹下。

文件结构如下:

```
flower_dataset
|--- classes.txt
|--- train.txt
|--- val.txt
|    |--- train
|    |    |--- daisy
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- dandelion
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- rose
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- sunflower
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- tulip
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |--- val
|    |    |--- daisy
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- dandelion
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- rose
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- sunflower
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
|    |    |--- tulip
|    |    |    |--- NAME1.jpg
|    |    |    |--- NAME2.jpg
|    |    |    |--- ...
```

6 创建并编辑标注⽂件将所有类别的名称写到 classes.txt 中,每⾏代表⼀个类别。

dandelion
daisy
sunflower
rose
tulip

7 ⽣成训练(可选)和验证⼦集标注列表 train.txt 和 val.txt ,每⾏应包含⼀个⽂件名和其对应的标签。如下,可将处 理好的数据集迁移到 mmclassification/data ⽂件夹下。

```
...
daisy/NAME**.jpg 0
daisy/NAME**.jpg 0
...
dandelion/NAME**.jpg 1
dandelion/NAME**.jpg 1
...
rose/NAME**.jpg 2
rose/NAME**.jpg 2
...
sunflower/NAME**.jpg 3
sunflower/NAME**.jpg 3
...
tulip/NAME**.jpg 4
tulip/NAME**.jpg 4
```

注:把数据集下载到mmclassification/data目录下,同时新建data_split.py文件。

数据集划分代码 data_split.py 如下,执⾏:

import os
import sys
import shutil
import numpy as np

def load_data(data_path):
    count=0
    data={}
    for dir_name in os.listdir(data_path):
        dir_path = os.path.join(data_path,dir_name)
        if not os.path.isdir(dir_path):
            continue
        
        data[dir_name]=[]
        for file_name in os.listdir(dir_path):
            file_path = os.path.join(dir_path,file_name)
            if not os.path.isfile(file_path):
                continue
            data[dir_name].append(file_path)
        
        count+=len(data[dir_name])
        print("{} :{}".format(dir_name,len(data[dir_name])))
    print("total of image : {}".format(count))
    return data

def copy_dataset(src_img_list, data_index, target_path):
    target_img_list = []
    for index in data_index:
        src_img = src_img_list[index]
        img_name = os.path.split(src_img)[-1]

        shutil.copy(src_img, target_path)
        target_img_list.append(os.path.join(target_path, img_name))
    return target_img_list

def write_file(data, file_name):
    if isinstance(data, dict):
        write_data = []
        for lab, img_list in data.items():
            for img in img_list:
                write_data.append("{} {}".format(img, lab))
    else:
        write_data = data

    with open(file_name, "w") as f:
        for line in write_data:
            f.write(line + "\n")

    print("{} write over!".format(file_name))

def split_data(src_data_path, target_data_path, train_rate=0.8):
    src_data_dict = load_data(src_data_path)

    classes = []
    train_dataset, val_dataset = {}, {}
    train_count, val_count = 0, 0
    for i, (cls_name, img_list) in enumerate(src_data_dict.items()):
        img_data_size = len(img_list)
        random_index = np.random.choice(img_data_size, img_data_size,replace=False)

        train_data_size = int(img_data_size * train_rate)
        train_data_index = random_index[:train_data_size]
        val_data_index = random_index[train_data_size:]

        train_data_path = os.path.join(target_data_path, "train", cls_name)
        val_data_path = os.path.join(target_data_path, "val", cls_name)
        os.makedirs(train_data_path, exist_ok=True)
        os.makedirs(val_data_path, exist_ok=True)

        classes.append(cls_name)
        train_dataset[i] = copy_dataset(img_list, train_data_index,train_data_path)

        val_dataset[i] = copy_dataset(img_list, val_data_index, val_data_path)

        print("target {} train:{}, val:{}".format(cls_name,len(train_dataset[i]), len(val_dataset[i])))

        train_count += len(train_dataset[i])
        val_count += len(val_dataset[i])

    print("train size:{}, val size:{}, total:{}".format(train_count, val_count,train_count + val_count))

    write_file(classes, os.path.join(target_data_path, "classes.txt"))
    write_file(train_dataset, os.path.join(target_data_path, "train.txt"))
    write_file(val_dataset, os.path.join(target_data_path, "val.txt"))

def main():
    src_data_path = sys.argv[1]
    target_data_path = sys.argv[2]
    split_data(src_data_path, target_data_path, train_rate=0.8)

if __name__ == '__main__':
    main()

8 在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= 'data/flower/train',
        ann_file='data/flower/train.txt',
        classes='data/flower/classes.txt'
    ),
    val=dict(
        data_prefix= 'data/flower/val',
        ann_file='data/flower/val.txt',
        classes='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/scz4239/run/mmclassification/configs/resnet18/checkpoints/resnet18_batch256_imagenet_20200708-34ab8f90.pth'

9 下载预训练模型:

模型库:

https://mmclassification.readthedocs.io/zh_CN/latest/modelzoo_statistics.html

在自己新建的resnet18目录下,新建checkpoints文件夹,同时找到对应的模型下载:

mkdir checkpoints
wget
https://download.openmmlab.com/mmclassification/v0/resnet/resnet18_batch256_imag
enet_20200708-34ab8f90.pth -P checkpoints

10 在mmclassification根目录新建run.sh文件:

#!/bin/bash
module load anaconda/2021.05
module load cuda/11.6
module load gcc/9.3

source activate openmmlab
export PYTHONUNBUFFERED=1

python tools/train.py \
       configs/resnet18/resnet18_b32_flower.py \
       --work-dir work/resnet18_b32_flower

11 打开 北京超算平台终端,输入

sbatch --gpus=1 run.sh

12 结束后,在mmclassification/work目录下,会有Log日志、模型文件等。可以从log日志看到最后的acc:

2023-02-04 11:41:55,152 - mmcls - INFO - Saving checkpoint at 100 epochs
2023-02-04 11:41:56,124 - mmcls - INFO - Epoch(val) [100][18]    accuracy_top-1: 95.4545, accuracy_top-5: 100.0000

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;