본문 바로가기
Keras Deep Learning

RNN(순환신경망) 문장을 판별하는 LSTM 케라스로 구현 실습

by yj.yoon 2020. 8. 25.

개발 환경 : pycharm-community-2020.2 (무료 에디션)

Anaconda, python3.7, Windows 10


순환신경망은 계층의 출력이 순환하는 인공신경망이다. 순환방식은 은닉 계층의 결과가 다음 계층으로 넘어가고 다시 자기 계층으로 다시 돌아온다.

 

RNN은 신호를 순환하여 시계열 신호와 같이 상호 관계가 있는 신호를 처리하는 인공신경망이다. 그런데 이런 단순한 방식으로 구현하면 경우에 따라 학습이 제대로 이루어지지 않는다. - 출력된 신호가 계속 순환하면 활성화 함수를 반복적으로 거치게 되어 경사값을 구하기가 힘들다.

 

 

가장 많이 사용되는 RNN 방식은 LSTM (long-term shot term memory)이다.

이 글에서는 LSTM을 이용하여 문장의 의미를 이해하는 예제를 실습한다.

 

 

1. 라이브러리 임포트

RNN에 필요한 케라스 클래스들을 불러온다.

from keras.preprocessing import sequence
from keras.datasets import imdb
from keras import layers, models

sequence는 preprocessing이 제공하는 서브패키지이다.

Dense는 완전 연결 계층을 만드는 클래스

 

 

2. 데이터 준비

케라스가 제공하는 공개 데이터인 IMDB를 사용한다. IMDB는 25,000건의 영화평과 이진화된 평점 정보(추천 =1, 비추 =0)를 담고 있다. - 평점 정보는 별점이 많은 경우 긍정, 아닌 경우는 부정으로 나눠져 있는 정보다.

 

클래스를 선언하고, 데이터셋을 불러오기 !

max_features : 최대 단어 빈도

maxlen : 최대 길이

class Data:
    def __init__(self, max_features=20000, maxlen=80):
        (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)

 

 

데이터셋에 들어 있는 문장들은 길이가 다르기 때문에, LSTM이 처리하기 적합하도록 길이를 통일하는 작업을 진행한다.

문장길이가 maxlen 보다 작으면 부족한 부분을 0으로 채운다. - pad_sequences() 를 이용

        x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
        x_test = sequence.pad_sequences(x_test, maxlen=maxlen)

 

 

3. 모델링

모델링을 위한 클래스 선언

models.Model 을 상속해서 모델링을 만든다. 

class RNN_LSTM(models.Model):
    def __init__(self, max_features, maxlen):

 

입력층을 만들고, 다음으로 임베딩 계층을 포함하게 한다. 임베딩 후 출력 벡터 크기를 128로 설정했다.

입력에 각 샘플은 80개의 원소로 된 1차 신호열이었지만, 임베딩을 통과하면서 각 단어가 128의 길이를 가지는 벡터로 바뀌면서 입력데이터 모양이 80 * 128로 변경된다.

	x = layers.Input((maxlen,))
	h = layers.Embedding(max_features, 128)(x)
	h = layers.LSTM(128, dropout=0.2, recurrent_dropout=0.2)(h)  #노드 128개로 구성됨

 

출력을 시그모이드 활성화 함수로 구성된 출력 노드 하나로 구성한다.

	y = layers.Dense(1, activation='sigmoid')(h)

 

손실함수와 최적화 함수를 아규먼트로 지정하여 모델을 컴파일 한다.

이진 판별값(0, 1)을 출력으로 다루므로 손실 함수는 binary_crossentropy, 최적화 함수를 adam으로 설정

epochs 마다 손실과 정확도를 구하기 때문에 metrics=['accuracy'

	self.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy'])

 

 

4. 학습 및 성능 평가

글에는 아주 다양한 단어가 무작위로 사용되지만, 빈도 순위가 20,000등 안에 드는 단어까지 취급한다.

max_features : 단어의 최대 수

maxlen : 한 문장의 최대 단어 수

class Machine:
    def __init__(self,
                 max_features=20000,
                 maxlen=80):
        self.data = Data(max_features, maxlen)
        self.model = RNN_LSTM(max_features, maxlen)

 

학습과 평가를 수행하는 run() 멤버 함수를 만든다.

    def run(self, epochs=3, batch_size=32):
        data = self.data
        model = self.model
        print('Training stage')
        print('==============')
        model.fit(data.x_train, data.y_train,
                  batch_size=batch_size,
                  epochs=epochs,
                  validation_data=(data.x_test, data.y_test))

 

학습이 얼마나 잘 되었는지 평가 데이터를 이용해 확인해본다. - 검증 데이터와 학습 데이터를 같은 것으로 사용했다.

	score, acc = model.evaluate(data.x_test, data.y_test, batch_size=batch_size)
	print('Test performance: accuracy={0}, loss={1}'.format(acc, score))

 

 

 

전체 코드

#라이브러리 임포트
from keras.preprocessing import sequence
from keras.datasets import imdb
from keras import layers, models

#데이터 준비
class Data:
    def __init__(self, max_features=20000, maxlen=80):
        (x_train, y_train), (x_test, y_test) = imdb.load_data(
            num_words=max_features)
        x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
        x_test = sequence.pad_sequences(x_test, maxlen=maxlen)

        self.x_train, self.y_train = x_train, y_train
        self.x_test, self.y_test = x_test, y_test

# 모델링
class RNN_LSTM(models.Model):
    def __init__(self, max_features, maxlen):
        x = layers.Input((maxlen,))
        h = layers.Embedding(max_features, 128)(x)
        h = layers.LSTM(128, dropout=0.2, recurrent_dropout=0.2)(h)
        y = layers.Dense(1, activation='sigmoid')(h)
        super().__init__(x, y)

        self.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

# 학습 및 성능 평가
class Machine:
    def __init__(self,
                 max_features=20000,
                 maxlen=80):
        self.data = Data(max_features, maxlen)
        self.model = RNN_LSTM(max_features, maxlen)

    def run(self, epochs=3, batch_size=32):
        data = self.data
        model = self.model
        print('Training stage')
        print('==============')
        model.fit(data.x_train, data.y_train,
                  batch_size=batch_size,
                  epochs=epochs,
                  validation_data=(data.x_test, data.y_test))

        score, acc = model.evaluate(data.x_test, data.y_test, batch_size=batch_size)
        print('Test performance: accuracy={0}, loss={1}'.format(acc, score))

# 실행
def main():
    m = Machine()
    m.run()


if __name__ == '__main__':
    main()

 

 


참고 : 3분 딥러닝 케라스맛 (김성진 지음)