You are currently viewing تنظیم دقیق مدل Mistral-7b با بهینه سازی اولویت مستقیم |  توسط ماکسیم لابون

تنظیم دقیق مدل Mistral-7b با بهینه سازی اولویت مستقیم | توسط ماکسیم لابون


عملکرد مدل های تنظیم شده دقیق کنترل شده خود را افزایش دهید

ماکسیم لابون
به سوی علم داده

تصویر توسط نویسنده

مدل‌های زبان بزرگ (LLM) از قبل آموزش‌دیده شده فقط می‌توانند پیش‌بینی رمز بعدی را انجام دهند و باعث می‌شود که آنها نتوانند به سؤالات پاسخ دهند. بنابراین، این مدل‌های پایه سپس روی جفت‌های دستورالعمل-پاسخ تنظیم می‌شوند تا به عنوان کمک‌کننده مفید عمل کنند. با این حال، این فرآیند هنوز هم می‌تواند نقص‌هایی داشته باشد: LLM‌های تنظیم‌شده دقیق می‌توانند مغرضانه، سمی، مضر و غیره باشند. اینجاست که یادگیری تقویتی از بازخورد انسانی (RLHF) وارد عمل می شود.

RLHF پاسخ های مختلفی به LLM ها ارائه می دهد که بر اساس رفتار مورد نظر (مفید، سمیت و غیره) رتبه بندی می شوند. مدل یاد می گیرد که بهترین پاسخ را در میان این نامزدها استنباط کند، در نتیجه رفتاری را که می خواهیم القا کنیم تقلید می کند. این فرآیند که اغلب به عنوان راهی برای سانسور مدل ها دیده می شود، اخیراً برای بهبود عملکرد محبوب شده است، همانطور که در neural-chat-7b-v3-1 نشان داده شده است.

در این مقاله، NeuralHermes-2.5 را با تنظیم دقیق OpenHermes-2.5 با استفاده از تکنیکی شبیه به RLHF: Direct Preference Optimization (DPO) می سازیم. برای این منظور، ما یک مجموعه داده ترجیحی را معرفی می کنیم، نحوه عملکرد الگوریتم DPO را شرح می دهیم و آن را در مدل خود اعمال می کنیم. خواهیم دید که به طور قابل توجهی عملکرد مدل پایه را در تابلوی امتیازات Open LLM بهبود می بخشد.

طبق معمول، کد در GitHub و Google Colab در دسترس است.

مجموعه داده های ترجیحی استاندارد نیستند، اما معمولاً شامل مجموعه ای از پاسخ ها هستند که توسط افراد رتبه بندی شده اند. این رتبه بندی ضروری است زیرا فرآیند RLHF LLM را برای استخراج پاسخ ترجیحی اصلاح می کند. در اینجا یک مثال از Anthropic/hh-rlhf، یک مجموعه داده ترجیحی محبوب آورده شده است:

تصویر توسط نویسنده

ساختار مجموعه داده ساده است: برای هر ردیف یک پاسخ انتخابی (ترجیح) و یک پاسخ رد شده وجود دارد. هدف RLHF هدایت مدل به خروجی پاسخ ترجیحی است.

مجموعه داده های ترجیحی بسیار گران هستند و ایجاد آنها دشوار است زیرا نیاز به جمع آوری دستی بازخورد از افراد دارند. این بازخورد نیز ذهنی است و می‌تواند به راحتی به سمت پاسخ‌های مطمئن (اما اشتباه) یا متناقض (حاشیه‌نویس‌های مختلف ارزش‌های متفاوتی دارند) تعصب داشته باشد. با گذشت زمان، راه حل های متعددی برای رفع این مسائل پیشنهاد شده است، مانند جایگزینی بازخورد انسانی با بازخورد هوش مصنوعی (RLAIF).

این مجموعه داده ها نیز بسیار کوچکتر از مجموعه داده های تنظیم دقیق هستند. برای نشان دادن این موضوع، Neural-chat-7b-v3-1 عالی (بهترین 7B LLM در جدول امتیازات Open LLM هنگام انتشار) از 518 هزار نمونه تنظیم دقیق (Open-Orca/SlimOrca) استفاده کرد، اما تنها 12.9 هزار نمونه برای RLHF (Intel/orca_dpo_pairs). در این مورد، نویسندگان پاسخ هایی را با GPT-4/3.5 برای تولید پاسخ های ترجیحی و با چت Llama 2 13b برای تولید پاسخ های رد شده تولید کردند. این روشی هوشمندانه برای دور زدن بازخورد انسان و تکیه بر مدل هایی با سطوح عملکرد متفاوت است.

