본문 바로가기
Python/NLP&LLM

RNN(Recurrent Neural Network)

by Mr.DonyStark 2024. 5. 2.

※ Word2Vec은 단어를 고차원 벡터로 매핑하는 기술로, 단어 간의 의미적 유사성을 측정할 수 있게 해줌. 이러한 Word-embedding은 자연어 처리(Natural Language Processing, NLP) 분야에서 널리 사용됨
RNN(Recurrent Neural Network)은 순환 신경망으로, 순차적인 데이터나 시퀀스 데이터를 처리하는 데 사용됨. 이전의 정보를 현재 상태로 전달하여 순서에 따른 패턴을 학습할 수 있음.
  Word2Vec과 RNN은 자연어 처리에서 서로 보완적으로 사용될 수 있음. Word2Vec은 단어를 고정된 차원의 밀집 벡터로 표현하여 단어 간의 의미적 유사성을 측정할 수 있음. 이런 단어 벡터는 RNN과 같은 모델에 입력으로 사용될 수 있음. 예를 들어, RNN은 단어 시퀀스를 입력으로 받아 각 단어의 의미를 파악하고, 이를 기반으로 다양한 자연어 처리 작업을 수행함.

□ 시퀀스 데이터에 특화

   ▷ 시퀀스 데이터란

      - Speech recognition : 단어의 연속변환
      - Music generation : 연속된 음표출력
      - Sentiment classification : 텍스트 부정/긍정 판단
      - DNA 분석 : 염기서열 > 질병유무, 단백질 종류
      - 자동번역
      - Video activity recognition
      - Financial Data
□ 기억 능력을 갖고 있음
  * 네트워크 기억 : 지금까지의 입력 데이터를 요약한 정보

h1 쪽에서 기억을 저장함


□ 입력을 모두 처리하고 난 후 네트워크에 남겨진 기억은 시퀀스 전체를 요약하는 정보(기억을 바탕으로 새로운 단어 이해)
□ 이 과정은 새로운 단어마다 계속해서 반복 > Recurrent(순환적)

□ RNN 훈련방법

 

□ RNN 개선 모델

  ○ RNN(Recurrent Neural Network)은 순환 신경망으로, 순차적인 데이터를 처리하는 데 사용됨.
  ○ RNN은 과거의 정보를 기억하고 현재 입력에 대한 출력을 계산하는 데 사용되는데 시퀀스 데이터에서 효과적으로 작동할 수 있지만, 특히 긴 시퀀스에서 발생하는 그래디언트 소실(vanishing gradient) 문제로 인해 장기 의존성을 캡처하기 어려운 경우가 있음.
  ○ 그러나 이러한 문제를 해결하기 위해 다양한 RNN의 변형이 개발되었고 아래와 같음.
    - Simple RNN (vanilla RNN)

가장 기본적인 형태의 순환 신경망. Simple RNN은 현재 입력과 이전 시간 단계의 은닉 상태를 사용하여 출력을 계산함. 그러나 Simple RNN은 장기 의존성을 처리하기에 적합하지 않고, 긴 시퀀스에서 발생하는 그래디언트 소실 문제가 있음.
    - LSTM (Long Short-Term Memory)

LSTM은 RNN의 변형 중 하나로, 그래디언트 소실 문제를 해결하기 위해 고안됨. LSTM은 이전 시간 단계의 정보를 오랫동안 기억할 수 있는 메모리 셀을 도입하여 장기 의존성을 캡처함. 또한, 게이트(gate) 메커니즘을 사용하여 정보를 업데이트하고 삭제함으로써 모델의 학습을 조절할 수 있음.

  ▶장기기억을 저장할 수 있는 Cell
  ▶ 단기기억을 기억할 수 있는 Forget gate
  ▶ 단기기억을 장기기억으로 보낼지말지 여부를 자동으로 결정해줌
  ▶ Output gate는 들어온 데이터를 과거 단기기억, 장기기억등의 값을 바탕으로 Forget gate 또는 Cell 쪽으로 보냄
      (이는 확률적 경사하강법이 잘되어 있어 신규 데이터에 대한 학습 평탄화가 잘되었다는 것을 의미)
  ▶ 시그모이드 함수(0,1)로 구성되어있어 인풋에 대해서 결과처리를 0, 1로 진행
   - GRU (Gated Recurrent Unit)

GRU는 LSTM과 유사한 메커니즘을 가지고 있지만, 더 간단한 구조를 가지고 있음. LSTM보다 더 적은 파라미터를 사용하며, 더 빠르게 학습할 수 있음. GRU는 업데이트 게이트와 리셋 게이트를 사용하여 정보의 흐름을 조절하고, 메모리 셀의 업데이트를 수행함. LSTM과 다르게 cell strate이 없음.

 

□ LSTN, Simple RNN, GRU 구현 주요함수
  ○ return_sequences(*Ouput 형태에 따라 알맞게 사용)

    - True : 모든 timestep의 output 모두 반환

    - False(default) : last time stemp의 output 반환
  ○ return_state (*hidden 부분 조정)

    - True : output, last step 의 hidden state, cell state(lstm의 경우) 반환

    - False(default) : output만 반환
  ○  Bididectional LSTM
    - 순반향, 역방향이 concatenate된 output출력
    - hidden state, cell state는 순방향, 역방향 별도 출력

 

 코드

○ keras의 model 호출

인풋값 변서 설정

시행 횟수 설정

LSTM을 통한 아웃풋 설정

#라이브러리
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, LSTM, Bidirectional, GRU
import numpy as np
import warnings #경고메세지 가리
warnings.filterwarnings("ignore")

