深度之眼Pytorch框架训练营第四期——PyTorch中的可视化工具

可视化工具TensorBoard

  • PyTorch从 1.2.0 版本开始,正式自带内置的Tensorboard支持了,可以不再依赖第三方工具来进行可视化
  • Tensorboard工作原理为:先使用Python脚本记录可视化数据,然后将数据存入硬盘,最后在终端中运行tensorboard,并在Web界面进行展示
1、SummaryWriter
class SummaryWriter(object):
    """Writes entries directly to event files in the log_dir to be
    consumed by TensorBoard.

    The `SummaryWriter` class provides a high-level API to create an event file
    in a given directory and add summaries and events to it. The class updates the
    file contents asynchronously. This allows a training program to call methods
    to add data to the file directly from the training loop, without slowing down
    training.
    """

    def __init__(self, log_dir=None, comment='', purge_step=None, max_queue=10,
                 flush_secs=120, filename_suffix='')
  • 功能:提供创建 event file 的高级接口

  • 属性:

  • log_direvent file 输出文件夹

  • comment:不指定log_dir时,文件夹后缀;(只有在不指定log_dir的情况下有效)

  • filename_suffixevent file 文件名后缀

  • 方法:

(1)add_scalar()
add_scalar(tag, scalar_value, global_step=None, walltime=None)
  • 功能:在一个图表中记录一个标量的变化,常用于 Loss 和 Accuracy 曲线的记录
  • 参数:
  • tag(string):该图的标签(唯一标示),类似于polt.title
  • scalar_value(float or string/blobname):用于存储的值,曲线图的 y y y坐标
  • global_step(int):曲线图的 x x x坐标
  • walltime(float):为 event 文件的文件名设置时间,默认为time.time()
  • 实例:
max_epoch = 100

writer = SummaryWriter(comment='test_comment', filename_suffix="test_suffix")

for x in range(max_epoch):

    writer.add_scalar('y=2x', x * 2, x)
    writer.add_scalar('y=pow_2_x', 2 ** x, x)

writer.close()
(2)add_scalars()
add_scalars(main_tag, tag_scalar_dict, global_step=None, walltime=None)
  • 功能:在一个图表中记录多个标量的变化,常用于对比,如 trainLoss 和 validLoss 的比较等
  • 参数:
  • main_tag:该图的标签
  • tag_scalar_dict:key 是变量的 tag,value 是变量的值
  • 实例:
max_epoch = 100

writer = SummaryWriter(comment='test_comment', filename_suffix="test_suffix")

for x in range(max_epoch):
    writer.add_scalars('data/scalar_group', {"xsinx": x * np.sin(x),
                                             "xcosx": x * np.cos(x)}, x)

writer.close()
(3)add_histgram()
add_histogram(tag, values, global_step=None, bins='tensorflow', walltime=None, max_bins=None)
  • 功能:绘制直方图和多分位数折线图,常用于监测权值及梯度的分布变化情况,便于诊断网 络更新方向是否正确
  • 参数:
  • tag(string):该图的标签。
  • values(torch.Tensor, numpy.array or string/blobname):用于绘制直方图的值
  • global_step(int):曲线图的 y 坐标
  • bins(string):决定如何取 bins,默认为’tensorflow’,可选:‘auto’,'fd’等
  • walltime(float):为event 文件的文件名设置时间,默认为time.time()
  • 实例:
writer = SummaryWriter(comment='test_comment', filename_suffix="test_suffix")

for x in range(2):

    np.random.seed(x)
    data_union = np.arange(100)
    data_normal = np.random.normal(size=1000)

    writer.add_histogram('distribution union', data_union, x)
    writer.add_histogram('distribution normal', data_normal, x)

writer.close()
(4)add_image()
add_image(tag, img_tensor, global_step=None, walltime=None, dataformats='CHW')
  • 功能:绘制图片,可用于检查模型的输入,监测 feature map 的变化,或是观察 weight。
  • 参数:
  • tag(string):该图的标签
  • img_tensor(torch.Tensor,numpy.array, or string/blobname):需要可视化的图片数据
  • global_step(int) x x x坐标
  • walltime(float):event 文件的文件名设置时间
  • dataformats:数据形式,可以有:“CHW”,“HWC”,“HW”,C表示通道数,H表示高度,W表示宽度
  • 实例:
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

# img 1     random 
fake_img = torch.randn(3, 512, 512)
writer.add_image("fake_img", fake_img, 1)
time.sleep(1)

# img 2     ones
fake_img = torch.ones(3, 512, 512)
time.sleep(1)
writer.add_image("fake_img", fake_img, 2)

# img 3     1.1
fake_img = torch.ones(3, 512, 512) * 1.1
time.sleep(1)
writer.add_image("fake_img", fake_img, 3)

# img 4     HW
fake_img = torch.rand(512, 512)
writer.add_image("fake_img", fake_img, 4, dataformats="HW")

# img 5     HWC
fake_img = torch.rand(512, 512, 3)
writer.add_image("fake_img", fake_img, 5, dataformats="HWC")

writer.close()

这里需要注意,如果所有的数字均小于等于1,则会自动乘上255;如果有任意一个数大于,则不会乘255;这就是代码中img 2是白色,而img 3是黑色的原因

