본문 바로가기

DEVELOPMENT/TensorFlow

[TensorFlow] 기본 텍스트 분류

기본 텍스트 분류

 

 

🔎 개요

텍스트 분류(Text Classification)은 주어진 텍스트를 특정 카테고리들 중 하나로 분류하는 자연어 처리(NLP 분야의) 작업이다.

TensorFlow는 텍스트 분류를 위한 다양한 기능과 도구를 제공한다.

 

📌 주제

영화 리뷰를 사용한 텍스트 분류

IMDB 데이터셋에 대한 감정 분석을 수행하도록 이진 분류기 훈련

 

📝 과정

① 데이터셋 다운로드 및 탐색

② 데이터셋 로드

③ 훈련을 위한 데이터셋 구성

④ 성능을 높이도록 데이터셋 구성

⑤ 모델 생성

⑥ 손실 함수와 옵티마이저

⑦ 모델 훈련

⑧ 모델 평가

⑨ 정확도와 손실 그래프 그리기

⑩ 모델 내보내기(새로운 데이터로 추론)

 

💻 개발환경

구글 코랩(Colab) : 클라우드 기반의 무료 Jupyter 노트북 개발 환경

 

 

TensorFlow 설정

 

import matplotlib.pyplot as plt
import os
import re
import shutil
import string
import tensorflow as tf

from tensorflow.keras import layers
from tensorflow.keras import losses

print(tf.__version__) # 2.11.0

 

 

데이터셋 다운로드 및 탐색

 

url = "https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz"

# 지정된 URL에서 데이터셋 파일 다운
dataset = tf.keras.utils.get_file("aclImdb_v1", url,
                                    untar=True, # tar.gz 압축 파일 해제 지정 
                                    cache_dir='.', # 데이터셋 파일 저장할 디렉토리 경로 지정  
                                    cache_subdir='')

dataset_dir = os.path.join(os.path.dirname(dataset), 'aclImdb')

os.listdir(dataset_dir) # 'dataset_dir'에 있는 파일 및 디렉토리의 목록 확인

train_dir = os.path.join(dataset_dir, 'train') # 'dataset_dir' 디렉토리 내에 있는 'train' 디렉토리 경로
os.listdir(train_dir)

sample_file = os.path.join(train_dir, 'pos/1181_9.txt') # 'train' 디렉토리 내의 'pos/1181_9.txt' 파일 경로
with open(sample_file) as f:
  print(f.read())

 

 

데이터셋 로드

 

remove_dir = os.path.join(train_dir, 'unsup') # 'train' 디렉토리 내의 'unsup' 경로를 remove_dir 변수에 할당
shutil.rmtree(remove_dir) # 해당 디렉토리와 그 하위 파일 및 디렉토리를 완전히 삭제

batch_size = 32
seed = 42

# 훈련 데이터셋 생성
raw_train_ds = tf.keras.utils.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='training', 
    seed=seed)

for text_batch, label_batch in raw_train_ds.take(1):
  for i in range(3):
    print("Review", text_batch.numpy()[i])
    print("Label", label_batch.numpy()[i])

# 검증 데이터셋 생성
raw_val_ds = tf.keras.utils.text_dataset_from_directory(
    'aclImdb/train', 
    batch_size=batch_size, 
    validation_split=0.2, 
    subset='validation', 
    seed=seed)

# 테스트 데이터셋 생성
raw_test_ds = tf.keras.utils.text_dataset_from_directory(
    'aclImdb/test', 
    batch_size=batch_size)

 

 

훈련을 위한 데이터셋 준비

 

# 데이터 전처리
def custom_standardization(input_data):
  lowercase = tf.strings.lower(input_data)
  stripped_html = tf.strings.regex_replace(lowercase, '<br />', ' ') # br 태그를 공백으로 대체
  return tf.strings.regex_replace(stripped_html,
                                  '[%s]' % re.escape(string.punctuation),
                                  '')

max_features = 10000 # 사용할 최대 토큰 수
sequence_length = 250 # 문장의 최대 길이

# 텍스트를 벡터로 변환
vectorize_layer = layers.TextVectorization(
    standardize=custom_standardization,
    max_tokens=max_features, # 고려할 최대 고유 단어 수 지정
    output_mode='int', # 정수 인덱스 벡터로 출력되도록 설정
    output_sequence_length=sequence_length) # 문장 최대 길이 지정

# 데이터셋에서 레이블을 제외한 텍스트 데이터만 추출
train_text = raw_train_ds.map(lambda x, y: x) 
# 레이어를 훈련 데이터에 맞게 적응시키기
vectorize_layer.adapt(train_text) 

def vectorize_text(text, label): # 레이블을 벡터화하는 함수
  text = tf.expand_dims(text, -1) # 차원 추가
  return vectorize_layer(text), label


text_batch, label_batch = next(iter(raw_train_ds)) # 데이터셋에서 한 번의 이터레이션으로 배치 가져오기
first_review, first_label = text_batch[0], label_batch[0]
print("Review", first_review)
print("Label", raw_train_ds.class_names[first_label])
print("Vectorized review", vectorize_text(first_review, first_label))

print("1287 ---> ",vectorize_layer.get_vocabulary()[1287]) # 특정 인덱스에 해당하는 단어 출력
print(" 313 ---> ",vectorize_layer.get_vocabulary()[313])
print('Vocabulary size: {}'.format(len(vectorize_layer.get_vocabulary())))

 

 

성능을 높이도록 데이터셋 구성

 

AUTOTUNE = tf.data.AUTOTUNE # 자동으로 조정되는 값을 나타내는 상수

# 캐싱 및 프리페치 적용
train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
test_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)

 

 

모델 생성

 

# 임베딩(단어나 텍스트를 고정된 길이의 벡터로 변환)
embedding_dim = 16 # 임베딩 차원을 16으로 설정

# Sequential 모델 생성
model = tf.keras.Sequential([
  layers.Embedding(max_features + 1, embedding_dim),
  layers.Dropout(0.2),
  layers.GlobalAveragePooling1D(),
  layers.Dropout(0.2),
  layers.Dense(1)])

# 모델의 구조 요약해서 출력
model.summary()

 

 

손실 함수와 옵티마이저

 

model.compile(loss=losses.BinaryCrossentropy(from_logits=True),
              optimizer='adam',
              metrics=tf.metrics.BinaryAccuracy(threshold=0.0))

 

 

모델 훈련

 

epochs = 10 # 에포크 수 : 전체 훈련 데이터셋 반복 횟수
history = model.fit( # 모델 훈련
    train_ds,
    validation_data=val_ds,
    epochs=epochs)

 

 

모델 평가

 

loss, accuracy = model.evaluate(test_ds) 

print("Loss: ", loss)
print("Accuracy: ", accuracy)

 

 

정확도와 손실 그래프 그리기

 

# history_dict를 사용하여 훈련 과정에서 기록된 메트릭 확인
history_dict = history.history
history_dict.keys()

acc = history_dict['binary_accuracy'] # 훈련 정확도
val_acc = history_dict['val_binary_accuracy'] # 검증 정확도
loss = history_dict['loss'] # 훈련 손실
val_loss = history_dict['val_loss'] # 검증 손실

epochs = range(1, len(acc) + 1)

# 훈련 손실에 대한 그래프
plt.plot(epochs, loss, 'bo', label='Training loss')
# 검증 손실에 대한 그래프
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
# 그래프 출력
plt.show()

# 훈련 정확도에 대한 그래프
plt.plot(epochs, acc, 'bo', label='Training acc')
# 검증 정확도에 대한 그래프
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
# 그래프 출력
plt.show()

 

 

모델 내보내기

 

export_model = tf.keras.Sequential([
  vectorize_layer,
  model,
  layers.Activation('sigmoid')
])

# 내보낸 모델의 손실 함수, 옵티마이저, 평가 지표 설정
export_model.compile(
    loss=losses.BinaryCrossentropy(from_logits=False), optimizer="adam", metrics=['accuracy']
)

# 'raw_test_ds' 데이터셋 평가, 손실과 정확도 출력
loss, accuracy = export_model.evaluate(raw_test_ds)
print(accuracy)

 

 

 

 

'DEVELOPMENT > TensorFlow' 카테고리의 다른 글

[TensorFlow] 워드 임베딩  (0) 2023.06.29
[TensorFlow] 기본 이미지 분류  (0) 2023.06.29
[TensorFlow] 텐서플로 2.0 시작하기  (0) 2023.06.29