본문 바로가기
PROGRAMMING/Python

[Pytorch] 딥러닝 실험 재현을 위해 난수 제어 (Deterministic, Benchmark, random seed)

by HYUNHP 2023. 11. 25.
728x90
반응형

안녕하세요, HELLO

PyTorch에서 완벽한 실험 재현을 위해 고려해야 할 무작위성(randomness)를 올바르게 제어하는 방법에 대해 설명하겠습니다. 

먼저, PyTorch의 난수 생성과 관련된 기능들은 난수 발생기(Random Number Generator, RNG)를 사용합니다. 이 난수 발생기에는 random seed를 설정할 수 있으며, 이를 통해 매번 동일한 순서로 난수를 생성할 수 있습니다. 

PyTorch에서는 난수와 관련된 여러 구성 요소가 있기 때문에, 각 구성 요소가 무엇을 의미하는지 살펴보고, 각각의 randomness를 제어하기 위한 방법에 대해 살펴보겠습니다.

각 코드에 대한 설명은 아래에서 자세히 다뤄보겠습니다.
 

import torch
import numpy as np
import random

def set_seed(seed):
    # Set the random seed for PyTorch on CPU and GPU
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)  # If using multi-GPU
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

    # Set the random seed for NumPy
    np.random.seed(seed)

    # Set the random seed for Python's built-in random module
    random.seed(seed)

# Example usage:
random_seed = 42  # Choose any integer value as the random seed
set_seed(random_seed)

# Now, the random seeds are set, and you can proceed with your PyTorch code.

 

 
STEP 1. 'Python random seed 설정'
 
STEP 2. 'Pytorch random seed 설정'


STEP 1. 'Python random seed 설정'
 

random_seed = 42  # 난수 시드로 사용할 임의의 정수 값을 선택합니다.

 
random_seed 변수에 값을 할당합니다. 여기서 42는 임의의 정수 값으로, 난수 발생기를 초기화하는 데 사용됩니다. 어떤 정수 값이든 사용할 수 있으며, 이 값은 난수 생성기를 초기화하는 데 사용됩니다.
 

# NumPy에 대한 난수 시드 설정
np.random.seed(random_seed)

 
NumPy의 난수 발생기에 시드를 설정합니다. 이렇게 하면 NumPy를 사용하는 모든 난수 연산이 다른 실행에서도 항상 동일한 결과를 생성합니다.
 

# Python의 내장된 random 모듈에 대한 난수 시드 설정
random.seed(random_seed)

 
Python의 내장된 random 모듈에서 사용되는 난수 발생기에 시드를 설정합니다. 코드에 NumPy나 PyTorch 이외의 난수 연산이 있는 경우에 중요합니다.


STEP 2. 'Pytorch random seed 설정'
 

# PyTorch의 CPU 및 GPU에 대한 난수 시드 설정
torch.manual_seed(random_seed)
torch.cuda.manual_seed(random_seed)
torch.cuda.manual_seed_all(random_seed)  # 다중 GPU 사용 시

 
torch.manual_seed(random_seed): CPU에서 PyTorch의 난수 발생기의 시드를 설정합니다. CPU에서 수행되는 연산이 다른 실행에서도 항상 동일한 결과를 생성합니다.
 
torch.cuda.manual_seed(random_seed): PyTorch에서 현재 GPU의 난수 발생기에 시드를 설정합니다. 모델이 GPU 연산을 포함하는 경우 중요합니다.
 
torch.cuda.manual_seed_all(random_seed): 여러 GPU를 사용하는 경우, 모든 GPU가 동일한 난수 발생기 시드를 사용하도록 보장합니다.


torch.backends.cudnn.deterministic = True

 
torch.backends.cudnn.deterministic = True로 설정하는 것은 CuDNN(CUDA Deep Neural Network 라이브러리) 작업이 결정론적으로 정하기 위함입니다 (deterministic). 결정론이란 것은 동일한 입력과 동일한 난수 시드가 주어지면 항상 동일한 결과를 생성하는 것을 의미합니다. 이는 결과의 재현성을 위해 중요하며, 만약에 CuDNN에서 비결정론적 알고리즘을 사용하는 경우, 동일한 입력에 대해 다소 다른 결과가 생성될 수 있습니다. 이를 항상 같은 알고리즘으로 설정하게 되면 항상 동일한 결과를 보장할 수 있습니다. 하지만 True로 설정하는 것은 CuDNN에서 비결정론적 알고리즘에 의존하는 일부 최적화를 사용할 수 없게 만들어 성능에 영향을 줄 수 있습니다.
 
