pytorch基础(八)-TensorBoard

news2024/12/23 14:17:12

一、TensorBoard运行机制

python记录可视化的数据--》存储到硬盘--》在web端进行可视化

1.python记录可视化的数据
writer.add_scalar('名称', y轴, x轴)
writer = SummaryWriter(comment='test_tensorboard')

for x in range(100):

    writer.add_scalar('y=2x', x * 2, x)
    writer.add_scalar('y=pow(2, x)',  2 ** x, x)
    
    writer.add_scalars('data/scalar_group', {"xsinx": x * np.sin(x),
                                             "xcosx": x * np.cos(x),
                                             "arctanx": np.arctan(x)}, x)
writer.close()
 2.存储到硬盘

安装环境:
pip install tensorboard
pip install future

运行程序

3.在web端进行可视化

(1)在终端输入
          tensorboard --logdir=保存数据的地址

(2)点击网址在web端查看

二、TensorBoard页面

三、保存event file文件

SummaryWriter
提供创建event file的高级接口

主要属性:
log_dir:event file的输出文件,默认为None
comment:log_dir为None时,文件夹的后缀
filename_suffix:event file文件名的后缀

 log_dir = "./train_log/test_log_dir"
 writer = SummaryWriter(log_dir=log_dir, comment='_scalars', filename_suffix="nihaoa")

 for x in range(100):
     writer.add_scalar('y=pow_2_x', 2 ** x, x)

 writer.close()

当log_dir不为None时不显示comment
当log_dir为None时,在py文件所在的文件夹下创建runs文件夹

log_dir = "./train_log/test_log_dir"
writer = SummaryWriter(comment='_scalars', filename_suffix="12345678")

for x in range(100):
    writer.add_scalar('y=pow_2_x', 2 ** x, x)

writer.close()

 

四、方法

1.保存曲线

writer.add_scalar('图的标签',  y轴,  x轴)
writer.add_scalars('图像总标签', {"第一个图的标签": 第一个要绘制的y轴, "第二个图的标签": 第二个要绘制的y轴}, x轴)

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.add_scalars('data/scalar_group', {"xsinx": x * np.sin(x),
                                             "xcosx": x * np.cos(x)}, x)

writer.close()

2.保存直方图

writer.add_histogram('标签', 数据, 几张图)

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()

 

3.绘制损失函数和梯度
train_curve = list()
valid_curve = list()

iter_count = 0

# 构建 SummaryWriter
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

for epoch in range(MAX_EPOCH):

    loss_mean = 0.
    correct = 0.
    total = 0.

    net.train()
    for i, data in enumerate(train_loader):

        iter_count += 1

        # forward
        inputs, labels = data
        outputs = net(inputs)

        # backward
        optimizer.zero_grad()
        loss = criterion(outputs, labels)
        loss.backward()

        # update weights
        optimizer.step()

        # 统计分类情况
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).squeeze().sum().numpy()

        # 打印训练信息
        loss_mean += loss.item()
        train_curve.append(loss.item())
        if (i+1) % log_interval == 0:
            loss_mean = loss_mean / log_interval
            print("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))
            loss_mean = 0.

        # 记录数据,保存于event file
        writer.add_scalars("Loss", {"Train": loss.item()}, iter_count)
        writer.add_scalars("Accuracy", {"Train": correct / total}, iter_count)

    # 每个epoch,记录梯度,权值
    for name, param in net.named_parameters():
        writer.add_histogram(name + '_grad', param.grad, epoch)
        writer.add_histogram(name + '_data', param, epoch)

    scheduler.step()  # 更新学习率

每个iter计算损失,每个epoch计算梯度

正确率和loss比较平滑的是验证集,验证集经过了平均

4.保存图像

torchvision.utils.make_grid(tensor, nrow, padding, normalize, range, scale_each, pad_value)

tensor:图像数据,B,C,H,W
nrow:行数(列数自动计算)
padding:图像间距
normalize:是否将图像标准化
range:标准化的范围(超出范围按范围内的最大值/最小值处理)
scale_each:是否单张图维度标准化
pad_value:填充的值

writer.add_image("标签名", 图像数据, x轴, 数据形式)

图像数据:在(0,1)之间时自动乘以255,若图像数据存在值大于1,图像数据保持原来的值不变
数据形式:主要形式有(C,H,W)(H,W,C) (H,W)

5.绘制卷积核和特征图
writer = SummaryWriter(comment='test_your_comment', filename_suffix="_test_your_filename_suffix")

alexnet = models.alexnet(pretrained=True)

kernel_num = -1
vis_max = 1
# 避免pytorch1.7下的一个小bug,增加 torch.no_grad
with torch.no_grad():
    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()

6.模型信息
可视化模型计算图

writer.add_graph(模型, 数据, verbose)

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()

打印模型信息

pip install torchsummary

summary(模型, input_size, device)

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

五、hook

1.Tensor.register_hook
注册一个反向传播hook函数

使用hook函数的原因是在后向传播时,除叶子节点外其他节点的梯度在后向传播后会被释放掉

w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)

