keras自定义回调函数查看训练的loss和accuracy方式


Posted in Python onMay 23, 2020

前言:

keras是一个十分便捷的开发框架,为了更好的追踪网络训练过程中的损失函数loss和准确率accuracy,我们有几种处理方式,第一种是直接通过 history=model.fit(),来返回一个history对象,通过这个对象可以访问到训练过程训练集的loss和accuracy以及验证集的loss和accuracy。

第二种方式就是通过自定义一个回调函数Call backs,来实现这一功能,本文主要讲解第二种方式。

一、如何构建回调函数Callbacks

本文所针对的例子是卷积神经网络Lenet-5,数据集是mnist数据集。

1.1 什么是回调函数

回调函数是一个函数的合集,会在训练的阶段中所使用。你可以使用回调函数来查看训练模型的内在状态和统计。你可以传递一个列表的回调函数(作为 callbacks 关键字参数)到 Sequential 或 Model 类型的 .fit() 方法。在训练时,相应的回调函数的方法就会被在各自的阶段被调用。

这里有两个关键的点:

(1)状态和统计:其实就是我们希望模型在训练过程中需要从过程中获取什么信息,比如我的损失loss,准确率accuracy等信息就是训练过程中的状态与统计信息;再比如我希望每一个epoch结束之后打印一些相应的自定义提示信息,这也是状态信息。

(2)各自的阶段:模型的训练一般是分为多少个epoch,然后每一个epoch又分为多少个batch,所以这个阶段可以是在每一个epoch之后执行回调函数,也可以是在每一个batch之后执行回调函数。

1.2 回调函数的本质

其实回调函数只是一个很形象的说法,它的本质是一个类,我们直接通过 history=model.fit()返回的history对象就是一个回调函数History类的对象,而History类又继承自Callback类。

回调函数的基类——Call back,他的定义如下:

class Callback(object): # 用来组建新的回调函数的抽象基类
 
 def __init__(self):
  self.validation_data = None
  self.model = None
 
 def set_params(self, params):
  self.params = params
 
 def set_model(self, model):
  self.model = model
 
 def on_epoch_begin(self, epoch, logs=None):
  pass
 
 def on_epoch_end(self, epoch, logs=None):
  pass
 
 def on_batch_begin(self, batch, logs=None):
  pass
 
 def on_batch_end(self, batch, logs=None):
  pass
 
 def on_train_begin(self, logs=None):
  pass
 
 def on_train_end(self, logs=None):
  pass

属性

params: 它是一个字典类型。训练参数, (例如,verbosity, batch size, number of epochs...)。

model: keras.models.Model 的实例。 指代被训练模型。

被回调函数作为参数的 logs 字典,它会含有于当前批量或训练轮相关数据的键。

特别需要注意的是,上面的每一个函数里面均有一个logs参数,这个参数也是记录训练信息的关键,需要注意以下几个点:

(1)logs是一个字典对象directory;

(2)在不同的方法中这个logs有不同的键值;分别如下:

on_epoch_end: 包括 acc 和 loss 的日志, 也可以选择性的包括 val_loss(如果在 fit 中启用验证),和 val_acc(如果启用验证和监测精确值)。这个用的是最多的。

on_batch_begin: 包括 size 的日志,在当前批量内的样本数量。

on_batch_end: 包括 loss 的日志,也可以选择性的包括 acc

1.3 系统预定义的回调函数

BaseLogger
TerminateOnNaN
ProgbarLogger
History
ModelCheckpoint
EarlyStopping
RemoteMonitor
LearningRateScheduler
TensorBoard
ReduceLROnPlateau
CSVLogger
LambdaCallback

二、keras实现自定义History回调函数记录loss和accuracy

2.1 回调函数的定义

