自从Tensorflow2.0发布以后,Keras被作为默认使用和推荐使用的高层模块集成到Tensorflow中,因此,使用Tensorflow和Keras的差异就愈发的小了。因此从此时开始,我们默认使用Tensorflow2.0使用Keras。
在本章中,我们主要介绍如何使用Tensorboard来观察模型的性能以及改进方向。
首先我们先回顾一下之前在Keras中如何可视化模型,主要有两条路径,使用Plot_model和History。
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可能会存在一些问题,这个问题多是由版本不同造成的。
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()
根据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后计算:
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])
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])] )
根据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中是非常常用的其参数解释如下:
使用方法如下:
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时,可能会有一些坑,这里提供一些参考。
当我们训练完成(例如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的几种方法》。