Keras与Tensorflow2.0入门(6)模型可视化与tensorboard的使用

1. 前言

自从Tensorflow2.0发布以后,Keras被作为默认使用和推荐使用的高层模块集成到Tensorflow中,因此,使用Tensorflow和Keras的差异就愈发的小了。因此从此时开始,我们默认使用Tensorflow2.0使用Keras。

在本章中,我们主要介绍如何使用Tensorboard来观察模型的性能以及改进方向。

首先我们先回顾一下之前在Keras中如何可视化模型,主要有两条路径,使用Plot_model和History。

1.1 Plot_model

Plot_model主要是用来绘制模型的样子,可以使得更加直观的观察模型是不是你预想的样子,当然你也可以使用Model.summary()来获取模型的各层信息,但是没有Plot_model直观。其使用方法如下。

from keras.utils import plot_model
plot_model(model, to_file='model.png')

其中plot_model 有 4 个可选参数:

show_shapes (默认为 False) 控制是否在图中输出各层的尺寸。
show_layer_names (默认为 True) 控制是否在图中显示每一层的名字。
expand_dim(默认为 False)控制是否将嵌套模型扩展为图形中的聚类。
dpi(默认为 96)控制图像 dpi。

当然也可以自己渲染,获得更加清晰的图像质量。

from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
SVG(model_to_dot(model).create(prog='dot', format='svg'))

但是,使用Plot_model可能会存在一些问题,这个问题多是由版本不同造成的。

1.2 History

History则是模型训练时的历史记录,我们更常见的时候是自己编写的层会没有History而报错。具体的获取形式如下:

import matplotlib.pyplot as plt

history = model.fit(x, y, validation_split=0.25, epochs=50, batch_size=16, verbose=1)

# 绘制训练 & 验证的准确率值
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

# 绘制训练 & 验证的损失值
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()

1.3 自定义评估函数

根据Keras手册中的描述,可以使用的预置函数如下:

binary_accuracy(y_true, y_pred) # 二元正确率
categorical_accuracy(y_true, y_pred) # 多元正确率
sparse_categorical_accuracy(y_true, y_pred) #稀疏分类正确率
top_k_categorical_accuracy(y_true, y_pred, k=5) # top k个分类正确率
sparse_top_k_categorical_accuracy(y_true, y_pred, k=5) # 稀疏top k个分类正确率

也可以使用mae或者acc调用预置函数,如果使用其他评估函数需要自己定义,下面为自定义的PRF函数。

def precision(y_true, y_pred):
    # Calculates the precision
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision


def recall(y_true, y_pred):
    # Calculates the recall
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall

def fbeta_score(y_true, y_pred, beta=1):
    # Calculates the F score, the weighted harmonic mean of precision and recall.

    if beta < 0:
        raise ValueError('The lowest choosable beta is zero (only precision).')
        
    # If there are no true positives, fix the F score at 0 like sklearn.
    if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:
        return 0

    p = precision(y_true, y_pred)
    r = recall(y_true, y_pred)
    bb = beta ** 2
    fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
    return fbeta_score

def fmeasure(y_true, y_pred):
    # Calculates the f-measure, the harmonic mean of precision and recall.
    return fbeta_score(y_true, y_pred, beta=1)
def auc(y_true, y_pred):
    ptas = tf.stack([binary_PTA(y_true,y_pred,k) for k in np.linspace(0, 1, 1000)],axis=0)
    pfas = tf.stack([binary_PFA(y_true,y_pred,k) for k in np.linspace(0, 1, 1000)],axis=0)
    pfas = tf.concat([tf.ones((1,)) ,pfas],axis=0)
    binSizes = -(pfas[1:]-pfas[:-1])
    s = ptas*binSizes
    return K.sum(s, axis=0)

model.compile( 
    optimizer=Adam(), 
    loss='binary_crossentropy',
    metrics = ['accuracy',  fmeasure, recall, precision])

在进行测试时,加载模型时需要指定评估方式,例如:

model_name = 'test_calssification_model.h5'
model_dfcw = load_model(model_name,
                        custom_objects={'focal_loss': focal_loss,'fbeta_score':fbeta_score})

