Pytorch中使用TensorBoard詳情

本文記錄瞭如何在Pytorch中使用Tensorboard(主要是為瞭備忘)

前言

雖然我本身就會用TensorBoard,但是因為TensorBoard隻有在寫訓練代碼的框架的時候才會寫,因此實際上寫的頻率的還是很低的,所以我每次要寫訓練代碼、使用TensorBoard的時候都需要看自己之前寫的代碼,或者查一下別人寫的博客。而且不少博客寫的都是一鱗半爪的,不少用法都要查很多博客,久而久之就會覺得很煩。而且很多技巧隨著時間的流逝也逐漸的忘記。

因此為瞭方便以後自己的查詢(備忘),同時也是能夠留下一個不錯的教程,因此決定自己寫一個比較全面的TensorBoard的教程。

一、 Introduction to TensorBoard

在煉丹的時候,經常需要追蹤模型在訓練過程中性能的變化,例如:Regression任務中的MSE、分類任務中的準確率、生成(圖片)任務中圖片的生成質量、此外還有合成語音的質量……

大體上來說,所有需要追蹤的數據包括:標量(scalar)、圖像(image)、統計圖(diagram)、視頻(video)、音頻(audio)、文本(text)、Embedding等等

除瞭有大量的數據需要追蹤外,我們還需要很好的把這些數據顯示出來,即數據的寫入和顯示(讀取)要有異步IO,有的時候服務器在學校的機房托管,因此還需要能夠通過內網提供可視化……

因此,在種種需求之下,使用一個網頁程序來幫助我們進行數據的追蹤就成瞭一個很好的解決方案。具體來說,網頁程序實現瞭前後端的分離,後端隻需要專註於數據的記錄,而前端專註於數據的顯示。此外,網頁程序可以進一步擴展,提供網絡服務。

因此,就有瞭TensorBoard這個網頁程序實現瞭我們上面的需求。TensorBoard最早是TensorFlow中的模塊,不過現在經過Pytorch團隊的努力,TensorBoard已經集成到瞭Pytorch中。

TensorBoard的教程主要分為兩部分,一部分是如何使用TensorBoard(即在訓練過程中添加數據,然後在瀏覽器中監視訓練的這整個pipeline)的教程,另外一部分是TensorBoard如何添加不同種類數據(即TensorBoard的API)的教程

二、TensoBoard Pipeline

上面說道,TensorBoard是分為前段顯示和後端數據記錄的,因此其Pipeline也分為兩步:

第一步:後端數據記錄第二步:前段查看數據

三、後端數據記錄

類似於FlaskDjango中把後端程序(服務器)被抽象為瞭一個類,然而這個類中提供瞭方法來開啟和關閉服務,TensorBoard中也是把後端服務器抽象成瞭一個類:SummaryWriter,不過不同的是,TensorBoard中的SummaryWriter類在被聲明後就開啟瞭對應的服務,直到我們使用瞭SummaryWriter關閉服務的API。

此外,還有一個不同的之處在於,TensorBoard的前段數據顯示和後端數據記錄是異步I/O的,即後端程序(SummaryWriter類的實例)將數據寫入到一個文件中,而前端程序讀取文件中的數據來進行顯示。因此後端所謂的服務指的就是數據的記錄,而非提供前端的顯示。數據記錄的實現方式即通過SummaryWriter類中的方法

然後在開啟瞭後端程序的服務器之後,我們就可以通過各種API來添加數據瞭

導入包:

我們首先導入包

import torch
from torch.utils.tensorboard import SummaryWriter

1. SummaryWriter類

SummaryWriter聲明之後就會開啟後端數據記錄的服務,因此在實例化該類的時候我們就需要保存數據的位置。聲明保存數據的位置有好幾種方式

SummaryWriter的簽名如下:

class torch.utils.tensorboard.writer.SummaryWriter(log_dir=None, comment='', purge_step=None, max_queue=10, flush_secs=120, filename_suffix='')

