목차
오늘은 파인튜닝(fine-tuning)을 다시한번 실행해 보도록 하겠습니다. 지난 번에는 Llama3.2 1b 모델을 기준으로 저사양 PC에서 8일이나 걸려서 진행해 봤죠. 물론, 그 때의 결과는 사실 그다지 좋지 못했어요. 로컬PC 사양으로 다시 실행할 수 없었기 때문에 단 한번 실행한 결과만을 살펴봤었죠. 이번에는 더 작은 생성형AI를 기준으로 한국어 글쓰기 파인튜닝을 테스트해 볼게요.

Qwen3-0.6B 파인튜닝 단계별 실습 #2-1
파인튜닝(Fine-tuning)
파인튜닝(fine-tuning)은 말 그대로 이미 학습된 모델(Pre-trained Model)을 특정한 목적에 맞게 미세 튜닝을 하는 거예요. 마치 대학에서 전공을 하고, 그 전공이나 관련 학문을 더 세밀하게 공부하기 위해 대학원에 가는 것 처럼 말이죠. 때문에 이러한 파인튜닝을 통해 생성된 모델은 특정 도메인(예: 법률, 의료)이나 특정 과제(예: 한국어 문장 생성, 챗봇 대화)에 더 고도화된 성능을 보이게 됩니다.
파인튜닝(fine-tuning) 과정을 요약해 보면 다음과 같습니다.
- 개발 목표 설정: 예를 들어, 한국어 능력 향상, 한글 글쓰기, 법률 자문하기 등 특정한 목표를 세웁니다.
- 모델 및 토크나이저 선택: 파인튜닝의 기반이 될 사전 학습 모델을 허깅페이스 Hub에서 선택하고 불러옵니다.
- 데이터셋 준비 및 전처리: 학습에 사용할 한국어 글쓰기 데이터셋을 준비하고, 모델이 이해할 수 있는 형태로 가공(토크나이징)합니다.
- 학습 설정 및 실행: 학습 관련 하이퍼파라미터를 설정하고 Trainer API를 사용하여 파인튜닝을 진행합니다.
- 모델 저장 및 추론: 파인튜닝된 모델을 저장하고, 새로운 텍스트를 생성하는 테스트를 진행합니다.
이글에서는 한글 글쓰기 능력 향상을 목표로 하고 파인튜닝 과정을 이야기해 보도록 하겠습니다.
모델 및 토크나이저 선택 및 불러오기
파인튜닝의 시작은 좋은 기반 모델을 선택하는 것입니다. 한국어 글쓰기 능력 향상을 목표로 하므로, 일단 한국어는 어느정도 학습된 모델이어야 합니다. 한국어를 전혀 모르는 모델이라면 다국어나 한국어 능력부터 주입해야 하기 때문이죠. 이때는 파인튜닝이 아니라 Pre-training 만큼 매우 큰 리소스로 학습을 해야합니다.
또, 개인 PC에서 fine-tuning을 수행할 것이므로 모델의 사이즈도 작아야 합니다. 물론 물리적인 용량도 작으면 좋겠죠. 때문에 여기서는 Qwen에서 공개한 Qwen3-0.6b 모델을 선택했습니다.
핵심 클래스: AutoTokenizer & AutoModelForCausalLM
- AutoTokenizer: 모델 이름이나 경로를 입력하면, 허깅페이스 Hub에서 해당 모델에 맞는 토크나이저 클래스를 자동으로 찾아 인스턴스를 생성해 줍니다.
- AutoModelForCausalLM: 인과 관계 언어 모델링(Causal Language Modeling), 즉 다음에 올 단어를 예측하는 텍스트 생성 과제를 위한 모델 구조를 자동으로 불러옵니다. AutoModelForSequenceClassification (문서 분류), AutoModelForQuestionAnswering (질의응답) 등 과제에 맞는 다양한 Auto* 모델 클래스가 존재합니다.
위 핵심 클래스를 사용한 코드 예를 볼게요.
from transformers import AutoTokenizer, AutoModelForCausalLM
# 사용할 모델의 이름
model_name = "Qwen/Qwen3-0.6B"
# 1. 토크나이저 불러오기
# from_pretrained() 메서드를 사용해 허깅페이스 Hub에서 모델에 맞는 토크나이저를 다운로드합니다.
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 2. 모델 불러오기
# from_pretrained() 메서드를 사용해 사전 학습된 가중치를 포함한 모델을 다운로드합니다.
model = AutoModelForCausalLM.from_pretrained(model_name)
# 이는 모델이 문장의 끝을 학습하고 생성 시 적절히 끊도록 돕는 중요한 전처리 과정입니다.
tokenizer.pad_token = tokenizer.eos_token
데이터셋 준비 및 전처리
여기서는 간단한 한국어 문장 리스트를 데이터셋으로 사용한다고 가정하겠습니다. 실제 데이터셋은 Ai-Hub에서 글쓰기 관련 데이터셋을 다운로드해서 사용했습니다. 데이터셋은 cvs 포멧과 json 포멧으로 이루어져 있습니다. 여기에서는 간단한 한국어 문장 리스트를 데이터셋으로 사용한다고 가정하겠습니다.
from datasets import Dataset
# 예시 데이터셋 (실제로는 파일에서 읽어오거나 허깅페이스 datasets 라이브러리로 로드)
texts = [
"오늘은 날씨가 좋아서 산책하기 좋은 날입니다.",
"허깅페이스 트랜스포머 라이브러리는 정말 강력한 도구입니다.",
"맛있는 저녁 식사를 위해 레시피를 찾아보고 있습니다.",
"인공지능 모델을 파인튜닝하는 과정은 매우 흥미롭습니다.",
"이 가이드를 통해 많은 것을 배울 수 있기를 바랍니다."
]
# 파인튜닝을 위해 데이터셋을 Dictionary 형태로 구성
data = {"text": texts}
# Hugging Face의 Dataset 객체로 변환
dataset = Dataset.from_dict(data)
토크나이징 (Tokenization)
LLM 모델은 글자(text)를 직접 이해할 수 없죠. 이 블로그를 보시는 분들에게는 이제 너무나 당연한 얘기일 거예요. 이러한 LLM들은 텍스트를 토큰(token)이라는 숫자 단위로 변환하고, 이를 다시 모델의 입력으로 사용되는 ID(숫자)로 매핑하는 과정이 거치게 된다는 것을 말이죠. 이 과정을 한마디로 토크나이징이라고 합니다.
def preprocess_function(examples):
# tokenizer는 텍스트를 모델이 이해할 수 있는 input_ids, attention_mask 등으로 변환합니다.
# - truncation=True: 모델의 최대 입력 길이를 초과하는 텍스트는 잘라냅니다.
# - padding="max_length": 배치 내 다른 문장들과 길이를 맞추기 위해 최대 길이까지 PAD 토큰을 채웁니다.
# - max_length: 모델이 한 번에 처리할 수 있는 최대 토큰 길이입니다.
return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=128)
# dataset.map() 메서드를 사용하여 모든 샘플에 대해 전처리 함수를 일괄 적용합니다.
tokenized_dataset = dataset.map(preprocess_function, batched=True, remove_columns=dataset.column_names)
# 전처리 결과 확인
print(tokenized_dataset[0])
# 출력 예시: {'input_ids': [30123, 1025, ...], 'attention_mask': [1, 1, ...]}
- input_ids: 텍스트가 변환된 토큰 ID의 시퀀스입니다.
- attention_mask: 해당 토큰이 실제 단어인지(1), 아니면 길이를 맞추기 위한 패딩(padding)인지(0)를 나타냅니다.
파인튜닝(fine-tuning) 실행
이제 Trainer API를 사용하여 실제 학습을 진행합니다. Trainer는 복잡한 PyTorch 학습 루프(loop)를 몇 줄의 코드로 쉽게 fine-tuning을 실행할 수 있도록 합니다.
핵심 클래스: TrainingArguments & Trainer
- TrainingArguments: 파인튜닝 과정에 필요한 모든 하이퍼파라미터와 설정을 담는 클래스입니다.
- output_dir: 학습된 모델과 체크포인트가 저장될 디렉토리 경로.
- num_train_epochs: 전체 데이터셋에 대한 학습 횟수(에포크).
- per_device_train_batch_size: 학습 시 GPU(또는 CPU) 당 배치 크기.
- logging_steps: 지정된 스텝 수마다 학습 손실(loss) 등 로그를 출력.
- evaluation_strategy: 평가를 언제 수행할지 결정 (‘no’, ‘steps’, ‘epoch’).
- Trainer: 모델, 학습 설정(TrainingArguments), 데이터셋, 토크나이저 등을 받아 실제 학습 과정을 관리하고 실행하는 핵심 클래스입니다.
from transformers import TrainingArguments, Trainer, DataCollatorForLanguageModeling
# 1. 학습 설정(TrainingArguments) 정의
training_args = TrainingArguments(
output_dir="./fine_tuned_qwen3_0.6b", # 모델 출력 디렉토리
num_train_epochs=3, # 총 에포크 수
per_device_train_batch_size=2, # GPU 당 배치 사이즈
logging_dir='./logs', # 로그 저장 디렉토리
logging_steps=100, # 100 스텝마다 로그 기록
)
# 2. 데이터 콜레이터(Data Collator) 설정
# DataCollatorForLanguageModeling은 텍스트 생성 과제를 위한 데이터 배치를 동적으로 구성합니다.
# 특히, 라벨(labels)을 자동으로 생성하고 MLM(Masked Language Modeling) 옵션을 관리합니다.
# mlm=False로 설정하면 Causal Language Modeling(다음 단어 예측)을 수행합니다.
data_collator = DataCollatorForLanguageModeling(
tokenizer=tokenizer,
mlm=False
)
# 3. Trainer 정의
trainer = Trainer(
model=model, # fine-tuning할 모델
args=training_args, # 위에서 정의한 학습 설정
train_dataset=tokenized_dataset["train"], # 학습 데이터셋
eval_dataset=tokenized_dataset["validation"], # 평가 데이터셋 (필요 시)
data_collator=data_collator, # 데이터 콜레이터
)
# 4. 파인튜닝 시작
trainer.train()
# 5. 최종 모델 저장
trainer.save_model("output_dir")
tokenizer.save_pretrained("output_dir")
여기까지 코드를 작성하고 실행하면 데이터셋이나 모델의 크기에 따라 몇 시간에서 몇 일이 소요됩니다. 코드만 보면 간단하지만, 실제 파인튜닝의 결과가 만족할 만큼의 결과를 얻기 위해서는 셀 수 없는 시행착오가 반복됩니다. 지금 실행 중인 fine-tuning 역시 아직은 결과를 얻지 못했어요. 앞으로 7시간 정도 더 시간이 지나야 결과를 한번 볼 수 있을 것 같습니다.
때문에 다음 글에서 실제 Qwen3 0.6B 모델로 한국어 글쓰기 파인튜닝한 결과를 분석해 보도록 하죠.