Python/Pytorch

[Pytorch] 파이토치 RNN 계열 layer 원리 이해해보기

jimmy_AI 2022. 11. 20. 21:43
반응형

Python torch RNN, LSTM, GRU 사용법

파이썬 파이토치에서 RNN 계열 layer들의 input, output 형태를 기준으로

layer 개수 및 양방향 여부에 따른 원리를 이해하기 쉽게 설명해보도록 하겠습니다.

 

 

1. 기본 RNN, 단층, 단방향

먼저, 가장 기본적인 경우로 일반 RNN이며 single layer, unidirectional인 경우의

예제를 살펴보도록 하겠습니다.

 

상황은 다음과 같이 가정하겠습니다.

sequence length = 2,(아래 그림에서 빨간색, 분홍색 순서입니다.)

batch size = 4,

input dimension = 5,(각 데이터는 5차원이며, 각 숫자는 x로 표시했습니다.)

output dimension = 3

 

이 경우에 input의 최종 shape은 (2, 4, 5)가 되며,

RNN 메소드에 input_size = 5, hidden_size = 3으로 설정하면 input/output의 shape를

위와 같이 정할 수 있습니다.

 

코드로 구현된 결과는 아래와 같습니다.

import torch
import torch.nn as nn

x = torch.randn(2, 4, 5) # sequence length = 2, batch size = 4, dimension = 5

Net = nn.RNN(input_size = 5, hidden_size = 3)

 

이제 x 벡터를 Net에 input으로 준 결과를 살펴보겠습니다.

output, hn = Net(x)
print(output.shape) # torch.Size([2, 4, 3])
print(hn.shape) # torch.Size([1, 4, 3])

각 sequence에 대하여 반환된 결과(파란색, 초록색)인 output 부분과

last sequence data에 대한 최종 hidden output인 hn(초록색)으로 나누어

결과가 반환된 것을 살펴볼 수 있습니다.

 

이해를 돕기 위하여 이를 그림으로 표현하면 다음과 같이 나타낼 수 있습니다.

 

 

2. 기본 RNN, 여러 층, 단방향

이번에는 RNN의 layer가 여러 층인 stacked RNN의 경우를 살펴보겠습니다.

전반적인 상황은 위의 1번 예제와 동일하나, layer의 개수를 3개로 가정하면

RNN 메소드 내에 num_layers = 3의 인자를 추가로 지정하여 구현할 수 있습니다.

x = torch.randn(2, 4, 5) # sequence length = 2, batch size = 4, dimension = 5

Net = nn.RNN(input_size = 5, hidden_size = 3, num_layers = 3)

 

이 경우, x를 Net에 input으로 주면 outputhn의 차원은 아래와 같이 변경됩니다.

output, hn = Net(x)
print(output.shape) # torch.Size([2, 4, 3])
print(hn.shape) # torch.Size([3, 4, 3])

 

여기서는 각 layer를 기준으로 결과 임베딩이 독립적으로 존재하는데,

hn에서는 last sequence data에 대하여 모든 layer의 임베딩을 저장하는 반면,

output에서는 각 sequence data에 대하여 최종 layer의 결과만을 1번 결과와

동일하게 반환하는 것을 살펴볼 수 있습니다.

 

반응형

 

3. 기본 RNN, 여러 층, 양방향

이번에는 더 복잡한 케이스로 여러 층이며, bidirectional인 경우에 대하여

예시를 다루어 보겠습니다.

 

2번 예제와 다른 조건은 동일하며, 방향만 양방향으로 바꾼 경우를 가정하겠습니다.

RNN 메소드에서 bidirectional = True 조건을 지정해주면 양방향 전환이 가능합니다.

 

해당 케이스에 대한 구현 코드 및 반환 값들의 shape는 다음과 같이 변경됩니다.

x = torch.randn(2, 4, 5) # sequence length = 2, batch size = 4, dimension = 5

Net = nn.RNN(input_size = 5, hidden_size = 3, num_layers = 3, bidirectional = True)

output, hn = Net(x)
print(output.shape) # torch.Size([2, 4, 6])
print(hn.shape) # torch.Size([6, 4, 3])

output정방향역방향에 대한 최종 layer 결과가 concatenation된 형태

등장하는 반면(파란색 + 하늘색, 초록색 + 연두색),

hn정방향역방향 기준 가장 끝 부분의 각 layer에서의 결과가 따로 합쳐져

등장하게 됩니다.(정방향초록색, 역방향하늘색)

 

 

4. LSTM, GRU의 경우 및 기타 옵션

LSTM 및 GRU의 경우에도 기본적인 메소드 원리는 일반 RNN과 거의 유사하게

구현되어 있습니다.

 

다만, LSTM의 경우에는 각 cell state에 해당하는 cnoutput, hn과 함께

반환되는 점을 참고해주시면 됩니다.


이 외에도 (seq, batch, feature) 차원이 아니라 (batch, seq, feature) 차원으로

input을 넣어주는 batch_first 옵션을 지정할 수도 있으며,

첫 hidden state인 h0를 특정 값으로 설정하여 RNN에 input으로 같이 반영도 가능합니다.

(위 예제에서는 h0를 설정하지 않았기에 h0가 영벡터로 취급하여 반영된 결과였습니다.)

 

기타 추가적인 RNN 관련 메소드의 사용법은 파이토치 공식 document를 참고하세요.

(dropout 비중, 활성함수 종류, bias 사용 여부 등도 지정이 가능합니다.)