其中:

  • log_dir (str):指定瞭數據保存的文件夾的位置,如果該文件夾不存在則會創建一個出來。如果沒有指定的話,默認的保存的文件夾是./runs/現在的時間_主機名,例如:Feb04_22-42-47_Alienware,因此每次運行之後都會創建一個新的文件夾。在寫論文的時候我們會涉及一系列實驗,從不同的角度來說明一些問題,例如我們的假設是否正確、模型性能是否更好……因此最好不要用默認的實現來直接作為存放數據的文件夾,而是使用具有含義的二級結構,例如:runs/exp1。這樣的話,所有的實驗1的數據都在這個文件夾下,這樣我們就可以方便的進行比較。
  • comment (string):給默認的log_dir添加的後綴,如果我們已經指定瞭log_dir具體的值,那麼這個參數就不會有任何的效果
  • purge_step (int):TensorBoard在記錄數據的時候有可能會崩潰,例如在某一個epoch中,進行到第 T + X T+X T+X個step的時候由於各種原因(內存溢出)導致崩潰,那麼當服務重啟之後,就會從 T T T個step重新開始將數據寫入文件,而中間的 X X X,即purge_step指定的step內的數據都被被丟棄。
  • max_queue (int):在記錄數據的時候,在內存中開的隊列的長度,當隊列慢瞭之後就會把數據寫入磁盤(文件)中。
  • flush_secs (int):以秒為單位的寫入磁盤的間隔,默認是120秒,即兩分鐘。
  • filename_suffix (string):添加到log_dir中每個文件的後綴。更多文件名稱設置要參考tensorboard.summary.writer.event_file_writer.EventFileWriter類。

因此,一個成熟的數據記錄方式就是在runs文件夾下按照一定的意義來劃分二級文件夾,例如網絡結構1網絡結構2實驗1實驗2等等。

2. 添加數據

想後端服務程序添加數據使用的是SummaryWriter類中的一系列方法,這些方法都以add_開頭,例如:add_scalaradd_scalarsadd_image……具體來說,所有的方法有:

import pprint
pprint.pprint([i for i in SummaryWriter.__dict__.keys() if i.startwith("add_")])

add_hparams,add_scalar,add_scalars,add_histogram,add_histogram_raw,add_image,add_images,add_image_with_boxes,add_figure,add_video,add_audio,add_text,add_onnx_graph,add_graph,add_embedding,add_pr_curve,add_pr_curve_raw,add_custom_scalars_multilinechart,add_custom_scalars_marginchart,add_custom_scalars,add_mesh

後面在第二部分會詳細的講解每個方法,這裡先講共性。

每個方法根據需要添加的數據的不同,方法中具體的參數也不同,但是所有的方法終歸都是要添加數據的,因此會存在相同的參數。具體來說,相同的參數包括:

  • tag (str):用於給數據進行分類的標簽,標簽中可以包含父級和子級標簽。例如給訓練的loss以loss/train的tag,而給驗證以loss/val的tag,這樣的話,最終的效果就是訓練的loss和驗證的loss都被分到瞭loss這個父級標簽下。而trainval則是具體用於區分兩個參數的標識符(identifier)。例如我們現在有兩個tag,cos/densecos/sparse,那麼最終展示下來的效果是這樣的。此外,隻支持二級標簽

  • globa_step (int):首先,每個epoch中我們都會更新固定的step。因此,在一個數據被加入的時候,有兩種step,第一種step是數據被加入時當前epoch已經進行瞭多少個step,第二種step是數據被加入時候,累計(包括之前的epoch)已經進行瞭多少個step。而考慮到我們在繪圖的時候往往是需要觀察所有的step下的數據的變化,因此global_step指的就是當前數據被加入的時候已經計算瞭多少個step。計算global_step的步驟很簡單,就是 g l o b a l _ s t e p = e p o c h ∗ l e n ( d a t a l o a d e r ) + c u r r e n t _ s t e p global\_step=epoch * len(dataloader) + current\_step global_step=epoch∗len(dataloader)+current_step
  • wlltime (int):從SummaryWriter實例化開始到當前數據被加入時候所經歷時間(以秒計算),默認是使用time.time()來自動計算的,當然我們也可以指定這個參數來進行修改。這個參數一般不改

以添加標量(add_scalar)為例,演示一下添加數據的方法的用法。其他的方法第二部分會講

