이번 문서의 목표: 원-핫 인코딩과 임베딩의 차이를 설명하고, Encoder–Decoder 기반 Seq2Seq 구조의 정보 병목 문제를 이해하며, Query·Key·Value로 어텐션 가중치를 실제로 계산할 수 있다.
왜 임베딩이 필요한가
컴퓨터는 “고양이”, “강아지” 같은 단어를 그 자체로 이해하지 못한다. 신경망에 넣으려면 단어를 숫자 벡터로 바꿔야 한다. 가장 단순한 방법은 원-핫 인코딩(one-hot encoding)이다. 어휘 사전(vocabulary)에 단어가 개 있다면, 각 단어를 길이 짜리 벡터로 표현하되 그 단어에 해당하는 위치만 1, 나머지는 전부 0으로 채운다.
예를 들어 어휘 사전이 [고양이, 강아지, 사과, 학교] 4개뿐이라면, “강아지”는 다음처럼 표현된다.
문제는 두 가지다. 첫째, 실제 어휘 사전은 보통 수만에서 수십만 단어이므로 벡터 하나가 그만큼 길어지고, 대부분이 0인 희소 벡터(sparse vector)라 메모리와 연산이 낭비된다. 둘째, 더 심각한 문제로 모든 단어 쌍의 내적(inner product)이 0이 되어 단어 사이의 의미적 유사도를 전혀 표현하지 못한다. “고양이”와 “강아지”는 둘 다 동물이라 의미가 가까운데도, 원-핫 벡터로는 “사과”나 “학교”와 다를 바 없이 완전히 독립적으로 취급된다.
쉽게 말하면: 원-핫 인코딩은 단어에 번호표만 붙일 뿐, 단어끼리 얼마나 비슷한지는 전혀 담지 못한다.
임베딩(embedding)은 이 문제를 해결한다. 각 단어를 훨씬 짧은(보통 수십에서 수백 차원) 실수 벡터로 대응시키되, 이 벡터를 신경망 학습 과정에서 함께 학습시킨다. 학습이 끝나면 의미가 비슷한 단어일수록 임베딩 공간에서 서로 가까운 위치에 놓이게 된다.
| 비교 항목 | 원-핫 인코딩 | 임베딩 |
|---|---|---|
| 벡터 차원 | 어휘 사전 크기 (수만 이상 가능) | 하이퍼파라미터로 지정(보통 수십–수백) |
| 값의 형태 | 0과 1로 구성된 희소 벡터 | 학습된 실수 값으로 구성된 밀집 벡터 |
| 단어 간 유사도 | 모든 쌍의 내적이 0(유사도 표현 불가) | 의미가 비슷한 단어끼리 벡터가 가까워짐 |
| 학습 여부 | 고정된 규칙(학습 대상 아님) | 학습 파라미터(다른 가중치처럼 역전파로 갱신) |
수학적으로 임베딩은 “원-핫 벡터에 임베딩 행렬(embedding matrix) 를 곱하는 것”으로 이해할 수 있다.
- : 어휘 사전 크기 행, 임베딩 차원 열로 이루어진 행렬. 학습을 통해 값이 갱신된다.
- : “강아지”에 해당하는 원-핫 벡터.
- : 결과로 얻는 차원 임베딩 벡터.
실제 구현에서는 행렬 곱셈 대신 에서 해당 행을 바로 조회(lookup)하는 방식으로 계산하지만, 수학적 의미는 위 식과 같다. 이렇게 얻은 임베딩은 13편에서 다룬 RNN이나 LSTM의 입력 로 그대로 사용된다.
Seq2Seq: 시퀀스를 시퀀스로 바꾸는 구조
기계 번역(“나는 학교에 간다” → “I go to school”)처럼 입력도 시퀀스, 출력도 시퀀스이면서 두 시퀀스의 길이가 서로 다를 수 있는 문제를 시퀀스-투-시퀀스(Seq2Seq, Sequence-to-Sequence) 문제라 부른다. 13편의 RNN·LSTM은 “각 시점마다 하나씩 출력”하는 구조였지만, 번역에서는 원문을 다 읽은 뒤에야 번역을 시작해야 하는 경우가 많고 문장 길이도 다르다.
Seq2Seq는 이 문제를 인코더(encoder)와 디코더(decoder)라는 두 개의 RNN(또는 LSTM·GRU)으로 나눠 해결한다.
- 인코더: 입력 시퀀스를 처음부터 끝까지 읽으며 은닉 상태를 갱신하고, 마지막 시점의 은닉 상태 하나를 “문장 전체의 의미를 압축한 벡터”로 사용한다. 이를 문맥 벡터(context vector)라 부른다.
- 디코더: 문맥 벡터를 초기 은닉 상태로 받아, 한 단어씩 출력을 생성한다. 각 시점의 출력은 다음 시점의 입력으로 다시 들어간다(자기 회귀적 생성, autoregressive generation).
정보 병목 문제
Seq2Seq의 근본적인 약점은 “아무리 긴 문장이라도 고정된 크기의 문맥 벡터 하나에 전부 압축해야 한다”는 점이다. 이를 정보 병목(information bottleneck)이라 부른다. 문장이 5단어면 문제없지만, 50단어짜리 문장을 128차원 벡터 하나에 눌러 담으면 앞부분 정보가 뒤쪽 정보에 밀려 희석되기 쉽다. 실제로 Seq2Seq 모델은 문장이 길어질수록 번역 품질이 급격히 떨어지는 경향을 보였다.
어텐션: 필요할 때마다 원문을 다시 들여다본다
쉽게 말하면: 어텐션(attention)은 디코더가 매 단어를 생성할 때마다 “원문에서 지금 가장 관련 있는 부분이 어디인지”를 다시 찾아보는 메커니즘이다.
문맥 벡터 하나에 모든 정보를 우겨넣는 대신, 어텐션은 인코더의 모든 시점의 은닉 상태()를 그대로 보관해 두고, 디코더가 각 출력을 생성할 때마다 이 은닉 상태들 중 어디에 더 집중할지를 가중치로 계산한다.
이 계산을 표준화한 것이 Query(질의), Key(키), Value(값) 세 벡터를 이용한 방식이다. 15편의 Transformer에서 이 구조를 정식으로 다루므로, 여기서는 어텐션의 핵심 계산을 아주 작은 예시로 직접 검산해 본다.
- Query : “지금 내가 찾고 싶은 정보가 무엇인지”를 나타내는 벡터. 디코더의 현재 은닉 상태에서 만든다.
- Key : “이 위치()가 어떤 정보를 담고 있는지”를 나타내는 벡터. 인코더의 각 시점 은닉 상태에서 만든다.
- Value : “이 위치가 실제로 담고 있는 내용물” 벡터. 최종적으로 가중합에 쓰인다.
점수 함수: 내적으로 유사도를 잰다
Query와 각 Key의 내적(dot product)을 계산해 “지금 필요한 정보와 이 위치가 얼마나 관련 있는지”를 점수(score)로 만든다.
내적이 크다는 것은 두 벡터의 방향이 비슷하다는 뜻이므로, 점수가 클수록 그 위치의 정보가 지금 Query와 관련이 높다고 해석한다.
작은 숫자로 직접 계산하기
3단어짜리 원문 “나는 학교에 간다”를 인코더가 읽어 만든 Key와 Value가 각각 다음과 같은 2차원 벡터라고 하자(실제로는 임베딩 차원이 훨씬 크지만, 계산을 손으로 검산하기 위해 2차원으로 단순화한다).
디코더가 “학교”라는 단어를 생성하려는 시점에서 만든 Query가 다음과 같다고 하자.
먼저 세 개의 점수를 각각 내적으로 계산한다.
세 점수 을 06편에서 다룬 소프트맥스(softmax) 함수에 넣어 합이 1인 가중치로 바꾼다. 소프트맥스는 로 정의된다.
이제 각 가중치를 구한다.
- (알파): 번째 위치에 대한 어텐션 가중치. 모두 더하면 1이 된다(, 반올림 오차).
마지막으로 이 가중치를 Value 벡터에 곱해 더한 가중합(weighted sum)이 최종 어텐션 출력이다.
결과 해석
원래 Query 는 와 완전히 같은 방향이고 와도 어느 정도 겹치지만, 과는 직각(내적 0)이라 전혀 관련이 없다. 계산 결과도 이를 그대로 반영한다. 에 대응하는 로 가장 작고, 에 대응하는 로 훨씬 크다. 즉 디코더가 “학교”를 생성할 때 원문의 2, 3번째 위치(“학교에”, “간다”)에 해당하는 정보에 더 집중해서 값을 가져왔다는 뜻이다. 이렇게 어텐션은 문맥 벡터 하나에 의존하지 않고, 매 출력 시점마다 원문 전체를 다시 훑어 관련 있는 부분에 가중치를 실어 준다.
자주 틀리는 점
- 임베딩을 “차원을 줄이는 압축 기법”으로만 이해하는 경우가 있다. 차원이 줄어드는 것은 결과일 뿐, 핵심은 학습을 통해 의미적 유사도를 벡터 공간의 거리로 표현하게 된다는 점이다.
- Seq2Seq의 문맥 벡터를 “인코더의 모든 은닉 상태를 평균 낸 것”으로 오해하기 쉽다. 기본 Seq2Seq는 평균이 아니라 인코더의 마지막 시점 은닉 상태 하나만을 문맥 벡터로 사용한다.
- 어텐션 가중치를 Query와 Value의 내적으로 계산한다고 착각하는 경우가 많다. 점수는 반드시 Query와 Key의 내적이며, Value는 점수 계산이 끝난 뒤 가중합에만 쓰인다.
- 소프트맥스를 적용하기 전 점수를 그대로 가중치로 쓰는 실수도 흔하다. 점수는 아무 실수 값이나 될 수 있으므로, 반드시 소프트맥스를 거쳐 합이 1인 확률 분포 형태로 바꾼 뒤 가중합을 계산해야 한다.
핵심 정리
- 원-핫 인코딩은 어휘 크기만큼 차원이 커지고 단어 간 유사도를 전혀 표현하지 못하지만, 임베딩은 학습된 밀집 벡터로 의미적 유사도를 거리로 표현한다.
- Seq2Seq는 인코더가 입력을 문맥 벡터 하나로 압축하고 디코더가 이를 초기 상태로 받아 출력을 생성하는 구조이며, 문장이 길어지면 정보 병목이 심해진다.
- 어텐션은 인코더의 모든 은닉 상태를 Key·Value로 남겨 두고, 디코더의 Query와 내적으로 점수를 낸 뒤 소프트맥스로 가중치를 만들어 Value를 가중합한다.
- 점수 함수는 , 최종 출력은 형태로, 15편의 Transformer에서 이 구조를 확장해 다룬다.
마무리 복습
참고 자료
- Stanford CS224n: Natural Language Processing with Deep Learning — https://cs224n.stanford.edu
- Ian Goodfellow 외, Deep Learning — https://www.deeplearningbook.org