[ML] Pytorch自学实战项目其3.1:超参数调优 可视化工具TensorBoard用实际例子从零开始使用

写在前面

避免原文过长便于查询,单独把超参数调整做笔记,回头再去调整我的模型

计划调节顺序为,用一个为调节而设立的demo 先是建立可视化然后下次把列表更新使用hyperopt调节

最后下一篇文章上,套用在我的Yawrated Demo上

outline

  • [X ]TensorBox: 在tensorflow下简单示例 在pytorch下demo实际演练
  • 套用在我的RNN学习yawrate上 :下篇在文章3.2中
  • hyperopt&&earlystop 看情况下期是否更新

学习资源

目前链接有点多,依据实用性质慢慢删除

知乎上对于超参数调整一个全面的总结:
https://zhuanlan.zhihu.com/p/654736778
早停标志的介绍:链接
实际例子来说明早停和学习率下降:https://www.zhihu.com/tardis/zm/art/424702158?source_id=1005
TensorBoard教程:https://blog.csdn.net/flyfor2013/article/details/112300883
Hyperopt官网:https://hyperopt.github.io/hyperopt/getting-started/search_spaces/
我用来学习安装TensorBoard的链接

TensorBoard

我的问题:(都解答了在文章中)

1. 我没有显式传入要显示的参数,这样就自动实现了?
2. 如果pytorch中怎么使用
3. 怎么设定自己想观察的参数

TensorBoard 调试练习 (Tensorflow下)

参考于https://zhuanlan.zhihu.com/p/471198169 写的很不错,但我最后要基于pytorch来做。文章里对于torsorboard图的含义的解读很好。

如果使用的是tensorflow其流程可以总结为:创建回调、指定一个目录来记录数据、在调用 fit 方法时传递回调。

基于以下代码

import tensorflow as tf 
 
# Load and normalize MNIST data 
mnist_data = tf.keras.datasets.mnist 
(X_train, y_train), (X_test, y_test) = mnist_data.load_data() 
X_train, X_test = X_train / 255.0, X_test / 255.0 
 
# Define the model 
model = tf.keras.models.Sequential([ 
tf.keras.layers.Flatten(input_shape=(28, 28)), 
tf.keras.layers.Dense(128, activation='relu'), 
tf.keras.layers.Dropout(0.2), 
tf.keras.layers.Dense(10, activation='softmax') 
]) 
 
# Compile the model 
model.compile( 
optimizer='adam', 
loss='sparse_categorical_crossentropy', 
metrics=['accuracy'])
tf_callback = tf.keras.callbacks.TensorBoard(log_dir="./TBlogs")


model.fit(X_train, y_train, epochs=5, callbacks=[tf_callback])

按照教程配置了环境,并且在本地命令行使用

tensorboard --logdir=./TBlogs

在这里插入图片描述

自定义观测量

使用Summary API(在pytorch下基本靠他)
以下代码也是参考自链接

import numpy as np
# Specify a directory for logging data 
logdir = "./TB2logs" 
 
# Create a file writer to write data to our logdir 
file_writer = tf.summary.create_file_writer(logdir) 
 
# Loop from 0 to 199 and get the sine value of each number 
for i in range(200): 
    with file_writer.as_default(): 
        tf.summary.scalar('sine wave', np.math.sin(i), step=i)

可以画出自定义的图

TB如何与Pytorch 互动

这里用一个自建的例子尝试了对pytorch如何使用TB,

我的结果
在这里插入图片描述在这里插入图片描述

我的例子代码

import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.tensorboard import SummaryWriter
from torch import nn
import torch.optim as optim

# 设置TensorBoard
writer = SummaryWriter('runs/fashion_mnist_experiment_1')

# 加载数据
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True)
# transform = ...: 定义了一个变换序列,将图像转换为PyTorch张量,并对图像进行标准化处理。
# trainset = torchvision.datasets.FashionMNIST(...): 
# 加载FashionMNIST数据集,并应用前面定义的变换。

