관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

텍스트를 위한 인공 신경망 3 - 순환 신경망으로 IMDB 리뷰 분류하기 1 : IMDB 리뷰 데이터셋과 순환 신경망 만들기 본문

인공지능/딥러닝

텍스트를 위한 인공 신경망 3 - 순환 신경망으로 IMDB 리뷰 분류하기 1 : IMDB 리뷰 데이터셋과 순환 신경망 만들기

huenuri 2024. 12. 18. 07:46

이번 시간에는 텐서플로를 활용해서 실습을 진행해보려고 한다.

 

 

시작하기 전에

앞 절에서 순환 신경망의 작동 원리를 살펴보았다. 이번 절에서는 대표적인 신경망 문제인 IMDB 리뷰 데이터셋을 사용해 가장 간단한 순환 신경망 모델을 훈련해 보겠다.

이 데이터셋을 두 가지 방법으로 변경하여 순환 신경망에 주입해 보겠다. 하나는 원-핫 인코딩이고 또 다른 하나는 단어 임베딩이다. 이 두 가지 방법의 차이점에 대해 설명하고 순환 신경망을 만들 때 고려해야 할 점을 알아보겠다.

그럼 먼저 이 절에서 사용할 IMDB 리뷰 데이터셋을 적재해 보겠다.


 

 

 

 

IMDB 리뷰 데이터셋

IMDB 리뷰 데이터셋은 유명한 인터넷 영화 데이터베이스인 imdb.com에서 수집한 리뷰를 감상평에 따라 긍정과 부정으로 분류해 놓은 데이터셋이다. 총 50,000개의 샘플로 이루어져 있고 훈련 데이터와 테스트 데이터에 각각 25,000개씩 나누어져 있다.

 

 

 

 

 

토근에 할당하는 정수 중 몇 개는 특정한 용도로 예약되어 있는 경우가 많다. 예를 들어 0은 패딩, 1은 문장의 시작, 2는 어휘 사전에 없는 토큰을 나타낸다.

 


 

 

 

 

실제 IMDB 리뷰 데이터셋은 영어로 된 문장이지만 편리하게도 텐서플로에는 이미 정수로 바꾼 데이터가 포함되어 있다. tensorflow, keras, datasets 패키지 아래 imdb 모듈을 임포트하여 이 데이터를 적재해 보겠다. 여기서는 전체 데이터셋에서 가장 자주 등장하는 단어 300개만 사용하겠다. 이렇게 하기 위해 load_data() 함수의 num_words 개개변수를 300으로 지정한다.

 

 

 

 

 

IMDB 리뷰 텍스트의 길기는 제각각이다. 따라서 고정 크기의 2차원 배열에 담기보다는 리뷰마다 별도의 파이썬 리스트로 담아야 메모리를 효율적으로 사용할 수 있다.

 

이 데이터는 개별 리뷰를 담은 파이썬 객체로 이루어진 넘파이 배열이다. 넘파이 배열은 정수나 실수 외에도 파이썬 객체를 담을 수 있다. 

 

 

이렇게 리뷰마다 각각 길이가 다르다. 여기서 하나의 리뷰가 하나의 샘플이 된다. 서로 다른 길이의 샘플을 어떻게 신경망에 전달하는지 조금 후에 살펴보겠다. 

 

IMDB 리뷰 데이터는 이미 정수로 변환되어 있다. 앞서 num_words=300으로지정했기 때문에 어휘 사전에는 300개의 단어만 들어가 있다. 따라서 어휘 사전에 없는 단어는 모두 2로 표시되어 나타난다.

 

 

해결할 문제는 리뷰가 긍정인지 부정인지를 판단하는 것이다. 그러면 이진 분류 문제로 볼 수 있으므로 타깃값이 0(부정)과 1(긍정)로 나누어진다.


 

 

 

 

 

데이터를 더 살펴보기 전에 훈련 세트에서 검증 세트를 떼어 놓도록 한다. 원래 훈련 세트의 크기가 25,000개였으므로 20%를 검증 세트로 떼어 놓으면 훈련 세트의 크기는 20,000개로 줄어들 것이다.

 

 

이제 훈련 세트에 대해 몇 가지 조사를 해보겠다. 먼저 각 리뷰의 길이를 계산해 넘파이 배열에 담겠다. 이렇게 하는 이유는 평균적인 리뷰의 길이와 가장 짧은 리뷰의 길이 그리고 가장 긴 리뷰의 길이를 확인하고 싶기 때문이다.

이를 위해 넘파이 리스트 내포를 사용해 train_input의 원소를 순회하면서 길이를 재도록 하겠다.

 

 

 

 

리뷰의 평균 단어 개수는 239개이고 중간값이 178인 것으로 보아, 이 리뷰 길이의 데이터는 한쪽에 치우친 분포를 보일 것 같다.

 

 

역시 한쪽으로 치우쳤다. 대부분 리뷰의 길이는 300 미만이다. 평균이 중간값보다 높은 이유는 오른쪽 끝에 아주 큰 데이터가 있기 때문이다. 어떤 리뷰는 100개의 단어가 넘는다.

이 예제에서는 중간값보다 훨씬 짧은 100개의 단어만 사용하겠다. 하지만 여전히 100개의 단어보다 작은 리뷰가 있다. 이런 리뷰들은 길이를 100에 맞추기 위해 패딩이 필요하다 보통 패딩을 나타내는 토큰으로 0을 사용한다.


 

 

 

 

 

수동으로 훈련 세트에 있는 20,000개의 리뷰를 순회하면서 길이가 100이 되도록 잘라내거나 0으로 패딩할 수 있다. 

 

 

 

길이를 100으로 맞춘 train_seq는 이제 2차원 배열이 되었다.

 

 

 

이 샘플의 앞뒤에 패딩값 0이 없는 것으로 보아 100보다는 길었을 것 같다. 

 

 

 

음수 인덱스와 슬라이싱을 사용해 train_input[0]에 있는 마지막 10개의 토큰을 출력했다. train_seq[0]의 출력값과 비교하면 정확히 일치한다.

 

pad_sequences() 함수는 기본적으로 maxlen보다 긴 시퀀스의 앞부분을 자른다. 이렇게 하는 이유는 일반적으로 시퀀스의 뒷부분의 정보가 더 유용하리라 기대하기 때문이다.

 

 

원한다면 pad_sequences() 함수의 padding 매개변수의 기본값인 pre를 post로 바꾸면 샘플의 뒷부분에 패딩을 추가할 수 있다.


 

 

 

 

순환 신경망 만들기

케라스는 여러 종류의 순환 신경층 클래스를 제공한다. 그중에 가장 간단한 것은 SimpleRNN 클래스이다. IMDB 리뷰 분류 문제는 이진 분류이므로 마지막 출력층은 1개의 뉴런을 가지고 시그모이드 활성화 함수를 사용해야 한다. 먼저 케라스의 Sequential 클래스로 만든 신경망 코드를 살펴보겠다.

 

 

 


 

 

 

 

 

 

 

 

 

 

처음 12개 원소를 출력해 보면 열한 번째 원소가 1인 것을 확인할 수 있다. 

 

 

 

 

 


 

 

 

 

 

 


 

 

 

 

학습을 마치고

실습과 함께 오늘의 첫 번째 학습을 마쳐본다. 순환 신경망을 훈련하는 것부터는 다음 포스트에 이어서 학습해 보겠다. 순환 신경망의 구조에 대해 이제 조금은 알 것 같다.

이전에 학습했던 딥러닝 공부가 많이 도움이 되었다.