通俗易懂之Tensorflow summary類 & 初識tensorboard


前面學習的cifar10項目雖小,但卻五臟俱全。全面理解該項目非常有利於進一步的學習和提高,也是走向更大型項目的必由之路。因此,summary依然要從cifar10項目說起,通俗易懂的理解並運用summary是本篇博客的關鍵。

先不管三七二十一,列出cifar10中定義模型和訓練模型中的summary的代碼:

# Display the training images in the visualizer.
  tf.summary.image('images', images)
def _activation_summary(x):
  """Helper to create summaries for activations.

  Creates a summary that provides a histogram of activations.
  Creates a summary that measure the sparsity of activations.

  Args:
    x: Tensor
  Returns:
    nothing
  """
  # Remove 'tower_[0-9]/' from the name in case this is a multi-GPU training
  # session. This helps the clarity of presentation on tensorboard.
  tensor_name = re.sub('%s_[0-9]*/' % TOWER_NAME, '', x.op.name)
  tf.summary.histogram(tensor_name + '/activations', x)
  tf.summary.scalar(tensor_name + '/sparsity', tf.nn.zero_fraction(x))
_activation_summary(conv1)
_activation_summary(conv2)
_activation_summary(local3)
_activation_summary(local4)
_activation_summary(softmax_linear)
def _add_loss_summaries(total_loss):
  """Add summaries for losses in CIFAR-10 model.

  Generates moving average for all losses and associated summaries for
  visualizing the performance of the network.

  Args:
    total_loss: Total loss from loss().
  Returns:
    loss_averages_op: op for generating moving averages of losses.
  """
  # Compute the moving average of all individual losses and the total loss.
  loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg')
  losses = tf.get_collection('losses')
  loss_averages_op = loss_averages.apply(losses + [total_loss])

  # Attach a scalar summary to all individual losses and the total loss; do the
  # same for the averaged version of the losses.
  for l in losses + [total_loss]:
    # Name each loss as '(raw)' and name the moving average version of the loss
    # as the original loss name.
    tf.summary.scalar(l.op.name +' (raw)', l)
    tf.summary.scalar(l.op.name, loss_averages.average(l))

  return loss_averages_op
tf.summary.scalar('learning_rate', lr)
# Add histograms for trainable variables.
  for var in tf.trainable_variables():
    tf.summary.histogram(var.op.name, var)
# Add histograms for gradients.
  for grad, var in grads:
    if grad is not None:
      tf.summary.histogram(var.op.name + '/gradients', grad)
# Build the summary operation based on the TF collection of Summaries.
summary_op = tf.summary.merge_all()

summary_writer = tf.summary.FileWriter(FLAGS.train_dir, sess.graph)

if step % 100 == 0: summary_str = sess.run(summary_op) summary_writer.add_summary(summary_str, step)

通過觀察,聰明的大家不禁發現以下問題:

  1.  函數_activation_summary可以為每一層激活值創建summary,而無任何返回值,既然沒有返回值,也就說明沒有數據的流動,也就是並非有意義的節點;
  2. summary類包含histogram和scalar兩種類型,而且似乎這兩種類型是有嚴格划分的:為什么這么說呢?代碼中可以看到,學習率就是scalar類型,梯度值就是histogram類型;
  3. summary類在cifar10項目中普遍存在,包含學習率、梯度值、激活值、變量、loss等,而這些似乎都是在深度學習過程中,我們比較關心的量,這似乎讓人無限遐想。

帶着這些發現,我們又不禁產生下列疑問:

  1. summary如果都不是節點,那它在會話中起到什么作用,又執行了什么操作?
  2. summary類包含的數據類型有哪些,它們之間是如何划分的?
  3. 我們可以為哪些量創建summary,除了上述函數,summary類中還包含哪些常見的函數?

帶着這些問題,打開官方的tutorial、API教程,這里是中文版。純粹點說,summary和TensorBoard有關,也就是和tf的可視化有關。

