LLM 엔지니어링2장 · 신경망과 딥러닝의 기본 원리16 / 23← 이전목차다음 →MetaContents

2장. 신경망과 딥러닝의 기본 원리

실습 2 — 자동 미분으로 직선 맞추기

PyTorch 의 자동 미분과 경사하강법을, 층 없이 가중치 두 개(w, b)만으로 직접 돌려 봅니다. 점 다섯 개가 y = 2x + 1 위에 있을 때, w 와 b 를 0 에서 출발시켜 2 와 1 을 찾아가게 합니다.

1단계. 기울기 하나 구해 보기

Python
import torch

# requires_grad=True: 이 값의 기울기가 필요하다고 표시한다
w = torch.tensor(2.0, requires_grad=True)
y = w ** 2 + 3 * w       # 계산 과정이 기록된다

y.backward()             # y 를 w 로 미분: 2w + 3
print("w = 2 에서의 기울기:", w.grad.item())
출력
w = 2 에서의 기울기: 7.0

이 단계의 함수입니다.

코드쉬운 뜻
torch.tensor(2.0, requires_grad=True)숫자 2 를 담은 0차원 텐서를 만들고, "이 값의 기울기가 필요하다"고 표시한다
y.backward()y 를 만든 계산을 거꾸로 따라가 기울기를 구해 w.grad 에 넣는다
w.grad.item()w.grad 에 담긴 기울기 텐서에서 숫자 하나를 꺼낸다

2단계. 데이터와 가중치 준비

Python
# 점 다섯 개: 모두 y = 2x + 1 위에 있다
x = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0])
y = 2 * x + 1

# 찾아야 할 가중치 w 와 편향 b. 0 에서 출발한다
w = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
lr = 0.02     # 학습률(보폭)
print("정답:", y.tolist())
출력
정답: [3.0, 5.0, 7.0, 9.0, 11.0]

이 단계의 함수입니다.

코드쉬운 뜻
torch.tensor([1.0, ..., 5.0])점 다섯 개의 x 값을 1차원 텐서로 만든다
2 * x + 1칸마다 계산한다. 다섯 점의 정답 y 가 한 번에 나온다
torch.tensor(0.0, requires_grad=True)찾아야 할 w, b 를 0 에서 출발시키고 기울기를 구하도록 표시한다
lr = 0.02학습률(보폭)을 정한다. 함수가 아니라 숫자 하나다
y.tolist()텐서를 파이썬 리스트로 바꾼다. 찍을 때 tensor(...) 없이 숫자만 보인다

3단계. 경사하강법 손으로 돌리기

Python
for step in range(1, 501):
    pred = w * x + b                       # 순전파: 지금의 w, b 로 예측
    loss = ((pred - y) ** 2).mean()        # 손실: MSE
    loss.backward()                        # 역전파: w.grad, b.grad 가 채워진다

    with torch.no_grad():                  # 가중치를 고치는 계산은 기록하지 않는다
        w -= lr * w.grad                   # 기울기 반대쪽으로 한 걸음
        b -= lr * b.grad
    w.grad.zero_()                         # 다음 걸음을 위해 기울기를 지운다
    b.grad.zero_()

    if step in (1, 10, 50, 100, 500):
        print(f"{step:3d}번째  w={w.item():.3f}  b={b.item():.3f}  손실={loss.item():.4f}")
출력
  1번째  w=1.000  b=0.280  손실=57.0000
 10번째  w=2.104  b=0.612  손실=0.0282
 50번째  w=2.082  b=0.705  손실=0.0161
100번째  w=2.058  b=0.790  손실=0.0082
500번째  w=2.004  b=0.986  손실=0.0000

이 단계의 함수입니다.

코드쉬운 뜻
for step in range(1, 501)경사하강법 걸음을 500번 되풀이한다
w * x + b지금의 w, b 로 다섯 점을 한꺼번에 예측한다(순전파)
((pred - y) ** 2).mean()오차를 제곱해 평균 낸다. nn.MSELoss() 와 같은 계산을 손으로 적은 것이다
loss.backward()손실에서 거꾸로 따라가 w.grad, b.grad 를 채운다
with torch.no_grad():이 들여쓰기 안의 계산은 기록하지 않는다. 가중치를 고치는 일은 학습할 계산이 아니기 때문이다
w -= lr * w.gradw 를 "학습률 × 기울기"만큼 줄인다. 기울기가 음수면 오히려 커진다
w.grad.zero_()기울기를 0 으로 지운다. 이름 끝의 _ 는 PyTorch 에서 "그 자리에서 바꾼다"는 표시다
w.item(), loss.item()텐서에서 숫자 하나를 꺼내 찍는다
f"{w.item():.3f}"소수 셋째 자리까지 찍는다. {step:3d} 는 세 칸에 맞춰 찍는다

