当前位置:   article > 正文

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

keras loss accuracy

前言: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,他的定义如下:

  1. class Callback(object): # 用来组建新的回调函数的抽象基类
  2. def __init__(self):
  3. self.validation_data = None
  4. self.model = None
  5. def set_params(self, params):
  6. self.params = params
  7. def set_model(self, model):
  8. self.model = model
  9. def on_epoch_begin(self, epoch, logs=None):
  10. pass
  11. def on_epoch_end(self, epoch, logs=None):
  12. pass
  13. def on_batch_begin(self, batch, logs=None):
  14. pass
  15. def on_batch_end(self, batch, logs=None):
  16. pass
  17. def on_train_begin(self, logs=None):
  18. pass
  19. def on_train_end(self, logs=None):
  20. pass

属性

  • params: 它是一个字典类型。训练参数, (例如,verbosity, batch size, number of epochs...)。
  • modelkeras.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 系统预定义的回调函数

  1. BaseLogger
  2. TerminateOnNaN
  3. ProgbarLogger
  4. History
  5. ModelCheckpoint
  6. EarlyStopping
  7. RemoteMonitor
  8. LearningRateScheduler
  9. TensorBoard
  10. ReduceLROnPlateau
  11. CSVLogger
  12. LambdaCallback

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

2.1 回调函数的定义

  1. # 写一个LossHistory类,保存训练集的loss和acc
  2. # 当然我也可以完全不这么做,可以直接使用model.fit()方法返回的 history对象去做
  3. '''Callback有6个常用的方法,这里实现其中的四个
  4. def on_epoch_begin(self, epoch, logs=None):
  5. def on_epoch_end(self, epoch, logs=None):
  6. def on_batch_begin(self, batch, logs=None):
  7. def on_batch_end(self, batch, logs=None):
  8. def on_train_begin(self, logs=None):
  9. def on_train_end(self, logs=None):
  10. '''
  11. class LossHistory(Callback): # 继承自Callback类
  12. '''
  13. 在模型开始的时候定义四个属性,每一个属性都是字典类型,存储相对应的值和epoch
  14. '''
  15. def on_train_begin(self, logs={}):
  16. self.losses = {'batch':[], 'epoch':[]}
  17. self.accuracy = {'batch':[], 'epoch':[]}
  18. self.val_loss = {'batch':[], 'epoch':[]}
  19. self.val_acc = {'batch':[], 'epoch':[]}
  20. # 在每一个batch结束后记录相应的值
  21. def on_batch_end(self, batch, logs={}):
  22. self.losses['batch'].append(logs.get('loss'))
  23. self.accuracy['batch'].append(logs.get('acc'))
  24. self.val_loss['batch'].append(logs.get('val_loss'))
  25. self.val_acc['batch'].append(logs.get('val_acc'))
  26. # 在每一个epoch之后记录相应的值
  27. def on_epoch_end(self, batch, logs={}):
  28. self.losses['epoch'].append(logs.get('loss'))
  29. self.accuracy['epoch'].append(logs.get('acc'))
  30. self.val_loss['epoch'].append(logs.get('val_loss'))
  31. self.val_acc['epoch'].append(logs.get('val_acc'))
  32. def loss_plot(self, loss_type):
  33. '''
  34. loss_type:指的是 'epoch'或者是'batch',分别表示是一个batch之后记录还是一个epoch之后记录
  35. '''
  36. iters = range(len(self.losses[loss_type]))
  37. plt.figure()
  38. # acc
  39. plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')
  40. # loss
  41. plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
  42. if loss_type == 'epoch':
  43. # val_acc
  44. plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
  45. # val_loss
  46. plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
  47. plt.grid(True)
  48. plt.xlabel(loss_type)
  49. plt.ylabel('acc-loss')
  50. plt.legend(loc="upper right")
  51. plt.savefig("mnist_keras.png")
  52. plt.show()

2.2 模型的搭建以及训练

mnist数据准备

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

模型的搭建以及训练

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

绘制训练过程loss和acc曲线

  1. #绘制训练的acc-loss曲线
  2. history.loss_plot('epoch') # 每一个epoch展示一次

最终的运行结果如下:

  1. Epoch 1/10
  2. 2019-06-23 08:44:32.930737: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties:
  3. name: GeForce GTX 950 major: 5 minor: 2 memoryClockRate(GHz): 1.2155
  4. pciBusID: 0000:01:00.0
  5. totalMemory: 2.00GiB freeMemory: 1.64GiB
  6. 2019-06-23 08:44:32.937390: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0
  7. 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:
  8. 2019-06-23 08:44:37.006358: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988] 0
  9. 2019-06-23 08:44:37.008076: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0: N
  10. 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)
  11. 60000/60000 [==============================] - 18s 302us/step - loss: 0.2979 - acc: 0.9151 - val_loss: 0.0863 - val_acc: 0.9730
  12. Epoch 2/10
  13. 60000/60000 [==============================] - 4s 61us/step - loss: 0.0810 - acc: 0.9753 - val_loss: 0.0611 - val_acc: 0.9808
  14. Epoch 3/10
  15. 60000/60000 [==============================] - 4s 59us/step - loss: 0.0575 - acc: 0.9826 - val_loss: 0.0518 - val_acc: 0.9849
  16. Epoch 4/10
  17. 60000/60000 [==============================] - 4s 59us/step - loss: 0.0451 - acc: 0.9857 - val_loss: 0.0480 - val_acc: 0.9848
  18. Epoch 5/10
  19. 60000/60000 [==============================] - 4s 59us/step - loss: 0.0375 - acc: 0.9886 - val_loss: 0.0449 - val_acc: 0.9860
  20. Epoch 6/10
  21. 60000/60000 [==============================] - 3s 57us/step - loss: 0.0307 - acc: 0.9907 - val_loss: 0.0392 - val_acc: 0.9863
  22. Epoch 7/10
  23. 60000/60000 [==============================] - 4s 68us/step - loss: 0.0242 - acc: 0.9923 - val_loss: 0.0389 - val_acc: 0.9882
  24. Epoch 8/10
  25. 60000/60000 [==============================] - 4s 75us/step - loss: 0.0192 - acc: 0.9944 - val_loss: 0.0354 - val_acc: 0.9891
  26. Epoch 9/10
  27. 60000/60000 [==============================] - 4s 66us/step - loss: 0.0180 - acc: 0.9942 - val_loss: 0.0385 - val_acc: 0.9885
  28. Epoch 10/10
  29. 60000/60000 [==============================] - 4s 67us/step - loss: 0.0143 - acc: 0.9956 - val_loss: 0.0516 - val_acc: 0.9860

得到的训练曲线如下:

三、模型的结果测试

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

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

 运行结果是:

  1. 10000/10000 [==============================] - 2s 151us/step
  2. accuracy: 0.98813
  3. precision: 0.8956631049654306
  4. recall: 0.9975
  5. f1score: 0.9438425509769599
  6. Macro-F1: 0.9686030934161676
  7. Micro-F1: 0.98813

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/133233
推荐阅读
相关标签
  

闽ICP备14008679号