Текущее состояние непрерывного обучения в искусственном интеллекте

Самая актуальная ситуация с непрерывным обучением в искусственном интеллекте

Почему ChatGPT обучен только до 2021 года?

Изображение, созданное автором с использованием DALL-E 3

Требования к знаниям:

Несколько лет назад я изучил основы глубокого обучения благодаря видеороликам StatQuest, блогам Лены Войты по NLP и книгам “Deep Learning for Coders” и “Talking Nets”. Теперь я хочу понять текущее состояние постоянного обучения в глубоком обучении. Я обнаружил, что доступно не так много информации, которая кратко описывает эту тему простыми словами, и для ее понимания необходимо прочитать множество экспертных исследовательских статей. Поэтому эту статью предназначена для читателей, которые имеют базовое понимание темы, но испытывают трудности в чтении научных исследований и могут не являться экспертами. Особое внимание уделяется чатботам, поэтому полезно знать этапы обучения ChatGPT.

Введение

ChatGPT говорит пользователю, что он обучен только до сентября 2021 года (скриншот автора)

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

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

В настоящее время тенденция в отрасли заключается в том, чтобы расширять возможности чатботов за счет дополнительных данных, используя векторные хранилища, комбинируя запрошенные векторы с инженерией подсказок для отвечания на вопросы, вместо продолжения обучения LLM новыми данными. Возможность нулевого обучения в ChatGPT, позволяющая ему отвечать на вопросы о новых, неизвестных данных, делает этот подход очень привлекательным. Например, вы можете обучить его новому языку программирования, а затем задать ему вопросы об этом языке всего с несколькими подсказками, хотя производительность может немного ухудшиться пропорционально количеству входных токенов. Непрерывное обучение модели для отвечания на вопросы, связанные с новой такой темой, требует значительных вычислительных ресурсов и, что еще более важно, широкого набора данных по соответствующей теме. Кроме того, если тема имеет очень низкое распространение в обучающем наборе, модель будет плохо обобщать на нее. Например, возьмите непопулярное открытое хранилище, и модель ничего не будет знать о нем, несмотря на то, что в какой-то момент видела его в процессе обучения. Окна контекста быстро увеличиваются, что делает векторный подход еще более привлекательным. Идеально же, не хотим ли мы иметь одну интеллектуальную всеобучающую модель, без необходимости использования внешней базы данных?

Постоянное обучение является важным шагом на пути к AGI, и некоторые сомневаются, что мы сможем достичь его без значительных изменений в архитектуре сетей глубокого обучения. Джефф Хокинс в своей книге “Тысяча мозгов” заявил, что по его мнению текущие нейронные сети не способны эффективно обучаться непрерывно и будущие модели, вероятно, должны быть построены схожим образом с человеческим мозгом, используя его теорию о координатных системах в кортикальных столбиках неокортекса.

Реклама

У меня есть проект с открытым исходным кодом, целью которого является помощь в постоянном обучении и сопутствующему чатботам расширенными данными. Я вел разговор с Дэном Майером из VectorFlow и, несмотря на то, что отрасль очень обширна, в этом направлении практически нет прогресса. Презентацию можно найти здесь 🙂

Постоянное обучение на этапах предварительного обучения и настройки языковых моделей

Ранее в этом году была опубликована научная статья под названием «LIMA: Less Is More for Alignment». В ней был представлен чатбот, который не был обучен с помощью обратной связи обучения с подкреплением от человека (RLHF), но был тщательно настроен на всего 1 000 вопросов и ответов. Удивительно, но исследователи заявили, что в 43% случаев «ответы чатбота находились на уровне GPT-4». Я не изучала подробно, как они были оценены, но тем не менее широко признается, что значительное количество знаний и способностей модели приобретается во время предварительного обучения, и исследования, подобные этому, дополнительно это доказывают.

Модели, такие как ChatGPT и Llama-chat, прошли обширную настройку для генерации более согласованных и эффективных ответов. OpenAI в настоящее время предлагает API для дополнительной настройки модели, которая использует входные данные вопросов и ответов. Однако это не следует использовать для обучения модели новым данным, а скорее для настройки тона и управляемости. Попытка настроить модель для обучения новым данным может привести к катастрофическому забыванию, проблеме, при которой модель забывает то, что уже узнала. В этой статье будут рассмотрены некоторые методы, направленные на смягчение этой проблемы.

