# 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() 완전 가이드]]