3-1. 트랜스포머
Transformer
작동 원리
GPT 모델은 'Transformer(트랜스포머)'라는 아키텍처를 기반으로 함
입력 처리: 문장을 단어 단위로 쪼개어 각 단어를 수치로 변환(임베딩)한다. 이 변환된 숫자 벡 터는 모델이 이해할 수 있는 형태로, 각 단어의 의미를 담고 있다.
어텐션 메커니즘 (Attention Mechanism): 트랜스포머의 핵심 아이디어는 어텐션 메커니즘이다. 어텐션은 입력의 모든 단어가 서로 얼마나 중요한지를 계산하여, 중요한 단어에 더 집중할 수 있도록 한다. 쉽게 말해, 문장 내에서 어떤 단어들이 서로 관련이 있는지를 판단하고, 그 연 관성을 바탕으로 정보의 흐름을 조절한다.
인코더와 디코더: 트랜스포머는 인코더와 디코더로 구성.
인코더: 입력 문장을 받아 어텐션을 통해 의미 있는 벡터로 변환.
디코더: 인코더에서 얻은 벡터를 받아 새로운 문장을 생성하거나, 번역 작업 등을 수행.
병렬 처리: 트랜스포머는 RNN이나 LSTM과 달리 모든 단어를 한 번에 처리할 수 있어 학습이 빠르다. 이는 어텐션 메커니즘 덕분에 가능하며, 이전 단어들을 순차적으로 보지 않아도 각 단어의 중요도를 빠르게 계산할 수 있다.
실습 - 트랜스포머의 인코더 블록을 이용한 영화평 분류
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential, Model
inputs = layers.Input(shape=(80,))
input_embedding = layers.Embedding(input_dim=10000, output_dim=32)(inputs)
positions = tf.range(start=0, limit=80)
pos_encoding = layers.Embedding(input_dim=80, output_dim=32)(positions)
pos_enc_output = pos_encoding + input_embedding
attention_output = layers.MultiHeadAttention(num_heads=3, key_dim=32)(pos_enc_output, pos_enc_output)
x = layers.add([pos_enc_output, attention_output])
x = layers.BatchNormalization()(x)
ffnn = Sequential([layers.Dense(64, activation="relu"),
layers.Dense(32, activation="relu")])(x)
x = layers.add([ffnn, x])
x = layers.BatchNormalization()(x)
x = layers.GlobalAveragePooling1D()(x)
x = layers.Dropout(0.1)(x)
x = layers.Dense(64, activation="relu")(x)
x = layers.Dropout(0.1)(x)
outputs = layers.Dense(2, activation="softmax")(x)
model = Model(inputs=inputs, outputs=outputs)
model.summary()
Model: "functional_3"
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Layer (type) ┃ Output Shape ┃ Param # ┃ Connected to ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ input_layer_2 │ (None, 80) │ 0 │ - │
│ (InputLayer) │ │ │ │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ embedding_2 │ (None, 80, 32) │ 320,000 │ input_layer_2[0]… │
│ (Embedding) │ │ │ │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ add_3 (Add) │ (None, 80, 32) │ 0 │ embedding_2[0][0] │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ multi_head_attenti… │ (None, 80, 32) │ 12,608 │ add_3[0][0], │
│ (MultiHeadAttentio… │ │ │ add_3[0][0] │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ add_4 (Add) │ (None, 80, 32) │ 0 │ add_3[0][0], │
│ │ │ │ multi_head_atten… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ batch_normalizatio… │ (None, 80, 32) │ 128 │ add_4[0][0] │
│ (BatchNormalizatio… │ │ │ │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ sequential_1 │ (None, 80, 32) │ 4,192 │ batch_normalizat… │
│ (Sequential) │ │ │ │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ add_5 (Add) │ (None, 80, 32) │ 0 │ sequential_1[0][… │
│ │ │ │ batch_normalizat… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ batch_normalizatio… │ (None, 80, 32) │ 128 │ add_5[0][0] │
│ (BatchNormalizatio… │ │ │ │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ global_average_poo… │ (None, 32) │ 0 │ batch_normalizat… │
│ (GlobalAveragePool… │ │ │ │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dropout_3 (Dropout) │ (None, 32) │ 0 │ global_average_p… │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dense_10 (Dense) │ (None, 64) │ 2,112 │ dropout_3[0][0] │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dropout_4 (Dropout) │ (None, 64) │ 0 │ dense_10[0][0] │
├─────────────────────┼───────────────────┼────────────┼───────────────────┤
│ dense_11 (Dense) │ (None, 2) │ 130 │ dropout_4[0][0] │
└─────────────────────┴───────────────────┴────────────┴───────────────────┘
Total params: 339,298 (1.29 MB)
Trainable params: 339,170 (1.29 MB)
Non-trainable params: 128 (512.00 B)
# model.compile(loss='binary_crossentropy', optimizer='adam',
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam',
metrics=['accuracy'])
from tensorflow.keras.datasets import imdb
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=10000)
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
(25000,) (25000,) (25000,) (25000,)
from tensorflow.keras.preprocessing.sequence import pad_sequences
X_train_pad = pad_sequences(X_train, maxlen=80, truncating='post', padding='post')
X_test_pad = pad_sequences(X_test, maxlen=80, truncating='post', padding='post')
%%time
model.fit(X_train_pad, y_train, epochs=10, batch_size=200)
Epoch 1/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 5s 27ms/step - accuracy: 0.7592 - loss: 0.4899
Epoch 2/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.8640 - loss: 0.3231
Epoch 3/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.8878 - loss: 0.2712
Epoch 4/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9075 - loss: 0.2230
Epoch 5/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9130 - loss: 0.1847
Epoch 6/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9304 - loss: 0.1498
Epoch 7/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9437 - loss: 0.1217
Epoch 8/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9532 - loss: 0.1093
Epoch 9/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9640 - loss: 0.0872
Epoch 10/10
125/125 ━━━━━━━━━━━━━━━━━━━━ 3s 27ms/step - accuracy: 0.9735 - loss: 0.0692
CPU times: total: 8min 35s
Wall time: 35.7 s
model.evaluate(X_test_pad, y_test)
782/782 ━━━━━━━━━━━━━━━━━━━━ 3s 3ms/step - accuracy: 0.7530 - loss: 1.8327
[1.8327292203903198, 0.7529600262641907]
print(X_test_pad.shape)
(25000, 80)
import numpy as np
pred = model.predict(X_test_pad)
# pred = (pred > 0.5).astype(int)
pred = np.argmax(pred, axis=1)
782/782 ━━━━━━━━━━━━━━━━━━━━ 3s 3ms/step
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, pred))
[[10780 1720]
[ 4456 8044]]
from sklearn.metrics import accuracy_score
accuracy_score(y_test, pred)
0.75296