1장. 준비 수학과 Transformer 개요
Softmax: 점수를 비율로 바꾸기
반장 선거 개표를 생각해 봅니다. 후보 A 가 3표, B 가 1표, C 가 0표를 받았다면 "A 가 몇 퍼센트를 얻었나"로 바꿔 말해야 한눈에 들어옵니다. 신경망의 마지막 출력도 이런 득표수 같은 점수입니다. 다만 점수는 음수일 수도 있어서 그대로 나누면 비율이 깨집니다. Softmax 는 점수를 먼저 모두 양수로 바꾼 뒤 합으로 나눠, 합이 1(100%)인 비율로 만듭니다.
강사자료 그림은 세 단계입니다. ① 점수 z 는 A 2.0, B 1.0, C 0.1 입니다. ② 각 점수를 e^z 로 바꾸면 7.39, 2.72, 1.11 로 모두 양수가 되고, 큰 점수는 더 크게 벌어집니다. e 는 약 2.718 인 수학 상수입니다. ③ 세 값의 합 7.39 + 2.72 + 1.11 = 11.22 로 나누면 0.66, 0.24, 0.10 이 되고 합은 1.00 입니다. 그림 아래 글처럼 점수 차이 1.0 은 확률에서 약 2.7배 차이로 바뀝니다.
Softmax 세 단계, 손으로 계산하기
| 단계 | 하는 일 | A | B | C | 투표로 치면 |
|---|---|---|---|---|---|
| ① 점수 z | 신경망의 출력 | 2.0 | 1.0 | 0.1 | 날것의 득표 점수 |
| ② e^z | 모두 양수로, 차이는 키우기 | 7.39 | 2.72 | 1.11 | 음수 없는 득표수로 바꾸기 |
| ③ 합으로 나누기 | 7.39 + 2.72 + 1.11 = 11.22 로 나눈다 | 0.66 | 0.24 | 0.10 | 투표 비율(합 100%) |
짧은 예시
import numpy as np
# 노트북 셀 14와 같은 꼴의 softmax 함수
def softmax(z):
# 가장 큰 점수를 빼 두면 e^z 가 너무 커져 넘치는 일을 막는다(결과 비율은 같다)
e = np.exp(z - z.max(axis=-1, keepdims=True))
# 합으로 나누면 합이 1인 비율이 된다
return e / e.sum(axis=-1, keepdims=True)
# 반장 선거의 득표 점수: A 3, B 1, C 0
votes = np.array([3.0, 1.0, 0.0])
print(np.round(np.exp(votes), 2)) # 결과: [20.09 2.72 1. ] → 합은 약 23.81
print(np.round(softmax(votes), 2)) # 결과: [0.84 0.11 0.04]
# 모든 점수에 100을 더해도 비율은 같다(점수 사이의 차이만 중요하다)
print(np.round(softmax(votes + 100), 2)) # 결과: [0.84 0.11 0.04]이 코드가 뜻하는 것
득표 점수를 투표 비율로 바꿨습니다. e^3 ≈ 20.09, e^1 ≈ 2.72, e^0 = 1 이고 합은 약 23.81 입니다. 20.09 ÷ 23.81 ≈ 0.84, 2.72 ÷ 23.81 ≈ 0.11, 1 ÷ 23.81 ≈ 0.04 입니다. 둘째 자리에서 반올림해 합이 0.99 로 보이지만, 반올림 전의 합은 정확히 1입니다. 여기서 득표 점수가 votes, 투표 비율이 softmax(votes) 입니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
np.exp(z - z.max(...)) | 최댓값을 뺀 뒤 e^z 를 구한다 | 넘치지 않게 눈금을 내린 득표수 |
e / e.sum(...) | 합으로 나눈다 | 득표수를 비율로 |
softmax(votes + 100) | 모든 점수에 같은 값을 더한다 | 모두에게 100표씩 주어도 순위와 비율은 같다 |
마지막 줄이 첫 줄의 "최댓값 빼기"가 안전한 까닭입니다. 모든 점수에서 같은 값을 빼거나 더해도 Softmax 의 결과는 변하지 않습니다.
주의할 점
- Softmax 는 점수 차이를 키웁니다. 점수 3과 1은 세 배 차이지만 비율은 0.84 와 0.11 로 일곱 배 넘게 벌어집니다. 6장의 temperature 는 이 벌어지는 정도를 조절하는 다이얼입니다.
np.exp(1000)처럼 아주 큰 점수를 그대로 넣으면 넘쳐서inf가 됩니다. 그래서 노트북의 함수도 최댓값을 먼저 뺍니다.axis=-1은 "마지막 축(행마다)"입니다. 점수가 표로 들어오면 행마다 따로 합이 1이 됩니다. Attention 표가 바로 이 꼴입니다.