본문 바로가기

ChatGPT/인공지능

[자연어처리] POS Tagging을 위한 Transformer 모델 구현하기

반응형

들어가며

자연어 처리란?

자연어 처리(Natural Language Processing, NLP)는 인간의 언어를 컴퓨터가 이해하고 처리할 수 있도록 하는 분야입니다. 자연어 처리 기술은 인간과 기계 간의 의사소통을 가능하게 하며, 다양한 분야에서 활용됩니다.

POS Tagging이란?

POS(Part-of-Speech) Tagging은 문장 내의 각 단어가 어떤 품사(noun, verb, adjective, adverb, etc.)에 해당하는지를 태깅하는 작업입니다. 이 작업은 문장을 이해하고 해석하는 데 매우 중요합니다.

Transformer 모델이란?

Transformer 모델은 딥러닝에서 자연어 처리 분야에서 최근에 많이 사용되는 모델 중 하나입니다. Transformer 모델은 기존의 RNN(Recurrent Neural Network) 계열 모델보다 훨씬 병렬화가 가능하며, 문장 내의 단어 사이의 관계를 더 잘 파악할 수 있습니다.

데이터 전처리

Treebank corpus

Treebank corpus는 Penn Treebank라고도 불리며, 자연어 처리 분야에서 가장 많이 사용되는 코퍼스 중 하나입니다. 이 코퍼스는 Wall Street Journal(WSJ)에서 발행된 영문 기사들을 수집하여 구성되었습니다.

토큰과 태그 추출

Treebank corpus에서 문장과 품사 태그를 추출합니다.

중복 제거 및 개수 계산

추출한 토큰과 태그에서 중복을 제거하고, 각각의 개수를 계산합니다.

딕셔너리 생성

중복을 제거한 토큰과 태그에 대해 각각 딕셔너리를 생성합니다. 이 딕셔너리는 각각의 토큰과 태그에 대한 인덱스 매핑을 위해 사용됩니다.

토큰 및 태그 인덱싱

모든 문장에서 사용된 토큰과 태그를 인덱스로 변환합니다.

토큰과 태그를 인덱스로 변환하는 이유는 모델의 입력 데이터를 수치형 데이터로 변환하기 위해서입니다. 모델은 수치형 데이터만 처리할 수 있기 때문에, 토큰과 태그와 같은 텍스트 형식의 데이터를 모델이 이해할 수 있는 형태로 변환해야 합니다.

따라서, 각각의 토큰과 태그에 대해 고유한 인덱스를 부여하고, 이를 기반으로 문장을 인덱스 시퀀스로 변환합니다. 예를 들어, "I love NLP"라는 문장에서 "I", "love", "NLP"는 각각 1, 2, 3과 같은 고유한 인덱스로 변환됩니다. 이와 마찬가지로, "I"가 대명사를 나타내는 품사이고, "love"가 동사를 나타내는 품사일 경우, "I"는 1, "love"는 2와 같은 인덱스로 변환됩니다.

이렇게 변환된 토큰과 태그의 인덱스 시퀀스는 모델이 이해할 수 있는 형태가 되며, 모델은 이를 입력으로 받아서 POS tagging을 수행합니다.

패딩 추가

각 문장의 길이를 동일하게 맞추기 위해, 패딩을 추가합니다.

패딩은 모델의 입력 시퀀스 길이를 일정하게 맞추기 위해 사용됩니다. 자연어 처리에서는 문장의 길이가 서로 다른 경우가 많은데, 이러한 시퀀스 데이터를 다룰 때는 모델의 입력 길이가 고정되어야 합니다. 이를 위해 시퀀스의 길이가 가장 긴 문장을 기준으로 모든 문장을 길이가 동일한 시퀀스로 변환해야 합니다.

따라서, 시퀀스의 길이가 긴 문장에 대해서는 모든 시퀀스를 일정한 길이로 자르고, 시퀀스의 길이가 짧은 문장에 대해서는 빈 공간을 채우는 작업이 필요합니다. 이 과정에서 패딩을 사용합니다. 패딩을 통해 모델의 입력 시퀀스 길이를 일정하게 맞추면, 배치 처리가 가능해져 모델 학습에 용이합니다.

One-hot encoding

인덱싱된 태그들을 One-hot encoding을 통해 벡터화합니다.

학습 및 검증 데이터 분할

전체 데이터셋을 학습 데이터와 검증 데이터로 분할합니다.

모델 구성

입력층

모델의 입력층은 시퀀스 데이터를 받습니다. 이 경우, 각 문장의 토큰 인덱스 시퀀스를 입력으로 받습니다.

임베딩층

입력된 토큰 인덱스 시퀀스는 임베딩층을 통해 밀집 벡터로 변환됩니다.

Transformer Encoder 레이어

Transformer Encoder 레이어는 Multi-head Self-Attention 레이어와 Feedforward Neural Network 레이어로 구성됩니다. 이 레이어들은 문장 내의 각 단어가 다른 단어들과 어떤 관계를 가지는지를 파악하여 토큰을 인코딩합니다.

Multi-head Self-Attention 레이어

Multi-head Self-Attention 레이어는 토큰들 간의 관계를 파악하기 위한 레이어입니다. 이 레이어는 입력 시퀀스의 모든 토큰에 대해 self-attention을 수행하고, 여러 개의 서로 다른 representation을 생성합니다. 이를 위해, attention 메커니즘을 여러 개의 head로 분할하고, 각 head에서 attention을 수행합니다.

Feedforward Neural Network 레이어

