일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 딥러닝
- Semantic Segmentation
- Neural Radiance Field
- 2022
- CVPR2023
- 논문
- Paper
- 융합연구
- 논문 리뷰
- 파이토치
- Vae
- paper review
- NERF
- 경희대
- Computer Vision
- linux
- Deep Learning
- IROS
- pytorch
- panoptic segmentation
- 논문리뷰
- panoptic nerf
- 리눅스
- GAN
- CVPR
- ICCV
- docker
- Python
- NeRF paper
- ICCV 2021
- Today
- Total
윤제로의 제로베이스
문자 단위 RNN(Char RNN) 본문
01. 문자 단위 RNN(Char RNN)
이번 챕터에서는 모든 시점의 입력에 대해서 모든 시점에 대해서 출력을 하는 다대다 RNN을 구현해봅시다. 다대다 RNN은 대표적으로 품사 태깅, 개체명 인식 등에서 사용됩니 ...
wikidocs.net
1. 문자 단위 RNN(Char RNN)
RNN의 입출력의 단위가 단어 레벨(word-level)이 아니라 문자 레벨(character-level)로 하여 RNN을 구현한다면, 이를 문자단위 RNN이라고 한다.
RNN의 구조가 달라진 것이 아니라 입,출력의 단위가 문자로 바뀐 것이다.
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
(1) 훈련 데이터 전처리하기
입력 데이터와 레이블 데이터에 대해서 문자 집합(vocabulary)을 만든다.
input_str = 'apple'
label_str = 'pple!'
char_vocab = sorted(list(set(input_str+label_str)))
vocab_size = len(char_vocab)
현재 문자 집합에는 총 5개의 문자가 있다.
!, a, e, l, p이다.
이제 하이퍼파라미터를 정의한다.
이때 입력은 원-핫 벡터를 사용할 것이므로 입력의 크기는 문자 집합의 크기여야만한다.
input_size = vocab_size # 입력의 크기는 문자 집합의 크기
hidden_size = 5
output_size = 5
learning_rate = 0.1
이제 문자 집합에 고유한 정수를 부여한다.
char_to_index = dict((c, i) for i, c in enumerate(char_vocab)) # 문자에 고유한 정수 인덱스 부여
!은 0, a는 1, e는 2, l은 3, p는 4가 부여된다.
나중에 예측 결과를 다시 문자 시퀀스로 보기 위해서 반대로 정수로부터 문자를 얻을 수 있는 index_to_char을 만든다.
index_to_char={}
for key, value in char_to_index.items():
index_to_char[value] = key
print(index_to_char)
입력 데이터와 레이블 데이터의 각각의 문자들을 정수로 맵핑한다.
x_data = [char_to_index[c] for c in input_str]
y_data = [char_to_index[c] for c in label_str]
파이토치의 nn.RNN()은 기본적으로 3차원 텐서를 입력받는다.
그렇기 때문에 배치 차원을 추가해준다.
# 배치 차원 추가
# 텐서 연산인 unsqueeze(0)를 통해 해결할 수도 있었음.
x_data = [x_data]
y_data = [y_data]
입력 시퀀스의 각 문자들을 원-핫 벡터로 바꿔준다.
x_one_hot = [np.eye(vocab_size)[x] for x in x_data]
입력 데이터와 레이블 데이터를 텐서로 바꿔준다.
X = torch.FloatTensor(x_one_hot)
Y = torch.LongTensor(y_data)
2. 모델 구현하기
class Net(torch.nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(Net, self).__init__()
self.rnn = torch.nn.RNN(input_size, hidden_size, batch_first=True) # RNN 셀 구현
self.fc = torch.nn.Linear(hidden_size, output_size, bias=True) # 출력층 구현
def forward(self, x): # 구현한 RNN 셀과 출력층을 연결
x, _status = self.rnn(x)
x = self.fc(x)
return x
net = Net(input_size, hidden_size, output_size)
outputs = net(X)
(1,5,5)의 크기를 가지는데 각각 배치차원, 시점, 출력의 크기이다.
나중에 정확도를 측정할 때는 이를 모두 펼쳐서 계산하게 되는데, 이때 view를 사용하여 배치 차원과 시점 차원을 하나로 만든다.
레이블 데이터는 (1,5)의 크기를 가지는데, 마찬가지로 나중에 정확도를 측정할 때는 이걸 펼쳐서 계산할 예정이다.
이 경우 (5)의 크기를 가지게 된다.
이제 옵티마이저와 손실 함수를 정의한다.
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), learning_rate)
for i in range(100):
optimizer.zero_grad()
outputs = net(X)
loss = criterion(outputs.view(-1, input_size), Y.view(-1)) # view를 하는 이유는 Batch 차원 제거를 위해
loss.backward() # 기울기 계산
optimizer.step() # 아까 optimizer 선언 시 넣어둔 파라미터 업데이트
# 아래 세 줄은 모델이 실제 어떻게 예측했는지를 확인하기 위한 코드.
result = outputs.data.numpy().argmax(axis=2) # 최종 예측값인 각 time-step 별 5차원 벡터에 대해서 가장 높은 값의 인덱스를 선택
result_str = ''.join([index_to_char[c] for c in np.squeeze(result)])
print(i, "loss: ", loss.item(), "prediction: ", result, "true Y: ", y_data, "prediction str: ", result_str)
'Background > Pytorch 기초' 카테고리의 다른 글
파이토치를 이용한 텍스트 분류(Text classification using Pytorch) (0) | 2022.01.26 |
---|---|
단어 단위 RNN - 임베딩 사용 (0) | 2022.01.26 |
장단기 메모리(Long Short-Term Memory, LSTM) (0) | 2022.01.26 |
순환 신경망(Recurrent Neural Network, RNN) (0) | 2022.01.26 |
파이토치의 nn.Embedding() (0) | 2022.01.26 |