🤖 AI/ML

Weight

가중치

신경망 연결의 강도를 나타내는 학습 가능한 파라미터. 모델이 데이터로부터 학습하는 핵심 요소.

📖 상세 설명

가중치(Weight)는 신경망에서 뉴런 간 연결의 강도를 나타내는 숫자 값입니다. 입력 데이터에 가중치를 곱한 후 합산하여 다음 층으로 전달하며, 이 가중치들이 바로 모델이 "학습"하는 대상입니다. GPT-4가 1.8조 개의 파라미터를 가진다고 할 때, 대부분이 이 가중치들입니다.

가중치의 개념은 1958년 Frank Rosenblatt의 퍼셉트론에서 시작되었습니다. 초기에는 단순한 선형 분류기의 계수였지만, 딥러닝 시대에는 수십억~수조 개의 가중치가 복잡한 패턴을 학습합니다. 가중치 업데이트 알고리즘(역전파 + 경사하강법)의 발전이 딥러닝 혁명의 핵심이었습니다.

가중치의 작동 원리는 간단합니다. 뉴런의 출력 = 활성화함수(입력1*가중치1 + 입력2*가중치2 + ... + 편향). 학습 시 손실 함수를 최소화하는 방향으로 가중치가 조금씩 업데이트됩니다. 이 과정이 수백만 번 반복되며, 가중치들은 점차 데이터의 패턴을 표현하게 됩니다.

실무에서 가중치는 모델 파일(.pt, .safetensors, .bin)로 저장됩니다. 사전학습된 가중치를 로드하여 파인튜닝하거나, 가중치를 공유하여 모델을 배포합니다. Hugging Face에서 다운로드하는 모델 파일이 바로 이 가중치들의 집합입니다. 양자화(Quantization)로 가중치 정밀도를 낮춰 모델 크기를 줄이기도 합니다.

💻 코드 예제

import torch
import torch.nn as nn

# 1. 간단한 신경망 정의
class SimpleNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(10, 5)  # 10 입력 -> 5 출력
        self.fc2 = nn.Linear(5, 2)   # 5 입력 -> 2 출력

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        return self.fc2(x)

model = SimpleNN()

# 2. 가중치 확인
print("=== fc1 레이어 가중치 ===")
print(f"가중치 shape: {model.fc1.weight.shape}")  # [5, 10]
print(f"편향 shape: {model.fc1.bias.shape}")      # [5]
print(f"가중치 값 (일부):\n{model.fc1.weight[:2, :3]}")

# 3. 전체 파라미터 수 계산
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f"\n총 파라미터: {total_params:,}")
print(f"학습 가능 파라미터: {trainable_params:,}")

# 4. 가중치 초기화
def init_weights(m):
    if isinstance(m, nn.Linear):
        nn.init.xavier_uniform_(m.weight)
        nn.init.zeros_(m.bias)

model.apply(init_weights)
print(f"\n초기화 후 가중치:\n{model.fc1.weight[:2, :3]}")

# 5. 가중치 저장 & 로드
torch.save(model.state_dict(), "model_weights.pt")
print("\n가중치 저장 완료: model_weights.pt")

# 새 모델에 가중치 로드
new_model = SimpleNN()
new_model.load_state_dict(torch.load("model_weights.pt"))
print("가중치 로드 완료!")

# 6. 학습 중 가중치 변화 관찰
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
criterion = nn.CrossEntropyLoss()

# 더미 데이터
x = torch.randn(32, 10)
y = torch.randint(0, 2, (32,))

print(f"\n학습 전 fc1.weight[0,0]: {model.fc1.weight[0,0].item():.6f}")

# 학습 스텝
for _ in range(10):
    optimizer.zero_grad()
    output = model(x)
    loss = criterion(output, y)
    loss.backward()
    optimizer.step()

print(f"학습 후 fc1.weight[0,0]: {model.fc1.weight[0,0].item():.6f}")

# 7. 가중치 프리징 (일부 레이어 학습 중지)
for param in model.fc1.parameters():
    param.requires_grad = False

print(f"\nfc1 프리징 후 학습 가능 파라미터: {sum(p.numel() for p in model.parameters() if p.requires_grad):,}")

🗣️ 실무에서 이렇게 말하세요

💬 회의에서

"이 모델 가중치 파일이 14GB인데요, INT4 양자화하면 3-4GB로 줄일 수 있어요. 정확도는 약간 떨어지지만 추론 속도가 빨라지고 GPU 메모리도 덜 먹습니다."

💬 면접에서

"가중치와 파라미터의 차이가 뭔가요?" - "가중치는 레이어 간 연결 강도고, 파라미터는 가중치와 편향(bias)을 모두 포함하는 상위 개념입니다. '70B 파라미터 모델'이라고 하면 가중치+편향이 총 700억 개라는 뜻이에요."

💬 기술 토론에서

"LoRA는 사전학습 가중치를 프리징하고 저랭크 어댑터만 학습해요. 원본 가중치 W에 델타 가중치 BA를 더하는 방식이라 전체 파인튜닝 대비 학습 파라미터가 0.1%도 안 됩니다."

⚠️ 흔한 실수 & 주의사항

가중치 초기화 무시

모든 가중치를 0이나 같은 값으로 초기화하면 대칭성 문제로 학습이 안 됩니다. Xavier, He 초기화 등 레이어와 활성화 함수에 맞는 초기화 방법을 사용하세요.

가중치 파일 형식 혼동

.pt(PyTorch), .safetensors(안전한 형식), .bin(Hugging Face), .ckpt(체크포인트) 등 형식이 다양합니다. 호환성 문제가 있으니 로드 방법을 확인하세요. safetensors는 pickle 취약점이 없어 권장됩니다.

Gradient Checkpointing 활용

대규모 모델 학습 시 중간 활성화를 저장하지 않고 역전파 때 재계산하면 메모리를 크게 절약할 수 있습니다. 속도는 느려지지만 더 큰 배치나 모델 학습이 가능해집니다.

🔗 관련 용어

📚 더 배우기