새소식

반응형
Vision AI/미분류

mmclassification config 작성법

  • -
반응형

2023. 4. 16 기준

 

https://github.com/open-mmlab/mmpretrain/tree/mmcls-0.x

openmmlab의 mmclassification이 mmpretrain으로 바뀐 것 같습니다. 간략히 살펴본 결과 매커니즘은 크게 바뀌지 않은 것 같으니, 일단은 dev-1.x 브랜치의 config 작성법 위주로 작성해보려고 합니다. mmcls-0.x 브랜치로도 작성할 수 있지만, dev 브랜치의 특정 기능 때문에 dev 브랜치를 사용중입니다. dev와 master 브랜치의 큰 틀은 다르지 않으니 걱정하지 않으셔도 됩니다.

 

mmpretrain 또한 거의 구조가 같습니다. 추후에 mmpretrain도 올려보도록 하겠습니다.

 

저만의 편한 방법을 찾아서 쓰고 있는 방법이니, 참고자료 정도로 봐주시면 좋을 것 같습니다.

예시로, efficientnet-b0을 이용한 config를 작성해보겠습니다.

 

 

1. configs/사용할모델(efficientnet)/efficientnet-b0_8xb32_in1k.py 파일을 복사해서 편한 경로에 둡니다.

 

2. 그러면 아래와 같은 정보가 입력되어 있을 것입니다. 보면 augmentation과 data loader가 정의되어 있습니다. 그리고, 모델이나 lr 스케줄러 같은 정보는 _base_ 에서 가져오는 형식으로 되어 있습니다.

_base_ = [
    '../_base_/models/efficientnet_b0.py',
    '../_base_/datasets/imagenet_bs32.py',
    '../_base_/schedules/imagenet_bs256.py',
    '../_base_/default_runtime.py',
]

# dataset settings
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='EfficientNetRandomCrop', scale=224),
    dict(type='RandomFlip', prob=0.5, direction='horizontal'),
    dict(type='PackClsInputs'),
]

test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='EfficientNetCenterCrop', crop_size=224),
    dict(type='PackClsInputs'),
]

train_dataloader = dict(dataset=dict(pipeline=train_pipeline))
val_dataloader = dict(dataset=dict(pipeline=test_pipeline))
test_dataloader = dict(dataset=dict(pipeline=test_pipeline))

 

3. 이제, base 인스턴스의 경로들의 파일에 들어갑니다.

 

4. 하나하나 복사해서 1번의 경로 스크립트에 붙여줍니다.

 

5. 그러면 아래와 같은 스크립트가 될 것입니다.

# defaults to use registries in mmcls
default_scope = 'mmcls'

# configure default hooks
default_hooks = dict(
    # record the time of every iteration.
    timer=dict(type='IterTimerHook'),

    # print log every 100 iterations.
    logger=dict(type='LoggerHook', interval=100),

    # enable the parameter scheduler.
    param_scheduler=dict(type='ParamSchedulerHook'),

    # save checkpoint per epoch.
    checkpoint=dict(type='CheckpointHook', interval=1),

    # set sampler seed in distributed evrionment.
    sampler_seed=dict(type='DistSamplerSeedHook'),

    # validation results visualization, set True to enable it.
    visualization=dict(type='VisualizationHook', enable=False),
)

# configure environment
env_cfg = dict(
    # whether to enable cudnn benchmark
    cudnn_benchmark=False,

    # set multi process parameters
    mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),

    # set distributed parameters
    dist_cfg=dict(backend='nccl'),
)

# set visualizer
vis_backends = [dict(type='LocalVisBackend')]
visualizer = dict(type='ClsVisualizer', vis_backends=vis_backends)

# set log level
log_level = 'INFO'

# load from which checkpoint
load_from = None

# whether to resume training from the loaded checkpoint
resume = False

# Defaults to use random seed and disable `deterministic`
randomness = dict(seed=None, deterministic=False)

# optimizer
optim_wrapper = dict(
    optimizer=dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0001))

# learning policy
param_scheduler = dict(
    type='MultiStepLR', by_epoch=True, milestones=[30, 60, 90], gamma=0.1)

# train, val, test setting
train_cfg = dict(by_epoch=True, max_epochs=100, val_interval=1)
val_cfg = dict()
test_cfg = dict()

# NOTE: `auto_scale_lr` is for automatically scaling LR,
# based on the actual training batch size.
auto_scale_lr = dict(base_batch_size=256)

# dataset settings
dataset_type = 'ImageNet'
data_preprocessor = dict(
    num_classes=1000,
    # RGB format normalization parameters
    mean=[123.675, 116.28, 103.53],
    std=[58.395, 57.12, 57.375],
    # convert image from BGR to RGB
    to_rgb=True,
)