利用torchvision.utils.make_grid可以将多张图片放到一张图片中,方便观察:

make_grid(tensor, nrow=8, padding=2,
              normalize=False, range=None, scale_each=False, pad_value=0)
  • 功能:制作网格图像
  • 参数:
  • tensor:图像数据,BCH*W形式(B为batch size)
  • nrow:行数(列数自动计算)
  • padding:每张图片之间的间隔,默认值为 2
  • normalize:是否进行归一化至(0,1)
  • range:标准化范围(设置归一化的 min 和 max,若不设置,默认从 tensor 中找 min 和 max)
  • scale_each:每张图片是否单独进行归一化,还是 min 和 max 的一个选择
  • pad_value:填充部分的像素值,默认为 0,即黑色
  • 实例:
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

split_dir = os.path.join("..", "..", "WeekTwo/lesson_6/data", "rmb_split")
train_dir = os.path.join(split_dir, "train")
# train_dir = "path to your training data"

transform_compose = transforms.Compose([transforms.Resize((32, 64)), transforms.ToTensor()])
train_data = RMBDataset(data_dir=train_dir, transform=transform_compose)
train_loader = DataLoader(dataset=train_data, batch_size=16, shuffle=True)
data_batch, label_batch = next(iter(train_loader))

img_grid = vutils.make_grid(data_batch, nrow=4, normalize=True, scale_each=True)
# img_grid = vutils.make_grid(data_batch, nrow=4, normalize=False, scale_each=False)
writer.add_image("input img", img_grid, 0)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DYDghdqU-1590656711575)(./_image/截屏2020-05-2816.27.03.png?r=40)][center]

(5)add_graph()
add_graph(model, input_to_model=None, verbose=False)
  • 功能:可视化模型计算图
  • 参数:
  • model:模型,必须是nn.Module
  • input_to_model:输出给模型的数据
  • verbose:是否打印计算图结构信息
  • 实例:
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

# 模型
fake_img = torch.randn(1, 3, 32, 32)

lenet = LeNet(classes=2)

writer.add_graph(lenet, fake_img)

writer.close()

print(summary(lenet, (3, 32, 32), device="cpu"))

# ----------------------------------------------------------------
#         Layer (type)               Output Shape         Param #
# ================================================================
#             Conv2d-1            [-1, 6, 28, 28]             456
#             Conv2d-2           [-1, 16, 10, 10]           2,416
#             Linear-3                  [-1, 120]          48,120
#             Linear-4                   [-1, 84]          10,164
#             Linear-5                    [-1, 2]             170
# ================================================================
# Total params: 61,326
# Trainable params: 61,326
# Non-trainable params: 0
# ----------------------------------------------------------------
# Input size (MB): 0.01
# Forward/backward pass size (MB): 0.05
# Params size (MB): 0.23
# Estimated Total Size (MB): 0.30
# ----------------------------------------------------------------
# None

在这里插入图片描述

2、利用Tensorboard对网络模型的卷积和和特征图进行可视化
  • 对卷积和的可视化
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

alexnet = models.alexnet(pretrained=True)
kernel_num = -1
vis_max = 1

for sub_module in alexnet.modules():
    if isinstance(sub_module, nn.Conv2d):
        kernel_num += 1
        if kernel_num > vis_max:
            break
        kernels = sub_module.weight
        c_out, c_int, k_w, k_h = tuple(kernels.shape)

        for o_idx in range(c_out):
            kernel_idx = kernels[o_idx, :, :, :].unsqueeze(1)   # make_grid需要 BCHW,这里拓展C维度
            kernel_grid = vutils.make_grid(kernel_idx, normalize=True, scale_each=True, nrow=c_int)
            writer.add_image('{}_Convlayer_split_in_channel'.format(kernel_num), kernel_grid, global_step=o_idx)

        kernel_all = kernels.view(-1, 3, k_h, k_w)  # 3, h, w
        kernel_grid = vutils.make_grid(kernel_all, normalize=True, scale_each=True, nrow=8)  # c, h, w
        writer.add_image('{}_all'.format(kernel_num), kernel_grid, global_step=322)

        print("{}_convlayer shape:{}".format(kernel_num, tuple(kernels.shape)))

writer.close()

在这里插入图片描述

  • 对特征图的可视化
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

# 数据
path_img = "./lena.png"     # your path to image
normMean = [0.49139968, 0.48215827, 0.44653124]
normStd = [0.24703233, 0.24348505, 0.26158768]

norm_transform = transforms.Normalize(normMean, normStd)
img_transforms = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    norm_transform
])

img_pil = Image.open(path_img).convert('RGB')
if img_transforms is not None:
    img_tensor = img_transforms(img_pil)
img_tensor.unsqueeze_(0)    # chw --> bchw

# 模型
alexnet = models.alexnet(pretrained=True)

# forward
convlayer1 = alexnet.features[0]
fmap_1 = convlayer1(img_tensor)

# 预处理
fmap_1.transpose_(0, 1)  # bchw=(1, 64, 55, 55) --> (64, 1, 55, 55)
fmap_1_grid = vutils.make_grid(fmap_1, normalize=True, scale_each=True, nrow=8)

writer.add_image('feature map in conv1', fmap_1_grid, global_step=322)
writer.close()

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值