*이 글을 읽기전에 작성자 개인의견이 있으니, 다른 블로그와 교차로 읽는것을 권장합니다.*
1. 순환 신경망(Recurrent Neural Network, RNN)
- 시계열 또는 자연어와 같은 Sequence 데이터를 모델링하는데 강력한 신경망, 시계열 데이터나 시퀀스 데이터를 잘 처리
- 예) 주식 가격, 텍스트 데이터, 오디오 데이터
- Sequence : 단어의 문장, 연결되어 있는 정보
- 예를들어 물건만드는 공장에서 3년동안 특정물건을 만든것에 대해, 1095개중 흐름예측(Regression)이 아닌, 구간을 정해서 패턴예측을 하면 가까운 시일내로 예측할 수 있음. 하나의 블록(구간, Sequence)을 정해서 Sequence간격마다 예측하면 더 세밀하게 예측하지 않을까? -> 나옴
1-1. RNN 동작방식
- 은닉층의 노드에서 활성화 함수를 통해 나온 결과값을 다시 출력층 방향으로 보내면서, 은닉층 노드의 다음 계산의 입력으로 보내는 것이 특징
- 셀(Cell) : 은닉층에서 활성화 함수를 통해 나온 결과를 내보내는 역할을 하는 것. 이전의 값을 기억하려고 하는 일종의 메모리 역할을 수행
- 은닉상태(hidden state) : 셀이 다음시점 또는 출력층 방향으로 자신에게 보내는 값
rnn = torch.nn.RNN(input_size, hidden_size) outputs, state = rnn(input_data) # state : hidden state
1-2. input size
- 단어가 입력되면 각 글자를 벡터의 형태로 변환하여 원 핫 인코딩해주는 과정이 필요
- 'hello'
- h = [1, 0, 0, 0]
- e = [0, 1, 0, 0]
- l = [0, 0, 1, 0]
- o = [0, 0, 0, 1]
- input_size = 4
- input_data의 3번째 차원으로 입력
1-3. hidden state size
- hidden state의 size는 output의 3번째 차원
- output size와 같음
- 셀에서 연산된 결과를 2가지로 나눠 하나는 output으로 출력되고, 다른 하나는 hidden state로 다음 step에 그대로 저장하고 전해짐
1-4. Sequence Length
- 입력하려는 단어의 갯수
- 총 Sequence가 몇 개 인지를 나타냄
- 'hello'를 입력으로 보내면 sequence length는 5
- 파이토치에서는 모델이 Sequence Length를 알아서 파악하기 때문에 파라미터로 전달해 줄 필요는 없음
1-5. Batch Size
- batch size : 한번의 학습반복(iteration)동안 모델의 입력으로 주어지는 샘플의 수
- 여러 데이터를 묶어 하나의 batch로 만들어 학습을 진행
- h, e, l, o를 가지고 만들 수 있는 데이터 중 배치사이즈로 정한 크기로 묶어 학습을 진행
- batch size를 모델에서 파악하고 output data, input data에서 첫번째 차원에 위치함
2. RNN 모델 학습 과정
2-1. 데이터 준비: 데이터 전처리, 시퀀스 분할, 패딩
2-2. 데이터셋 및 데이터 로더 생성: 텐서로 변환, DataLoader 설정
2-3. 모델 정의: RNN 아키텍처 설정 (예: nn.RNN, nn.LSTM, nn.GRU)
2-4. 손실 함수 및 옵티마이저 정의: 손실 함수 설정, 옵티마이저 설정
2-5. 모델 학습: 학습 루프, 손실 계산, 역전파 및 가중치 업데이트
2-6. 모델 평가 및 예측: 검증 데이터 평가, 예측 수행
import torch
import numpy as np
from torch.nn import RNN # 순환신경망 RNN 모듈
input_size = 4
hidden_size = 2
h= [1, 0, 0, 0]
e= [0, 1, 0, 0]
l= [0, 0, 1, 0]
o= [0, 0, 0, 1]
input_data_np = np.array([[h, e, l, l, o],
[e, o, l, l, l],
[l, l, e, e, l]], dtype=np.float32)
input_data = torch.Tensor(input_data_np)
rnn = RNN(input_size, hidden_size)
outputs, state = rnn(input_data)
state
test = 'hello! word'
string_set = list(set(test))
print(string_set)
string_dic = {c: i for i, c in enumerate(string_set)}
print(string_dic)
input_size = len(string_dic)
print(input_size)
hidden_size = len(string_dic)
print(hidden_size)
test_idx = [string_dic[c] for c in test]
print(test_idx)
x_data = [test_idx[:]]
print(x_data)
# np.eye() : 단위 행렬(Identity matrix)을 생성 -> 9x9
# x_data의 각 요소(x)에 대해 해당하는 단위 행렬의 행을 선택
x_one_hot = [np.eye(input_size)[x] for x in x_data]
print(x_one_hot)
# x가 i
y_data = [test_idx[:]]
print(y_data)
X = torch.FloatTensor(x_one_hot)
y = torch.LongTensor(y_data)
rnn = RNN(input_size, hidden_size)
loss_fun = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(rnn.parameters(), lr=0.1)
# outputs, state = rnn(X)
# loss: x, predition: x(idx), predition_str: x(str)
for i in range(100):
optimizer.zero_grad()
outputs, state = rnn(X)
# (배치사이즈, 시퀀스길이, 히든사이즈)
# outputs: (1, 12, 12) -> (12, 12)
# y: (1, 12) -> (12)
# loss_fun() : outputs.view - y.view의 손실값 계산하는 손실함수
loss = loss_fun(outputs.view(-1, input_size), y.view(-1)) # view(-1)이 -1차원이구나
loss.backward() # 역전파 : 손실 역전파 -> 매개변수 기울기 계산
optimizer.step() # 경사하강법 : 매개변수 업데이트
# outputs.data의 예측값 numpy배열로 변환
# argmax() : 가장 높은 확률을 인덱스로 선택
result = outputs.data.numpy().argmax(axis=2) # array([[2, 8, 0, 0, 7, 1, 4, 3, 7, 6, 5]])
result_str = ''.join([string_set[ch] for ch in np.squeeze(result)]) # 'hello! word'
print(i, 'loss: ', loss)
print('prediction: ', result, ' prediction_str: ', result_str)
참고 : arg - argument : f(x)에서 x부분-> 매개변수 부분을 말함.
'Python > 자연어처리' 카테고리의 다른 글
Python(44)- CNN 분류 (0) | 2024.07.02 |
---|---|
Python(43)- cbow 분류 (0) | 2024.07.02 |
Python(41)- 워드 임베딩 시각화 (0) | 2024.06.27 |
Python(40)- 워드 임베딩 (0) | 2024.06.25 |
Python(39)- 임베딩 (0) | 2024.06.25 |