수달이네 기술 블로그

8. GRU(Gated Recurrent Unit) 본문

AI공부/자연어처리

8. GRU(Gated Recurrent Unit)

슬픈 수달이 2026. 2. 28. 20:20

GRU(Gated Recurrent Unit)

RNN의 장기 의존성 문제를 해결하기 위해 개발한 신경망 구조

GRU구조

  • 업데이트 게이트(Update Gate): 이전 정보를 얼마나 유지할지 결정
  • 리셋 게이트(Reset Gate): 새로운 정보를 반영하기 위해 이전 정보를 얼마나 잊을지 결정

GRU 특징

  • LSTM보다 훨씬 간단한 구조를 가져 연산량이 적고, 학습 속도가 빠르다.
    • 2개의 게이트만 가진 구조
  • 텍스트 처리, 음성인식, 시계열 예측에서 LSTM보다 빠르고 효율적
  • 그러나 장기 의존성이 더 중요한 경우 LSTM이 더 나을 수 있음.
    • 지금은 LSTM이 더 많이 사용됨.

GRU구현

이전 부분은 LSTM에서 사용한 데이터 로드, 전처리 부분 활용.

GRU모델 정의

class SentimentGRU(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, dropout):
        super(SentimentGRU, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)

        # LSTM -> GRU 변경
        self.gru = nn.GRU(embedding_dim, hidden_dim, num_layers=n_layers, batch_first=True, dropout=dropout, bidirectional=True)
        self.batch_norm = nn.BatchNorm1d(hidden_dim * 2)  # 배치 정규화 추가
        self.fc = nn.Linear(hidden_dim * 2, output_dim)

    def forward(self, x):
        embedded = self.embedding(x)
        gru_out, _ = self.gru(embedded)  # GRU 실행
        out = self.batch_norm(gru_out[:, -1, :])  # 마지막 타임스텝의 출력 사용
        out = self.fc(out)
        return out  # BCEWithLogitsLoss 내부에서 sigmoid 적용됨
  • bidirectional 이란?
    • 문장을 정방향으로 넣기도, 역방향으로 넣기도 하며 학습하는 방식
    • 즉, 입력 시퀀스의 과거, 미래 정보를 모두 활용하여 풍부한 문맥 정보를 학습 가능하다.
    • 원래 GRU 논문엔 없는 내용이지만 파이토치에서 업데이트하며 추가된 부분(BERT모델에서 나온 내용)
# 모델 초기화
embedding_dim = 128
hidden_dim = 512
output_dim = 1
n_layers = 2
dropout = 0.2

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model = SentimentGRU(vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, dropout)
model.to(device)
  • 위 부분만 변화 나머지는 같음.

위를 실제로 돌리면 6분이상 나오는데 이건 bidirection옵션을 켰기 때문에 hiddenlayer가 사실상 2배 증가했기 때문이다.

다시 돌아와서 비교하기 위해 bidirection옵션을 끄고 진행한다면

class SentimentGRU(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, dropout):
        super(SentimentGRU, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)

        # LSTM -> GRU 변경
        self.gru = nn.GRU(embedding_dim, hidden_dim, num_layers=n_layers, batch_first=True, dropout=dropout, bidirectional=False)
        self.batch_norm = nn.BatchNorm1d(hidden_dim)  # 배치 정규화 추가
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        embedded = self.embedding(x)
        gru_out, _ = self.gru(embedded)  # GRU 실행
        out = self.batch_norm(gru_out[:, -1, :])  # 마지막 타임스텝의 출력 사용
        out = self.fc(out)
        return out  # BCEWithLogitsLoss 내부에서 sigmoid 적용됨

그러나 내 출력에서는 LSTM이 더 빠르게 출력되진 않았다.

'AI공부 > 자연어처리' 카테고리의 다른 글

10. Seq2Seq구현  (0) 2026.03.03
9. Seq2Seq(Sequence-to-Sequence)  (0) 2026.03.02
7. LSTM(Long Short Term Memory)  (0) 2026.02.27
6. RNN활용 KOSPI예측(시퀀스데이터)  (0) 2026.02.23
5. RNN(Recurrent Neural Network)기초  (1) 2026.02.22