Это также приводит нас к паре ключевых вопросов о целесообразности и стратегии непрерывного обучения:

  • На какой стадии разработки наиболее выгодно и проще внедрить непрерывное обучение?
  • Учитывая, что как настройка модели, так и RLHF изменяют параметры всей модели, возможно ли вернуться к стадии предварительного обучения для дальнейшей модификации?

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

5 подкатегорий методов непрерывного обучения

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

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

1. Методы, основанные на регуляризации

Мягкое маскирование параметров

Следующие методы мягкого маскирования маскируют и корректируют градиенты каждого параметра в процессе обучения. Последующие описанные методы, основанные на оптимизации, также используют градиенты для непрерывного обучения. Помните, что градиенты не являются временными числами, которые появляются и исчезают во время обучения; они являются сигналами, которые направляют эволюцию весов.

SPG

В этой статье предлагается метод, называемый SPG (маскирование градиента на уровне параметра), который стремится:

  1. Провести обучение модели для каждой задачи до сходимости.
  2. После обучения рассчитать «важность» каждого параметра для задачи.
  3. Маскировать параметры на основе их накопленной важности, делая важные параметры менее вероятными для изменения во время обучения новых задач.

Давайте разберем подход пошагово:

1. Обучение первой задаче

Обучите модель на датасете первой задачи, как обычно.

2. Вычисление важности параметров для первой задачи

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

Градиенты также нормализуются, потому что градиенты в первом слое могут быть маленькими, в то время как в последнем слое они могут быть большими. Если вы вычисляете важность на основе этих сырых значений градиента, параметры в последнем слое будут казаться более важными из-за масштаба их градиентов, а не обязательно потому, что они действительно важнее для задачи.

Уравнения для вычисления важности параметров модели в SPG (раздел 3.1 статьи)

Давайте переведем этот расчет в псевдокод, похожий на PyTorch:

загрузка torchdef вычислить_окончательную_важность(model, функция_потерь, загрузчик_данных):    # Получить одну партию из загрузчика данных    входы, метки = следующий(iter(загрузчик_данных))     # Прямой и обратный проход для вычисления градиентов всех параметров    выходы = model(входы)    потеря = функция_потерь(выходы, метки)    потеря.backward()        важности = []    # Вычислить важность на основе градиентов    для параметра в model.parameters():        если param.grad не является None:  # Градиенты могут быть None для некоторых неиспользуемых параметров            нормализованный_град = (param.grad - torch.mean(param.grad)) / torch.std(param.grad)            важность = torch.tanh(нормализованный_град)            важности.append(важность)    return torch.stack(важности).mean(dim=0)

3. Накопление важности для всех задач

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

4. Обучение последующих задач, объединенная потеря и механизм мягкого маскирования:

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

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

Обучите модель на следующей задаче. Используйте стандартный цикл обучения, но измените градиенты во время обратного распространения ошибки на основе накопленной важности. Это механизм мягкого маскирования:

import torchнакопленная_важность = # вычислено в конце каждой задачиfor эпоха в range(num_epochs):  для x, y в train_loader:                # Прямой проход: Вычислить потерю для текущей задачи, используя соответствующую функцию потерь    логиты = new_model(x)    потеря_текущей_задачи = nn.CrossEntropyLoss()(логиты, y)                # Прямой проход: Вычислить дополнительные потери для предыдущих задач (механизм CHI)    потеря_предыдущих_задач = 0    for prev_task_id in range(task_id):        логиты_предыдущих = old_model(x, prev_task_id)        потеря_предыдущих_задач += логиты_предыдущих.sum()                # Объединение потерь    объединенная_потеря = потеря_текущей_задачи + потеря_предыдущих_задач                # Обратный проход    optimizer.zero_grad()    объединенная_потеря.backward()                # Обновление накопленной важности    for param, acc_imp in zip(model.parameters(), accumulated_importance):        grad = param.grad        acc_imp = torch.max(acc_imp, torch.abs(grad))     # Мягкое маскирование градиентов перед выполнением шага оптимизации    for param, imp in zip(model.parameters(), accumulated_importance):        param.grad *= (1 - importance)                optimizer.step()

