timm documentation
Планировщики скорости обучения
Планировщики скорости обучения
На этой странице приведена справочная документация по API планировщиков скорости обучения, входящих в timm, а также обзор того, как они создаются и обновляются.
Использование
Планировщики создаются по имени с помощью create_scheduler_v2, который возвращает планировщик и общее количество эпох для обучения (включая любую префиксную фазу разгона, циклы и охлаждение, см. ниже).
В отличие от torch.optim.lr_scheduler, планировщики timm не подсчитывают шаги самостоятельно. Они спроектированы как
бессостоятельные: lr является функцией конфигурации расписания и явного номера эпохи или количества обновлений, поэтому для возобновления
запуска требуется только номер эпохи, а состояние планировщика не сохраняется в контрольных точках. Цикл обучения явно передает номер эпохи или
количество обновлений:
scheduler.step(epoch)в конце каждой эпохи, с индексом следующей эпохи (epoch + 1)scheduler.step_update(num_updates)после каждого обновления оптимизатора, с количеством выполненных обновлений
Планировщик сдвигается либо на каждый эпоху, либо на каждый шаг обновления (step_on_epochs), другой вызов не выполняет никаких действий, поэтому цикл обучения может делать оба вызова и поддерживать оба варианта.
import timm
from timm.optim import create_optimizer_v2
from timm.scheduler import create_scheduler_v2
model = timm.create_model('resnet50')
optimizer = create_optimizer_v2(model, opt='adamw', lr=1e-3, weight_decay=0.05)
updates_per_epoch = len(loader) # optimizer updates per epoch
# Cosine decay w/ 5 epochs of linear warmup, stepped per update for a smooth schedule.
scheduler, num_epochs = create_scheduler_v2(
optimizer,
sched='cosine',
num_epochs=100,
warmup_epochs=5,
min_lr=1e-6,
step_on_epochs=False,
updates_per_epoch=updates_per_epoch,
)
num_updates = 0
for epoch in range(num_epochs):
for batch in loader:
... # forward, backward, optimizer.step()
num_updates += 1
scheduler.step_update(num_updates=num_updates)
scheduler.step(epoch + 1) # pass the eval metric too for 'plateau', scheduler.step(epoch + 1, metric)Длительности (num_epochs, warmup_epochs, decay_epochs, …) всегда задаются в эпохах; фабрика преобразует их в обновления, когда step_on_epochs=False. Планировщики также можно создавать напрямую из их классов, при этом длительности указываются в единицах, в которых выполняется шаг (t_in_epochs).
Скрипт обучения (train.py) предоставляет аргументы фабрики через эти флаги:
--schedвыбирает расписание.--epochsзадаёт длину расписания.- Шагов на обновление вместо шагов на эпоху для
--sched-on-updates. --warmup-epochsзадаёт длительность прогрева.--warmup-lrзадает начальную скорость обучения для warmup.--warmup-prefixдобавляет разгон перед расписанием, а не перекрывает его начало.--min-lrзадает минимальную скорость обучения.--decay-epochsзадаёт интервал ступенчатого снижения или длительность финального снижения для WSD / rsqrt.--decay-milestonesзадаёт эпохи затухания для многошагового расписания.--decay-rateзадаёт коэффициент затухания, то есть степень для полиномиального расписания.--cooldown-epochsдобавляет эпохи с минимальной скоростью обучения после завершения расписания.--patience-epochsзадаёт терпеливость планировщика plateau.--lr-noiseвыбирает часть расписания с шумом скорости обучения.--lr-noise-pctограничивает величину шума.--lr-noise-stdзадает стандартное отклонение шума.--lr-cycle-mulзадает множитель длины цикла.--lr-cycle-decayзадает множитель пиковой скорости обучения между циклами.--lr-cycle-limitзадает количество циклов.--lr-k-decayзадаёт k-decay для косинусных и полиномиальных расписаний.--lr-decay-fnвыбирает итоговую функцию затухания для WSD / rsqrt.--lr-stable-timescaleзадаёт масштаб времени фазы rsqrt stable.
Расписания
sched | Класс | Расписание |
|---|---|---|
cosine | CosineLRScheduler | Косинусная аннелинг от базовой lr до min_lr (SGDR), необязательные перезапуски (циклы) и k-затухание |
tanh | TanhLRScheduler | Затухание гиперболического тангенса (статья), необязательные перезапуски |
poly | PolyLRScheduler | Полиномиальное затухание до min_lr, степень задается параметром decay_rate, необязательные перезапуски и k-затухание |
step | StepLRScheduler | lr умножается на decay_rate каждые decay_epochs |
multistep | MultiStepLRScheduler | lr умножается на decay_rate на каждом из эпох decay_milestones |
plateau | PlateauLRScheduler | Устарело. lr умножается на decay_rate, если метрика eval не улучшалась в течение patience_epochs, только при пошаговом изменении по эпохам |
wsd | WSDLRScheduler | Warmup-stable-decay (MiniCPM), постоянная lr, затем спад до min_lr в течение последних decay_epochs, по умолчанию спад 1-sqrt (статья) |
rsqrt | WSDLRScheduler | Затухание обратной квадратной корени с линейным охлаждением в течение последних decay_epochs (Big Vision) |
Часто используемые параметры
- Warmup.
warmup_epochsлинейного прогрева сwarmup_lrдо базовой lr, поддерживается всеми расписаниями.warmup_prefix: по умолчанию warmup перекрывает начало расписания (расписание вычисляется с эпохи 0, warmup заменяет его первые эпохи), поэтомуnum_epochs— это общая длина. Приwarmup_prefix=Trueрасписание начинается после warmup, и warmup добавляется к общей длине.- Для
wsdиrsqrtстабильная фаза всегда начинается после прогрева; безwarmup_prefixфазы стабильности и затухания укладываются вnum_epochs - warmup_epochs, поэтомуnum_epochsостаётся общим количеством эпох.
min_lr: значение lr, которого достигают затухающие расписания (cosine,tanh,poly,wsd,rsqrt) в конце, и нижняя граница дляplateau.
Расписание plateau устарело и будет удалено в одном из будущих релизов. Оно никогда не вписывалось в описанный выше stateless-дизайн: его lr зависит от истории метрики оценки, а не от эпохи, и эта история (лучшая метрика, счётчики patience и cooldown) не сохраняется в контрольных точках, поэтому при возобновлении запуска логика plateau начинается заново. Поддержка контрольных точек не будет добавлена. Кроме того, плато на валидации — слабый сигнал для определения момента аннелинга; фиксированное расписание, такое как cosine или wsd, воспроизводимо и возобновляется точно, а WSD-свип (см. Hyperparameter Sweeps) сравнивает cooldown при нескольких бюджетах на основе одного стабильного запуска.
cooldown_epochs: эпохи, в течение которых обучение продолжается сmin_lrпосле завершения расписания (cosine,tanh,poly,wsd,rsqrt), добавляются к возвращаемомуnum_epochs. Поскольку расписание достигаетmin_lrна один шаг позже своего последнего шага, эпоха cooldown также позволяет обучаться сmin_lrпри выполнении шагов по эпохам.- Циклы (
cosine,tanh,poly):cycle_limit > 1перезапускает расписание, при этом каждый цикл длится вcycle_mulраз дольше, а его пиковое значение lr умножается наcycle_decayпо сравнению с предыдущим. Возвращаемоеnum_epochsохватывает все циклы. k_decay(cosine,poly): k-decay изменяет форму затухания (t ** k),k > 1поддерживает высокий lr дольше.- Шум:
noiseдобавляет случайный мультипликативный шум к lr на участке расписания, заданном в долях отnum_epochs(начало, или начало и конец), ограниченныйnoise_pct.
WSD и rsqrt
У WSDLRScheduler есть три фазы: линейное разогревание, стабильная фаза и
спад до min_lr.
decay_epochsзадаёт длительность финального затухания. Значение в диапазоне (0, 1) — это доля от общей длины стабильной фазы и фазы затухания, по умолчанию 20%.decay_fn(--lr-decay-fn) выбирает1-sqrt(по умолчанию дляwsd),linear(по умолчанию дляrsqrt),cosine,powerилиexp.stable_timescale(--lr-stable-timescale, в эпохах) управляет стабильной фазойrsqrt, которая затухает по закону(1 + t / timescale) ** -0.5после окончания warmup. По умолчанию значение равно длине warmup и должно быть задано явно, если warmup отсутствует.
Класс также поддерживает обобщённую power стабильную фазу и пользовательские функции затухания.
Именно на финальном отжиге расписания WSD получают наибольшую выгоду, поэтому используйте шаг на обновление (--sched-on-updates) или добавьте эпоху охлаждения, если фаза затухания длится всего несколько эпох. При шаге на эпоху последняя эпоха короткого затухания заметно выше min_lr (около 10% от базовой lr для последней из 5 эпох затухания с 1-sqrt).
# 300 epochs, 5 epoch warmup, constant lr, then a 1-sqrt decay over the final 20%
scheduler, num_epochs = create_scheduler_v2(
optimizer, sched='wsd', num_epochs=300, warmup_epochs=5, decay_epochs=0.2,
step_on_epochs=False, updates_per_epoch=updates_per_epoch,
)Масштабирование групп параметров lr
Группы параметров с полем lr_scale (например, группы для послойного затухания lr из param_groups_layer_decay) получают запланированное lr, умноженное на их масштаб. Базовое lr каждой группы записывается как initial_lr в группе при создании планировщика.
Возобновление
По мере передачи количества шагов планировщик для возобновлённого запуска настраивается путём его создания так же, как для исходного запуска, и приведения к точке возобновления: scheduler.step(start_epoch) или scheduler.step_update(start_epoch * updates_per_epoch). state_dict() / load_state_dict() сохраняют и восстанавливают атрибуты планировщика.
API
Фабричные функции
timm.scheduler.create_scheduler_v2
< source >( optimizer: Optimizersched: str = 'cosine'num_epochs: int = 300decay_epochs: typing.Optional[float] = Nonedecay_milestones: typing.List[int] = (90, 180, 270)cooldown_epochs: int = 0patience_epochs: int = 10decay_rate: float = 0.1min_lr: float = 0.0warmup_lr: float = 1e-05warmup_epochs: int = 0warmup_prefix: bool = Falsenoise: typing.Union[float, typing.List[float]] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42cycle_mul: float = 1.0cycle_decay: float = 0.1cycle_limit: int = 1k_decay: float = 1.0decay_fn: typing.Optional[str] = Nonestable_timescale: typing.Optional[float] = Noneplateau_mode: str = 'max'step_on_epochs: bool = Trueupdates_per_epoch: int = 0 )
Параметры
- optimizer — оптимизатор для планирования
- sched — имя планировщика, одно из ‘cosine’, ‘tanh’, ‘step’, ‘multistep’, ‘poly’, ‘wsd’, ‘rsqrt’, ‘constant’, ‘plateau’ (устаревшее) или ‘none’ для отключения планировщика (возвращает None, lr оптимизатора не изменяется). ‘constant’ удерживает lr после warmup с применением param group lr_scale (послойное затухание lr).
- num_epochs — количество эпох в расписании (без учёта warmup, если warmup_prefix, и без учёта cooldown)
- decay_epochs — интервал затухания lr (шаг) или длина фазы затухания (wsd / rsqrt) в эпохах; значение в диапазоне (0, 1) означает долю от общей длины расписания. None = 90 (шаг), 0.2 (wsd / rsqrt)
- decay_milestones — эпохи, на которых нужно снижать lr (multistep)
- cooldown_epochs — количество эпох, в течение которых lr удерживается на уровне min_lr после завершения расписания
- patience_epochs — количество эпох без улучшения перед снижением lr (plateau, устарело)
- decay_rate — коэффициент затухания lr (step, multistep, plateau), степень полинома (poly)
- min_lr — нижняя граница lr для планировщиков, которые затухают до этого значения
- warmup_lr — lr в начале warmup
- warmup_epochs — эпохи линейного прогрева
- warmup_prefix — исключает период прогрева из num_epochs (добавляется к общему количеству); wsd / rsqrt всегда имеют префикс прогрева, при warmup_prefix=False их стабильная и фаза затухания укладываются в num_epochs
- noise — точки включения/выключения шума lr как доли длины расписания
- noise_pct — процент ограничения шума для lr
- noise_std — стандартное отклонение шума lr
- noise_seed — seed шума для lr
- cycle_mul — множитель длины цикла (cosine, tanh, poly)
- cycle_decay — затухание lr в каждом цикле (cosine, tanh, poly)
- cycle_limit — количество циклов (cosine, tanh, poly)
- k_decay — k-затухание (cosine, poly)
- decay_fn — функция фазы затухания (wsd / rsqrt), None = ‘1-sqrt’ для wsd, ‘linear’ для rsqrt
- stable_timescale — масштаб времени rsqrt в эпохах (rsqrt), None = warmup_epochs
- plateau_mode — ‘max’ или ‘min’, направление метрики (плато)
- step_on_epochs — обновлять расписание по эпохам, иначе — по каждому обновлению (требуется updates_per_epoch)
- updates_per_epoch — количество обновлений оптимизатора на эпоху (step_on_epochs=False)
Создайте планировщик скорости обучения по имени.
Классы планировщиков
класс timm.scheduler.CosineLRScheduler
< source >( optimizer: Optimizert_initial: intlr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42k_decay: float = 1.0initialize: bool = True )
Косинусное затухание с перезапусками. Это описано в статье https://arxiv.org/abs/1608.03983.
Вдохновлено https://github.com/allenai/allennlp/blob/master/allennlp/training/learning_rate_schedulers/cosine.py
Опция k-decay, основанная на k-decay: A New Method For Learning Rate Schedule - https://arxiv.org/abs/2004.05909
класс timm.scheduler.MultiStepLRScheduler
< source >( optimizer: Optimizerdecay_t: typing.List[int]decay_rate: float = 1.0warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Truet_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
Многошаговое расписание скорости обучения с разминкой и шумом.
Вне warmup контрольные точки затухания сравниваются с t + 1, где t исключает warmup, если warmup_prefix=True. Например, без warmup контрольная точка 10 применяется на индексе расписания 9.
Эта устоявшаяся конвенция отличается от MultiStepLR в PyTorch и сохраняется для совместимости с существующими графиками обучения.
класс timm.scheduler.PlateauLRScheduler
< source >( optimizer: Optimizerdecay_rate: float = 0.1patience_t: int = 10threshold: float = 0.0001cooldown_t: int = 0warmup_t: int = 0warmup_lr_init: float = 0.0lr_min: float = 0.0mode: str = 'max'noise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_type: str = 'normal'noise_pct: float = 0.67noise_std: float = 1.0noise_seed: typing.Optional[int] = Noneinitialize: bool = True )
Уменьшайте LR в несколько раз каждый раз, когда валидационная потеря выходит на плато.
Устарело: этот планировщик будет удалён в будущей версии. Планировщики timm спроектированы как безсостоятельные функции от номера эпохи или количества обновлений, чем этот метрико-управляемый расписание никогда не было. Его состояние (лучшая метрика, счётчики терпения и охлаждения) не сохраняется в контрольных точках обучения, поэтому при возобновлении запуска логика плато перезапускается, и поддержка контрольных точек не будет добавлена. Рекомендуется использовать фиксированное расписание, такое как cosine или wsd; ветвление WSD cooldown в sweep.py сравнивает отжиг при нескольких бюджетах с воспроизводимыми расписаниями.
класс timm.scheduler.PolyLRScheduler
< source >( optimizer: Optimizert_initial: intpower: float = 0.5lr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42k_decay: float = 1.0initialize: bool = True )
Полиномиальный планировщик LR с warmup, шумом и k-затуханием
Опция k-decay, основанная на k-decay: A New Method For Learning Rate Schedule - https://arxiv.org/abs/2004.05909
класс timm.scheduler.StepLRScheduler
< source >( optimizer: Optimizerdecay_t: floatdecay_rate: float = 1.0warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Truet_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
класс timm.scheduler.TanhLRScheduler
< source >( optimizer: Optimizert_initial: intlb: float = -7.0ub: float = 3.0lr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
Затухание гиперболического тангенса с перезапусками. Это описано в статье https://arxiv.org/abs/1806.01593
класс timm.scheduler.WSDLRScheduler
< source >( optimizer: Optimizert_initial: intdecay_t: intlr_min: float = 0.0stable_fn: str = 'constant'stable_timescale: typing.Optional[float] = Nonestable_power: float = 0.5decay_fn: typing.Union[str, typing.Callable[[float], float]] = '1-sqrt'decay_power: float = 0.5decay_ratio: float = 0.1warmup_t: int = 0warmup_lr_init: float = 0.0t_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
Параметры
- optimizer — оптимизатор для планирования
- t_initial — длина фаз стабильности и затухания (эпохи или обновления, см.
t_in_epochs) - decay_t — длина фазы затухания, последние
decay_tшагов изt_initial - lr_min — lr в конце фазы затухания
- stable_fn — функция стабильной фазы, одно из значений: ‘constant’, ‘rsqrt’, ‘power’
- stable_timescale — временная шкала для стабильных функций ‘rsqrt’ / ‘power’, по умолчанию
warmup_t - stable_power — показатель степени функции «power»
- decay_fn — функция фазы затухания, одно из значений ‘linear’, ‘1-sqrt’, ‘cosine’, ‘power’, ‘exp’ или вызываемый объект
- decay_power — показатель степени функции затухания «power»
- decay_ratio — конечная доля (до нормализации) функции затухания ‘exp’
- warmup_t — длина разгона, префикс к
t_initial - warmup_lr_init — lr в начале warmup
- t_in_epochs —
tизмеряется в эпохах (step()), иначе — в обновлениях (step_update()) - noise_range_t — диапазон шума lr, см.
Scheduler - noise_pct — процент ограничения шума для lr
- noise_std — стандартное отклонение шума lr
- noise_seed — seed шума для lr
- initialize — инициализирует поле
initial_lrгруппы параметров из текущего значения lr
График изменения скорости обучения Warmup-Stable-Decay (WSD) с возможностью выбора функций для стабильной фазы и фазы затухания.
Три фазы: линейное повышение в течение warmup_t шагов, стабильная фаза и снижение до lr_min в последние decay_t шагов. t_initial — это длина фаз стабильности и снижения; фаза повышения всегда является префиксом, поэтому общая длина расписания составляет warmup_t + t_initial (см. get_cycle_length()), после чего поддерживается значение lr_min.
NOTE: как и в случае с другими планировщиками, lr_min достигается при t = warmup_t + t_initial, то есть на один шаг позже последнего запланированного шага, поэтому последний запланированный шаг на один шаг затухания короче. При короткой фазе затухания, выполняемой по эпохам, это существенно (например, последняя из 5 эпох затухания с ‘1-sqrt’ находится примерно на 10% от стабильного lr). Финальное отжигание важно для WSD, поэтому выполняйте шаги по обновлениям (t_in_epochs=False, --sched-on-updates в train.py) или добавьте эпоху охлаждения (удерживаемую на lr_min, --cooldown-epochs).
Стабильная функция вычисляется по времени с момента окончания warmup (t_s) и равна 1 при t_s = 0, поэтому warmup всегда передаёт управление на базовом lr. Функция затухания отображает прогресс затухания frac в диапазоне [0, 1] в коэффициент от 1 до 0 и умножает на стабильное значение, так что затухающая стабильная функция продолжает затухать на протяжении фазы decay (как в расписании Big Vision rsqrt + linear cooldown).
lr(t) = lr_min + (base_lr stable(t_s) - lr_min) decay(frac)
Стабильные функции:
constant: 1, расписание WSDrsqrt: (1 + t_s / timescale) ** -0.5, расписание обратного квадратного корня Big Vision, когдаstable_timescale == warmup_t(по умолчанию)power: (1 + t_s / timescale) ** -stable_power, обобщённый rsqrt (планировщик Power)
Функции затухания:
1-sqrt: 1 - sqrt(frac), наиболее эффективный cooldown в https://arxiv.org/abs/2405.18392 (по умолчанию)linear: 1 - frac, расписание «трапеция» и Big Vision cooldowncosine: 0.5 (1 + cos(pi frac))power: 1 - frac ** decay_power, 0.5 == ‘1-sqrt’, 1.0 == ‘linear’, 2.0 is a ‘square’ decayexp: экспоненциальное затухание до долиdecay_ratioот стабильного значения, нормированное для достижения lr_min- вызываемая функция
fn(frac) -> factorдля всех остальных случаев