写在前面
避免原文过长便于查询,单独把超参数调整做笔记,回头再去调整我的模型
计划调节顺序为,用一个为调节而设立的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 和它们的用法:
-
add_scalar
用途:记录标量数据,如损失值、准确率等。
参数:
tag:标量的名称。
scalar_value:标量的值。
global_step:可选,标量记录的步数(如迭代次数)。 -
add_image
用途:记录图像数据。
参数:
tag:图像的标签。
img_tensor:图像数据,可以是 torch.Tensor、numpy.ndarray 或 PIL.Image。
global_step:可选,记录的步数。
dataformats:可选,描述图像数据的布局。 -
add_graph
用途:记录模型的计算图。
参数:
model:PyTorch 模型。
input_to_model:模型的输入数据。 -
add_histogram
用途:记录参数或层的分布情况,例如权重或梯度的分布。
参数:
tag:直方图的标签。
values:需要记录的数据。
global_step:可选,记录的步数。
bins:可选,直方图的分箱数量。 -
add_figure
用途:记录 matplotlib 图形。
参数:
tag:图形的标签。
figure:matplotlib.figure.Figure 对象。
global_step:可选,记录的步数。 -
add_video
用途:记录视频数据。
参数:
tag:视频的标签。
vid_tensor:视频数据,形状为 (N, C, T, H, W),其中 N 是批量大小,C 是通道数,T 是帧数,H 和 W 是高度和宽度。
global_step:可选,记录的步数。
fps:可选,每秒帧数。 -
add_audio
用途:记录音频数据。
参数:
tag:音频的标签。
snd_tensor:音频数据,形状为 (1, N) 或 (N, ),其中 N 是音频样本数。
global_step:可选,记录的步数。
sample_rate:音频的采样率。 -
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()