在深度学习训练模型的时候,用Tensorboard中画图有时候想要在一张图中同时画出训练集的准确率曲线和验证集的准确率曲线。
我通过多次实验,碰了不少坑,在这里做个小小的总结。
注意:以下代码适用于TensorFlow1.X版本,不保证2.0版本
在自己训练的模型代码中计算accuracy和loss的代码段后增加以下两句:
'''记录loss值标量信息'''
tf.summary.scalar("loss", self.loss)
'''记录accuracy值标量信息'''
tf.summary.scalar("accuracy", self.acc)
然后在训练的train函数里面,加入Tensorboard需要的代码:
'''1.tensorboard的记录地址'''
tensorboard_tradir = 'tensorboard/trainlog'
if not os.path.exists(tensorboard_tradir):
os.makedirs(tensorboard_tradir)
'''2.merge_all 可以将所有summary全部保存到磁盘,以便tensorboard显示'''
merged_summary_train = tf.summary.merge_all()
'''3.FileWriter()指定一个文件来保存图,于此配套的是add_summary()方法'''
writer_train = tf.summary.FileWriter(tensorboard_tradir)
'''4.这里的graph图是用来看自己训练模型的结构的,在测试集里面不需要'''
writer_train.add_graph(session.graph)
·······(省略与tensorboard无关的代码,如创建Session等)··········
'''5.在session中run之前创建的merge_all,这个就是tensorboard来源的数据'''
train_accuracy,train_loss,train_summaries = session.run(model.acc,model.loss,merged_summary_train)
'''6.将这个数据,记录在FileWriter中,同时加上横轴信息。'''
writer_train.add_summary(train_summaries, total_batch)
以上就是在Tensorboard中画出训练集的accuracy和loss的全部必需的代码。
如果这些代码放在正确的位置的话,通过训练得到TensorBoard的log文件,显示在Tensorboard中,会得到下面的图示
沿用上面的代码,对比的位置不同。
画验证集是不需要加tf.summary.scalar
的。
'''不同点1:以下的的代码,与训练集一样,只要copy,并加以复制。'''
tensorboard_tradir = 'tensorboard/trainlog'
tensorboard_valdir = 'tensorboard/vallog'
if not os.path.exists(tensorboard_tradir):
os.makedirs(tensorboard_tradir)
if not os.path.exists(tensorboard_valdir):
os.makedirs(tensorboard_valdir)
merged_summary_train = tf.summary.merge_all()
merged_summary_val = tf.summary.merge_all()
writer_train = tf.summary.FileWriter(tensorboard_tradir)
writer_val = tf.summary.FileWriter(tensorboard_valdir)
'''不同点2.在测试集里面不需要graph'''
writer_train.add_graph(session.graph)
'''以下代码与上面一样,省略'''
画出测试集曲线,最重要的点在于其merge_all() run的地点不在与train的位置不一样,而是在模型的evaluate函数内
'''evaluate函数'''
def evaluate(sess,dev_data,writer_val,merged_summary_val,total_batch):
'''批量的形式计算验证集或测试集上数据的平均loss,平均accuracy'''
data_len = 0
total_loss = 0.0
total_acc = 0.0
for batch_ids,batch_mask,batch_segment,batch_label in batch_iter(dev_data,config.batch_size):
batch_len = len(batch_ids)
data_len+=batch_len
feed_dict = feed_data(batch_ids,batch_mask,batch_segment,batch_label, 1.0)
'''关键代码1'''
if merged_summary_val is not None:
val_summaries,loss, acc = sess.run([merged_summary_val,model.loss, model.acc], feed_dict=feed_dict)
else:
loss, acc = sess.run([model.loss, model.acc], feed_dict=feed_dict)
total_loss += loss * batch_len
total_acc += acc * batch_len
'''关键代码2'''
if writer_val is not None:
writer_val.add_summary(val_summaries, total_batch)
return total_loss/data_len, total_acc/data_len
在上面的evaluate代码中,只需要关注我贴的关键代码1和2,其余的都是分batch进行验证的代码。
代码1的功能是:把验证数据记录在val_summaries中。
代码2的功能是:把val_summaries里的数据写在writer_val中。
思想和训练集的时候是一样的
因此,会得到两个log文件,通过tensorboard对log文件进行显示,会得到类似下面的图。
Acc图
loss图
需要注意的一个点,在evaluate函数中,有for循环,如果在for循环内把数据记录到FileWriter里面的话,会让验证集的点产生很大的震荡,因此要把写入FileWriter的操作放在for循环之外。