본문 바로가기

문돌이 존버/데이터 분석

RNN 개념 잡고 간단 예제 코드 돌려보기 (1)

반응형
해당 글은 핸즈온 머신러닝 2판을 기준으로 작성되었습니다.

RNN이란?

RNN은 recurrent neural networks의 약자로, 한국어로 번역하면 순환 신경망이 된다. 고정 길이 입력이 아닌 임의 길이를 가진 시퀀스를 다룰 수 있어, 문장, 문서, 오디오 샘플을 입력으로 받고 자동 번역, STT와 같은 NLP 작업에도 유용하다.

<출처: medium>

input: x
output: y

위 RNN 구조를 보면 각 타임 스텝 t(또는 프레임)마다 $x_{(t)}$와 이전 타임 스텝의 출력인 $y_{(t-1)}$을 입력으로 받는다. 첫 번째 타임 스텝은 이전 출력이 없으므로 일반적으로 0으로 설정한다. 아래 왼쪽 그림은 순환층을 직관적으로 나타낸 것인데, 이것이 헷갈리면 시간에 따라 네트워크를 펼친(unrolling the network through time) 오른쪽 그림을 참고하면 된다. 

<출처: Excelsior-JH 블로그>

각 순환 뉴런은 두 벌의 가중치를 가진다. 하나는 입력 $x_{(t)}$를 위한 것이고 다른 하나는 이전 타임 스텝의 출력 $y_{(t-1)}$을 위한 것이다. 이를 각각 $w_x$ 와 $w_y$라고 하겠다. 하나의 순환 뉴런이 아니라 순환 층 전체를 생각하면 가중치 벡터를 행렬 $W_x$와 $W_y$로 바꿀 수 있다. 순환 층 전체의 출력 벡터는 아래 식과 같이 계산된다.

$y_{(t)} = \phi (W_x^T x_{(t)} + W_y^T y_{(t-1)} + b)$
$\phi$: 활성화 함수로 RNN에선 보통 하이퍼볼릭 탄젠트(tanh) 활성화 함수를 선호한다.

타임 스텝 t에서의 모든 입력을 행렬 $X_{(t)}$로 만들어 미니배치 전체에 대해 순환 층 출력을 한 번에 계산할 수 있다. 참고로 $W$를 Andrew Ng 강의에선 stacking이라고 칭한다.

$Y_{(t)} = \phi (X_{(t)} W_x + Y_{(t-1)} W_y + b)
        = \phi ([X_{(t)} Y_{(t-1)}] W + b)$ where $W=[W_x, W_y]^T$
표기법 정리
$Y_{(t)}$: 타임 스텝 t에서 미니배치에 있는 각 샘플에 대한 층의 출력을 담은 $m \times n_{neurons}$ 행렬 ($m$은 미니배치에 있는 샘플 수, $n_{neurons}$은 뉴런 수)
$X_{(t)}$: 모든 샘플의 입력값을 담은 $m \times n_{inputs}$ 행렬 ($n_{inputs}$은 입력 특성 수)
$W_x$: 현재 타임 스텝의 입력에 대한 연결 가중치를 담은 $n_{inputs} \times n_{neurons}$ 행렬
$W_y$: 이전 타임 스텝의 출력에 대한 연결 가중치를 담은 $n_{neurons} \times n_{nerouns}$ 행렬
$b$: 각 뉴런의 편향을 담은 $n_{nerouns}$ 크기의 벡터

보통 $W_x$와 $W_y$를 합쳐서 $(n_{inputs} + n_{neurons}) \times n_{neurons}$ 크기의 가중치 행렬 $W$ 하나로 연결한다.

$Y_{(t)}$는 $X_{(t)}$와 $Y_{(t-1)}$의 함수고, $Y_{(t-1)}$는 $X_{(t-1)}$와 $Y_{(t-2)}$의 함수고, 이를 계속 반복하다보면 결국 $Y_{(t)}$은 시간 t=0에서부터 모든 입력에 대한 함수가 된다. 

메모리 셀

타임 스텝 t에서 순환 뉴런의 출력은 이전 타임 스텝의 모든 입력에 대한 함수이므로 이를 일종의 메모리 형태라고 말할 수 있다. 타임 스텝에 걸쳐 어떤 상태를 보존하는 신경망의 구성 요소를 메모리 셀(memory cell)이라고 한다. 일반적으로 타임 스텝 t에서의 셀 상태를 $h_{(t)}$라고 한다. 

RNN은 입력 형태와 출력 형태를 다양하게 설정할 수 있다. 

vector-to-sequnece network(one to many): 하나의 입력 벡터를 반복해서 네트워크에 주입하고 하나의 시퀀스를 출력 ex) 이미지(또는 CNN 출력)를 입력하여 이미지에 대한 캡션 출력
sequence-to-vector network(many to one): 입력 시퀀스를 네트워크에 주입하고 하나의 시퀀스를 출력 ex) 영화 리뷰의 연속된 단어를 주입하여 감성 점수 출력
sequence-to-sequence network(synched many to many): 입력 시퀀스를 받아 출력 시퀀스를 출력 ex) 주식가격 같은 시계열 데이터 예측
encoder-decoder sequence network(many to many): 인코더라 부르는 시퀀스-투-벡터 네트워크 뒤에 디코더라 부르는 벡터-투-시퀀스 네트워크를 연결 ex) 한 언어의 문장을 다른 언어로 번역하는 데 사용

<출처: cs231n 강의>

RNN 훈련하기

RNN은 학습할 때 보통 역전파를 사용한다. 이를 BPTT(backpropogation through time)이라고도 부른다. 딥러닝에서 사용되는 역전파와 똑같이 작용하며, 현재 메모리 셀이 예측한 값이 실제값과 차이(=error)가 나면 이는 이전의 메모리 셀에서 잘못한 것이라고 생각하면 쉽다. 즉 연대 책임을 묻는 것이다.

주의할 점은 가중치가 각 메모리 셀마다 다른 값을 가지는 것이 아니라 정방향 패스 동안 모든 타임 스텝이 동일한 가중치 행렬을 공유한다는 것이다. 아래 그림에서 $W_a$, $b_a$는 각 셀마다 똑같이 적용된다. 따라서 역전파로 최종 업데이트되는 가중치는 모든 타임 스텝에 걸쳐 합산된 값이다.

<출처: Andrew Ng 강의>

위에서 Loss function은 보면 알 수 있듯이 sigmoid function을 사용한 예시이다. 

지금까지 RNN 개념을 살펴봤고, 케라스를 활용한 예시 코드는 다음 글에서 소개한다. 이후에는 RNN의 단기 기억 문제를 해결한 LSTM에 대해서도 정리하려고 한다.

728x90
반응형