TRL documentation
مدرب تقطير المعرفة المعمّم
مدرب تقطير المعرفة المعمّم
نظرة عامة
قُدمت تقنيّة تقطير المعرفة المعمّم (GKD) في On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes من قِبل Rishabh Agarwal وNino Vieillard وYongchao Zhou وPiotr Stanczyk وSabela Ramos وMatthieu Geist وOlivier Bachem.
المستخلص من الورقة البحثية هو كالتالي:
تُستخدم تقنيات تقطير المعرفة (KD) على نطاق واسع لضغط نموذج المعلم لتقليل تكلفة الاستدلال ومساحة الذاكرة، وذلك من خلال تدريب نموذج طالب أصغر حجماً. ومع ذلك، فإن طرق تقطير المعرفة الحالية للنماذج التسلسلية التلقائية (auto-regressive) تعاني من عدم تطابق التوزيع بين التسلسلات الناتجة التي تُشاهد أثناء التدريب وتلك التي يولدها الطالب أثناء الاستدلال. لمعالجة هذه المشكلة، نطرح تقطير المعرفة المعمم (GKD). بدلاً من الاعتماد حصرياً على مجموعة ثابتة من التسلسلات الناتجة، يدرب GKD الطالب على التسلسلات الناتجة التي يولدها بنفسه، مستفيداً من ملاحظات المعلم على مثل هذه التسلسلات. وعلى عكس أساليب تقطير المعرفة الإشرافية، يوفر GKD أيضاً المرونة في استخدام دوال خسارة بديلة بين الطالب والمعلم، وهو ما قد يكون مفيداً عندما يفتقر الطالب إلى القدرة التعبيرية اللازمة لمحاكاة توزيع المعلم. علاوة على ذلك، يسهّل GKD التكامل السلس بين التقطير وضبط الدقة بالتعزيز (RLHF). نُظهر فعالية GKD في تقطير نماذج اللغة التلقائية على مهام تلخيص النصوص والترجمة والاستدلال الحسابي، وكذلك التقطير غير المرتبط بالمهمة الخاصة بضبط التعليمات.
تتمثل الجوانب الرئيسية لـ GKD فيما يلي:
- يعالج عدم تطابق التوزيع بين التدريب والاستدلال في نماذج التسلسل التلقائي التوليدية من خلال تدريب نموذج الطالب على تسلسلات المخرجات التي يولّدها بنفسه.
- يتيح GKD مرونة في اختيار مقاييس تباعد مختلفة بين نموذج الطالب ونموذج المعلم عبر تباعد Jensen-Shannon المعمّم (JSD)، وهو ما قد يكون مفيدًا عندما يفتقر الطالب إلى القدرة على تقليد المعلم بالكامل.
تمت مساهمة طريقة ما بعد التدريب هذه من قِبل Kashif Rasul وLewis Tunstall.
نصائح للاستخدام
يُعدّ experimental.gkd.GKDTrainer غلافًا لفئة SFTTrainer يستقبل حجة نموذج المعلم. ويتطلب ضبط ثلاثة معاملات عبر experimental.gkd.GKDConfig وهي:
lmbda: يتحكم في نسبة بيانات الطالب، أي نسبة المخرجات التي يولدها الطالب وفق سياسته. عندما يكونlmbda=0.0، تقل الخسارة إلى JSD الإشرافي حيث يُدرَّب الطالب باستخدام احتمالات مستوى الرمز للمعلم. عندما يكونlmbda=1.0، تقل الخسارة إلى JSD وفق السياسة، حيث يولّد الطالب تسلسلات المخرجات ويحصل على ملاحظات محددة لكل رمز على هذه التسلسلات من المعلم. أما بالنسبة للقيم الواقعة بين [0, 1]، فهي عشوائية بين النوعين بناءً على قيمةlmbdaلكل دفعة.seq_kd: يتحكم في ما إذا كان سيتم تنفيذ KD على مستوى التسلسل (يمكن النظر إليه على أنه تدريب مُشرَف على المخرجات التي يولّدها المعلم). عندseq_kd=Trueوlmbda=0.0، تقلّص الدالة إلى JSD مُشرَف، حيث يولّد المعلم تسلسلات المخرجات ويحصل الطالب على ملاحظات محددة لكل رمز على هذه التسلسلات من المعلم.beta: يتحكم في الاستيفاء في تباعد Jensen-Shannon المعمّم. عندما يكونbeta=0.0فإن الخسارة تقارب تباعد KL الأمامي، بينما عندbeta=1.0تقارب الخسارة تباعد KL العكسي. أما للقيم الواقعة بين [0, 1] فإنها تستوفي بين النوعين.
وجد المؤلفون أن البيانات على السياسة (قيمة عالية لـlmbda) تحقق أداءً أفضل، وأن القيمة المثلى لـbeta تتفاوت اعتماداً على المهمة وطريقة التقييم.
تأكد من أن
attn_implementation="kernels-community/flash-attn2"عند تدريب نماذج Gemma. وإلا فستواجه قيم NaN في logits بسبب تقنية soft capping المعتمدة في هذه البنية.
الواجهة البرمجية الأساسية هي على النحو التالي:
from datasets import Dataset
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl.experimental.gkd import GKDConfig, GKDTrainer
NUM_DUMMY_SAMPLES = 100
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
# The model to optimise
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
# The teacher model to calculate the KL divergence against
teacher_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2-1.5B-Instruct")
train_dataset = Dataset.from_dict(
{
"messages": [
[
{"role": "user", "content": "Hi, how are you?"},
{"role": "assistant", "content": "I'm great thanks"},
]
]
* NUM_DUMMY_SAMPLES
}
)
eval_dataset = Dataset.from_dict(
{
"messages": [
[
{"role": "user", "content": "What colour is the sky?"},
{"role": "assistant", "content": "The sky is blue"},
]
]
* NUM_DUMMY_SAMPLES
}
)
training_args = GKDConfig(output_dir="gkd-model", per_device_train_batch_size=1)
trainer = GKDTrainer(
model=model,
teacher_model=teacher_model,
args=training_args,
processing_class=tokenizer,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()نوع مجموعة البيانات المتوقع
يجب تنسيق مجموعة البيانات على شكل قائمة من "الرسائل" حيث تكون كل رسالة قائمة من القواميس التي تحتوي على المفاتيح التالية:
role: إماsystemأوassistantأوusercontent: محتوى الرسالة
GKDTrainer
فئة trl.experimental.gkd.GKDTrainer
< source >( model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.Module, str, NoneType] = Noneteacher_model: typing.Union[transformers.modeling_utils.PreTrainedModel, torch.nn.Module, str] = Noneargs: trl.experimental.gkd.gkd_config.GKDConfig | None = Nonedata_collator: collections.abc.Callable[[list[typing.Any]], dict[str, typing.Any]] | None = Nonetrain_dataset: datasets.arrow_dataset.Dataset | None = Noneeval_dataset: datasets.arrow_dataset.Dataset | dict[str, datasets.arrow_dataset.Dataset] | None = Noneprocessing_class: transformers.tokenization_utils_base.PreTrainedTokenizerBase | transformers.image_processing_utils.BaseImageProcessor | transformers.feature_extraction_utils.FeatureExtractionMixin | transformers.processing_utils.ProcessorMixin | None = Nonecompute_metrics: collections.abc.Callable[[transformers.trainer_utils.EvalPrediction], dict] | None = Nonecallbacks: list[transformers.trainer_callback.TrainerCallback] | None = Noneoptimizers: tuple[torch.optim.Optimizer, torch.optim.lr_scheduler.LambdaLR] = (None, None)preprocess_logits_for_metrics: collections.abc.Callable[[torch.Tensor, torch.Tensor], torch.Tensor] | None = Nonepeft_config: PeftConfig | None = Noneformatting_func: collections.abc.Callable | None = None )
المعاملات
- model (PreTrainedModel أو
torch.nn.Moduleأوstr، اختياري) — النموذج المراد تدريبه، أو المعرّف النصي للنموذج الذي سيتم إنشاؤه من نموذج مُسبق التدريب. - teacher_model (PreTrainedModel أو
torch.nn.Moduleأوstr، اختياري) — نموذج المعلم للتقطير المعرفي، أو المعرّف النصي للنموذج الذي سيتم إنشاؤه من نموذج مُدرَّب مسبقًا. - args (experimental.gkd.GKDConfig، اختياري) — حجج التدريب.
- data_collator (
DataCollator، اختياري) — أداة تجميع البيانات لتجميع العينات من مجموعة البيانات. الافتراضي هوexperimental.utils.DataCollatorForChatMLباستخدامprocessing_class. - train_dataset (Dataset، اختياري) — مجموعة بيانات للتدريب.
- eval_dataset (Dataset أو
dictمن Dataset، اختياري) — مجموعة بيانات للتقييم. - processing_class (PreTrainedTokenizerBase أو BaseImageProcessor أو FeatureExtractionMixin أو ProcessorMixin، اختياري) — الفئة المستخدمة لمعالجة البيانات.
- compute_metrics (
Callable، اختياري) — دالة لحساب المقاييس أثناء التقييم. يجب أن تستقبل EvalPrediction وتعيد قاموسًا من السلاسل النصية إلى الأرقام العشرية. - callbacks (
listمن TrainerCallback، اختياري) — المكالمات العكسية (Callbacks) المستخدمة أثناء التدريب. - optimizers (
tupleمنtorch.optim.Optimizerوtorch.optim.lr_scheduler.LambdaLR، اختياري، القيمة الافتراضية(None, None)) — مجموعة تحتوي على المُحسِّن ومجدول معدل التعلم المطلوب استخدامه للتدريب. - preprocess_logits_for_metrics (
Callable، اختياري) — دالة لمعالجة logits مسبقًا قبل حساب المقاييس. يجب أن تستقبلlogitsوlabelsوتعيد logits التي ستُستخدم لحساب المقاييس. - peft_config (PeftConfig، اختياري) —
إعدادات PEFT لاستخدام PEFT في التدريب. إذا كانت
None، فلن يتم استخدام PEFT. إذا تم تقديمها، فسيتم تغليفmodelبمحوّل PEFT المحدد. - formatting_func (
Callable، اختياري) — دالة لتنسيق مجموعة البيانات. يجب أن تستقبل مثالاً وتعيد مثالاً.
Trainer لتعميم تقطير المعرفة (GKD) لنماذج اللغة.
لمزيد من التفاصيل حول GKD، راجع الورقة البحثية: التقطير على سياسة نماذج اللغة: التعلم من الأخطاء التي تولدها ذاتياً.
تدريب
< source >( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput
المعاملات
- resume_from_checkpoint (
strأوbool، اختياري) — إذا كانstr، فهو المسار المحلي لنقطة تفتيش محفوظة بواسطة نسخة سابقة منTrainer. وإذا كانboolويساويTrue، يتم تحميل آخر نقطة تفتيش في args.output_dir كما حفظتها نسخة سابقة منTrainer. إذا كانت موجودة، فسيستأنف التدريب من حالات النموذج/المُحسِّن/المُجدوِل المحمَّلة هنا. - trial (
optuna.Trialأوdict[str, Any]، اختياري) — التجربة أو قاموس المعاملات الفائقة للبحث في المعاملات الفائقة. - ignore_keys_for_eval (
list[str]، اختياري) — قائمة بالمفاتيح في مخرجات النموذج الخاص بك (إذا كان قاموسًا) التي يجب تجاهلها عند جمع التوقعات للتقييم أثناء التدريب.
يعيد
~trainer_utils.TrainOutput
كائن يحتوي على عدد الخطوات العالمية، وخسارة التدريب، والمقاييس.
نقطة الدخول الرئيسية للتدريب.
سيحفظ النموذج، بحيث يمكنك إعادة تحميله باستخدام from_pretrained().
سيتم الحفظ من العملية الرئيسية فقط.
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )
المعاملات
- commit_message (
str، اختياري، الافتراضي"End of training") — الرسالة التي تُرسل عند الدفع. - blocking (
bool، اختياري، الافتراضيTrue) — ما إذا كان ينبغي للدالة أن تُرجع فقط بعد اكتمالgit push. - token (
str، اختياري، القيمة الافتراضيةNone) — رمز (Token) يملك صلاحية الكتابة لتجاوز الحجج الأصلية الخاصة بـ Trainer. - revision (
str، اختياري) — مراجعة git التي سيتم الالتزام منها. الافتراضي هو رأس فرع “main”. - kwargs (
dict[str, Any]، اختياري) — معلمات إضافية تُمرَّر إلى~Trainer.create_model_card.
ارفع self.model وself.processing_class إلى مركز النماذج 🤗 في المستودع self.args.hub_model_id.
GKDConfig
فئة trl.experimental.gkd.GKDConfig
< source >( output_dir: str | None = Noneper_device_train_batch_size: int = 8num_train_epochs: float = 3.0max_steps: int = -1learning_rate: float = 2e-05lr_scheduler_type: transformers.trainer_utils.SchedulerType | str = 'linear'lr_scheduler_kwargs: dict | str | None = Nonewarmup_steps: float = 0optim: transformers.training_args.OptimizerNames | str = 'adamw_torch_fused'optim_args: str | None = Noneweight_decay: float = 0.0adam_beta1: float = 0.9adam_beta2: float = 0.999adam_epsilon: float = 1e-08optim_target_modules: None | str | list[str] = Nonegradient_accumulation_steps: int = 1average_tokens_across_devices: bool = Truemax_grad_norm: float = 1.0label_smoothing_factor: float = 0.0bf16: bool | None = Nonefp16: bool = Falsebf16_full_eval: bool = Falsefp16_full_eval: bool = Falsetf32: bool | None = Nonegradient_checkpointing: bool = Truegradient_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonetorch_compile: bool = Falsetorch_compile_backend: str | None = Nonetorch_compile_mode: str | None = Noneuse_liger_kernel: bool = Falseliger_kernel_config: dict[str, bool] | None = Noneuse_cache: bool = Falseneftune_noise_alpha: float | None = Nonetorch_empty_cache_steps: int | None = Noneauto_find_batch_size: bool = Falselogging_strategy: transformers.trainer_utils.IntervalStrategy | str = 'steps'logging_steps: float = 10logging_first_step: bool = Falselog_on_each_node: bool = Truelogging_nan_inf_filter: bool = Trueinclude_num_input_tokens_seen: str | bool = 'no'log_level: str = 'passive'log_level_replica: str = 'warning'disable_tqdm: bool | None = Nonereport_to: None | str | list[str] = 'none'run_name: str | None = Noneproject: str = 'huggingface'trackio_space_id: str | None = Nonetrackio_bucket_id: str | None = Nonetrackio_static_space_id: typing.Union[str, NoneType, typing.Literal[False]] = Noneeval_strategy: transformers.trainer_utils.IntervalStrategy | str = 'no'eval_steps: float | None = Noneeval_delay: float = 0per_device_eval_batch_size: int = 8prediction_loss_only: bool = Falseeval_on_start: bool = Falseeval_do_concat_batches: bool = Trueeval_use_gather_object: bool = Falseeval_accumulation_steps: int | None = Noneinclude_for_metrics: list[str] = <factory>batch_eval_metrics: bool = Falsesave_only_model: bool = Falsesave_strategy: transformers.trainer_utils.SaveStrategy | str = 'steps'save_steps: float = 500save_on_each_node: bool = Falsesave_total_limit: int | None = Noneenable_jit_checkpoint: bool = Falsepush_to_hub: bool = Falsehub_token: str | None = Nonehub_private_repo: bool | None = Nonehub_model_id: str | None = Nonehub_strategy: transformers.trainer_utils.HubStrategy | str = 'every_save'hub_always_push: bool = Falsehub_revision: str | None = Noneload_best_model_at_end: bool = Falsemetric_for_best_model: str | None = Nonegreater_is_better: bool | None = Noneignore_data_skip: bool = Falserestore_callback_states_from_checkpoint: bool = Falsefull_determinism: bool = Falseseed: int = 42data_seed: int | None = Noneuse_cpu: bool = Falseaccelerator_config: dict | str | None = Noneparallelism_config: accelerate.parallelism_config.ParallelismConfig | None = Nonedataloader_drop_last: bool = Falsedataloader_num_workers: int = 0dataloader_pin_memory: bool = Truedataloader_persistent_workers: bool = Falsedataloader_prefetch_factor: int | None = Nonedataloader_multiprocessing_context: str | None = Nonedataloader_in_order: bool = Trueremove_unused_columns: bool = Truelabel_names: list[str] | None = Nonetrain_sampling_strategy: str = 'random'length_column_name: str = 'length'ddp_find_unused_parameters: bool | None = Noneddp_bucket_cap_mb: int | None = Noneddp_broadcast_buffers: bool | None = Noneddp_static_graph: bool | None = Noneddp_backend: str | None = Noneddp_timeout: int = 1800fsdp: str | None = Nonefsdp_config: dict[str, typing.Any] | str | None = Nonedeepspeed: dict | str | None = Nonedebug: str | list[transformers.debug_utils.DebugOption] = ''skip_memory_metrics: bool = Truedo_train: bool = Falsedo_eval: bool = Falsedo_predict: bool = Falseresume_from_checkpoint: str | None = Nonelocal_rank: int = -1model_init_kwargs: dict[str, typing.Any] | str | None = Nonetrust_remote_code: bool = Falserouter_aux_loss_coef: float | None = Nonechat_template_path: str | None = Nonedataset_text_field: str = 'text'dataset_kwargs: dict[str, typing.Any] | str | None = Nonedataset_num_proc: int | None = Noneeos_token: str | None = Nonemax_length: int | None = 1024truncation_mode: str = 'keep_start'shuffle_dataset: bool = Falsepacking: bool = Falsepacking_strategy: str = 'bfd'padding_free: bool = Falsepad_to_multiple_of: int | str | None = 'auto'eval_packing: bool | None = Nonecompletion_only_loss: bool | None = Noneassistant_only_loss: bool = Falseloss_type: str = 'nll'activation_offloading: bool = Falsepad_token: str | None = Nonetemperature: float = 0.9lmbda: float = 0.5beta: float = 0.5max_new_tokens: int = 128teacher_model_name_or_path: str | None = Noneteacher_model_init_kwargs: dict[str, typing.Any] | str | None = Nonedisable_dropout: bool = Trueseq_kd: bool = False )
المعاملات
- temperature (
float، اختياري، القيمة الافتراضية0.9) — درجة الحرارة للعينات. كلما زادت درجة الحرارة، زادت عشوائية المكملات. - lmbda (
float، اختياري، القيمة الافتراضية0.5) — معامل Lambda الذي يتحكم في نسبة بيانات الطالب (أي نسبة المخرجات التي يولدها الطالب وفق السياسة). - beta (
float، اختياري، القيمة الافتراضية0.5) — معامل الاستيفاء بين0.0و1.0لخسارة تباعد جنسن-شونون المعمّم. عندما تكون قيمة beta هي0.0، تكون الخسارة هي تباعد KL. وعندما تكون قيمة beta هي1.0، تكون الخسارة هي تباعد KL العكسي. - max_new_tokens (
int، اختياري، القيمة الافتراضية128) — الحد الأقصى لعدد الرموز (tokens) التي سيتم توليدها لكل استكمال. - teacher_model_name_or_path (
str, اختياري) — اسم النموذج أو المسار الخاص بنموذج المعلم. إذا كانNone، فسيكون نموذج المعلم هو نفسه النموذج قيد التدريب. - teacher_model_init_kwargs (
dict[str, Any], اختياري) — حجج الكلمات المفتاحية التي يتم تمريرها إلىAutoModelForCausalLM.from_pretrainedعند إنشاء نموذج المعلم من نص. - disable_dropout (
bool، اختياري، القيمة الافتراضيةTrue) — ما إذا كان سيتم تعطيل إسقاط العينة (dropout) في النموذج. - seq_kd (
bool، اختياري، القيمة الافتراضيةFalse) — المعامل الذي يتحكم في ما إذا كان سيتم تنفيذ KD على مستوى التسلسل (يمكن النظر إليه على أنه تدريب موجه على المخرجات التي يولّدها المعلم).
فئة التهيئة لـ experimental.gkd.GKDTrainer.
تتضمن هذه الفئة فقط المعلمات الخاصة بتدريب GKD. للحصول على قائمة كاملة بحجج التدريب، يرجى الرجوع إلى توثيق TrainingArguments و SFTConfig.