5. Особые случаи мягкого маскирования

  • Экстрактор функций: Градиенты параметров в общем экстракторе функций изменяются в соответствии с их накопленной важностью.
  • Голова классификации: Для головы классификации градиенты изменяются в соответствии со средней важностью экстрактора функций.

Применение этого к LLMs

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

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

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

В этой статье представлена техника, называемая DAS (Continual DA-pre-training of LMs with Soft-masking), для последовательного обучения на этапе предварительного обучения большой языковой модели. Она применяет метод мягкого маскирования, подобный описанному ранее, вместе с несколькими другими методами, чтобы продолжить предварительное обучение LLM без возникновения катастрофического забывания.

Разберем это по шагам:

Этап начального предварительного обучения

Предварительно обучаем LLM как обычно.

Дальнейшее предварительное обучение в новой области

Подготовка данных новой области:

Подготавливаем новый набор данных из другой области.

Вычисление важности каждого нейрона

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

В данной статье используются два разных метода для вычисления важности нейронов в зависимости от поставленной задачи. Первый – метод определения важности на основе градиентов (первоначально описанный в этой статье), а второй – пользовательская “прокси-функция потерь”.

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

И предлагается использовать “прокси-функцию потерь”:

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

Согласно статье, важность вычисляется для каждого “блока” в сети, где блоком может быть нейрон или головка внимания.

Прокси-функция потерь (“Proxy KL-расхождение”):

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

Измененный поток обратного распространения с прокси-функцией и объединенной потерей

  1. Прямой проход: Данные проходят через нейронную сеть.
  2. Обратное распространение:

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

adjusted_grad *= (1 − unit_level_importance)

Расчет совместной потери (MLM + контрастивная потеря): Вычислить совместную потерю, используя и MLM, и контрастивную потерю.

Дополнительное предварительное обучение на более широком спектре областей

  1. Прямой расчет важности: Для каждой новой области важность каждой единицы теперь может быть прямо вычислена с использованием данных из новой области с помощью метода на основе градиента, описанного в уравнении 3, что исключает необходимость использования функции потерь-заместителя, которая используется только один раз после начального предварительного обучения.
  2. Важность нейронов обновляется постепенно при обучении каждой новой задачи. Это обновление выполняется с использованием поэлементной операции максимума. “Операция максимума поэлементно (EMax)” означает сравнение двух векторов элемент за элементом и взятие максимального значения для каждого соответствующего элемента для создания нового вектора. Например: если у вас есть два вектора A и B одинаковой длины, поэлементный максимум приведет к созданию нового вектора C, где каждый элемент C[i] является максимальным значением между A[i] и B[i].

2. Основанные на оптимизации подходы

Мы будем ссылаться на две техники, описанные в комплексном обзоре статьи в разделе 3.1

Сохранение направления градиента

В статье рассказывается о модификации процесса градиентной оптимизации для того, чтобы направления градиентов новых обучающих примеров были близки к направлениям градиентов старых обучающих примеров. Формула

⟨ ∇θ Lₖ(θ; Dₖ), ∇θ Lₖ(θ; Mₜ) ⟩ ≥ 0

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

Разделив формулу, мы берем скалярное произведение градиента потери новой задачи (∇θ Lₖ(θ; Dₖ)) и градиента потери старой задачи (∇θ Lₖ(θ; Mₜ)), которое должно быть неотрицательным. В этом контексте положительное скалярное произведение означает, что градиенты для старой задачи и новой задачи, в основном, указывают в одном направлении, и угол между этими двумя векторами менее или равен 90 градусам.

Прямой / Обратный проходы:

Прямой проход:

Вы должны пропустить входные данные Dₖ для новой задачи и Mₜ для старой задачи через ту же модель для вычисления потери для каждой из них.

Обратный проход:

  1. Вычислите градиенты потери по отношению к параметрам сети для старой и новой задачи.
  2. Проверка выравнивания: Вычислите скалярное произведение двух градиентов. Затем используйте эту информацию для модификации градиентов для новой задачи таким образом, чтобы скалярное произведение было неотрицательным.
  3. Обновление весов: Обновите параметры модели, используя эти “выровненные” градиенты.
