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 相关文章推荐
python中for语句简单遍历数据的方法
May 07 Python
Python实现HTTP协议下的文件下载方法总结
Apr 20 Python
python 接口返回的json字符串实例
Mar 27 Python
Matplotlib 生成不同大小的subplots实例
May 25 Python
python截取两个单词之间的内容方法
Dec 25 Python
Python图像处理之直线和曲线的拟合与绘制【curve_fit()应用】
Dec 26 Python
Python设计模式之建造者模式实例详解
Jan 17 Python
python实现点击按钮修改数据的方法
Jul 17 Python
pytorch在fintune时将sequential中的层输出方法,以vgg为例
Aug 20 Python
Python基于QQ邮箱实现SSL发送
Apr 26 Python
学会python自动收发邮件 代替你问候女友
May 20 Python
python实现测试工具(一)——命令行发送get请求
Oct 19 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
html中select语句读取mysql表中内容
2006/10/09 PHP
PHP代码优化的53个细节
2014/03/03 PHP
PHP PDO fetch 模式各种参数的输出结果一览
2015/01/07 PHP
把html页面的部分内容保存成新的html文件的jquery代码
2009/11/12 Javascript
40款非常棒的jQuery 插件和制作教程(系列二)
2011/11/02 Javascript
javascript右下角弹层及自动隐藏(自己编写)
2013/11/20 Javascript
jquery为页面增加快捷键示例
2014/01/31 Javascript
使用nodejs中httpProxy代理时候出现404异常的解决方法
2016/08/15 NodeJs
JS+HTML5实现的前端购物车功能插件实例【附demo源码下载】
2016/10/17 Javascript
正则 js分转元带千分符号详解
2017/03/08 Javascript
vue实现动态添加数据滚动条自动滚动到底部的示例代码
2018/07/06 Javascript
解决layui中table异步数据请求不支持自定义返回数据格式的问题
2018/08/19 Javascript
jquery拖拽自动排序插件使用方法详解
2020/07/20 jQuery
详解es6新增数组方法简便了哪些操作
2019/05/09 Javascript
解决VUE-Router 同一页面第二次进入不刷新的问题
2020/07/22 Javascript
[02:27]2014DOTA2国际邀请赛 VG赛后采访:更大的挑战在等着我们
2014/07/13 DOTA
[50:21]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第二场
2018/08/19 DOTA
python计算圆周长、面积、球体体积并画出圆
2014/04/08 Python
Python实现FTP上传文件或文件夹实例(递归)
2017/01/16 Python
Python实现的选择排序算法示例
2017/11/29 Python
python基于ID3思想的决策树
2018/01/03 Python
python 实现读取一个excel多个sheet表并合并的方法
2019/02/12 Python
Pandas删除数据的几种情况(小结)
2019/06/21 Python
解决django FileFIELD的编码问题
2020/03/30 Python
python模拟哔哩哔哩滑块登入验证的实现
2020/04/24 Python
使用HTML和CSS3绘制基本卡通图案的示例分享
2015/11/06 HTML / CSS
一份比较全的PHP面试题
2016/07/29 面试题
营业员个人总结的自我评价
2013/10/25 职场文书
医学院四年学习生活的自我评价
2013/11/06 职场文书
《寓言两则》教学反思
2014/02/27 职场文书
《桂花雨》教学反思
2014/04/12 职场文书
暑假家长评语大全
2014/04/17 职场文书
南京青奥会口号
2014/06/12 职场文书
小学开学标语
2014/07/01 职场文书
六年级语文教学反思
2016/03/03 职场文书
springboot拦截器无法注入redisTemplate的解决方法
2021/06/27 Java/Android