TRL documentation

LoRA без сожалений

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.18.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

LoRA без сожалений

Недавние исследования команды из Thinking Machines Lab (Schulman et al., 2025) показывают, что LoRA может обеспечить производительность, сопоставимую с полной дообучением, при правильной конфигурации, используя при этом лишь ~67% вычислительных ресурсов. Эти результаты вызывают интерес у пользователей TRL, поскольку их легко реализовать, а они позволяют повысить качество модели при меньшем бюджете.

В этом руководстве приведены простые инструкции по воспроизведению результатов блога в TRL.

Рекомендуется прочитать статью в блоге перед следованием этому руководству или использовать оба ресурса параллельно для достижения наилучших результатов.

Преимущества LoRA перед полной дообучением

Прежде всего, напомним о преимуществах LoRA перед полной дообучением.

LoRA добавляет адаптерные слои поверх базовой модели, которые содержат значительно меньше параметров, чем сама базовая модель. Такой дизайн снижает требования к памяти GPU и обеспечивает более эффективное обучение. Как описано в блог-посте, изначально считалось, что этот подход связан с компромиссом в производительности, хотя тщательная настройка позволяет преодолеть этот компромисс и достичь производительности, сопоставимой с полным дообучением.

Примеры с TRL

Реализуем и обучим адаптеры LoRA в скриптах TRL, опираясь на ключевые выводы из блога. Затем мы рассмотрим каждый вывод в свете результатов TRL.

Добучение с учителем (SFT)

В блоге выполняется SFT на различных моделях и наборах данных из Hub, что мы можем воспроизвести в TRL.

МодельНабор данных
Llama-3.2-1B-Instructallenai/tulu-3-sft-mixture
Llama-3.2-1B-Instructopen-thoughts/OpenThoughts-114k
Llama-3.1-8B-Instructallenai/tulu-3-sft-mixture
Llama-3.1-8B-Instructopen-thoughts/OpenThoughts-114k
python
jobs
local

Мы можем интегрировать эти результаты с Python API TRL следующим образом:


from datasets import load_dataset
from peft import LoraConfig
from trl import SFTTrainer, SFTConfig

dataset = load_dataset("open-thoughts/OpenThoughts-114k", split="train")

peft_config = LoraConfig(r=256, lora_alpha=16, target_modules="all-linear")

training_args = SFTConfig(
    learning_rate=2e-4,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=4,
    num_train_epochs=1,
    report_to=["trackio"],
)

trainer = SFTTrainer(
    model="Qwen/Qwen2.5-3B-Instruct",
    train_dataset=dataset,
    peft_config=peft_config,
    args=training_args,
)

trainer.train()

После начала обучения вы можете отслеживать прогресс в Trackio, который зафиксирует URL.

Укрепляющее обучение (GRPO)

В блоге выполняется GRPO на различных моделях и наборах данных из Hub, и, как и в предыдущем случае, мы можем воспроизвести результаты в TRL.

МодельНабор данных
Llama-3.1-8B-BaseGSM8k
Llama-3.1-8B-BaseDeepMath-103K
Qwen3-8b-baseDeepMath-103K

Для обучения с подкреплением в блоге используется задача математического рассуждения, которую мы можем воспроизвести в виде функции на Python.

python
jobs
local

Мы можем реализовать эти рекомендации с помощью Python API TRL следующим образом:


from datasets import load_dataset
from peft import LoraConfig
from trl import GRPOConfig, GRPOTrainer
from trl.rewards import reasoning_accuracy_reward

dataset = load_dataset("HuggingFaceH4/OpenR1-Math-220k-default-verified", split="train")

peft_config = LoraConfig(
    r=1,
    lora_alpha=32,
    target_modules="all-linear"
)

training_args = GRPOConfig(
    learning_rate=5e-5,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=4,
    num_train_epochs=1,
    num_generations=8,
    generation_batch_size=8,
    report_to=["trackio"],
)

trainer = GRPOTrainer(
    model="Qwen/Qwen3-0.6B",
    reward_funcs=reasoning_accuracy_reward,
    args=training_args,
    train_dataset=dataset,
    peft_config=peft_config,
)

trainer.train()

В этом фрагменте пропущена функция вознаграждения, определённая выше, чтобы пример оставался лаконичным.

Скрипт обучения с подкреплением с GRPO реализован как пользовательский скрипт в TRL, который использует функцию вознаграждения, показанную выше. Вы можете ознакомиться с ним по адресу grpo.py — Лучшие практики обучения с подкреплением с LoRA

Ключевые результаты оптимизации LoRA

Авторы рекомендуют применять LoRA ко всем матрицам весов, а не ограничиваться слоями внимания, поскольку увеличение ранга не компенсирует это ограничение. В TRL это можно настроить с помощью --lora_target_modules all-linear, чтобы применить LoRA ко всем матрицам весов.

