-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcallbacks.py
76 lines (57 loc) · 3.21 KB
/
callbacks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""
Author: Ani Aggarwal
Github: www.github.com/AniAggarwal
"""
import tensorflow.keras as keras
from tensorflow.keras import backend as K
import numpy as np
class EarlyStopCallback(keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
# if logs.get("loss") < 0.4:
# print("\nReached loss of 0.4 so cancelling training!")
# self.model.stop_training = True
if logs.get("accuracy") > 0.75:
print("\nReached 75% accuracy so cancelling training!")
self.model.stop_training = True
# from https://www.kaggle.com/fergusoci/keras-loss-based-learning-rate-scheduler
class LossLearningRateScheduler(keras.callbacks.History):
"""
A learning rate scheduler that relies on changes in loss function
value to dictate whether learning rate is decayed or not.
LossLearningRateScheduler has the following properties:
base_lr: the starting learning rate
lookback_epochs: the number of epochs in the past to compare with the loss function at the current epoch to determine if progress is being made.
decay_threshold / decay_multiple: if loss function has not improved by a factor of decay_threshold * lookback_epochs, then decay_multiple will be applied to the learning rate.
spike_epochs: list of the epoch numbers where you want to spike the learning rate.
spike_multiple: the multiple applied to the current learning rate for a spike.
"""
def __init__(self, base_lr, lookback_epochs, spike_epochs=None, spike_multiple=10, decay_threshold=0.002,
decay_multiple=0.5, loss_type='val_loss'):
super(LossLearningRateScheduler, self).__init__()
self.base_lr = base_lr
self.lookback_epochs = lookback_epochs
self.spike_epochs = spike_epochs
self.spike_multiple = spike_multiple
self.decay_threshold = decay_threshold
self.decay_multiple = decay_multiple
self.loss_type = loss_type
def on_epoch_begin(self, epoch, logs=None):
if len(self.epoch) > self.lookback_epochs:
current_lr = K.get_value(self.model.optimizer.lr)
target_loss = self.history[self.loss_type]
loss_diff = target_loss[-int(self.lookback_epochs)] - target_loss[-1]
if loss_diff <= np.abs(target_loss[-1]) * (self.decay_threshold * self.lookback_epochs):
print(' '.join(
('Changing learning rate from', str(current_lr), 'to', str(current_lr * self.decay_multiple))))
K.set_value(self.model.optimizer.lr, current_lr * self.decay_multiple)
current_lr = current_lr * self.decay_multiple
else:
print(' '.join(('Learning rate:', str(current_lr))))
if self.spike_epochs is not None and len(self.epoch) in self.spike_epochs:
print(' '.join(
('Spiking learning rate from', str(current_lr), 'to', str(current_lr * self.spike_multiple))))
K.set_value(self.model.optimizer.lr, current_lr * self.spike_multiple)
else:
print(' '.join(('Setting learning rate to', str(self.base_lr))))
K.set_value(self.model.optimizer.lr, self.base_lr)
return K.get_value(self.model.optimizer.lr)