난수 텐서 생성
왜 난수 텐서가 필요한가?
섹션 제목: “왜 난수 텐서가 필요한가?”딥러닝에서 난수는 두 가지 핵심 역할을 합니다.
- 가중치 초기화 — 모든 가중치를 같은 값으로 시작하면 대칭성 문제로 학습이 안 됩니다. 난수로 시작해야 각 뉴런이 다른 특성을 학습합니다.
- 데이터 셔플링 및 드롭아웃 — 학습 데이터의 순서를 무작위로 바꾸거나, 드롭아웃으로 뉴런을 무작위로 끕니다.
세 가지 주요 난수 함수
섹션 제목: “세 가지 주요 난수 함수”torch.rand() — 균등분포 [0, 1)
섹션 제목: “torch.rand() — 균등분포 [0, 1)”0 이상 1 미만의 실수를 균일하게 뽑습니다. 모든 구간에서 값이 나올 확률이 동일합니다.
분포 모양:확률│████████████████████│████████████████████│████████████████████└─────────────────────▶ 값 0 1import torch
# 기본 사용r1 = torch.rand(4)print(r1) # tensor([0.4963, 0.7682, 0.0885, 0.1320]) ← 실행마다 다름
# 2D 난수 텐서r2 = torch.rand(3, 4)print(r2.shape) # torch.Size([3, 4])print(r2.min()) # ≥ 0.0print(r2.max()) # < 1.0
# 범위 조정: [a, b) 범위로 변환a, b = -1.0, 1.0r_range = torch.rand(5) * (b - a) + aprint(r_range) # -1.0 ~ 1.0 사이 값주요 사용처: 드롭아웃 마스크, 무작위 샘플링, 균등 초기화
torch.randn() — 표준 정규분포 N(0, 1)
섹션 제목: “torch.randn() — 표준 정규분포 N(0, 1)”평균 0, 표준편차 1인 **정규분포(가우시안 분포)**에서 뽑습니다. 값들이 0 근처에 몰리고 멀어질수록 드물어집니다.
분포 모양 (종 모양):확률│ ▲│ ██████│ ██████████│ ██████████████│ ████████████████████└─────────────────────▶ 값 -3 -1 0 1 3# 기본 사용n1 = torch.randn(4)print(n1) # tensor([-0.5557, 0.7085, 0.3604, -1.1529])
# 2Dn2 = torch.randn(3, 4)print(n2.mean()) # ≈ 0.0print(n2.std()) # ≈ 1.0
# 평균 μ, 표준편차 σ로 조정mu, sigma = 5.0, 2.0n_custom = torch.randn(1000) * sigma + muprint(n_custom.mean().item()) # ≈ 5.0print(n_custom.std().item()) # ≈ 2.0
# 또는 torch.normal() 직접 사용n_normal = torch.normal(mean=5.0, std=2.0, size=(1000,))주요 사용처: Xavier/He 가중치 초기화의 기반, 가우시안 노이즈 추가
torch.randint() — 정수 난수
섹션 제목: “torch.randint() — 정수 난수”지정한 범위에서 정수를 무작위로 뽑습니다.
# randint(low, high, size) — [low, high) 범위i1 = torch.randint(0, 10, (5,))print(i1) # tensor([7, 2, 9, 0, 4])
# low 생략 시 기본값 0i2 = torch.randint(10, (3, 4))print(i2)# tensor([[3, 1, 7, 5],# [9, 2, 0, 8],# [4, 6, 3, 1]])
# 실전: 배치 레이블 생성 (클래스 10개)num_classes = 10batch_size = 32labels = torch.randint(0, num_classes, (batch_size,))print(labels.shape) # torch.Size([32])print(labels.dtype) # torch.int64주요 사용처: 무작위 레이블 생성, 인덱스 샘플링, 테스트 데이터 생성
균등분포 vs 정규분포 한눈에 비교
섹션 제목: “균등분포 vs 정규분포 한눈에 비교”| 항목 | torch.rand() | torch.randn() |
|---|---|---|
| 분포 | 균등분포 (Uniform) | 정규분포 (Normal/Gaussian) |
| 범위 | [0, 1) | 이론상 (-∞, +∞) |
| 평균 | 0.5 | 0.0 |
| 표준편차 | ≈ 0.289 | 1.0 |
| 모양 | 평평한 직사각형 | 종 모양 곡선 |
| 주 용도 | 드롭아웃, 샘플링 | 가중치 초기화 |
# 두 분포의 통계 비교 (큰 샘플로)uniform = torch.rand(10000)normal = torch.randn(10000)
print(f"균등분포 — 평균: {uniform.mean():.3f}, 표준편차: {uniform.std():.3f}")print(f"정규분포 — 평균: {normal.mean():.3f}, 표준편차: {normal.std():.3f}")# 균등분포 — 평균: 0.500, 표준편차: 0.289# 정규분포 — 평균: 0.002, 표준편차: 0.998재현성: torch.manual_seed()
섹션 제목: “재현성: torch.manual_seed()”같은 시드(seed)를 설정하면 매 실행마다 동일한 난수 시퀀스가 생성됩니다. 실험 재현성 확보에 필수입니다.
# 시드 없이 실행 — 매번 다른 결과print(torch.rand(3)) # tensor([0.4963, 0.7682, 0.0885])print(torch.rand(3)) # tensor([0.1320, 0.3074, 0.6341]) ← 다름
# 시드 설정 후 — 항상 같은 결과torch.manual_seed(42)print(torch.rand(3)) # tensor([0.8823, 0.9150, 0.3829])
torch.manual_seed(42) # 다시 같은 시드print(torch.rand(3)) # tensor([0.8823, 0.9150, 0.3829]) ← 동일!완전한 재현성을 위한 설정
섹션 제목: “완전한 재현성을 위한 설정”import torchimport randomimport numpy as np
def set_seed(seed: int = 42): """모든 난수 생성기의 시드를 고정합니다.""" torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.cuda.manual_seed_all(seed) # 멀티 GPU np.random.seed(seed) random.seed(seed) # 결정론적 연산 강제 (속도 저하 가능) torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False
set_seed(42)실전 활용: 가중치 초기화
섹션 제목: “실전 활용: 가중치 초기화”import torch.nn as nn
# nn.Linear 내부에서 실제로 일어나는 초기화 (단순화)in_features = 256out_features = 128
# He 초기화 (ReLU 활성화 함수와 함께 사용)std = (2.0 / in_features) ** 0.5weight_he = torch.randn(out_features, in_features) * stdprint(f"He init — 평균: {weight_he.mean():.4f}, 표준편차: {weight_he.std():.4f}")
# Xavier 초기화 (sigmoid/tanh 활성화 함수와 함께 사용)std_xavier = (2.0 / (in_features + out_features)) ** 0.5weight_xavier = torch.randn(out_features, in_features) * std_xavierprint(f"Xavier — 평균: {weight_xavier.mean():.4f}, 표준편차: {weight_xavier.std():.4f}")
# PyTorch가 제공하는 초기화 함수로 더 간편하게weight = torch.empty(out_features, in_features)nn.init.kaiming_normal_(weight, mode='fan_in', nonlinearity='relu')nn.init.xavier_normal_(weight)핵심 요약
섹션 제목: “핵심 요약”torch.rand()→ [0, 1) 균등분포, 드롭아웃/샘플링에 사용torch.randn()→ 평균 0, 표준편차 1 정규분포, 가중치 초기화에 사용torch.randint(low, high, size)→ 정수 난수, 레이블/인덱스 생성에 사용torch.manual_seed(n)→ 재현 가능한 실험을 위해 학습 시작 전 한 번 호출- 완전한 재현성은 numpy, random 시드도 함께 고정해야 함