archive
[교재] 9. 텍스트를 위한 인공 신경망 본문
9-1 순차데이터와 순환 신경망
1. 순차데이터
- 순차데이터 (sequential data) 는 텍스트나 시계열 데이터(time series data)와 같이 순서에 의미가 있는 데이터를 말함
- 즉, 데이터의 입력 순서가 중요한 데이터가 순차데이터 -> 데이터의 순서를 유지하며 신경망에 주입해야 함
- 따라서 순차데이터를 다룰 때는 이전에 입력한 데이터를 기억하는 기능이 필요
-순환신경망 : 완전 연결 신경망에 이전 데이터의 처리 흐름을 고려한 순환하는 고리 하나만 추가하면 됨
-즉, 뉴런의 출력이 자기자신으로 전달 (재사용)
-그 다음 데이터를 처리할 때에는 첫 번째 샘플을 처리하고 난, 해당 노드에 대한 정보가 다분히 들어있는 정보가 추가된 노드를 통해 처리가 됨, 즉 앞에서 만든 이전 노드를 사용해 출력을 만들어내는 것
-이와 같이 순환 신경망에는 '이전 샘플에 대한 기억을 가지고 있다' 라고 이야기하는데, 이렇게 샘플을 처리하는 하나의 단계를 타임 스탭(time step)이라고 이야기한다.
- 순환신경망은 이전 타임스텝의 샘플을 기억, 타임 스텝이 오래될 수록 순환되는 정보는 희미해짐
- 즉 현재의 노드에는 가장 최근에 순환한 샘플의 정보가 가장 선명히 남아있게 됨
- 하나의 셀에는 여러 뉴런이 있지만 완전 연결 신경망과 다르게 뉴런을 모두 표시하지 않고 하나의 셀로 층을 표현
- 또 이 셀의 출력을 은닉 상태 (hidden state) 라고 부름
- 탄젠트 함수 (tahn)를 활성화 함수로 사용 -> 시그모이드 (0~1) 와 달리 tahn은 -1과 1 사이의 값
- 순환 신경망의 뉴런은 가중치가 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 배열을 바로 사용 가능
-따라서 메모리를 훨씬 효율적으로 사용할 수 있게 된다
*** 실습 파일
'ML_AI > 24_여름방학 인공지능 스터디' 카테고리의 다른 글
[논문 리뷰] Attention Is All You Need (0) | 2024.09.22 |
---|---|
[논문 리뷰] Deep Residual Learning for Image Recognition (0) | 2024.08.07 |
[교재] 5. 트리 알고리즘 (2) (0) | 2024.07.10 |
[교재] 5. 트리 알고리즘 (1) (0) | 2024.07.09 |
[교재] 3. 회귀 알고리즘과 모델 규제 (2) (0) | 2024.07.09 |