LangChain 101 Часть 2с. Тонкая настройка LLM с использованием PEFT, LORA и RL

LangChain 101 Часть 2 Улучшение работы LLM с применением PEFT, LORA и RL

Чтобы лучше понять эту статью, ознакомьтесь с предыдущей частью, где я обсуждаю большие языковые модели:

LangChain 101: Часть 2ab. Все, что вам нужно знать о (больших языковых) моделях

pub.towardsai.net

Если вас интересует langchain и большие языковые модели, рекомендуется посетить первую часть серии:

LangChain 101: Часть 1. Создание простого приложения вопрос-ответ

В этой статье я расскажу вам основы LangChain, фреймворка для создания приложений с использованием больших…

pub.towardsai.net

Следите за автором, чтобы не пропустить следующую часть 🙂

В машинном обучении и науке о данных часто называют моделью черный ящик, который делает предсказания. Существуют разные модели, и одна из них – языковая модель. Языковые модели существовали некоторое время, но не были так популярны, как после появления ChatGPT. Одна из причин заключается в том, что модель GPT-1 была обучена на небольшом количестве данных. С ростом числа после GPT возросло и количество данных, что привело к появлению больших языковых моделей, или LLM, как их чаще называют.

Тонкая настройка модели

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

https://github.com/IvanReznikov/DataVerse/tree/main/Courses/LangChain/Lecture2.%20Models

Я слышал много вопросов: стоит ли настраивать большую языковую модель? Почему бы не использовать подсказки – они, казалось бы, в порядке. Можно ли вместо этого использовать векторное хранение? И другие вопросы, касающиеся этой темы…

Подумайте о следующей ситуации: вы собираетесь к стоматологу. Какого вы предпочтете:

  • Человека, который действует как врач (подсказка: “Представьте, что вы – стоматолог…”)
  • Человека, который прочитал всю литературу о стоматологическом уходе (использование векторных хранилищ)
  • Врача, который был обучен делать стоматологические операции (модель с тонкой настройкой)

Аудитория, с которой я общался, определенно выбрала последний вариант (PyData и митапы по науке о данных)

PEFT – параметр-эффективная тонкая настройка

PEFT, или параметр-эффективная тонкая настройка, – это метод, который улучшает производительность предварительно обученных языковых моделей без тонкой настройки всех параметров модели. Это делает его более эффективным и экономичным способом для тонкой настройки LLM, особенно для больших моделей с миллиардами или триллионами параметров.

PEFT работает путем замораживания некоторых слоев предварительно обученной модели и тонкой настройки только последних нескольких слоев, специфичных для конкретной задачи. Это основано на наблюдении, что нижние слои LLM-моделей обычно более общего назначения и менее связаны с конкретной задачей, в то время как более высокие слои более специализированы для задачи, на которой была обучена LLM. Классическая передача обучения.

Вот пример того, как PEFT может быть использован для настройки LLM для задач классификации текста:

  1. Заморозьте первые несколько слоев предобученной модели LLM.
  2. Настройте незамороженные слои LLM на более небольшом наборе данных с пометками текста.
  3. Модель настроена и может быть протестирована на невидимых данных.

LoRa — Адаптация низкого ранга, о которой все говорят

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

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

Теперь, в чем разница между PEFT и LoRa? PEFT – это метод, который эффективно использует различные техники, включая LoRa, для настройки крупных моделей языка.

https://github.com/IvanReznikov/DataVerse/tree/main/Courses/LangChain/Lecture2.%20Models

У этого подхода есть несколько преимуществ:

  1. Это более эффективный в плане времени способ, чем полная настройка параметров, особенно для крупных моделей трансформатора.
  2. Это более экономичный по памяти способ, что позволяет настраивать модели на устройствах с ограниченной памятью.
  3. Это более контролируемая настройка, поскольку матрицы низкого ранга кодируют определенные знания или ограничения.

Обучение с подкреплением

Обучение с подкреплением (RL) – это еще один способ настройки моделей. Для этого требуется две копии оригинальной модели. Одна копия является активной моделью, обученной выполнять желаемую задачу. Другая копия – модель-справка, которая используется для генерации логитов (нормализованный вывод модели), ограничивающих обучение активной модели.

Как LLM генерирует текст?

Эта статья не будет обсуждать трансформаторы или то, как обучаются крупные модели языка. Вместо этого мы сосредоточимся на использовании…

pub.towardsai.net

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

https://github.com/IvanReznikov/DataVerse/tree/main/Courses/LangChain/Lecture2.%20Models

