MLOps study - Raviraja Week 2: Hydra
13 Oct 2022Week 2는 Hydra에 대한 내용입니다. Pytorch Lightning이 모델과 데이터셋 구축에 집중하고, WandB를 통해 그것을 기록했다면, Hydra는 configuration을 관리하는 작업에 초점을 맞추고 있습니다. Configuration은 reproducability를 위해 정확히 기록될 필요성이 있습니다. 저는 Argparser를 이용해서 항상 configuration을 기록해 왔었는데, Hydra에 대해서 한 번 알아보도록 하겠습니다.
Start hydra
.py 형식의 파일을 이용해 개발환경을 구성할 때에는 decorator를 사용하는 것이 간편합니다.
import hydra
from omegaconf import OmegaConf
=
@hydra.main(config_path="configs", config_name="config.yaml", version_base="1.2")
def main(cfg):
print(OmegaConf.to_yaml(cfg, resolve=True))
main()
Decorator를 사용하게 되면 다음과 같이 runtime에서 configuration을 수정할 수 있다 (Argparser 역할을 대신 할 수 있게 되는 것이다.)
python main.py perferences.trait=i_like_stars
Week 0,1 에서 진행했던 코드에 hydra decorator를 사용하면 다음과 같이 간단하게 configuration을 변수화 할 수 있습니다.
# 예시
@hydra.main(config_path="./configs", config_name="config")
def main(cfg):
# print(OmegaConf.to_yaml(cfg))
cola_data = DataModule(
cfg.model.tokenizer, cfg.processing.batch_size, cfg.processing.max_length
)
cola_model = ColaModel(cfg.model.name)
checkpoint_callback = ModelCheckpoint(
dirpath="./models",
filename="best-checkpoint.ckpt",
monitor="valid/loss",
mode="min",
)
wandb_logger = WandbLogger(project="MLOps Basics", entity="raviraja")
trainer = pl.Trainer(
max_epochs=cfg.training.max_epochs,
logger=wandb_logger,
callbacks=[checkpoint_callback, SamplesVisualisationLogger(cola_data)],
log_every_n_steps=cfg.training.log_every_n_steps,
deterministic=cfg.training.deterministic,
limit_train_batches=cfg.training.limit_train_batches,
limit_val_batches=cfg.training.limit_val_batches,
)
trainer.fit(cola_model, cola_data)
그러나 Jupyter notebook에서는 decorator 방식이 동작하지 않기 때문에, compose 방식을 사용해 configuration을 사용할 수 있습니다.
hydra.core.global_hydra.GlobalHydra.instance().clear()
hydra.initialize("./configs", version_base=None)
cfg = hydra.compose(config_name="config.yaml")
print(OmegaConf.to_yaml(cfg))
Multiple configuration file
Configuration 파일을 여러 개로 분리해서 관리하는 것이 편할 때가 있습니다.. 하지만 그 때 마다 configuration 파일을 따로 load 해야 한다면 불편하겠죠? 하나의 yaml 파일만 불러와도 모든 config를 불러 올 수 있는 default list 기능이 있습니다.
├── configs
│ ├── config.yaml
│ └── model
│ └── default.yaml
│ └── data
│ └── default.yaml
다음과 같은 구조로 configuration 폴더가 존재할 때, config.yaml 을 아래와 같이 수정해 줍시다.
defaults:
- model: default
- data: default
놀랍게도 config.yaml만 불러오면 모든게 한 번에 다 불러와 지는 것을 알 수 있습니다.
응용해보면 다음과 같은 폴더 구조를 만들고 config.yaml 만 그때그때 수정해 주면 되는 것입니다!! (놀랍다 놀라워)
├── configs
│ ├── config.yaml
│ └── model
│ └── default.yaml
│ └── bert.yaml
│ └── transformers.yaml
│ └── database
│ └── default.yaml
│ └── mongoDB.yaml
│ └── AmazonDB.yaml
# in config.yaml
defaults:
- model: default
- database: mongoDB
Variable dependency가 있는 경우에는 어떨까요? 아주 간단합니다.
max_epochs: 1
log_every_n_steps: 10
deterministic: true
limit_train_batches: 0.25
limit_val_batches: ${training.limit_train_batches}
다음과 같은 방식으로 바인딩 해주면 됩니다.
OmegaConf에서 바인딩이 제대로 안된다고요? 그러면 resolve=True
를 추가해 주면 간단히 해결!
OmegaConf.to_yaml(cfg, resolve=True)
Running multiple jobs
python train.py -m training.max_epochs=1,2 processing.batch_size=32,64,128
이런 식으로 실행해주면 총 6가지가 동시에 수행됩니다!!! 만약 동시에 돌리고 싶다면 어떻게 해야 할까요? Joblib 라이브러리를 사용한다면 병렬 수행이 가능합니다.
pip install hydra-joblib-launcher --upgrade
python train.py -m training.max_epochs=1,2 processing.batch_size=32,64,128 hydra/launcher=joblib