ko/1_instruction_tuning/notebooks/sft_finetuning_example.ipynb (271 lines of code) (raw):
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# SFTTrainer를 활용한 지도 학습 기반 미세 조정\n",
"\n",
"이 노트북은 `trl` 라이브러리에서 제공하는 `SFTTrainer`를 이용해 `HuggingFaceTB/SmolLM2-135M` 모델을 미세 조정하는 법을 설명합니다. 노트북 셀을 실행하면 모델이 미세 조정됩니다. 다른 데이터셋을 사용해 난이도를 조절할 수 있습니다.\n",
"\n",
"<div style='background-color: lightblue; padding: 10px; border-radius: 5px; margin-bottom: 20px; color:black'>\n",
" <h2 style='margin: 0;color:blue'>연습: SFTTrainer를 활용한 SmolLM2 미세 조정</h2>\n",
" <p>Hugging Face 허브에서 가져온 데이터셋으로 모델은 미세 조정해보세요. </p> \n",
" <p><b>난이도</b></p>\n",
" <p>🐢 `HuggingFaceTB/smoltalk` 데이터셋 사용해보기</p>\n",
" <p>🐕 `bigcode/the-stack-smol` 데이터셋의 하위 집합인 `data/python`을 활용해 코드 생성 모델 미세 조정해보기</p>\n",
" <p>🦁 실제 사용 사례와 관련된 관심 있는 데이터셋 사용해보기</p>\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Google Colab에서 requirements 설치\n",
"# !pip install transformers datasets trl huggingface_hub\n",
"\n",
"# Hugging Face 인증\n",
"\n",
"from huggingface_hub import login\n",
"login()\n",
"\n",
"# 허브 토큰을 HF_TOKEN 환경 변수로 설정해두면 편하게 사용할 수 있습니다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 주요 라이브러리 불러오기\n",
"from transformers import AutoModelForCausalLM, AutoTokenizer\n",
"from datasets import load_dataset\n",
"from trl import SFTConfig, SFTTrainer, setup_chat_format\n",
"import torch\n",
"\n",
"device = (\n",
" \"cuda\"\n",
" if torch.cuda.is_available()\n",
" else \"mps\" if torch.backends.mps.is_available() else \"cpu\"\n",
")\n",
"\n",
"# 모델과 토크나이저 불러오기\n",
"model_name = \"HuggingFaceTB/SmolLM2-135M\"\n",
"model = AutoModelForCausalLM.from_pretrained(\n",
" pretrained_model_name_or_path=model_name\n",
").to(device)\n",
"tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path=model_name)\n",
"\n",
"# 대화 형식 설정\n",
"model, tokenizer = setup_chat_format(model=model, tokenizer=tokenizer)\n",
"\n",
"# 미세 조정 결과를 저장하고 업로드하기 위한 이름 설정\n",
"finetune_name = \"SmolLM2-FT-MyDataset\"\n",
"finetune_tags = [\"smol-course\", \"module_1\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 기본 모델을 활용한 답변 생성\n",
"\n",
"여기서는 대화 템플릿이 없는 기본 모델을 사용해보겠습니다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 학습 전 기본 모델 테스트 진행\n",
"prompt = \"Write a haiku about programming\"\n",
"\n",
"# 템플릿으로 메시지 형식 지정\n",
"messages = [{\"role\": \"user\", \"content\": prompt}]\n",
"formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False)\n",
"\n",
"# 응답 생성\n",
"inputs = tokenizer(formatted_prompt, return_tensors=\"pt\").to(device)\n",
"outputs = model.generate(**inputs, max_new_tokens=100)\n",
"print(\"Before training:\")\n",
"print(tokenizer.decode(outputs[0], skip_special_tokens=True))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 데이터셋 준비\n",
"\n",
"샘플 데이터셋을 불러와서 학습을 위한 형식을 지정합니다. 데이터셋은 입력-출력 쌍으로 구성되어야 하며, 각 입력은 프롬프트이고 출력은 모델에서 예상되는 응답입니다. **TRL은 모델의 대화 템플릿에 맞게 입력 메시지 형식을 맞춥니다.** 메시지는 `role`과 `content` 키를 가진 딕셔너리 리스트로 표현되어야 합니다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 샘플 데이터셋 불러오기\n",
"from datasets import load_dataset\n",
"\n",
"# TODO: path와 name 파라미터를 이용해 데이터셋과 configuration 정의하기\n",
"ds = load_dataset(path=\"HuggingFaceTB/smoltalk\", name=\"everyday-conversations\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# TODO: 🦁 데이터셋이 TRL에서 대화 템플릿으로 변환할 수 있는 형식이 아니라면, 해당 데이터를 처리해야 합니다. 자세한 내용은 [모듈](../chat_templates.md)을 참고하세요."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## SFTTrainer 설정\n",
"\n",
"`SFTTrainer`는 학습 단계 수, 배치 크기, 학습률, 평가 방식과 같이 학습 과정을 제어하는 다양한 파라미터로 구성됩니다. 특정 요구 사항과 연산 자원에 맞춰 파라미터를 조정하세요. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# SFTTrainer를 위한 SFT configuration 설정\n",
"sft_config = SFTConfig(\n",
" output_dir=\"./sft_output\",\n",
" max_steps=1000, # 원하는 학습 시간과 데이터셋 크기에 따라 조정\n",
" per_device_train_batch_size=4, # GPU 메모리 용량에 따라 설정\n",
" learning_rate=5e-5, # 미세 조정을 위해 일반적으로 쓰이는 값\n",
" logging_steps=10, # 학습 지표 로깅 빈도\n",
" save_steps=100, # 모델 체크포인트 저장 빈도\n",
" evaluation_strategy=\"steps\", # 주기적인 모델 평가 설정\n",
" eval_steps=50, # 평가 빈도\n",
" use_mps_device=(\n",
" True if device == \"mps\" else False\n",
" ), # 혼합 정밀도 학습(mixed precision training)을 위한 MPS 사용\n",
" hub_model_id=finetune_name, # 모델 이름 설정\n",
")\n",
"\n",
"# SFTTrainer 초기화\n",
"trainer = SFTTrainer(\n",
" model=model,\n",
" args=sft_config,\n",
" train_dataset=ds[\"train\"],\n",
" tokenizer=tokenizer,\n",
" eval_dataset=ds[\"test\"],\n",
")\n",
"\n",
"# TODO: 🦁 🐕 선택한 데이터셋에 맞게 SFTTrainer 파라미터를 조절하세요. 예를 들어, `bigcode/the-stack-smol` 데이터셋을 사용하는 경우 `content` 열을 선택해야 합니다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 모델 학습\n",
"\n",
"트레이너가 구성되었기 때문에 이제 모델을 학습시킬 수 있습니다. 학습 과정은 데이터셋을 반복적으로 처리하며 손실을 계산하고, 이 손실을 최소화하기 위해 모델의 파라미터를 업데이트하는 과정을 포함합니다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 모델 학습\n",
"trainer.train()\n",
"\n",
"# 모델 저장\n",
"trainer.save_model(f\"./{finetune_name}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"trainer.push_to_hub(tags=finetune_tags)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div style='background-color: lightblue; padding: 10px; border-radius: 5px; margin-bottom: 20px; color:black'>\n",
" <h2 style='margin: 0;color:blue'>추가 연습: 미세 조정 모델로 응답 생성하기</h2>\n",
" <p>🐕 기본 예제에서와 마찬가지로 미세 조정된 모델을 사용하여 응답을 생성해보세요.</p>\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 동일한 프롬프트로 미세 조정된 모델을 테스트해보세요.\n",
"\n",
"# 학습 전 기본 모델 테스트 진행\n",
"prompt = \"Write a haiku about programming\"\n",
"\n",
"# 템플릿으로 메시지 형식 지정\n",
"messages = [{\"role\": \"user\", \"content\": prompt}]\n",
"formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False)\n",
"\n",
"# 응답 생성\n",
"inputs = tokenizer(formatted_prompt, return_tensors=\"pt\").to(device)\n",
"\n",
"# TODO: 기본 예제에서 했던 것처럼 미세 조정된 모델을 사용해 응답을 생성해보세요."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 💐 완료!\n",
"\n",
"이 노트북은 `SFTTrainer`를 사용하여 `HuggingFaceTB/SmolLM2-135M` 모델을 미세 조정하는 단계별 가이드를 제공합니다. 이 단계를 따라 특정 작업을 보다 효과적으로 수행하도록 모델을 조정할 수 있습니다. 이 과정을 계속 진행하려면 다음 단계를 시도해 보세요:\n",
"\n",
"- 더 어려운 방법으로 노트북 실습해보기\n",
"- 동료의 PR 검토하기\n",
"- 이슈 또는 PR을 통해 자료 개선하기"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "py310",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}