keras回调函数

  回调函数在模型训练和模型学习结果分析中有非常重要的作用,如动态学习率调整,早停,tensorboard可视化分析模型训练过程。

Tensorboard可视化

1
2
3
4
5
6
7
8
9
10
11
from keras.callbacks import TensorBoard
tensorboard_k = TensorBoard(log_dir='./logs', # log 目录
histogram_freq=1, # 画直方图的频率
batch_size=32, # 用多大量的数据计算直方图
write_graph=True, # 是否存储网络结构图
write_grads=False, # 是否可视化梯度直方图
write_images=False,# 是否可视化权重
embeddings_freq= 0, #嵌入输出可视化
embeddings_layer_names=None, #可视化层的name
embeddings_metadata=None) #metadata的通俗理解是嵌入的标签
callbacks = [tensorboard_k]

嵌入层效果图:

t_sne
t_sne
编写自己的可视化回调函数示例—PR曲线

代码参考

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
from keras.callbacks import TensorBoard
from tensorboard.plugins.pr_curve import summary as pr_summary
class PRTensorBoard(TensorBoard):
def __init__(self, *args, **kwargs):
# One extra argument to indicate whether or not to use the PR curve summary.
self.pr_curve = kwargs.pop('pr_curve', True)
super(PRTensorBoard, self).__init__(*args, **kwargs)#super用于多重继承可自行百度其用法

global tf
import tensorflow as tf

def set_model(self, model):
super(PRTensorBoard, self).set_model(model)

if self.pr_curve:
# Get the prediction and label tensor placeholders.
predictions = self.model._feed_outputs[0]
labels = tf.cast(self.model._feed_targets[0], tf.bool)
# Create the PR summary OP.
self.pr_summary = pr_summary.op(name='pr_curve',
predictions=predictions,
labels=labels,
display_name='Precision-Recall Curve')

def on_epoch_end(self, epoch, logs=None):
super(PRTensorBoard, self).on_epoch_end(epoch, logs)

if self.pr_curve and self.validation_data:
# Get the tensors again.
tensors = self.model._feed_targets + self.model._feed_outputs
# Predict the output.
predictions = self.model.predict(self.validation_data[:-2])
# Build the dictionary mapping the tensor to the data.
val_data = [self.validation_data[-2], predictions]
feed_dict = dict(zip(tensors, val_data))
# Run and add summary.
result = self.sess.run([self.pr_summary], feed_dict=feed_dict)
self.writer.add_summary(result[0], epoch)
self.writer.flush()

效果图展示:

PR曲线
PR曲线

ModelCheckpoint

1
2
3
4
keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)
#在每个训练期之后保存模型。
#filepath 可以包括命名格式选项,可以由 epoch 的值和 logs 的键(由 on_epoch_end 参数传递)来填充。
#例如:如果 filepath 是 weights.{epoch:02d}-{val_loss:.2f}.hdf5, 那么模型被保存的的文件名就会有训练轮数和验证损失。

EarlyStopping

1
2
3
4
5
6
keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=0, verbose=0, mode='auto')
#monitor: 被监测的数据。
#min_delta: 在被监测的数据中被认为是提升的最小变化, 例如,小于 min_delta 的绝对变化会被认为没有提升。
#patience: 没有进步的训练轮数,在这之后训练就会被停止。
#verbose: 详细信息模式。
#mode: {auto, min, max} 其中之一。 在 min 模式中, 当被监测的数据停止下降,训练就会停止;在 max 模式中,当被监测的数据停止上升,训练就会停止;在 auto 模式中,方向会自动从被监测的数据的名字中判断出来。

LearningRateScheduler

1
2
3
keras.callbacks.LearningRateScheduler(schedule, verbose=0)
#schedule: 一个函数,接受轮索引数作为输入(整数,从 0 开始迭代) 然后返回一个学习速率作为输出(浮点数)。
#verbose: 整数。 0:安静,1:更新信息。
Scheduler示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
callbacks = []
class Schedule:
def __init__(self, nb_epochs, initial_lr):

self.epochs = nb_epochs

self.initial_lr = initial_lr

def __call__(self, epoch_idx):
if epoch_idx < self.epochs * 0.1:

return self.initial_lr

elif epoch_idx < self.epochs * 0.200:

return self.initial_lr * 0.1

elif epoch_idx < self.epochs * 0.3:

return self.initial_lr * 0.005

return self.initial_lr * 0.0005

callbacks.append(LearningRateScheduler(schedule=Schedule(nb_epochs, lr)))

创建自定义回调函数

简单的创建使用LambdaCallback
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
keras.callbacks.LambdaCallback(on_epoch_begin=None, on_epoch_end=None, on_batch_begin=None, on_batch_end=None, on_train_begin=None, on_train_end=None)

在训练进行中创建简单,自定义的回调函数的回调函数。

这个回调函数和匿名函数在合适的时间被创建。 需要注意的是回调函数要求位置型参数,如下:

on_epoch_begin 和 on_epoch_end 要求两个位置型的参数: epoch, logs

on_batch_begin 和 on_batch_end 要求两个位置型的参数: batch, logs

on_train_begin 和 on_train_end 要求一个位置型的参数: logs

参数:

on_epoch_begin: 在每轮开始时被调用。

on_epoch_end: 在每轮结束时被调用。

on_batch_begin: 在每批开始时被调用。

on_batch_end: 在每批结束时被调用。

on_train_begin: 在模型训练开始时被调用。

on_train_end: 在模型训练结束时被调用。
1
2
#示例 在每一个批开始时,打印出批数。
batch_print_callback = LambdaCallback(on_batch_begin=lambda batch,logs: print(batch))

通过继承回调函数基类定义回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#在训练时,保存一个列表的批量损失值:
class LossHistory(keras.callbacks.Callback):

def on_train_begin(self, logs={}):

self.losses = []

def on_batch_end(self, batch, logs={}):

self.losses.append(logs.get('loss'))

history = LossHistory()

model.fit(x_train, y_train, batch_size=128, epochs=20, verbose=0, callbacks=[history])

print(history.losses)
# 输出
'''
[0.66047596406559383, 0.3547245744908703, ..., 0.25953155204159617, 0.25901699725311789]
'''

Reference

所有参考均以贴上链接