TF2 Callback
- 一、回调函数简介
- 二、TF2中的内置回调函数
- 1- tf.keras.callbacks.BaseLogger 基础日志
- 2- tf.keras.callbacks.History 记录metrics日志
- 3- tf.keras.callbacks.EarlyStopping 终止训练
- 4- tf.keras.callbacks.TensorBoard 可视化日志保存
- 5- tf.keras.callbacks.ModelCheckpoint 保存模型
- 6- tf.keras.callbacks.ReduceLROnPlateau 减少学习率
- 7- tf.keras.callbacks.TerminateOnNaN LossNaN终止训练
- 8- tf.keras.callbacks.LearningRateScheduler 学习率控制器
- 9- tf.keras.callbacks.CSVLogger CSV日志记录
- 10- tf.keras.callbacks.ProgbarLogger Logs输出
- 11- tf.keras.callbacks.LambdaCallback 自定义回调类
- 三、定义回调函数
一、回调函数简介
回调函数,本身就是固定事件触发会调用的操作步骤。
在tf2的模型训练过程中,可以针对epoch,batch,train,test等操作步骤进行拦截,并触发回调函数。
其实,在tf2中不止对 model.fit, 而且对 model.evaluate , model.predict 也可以指定callbacks参数,配置回调函数,即:
- keras.Model.fit()
- keras.Model.evaluate()
- keras.Model.predict()
二、TF2中的内置回调函数
1- tf.keras.callbacks.BaseLogger 基础日志
用于记录每个epoch的平均metrics,该回调会对每个batch累加metrics,并在一个epoch结束后计算整体平均metrics作为一个epoch中metric的输出值。
该回调函数在每个模型中都会被 自动调用。
2- tf.keras.callbacks.History 记录metrics日志
将BaseLogger计算的各个epoch的metrics结果记录到history这个dict变量中,并作为model.fit的返回值。
该回调函数在所有模型中都会被调用,在BaseLogger之后被添加。
3- tf.keras.callbacks.EarlyStopping 终止训练
当被监控指标在设定的若干个epoch后没有提升,那么终止训练
4- tf.keras.callbacks.TensorBoard 可视化日志保存
为tensorboard的可视化保存日志信息,支持评估指标,计算图,模型参数等的可视化。
这个个人感觉,比tf1中更方便了。
参数:
keras.callbacks.TensorBoard(log_dir='./logs',
histogram_freq=0,
write_graph=True,
write_images=False,
embeddings_freq=0,
embeddings_layer_names=None,
embeddings_metadata=None)
-
log_dir
:保存日志文件的地址,该文件将被TensorBoard解析以用于可视化 -
histogram_freq
:计算各个层激活值直方图的频率(每多少个epoch计算一次),如果设置为0则不计算。 -
write_graph
: 是否在Tensorboard上可视化图,当设为True时,log文件可能会很大 -
write_images
: 是否将模型权重以图片的形式可视化 -
embeddings_freq
: 依据该频率(以epoch为单位)筛选保存的embedding层 -
embeddings_layer_names
:要观察的层名称的列表,若设置为None或空列表,则所有embedding层都将被观察。 -
embeddings_metadata
: 字典,将层名称映射为包含该embedding层元数据的文件名,参考这里获得元数据文件格式的细节。如果所有的embedding层都使用相同的元数据文件,则可传递字符串。
使用:
如果已经通过pip安装了TensorFlow,我们可通过下面的命令启动TensorBoard:
tensorboard --logdir=/full_path_to_your_logs
5- tf.keras.callbacks.ModelCheckpoint 保存模型
在每个epoch后保存模型
参数:
keras.callbacks.ModelCheckpoint(filepath,
monitor='val_loss',
verbose=0,
save_best_only=False,
save_weights_only=False,
mode='auto',
period=1)
-
filename
:字符串,保存模型的路径
filepath可以是格式化的字符串,里面的占位符将会被epoch值和传入on_epoch_end的logs关键字所填入。例如:filepath若为weights.{epoch:02d-{val_loss:.2f}}.hdf5,则会生成对应epoch和验证集loss的多个文件。 -
monitor
:需要监视的值 -
verbose
:信息展示模式,0或1 -
save_best_only
:当设置为True时,将只保存在验证集上性能最好的模型 -
mode
:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。 -
save_weights_only
:若设置为True,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等) -
period:CheckPoint之间的间隔的epoch数
6- tf.keras.callbacks.ReduceLROnPlateau 减少学习率
如果监控指标在若干个epoch后没有提升,那么以一定的变化因子减少学习率。
当评价指标不再提升时,那么就需要减少学习率,可以减少2倍或者10倍等的学习率通常能够获得比较好的效果。
参数:
ReduceLROnPlateau( monitor='val_loss',
factor=0.1,
patience=10,
verbose=0,
mode='auto',
min_delta=1e-4,
cooldown=0,
min_lr=0 )
monitor
:被监测的量factor
:每次减少学习率的因子,学习率将以lr = lr*factor的形式被减少patience
:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发mode
:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少。epsilon
:阈值,用来确定是否进入检测值的“平原区”cooldown
:学习率减少后,会经过cooldown个epoch才重新进行正常操作min_lr
:学习率的下限
7- tf.keras.callbacks.TerminateOnNaN LossNaN终止训练
如果遇到loss为NaN,那么提前终止训练
8- tf.keras.callbacks.LearningRateScheduler 学习率控制器
给定学习率lr和epoch的函数关系,根据该函数关系在每个epoch前调整学习率
参数:
keras.callbacks.LearningRateScheduler(schedule)
schedule
: 函数,该函数以epoch号为参数(从0算起的整数),返回一个新的学习率(float类型)。
9- tf.keras.callbacks.CSVLogger CSV日志记录
将每个epoch后的logs结果记录到CSV文件中
支持所有可被转换为string的值,包括1D的可迭代数值如 np.ndarray
。
参数:
keras.callbacks.CSVLogger(filename, separator=',', append=False)
fiename
:保存的csv文件名,如run/log.csvseparator
:字符串,csv分隔符append
:默认为False,为True时csv文件如果存在则继续写入,为False时总是覆盖csv文件
10- tf.keras.callbacks.ProgbarLogger Logs输出
将每个epoch后的logs结果打印到标准输出流中。
11- tf.keras.callbacks.LambdaCallback 自定义回调类
用于自定义创建简单回调函数的类
该callback的匿名函数将会在适当的时候调用,注意,该回调函数假定了一些位置参数
- on_eopoch_begin和on_epoch_end假定输入的参数是epoch, logs.
- on_batch_begin和on_batch_end假定输入的参数是batch, logs,
- on_train_begin和on_train_end假定输入的参数是logs
on_epoch_begin: 在每个epoch开始时调用
on_epoch_end: 在每个epoch结束时调用
on_batch_begin: 在每个batch开始时调用
on_batch_end: 在每个batch结束时调用
on_train_begin: 在训练开始时调用
on_train_end: 在训练结束时调用
最后有实例。
三、定义回调函数
1、使用LambdaCallback编写简单回调函数
# !/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName :optimizer1.py
# @Time :2021/1/22 0022 19:59
# @Author :gaofei
# model.fit
import json
import tensorflow as tf
from tensorflow.keras import Model, callbacks
import numpy as np
def close(logs):
json_log.write('{}]')
json_log.close()
tf.keras.backend.clear_session()
# 示范使用LambdaCallback编写较为简单的回调函数 ----------
json_log = open('./log/lbd.json', 'wt', buffering=1)
json_logging_callback = callbacks.LambdaCallback(
on_epoch_end=lambda epoch, logs: json_log.write(
json.dumps(
dict(epoch=epoch, **logs)
) + ',\n'
),
on_train_end=close,
on_train_begin=lambda logs: json_log.write('[')
)
# ----------------------------------------------------
class CalcModel(tf.keras.models.Model):
def __init__(self, a, b, c):
super(CalcModel, self).__init__()
self.a = a
self.b = b
self.c = c
def build(self):
self.x = tf.Variable(0.0, name='x')
self.built = True
def call(self, features):
print('features:', tf.print(features))
loss = self.a * (self.x) ** 2 + self.b * (self.x) + self.c
tf.print(self.x)
res = (tf.ones_like(features) * loss)
return res
def myloss(y_true, y_pred):
return tf.reduce_mean(y_pred)
model = CalcModel(tf.constant(1.0), tf.constant(-2.0), tf.constant(1.0))
model.build()
model.summary()
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.001), loss=myloss)
history = model.fit(tf.zeros(100), tf.ones(100), batch_size=1, epochs=10, callbacks=[json_logging_callback])
tf.print('x = ', model.x)
tf.print('loss = ', model(tf.constant(0.0)))
生成日志记录为:
2、子类化Callback编写回调函数
@keras_export('keras.callbacks.LearningRateScheduler')
class LearningRateScheduler(Callback):
"""Learning rate scheduler.
Arguments:
schedule: a function that takes an epoch index as input
(integer, indexed from 0) and returns a new
learning rate as output (float).
verbose: int. 0: quiet, 1: update messages.
```python
# This function keeps the learning rate at 0.001 for the first ten epochs
# and decreases it exponentially after that.
def scheduler(epoch):
if epoch < 10:
return 0.001
else:
return 0.001 * tf.math.exp(0.1 * (10 - epoch))
callback = tf.keras.callbacks.LearningRateScheduler(scheduler)
model.fit(data, labels, epochs=100, callbacks=[callback],
validation_data=(val_data, val_labels))
"""
def __init__(self, schedule, verbose=0):
super(LearningRateScheduler, self).__init__()
self.schedule = schedule
self.verbose = verbose
def on_epoch_begin(self, epoch, logs=None):
if not hasattr(self.model.optimizer, 'lr'):
raise ValueError('Optimizer must have a "lr" attribute.')
try: # new API
lr = float(K.get_value(self.model.optimizer.lr))
lr = self.schedule(epoch, lr)
except TypeError: # Support for old API for backward compatibility
lr = self.schedule(epoch)
if not isinstance(lr, (ops.Tensor, float, np.float32, np.float64)):
raise ValueError('The output of the "schedule" function '
'should be float.')
if isinstance(lr, ops.Tensor) and not lr.dtype.is_floating:
raise ValueError('The dtype of Tensor should be float')
K.set_value(self.model.optimizer.lr, K.get_value(lr))
if self.verbose > 0:
print('\nEpoch %05d: LearningRateScheduler reducing learning '
'rate to %s.' % (epoch + 1, lr))
def on_epoch_end(self, epoch, logs=None):
logs = logs or {}
logs['lr'] = K.get_value(self.model.optimizer.lr)