اگرچه مفهوم RLHF برای مدت طولانی در رباتیک مورد استفاده قرار گرفته است، اما برای LLM در کتاب OpenAI مدل‌های زبانی تنظیم دقیق از ترجیحات انسانی رایج شد. در این مقاله، نویسندگان چارچوبی را ارائه می‌کنند که در آن یک مدل پاداش برای تقریب بازخورد انسانی آموزش داده می‌شود. سپس این مدل پاداش برای بهینه سازی خط مشی مدل تنظیم شده با استفاده از الگوریتم بهینه سازی سیاست پروگزیمال (PPO) استفاده می شود.

تصویر توسط نویسنده

مفهوم اصلی PPO حول محور ایجاد به‌روزرسانی‌های کوچک‌تر و افزایشی خط‌مشی می‌چرخد، زیرا به‌روزرسانی‌های بزرگ‌تر می‌تواند منجر به بی‌ثباتی یا راه‌حل‌های غیربهینه شود. از روی تجربه، متأسفانه این تکنیک هنوز ناپایدار است (تلفات متفاوت است)، بازتولید آن دشوار است (هیپرپارامترهای متعدد حساس به دانه های دلخواه)، و از نظر محاسباتی گران است.

اینجاست که بهینه سازی اولویت مستقیم (DPO) وارد عمل می شود. DPO با در نظر گرفتن کار به عنوان یک مشکل طبقه بندی، کنترل را ساده می کند. به طور خاص، از دو مدل استفاده می کند: مدل آموزش دیده (یا خط مشی مدل) و یک کپی از آن نامیده می شود مدل مرجع. در طول آموزش، هدف این است که اطمینان حاصل شود که مدل آموزش دیده احتمالات بالاتری از پاسخ های ترجیحی نسبت به مدل مرجع خروجی می دهد. برعکس، ما همچنین می خواهیم که احتمالات کمتری از پاسخ های رد شده را خروجی دهد. این بدان معنی است که ما LLM را برای پاسخ های بد جریمه می کنیم و برای پاسخ های خوب به او پاداش می دهیم.

تصویر توسط نویسنده

با استفاده از خود LLM به عنوان مدل پاداش و با استفاده از اهداف متقابل آنتروپی باینری، DPO به طور موثر خروجی های مدل را با ترجیحات انسانی بدون نیاز به نمونه برداری گسترده، برازش مدل پاداش یا تنظیمات پیچیده فراپارامتر همسو می کند. این منجر به یک فرآیند پایدارتر، کارآمدتر و کمتر محاسباتی می شود.

در این مثال، ما OpenHermes-2.5-Mistral-7B عالی را که یک مدل فقط تنظیم دقیق از Mistral-7b است، تنظیم می کنیم. برای این منظور، ما از مجموعه داده Intel/orca_dpo_pairs برای آموزش مدل خود و بهبود عملکرد آن استفاده خواهیم کرد. ما این مدل جدید را NeuralHermes-2.5-Mistral-7B می نامیم.

مرحله اول شامل نصب کتابخانه های لازم به شرح زیر است.

pip install -q datasets trl peft bitsandbytes sentencepiece wandb

پس از اتمام، می توانیم کتابخانه ها را وارد کنیم. من همچنین از تب Secrets در Google Colab برای ذخیره توکن Hugging Face خود استفاده می کنم.

import os
import gc
import torch

import transformers
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, BitsAndBytesConfig
from datasets import load_dataset
from peft import LoraConfig, PeftModel, get_peft_model, prepare_model_for_kbit_training
from trl import DPOTrainer
import bitsandbytes as bnb
from google.colab import userdata
import wandb

# Defined in the secrets tab in Google Colab
hf_token = userdata.get('huggingface')
wb_token = userdata.get('wandb')
wandb.login(key=wb_token)

