먹고 싶습니다
요소 앞에는 먹을 것
이 오며 단어에 받침이 있을 경우에는 이
가 조사로 붙어야 함.Sequential Data를 다루는 가장 대표적인 모델
단어를 순서대로 하나의 Hidden Layer에 입력해 반복 업데이트
파라미터: , ,
Hidden Layer은 이전 Token들의 정보가 자동으로 축적
Loss는 Token별로 나오는 Loss를 더한 총합
Gradient Vanishing/Exploding 문제 발생(장기 기억력 떨어짐) Activation Function
rnn = nn.RNN(input_size, hidden_size)
outputs, _status = rnn(input_data)
# input_shape = (batch_size, sequence_length, input_size)
# output_shape = (batch_size, sequence_length, hidden_size)
## input_size: 단어 벡터의 차원
## sequence_length: 문장의 길이
## hidden_size: output(hidden state)의 차원
# 다음 character을 예측하는 모델 구축
# charseq 문제
sample = ' if you want you'
# make dictionary
char_set = list(set(sample))
char_dic = {c:i for i,c in enumerate(char_set)}
# hyperparameters
input_size = len(char_set)
dic_size = len(char_dic)
hidden_size = len(char_dic)
learning_rate = 0.1
# data setting
sample_idx = [char_dic[c] for c in sample] # index 가져옴
x_data = [sample_idx[:-1]] # 마지막 character 제외 후 가져옴
x_one_hot = [np.eye(dic_size)[x] for x in x_data] # np.eye는 Identity matrix임-여기서 원하는 vector 가져옴
y_data = [sample_idx[1:]]
# transform as torch tensor variable
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
# declare RNN
rnn = torch.nn.RNN(input_size, hidden_size, batch_first=True)
# loss&optimizer setting
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), learning_rate)
# start training
for i in range(100):
optimizer.zero_grad()
outputs, _status = rnn(X)
loss = criterion(outputs.view(-1, input_size), Y.view(-1))
loss.backward()
optimizer.step()
result = outputs.data.numpy().argmax(axis=2)
result_str = ''.join([char_set[c] for c in np.squeeze(result)])
print(F'{i}, loss: {loss.item()}, prediction: {result}, true Y: {y_data}, prediction str: {result_str}')
# 문장 자르기
sentence = "if you wnat to build a ship, don't drum up people together to collect wood and don't assign them tasks and work, but rather teach them to long for the endless immensity of the area"
char_set = list(set(sentence))
char_dic = {c:i for i,c in enumerate(char_set)}
sequence_length = 10
input_size = len(char_set)
dic_size = len(char_dic)
hidden_size = len(char_dic)
learning_rate = 0.1
x_data = []
y_data = []
for i in range(0, len(sentence)-sequence_length):
x_str = sentence[i:i+sequence_length]
y_str = sentence[i+1:i+sequence_length+1]
print(i, x_str, '->',y_str)
x_data.append([char_dic[c] for c in x_str]) # x str to index
y_data.append([char_dic[c] for c in y_str]) # y str to index
x_one_hot = [np.eye(dic_size)[x] for x in x_data] # one_hot vector로 만듦
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
# declare model
class Net(nn.Module): # nn.Module을 상속한 다음 Net이라는 Class로 정의
def __init__(self, input_dim, hidden_dim, layers): # 모듈의 내부적 하위 모듈 정의
super(Net, self).__init__()
self.rnn = nn.RNN(input_dim, hidden_dim, num_layers=layers, batch_first=True)
self.fc = torch.nn.Linear(hidden_dim, hidden_dim, bias=True)
def forward(self, x):
x, _stats = self.rnn(x)
x = self.fc(x)
return x
net = Net(dic_size, hidden_size, 2)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), learning_rate)
# train
for i in range(100):
optimizer.zero_grad()
outputs = net(X)
loss = criterion(outputs.view(-1, dic_size), Y.view(-1))
loss.backward()
optimizer.step()
results = outputs.argmax(dim=2)
predict_str = ''
for j, result in enumerate(results):
print(i, j, ''.join([char_set[t] for t in result]), loss.item())
if j==0:
predict_str += ''.join([char_set[t] for t in result])
else:
predict_str += char_set[result[-1]]
참고
파이썬 딥러닝 파이토치 (이경택, 방성수, 안상준)
모두를 위한 딥러닝 시즌 2 Lab 11-0, 11-1, 11-3, 11-4