PEFT documentation
دمج النماذج
دمج النماذج
قد يكون تدريب نموذج لكل مهمة مكلفًا، ويستهلك مساحة تخزين كبيرة، كما أن هذه النماذج غير قادرة على تعلم معلومات جديدة لتحسين أدائها. يمكن لتعلم المهام المتعددة التغلب على بعض هذه القيود من خلال تدريب نموذج ليتعلم عدة مهام، لكن تدريبه مكلف وتصميم مجموعة بيانات له أمر صعب. يقدم دمج النماذج حلاً لهذه التحديات من خلال دمج عدة نماذج مُسبقة التدريب في نموذج واحد، مما يمنحه القدرات المجمعة لكل نموذج فردي دون أي تدريب إضافي.
توفر PEFT عدة طرق لدمج النماذج، مثل الجمع الخطي أو الجمع باستخدام التحليل القيمي المفرد (SVD). يركّز هذا الدليل على طريقتين أكثر كفاءةً لدمج محوِّلات LoRA من خلال إزالة المعاملات الزائدة:
- TIES - TrIm, Elect, and Merge (TIES) is a three-step method for merging models. First, redundant parameters are trimmed, then conflicting signs are resolved into an aggregated vector, and finally the parameters whose signs are the same as the aggregate sign are averaged. This method takes into account that some values (redundant and sign disagreement) can degrade performance in the merged model.
- DARE - Drop And REscale هي طريقة يمكن استخدامها للتحضير لطرق دمج النماذج الأخرى مثل TIES. تعمل عن طريق إسقاط المعاملات عشوائياً وفقاً لمعدل إسقاط، وإعادة تحجيم المعاملات المتبقية. يساعد ذلك في تقليل عدد المعاملات الزائدة عن الحاجة والتي قد تتداخل مع بعضها بين عدة نماذج.
تتم دمج النماذج باستخدام طريقة add_weighted_adapter()، ويُحدَّد أسلوب دمج النموذج المحدد في معامل combination_type.
طريقة الدمج
مع TIES و DARE، يتم تفعيل الدمج عن طريق تعيين combination_type و density إلى قيمة الأوزان التي يجب الاحتفاظ بها من النماذج الفردية. على سبيل المثال، لنقم بدمج ثلاثة نماذج TinyLlama/TinyLlama-1.1B-intermediate-step-1431k-3T مُعدّلة: tinyllama_lora_nobots، و tinyllama_lora_sql، و tinyllama_lora_adcopy.
عند محاولتك دمج نماذج مدرَّبة بالكامل باستخدام TIES، يجب أن تكون على دراية بأي رموز خاصة قد أضافها كل نموذج إلى طبقة التضمين (embedding layer) والتي لا تُشكّل جزءاً من قاموس نقطة الحفظ (checkpoint) الأصلية. قد يتسبب ذلك في مشكلة لأن كل نموذج قد أضاف رمزاً خاصاً إلى موضع التضمين نفسه. في هذه الحالة، يجب عليك استخدام طريقة resize_token_embeddings لتجنب دمج الرموز الخاصة عند فهرس التضمين نفسه.
لا ينبغي أن يكون هذا مشكلة إذا كنت تدمج محوِّلات LoRA التي تم تدريبها من نفس النموذج الأساسي فقط.
قم بتحميل نموذج أساسي ويمكنك استخدام طريقة load_adapter() لتحميل كل مُكيّف وتعيين اسم له:
from peft import PeftConfig, PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
config = PeftConfig.from_pretrained("smangrul/tinyllama_lora_norobots")
model = AutoModelForCausalLM.from_pretrained(config.base_model_name_or_path, load_in_4bit=True, device_map="auto").eval()
tokenizer = AutoTokenizer.from_pretrained("smangrul/tinyllama_lora_norobots")
model.config.vocab_size = 32005
model.resize_token_embeddings(32005)
model = PeftModel.from_pretrained(model, "smangrul/tinyllama_lora_norobots", adapter_name="norobots")
_ = model.load_adapter("smangrul/tinyllama_lora_sql", adapter_name="sql")
_ = model.load_adapter("smangrul/tinyllama_lora_adcopy", adapter_name="adcopy")اضبط المُكيّفات والأوزان وadapter_name وcombination_type وdensity باستخدام طريقة add_weighted_adapter().
عادةً ما تُنتج قيم الأوزان الأكبر من 1.0 نتائج أفضل لأنها تحافظ على المقياس الصحيح. قيمة البداية الافتراضية الجيدة للأوزان هي ضبط جميع القيم على 1.0.
adapters = ["norobots", "adcopy", "sql"]
weights = [2.0, 1.0, 1.0]
adapter_name = "merge"
density = 0.2
model.add_weighted_adapter(adapters, weights, adapter_name, combination_type="ties", density=density)adapters = ["norobots", "adcopy", "sql"]
weights = [2.0, 0.3, 0.7]
adapter_name = "merge"
density = 0.2
model.add_weighted_adapter(adapters, weights, adapter_name, combination_type="dare_ties", density=density)اضبط النموذج المدمج حديثًا كنموذج نشط باستخدام طريقة set_adapter().
model.set_adapter("merge")الآن يمكنك استخدام النموذج المدمج كنموذج مُدرَّب على التعليمات لكتابة نصوص إعلانية أو استعلامات SQL!
device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda"
messages = [
{"role": "user", "content": "Write an essay about Generative AI."},
]
text = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
inputs = tokenizer(text, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}
outputs = model.generate(**inputs, max_new_tokens=256, do_sample=True, top_p=0.95, temperature=0.2, repetition_penalty=1.2, eos_token_id=tokenizer.eos_token_id)
print(tokenizer.decode(outputs[0]))device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda"
messages = [
{"role": "system", "content": "Create a text ad given the following product and description."},
{"role": "user", "content": "Product: Sony PS5 PlayStation Console\nDescription: The PS5 console unleashes new gaming possibilities that you never anticipated."},
]
text = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
inputs = tokenizer(text, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}
outputs = model.generate(**inputs, max_new_tokens=128, do_sample=True, top_p=0.95, temperature=0.2, repetition_penalty=1.2, eos_token_id=tokenizer.eos_token_id)
print(tokenizer.decode(outputs[0]))device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda"
text = """Table: 2-11365528-2
Columns: ['Team', 'Head Coach', 'President', 'Home Ground', 'Location']
Natural Query: Who is the Head Coach of the team whose President is Mario Volarevic?
SQL Query:"""
inputs = tokenizer(text, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}
outputs = model.generate(**inputs, max_new_tokens=64, repetition_penalty=1.1, eos_token_id=tokenizer("</s>").input_ids[-1])
print(tokenizer.decode(outputs[0]))دمج نماذج (IA)³
تُسهّل نماذج (IA)³ الدمج الخطي للمُكيّفات. لدمج المُكيّفات في نموذج (IA)³، استخدم طريقة add_weighted_adapter من فئة IA3Model. هذه الطريقة مشابهة لطريقة add_weighted_adapter المستخدمة في LoraModel، مع الفارق الرئيسي المتمثل في غياب معامل combination_type. على سبيل المثال، لدمج ثلاثة مُكيّفات (IA)³ في نموذج PEFT، يمكنك المتابعة على النحو التالي:
adapters = ["adapter1", "adapter2", "adapter3"]
weights = [0.4, 0.3, 0.3]
adapter_name = "merge"
model.add_weighted_adapter(adapters, weights, adapter_name)يُوصى بأن يكون مجموع الأوزان 1.0 للحفاظ على مقياس النموذج. يمكن بعد ذلك تعيين النموذج المدمج كنموذج نشط باستخدام طريقة set_adapter:
model.set_adapter("merge")