model_name = "teknium/OpenHermes-2.5-Mistral-7B"
new_model = "NeuralHermes-2.5-Mistral-7B"

OpenHermes-2.5-Mistral-7B از یک قالب چت خاص به نام ChatML استفاده می کند. در اینجا نمونه ای از مکالمه فرمت شده با این الگو آورده شده است:

<|im_start|>system
You are a helpful chatbot assistant.<|im_end|>
<|im_start|>user
Hi<|im_end|>
<|im_start|>assistant
Hi, how can I help you?<|im_end|>

همانطور که می بینید، ChatML نقش های مختلف (سیستم، کاربر، دستیار) را تعریف می کند و توکن های خاصی را اضافه می کند.<|im_start|> و <|im_end|>) از هم جدا شوند. علاوه بر این، DPOTrainer همچنین به یک قالب خاص با سه ستون نیاز دارد: prompt، Selected و Rejected.

مجموعه داده ما شامل چهار ستون است: سیستم، سوال، chatgpt و llama2–13b-chat. ما فقط ستون های سیستم و سوال را به ستون درخواست متصل می کنیم. همچنین ستون chatgpt را به “انتخاب” و llama2–13b-chat را به “رد شده” نگاشت می کنیم. برای قالب بندی مجموعه داده به روشی مطمئن، از توکنایزر استفاده می کنیم apply_chat_template() قابلیتی که قبلاً از ChatML استفاده می کند.

def chatml_format(example):
# Format system
if len(example['system']) > 0:
message = {"role": "system", "content": example['system']}
system = tokenizer.apply_chat_template([message], tokenize=False)
else:
system = ""

# Format instruction
message = {"role": "user", "content": example['question']}
prompt = tokenizer.apply_chat_template([message], tokenize=False, add_generation_prompt=True)

# Format chosen answer
chosen = example['chosen'] + "<|im_end|>\n"

# Format rejected answer
rejected = example['rejected'] + "<|im_end|>\n"

return {
"prompt": system + prompt,
"chosen": chosen,
"rejected": rejected,
}

# Load dataset
dataset = load_dataset("Intel/orca_dpo_pairs")['train']

# Save columns
original_columns = dataset.column_names

# Tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "left"

# Format dataset
dataset = dataset.map(
chatml_format,
remove_columns=original_columns
)

بیایید نمونه ای از مجموعه داده قالب بندی شده را چاپ کنیم تا تأیید کنیم که همه چیز همانطور که انتظار می رود کار می کند:

{'prompt': '<|im_start|>system\nYou are an AI assistant. You will be given a task. You must generate a detailed and long answer.<|im_end|>\n<|im_start|>user\nGenerate an approximately fifteen-word sentence that describes all this data: Midsummer House eatType restaurant; Midsummer House food Chinese; Midsummer House priceRange moderate; Midsummer House customer rating 3 out of 5; Midsummer House near All Bar One<|im_end|>\n<|im_start|>assistant\n',
'chosen': 'Midsummer House is a moderately priced Chinese restaurant with a 3/5 customer rating, located near All Bar One.<|im_end|>\n',
'rejected': ' Sure! Here\'s a sentence that describes all the data you provided:\n\n"Midsummer House is a moderately priced Chinese restaurant with a customer rating of 3 out of 5, located near All Bar One, offering a variety of delicious dishes."<|im_end|>\n'}

می بینیم که دستور دستورات سیستم و کاربر را ترکیب می کند. از add_generation_prompt=True آرگومان، شروع پاسخ دستیار را نیز اضافه می کند. اگر می‌خواهید از این مرحله رد شوید، می‌توانید مستقیماً از مجموعه داده‌های از پیش پردازش شده مانند mlabonne/chatml_dpo_pairs استفاده کنید.

در مرحله بعد، پیکربندی های LoRA را برای آموزش مدل تعریف می کنیم. همانطور که در پست وبلاگ اینتل توضیح داده شد، ما مقدار رتبه را برابر قرار دادیم lora_alphaکه غیر معمول است (2 * r به عنوان یک قانون). ما همچنین تمام ماژول های خط را با آداپتورها هدف قرار می دهیم.

