初学tensorboardX 在pytorch中的使用,做一些笔记,以备忘。
官方文档(github):https://github.com/lanpa/tensorboardX/blob/master/docs/tutorial.rst
各种应用的综合demo:https://github.com/lanpa/tensorboardX
比较详细的知乎介绍:https://zhuanlan.zhihu.com/p/37626738
比较详细的简书文章:https://www.jianshu.com/p/46eb3004beca
安装:
pip install tensorboardX
pip install tensorflow
应用:
每执行一次writer.add_***,都会在显示界面生成一个对应的figure
## 添加标量
writer.add_scalar('tag', y_value, x_value)
# demo.py
import torch
import torchvision.utils as vutils
import numpy as np
import torchvision.models as models
from torchvision import datasets
from tensorboardX import SummaryWriter
resnet18 = models.resnet18(False)
writer = SummaryWriter(log_dir = "demo_log")
sample_rate = 44100
freqs = [262,294,330,349,392,440,440,440,440,440,440]
for n_iter in range(100):
dummy_s1 = torch.rand(1)
dummy_s2 = torch.rand(1)
## data grouping by 'slash'
## add_scalar在每个n_iter保存一个点,n_iter以横轴的形式出现
####-------------绘制并保存散点-折线图------------------------####
"""
理解:每执行一次 writer.add_** 都是向 可视化界面添加一个figure,
该 figure 的 tag 是 add_** 的参数的第一个string类型的参数
add_** 的参数:
第一个参数:该figure的tag
第二个参数:figure的 y 轴数值
第三个参数:figure的x轴参数
在可视化的时候,只要在logdir的父文件夹里执行 'tensorboard --logdir ***'即可,
其中的***是在writer = SummaryWriter(log_dir="xxx_loss")中定义的 log_dir
如果在writer = SummaryWriter(log_dir="wzg_loss")命令中不注明 log_dir ,则命令默认
log_dir = './runs'
##
当需要在同一个figure里绘制多条曲线时,需要将y轴坐标的地方设置成字典的形式,每个曲线分量需要 有一个自己的名称
"""
## 每执行一次,在对应的 figure 上添加一个对应的点,寻找 figure 是通过 tag
writer.add_scalar('data/scalar1',dummy_s1[0],n_iter)
writer.add_scalar('data/scalar2',dummy_s2[0],n_iter)
writer.add_scalars('data/scalar_group',{
'xsin':n_iter*np.sin(n_iter),
'xcos':n_iter*np.cos(n_iter),
'arctanx':np.arctan(n_iter)},
n_iter)
####-------------绘制并保存image ------------------------####
dummy_img = torch.rand(32,3,64,64)
if n_iter % 10 == 0:
x = vutils.make_grid(dummy_img,nrow=8,padding=50,normalize=True,scale_each=True,pad_value=1)## 生成一幅图像
'''
torchvision.utils.make_grid(tensor, nrow=8, padding=2, normalize=False, range=None, scale_each=False, pad_value=0)
作用;Make a grid of images.
tensor :4D mini-batch Tensor of shape (B x C x H x W) or a list of images all of the same size
nrow (int, optional) – Number of images displayed in each row of the grid. The Final grid size is (B / nrow, nrow). Default is 8.
padding (int, optional) – amount of padding. Default is 2,为每幅图像增加0边界的宽度
scale_each (bool, optional) – If True, scale each image in the batch of images separately rather than the (min, max) over all images.
pad_value (float, optional) – Value for the padded pixels.
'''
####-------------绘制并保存image ------------------------####
writer.add_image('Image',x,n_iter)## 每个n_iter保存一幅图像,n_iter以一个滑动轴的形式出现
####-------------绘制并保存声音------------------------####
dummy_audio = torch.zeros(sample_rate * 2)
for i in range(x.size(0)):
dummy_audio[i] = np.cos(freqs[n_iter // 10] * np.pi * float(i)/float(sample_rate))
writer.add_audio('myAudio',dummy_audio,n_iter,sample_rate=sample_rate)
####-------------保存文本 ------------------------####
## 以block列表的形式出现,每执行一次 add_text ,就会在对应的 tag 的
writer.add_text('Text','text logged at step:'+str(n_iter),n_iter)
####-------------显示 net 的名称及保存的对应参数------------------------####
for name,param in resnet18.named_parameters():
writer.add_histogram(name,param.clone().cpu().data.numpy(),n_iter)
####-------------显示曲线------------------------####
## 绘制 PR 曲线 : add_pr_curve (tag, labels, predictions, step)
## labels :是标准答案(one hot 形式)
## predictions:预测结果值,每个元素的取值范围为 [0,1],表示概率
## n_iter: 会在每次迭代生成一个PR曲线图,n_iter 会在界面左侧以滑动轴的形式出现
## 函数 add_pr_curve 会内在自动设计阈值从 1 变换到 0,得到不同的TP,FP,TN,FN的值,用以计算PR曲线
## 目前没有直接的 生成ROC曲线的 函数
labels = np.random.randint(2,size=100)
prediction = np.random.rand(100)
writer.add_pr_curve('xoxo',labels,prediction,n_iter)
'''
pr curve
根據預測的機率值以及其對應的標準答案計算 precision-recall 的結果並保存。
add_pr_curve (tag, labels, predictions, step)
labels是標準答案,predictions是程式對樣本的預測。
假設有十筆資料 labels就會長得像[0, 0, 1, 0, 0, 1, 0, 1, 0, 1] ,predictions則長的像[0.1, 0.3, 0.8, 0.2, 0.4, 0.5, 0.1, 0.7, 0.9, 0.2]
'''
# writer.add_roc_curve()
dataset = datasets.MNIST('mnist',train=False,download=True)
images = dataset.test_data[:100].float()
label = dataset.test_labels[:100]
features = images.view(100,784)
####-------------降维显示------------------------####
writer.add_embedding(features,metadata=label,label_img = images.unsqueeze(1))
## export scalar data to json for external processing
writer.export_scalars_to_json('./all_scalars.json')
writer.close()
保存网络结构
import torch
import torch.nn as nn
import torch.nn.functional as F
from tensorboardX import SummaryWriter
class Net1(nn.Module):
def __init__(self):
super(Net1,self).__init__()
self.conv1 = nn.Conv2d(1,10,kernel_size=5)
self.conv2 = nn.Conv2d(10,20,kernel_size=5)
self.conv2_drop = nn.Dropout2d()
self.fc1 = nn.Linear(320,50)
self.fc2 = nn.Linear(50,10)
self.bn = nn.BatchNorm2d(20)
def forward(self,x):
x = F.max_pool2d(self.conv1(x),2)
x = F.relu(x) + F.relu(-x)
x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)),2))
x = self.bn(x)
x = x.view(-1,320)
x = F.relu(self.fc1(x))
x = F.dropout(x,training=self.training)
x = self.fc2(x)
x = F.softmax(x,dim=1)
return x
model = Net1()
dummy_input = torch.rand(13,1,28,28)
with SummaryWriter(comment='Net1',log_dir="my_net") as w:
w.add_graph(model,(dummy_input,))
'''
記錄網路架構。 (實驗性的功能,模型複雜的時候不確定對不對)
問題很多的功能。使用上比較複雜。需要準備兩個東西:網路模型 以及 你要餵給他的 Tensor
舉例來說,令模型為 m,輸入為 x,則使用方法為:
add_graph(m, (x, )) 這裡使用 tuple 的原因是當網路有多個輸入時,可以把他擴充成
add_graph(m, (x, y, z)) ,如果只有單一輸入,寫成add_graph(m, x)也無妨。
常會出錯的原因:
較新的 operator pytorch本身不支援JIT
輸入是 cpu tensor,model 在 GPU 上。(或是反過來)
輸入的 tensor 大小錯誤,跑到後面幾層維度消失了(或是爆掉)
model 寫錯,前後兩層 feature dimension 對不上
除錯方法
forward propagate 一次 m(x) 或是多個輸入時:m((x, y, z))
2. 用 torch.onnx.export 導出模型,觀察錯誤訊息
'''