B = 2 #batch size / 2개의 인풋 값이 들어가도록 설정
T = 5 #time steps
D = 1 #features 워드 임베딩의 디멘션 수, 즉, 차원 개수
U = 3 #LSTM units / LSTM output 유닛 개수

X = np.random.randn(B,T,D)
print(X.shape)
print("\n")
print(X)

값을 받고 5번의 time을 갖는 feature 2개

○ lstm : return_sequences 조정을 통한 Out put 조정

def lstm(return_sequences=False):
    inp = Input(shape=(T, D)) #input
    out = LSTM(U,return_sequences=return_sequences)(inp) #Output LSTM 출력
    model = Model(inputs=inp, outputs=out) #모델 형성
    return model.predict(X)

print("--return_sequences=False > last timestep의 output만 반환")
print(lstm_out.shape)
lstm_out = lstm(return_sequences=False)
lstm_out

print("--return_sequences=True > last timestep 별 output만 반환")
print(lstm_out.shape)
lstm_out = lstm(return_sequences=True)
lstm_out

위에서 LSTM input 개수를 2로 지정했기에 False일땐 1개, True일땐 2개

 

○ lstm : return_state 조정을 통한 hidden state, cell state 반환

#return_state : False > out만 반환, True > out,last step의 hidden state, cell state 반환
def lstm(return_state=False):
    inp = Input(shape=(T,D))
    out = LSTM(U, return_state=return_state)(inp)
    model = Model(inputs=inp, outputs=out)

    if return_state == True:
        o, h, c = model.predict(X)
        print(f"o:{o.shape}")        
        print(o.shape)
        print(f"h:{h.shape}")        
        print(h.shape)
        print(f"c:{c.shape}")
        print(c.shape)
    else: #False 경우에는 output만 나옴
        o = model.predict(X)
        print(f"o:{o.shape}")
        print(o.shape)

print("return_state=True > output, hidden state, cell state 출력")
lstm(return_state=True)
print("\n")
print("return_state=False > output only")
lstm(return_state=False)

 

○ Bidirctional LSTM : 순방향, 역방향이 concatenate 된 output 출력 / hidden state, cell state는 순방향, 역방향 별도 출력

def bi_lstm(return_sequences=False, return_state=False):
    inp = Input(shape=(T, D))
    #Bidirectional 함수로 감싸서 역방향, 순방향 진행 (2,3) > (2,6)이 됨. 단, hidden layer는 변함 없음
    out = Bidirectional(
            LSTM(U, return_state=return_state, return_sequences=return_sequences))(inp)
    
    model = Model(inputs=inp, outputs=out)
    
    if return_state:    
        o, h1, c1, h2, c2 = model.predict(X)
        print("o :",o.shape)
        print("h1 :", h1.shape)
        print("c1 :", c1.shape)
        print("h2 :", h2.shape)
        print("c2 :", c2.shape)
    else:
        o = model.predict(X)
        print("o :", o.shape)

print("*** 순방향, 역방향이 concatenate ***")
print("---- return_sequences=False ----> last timestep 의 output 만 반환")
bi_lstm(return_sequences=False, return_state=False)
print()
print("---- return_sequences=True ----> 모든 timestep 별 output 출력")
bi_lstm(return_sequences=True)
print()
print("---- return_sequences=True, return_state=True")
bi_lstm(return_state=True)

○ GRU : Cell state가 없는 것이 LSTM과의 차이임

#GRU는 Cell state가 없는 것만 LSTM과 차이
def gru(return_sequences=False, return_state=False):
    inp = Input(shape=(T, D))
    out = GRU(U, return_state=return_state, return_sequences=return_sequences)(inp)
    
    model = Model(inputs=inp, outputs=out)
    
    if return_state:    
        o, h = model.predict(X)
        print("o :", o.shape)
        print("h :", h.shape)
    else:
        o = model.predict(X)
        print("o :", o.shape)

print("---- Many-to-One output ----")
gru(return_sequences=False, return_state=False)
print()
print("---- Many-to-Many output ----")
gru(return_sequences=True)
print()
print("---- Sequence-to-Vector output ----")
gru(return_state=True)

Bidirectional GRU

#Bidirectional GRU
#cell state 가 없는 것 외에 LSTM 과 동일
def bi_gru(return_sequences=False, return_state=False):
    inp = Input(shape=(T, D))
    out = Bidirectional(
            GRU(U, return_state=return_state, return_sequences=return_sequences))(inp)
    
    model = Model(inputs=inp, outputs=out)
    if return_state:    
        o, h1, h2 = model.predict(X)
        print("o :", o.shape)
        print("h1 :", h1.shape)
        print("h2 :", h2.shape)
    else:
        o = model.predict(X)
        print("o :", o.shape)
        
print("---- 순방향, 역방향이 concatenate 된 many-to-one output")
bi_gru(return_sequences=False, return_state=False)
print()
print("---- 순방향, 역방향이 concatenate 된 many-to-many output")
bi_gru(return_sequences=True)
print()
print("---- 순방향, 역방향이 concatenate 된 sequence-to-vector output")
bi_gru(return_state=True)

'Python > NLP&LLM' 카테고리의 다른 글

Tokenizer 심화  (0) 2024.05.03
영화리뷰 : 감정분석  (1) 2024.05.03
Word Embedding과 Word2Vec  (0) 2024.05.02
문장 Vector 작업  (0) 2024.05.01
자연어 처리(Natural Language Processing) 및 발전단계  (0) 2024.04.30