본문 바로가기
Deep Learning

[DL] PyTorch에서의 Reproductibility 보장하기

by JJuOn 2022. 7. 22.

PyTorch를 비롯한 많은 딥러닝 프레임워크는 weight initialization 부터 시작하여 수많은 요소가 랜덤하게 적용된다.

 

연구나 모델링 대회(Kaggle, Dacon 등)을 진행할 때 중요한 것중 하나는 코드의 재현성(reproductibility)을 확보하는 것이다. 연구나 대회를 진행함에 있어 성능 변화가 실제로 코드 수정에 의한 것인지, 아니면 랜덤한 요소 때문에 운좋게 혹은 운나쁘게 성능이 변화한 것인지 구분하기가 어렵다. 그렇기 때문에 주로 시드를 고정하는 방식으로 재현성을 확보하는 방법이 일반적이다.

PyTorch에서의 reproductibility

import torch

seed = 0
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)

 Pytorch에서는 torch.manual_seed()와 torch.cuda.manual_seed()를 통해 시드를 고정해 준다.

Numpy에서의 reproductibility

import numpy as np

seed = 0

np.random.seed(seed)

뿐만 아니라, PyTorch는 numpy를 기반으로 많은 연산들이 수행되고 있기 때문에  numpy의 시드도 고정해주어야 한다.

Random module에서의 reproductibility

import random

seed = 0

random.seed(seed)

마지막으로 파이썬의 내장 모듈인 random 모듈의 시드도 위와 같이 고정해 줄 수 있다.

위 세가지를 정리해보자면 아래와 같다.

import random
import torch

import numpy as np

seed = 0

random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)

이렇게 하면 항상 같은 값을 뽑아낼 수 있을까?

정답은 아니다. 아래 두가지를 새로 추가해 주어야 한다.

import torch

torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

pytorch의 CUDA convolution 연산은 cuDNN 라이브러리를 활용한다. 이때, 연산을 진행할 때 마다 여러개의 convolution 알고리즘들을 수행하고 가장 빠른 것을 탐색하는데 이를 제어하는 것이 torch.backends.cudnn.benckmark 이다. 그러나 이 과정으로 인해 같은 환경일 지라도 서로 다른 연산과정이 존재할 수 있다. 이 점으로 인해 앞서 시드를 고정해 주어도 재현이 제대로 되지 않는 것이다. 그리고 non-deterministic한 연산(알고리즘)들을 제어하기 위해 torch.backends.cudnn.detetministic = True로 설정하게 되면 확실하게 재현성을 확보할 수 있게된다.

 

따라서, pytorch에서 재현성을 확보하기 위해서는 아래 코드를 작성하면 된다.

import random
import torch

import numpy as np

seed = 0

random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

References

[1] https://pytorch.org/docs/stable/notes/randomness.html

[2] https://hoya012.github.io/blog/reproducible_pytorch/

댓글