이 노트북에서 다중 병렬 합성곱 층의 출력을 연결하여 감성에 따라 IMDB 영화 리뷰를 분류합니다.
from tensorflow import keras
from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Model # new!
from tensorflow.keras.layers import Input, concatenate # new!
from tensorflow.keras.layers import Dense, Dropout, Embedding, SpatialDropout1D, Conv1D, GlobalMaxPooling1D
from tensorflow.keras.callbacks import ModelCheckpoint
import os
from sklearn.metrics import roc_auc_score
import matplotlib.pyplot as plt
%matplotlib inline
# 출력 디렉토리
output_dir = 'model_output/multiconv'
# 훈련
epochs = 4
batch_size = 128
# 벡터 공간 임베딩
n_dim = 64
n_unique_words = 5000
max_review_length = 400
pad_type = trunc_type = 'pre'
drop_embed = 0.2
# 합성곱 층 구조
n_conv_1 = n_conv_2 = n_conv_3 = 256
k_conv_1 = 3
k_conv_2 = 2
k_conv_3 = 4
# 밀집 층 구조
n_dense = 256
dropout = 0.2
(x_train, y_train), (x_valid, y_valid) = imdb.load_data(num_words=n_unique_words)
x_train = pad_sequences(x_train, maxlen=max_review_length, padding=pad_type, truncating=trunc_type, value=0)
x_valid = pad_sequences(x_valid, maxlen=max_review_length, padding=pad_type, truncating=trunc_type, value=0)
input_layer = Input(shape=(max_review_length,),
dtype='int16', name='input')
# 임베딩
embedding_layer = Embedding(n_unique_words, n_dim,
name='embedding')(input_layer)
drop_embed_layer = SpatialDropout1D(drop_embed,
name='drop_embed')(embedding_layer)
# 3개의 병렬 합성곱 층
conv_1 = Conv1D(n_conv_1, k_conv_1,
activation='relu', name='conv_1')(drop_embed_layer)
maxp_1 = GlobalMaxPooling1D(name='maxp_1')(conv_1)
conv_2 = Conv1D(n_conv_2, k_conv_2,
activation='relu', name='conv_2')(drop_embed_layer)
maxp_2 = GlobalMaxPooling1D(name='maxp_2')(conv_2)
conv_3 = Conv1D(n_conv_3, k_conv_3,
activation='relu', name='conv_3')(drop_embed_layer)
maxp_3 = GlobalMaxPooling1D(name='maxp_3')(conv_3)
# 합성곱 층의 활성화 연결
concat = concatenate([maxp_1, maxp_2, maxp_3])
# 밀집 은닉층
dense_layer = Dense(n_dense,
activation='relu', name='dense')(concat)
drop_dense_layer = Dropout(dropout, name='drop_dense')(dense_layer)
dense_2 = Dense(int(n_dense/4),
activation='relu', name='dense_2')(drop_dense_layer)
dropout_2 = Dropout(dropout, name='drop_dense_2')(dense_2)
# 출력층
predictions = Dense(1, activation='sigmoid', name='output')(dropout_2)
# 모델 생성
model = Model(input_layer, predictions)
model.summary()
Model: "model_1" __________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ================================================================================================== input (InputLayer) [(None, 400)] 0 [] embedding (Embedding) (None, 400, 64) 320000 ['input[0][0]'] drop_embed (SpatialDropout1D) (None, 400, 64) 0 ['embedding[0][0]'] conv_1 (Conv1D) (None, 398, 256) 49408 ['drop_embed[0][0]'] conv_2 (Conv1D) (None, 399, 256) 33024 ['drop_embed[0][0]'] conv_3 (Conv1D) (None, 397, 256) 65792 ['drop_embed[0][0]'] maxp_1 (GlobalMaxPooling1D) (None, 256) 0 ['conv_1[0][0]'] maxp_2 (GlobalMaxPooling1D) (None, 256) 0 ['conv_2[0][0]'] maxp_3 (GlobalMaxPooling1D) (None, 256) 0 ['conv_3[0][0]'] concatenate_1 (Concatenate) (None, 768) 0 ['maxp_1[0][0]', 'maxp_2[0][0]', 'maxp_3[0][0]'] dense (Dense) (None, 256) 196864 ['concatenate_1[0][0]'] drop_dense (Dropout) (None, 256) 0 ['dense[0][0]'] dense_2 (Dense) (None, 64) 16448 ['drop_dense[0][0]'] drop_dense_2 (Dropout) (None, 64) 0 ['dense_2[0][0]'] output (Dense) (None, 1) 65 ['drop_dense_2[0][0]'] ================================================================================================== Total params: 681,601 Trainable params: 681,601 Non-trainable params: 0 __________________________________________________________________________________________________
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
modelcheckpoint = ModelCheckpoint(filepath=output_dir+"/weights.{epoch:02d}.hdf5")
if not os.path.exists(output_dir):
os.makedirs(output_dir)
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_valid, y_valid), callbacks=[modelcheckpoint])
Epoch 1/4 196/196 [==============================] - 11s 50ms/step - loss: 0.5000 - accuracy: 0.7244 - val_loss: 0.2862 - val_accuracy: 0.8797 Epoch 2/4 196/196 [==============================] - 10s 49ms/step - loss: 0.2495 - accuracy: 0.9002 - val_loss: 0.2611 - val_accuracy: 0.8910 Epoch 3/4 196/196 [==============================] - 9s 45ms/step - loss: 0.1728 - accuracy: 0.9358 - val_loss: 0.2727 - val_accuracy: 0.8936 Epoch 4/4 196/196 [==============================] - 9s 48ms/step - loss: 0.1163 - accuracy: 0.9597 - val_loss: 0.2975 - val_accuracy: 0.8940
<keras.callbacks.History at 0x7f3f7e326eb0>
model.load_weights(output_dir+"/weights.02.hdf5")
y_hat = model.predict(x_valid)
782/782 [==============================] - 3s 4ms/step
plt.hist(y_hat)
_ = plt.axvline(x=0.5, color='orange')
"{:0.2f}".format(roc_auc_score(y_valid, y_hat)*100.0)
'96.11'