반면에, torch.backends.cudnn.deterministic = False로 설정하면 CuDNN이 주어진 입력 크기와 데이터 분포에 대해 최적의 알고리즘을 동적으로 선택할 수 있습니다. 이로 인해 성능이 향상될 수 있지만, 결과에는 약간의 변동성이 도입됩니다. 즉, CuDNN은 동일한 입력에 대해 다른 실행에서 다른 알고리즘을 선택할 수 있으므로 결과에 약간의 불확실성이 생깁니다.
 
이러한 두 가지 설정 간의 트레이드오프 (Trade off)는 결정론적인 결과를 원하는 경우에는 True로 설정하고, 성능이 더 중요한 경우에는 False로 설정하여 약간의 결과 변동성을 허용할 수 있습니다. 특정 사례에 맞게, 결과의 일관성과 성능에서 선택해서 사용하면 됩니다.


torch.backends.cudnn.benchmark = False

 
torch.backends.cudnn.benchmark = False로 설정하는 것은 CuDNN이 동일한 입력에서 일관된 알고리즘을 사용하여 결과에 변동성을 줄입니다. 이를 통해 결과의 일관성을 높일 수 있으며, 디버깅 및 결과 재현성이 향상됩니다. 다 실행 시간이 늘어날 수 있으며, 최적화되지 않은 알고리즘을 사용하여 성능이 감소할 수 있습니다.
 
반면에 torch.backends.cudnn.benchmark = True로 설정하는 것은 CuDNN이 최적의 알고리즘을 동적으로 선택하여 최상의 성능을 추구합니다. 실행 시간을 단축하고 모델의 학습 및 추론 성능을 최적화할 수 있습니다. 하지만 결과에 약간의 변동성이 도입될 수 있습니다. 다양한 입력 크기 및 데이터 분포에 따라 선택된 알고리즘이 달라질 수 있습니다.
 
이러한 두 가지 설정 간의 트레이드 오프는 결과의 일관성이 중요하거나 디버깅이 필요한 경우에 유용합니다. 상황에 따라 실험해 보고 특정 사용 사례에 맞게 조정하는 것이 좋습니다.


torch.backends.cudnn.benchmarktorch.backends.cudnn.deterministic의 차이점은 다음과 같습니다.

torch.backends.cudnn.benchmark은 CuDNN이 최적의 알고리즘을 동적으로 선택하여 최대 성능을 추구하되, 결과에 약간의 변동성이 도입됩니다.
 
torch.backends.cudnn.deterministic은 CuDNN이 항상 동일한 입력에 대해 동일한 출력을 생성하도록 설계되어, 결과에 변동성을 줄입니다. 그러나 이 설정을 사용하면 성능이 최적화되지 않을 수 있습니다.
 
두 설정은 주로 디버깅, 실험 재현성, 그리고 성능 최적화의 트레이드오프를 다루기 위해 사용됩니다.
 

반응형

 
■ REFERENCE
 
https://hoya012.github.io/blog/reproducible_pytorch/
https://pytorch.org/docs/stable/notes/randomness.html


■ 마무리

'딥러닝 실험 재현을 위해 난수 제어 (Deterministic, Benchmark, random seed)'에 대해서 알아봤습니다.
 
난수 시드 설정은 재현성을 위해 중요합니다. 다양한 실행에서 난수 발생기의 초기 조건이 항상 동일하게 유지되어 일관된 결과를 얻을 수 있도록 합니다. 이는 특히 기계 학습 실험에서 중요하며, 결과를 신뢰성 있게 재현하고 비교할 수 있게 합니다.

좋아요댓글 부탁드리며,
오늘 하루도 즐거운 날 되시길 기도하겠습니다 :)

감사합니다.

반응형

댓글