上面列出的代碼實際上給我們列出了一個過程,就是使用summary或者可視化tensorboard的過程,具體來說:

  1. 為你需要可視化記錄的量創建summary,summary其實就相當於一個監測器,你讓它監測誰就監測誰,附加在你想監測的量上,如果沒有它,也就無從談起tensorboard可視化,根本不知道可視化什么量;
  2. 收集匯總圖中所有創建的summary,如果不匯總,相互之間就沒有關聯,需要一個一個在會話中運行,麻煩費事;
  3. 把收集的數據寫入指定的文件,summary本身並不能可視化,保存數據則是為了tensorboard的可視化;

再從表面上來看,訓練cifar10模型,得到的文件問下:

歸納一下就是:

  • checkpoint文件。打開該文件,內容如下:
model_checkpoint_path: "model.ckpt-1000"
all_model_checkpoint_paths: "model.ckpt-0"
all_model_checkpoint_paths: "model.ckpt-1000"

可見,該文件是記錄中間保存模型的位置的,第一行表明最新的模型,其他行是保存的其它模型,隨迭代次數從低到高排列。

  • tfevents文件。該文件是保存的summary日志文件,比如cifar10項目是每隔100次進行更新,代碼如下:
if step % 100 == 0:
        summary_str = sess.run(summary_op)
        summary_writer.add_summary(summary_str, step)

里面就記錄着整個匯總summary監測的數據以及模型圖。這個文件是要在tensorboard可視化中要用到的。

  • model data文件。該文件保存了所有訓練變量所在迭代次數時的值。比如上面的0和1000次。
  • model index文件。該文件保存了所有訓練變量的名稱。
  • model meta文件。該文件保存在模型圖的結構。

上述三個model文件data和index是結合在一起確定變量的,meta是模型網絡的結構,這和變量的加載聯系起來,就會發現,加載時data和index是必須的,因此可以只加載變量不加載圖結構,或者都加載,下面的例子是cifar10_eval.py中的例子,顯然這是屬於第一種,只加載了變量沒有加載圖結構而使用了默認圖。

tf.app.flags.DEFINE_string('checkpoint_dir', 'cifar10_train/',
                           """Directory where to read model checkpoints.""")

def eval_once(saver, summary_writer, top_k_op, summary_op):
  """Run Eval once.

  Args:
    saver: Saver.
    summary_writer: Summary writer.
    top_k_op: Top K op.
    summary_op: Summary op.
  """
  with tf.Session() as sess:
    ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
    if ckpt and ckpt.model_checkpoint_path:
      # Restores from checkpoint
      saver.restore(sess, ckpt.model_checkpoint_path)
      # Assuming model_checkpoint_path looks something like:
      #   /my-favorite-path/cifar10_train/model.ckpt-0,
      # extract global_step from it.
      global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
    else:
      print('No checkpoint file found')
      return
def evaluate():
  """Eval CIFAR-10 for a number of steps."""
  with tf.Graph().as_default():

也可以都加載,例如:

tf.app.flags.DEFINE_string('checkpoint_dir', 'cifar10_train/',
                           """Directory where to read model checkpoints.""")
ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
saver = tf.train.import_meta_graph(ckpt.model_checkpoint_path +'.meta')
with tf.Session() as sess:
    saver.restore(sess,ckpt.model_checkpoint_path)

那如何用summary保存的訓練日志啟動tensorboard呢?

只需要tensorboard --logdir=cifar10_train,注意cifar10_train是日志所在的文件夾,同時請在cifar10_train所在目錄下執行該命令,可得:

 請用IE瀏覽器,或者其它高級的瀏覽器(chrome、Firefox)打開圖片中出現的網址即可:http://DESKTOP-HMQ55PS:6006

 

到此為止,在表面上對summary類有了一定的認識,那接下來可以回答上述的三個疑問。

  • summary如果都不是節點,那它在會話中起到什么作用,又執行了什么操作?

