<aside> 💡 허깅 페이스 라이브러리의 BART 모델과 뉴스 요약 데이터세트를 활용해 문장 요약 모델을 미세 조정

</aside>

데이터세트

허깅 페이스에서 제공하는 데이터세트 라이브러리를 통해 불러온다.

pip install datasets

언어 이해, 기계 번역, 감성 분석 등 다양한 데이터세트를 제공하며, 학습, 검증 및 테스트용으로 구성된다.

#뉴스 요약 데이터세트 불러오기
import numpy as np
from datasets import load_dataset

# "argilla/news-summary" 데이터셋에서 테스트 데이터셋을 로드합니다.
news = load_dataset("argilla/news-summary", split="test")

# 데이터셋을 판다스 데이터프레임으로 변환하고, 5000개의 샘플을 랜덤하게 선택합니다.
df = news.to_pandas().sample(5000, random_state=42)[["text", "prediction"]]

# "prediction" 열의 값을 각 요소의 첫 번째 텍스트로 매핑합니다.
df["prediction"] = df["prediction"].map(lambda x: x[0]["text"])

# 데이터프레임을 훈련, 검증, 테스트 세트로 나눕니다. 훈련 세트는 전체의 60%, 검증 세트는 전체의 20%, 테스트 세트는 전체의 20%입니다.
train, valid, test = np.split(
    df.sample(frac=1, random_state=42), [int(0.6 * len(df)), int(0.8 * len(df))]
)

# 훈련 데이터 중 첫 번째 샘플의 일부를 출력합니다.
print(f"Source News : {train.text.iloc[0][:200]}")

# 훈련 데이터 중 첫 번째 샘플의 요약을 출력합니다.
print(f"Summarization : {train.prediction.iloc[0][:50]}")

# 훈련, 검증, 테스트 데이터의 크기를 출력합니다.
print(f"Training Data Size : {len(train)}")
print(f"Validation Data Size : {len(valid)}")
print(f"Testing Data Size : {len(test)}")

Untitled

뉴스 요약 데이터세트: 뉴스 본문과 이를 요약한 짧은 텍스트로 구성

모델: 뉴스 본문을 입력으로 받아 요약된 텍스트를 출력해야 한다.

문장 요약 작업: 문장 길기가 긴 텍스트를 다루기에 연산량이 많다. 그러므로 테스트 데이터세트를 5000개만 샘플링해 6:2:2 비율로 학습, 검증, 테스트 데이터로 분리해 사용한다.

분리된 데이터 세트를 BART 토크나이저 클래스로 전처리를 수행한다.

#BART 입력 텐서 생성
import torch
from transformers import BartTokenizer
from torch.utils.data import TensorDataset, DataLoader
from torch.utils.data import RandomSampler, SequentialSampler
from torch.nn.utils.rnn import pad_sequence

# 데이터셋 생성 함수 정의
def make_dataset(data, tokenizer, device):
    # 토크나이저를 사용하여 입력 텍스트를 토큰화하고 텐서로 변환합니다.
    tokenized = tokenizer(
        text=data.text.tolist(),
        padding="longest",
        truncation=True,
        return_tensors="pt"
    )
    # 라벨 데이터를 인코딩하고 패딩합니다.
    labels = []
    input_ids = tokenized["input_ids"].to(device)
    attention_mask = tokenized["attention_mask"].to(device)
    for target in data.prediction:
        labels.append(tokenizer.encode(target, return_tensors="pt").squeeze())
    labels = pad_sequence(labels, batch_first=True, padding_value=-100).to(device)
    # 입력 텐서와 어텐션 마스크, 라벨을 포함하는 TensorDataset 생성
    return TensorDataset(input_ids, attention_mask, labels)

# 데이터로더 생성 함수 정의
def get_dataloader(dataset, sampler, batch_size):
    # 데이터 샘플러를 이용하여 데이터셋에서 샘플을 가져와 데이터로더를 생성합니다.
    data_sampler = sampler(dataset)
    dataloader = DataLoader(dataset, sampler=data_sampler, batch_size=batch_size)
    return dataloader

# 하이퍼파라미터 설정
epochs = 5
batch_size = 8
device = "cuda" if torch.cuda.is_available() else "cpu"

# BART 토크나이저 로드
tokenizer = BartTokenizer.from_pretrained(
    pretrained_model_name_or_path="facebook/bart-base"
)

# 훈련 데이터셋 생성
train_dataset = make_dataset(train, tokenizer, device)
# 훈련 데이터로더 생성 (랜덤 샘플링)
train_dataloader = get_dataloader(train_dataset, RandomSampler, batch_size)

# 검증 데이터셋 생성
valid_dataset = make_dataset(valid, tokenizer, device)
# 검증 데이터로더 생성 (순차적 샘플링)
valid_dataloader = get_dataloader(valid_dataset, SequentialSampler, batch_size)

# 테스트 데이터셋 생성
test_dataset = make_dataset(test, tokenizer, device)
# 테스트 데이터로더 생성 (순차적 샘플링)
test_dataloader = get_dataloader(test_dataset, SequentialSampler, batch_size)

# 훈련 데이터셋의 첫 번째 샘플 출력 (입력 텐서, 어텐션 마스크, 라벨)
print(train_dataset[0])

Untitled

사전 학습된 모델: facebook/bart-base (BART 모델의 기본 버전)

요약 작업: 입력값과 출력값이 모두 텍스트 데이터로 구성됨

패딩: 문장의 길이는 각각 다르기 때문에 길이를 맞춰주기 위해 패딩을 적용. 패딩값은 -100을 사용한다: 교차 엔트로피와 같은 손실 함수에서 패딩된 토큰을 무시하게 하기 위해 사용한다. 패딩된 토큰은 모델의 출력과 비교하지 않고 실제 레이블을 가진 토큰만 손실을 계산하는데 사용한다.