긴 글을 나누어 다음 문자 예측하기
인공지능응용 · 13주차
이번 주 목표 · 긴 글에서 짧은 학습 예제를 만드는 방법을 이해하고, 같은 데이터로 RNN·LSTM·GRU의 예측을 비교합니다.
실행: Colab에서 내 Drive에 사본을 저장한 뒤 Code Cell의 ▶ 또는 Shift+Enter로 위에서부터 실행하세요. ⟦직접 입력⟧ 표시가 있는 Text Cell은 더블클릭해서 수정합니다.
1. 같은 예측 문제에서 기억하는 구조를 바꾸기
hello!를 h → e → l → l → o → !처럼 순서대로 놓아 보세요. 이렇게 순서가 있는 데이터의 나열을 Sequence라고 합니다. 이번에는 문자 하나가 한 시점의 입력입니다. 공백과 문장부호도 문자 하나로 셉니다.
12주차와 마찬가지로, 앞에서 읽은 문자를 바탕으로 각 위치의 다음 문자를 맞힙니다. Input과 Target을 만드는 규칙, Linear 출력, Loss 계산은 유지하고 RNN Cell을 LSTM·GRU로 바꾸어 비교합니다.
RNN은 이전 Hidden State를 매 시점 새 값으로 갱신합니다. Sequence가 길어지면 앞쪽 정보와 학습 신호가 여러 변환을 거치며 약해질 수 있습니다. LSTM과 GRU는 Gate를 이용해 이전 정보와 새 정보가 반영되는 정도를 학습합니다.
2. 긴 글에서 짧은 학습 예제 만들기
개념 설명용 예시 · 아래에서는 짧은 문자열 hello!로 Window와 Input–Target 관계를 설명합니다. 실습에서는 Notebook에 제공된 더 긴 원문에 같은 규칙을 적용합니다.
긴 글도 문자들이 이어진 Sequence입니다. 한 번에 다루기 쉽게 일정한 길이만큼 잘라 여러 학습 예제를 만들겠습니다. 원문에서 잘라 보는 연속된 구간을 Window라고 부릅니다. Window는 데이터의 한 구간이며, RNN과 같은 모델의 이름은 아닙니다.
먼저 세 글자만 읽어 보기
hello!에서 처음 세 글자 hel을 Input으로 고릅니다. 모델은 각 위치에서 바로 다음 문자를 예측하므로 Target은 ell입니다.
원문 위치 0 1 2 3 4 5
원문 문자 h e l l o !
└── hel ──┘ Input: 위치 0~2
└── ell ──┘ Target: 위치 1~3
읽은 문자 h → e → l
맞힐 문자 e l l
첫 출력은 h 다음의 e, 두 번째 출력은 he 다음의 l, 세 번째 출력은 hel 다음의 l을 맞힙니다. 세 글자를 읽은 뒤 정답 하나만 내는 것이 아니라, 각 위치에 정답이 하나씩 있습니다. Input과 Target은 모두 길이 3입니다.
시작점을 옮겨 다음 예제 만들기
이번에는 시작점을 두 칸 옮겨 원문 위치 2부터 읽습니다. Input은 llo, Target은 lo!가 됩니다.
| 학습 예제 | 시작 위치 | Input: 세 글자 읽기 | Target: 각 위치의 다음 문자 |
|---|---|---|---|
| 첫 번째 | 0 | hel |
ell |
| 두 번째 | 2 | llo |
lo! |
이처럼 구간의 시작점을 옮겨 가며 예제를 만드는 방식을 Sliding Window라고 합니다. 여기서 Window Size=3은 한 예제의 입력 길이이고, Stride=2는 다음 예제의 시작점을 옮기는 간격입니다. 두 구간은 원문의 위치 2를 함께 포함하므로 서로 겹칩니다.
두 가지 이동을 구별하세요. Target은 다음 문자 예측 문제이므로 Input보다 항상 한 글자 뒤에서 시작합니다. Stride는 다음 학습 예제로 넘어갈 때 이동하는 간격입니다. Stride를 2로 정해도 두 글자 뒤를 예측하는 문제가 되지는 않습니다.
Stride를 1로 바꾸면?
같은 hello!와 길이 3을 사용해 시작 위치 0·1·2에서 hel→ell, ell→llo, llo→lo!의 세 쌍을 만듭니다. Stride가 작아지면 이 예에서는 겹치는 부분과 학습 예제 수가 늘어납니다.
위치 3에서 Input을 lo!로 자를 수는 있지만, 마지막 ! 다음에 정답으로 사용할 문자가 없습니다. 따라서 이 실습에서는 그 구간을 학습 예제로 만들지 않습니다. 길이 S의 Input과 Target 한 쌍에는 연속된 문자 S+1개가 필요합니다.
여러 예제를 묶으면 Batch가 된다
위 두 예제를 행으로 쌓으면 다음과 같습니다. 한 행을 왼쪽에서 오른쪽으로 읽는 순서와 서로 다른 예제를 위아래로 쌓는 방향을 구별해 보세요.
Input Target
예제 1 h e l e l l
예제 2 l l o l o !
──────→ 시간 순서
예제 수는 N=2, 각 예제의 길이는 S=3입니다. 문자마다 길이 E의 One-hot 벡터로 바꾸면 Input은 (2,3,E)가 됩니다. Target은 문자 번호 하나씩만 저장하므로 (2,3)입니다. 이번 실습에서는 만든 예제를 모두 한 Batch로 묶어 학습합니다.
실습에서는 길이 20, 이동 간격 5 사용하기
Notebook도 같은 규칙으로 더 긴 영어 글을 자릅니다. window_size=20은 입력 문자 20개, window_stride=5는 시작 위치 0·5·10·…을 뜻합니다. 각 Target은 해당 Input보다 한 글자 뒤에서 시작합니다. 실제 예제 수 N과 문자 종류 수 E는 출력으로 확인하세요.
| 값 | shape | 각 축의 뜻 |
|---|---|---|
One-hot Input X |
(N,20,E) |
예제 수 · 읽을 문자 수 · 문자 표현 크기 |
다음 문자 Target Y |
(N,20) |
예제 수 · 위치별 정답 문자 번호 |
| 각 모델의 최종 Logit | (N,20,C) |
예제 수 · 각 위치 · 문자별 점수 |
구간이 겹치면 모델의 기억도 이어지나요?
원문에서 구간이 겹치는 것과 모델의 State를 이어 주는 것은 별개입니다. 한 예제 안에서는 왼쪽 문자를 읽으며 만든 State가 다음 문자로 전달됩니다. 하지만 이 실습은 앞 예제의 마지막 State를 다음 예제에 넘기지 않고, 각 예제를 별도로 처리합니다.
겹친 예제들을 무작위로 나누어 평가하면 학습 때 본 문자 구간이 평가 데이터에도 들어갈 수 있습니다. 따라서 이를 독립적인 새 글에 대한 성능으로 해석하면 안 됩니다. 지금 비교하는 값은 학습에 사용한 예제에서의 Training Accuracy입니다.
3. LSTM과 GRU의 Gate 읽기
Gate는 각 성분에 0~1 사이의 값을 곱해 얼마나 반영할지 정합니다. 사람이 문장마다 if문으로 결정하는 것이 아니라, 학습되는 Parameter가 Gate 값을 계산합니다.
| 구조 | 유지하는 State | Gate의 역할 |
|---|---|---|
| RNN | Hidden State | 이전 State와 현재 Input으로 새 State 계산 |
| LSTM | Hidden State와 Cell State | Forget: 이전 Cell State를 남길 정도, Input: 새 정보를 넣을 정도, Output: Hidden State로 드러낼 정도 |
| GRU | Hidden State | Reset: 후보 State 계산에 과거 정보를 반영할 정도, Update: 이전 State와 후보를 섞는 정도 |
Gate 값 하나로 생각해보기
이전 Cell State의 한 성분이 2이고 Forget Gate가 0.9이면, 새 정보를 더하기 전에 1.8이 남습니다. Gate가 0.1이면 0.2가 남습니다. LSTM은 여기에 Input Gate로 조절한 새 정보를 더합니다. 이 설명은 숫자 흐름을 보기 위한 예이며, 실제 Gate는 벡터입니다.
LSTM의 Cell State와 Hidden State는 같은 값이 아닙니다. GRU는 별도 Cell State 없이 Hidden State 안에서 정보를 조절합니다. 세 모델의 성능 순위가 항상 같다고 가정하지 마세요.
4. 같은 조건으로 세 모델 비교하기
fit_char('RNN', ...), fit_char('LSTM', ...), fit_char('GRU', ...)는 같은 데이터를 받아 새 모델을 학습합니다. Hidden Size=32, 300 epoch, Learning Rate=0.01, Adam을 기준으로 비교합니다. 먼저 한 번씩 실행해 Loss·Training Accuracy·첫 Window의 예측 문자열을 나란히 기록하세요.
새 모델을 같은 Seed로 초기화하더라도 구조와 Parameter 수는 다릅니다. 따라서 이 실험은 학습 조건을 맞춘 구조 비교이며, 모든 상황에서 더 좋은 모델을 결정하는 실험은 아닙니다. 같은 원문을 잘 맞히는 것만으로 긴 문맥을 이해했다고 판단하지 마세요.
전체 학습을 다시 하지 않고 확인할 수 있는 것
학습된 모델을 results에 저장합니다. 각 모델의 output, 최종 State, 예측 문자열을 출력하는 데는 재학습이 필요 없습니다. 반복 기록표는 앞서 비교한 세 모델의 결과로 채우면 됩니다. 같은 Window 크기를 바꿔 비교하되 세 모델에 동일한 데이터를 사용하세요.
5. 반환값을 확인하는 순서
먼저 2번 실습 Section에서 모델을 만든 뒤 반환값을 확인합니다. 단방향 1개 Layer일 때 다음과 같습니다.
| 구조 | 모든 시점의 output |
마지막 State |
|---|---|---|
| RNN / GRU | (N,S,32) |
h_n: (1,N,32) |
| LSTM | (N,S,32) |
h_n, c_n: 각각 (1,N,32) |
batch_first=True는 Input과 output을 (N,S,...)로 배치합니다. 마지막 State의 첫 축은 Layer·방향 축이므로 (1,N,32)로 남습니다. 문자 점수는 이 output에 Linear를 적용한 뒤 얻습니다.
학습 내용 확인
- 다음 문자 Target을 만드는 규칙과 RNN·LSTM·GRU의 State 차이를 설명할 수 있나요?
- Window 길이와 Window 이동 간격을 구별할 수 있나요?
- 한 실험의 Accuracy로 모델의 우열을 일반화하지 않고 관찰한 결과를 설명할 수 있나요?
실습 자료
- AI_Applications_Week13_LstmGru.ipynbColab 노트북 미리보기 · Colab 노트북 다운로드
- L19_LSTM&GRU.ipynbColab 노트북 미리보기 · Colab 노트북 다운로드