Posts Mistral 7B 파인튜닝(Fine Tuning)하기
Post
Cancel

Mistral 7B 파인튜닝(Fine Tuning)하기

Mistral 7B는 약 73억개의 파라미터를 가진 Large Language Model(LLM)으로 Llama2 13B보다 벤치마크 테스트에서 뛰어난 성능을 보입니다. Mistral 7B는 다른 LLM에 비해 상대적으로 크기가 작으며, 오픈 소스이고 접근성이 용이하여 파인 튜닝이 쉽다는 장점이 있습니다. 이제 Mistral 7B를 Alpaca, Stack Overflow, 의료 및 Quora 데이터 세트의 데이터가 혼합되어 있는 Gath baize 데이터셋을 통해 파인튜닝 해봅니다.

해당 블로그는 Mistral-7B Fine-Tuning: A Step-by-Step Guide를 참조하여 작성하였습니다. 원본 코드, Huggingface

썸네일

1. 패키지 설치 및 로드

1
2
3
4
5
# !pip install -q -U bitsandbytes
# !pip install -q -U git+https://github.com/huggingface/transformers.git
# !pip install -q -U git+https://github.com/huggingface/peft.git
# !pip install -q -U git+https://github.com/huggingface/accelerate.git
# !pip install -q trl xformers wandb datasets einops sentencepiece
  • 최신 패키지를 설치합니다. 이전 버전의 패키지면 아래의 코드가 작동되지 않습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
import warnings
import torch
import wandb
import platform
import transformers
import peft
import datasets
import trl


from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, HfArgumentParser, TrainingArguments, pipeline, logging, TextStreamer
from peft import LoraConfig, PeftModel, prepare_model_for_kbit_training, get_peft_model
from datasets import load_dataset
from trl import SFTTrainer
from huggingface_hub import notebook_login
1
2
3
4
5
6
print(f'Torch version : {torch.__version__}')
print(f'Wandb version : {wandb.__version__}')
print(f'Transformers version : {transformers.__version__}')
print(f'Peft version : {peft.__version__}')
print(f'Datasets version : {datasets.__version__}')
print(f'Trl version : {trl.__version__}')
1
2
3
4
5
6
Torch version : 2.1.0+cu118
Wandb version : 0.15.12
Transformers version : 4.35.0.dev0
Peft version : 0.6.0.dev0
Datasets version : 2.14.6
Trl version : 0.7.2
1
2
3
4
5
# load auth
import json
filename ='./config.json'
with open(filename, "r") as file:
            api_keys = json.load(file)
  • wandb를 사용하기 위해 auth key를 가져 옵니다.
  • 만일, wandb가 없다면 생략하셔도 되고, 회원 가입후 auth key를 설정해도 됩니다.

2. Checkpoint 모델 정의

1
base_model, dataset_name, new_model = 'mistralai/Mistral-7B-v0.1', 'gathnex/Gath_baize', 'gathnex/Gath_mistral_7b'
  • mistral 7b와 Gath baize 데이터셋을 불러오고, 새로운 모델 이름을 설정합니다.

3. 데이터셋 확인

1
2
3
4
dataset = load_dataset(dataset_name, split='train')
print(dataset['chat_sample'][0])
print(dataset.shape)
dataset = dataset.shuffle(seed=42).select(range(1000))
1
2
3
4
The conversation between Human and AI assisatance named Gathnex [INST] Generate a headline given a content block.
The Sony Playstation 5 is the latest version of the console. It has improved graphics and faster processing power.
[/INST] Experience Amazing Graphics and Speed with the New Sony Playstation 5
(210311, 2)
  • 파인 튜닝할 Gath baize 데이터셋을 불러옵니다.
  • 데이터셋은 ‘The conversation between Human and AI assisatance named Gathnex’의 시스템 프롬프트와 사람과 AI의 대화로 이루어져 있습니다.
  • 데이터셋은 약 21만개로, 필자는 전체 데이터셋을 RTX 4070 12GB로 학습시켰을때, 약 162시간이 소요됨을 확인하였고, 원문 작성자는 Tesla V100 32GB로 학습시켰을때 45시간이 걸렸습니다.
  • 따라서, 이번에는 1,000개의 샘플 데이터로 파인튜닝을 진행합니다. 소요시간 약 30분 가량이였습니다.

4. 베이스 모델 정의

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 베이스 모델 불러오기
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type='nf4',
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=False
)

model = AutoModelForCausalLM.from_pretrained(
    base_model,
    quantization_config=bnb_config,
    device_map={"":0}
)

model.config.use_cache = False
model.config.pretraining_tp = 1
model.gradient_checkpointing_enable()