Давайте пройдем через процесс настройки:

  1. Справочная модель инициализируется параметрами предварительно обученной модели языка.
  2. Активная модель начинает обучение с помощью обучения с подкреплением.
  3. На каждом оптимизационном шаге вычисляются логиты как для активной, так и для справочной моделей (лог-вероятности).
  4. Затем функция потерь вычисляется с использованием логитов как для активной, так и для справочной моделей (метрика KL).
  5. Затем параметры активной модели обновляются с использованием градиентов функции потерь или проксимальной политики оптимизации.

Время писать код!

Полный код доступен на GitHub.

Мы начнем с импорта пакета peft и его подготовки к настройке.

from peft import prepare_model_for_kbit_trainingpretrained_model.gradient_checkpointing_enable()model = prepare_model_for_kbit_training(pretrained_model)

Мы зададим параметры LoraConfig и используем метод get_peft_model для создания PeftModel:

  • r: Ранг низкоранговых матриц представляет разницу между исходными предварительно обученными весами и желаемыми весами при настройке. Более высокое значение r позволяет LORA изучать более сложные взаимосвязи между параметрами, но это также требует больше вычислительных ресурсов.
  • lora_alpha: Гиперпараметр, который контролирует баланс между функцией потерь для задачи вторичного обучения и функцией потерь для сохранения исходных предварительно обученных весов. Более высокое значение lora_alpha дает больше веса функции потерь для сохранения исходных предварительно обученных весов.
  • target_modules: Список названий модулей в модели, которые должны быть настроены с помощью LORA.
  • lora_dropout: Коэффициент отсева для низкоранговых матриц во время обучения.
  • bias: Тип смещения, который будет использоваться в низкоранговых матрицах. Допустимые варианты: “none”, “shared” и “individual”.
  • task_type: Тип задачи, для которой модель настраивается. Допустимые варианты: “CAUSAL_LM” и “CLASSIFICATION”.
from peft import LoraConfig, get_peft_modelconfig = LoraConfig(    r=16,    lora_alpha=32,    target_modules=["query_key_value"],    lora_dropout=0.05,    bias="none",    task_type="CAUSAL_LM",)model = get_peft_model(model, config)

Теперь настало время настроить класс Trainer:

  • data_collator: Функция, используемая для объединения тренировочных данных в пакеты.
  • per_device_train_batch_size: Размер пакета на одном графическом процессоре.
  • gradient_accumulation_steps: Количество шагов для накопления градиентов перед обновлением параметров модели. Это может использоваться для уменьшения использования памяти и улучшения скорости обучения.
  • warmup_ratio: Пропорция шагов обучения, затраченных на линейный режим разогрева скорости обучения.
  • fp16: Использовать ли обучение с плавающей запятой с 16-битной (FP16) точностью. Это может улучшить скорость обучения и уменьшить использование памяти.
  • logging_steps: Количество шагов обучения между обновлениями записей.
  • output_dir: Директория, в которой будут сохранены обученная модель и другие артефакты обучения.
  • optim: Оптимизатор для обучения модели. Допустимые варианты: “adamw”, “sgd” и “paged_adamw_8bit”.
  • lr_scheduler_type: Используемый планировщик скорости обучения. Допустимые варианты: “cosine”, “linear” и “constant”.
trainer = transformers.Trainer(    model=model,    train_dataset=train_dataset,    # eval_dataset=val_dataset,    args=transformers.TrainingArguments(        num_train_epochs=10,        per_device_train_batch_size=8,        gradient_accumulation_steps=4,        warmup_ratio=0.05,        max_steps=40,        learning_rate=2.5e-4,        fp16=True,        logging_steps=1,        output_dir="outputs",        optim="paged_adamw_8bit",        lr_scheduler_type="cosine",    ),    data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),)

Все, что нам осталось сделать, это начать тренировку:

trainer.train()

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

trained_model = (    trainer.model.module if hasattr(trainer.model, "module") else trainer.model)  # Позаботьтесь о распределенном/параллельном обучении# Использование модельtrained_model.generate(input_ids)# Сохранение моделиtrained_model.save_pretrained("outputs")

Напоминание: полный код доступен на GitHub.

Это конец Части 2с. Следующая часть (de) будет посвящена настройке моделей с использованием отзывов пользователей.

LangChain 101: Часть 1. Создание простого приложения для вопросов и ответов

В этой статье я познакомлю вас с основами LangChain, фреймворка для создания приложений с большими…

pub.towardsai.net

LangChain 101: Часть 2аб. Все, что вам нужно знать о (больших языковых) моделях

pub.towardsai.net

Поставьте лайк и подпишитесь на меня, таким образом вы мотивируете меня писать новые статьи и узнаете, когда выйдет следующая часть.