虽然tf官方但愿用户把 train , val 程序分开写,但实际开发中,明显写在一块儿比较简单舒服,但在保存数据到 summary 时, val 部分和 train 部分不太同样,会有一些问题,下面讨论如何在这种状况下记录 train/val 的 summary 。网络
假设训练时的主要代码结构以下:spa
losssummary = ...
othersummary = ...
trainsummaries = tf.summary.merge([losssummary, othersummary])
for i in range(self.batchnum):
batching data...
... ... step ... trainsummaryresults = sess.run(... , trainsummaries)
trainfilewriter.addsummary(trainsummaryresults) if step % self.saveinter == 0:
... # save checkpoint if step % self.dispinter == 0:
... # display training process if step % self.testinter == 0:
... # run model on test data
保存 train 部分的 summary 很简单,tf的示例代码也给了不少,先利用 sess.run 计算出 trainsummaryresults ,即当前 batch 的统计数据,而后保存到文件scala
但在 val 部分时,通常都在全部验证数据上获取 loss , accuracy 等 summary 数据,再保存到文件。这样只有两种方法:设计
1. val 部分的 batchsize 改成验证集大小
2. batchsize 不变,对全部 batch 上获取的 loss , accuracy 计算平均code
第一种方法存在的问题是,若是验证集数据较大, batchsize 会设置的较大,可能会引发内存or显存溢出,这个无法解决。blog
第二种方法存在的问题是,无法按照train部分的作法作,由于要的是整个验证数据的平均值,而不是每一个 batch 的值,这个有办法解决。内存
在设计模型结构的时候,不管是 train 仍是 val ,网络结构都是同样的,每次只能计算一个 batch 的 loss , accuracy ,无法单独为验证集修改。因而我想到了以下投机取巧的方法:先利用循环计算验证集每一个 batch 的 loss , accuracy ,进行累加,记为 averageloss 和 averageaccuracy ,而后进行以下操做:开发
testsummaries = tf.Summary() lossval = testsummaries.value.add() lossval.tag = 'loss' lossval.simplevalue = averageloss / batchnum accval = testsummaries.value.add() accval.tag = 'accuracy' accval.simplevalue = averageaccuracy / batchnum testfilewriter.addsummary(testsummaries, step)
其实就是本身建立一个 test_summaries ,把须要的东西填进去,模仿利用 sess.run 生成的 train_summary_results ,再保存到文件。你们若是感兴趣能够把 train_summary_results 打印出来,其实就是这么个结构。目前我只保存过 scalar ,可是其余值应该也能够这么保存。it