P23_ 优化器(一)
23.1打开官网:torch.optim
1.优化器的使用
(1)构造优化器
放入模型参数、学习速率
(2)调用优化器的step方法
optimizer.zero_grad()一定要写
(3)优化器算法
params:参数,lr:学习速率(learning rate)
23.2代码实战:
1.复制nn_loss_network的代码
(1)前面:
加载数据集dataset,将其转成tensor数据类型,用dataloader进行加载,创建相应的网络,并计算出loss,再搭建了相应的网络:
现在:设置优化器
(2)随机梯度下降SGD
optim = torch.optim.SGD(dyl_seq.parameters(),lr = 0.01)
2.优化器SGD的使用
(1)输入代码
点击查看代码
import torch
import torchvision.transforms
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential#定义数据集
from torch.utils.data import DataLoaderdataset = torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=1)#定义神经网络
class DYL_seq(nn.Module):def __init__(self):super(DYL_seq, self).__init__()self.model1 = Sequential(Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),MaxPool2d(kernel_size=2),Conv2d(32, 32, 5, padding=2),MaxPool2d(kernel_size=2),Conv2d(32, 64, 5, padding=2),MaxPool2d(kernel_size=2),Flatten(),Linear(1024, 64),Linear(64, 10))def forward(self,x):x = self.model1(x)return xloss = nn.CrossEntropyLoss()#创建网络
dyl_seq = DYL_seq()#创建优化器
optim = torch.optim.SGD(dyl_seq.parameters(),lr = 0.01)#从dataloader去取数据
for data in dataloader:imgs,targets = data#再把数据送到网络当中:outputs = dyl_seq(imgs)#计算出网络的输出和真实的target的差距result_loss = loss(outputs,targets)#梯度调为0optim.zero_grad()#反向传播:得到每一个可调节参数的对应的梯度result_loss.backward()#对每一个参数进行调优optim.step()print(result_loss)
(2)运行结果
点击查看代码
Files already downloaded and verified
tensor(2.2236, grad_fn=<NllLossBackward0>)
tensor(2.1527, grad_fn=<NllLossBackward0>)
tensor(2.0960, grad_fn=<NllLossBackward0>)
tensor(2.4661, grad_fn=<NllLossBackward0>)
tensor(2.3052, grad_fn=<NllLossBackward0>)
......
运行结果是在每个节点上的loss的变化,但是loss似乎并没有减小:
因为dataloader就是在网络模型对数据只看了一遍,现在看到的数据对于下次看到数据预测的影响不大
解决方法:
对数据进行多轮学习,在for循环外再套一层循环:epoch
3.多轮学习的设置
(1)外层嵌套轮次的for循环
点击查看代码
for epoch in range(20):running_loss = 0.0#从dataloader去取数据for data in dataloader:imgs,targets = data#再把数据送到网络当中:outputs = dyl_seq(imgs)#计算出网络的输出和真实的target的差距result_loss = loss(outputs,targets)#梯度调为0optim.zero_grad()#反向传播:得到每一个可调节参数的对应的梯度result_loss.backward()#对每一个参数进行调优optim.step()running_loss = running_loss + result_lossprint(running_loss)
(2)整体流程
点击查看代码
对于每一个轮次 (Epoch):①初始化总损失为 0。②对于数据集中的每一个批次 (Batch):a. 取出一个批次的图片和标签。b. 将图片输入模型,得到模型的预测输出。(前向传播)c. 用损失函数计算预测输出和真实标签的差距。d. 清空上一次的梯度。e. 反向传播,计算出每个参数的梯度。f. 根据梯度,更新模型的所有参数。(优化器.step ())g. 将这个批次的损失累加到总损失上。③一轮结束后:a. 打印出本轮的总损失。
(3)每一轮学习过程中
外层循环:控制训练的轮次
内层循环:遍历整个数据集
①for epoch in range(20):
模型会把整个 CIFAR-10 测试集看 20 遍
【因为只看一遍数据,模型学不会复杂的模式。它需要反复地观察、学习,才能不断调整内部的参数(权重和偏置),从而提高预测的准确率。】
②解包数据:imgs, targets = data
把 data 元组里的两个部分分开,分别赋值给 imgs 和 targets
其中:
imgs: PyTorch 的张量(Tensor),设置其形状是 [1, 3, 32, 32],即 “1 张 3 通道(RGB)的32x32 像素的图片”;
targets:这也是一个张量,形状是 [batch_size]。对于 CIFAR-10,它的值是一个 0 到 9 之间的整数,表示这张图片对应的类别(比如 0 是飞机,1 是汽车等);
③前向传播:outputs = dyl_seq(imgs)
④反向传播
点击查看代码
optim.zero_grad() # 1. 清空之前的梯度
result_loss.backward() # 2. 计算梯度
⑤参数更新:optim.step()
⑥累加损失:running_loss = running_loss + result_loss
在每一轮(epoch)开始时,我们把变量running_loss初始化为 0;对于每一个批次,我们都把这个批次的损失 result_loss 加到 running_loss 上;
这样,当整个 epoch 结束时,running_loss 就等于这个轮次中所有图片的损失之和。
打印它可以让我们直观地看到,随着训练轮次的增加,模型的总损失是不是在下降,从而判断训练是否有效。
(4)print打印结果
点击查看代码
Files already downloaded and verified
tensor(18790.3555, grad_fn=<AddBackward0>)
tensor(16177.8945, grad_fn=<AddBackward0>)
tensor(15394.5410, grad_fn=<AddBackward0>)
tensor(15897.9082, grad_fn=<AddBackward0>)
tensor(17882.6699, grad_fn=<AddBackward0>)
tensor(20084.4277, grad_fn=<AddBackward0>)
tensor(22518.1348, grad_fn=<AddBackward0>)
tensor(23672.5508, grad_fn=<AddBackward0>)
tensor(24243.7734, grad_fn=<AddBackward0>)
tensor(25187.7676, grad_fn=<AddBackward0>)
tensor(25525.9375, grad_fn=<AddBackward0>)
tensor(26094.1387, grad_fn=<AddBackward0>)
tensor(26918.0039, grad_fn=<AddBackward0>)
tensor(27612.7695, grad_fn=<AddBackward0>)
tensor(29427.4512, grad_fn=<AddBackward0>)
tensor(30726.7402, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)
tensor(nan, grad_fn=<AddBackward0>)进程已结束,退出代码0
可见,核心问题是梯度爆炸
①前几轮:损失在下降,模型正常学习。
②中间轮次:损失开始回升并剧烈震荡,说明梯度已经开始不稳定。
③最后几轮:损失值变成 nan(Not a Number,不是一个数字),训练彻底崩溃。
④如何解决?
使用训练集进行训练:train=True;
增大 batch_size:例如 batch_size=64;
添加激活函数:在每个卷积层和全连接层后添加 nn.ReLU();
降低学习率:例如 lr=0.001;
使用动量(Momentum):momentum=0.9,帮助稳定训练;
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/973821.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!