另外,也可以使用回调函数在每个Epoch后计算:

PRF值的计算方法

import numpy as np
from keras.callbacks import Callback
from sklearn.metrics import confusion_matrix, f1_score, precision_score, recall_score
class Metrics(Callback):
  def on_train_begin(self, logs={}):
    self.val_f1s = []
    self.val_recalls = []
    self.val_precisions = []

  def on_epoch_end(self, epoch, logs={}):
    val_predict=(np.asarray(self.model.predict(self.model.validation_data[0]))).round()
    val_targ = self.model.validation_data[1]
    _val_f1 = f1_score(val_targ, val_predict)
    _val_recall = recall_score(val_targ, val_predict)
    _val_precision = precision_score(va_targ, val)
    self.val_f1s.append(_val_f1)
    self.val_recalls.append(_val_recall)
    self.val_precisions.append(_val_precision)
    print('-val_f1: %.4f --val_precision: %.4f --val_recall: %.4f'%(_val_f1, _val_precision, _val_recall))
    return

metrics = Metrics()
#需要查看训练过程中的评价函数值时,可以直接输出
print(metrics.val_f1s)
#定义好模型后,使用新的评价函数来训练模型:
model.fit(training_data, training_target, 
          validation_data=(validation_data, validation_target),
          np_epoch=10, batch_size=64, callbacks =[metrics])

AUC的计算方法

from sklearn.metrics import roc_auc_score

class roc_callback(keras.callbacks.Callback):
    def __init__(self,training_data, validation_data):
        
        self.x = training_data[0]
        self.y = training_data[1]
        self.x_val = validation_data[0]
        self.y_val = validation_data[1]
        
    
    def on_train_begin(self, logs={}):
        return
 
    def on_train_end(self, logs={}):
        return
 
    def on_epoch_begin(self, epoch, logs={}):
        return
 
    def on_epoch_end(self, epoch, logs={}):        
        y_pred = self.model.predict(self.x)
        roc = roc_auc_score(self.y, y_pred)      
        
        y_pred_val = self.model.predict(self.x_val)
        roc_val = roc_auc_score(self.y_val, y_pred_val)      
        
        print('\rroc-auc: %s - roc-auc_val: %s' % (str(round(roc,4)),str(round(roc_val,4))),end=100*' '+'\n')
        return
 
    def on_batch_begin(self, batch, logs={}):
        return
 
    def on_batch_end(self, batch, logs={}):
        return   
model.fit(X_train, y_train, epochs=10, batch_size=4, 
          callbacks = [roc_callback(training_data=[X_train, y_train], validation_data=[X_test, y_test])] )

2. tensorboard

2.1 tensorboard是什么

根据W3Cschool的定义:

tf.keras.callbacks.TensorBoard函数
类 TensorBoard
继承自:Callback
定义在:tensorflow/python/keras/callbacks.py。
Tensorboard基本可视化。
TensorBoard是由Tensorflow提供的一个可视化工具。 
此回调为TensorBoard编写日志,该日志允许您可视化训练和测试度量的动态图形,也可以可视化模型中不同层的激活直方图。
如果您已经使用pip安装了TensorFlow,那么您应该能够从命令行启动TensorBoard:
tensorboard --logdir=/full_path_to_your_logs

