- Tensorboard最初是作为TensorFlow的可视化工具迅速流行开来。作为和TensorFlow深度集成的工具,Tensorboard能够展现你的TensorFlow网络计算图,绘制图像生成的定量指标图以及附加数据。但同时Tensorboard也是一个相对独立的工具,只要用户保存的数据遵循相应的格式,tensorboard就能读取这些数据并进行可视化。这里我们将主要介绍如何在PyTorch中使用tensorboardX^1进行训练损失的可视化。 TensorboardX是将Tensorboard的功能抽取出来,使得非TensorFlow用户也能使用它进行可视化,几乎支持原生TensorBoard的全部功能。
tensorboardX的使用非常简单。首先用如下命令启动tensorboard:
tensorboard --logdir <your/running/dir> --port <your_bind_port>
下面举例说明tensorboardX的使用。
from tensorboardX import SummaryWriter
# 构建logger对象,logdir用来指定log文件的保存路径
# flush_secs用来指定刷新同步间隔
logger = SummaryWriter(log_dir='experimient_cnn', flush_secs=2)
for ii in range(100):
logger.add_scalar('data/loss', 10-ii**0.5)
logger.add_scalar('data/accuracy', ii**0.5/10)
打开浏览器输入http://localhost:6006(其中6006应改成你的tensorboard所绑定的端口)。
- Visdom的使用有两点需要注意的地方:
需手动指定保存env,可在web界面点击save按钮或在程序中调用save方法,否则visdom服务重启后,env等信息会丢失。
客户端与服务器之间的交互采用tornado异步框架,可视化操作不会阻塞当前程序,网络异常也不会导致程序退出。
%%sh
# 启动visdom服务器
# nohup python -m visdom.server &
import visdom
import torch as t
# 新建一个连接客户端
# 指定env = u'test1',默认端口为8097,host是‘localhost'
vis = visdom.Visdom(env=u'test1',use_incoming_socket=False)
x = t.arange(1, 30, 0.01)
y = t.sin(x)
vis.line(X=x, Y=y, win='sinx', opts={'title': 'y=sin(x)'})
下面逐一分析这几行代码:
vis = visdom.Visdom(env=u’test1’),用于构建一个客户端,客户端除指定env之外,还可以指定host、port等参数。
vis作为一个客户端对象,可以使用常见的画图函数,包括:
- line:类似Matlab中的plot操作,用于记录某些标量的变化,如损失、准确率等
- image:可视化图片,可以是输入的图片,也可以是GAN生成的图片,还可以是卷积核的信息
- text:用于记录日志等文字信息,支持html格式
- histgram:可视化分布,主要是查看数据、参数的分布
- scatter:绘制散点图
- bar:绘制柱状图
- pie:绘制饼状图
更多操作可参考visdom的github主页
这里主要介绍深度学习中常见的line、image和text操作。
Visdom同时支持PyTorch的tensor和Numpy的ndarray两种数据结构,但不支持Python的int、float等类型,因此每次传入时都需先将数据转成ndarray或tensor。上述操作的参数一般不同,但有两个参数是绝大多数操作都具备的:
- win:用于指定pane的名字,如果不指定,visdom将自动分配一个新的pane。如果两次操作指定的win名字一样,新的操作将覆盖当前pane的内容,因此建议每次操作都重新指定win。
- opts:选项,接收一个字典,常见的option包括title、xlabel、ylabel、width等,主要用于设置pane的显示格式。
之前提到过,每次操作都会覆盖之前的数值,但往往我们在训练网络的过程中需不断更新数值,如损失值等,这时就需要指定参数update='append’来避免覆盖之前的数值。而除了使用update参数以外,还可以使用vis.updateTrace方法来更新图,但updateTrace不仅能在指定pane上新增一个和已有数据相互独立的Trace,还能像update='append’那样在同一条trace上追加数据。
- 要实现模型单机多卡十分容易,直接使用 new_module = nn.DataParallel(module, device_ids), 默认会把模型分布到所有的卡上。多卡并行的机制如下:
- 将模型(module)复制到每一张卡上
- 将形状为(N,C,H,W)的输入均等分为 n份(假设有n张卡),每一份形状是(N/n,
C,H,W),然后在每张卡前向传播,反向传播,梯度求平均。要求batch-size 大于等于卡的个数(N>=n)
在绝大多数情况下,new_module的用法和module一致,除了极其特殊的情况下(RNN中的PackedSequence)。另外想要获取原始的单卡模型,需要通过new_module.module访问。