ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 순환 신경망(RNN)의 개념
    AI 2026. 2. 22. 19:11

    전부 은닉층에서 활성화 함수를 지난 값은 오직 출력층 방향으로만 향하는  피드 포워드 신경망(Feed Forward Neural Network) 다르게,순환 신경망(Recurrent Neural Network, RNN)은 은닉층의 노드에서 활성화 함수를 통해 나온 결과값을 출력층 방향으로도 보내면서, 다시 은닉층 노드의 다음 계산의 입력으로 보내는 특징을 갖고있습니다.

    즉, 은닉층의 결과값이 다시 자기 자신에게 입력되는 '재귀적 구조'를 갖는 것이 가장 큰 특징입니다.

    순환 신경망(Recurrent Neural Network, RNN)은 데이터의 순서(Sequence)가 중요한 연속적인 데이터를 처리하기 위해 고안된 인공지능 신경망의 한 종류입니다.

    • 연속형 데이터(Sequential Data): 특정 시점 $t$에서의 데이터가 이전 시점의 영향을 받는 데이터를 의미합니다.
    • 대표적인 예시 - 자연어(NLP): 문장은 단어들이 순차적으로 배열되어 있으며, 긴 문장일수록 앞선 단어와 뒤따르는 단어들 사이에 강한 상관관계(Correlation)가 존재합니다.
    • 핵심 원리: RNN은 이전에 처리한 데이터를 다음 단계에 활용합니다. 모델 내부에서 과거의 상태를 기억(Memory)하여 현재의 입력을 해석하고 미래 상태를 예측합니다.

    RNN의 핵심 구조와 작동 원리

    셀(Cell)과 은닉 상태(Hidden State)

    RNN에서 각 시점($t$)의 데이터를 입력받아 은닉 상태와 출력값을 계산하는 노드를 셀(Cell)이라고 부릅니다. 이 셀은 이전 시점의 정보를 은닉 상태(Hidden State)라는 형태로 저장하여 다음 시점으로 전달합니다. 이전의 값을 기억하려고 하는 일종의 메모리 역할을 수행하므로 이를 메모리 셀 또는 RNN 셀이라고 표현합니다.

    현재 시점 t에서의 메모리 셀이 갖고있는 값은 과거의 메모리 셀들의 값에 영향을 받은 것임을 의미합니다.메모리 셀이 출력층 방향 또는 다음 시점인 t+1의 자신에게 보내는 값을 은닉 상태(hidden state) 라고 합니다.

     

    셀은 t-1 시점의 메모리 셀이 보낸 은닉 상태값을 t 시점의 은닉 상태 계산을 위한 입력값으로 사용합니다.

     

    현재 시점 $t$에서의 은닉 상태 $h_t$는 다음과 같이 계산됩니다:

    $$h_t = \tanh(W_{xh}x_t + W_{hh}h_{t-1} + b)$$
    • $x_t$: 현재 시점의 입력값(Embedding Vector)
    • $h_{t-1}$: 이전 시점의 은닉 상태
    • $W_{xh}$: 입력값 $x_t$의 가중치(Weight)
    • $W_{hh}$: $h_{t-1}$에 대한 가중치(Weight)
    • $b$: 편향(Bias)

    계산된 현재의 은닉 상태($h_t$)를 바탕으로 최종 예측값($y_t$)을 도출합니다.

    $$y_t = f(W_{hy}h_t + b_y)$$

    (여기서 $f$는 활성화 함수로, 이진 분류라면 시그모이드, 다중 분류라면 소프트맥스를 주로 사용합니다.)

    • $W_{hy}$ (Hidden-to-Output)는 은닉 상태($h_t$)를 바탕으로 최종 출력값($y_t$)을 만들기 위해 사용하는 가중치 행렬

     

    1. $W_{xh}$ (Input-to-Hidden): 입력 가중치

    • 대상: 현재 시점($t$)에 새로 들어온 데이터 $x_t$ (예: 현재 읽고 있는 단어)와 곱해집니다.
    • 역할: 외부에서 들어온 정보를 신경망이 이해할 수 있는 수치적 특징(Feature)으로 변환하여 은닉층에 반영합니다.
    • 의미: "지금 이 순간 들어온 정보가 현재 상태($h_t$)를 만드는 데 얼마나 중요한가?"를 결정합니다. 새로운 정보를 문맥에 업데이트하는 역할을 수행합니다.

    2. $W_{hh}$ (Hidden-to-Hidden): 순환가중치

    • 대상: 이전 시점($t-1$)의 은닉 상태인 $h_{t-1}$ (예: 지금까지 읽어온 문장들의 요약본)과 곱해집니다.
    • 역할: 과거의 정보를 현재 시점으로 얼마나 전달(Recurrent)할지 결정합니다.
    • 의미: RNN이 '순환'할 수 있게 만드는 핵심 가중치입니다. 모델이 지금까지 읽어온 문맥(Context)을 잊지 않고 다음 단계로 이어주는 '기억의 끈' 역할을 합니다.

    3. $W_{hy}$ (Hidden-to-Output): 출력 가중치

    • 대상: 현재 시점의 계산이 끝난 은닉 상태($h_t$)와 곱해집니다.
    • 역할 (변환): 모델 내부의 추상적인 정보인 '은닉 상태'를 우리가 실제로 알고 싶은 '예측값(결과값)'의 형태로 변환합니다.
    • 의미: "현재까지 파악된 문맥($h_t$) 중에서 어떤 정보가 정답($y_t$)을 맞히는 데 결정적인가?"를 결정합니다.

    만약 다음에 올 단어를 예측하는 모델이라면:

    • $h_t$: "나는 사과를..."까지 읽고 머릿속에 정리된 '무언가를 먹으려 한다'는 정보 (추상적 벡터)
    • $W_{hy}$: 이 추상적인 정보를 바탕으로 '먹는다', '좋아한다' 같은 실제 단어들의 확률로 바꾸는 가중치
    • $y_t$: 최종적으로 도출된 단어 후보들의 확률값

     

    RNN 셀은 매 순간 새 정보를 받는 $W_{xh}$, 옛 기억을 잇는 $W_{hh}$, 정답을 내놓는 $W_{hy}$라는 세 가지 도구를 돌려가며 사용한다!

     

     


    🕒 RNN의 단계별 작업 순서 (Time Step)

    RNN이 "나는 학교가 싫다"라는 문장을 처리할 때, 내부에서는 다음과 같이 한 단계(Time Step)씩 가중치 계산이 반복됩니다.

    Step 1: 첫 번째 단어 처리 ($t=1$)

    • 입력($x_1$): "나는" (Word2Vec 등으로 변환된 임베딩 벡터)
    • 계산: $h_1 = \tanh(W_x x_1 + W_h h_0 + b)$
      • (이때 $h_0$는 이전 정보가 없으므로 보통 0으로 초기화된 벡터입니다.)
    • 결과: "나는"이라는 단어 정보가 담긴 첫 번째 은닉 상태($h_1$)가 생성됩니다.

    Step 2: 두 번째 단어 처리 ($t=2$)

    • 입력($x_2$): "학교가"
    • 이전 기억: 바로 전 단계에서 만든 $h_1$을 가져옵니다.
    • 계산: $h_2 = \tanh(W_x x_2 + W_h h_1 + b)$
    • 결과: "나는" + "학교가"의 맥락이 합쳐진 두 번째 은닉 상태($h_2$)가 생성됩니다.

    Step 3: 세 번째 단어 처리 ($t=3$)

    • 입력($x_3$): "싫다.."
    • 이전 기억: 앞선 맥락이 모두 담긴 $h_2$를 가져옵니다.
    • 계산: $h_3 = \tanh(W_x x_3 + W_h h_2 + b)$
    • 결과: 문장 전체의 의미("학교에 가기 싫어하는 화자의 상태")가 응축된 최종 은닉 상태($h_3$)가 만들어집니다.

    💡 여기서 꼭 기억해야 할 포인트!

    1. 매 단계 가중치 계산: 데이터가 한 단어씩 들어올 때마다 가중치 곱셈과 활성화 함수 연산이 매번 일어납니다.
    2. 임베딩과의 관계: Word2Vec 같은 임베딩은 RNN이 계산하기 좋게 단어를 숫자로 바꿔주는 '재료 준비' 과정이며, RNN은 이 재료들을 순서대로 요리해 '문맥'이라는 결과물을 만드는 과정입니다.

     

    티처 포싱(Teacher Forcing)이란?

    RNN 기반 모델(특히 Seq2Seq의 Decoder)을 학습시킬 때, 실제 정답(Ground Truth)을 다음 시점의 입력으로 강제 주입하는 학습 기법입니다.

    1. 왜 필요한가? (The Problem)

    RNN은 이전 시점의 출력($y_{t-1}$)을 다음 시점의 입력($x_t$)으로 사용합니다. 만약 모델이 초반에 잘못된 단어를 예측한다면, 그 잘못된 정보가 다음 단계로 전달되어 이후의 모든 예측이 망가지는 '에러 누적 현상'이 발생합니다. 학습 초기에는 모델이 매우 미숙하므로 정답을 맞히기 어렵고, 이로 인해 학습 속도가 매우 느려집니다.

    2. 작동 원리 (The Mechanism)

    • 일반 학습 (Without Teacher Forcing): * $t=1$: 나 → [RNN] → 병원에(오답)
      • $t=2$: 병원에 → [RNN] → 가서 (잘못된 입력을 바탕으로 계속 오답 생성)
    • 티처 포싱 (With Teacher Forcing):
      • $t=1$: 나 → [RNN] → 병원에(오답 발생!)
      • $t=2$: 학교에 (실제 정답 강제 주입) → [RNN] → 간다 (모델이 정신 차리고 다시 학습 가능)

    RNN의 치명적인 한계

     기울기 소실(Vanishing Gradient)

    RNN은 이론적으로는 과거의 모든 정보를 기억할 수 있지만, 실제 학습 과정에서는 장기 의존성(Long-Term Dependency) 문제를 겪습니다.

     

    왜 먼 과거를 기억하지 못할까?

    1. 역전파의 누적 곱: 모델 학습 시 오차를 앞쪽으로 전달(Backpropagation Through Time)하는데, 문장이 길어질수록 기울기(Gradient)가 반복적으로 곱해집니다.문제는 여기서 각 시점 사이의 기울기인 $\frac{\partial h_t}{\partial h_{t-1}}$에 순환 가중치 $W_{hh}$가 포함된다는 점입니다.

    2. 기울기 소실: 이때 기울기가 1보다 작으면 계속 곱해지면서 결국 0에 수렴하게 됩니다.
    3. 정보의 단절: 기울기가 0이 되면 앞쪽 층의 가중치들이 업데이트되지 않습니다. 결과적으로 모델은 문장 앞부분의 핵심 단서를 잊어버리고, 직전의 정보에만 의존하게 됩니다. (반대로 기울기가 너무 커지면 폭주(Exploding) 현상이 발생하기도 합니다.)

    수식적 설명

    은닉 상태를 계산하는 기본 식을 다시 보겠습니다.

    $$h_t = \tanh(W_{xh}x_t + W_{hh}h_{t-1} + b)$$

    여기서 $h_t$를 바로 전 단계인 $h_{t-1}$로 미분($\frac{\partial h_t}{\partial h_{t-1}}$)하면 어떻게 될까요?

    1. 괄호 안의 $W_{xh}x_t$$b$는 $h_{t-1}$과 상관이 없으니 0이 됩니다.
    2. $W_{hh}h_{t-1}$을 $h_{t-1}$로 미분하면 $W_{hh}$만 남습니다.
    3. 여기에 겉미분인 $\tanh$의 미분값이 곱해집니다.

    즉, $\frac{\partial h_t}{\partial h_{t-1}} = \tanh'(\dots) \times W_{hh}$ 가 됩니다.

    우리가 $t=3$ 시점에서 발생한 오차($E_3$)를 가지고 맨 앞인 $t=1$ 시점의 가중치를 수정하고 싶다고 가정해 봅시다. 미분값(기울기)은 시간을 거슬러 올라가며 다음과 같이 곱해집니다.

    $$\frac{\partial E_3}{\partial h_1} = \frac{\partial E_3}{\partial h_3} \times \color{red}{\frac{\partial h_3}{\partial h_2}} \times \color{red}{\frac{\partial h_2}{\partial h_1}}$$

     

    위에서 구한 값을 대입해 보면:

    $$\frac{\partial E_3}{\partial h_1} = (\text{오차 미분값}) \times \color{red}{(\tanh' \cdot W_{hh})} \times \color{red}{(\tanh' \cdot W_{hh})}$$

    보이시나요? 시점이 한 단계 멀어질 때마다 $W_{hh}$가 한 번씩 더 곱해집니다. 만약 100번째 시점에서 1번째 시점으로 가려면 $W_{hh}$를 99번 거듭제곱($W_{hh}^{99}$)해야 한다는 뜻입니다.

     

    기울기가 너무 커지면 폭주(Exploding)

     

    • 전달 과정: $t=100$에서 시작한 기울기가 $t=1$까지 가려면 연쇄 법칙(Chain Rule)에 의해 다음과 같이 계산됩니다.
      $$\frac{\partial E_{100}}{\partial h_1} = \frac{\partial E_{100}}{\partial h_{100}} \times \underbrace{(W_{hh} \cdot \dots \cdot W_{hh})}_{99번 \text{ 반복 곱}} \times (\text{기타 미분값})$$
    • 거듭제곱의 탄생: 만약 $W_{hh}$의 값이 $2$라고 가정하면, 99단계를 거슬러 올라가는 동안 $2$가 약 100번 곱해지게 됩니다.
      • 즉, 기울기에 $2^{100}$이라는 어마어마한 숫자가 포함되는 것이죠.
    • 실제 크기:  $2^{10} = 1,024$ (약 1천)
      • $2^{20} = 1,048,576$ (약 1백만)
      • $2^{100} \approx 1.26 \times 10^{30}$ (0이 30개 붙는 숫자)

    숫자가 너무 커서 메모리에 담을 수 없게 되면 프로그램은 이를 NaN (Not a Number, 숫자가 아님)으로 표시하고, 모델 학습은 그 즉시 망가집니다.


    RNN 기반 번역의 근본적 한계

     

    • 고정된 입력/출력 길이: 기본 RNN은 $T_x = T_y$ 구조(다대다 동기형)를 가집니다. 하지만 "나는 학교에 간다(3단어)"를 영어로 번역하면 "I go to school(4단어)"이 되듯, 언어별로 문장 길이는 제각각입니다.
    • 정보의 희미함: 문장이 길어질수록 앞부분의 단어 정보가 마지막 은닉 상태까지 도달하지 못하고 사라집니다.

    컨텍스트 벡터(Context Vector)

    컨텍스트 벡터는 인코더(Encoder) RNN의 마지막 시점($T$)의 은닉 상태($h_T$)를 말합니다.

    • 원리: 인코더는 문장의 첫 단어부터 마지막 단어까지 순차적으로 읽으며 은닉 상태를 업데이트합니다.
    • 수식적 의미: $h_T$는 앞선 모든 시점($t=1 \dots T-1$)의 정보를 누적하여 가지고 있는 '압축 파일'과 같습니다.
    • 역할: 인코더와 디코더 사이의 '유일한 다리'입니다. 디코더는 이 벡터 하나만 전해 받고, 그 안의 수치들을 해석해서 번역을 시작합니다.

    ① 고정 크기의 한계 (Fixed-length Constraint)

    컨텍스트 벡터는 보통 128, 256, 512 같이 고정된 차원의 벡터(숫자 묶음)입니다.

    • 5단어짜리 짧은 문장을 압축할 때는 여유롭지만, 50단어, 100단어가 넘어가는 긴 문장을 압축할 때도 똑같은 크기의 벡터에 정보를 밀어 넣어야 합니다.
    • 이 과정에서 정보의 '손실(Loss)'이 발생하며, 문장이 길어질수록 번역 품질이 급격히 떨어집니다. (이것을 병목 현상이라고 합니다.)

    ② 초기 정보의 소실 (Vanish of Early Information)

    RNN의 고질병인 기울기 소실과 연결됩니다.

    • 인코더가 문장 끝까지 다 읽었을 때, 마지막 은닉 상태($h_T$)에는 방금 읽은 문장 끝 단어의 정보는 생생하지만, 문장 맨 앞 단어의 정보는 희미해진 상태입니다.
    • 디코더는 문장 첫 단어부터 뱉어야 하는데, 컨텍스트 벡터에 첫 단어 정보가 부족하니 시작부터 엉뚱한 번역을 하게 됩니다.

     

    Seq2Seq (Sequence-to-Sequence): 인코더-디코더의 탄생

    번역과 같이 입력과 출력의 길이가 다른 문제를 해결하기 위해 인코더(Encoder)와 디코더(Decoder)를 분리한 구조입니다.

    • 인코더 (Encoder): 입력 문장 전체를 훑으며 정보를 압축합니다. 마지막 시점의 은닉 상태를 컨텍스트 벡터(Context Vector)라고 부르며, 여기에 전체 문장의 의미를 담습니다.
    • 디코더 (Decoder): 인코더가 넘겨준 하나의 컨텍스트 벡터만 보고, 출력 문장을 한 단어씩 생성합니다.
    • 의의: 입력과 출력의 길이를 다르게 가져갈 수 있어 본격적인 기계 번역 시대를 열었습니다.
    • 문제점 (병목 현상): 문장이 아무리 길어도 단 하나의 고정된 크기의 벡터에 모든 정보를 구겨 넣어야 합니다. 이로 인해 긴 문장에서는 정보 손실이 발생하며 성능이 급격히 저하됩니다.

    Attention Mechanism: "필요한 곳만 집중하라"

    고정된 컨텍스트 벡터의 병목 현상을 해결하기 위해 등장한 혁신적인 아이디어입니다.

    • 핵심 원리: 디코더가 단어를 생성할 때마다 인코더의 마지막 은닉 상태만 보는 것이 아니라, 인코더의 모든 시점($t=1 \dots T$)의 은닉 상태를 다시 한 번 훑어봅니다.
    • 작동 메커니즘:
      1. 유사도 계산: 현재 디코더의 상태와 인코더의 각 단어들이 얼마나 관련 있는지 점수(Attention Score)를 매깁니다.
      2. 가중치 부여 (Alignment): 점수가 높은 단어에는 높은 가중치를, 낮은 단어에는 낮은 가중치를 부여합니다.
      3. 동적 컨텍스트 벡터: 가중치가 반영된 새로운 컨텍스트 벡터를 매 시점마다 다르게 생성하여 디코더에 전달합니다.
    • 의의: * 병목 해결: 모든 단어의 정보를 활용하므로 긴 문장에서도 정보 소실이 없습니다.
      • 해석 가능성: 모델이 어느 단어에 집중해서 번역했는지 시각화(Attention Map)할 수 있습니다.

     


    입출력 구조의 상세 메커니즘

    RNN은 입력 시퀀스 길이($T_x$)와 출력 시퀀스 길이($T_y$)를 자유롭게 조절할 수 있습니다.

    일대다 (One-to-Many): "고정 입력 → 가변 출력"

    • 흐름: 하나의 벡터 $x$를 첫 번째 셀에 입력합니다. 이후 시점($t=2, 3...$)부터는 별도의 외부 입력 없이, 이전 시점의 출력이나 은닉 상태만을 사용하여 다음 출력을 만들어냅니다.
    • 상세 구조: 첫 번째 셀에서 나온 $h_1$이 다음 셀의 입력으로 전달되며 시퀀스를 이어갑니다.
    • 활용: 이미지 캡셔닝(Image Captioning). 이미지의 특징 벡터(1개)를 보고 "A", "dog", "is", "running"이라는 단어 시퀀스를 하나씩 뱉어냅니다.

    다대일 (Many-to-One): "가변 입력 → 고정 출력"

    • 흐름: $x_1, x_2, \dots, x_T$까지 모든 시퀀스를 순차적으로 입력받으며 은닉 상태를 업데이트합니다. 최종 시점($T$)의 은닉 상태 $h_T$만을 사용하여 최종 결과를 출력합니다.
    • 상세 구조: 이전 시점들의 정보가 축적된 마지막 $h_T$가 문장 전체를 대표하는 '문맥 벡터(Context Vector)' 역할을 하게 됩니다.
    • 활용: 감성 분석. "이 영화 진짜 재밌다"라는 4개 단어를 다 읽은 후, 마지막에 '긍정'이라는 결과 하나를 도출합니다.

    다대다 (Many-to-Many): "가변 입력 → 가변 출력"

    이 구조는 두 가지로 나뉘는데, 이 차이를 설명하는 것이 기술 블로그의 핵심입니다.

    • 동기형 (Sync): 입력 $x_t$가 들어올 때마다 출력 $y_t$가 즉시 나옵니다. ($T_x = T_y$)
      • 예: 형태소 분석, 비디오 프레임별 객체 인식.
    • 비동기형 (Async / Seq2Seq): 입력 시퀀스를 다 읽어서 은닉 상태에 저장(Encoder)한 뒤, 그 요약된 정보를 바탕으로 새로운 시퀀스를 생성(Decoder)합니다. ($T_x \neq T_y$ 가능)
      • 예: 번역기. 한국어 5단어를 읽고 영어 7단어로 번역할 때 사용합니다

    구조에 따른 분류

    양방향 순환 신경망 (Bidirectional RNN)

    기본 RNN은 과거의 정보만 참고하여 현재를 판단합니다. 하지만 문맥상 뒤에 나올 단어가 앞의 단어 결정에 결정적인 힌트가 되는 경우가 많습니다.

    • 핵심 원리: 정방향 RNN: 문장을 앞에서부터 읽음 ($t=1 \rightarrow t=100$)
      • 역방향 RNN: 문장을 뒤에서부터 거꾸로 읽음 ($t=100 \rightarrow t=1$)
    • 작동 방식: 두 개의 독립적인 은닉층을 두고, 특정 시점 $t$에서 두 방향의 은닉 상태를 결합하여 출력층으로 보냅니다.
    • 장점: 과거와 미래의 정보를 모두 활용하므로 자연어 처리(NLP)에서 성능이 비약적으로 향상됩니다.
    • 예시: "나의 취미는 [ ]을 치는 것이다." 뒤에 "테니스"나 "피아노" 같은 목적어가 나와야 빈칸의 의미가 명확해지는 경우에 유용합니다.

    다중 순환 신경망 (Stacked / Deep RNN)

    은닉층을 한 층만 쌓는 것이 아니라, 여러 층으로 쌓아 올린 구조입니다.

    • 구조: 첫 번째 은닉층의 출력($h_t^{(1)}$)이 다음 시점의 입력이 되는 동시에, 바로 위층에 있는 은닉층의 입력($x_t^{(2)}$)이 됩니다.
    • 설명: 층이 깊어질수록 모델은 더 복잡하고 추상적인 특징을 학습할 수 있습니다.
      • 아래층: 단어의 물리적 형태나 문법 학습
      • 위층: 문장의 주제나 고도의 문맥 학습
    • 주의점: 층이 너무 깊어지면 위에서 배운 '기울기 소실' 문제가 더 심해질 수 있어 주의가 필요합니다.

     

    구조 특징 대표 사례
    일대다 사진 1장 → 문장 설명 이미지 캡셔닝
    다대일 문장 → 감정 판단 감성 분석, 스팸 분류
    다대다 문장 → 문장 기계 번역, 챗봇
    양방향 미래 정보까지 참고 자연어 이해 (BERT 등)
    다중(Stacked) 은닉층을 여러 겹 쌓음 복잡한 데이터 특징

     

    'AI' 카테고리의 다른 글

    Seq2Seq의 한계를 넘어서: Attention 메커니즘  (0) 2026.02.23
    LSTM(Long Short-Term Memory)  (1) 2026.02.22
    통계적 언어 모델(SLM)과 N-gram  (0) 2026.02.22
    FastText  (0) 2026.02.22
    Word2Vec: Negative Sampling  (0) 2026.02.21
Designed by Tistory.