这个工具在Tensorflow中是非常常用的其参数解释如下:

  • log_dir:保存TensorBoard要解析的日志文件的目录的路径。
  • histogram_freq:频率(在epoch中),计算模型层的激活和权重直方图。如果设置为0,则不会计算直方图。必须为直方图可视化指定验证数据(或拆分)。
  • write_graph:是否在TensorBoard中可视化图像。当write_graph设置为True时,日志文件可能会变得非常大。
  • write_grads:是否在TensorBoard中可视化渐变直方图。 histogram_freq必须大于0。
  • batch_size:用以直方图计算的传入神经元网络输入批的大小。
  • write_images:是否在TensorBoard中编写模型权重以显示为图像。
  • embeddings_freq:将保存所选嵌入层的频率(在epoch中)。如果设置为0,则不会计算嵌入。要在TensorBoard的嵌入选项卡中显示的数据必须作为embeddings_data传递。
  • embeddings_layer_names:要关注的层名称列表。如果为None或空列表,则将监测所有嵌入层。
  • embeddings_metadata:将层名称映射到文件名的字典,其中保存了此嵌入层的元数据。如果相同的元数据文件用于所有嵌入层,则可以传递字符串。
  • embeddings_data:要嵌入在embeddings_layer_names指定的层的数据。Numpy数组(如果模型有单个输入)或Numpy数组列表(如果模型有多个输入)。
  • update_freq:‘batch’或’epoch’或整数。使用’batch’时,在每个batch后将损失和指标写入TensorBoard。这同样适用’epoch’。如果使用整数,比方说1000,回调将会在每1000个样本后将指标和损失写入TensorBoard。请注意,过于频繁地写入TensorBoard会降低您的训练速度。
    可能引发的异常:
  • ValueError:如果设置了histogram_freq且未提供验证数据。

2.2 如何使用Tensorboard

使用方法如下:

from tensorflow.keras.callbacks import TensorBoard
#设定格式化模型名称,以时间戳作为标记
model_name = "模型名-{}".format(int(time.time()))
#设定存储位置,每个模型不一样的路径
tensorboard = TensorBoard(log_dir='logs/{}'.format(model_name))
#使用它
model.fit(X, y, batch_size =32, epochs=10, validation_split=0.1, callbacks=[tensorboard])

鉴于此,我们推荐的参数如下:

TensorBoardcallback = keras.callbacks.TensorBoard(
    log_dir='logs/{}'.format(model_name),
    histogram_freq=1, batch_size=32,
    write_graph=True, write_grads=False, write_images=True,
    embeddings_freq=0, embeddings_layer_names=None,
    embeddings_metadata=None, embeddings_data=None, update_freq=500
)

想查看的时候,就可以新开一个终端,输入:

tensorboard --logdir=/full_path_to_your_logs 

之后打开终端给出的网址即可,打开后的样子如《使用Tensorboard分析模型》所示,这样就可以进一步《使用Tensorboard优化模型》。

最后,在使用Tensorboard时,可能会有一些坑,这里提供一些参考

2.3 继续训练与Checkpoint在Tensorboard中的显示

当我们训练完成(例如10轮),使用Checkpoint保存过模型,在Tensorboard中分析过结果后,想再次训练时,而且想让下一次训练模型(11-20轮)性能不要和之前的重叠,而是保持续接原有的性能曲线时,这就需要Initial_epoch,具体使用代码如下。

import numpy as np
from keras.models import Model
from keras.layers import Input, Dense
from keras.callbacks import TensorBoard

test = np.arange(2000.).reshape((-1, 1))

x = Input(shape=(1,))
y = Dense(1)(x)
model = Model(inputs=x, outputs=y)
model.compile(optimizer='Adam',
              loss='logcosh',
              metrics=['accuracy'])

# 第一次训练
first_epoch = 20
model.fit(x=test, y=test, epochs=first_epoch,
          callbacks=[TensorBoard()])
json_string = model.to_json()
model.save_weights('./logs/my_model_weights.h5') #保存的模型位置
del model

# 重新训练
from keras.models import model_from_json
from keras.optimizers import SGD

new_model = model_from_json(json_string)
new_model.load_weights('./logs/my_model_weights.h5') #载入模型
new_model.compile(optimizer=SGD(lr=1e-7),
              loss='mean_squared_error',
              metrics=['accuracy'])

second_epoch = 10
new_model.fit(x=test, y=test,
              epochs=first_epoch+second_epoch,
              callbacks=[TensorBoard()],
              initial_epoch=first_epoch) #关键的初始化epoch数

它可以让我们两次训练的模型性能曲线连在一起。

另外,这里附上使用《Checkpoint的几种方法》。

发布了232 篇原创文章 · 获赞 547 · 访问量 51万+

猜你喜欢

转载自blog.csdn.net/qq_35082030/article/details/94379395
今日推荐