인코더(Encoder)는 입력 데이터를 받아 특징(feature)을 추출하는 모듈 또는 기능이다. 입력 데이터의 종류에 따라 다양한 구조로 구현될 수 있다.
인코더는 입력 값(토큰화된 단어 또는 문장)을 받아들인다. 어텐션 매커니즘을 이용해 입력 값 간의 관계를 파악한 다음, 이를 고차원의 벡터 표현으로 바꾼다. 이렇게 하면 입력 값의 의미와 문맥이 파악된다.
인코더는 입력 데이터를 받아 특정한 특징을 추출하고 고차원 벡터로 변환하는 기능을 수행한다. 이는 자연어 처리(NLP), 이미지 처리, 신호 처리 등 다양한 분야에서 활용된다.
Seq2Seq(Sequence-to-Sequence) 모델은 '입력된 문장을 요약하고 새로운 문장으로 변환하는 모델'이다. 마치 동시통역사와 같다. 우리가 외국인과 대화한다고 생각해 보자. 예를 들어 영어로 말을 하면 이를 한국어로 번역해 주는 동시통역사가 있다고 가정해 보자. 이 통역사는 두 가지 역할을 한다.
통역사는 상대방의 말을 주의 깊게 듣고, 중요한 의미를 머릿속에 정리한다. 하지만 영어 문장을 그대로 외우지는 않고, 핵심 내용을 요약해서 머릿속에 저장한다.
[입력 문장(영어)]
I am studying AI because I want to develop smart systems in the future.
[인코더(요약 과정)]
(머릿속에서 정리) → "AI 공부 중. 이유: 스마트 시스템 개발하고 싶음."
여기에서 중요한 점은 이렇게 요약한 정보를 다음 사람이 이해할 수 있도록 '압축된 형태'로 전달해야 한다는 것이다. 즉, 인코더는 전체 문장을 그대로 넘기는 것이 아니라, 핵심 정보(핵심 벡터)로만 정리하여 전달하는 역할을 한다. 이것이 바로 문장을 벡터(vector) 형태로 압축하여 디코더에 넘기는 과정이다. 이 압축된 벡터는 컨텍스트 벡터(context vector)라고도 한다.
통역사는 이때 들은 내용을 바탕으로 한국어로 자연스럽게 번역해서 전달한다. 하지만 단어 하나하나를 그대로 변환하는 것이 아니라, 전체적인 의미를 고려해서 자연스럽게 문장을 생성해야 한다.
[디코더(출력 생성 과정)]
(압축된 정보를 기반으로 새 문장 생성) → "나는 미래에 스마트 시스템을 개발하고 싶어서 AI를 공부하고 있다."
즉, 디코더는 인코더가 압축한 정보를 받아 이를 다시 자연어로 풀어내는 역할을 한다. 이 과정은 마치 암호화된 메시지를 풀어서 자연스럽게 전달하는 것과 비슷하다. 그렇다면 인코더는 어떻게 원래 문장을 압축할 수 있었을까? 토큰화(tokenization)와 임베딩(embedding)으로 인공지능이 계산할 수 있도록 문장을 숫자로 바꾸고 벡터로 변환했기 때문이다.
다음 문장으로 토큰화와 임베딩의 전 과정을 살펴보자. 다음 내용은 토큰화와 임베딩의 과정을 직관적으로 이해하기 위함이니 각 숫자가 무엇을 의미하는지는 크게 신경 쓰지 않아도 된다.
"I am studying AI because I want to develop smart systems in the future."
먼저 이 문장을 작은 단위(토큰)로 나누어야 한다.
['I', 'am', 'studying', 'AI', 'because', 'I', 'want', 'to', 'develop', 'smart', 'systems', 'in', 'the', 'future', '.']
문장을 나눈 후 각 토큰을 숫자로 변환하는 과정을 거친다.
[101, 2023, 1024, 30522, 2015, 1045, 2215, 2000, 9377, 6045, 3000, 1999, 1996, 2920, 102]
이렇게 토큰 ID(숫자)로 변환한 후 토큰 관계를 모델이 이해할 수 있도록 벡터 형태로 변환하는 '임베딩 과정'을 거친다. 4차원 벡터로 변환한다고 가정하면 다음과 같이 변환된다.
40 → [ 0.12, -0.85, -0.32, 0.78 ] # "I"
1097 → [ 0.67, 0.15, -0.45, -0.23 ] # "am"
21630 → [ 0.22, 0.89, 0.57, -0.12 ] # "studying"
4037 → [-0.44, -0.32, 0.91, 0.28 ] # "AI"
2015 → [-1.00, -0.76, -0.31, 0.55 ] # "because"
1045 → [-0.86, -0.21, 0.87, -0.65 ] # "I"
2215 → [-0.19, 0.32, -0.12, 0.39 ] # "want"
2000 → [ 0.29, 0.53, 0.60, -0.41 ] # "to"
9377 → [ 0.25, 0.78, 0.52, -0.37 ] # "develop"
6045 → [ 0.11, 0.72, -0.39, 0.59 ] # "smart"
3000 → [-0.16, 0.33, -0.76, -0.08 ] # "systems"
1999 → [ 0.36, -0.12, 0.95, 0.30 ] # "in"
1996 → [ 0.22, 0.90, -0.48, 0.62 ] # "the"
2920 → [ 0.17, -0.35, 0.89, -0.50 ] # "future"
102 → [ 0.17, -0.35, 0.89, -0.50 ] # "."
이제 Seq2Seq 인코더의 핵심이 등장한다. 바로 정보를 압축하여 디코더로 넘기는 것이다.
인코더는 이 토큰 임베딩 벡터들을 분석하여 문장의 핵심 정보를 하나의 벡터로 압축한다. 이 벡터를 컨텍스트 벡터(context vector)라고 한다. 문맥 정보를 담고 있다고 해서 문맥을 의미하는 컨텍스트 벡터라는 이름을 붙였다. 컨텍스트 벡터는 마치 문장의 요약본처럼 작동한다. 예를 들어 다음과 같이 전체 문장을 요약하는 하나의 벡터가 생성될 수 있다.
컨텍스트: AI 공부 중, 이유: 스마트 시스템 개발
컨텍스트 벡터: [0.45, -0.12, 0.78, 0.34]
이제 인코더는 이 벡터를 디코더에 넘긴다. 디코더는 압축된 정보, 즉 이 컨텍스트 벡터를 받아서 새로운 문장을 생성한다. 하지만 문제는 단순한 숫자 벡터를 어떻게 자연어 문장으로 바꾸냐는 것이다. 그래서 디코더는 RNN(순환 신경망)을 이용하여 한 단어씩 생성하면서 문장을 만든다.
[디코더(출력 생성 과정)]
step 1. 초기 입력
컨텍스트 벡터 → "나는" 예측
step 2. 이전 단어 + 컨텍스트 벡터
"나는" + 컨텍스트 벡터 → "나는 미래에" 예측
step 3. 이전 단어 + 컨텍스트 벡터
"나는 미래에" + 컨텍스트 벡터 → "나는 미래에 스마트" 예측
step 4. 이전 단어 + 컨텍스트 벡터
"나는 미래에 스마트" + 컨텍스트 벡터 → "나는 미래에 스마트 시스템을" 예측
step 5. 이전 단어 + 컨텍스트 벡터
"나는 미래에 스마트 시스템을" + 컨텍스트 벡터 → "나는 미래에 스마트 시스템을 개발하고 싶어서" 예측
최종 출력 문장은 다음과 같습니다.
"나는 미래에 스마트 시스템을 개발하고 싶어서 AI를 공부하고 있다."
즉, 디코더는 '압축된 의미'를 받아 한 단어씩 문장을 만들어 가는 역할을 한다. 이 과정은 마치 요약한 개요를 보고 새로운 글을 써 내려가는 것과 비슷하다.
Seq2Seq 모델은 기존 RNN과 달리 단순히 예측하는 것이 아니라 새로운 문장을 생성하는 모델이다.
이 구조를 기반으로 챗봇, 번역 모델, 텍스트 요약 모델, 문장 생성 AI가 발전할 수 있었다. 하지만 RNN 기반 알고리즘이기 때문에 몇 가지 문제점이 있다.
먼저 긴 문장을 처리하는 데 한계가 있다. 문장이 길어질수록 앞부분 정보가 점점 희미해지는 문제가 발생하기 때문이다.
그리고 컨텍스트 벡터의 한계가 있다. 인코더가 디코더로 넘기는 압축 정보(컨텍스트 벡터)가 너무 작으면 중요한 정보를 충분히 전달하지 못할 수도 있다. 그래서 문장이 길어진다면 번역 품질이 떨어지는 문제가 발생할 수 있다.
이러한 문제를 해결하기 위해 '어텐션 메커니즘'이 도입되었고, 어텐션 모델은 마침내 트랜스포머(Transformer)의 핵심 요소로 발전했다. 즉, Seq2Seq는 자연어 생성(Natural Language Generation, NLG)의 시작을 알린 중요한 모델이었다.