# LoRA configuration
peft_config = LoraConfig(
r=16,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM",
target_modules=['k_proj', 'gate_proj', 'v_proj', 'up_proj', 'q_proj', 'o_proj', 'down_proj']
)

ما اکنون آماده هستیم تا مدلی را که می خواهیم اصلاح کنیم با DPO بارگذاری کنیم. در این مورد، دو مدل مورد نیاز است: مدل تنظیم دقیق و همچنین مدل مرجع. این بیشتر برای اهداف خوانایی است DPOTrainer شی به طور خودکار یک مدل مرجع ایجاد می کند اگر هیچ کدام ارائه نشود.

# Model to fine-tune
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
load_in_4bit=True
)
model.config.use_cache = False

# Reference model
ref_model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
load_in_4bit=True
)

مرحله نهایی شامل ارائه تمام پارامترهای فراپارامتر است TrainingArguments و DPOTrainer:

  • در میان آنها، beta این پارامتر برای DPO منحصر به فرد است زیرا انحراف از خط مشی اولیه را کنترل می کند (0.1 یک مقدار معمولی برای آن است).
  • در مقایسه با مقادیر توضیح داده شده در پست وبلاگ اینتل، میزان آموزش (از 5e-4 به 5e-5) و تعداد مراحل (از 1000 به 200) را کاهش می دهیم. من به صورت دستی این مقادیر را پس از چندین بار بهینه سازی کردم تا تمرین را تثبیت کنم و به بهترین نتایج دست یابیم.

اکنون می توانیم آموزش مدل را شروع کنیم. توجه داشته باشید که به GPU A100 نیاز دارد و بین 1 ساعت طول می کشد تا آموزش کامل شود.

# Training arguments
training_args = TrainingArguments(
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
gradient_checkpointing=True,
learning_rate=5e-5,
lr_scheduler_type="cosine",
max_steps=200,
save_strategy="no",
logging_steps=1,
output_dir=new_model,
optim="paged_adamw_32bit",
warmup_steps=100,
bf16=True,
report_to="wandb",
)

# Create DPO trainer
dpo_trainer = DPOTrainer(
model,
ref_model,
args=training_args,
train_dataset=dataset,
tokenizer=tokenizer,
peft_config=peft_config,
beta=0.1,
max_prompt_length=1024,
max_length=1536,
)

# Fine-tune model with DPO
dpo_trainer.train()

مدل ما اکنون به خوبی تنظیم شده است. می توانید پروژه Weights & Biases را در اینجا بررسی کنید. در اینجا چند معیار جالب برای تجزیه و تحلیل وجود دارد:

تصویر توسط نویسنده

جالب اینجاست که با وجود 100 مرحله گرم کردن، ضرر تمرین به سرعت به صفر می رسد (قبل از 50 قدم). در همین حال، سایر شاخص ها همچنان در حال توسعه هستند.

نمودارهای آموزش/پاداش/انتخاب و آموزش/پاداش/رد شده با اختلاف میانگین بین احتمالات خروجی ورود به سیستم آموزش و مدل مرجع مطابقت دارد. به طور منطقی، زمانی که مدل آموزش دیده ما پاسخ های ترجیحی را می آموزد، آنها با گذشت زمان از هم جدا می شوند. نمودار قطار/پاداش/حاشیه نیز تفاوت بین این دو نمودار را نشان می دهد. در نهایت، نمودار قطار/پاداش/دقت تعداد دفعات انتخاب پاسخ ترجیحی را نشان می‌دهد. مدل آموزش دیده به سرعت به نمره دقت کامل می رسد، که نشانه خوبی است، اما می تواند به این معنی باشد که تفاوت بین پاسخ های ترجیحی و رد شده بسیار آشکار است.

اکنون که آموزش داده شده است، می توانیم آداپتور را با مدل اصلی ادغام کنیم. سپس مدل ادغام شده و توکنایزر را قبل از انتقال به Hugging Face Hub ذخیره می کنیم.

# Save artifacts
dpo_trainer.model.save_pretrained("final_checkpoint")
tokenizer.save_pretrained("final_checkpoint")

# Flush memory
del dpo_trainer, model, ref_model
gc.collect()
torch.cuda.empty_cache()

