9 분 소요

트랜스포머 아키텍처 기반 모델


✅ 트랜스포머 아키텍처란?

  • 트랜스포머(Transformer)는 Attention(어텐션) 메커니즘에 기반해 입력 시퀀스의 모든 요소 간 관계를 효과적으로 파악하고 처리하는 딥러닝 모델 구조.

  • 기존 RNN/LSTM 기반 seq2seq의 한계를 극복하고, 병렬 처리와 긴 문맥 포착이 뛰어남.

  • 대표적으로 자연어 처리(NLP) 분야에서 광범위하게 사용되고, 번역, 요약, 질의응답, 텍스트 생성 등 다양한 Task에 적용됨.

1️⃣ 인코더기반, 디코더기반, 인코더-디코더기반 모델 각각의 특징 및 비교

인코더 기반 📥

입력 전체를 한 번에 받아 각 토큰의 상호관계를 양방향으로 인코딩함. “분석” 중심 작업에 특화

  • 대표 모델: BERT, RoBERTa, KoBERT(한국어).​

  • 주요 Task: 문장 분류, 감정 분석, 개체명 인식, 문맥 이해 등​

디코더 기반 📤

이전까지 생성된 출력만을 바탕으로 순차적으로 다음 토큰을 예측·생성함. “생성” 중심 작업에 특화

  • 대표 모델: GPT, KoGPT(한국어).​

  • 주요 Task: 텍스트 생성, 대화, 요약, 문장 완성 등

인코더-디코더 기반 📥 📤

인코더가 입력 정보를 벡터로 임베딩하면, 디코더가 이를 바탕으로 출력 시퀀스를 순차적으로 생성함. “입력과 출력이 모두 시퀀스인” 작업에 특화

  • 대표 모델: T5, BART, KoT5(한국어).​

  • 주요 Task: 기계 번역, 요약, 질의응답 등 ​

주요 차이점을 중심으로 모델 비교

정보 처리 방식의 차이

  • 인코더 기반: 입력 전체 문맥을 양방향으로 파악하여 분석함.
    • 입력 전체 병렬 처리 가능
  • 디코더 기반: 이전 정보만 참고하여 단방향으로 생성함.
    • 시퀀스 생성단계 순차 처리 필요
  • 인코더-디코더 기반: 입력은 양방향으로 이해하고(인코더), 출력은 단방향으로 생성(디코더)하는 연속적인 변환 작업에 사용됨.
    • 입력 인코딩은 병렬 가능, 출력 생성은 순차 처리 필요

주요 task의 차이

  • 인코더 기반: 분류, 질의응답(QA), 개체명 인식(NER), 문장 이해 등 자연어 이해 중심 태스크
  • 디코더 기반: 텍스트 생성, 대화, 요약 등 자연어 생성 중심 태스크
  • 인코더-디코더 기반: 번역, 요약, 질의응답 등 입력-출력 모두 시퀀스 형태인 복합 태스크

속도 및 효율의 차이

  • 인코더 기반: 빠른 학습/추론 가능, 출력 생성에는 불리함.
  • 디코더 기반: 생성 속도 상대 느림, 자연스러운 문장 생성 가능함.
  • 인코더-디코더 기반: 인코더-디코더 모두 병렬+순차 조합, 복합 태스크에 적합함.

장단점을 중심으로 모델 비교

  • 인코더 기반
    • 장점: 문장 전체 의미와 관계 파악에 우수함.
    • 단점: 출력 생성을 직접 지원하기는 어려움.
  • 디코더 기반
    • 장점: 자연스러운 텍스트 생성에 우수함, 생성형 AI에 적합함.
    • 단점: 긴 문맥 예측 어려움, 출력 속도가 느림.
  • 인코더-디코더 기반
    • 장점: 입력-출력 모두 필요한 복잡한 태스크에서 높은 성능을 보임.
    • 단점: 구조가 복잡하고, 학습과 추론 시 자원 소모가 큼.

✅ 인코더 기반 모델: KoBERT(kcbert-base)

1️⃣ 모델 조사

모델명: KoBERT(beomi/kcbert-base)

제공사: Beomi (개인 및 연구자 공개)

년도: 2022년경 (최초 공개)

모델 크기: 약 1.1억 파라미터 (BERT base 구조)

텍스트/이미지 지원: 텍스트 O / 이미지 X

지원 Task: 텍스트 분류, 감정 분석, 개체명 인식, 다중 분류 등

