1. 程式人生 > >使用keras繪製實時的loss與acc曲線

使用keras繪製實時的loss與acc曲線

廢話不多說,直接上程式碼,程式碼有註釋,不懂得評論問博主即可

# -*- coding: utf-8 -*-
import keras
from keras.models import Sequential
from keras.layers import Dense
import numpy as np
import matplotlib.pyplot as plt
import time
# 輸入訓練資料 keras接收numpy陣列型別的資料
x = np.array([[0, 1, 0],
              [0, 0, 1],
              [1, 3, 2],
              [3, 2, 1]])
y = np.array([0, 0, 1, 1]).T
# 最簡單的序貫模型,序貫模型是多個網路層的線性堆疊
simple_model = Sequential()
# dense層為全連線層
# 第一層隱含層為全連線層 5個神經元 輸入資料的維度為3
simple_model.add(Dense(5, input_dim=3, activation='relu'))
# 第二個隱含層 4個神經元
simple_model.add(Dense(4, activation='relu'))
# 輸出層為1個神經元
simple_model.add(Dense(1, activation='sigmoid'))
# 編譯模型,訓練模型之前需要編譯模型
# 編譯模型的三個引數:優化器、損失函式、指標列表
simple_model.compile(optimizer='sgd', loss='mean_squared_error', metrics=['accuracy'])


class LossHistory(keras.callbacks.Callback):
    #函式開始時建立盛放loss與acc的容器
    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={}):
        #每一個batch完成後向容器裡面追加loss,acc
        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'))
        #每五秒按照當前容器裡的值來繪圖
        if int(time.time()) % 5 == 0:
            self.draw_p(self.losses['batch'], 'loss', 'train_batch')
            self.draw_p(self.accuracy['batch'], 'acc', 'train_batch')
            self.draw_p(self.val_loss['batch'], 'loss', 'val_batch')
            self.draw_p(self.val_acc['batch'], 'acc', 'val_batch')
    def on_epoch_end(self, batch, logs={}):
        # 每一個epoch完成後向容器裡面追加loss,acc
        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'))
        # 每五秒按照當前容器裡的值來繪圖
        if int(time.time()) % 5 == 0:
            self.draw_p(self.losses['epoch'], 'loss', 'train_epoch')
            self.draw_p(self.accuracy['epoch'], 'acc', 'train_epoch')
            self.draw_p(self.val_loss['epoch'], 'loss', 'val_epoch')
            self.draw_p(self.val_acc['epoch'], 'acc', 'val_epoch')
    #繪圖,這裡把每一種曲線都單獨繪圖,若想把各種曲線繪製在一張圖上的話可修改此方法
    def draw_p(self, lists, label, type):
        plt.figure()
        plt.plot(range(len(lists)), lists, 'r', label=label)
        plt.ylabel(label)
        plt.xlabel(type)
        plt.legend(loc="upper right")
        plt.savefig(type+'_'+label+'.jpg')
    #由於這裡的繪圖設定的是5s繪製一次,當訓練結束後得到的圖可能不是一個完整的訓練過程(最後一次繪圖結束,有訓練了0-5秒的時間)
    #所以這裡的方法會在整個訓練結束以後呼叫
    def end_draw(self):
        self.draw_p(self.losses['batch'], 'loss', 'train_batch')
        self.draw_p(self.accuracy['batch'], 'acc', 'train_batch')
        self.draw_p(self.val_loss['batch'], 'loss', 'val_batch')
        self.draw_p(self.val_acc['batch'], 'acc', 'val_batch')
        self.draw_p(self.losses['epoch'], 'loss', 'train_epoch')
        self.draw_p(self.accuracy['epoch'], 'acc', 'train_epoch')
        self.draw_p(self.val_loss['epoch'], 'loss', 'val_epoch')
        self.draw_p(self.val_acc['epoch'], 'acc', 'val_epoch')
logs_loss = LossHistory()

# 訓練網路 2000次
# Keras以Numpy陣列作為輸入資料和標籤的資料型別。訓練模型一般使用fit函式
simple_model.fit(x, y, epochs=20000, callbacks=[logs_loss])
# 應用模型 進行預測
y_ = simple_model.predict_classes(x[0:1])
print("[0,1,0]的分類結果:" + str(y[0]))

logs_loss.end_draw()