STEP 10 / 18

한 단어씩 생성하기: greedy decoding

모델이 완성됐으니 문장을 만들어 보자. 디코더는 한 번에 한 토큰만 정한다.

  1. 원문을 한 번만 encode해서 memory를 만든다.
  2. 시작 토큰 하나(start_symbol)로 ys를 시작한다.
  3. ys를 decode하고 마지막 위치의 확률 분포(out[:, -1])에서 가장 높은 토큰을 고른다.
  4. 그 토큰을 ys 뒤에 붙이고 3번으로 돌아간다.

매번 가장 확률이 높은 것 하나만 고르므로 "greedy(탐욕적)"라고 부른다. 논문은 beam search를 썼지만 원본 노트북은 단순하게 greedy만 구현했다.

원본 노트북에서는 inference_test 안에 같은 반복문이 들어 있고 greedy_decode는 2부에 따로 나온다. 여기서는 같은 코드를 greedy_decode 함수 하나로 합쳐 먼저 소개했다.

실행 결과에서 볼 것

원본의 inference_test를 10번 실행한다. 학습하지 않은 모델이라 입력 1..10과 상관없이 같은 토큰을 반복하거나 둘을 번갈아 낸다. 이제 이 모델을 학습시킬 차례다.

코드 변화

+16 −0 · 파일 전체 291줄

이전 단계의 transformer.py와 비교했다. 초록 줄이 새로 생긴 줄, 빨간 줄이 사라진 줄이다.

GitHub에서 보기 ↗
273273 if p.dim() > 1:
274274 nn.init.xavier_uniform_(p)
275275 return model
276+
277+
278+def greedy_decode(model, src, src_mask, max_len, start_symbol):
279+ memory = model.encode(src, src_mask)
280+ ys = torch.zeros(1, 1).fill_(start_symbol).type_as(src.data)
281+ for i in range(max_len - 1):
282+ out = model.decode(
283+ memory, src_mask, ys, subsequent_mask(ys.size(1)).type_as(src.data)
284+ )
285+ prob = model.generator(out[:, -1])
286+ _, next_word = torch.max(prob, dim=1)
287+ next_word = next_word.data[0]
288+ ys = torch.cat(
289+ [ys, torch.zeros(1, 1).type_as(src.data).fill_(next_word)], dim=1
290+ )
291+ return ys

실행 결과

실행한 코드 demo.py 보기
1import torch
2
3from transformer import greedy_decode, make_model
4
5torch.manual_seed(0)
6
7
8# 원본 노트북의 inference_test: 학습하지 않은 모델로 한 토큰씩 생성
9def inference_test():
10 test_model = make_model(11, 11, 2)
11 test_model.eval()
12 src = torch.LongTensor([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])
13 src_mask = torch.ones(1, 1, 10)
14 ys = greedy_decode(test_model, src, src_mask, max_len=10, start_symbol=0)
15 print("Example Untrained Model Prediction:", ys)
16
17
18for _ in range(10):
19 inference_test()
20print()
21print("→ 아직 학습하지 않아서 입력과 상관없는 토큰을 반복한다. 14단계에서 이 모델에 복사를 가르친다")
Example Untrained Model Prediction: tensor([[0, 6, 4, 3, 3, 3, 3, 3, 3, 3]])
Example Untrained Model Prediction: tensor([[0, 9, 2, 9, 2, 9, 2, 9, 2, 9]])
Example Untrained Model Prediction: tensor([[0, 8, 6, 9, 8, 6, 6, 6, 6, 6]])
Example Untrained Model Prediction: tensor([[ 0,  7,  3,  8,  7,  3, 10,  8,  7,  3]])
Example Untrained Model Prediction: tensor([[ 0, 10,  0, 10,  0, 10, 10,  0, 10,  0]])
Example Untrained Model Prediction: tensor([[0, 2, 2, 2, 8, 1, 9, 0, 7, 4]])
Example Untrained Model Prediction: tensor([[0, 1, 7, 1, 7, 1, 7, 1, 7, 6]])
Example Untrained Model Prediction: tensor([[0, 7, 2, 8, 9, 3, 3, 3, 3, 3]])
Example Untrained Model Prediction: tensor([[0, 5, 9, 1, 6, 3, 9, 1, 5, 5]])
Example Untrained Model Prediction: tensor([[0, 4, 0, 0, 4, 0, 4, 0, 0, 0]])

→ 아직 학습하지 않아서 입력과 상관없는 토큰을 반복한다. 14단계에서 이 모델에 복사를 가르친다