본문 바로가기
인공지능 개발하기/Machine Learning

[Tensorflow] 30. keras RNN 모델 살펴보기

by 선의공 2024. 2. 3.

 

이번 포스팅에서는

저번 포스팅에서 설명한 RNN 모델을

keras layers 모듈에서는

어떻게 제공하는지 살펴보겠습니다.

https://aigaeddo.tistory.com/35

 

29. RNN(Recurrent neural network)

이번 포스팅에서는 CNN에 이어 RNN(Recurrent neural network)에 대해서 더욱 이해하기 위해서 학습해보겠습니다. 해당 포스팅들을 참고가며 학습해보겠습니다. https://boardmix.com/kr/skills/what-is-time-series-data

aigaeddo.tistory.com

 

 


 

1. keras. layers

 

 

https://keras.io/api/layers/recurrent_layers/

 

Keras documentation: Recurrent layers

 

keras.io

 

keras 공식문서에는 9개의 Recurrent layer를

지원하고 있는 것을 확인 할 수 있습니다.

 

 

레이어들이

어떤건지 공식문서를 살펴보며

확인해보겠습니다.

 

 


 

 

2-1. BaseRNN

https://keras.io/api/layers/recurrent_layers/rnn/

 

Keras documentation: Base RNN layer

Base RNN layer [source] RNN class keras.layers.RNN( cell, return_sequences=False, return_state=False, go_backwards=False, stateful=False, unroll=False, zero_output_for_mask=False, **kwargs ) Base class for recurrent layers. Arguments cell: A RNN cell insta

keras.io

 

서브클래싱을 해서 RNN의 구조를 Customizing 할때 사용하는 기본 레이어 같습니다.

예제에서 보면 RNN을 받아서 RNN의 구조를 재구성하는 것을 볼 수 있습니다.

 

from keras.layers import RNN
from keras import ops

# First, let's define a RNN Cell, as a layer subclass.
class MinimalRNNCell(keras.layers.Layer):

    def __init__(self, units, **kwargs):
        super().__init__(**kwargs)
        self.units = units
        self.state_size = units

    def build(self, input_shape):
        self.kernel = self.add_weight(shape=(input_shape[-1], self.units),
                                      initializer='uniform',
                                      name='kernel')
        self.recurrent_kernel = self.add_weight(
            shape=(self.units, self.units),
            initializer='uniform',
            name='recurrent_kernel')
        self.built = True

    def call(self, inputs, states):
        prev_output = states[0]
        h = ops.matmul(inputs, self.kernel)
        output = h + ops.matmul(prev_output, self.recurrent_kernel)
        return output, [output]

# Let's use this cell in a RNN layer:

cell = MinimalRNNCell(32)
x = keras.Input((None, 5))
layer = RNN(cell)
y = layer(x)

# Here's how to use the cell to build a stacked RNN:

cells = [MinimalRNNCell(32), MinimalRNNCell(64)]
x = keras.Input((None, 5))
layer = RNN(cells)
y = layer(x)

 


 

2-2. SimpleRNNLayer

 

https://keras.io/api/layers/recurrent_layers/simple_rnn/

 

Keras documentation: SimpleRNN layer