# 写一个LossHistory类,保存训练集的loss和acc
# 当然我也可以完全不这么做,可以直接使用model.fit()方法返回的 history对象去做
'''Callback有6个常用的方法,这里实现其中的四个
 def on_epoch_begin(self, epoch, logs=None):
 def on_epoch_end(self, epoch, logs=None):
 def on_batch_begin(self, batch, logs=None):
 def on_batch_end(self, batch, logs=None):
 def on_train_begin(self, logs=None):
 def on_train_end(self, logs=None):
'''
class LossHistory(Callback): # 继承自Callback类
 
 '''
 在模型开始的时候定义四个属性,每一个属性都是字典类型,存储相对应的值和epoch
 '''
 def on_train_begin(self, logs={}):
  self.losses = {'batch':[], 'epoch':[]}
  self.accuracy = {'batch':[], 'epoch':[]}
  self.val_loss = {'batch':[], 'epoch':[]}
  self.val_acc = {'batch':[], 'epoch':[]}
 
 # 在每一个batch结束后记录相应的值
 def on_batch_end(self, batch, logs={}):
  self.losses['batch'].append(logs.get('loss'))
  self.accuracy['batch'].append(logs.get('acc'))
  self.val_loss['batch'].append(logs.get('val_loss'))
  self.val_acc['batch'].append(logs.get('val_acc'))
 
 # 在每一个epoch之后记录相应的值
 def on_epoch_end(self, batch, logs={}):
  self.losses['epoch'].append(logs.get('loss'))
  self.accuracy['epoch'].append(logs.get('acc'))
  self.val_loss['epoch'].append(logs.get('val_loss'))
  self.val_acc['epoch'].append(logs.get('val_acc'))
 
 def loss_plot(self, loss_type):
  '''
  loss_type:指的是 'epoch'或者是'batch',分别表示是一个batch之后记录还是一个epoch之后记录
  '''
  iters = range(len(self.losses[loss_type]))
  plt.figure()
  # acc
  plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')
  # loss
  plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
  if loss_type == 'epoch':
   # val_acc
   plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
   # val_loss
   plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
  plt.grid(True)
  plt.xlabel(loss_type)
  plt.ylabel('acc-loss')
  plt.legend(loc="upper right")
  plt.savefig("mnist_keras.png")
  plt.show()

2.2 模型的搭建以及训练

mnist数据准备

# 训练参数
learning_rate = 0.001
epochs = 10
batch_size = 128
n_classes = 10
 
# 定义图像维度reshape
img_rows, img_cols = 28, 28
 
# 加载keras中的mnist数据集 分为60,000个训练集,10,000个测试集
(x_train, y_train), (x_test, y_test) = mnist.load_data()
 
# 将图片转化为(samples,width,height,channels)的格式
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
 
# 将X_train, X_test的数据格式转为float32
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
# 将X_train, X_test归一化0-1
x_train /= 255
x_test /= 255
 
# 输出0-9转换为ont-hot形式
y_train = np_utils.to_categorical(y_train, n_classes)
y_test = np_utils.to_categorical(y_test, n_classes)

模型的搭建以及训练

# 建立模型
model = Sequential()
 
