This repository has been archived by the owner on Oct 19, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 245
/
sequence_to_sequence.py
97 lines (72 loc) · 3.1 KB
/
sequence_to_sequence.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python
# coding: utf-8
# # Seq2Seq 기계 번역
# 이번 프로젝트에선 임의로 Seq2Seq 모델을 아주 간단화 시켰습니다.
# 한 언어로 된 문장을 다른 언어로 된 문장으로 번역하는 덩치가 큰 모델이 아닌
# 영어 알파벳 문자열("hello")을 스페인어 알파벳 문자열("hola")로 번역하는 Mini Seq2Seq 모델을 같이 구현해 보겠습니다.
import torch
import torch.nn as nn
import torch.nn.functional as F
import random
import matplotlib.pyplot as plt
vocab_size = 256 # 총 아스키 코드 개수
x_ = list(map(ord, "hello")) # 아스키 코드 리스트로 변환
y_ = list(map(ord, "hola")) # 아스키 코드 리스트로 변환
print("hello -> ", x_)
print("hola -> ", y_)
x = torch.LongTensor(x_)
y = torch.LongTensor(y_)
class Seq2Seq(nn.Module):
def __init__(self, vocab_size, hidden_size):
super(Seq2Seq, self).__init__()
self.n_layers = 1
self.hidden_size = hidden_size
self.embedding = nn.Embedding(vocab_size, hidden_size)
self.encoder = nn.GRU(hidden_size, hidden_size)
self.decoder = nn.GRU(hidden_size, hidden_size)
self.project = nn.Linear(hidden_size, vocab_size)
def forward(self, inputs, targets):
# 인코더에 들어갈 입력
initial_state = self._init_state()
embedding = self.embedding(inputs).unsqueeze(1)
# embedding = [seq_len, batch_size, embedding_size]
# 인코더 (Encoder)
encoder_output, encoder_state = self.encoder(embedding, initial_state)
# encoder_output = [seq_len, batch_size, hidden_size]
# encoder_state = [n_layers, seq_len, hidden_size]
# 디코더에 들어갈 입력
decoder_state = encoder_state
decoder_input = torch.LongTensor([0])
# 디코더 (Decoder)
outputs = []
for i in range(targets.size()[0]):
decoder_input = self.embedding(decoder_input).unsqueeze(1)
decoder_output, decoder_state = self.decoder(decoder_input, decoder_state)
projection = self.project(decoder_output)
outputs.append(projection)
#티처 포싱(Teacher Forcing) 사용
decoder_input = torch.LongTensor([targets[i]])
outputs = torch.stack(outputs).squeeze()
return outputs
def _init_state(self, batch_size=1):
weight = next(self.parameters()).data
return weight.new(self.n_layers, batch_size, self.hidden_size).zero_()
seq2seq = Seq2Seq(vocab_size, 16)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(seq2seq.parameters(), lr=1e-3)
log = []
for i in range(1000):
prediction = seq2seq(x, y)
loss = criterion(prediction, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
loss_val = loss.data
log.append(loss_val)
if i % 100 == 0:
print("\n 반복:%d 오차: %s" % (i, loss_val.item()))
_, top1 = prediction.data.topk(1, 1)
print([chr(c) for c in top1.squeeze().numpy().tolist()])
plt.plot(log)
plt.ylabel('cross entropy loss')
plt.show()