a_grad = list()


def grad_hook(grad):
    a_grad.append(grad)


handle = a.register_hook(grad_hook)

y.backward()

# 查看梯度
print("gradient:", w.grad, x.grad, a.grad, b.grad, y.grad)
print("a_grad[0]: ", a_grad[0])
handle.remove()


在运行完毕后,a的梯度为None,可以使用hook函数保存a的梯度

也可以通过hook函数改变梯度值

w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)

a_grad = list()


def grad_hook(grad):
    a_grad.append(grad)


handle = a.register_hook(grad_hook)

y.backward()

# 查看梯度
print("gradient:", w.grad, x.grad, a.grad, b.grad, y.grad)
print("a_grad[0]: ", a_grad[0])
handle.remove()

w的梯度值由5-->30

2.Module.register_forward_hook
注册module的前向传播hook函数

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 2, 3)
        self.pool1 = nn.MaxPool2d(2, 2)

    def forward(self, x):
        x = self.conv1(x)
        x = self.pool1(x)
        return x


def forward_hook(module, data_input, data_output):
    fmap_block.append(data_output)
    input_block.append(data_input)


# 初始化网络
net = Net()
net.conv1.weight[0].detach().fill_(1)
net.conv1.weight[1].detach().fill_(2)
net.conv1.bias.data.detach().zero_()

# 注册hook
fmap_block = list()
input_block = list()
net.conv1.register_forward_hook(forward_hook)


# inference
fake_img = torch.ones((1, 1, 4, 4))  # batch size * channel * H * W
output = net(fake_img)

# 观察
print("output shape: {}\noutput value: {}\n".format(output.shape, output))
print("feature maps shape: {}\noutput value: {}\n".format(fmap_block[0].shape, fmap_block[0]))
print("input shape: {}\ninput value: {}".format(input_block[0][0].shape, input_block[0]))

输出的特征图和输入 

3.利用hook函数绘制特征图

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)

# 注册hook
fmap_dict = dict()
for name, sub_module in alexnet.named_modules():

    if isinstance(sub_module, nn.Conv2d):
        key_name = str(sub_module.weight.shape)
        fmap_dict.setdefault(key_name, list())

        n1, n2 = name.split(".")

        def hook_func(m, i, o):
            key_name = str(m.weight.shape)
            fmap_dict[key_name].append(o)

        alexnet._modules[n1]._modules[n2].register_forward_hook(hook_func)

# forward
output = alexnet(img_tensor)

# add image
for layer_name, fmap_list in fmap_dict.items():
    fmap = fmap_list[0]
    fmap.transpose_(0, 1)

    nrow = int(np.sqrt(fmap.shape[0]))
    fmap_grid = vutils.make_grid(fmap, normalize=True, scale_each=True, nrow=nrow)
    writer.add_image('feature map in {}'.format(layer_name), fmap_grid, global_step=322)

4.CAM

PyTorch的hook及其在Grad-CAM中的应用 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1368881.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go新手别再被切片复制坑了

概述 Go 语言中切片的复制是非常重要也比较容易让新手困惑的问题。本文将通过大量示例代码,全面介绍切片复制的相关知识,包括: 切片的结构 copy()函数的用法 切片复制的本质 浅复制和深复制的区别 如何实现切片深复制 copy()函数的常见用途 切片复制需要注意的几点 1. 切…

GB28181视频汇聚平台EasyCVR级联后,部分通道视频无法播放是什么原因?

GB28181协议智慧安防平台EasyCVR是基于各种IP流媒体协议传输的视频汇聚和融合管理平台。视频流媒体服务器EasyCVR采用了开放式的网络结构,支持高清视频的接入和传输、分发,平台提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制…

如何计算JMeter性能和稳定性测试中的TPS?

1、普通计算公式 TPS 总请求数 / 总时间 按照需求得到基础数据,比如在去年第xxx周,某平台有5万的浏览量那么总请求数我们可以估算为5万(1次浏览都至少对应1个请求) 总请求数 50000请求数 总时间:由于不知道每个请…

CAN FD和传统CAN的组网技术

在汽车领域,特别是新能源汽车技术的发展,对汽车内部的数据传输带宽提出了越来越高的要求,因此新的总线协议CAN FD应运而生,其最大传输速率可达8Mbps。然而由于历史原因以及成本因素,在相当长的一段时间内,传…

python 工作目录 与 脚本所在目录不一致

