# PyTorch 랜덤 시드와 텐서 shape 완벽 이해 ## 1. 랜덤 시드(Random Seed)란? ### 1.1 컴퓨터의 '가짜' 랜덤 컴퓨터는 실제로 **진짜 랜덤**을 만들 수 없습니다. 대신 **의사 난수(pseudo-random)**를 생성합니다. ```python # 컴퓨터의 랜덤 생성 원리 (단순화) def fake_random(seed): # 시드값을 기반으로 복잡한 수학 계산 next_value = (seed * 1103515245 + 12345) % (2**31) return next_value ``` ### 1.2 시드의 역할 **시드(Seed)**는 랜덤 숫자 생성의 **시작점**입니다. ```python # 시드 없이 - 매번 다른 결과 import torch print(torch.randint(0, 10, (3,))) # tensor([7, 2, 9]) print(torch.randint(0, 10, (3,))) # tensor([4, 1, 6]) - 다름! # 시드 설정 - 재현 가능한 결과 torch.manual_seed(42) print(torch.randint(0, 10, (3,))) # tensor([8, 4, 2]) torch.manual_seed(42) # 같은 시드 다시 설정 print(torch.randint(0, 10, (3,))) # tensor([8, 4, 2]) - 똑같음! ``` ### 1.3 시드 작동 원리 비유 시드는 **주사위 던지기 시작 위치**와 같습니다: - 시드 1234 = "테이블의 왼쪽 모서리에서 시작" - 시드 5678 = "테이블의 오른쪽 모서리에서 시작" - 같은 시작점 = 같은 결과 ### 1.4 시드값과 생성 범위는 완전히 별개! 많은 사람들이 헷갈리는 부분입니다. **시드 42**는 0~10 사이의 숫자가 아닙니다! ```python # torch.randint의 구조 torch.randint(low, high, size) # low: 최소값 (포함) # high: 최대값 (미포함) # size: 생성할 텐서의 크기 # 시드는 randint 안에 들어가지 않음! torch.manual_seed(42) # 랜덤 생성기의 시작점 설정 result = torch.randint(0, 10, (3,)) # 0~9 사이 3개 생성 ``` ### 1.5 시드의 진짜 의미 - 계산의 시작점 시드는 **랜덤 숫자를 만드는 수학 공식의 초기값**입니다: ```python # 단순화된 랜덤 생성기 예시 class 가짜_랜덤생성기: def __init__(self, seed): self.현재값 = seed # 시작점 (시드) def 다음_랜덤(self, 최대값): # 복잡한 수학 계산 self.현재값 = (self.현재값 * 1103515245 + 12345) % (2**31) return self.현재값 % 최대값 # 시드 42로 시작 생성기1 = 가짜_랜덤생성기(42) print(생성기1.다음_랜덤(10)) # 8 print(생성기1.다음_랜덤(10)) # 4 print(생성기1.다음_랜덤(10)) # 2 # 같은 시드 42로 새 생성기 생성기2 = 가짜_랜덤생성기(42) print(생성기2.다음_랜덤(10)) # 8 - 똑같음! print(생성기2.다음_랜덤(10)) # 4 - 똑같음! print(생성기2.다음_랜덤(10)) # 2 - 똑같음! ``` ### 1.6 왜 같은 값이 나오는가? 컴퓨터는 진짜 랜덤을 못 만들어서 **결정론적 알고리즘**을 사용합니다: ```python # 시드가 다르면 완전히 다른 결과 torch.manual_seed(42) print(torch.randint(0, 10, (3,))) # [8, 4, 2] print(torch.randint(0, 100, (3,))) # [84, 42, 28] print(torch.randint(0, 1000, (3,))) # [848, 423, 285] # 시드가 같으면 항상 같은 순서 torch.manual_seed(42) # 다시 42로 리셋 print(torch.randint(0, 10, (3,))) # [8, 4, 2] - 똑같음! # 다른 시드 = 다른 결과 torch.manual_seed(999) print(torch.randint(0, 10, (3,))) # [7, 1, 5] - 다름! ``` **핵심**: 시드값(42, 1234 등)은 생성 범위와 무관한 "계산 시작점"일 뿐! ## 2. (3,) vs (3)의 차이 - 튜플 문법 ### 2.1 Python에서 튜플 생성 ```python # 숫자 하나만 있으면 그냥 정수 a = (3) print(type(a)) # <class 'int'> - 정수! # 콤마가 있어야 튜플 b = (3,) print(type(b)) # <class 'tuple'> - 튜플! # 여러 개일 때는 콤마 자동 c = (3, 4) print(type(c)) # <class 'tuple'> ``` ### 2.2 왜 튜플이 필요한가? `torch.randint`는 생성할 텐서의 **모양(shape)**을 튜플로 받습니다. ```python # 1차원 텐서: 3개 요소 torch.randint(0, 10, (3,)) # [?, ?, ?] # 2차원 텐서: 2x3 행렬 torch.randint(0, 10, (2, 3)) # [[?, ?, ?], # [?, ?, ?]] # 3차원 텐서: 2x3x4 torch.randint(0, 10, (2, 3, 4)) # 2개의 3x4 행렬 ``` ### 2.3 shape 파라미터 예시 ```python # 다양한 shape 예시 shape1 = (5,) # 1차원: 5개 요소 shape2 = (3, 4) # 2차원: 3행 4열 shape3 = (2, 3, 4) # 3차원: 2개의 3x4 행렬 # 실제 사용 tensor1 = torch.randint(0, 100, shape1) print(tensor1) # tensor([45, 23, 67, 89, 12]) tensor2 = torch.randint(0, 100, shape2) print(tensor2) # tensor([[45, 23, 67, 89], # [12, 34, 56, 78], # [90, 11, 22, 33]]) ``` ## 3. 실제 코드에서의 활용 ### 3.1 배치 함수에서의 사용 ```python def batch_function(mode): dataset = train_dataset if mode == "train" else test_dataset # (batch_size,) = (4,) = 4개의 랜덤 인덱스 생성 idx = torch.randint(len(dataset) - block_size, (batch_size,)) # 예: tensor([234, 567, 123, 890]) # 각 인덱스에서 데이터 추출 x = torch.stack([dataset[i:i+block_size] for i in idx]) return x ``` ### 3.2 시드 설정의 중요성 ```python # 실험 1 torch.manual_seed(1234) batch1 = batch_function("train") # 실험 2 - 같은 시드 torch.manual_seed(1234) batch2 = batch_function("train") # batch1과 batch2는 완전히 동일! print(torch.equal(batch1, batch2)) # True ``` ## 4. 핵심 정리 ### 시드(Seed) - **목적**: 랜덤 결과를 재현 가능하게 만듦 - **원리**: 난수 생성의 시작점 고정 - **사용**: 디버깅, 실험 재현, 공정한 비교 ### Shape 튜플 - **(3)**: 그냥 숫자 3 - **(3,)**: 1차원 shape을 나타내는 튜플 - **(3, 4)**: 2차원 shape을 나타내는 튜플 - PyTorch는 텐서의 차원을 명확히 하기 위해 튜플 사용 ### 실용적 팁 ```python # 프로젝트 시작 시 항상 시드 설정 def set_all_seeds(seed): torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False set_all_seeds(42) # 모든 랜덤 연산이 재현 가능해짐 ``` ## 관련 참고 자료 - [[GPT 배치 생성 함수 완벽 가이드]] - [[Python 기초 문법 - 컴프리헨션과 메서드]] - [[PyTorch 텐서와 torch.tensor() 완전 가이드]]