특징:

  • 네이버 뉴스 댓글 및 대댓글 데이터를 대규모로 수집하여 토크나이저와 BERT 구조를 처음부터 학습한 한국어 특화 사전학습 BERT 모델

  • 12개 레이어와 12개의 어텐션 헤드를 사용함

  • 자연어처리 실무에서 다양한 현장형 한국어 데이터 특성을 반영하여 설계됨

  • 한글 및 영어, 특수문자, 이모지 등 다양한 문자와 신조어까지 학습 대상에 포함함.

  • PyTorch 기반 구현체로 다수의 downstream task에서 검증된 높은 성능을 제공함.

  • 옵티마이저, 손실함수, 학습 스케줄러 등으로 파인튜닝에 최적화됨.

출처: Hugging Face ([beomi/kcbert-base])

2️⃣ 모델 테스트 코드

# 1. 환경 설정 및 라이브러리 설치
!pip install transformers torch scikit-learn pandas

# 2. 라이브러리 임포트 및 모델 로드
import torch
import pandas as pd
import numpy as np
from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# --- 모델 설정 ---
# 파인튜닝된 감정 분류 모델 로드
model_name = "beomi/kcbert-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)

# num_labels=2 를 명시하여 출력 레이어를 2개로 재설정
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=2,
    ignore_mismatched_sizes=True
)
print(f"✅ 모델 로드 완료: {model_name} (출력 클래스 2개로 재설정)")



# 샘플 데이터셋
data = {
    'text': [
        "이번 주말 여행은 완벽했어요. 날씨도 좋고 숙소도 최고!",  # 긍정 (1)
        "기다렸던 공연인데, 사운드 문제가 심각해서 너무 실망했어요.", # 부정 (0)
        "강의 내용이 체계적이고 알차서 많은 것을 배웠습니다.",  # 긍정 (1)
        "문의 전화를 여러 번 했는데 응대가 불친절하고 느렸습니다.", # 부정 (0)
        "이 책은 내용이 흥미롭고 문체가 아름다워 읽는 내내 행복했습니다.",  # 긍정 (1)
        "주문한 상품에 하자가 있는데, 교환 절차가 너무 복잡하고 까다로웠습니다.", # 부정 (0)
        "새로 추가된 기능이 사용자 편의성을 크게 높여준 것 같아요.", # 긍정 (1)
        "결과가 기대치에 한참 못 미쳐서 프로젝트를 다시 해야 할 것 같습니다." # 부정 (0)
    ],
    'label': [1, 0, 1, 0, 1, 0, 1, 0]  # 1: 긍정, 0: 부정
}
df = pd.DataFrame(data)
train_df, val_df = train_test_split(df, test_size=0.2, random_state=42)

# 데이터셋 클래스 정의
class SentimentDataset(torch.utils.data.Dataset):
    def __init__(self, texts, labels, tokenizer, max_length=128):
        self.texts = texts
        self.labels = labels
        self.tokenizer = tokenizer
        self.max_length = max_length

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        text = str(self.texts.iloc[idx])
        label = self.labels.iloc[idx]

        encoding = self.tokenizer(
            text,
            truncation=True,
            padding='max_length',
            max_length=self.max_length,
            return_tensors='pt'
        )

        return {
            'input_ids': encoding['input_ids'].flatten(),
            'attention_mask': encoding['attention_mask'].flatten(),
            'labels': torch.tensor(label, dtype=torch.long)
        }

# 데이터셋 생성
train_dataset = SentimentDataset(train_df['text'], train_df['label'], tokenizer)
val_dataset = SentimentDataset(val_df['text'], val_df['label'], tokenizer)

# 훈련 설정 및 트레이너 초기화

# 훈련 인자 설정
training_args = TrainingArguments(
    output_dir='./results',
    num_train_epochs=5,
    per_device_train_batch_size=8,
    per_device_eval_batch_size=8,
    warmup_steps=500,
    weight_decay=0.01,
    logging_dir='./logs',
    eval_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
)

# 평가 지표 함수
def compute_metrics(eval_pred):
    predictions, labels = eval_pred
    predictions = np.argmax(predictions, axis=1)
    return {'accuracy': accuracy_score(labels, predictions)}

# 트레이너 초기화
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=val_dataset,
    compute_metrics=compute_metrics
)

print("✅ Trainer 초기화가 성공적으로 완료되었습니다. 이제 훈련을 시작할 수 있습니다.")


import os
os.environ["WANDB_DISABLED"] = "true"
print("✅ WandB 로깅 비활성화 설정 완료. 훈련을 시작합니다.")

# 모델 훈련
print("\n모델 훈련을 시작합니다. 5 epoch 후 확신도가 높은 결과가 출력될 것입니다.")
trainer.train()