Нам удалось воспроизвести результаты из блога с использованием TRL и модели SmolLM3. Мы обучали модель в течение 500 шагов на наборе данных Math 220k с использованием функции вознаграждения и конфигурации, описанных выше. Как видно на рисунке ниже, средняя кривая вознаграждения при обучении модели LoRA совпадает с кривой полного дообучения.

train reward

И, что самое главное, модель LoRA использует значительно меньше памяти, чем модель полного дообучения, как мы можем увидеть на рисунке ниже.

memory usage

Ниже приведены параметры, которые мы использовали для обучения указанных выше моделей

ПараметрLoRAПолная FT
--model_name_or_pathHuggingFaceTB/SmolLM3-3BHuggingFaceTB/SmolLM3-3B
--dataset_nameHuggingFaceH4/OpenR1-Math-220k-default-verifiedHuggingFaceH4/OpenR1-Math-220k-default-verified
--learning_rate1.0e-51.0e-6
--max_completion_length40964096
--lora_r1-
--lora_alpha32-
--lora_dropout0.0-
--lora_target_modulesall-linear-

Разберём ключевые выводы из блога и то, как нам удалось их воспроизвести.

1. LoRA показывает лучшие результаты при применении ко всем матрицам весов

Авторы рекомендуют применять LoRA ко всем матрицам весов, а не ограничиваться слоями внимания, поскольку увеличение ранга не компенсирует это ограничение.

all layers

LoRA, применяемый только к слоям внимания, показывает худшие результаты даже при использовании более высокого ранга для соответствия количеству параметров. В TRL это можно настроить с помощью --lora_target_modules all-linear, чтобы применить LoRA ко всем матрицам весов. На Python это делается так:

from peft import LoraConfig  

peft_config = LoraConfig(target_modules="all-linear")  

2. Адаптеру необходима достаточная ёмкость для обучения на наборе данных

В блоге рекомендуется использовать достаточный ранг LoRA для обучения на наборе данных. Ранг определяет количество обучаемых параметров в адаптере LoRA. Поэтому «для наборов данных, превышающих ёмкость LoRA, LoRA уступает FullFT».

learning rate

В скрипте TRL можно использовать --lora_r, чтобы задать ранг и подобрать его в зависимости от задачи и набора данных, на котором выполняется обучение. В блоге рекомендуются следующие значения ранга в зависимости от задачи и размера набора данных:

Задачи обучения с подкреплением обычно требуют меньшей ёмкости, поэтому можно использовать меньшие ранги LoRA. Это связано с тем, что алгоритмы градиента политики извлекают примерно ~1 бит информации на эпизод, что требует минимальной ёмкости параметров.

В блоге определяется идеальный размер датасета для LoRA, при котором результаты сопоставимы с полным дообучением, как «Масштаб пост-тренинга». Мы можем использовать его для определения рекомендуемого ранга для LoRA в задачах SFT и RL:

Тип задачиРазмер набора данныхРекомендуемый ранг
SFTМасштаб пост-обучения256
RLЛюбой размер1-32

3. «FullFT и LoRA с высоким рангом имеют схожие кривые обучения»

Контринтуитивно, но в блоге рекомендуется использовать более высокую скорость обучения, чем при полной дообучении. В таблице выше мы использовали 1.0e-5 для LoRA и 1.0e-6 для полной дообучения. В скрипте TRL мы могли бы использовать --learning_rate для установки скорости обучения. Масштабирование 1r \frac{1}{r} в LoRA делает оптимальную скорость обучения приблизительно независимой от ранга.

learning rate

4. «В некоторых сценариях LoRA менее устойчива к большим размерам батчей, чем полная дообучение.»

В блоге рекомендуется использовать эффективный размер батча < 32, поскольку авторы обнаружили, что LoRA менее устойчива к большим размерам батча. Это не удалось компенсировать за счёт увеличения ранга LoRA. В скрипте TRL размер батча можно задать с помощью параметров --per_device_train_batch_size и --gradient_accumulation_steps.

learning rate

Выводы

С помощью TRL вы можете эффективно реализовать адаптеры LoRA, сопоставимые по производительности с полным дообучением, применяя ключевые принципы (целевое воздействие на все матрицы весов, выбор подходящего ранга, а также управление размером пакета и скоростью обучения) без высоких вычислительных затрат, связанных с FullFT.

Цитирование

@article{schulman2025lora,  
    title        = {{LoRA Without Regret}},  
    author       = {John Schulman and Thinking Machines Lab},  
    year         = 2025,  
    journal      = {Thinking Machines Lab: Connectionism},  
    doi          = {10.64434/tml.20250929},  
    note         = {https://thinkingmachines.ai/blog/lora/}  
}  
Update on GitHub