Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Tags
more
Archives
Today
Total
관리 메뉴

archive

[교재] 9. 텍스트를 위한 인공 신경망 본문

ML_AI/24_여름방학 인공지능 스터디

[교재] 9. 텍스트를 위한 인공 신경망

안정민 2024. 7. 23. 21:00

9-1 순차데이터와 순환 신경망

1. 순차데이터

- 순차데이터 (sequential data) 는 텍스트나 시계열 데이터(time series data)와 같이 순서에 의미가 있는 데이터를 말함

- 즉, 데이터의 입력 순서가 중요한 데이터가 순차데이터 -> 데이터의 순서를 유지하며 신경망에 주입해야 함

- 따라서 순차데이터를 다룰 때는 이전에 입력한 데이터를 기억하는 기능이 필요

 

-순환신경망 : 완전 연결 신경망에 이전 데이터의 처리 흐름을 고려한 순환하는 고리 하나만 추가하면 됨

-즉, 뉴런의 출력이 자기자신으로 전달 (재사용)

-그 다음 데이터를 처리할 때에는 첫 번째 샘플을 처리하고 난, 해당 노드에 대한 정보가 다분히 들어있는 정보가 추가된 노드를 통해 처리가 됨, 즉 앞에서 만든 이전 노드를 사용해 출력을 만들어내는 것

-이와 같이 순환 신경망에는 '이전 샘플에 대한 기억을 가지고 있다' 라고 이야기하는데, 이렇게 샘플을 처리하는 하나의 단계를 타임 스탭(time step)이라고 이야기한다.

- 순환신경망은 이전 타임스텝의 샘플을 기억, 타임 스텝이 오래될 수록 순환되는 정보는 희미해짐

- 즉 현재의 노드에는 가장 최근에 순환한 샘플의 정보가 가장 선명히 남아있게 됨

 

- 하나의 셀에는 여러 뉴런이 있지만 완전 연결 신경망과 다르게 뉴런을 모두 표시하지 않고 하나의 셀로 층을 표현
- 또 이 셀의 출력을 은닉 상태 (hidden state) 라고 부름

- 탄젠트 함수 (tahn)를 활성화 함수로 사용 -> 시그모이드 (0~1) 와 달리 tahn은 -1과 1 사이의 값

 

wx는 입력에 대한 가중치, wh는 이전 타임스텝의 은닉 상태에 대한 가중치

 

- 순환 신경망의 뉴런은 가중치가 2 개임

- ( 입력 * 입력에 대한 가중치 ) + (이전 타임스텝의 은닉 상태 * 이전 타임스텝의 은닉 상태에 대한 가중치)

- 셀은 입력과 이전 타임 스텝의 은닉 상태를 사용하여 현재 타임 스텝의 은닉 상태를 만든다

-여기서 알 수 있는 점은 모든 타임 스텝에서 사용되는 가중치 wh는 하나라는 점이다

 

  피드 포워드 신경망 (feed forward neural network) 순환 신경망 (recurrent neural network)
정의 입력 데이터의 흐름이 앞으로만 전달되는 신경망  일반적인 완전 연결 신경망과 비슷하나, 이전 데이터의 처리 흐름을 순환하는 고리 하나만 추가하면 됩니다.
예시 완전 연결 신경망, 합성곱 신경망  
특징 - 하나의 샘플(배치) 를 사용해 정방향 계산을 수행하고 나면 그 샘플은 버려지고 다음 샘플을 처리할 때 재사용하지 않음 - 층의 출력을 다음 타임 스텝에 재사용
- 하나의 셀에는 여러 뉴런이 있지만 완전 연결 신경망과 다르게 뉴런을 모두 표시하지 않고 하나의 셀로 층을 표현
- 또 이 셀의 출력을 은닉 상태 (hidden state) 라고 부름

- 순환신경망은 이전 타임스텝의 샘플을 기억, 타임 스텝이 오래될 수록 순환되는 정보는 희미해짐
층의
명칭
층, 레이어 (layer) 셀 (cell)
활성화 함수 시그모이드, 소프트맥스 탄젠트 함수 (tahn)

 

 

2. 셀의 가중치와 입출력

- 순환 신경망의 셀에서 필요한 가중치 크기 계산

 

- wx의 크기

- 입력층과 순환층의 뉴런이 모두 연결되기 때문에 가중치 wx의 크기는 12개가 된다 (완전 연결 신경망의 연결과 동일)

 

-순환층은 일반적으로 샘플마다 2개의 차원을 가짐, 보통 하나의 샘플을 하나의 시퀀스(sequence)라고 말함

-하나의 시퀀스 안에는 여러 개의 아이템이 들어있음, 아이템의 길이가 타임스텝의 길이가 됨