# 3. 새로운 테스트 텍스트로 추론
new_test_texts = [
    "어제 산 커피가 너무 맛있어서 하루 종일 기분이 좋았어요.",  # 긍정
    "고객 센터 연결이 안 돼서 환불을 못 받았어요. 화가 납니다.", # 부정
    "새로운 정책이 적용되었지만, 아직 장단점을 모르겠습니다.",   # 중립/불확실 (모델이 긍정 또는 부정 중 하나로 분류)
    "와, 이 노트북 배터리 성능 정말 최고네요!", # 긍정
    "작업 결과가 기대에 훨씬 못 미쳤다." # 부정
]

# 토큰화 및 인코딩
encoded = tokenizer(new_test_texts, padding=True, truncation=True, return_tensors='pt')
print("\n--- 토큰화 결과 (샘플) ---")
print(f"'{new_test_texts[0]}' -> {tokenizer.tokenize(new_test_texts[0])}")

# 4. 예측 함수 정의 및 추론
def predict_sentiment(text):
    inputs = tokenizer(text, return_tensors='pt', padding=True, truncation=True)

    # GPU 사용 시 모델과 입력을 GPU로 이동
    if torch.cuda.is_available():
        inputs = {k: v.to('cuda') for k, v in inputs.items()}
        model.to('cuda')

    with torch.no_grad():
        outputs = model(**inputs)
        # Softmax를 적용하여 확률로 변환
        predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)

        predicted_class = torch.argmax(predictions, dim=-1).item()
        confidence = predictions[0][predicted_class].item()

    # 이 모델은 클래스 1을 긍정, 클래스 0을 부정으로 분류할 가능성이 높다고 가정합니다.
    sentiment = "긍정" if predicted_class == 1 else "부정"

    return sentiment, confidence

print("\n--- 새로운 테스트 결과 ---")
for text in new_test_texts:
    sentiment, confidence = predict_sentiment(text)
    print(f"'{text}' -> {sentiment} (확신도: {confidence:.2f})")

