训练代码
导入数据部分
train_data = torchvision.datasets.MNIST(
root="./data/FashionMNIST",
train=True,
transform=torchvision.transforms.ToTensor(),
download=False
)
train_loader = Data.DataLoader(
dataset=train_data,
batch_size=128,
shuffle=True,
num_workers=0,
# pin_memory=True # 将内存的tensor转移到gpu
)
训练部分
MyConvNet = ConvNet().to(device)
# 定义优化器
optimizer = torch.optim.Adam(MyConvNet.parameters(), lr=0.003)
# 交叉熵损失函数
loss_func = nn.CrossEntropyLoss()
loss_func = loss_func.to(device)
train_loss = 0
train_loss = train_loss
print_step = 100 # 每经过100次迭代之后输出损失
# 对模型进行迭代训练,对所有的数据训练epoch轮
for epoch in range(10):
print(train_loss)
# 对训练数据的加载器进行迭代计算
for step, (b_x, b_y) in enumerate(train_loader):
b_x = b_x.to(device)
b_y = b_y.to(device)
# 计算每个batch的损失
output = MyConvNet(b_x) # 卷积神经网络计算得出的结果
loss = loss_func(output, b_y) # 交叉熵损失函数
optimizer.zero_grad() # 每个迭代步的梯度初始化为0
loss.backward() # 后向传播
optimizer.step() # 使用梯度进行优化
train_loss = train_loss + loss # 损失求和
需要注意的是书上使用cpu训练,如果要使用gpu训练,必须把网络和训练过程中用到的所有参数放到gpu里。方法就是.to(device)。这里的device是显卡的序列号。
还有就是如果想知道自己设置的变量是在cpu还是gpu,可以用 print(data.is_cuda),打印出来的是true则是在gpu里。
训练集一共有60000张图片,batch_size=128,那train_loader就是60000/128=468yu96。也就是说train_loader里有469个分组,前468组里面有128张图片,469组有96张。
这里用的应该是mini_batch。那就是每训练一个epoch,step都会从0一直到468,每一次step都会训练128张图片,并求出这128张图片的损失,然后用bp算法更新参数,然后将损失累加到train_loss。这些做完之后就进入下一个step,如果算法没问题的话,loss会越来越小,train_loss的增长速度也会越来越慢,最后会趋于水平。
最后的train_loss求和就是求得60032张图片的损失和。但是这里为什么不在运行一个epoch之后将train_loss清零呢?不清零的话train_loss不就会越来越大吗。
tensorboardx可视化代码
# 计算迭代次数
niter = epoch * len(train_loader) + step + 1
# 计算每经过print_step次迭代后的输出
if niter % print_step == 0:
# 为日志添加训练集损失函数
SumWriter.add_scalar("train loss", train_loss.item() / niter, global_step=niter)
# 计算在测试集上的精度
# torch.cuda.empty_cache()
output = MyConvNet(test_data_x)
_, pre_lab = torch.max(output, 1)
pre_lab = pre_lab.cpu()
test_data_y = test_data_y.cpu()
acc = accuracy_score(test_data_y, pre_lab)
# 为日志中添加在测试集上的预测精度
SumWriter.add_scalar("test acc", acc.item(), niter)
# 为日志中添加训练数据的可视化图像,使用当前batch的图像
# 将一个batch的数据进行预处理
b_x_im = vutils.make_grid(b_x, nrow=12)
SumWriter.add_image('train image sample', b_x_im, niter)
# 使用直方图可视化网络中参数的分布情况
for name, param in MyConvNet.named_parameters():
param = param.cpu().detach()
SumWriter.add_histogram(name, param.data.numpy(), niter)
这里的 niter = epoch * len(train_loader) + step + 1,我没理解错的话,算的是训练了多少次 “一组128张图片”,这里最大迭代次数应该是469*10=4690次。
_, pre_lab = torch.max(output, 1) 这个函数的解释见下链接
添加链接描述
然后这里画train_loss的图像的时候,是train_loss/niter,是求的平均损失。由于train_loss增长速度会越来越慢,train_loss/niter也会也来越小。
查看可视化
在log文件所在目录下打开cmd,输入tensorboard --logdir="log"
回车即可。
将这个网址复制到浏览器中就可以看到训练过程的图片了,需要注意的是,网页打开时,cmd千万不要停止运行或关掉。这样的话网页可能会打不开。