欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

keras自定義回調函數查看訓練的loss和accuracy方式

 更新時間:2020年05月23日 08:48:14   作者:LoveMIss-Y  
這篇文章主要介紹了keras自定義回調函數查看訓練的loss和accuracy方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

前言:

keras是一個十分便捷的開發(fā)框架,為了更好的追蹤網絡訓練過程中的損失函數loss和準確率accuracy,我們有幾種處理方式,第一種是直接通過 history=model.fit(),來返回一個history對象,通過這個對象可以訪問到訓練過程訓練集的loss和accuracy以及驗證集的loss和accuracy。

第二種方式就是通過自定義一個回調函數Call backs,來實現這一功能,本文主要講解第二種方式。

一、如何構建回調函數Callbacks

本文所針對的例子是卷積神經網絡Lenet-5,數據集是mnist數據集。

1.1 什么是回調函數

回調函數是一個函數的合集,會在訓練的階段中所使用。你可以使用回調函數來查看訓練模型的內在狀態(tài)和統(tǒng)計。你可以傳遞一個列表的回調函數(作為 callbacks 關鍵字參數)到 Sequential 或 Model 類型的 .fit() 方法。在訓練時,相應的回調函數的方法就會被在各自的階段被調用。

這里有兩個關鍵的點:

(1)狀態(tài)和統(tǒng)計:其實就是我們希望模型在訓練過程中需要從過程中獲取什么信息,比如我的損失loss,準確率accuracy等信息就是訓練過程中的狀態(tài)與統(tǒng)計信息;再比如我希望每一個epoch結束之后打印一些相應的自定義提示信息,這也是狀態(tài)信息。

(2)各自的階段:模型的訓練一般是分為多少個epoch,然后每一個epoch又分為多少個batch,所以這個階段可以是在每一個epoch之后執(zhí)行回調函數,也可以是在每一個batch之后執(zhí)行回調函數。

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(如果啟用驗證和監(jiān)測精確值)。這個用的是最多的。

on_batch_begin: 包括 size 的日志,在當前批量內的樣本數量。

on_batch_end: 包括 loss 的日志,也可以選擇性的包括 acc

1.3 系統(tǒng)預定義的回調函數

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

得到的訓練曲線如下:

三、模型的結果測試

這里需要使用到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方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

最新評論