Стратегии распада и отжига LR для глубокого обучения в Python

Какова скорость обучения в глубоком обучении?

Нейронные сети имеют множество гиперпараметров, влияющих на производительность модели. Одним из необходимых гиперпараметров является скорость обучения (LR), которая определяет, насколько меняются веса модели между этапами обучения. В простейшем случае значение LR является фиксированным значением от 0 до 1.

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

Что такое планировщик скорости обучения?

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

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

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

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

Планировщики скорости обучения

В этой статье мы используем PyTorch версии 1.13.0. Подробнее о планировщиках скорости обучения можно прочитать в Документации PyTorch.

import torch

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

СтепЛР

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

from torch.optim.lr_scheduler import StepLR

scheduler = StepLR(optimizer, 
                   step_size = 4, # Period of learning rate decay
                   gamma = 0.5) # Multiplicative factor of learning rate decay

MultiStepLR

MultiStepLR — аналогично StepLR — также снижает скорость обучения с помощью мультипликативного коэффициента, но после каждого заранее определенного этапа.

from torch.optim.lr_scheduler import MultiStepLR

scheduler = MultiStepLR(optimizer, 
                        milestones=[8, 24, 28], # List of epoch indices
                        gamma =0.5) # Multiplicative factor of learning rate decay

КонстантаLR

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

from torch.optim.lr_scheduler import ConstantLR

scheduler = ConstantLR(optimizer, 
                       factor = 0.5, # The number we multiply learning rate until the milestone.
                       total_iters = 8) # The number of steps that the scheduler decays the learning rate

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

ЛинейныйLR

LinearLR — аналогично ConstantLR — также снижает скорость обучения на мультипликативный коэффициент в начале обучения. Но он линейно увеличивает скорость обучения в течение определенного количества шагов обучения, пока не достигнет первоначально установленной скорости обучения.

from torch.optim.lr_scheduler import LinearLR

scheduler = LinearLR(optimizer, 
                     start_factor = 0.5, # The number we multiply learning rate in the first epoch
                     total_iters = 8) # The number of iterations that multiplicative factor reaches to 1

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

ЭкспоненциальныйLR

ExponentialLR снижает скорость обучения на мультипликативный коэффициент на каждом этапе обучения.

from torch.optim.lr_scheduler import ExponentialLR

scheduler = ExponentialLR(optimizer, 
                          gamma = 0.5) # Multiplicative factor of learning rate decay.

Полином LR

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

from torch.optim.lr_scheduler import PolynomialLR

scheduler = PolynomialLR(optimizer, 
                         total_iters = 8, # The number of steps that the scheduler decays the learning rate.
                         power = 1) # The power of the polynomial.

Ниже вы можете увидеть результирующее снижение скорости обучения для power = 1.

С power = 2 результирующее снижение скорости обучения будет выглядеть следующим образом.

Косинусный отжигLR

CosineAnnealingLR уменьшает скорость обучения с помощью функции косинуса.

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

from torch.optim.lr_scheduler import CosineAnnealingLR

scheduler = CosineAnnealingLR(optimizer,
                              T_max = 32, # Maximum number of iterations.
                             eta_min = 1e-4) # Minimum learning rate.

Филипп Сингер и Евгений Бабахин, два гроссмейстера соревнований Kaggle, рекомендуют использовать косинусное затухание в качестве планировщика скорости обучения для глубокого обучения переносу [2].

Косинусный отжигWarmRestartsLR

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

from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts
scheduler = CosineAnnealingWarmRestarts(optimizer, 
                                        T_0 = 8,# Number of iterations for the first restart
                                        T_mult = 1, # A factor increases TiTi​ after a restart
                                        eta_min = 1e-4) # Minimum learning rate

Это называется теплым перезапуском и было введено в 2017 году [1]. Увеличение LR приводит к тому, что модель расходится. Однако это преднамеренное расхождение позволяет модели избежать локальных минимумов и найти еще лучший глобальный минимум.

циклическийLR

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

from torch.optim.lr_scheduler import CyclicLR