import torch# Прямой проход для новой задачиoutput_k = model(D_k)loss_k = criterion(output_k, y_k)# Прямой проход для старой задачиoutput_t = model(M_t)loss_t = criterion(output_t, y_t)# Вычисление градиентов для обеих задачloss_k.backward(retain_graph=True)  # Вычисление градиентов для новой задачи, но сохранение графа вычисленийgrad_k = torch.cat([p.grad.view(-1) for p in model.parameters()])  optimizer.zero_grad() loss_t.backward()  # Вычисление градиентов для старой задачиgrad_t = torch.cat([p.grad.view(-1) for p in model.parameters()]) # Вычисление скалярного произведения и модификация градиентов, если они не выравниваютсяdot_product = torch.dot(grad_k, grad_t)if dot_product < 0:    # Я не уверен, как модифицировать градиенты, если они не выравниваются, я не уверен, что это указано в статье# Используйте модифицированный градиент для обновления параметров моделиindex = 0for p in model.parameters():    num_params = p.numel()    # Обновление с использованием модифицированных градиентов    p.grad = grad_k[index: index + num_params].view(p.shape)    index += num_paramsoptimizer.step()

Сохранение направления градиента без необходимости старых обучающих примеров

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

Процесс обучения пошагово:

Прямой проход:

Вы запускаете новые данные через сеть и вычисляете потери, как обычно.

Обратный проход:

Цель: Минимизировать специфические для задачи потери ℓk(θ), соблюдая ограничение расстояния d(θ,θ+δ)≤r.

Алгоритм пошагово:

  1. Как обычно, вычисляется градиент потерь по параметрам модели ∇θ​ℓk​(θ).
  2. Значение δ вычисляется с использованием правила обновления. Это позволяет получить «предлагаемые» изменения параметров модели θ на основе требований новой задачи.
  3. Затем вы подставляете это значение δ в формулу ограничения расстояния: d(θ,θ+δ)=квадратный корень(δ⊤Λ_k-1​δ)​. Ограничение действует как граница вокруг текущих параметров θ, определенная метрикой расстояния d(θ,θ+δ) и радиусом r. Мне было трудно понять, почему они назвали это «радиусом», а не просто «ограничением числа» или что-то в этом роде. Я думаю, что исследователи визуализируют градиенты и процесс обучения в многомерном пространстве. Когда вы применяете ограничение на основе метрики расстояния, вы фактически определяете «сферу» вокруг текущих значений параметров в этом многомерном пространстве. «Радиус» r этой сферы устанавливает ограничение на то, насколько параметр может перемещаться при изучении новой задачи.
  4. Если предлагаемое значение δ согласно этой метрике расстояния переместит θ слишком далеко, то есть за пределы этой границы, его можно уменьшить, чтобы оно оставалось в допустимой области, определенной радиусом r.

Давайте рассмотрим каждую часть более подробно:

Правило обновления: Правило обновления указывает, в каком направлении должен двигаться θ.

Правило обновления NCL из раздела 3.1 в полном обзоре доклада о непрерывном обучении

Разберем это подробнее:

  • ∇θ ℓk(θ) представляет градиенты для всех параметров (θ), рассчитанные функцией потерь.
  • Расчет важности параметров (Λ^(k-1)_(-1)): Этот термин представляет собой матрицу точности и является еще одним способом рассчета важности параметров в сети. Более подробная информация ниже
  • Терм регуляризации (θ — μ_(k-1)): Этот термин притягивает обновленные параметры ближе к оптимальным параметрам μ_(k-1)​ предыдущей задачи. Как и в предыдущих методах, он действует как регуляризатор, чтобы избежать отклонения от того, что уже было изучено.
  • Скорость обучения (λ)

Ограничение расстояния: Прежде чем применять это обновление, обычно проверяется, нарушает ли это изменение δ ограничение расстояния d(θ,θ+δ)≤r. Если да, то обычно уменьшают δ так, чтобы оно удовлетворяло ограничению.

Объяснение матрицы точности: ранее в методах мягкой маскировки мы видели расчет важности с помощью вывода всех нейронов или их градиентов. В этом методе используется матрица точности. Это немного сложнее, поэтому я постараюсь объяснить:

Сначала мы рассчитываем матрицу ковариации для параметров сети. В контексте нейронных сетей столбцы в матрице градиента G соответствуют параметрам (весам и смещениям) модели. Каждая строка в G представляет градиентный вектор для одного обучающего примера относительно всех этих параметров.