train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='RandomResizedCrop', scale=224),
    dict(type='RandomFlip', prob=0.5, direction='horizontal'),
    dict(type='PackClsInputs'),
]

test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='ResizeEdge', scale=256, edge='short'),
    dict(type='CenterCrop', crop_size=224),
    dict(type='PackClsInputs'),
]

train_dataloader = dict(
    batch_size=32,
    num_workers=5,
    dataset=dict(
        type=dataset_type,
        data_root='data/imagenet',
        ann_file='meta/train.txt',
        data_prefix='train',
        pipeline=train_pipeline),
    sampler=dict(type='DefaultSampler', shuffle=True),
)

val_dataloader = dict(
    batch_size=32,
    num_workers=5,
    dataset=dict(
        type=dataset_type,
        data_root='data/imagenet',
        ann_file='meta/val.txt',
        data_prefix='val',
        pipeline=test_pipeline),
    sampler=dict(type='DefaultSampler', shuffle=False),
)
val_evaluator = dict(type='Accuracy', topk=(1, 5))

# If you want standard test, please manually configure the test dataset
test_dataloader = val_dataloader
test_evaluator = val_evaluator

# model settings
model = dict(
    type='ImageClassifier',
    backbone=dict(type='EfficientNet', arch='b0'),
    neck=dict(type='GlobalAveragePooling'),
    head=dict(
        type='LinearClsHead',
        num_classes=1000,
        in_channels=1280,
        loss=dict(type='CrossEntropyLoss', loss_weight=1.0),
        topk=(1, 5),
    ))

# dataset settings
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='EfficientNetRandomCrop', scale=224),
    dict(type='RandomFlip', prob=0.5, direction='horizontal'),
    dict(type='PackClsInputs'),
]

test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='EfficientNetCenterCrop', crop_size=224),
    dict(type='PackClsInputs'),
]

train_dataloader = dict(dataset=dict(pipeline=train_pipeline))
val_dataloader = dict(dataset=dict(pipeline=test_pipeline))
test_dataloader = dict(dataset=dict(pipeline=test_pipeline))

 

6. 기본적인 세팅과, 디폴트 하이퍼파라미터들이 세팅되어 있습니다. 사실 여기서 나의 데이터셋 경로, 내가 분류하고 싶은 num_classes만 수정해주면 바로 학습을 시도해볼 수 있습니다. 학습을 위해 데이터셋 세팅 방법을 알아봅시다.

 

# 폴더 트리 구조
data
    |— 이미지_폴더
    |        |— image1.jpg
    |        |— image2.jpg 
    |        |— ….
    |— annotation_폴더
             |— train_list.txt
             |— validation_list.txt
  • 데이터셋 세팅 방법
    • 폴더 트리 구조는 위와 같습니다. 티스토리에 이쁘게 넣기가 어렵네요..
    • 이미지 폴더에는 이미지 파일을 몽땅 넣어두시면 됩니다.
    • annotation 폴더에는 학습과 검증셋을 분류해서 텍스트파일로 두시면 됩니다.
    • 텍스트 파일 형식 예시는 다음과 같습니다.
      • 예시)
        image1.jpg 333
        image2.jpg 232
        image1.jpg 1
        …..
    • config의 데이터셋 경로는 아래과 같이 수정하시면 됩니다.
train_dataloader = dict(
    batch_size=32,
    num_workers=5,
    dataset=dict(
        type=dataset_type,
        data_root='data/이미지_폴더',
        ann_file='annotation_폴더/train_list.txt',
        data_prefix='train',
        pipeline=train_pipeline),
    sampler=dict(type='DefaultSampler', shuffle=True),
)

val_dataloader = dict(
    batch_size=32,
    num_workers=5,
    dataset=dict(
        type=dataset_type,
        data_root='data/이미지_폴더',
        ann_file='annotation_폴더/validation_list.txt',
        data_prefix='vallidation',
        pipeline=test_pipeline),
    sampler=dict(type='DefaultSampler', shuffle=False),
)

 

 

7. 데이터셋 세팅 후에 하이퍼파라미터를 맞게 조정하시고 다음 스크립트를 터미널에 입력하시면 학습이 될 것입니다.

bash ./tools/dist_train.sh config_경로 GPU_사용갯수

 

저는 다음과 같이 주로 사용합니다.

CUDA_VISIBLE_DEVICES=0,1,2,3 ./tools/dist_train.sh config_경로 4
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감과 광고 클릭 부탁드립니다~