工作目录:执行脚本的地方 我以为工作目录会是当前执行脚本的目录位置,但其实不是,例如: 图中红色文件为我执行的脚本文件,但是实际的工作目录是PYTHON LEARNING 可以用如下代码查询当前工作目录: import os…

游戏引擎支持脚本编程有啥好处

很多游戏引擎都支持脚本编程。Unity、Unreal Engine、CryEngine等大型游戏引擎都支持使用脚本编写游戏逻辑和功能。脚本编程通常使用C#、Lua或Python等编程语言,并且可以与游戏引擎的API进行交互来控制游戏对象、设置变量、执行行为等。使用脚本编程,游戏…

【Proteus仿真】【Arduino单片机】路灯控制系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用LCD1602显示模块、人体红外传感器、光线检测模块、路灯继电器控制等。 主要功能: 系统运行后,LCD1602显示时间、工作…

TCP三次握手过程?

TCP三次握手过程? 分享 回答 1 浏览 3662 一颗小胡椒 2 CISM-WSE CISP-PTS 三次握手是 TCP 连接的建立过程。在握手之前,主动打开连接的客户端结束 CLOSE 阶段,被动打开的服务器也结束 CLOSE 阶段,并进入 LISTEN 阶段。随后进入…

LeetCode(209)长度最小的子数组⭐⭐

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。 示例: 输入:s 7, nums [2,3,1,2,4,3]输出:2…

Linux———head,tail命令详解(狠狠爱住)

目录 head 命令: head 命令基本语法: 常用选项 示例 显示文件的前 10 行: 显示文件的前 5 行: 显示文件的前 100 个字节: 不显示文件名的标题信息: 显示文件名的标题信息: tail 命令&…

网络原理OSI

目录 一、应用层 1、功能 2、协议的分类 二、UDP原理(传输层) 1、协议端格式 2、格式解释 三、TCP原理(传输层) 1、协议端格式 2、长度 3、可靠传输 (1)确认应答 (2)超时…

RBAC权限管理概念

基于RBAC模型的权限设计:如何设计系统权限体系? | 人人都是产品经理 一,什么是RBAC RBAC(基于角色的权限控制)模型的核心是在用户和权限之间引入了角色的概念。取消了用户和权限的直接关联,改为通过用户关联角色、角色关联权限的…

软件测试|MySQL主键自增详解:实现高效标识与数据管理

简介 在MySQL数据库中,主键自增是一种常见的技术,用于自动为表中的主键字段生成唯一的递增值。本文将深入讨论MySQL主键自增的原理、用途、使用方法,以及在实践中的注意事项和最佳实践。 主键自增 主键自增的原理 主键自增是通过使用AUTO…

蓝桥杯 python 第二题 数列排序

这里给出一种解法 """ # 错的 n int(input()) dp[int(i) for i in input().split(" ")] dp.sort() print(" ".join(str(i) for i in dp)) """#这个是对的 num int(input())l list(map(int, input().split()))l.sort()pr…

CLIP论文总结

文章目录 NLP的积淀Method1. 预训练的方法:放宽约束:对比学习2. 模型训练训练时间 ExperimentsMotivationPrompt:提示:也就是文本的引导作用Prompt enginneringPrompt ensembling 对比实验 NLP的积淀 取之不尽用之不竭的自监督信…

常孝元宇宙《神由都城》发布会成功召开

2024年1月9日,2024常孝元宇宙《神由都城》发布会在北京市中国科技会堂举办,由中国移动通信联合会元宇宙产业工作委员会主办,常州神由之星数字信息产业发展有限公司、常州孝道文化产业股份有限公司共同承办。 本次发布会以“创新引领、协同发展”为主题,邀请第十二届全国政协副主…

海淘注意事项科普

关税和税费: 在海淘过程中,您可能需要支付关税和其他税费。了解目标国家的相关规定,预先了解可能的费用,并确保考虑到这些额外成本。 货币汇率: 注意货币汇率的波动,以避免因兑换率变化导致支付更多费用。…

Unity | Shader基础知识(第九集:shader常用单词基础知识速成)

目录 一、顶点(Vertex)和法线(Normal) 二、UV信息 三、 基础数据种类 1 基础数据种类 2 基础数据数组 3 基础数据数组的赋值 4 对数据数组的调用 四、 基础矩阵 1 基础矩阵种类 2 对矩阵数组的调用 2.1对一个数据的调用 2.2对多个数据的调用 2…

【华为】IPsec VPN 实验配置(动态地址接入)

【华为】IPsec VPN 实验配置(动态地址接入) 注意实验需求配置思路配置命令拓扑R1基础配置配置第一阶段 IKE SA配置第二阶段 IPsec SA ISP_R2基础配置 R3基础配置配置第一阶段 IKE SA配置第二阶段 IPsec SA PCPC1PC2 检查建立成功查看命令清除IKE / IPsec…