Итак, если у вас есть нейронная сеть с P параметрами (включая все веса и смещения всех слоев), то каждый вектор градиента будет иметь P элементов, по одному для каждого параметра. Следовательно, G будет матрицей формы N × P, где N представляет каждую партию и, следовательно, каждая строка представляет средний вектор градиента по всем примерам обучения в данной партии.

При вычислении матрицы ковариации Σ из G, итоговая матрица будет иметь размерности P × P. Диагональные элементы Σii будут указывать на дисперсию градиента по отношению к i-му параметру, а внедиагональные элементы Σij будут указывать на ковариацию между градиентами по отношению к i-му и j-му параметрам. Это дает представление о том, как эти параметры взаимодействуют или коварьируют в процессе обучения. Обратная матрица является матрицей точности, которую мы используем для определения важности.

Почему матрица точности вместо матрицы ковариации? Хотя матрица ковариации Σ учитывает взаимодействие параметров друг с другом во время обучения, она не указывает специфически, насколько важен каждый параметр для задачи при учете всех остальных параметров. В отличие от этого, матрица точности позволяет оценить условную независимость (это концепт в теории вероятностей, поищите информацию) параметров. Большие значения в матрице точности указывают на то, что знание одного параметра является существенно информативным для другого, при известных остальных параметрах. Я не собираюсь приводить примеры того, как это работает, поэтому попросите ChatGPT создать некоторые примеры, используя очень маленькую нейронную сеть, чтобы увидеть, как значения могут быть интерпретированы.

Предыдущие методы, которые мы видели для расчета значимости, сосредотачивались на отдельных нейронах или параметрах, игнорируя взаимосвязи между ними. Матрица точности, с другой стороны, может улавливать эти взаимосвязи. Как и всё в глубинном обучении, то, является ли это лучшим способом расчета важности сети, будет эмпирическим и может отличаться в зависимости от задачи и масштаба сети.

Алгоритм пошагово на PyTorch:

import torch# Ограничение радиусаradius = 0.1for epoch in range(num_epochs):      for batch_idx, (data, target) in enumerate(data_loader):        optimizer.zero_grad()        # Проход вперед        output = model(data)        loss = loss_function(output, target)        # Обратный проход для получения градиентов по параметрам        loss.backward()        model_grad = torch.cat([p.grad.data.view(-1) for p in model.parameters()])        # Вычисление δ с использованием метода NCL        # δ = Λ^(-1) * grad - (θ - µ)        delta = torch.matmul(torch.inverse(covarianceMatrix), model_grad) - (torch.cat([p.data.view(-1) for p in model.parameters()]) - parametersForPrevTask)        # Проверка ограничения        if torch.norm(delta) > radius:            delta = radius * delta / torch.norm(delta)        # Обновление параметров модели (θ) с использованием δ        idx = 0        for p in model.parameters():            length = p.data.numel()            p.data += delta[idx: idx + length].view(p.data.shape)            idx += length        # Обновление Λ и µ для следующей задачи, возможно, будет специфично для задачи и нетривиально

3. Подход на основе репрезентации

Прежде всего, важно отметить, что предварительное обучение LLM для дальнейшей настройки на последующую задачу является примером непрерывного обучения в этой подкатегории. Я считаю, что способность ChatGPT рассуждать о ранее не виденных данных также является примером этого подхода. Хотя технически мы называем это обучением с нуля, а термин “непрерывное обучение” требует обновления параметров модели, это превосходит все, что мы видели раньше. Как обсуждалось во введении, инженерия запросов может быть будущим непрерывного обучения, вместо постоянного обновления параметров.

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

Дистилляция знаний для непрерывного обучения

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

Обучается дистиллированная модель (студент) с целью имитировать вывод большей сети (учителя), а не обучаться непосредственно на необработанных данных. Например, скажем, вы хотите обучить более маленькую модель-студент, чтобы она имитировала большую предварительно обученную языковую модель (учителя). Пропустите исходный набор данных предварительного обучения через модель учителя, чтобы сгенерировать “мягкие цели”. Это вероятностные распределения для потенциальных выводов, например: предсказания следующего слова. Например, для задачи предсказания следующего слова, вместо предсказания “кошка” учитель может дать вероятности, такие как 90% для “кошка”, 5% для “котенок”, 3% для “кошачий” и так далее.