Multi-head Self-Attention 레이어 다음에는 Feedforward Neural Network 레이어가 이어집니다. 이 레이어는 self-attention에서 파악된 토큰들의 관계를 이용하여, 토큰의 정보를 다시 한 번 더 정제합니다.

Global Average Pooling 레이어

Encoder 레이어를 거친 문장의 토큰들은 각각 다른 representation을 가지게 됩니다. 이를 평균내어 문장의 고정된 representation을 생성하기 위해 Global Average Pooling 레이어를 사용합니다.

Time-Distributed Dense 레이어

Time-Distributed Dense 레이어는 문장 내 각 토큰에 대한 출력을 생성하는 데 사용됩니다. 출력값은 각 태그의 확률 분포로 나타내어집니다.

전체 코드

import nltk
from nltk.corpus import treebank
import tensorflow as tf
from tensorflow.python.keras.models import Model
from tensorflow.keras.layers import Input, Dense, Dropout, TimeDistributed
from tensorflow.keras.layers import Embedding, GlobalAveragePooling1D
from tensorflow.keras.layers import MultiHeadAttention, LayerNormalization
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
import numpy as np

nltk.download('treebank')

# 데이터셋에서 문장과 품사 태그 추출
sentences = treebank.tagged_sents()

# 모든 문장에서 사용된 토큰들과 태그들 추출
tokens = []
tags = []
for sentence in sentences:
    for token, tag in sentence:
        tokens.append(token)
        tags.append(tag)

# 토큰과 태그들을 중복 제거하여 리스트로 변환
tokens = list(set(tokens))
tags = list(set(tags))

# 토큰과 태그의 개수 계산
num_tokens = len(tokens)
num_tags = len(tags)

# 토큰과 태그에 대한 딕셔너리 생성
token_to_index = {token: i+1 for i, token in enumerate(tokens)}
tag_to_index = {tag: i for i, tag in enumerate(tags)}

# 모든 문장의 토큰과 태그를 숫자 인덱스로 변환
X = [[token_to_index[token] for token, tag in sentence] for sentence in sentences]
y = [[tag_to_index[tag] for token, tag in sentence] for sentence in sentences]

# 각 문장의 길이를 동일하게 맞추기 위해 패딩 추가
X = pad_sequences(X, padding='post')
y = pad_sequences(y, padding='post')

y = to_categorical(y, num_classes=num_tags)

# 학습 데이터와 검증 데이터로 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)

# Transformer 모델 구성
inputs = Input(shape=(None,))
embedding = Embedding(input_dim=num_tokens+1, output_dim=64)(inputs)
encoder_output = embedding
for i in range(2):
    self_attention = MultiHeadAttention(num_heads=8, key_dim=64, dropout=0.1)
    attention_output = self_attention(encoder_output, encoder_output)
    add_output = tf.keras.layers.Add()([encoder_output, attention_output])
    normalization_output = LayerNormalization()(add_output)
    feed_forward = Dense(units=256, activation='relu')(normalization_output)
    dropout_output = Dropout(rate=0.1)(feed_forward)

    if normalization_output.shape[-1] != dropout_output.shape[-1]:
        normalization_output = Dense(units=dropout_output.shape[-1], activation='linear')(normalization_output)

    add_output = tf.keras.layers.Add()([normalization_output, dropout_output])
    normalization_output = LayerNormalization()(add_output)
    encoder_output = normalization_output
pooling = GlobalAveragePooling1D()(encoder_output)
outputs = TimeDistributed(Dense(num_tags, activation='softmax'))(encoder_output)
model = Model(inputs=inputs, outputs=outputs)

# 모델 컴파일
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 모델 학습
history = model.fit(X_train, np.array(y_train), validation_split=0.2, batch_size=32, epochs=5)

# 모델 평가
score = model.evaluate(X_test, np.array(y_test), batch_size=32)
print("Accuracy:", score[1])

모델 학습 및 평가

모델 컴파일

모델을 컴파일합니다. 이때, optimizer로는 Adam을, loss 함수로는 categorical_crossentropy를 사용합니다.

모델 학습

모델을 학습합니다. 이때, batch_size는 32로 설정하고, epochs는 5로 설정합니다.

모델 평가

학습된 모델을 검증 데이터에 대해 평가합니다. 이때, batch_size는 32로 설정합니다. 모델의 평가 결과는 accuracy와 loss로 나타내어집니다.

결론

이번 포스팅에서는 POS Tagging을 위한 Transformer 모델을 구현하였습니다. 데이터 전처리, 모델 구성, 학습 및 평가를 통해 POS Tagging 모델을 만드는 전체적인 과정을 살펴보았습니다.

Transformer 모델은 최근에 자연어 처리 분야에서 많은 관심을 받고 있는 모델 중 하나입니다. 이 모델은 RNN 계열 모델보다 높은 성능을 보이고, 문장 내의 단어 사이의 관계를 더 잘 파악할 수 있습니다.

POS Tagging은 자연어 처리 분야에서 매우 중요한 작업 중 하나입니다. 이 작업은 문장 내의 각 단어가 어떤 품사에 해당하는지를 태깅하는 작업으로, 문장을 이해하고 해석하는 데 매우 중요합니다.

이번 포스팅을 통해 POS Tagging을 위한 Transformer 모델의 구현 방법을 살펴보았습니다. 이를 통해, 자연어 처리 분야에서 Transformer 모델의 활용 가능성에 대해 더욱 깊이 이해할 수 있었습니다.

이 글은 ChatGPT의 도움을 받아 작성되었습니다.

반응형