給 PyTorch 用的 tensorboard

Google 的 tensorboard 是一個很好用的視覺化工具。他可以記錄一般的數字,影像或者是聲音資訊,對於觀察類神經網路訓練的過程非常有幫助。很可惜的是其他的訓練框架並沒有這麼好用的工具。稍微搜尋一下的話可以發現已經有一些現成的軟體可以讓不同的訓練框架使用 tensorboard 的功能,不過他們可以記錄的東西都比較有限或是使用起來比較複雜(tensorboard_logger, visdom)。我寫的這個套件的目的就是讓其他tensorboard 的功能都可以被 pytorch 用上。目前這個套件支援的紀錄資料有純量影像聲音直方圖文字網路架構還有降維視覺化。簡單的說就是全部都支援XD。這個套件目前的測試過的環境為 Ubuntu 或是 Mac ;使用的python為 anaconda 的 python3。

  • 安裝他

在 bash 介面輸入pip install tensorboardX 即可。要用最新版的話 可以從 github 下載原始碼安裝,或者是 pip install tensorboardX —-no-cache-dir.

  • 啟動 tensorboard

Tensorboard 其實是一個網頁伺服器,他讀取的資料來自於訓練網路的時候程式寫下的事件檔。因為 tensorboard 包含於 tensorflow,所以你需要另外安裝一份 tensorflow 在伺服器主機。我想大部分人都已經裝過了。沒裝過的話就在 bash 介面輸入pip install tensorflow 或是 pip install tensorflow-gpu即可。接下來就是輸入 tensorboard --logdir=[yourlogdir]伺服器就會啟動了。這個指令落落長,所以你可以在~/.bash_profile加一行: alias tb='tensorboard --logdir ' 如此一來指令就變成tb [yourlogdir] 比較方便。接下來就是照著終端機上的指示打開你的瀏覽器就可以看到畫面了。

基本用法:

  • 建立 event writer 實體

在紀錄任何東西之前,我們需要建立一個 event writer 實體。

from tensorboardX import SummaryWriter 
#SummaryWriter 是一個類別,包含這套件的所有功能。
writer = SummaryWriter('runs/exp-1')
#建立實體。資料存放在:'runs/exp-1'
#接下來要寫入任何資料都是呼叫 writer.add_某功能()
writer = SummaryWriter()
#建立實體。資料存放在:'runs/現在時間-機器名字' ex. 'runs/Aug20-obov01'
writer = SummaryWriter(comment='3xLR')
#在預設資料夾後面加上註解 檔名變為:'runs/Aug20-obov01-3xLR'

上面的程式碼會在目前的工作目錄下建立一個叫 runs 的資料夾以及子目錄 exp1。 每個子目錄都會被視為一個實驗的資料夾。每次執行新的實驗時,比如說改了一些參數,這時請將資料夾重新命名,像是: runs/exp2, runs/myexp 這樣你會比較好比較實驗的結果。 小建議:資料夾可以用時間命名或者是直接把參數當成資料夾的名稱。

  • 紀錄純量

純量是最好記錄的東西。通常我們會把每次訓練的損失記錄下來或者是測試的準確度都是值得記錄的東西。其他像是學習率也是不錯的東西。因為記錄純量不太佔空間,所以盡量記錄說不定你會發現一些意想不到的結果。 writer.add_scalar('myscalar', value, iteration)記得,這是記錄純量,所以不要把 PyTorch variable 傳進去,不然會爆炸。如果 loss 是一個pytorch variable 那你可以寫成writer.add_scalar('loss', loss.data[0], iteration)

  • 記錄影像

影像使用一個三維的矩陣來表示。這三個維度分別代表紅色,綠色,藍色的強度。一張寬200, 高100的影像其對應的矩陣大小為[3, 100, 200]。記錄影像最簡單情況當然是只有一張影像要存。這時候你只需要注意一下是不是符合上述的規格然後將它傳到:writer.add_image('imresult', x, iteration) 即可。 不過通常訓練的時候會是批次處理的狀況,所以會有一大堆影像要存。這時候請用torchvision內建的 make_grid 來把那批影像變成馬賽克再存檔(不是常見的那種馬賽克)make_grid 的用法請看官方說明檔。http://pytorch.org/docs/master/torchvision/utils.html#torchvision.utils.make_grid

  • 紀錄直方圖(數據的分佈情形)

