十一、【TF2】Callback 回调函数

一、回调函数简介

回调函数,本身就是固定事件触发会调用的操作步骤。
在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.csv
  • separator:字符串,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)

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值