# lenet-5
model.add(Convolution2D(filters=6, kernel_size=(5, 5), padding='valid', input_shape=(img_rows, img_cols, 1), activation='tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(filters=16, kernel_size=(5, 5), padding='valid', activation='tanh'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(120, activation='tanh'))
model.add(Dense(84, activation='tanh'))
model.add(Dense(n_classes, activation='softmax'))
 
#打印模型# verbose=1显示进度条
model.summary()
 
# 编译模型
model.compile(optimizer=Adam(lr=learning_rate), loss='categorical_crossentropy',metrics=['accuracy'])
 
history = LossHistory() # 这里是使用自定义的Callback回调函数,当然本身fit函数也会返回一个history可供使用
model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs, verbose=1,validation_data=(x_test, y_test),callbacks=[history])
model.save('./models/lenet5_weight.h5')

绘制训练过程loss和acc曲线

#绘制训练的acc-loss曲线

history.loss_plot('epoch') # 每一个epoch展示一次

最终的运行结果如下:

Epoch 1/10
2019-06-23 08:44:32.930737: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties:
name: GeForce GTX 950 major: 5 minor: 2 memoryClockRate(GHz): 1.2155
pciBusID: 0000:01:00.0
totalMemory: 2.00GiB freeMemory: 1.64GiB
2019-06-23 08:44:32.937390: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0
2019-06-23 08:44:37.003650: I tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect StreamExecutor with strength 1 edge matrix:
2019-06-23 08:44:37.006358: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988]  0
2019-06-23 08:44:37.008076: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0: N
2019-06-23 08:44:37.012620: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 1388 MB memory) -> physical GPU (device: 0, name: GeForce GTX 950, pci bus id: 0000:01:00.0, compute capability: 5.2)
60000/60000 [==============================] - 18s 302us/step - loss: 0.2979 - acc: 0.9151 - val_loss: 0.0863 - val_acc: 0.9730
Epoch 2/10
60000/60000 [==============================] - 4s 61us/step - loss: 0.0810 - acc: 0.9753 - val_loss: 0.0611 - val_acc: 0.9808
Epoch 3/10
60000/60000 [==============================] - 4s 59us/step - loss: 0.0575 - acc: 0.9826 - val_loss: 0.0518 - val_acc: 0.9849
Epoch 4/10
60000/60000 [==============================] - 4s 59us/step - loss: 0.0451 - acc: 0.9857 - val_loss: 0.0480 - val_acc: 0.9848
Epoch 5/10
60000/60000 [==============================] - 4s 59us/step - loss: 0.0375 - acc: 0.9886 - val_loss: 0.0449 - val_acc: 0.9860
Epoch 6/10
60000/60000 [==============================] - 3s 57us/step - loss: 0.0307 - acc: 0.9907 - val_loss: 0.0392 - val_acc: 0.9863
Epoch 7/10
60000/60000 [==============================] - 4s 68us/step - loss: 0.0242 - acc: 0.9923 - val_loss: 0.0389 - val_acc: 0.9882
Epoch 8/10
60000/60000 [==============================] - 4s 75us/step - loss: 0.0192 - acc: 0.9944 - val_loss: 0.0354 - val_acc: 0.9891
Epoch 9/10
60000/60000 [==============================] - 4s 66us/step - loss: 0.0180 - acc: 0.9942 - val_loss: 0.0385 - val_acc: 0.9885
Epoch 10/10
60000/60000 [==============================] - 4s 67us/step - loss: 0.0143 - acc: 0.9956 - val_loss: 0.0516 - val_acc: 0.9860

得到的训练曲线如下:

keras自定义回调函数查看训练的loss和accuracy方式

三、模型的结果测试

这里需要使用到sklearn库,代码如下:

from keras.models import load_model
from sklearn.metrics import confusion_matrix, f1_score, precision_score, recall_score,accuracy_score
 
# 测试
model=load_model('./models/lenet5_weight.h5')
 
y_predict = model.predict(x_test, batch_size=512, verbose=1)
# y_predict = (y_predict > 0.007).astype(int)
y_predict = (y_predict > 0.01).astype(int)
y_true = np.reshape(y_test, [-1])
y_pred = np.reshape(y_predict, [-1])
 
# 评价指标
accuracy = accuracy_score(y_true, y_pred)
precision = precision_score(y_true, y_pred)
recall = recall_score(y_true, y_pred, average='binary')
f1score = f1_score(y_true, y_pred, average='binary')
 
# Micro F1: 将n分类的评价拆成n个二分类的评价,将n个二分类评价的TP、FP、RN对应相加,计算评价准确率和召回率,由这2个准确率和召回率计算的F1 score即为Micro F1。
# Macro F1: 将n分类的评价拆成n个二分类的评价,计算每个二分类的F1 score,n个F1 score的平均值即为Macro F1。
# 一般来讲,Macro F1、Micro F1高的分类效果好。Macro F1受样本数量少的类别影响大。
micro_f1 = f1_score(y_true, y_pred,average='micro')
macro_f1 = f1_score(y_true, y_pred,average='macro')
 
print('accuracy:',accuracy)
print('precision:',precision)
print('recall:',recall)
print('f1score:',f1score)
print('Macro-F1: {}'.format(macro_f1))
print('Micro-F1: {}'.format(micro_f1))

