Документация Engee

Вспомогательные функции обратных вызовов

throttle(f, timeout; leading=true, trailing=false)

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

Обычно регулируемая функция будет выполняться столько, сколько сможет, не более одного раза за время ожидания (wait). Но если вы хотите отключить выполнение на переднем фронте, передайте leading=false. Чтобы включить выполнение на заднем фронте, передайте trailing=true.

Примеры

julia> a = Flux.throttle(() -> println("Flux"), 2);

julia> for i = 1:4  # a, вызываемое в альтернативных итерациях
           a()
           sleep(1)
       end
Flux
Flux

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

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

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

# создадим псевдопотерю, которая уменьшается в течение 4 вызовов, а затем начинает увеличиваться
# назовем это loss()
loss = let t = 0
  () -> begin
    t += 1
    (t - 4) ^ 2
  end
end

# создадим триггер ранней остановки
# возвращает true, если потери увеличиваются в течение двух последовательных шагов
es = early_stopping(loss, 2; init_score = 9)

# остановится на 6-й (4 уменьшающихся + 2 увеличивающихся вызова) эпохе
for epoch in 1:10
  es() && break
end

Именованный аргумент distance функции early_stopping является функцией вида distance(best_score, score). По умолчанию distance имеет значение -, что означает, что отслеживаемая метрика f должна быть уменьшающейся и минимизированной. Если вы используете какую-то увеличивающуюся метрику (например, точность), можно настроить функцию distance: (best_score, score) -> score - best_score.

# создадим псевдоточность, которая увеличивается на 0,01 каждый раз от 0 до 1
# назовем это acc()
acc = let v = 0
  () -> v = max(1, v + 0.01)
end

# создадим триггер досрочной остановки для точности
es = early_stopping(acc, 3; delta = (best_score, score) -> score - best_score)

# итерация будет выполняться до 10-й эпохи
for epoch in 1:10
  es() && break
end

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

threshold(f, thresh, delay) = patience(delay) do
  f() < thresh
end

predicate в patience и f в early_stopping/plateau могут принимать дополнительные аргументы. Такие дополнительные аргументы можно передать в predicate или f через возвращаемую функцию:

trigger = patience((a; b) -> a > b, 3)

# итерация будет выполняться до 10-й эпохи
for epoch in 1:10
  trigger(1; b = 2) && break
end

# остановится на 3-й эпохе
for epoch in 1:10
  trigger(3; b = 2) && break
end
patience(predicate, wait)

Возвращает функцию, которая ведет внутренний счет по одному, если predicate(...) == true, в противном случае подсчет обнуляется. Если подсчет больше или равен wait, функция возвращает true, в противном случае возвращает false.

Примеры

julia> loss() = rand();

julia> trigger = Flux.patience(() -> loss() < 1, 3);


julia> for i in 1:10
         @info "Epoch $i"
         trigger() && break
       end
[ Info: Epoch 1
[ Info: Epoch 2
[ Info: Epoch 3
early_stopping(f, delay; distance = -, init_score = 0, min_dist = 0)

Возвращает функцию, которая ведет внутренний счет по одному, если distance(best_score, f(...)) <= min_dist, где best_score — последнее наилучшее значение f(...). Если подсчет больше или равен delay, функция возвращает true, в противном случае возвращает false. Подсчет сбрасывается, когда distance(best_score, f(...)) > min_dist.

Примеры

julia> loss = let l = 0
         () -> l += 1
       end; # функция псевдопотерь, возвращающая возрастающие значения

julia> es = Flux.early_stopping(loss, 3);


julia> for i in 1:10
         @info "Epoch $i"
         es() && break
       end
[ Info: Epoch 1
[ Info: Epoch 2
[ Info: Epoch 3
plateau(f, width; distance = -, init_score = 0, min_dist = 1f-6)

Возвращает функцию, которая ведет внутренний счет по одному, если abs(distance(last_score, f(...))) <= min_dist, где last_score содержит последнее значение f(...). Если подсчет больше или равен width, функция возвращает true, в противном случае возвращает false. Подсчет сбрасывается, когда abs(distance(last_score, f(...))) > min_dist.

Примеры

julia> f = let v = 10
         () -> v = v / abs(v) - v
       end; # -9, 8, -7, 6, ...

julia> trigger = Flux.plateau(f, 3; init_score=10, min_dist=18);


julia> for i in 1:10
         @info "Epoch $i"
         trigger() && break
       end
[ Info: Epoch 1
[ Info: Epoch 2
[ Info: Epoch 3
[ Info: Epoch 4