티스토리 뷰
https://www.tensorflow.org/tutorials/keras/text_classification?hl=ko
영화 리뷰를 사용한 텍스트 분류 | TensorFlow Core
도움말 Kaggle에 TensorFlow과 그레이트 배리어 리프 (Great Barrier Reef)를 보호하기 도전에 참여 영화 리뷰를 사용한 텍스트 분류 Note: 이 문서는 텐서플로 커뮤니티에서 번역했습니다. 커뮤니티 번역
www.tensorflow.org
1. 데이터셋
텐서플로우에서 제공하는 IMDB 데이터셋[단어 시퀀스가 미리 전처리되어 정수 시퀀스로 변환된 데이터셋]
=> 각 정수는 어휘 사전에 있는 특정 단어를 의미함
imdb = keras.datasets.imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
훈련 데이터에서 가장 많이 등장하는 상위 10,000개의 단어를 선택해서 거의 등장하지 앟는 단어는 처리하지 않음으로써 성능을 높여줍니다. => NUM_WORD=10000개로 선택(사전에 등록된 단어를 10000개로 한다)
[입력데이터셋과 결과로 나와야하는 label데이터셋을 설정]
train_data : 250000개의 정수 배열(각각 정수배열로 구성이 되어있는데 이때 데이터 하나마다 길이가 단어의 개수가 다르기때문에 길이가 다름) // train_label : 25000개로 1 or 0 으로 구성(긍정 혹은 부정으로 구성)
정수를 단어로 다시 변환해봅시다 [신경망의 훈련에는 상관없으며 그저 단어를 뽑아보고 싶을 때 사용]
word_index => imdb에서 get_word_index()를 word_index로 받아서 해당 단어가 key로, 해당 단어에 대한 정수를 value로 가지고 있는 딕셔너리를 사용하여 변환하도록 합시다.
=> decode_review
reverse_word_index에 word_index에 담긴 딕셔너리의 key값과 value값을 swap해서 저장하게 된다면 딕셔너리의 key(숫자 = 정수)에 접근해서 word(value)를 사용할 수 있게 된다. 이때, 이것을 for문을 사용해서 text 배열안의 word들을 다 찾아낼 수 있고 이것을 join하게 되면 text 배열 전체를 다 decoding이 가능하다 => decode_review함수에 대한 설명..
def decode_review(text):
return ' '.join([reverse_word_index.get(i, '?') for i in text])
이제 단어들을 encoding해서 신경망에 주입하자.
방법1. one-hot-encoding을 통해서 10,000개의 단어의 사용을 처리한다면?
리뷰 데이터에 저장된 정수형 배열의 각 단어들을 one-hot encoding을 사용해서 그 단어가 들어갔다면 1로 아니라면 0으로 벡터를 변환해보자.
만약 하나의 리뷰의 단어 개수가 (nun_reviews)이라면 각각 one-hot encoding되어 단어들을 신경망에 주입하기 위한 형태로 변형이 가능합니다. -> 이때, 단어마다 word 종류 수 10000 크기의 배열이 필요하고 따라서 최종 num_word * num_review 사이즈의 행렬이 필요합니다.
단점 : 메모리를 많이 사용함, 단어간의 유사도를 확인할 수 없음., 이러한 희소표현 데이터들은 사전의 단어가(num_word)가 커지면 그에따라서 차원이 증가된다는 점이 있어서 잘 사용하지 않는 것이 좋음
뿐만 아니라 단어의 의미를 담지 못한다는 큰 단점을 지닌다는 것도 알아놓기
[+ 추가) 희소표현을 대신해 밀집표현(정해진 사이즈만큼의 배열을 만들어 10000차원이 아니라 해당 사이즈만큼의 차원으로 하나의 단어를 표현하게 되는 것) or word embedding을 할 수 있습니다]
방법2. padding을 통해서 max_lenght 크기의 배열에 리뷰의 단어들이 가지는 정수값을 넣는다면?
padding을 사용하는 이유는 데이터의 길이가 모두 다르기에 가장 긴 데이터의 길이에 모든 리뷰들을 맞춰서 하나의 행렬로 보게끔해서 병렬 처리를 하기 위해서임. => 확실히 하나의 리뷰를 하나의 배열로 처리한다는 점에서 각 리뷰의 한 단어를 one-hot encoding하는 것보다 메모리를 확 줄일 수 있다는 장점이 있음.
https://wikidocs.net/83544
07) 패딩(Padding)
자연어 처리를 하다보면 각 문장(또는 문서)은 서로 길이가 다를 수 있습니다. 그런데 기계는 길이가 전부 동일한 문서들에 대해서는 하나의 행렬로 보고, 한꺼번에 묶어서 처리 ...
wikidocs.net
train_data = keras.preprocessing.sequence.pad_sequences(train_data,
value=word_index["<PAD>"],
padding='post',
maxlen=256)
test_data = keras.preprocessing.sequence.pad_sequences(test_data,
value=word_index["<PAD>"],
padding='post',
maxlen=256)
=> 이때, padding값은 원래 배열크기에 지정한 value값을 앞에서부터 채우고 리뷰의 word를 뒤에서부터 앞으로 채워나가는 형태인데, 앞에서부터 word를 채우고 싶다면 'post'를 padding값으로 주어서 처리함;
=> 이때, value = word_index["pad"]라는 것은 word_index 딕셔너리의 pad의 value값이 0이기때문에 패딩할 때 빈 공간을 '0'으로 채운다는 것을 의미함.
=> 이때, maxlen를 통해서 각 리뷰의 len를 maxlen로 고정함.
[ 1 14 22 16 43 530 973 1622 1385 65 458 4468 66 3941
4 173 36 256 5 25 100 43 838 112 50 670 2 9
35 480 284 5 150 4 172 112 167 2 336 385 39 4
172 4536 1111 17 546 38 13 447 4 192 50 16 6 147
2025 19 14 22 4 1920 4613 469 4 22 71 87 12 16
43 530 38 76 15 13 1247 4 22 17 515 17 12 16
626 18 2 5 62 386 12 8 316 8 106 5 4 2223
5244 16 480 66 3785 33 4 130 12 16 38 619 5 25
124 51 36 135 48 25 1415 33 6 22 12 215 28 77
52 5 14 407 16 82 2 8 4 107 117 5952 15 256
4 2 7 3766 5 723 36 71 43 530 476 26 400 317
46 7 4 2 1029 13 104 88 4 381 15 297 98 32
2071 56 26 141 6 194 7486 18 4 226 22 21 134 476
26 480 5 144 30 5535 18 51 36 28 224 92 25 104
4 226 65 16 38 1334 88 12 16 283 5 16 4472 113
103 32 15 16 5345 19 178 32 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0]
train_data[0]을 패딩후 출력한 결과이며 앞에 들어있는 정수부터 리뷰의 text라고 보면 되고 0이 시작될 때부터는 리뷰가 없다고 보면 된다.
2. 모델구성
이전과 같이 모델 구성에는 1. 신경망 층 만들기 2. 데이터 훈련하며 parameter를 조정하기 이렇게 두가지로 나뉜다고 생각하면 됩니다.
1. 신경망 층 만들기
=> keras를 활용해 layer를 생성할 수 있습니다.
어떤 활성화함수를 설정해야하며 몇개의 은닉 유닛[각 층마다의 node개수]을 사용해야하는지 설정해야하합니다.
우리는 리뷰 하나당 padding되어 저장된 것을 알고 있습니다. 그리고 결과로 이러한 리뷰가 긍정인지 부정인지를 뽑아내는 이진분류 모델을 구성해야합니다.
이진분류에는 주로 마지막 Dense층에 activation함수로 sigmoid함수를 사용합니다. 그전에는 흔히 신경망 분류에 사용되는 relu함수를 activation함수로 사용할 것입니다. 그리고 그 전에는 pooling을 통해서 각 리뷰에 대한 저장된 벡터들의 평균을 뽑아내서 고정된 길이의 출력 벡터로 반환힙니다. 그 전에는 가장 첫 신경망 층을 Embedding하는데 사용하며 Embedding을 위해서는 새로운 차원이 생성됩니다.
이때, Embedding은 왜 하는걸까요?
단어 Embedding 방법을 사용해서 각 단어에 해당하는 벡터를 만드는 과정을 진행합니다. 즉, 각 단어 10000개를 하나씩 16 size를 가지는 배열마다 특정 실수값을 가지게해서 각단어를 벡터화해서 저장하는 것입니다. 10000개의 단어 하나당 16사이즈의 배열을 가지고 있게끔하여 단어를 분류모델을 적용하기 쉽게끔 만드는 것입니다.
=> 그렇게 되면 차원이 하나 증가하겠죠?
=> batch, sequece였던 차원이 batch, sequence, embedding으로 3차원으로 증가하게 됩니다.
=> Embedding 적용 후 pooling을 통해서 하나의 리뷰를(하나의 데이터를) 모두 하나의 값인 average로 뽑아내어 전체데이터를 1차원화 시켜 전체를 2차원으로 만들어 다음으로 넘기는 과정을 진행합니다.
따라서 모델구성은 다음과 같습니다.
vocab_size = 10000
model = keras.Sequential()
model.add(keras.layers.Embedding(vocab_size, 16, input_shape=(None,)))
model.add(keras.layers.GlobalAveragePooling1D())
model.add(keras.layers.Dense(16, activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid'))
2. parameter 조정[COMPILE -> FITTING]
parameter를 조정한다는 것은 오류를 줄이는 방향으로 가중치를 업그레이드 시키며 정확도를 높이며 모델을 생성한다는 것을 의미합니다.
모델에 대한 fit전에 손실함수, 옵티마이저를 설정해야합니다. 이진분류 모델일 때는 sigmoid함수를 사용합니다. 이진분류에서는 binary_crossentropy를 선택해서 확률분포 간의 차이=거리를 측정합니다.
binary_crossentropy => loss function으로 이진분류에서 채택
y값의 결과가 sigamoid 활성화함수를 통해서 확률값의 결과로 0-1사이의 값으로 나올 때 0에 가까우면 label중 false, 1에 가까우면 true를 반환합니다. 이때, true일때, 얼마나 그 확률값이 1과 얼마나 떨어져있냐를 비교를 하는 그 함수가 binary_crossentory이며 값이 클수록 손실L이 커지며 확률값이 0에 가까워질수록 L은 무한대로 가까워지게 되는 형태르를 띕니다.
http://www.gisdeveloper.co.kr/?p=8521
이진분류(Binary Classification)에 대한 Cross Entropy Error – GIS Developer
현재 딥러닝에서 분류에 대해 가장 흔히 사용되는 손실함수는 Cross Entropy Error(CEE)입니다. CEE를 비롯하여 다른 손실함수를 간단이 정리하는 글은 아래와 같습니다. 손실함수(Loss Function) 다시, CEE
www.gisdeveloper.co.kr
를 보면 이해가 쉽습니다.
손실함수를 줄이고 가중치를 최적화시킬 함수인 optimizer의 경우 ADAM을 사용합니다.
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
이후, fit을 시키며 parameter를 정의한 optimizer와 loss fuction, epoch를 토대로 조정하여 최적의 모델로 만드는 시도를 합니다.
history = model.fit(partial_x_train,
partial_y_train,
epochs=40,
batch_size=512,
validation_data=(x_val, y_val),
verbose=1)
모델을 fitting할 때는 당연히 training data와 training dataset에 대한 label 즉 긍정, 부정 여부를 넣어줘야합니다.
또한 여기서는 batch_size를 512개로하여 trianing dataset에서 무작위로 512개를 선택해서 학습을 40번 시킵니다.
* 여기서는 검증데이터셋을 설정하였습니다.
x_val = train_data[:10000]
partial_x_train = train_data[10000:]
y_val = train_labels[:10000]
partial_y_train = train_labels[10000:]
25000개의 train_data에서 10000개를 training 과정에 있어서 유효성 검사를 합니다. 만약 training 과정에서 validation data의 정확도가 낮아지는 순간이 발생한다면 이것은 training model이 과적합했다는 것을 의미합니다. 그 순간 전까지만 데이터를 학습시키고 학습을 멈추는 방법을 사용해서 모델의 testing과정에서 성능(=정확도)를 높일 수 있습니다.
3,. Evaluate
모델을 test data를 통해서 평가하는 과정을 거칠 수 있습니다. 그 결과 40번 parameter를 조정하며 학습한 결과는
[0.3335219919681549, 0.8722400069236755]
으로 loss가 0.33이며 정확도가 0.87인 모델임을 알 수 있습니다.
validation data를 활용해서 분석을 해보면 유효성검사 data의 정확도가 증가하다가 어느한순간 (20번째 epoch)에서 낮아지는 것을 확인할 수 있는데, 거기까지 학습하는 모델을 만든다면 과적합을 줄일 수 있을 것이라고 예측됩니다.
'데이터분석 및 인공지능' 카테고리의 다른 글
기본 이미지 분류[기본분류] (0) | 2021.12.10 |
---|---|
1. 의류 이미지 분류 (0) | 2021.11.03 |
강화학습 (0) | 2021.06.28 |
순환 신경망을 활용한 문자열 생성 (0) | 2021.03.29 |
csv파일을 활용한 데이터처리 (0) | 2021.03.29 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 백준 4963
- 소프트웨어공학설계
- c++덱
- 13886
- DRF 회원관리
- 딥러닝입문
- 영화 리뷰 긍정 부정 분류
- 11053 백준
- mm1queue
- 4963 섬의개수
- 백준 15650 파이썬
- LAMBDA
- 시뮬레이션 c
- 스택 파이썬
- 효율적인방법찾기
- 모듈 사용법
- 백준 11053 파이썬
- CSMA/CD란?
- 10866 백준
- 기사작성 대외활동
- 백준 10866
- 백트래킹(1)
- 온라인프로필 만들기
- CREATE ASSERTION
- 백준 숫자놀이
- 기본 텍스트 분류
- 코딩월드뉴스
- 핀테크 트렌드
- stack 컨테이너
- 파이썬 알아두면 유용
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함