# 定义一个简单的神经网络
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(28 * 28, 64)
        self.fc2 = nn.Linear(64, 10)

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

net = Net()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

# 训练网络
for epoch in range(1):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data

        optimizer.zero_grad()

        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

        # 每1000个batch记录一次数据
        if i % 1000 == 999:    
            print(f"[{epoch + 1}, {i + 1}] loss: {running_loss / 1000:.3f}")
            writer.add_scalar('training loss', running_loss / 1000, epoch * len(trainloader) + i)
            running_loss = 0.0

print('Finished Training')

# 关闭writer
writer.close()

针对上面的例子使用更复杂的功能

使用直方图观察我的参数

方法1:

# 记录每个感兴趣的层的参数
    if epoch % 3 == 2:

                for name, param in net.named_parameters():
                    writer.add_histogram(name, param.clone().cpu().data.numpy(), epoch)

或者方法2:

#每一千次一下fc1层的权重效果
if i % 1000 == 999:    
        writer.add_histogram('weight of fc1', net.fc1.weight, epoch * len(trainloader) + i)

如何显示一次训练但跨越了不同的Epoch的结果

没有查询到到特殊的做法,目前通过使用代码,先处理好结果获取想要显示的形式,再传入画图API的做法,但是如此不使用TB 而用其他画图的库也可以做到,用TB的意义何在

同时使用直方图查看我的模型参数在训练中的变化
在这里插入图片描述
这里我使用了以上两种不同的方式,

  • 自己命名以及使用for循环自动读取模型所有参数。在实验的时候我自己命令读取的方式记录了一个epoch的每1000个为一组的结果,为了避免被覆盖我乘上了epoch的数量。

  • 第二个方式我只对比了epoch整体结尾时候的参数状态

在这里插入图片描述

如何对比使用了不同超参数比如不同batchsize的结果

貌似要跑三次不同的结果,然后保存在不同的log中,在同一个文件夹子下,然后打开父文件夹这样子来对比。。。。。

那么自动化一点就是在代码里设定列表的超级参数,遍历的时候同时在不同循环层级保存不同的参数,放在同一个文件夹下的不同子文件夹下(后发现可以使用comment来在同一个子文件夹子下实现)

以下例子中我修改了epoch来做了不同的实验

在这里插入图片描述
在这里插入图片描述确实可以,他会自动递归向子文件夹读取对应类型的文件输出
在这里插入图片描述如此看还是有点便利的

如何对比以前跑的结果(其实就是以上几种情况的总结和实现自动化)

方法如下

基本逻辑是:每一个循环用list元素来控超参,把原来使用超级参的东西放在循环内,每一个cycle设定一个writer,同时设定comment 来改文件夹名区分不同的循环的结果

# 设置TensorBoard saving path 
log_dir='runs/fashion_mnist_experiment_3'




#set super Para List 
batch_size_list = [5, 10]
lr_list = [.01, .001]

for batch_size in batch_size_list:
    for lr in lr_list:
        # Setting comment and creat writer
        comment = f'batch_size={batch_size} lr={lr}'
        writer = SummaryWriter(log_dir=f'{log_dir}/{comment}')

在这里插入图片描述

在这里插入图片描述到此为止可以很直观的看出不同参数组合的训练效果了!

附录 记录常用summeray writer API

Browsing