Это обычно делается для передачи знаний менее масштабным моделям, и это приносит отличные результаты, несмотря на уменьшенную модель.

Посмотрим, как некоторые исследователи применили это с успехом к модели NER (распознавание именованных сущностей). Процесс обучения довольно прост:

Шаги процесса обучения

В статье описаны два основных метода: AddNER и ExtendNER.

Модель AddNER

Обратите внимание, что модели NER работают, принимая последовательность токенов (обычно предложение) на вход и выводя для каждого токена распределение вероятности (для различных типов сущностей). Часто для моделей NER используется маркировка IOB, при которой каждый токен может быть помечен как ‘O’ или как начало (‘B-’) или внутри (‘I-’) сущности типа X. ‘O’ означает ‘Снаружи’ и означает, что текущий токен не принадлежит ни одной сущности. Поэтому для n типов сущностей у вас будет 2n нейронов на выходном слое классификации: n для тегов ‘B-’ (по одному для каждого типа сущности) и n для тегов ‘I-’ (снова по одному для каждого типа сущности). К этому добавляется метка ‘O’, которая означает, что токен не принадлежит ни одной сущности, и тогда у вас есть 2n + 1 возможных меток для каждого токена. Итоговые размерности могут быть записаны как h × (2n + 1), где h – это размер выходного слоя скрытого слоя. Имейте в виду, это только для моделей, в которых токены могут принадлежать только одной сущности. Например, “Apple” может быть помечено как “FOOD” и “COMPANY” одновременно.

Архитектура и установка учителя-ученика

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

После обучения старые выходные слои не выбрасываются. Затем используется алгоритм и эвристики, описанные в разделе решателя конфликтов (конец раздела 3.3), чтобы объединить эти выходы в одну окончательную предсказание для каждого токена в последовательности.

Диаграмма модели AddNER из раздела 3.2 статьи

Прямой проход

  1. Старые типы сущностей: Входное предложение проходит через модель учителя для получения распределений вероятности («моющиеся мишени» в этом контексте) для старых типов сущностей.
  2. Новые типы сущностей: То же самое предложение также проходит через новую модель ученика с дополнительными выходными слоями, специфичными для новых типов сущностей.

Обратный проход

Объединенная функция потерь:

  1. Потеря KD: вычисляется путем сравнения того, насколько тесно выходные вероятности старых типов сущностей новой модели (студента) соответствуют тем из старой модели (учителя). Для этого используется KL-дивергенция. Вероятно, это вычисляется токен за токеном, а затем суммируется или усредняется по всем токенам в предложении или пакете, но я не думаю, что в статье углубляются в эту тему.
  2. Потеря перекрестной энтропии: это обычная функция потерь, которая сравнивает прогнозы модели для новых типов сущностей с фактическими метками из нового набора данных.
  3. Объединение двух функций потерь: эти две потери объединяются вместе, взяв взвешенную сумму обоих. Веса для объединения этих потерь устанавливаются гиперпараметрами альфа и бета, которые подбираются, как и любой другой гиперпараметр, для достижения лучшей производительности на основе экспериментов.
# Гиперпараметры альфа и бета для взвешивания двух функций потерьalpha = 0.5beta = 0.5for epoch in range(num_epochs):    for sentence, labels in D_new:        # Прямой проход в модели учителя для старых типов сущностей        teacher_probs_Ei = teacher_model(sentence)                # Прямой проход в студенческой модели для старых и новых типов сущностей        # Примечание: новые типы сущностей должны проходить через новый выходной слой (не показан в этом псевдокоде)        student_probs_Ei, student_probs_Enew = student_model(sentence)                # Вычисление потери KD        kd_loss = KL_divergence(teacher_probs_Ei, student_probs_Ei)                # Вычисление потери перекрестной энтропии для новых типов сущностей        ce_loss = cross_entropy(labels, student_probs_Enew)                # Общая потеря        total_loss = alpha * kd_loss + beta * ce_loss                # Обратный проход        total_loss.backward()                # Обновление параметров студенческой модели        optimizer.step()

Модель ExtendNER

Архитектура и настройка учителя-ученика

Модель ExtendNER расширяет размерность выходного слоя для размещения новых типов сущностей, вместо добавления новых выходных слоев. В статье просто объясняется, как должны быть размерности:

