Hydra 사용법 정리

싶만생각
|2022. 6. 19. 19:26

https://www.sscardapane.it/tutorials/hydra-tutorial/#executing-multiple-runs

 

Hydra?

  • configuration을 모듈로 세분화하여 관리 가능
  • 미리 정의한 configration을 hydra 환경에서 사용
  • 실행된 hydra 환경에서의 실행 기록을 outputs/날짜/시간/.hydra/config.yaml 에 저장 
    • 어떤 configuration을 사용했는 지 모두 기록해 실험 관리에 도움
├── outputs
│   └── 2022-06-19
│       └── 19-23-30
│           ├── .hydra
│           	└── config.yaml
|           	└── ...
  • MNIST 분류 문제를 해결하는 경우 다음과 같이 config 구성 가능

 

Configuration 구성

  • 모듈별 폴더를 생성해 configuration 구성 
    • model에서 처럼 다양하게 구성해뒀다가 실험 환경에 맞게 변경 가능
├── configs
│   ├── config.yaml
│   ├── checkpoint
│   │   └── checkpoint.yaml
│   ├── data
│   │   └── mnist.yaml
│   ├── early_stopping
│   │   └── early_stopping.yaml
│   ├── logger
│   │   └── tensorboard.yaml
│   ├── lr_monitor
│   │   └── lr_monitor.yaml
│   ├── model
│   │   ├── resnet18.yaml
│   │   └── resnet34.yaml
│   ├── optimizer
│   │   └── sgd.yaml
│   ├── scheduler
│   │   └── steplr.yaml
│   └── trainer
│       └── trainer.yaml

 

config.yaml
  •  configs의 main 역할
  • 각 모듈에서 선택하고 싶은 yaml을 defaults를 통해서 지정 가능
  • 별도의 조작 없으면 defaults에 지정된 yaml이 사용됨
  • 다른 모듈의 변수들을 참조 가능하기 때문에 공통되는 변수는 여기에 선언하는 것을 추천
  • python trainer.py model=resnet34 와 같이 선언하면 model의 resnet18 대신 resnet34.yaml이 선택 됨
  • 위 경우 outputs에 resnet18 대신 resnet34가 사용됐다고 log 남음
# 공통 변수
seed : 42
monitor : "val_loss"

defaults:
  - model: resnet18
  - data : mnist
  - optimizer : sgd
  - scheduler : steplr
  - trainer : trainer
  - logger : tensorboard
  - early_stopping : early_stopping
  - lr_monitor : lr_monitor
  - checkpoint : checkpoint

 

변수 참조 방법
  • ${변수} 형태
  • 이때, config.yaml(main config)의 변수는 폴더 명 없이 참조 가능 
  • 다른 폴더의 변수를 참고하기 위해서는 ${폴더명.변수명}
# config.yaml의 monitor 참조
monitor: ${monitor}
# model 폴더의 yaml들이 data 폴더의 num_classes 변수를 참조하고 싶은 경우
num_classes : ${data.num_classes}
변수 선언 예시
  • trainer.yaml
  • cfg.trainer를 참조하면 다음과 같이 파라미터로 사용 가능
  • Trainer(**cfg.trainer)
max_epochs: 30
deterministic: true
log_every_n_steps: 50
track_grad_norm: 2
profiler: simple
accelerator: gpu
devices : 1

 

object instantiate
  • 문자 그대로 생성할 instance의 정보를 저장할 수 있음
  • 개인적으로 코드 가독성을 해치지 않는 선에서 활용하면 좋다고 생각

 

  • resnet18.yaml을 활용한 예시 
    • _target_ : object 
    • _target_ 밑엔 instance를 만들 때 선언 할 parameter를 정의해 줌
    • 이때, parameter는 tuple 형태 대신 list 형태로 선언해줘야 인식
    • ${data.num_classes} : data 모듈의 num_classes 참조
model:
  _target_ : torchvision.models.resnet18
  pretrained : false
  num_classes : ${data.num_classes}

conv:
  _target_ : torch.nn.Conv2d
  in_channels : ${data.in_channels}
  out_channels: 64
  kernel_size : [1, 1]
  stride : [1, 1]
  padding : [1, 1]

 

hydra 사용하기

  • 사용하고자 하는 함수에 @hydra.main으로 표시
  • 이때, hydra 환경에선 cwd()가 hydra 실행에 따라 생긴 outputs 폴더 안으로 변경되기 때문에 실제 cwd()를 알고 싶다면 get_original_cwd 활용
from hydra.utils import get_original_cwd
from omegaconf import DictConfig

@hydra.main(config_path='configs', config_name="config")
def main_hydra(cfg: DictConfig):
    seed_everything(cfg.seed, workers=True)
    data = MNISTDataModule(data_dir=get_original_cwd(), val_split=cfg.data.val_split, num_workers=cfg.data.num_workers, batch_size=cfg.data.batch_size,
                           normalize=True, shuffle=True, pin_memory=True)
    lit_model = Resnet(cfg)
    # logger 
    logger = TensorBoardLogger(**cfg.logger)
    # callbacks
    early_stopping = EarlyStopping(**cfg.early_stopping)
    lr_monitor = LearningRateMonitor(**cfg.lr_monitor)
    check_point = ModelCheckpoint(**cfg.checkpoint)
    # Trainer
    trainer = Trainer(**cfg.trainer, logger=logger, callbacks=[early_stopping, lr_monitor, check_point])
    trainer.fit(lit_model, datamodule=data)
    trainer.test(lit_model, datamodule=data)

if __name__ == "__main__":
    main_hydra()
  • object instantiate를 활용하고 싶다면 다음과 같이 사용
from hydra.utils import instantiate

self.model = instantiate(cfg.model.model)
self.model.conv1 = instantiate(cfg.model.conv)
  • optimizer와 scheduler는 다음과 같이 사용
# sgd.yaml
_target_ : torch.optim.SGD
lr: 0.1
momentum: 0.9
weight_decay: 1e-4
# class init
self.optimizer = cfg.optimizer
self.scheduler = cfg.scheduler
self.monitor = cfg.monitor

def configure_optimizers(self):
    optimizer = instantiate(self.optimizer, self.parameters())
    scheduler = instantiate(self.scheduler, optimizer)
    return {"optimizer": optimizer, "lr_scheduler": scheduler, "monitor": self.monitor}

 

코드 샘플
 

GitHub - Woodywarhol9/pytorch-lightning-practice

Contribute to Woodywarhol9/pytorch-lightning-practice development by creating an account on GitHub.

github.com

  • Hydra와 Lightning을 활용해 간단한 MNIST 분류기를 구성했고, 이는 링크를 통해 확인할 수 있다.

참고

 

GitHub - graviraja/MLOps-Basics

Contribute to graviraja/MLOps-Basics development by creating an account on GitHub.

github.com

 

Tutorial: Learning Hydra for configuring ML experiments

Over the last month, I have been exploring Hydra for configuring and managing machine learning experiments. Despite its simplicity, it is an incredibly powerful tool for a lot of scenarios, building on the flexibility of OmegaConf, a large community base,

www.sscardapane.it

 

GitHub - facebookresearch/hydra: Hydra is a framework for elegantly configuring complex applications

Hydra is a framework for elegantly configuring complex applications - GitHub - facebookresearch/hydra: Hydra is a framework for elegantly configuring complex applications

github.com