3D Pose Estimation 딥러닝 실험 환경

나용수·2021년 2월 16일
1

pre-refinement에서 지수이동평균 필터의 효용같은 포스팅을 쓰면서, 여러가지 옵션을 비교할 필요를 느꼈다.

옵션은 물론이고, 모델 구조도 변화를 주면서 해야했는데, 이런 옵션을 for문으로 하드코딩하거나 argparse로 변화를 주면서 실험했었다.

문제는 이런 짓을 반복하다보니 여간 귀찮은 게 아니어서, config 파일에서 변화주고자 하는 옵션을 지정해서 실행하면 바로 경우의 수를 모두 계산해 실험해주는 환경을 간단하게 만들어 봤다.

이름하야 3D-Human-Pose-Estimation-Experiment-Environment. 줄여서 3D-HM-POSE-EST-EXP-ENV이다! (...)

레포 링크

일단 3D pose estimation의 two-step approach에 한정하여 개발했다.

pipeline이나 preprocessor, dataset 등만 조금 커스텀해주면 나머지는 자동으로 실험할 수 있다.

Variable:
  - Dataset/Generator/preprocessor_parameter

Pipeline:
  - tcn1024_nlb51

Dataset:
  dataset: h36m
  filepath: data/h36m_cpn+detectron+gt_2d_normalized+unnormlized_gt_3d.npy
  train_subjects: "S1,S5,S6,S7,S8"
  test_subjects: "S9,S11"
  
  Generator:
    preprocessor: EMA
    preprocessor_parameter: [0.5, 0.75, 0.9, 0.95]
    
    keypoint: gt
    chunked: True
    normalized: True
    batch_size: 128
    receptive_field: 243
    padding: True
    length: 10

HyperParameters:
  epochs: 100
  lr: 0.01
  lr_decay: [0.99, 0.9, 0.8]
  lr_decay_step: [1, 10, 50]

Optimizer:
  optimizer: adam
  amsgrad: False

Process:
  amp: True
  cuda: True
  dynamic_learning: True

config.yaml 파일은 위처럼 되어 있다.

일반적인 옵션들은 제쳐두고, 특이한 옵션들만 설명하겠다.

amp

PyTorch의 Automatic Mixed-Precision 모드를 사용하는지에 대한 여부이다. 텐서코어가 있는 RTX 그래픽카드부터는 amp를 쓰는 게 더 좋을 것이다.

dynamic_learning

내가 자체적으로 만든 옵션이다. 학습 epoch을 100~1000으로 크게 잡았을 때, 학습을 시작한 후 한참 뒤에 다시 모니터링하면 loss가 제대로 수렴하지 못하거나 폭발하는 경우가 많다. 그럴 때는 학습을 중단하고 적절한 시점부터 학습률을 조절해 resume 해줘야 하는데, 솔직히 귀찮은 작업이다. dynamic_learning 옵션을 키면 매 epoch이 끝날 때마다 학습률을 조절할 수 있다. (lr값을 변경할 지 물어보고, 10초가 지나도록 입력이 없으면 미리 정의된 학습 전략대로 진행된다.)

lr_decay / lr_decay_step

lr_decay가 리스트 타입으로 되어 있는 이유는, 학습률 조정이 여러가지일 수도 있기 때문이다. 단순히 epoch마다 0.9를 곱하는 것이 아니라, 1 epoch마다 0.9, 10 epoch마다 0.5를 곱하는 등의 전략을 취할 수 있다.

따라서 sis_i epoch마다 학습률에 αi\alpha_i만큼을 곱해주고 싶을 때에는 lr_decay와 lr_decay_step을 각각 아래처럼 입력하면 된다.

lr_decay: [a0, a1, a2, ..., an]
lr_decay_step: [s0, s1, s2, ..., sn]

Generator

config의 여러 옵션들은 [논문] 3D human pose estimation in video with temporal convolutions and semi-supervised training 에서 제안되는 것들을 기반으로 구성되었다.

chunked 옵션은 데이터 제네레이터가 여러개의 프레임으로부터 하나의 프레임을 예측하는 데이터쌍을 리턴하도록 한다.

length 옵션은 하나의 샘플에서 예측하고자 하는 프레임의 개수이다.

padding은 하나의 비디오 영상에서 chunked 옵션을 적용했을 때 앞뒤 몇 개의 프레임을 버리는 현상을 막기 위해 각각 첫 프레임과 마지막 프레임의 데이터로 패딩할지 결정한다.

최종적으로 chunked옵션이 활성화되어 있을 때 데이터 제네레이터는 아래와 같은 데이터를 반환한다.

x_batch: (batch_size,receptive_field+length1,J,2)y_batch: (batch_size,length,J,3)\text {x\_batch}:\ (\text{batch\_size}, \text{receptive\_field}+\text{length}-1,J,2)\\\text{y\_batch}:\ (\text{batch\_size},\text{length},J,3)

chunked 옵션이 활성화되어 있지 않을 경우에는 아래와 같다.

x_batch: (batch_size,length,J,2)y_batch: (batch_size,length,J,3)\text{x\_batch}:\ (\text{batch\_size}, \text{length},J,2)\\\text{y\_batch}:\ (\text{batch\_size},\text{length},J,3)

normalized 옵션은 2d 입력 정규화 여부에 대한 것이다.

preprocessor는 현재 MA와 EMA가 구현되어 있다.

Variable (중요!!)

Variable 옵션이 이 프로젝트를 만든 이유이다. yaml파일에 리스트를 코딩하면 실제로 인스턴스나 함수에 파라미터로 리스트가 입력된다. 근데 Variable에 옵션 키값을 추가하고 해당 옵션의 값이 리스트일 때에는 리스트의 element의 개수만큼 config가 나눠진다.

예시에서는 preprocessor_parameter값이 Variable로 설정되어 있는데, 이렇게 실행할 경우에는 지수이동평균 필터의 파라미터값이 각각 0.5, 0.75, 0.9, 0.95일 때 총 4가지 경우에 대해 학습을 진행한다. 다른 건 모두 동일한 상태에서 저 옵션만 바꾸면서 4번 학습한다는 것이다.

Variable은 여러개를 설정할 수 있다. 만약 Generator의 length 옵션을 10이 아니라 [1, 10]으로 바꾸고 Variable에 Dataset/Generator/length 를 추가한다면 총 4×2=84\times2=8개의 옵션이 생성되어 8번을 학습하게 된다.

Pipeline

pipelines 폴더 안에 pipeline_name.py 파일을 만들어 common.pipeline.Pipeline 클래스를 상속받는 pipeline 클래스를 파이토치 모듈처럼 구현하면, config.yaml파일에서 Pipeline에 pipeline_name(.py 파일 이름)을 추가했을 때 해당 모델을 불러와 학습할 수 있다. 이를 통해 여러 모델 구현을 비교할 수 있다.

아직은 여러모로 비효율적인 코드가 많을 것인데, 점차 개선해 나가면서 여러 옵션을 쉽게 비교할 수 있도록 할 것이다.

profile
컴퓨터에 관심 많은 산업공학과 학부생. 슬프게도 지금은 대한민국 육군에서 복무 중입니다.

0개의 댓글