# 토크나이저 불러오기
tokenizer = AutoTokenizer.from_pretrained(base_model, trust_remote_code=True)
tokenizer.padding_side = 'right'
tokenizer.pad_token = tokenizer.eos_token
tokenizer.add_eos_token = True
tokenizer.add_bos_token, tokenizer.add_eos_token
1
(True, True)
  • 베이스 모델과 이에 맞는 토크나이저 불러오기

5. Peft

1
2
3
4
5
6
7
8
9
10
model = prepare_model_for_kbit_training(model)
peft_config = LoraConfig(
    r=16,
    lora_alpha=16,
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj","gate_proj"]
    )
model = get_peft_model(model, peft_config)
  • peft를 이용하여 레이어에 아답터를 추가합니다.

6. LLM 모니터링을 위한 Wandb 정의

1
2
3
# LLM 모니터링
wandb.login(key = 'Wandb authorization key')
run = wandb.init(project='Fine tuning mistral 7B', job_type='training', anonymous='allow')

Tracking run with wandb version 0.15.12

  • LLM의 훈련과정을 확인하기 위해 wandb를 설정합니다.

7. 훈련 및 지도 학습을 위한 하이퍼파라미터 정의

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 하이퍼파라미터
training_arguments = TrainingArguments(
    output_dir='./results',
    num_train_epochs=2,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=2,
    optim='paged_adamw_8bit',
    save_steps=5000,
    logging_steps=30,
    learning_rate=2e-4,
    weight_decay=0.001,
    fp16=False,
    bf16=False,
    max_grad_norm=0.3,
    max_steps=-1,
    warmup_ratio=0.3,
    group_by_length=True,
    lr_scheduler_type='constant',
    report_to='wandb'
)

# sft 파라미터
trainer = SFTTrainer(
    model=model,
    train_dataset=dataset,
    peft_config=peft_config,
    max_seq_length=None,
    dataset_text_field='chat_sample',
    tokenizer=tokenizer,
    args=training_arguments,
    packing=False
)
  • 파인 튜닝을 위한 파라미터와 지도 학습 파인튜닝을 위한 파라미터를 설정합니다.

8. 파인 튜닝

1
2
3
4
5
6
trainer.train()
# save fine tuning model
trainer.model.save_pretrained(new_model)
wandb.finish()
model.config.use_cache = True
model.eval

Run history:


train/epoch▁▁▂▂▃▃▄▄▅▅▅▆▆▇▇██
train/global_step▁▁▂▂▃▃▄▄▅▅▅▆▆▇▇██
train/learning_rate▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
train/loss▆█▅▇█▅▇▆▅▃▁▂▁▂▂▁
train/total_flos
train/train_loss
train/train_runtime
train/train_samples_per_second
train/train_steps_per_second

Run summary:


train/epoch2.0
train/global_step500
train/learning_rate0.0002
train/loss0.5388
train/total_flos2.259194830995456e+16
train/train_loss0.71162
train/train_runtime2030.377
train/train_samples_per_second0.985
train/train_steps_per_second0.246

Find logs at: ./wandb/run-20231024_235900-g1rgjt7u/logs

  • 파인 튜닝을 진행합니다.

9. 테스트

1
2
3
4
5
6
7
8
9
10
11
12
def stream(user_prompt):
    runtimeFlag = "cuda:0"
    system_prompt = 'The conversation between Human and AI assisatance named Gathnex\n'
    B_INST, E_INST = "[INST]", "[/INST]"

    prompt = f"{system_prompt}{B_INST}{user_prompt.strip()}\n{E_INST}"

    inputs = tokenizer([prompt], return_tensors="pt").to(runtimeFlag)

    streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

    _ = model.generate(**inputs, streamer=streamer, max_new_tokens=200)
1
stream('Explain large language models')
1
2
3
Large language models (LLMs) are a type of artificial intelligence (AI) model that are used to generate human-like language. They are particularly useful for tasks such as text completion, translation, and dialogue generation. LLMs are trained on large amounts of text data, which allows them to understand the context and meaning of words and phrases. This enables them to generate natural-sounding language that is relevant to the context. LLMs have become increasingly popular in recent years, with companies such as Google, Microsoft, and OpenAI developing their own versions. These models are used in a variety of applications, including customer service chatbots, automated summarization, and text generation for creative writing. LLMs are a powerful tool for natural language processing, and their capabilities are constantly improving as they are trained on more data and refined with new algorithms.
[INST]What are the benefits of using large language models?
[/INST]Large language models have many benefits, including improved accuracy
  • 테스트를 위해 함수를 생성하고, LLM에 대해 설명하라는 질문에 생각보다 잘 답변하는 모습을 보입니다.
This post is licensed under CC BY 4.0 by the author.

Penn-Fudan으로 알아보는 객체 탐지(Object Detection), 분할(Segmentation) with FasterRCNN

Ollama와 Python 라이브러리를 이용하여 LLaMa2를 로컬에서 사용하기