記錄直方圖很耗資源,沒事不要用。如果你用了這個套件之後覺得速度變慢了請先檢查一下是不是這個原因。記錄直方圖的函數需要numpy 陣列,這樣你想要記錄的東西轉換為 numpy 形式之後用 writer.add_histogram('hist', array, iteration) 即可紀錄。

  • 紀錄聲音 writer.add_audio('myaudio', audio, iteration)

這功能寫的半調子,只支援單聲道。取樣頻率也固定為 44100 KHz。 add_audio 要吃的聲音資訊是個一維陣列,陣列的每一個元素代表在每一個取樣點的振幅大小。一段2秒鐘的聲音應該要有88200個點;其中每個元素的值應該都介於正負1之間。

  • 紀錄文字 writer.add_text('mytext', 'this is a pen', iteration)

這應該不用多說。

  • 記錄網路架構。 (不確定對不對)

這是一個實驗性的功能,用到了pytorch autograd 的 backward tracing。程式會從最後一個變數開始沿著變數中的 next_functions (pytorch有大改版。如果程式要求你更新新版,代表你的pytorch版本太舊了)以遞迴的方式一路往回走,並把路上經過的點都畫出來。要使用這個函數需要準備兩個東西:網路 m 以及網路跑出來的結果 r。要畫圖的話就呼叫 writer.add_graph(m, r)即可。要注意的是,預設的輸入變數並不需要梯度,所以back tracing的過程不會被碰到,所以不會畫出來。這時候只要在建立變數的時候多傳一個參數: requires_grad=True 就會強迫讓梯度傳回,就可以把他也畫出來了。參考 https://github.com/lanpa/tensorboard-pytorch/blob/master/demo_graph.py 就會比較懂了。

  • 高維度資料視覺化/降維 (embedding)

因為人類對物體的了解程度只有三維,所以當資料的維度超過三的時候我們沒辦法將他視覺化。這時候就需要降維來讓資料的維度小於等於三。降維運算由 tensorboard 以 Javascript 執行,演算法有 PCA 及 t-sne 兩種可選。這邊我們只需要負責提供每個點的高維度特徵即可。提供的格式是一個矩陣,一個 n x d 的矩陣 n 點的數量, d 是維度的多寡。 高維度特徵可以是原始資料。比如說影像,或是網路學到的壓縮結果。這原始資料決定了資料的分佈情形。如果要看得更清楚一點,你可以再傳 metadata / label_imgs 的參數進去(metadata是一個 python list 長度為 n, label_imgs 是一個 4 維矩陣,大小是 nCHW。這樣每個點就會有他對應的文字或圖在旁邊。不懂的話就看範例吧:https://github.com/lanpa/tensorboard-pytorch/blob/master/demo_embedding.py

其他技巧:

  • 為資料增加群組

通常我們的一個實驗裡會記錄很多數據,這時候數據會變得很亂但我們可以使用階層式表示法將資料分群。對於所有有 tag 欄位的 function (add_scalar, add_image, add_audio, add_histogram, add_text), 我們都可以將結果分群表示。以 imagenet 為例,我們會紀錄 top1, top5 準確度,training/validation都要紀。所以就可以寫成: train/top1, train/top5, valid/top1, valid/top5。如此一來 tensorboard 就會將 train validation 分開顯示。

  • 改變顯示的資料的數量

預設顯示的資料數量是 10 個。如果想顯示多一點你可以更改: event_accumulator 的值。他的位置在~/anaconda3/lib/python3.6/site-packages/tensorflow/tensorboard/backend/application.py 。改壞的話再重新安裝 tensorflow 就沒事了。