«Предполагая, что M{i} смог распознать n типов сущностей, его последний слой можно рассматривать как матрицу размером h×(2n+1). Выходной слой M{i+1} затем будет расширен до матрицы размером h×(2n+2m+1), чтобы вместить новые типы сущностей».

Диаграмма модели ExtendNER из раздела 3.4 статьи

Прямой проход

То же самое, что в модели AddNER, но с расширенными размерностями.

Обратный проход

Расчет потерь выполняется с использованием либо потери Дивергенции Кульбака-Лейблера, либо потери перекрестной энтропии в зависимости от следующего:

  • Когда метка категории NER y равна “O” (в схеме разметки IOB), используется потеря Дивергенции Кульбака-Лейблера.
  • Когда метка категории y НЕ является “O”, используется потеря перекрестной энтропии.

Окончательное предсказание

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

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

4. Подход с повторением

“Fine-tuned language models are continual learners”

ссылка на статью

Модель в статье не является универсальной, моделью одной задачи, подобной GPT, обученной только для ответов в разговоре. Вместо этого она подвергается тонкой настройке для последовательности специализированных задач, включая упрощение текста и генерацию хайку. Каждая из этих задач имеет уникальные требования, метрики оценки и специализированные наборы данных для обучения.

Исследователи смешивают части старого набора данных с новым набором данных и добиваются отличных результатов, смешивая всего 1% набора данных предыдущей задачи при тонкой настройке для новой задачи. Это делается последовательно для многих задач (8). Модель также хорошо справляется в условиях нулевого обучения, что означает, что она может хорошо обобщать задачи, для которых не была обучена. Например, она может генерировать хайку с правильным количеством слогов при заданной незнакомой теме, показывая свою способность к обобщению. Исследователи также отмечают, что их подход инвариантен к порядку задач, что означает, что последовательность, в которой задачи изучаются, не влияет на производительность модели. Исследования показывают, что количество старого набора данных, смешанного с новым, не оказывает существенного влияния на производительность основной задачи. Однако оно влияет на нулевое обучение. При отсутствии повторных тренировок модель склонна забывать задачи нулевого обучения, тогда как при повторных тренировках с 1% модель хорошо сохраняет свою производительность в этих задачах.

Все это кажется положительным, тот факт, что мы можем просто добавить 1% старого набора данных и непрерывное обучение решено, однако, конечно же, его применение к чатботу, такому как chatGPT, будет эмпирическим и может быть совершенно иным. Даже если, гипотетически, chatGPT может быть непрерывно обучен в стадиях тонкой настройки и RLHF, подобно этому, потребуется огромное количество размеченных данных для разговоров.

5. Архитектурный подход

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

  1. Выделение параметров: здесь подмножество параметров сети отводится каждой задаче. Это можно сделать путем маскировки нерелевантных нейронов или явного определения важных нейронов для текущей задачи.
  2. Модульная сеть: это предполагает использование отдельных подсетей или модулей для каждой задачи.

Подсети могут быть соединены различными способами для формирования ансамбля или более сложной архитектуры. Ниже представлены несколько общих методов соединения подсетей:

Конкатенация выводов:

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

Механизм голосования:

В некоторых моделях каждая подсеть “голосует” за предполагаемый результат, и окончательное решение принимается путем большинственного голосования или взвешенного голосования. Этот метод имеет биологическое вдохновение, так как он похож на то, как различные кортикальные столбики в неокортексе голосуют.

Соединения с пропуском:

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

Последовательность:

В этом случае вывод одной подсети служит входом для следующей.

Вернемся к разговору о чатботах. Мне особенно интересно было бы создать такую архитектуру с двумя подсетями. Первая – это предварительно обученная модель, которая хранит общие “знания”. Вторая – это знания для выравнивания модели. После выравнивания модели ей уже не потребуются размеченные разговорные данные. Вместо этого она может быть непрерывно обновляема путем обучения предварительно обученной подсети в безнадзорном режиме.

Вывод

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

Я заметил в прошлом месяце, что ChatGPT (только GPT-4) был обновлен, и теперь он говорит “С моей ​​обучающей отсечкой в январе 2022 года”, поэтому я задаюсь вопросом, что сделала команда OpenAI, чтобы достичь этого.

ChatGPT (variant GPT-4) сообщает пользователю, что он обучен до января 2022 года (скриншот автора)