SimpleRNN layer [source] SimpleRNN class keras.layers.SimpleRNN( units, activation="tanh", use_bias=True, kernel_initializer="glorot_uniform", recurrent_initializer="orthogonal", bias_initializer="zeros", kernel_regularizer=None, recurrent_regularizer=None

keras.io

 

이전의 timestep의 출력이 다음 timestep으로 완전 연결된 모델이라고 합니다.
기본적인 RNN 구조의 레이어입니다.

 

inputs = np.random.random((32, 10, 8))
simple_rnn = keras.layers.SimpleRNN(4)
output = simple_rnn(inputs)  # The output has shape `(32, 4)`.
simple_rnn = keras.layers.SimpleRNN(
    4, return_sequences=True, return_state=True
)
# whole_sequence_output has shape `(32, 10, 4)`.
# final_state has shape `(32, 4)`.
whole_sequence_output, final_state = simple_rnn(inputs)

 

 

 


 

2-3. LSTM Layer

https://keras.io/api/layers/recurrent_layers/lstm/

 

Keras documentation: LSTM layer

LSTM layer [source] LSTM class keras.layers.LSTM( units, activation="tanh", recurrent_activation="sigmoid", use_bias=True, kernel_initializer="glorot_uniform", recurrent_initializer="orthogonal", bias_initializer="zeros", unit_forget_bias=True, kernel_regu

keras.io

이전 포스팅에서 설명한 장기 문맥 의존성을 해결하기 위해

고안된 구조 모델입니다.

 

이전 포스팅에서 RNN의 단점인

병렬 처리가 불가능해 GPU에서 큰 성능을 발휘하지 못하는 문제를

해결하는 방식도 제공하나보네요!

 

 cuDNN 커널의 요구사항을 충족하도록아래와 같은 세팅을 하면

텐서플로우 벡엔드(keras 환경)에서 cuDNN 구현이 가능하다고 합니다.

(1,2,3,4,5 는 default 값이라 따로 변경하지 않으면 설정되어 있네요)

 

1. activation == tanh

2. recurrent_activation==sigmoid

3. dropout ==0 or recurrent_dropout ==0

4. unroll is False

5.use_bias is True

6. 입력 데이터가 masking 한다면 오른쪽 padding을 함

7.  Eager execution(?)은 구문 밖에서 실행.

 

 

 

>>> inputs = np.random.random((32, 10, 8))
>>> lstm = keras.layers.LSTM(4)
>>> output = lstm(inputs)
>>> output.shape
(32, 4)
>>> lstm = keras.layers.LSTM(
...     4, return_sequences=True, return_state=True)
>>> whole_seq_output, final_memory_state, final_carry_state = lstm(inputs)
>>> whole_seq_output.shape
(32, 10, 4)
>>> final_memory_state.shape
(32, 4)
>>> final_carry_state.shape
(32, 4)

 


2-4. GRU Layer

https://keras.io/api/layers/recurrent_layers/gru/

 

Keras documentation: GRU layer

GRU layer [source] GRU class keras.layers.GRU( units, activation="tanh", recurrent_activation="sigmoid", use_bias=True, kernel_initializer="glorot_uniform", recurrent_initializer="orthogonal", bias_initializer="zeros", kernel_regularizer=None, recurrent_re

keras.io

 

LSTM의 단점인 느린 속도를 개선한 구조라고 합니다. 

 

LSTM과 동일하게 아래 요구사항을 충족하면

텐서플로우 벡엔드(keras 환경)에서

빠른  cuDNN 구현이 가능하다고 합니다.

(마찬가지로 1,2,3,4,5 는 default 값입니다.)

 

1. activation == tanh

2. recurrent_activation==sigmoid

3. dropout ==0 or recurrent_dropout ==0

4. unroll is False

5.use_bias is True

6. 입력 데이터가 masking 한다면 오른쪽 padding을 함

7.  Eager execution(?)은 구문 밖에서 실행.

 

 

>>> inputs = np.random.random((32, 10, 8))
>>> gru = keras.layers.GRU(4)
>>> output = gru(inputs)
>>> output.shape
(32, 4)
>>> gru = keras.layers.GRU(4, return_sequences=True, return_state=True)
>>> whole_sequence_output, final_state = gru(inputs)
>>> whole_sequence_output.shape
(32, 10, 4)
>>> final_state.shape
(32, 4)

 


2-5. Bidirectional Layer

https://keras.io/api/layers/recurrent_layers/bidirectional/

 

Keras documentation: Bidirectional layer

Bidirectional layer [source] Bidirectional class keras.layers.Bidirectional( layer, merge_mode="concat", weights=None, backward_layer=None, **kwargs ) Bidirectional wrapper for RNNs. Arguments layer: keras.layers.RNN instance, such as keras.layers.LSTM or

keras.io

 

양방향 Wrapper, 단독으로 사용하는 게 아닌 

RNN레이어를 래핑해서 사용한다고 합니다.

RNN을 순방향, 역방향 두번 연산하는 레이어 같습니다.

순방향 혹은 역방향의 출력을 결합하는 방식 설정도 있고,

역방향 레이어도 따로 설정이 가능하네요.

 

model = Sequential([
    Input(shape=(5, 10)),
    Bidirectional(LSTM(10, return_sequences=True),
    Bidirectional(LSTM(10)),
    Dense(5, activation="softmax"),
])
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

# With custom backward layer
forward_layer = LSTM(10, return_sequences=True)
backward_layer = LSTM(10, activation='relu', return_sequences=True,
                      go_backwards=True)
model = Sequential([
    Input(shape=(5, 10)),
    Bidirectional(forward_layer, backward_layer=backward_layer),
    Dense(5, activation="softmax"),
])
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')

 

 


2-6 TimeDistributed Layer

https://keras.io/api/layers/recurrent_layers/time_distributed/

 

Keras documentation: TimeDistributed layer

TimeDistributed layer [source] TimeDistributed class keras.layers.TimeDistributed(layer, **kwargs) This wrapper allows to apply a layer to every temporal slice of an input. Every input should be at least 3D, and the dimension of index one of the first inpu

keras.io

이것도 Wrapper 레이어네요.

모든 입력  temporal slice?에 레이어가 적용된다고 합니다.

비디오 같은 다수의 프레임이 있는 이미지 훈련에 필요한 레이어 같습니다.

예제에서는 CNN과 같이 쓰이네요.

 

이전 포스팅에서

many to many2로 설명한 이 형태를 구현할 수 있게

시간 레이어인 걸까요? 아직은 잘 모르겠군요.

 

>>> inputs = layers.Input(shape=(10, 128, 128, 3), batch_size=32)
>>> conv_2d_layer = layers.Conv2D(64, (3, 3))
>>> outputs = layers.TimeDistributed(conv_2d_layer)(inputs)
>>> outputs.shape
(32, 10, 126, 126, 64)

 


2-7 ConvLSTM1D Layer

https://keras.io/api/layers/recurrent_layers/conv_lstm1d/

 

Keras documentation: ConvLSTM1D layer

ConvLSTM1D layer [source] ConvLSTM1D class keras.layers.ConvLSTM1D( filters, kernel_size, strides=1, padding="valid", data_format=None, dilation_rate=1, activation="tanh", recurrent_activation="sigmoid", use_bias=True, kernel_initializer="glorot_uniform",

keras.io

 

1차원 Convolution 방식이 적용된 LSTM이라고 합니다.

입력형태는 4차원 텐서,

출력형태는 return_state 파라미터 설정에 따라

3차원 텐서 혹은 4차원 텐서입니다.

 

Convolution 방식은 (n,) 형태의 kernel로 진행됩니다. 

 


 

2-8 ConvLSTM2D Layer

https://keras.io/api/layers/recurrent_layers/conv_lstm2d/

 

Keras documentation: ConvLSTM2D layer

ConvLSTM2D layer [source] ConvLSTM2D class keras.layers.ConvLSTM2D( filters, kernel_size, strides=1, padding="valid", data_format=None, dilation_rate=1, activation="tanh", recurrent_activation="sigmoid", use_bias=True, kernel_initializer="glorot_uniform",

keras.io

 

2차원 Convolution 방식이 적용된 LSTM 입니다.

입력형태는 5차원 텐서, 출력형태는

출력형태는 return_state 파라미터 설정에 따라

4차원 텐서 혹은 5차원 텐서입니다.

 

kernel 설정이나 padding 방식은 Conv2D와 동일하네요.

 


 

2-9 ConvLSTM3D Layer

https://keras.io/api/layers/recurrent_layers/conv_lstm3d/

 

Keras documentation: ConvLSTM3D layer

ConvLSTM3D layer [source] ConvLSTM3D class keras.layers.ConvLSTM3D( filters, kernel_size, strides=1, padding="valid", data_format=None, dilation_rate=1, activation="tanh", recurrent_activation="sigmoid", use_bias=True, kernel_initializer="glorot_uniform",

keras.io

 

마찬가지로 3차원 Convolution 방식이 적용된 LSTM 입니다.

입력형태는 6차원 텐서, 출력형태는

출력형태는 return_state 파라미터 설정에 따라

4차원 텐서 혹은 5차원 텐서입니다.

 

 


 

 

이번 포스팅에서는

제가 개인적으로 궁금해서

keras RNN 레이어들을 

찍먹해봤습니다.

 

자주 사용하는 LSTM, GRU 외에도

baseRNN을 이용해 커스텀 RNN을 만들거나

LSTM에 convolution 방식을 섞은 ConvLSTM도

 한 번 써봐야겠네요!

 

 

 

 

틀린 내용이 있다면 지적 부탁드립니다!