1장. 준비 수학과 Transformer 개요
신경망에서 shape 가 바뀌는 모습
공장의 설비 점검표를 생각해 봅니다. 기계 4대에서 센서 값 3개씩을 읽어(4행 3열 표) 담당자에게 넘기면, 담당자는 이를 살펴 중간 메모 5칸으로 정리하고(4행 5열), 최종 판정표에 "정상, 주의, 고장" 세 칸의 점수를 적습니다(4행 3열). 기계 대수 4는 끝까지 그대로이고, 칸 수만 3 → 5 → 3으로 바뀝니다. 신경망의 층도 행렬곱으로 이렇게 칸 수를 바꿉니다.
강사자료 그림의 왼쪽은 입력 x(센서 3개), 가운데는 은닉 표현(노드 5개), 오른쪽은 출력 z(정상, 주의, 고장 점수 3개)입니다. 그 사이의 가중치 W₁ 은 3행 5열, W₂ 는 5행 3열입니다. 아래 두 줄이 샘플 4개를 한꺼번에 넣을 때의 계산입니다. x (4, 3) @ W₁ (3, 5) → (4, 5), (4, 5) @ W₂ (5, 3) → (4, 3) 입니다. 그림 아래 글처럼 ReLU 와 softmax 는 shape 를 바꾸지 않습니다.
층마다 바뀌는 shape
| 단계 | shape | 하는 일 | 점검표로 치면 |
|---|---|---|---|
| 입력 x | (4, 3) | 샘플 4개, 센서 값 3개 | 기계 4대의 센서 기록 |
| 은닉 표현 | (4, 5) | x @ W1 (행렬곱) | 담당자의 중간 메모 5칸 |
| 출력 | (4, 3) | 은닉 표현 @ W2 (행렬곱) | 정상·주의·고장 점수 |
| 확률 | (4, 3) | 행마다 softmax | 기계마다 판정 비율, 합 1 |
짧은 예시
import numpy as np
def softmax(z):
e = np.exp(z - z.max(axis=-1, keepdims=True))
return e / e.sum(axis=-1, keepdims=True)
# default_rng(0): 씨앗 0으로 정한 난수 생성기. 실행할 때마다 같은 숫자가 나온다
rng = np.random.default_rng(0)
x = rng.normal(size=(4, 3)) # 기계 4대 × 센서 3개(정규분포에서 뽑은 예시 값)
W1 = rng.normal(size=(3, 5)) # 입력 3 → 은닉 5 로 바꾸는 가중치
W2 = rng.normal(size=(5, 3)) # 은닉 5 → 출력 3 으로 바꾸는 가중치
# np.maximum(0, ...): 음수는 0으로 바꾸는 ReLU. shape 는 그대로다
h = np.maximum(0, x @ W1)
z = h @ W2
p = softmax(z)
print(x.shape, h.shape, z.shape, p.shape) # 결과: (4, 3) (4, 5) (4, 3) (4, 3)
print(p.sum(axis=1)) # 결과: [1. 1. 1. 1.] → 기계마다 합이 1이 코드가 뜻하는 것
강사자료 그림의 2층 신경망을 NumPy 로 그대로 따라가며 shape 만 찍었습니다. 가중치는 학습하지 않은 무작위 값이라 판정 자체는 뜻이 없고, 모양이 어떻게 바뀌는지만 봅니다. 여기서 센서 기록이 x, 중간 메모가 h, 판정 점수가 z, 판정 비율이 p 입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
x @ W1 | (4, 3) @ (3, 5) → (4, 5) | 센서 3칸을 메모 5칸으로 |
np.maximum(0, ...) | 음수를 0으로 바꾼다 | 쓸모없는 메모는 지우기 |
h @ W2 | (4, 5) @ (5, 3) → (4, 3) | 메모 5칸을 판정 3칸으로 |
softmax(z) | 행마다 합 1로 | 기계마다 판정 비율 |
샘플 수 4는 처음부터 끝까지 그대로입니다. 가중치 shape 의 앞 숫자는 "들어오는 칸 수", 뒤 숫자는 "나가는 칸 수"라고 읽으면 됩니다.