๐ก(1)ํธ์์๋ RNN์ ๋ํด์ ์์๋ดค์ต๋๋ค. ์ด ๊ธ์์๋ ์ด๋ฅผ ํ์ฉํด ๋ฌธ์๋ฅผ ๋ถ๋ฅํ๋ ๊ณผ์ ์ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ค์ต ๋ฐ์ดํฐ๋ก๋ NLTK ์ํ ๋ฆฌ๋ทฐ๋ฅผ ์ฌ์ฉํ๋๋ก ํ๊ฒ ์ต๋๋ค.
(1)ํธ ๋งํฌ : https://jungnerd.tistory.com/4
NLTK ์ํ ๋ฆฌ๋ทฐ ๊ฐ์ฑ ๋ถ์
์๋ ์๋ฒ ๋ฉ์ ์ํ ๋ฐ์ดํฐ ์ค๋น
from nltk.corpus import movie_reviews
fileids = movie_reviews.fileids() #movie review data์์ file id๋ฅผ ๊ฐ์ ธ์ด
reviews = [movie_reviews.raw(fileid) for fileid in fileids] #file id๋ฅผ ์ด์ฉํด raw text file์ ๊ฐ์ ธ์ด
categories = [movie_reviews.categories(fileid)[0] for fileid in fileids]
#file id๋ฅผ ์ด์ฉํด label๋ก ์ฌ์ฉํ category ์ฆ positive์ negative ์ ๋ณด๋ฅผ ์์๋๋ก ๊ฐ์ ธ์ด
print('Reviews count:', len(reviews))
print('Length of the first review:', len(reviews[0]))
print('Labels:', set(categories))
Reviews count: 2000
Length of the first review: 4043
Labels: {'neg', 'pos'}
๋จผ์ NLTK ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์์ ๋ฆฌ๋ทฐ๋ reviews์, ๊ธ์ ๋ถ์ ์ ๋ํ ๋ผ๋ฒจ์ categories์ ์ ์ฅํฉ๋๋ค.
๊ฒฐ๊ด๊ฐ์ ๋ณด๋ฉด, ์ด ๋ฆฌ๋ทฐ์ ๊ฐ์๋ 2,000๊ฐ์ด๊ณ ์ฒซ ๋ฒ์งธ ๋ฆฌ๋ทฐ๋ 4043๊ฐ์ ๋จ์ด๋ก ์ด๋ฃจ์ด์ ธ ์์์ ์ ์ ์์ต๋๋ค.
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
np.random.seed(7)
tf.random.set_seed(7)
max_words = 10000 #์ฌ์ฉํ ๋จ์ด์ ์
# ๋น๋๊ฐ ๋์ 10000๊ฐ์ ๋จ์ด๋ฅผ ์ ํํ๋๋ก ๊ฐ์ฒด ์์ฑ
tokenizer = Tokenizer(num_words=max_words, oov_token='UNK')
tokenizer.fit_on_texts(reviews) #๋จ์ด ์ธ๋ฑ์ค ๊ตฌ์ถ
#๋ง๋ค์ด์ง ๋จ์ด ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ๋ฌธ์๋ค์ ๋ณํ
X = tokenizer.texts_to_sequences(reviews)
print('Lengths of first 10 documents:', [len(doc) for doc in X[:10]])
Lengths of first 10 documents: [710, 240, 486, 479, 733, 671, 550, 584, 702, 776]
๋จผ์ Numpy์ Tensorflow๋ฅผ ์ํฌํธ ํฉ๋๋ค.
๋ค์์ RNN ๋ชจํ์ ์ผ๋ผ์ค๋ฅผ ์ด์ฉํด์ ๊ตฌ์ถํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ Keras๊ฐ ์ ๊ณตํ๋ ํ ํฌ๋์ด์ ๋ฅผ ์ฌ์ฉํด
RNN ๋ชจํ์ ์ ํฉํ ํํ๋ก ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ๋ณํํ๊ฒ ์ต๋๋ค.
Tokenizer ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋, num_words๋ฅผ ์ด์ฉํด์ ๋ชจํ์ ์ฌ์ฉํ ๋จ์ด ์๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์์๋ ์ฌ์ฉํ ๋จ์ด์ ์๋ฅผ 10,000๊ฐ๋ก ์ค์ ํ๊ฒ ์ต๋๋ค. ์ด๋, ์ค์ ๋ง๋ญ์น์ ์ฌ์ฉ๋ ๋จ์ด ์๊ฐ 10,000๊ฐ ๋ณด๋ค ํฐ ๊ฒฝ์ฐ์๋ ์ฌ์ ์ ์๋ ๋จ์ด๋ฅผ ๋นผ๊ณ ์ํ์ค๋ฅผ ์์ฑํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฐ ์ฌ์ ์ ์๋ ๋จ์ด๋ค์ ์๋ตํ๊ณ ์ถ์ง ์๋ค๋ฉด, oov_token์ ์ด์ฉํด ์ด ๋จ์ด๋ค์ ๋ณํํ ๋ฌธ์์ด์ ํ ๋นํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์๋ ์ฌ์ ์ ์๋ ๋จ์ด๋ค์ ๋ชจ๋ unknown์ ์ฝ์์ธ UNK๋ก ๋ณํ์ํค๊ฒ ์ต๋๋ค.
fit_on_texts๋ฅผ ์ํํ๋ฉด reviews์ ์๋ ๋จ์ด๋ค์ ๋ํด ๋จ์ด ์ธ๋ฑ์ค ์ฌ์ ์ด ์์ฑ๋ฉ๋๋ค.
๊ทธ ํ์ texts_to_sequence๋ฅผ ์ํํ๋ฉด ์ด ๋จ์ด ์ธ๋ฑ์ค ์ฌ์ ์ ์ด์ฉํด ๋ฌธ์๋ค์ ์ธ๋ฑ์ค์ ์ํ์ค๋ก ๋ณํํฉ๋๋ค.
print("Index of 'the':", tokenizer.word_index["the"])
print("Index of 'review':", tokenizer.word_index["two"])
print("Index of out-of-vocabulary words:", tokenizer.word_index["UNK"])
Index of 'the': 2
Index of 'review': 77
Index of out-of-vocabulary words: 1
ํ ํฌ๋์ด์ ๊ฐ ์์ฑํ ์ฌ์ ์์ ๋จ์ด์ ์ธ๋ฑ์ค๋ฅผ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
์์ ์ฝ๋์์ ๋ณด์๋ฉด ๋จ์ด 'the'์ ์ธ๋ฑ์ค๊ฐ '2'์ธ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ค์ ๋ก ํ์ธํด๋ณด๋ฉด, ๋ฌธ์์ 'the' ๋ถ๋ถ์ด
์ด๋ ๊ฒ 2๋ก ๋ํ๋ธ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
from tensorflow.keras.preprocessing.sequence import pad_sequences
maxlen = 500 #๋ฌธ์์ ๋จ์ด ์๋ฅผ ์ ํ
# ๋ฌธ์์ ๋จ์ด ์๊ฐ 500๋ณด๋ค ์์ผ๋ฉด 0์ ์ฑ์ฐ๊ณ , ํฌ๋ฉด ์๋ผ๋
# ์๋ผ๋ผ ๋, ์์ ์๋ฅผ ์ง, ๋ค๋ฅผ ์๋ฅผ ์ง ์ ํํ ์ ์์. ์์ ์๋ฅด๊ณ ๋ท๋ถ๋ถ์ ์ฐ๊ณ ์ ํ๋ฉด 'pre' ์ ํ.
# ๋ท๋ถ๋ถ์ ์๋ฅด๊ณ ์ถ์ผ๋ฉด 'post' ์ ํ
X = pad_sequences(X, maxlen=maxlen, truncating='pre')
import numpy as np
# label์ 0, 1์ ๊ฐ์ผ๋ก ๋ณํ
label_dict = {'pos':1, 'neg':0}
y = np.array([label_dict[c] for c in categories])
print(set(y))
{0, 1}
์ ๊ฒฝ๋ง ๋ชจํ์ ์ ๋ ฅ์ ๊ธธ์ด๊ฐ ์ผ์ ํด์ผ ํ๋๋ฐ ๊ฐ ๋ฆฌ๋ทฐ์ ๊ธธ์ด๊ฐ ๋ค๋ฅด๋ฏ๋ก pad_sequence๋ฅผ ์ด์ฉํด ๋ชจ๋ ์ ๋ ฅ ์ํ์ค์ ๊ธธ์ด๋ฅผ ๋งค๊ฐ๋ณ์ maxlen์ ์ธ์๋งํผ ๋์ผํ๊ฒ ๋ณํํฉ๋๋ค. ์ด ์ค์ต์์๋ ์ํ์ค์ ๊ธธ์ด๋ฅผ 500์ผ๋ก ํ๊ฒ ์ต๋๋ค.
๋ง์ฝ ์ ๋ ฅ ๋ฐ์ดํฐ์ ๊ธธ์ด๊ฐ 500๋ณด๋ค ํฌ๋ค๋ฉด ๋จ๋ ๋ถ๋ถ์ ์๋ผ๋ด์ผ ํ๋๋ฐ, ์์ ์๋ฅด๊ณ ๋ค๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด truncating์ ๊ฐ์ 'pre'๋ก, ๋์ ์๋ฅด๊ณ ์์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด 'post'๋ฅผ ์ ํํ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ถ๋ ฅ ๋ฐ์ดํฐ๋ Keras์ ์ด์ง ๋ถ๋ฅ ๋ชจํ์ 0๊ณผ 1์ ๊ฐ์ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ positive๋ฅผ 1๋ก, negative๋ฅผ 0์ผ๋ก ๋ณํํฉ๋๋ค.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=10)
print('Train set count:', len(X_train))
print('Test set count:', len(X_test))
print('Test samples:', y_test[:20])
Train set count: 1600
Test set count: 400
Test samples: [0 1 1 0 1 1 0 0 0 0 1 1 0 0 1 0 0 1 1 1]
๋ชจํ์ ๊ฒ์ฆํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด test_size๋ฅผ 0.2๋ก ์ค์ ํด ์ด ๋ฐ์ดํฐ์ 2,000๊ฐ ์ค์์ ํ์ต ๋ฐ์ดํฐ์ ์ 1,600๊ฐ, ํ ์คํธ ๋ฐ์ดํฐ์ ์ 400๊ฐ๋ก ๋ถ๋ฅํฉ๋๋ค.
RNN์ด ์๋ ์ผ๋ฐ์ ์ธ ์ ๊ฒฝ๋ง ๋ชจํ์ ์ด์ฉํ ๋ถ๋ฅ
๋จ์ด ์๋ฒ ๋ฉ์ ๋ํด RNN์ ์ฑ๋ฅ์ ๋น๊ตํ๊ธฐ ์ํด ๋จผ์ Rogistic ํ๊ท ๋ชจํ์ ๊ตฌํํด์ ์ํ์ค ์ ๋ณด ์์ด ์์ธก์ ์ํํด๋ณด๊ฒ ์ต๋๋ค.
Keras๊ฐ ์ ๊ณตํ๋ Sequential ๋ชจํ์ ๋จ์ํ๊ฒ ์์ฐจ์ ์ผ๋ก ์ธต์ ์์์ ์ ๊ฒฝ๋ง ๋ชจํ์ ๊ตฌ์ฑํ๋๋ฐ ํ์ฉํ ์ ์๋, ์ฝ๊ณ ๋จ์ํ ๋๊ตฌ์ ๋๋ค. ์ด ์ค์ต์์๋ Embedding ๋ ์ด์ด, Flatten ๋ ์ด์ด, ๊ทธ๋ฆฌ๊ณ Dense ๋ ์ด์ด๋ฅผ ์์์ ์ ๊ฒฝ๋ง ๋ชจํ์ ๋ง๋ค๊ฒ ์ต๋๋ค.
๋จผ์ , Embedding ๋ ์ด์ด๋ ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ์-ํซ ์ธ์ฝ๋ฉ๊ณผ ์๋ ์๋ฒ ๋ฉ์ ์ํํ๋ ๋ ์ด์ด์ ๋๋ค.
ํ์ฌ ๋ฌธ์๋ 500๊ฐ์ ๋จ์ด๋ก ์ด๋ฃจ์ด์ ธ ์๊ณ ๋จ์ด ์ฌ์ ์ ๋จ์ด ๊ฐ์๋ 10,000๊ฐ์ด๋ฏ๋ก ํ๋์ ๋ฌธ์๋ (500, 10000) ํฌ๊ธฐ์ 2์ฐจ์ ํ๋ ฌ๋ก ํํํ ์ ์์ต๋๋ค. ์ด 2์ฐจ์ ํ๋ ฌ์ ๋ฐ์ง ๋ฒกํฐ๋ก ๋ณํํด์ผ ํ๋๋ฐ ์ด ์ค์ต์์๋ ๋ฐ์ง ๋ฒกํฐ์ ํฌ๊ธฐ๋ฅผ 32๋ก ์ง์ ํ๊ฒ ์ต๋๋ค. ๋ฐ๋ผ์ 1 X 10,000 ํฌ๊ธฐ์ ๋ฒกํฐ๋ฅผ 1 X 32 ํฌ๊ธฐ์ ๋ฒกํฐ๋ก ๋ง๋ค๊ธฐ ์ํด์๋ 10,000 X 32 ํฌ๊ธฐ์ ๋ฒกํฐ๋ฅผ ๊ณฑํด์ผ ํ๊ธฐ ๋๋ฌธ์ 10,000 X 32 ๋งํผ์ ๊ฐ์ค์น ๋ณ์๊ฐ ํ์ํฉ๋๋ค.
Flatten ๋ ์ด์ด๋ 2์ฐจ์ ํ๋ ฌ์ 1์ฐจ์ ๋ฒกํฐ๋ก ์ญ ํผ์น๋ ์ญํ ์ ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก Dense ๋ ์ด์ด๋ ๋ชจ๋ ๋ ธ๋๋ค์ด ์ฐ๊ฒฐ๋๋ ๋ฐ์ง ์ธต์ ์์ฑํด ์๋์ธต์ ๋ง๋ญ๋๋ค. ์ด ์ค์ต์์๋ ๊ฐ์ฑ ๋ถ์์ ์ํด ์ด์ง ๋ถ๋ฅ๋ฅผ ํด์ผ ํ๋ฏ๋ก ์ถ๋ ฅ๊ฐ์ ๊ณ์ฐํ ๋ Sigmoid ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
# ์ผ๋ผ์ค ๋ชจํ ์์ฑ ๋ฐ ํ์ต
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense, Embedding
model = Sequential([ #์์ฐจ์ ๋ชจํ
Embedding(max_words, 32, input_length=maxlen), #word embedding layer ์์ฑ
# max_words๋ one-hot encoding์ ํ ๋์ vector ํฌ๊ธฐ๊ฐ ๋จ - ์ฌ์ฉ๋ ๋จ์ด์ ์๋งํผ
# ๊ฐ ๋จ์ด๋ 32 ํฌ๊ธฐ์ dense vector๋ก embedding ๋จ
# input_length๋ ํ document์ ๋จ์ด ์๋ก ํํ
# ์ด ๊ณผ์ ์ ๊ฑฐ์น๋ฉด ๊ฐ document๋ (maxlen, 32)์ 2์ฐจ์ ํ๋ ฌ์ด ๋จ - ์ฆ word์ sequence๊ฐ ๋จ
Flatten(), # 2์ฐจ์ ํ๋ ฌ์ 1์ฐจ์์ผ๋ก ํผ์นจ
Dense(1, activation='sigmoid') #binary logistic regression์ ์ํ
])
model.summary() #๋ชจ๋ธ์ ์์ฝ์ ๋ณด ์ถ๋ ฅ
Metal device set to: Apple M1 Pro
systemMemory: 16.00 GB
maxCacheSize: 5.33 GB
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 500, 32) 320000
flatten (Flatten) (None, 16000) 0
dense (Dense) (None, 1) 16001
=================================================================
Total params: 336,001
Trainable params: 336,001
Non-trainable params: 0
_________________________________________________________________
์ฝ๋๋ฅผ ๋ณด์๋ฉด, ๋ฐ์ง ๋ฒกํฐ์ ํฌ๊ธฐ๋ฅผ 32๋ก ์ง์ ํ ๊ฒ์ ๋ณผ ์ ์๊ณ Dense ๋ ์ด์ด์ ํ์ฑํ ํจ์๋ฅผ Sigmoid๋ก ์ค์ ํ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ชจ๋ธ์ ์์ฝ ์ ๋ณด๋ฅผ ๋ณด์๋ฉด ํ ๋จ์ด๋ฅผ ํฌ๊ธฐ 32์ ๋ฐ์ง ๋ฒกํฐ๋ก ๋ณํํ๊ธฐ ๋๋ฌธ์ Embedding ๋ ์ด์ด์ ๊ฒฐ๊ด๊ฐ์ด 'ํ ๋ฌธ์ฅ ๋จ์ด ๊ฐ์' = 500 ๊ณฑํ๊ธฐ 'ํ ๋จ์ด์ ํฌ๊ธฐ' = 32, ์ฆ (500, 32) ํฌ๊ธฐ์ ๋ฒกํฐ๊ฐ ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ Flatten ๋ ์ด์ด์ ๊ฒฐ๊ด๊ฐ์ 500 X 32 ํฌ๊ธฐ์ 2์ฐจ ๋ฒกํฐ๋ฅผ 1์ฐจ์์ผ๋ก ๋ง๋ค์ด์ฃผ๊ธฐ ๋๋ฌธ์, 500 X 32 = 16,000 ํฌ๊ธฐ์ 1์ฐจ ๋ฒกํฐ๊ฐ ๋ฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก, Dense ๋ ์ด์ด๋ 0 ๋๋ 1์ ๊ฐ์ ์ฃผ๊ธฐ ๋๋ฌธ์ ํฌ๊ธฐ๊ฐ 1์ธ ๋ฒกํฐ๋ฅผ ๊ฒฐ๊ด๊ฐ์ผ๋ก ์ค๋๋ค.
์ด์ ์ด ๋ชจํ์ ๊ฐ์ง๊ณ ํ์ต์ ์งํํ๊ฒ ์ต๋๋ค.
# ๋ชจํ์ optimizer์ loss function ๋ฑ์ ์ง์
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
# ํ์ต์ ์ํ
history = model.fit(X_train, y_train,
epochs=10,
verbose=1,
validation_split=0.2)
ํ์ต์ ํ๋ ค๋ฉด loss ํจ์์ optimizer๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. ์ ์ฝ๋์ ๊ฐ์ด compile ๋ฉ์๋๋ฅผ ํตํด ์ด ๋์ ์ง์ ํ ์ ์์ต๋๋ค.
์ด์ง ๋ถ๋ฅ ๋ฌธ์ ์ด๋ฏ๋ก loss ํจ์๋ 'binary_crossentropy'๋ฅผ ์ฌ์ฉํ๊ณ optimizer๋ ๋ง์ด ์ฌ์ฉ๋๋ 'rmsprop'๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ถ๊ฐ๋ก ํ์ต๋ณ๋ก ์ ํ๋๋ฅผ ์์๋ณด๊ธฐ ์ํด metrics์ ์ ํ๋('acc')๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ตํ ๋ ๋ฐ๋ณต ํ์๋ 10๋ฒ, ๊ทธ๋ฆฌ๊ณ ๋งค ํ์ต๋ง๋ค ํ์ต ํํฉ์ ์ถ๋ ฅํ๊ณ ํ์ต์ ํ๋ฉด์ ์ฌ์ฉํ ๊ฒ์ฆ ๋ฐ์ดํฐ์ ์ ๋น์จ์ 0.2๋ก ์ค์ ํ์ต๋๋ค. ๊ฒ์ฆ ๋ฐ์ดํฐ์ ์ ๋ชจํ์ ํ์ต ํํฉ์ ํ์ ํจ์ผ๋ก์จ ๊ณผ๋ ์ ํฉ์ ์ฌ๋ถ๋ฅผ ํ๋จํ๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋งค๊ฐ๋ณ์๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
%matplotlib inline
import matplotlib.pyplot as plt
def plot_results(history, metric):
plt.plot(history.history[metric], 'b', label='Training '+metric)
plt.plot(history.history['val_'+metric], 'r--', label='Validation '+metric)
plt.title('Training vs. Validation '+metric)
plt.xlabel('Epochs')
plt.ylabel(metric)
plt.legend()
plt.show()
plot_results(history, 'acc')
์ ์ฝ๋๋ฅผ ํตํด ํ์ต์ด ์๋์๋์ง ๊ทธ๋ํ๋ก ํ์ธํด๋ณด๋ฉด
์ ํ๋๋ 4๋ฒ์งธ ๋ฐ๋ณต ๋ ์ด๋ฏธ ์ต๋์น์ ๋๋ฌํ๊ณ ๊ฒ์ฆ ๋ฐ์ดํฐ์ ์ ๋ํ ์ ํ๋๋ 4๋ฒ์งธ ๋ฐ๋ณต ์ดํ์๋ ์กฐ๊ธ์ฉ ์ฆ๊ฐํ์ง๋ง ํฐ ์ฐจ์ด๋ ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ๋ํ ๊ฒ์ฆ ๋ฐ์ดํฐ์ ๊ณผ ํ์ต ๋ฐ์ดํฐ์ ์ ๋ํ ์ ํ๋ ๊ฒฉ์ฐจ๊ฐ ๊ฝค ํฐ ํธ์ด๊ธฐ ๋๋ฌธ์ ๊ณผ๋ ์ ํฉ์ ๊ฐ๋ฅ์ฑ์ด ์์ด ๋ณด์ ๋๋ค.
#ํ
์คํธ ์
์ผ๋ก ํ์ต๋ ๋ชจํ์ ์ฑ๋ฅ์ ํ๊ฐ
score = model.evaluate(X_test, y_test)
print(f'#Test accuracy:{score[1]:.3f}')
13/13 [==============================] - 0s 7ms/step - loss: 0.5641 - acc: 0.7200
#Test accuracy:0.720
๋ง์ง๋ง์ผ๋ก ํ ์คํธ ๋ฐ์ดํฐ์ ์ ๋ํด ๋ชจํ์ ์ต์ข ์ฑ๋ฅ์ ํ์ธํด๋ณด๋ฉด, ์ต์ข ์ฑ๋ฅ์ 72%๊ฐ ๋์ต๋๋ค.
์ ํ๋๊ฐ ๊ธฐ๋๋ณด๋ค ๋์ง ์์๋ฐ ๊ทธ ์ด์ ๋ก๋
1. ๋จ์ด๋ฅผ 500๊ฐ๋ก ์ ํํ๋ฉด์ ๋ฌธ์๊ฐ ์๋ ค๋๊ฐ ๊ฒ
2. ๊ฒ์ฆ ๋ฐ์ดํฐ์ ์ผ๋ก ์ธํด ํ์ต ๋ฐ์ดํฐ์ ์ 20%๊ฐ ํ์ต์ ์ฌ์ฉ๋์ง ๋ชปํ ๊ฒ
3. ๊ณผ๋ ์ ํฉ
4. ๋จ์ด ์์ ์ ๋ณด๊ฐ ์ฌ๋ผ์ง ๊ฒ
๋ฑ์ ์์ธ์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค.
๋ฌธ์์ ์์ ์ ๋ณด๋ฅผ ํ์ฉํ๋ RNN ๊ธฐ๋ฐ ๋ฌธ์ ๋ถ๋ฅ
์ด์ RNN ๋ชจํ์ ์ฌ์ฉํด์ ๋ฌธ์ ๋ถ๋ฅ๋ฅผ ํด๋ณด๊ฒ ์ต๋๋ค.
์์ ์ฌ์ฉํ ๋ชจํ๊ณผ ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ Flatten ๋ ์ด์ด ๋์ SimpleRNN ๋ ์ด์ด๋ฅผ ์ฌ์ฉํด์ RNN ์ธต์ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ์๋ SimpleRNN์ ์ธ์์ 32๋ฅผ ์ ๋ ฅํ๋๋ฐ, ์ด๊ฒ์ ์๋ ๋ ธ๋์ ํฌ๊ธฐ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด์ ๋ชจํ๊ณผ ๋ค๋ฅด๊ฒ SimpleRNN ๋ ์ด์ด ๋ค์ Dense ๋ ์ด์ด๋ฅผ ์ถ๊ฐํ๋๋ฐ ์ต์ข ๋ ธ๋์ ๋ํด ์๋์ธต ํ๋๋ฅผ ์ถ๊ฐํด ๋ชจํ์ ์ฑ๋ฅ์ ๋์ธ ๊ฒ์ ๋๋ค. ๋ํ optimizer๋ฅผ ์๊น์ ๋ค๋ฅด๊ฒ Adam์ ์ฌ์ฉํ๋๋ฐ ์ฑ๋ฅ์ ์ํด์๋ผ๊ธฐ๋ณด๋ค๋ ๋ค์ํ optimizer๋ฅผ ์ฌ์ฉํด ์ค์ต์ ํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
์ ๋ฉํ์์๋ ์ฝ๋๋ฅผ ์คํ์ํค๋ฉด ๊ณ์ ์ค๋ฅ๊ฐ ๋์ ์ฐธ๊ณ ํ๋ฉฐ ๊ณต๋ถํ ์ฑ ์ ์คํ ๊ฒฐ๊ด๊ฐ์ ๊ทธ๋๋ก ๋ค๊ณ ์์ต๋๋ค.
๊ฒฐ๊ณผ๋ฅผ ๋ณด์๋ฉด ํ์ต์ด ๊ฑฐ์ ์ด๋ค์ง์ง ์์ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
ํ์ต ๋ฐ์ดํฐ์ ์ ๋ํ ์ ํ๋๋ 1.0๊น์ง ์ฌ๋ผ๊ฐ์ง๋ง ๊ฒ์ฆ ๋ฐ์ดํฐ์ ๊ณผ ํ ์คํธ ๋ฐ์ดํฐ์ ์ ๋ํ ์ ํ๋๋ 0.5 ์ ๋๋ฐ์ ์๋ฉ๋๋ค.
์ด๋ ๊ฒ ํ์ต์ด ์๋ ์ด์ ๋ ๋ฅ๋ฌ๋์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์ ์ธ ๊ฒฝ์ฌ ์์ค ๋๋ฌธ์ ๋๋ค.
์์์๋ถํฐ ์์์ ๋ฐ๋ผ ๋ค์ ๋จ์ด์ ๋ฏธ์น๋ ์ํฅ์ ์ถ์ ํด์ ํ์ตํ๋๋ฐ ๊ฒฝ์ฌ ์์ค๋ก ์ธํด ํ์ต์ด ์ ๋์ง ๋ชปํ๊ณ , ๋ฐ๋ผ์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์ ๋ณด๊ฐ ์ ๋๋ก ์ถ์ ๋์ง ๋ชปํ์ต๋๋ค. ์ด๋ฐ ํ์์ Long-term dependency, ์ฅ๊ธฐ๊ฐ์ ๊ฑธ์น ์๊ฐ์์กด์ฑ์ด ํ์ต๋์ง ๋ชปํ๋ ํ์์ด๋ผ๊ณ ํ๊ณ RNN์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์ ์ ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด LSTM ๋ชจํ์ ์ฌ์ฉํฉ๋๋ค.
LSTM, Bi-LSTM๊ณผ GRU๋ฅผ ์ด์ฉํ ์ฑ๋ฅ ๊ฐ์
LSTM์ ๋ชฉ์ ์ ์๋ถ๋ถ์ ์ ๋ณด๊ฐ ๋ค๋ก ๊ฐ์๋ก ์์ค๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฅ๊ธฐ ์์กด์ฑ๊ณผ ๋จ๊ธฐ ์์กด์ฑ์ ๋ชจ๋ ํํํ๊ณ ํ์ตํ๋ ๊ฒ์ ๋๋ค.
GRU๋ LSTM์ ๊ฐ์ํํ ๋ชจํ์ผ๋ก LSTM์ ๋นํด ๊ณ์ฐ๋์ด ์ ๊ณ ์๋๊ฐ ๋น ๋ฅด๋ฉด์๋ ์ข์ ์ฑ๋ฅ์ ๋ด๋ ๊ฒ์ผ๋ก ์๋ ค์ ธ ์์ต๋๋ค.
Bi-LSTM์ RNN์ ๊ฐ์ ํ๊ธฐ ์ํด ์๋ฐฉํฅ์ผ๋ก ๋ชจํ์ ๊ตฌ์ถํ ๊ฒ์ ๋๋ค.
LSTM, Bi-LSTM, ๊ทธ๋ฆฌ๊ณ GRU๋ฅผ ์ด์ฉํด ๋ง์ฐฌ๊ฐ์ง๋ก NLTK ๊ฐ์ฑ ๋ถ์ ์ค์ต์ ํด๋ณด๊ฒ ์ต๋๋ค.
SimpleRNN์์ ์ฌ์ฉํ๋ ์ฝ๋์ ๋ชจ๋ ๋์ผํ์ง๋ง 'SimpleRNN' ๋์ , LSTM์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด LSTM, GRU๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด GRU, Bi-LSTM์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด Bidirectional๋ก LSTM์ ๊ฐ์ธ์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์ ๊ทธ๋ฆผ์์๋ Bi-LSTM์ ์ฌ์ฉํ์ต๋๋ค.
์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, ๊ฒ์ฆ ๋ฐ์ดํฐ์ ๊ณผ ํ ์คํธ ๋ฐ์ดํฐ์ ์ ๋ํ ์ ํ๋๊ฐ SimpleRNN์ ์ฌ์ฉํ์ ๋๋ณด๋ค ํ์คํ ์ข์์ง ๊ฒ์ ์ ์ ์์ต๋๋ค.
ํ์ง๋ง SimpleRNN์ ์ฌ์ฉํ ๊ฒฐ๊ณผ๋ณด๋ค๋ ๋์์ก์ง๋ง ์ฐ๋ฆฌ๊ฐ ๊ธฐ๋ํ, ๋ฌธ๋งฅ์ ๋ํ ํ์ต์ ํตํด ๋ ์ข์ ์ฑ๋ฅ์ ๋ณด์ด์ง๋ ๋ชปํ์ต๋๋ค.
๊ทธ ์ด์ ๋ก๋ ์๊น์ ๊ฐ์ด,
1. ๋จ์ด๋ฅผ 500๊ฐ๋ก ์ ํํ๋ฉด์ ๋ฌธ์๊ฐ ์๋ ค๋๊ฐ ๊ฒ
2. ๊ฒ์ฆ ๋ฐ์ดํฐ์ ์ผ๋ก ์ธํด ํ์ต ๋ฐ์ดํฐ์ ์ 20%๊ฐ ํ์ต์ ์ฌ์ฉ๋์ง ๋ชปํ ๊ฒ
3. ๊ณผ๋ ์ ํฉ
4. ๋ฅ๋ฌ๋์ ํ์ต์ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์๊ตฌํ๋๋ฐ NLTK์ ํ์ต ๋ฐ์ดํฐ๋ 2,000๊ฐ ๋ฐ์ ์๋๊ธฐ ๋๋ฌธ์
์ ๋๋ค.
y_pred = np.round(model.predict(X_test[:10]))
for pred, y_t in zip(y_pred, y_test[:10]):
print(f'predicted value: {pred[0]}, true value: {y_t}, so the prediction is {pred[0] == y_t}')
๋ง์ง๋ง์ผ๋ก, ํ์ต๋ ๋ชจํ์ ์ด์ฉํด ๊ฒฐ๊ณผ๋ฅผ ์์ธกํ๊ณ ์ถ๋ค๋ฉด model์ predict ๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด ๋ฉ๋๋ค.
์ฌ๊ธฐ์๋ ๊ทธ๋ฅ ๋ฐ์ฌ๋ฆผ์ ํด์ ์์ธก ๊ฒฐ๊ณผ์ ์ค์ ๊ฐ์ ๋น๊ตํ๊ณ ์ ๋ต ์ฌ๋ถ๋ฅผ ์ถ๋ ฅํ์ต๋๋ค.
'ML & AI > Natural Language Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
RNN - ๋ฅ๋ฌ๋์ ์ด์ฉํ ๋ฌธ์ ๋ถ๋ฅ(1) (0) | 2022.12.05 |
---|---|
๋ฐ์ดํฐ ๋ถ์ ํ์ ํจํค์ง ์ผ๋์ฅ - 1) Pandas (0) | 2022.01.30 |