scheduler = CyclicLR(optimizer, 
                     base_lr = 0.0001, # Initial learning rate which is the lower boundary in the cycle for each parameter group
                     max_lr = 1e-3, # Upper learning rate boundaries in the cycle for each parameter group
                     step_size_up = 4, # Number of training iterations in the increasing half of a cycle
                     mode = "triangular")

С mode = "triangular" результирующее снижение скорости обучения будет следовать основному треугольному циклу без масштабирования амплитуды, который будет выглядеть следующим образом.

С mode = "triangular2" результирующее снижение скорости обучения будет следовать базовому треугольному циклу, который масштабирует начальную амплитуду наполовину в каждом цикле, который будет выглядеть следующим образом.

С mode = "exp_range" результирующее снижение скорости обучения будет выглядеть следующим образом.

OneCycleLR

OneCycleLR снижает скорость обучения в соответствии с политикой скорости обучения 1 цикла, которая была представлена ​​в статье 2017 года [3].

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

from torch.optim.lr_scheduler import OneCycleLR


scheduler = OneCycleLR(optimizer, 
                       max_lr = 1e-3, # Upper learning rate boundaries in the cycle for each parameter group
                       steps_per_epoch = 8, # The number of steps per epoch to train for.
                       epochs = 4, # The number of epochs to train for.
                       anneal_strategy = 'cos') # Specifies the annealing strategy

С anneal_strategy = "cos" результирующее снижение скорости обучения будет выглядеть следующим образом.

С anneal_strategy = "linear" результирующее снижение скорости обучения будет выглядеть следующим образом.

УменьшитьLOnPlateauLR

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

Пользовательские планировщики скорости обучения с лямбда-функциями

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

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

lr_epoch[t] = lr_initial * lambda(epoch)

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

lr_epoch[t] = lr_epoch[t-1] * lambda(epoch)

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

Заключение и визуальная шпаргалка

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

К сожалению, ответ не так прост — как это часто бывает в жизни. Какое-то время ReduceLROnPlateau был популярным планировщиком скорости обучения. Сегодня все большую популярность набирают другие подходы, такие как CosineAnnealingLR и OneCycleLR, или подходы с теплым перезапуском, такие как CosineAnnealingWarmRestarts и CyclicLR.

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

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

Понравилась эта история?

Если вы хотите получать мои новые истории прямо на свой почтовый ящик, подпишитесь!

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



Найди меня в Twitter, LinkedIn,и Kaggle!

Рекомендации

[1] Лощилов И. и Хаттер Ф. (2016). Sgdr: Стохастический градиентный спуск с теплыми перезапусками. препринт arXiv arXiv:1608.03983.

[2] Сингер П. и Бабахин Ю. (2022) Практические советы по глубокому трансферному обучению. В: Kaggle Days Paris 2022.

[3] Смит, Л. Н., и Топин, Н. (2019). Супер-конвергенция: очень быстрое обучение нейронных сетей с использованием больших скоростей обучения. В Искусственный интеллект и машинное обучение для многодоменных операционных приложений (том 11006, стр. 369–386). ШПАЙ.

Приложение

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

import torch
from torch.optim.lr_scheduler import StepLR # Import your choice of scheduler here

import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator

LEARNING_RATE = 1e-3
EPOCHS = 4
STEPS_IN_EPOCH = 8

# Set model and optimizer
model = torch.nn.Linear(2, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=LEARNING_RATE)

# Define your scheduler here as described above
# ...

# Get learning rates as each training step
learning_rates = []

for i in range(EPOCHS*STEPS_IN_EPOCH):
    optimizer.step()
    learning_rates.append(optimizer.param_groups[0]["lr"])
    scheduler.step()

# Visualize learinig rate scheduler
fig, ax = plt.subplots(1,1, figsize=(10,5))
ax.plot(range(EPOCHS*STEPS_IN_EPOCH), 
        learning_rates,
        marker='o', 
        color='black')
ax.set_xlim([0, EPOCHS*STEPS_IN_EPOCH])
ax.set_ylim([0, LEARNING_RATE + 0.0001])
ax.set_xlabel('Steps')
ax.set_ylabel('Learning Rate')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.xaxis.set_major_locator(MultipleLocator(STEPS_IN_EPOCH))
ax.xaxis.set_minor_locator(MultipleLocator(1))
plt.show()