writer = SummaryWriter()
for epoch in range(n_epoch := 10):
    for step in range(total_step := 100):
        # 訓練代碼讀取數據來進行顯示。
        # ...
        # ...

        # 計算 loss
        loss = np.sin(step * 0.01)
        # 添加標量
        writer.add_scalar(tag="loss/train", scalar_value=loss,
                          global_step=epoch * total_step + step)

然後可以看到的效果如下:

3. 關閉SummaryWriter

我們剛才說過,SummaryWriter這樣的後端程序在被實例化出來就自動開啟瞭數據記錄的服務,而我們在完成瞭所有的數據記錄隻有,需要關閉服務。

關閉服務很簡單,就是直接調用close方法即可

writer.close()

4. Summary

最終,總結一下整個後端數據記錄的流程,其實就三步:

實例化SummaryWriter類,同時指定數據保存的文件夾利用SummaryWriter類提供的方法,添加不同類型的的數據關閉SummaryWriter類,中止服務

四、前端顯示數據

因為TensorBoard是異步I/O的網頁服務程序,因此後端程序在把數據寫入到文件的時候,前端程序可以讀取數據來進行顯示。

具體來說,後端數據記錄程序會把所有的數據記錄到同一個文件夾下的多個文件內,以方便前端顯示程序多線程加速讀取。因此,前端顯示程序在啟動的時候需要指定讀取的文件夾

1. 默認使用

前端顯示程序提供瞭CLI(命令行)界面,因此我們直接在命令行啟動就行瞭

tensorboard --logdir=數據文件夾

其中數據文件夾就是在聲明SummaryWriter時候指定的文件夾。

例如:

tensorboard --logdir=./Feb05_01-00-48_Alienware/

而在我們啟動前端顯示程序之後,就會得到一個端口,訪問這個端口就能看到顯示的效果

訪問該端口就能看到程序:

2. 修改端口

有的時候,在服務器上訓練模型的時候為瞭避免和別人的TensorBoard的端口撞瞭,我們需要指定新的端口。或者有的時候我們在docker容器裡跑TensorBoard,我們通過一個端口映射到主機上去,這個時候就需要指定TensorBoard使用特定的端口。

具體來說就是通過CLI的--port參數

tensorboard --logdir=數據文件夾 --port=端口

例如我們現在指定上面的例子端口為10000

tensorboard --logdir=./Feb05_01-00-48_Alienware/ --port=10000

五、Summary

最後,總結一下使用TensorFlow的Pipeline,首先在訓練的過程中使用SummaryWriter來記錄數據,記錄的過程中需要註意文件夾需要來合理的劃分。

然後我們在前端查看的時候,運行tensorboard的CLI程序即可,一般用的最多的就是--log_dir--port兩個參數。

此外,如果是服務器上的話,那麼tensorboard的CLI運行在服務器上,然後在自己的電腦上,利用瀏覽器,通過內網來查看訓練過程。

1. SummaryWriter APIs

上面講完瞭SummaryWriter的Workflow/Pipeline,剩下的就是SummaryWriter添加數據的API的講解瞭。關於這些API的話,正如上面介紹的,他們都以add_開頭,具體有:

標量類:add_scalaradd_scalarsadd_custom_scalarsadd_custom_scalars_marginchartadd_custom_scalars_multilinechart

數據顯示類:

  • 圖像:add_imageadd_imagesadd_image_with_boxesadd_figure
  • 視頻:add_video
  • 音頻:add_audio
  • 文本:add_text
  • ​​​​​​​Embedding:add_embedding
  • ​​​​​​​點雲:add_mesh

統計圖:add_histogramadd_histogram_rawadd_pr_curve、add_pr_curve_raw

網絡圖:add_onnx_graphadd_graph

​​​​​​​超參數圖:add_hparams

因為我目前主要在做CV、點雲和NLP,對於語音、視頻設計的比較少,因此關於這些API以後用到瞭我再慢慢補充。

其實主要就是對官網上的翻譯,可以直接看官網上的介紹:https://pytorch.org/docs/stable/tensorboard.html

到此這篇關於Pytorch中使用TensorBoard詳情的文章就介紹到這瞭,更多相關Pytorch TensorBoard內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: