순차 데이터
텍스트나 시계열 데이터와 같이 순서에 의미가 있는 데이터이다. 대표적으로 글, 대화, 일자별 날씨 등이 있다.
순환 신경망
순차 데이터에 잘맞는 인공신경망의 한 종류이다. 순환층을 셀이라고 부르고 셀의 출력을 은닉 상태라고 부른다. 은닉상태는 다음층으로 전달될 뿐만 아니라 셀이 다음 타임스텝의 데이터를 처리할 때 재사용된다.
말뭉치
자연어 처리에서 사용하는 텍스트 데이터의 모음, 즉 훈련 데이터셋을 일컫는다.
토큰
텍스트에서 공백으로 구분되는 문자열을 말한다. 종종 소문자로 변환하고 구둣점은 삭제한다.
원-핫 인코딩
어떤 클래스에 해당하는 원소만 1이고 나머지는 모두 0인 벡터이다. 정수로 변환된 토큰을 원-핫 인코딩으로 변환하려면 어휘사전 크기의 벡터가 만들어진다.
단어 임베딩
정수로 변환된 토큰을 비교적 작은 크기의 실수 밀집 벡터로 변환한다. 밀집 벡터는 단어 사이의 관계를 표현할 수 있어서 자연어 처리에서 좋은 성능을 발휘한다.
from tensorflow.keras.datasets import imdb
(train_input,train_target),(test_input,test_target) = imdb.load_data(num_words=500)
print(train_input.shape,test_input.shape)
배열이 1차원인 이유
imdb 리뷰텍스트의 길이는 제각각임
->고정된 2차원 배열에 담기보다 리뷰마다 별도의 파이썬 리스트로 담아야 메모리를 효율적으로 사용할 수 있음
print(len(train_input[0]))
print(len(train_input[1]))
-> 리뷰의 길이는 제각각이다.
print(train_input[0])
첫번째 리뷰에 담긴 내용 (218개의 토큰)
앞서 num_words를 500으로 설정했기에 어휘사전에 포함되지않은 단어는 2로 표시됨
※ 0 : 패딩 / 1 : 시작 / 2 : 어휘사전에 없는 단어
print(train_target[:20])
from sklearn.model_selection import train_test_split
train_input,val_input,train_target,val_target = train_test_split(train_input,train_target,test_size=0.2,random_state=42)
import numpy as np
lengths = np.array([len(x) for x in train_input])
print(np.mean(lengths),np.median(lengths))
-> 한쪽으로 치우침을 예상할 수 있다.
import matplotlib.pyplot as plt
plt.hist(lengths)
plt.xlabel('lengths')
plt.ylabel('frequency')
plt.show()
from tensorflow.keras.preprocessing.sequence import pad_sequences
train_seq = pad_sequences(train_input,maxlen=100)
print(train_seq.shape)
print(train_seq[0])
print(train_input[0][-10:])
실제 첫번째 리뷰의 마지막 10개의 토큰을 확인해봄
train_seq 의 마지막 10개의 토큰과 일치
-> 길이를 맞추기위해 앞쪽을 자름
일반적으로 시퀀스의 뒷부분이 더 유용한 정보가 많다고 생각하기에 앞쪽을 슬라이싱함
만약, 뒤쪽을 자르고 싶으면 pad_sequences() 함수의 truncating='post'로 설정하면됨
print(train_seq[5])
val_seq = pad_sequences(val_input,maxlen=100)
from tensorflow import keras
model = keras.Sequential()
model.add(keras.layers.SimpleRNN(8,input_shape=(100,500)))
model.add(keras.layers.Dense(1,activation='sigmoid'))
train_oh = keras.utils.to_categorical(train_seq)
print(train_oh.shape)
train_seq -> train_oh
(200000,100) -> (200000,100,500)
print(train_oh[0][0][:12])
print(np.sum(train_oh[0][0]))
val_oh = keras.utils.to_categorical(val_seq)
model.summary()
rmsprop = keras.optimizers.RMSprop(learning_rate=1e-4)
model.compile(optimizer=rmsprop,loss='binary_crossentropy',metrics=['accuracy'])
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-simplernn-model.h5',save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=3,restore_best_weights=True)
history = model.fit(train_oh,train_target,epochs=100,batch_size=64,validation_data=(val_oh,val_target),callbacks=[checkpoint_cb,early_stopping_cb])
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epochs')
plt.ylabel('loss')
plt.legend(['train','val'])
plt.show()
print(train_seq.nbytes,train_oh.nbytes)
model2 = keras.Sequential()
model2.add(keras.layers.Embedding(500,16,input_length=100))
model2.add(keras.layers.SimpleRNN(8))
model2.add(keras.layers.Dense(1,activation='sigmoid'))
Embedding
model2.summary()
rmsprop = keras.optimizers.RMSprop(learning_rate=1e-4)
model2.compile(optimizer=rmsprop,loss='binary_crossentropy',metrics=['accuracy'])
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-embedding-model.h5',save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=3,restore_best_weights=True)
history = model2.fit(train_seq,train_target,epochs=100,validation_data=(val_seq,val_target),callbacks=[checkpoint_cb,early_stopping_cb])
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epochs')
plt.ylabel('label')
plt.legend(['train','val'])
plt.show()