2014년, Sutskever·Vinyals·Le는 LSTM 두 개를 이어붙였다. 하나는 문장을 고정 길이 벡터 하나로 압축하고(인코더), 다른 하나는 그 벡터를 풀어 새 문장을 만든다(디코더). 신경망만으로 기계번역이 통계 기반 시스템을 이긴 첫 순간 — 그리고 그 구조의 병목이 곧 어텐션과 트랜스포머를 부른다. 이 페이지의 모든 데모는 외부 라이브러리 없이 브라우저에서 직접 실행되며, 미니 seq2seq가 지금 이 페이지 안에서 실제로 학습된다.
4장까지의 RNN은 입력과 출력이 한 스텝씩 맞물려 있었다. 문자 하나를 읽으면 다음 문자 하나를 예측한다. 그런데 번역은 다르다 — 입력은 영어 5단어, 출력은 프랑스어 7단어일 수 있다. 길이도 다르고, 어순도 다르다. 가변 길이 시퀀스를 가변 길이 시퀀스로 사상하는 문제.
seq2seq의 답은 문제를 둘로 쪼개는 것이다. 인코더 LSTM이 입력을 끝까지 읽고
마지막 상태(은닉 상태 h와 셀 상태 C)를 문맥 벡터 c로 삼는다. 디코더 LSTM은 c를
초기 상태로 받아, 직전에 자기가 생성한 단어를 다시 입력으로 넣으며(자기회귀)
<EOS>가 나올 때까지 한 단어씩 출력한다.
단, 논문의 LSTM은 한 층이 아니라 4층으로 쌓여 있다. 그래서 실제 c는
벡터 하나가 아니라 층마다 하나씩 있는 (h, C) 묶음이고, 인코더 층 l의 마지막 상태가
디코더 층 l의 초기 상태로 1:1로 넘어간다. 아래 첫 데모는 흐름을 보기 위해 1층으로 단순화했고,
두 번째 데모가 층을 쌓은 실제 구조다.
층 l = 1…L, C는 셀 상태. 층 1의 입력은 단어, 층 l>1의 입력은 바로 아래층의 h
인코더: (h_t^l, C_t^l) = LSTM_enc^l((h_{t-1}^l, C_{t-1}^l), h_t^{l-1}) h_t^0 = x_t
문맥: c = {(h_T^l, C_T^l)}_{l=1…L} ← 문장 전체가 층별 (h, C) 묶음 하나로
디코더: (s_j^l, S_j^l) = LSTM_dec^l((s_{j-1}^l, S_{j-1}^l), s_j^{l-1}) s_j^0 = y_{j-1}
(s_0^l, S_0^l) = (h_T^l, C_T^l) ← 같은 층끼리 이어받음
p(y_j | y_<j, x) = softmax(W · s_j^L) ← 출력은 맨 위층에서만
목적: P(y_1…y_U | x_1…x_T) = Π_j p(y_j | c, y_<j)
"I am a student"가 프랑스어 "je suis étudiant"로 번역되는 과정을 스텝별로 따라가 보자.
인코더가 단어를 읽을 때마다 은닉 상태(색 띠)가 갱신되고, 문장 전체가 벡터 c 하나에 담긴 뒤,
디코더가 그것만 보고 단어를 하나씩 뽑아낸다.
가로는 시간, 세로는 층이다. 층 1은 단어를 입력으로 받고, 그 위층은 바로 아래층의 은닉 상태 h를 입력으로 받는다.
주황 화살표가 문맥 벡터 c의 정체다. 인코더의 각 층이 마지막 (h, C)를 디코더의 같은 층에 넘긴다.
층 수를 바꿔 보자.
구조를 다시 보자. 입력이 5단어든 50단어든, 디코더에게 전달되는 것은
고정 차원 벡터 c 하나다. 문장이 길어질수록 같은 크기 벡터에
더 많은 정보를 밀어 넣어야 하고, 압축은 점점 손실적이 된다.
인코더가 문장 끝에 도달할 무렵, 앞부분의 정보는 이미 흐려져 있다.
이 병목은 추측이 아니라 측정된 사실이다. 이듬해 Bahdanau·Cho·Bengio가 고정 벡터 인코더–디코더(RNNencdec)의 번역 품질을 문장 길이별로 재 보니, 약 20단어를 넘어서면 BLEU가 급락했다.
슬라이더로 입력 문장 길이를 늘려보자. 단어(파란 칸)는 늘어나는데 문맥 벡터의 칸 수는 그대로다. 앞쪽 단어일수록 인코더 끝에 도달할 때까지 더 많은 스텝을 살아남아야 해서 정보가 흐려진다(투명해지는 칸).
Bahdanau et al. (2015) 그림 2의 고정 벡터 모델(RNNencdec-50) 곡선을 근사 재구성한 것. 20단어 부근을 정점으로, 문장이 길어질수록 번역 품질이 무너진다. 이 곡선이 어떻게 해소됐는지는 §6에서 본다.
논문에서 가장 유명한 발견은 어이없을 만큼 단순하다. 소스 문장의 단어 순서만 뒤집어서 넣었더니 — 타깃은 그대로 두고 — 퍼플렉시티가 5.8 → 4.7로 내려가고 단일 모델 BLEU가 25.9 → 30.6으로 뛰었다.
왜일까? 순방향이면 소스의 첫 단어를 읽고 나서 타깃의 첫 단어를 생성할 때까지 항상 문장 길이만큼의 스텝이 걸린다. 역순이면 소스 첫 단어가 인코더의 맨 마지막에 읽히므로, 타깃 첫 단어와의 거리가 1로 줄어든다. 전체 평균 거리는 정확히 같지만, 짧은 의존성이 여럿 생겨서 경사가 흐를 첫 통로가 열리고 최적화가 굴러가기 시작한다.
소스 x₁…x_T를 읽은 뒤 타깃 y₁…y_T를 생성한다고 하자(단조 정렬 가정). x_j를 읽은 시점부터 y_j를 생성하는 시점까지의 스텝 수가 곧 "정보가 살아남아야 하는 거리"다. 역순 토글을 눌러 거리들이 어떻게 재배치되는지 보자.
역순 트릭이 정말 효과가 있는지 지금 여기서 실험해 보자.
아래 데모는 진짜 LSTM 인코더–디코더 두 벌을 자바스크립트로 구현한 것이다(은닉 32차원, 어휘 6개).
과제는 복사: a b c d 네 글자로 된 무작위 문자열(길이 2–6)을 읽고
똑같이 출력하면 성공. 단순해 보이지만 첫 글자를 출력하려면 인코더 처음에 읽은 정보가
문장 끝까지 살아남아야 하는, 병목이 그대로 드러나는 과제다.
모델 A는 입력을 그대로, 모델 B는 역순으로 읽는다. 그 외 조건(구조·초기화·학습 데이터)은 동일하다. 복사 과제에서 순방향은 모든 글자의 의존 거리가 똑같이 T지만, 역순은 첫 글자의 거리가 1이 된다 — §3의 상황 그대로다.
학습은 CPU에서 실행되며 수십 초면 충분하다(1,500 배치 전후부터 차이가 벌어진다). 손실 곡선도 곡선이지만, 진짜 차이는 아래 길이별 정확도에서 드러난다 — 학습 중간중간 눌러 비교해 보자.
학습은 길이 2–6에서만 했다. 길이 7–9는 모델이 한 번도 본 적 없는 학습 범위 밖(extrapolation) 구간 — 문장이 길어질수록 BLEU가 떨어지던 §2 곡선의 미니어처를 여기서 재현할 수 있다.
인코더/디코더 각각: 표준 LSTM 1층, 은닉 32차원
[i, f, o, g] = W·[x; h_prev] + b, c = σ(f)∘c_prev + σ(i)∘tanh(g), h = σ(o)∘tanh(c)
어휘: {a, b, c, d, <EOS>, <SOS>} — 원-핫 입력
학습: teacher forcing, Adam(lr 0.003), 그래디언트 클리핑 5.0, 배치 8
디코더 초기 상태 = 인코더의 마지막 (h, c) — 논문과 동일한 "문맥 벡터" 방식
A와 B는 매 배치 같은 문장을 받는다. B만 인코더 입력을 뒤집는다.
디코더는 매 스텝 확률 분포를 내놓을 뿐, 문장 전체의 최적 조합을 보장하지 않는다. 매번 가장 확률 높은 단어만 고르면(그리디) 초반의 한 번의 실수가 끝까지 발목을 잡는다. 빔 서치는 상위 B개의 부분 가설을 병렬로 유지하며 전개하다가, 누적 로그확률이 가장 높은 완성 문장을 고른다.
원논문은 빔 폭 12를 썼지만, 재미있게도 빔 폭 2만으로 이득의 대부분을 얻었다고 보고한다. 심지어 빔 폭 1(그리디)도 꽤 잘 동작했다 — 모델이 좋으면 탐색은 거들 뿐.
§4에서 학습한 모델 B(역순 입력)의 실제 확률로 빔 서치를 전개한다. 각 열이 디코딩 한 스텝. 테두리가 초록인 가설만 살아남고, 흐려진 가설은 빔에서 잘린 것. 학습을 먼저 돌려야 의미 있는 확률이 나온다.
seq2seq는 서츠케버 목록에 없다. 하지만 목록의 5장 전체가 이 논문이 깔아놓은 무대 위에서 진행된다. "문장 전체를 벡터 하나로"라는 설계는 힌턴의 생각 벡터(thought vector) 직관의 구현이었고, 동시에 그 직관의 한계 증명이 됐다. 압축이 병목이라면? 답은 압축을 포기하는 것이었다.
Bahdanau 어텐션은 c를 하나로 고정하는 대신 디코더 스텝마다 다시 만든다 —
소스 전체를 훑어 지금 필요한 단어에 가중치를 주면서. 그리고 3년 뒤 트랜스포머는
"그럼 순환이 애초에 왜 필요한가"라고 묻는다. 인코더–디코더라는 뼈대, 자기회귀 생성,
빔 서치, <EOS> 토큰 — 오늘의 LLM이 물려받은 유산 대부분이 이 6페이지 논문에서 왔다.
seq2seq (2014): c = {(h_T^l, C_T^l)}_l ← 고정 크기 묶음 하나에 전부
어텐션 (2015): c_j = Σ_t α_{jt}·h_t ← 생성 스텝마다 소스 전체를 다시 조회
트랜스포머 (2017): 순환 제거, attention만으로 ← 5장에서 계속
§2에서 본 고정 벡터 곡선(RNNencdec-50)에 같은 논문의 어텐션 모델(RNNsearch-50)을 겹쳤다. 매 생성 스텝마다 소스 전체를 다시 보는 어텐션은 60단어까지 거의 평탄하다. 병목은 실재했고, 어텐션이 그것을 걷어냈다.
각 문제의 답을 고르면 해설이 열린다. 0 / 6