运行结果是:

10000/10000 [==============================] - 2s 151us/step
accuracy: 0.98813
precision: 0.8956631049654306
recall: 0.9975
f1score: 0.9438425509769599
Macro-F1: 0.9686030934161676
Micro-F1: 0.98813

以上这篇keras自定义回调函数查看训练的loss和accuracy方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python3.2模拟实现webqq登录
Feb 15 Python
Python标准库shutil用法实例详解
Aug 13 Python
在python 中实现运行多条shell命令
Jan 07 Python
python批量下载抖音视频
Jun 17 Python
Django Docker容器化部署之Django-Docker本地部署
Oct 09 Python
Python中base64与xml取值结合问题
Dec 22 Python
python列表推导和生成器表达式知识点总结
Jan 10 Python
python生成13位或16位时间戳以及反向解析时间戳的实例
Mar 03 Python
python的pip有什么用
Jun 17 Python
python实现学生成绩测评系统
Jun 22 Python
Python Tornado核心及相关原理详解
Jun 24 Python
Keras实现DenseNet结构操作
Jul 06 Python
Keras设定GPU使用内存大小方式(Tensorflow backend)
May 22 #Python
tensorflow使用L2 regularization正则化修正overfitting过拟合方式
May 22 #Python
Softmax函数原理及Python实现过程解析
May 22 #Python
Python接口测试文件上传实例解析
May 22 #Python
计算Python Numpy向量之间的欧氏距离实例
May 22 #Python
python numpy矩阵信息说明,shape,size,dtype
May 22 #Python
python查看矩阵的行列号以及维数方式
May 22 #Python
You might like
php防注入及开发安全详细解析
2013/08/09 PHP
Yii中实现处理前后台登录的新方法
2015/12/28 PHP
php htmlentities()函数的定义和用法
2016/05/13 PHP
Laravel中10个有用的用法小结
2019/05/06 PHP
php中yii框架实例用法
2020/12/22 PHP
Javascript 陷阱 window全局对象
2008/11/26 Javascript
jquery 多级下拉菜单核心代码
2010/05/21 Javascript
给artDialog 5.02 增加ajax get功能详细介绍
2012/11/13 Javascript
jquery带下拉菜单和焦点图代码分享
2015/08/24 Javascript
封装好的javascript前端分页插件pagination
2016/01/04 Javascript
50 个 jQuery 插件可将你的网站带到另外一个高度
2016/04/26 Javascript
JS实现六边形3D拖拽翻转效果的方法
2016/09/11 Javascript
使用BootStrap实现悬浮窗口的效果
2016/12/13 Javascript
Bootstrap轮播图学习使用
2017/02/10 Javascript
微信小程序实现滑动删除效果
2017/05/19 Javascript
vue移动端微信授权登录插件封装的实例
2018/08/28 Javascript
vue基于element的区间选择组件
2018/09/07 Javascript
JS简单数组排序操作示例【sort方法】
2019/05/17 Javascript
vue 自动化路由实现代码
2019/09/03 Javascript
JS实现TITLE悬停长久显示效果完整示例
2020/02/11 Javascript
[46:14]VGJ.T vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
在Django框架中运行Python应用全攻略
2015/07/17 Python
详解Python之数据序列化(json、pickle、shelve)
2017/03/30 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
python3.7简单的爬虫实例详解
2019/07/08 Python
Python模拟FTP文件服务器的操作方法
2020/02/18 Python
python中如何进行连乘计算
2020/05/28 Python
台湾团购、宅配和优惠券:17Life
2017/08/14 全球购物
幼儿园安全责任书
2014/04/14 职场文书
《谁的本领大》教后反思
2014/04/25 职场文书
我的中国梦演讲稿800字
2014/08/19 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书
总经理致辞
2015/07/29 职场文书
Redis 彻底禁用RDB持久化操作
2021/07/09 Redis
MySQL中utf8mb4排序规则示例
2021/08/02 MySQL
Ubuntu Server 安装Tomcat并配置systemctl
2022/04/28 Servers