TensorBoard 的 SummaryWriter 是 PyTorch 中一个非常有用的工具,用于记录训练过程中的不同类型的数据,以便在 TensorBoard 上进行可视化。下面我将列举一些常用的 API 和它们的用法:

  1. add_scalar

    用途:记录标量数据,如损失值、准确率等。
    参数:
    tag:标量的名称。
    scalar_value:标量的值。
    global_step:可选,标量记录的步数(如迭代次数)。

  2. add_image

    用途:记录图像数据。
    参数:
    tag:图像的标签。
    img_tensor:图像数据,可以是 torch.Tensor、numpy.ndarray 或 PIL.Image。
    global_step:可选,记录的步数。
    dataformats:可选,描述图像数据的布局。

  3. add_graph

    用途:记录模型的计算图。
    参数:
    model:PyTorch 模型。
    input_to_model:模型的输入数据。

  4. add_histogram

    用途:记录参数或层的分布情况,例如权重或梯度的分布。
    参数:
    tag:直方图的标签。
    values:需要记录的数据。
    global_step:可选,记录的步数。
    bins:可选,直方图的分箱数量。

  5. add_figure

    用途:记录 matplotlib 图形。
    参数:
    tag:图形的标签。
    figure:matplotlib.figure.Figure 对象。
    global_step:可选,记录的步数。

  6. add_video

    用途:记录视频数据。
    参数:
    tag:视频的标签。
    vid_tensor:视频数据,形状为 (N, C, T, H, W),其中 N 是批量大小,C 是通道数,T 是帧数,H 和 W 是高度和宽度。
    global_step:可选,记录的步数。
    fps:可选,每秒帧数。

  7. add_audio

    用途:记录音频数据。
    参数:
    tag:音频的标签。
    snd_tensor:音频数据,形状为 (1, N) 或 (N, ),其中 N 是音频样本数。
    global_step:可选,记录的步数。
    sample_rate:音频的采样率。

  8. add_text

    用途:记录文本数据。
    参数:
    tag:文本的标签。
    text_string:文本内容。
    global_step:可选,记录的步数。

附录2 我的全代码


import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.tensorboard import SummaryWriter
from torch import nn
import torch.optim as optim

# 设置TensorBoard saving path 
log_dir='runs/fashion_mnist_experiment_3'

# 加载数据
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = torchvision.datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)


#set super Para List 
batch_size_list = [5, 10]
lr_list = [.01, .001]

for batch_size in batch_size_list:
    for lr in lr_list:
        # Setting comment and creat writer
        comment = f'batch_size={batch_size} lr={lr}'
        writer = SummaryWriter(log_dir=f'{log_dir}/{comment}')

        trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True,drop_last = True)
        # transform = ...: 定义了一个变换序列,将图像转换为PyTorch张量,并对图像进行标准化处理。
        # trainset = torchvision.datasets.FashionMNIST(...): 
        # 加载FashionMNIST数据集,并应用前面定义的变换。

        # 定义一个简单的神经网络
        class Net(nn.Module):
            def __init__(self):
                super(Net, self).__init__()
                self.fc1 = nn.Linear(28 * 28, 64)
                self.fc2 = nn.Linear(64, 10)

            def forward(self, x):
                x = x.view(-1, 28 * 28)
                x = torch.relu(self.fc1(x))
                x = self.fc2(x)
                return x

        net = Net()



        # 定义损失函数和优化器
        criterion = nn.CrossEntropyLoss()
        optimizer = optim.SGD(net.parameters(), lr=lr, momentum=0.9)

        # 训练网络
        for epoch in range(2):
            running_loss = 0.0
            for i, data in enumerate(trainloader, 0):
                inputs, labels = data

                optimizer.zero_grad()

                outputs = net(inputs)
                loss = criterion(outputs, labels)
                loss.backward()
                optimizer.step()

                running_loss += loss.item()

                # 每1000个batch记录一次数据
                if i % 1000 == 999:    
                    print(f"[{epoch + 1}, {i + 1}] loss: {running_loss / 1000:.3f}")
                    writer.add_scalar('training loss', running_loss / 1000, epoch * len(trainloader) + i)
                    #writer.add_histogram('weight of fc1', net.fc1.weight, epoch * len(trainloader) + i)
                    running_loss = 0.0
            if epoch % 2 == 1 or 0:
                    # 记录每个感兴趣的层的参数
                    for name, param in net.named_parameters():
                        writer.add_histogram(name, param.clone().cpu().data.numpy(), epoch) # 我这里没有设置为GPU 可以不用后面的操作
        print(f'Finished Training in with lr :{lr} BS:{batch_size}')

        # 关闭writer
        writer.close()



  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值