# Reload model in FP16 (instead of NF4)
base_model = AutoModelForCausalLM.from_pretrained(
model_name,
return_dict=True,
torch_dtype=torch.float16,
)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# Merge base model with the adapter
model = PeftModel.from_pretrained(base_model, "final_checkpoint")
model = model.merge_and_unload()

# Save model and tokenizer
model.save_pretrained(new_model)
tokenizer.save_pretrained(new_model)

# Push them to the HF Hub
model.push_to_hub(new_model, use_temp_dir=False, token=hf_token)
tokenizer.push_to_hub(new_model, use_temp_dir=False, token=hf_token)

بیایید ببینیم مدل ما در یک آزمایش واقعی چگونه عمل می کند. ما درخواست را برای پرسیدن یک سوال اساسی قالب بندی می کنیم: “الگوی زبان بزرگ چیست؟”

# Format prompt
message = [
{"role": "system", "content": "You are a helpful assistant chatbot."},
{"role": "user", "content": "What is a Large Language Model?"}
]
tokenizer = AutoTokenizer.from_pretrained(new_model)
prompt = tokenizer.apply_chat_template(message, add_generation_prompt=True, tokenize=False)

# Create pipeline
pipeline = transformers.pipeline(
"text-generation",
model=new_model,
tokenizer=tokenizer
)

# Generate text
sequences = pipeline(
prompt,
do_sample=True,
temperature=0.7,
top_p=0.9,
num_return_sequences=1,
max_length=200,
)
print(sequences[0]['generated_text'])

اینم جواب مدل:

A large language model is a type of artificial intelligence (AI) system that has been trained on vast amounts of text data. These models are designed to understand and generate human language, allowing them to perform various natural language processing tasks, such as text generation, language translation, and question answering. Large language models typically use deep learning techniques, like recurrent neural networks (RNNs) or transformers, to learn patterns and relationships in the data, enabling them to generate coherent and contextually relevant responses. The size of these models, in terms of the number of parameters and the volume of data they are trained on, plays a significant role in their ability to comprehend and produce complex language structures.

به نظر می رسد همه چیز کار می کند، اکنون می توانیم مدل ادغام شده را ارزیابی کنیم. از آنجایی که این یک مدل هدف کلی است، می توانیم از lm-evaluation-harness برای ارزیابی آن استفاده کنیم. از آنجایی که این فرآیند کاملاً منابع فشرده است، می‌توانیم آن را مستقیماً برای ارزیابی در تابلوی امتیازات Open LLM ارسال کنیم. چند روز طول کشید، اما در اینجا نتایج در مقایسه با سایر مدل‌های OpenHermes آمده است:

تصویر توسط نویسنده

در مقایسه با مدل اصلی، مدل NeuralHermes-2-5-Mistral-7B میانگین امتیاز را 6.7 امتیاز (به ویژه در GSM8K) بهبود بخشید. این یک پیشرفت غیرمنتظره بزرگ است که قدرت بهینه‌سازی اولویت مستقیم را نشان می‌دهد.

در این مقاله، ما یک مدل تنظیم دقیق از قبل کنترل شده را با استفاده از DPO تنظیم کردیم و مدل NeuralHermes-2.5 خود را ایجاد کردیم. با استفاده از مجموعه داده ترجیحی با کیفیت بالا، ما یک خط لوله تنظیم دقیق کارآمد ایجاد کردیم که منجر به بهبود قابل توجهی در تابلوی امتیازات Open LLM شد. اگر می خواهید امتحان کنید، می توانید تغییرات کوانتیزه شده این الگو را پیدا کنید یا از این فضای در آغوش گرفتن صورت استفاده کنید.

توجه داشته باشید که کانال تنظیم دقیق ما همچنان می تواند به روش های مختلف بهبود یابد. به عنوان مثال، مجموعه داده ترجیحی هنوز کاملاً خام است و می‌تواند با فیلتر کردن بیشتر و با استفاده از مدل‌های مختلف بهبود یابد. علاوه بر این، هنوز هم می توان بسیاری از هایپرپارامترها را برای دستیابی به نتایج بهتر تغییر داد. به طور خاص، نرخ آموزش همچنان می تواند کاهش یابد تا مدل در مراحل بیشتری آموزش داده شود و داده های ترجیحی بیشتری تزریق شود.



Source link