Unsloth: از مبانی تا فاینتیون کردن مدلهای زبانی بینایی (VLM)

Unsloth به عنوان یک ابزار متحولکننده در دنیای فاینتیونینگ (بهینهسازی دقیق) مدلهای زبان بزرگ (LLM) ظهور کرده است. این ابزار به چالشی دیرینه، یعنی فرآیندی که همواره به منابع فشرده و پیچیدگیهای فنی وابسته بود، پاسخ میدهد. سازگار کردن مدلهایی مانند LLaMA، Mistral یا Qwen پیش از این به مجموعهای از GPUهای قدرتمند، مهندسی پیچیده و هزینههای قابلتوجهی نیاز داشت. Unsloth با فعال کردن فاینتیونینگ سریع، کارآمد در مصرف حافظه و در دسترس، حتی روی یک GPU مخصوص کاربران خانگی، این روایت را تغییر میدهد.
این راهنما شما را از صفر تا صد Unsloth، از آمادهسازی مجموعه داده گرفته تا استراتژیهای فاینتیون کردن، بهینهسازیهای کوانتیزیشن، آموزش مدل بینایی-زبان (VLM) و در نهایت تسلط بر فاینتیونینگ مدل Qwen2.5-VL-7B، همراهی میکند.
- Unsloth چیست؟
- چرا به Unsloth نیاز داریم؟ (پاسخ جزئی)
- آخرین بهروزرسانیهای Unsloth (تا سال 2024–2025)
- پشتیبانی Unsloth از GGUF
- برنامهریزی مجموعه داده برای فاینتیونینگ با Unsloth
- فاینتیونینگ مدل Qwen2.5-VL-7B روی LaTeX-OCR با استفاده از Unsloth
- نکات کلیدی پس از فاینتیونینگ مدل Qwen2.5-VL-7B با Unsloth
- نتیجهگیری
- منابع
Unsloth چیست؟
Unsloth یک کتابخانه مدرن پایتون است که برای افزایش سرعت و بهینهسازی فاینتیونینگ مدلهای زبان بزرگ (LLM) مانند LLaMA، Mistral، Mixtral و سایر مدلها طراحی شده است. این کتابخانه آموزش و فاینتیونینگ مدل را به شدت سریع، کارآمد در مصرف حافظه و آسان میکند، به خصوص روی سختافزارهای محدود مانند یک GPU مجزا یا حتی سیستمهای مخصوص کاربران خانگی.
این کتابخانه به دلیل مزایای زیر مورد توجه قرار گرفته است:
- فاینتیونینگ مدلهای با ۹B پارامتر با استفاده از ۱۶ بیتی LoRA روی ۲۴ گیگابایت VRAM و تنها با ۶.۵ گیگابایت VRAM در حالت کوانتیزیشن ۴ بیتی QLoRA.
- افزایش سرعت آموزش به ۲ تا ۵ برابر در مقایسه با روشهای سنتی Hugging Face.
- کاهش مصرف حافظه با بهینهسازی داخلی مدل.
- پشتیبانی از تکنیکهایی مانند QLoRA (LoRA کوانتیزه شده)، آموزش ۸ بیتی و ۴ بیتی، گرادینت چکپوینتینگ (gradient checkpointing) و غیره.
معماری آموزشی Unsloth نقش مهمی در کارایی حافظه ایفا میکند. این ابزار تنها باعث سبک شدن حافظه LoRA نمیشود، بلکه آن را در مقیاسهای کوچک نامرئی و حتی در مقیاسهای بزرگ مهارشده نگه میدارد. این بخشی از ویژگی خاص Unsloth است: شما فقط در محاسبات صرفهجویی نمیکنید، بلکه به طور کلی از هدر رفتن جلوگیری مینمایید.
به زبان ساده:
Unsloth = سرعت + کارایی حافظه + سادگی برای فاینتیونینگ LLMها.
انقلابی در فرآیند Fine-Tune مدلهای هوش مصنوعی با Unsloth
چرا به Unsloth نیاز داریم؟ (پاسخ جزئی)
شکستن موانع فاینتیونینگ
در گذشته، فاینتیونینگ مدلهای بزرگ به محاسبات با دقت کامل (FP32) نیاز داشت. این به معنای استفاده از GPUهای با ۸۰ گیگابایت VRAM و هزینههای سرسامآور انرژی بود. Unsloth با ترکیب چندین نوآوری این موانع را از بین میبرد:
- QLoRA (Quantized Low-Rank Adaptation) فاینتیونینگ مدلها را با دقت ۴ بیتی ممکن میسازد و نیاز به حافظه را ۷۰ تا ۸۰ درصد بدون افت کیفیت کاهش میدهد.
در بخش فاینتیونینگ در ادامه این پست، ما مصرف حافظه نزدیک به صفر برای آداپتورهای LoRA را در طول فاینتیونینگ ۳,۰۰۰ نمونه مشاهده خواهیم کرد، که تنها به دلیل سبک بودن LoRA نیست؛ بلکه به این دلیل است که Unsloth برای مدیریت حافظه با دقت جراحی به شدت بهینه شده است.
- PEFT (Parameter-Efficient Fine-Tuning) به شما اجازه میدهد آداپتورهای سبک LoRA را فقط در لایههای حیاتی (مانند Q، V، و پروجکشنهای خروجی) تزریق کنید و از نیاز به آموزش مجدد میلیاردها پارامتر جلوگیری میکند.
- SFTTrainer، یک آموزشدهنده سفارشی، تضمین میکند که محاسبه اتلاف (loss) فقط روی خروجیهای دستیار (assistant) رخ میدهد و فاینتیونینگ را با کاربردهای واقعی همسو میکند.
- Dynamic Quantization 2.0 خروجی مدل GGUF را با انطباق هوشمندانه کوانتیزیشن در هر لایه بهینه میکند و ضمن حفظ کیفیت، سرعت را به حداکثر میرساند. این مورد به تفصیل در ادامه پست توضیح داده شده است.
سرعت: فاینتیونینگ و اینفرنس سریعتر
- آموزش سنتی (با استفاده از Hugging Face، bitsandbytes، DeepSpeed) اغلب کند است زیرا:
- از پیادهسازیهای بهینهنشده برای لایههای توجه (attention)، MLP و کپیهای حافظه استفاده میکند.
- هزینههای اضافی برای اعمال دستی آداپتورهایی مانند LoRA وجود دارد.
- از Flash Attention 2 یا PyTorch compile به طور کامل استفاده نمیکند.
- Unsloth با این موارد مقابله میکند:
- بازنویسی داخلی LLM (توجه، MLP، نرمالسازی) برای سرعت.
- استفاده مستقیم از Flash Attention 2.
- استفاده از کامپایلر PyTorch،
torch.compile، برای بهینهسازی گراف بکاند. - ادغام عملیات QLoRA در مدل و جلوگیری از گلوگاهها.
- نتیجه
- آموزش ۲ تا ۵ برابر سریعتر.
- فاینتیون سریعتر حتی با طول دنبالههای بزرگ (مثلاً ۴k–۱۲۸k توکن)
دوره فارسی مدلهای زبانی بزرگ (LLM)
کارایی حافظه: آموزش مدلهای بزرگ روی GPUهای کوچک
- مدلهای بزرگ مانند Llama 13B و Mixtral 8x7B به راحتی به ۶۰ تا ۱۰۰ گیگابایت VRAM بدون بهینهسازی نیاز دارند.
- حتی استفاده از دقت ۸ بیتی همیشه کافی نیست.
- QLoRA کمک میکند (کوانتیزیشن ۴ بیتی)، اما QLoRA در Hugging Face همچنان به حافظه زیادی نیاز دارد.
- مزایای Unsloth:
- کوانتیزیشن ۴ بیتی واقعی به شکل هوشمندانهتری انجام میشود.
- بهینهسازهای صفحهبندیشده (Paged optimizers) و گرادینت چکپوینتینگ در آن تعبیه شده است.
- در صورت ناکافی بودن حافظه، امکان Offloading به CPU به صورت اختیاری وجود دارد.
- عدم وجود کپیهای تکراری تنسور (مدلهای Hugging Face گاهی تنسورها را در طول آموزش کپی میکنند).
- نتیجه
- میتوانید یک مدل ۷B را روی ۵ گیگابایت VRAM (کوانتیزه شده با QLoRA ۴ بیتی) فاینتیونینگ کنید.
- میتوانید مدلهای ۱۳B را روی ۸ گیگابایت VRAM (کوانتیزه شده با QLoRA) فاینتیونینگ کنید.
- فاینتیونینگ Gemma 3 (27B) با Unsloth روی کمتر از ۲۲ گیگابایت VRAM جای میگیرد. همچنین ۱.۶ برابر سریعتر است.
سادگی در فاینتیونینگ
- راهاندازی Hugging Face + bitsandbytes + Deepspeed + PEFT + QLoRA = پیچیده (بیش از ۵ کتابخانه برای همگامسازی و تطبیق نسخهها).
- Unsloth فراهم میکند:
- API واحد برای بارگذاری مدلهای کوانتیزه شده.
- یک فراخوانی واحد برای اضافه کردن آداپتورهای LoRA.
- مدیریت بومی توکنایزر.
- اسکریپتهای نمونه برای استفاده آسان (plug-and-play).
model, tokenizer = FastLanguageModel.from_pretrained(...) model = FastLanguageModel.get_peft_model(...)
- بدون نیاز به اقدامات دستی برای:
- درج LoRA
- مدیریت Bitsandbytes
- پیکربندی Deepspeed
- پیکربندیهای خاص بهینهساز
- نتیجه
- راهاندازی ۱۰ دقیقهای به جای چند ساعت.
- احتمال کمتر برای بروز باگهایی مانند کوانتیزه نشدن صحیح لایههای نرمالسازی.
کاهش نیازهای سختافزاری
- دوران قدیم:
- به کلاسترها (A100s, H100s) نیاز داشتید.
- هزینهها: هزاران دلار در ماه.
- با Unsloth:
- ۴۰۹۰ با ۲۴ گیگابایت یا A6000 با ۴۸ گیگابایت برای بیشتر مدلهای ۷B تا ۱۳B کافی است.
- حتی مکبوکها (M3, M2) با پشتیبانی از Metal backend قادر به فاینتیونینگ مدلهای کوچکتر هستند.
- GPUهای AMD (ROCm) نیز اکنون کار میکنند.
- نتیجه:
- هزینههای فاینتیونینگ به صدها دلار، نه هزاران دلار کاهش مییابد.
- سیستمهای با یک GPU (برای فریلنسرها، استارتاپها، دانشجویان) به اندازه کافی قدرتمند میشوند.
تکنیکهای آموزشی بهتر
- گرادینت چکپوینتینگ: صرفهجویی در VRAM در طول پسانتشار (backprop).
- بهینهسازهای صفحهبندیشده: مدیریت کارآمدتر تعداد پارامترهای زیاد.
- پنجرههای زمینه طولانی: تا ۱۲۸k توکن به صورت بومی.
- Flash Attention 2: محاسبه توجه با کارایی فوقالعاده.
- دقت ترکیبی (Mixed precision): مدیریت هوشمندانه bfloat16 و float16.
دسترسی به انواع مدلهای جدید (MoE, Llama2, Mixtral, Gemma)
- مدلهای MoE (Mixture of Experts) مانند Mixtral به مدیریت ویژهای نیاز دارند (مسیریابی توکنها به متخصصین).
- کتابخانههای سنتی هنوز برای فاینتیونینگ MoE بهینه نشدهاند.
- Unsloth به صورت بومی از این مدلها پشتیبانی میکند.
ویژگی | جزئیات |
LoRA سریعتر | LoRA (Low Rank Adaptation) روشی برای فاینتیونینگ است که با Unsloth حتی سریعتر و سبکتر میشود. |
QLoRA بهتر | QLoRA = LoRA کوانتیزه شده (با استفاده از دقت ۴ بیتی). QLoRA در Unsloth تا ۲ برابر سریعتر از پیادهسازی مرجع Hugging Face است. |
بهینهسازی حافظه | بازنویسی توجه، MLP (feed-forward)، نرمالسازی و غیره برای کارایی بیشتر در مصرف حافظه. |
Flash Attention 2 | استفاده از حالتهای کامپایلر PyTorch مانند torch.compile برای سرعتهای بیشتر. |
Pytorch 2.1+ | استفاده از حالتهای کامپایلر PyTorch مانند torch.compile برای سرعتهای بیشتر. |
پشتیبانی از چند بکاند | پشتیبانی از CUDA، AMD ROCm و Metal اپل (MPS). |
این ابزار همچنین از ویژگیهای خاصی پشتیبانی میکند، مانند:
- بهینهسازهای صفحهبندیشده (Paged optimizers).
- گرادینت چکپوینتینگ (صرفهجویی در VRAM).
- Offloading به CPU در صورت نیاز.
نیاز | چرا Unsloth؟ |
سرعت | آموزش ۲ تا ۵ برابر سریعتر |
کارایی حافظه | مصرف VRAM کمتر به میزان ۳۰ تا ۵۰ درصد |
سادگی | راهاندازی آسان با ۲ خط کد |
نیازهای سختافزاری | اجرای مدلهای ۱۳B روی ۲۴ گیگابایت VRAM |
صرفهجویی در هزینه | فاینتیونینگ ۵ تا ۱۰ برابر ارزانتر |
مدلهای جدید | پشتیبانی آسان از MoE، Llama2، Gemma |
توالیهای طولانی | امکان آموزش با ۱۲۸k توکن |
آخرین بهروزرسانیهای Unsloth (تا سال 2024–2025)
- پشتیبانی کامل از مدلهای MoE Mixtral 8x7B.
- پشتیبانی بومی از ۱28k طول زمینه (promptهای فوقالعاده طولانی).
- پشتیبانی خودکار از آموزش ۴ بیتی واقعی.
- سازگاری کامل با RoCm (AMD).
- شروع بهینهسازی برای Apple Silicon (MPS).
پشتیبانی Unsloth از GGUF
Dynamic Quantization 2.0 در Unsloth، استاندارد جدیدی را برای خروجی مدل پس از آموزش تعیین میکند. به جای اعمال کوانتیزیشن یکپارچه (که به لایههای استدلالی حیاتی آسیب میزند)، Unsloth حساسیت هر لایه به فشردهسازی را با استفاده از یک مجموعه داده کالیبراسیون در محدوده ۳۰۰K تا ۱.۵M توکن تحلیل میکند. Unsloth از GGUF (Grokking GGML Unified Format) به صورت قدرتمند پشتیبانی میکند و کاربران را قادر میسازد تا:
- مدلهای فاینتیونینگ شده را به GGUF خروجی بگیرند: Unsloth متدهایی مانند
model.save_pretrained_gguf()
وmodel.push_to_hub_gguf()
را برای ذخیره مدلها در فرمت GGUF و تسهیل استقرار در پلتفرمهای مختلف فراهم میکند.
- از Dynamic Quantization استفاده کنند: با معرفی Unsloth Dynamic v2.0، Unsloth از استراتژیهای هوشمندانه کوانتیزیشن لایهای استفاده میکند که عملکرد و کارایی مدل را در خروجیهای GGUF افزایش میدهد.
- سازگاری با موتورهای اینفرنس را تضمین کنند: مدلهای خروجی گرفته شده در فرمت GGUF از طریق Unsloth با موتورهای اینفرنس مانند llama.cpp، Ollama و Open WebUI سازگار هستند و گزینههای استقرار را گسترش میدهند.
ویژگیهای کلیدی نسخه Unsloth Dynamic v2.0 GGUFs
- بازنگری در انتخاب لایه + پشتیبانی از Safetensors
- برخلاف کوانتیزیشن استاتیک، Dynamic v2.0 انواع کوانت را به صورت هوشمند برای هر لایه انتخاب میکند.
- این به معنای کوانتیزه کردن هر لایه ممکن به صورت متفاوت، بسته به حساسیت آن است.
- از روشی هوشمندانهتر نسبت به تبدیلهای قدیمی QLoRA یا GGUF استاتیک استفاده میکند.
- همچنین در صورت نیاز از خروجی گرفتن در فرمت .safetensors پشتیبانی میکند.
- Dynamic Quantization برای تمام مدلها (نه فقط MoEها)
- در ابتدا فقط برای MoE (Mixture of Experts) مانند DeepSeek-R1 استفاده میشد.
- اکنون از تمام انواع مدلها از جمله LLaMA، Mistral، Gemma، Mixtral و غیره پشتیبانی میکند.
- تایید شده: “کوانتیزیشن Dynamic 2.0 اکنون روی تمام مدلها (از جمله MoEها) کار میکند.”
- مجموعه داده کالیبراسیون جدید برای GGUFها
- کالیبراسیون از دادههای با کیفیت بالا در محدوده ۳۰۰K تا ۱.۵M توکن استفاده میکند.
- برای کیفیت گفتوگو و پیروی از دستورالعملها کالیبره شده، نه فقط معیارهای اتلاف (loss).
- GGUFهای کوانتیزه شده بهتری با حداقل افت عملکرد تولید میکند.
- طرحهای کوانتیزیشن مخصوص هر مدل
- مثال: لایههای کوانتیزه شده در Gemma-3 با لایههای LLaMA-4 متفاوت است.
- Unsloth برای هر معماری از یک طرح کوانت سفارشی استفاده میکند.
- این کار عملکرد در دستگاههای مختلف (به ویژه برای سختافزارهای غیرNVIDIA) را بهبود میبخشد.
- پشتیبانی از فرمتهای کوانت بیشتر GGUF
- Unsloth Dynamic 2.0 اکنون خروجی میگیرد و از فرمتهای زیر پشتیبانی میکند:
- Q4_K_M, Q4_K_S
- Q4_NL, Q5_0, Q5_1, Q6_K, Q8_0
- با کدگذاری غیرخطی (IQ4_NL, etc.) برای بهبود اینفرنس CPU (چیپهای Apple M، ARM).
- Unsloth Dynamic 2.0 اکنون خروجی میگیرد و از فرمتهای زیر پشتیبانی میکند:
قبل از رفتن به بخش کد، تمام کدها در یک مکان جمعآوری شدهاند که میتوانید با کلیک روی دکمه ‘Download Code’ در زیر، آنها را دانلود کنید.
دانلود کد برای اینکه بتوانید به راحتی این آموزش را دنبال کنید، با کلیک بر روی دکمه زیر، کد را دانلود کنید:
برنامهریزی مجموعه داده برای فاینتیونینگ با Unsloth
چرا ساختار مجموعه داده شما مهم است؟
مهم نیست چارچوب آموزشی شما چقدر قدرتمند باشد، یک مجموعه داده با ساختار ضعیف میتواند فاینتیونینگ شما را محکوم به شکست کند. در Unsloth، مجموعههای داده باید به طور تمیز قابل توکنایز شدن، دارای برچسب نقش (کاربر در مقابل دستیار) و مطابق با انتظارات مدل باشند.
هنگام طراحی مجموعه داده خود، با دقت در مورد موارد زیر فکر کنید:
- هدف: آیا در حال ساخت یک عامل گفتوگو هستید؟ یک دستیار کد؟ یک مدل متخصص در حوزه خاص؟
- سبک خروجی: آیا مدل باید خروجی Markdown، متن ساده، HTML یا کد برنامهنویسی تولید کند؟
- منبع داده: آیا داده شما از منابع باز جمعآوری شده، به صورت مصنوعی توسط مدلهای GPT تولید شده یا به صورت دستی برچسبگذاری شده است؟
یک مجموعه داده با ساختار مناسب، پایهای است که موفقیت فاینتیونینگ شما بر آن استوار خواهد بود.
فرمتهای مجموعه داده پشتیبانیشده در Unsloth
Unsloth از چندین فرمت داده رایج پشتیبانی میکند:
- Raw Corpus (پیکره خام): بلوکهای بزرگی از متن – کتابها، مقالات – که برای پیشآموزش مستمر (CPT) استفاده میشوند.
{ "text": "Pasta carbonara is a traditional Roman pasta dish..." }
- Instruction Format (فرمت دستورالعمل) (به سبک Alpaca): سهتاییهای دستورالعمل، ورودی اختیاری و خروجی.
{ "instruction": "Task we want the model to perform.", "input": "Optional user query or context.", "output": "Expected response or result." }
- Conversation Format (فرمت گفتوگو) (به سبک ShareGPT): گفتوگوهای چند نوبتی که در آنها هر پیام دارای برچسب نقش است (کاربر یا دستیار).
{ "conversations": [ {"from": "human", "value": "Can you help me make pasta carbonara?"}, {"from": "gpt", "value": "Would you like the traditional Roman recipe..."}, ... ] }
- RLHF Datasets: مجموعههای دادهای که شامل ترجیحات رتبهبندی شده بین خروجیهای مختلف مدل هستند.
فرمت | توضیحات | نوع آموزش |
Raw Corpus | متن خام بدون ساختار از کتابها، مقالات و غیره. | پیشآموزش مستمر (CPT) |
Instruct | نمونههای دستورالعمل + خروجی (مانند سبک Alpaca) | فاینتیونینگ نظارتشده (SFT) |
Conversation | چت چند نوبتی بین کاربر و دستیار | فاینتیونینگ نظارتشده (SFT) یا مدلسازی گفتوگو |
RLHF | چت با رتبهبندی پاسخها توسط انسان یا اسکریپت | چت چند نوبتی بین کاربر و دستیار |
هر فرمت برای اهداف فاینتیونینگ متفاوتی مناسب است: عوامل گفتوگو، دنبالکنندگان دستورالعملهای خاص، مدلهای زبان عمومی یا مدلهای آموزشدیده بر اساس ترجیحات.
درک توکنایزیشن و الگوهای گفتوگو (Chat Templates)
توکنایزیشن – تقسیم متن به توکنهایی که مدلها میتوانند درک کنند – یک مرحله ظریف اما حیاتی است. توکنایزیشن بد باعث میشود مدلها ورودیهای کاربر را با پاسخهای دستیار اشتباه بگیرند، که منجر به توهم یا پاسخهای نادرست میشود. Unsloth الگوهای گفتوگوی سفارشی را یکپارچه میکند که گفتوگوها را به فرمتهای واضح و بدون ابهام ساختاربندی میکند.
یک مجموعه داده مناسب به یک الگوی گفتوگوی با تعریف دقیق و توکنایزیشن ثابت نیاز دارد تا مدلها بتوانند:
- نقشها را درک کنند (کاربر در مقابل دستیار)
- مرزهای زمینه را بیاموزند (prompts سیستم، پاسخهای دستیار)
- توکن مناسب بعدی را با دقت پیشبینی کنند
from unsloth.chat_templates import get_chat_template tokenizer = get_chat_template(tokenizer, chat_template="mixtral")
فرقی نمیکند از ChatML، ShareGPT، Alpaca، OpenChat یا Vicuna استفاده کنید، باید در تمام مجموعه داده ثابت باشد. الگو مشخص میکند که متن چگونه:
- بخشبندی شود
- برچسبگذاری شود (کاربر/دستیار/سیستم)
- کدگذاری شود (با توکنهای خاص)
الگویی که استفاده میکنید مستقیماً بر توکنایزیشن و در نتیجه بر بردارهای نهایی (final embeddings) و آنچه مدل میآموزد، تأثیر میگذارد.
اعمال الگوهای گفتوگو با Unsloth
الگوهای گفتوگوی پشتیبانیشده در Unsloth
from unsloth.chat_templates import CHAT_TEMPLATES print(list(CHAT_TEMPLATES.keys()))
الگوهای گفتوگوی پشتیبانیشده –
['unsloth', 'zephyr', 'chatml', 'mistral', 'llama', 'vicuna', 'vicuna_old', 'vicuna old', 'alpaca', 'gemma', 'gemma_chatml', 'gemma2', 'gemma2_chatml', 'llama-3', 'llama3', 'phi-3', 'phi-35', 'phi-3.5', 'llama-3.1', 'llama-31', 'llama-3.2', 'llama-3.3', 'llama-32', 'llama-33', 'qwen-2.5', 'qwen-25', 'qwen25', 'qwen2.5', 'phi-4', 'gemma-3', 'gemma3']
استفاده از یک الگوی گفتوگو
from unsloth.chat_templates import get_chat_template tokenizer = get_chat_template( tokenizer, chat_template = "gemma-3" # Adjust as needed )
تابع فرمتدهی – این تابع روی مجموعه داده شما حلقه میزند و الگوی گفتوگوی تعریف شده را برای هر نمونه اعمال میکند.
def formatting_prompts_func(examples): texts = [tokenizer.apply_chat_template(e, tokenize=False, add_generation_prompt=True) for e in examples["conversations"]] return {"text": texts}
بارگذاری مجموعه داده
# Import and load dataset from datasets import load_dataset dataset = load_dataset("repo_name/dataset_name", split = "train") Apply the formatting function to your dataset using the map method dataset = dataset.map(formatting_prompts_func, batched = True,)
اگر مجموعه داده شما از فرمت ShareGPT با کلیدهای “from”/”value” به جای فرمت ChatML “role”/”content” استفاده میکند، میتوانید ابتدا از تابع standardize_sharegpt
برای تبدیل آن استفاده کنید. کد بازبینی شده اکنون به صورت زیر خواهد بود:
# Import dataset from datasets import load_dataset dataset = load_dataset("mlabonne/FineTome-100k", split = "train") Convert your dataset to the "role"/"content" format if necessary from unsloth.chat_templates import standardize_sharegpt dataset = standardize_sharegpt(dataset) Apply the formatting function to your dataset using the map method dataset = dataset.map(formatting_prompts_func, batched = True,)
تبدیل ShareGPT به ChatML
کد زیر لیستی از پیامهای ShareGPT را میگیرد و آن را به یک گفتوگوی زیبای ChatML تبدیل میکند.
def sharegpt_to_chatml(sharegpt_conversation, system_prompt="You are a helpful assistant.", add_default_system_prompt_if_missing=True): """ Converts a ShareGPT style conversation (list of dicts) into a ChatML string. Handles common ShareGPT role keys ('from', 'role') and content keys ('value', 'content'). Handles common ShareGPT roles ('human', 'user', 'gpt', 'assistant', 'system'). """ chatml_parts = [] has_system_prompt_in_data = False for turn in sharegpt_conversation: role_key = 'role' if 'role' in turn else 'from' if turn.get(role_key) == "system": has_system_prompt_in_data = True break if add_default_system_prompt_if_missing and not has_system_prompt_in_data and system_prompt: chatml_parts.append(f"<|system|>{system_prompt.strip()}<|end|>") for turn in sharegpt_conversation: role_key = 'role' if 'role' in turn else 'from' content_key = 'content' if 'content' in turn else 'value' if role_key not in turn or content_key not in turn: print(f"Skipping turn due to missing keys: {turn}") continue role = turn[role_key] content = turn[content_key].strip() if role in ["user", "human"]: chatml_parts.append(f"<|user|>{content}<|end|>") elif role in ["assistant", "gpt", "model"]: chatml_parts.append(f"<|assistant|>{content}<|end|>") elif role == "system": chatml_parts.append(f"<|system|>{content}<|end|>") else: raise ValueError(f"Unknown role: {role} in turn: {turn}") return "\n".join(chatml_parts)
تبدیل ChatML به ShareGPT
کد زیر نوبتهای کاربر و دستیار را از متن ChatML استخراج کرده و به یک لیست تمیز به سبک ShareGPT تبدیل میکند.
import re def chatml_to_sharegpt( chatml_text, include_system_messages=False, role_key_name="role", # or "from" content_key_name="content" # or "value" ): """ Converts a ChatML formatted string back into ShareGPT list format. Allows configuration for including system messages and output key names. """ pattern = r"<\|(\w+)\|>(.*?)<\|end\|>" matches = re.findall(pattern, chatml_text, flags=re.DOTALL) sharegpt_conversation = [] for role, content in matches: role_standardized = role.lower() if role_standardized == "system" and not include_system_messages: continue sharegpt_conversation.append({ role_key_name: role_standardized, # Use the standardized role content_key_name: content.strip() }) return sharegpt_conversation
گفتوگوهای چند نوبتی در Unsloth (برای مجموعه دادههای به سبک Alpaca)
فرمت Alpaca یک نوبتی است – یک دستورالعمل، یک خروجی.
اما LLMها مانند ChatGPT برای مدیریت گفتوگوهای چند نوبتی طراحی شدهاند.
Unsloth ویژگی conversation_extension
را معرفی میکند تا با استفاده از دادههای Alpaca یک نوبتی، گفتوگوی چند نوبتی را شبیهسازی کند.
عملکرد:
- به صورت تصادفی
N
نمونه از مجموعه داده را انتخاب میکند. - آنها را در یک گفتوگوی ساختاریافته (شبیهسازی شده) ادغام میکند.
- به مدل اجازه میدهد زمینه و جریان بین نوبتها را بیاموزد.
مثال قبل و بعد:
قبل (یک نوبتی):
{ "instruction": "What is 2+2?", "output": "2 + 2 equals 4." } { "instruction": "How are you?", "output": "I'm doing fine!" } { "instruction": "Flip a coin.", "output": "I got heads!" }
بعد (conversation_extension = 3):
{ "instruction": "What is 2+2?", "output": "2 + 2 equals 4." }, { "instruction": "Flip a coin.", "output": "I got heads!" }, { "instruction": "How are you?", "output": "I'm doing fine!" }
این به یک چت جعلی اما باورپذیر چند نوبتی تبدیل میشود، که به طور قابل توجهی کیفیت SFT (Supervised Fine-Tuning) را برای گفتوگو بهبود میبخشد.
نحوه استفاده عملی
conversation_extension = N را تنظیم کنید، که در آنN
= تعداد ردیفها برای پیوند به یک گفتوگو است.
output_column_name را روی نام ستون خروجی تنظیم کنید، که معمولاً در Alpaca
output"
"
است.
فاینتیونینگ مدل Qwen2.5-VL-7B روی LaTeX-OCR با استفاده از Unsloth
برای نمایش قابلیتهای فاینتیونینگ چندوجهی Unsloth در عمل، یک وظیفه واقعی را انتخاب کردیم که به درک بصری و متنی نیاز دارد: تبدیل عبارات ریاضی در تصاویر به LaTeX. برای این آزمایش، از مجموعه داده LaTeX-OCR استفاده خواهیم کرد که تصاویر ریاضی رندر شده را با کد LaTeX مربوطه جفت میکند. این مجموعه داده آن را به یک معیار ایدهآل برای ارزیابی عملکرد مدل زبان-بینایی در تولید خروجی ساختاریافته تبدیل میکند. در یکی از پستهای قبلی بلاگ، فاینتیونینگ مدل Gemma 3 4B را روی همین مجموعه داده LatexOCR نشان دادیم. با این حال، مقایسه مستقیم به دلیل تفاوتهای پارامتری مدل و نحوه مدیریت لایههای بینایی و توجه بین Gemma 3 و Qwen2.5-VL، ایدهآل نخواهد بود.
با این حال، ما برخی از آمار مصرف حافظه و زمان استفاده شده در فاینتیونینگ هر دو مدل را روی همان نمونههای آموزشی و با همان پیکربندیهای LoRA و SFT مشاهده خواهیم کرد، که به کارایی فاینتیونینگ هنگام استفاده از Unsloth روشنایی میبخشد.
بارگذاری مدل Qwen2.5-VL-7B با Unsloth
from unsloth import FastVisionModel # FastLanguageModel for LLMs import torch model, tokenizer = FastVisionModel.from_pretrained( "unsloth/Qwen2.5-VL-7B-Instruct-bnb-4bit", load_in_4bit = True, # Use 4bit to reduce memory use. False for 16bit LoRA. use_gradient_checkpointing = "unsloth", # True or "unsloth" for long context )
این قطعه کد، مدل Qwen2.5-VL-7B-Instruct را با استفاده از
FastVisionModel Unsloth، که برای فاینتیونینگ زبان-بینایی طراحی شده است، مقداردهی اولیه میکند. مدل با دقت ۴ بیتی (load_in_4bit=True
) بارگذاری میشود تا مصرف حافظه GPU به طور قابل توجهی کاهش یابد. علاوه بر این،
use_gradient_checkpointing=”unsloth” پسانتشار (backpropagation) با کارایی حافظه را فعال میکند، که به دنبالههای ورودی طولانیتر اجازه میدهد بدون تجاوز از محدودیتهای VRAM پردازش شوند.
اعمال LoRA با کنترل فاینتیونینگ بر روی لایههای بینایی و زبان
model = FastVisionModel.get_peft_model( model, finetune_vision_layers = True, # False if not finetuning vision layers finetune_language_layers = True, # False if not finetuning language layers finetune_attention_modules = True, # False if not finetuning attention layers finetune_mlp_modules = True, # False if not finetuning MLP layers r = 8, # The larger, the higher the accuracy, but might overfit lora_alpha = 16, # Recommended alpha == r at least lora_dropout = 0, bias = "none", random_state = 3407, use_rslora = False, # We support rank stabilized LoRA loftq_config = None, # And LoftQ target_modules = "['down_proj', 'o_proj', 'k_proj', 'q_proj', 'gate_proj', 'up_proj', 'v_proj']", )
این قطعه کد LoRA (Low-Rank Adaptation) را برای مدل Qwen2.5-VL با استفاده از
get_peft_model پیکربندی میکند. این کد فاینتیونینگ لایههای بینایی، زبان، توجه و MLP را فعال میکند. با تنظیم
use_rslora=False، از LoRA با ثبات رتبه صرف نظر میشود. این تنظیمات کنترل کاملی بر روی بخشهایی از مدل که فاینتیونینگ میشوند، با حفظ کارایی حافظه و عملکرد، تضمین میکند.
فرمتدهی نمونهها به جفتهای زبان-بینایی شبیه به چت
from datasets import load_dataset dataset = load_dataset("unsloth/LaTeX_OCR", split = "train[:3000]") instruction = "Write the LaTeX representation for this image." def convert_to_conversation(sample): conversation = [ { "role": "user", "content" : [ {"type" : "text", "text" : instruction}, {"type" : "image", "image" : sample["image"]} ] }, { "role" : "assistant", "content" : [ {"type" : "text", "text" : sample["text"]} ] }, ] return { "messages" : conversation } pass converted_dataset = [convert_to_conversation(sample) for sample in dataset]
این تابع یک جفت تصویر-متن خام را به فرمت پیام به سبک ChatML سازگار با مدلهای بینایی Unsloth تبدیل میکند. این کار یک کاربر را شبیهسازی میکند که از دستیار میخواهد کد LaTeX را برای تصویر داده شده بنویسد.
انجام اینفرنس با مدل زبان-بینایی فاینتیونینگ شده
FastVisionModel.for_inference(model) # Enable for inference! image = dataset[2]["image"] instruction = "Write the LaTeX representation for this image." messages = [ {"role": "user", "content": [ {"type": "image"}, {"type": "text", "text": instruction} ]} ] input_text = tokenizer.apply_chat_template(messages, add_generation_prompt = True) inputs = tokenizer( image, input_text, add_special_tokens = False, return_tensors = "pt", ).to("cuda") from transformers import TextStreamer text_streamer = TextStreamer(tokenizer, skip_prompt = True) _ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128, use_cache = True, temperature = 1.5, min_p = 0.1)
بلاک کد بالا نحوه اجرای اینفرنس با مدل فاینتیونینگ شده Qwen2.5-VL را نشان میدهد. ابتدا حالت اینفرنس با
FastVisionModel.for_inference(model) فعال میشود، سپس یک پیام چندوجهی که شامل تصویر و دستورالعمل LaTeX است، ساخته میشود. پیام از طریق
apply_chat_template() عبور داده میشود تا به درستی فرمتبندی شود. پس از توکنایز کردن ورودیها، مدل با استفاده از
.generate() با خروجی استریمینگ از طریق
TextStreamer، یک پاسخ تولید میکند. تنظیمات temperature و
min_p تنوع و خلاقیت نمونهگیری را کنترل میکنند.
پیکربندی آموزشدهنده برای فاینتیونینگ زبان-بینایی
from unsloth import is_bf16_supported from unsloth.trainer import UnslothVisionDataCollator from trl import SFTTrainer, SFTConfig FastVisionModel.for_training(model) # Enable for training! trainer = SFTTrainer( model = model, tokenizer = tokenizer, data_collator = UnslothVisionDataCollator(model, tokenizer), train_dataset = converted_dataset, args = SFTConfig( per_device_train_batch_size = 1, gradient_accumulation_steps = 4, warmup_steps = 10, #max_steps = 30, num_train_epochs = 1, learning_rate = 2e-4, fp16 = not is_bf16_supported(), bf16 = is_bf16_supported(), logging_steps = 200, save_strategy='steps', save_steps=200, save_total_limit=2, optim = "adamw_8bit", weight_decay = 0.01, lr_scheduler_type = "linear", seed = 3407, output_dir = "outputs", report_to = "none", # For Weights and Biases # You MUST put the below items for vision finetuning: remove_unused_columns = False, dataset_text_field = "", dataset_kwargs = {"skip_prepare_dataset": True}, dataset_num_proc = 4, max_seq_length = 2048, ), )
قطعه کد بالا حلقه آموزشی را با استفاده از SFTTrainer
از کتابخانه TRL، که برای پشتیبانی زبان-بینایی Unsloth بهینه شده است، راهاندازی میکند. این کد حالت آموزشی را با
FastVisionModel.for_training(model) فعال میکند و از
UnslothVisionDataCollator استفاده میکند، که برای دستهبندی صحیح ورودیهای چندوجهی (متن + تصویر) الزامی است. پیکربندی آموزش شامل گزینههای کارآمد در مصرف حافظه مانند بهینهساز adamw_8bit
، مدیریت دقت دینامیک bfloat16/float16 و اندازه دسته کوچک با انباشت گرادیان است. پارامترهای اضافی مخصوص فاینتیونینگ بینایی، مانند
remove_unused_columns=False و
dataset_kwargs نیز ارائه شده است که جفت شدن صحیح تصویر-متن در طول آموزش را تضمین میکند.
نظارت بر مصرف حافظه GPU قبل از آموزش
gpu_stats = torch.cuda.get_device_properties(0) start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3) max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3) print(f"GPU = {gpu_stats.name}. Max memory = {max_memory} GB.") print(f"{start_gpu_memory} GB of memory reserved.")
این کد آمار فعلی GPU را برای کمک به نظارت بر در دسترس بودن حافظه قبل از آموزش نمایش میدهد. این کد حافظه کل GPU و مقدار از پیش رزرو شده توسط PyTorch را با استفاده از
torch.cuda به دست میآورد.
پیگیری حافظه GPU نهایی و مصرف زمان آموزش
# @title Show final memory and time stats used_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3) used_memory_for_lora = round(used_memory - start_gpu_memory, 3) used_percentage = round(used_memory / max_memory * 100, 3) lora_percentage = round(used_memory_for_lora / max_memory * 100, 3) print(f"{trainer_stats.metrics['train_runtime']} seconds used for training.") print( f"{round(trainer_stats.metrics['train_runtime']/60, 2)} minutes used for training." ) print(f"Peak reserved memory = {used_memory} GB.") print(f"Peak reserved memory for training or used memory for lora = {used_memory_for_lora} GB.") print(f"Peak reserved memory % of max memory = {used_percentage} %.") print(f"Peak reserved memory for training % of max memory = {lora_percentage} %.")
کد بالا آمار دقیق منابع را پس از اتمام آموزش ثبت میکند. این کد کل حافظه GPU استفاده شده، حافظه مخصوص LoRA و درصدهای مربوطه از کل ظرفیت GPU را محاسبه میکند. همچنین کل زمان آموزش را به ثانیه و دقیقه نمایش میدهد.
نکات کلیدی پس از فاینتیونینگ مدل Qwen2.5-VL-7B با Unsloth
مصرف حافظه قبل از فاینتیونینگ
GPU = Tesla T4. Max memory = 14.741 GB. 7.111 GB of memory reserved.
قبل از آموزش، تقریباً ۷.۱۱ گیگابایت از حافظه GPU هنگام بارگذاری مدل Qwen2.5-VL در دقت ۴ بیتی رزرو شده بود. این مقدار به طرز شگفتانگیزی کم است، با توجه به اینکه مدلهای زبان-بینایی معمولاً به بیش از ۱۵ تا ۲۰ گیگابایت حتی قبل از شروع آموزش نیاز دارند.
مصرف حافظه و زمان در طول فاینتیونینگ
Step Training Loss 200 0.254500 400 0.094800 600 0.090900 Unsloth: Will smartly offload gradients to save VRAM! 2921.7907 seconds used for training. 48.7 minutes used for training. Peak reserved memory = 7.111 GB. Peak reserved memory for training or used memory for lora = 0.0 GB. Peak reserved memory % of max memory = 48.24 %. Peak reserved memory for training % of max memory = 0.0 %.
معیارهای آموزش به طور دقیق نشان میدهند که چرا Unsloth به طور منحصر به فردی برای فاینتیونینگ مدلهای بزرگ با کارایی حافظه و زمان، حتی روی GPUهای میانرده مانند Tesla T4، مناسب است.
- حداکثر حافظه رزرو شده در اوج، زیر ۵۰ درصد از کل ظرفیت GPU (۱۴.۷ گیگابایت) باقی ماند، که تأیید میکند LoRA با کوانتیزیشن ۴ بیتی به طور قابل توجهی ردپای VRAM را کاهش میدهد.
- حافظه استفاده شده به طور خاص توسط ماژولهای LoRA ناچیز بود (
۰.۰ GB
)، که ماهیت پارامتر-کارآمد فاینتیونینگ مبتنی بر PEFT در Unsloth را بیشتر تأیید میکند.
- جلسه آموزش تنها در ۴۸.۷ دقیقه (≈۲۹۲۲ ثانیه) به پایان رسید، که نشان میدهد چگونه یکپارچهسازی
gradient_checkpointing،
paged_adamw_8bit و تخصیص هوشمندانه حافظه توسط Unsloth، سرعت را بدون هدر رفتن منابع ارائه میدهد.
با وجود اینکه **Qwen2.5 تقریباً دو برابر اندازه پارامترهای مدل Gemma 3 (7B در مقابل ۴B) است، Unsloth کل فاینتیونینگ را تنها در ۵۱ دقیقه به پایان رساند، در حالی که Gemma 3 4B با استفاده از تنظیمات سنتی مبتنی بر TRL، ۱ ساعت و ۲ دقیقه زمان برد، یعنی بیش از ۲۰ درصد طولانیتر.
اگرچه Gemma 3 کوچکتر است، اندازه مدل به تنهایی سرعت یا کارایی بیشتر در آموزش را تضمین نمیکند. ابزارها مهم هستند. اگرچه نحوه مدیریت لایههای داخلی این مدلها مهم است، اما مدل با اندازه دو برابر از نظر پارامترها، با همان پیکربندیهای آموزشی، زمان آموزش کمتری میبرد و حافظه بسیار کمتری نسبت به مدل Gemma 3 4B مصرف میکند. پایپلاین آموزشی عمیقاً بهینهسازی شده Unsloth به وضوح از تنظیمات سنتی بهتر عمل میکند، به خصوص برای محیطهای با منابع محدود یا وظایف چندوجهی.
نتیجهگیری
فاینتیونینگ مدلهای زبان بزرگ، به ویژه مدلهای زبان-بینایی، به طور سنتی یک فرآیند پر از اصطکاک و با نیاز به منابع بالا بوده است. اما ابزارهایی مانند Unsloth این معادله را به طور اساسی تغییر میدهند. Unsloth آموزش را با این ویژگیها ساده میکند:
- کوانتیزیشن ۴ بیتی QLoRA، که به طور چشمگیری نیاز به VRAM را بدون از دست دادن عملکرد کاهش میدهد.
- تزریق آداپتور LoRA به هر دو بخش بینایی و زبان برای یادگیری کارآمد و مختص به وظیفه.
- دستهبندی هوشمند و دادهکالکتورهای سفارشیسازی شده برای مجموعههای داده چندوجهی.
- و بهینهسازیهای سطح پایین مانند گرادینت چکپوینتینگ و بهینهسازهای صفحهبندیشده که مصرف حافظه را حتی در طول فرآیندهای فشرده آموزش کنترل میکنند.
در آزمایشهای مقایسهای، آموزش مدلهای بزرگ در کمتر از یک ساعت به پایان میرسد، با مصرف حافظه که به طور مداوم زیر ۵۰ درصد ظرفیت GPU باقی میماند و هزینههای اضافی ناچیزی از آداپتورهای LoRA. این نتایج نشان میدهند که اندازه مدل به تنهایی یک گلوگاه نیست، بلکه ابزارهایی که استفاده میکنیم نیز به همان اندازه حیاتی هستند. و Unsloth در تمام این زمینهها موفق است: سرعت، کارایی حافظه، ماژولار بودن و سادگی.
منابع
شروع متخصص شدن
اگر این مقاله را دوست داشتید و مایلید یادگیری عمیق را اصولی یادبگیرید، دوره های کلاس ویژن را از دست ندهید.
دیدگاهتان را بنویسید