이 실습이 뜻하는 것

이 실습은 샤워기의 물 온도를 맞추는 일과 같습니다. 먼저 손잡이를 살짝 돌리면 온도가 얼마나 바뀌는지 느껴 보고(1단계), 원하는 온도를 정하고 손잡이를 맨 처음 자리에 둔 뒤(2단계), "너무 차다, 조금 더"를 500번 되풀이하며 손잡이를 고칩니다(3단계). 여기서 손잡이 위치가 w 와 b, 원하는 온도가 정답 y, 지금 온도와의 차이가 손실, "얼마나 돌릴까"가 학습률 × 기울기입니다. 비유와 다른 점은, 샤워기는 손잡이가 하나지만 여기서는 w 와 b 두 개를 함께 돌린다는 것입니다.

단계출력뜻
1. 기울기7.0w 를 조금 늘리면 y 가 그 7배쯤 늘어난다는 뜻입니다. 미분 식을 적지 않았는데 backward() 가 구했습니다
2. 정답[3.0, 5.0, 7.0, 9.0, 11.0]점 다섯 개의 정답입니다. 모델은 이 숫자만 보고 2 와 1 을 찾아야 합니다
3. 1번째w=1.000, b=0.280, 손실 57.0000손실 57 은 w, b 가 0 일 때 잰 값입니다. 한 걸음 만에 w 가 1 로 크게 움직였습니다
3. 10번째w=2.104, 손실 0.0282w 가 정답 2 를 조금 넘었습니다. 손실은 이미 크게 줄었습니다
3. 100번째w=2.058, b=0.790w 는 2 쪽으로 돌아오고, b 는 1 을 향해 천천히 올라갑니다
3. 500번째w=2.004, b=0.986, 손실 0.00002 와 1 에 거의 닿았습니다. 손실 0.0000 은 소수 넷째 자리 아래로 작아졌다는 뜻입니다

한 줄로 줄이면, 정답 공식(y = 2x + 1)을 알려 주지 않아도 "기울기 반대쪽으로 조금씩"만 되풀이하면 w 와 b 가 2 와 1 을 찾아간다는 것을 보인 실습입니다. 실습 4부터는 이 손 계산을 nn.Linear 와 옵티마이저가 대신합니다. 점 다섯 개가 정확히 한 직선 위에 있는 쉬운 문제라서 손실이 0 근처까지 내려간 것이고, 실제 데이터에서는 손실이 0 까지 가지 않습니다.

코드 설명

  • 1단계의 기울기 7.0 은 2w + 3 에 w = 2 를 넣은 값입니다. 미분 식을 적지 않았는데도 backward() 가 구했습니다.
  • torch.no_grad() 안에서 가중치를 고치는 까닭은, 고치는 계산까지 기록되면 다음 역전파가 엉키기 때문입니다.
  • w.grad.zero_() 를 빼면 기울기가 걸음마다 쌓여서 점점 큰 걸음을 걷게 됩니다. 학습 루프의 zero_grad() 와 같은 일입니다.
  • 첫 걸음 뒤 w=1.000, b=0.280 에서 출발해, 10번째에 w 가 2.104 로 정답 2 를 조금 넘었다가 다시 내려옵니다. 500번째에는 w=2.004, b=0.986 으로 2 와 1 에 거의 닿고, 손실은 0.0000 으로 찍힙니다(소수 넷째 자리 아래로 작아졌다는 뜻입니다). b 가 w 보다 늦게 따라오는 것은 b 의 기울기가 더 작기 때문입니다.
  • 실습 4부터는 이 손 계산을 nn.Linear 와 옵티마이저가 대신 해 줍니다. 하는 일은 똑같습니다.
← 이전 절2장 · 실습 1 — 텐서 다루고 GPU 확인하기다음 절 →2장 · 실습 3 — 주문량 데이터 준비하기