728x90
반응형

RNNLM 구현

 

 

SimpleRnnlm의 계층 구성 : RNN 계층의 상태는 클래스 내부에서 관리

[그림1] SimpleRnnlm의 계층 구성

 

SimpleRnnlm

import sys
sys.path.append('..')
import numpy as np
from time_layers import *


class SimpleRnnlm:
    def __init__(self, vocab_size, wordvec_size, hidden_size):
        V, D, H = vocab_size, wordvec_size, hidden_size
        rn = np.random.randn

        # 가중치 초기화
        embed_W = (rn(V, D) / 100).astype('f')
        rnn_Wx = (rn(D, H) / np.sqrt(D)).astype('f')
        rnn_Wh = (rn(H, H) / np.sqrt(H)).astype('f')
        rnn_b = np.zeros(H).astype('f')
        affine_W = (rn(H, V) / np.sqrt(H)).astype('f')
        affine_b = np.zeros(V).astype('f')

        # 계층 생성
        self.layers = [
            TimeEmbedding(embed_W),
            TimeRNN(rnn_Wx, rnn_Wh, rnn_b, stateful=True),
            TimeAffine(affine_W, affine_b)
        ]
        self.loss_layer = TimeSoftmaxWithLoss()
        self.rnn_layer = self.layers[1]

        # 모든 가중치와 기울기를 리스트에 모은다.
        self.params, self.grads = [], []
        for layer in self.layers:
            self.params += layer.params
            self.grads += layer.grads

    def forward(self, xs, ts):
        for layer in self.layers:
            xs = layer.forward(xs)
        loss = self.loss_layer.forward(xs, ts)
        return loss

    def backward(self, dout=1):
        dout = self.loss_layer.backward(dout)
        for layer in reversed(self.layers):
            dout = layer.backward(dout)
        return dout

    def reset_state(self):
        self.rnn_layer.reset_state()

 

 

언어 모델의 평가

  • 언어 모델은 주어진 과거 단어(정보)로부터 출현할 단어의 확률분포를 출력한다. 
  • 이때 언어 모델의 예측 성능을 평가하는 척도로 퍼블렉서티(perplexity, 훈련도)를 자주 이용한다.
  • 퍼블렉서티 - 확률의 역수
    • 데이터 수가 하나일 때에 정확히 일치한다.
    • 퍼블렉서티는 작을수록 좋다.

 

퍼블렉서티 

  • 입력 데이터가 여러 개일때의 공식

[그림2] 퍼블렉서티 여러개의 입력 데이터

  • N은 데이터의 총개수
  • tn은 원핫 벡터로 정답을 나타낸 레이블
  • tnk는 n개째 데이터의 k번째 값을 의미한다.
  • ynk는 확률분포를 나타낸다. (신경망에서는 Softmax의 출력)
  • L은 신경망의 손실
  • L을 이용해 e^L을 계산한 값이 곧 퍼블렉서티다.

 

 

RNNLM의 학습 코드

  • PTB 데이터셋(훈련 데이터) 전부를 대상으로 학습하면 좋은 결과를 낼 수 없기 때문에, 처음 1,000개의 단어만 이용
# RNNLM의 학습 코드

import sys
sys.path.append('..')
import matplotlib.pyplot as plt
import numpy as np
from optimizer import SGD
import pbt

#하이퍼파라미터 설정
batch_size = 10
wordvec_size = 100
hidden_size = 100 # RNN 은닉 벡터 원소 수
time_size = 5 # Truncated BPTT가 한 번에 펼치는 시간 크기
lr = 0.1
max_epoch = 100

# 학습 데이터 읽기(전체 중 1000개만)
corpus, word_to_id, id_to_word = pbt.load_data('train')
corpus_size = 1000
corpus = corpus[:corpus_size]
vocab_size = int(max(corpus) + 1)

xs = corpus[:-1] # 입력
ts = corpus[1:] # 출력 (정답 레이블
data_size = len(xs)
print('말뭉치 크기 : %d, 어휘 수 : %d ' %(corpus_size, vocab_size) )

# 학습 시 사용하는 변수
max_iters = data_size # (batch_size * time_size)
time_idx = 0
total_loss = 0
loss_count = 0
ppl_list = []


# 모델 생성
model = SimpleRnnlm(vocab_size, wordvec_size, hidden_size)
optimizer = SGD(lr)

# 각 미니배치에서 샘플을 읽기 시작 위치를 계산
jump = (corpus_size - 1) # batch_size
offsets = [i*jump for i in range(batch_size)]

for epoch in range(max_epoch):
    for iter in range(max_iters):
        # 미니배치 흭득
        batch_x = np.empty((batch_size, time_size), dtype='i')
        batch_t = np.empty((batch_size, time_size), dtype='i')
        for t in range(time_size):
            for i, offset in enumerate(offsets):
                batch_x[i, t] = xs[(offset + time_idx) %data_size]
                batch_t[i, t] = ts[(offset + time_idx) %data_size]
            time_idx += 1
            
        # 기울기를 구하여 매개변수 갱신
        loss = model.forward(batch_x, batch_t)
        model.backward()
        optimizer.update(model.params, model.grads)
        total_loss += loss
        loss_count +=1
        
    # 에폭마다 퍼블렉서티 평가
    ppl = np.exp(total_loss / loss_count)
    print('|| 에폭  %d || 퍼블렉서티 %.2f' %(epoch+1, ppl))
    ppl_list.append(float(ppl))
    total_loss, loss_count = 0,0 

[그림3] RNNLM 학습 결과

 

과정

  1. 미니배치를 '순차적으로' 만들기
  2. 모델의 순전파와 역전파를 호출
  3. 옵티마이저로 가중치 갱신
  4. 퍼블렉서티를 구하기

 

 

정리

 

 

RNN(순환 신경망)

  • RNN은 데이터를 순환시킴으로써 과거에서 현재, 그리고 미래로 데이터를 계속해서 흘려보낸다.
  • RNN 계층 내부에는 '은닉 상태'를 기억하는 능력이 추가
  • 언어 모델은 단어 시퀀스에 확률을 부여한다.
  • 조건부 언어 모델은 지금까지의 단어 시퀀스로부터 다음에 출현할 단어의 확률을 계산해준다.
  • RNN을 대체하는 새로운 계층들(LSTM, GRU 계층)

 

 

 

출처 : 밑바닥부터 시작하는 딥러닝2

https://www.hanbit.co.kr/store/books/look.php?p_code=B8950212853

 

밑바닥부터 시작하는 딥러닝 2

이 책은 『밑바닥부터 시작하는 딥러닝』에서 다루지 못했던 순환 신경망(RNN)을 자연어 처리와 시계열 데이터 처리에 사용하는 딥러닝 기술에 초점을 맞춰 살펴본다. 8장 구성으로 전체를 하나

www.hanbit.co.kr

 

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기