순환 신경망(Recurrent Neural Network)
이론
- RNN(Recurrent Neural Network)은 은닉층의 노드에서 활성화 함수를 통해 나온 결과값을 출력층으로 보내면서 다시 은닉층 노드의 다음 계산의 입력으로 보내는 특징을 가지고 있다.

- x는 입력층의 입력 벡터이고 y는 출력층의 출력 벡터이다.
- RNN 은닉층에서 활성화 함수를 통해 결과를 내보내는 역할을 하는 노드를 셀(cell)이라고 한다.
- 이전 값을 기억하려고 하는 일종의 메모리 역할을 하기 때문에 RNN cell 또는 메모리 셀이라고도 한다.
- 은닉층의 메모리 셀은 각각의 시점(time step)에서 바로 이전 시점에서의 은닉층의 메모리 셀에서 나온 값을 자신의 입력으로 사용한다.
- 현재 시점을 변수 t라고 할때, 현재 시점 t에서의 메모리 셀이 갖고있는 값은 과거의 메모리 셀들의 값에 영향을 받았다고 할 수 있다.

- 메모리 셀이 출력층 방향 또는 다음 시점인 t+1의 자신에게 보내는 값을 은닉 상태(hidden state) 한다.
- t 시점의 메모리 셀은 t-1 시점의 메모리 셀이 보낸 은닉 상태값을 t 시점의 은닉 상태 계산을 위한 입력값으로 사용하게 된다.

- MLP는 대표적인 순방향 신경망(Feedfoward neural network)로써 입력에서 출력층 방향으로 연산이 되는 구조이다.
- RNN은 순환 신경망으로써 현재의 상태(state)가 이전 상태(state)를 사용하는 순환되는 연산있는 구조이다.
코드
- Keras에는 세 개의 내장 RNN 레이어와 RNN 셀이 있다.
셀은 RNN 레이어의 for 루프 내부이다. keras.layers.RNN 레이어 내에 셀을 래핑하면 RNN(LSTMCell(10))과 같은 시퀀스 배치를 처리할 수 있는 레이어를 얻을 수 있다.
예를 들면 RNN(LSTMCell(10))은 LSTM(10)과 동일한 결과를 낼 수 있다.
- keras.layers.SimpleRNN
- keras.layers.GRU
- keras.layers.LSTM
- keras.layers.SimpleRNNCell
- keras.layers.GRUCell
- keras.layers.LSTMCell
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
mnist = keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
sample, sample_label = x_train[0], y_train[0]
input_dim = 28
units = 64
output_size = 10
model = keras.layers.RNN(keras.layers.SimpleRNNCell(units), input_shape=(None, input_dim))
model = keras.models.Sequential([model, keras.layers.BatchNormalization(), keras.layers.Dense(output_size),])
model.set_weights(model.get_weights())
model.compile( loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer="sgd",
metrics=["accuracy"],
)
model.fit(
x_train, y_train, validation_data=(x_test, y_test), batch_size=batch_size, epochs=1
)
model.summary()
predict_num = model.predict(np.expand_dims(sample,axis=0))
print("예측한 숫자 : {}, 정답 숫자 : {}".format(predict_num.argmax(), sample_label))
print("성능 평가")
model.evaluate(x_test,y_test)