Recurrent Neural Network (RNN)
순환 신경망(RNN)은 시퀀스를 한 단계씩 읽으며 은닉 상태를 다음 단계로 전달합니다. 순환 구조, 학습, 변형 및 코드를 다룹니다.
순환 신경망(RNN)은 은닉 상태를 각 단계에서 다음 단계로 전달하면서 시퀀스를 요소별로 처리하는 신경망입니다. 따라서 각 단계의 출력은 지금까지 읽은 모든 내용에 좌우될 수 있습니다. 모든 단계에서 동일한 가중치를 적용하므로 하나의 네트워크로 문장부터 몇 시간 분량의 센서 기록까지 길이에 상관없이 다양한 시퀀스를 처리할 수 있습니다. RNN은 2010년대 후반 Transformer가 대부분의 언어 작업에서 이를 대체하기 전까지 자연어 처리(NLP), 음성 인식, 시계열 분석의 주요 아키텍처였습니다. 게이트 방식 RNN은 스트리밍 및 온디바이스 모델에서 여전히 널리 사용되며, Mamba와 같은 상태 공간 모델(SSM)에서 순환 구조가 다시 활용되고 있습니다.
RNN의 작동 방식#
Jeffrey Elman이 1990년에 발표한 논문에서 이름을 딴 Elman 네트워크라고도 하는 단순 RNN은 hₜ = tanh(Wxₜ + Uhₜ₋₁ + b)로 은닉 상태를 갱신하며, 각 단계에서 yₜ = Vhₜ + c의 출력을 내보낼 수 있습니다. 은닉 상태는 지금까지의 시퀀스를 요약하는 고정 크기 벡터이며, tanh는 피드백되는 값이 −1과 1 사이에 유지되도록 합니다. 각 단계에 네트워크 사본 하나씩을 그려 순환 과정을 펼치면, 동일한 가중치를 계층 간에 공유하는 딥 피드포워드 네트워크가 됩니다.
아래 코드 조각은 시퀀스에 대해 PyTorch의 nn.RNN을 실행하고 일반 반복문에서 동일한 순환을 반복합니다.
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=3, hidden_size=4, batch_first=True)
x = torch.randn(1, 6, 3) # one sequence: 6 time steps, 3 features each
# PyTorch runs the whole sequence; output holds the hidden state after every step
output, h_n = rnn(x)
# The same recurrence by hand, reusing one set of weights at every step
h = torch.zeros(1, 4)
for t in range(x.shape[1]):
h = torch.tanh(x[:, t] @ rnn.weight_ih_l0.T + rnn.bias_ih_l0 + h @ rnn.weight_hh_l0.T + rnn.bias_hh_l0)
print(f"Output shape: {tuple(output.shape)}, final state shape: {tuple(h_n.shape)}")
print(f"Hand-written loop matches nn.RNN: {torch.allclose(h, h_n[0], atol=1e-6)}")Output shape: (1, 6, 4), final state shape: (1, 1, 4)과 Hand-written loop matches nn.RNN: True을 출력합니다. 출력에는 시간 단계마다 4차원 은닉 상태 하나가 포함되며, 입력에 대한 가중치 행렬 하나와 이전 상태에 대한 가중치 행렬 하나만 사용하는 반복문으로 최종 상태를 재현합니다.
시퀀스 작업#
같은 순환 구조를 입력 및 출력 길이가 서로 다른 작업에 적용할 수 있습니다.
- 다대일: 전체 시퀀스를 읽고 최종 상태를 기반으로 분류합니다. 감성 분석이나 센서 데이터 구간 라벨링이 이에 해당합니다.
- 다대다: 문장의 각 단어에 태그를 지정하거나 오디오의 각 프레임을 처리하는 것처럼 각 단계마다 출력을 생성합니다.
- 시퀀스-투-시퀀스: 인코더 RNN이 입력을 읽고 디코더 RNN이 길이가 다른 출력을 생성합니다. 초기 신경 기계 번역과 기타 시퀀스-투-시퀀스 모델이 이 설계를 사용합니다.
- 일대다: 초기 이미지 캡셔닝 모델에서 이미지의 특성 벡터로 캡션을 생성하는 것처럼 단일 입력에서 시퀀스를 생성합니다.
양방향 RNN은 시퀀스를 역방향으로 읽는 두 번째 RNN을 추가하고 각 단계에서 두 상태를 결합하므로 모든 출력이 과거와 미래의 문맥을 모두 참조합니다. 스택형 RNN은 한 계층의 은닉 상태를 다음 계층의 입력 시퀀스로 전달합니다.
시간에 따른 역전파를 이용한 학습#
RNN은 시간에 따른 역전파(BPTT)로 학습합니다. 시퀀스에 따라 네트워크를 펼치고 단계별 손실을 합산한 다음 펼친 그래프를 통해 역전파를 수행합니다. T단계에서 t단계로 전달되는 기울기는 순환 계층의 복사본 T − t개를 거치며 매번 U와 tanh의 도함수를 곱합니다. 이 인자들이 대부분 1보다 작으면 기울기가 기하급수적으로 줄어듭니다. 이는 Yoshua Bengio, Patrice Simard, Paolo Frasconi가 1994년에 분석한 기울기 소실 문제입니다. 인자들이 1보다 크면 기울기는 기하급수적으로 커지며, 이를 기울기 폭발 문제라고 합니다. 아래 코드 조각은 길이 50인 시퀀스의 각 입력이 최종 은닉 상태에 미치는 영향을 측정합니다.
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=8, hidden_size=32, batch_first=True)
x = torch.randn(1, 50, 8, requires_grad=True) # one 50-step sequence
# Backpropagate from the final hidden state to the input at every step
output, h_n = rnn(x)
h_n.sum().backward()
grad_norms = x.grad[0].norm(dim=1)
for distance in [0, 10, 20, 30, 40]:
print(f"Input {distance:>2} steps before the end: gradient {grad_norms[-1 - distance]:.1e}")이 코드는 끝나기 전 0, 10, 20, 30, 40번째 단계에서 1.6e+00, 3.4e-03, 6.2e-06, 1.2e-08, 1.1e-11의 그래디언트를 출력합니다. 10단계마다 비용이 약 세 자릿수 배씩 증가하므로, 학습 중에는 몇십 단계 이전의 입력을 활용하도록 가중치를 거의 조정할 수 없습니다. 2013년 Razvan Pascanu와 동료들이 RNN을 대상으로 분석한 그래디언트 클리핑은 폭주하는 그래디언트를 제한하고, 절단된 BPTT는 역전파를 고정된 윈도우로 제한해 메모리 사용량을 제어합니다. 기울기 소실을 해결하려면 아키텍처를 변경해야 하며, LSTM과 GRU의 게이트가 바로 이 역할을 합니다.
RNN과 관련 아키텍처 비교#
- LSTM과 GRU: 정보와 그래디언트가 여러 단계를 거쳐 전달되도록 하는 가산 상태 업데이트를 갖춘 게이트형 RNN입니다. 실제로 "RNN"은 단순 RNN뿐 아니라 이 두 아키텍처 중 하나를 가리키는 경우도 많습니다.
- Transformer: 이력 정보를 하나의 상태로 압축하는 대신 이전의 모든 위치에 직접 주의를 기울이고, 모든 위치를 병렬로 학습합니다. 시퀀스 길이가 늘어나면 어텐션 비용도 증가하지만, RNN은 새 단계마다 동일한 연산량과 메모리를 사용합니다.
- 합성곱 신경망(CNN): 이미지에서는 공간을, 1D 합성곱에서는 시간을 기준으로 고정 크기 필터를 사용해 인접 위치를 결합하며, 수용 영역은 네트워크 깊이에 따라 정해집니다.
- 상태 공간 모델: Mamba와 같은 선형 순환 모델은 스캔 방식으로 병렬 학습되고 추론 시에는 RNN처럼 단계별로 실행됩니다. 액체 신경망은 뉴런이 미분 방정식을 따르는 연속 시간 RNN입니다.
응용 분야#
- 키보드 예측: Gboard의 다음 단어 모델은 입력-망각 게이트를 결합한 경량 LSTM 변형인 LSTM으로, Google 연구진이 2018년에 설명한 것처럼 사용자 휴대전화에서 연합 학습으로 학습했습니다.
- 수요 예측: Amazon의 DeepAR은 서로 관련된 여러 시계열에 걸쳐 하나의 자기회귀 RNN을 학습하고 각 미래 값에 대한 확률 분포를 출력합니다.
- 스트리밍 오디오: 웨이크 워드 감지기와 노이즈 억제기는 작은 순환 레이어를 사용해 오디오를 프레임 단위로 처리하므로 휴대전화와 이어버드에서 메모리와 지연 시간이 일정하게 유지됩니다.
- 객체 추적: 추적기는 프레임마다 각 객체의 상태를 이어서 관리하며, 이는 RNN의 은닉 상태가 담당하는 역할과 같습니다. YOLO26의 추적 모드에 내장된 모든 추적기는 ByteTrack과 BoT-SORT부터 기본값인 TrackTrack까지 칼만 필터로 해당 상태를 업데이트합니다. 칼만 필터는 학습된 가중치 대신 손으로 설정한 등속도 방정식을 사용하는 선형 순환 모델입니다.