- 순환층의 다음 타임스텝에 재사용되는 은닉 상태를 위한 가중치 wh의 크기

- 그러나 사실 순환층은 기본적으로 마지막 타임스텝의 은닉 상태만 출력으로 내보낸다, 모든 타임스텝에서 출력을 만드는 것이 아님

- 마치 입력된 시퀀스 길이를 모두 읽어서 정보를 마지막 은닉 상태에 압축하여 전달하는 것처럼 볼 수 있음

- 즉, 순환 신경망이 정보를 기억하는 메모리를 가짐

- 이러한 이유로 순환 신경망이 순차데이터에 잘 맞음

- 나아가 위의 그림과 같이 순환 신경망도 완전 연결 신경망이나 합성곱 신경망처럼 여러 개의 층을 쌓을 수 있음

- 셀의 입력은 샘플마다 타임스텝과 단어 표현으로 이루어진 2차원 배열이어야 함

- 마지막 셀을 제외한 다른 모든 셀들은 모든 타임 스텝의 은닉 상태를 출력

- 첫 번째 셀은 모든 타임 스텝의 은닉 상태를 출력

- 두 번째 셀은 마지막 타임스텝의 은닉 상태만 출력

 

 

 

 

9-2 순환신경망으로 IMDB 리뷰 분류하기

1. IMDB 리뷰 데이터셋

- IMDB 리뷰 데이터셋은 영화 데이터베이스 imdb에서 수집한 리뷰를 감상평에 따라 긍정과 부정으로 분류한 데이터셋

**자연어처리 (NLP) : 컴퓨터를 사용해 인간의 언어를 처리하는 분야
**말뭉치(corpus) : 자연어처리 분야에서는 훈련 데이터를 종종 말뭉치라고 부른다

 

- 컴퓨터에서 처리하는 모든 것은 어떤 숫자 데이터이므로 텍스트 자체를 신경망에 전달 X

- 이미지는 정수 픽셀값으로 이루어져있기 때문에 특별한 변환이 필요 없음

- 텍스트 데이터의 경우 단어를 숫자 데이터로 바꾸기 위해, 데이터에 등장하는 단어마다 고유한 정수를 부여한다

ex) he (10) follows (11) the (12) cat.(13) He(10) loves(14) the (12) cat. (13)

- 부여된 정수값에는 의미나 크기와 관련이 없음

- 일반적으로 영어 문장은 모두 소문자로 바꾸고 구두점을 삭제한 다음 공백을 기준으로 분리

- 이렇게 분리된 단어를 토큰 (token)이라고 부름

- 하나의 샘플은 여러 개의 토큰으로 이루어져있고, 1개의 토큰이 하나의 타임 스텝에 해당한다.

-토큰에 할당하는 정수 중 몇 개는 특정한 용도 (패딩, 문장의 시작, 어휘사전에 없는 토큰 등)로 예약되어있는 경우도 있다

**어휘사전 : 훈련 세트에서 고유한 단어를 뽑아 만든 목록, 테스트세트 안에 어휘 사전에 없는 단어가 있다면 2로 변환하여 신경망 모델에 주입한다.

 

from tensorflow.keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=300)

 

- 전체 데이터셋에서 가장 자주 등장하는 단어 300개만 어휘 사전에서 임포트하기 위해 매개변수로 설정

- 어휘 사전에는 300개의 단어만 들어가 있기 때문에 어휘사전에 없는 단어는 모두 2로 표시된다.

-이진 분류 문제로 타깃 값은 0(부정)과 1(긍정)으로 나뉘게 된다

from sklearn.model_selection import train_test_split
import numpy as np

train_input, val_input, train_target, val_target = train_test_split(train_data, train_labels, test_size=0.2, random_state=42)

length = np.array([len(i) for i in train_data])
print(np.mean(length), np.std(length))

>>> 238.71364 176.49367364852034

 

- 리뷰의 평균 단어의 개수가 239개이고, 중간 값이 178인 것을 보아 이 리뷰 길이 데이터는 한쪽에 치우쳐진 분포일 가능성이 높음

-대부분의 리뷰 길이는 300 미만

-본문을 크기 100으로 청킹 -> 100개의 단어보다 작은 리뷰의 경우, 길이를 맞추기 위해 패딩이 필요함, 보통 패딩은 토큰 0으로 표현

- 케라스에서는 pad_sequence()라는 함수를 통해 패딩을 지원한다

from tensorflow.keras.preprocessing.sequence import pad_sequences
train_seq = pad_sequences(train_input, maxlen=100)
print(train_seq[0])