:summary類是tensorboard可視化訓練過程和圖結構的基礎,它相當於一個監測器,在哪加就說明想要監測哪,summary類沒有執行任何實質性操作,tf就是這樣,如果不建立會話啟動的話,一切都是靜態的,當然,summary類只是監測動態性,因此無實質性操作,只能說不同的函數有不同的功能和目的,這將在第三問探討。

  • summary類包含的數據類型有哪些,它們之間是如何划分的?

:從tensorboard可視化的截圖中可以發現,summary類包含的數據類型有:scalar、image、graph、histogram、audio。其中前四種在本項目中都出現了,只有audio類型沒有出現。那它們是如何划分的呢?顯然是按照類型划分的......scalar表示標量,image表示圖片,graph表示網絡節點模型圖,histogram表示變量的直方圖,audio表示音頻數據,具體內容參考上述代碼,也很容易明白,scalar通常表示單一的量,例如學習率、loss、AP等,而histogram表示的是統計信息,比如梯度、激活值等。graph通過summary_writer = tf.summary.FileWriter(FLAGS.train_dir, sess.graph)代碼中的sess.graph得到。注意除此之外,tensorboard還有兩個統計信息,一個是distributions,統計權值、偏置和梯度的分布,另一個是projector,包含T-SNE和PCA。

  • 我們可以為哪些量創建summary,除了上述函數,summary類中還包含哪些常見的函數?

 答:通常意義上只要符合上述5類的都可以創建summary,但是常用的有意義的量就上述常見的那些。summary類中常見的函數上面寫得也很全了,但是問題的焦點是很多網上的博客包括一些中文社區都沒有及時對最新版本的API內容進行更新,無意之間卻帶來了誤導,因此,我們必須看官方提供的API,請看這里

大致總結一下就是:

  1. tf.summary.scalar(name, tensor, collections=None,  family=None) tensor為單一的標量。
  2. tf.summary.histogram(name, values, collections=None,  family=None) values為任意shape的數字型tensor。
  3. tf.summary.image(name, tensor, max_outputs=3, collections=None,  family=None) tensor的shape為[batch_size, height, width, channels],其中channels=1表示灰度圖,3表示RGB,4表示RGBA。注意max_outputs默認為3表示每輪默認顯示三張圖。
  4. tf.summary.audio( name, tensor, sample_rate, max_outputs=3, collections=None,  family=None) tensor為3D shape [batch_size, frames, channels],或者2D shape [batch_size, frames];sample_rate表示聲音類型信號tensor的采樣率,大小在[-1.0,1.0]之間。
  5. tf.summary.text(name, tensor, collections=None) 將文本數據轉換為string類型的tensor。
  6. tf.summary.merge(inputs, collections=None, name=None) 將inputs里面的summary匯集在一起,其中inputs為string類型tensor的列表。
  7. tf.summary.merge_all( key=tf.GraphKeys.SUMMARIES, scope=None) 把所有的summary匯集在一起。
  8. tf.summary.FileWriter(logdir, sess.graph) 把summary protocol buffers 寫進 tfevents文件里。
  9. tf.summary.tensor_summary( name, tensor, summary_description=None, collections=None, summary_metadata=None, family=None, display_name=None) 將任意shape和類型的tensor序列化,並返回一個string類型的tensor。

總結:通過上面的試驗,其實tensorboard是一個日志展示系統,因此首先用戶需要對各種類型的單個數據提出監測(記錄日志),並在session中運算圖時,將各種類型的數據匯總並輸出到日志文件中。而后啟動tensorboard服務,讀取這些記錄的日志文件,開啟6006端口在Web上實時監測用戶匯總的數據。

人人都說,創作需要靈感,甚至需要一些情愫,感動的、真誠的、又或是善意的,這就是生活,如果我們能把工作和學習當作是創作一樣,又有什么遺憾呢?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM