torch.optim
torch.optim — пакет, реализующий различные алгоритмы оптимизации. Наиболее часто используемые методы уже поддерживаются, а интерфейс достаточно общий, чтобы в будущем легко интегрировать и более сложные алгоритмы.
Как использовать оптимизатор
Для использования torch.optim необходимо создать объект оптимизатора, который будет хранить текущее состояние и обновлять параметры на основе вычисленных градиентов.
Создание оптимизатора
Для создания объекта Optimizer нужно передать итерируемый объект, содержащий параметры (все должны быть Variable), которые необходимо оптимизировать. Затем можно указать опции, специфичные для оптимизатора, такие как скорость обучения, регуляризация по весам и т. д.
Пример:
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9) optimizer = optim.Adam([var1, var2], lr=0.0001)
Опции для каждого параметра
Объекты Optimizer также поддерживают указание опций для каждого параметра. Для этого вместо передачи итерируемого объекта Variable передайте итерируемый объект dict с параметрами. Каждый из них определит отдельную группу параметров и должен содержать ключ params, содержащий список параметров, относящихся к этой группе. Другие ключи должны соответствовать ключевым аргументам, принимаемым оптимизаторами, и будут использоваться в качестве параметров оптимизации для этой группы.
Примечание
Вы по-прежнему можете передавать параметры в виде ключевых аргументов. Они будут использоваться как значения по умолчанию в группах, которые их не переопределили. Это полезно, когда вы хотите изменить только один параметр, сохраняя все остальные параметры согласованными в различных группах параметров.
Например, это очень полезно, когда необходимо указать скорость обучения для каждого слоя:
optim.SGD([
{'params': model.base.parameters()},
{'params': model.classifier.parameters(), 'lr': 1e-3}
], lr=1e-2, momentum=0.9)
Это означает, что параметры model.base будут использовать скорость обучения по умолчанию 1e-2, параметры model.classifier будут использовать скорость обучения 1e-3, а для всех параметров будет использоваться импульс 0.9.
Выполнение шага оптимизации
Все оптимизаторы реализуют метод step(), который обновляет параметры. Он может использоваться двумя способами:
optimizer.step()
Это упрощенная версия, поддерживаемая большинством оптимизаторов. Функция может быть вызвана после вычисления градиентов, например, с помощью backward().
Пример:
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
optimizer.step(closure)
Некоторые алгоритмы оптимизации, такие как сопряжённый градиент и LBFGS, требуют многократного переоценки функции, поэтому нужно передать замыкание, которое позволит им пересчитать вашу модель. Замыкание должно очищать градиенты, вычислять потерю и возвращать её.
Пример:
for input, target in dataset:
def closure():
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
return loss
optimizer.step(closure)
Базовый класс
-
class torch.optim.Optimizer(params, defaults)[source] -
Базовый класс для всех оптимизаторов.
Предупреждение
Параметры должны быть указаны как коллекции с детерминированным порядком, который сохраняется между запусками. Примерами объектов, которые не удовлетворяют этим свойствам, являются множества и итераторы по значениям словарей.
- Параметры:
-
-
params (iterable) – итерируемый объект, содержащий
torch.Tensorилиdict. Указывает, какие тензоры должны быть оптимизированы. - defaults – (dict): словарь, содержащий значения параметров оптимизации по умолчанию (используется, когда группа параметров не указывает их).
-
params (iterable) – итерируемый объект, содержащий
Добавляет группу параметров в | |
Загружает состояние оптимизатора. | |
Возвращает состояние оптимизатора в виде | |
Выполняет один шаг оптимизации (обновление параметров). | |
Устанавливает градиенты всех оптимизируемых |
Алгоритмы
Adadelta
| Реализует алгоритм Adadelta. |
Adagrad
| Реализует алгоритм Adagrad. |
Adam
| Реализует алгоритм Adam. |
AdamW
| Реализует алгоритм AdamW. |
SparseAdam
| Реализует ленивую версию алгоритма Adam, подходящую для разреженных тензоров. |
Adamax
| Реализует алгоритм Adamax (вариант Adam, основанный на бесконечной норме). |
ASGD
| Реализует усреднённый стохастический градиентный спуск. |
LBFGS
| Реализует алгоритм L-BFGS, сильно вдохновлённый minFunc. |
NAdam
| Реализует алгоритм NAdam. |
RAdam
| Реализует алгоритм RAdam. |
RMSprop
| Реализует алгоритм RMSprop. |
Rprop
| Реализует алгоритм результирующего обратного распространения. |
SGD
| Реализует стохастический градиентный спуск (по желанию с импульсом). |
Как настроить скорость обучения
torch.optim.lr_scheduler предоставляет несколько методов настройки скорости обучения на основе количества эпох. torch.optim.lr_scheduler.ReduceLROnPlateau позволяет динамически уменьшать скорость обучения на основе некоторых показателей валидации.
График изменения скорости обучения следует применять после обновления оптимизатора; например, ваш код должен быть написан следующим образом:
Пример:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler = ExponentialLR(optimizer, gamma=0.9)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler.step()
Большинство планировщиков скорости обучения могут быть вызваны друг за другом (также называемые цепочкой планировщиков). В результате каждый планировщик применяется один за другим к скорости обучения, полученной предыдущим.
Пример:
model = [Parameter(torch.randn(2, 2, requires_grad=True))]
optimizer = SGD(model, 0.1)
scheduler1 = ExponentialLR(optimizer, gamma=0.9)
scheduler2 = MultiStepLR(optimizer, milestones=[30,80], gamma=0.1)
for epoch in range(20):
for input, target in dataset:
optimizer.zero_grad()
output = model(input)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
scheduler1.step()
scheduler2.step()
Во многих разделах документации мы будем использовать следующую схему для ссылки на алгоритмы планировщиков.
>>> scheduler = ... >>> for epoch in range(100): >>> train(...) >>> validate(...) >>> scheduler.step()
Предупреждение
До PyTorch 1.1.0 планировщик скорости обучения должен был вызываться до обновления оптимизатора; 1.1.0 изменил это поведение, что повлекло за собой разрыв обратной совместимости. Если вы используете планировщик скорости обучения (вызывая scheduler.step()) перед обновлением оптимизатора (вызывая optimizer.step()) , это пропустит первое значение графика скорости обучения. Если вы не можете воспроизвести результаты после обновления до PyTorch 1.1.0, проверьте, вызываете ли вы scheduler.step() в неправильное время.
Устанавливает скорость обучения каждого параметра группы в начальную lr, умноженную на заданную функцию. | |
Умножает скорость обучения каждой параметрической группы на множитель, указанный в заданной функции. | |
Уменьшает скорость обучения каждой параметрической группы на множитель gamma через каждые step_size эпох. | |
Уменьшает скорость обучения каждой параметрической группы на множитель gamma, как только количество эпох достигнет одной из вех. | |
Уменьшает скорость обучения каждой параметрической группы на небольшой постоянный множитель до тех пор, пока количество эпох не достигнет предварительно определенной вехи: total_iters. | |
Уменьшает скорость обучения каждой параметрической группы путём линейного изменения небольшого множителя до тех пор, пока количество эпох не достигнет предварительно определённой вехи: total_iters. | |
Уменьшает скорость обучения каждой параметрической группы на множитель gamma через каждую эпоху. | |
Уменьшает скорость обучения каждой параметрической группы с использованием полиномиальной функции в заданном total_iters. | |
Устанавливает скорость обучения каждой параметрической группы с помощью расписания косинусного отжига, где устанавливается на начальную lr, а — количество эпох с момента последнего перезапуска в SGDR: | |
Цепочкой список планировщиков скорости обучения. | |
Принимает список планировщиков, которые должны вызываться последовательно во время процесса оптимизации, и контрольные точки, которые предоставляют точные интервалы, отражающие, какой планировщик должен вызываться в данной эпохе. | |
Уменьшить скорость обучения, когда метрика перестала улучшаться. | |
Устанавливает скорость обучения каждой параметрической группы в соответствии с циклической политикой скорости обучения (CLR). | |
Устанавливает скорость обучения каждой параметрической группы в соответствии с политикой скорости обучения 1cycle. | |
Устанавливает скорость обучения каждой параметрической группы с помощью расписания косинусного отжига, где устанавливается на начальную lr, — количество эпох с момента последнего перезапуска, а — количество эпох между двумя перезапусками в SGDR: |
Среднее арифметическое стохастических весов
torch.optim.swa_utils реализует метод усреднения стохастических весов (SWA). В частности, torch.optim.swa_utils.AveragedModel класс реализует модели SWA, torch.optim.swa_utils.SWALR реализует планировщик скорости обучения SWA, а torch.optim.swa_utils.update_bn() — вспомогательная функция, используемая для обновления статистических данных пакетной нормализации SWA в конце обучения.
Метод SWA был предложен в статье Averaging Weights Leads to Wider Optima and Better Generalization.
Создание усредненных моделей
Класс AveragedModel служит для вычисления весов модели SWA. Вы можете создать усредненную модель, выполнив следующие действия:
>>> swa_model = AveragedModel(model)
Здесь модель model может быть любым объектом torch.nn.Module. swa_model будет отслеживать текущие средние значения параметров model. Чтобы обновить эти средние значения, вы можете использовать функцию update_parameters():
>>> swa_model.update_parameters(model)
Планировщики скорости обучения SWA
Обычно в SWA скорость обучения устанавливается в высокое постоянное значение. SWALR — это планировщик скорости обучения, который уменьшает скорость обучения до фиксированного значения, а затем держит её постоянной. Например, следующий код создаёт планировщик, линейно уменьшающий скорость обучения от её начального значения до 0,05 за 5 эпох в каждой группе параметров:
>>> swa_scheduler = torch.optim.swa_utils.SWALR(optimizer, \ >>> anneal_strategy="linear", anneal_epochs=5, swa_lr=0.05)
Вы также можете использовать косинусное уменьшение до фиксированного значения вместо линейного, установив anneal_strategy="cos".
Обработка пакетной нормализации
update_bn() — это вспомогательная функция, которая позволяет вычислять статистику пакетной нормализации для модели SWA на заданном наборе данных loader в конце обучения:
>>> torch.optim.swa_utils.update_bn(loader, swa_model)
update_bn() применяет swa_model к каждому элементу в наборе данных и вычисляет статистику активации для каждого слоя пакетной нормализации в модели.
Предупреждение
update_bn() предполагает, что каждый пакет в наборе данных loader представляет собой тензор или список тензоров, где первый элемент — тензор, к которому должна применяться сеть swa_model. Если ваш набор данных имеет другую структуру, вы можете обновить статистику пакетной нормализации swa_model путём выполнения прохода вперёд с swa_model для каждого элемента набора данных.
Настройка стратегий усреднения
По умолчанию, torch.optim.swa_utils.AveragedModel вычисляет среднее значение параметров, которые вы предоставляете, но вы также можете использовать пользовательские функции усреднения с параметром avg_fn. В следующем примере ema_model вычисляет экспоненциально скользящее среднее.
Пример:
>>> ema_avg = lambda averaged_model_parameter, model_parameter, num_averaged:\ >>> 0.1 * averaged_model_parameter + 0.9 * model_parameter >>> ema_model = torch.optim.swa_utils.AveragedModel(model, avg_fn=ema_avg)
Объединение всего в одно целое
В примере ниже, swa_model — это модель SWA, которая накапливает средние значения весов. Мы обучаем модель в течение 300 эпох, переключаемся на планировщик скорости обучения SWA и начинаем собирать средние значения SWA параметров на 160 эпохе:
>>> loader, optimizer, model, loss_fn = ... >>> swa_model = torch.optim.swa_utils.AveragedModel(model) >>> scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=300) >>> swa_start = 160 >>> swa_scheduler = SWALR(optimizer, swa_lr=0.05) >>> >>> for epoch in range(300): >>> for input, target in loader: >>> optimizer.zero_grad() >>> loss_fn(model(input), target).backward() >>> optimizer.step() >>> if epoch > swa_start: >>> swa_model.update_parameters(model) >>> swa_scheduler.step() >>> else: >>> scheduler.step() >>> >>> # Update bn statistics for the swa_model at the end >>> torch.optim.swa_utils.update_bn(loader, swa_model) >>> # Use swa_model to make predictions on test data >>> preds = swa_model(test_input)
© 2024, PyTorch Contributors
PyTorch has a BSD-style license, as found in the LICENSE file.
https://pytorch.org/docs/1.13/optim.html