>>> [ 10 4 20 9 2 2 2 5 45 6 2 2 33 269 8 2 142 2 5 2 17 73 17 204 5 2 19 55 2 2 92 66 104 14 20 93 76 2 151 33 4 58 12 188 2 151 12 215 69 224 142 73 237 6 2 7 2 2 188 2 103 14 31 10 10 2 7 2 5 2 80 91 2 30 2 34 14 20 151 50 26 131 49 2 84 46 50 37 80 79 6 2 46 7 14 20 10 10 2 158]

 

-해당 샘플의 앞뒤에 패딩값 0이 없는 것으로 보아 100보다는 해당 리뷰의 길이가 길었을 것

 

print(train_input[0][-10:])

>>> [6 2 46 7 14 20 10 10 2 158]

 

-해당 값의 확인을 통해 샘플을 청킹할 때, 샘플의 앞부분이 잘렸을 것이라고 추측할 수 있다.

- pad_sequence() 함수는 기본으로 maxlen 보다 긴 시퀀스의 앞부분을 자른다.

- 이렇게 하는 이유는 일반적으로 시퀀스의 뒷부분의 정보가 더 유용할 것이라고 기대하기 때문이다

-리뷰의 경우 결정적인 소감을 리뷰의 끝에 얘기할 가능성이 높음

- 만약 시퀀스의 뒷부분을 잘라내고 싶다면 pad_sequence() 함수의 truncating 매개변수의 값을 디폴트인 pre가 아니라 post로 변경하면 된다.

 

 

2. 순환 신경망 만들기

from tensorflow import keras

model = keras.Sequential()
model.add(keras.layers.SimpleRNN(8, input_shape = (100,300)))
model.add(keras.layers.Dense(1, activation='sigmoid'))

- 첫 번째 차원이 100인 이유는  청킹 사이즈가 100이기 때문

-두 번째 차원이 300인 이유 ★

:토큰을 정수로 변환한 이 데이터를 신경망에 주입하면 큰 정수가 큰 활성화 출력을 만들어냄

:따라서 단순한 정수값을 신경망에 입력하기 위해서는 다른 방식을 찾아야 함

:크기 속성을 없애고 각 정수를 고유하게 표현 -> 원핫인코딩

 

--------100개의 단어열------------------ 하나의 단어가 하나의 열로 표현됨

0 1 0 ... 0 0
0 0 0 ... 0 0
1 0 0 ... 0 1
0 0 0 ... 1 0
0 0 0 ... 0 0
... ... ... ... ... ...
0 0 1 ... 0 0

 

: 세로가 300 -> load_data()에서 300개의 어휘사전 단어 개수를 지정, 고유한 단어 수는 300개

: 즉, 훈련 데이터에 포함될 수 있는 정수값의 버뮈는 0(패딩토큰) 부터 299까지, 이 범위를 원핫 인코딩으로 표현하기 위해서는 배열의 길이가 300이어야 함

 

- 케라스에서는 keras.utils 패키지 아래에 to_categorical() 함수를 통해 원핫인코딩을 지원한다.

- 정수 배열을 입력하면 자동으로 원핫인코딩 된 배열을 반환한다.

train_oh = keras.utils.to_categorical(train_seq)
val_oh = keras.utils.to_categorical(val_seq)

 

-위와 같이 만든 모델의 구조를 출력하면 다음과 같다

-SimpleRNN에 전달할 샘플의 크기는 (100, 300)이지만, 이 순환층은 마지막 타임스텝의 은닉 상태만 출력한다

- 이 떄문에 출력 크기가 순환층의 뉴런 개수와 동일한 8임을 확인 가능하다

 

3. 단어 임베딩을 사용하기

- 단어 임베딩 (word embedding) : 각 단어를 고정된 크기의 실수 벡터로 바꾸어주는 것

ex) cat 단어의 임베딩 벡터

0.2 0.1 1.3 0.8 0.2 0.4 1.1 0.9 0.2 0.1

 

- 이와 같은 단어 임베딩으로 만들어진 벡터는 원-핫 인코딩된 벡터보다 훨씬 의미있는 값으로 채워져 있기 때문에 자연어 처리에서 더 좋은 성능을 낸다

- keras.layer 패키지 아래의 Embedding 클래스로 임베딩 기능을 제공하고 있음

-이 클래스는 다른 층처럼 모델에 추가하면 처음에는 모든 벡터가 랜덤하게 초기화, 훈련을 통해 데이터에서 좋은 단어 임베딩을 학습하게 된다.

 

-단어 임베딩의 장점은 입력으로 정수 데이터를 받는다는 것

-즉, 원핫 인코딩으로 변경된 train_oh 배열이 아니라 train_seq 배열을 바로 사용 가능

-따라서 메모리를 훨씬 효율적으로 사용할 수 있게 된다

 

*** 실습 파일

9_2IMDB_리뷰_분류하기.ipynb
0.01MB