3️⃣ 실행결과

  • KoBERT는 WordPiece 토크나이저를 사용하며, 실행 결과에서 볼 수 있듯 ‘커피가’를 [‘커피’, ‘##가’]처럼 의미 있는 단위를 분리하여 미등록 단어 문제에 효과적으로 대응한다.

  • Validation Loss: 0.646 -> 0.656 (증가)

    • 오버피팅(Overfitting)발생. 모델이 훈련 데이터에 너무 집중한 나머지, 일반적인 검증 데이터(Validation Data)에 대해서는 오히려 성능이 나빠지고 있음.
  • Accuracy: 1.000(100%)

    • 검증 데이터가 너무 적기 때문에(1~2개 문장), 우연히 모두 맞춰도 100%가 나온다. 하지만 손실(Loss)이 증가하고 있으므로 모델이 의미 있는 학습을 하고 있다고 볼 수 없다.
  • 긍정(1)과 부정(0)을 구분하는 이진 분류에서 확신도 0.5는 “모델이 찍는 것과 다름없다”는 의미로, 모델이 긍정과 부정 중 무엇을 선택해야 할지 매우 혼란스러워하고 있다는 뜻이다.

  • 발생한 문제: 테스트한 언어 모델(beomi/kcbert-base)은 약 1.1억개의 파라미터를 가지고 있는데, 이 거대한 모델에게 6~7개의 샘플만 주고 학습을 시켰기 때문에, 모델은 일반적인 규칙을 배우지 못하고 주어진 7개의 샘플을 단순 암기하는(과적합)결과가 나왔다.

    • 훈련 샘플 수: 6~7개 (8개 샘플 중 20%를 검증 데이터로 나눔)

✅ 디코더 기반 모델: KoGPT(ko-gpt-trinity-1.2B-v0.5)

1️⃣ 모델 조사

모델명: KoGPT (skt/ko-gpt-trinity-1.2B-v0.5)

제공사: SK Telecom (SKT)

년도: 2022

모델 크기: 약 11.6억 파라미터

텍스트/이미지 지원: 텍스트 O / 이미지 X

지원 Task: 텍스트 생성, 대화, 요약, 문장 완성 등 다양하고 복합적인 생성형 Task

특징:

  • SK텔레콤에서 공개한 오픈소스 한국어 GPT 계열 대형 트랜스포머 디코더(Decoder-only) 구조의 생성형 모델

  • GPT-2/3 아키텍처처럼 다음 토큰 예측(Next Token Prediction) 방식으로 학습되었음
  • 대규모 한국어 코퍼스를 중심으로 사전훈련되어 한국어 자연어 생성, 문장 완성, 요약, 대화 등 다양한 자연어 생성 태스크에 활용가능.

  • 한국어 챗봇, 텍스트 생성, 문장 변환, 감성분석 등의 연구 및 실험적 용도에 적합

  • 내부적으로는 24레이어, 1920 임베딩, 16 어텐션 헤드를 사용하며, 모델 파일 크기는 약 4.7GB

  • 공개 모델로 Hugging Face에서 사용 가능

출처: Hugging Face ([skt/ko-gpt-trinity-1.2B-v0.5])

2️⃣ 테스트 코드

from transformers import pipeline

print("SK텔레콤 KoGPT Trinity 모델을 로딩합니다...")
text_generator = pipeline(
    "text-generation",
    model="skt/ko-gpt-trinity-1.2B-v0.5"
)
print("모델 로딩이 완료되었습니다!")

# 텍스트 생성 시작 문장
prompt = "자연어 처리 기술이 발전하면서"

# 텍스트 생성, max_length 조절, 3개의 서로 다른 생성문 출력
generated_texts = text_generator(
    prompt,
    max_length=80,
    num_return_sequences=3
)

print("\n" + "="*50)
print(f"시작 문장(Prompt): '{prompt}'")
print("="*50 + "\n")

for i, text in enumerate(generated_texts):
    print(f"--- [생성 결과 {i+1}] ---")
    print(text['generated_text'])
    print("\n")

3️⃣ 실행결과

  • 한국어가 자연스럽고 문법적 오류가 거의 없다.
  • 문장 간의 연결이 매우 매끄럽다.
  • 전문적인 형태나 블로그 형태의 문체도 잘 구현한다.
  • 세 가지 생성 결과가 각각 다른 주제와 다른 문체로 작성된다. 즉, 모델이 높은 다양성을 가지고 있다.

✅ 인코더-디코더 기반 모델: KoT5(long-ke-t5-base-summarization_e10)

1️⃣ 모델 조사

모델명: KoT5(KETI-AIR-Downstream/long-ke-t5-base-summarization_e10)

제공사: KETI-AIR (한국전자통신연구원 및 AI 연구팀)

년도: 2023

모델 크기: Base 기준 약 1.8억 파라미터 (T5-base 구조)

텍스트/이미지 지원: 텍스트 O / 이미지 X

지원 Task: 텍스트 요약, 번역, 질의응답(QA), 분류, 텍스트-투-텍스트 작업

특징:

  • KETI-AIR의 long-ke-t5-base 모델을 기반으로 한국어 요약 데이터셋(jsonl_dataset_sum.py)에서 파인튜닝된 텍스트 요약용 모델

    • “요약” 목적에 파인튜닝 되어있다.
  • 한국어와 영어 혼합 환경 대응에 최적화된 서브워드 토크나이저를 사용함.

  • 학습 시 하이퍼파라미터로는 학습률 0.001, 배치 사이즈 1, 총 10 에폭(epoch) 등이 사용됨.

  • 다중 GPU 환경에서 Adam 옵티마이저와 선형 학습률 스케줄러로 훈련됨.

  • 평가 결과는 Rouge 계열 지표에서 Rouge1 약 22, Rouge2 약 10, Rougel 약 21 정도를 기록하여 요약 성능을 어느 정도 입증함.

  • 구글의 T5(Text-to-Text Transfer Transformer) 아키텍처 기반 모델을 한국어 및 영어 비정형 데이터에 맞게 사전학습함

  • 최대 입력 길이 4096 토큰, 출력 길이 1024 토큰 지원

  • 공개 Hugging Face 저장소에서 사용 가능

출처:

  • Hugging Face ([KETI-AIR-Downstream/long-ke-t5-base-summarization_e10])

2️⃣ 테스트 코드

from transformers import pipeline
import torch

# 1. KoT5 기반 한국어 장문 요약 모델 로드
print("KETI의 long-ke-t5-base-summarization_e10 모델을 로딩합니다...")
pipe = pipeline(
    "text2text-generation",
    model="KETI-AIR-Downstream/long-ke-t5-base-summarization_e10",
    device_map="auto",
    torch_dtype=torch.float16
)
print("모델 로딩 완료!")

# 2. 요약할 긴 텍스트
long_text = (
    "최근 국내 ICT 업계에서는 인공지능 기술을 이용한 다양한 서비스 개발이 빠르게 이루어지고 있습니다."
    "인공지능 챗봇, 음성 인식, 의료 데이터 분석, 자동 번역 시스템 등 여러 분야에서 활용도가 높아지고 있음은 물론,"
    "기존 업계의 경쟁구도 역시 크게 변화하고 있습니다. 특히 2025년 들어 대형 IT 기업들이 대규모 한국어 자연어처리"
    "모델을 공개함으로써, 소상공인과 중소기업들도 비교적 저렴한 비용으로 첨단 서비스를 도입할 수 있게 되었습니다."
    "전문가들은 향후 인공지능 기반 자동화 서비스가 금융, 법률, 교육 등 사회 전 영역으로 확산될 것으로 전망하고 있습니다. "
    "다만 데이터 품질 관리, 개인정보보호, 편향 문제 등 추가 논의가 필요한 과제도 적지 않으며, 관련 법과 정책의 마련이 중요하다는"
    "의견도 많습니다. 실제로 최근 논의된 국가 데이터댐 프로젝트와 AI 윤리 가이드라인은 산업 경쟁력 확보는 물론 사회적 신뢰 형성에"
    "기여할 것으로 평가받고 있습니다. 이러한 변화 속에서 우리 사회가 기술의 효율성과 인간 중심"
    "원칙 사이에서 균형을 어떻게 잡아 나갈지가 앞으로 주요 과제가 될 것입니다."
)


# 3. 모델을 사용해 요약 생성
result = pipe(long_text, max_length=100, num_return_sequences=1)

print("\n=== 원문 ===")
print(long_text)
print("\n=== 요약 결과 ===")
print(result[0]['generated_text'])

3️⃣ 실행결과

  • 가장 중요한 정보에 집중하여 간결한 요약을 작성했다.

  • 모델은 원문에 있는 문장을 그대로 사용하지 않고, 여러 문장의 핵심 구문과 단어를 재조합하여 새로운 문장을 만들었다.

  • 단순 추출 요약(Extractive)보다 발전된 추상 요약(Abstractive) 능력을 보여주었다.

💡 모델 테스트 후 느낀점

이번 기계학습 프로그래밍 과제를 통해 트랜스포머 아키텍처 기반 모델을 직접 조사하고 실습해 보았다. Hugging Face 생태계를 활용하여 인코더, 디코더, 인코더-디코더 모델을 테스트하며 배운 점과 느낀 점을 정리한다.

1. Hugging Face 활용의 용이성과 접근성

  • 처음에는 대규모 언어 모델(LLM)을 다루고 파인튜닝하는 일이 매우 복잡하고 어려울 것이라고 생각했지만, 실제로는 이미 파인튜닝된 모델을 가져와 준비한 데이터셋에 맞게 학습시키거나 바로 테스트하는 방법이여서 훨씬 간단했다. 괜히 겁을 먹었다는 생각이 들었다.

  • 모델을 로드하고 테스트 코드를 실행하는 시간이 오래 걸리지 않아 생각보다 빠르게 결과를 확인할 수 있었다.

2. 모델 탐색에서의 시간 투자

  • 실제 실습 과정 중 가장 많은 시간이 소요된 부분은 적합한 파인튜닝 모델을 찾는 일이었다.
  • hugging Face에 너무 많은 모델들이 있어서 원하는 작업에 최적화된 파인튜닝 모델을 찾는 과정에서 시간이 오래 걸렸다.

3. 데이터와 과적합(Overfitting) 경험

인코더 기반 모델(KoBERT)의 감정 분류 파인튜닝 실습을 통해 데이터의 중요성을 경험했다.

  • 극단적 과적합 경험: 8개의 매우 작은 샘플 데이터셋으로 5 Epoch을 훈련했을 때, 모델이 일반적인 감정 규칙을 배우지 못하고 훈련 데이터에 과적합(Overfitting)되는 결과가 나왔다. 테스트 결과의 확신도가 0.5대에 머물러 모델이 예측을 포기하는 수준이었다.

  • 향후 과제: 다음 실습에서는 더 많은 데이터셋을 준비하고 적절한 Epoch 수로 훈련해서 과적합 문제를 해결하고 더 높은 확신도의 결과를 만들고싶다.

4. 인코더-디코더 모델의 뛰어난 성능

인코더-디코더 기반 모델(KoT5)을 사용한 텍스트 요약 성능은 생각보다 더 좋았다.

  • KoT5 모델의 긴 문장의 핵심 내용을 파악하고 자연스러운 추상 요약 문장으로 출력하는 능력을 보고, 입력과 출력이 모두 시퀀스인 복잡한 작업(번역, 요약)에서 트랜스포머 아키텍처 모델의 강력함을 느꼈다.

댓글남기기