본문 바로가기
HRDI_AI/[인공지능] RNN을 이용한 자연어처리 모델 구현

3. 허깅페이스와 트랜스포머 알아보기 - 1(Transformer)

by Toddler_AD 2025. 12. 5.

3-1. 트랜스포머

  • Transformer
    • 작동 원리
      • GPT 모델은 'Transformer(트랜스포머)'라는 아키텍처를 기반으로 함
        • 트랜스포머 모델은 자연어 처리와 같은 순차적인 데이터를 처리하기 위해 설계된 딥러닝 모델.
        • 2017년 구글이 “Attention is all you need” 논문에서 발표한 모델(https://arxiv.org/abs/1706.03762)
      • 입력 처리: 문장을 단어 단위로 쪼개어 각 단어를 수치로 변환(임베딩)한다. 이 변환된 숫자 벡 터는 모델이 이해할 수 있는 형태로, 각 단어의 의미를 담고 있다.
      • 어텐션 메커니즘 (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