赞
踩
就只是贴了一个代码,部分解释写在代码注释里面了,之后会补上文字解释:
- import torch
- import torchvision
- import time #用于计时的
- from torch import nn
- from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
- from torch.utils.data import DataLoader
-
- """
- 方法一:
- 想要使用GPU训练:那么在 "网络模型的实体" 、 "从Dataoader中加载的数据" 、 "损失函数实体" 都是可以 .cuda()来表明时可以使用GPU的
- 并且,网络模型的实体 、 损失函数实体 是可以 不去赋值的
- 即: 可以写为 z1 = z1.cuda() 也可以直接略写为 z1.cuda()
- PS 对于这种方式,其实为了增强容错,可以加一句:
- if torch.cuda.is_available() :
- z1 = z1.cuda()
- loss_fn = loss_fn.cuda()
- imgs = imgs.cuda()
- targets = targets.cuda()
- """
-
-
- #定义一个名为Zch的神经网络模型的类 ,之所以是神经网络模型的类是因为Zch继承了nn.Module
- class Zch(nn.Module):
- def __init__(self):
- super(Zch, self).__init__()
- self.module1 = Sequential(
- Conv2d(3, 32, 5, padding=2) ,
- MaxPool2d(2) ,
- Conv2d(32, 32, 5, padding=2) ,
- MaxPool2d(2) ,
- Conv2d(32, 64, 5, padding=2) ,
- MaxPool2d(2) ,
- Flatten() , # torch对于在nn.Module中也有专门的flatten函数,torch.nn.Flatten()
- Linear(1024, 64) ,
- Linear(64, 10)
- )
-
- #对于神经网络模型,虽说训练时要一来一回 : (来:)需要前向传播计算loss,grad ; (回:)需要反向传播时修正模型中的参数
- #但显然,通过前想传播就可以构造出计算图了(计算的流程图了) , 所以 ,反向传播写在神经网络类的定以外就可以了(而且反响传播人家pytorch已经集装好了,两条函数调用就可以了)
- def forward(self,x):
- output = self.module1(x)
- return output
-
-
- #引入(下载)torch官方已经整理好的数据集CIFAR10
- train_dataset = torchvision.datasets.CIFAR10("dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是训练数据集;
- test_dataset = torchvision.datasets.CIFAR10("dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是测试数据集;
- #展示train_dataset 、 test_dataset 的长度
- print( len( train_dataset ) )
- print( len( test_dataset ) )
-
- #通过DataLoader类实例化训练集数据和测试集数据的Dataloader数据加载器
- train_dataloader = DataLoader(train_dataset,batch_size=64)
- test_dataloader = DataLoader(test_dataset,batch_size=64)
-
-
- z1 = Zch() # 实例化模型,我们得把训练的数据塞到一个实例出来的模型中去
- z1 = z1.cuda() # 将模型变为cuda模式: z1.cuda()
-
- loss_fn = nn.CrossEntropyLoss() # 定义(实例化) 损失函数,由于CIFAR10是一个10分类问题,所以将损失函数实例化为一个交叉熵计算工具,用于计算预测值和真实值之间的差距loss , 并可以通过调用.backward()来根据loss计算出模型中的各个参数的梯度grad
- loss_fn = loss_fn.cuda() #损失函数也是可以转换为cuda形式的 : loss_fn.cuda()
-
- learning_rate = 1e-2 # 1e-2 就是0.01的意思,这样更好看、直观。并且,learning_rate是一个学习是比较重要的参数,所以,但提出来,方便查找和修改
- optim = torch.optim.SGD(z1.parameters() , lr=learning_rate) #定义(实例化)一个优化器,把模型的实例z1的参数与optim绑定,好让优化器知道 该通过loss_fn.backward()计算出的grad 来去修正谁
-
- #一般会训练多个epoch (1个epoch就是一个全数据集走一遍)
- epoch = 10 # 训练的轮数
- train_step = 0
- test_step = 0
-
- #计算训练时间
- start_time = time.time()
-
- for idx in range(epoch):
- #训练开始:
- z1.train() #对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
- for data in train_dataloader :
- imgs,labels = data #由于CIFAR10是一个10分类问题,所以对于每个图片他都是输出一个数值代表一个类别。由于我们设置batch_size=64 , 所以,labels就算一个长度为64的1维度tensor向量
- imgs = imgs.cuda() #对于数据来说就必须得赋值了,无法略写为 imgs.cuda() 或 labels.cuda()
- labels = labels.cuda() #labels同理
-
- outputs = z1(imgs)
- loss = loss_fn(outputs , labels) # 计算得到loss
- #接下来准备用优化器根据loss调用backward()函数 求出的 grad 来对模型参数进行更新 。
- #【注意】由于我们是在一套循环里面反复调用优化器对模型参数进行更新,为了避免上一轮的干扰,每次在loss计算相应的grad前,先将优化器的内容清空
- optim.zero_grad()
- loss.backward() #根据计算得到的loss计算出对应的grad
- optim.step() #调用优化器,根据 loss.backward()求得的grad 对模型参数进行更新
- train_step += 1
- tt_time = time.time()
- if train_step % 100 == 0 :
- print("第",train_step,"次训练迭代时,loss为:",loss.item()) #loss.item()和loss的区别在于:区别不大,略
- print("到第", train_step, "次训练迭代时,耗时:", tt_time-start_time)
-
- #测试开始 :
- #如何确认训练的模型是否有效呢? -- 通过测试数据集:测试集数据 传入 刚刚在训练的模型 ,查看其准确率,毕竟loss没有准确率来的直观
- z1.eval() # 对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
- with torch.no_grad() : #在测试的时候就不需要对模型进行调优了,所以我们需要写明no_grad()
- test_total_loss = 0
- test_total_accuracy = 0 #在一轮epoch中可以正确预测多少个图片分类
- for data in test_dataloader :
- imgs , targets = data
- imgs = imgs.cuda()
- targets = targets.cuda()
-
- outputs = z1(imgs)
- #计算loss
- loss = loss_fn(outputs , targets)
- test_total_loss += loss
- #计算accuracy
- #labels是一个1维的64元素的tensor,我们的outputs是一个2维的64*10的tensor,64是batchsize大小,而10是因为我们的输出是经网络训练后,该张图片是10分类中的各个分类的概率
- outputs = outputs.argmax(1) #找到一维array中的最大值,并返回该最大值所在的array的下标 ; 参数为0意味着一列列对比,参数为1意味着一行行对比
- accuracy = (outputs == targets).sum()
- test_total_accuracy += accuracy
-
- print("第",idx,"轮测试集上的总loss是:",test_total_loss.item()) #不加.item()输出是:tensor(311.6063) 而非 311.6063 就很乱
- print("第", idx, "轮测试集上的总accuracy是:", test_total_accuracy.item())
-
-
-
-
-
-
-
- # #补充解释一下求解accuracy时的公式: accuracy = (outputs == targets).sum()
- # a1 = torch.tensor([1,3,5,7])
- # b1 = torch.tensor([1,36,15,7])
- #
- # res = (a1 == b1) #因为两个tensor相 == 就是会返回一个元素是True或者False的tensor阿
- # print(res)
- # print(res.sum()) #该元素是True或者False的tensor的调用sum()函数返回该tensor中所有的True值的加和
-
- import torch
- import torchvision
- import time #用于计时的
- from torch import nn
- from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
- from torch.utils.data import DataLoader
-
- """
- 方法二:
- 使用.to(device)来定义训练的设备
- 方法二 和 方法一 相同,想要使用GPU训练:也是只能在 "网络模型的实体" 、 "从Dataoader中加载的数据" 、 "损失函数实体" 上做文章,将其通过.to()传送至对应的device上
- 并且,网络模型的实体 、 损失函数实体 是可以 不去赋值的
- 即: 可以写为 z1 = z1.to(device) 也可以直接略写为 z1.to(device)
- PS 对于这种方式,其实为了增强容错,更合适的做法是:
- if torch.cuda.is_available() :
- device = torch.device("cuda:0") # 和 device = torch.device("cuda") 在只有一个GPU时是完全没有差别的
- else :
- device = torch.device("cpu")
- 或者利用语法糖,简单地写为:
- device = torch.drvice( "cuda" if torch.cuda.is_availabel() else "cpu" )
- """
-
-
-
- #定义一个名为Zch的神经网络模型的类 ,之所以是神经网络模型的类是因为Zch继承了nn.Module
- class Zch(nn.Module):
- def __init__(self):
- super(Zch, self).__init__()
- self.module1 = Sequential(
- Conv2d(3, 32, 5, padding=2) ,
- MaxPool2d(2) ,
- Conv2d(32, 32, 5, padding=2) ,
- MaxPool2d(2) ,
- Conv2d(32, 64, 5, padding=2) ,
- MaxPool2d(2) ,
- Flatten() , # torch对于在nn.Module中也有专门的flatten函数,torch.nn.Flatten()
- Linear(1024, 64) ,
- Linear(64, 10)
- )
-
- #对于神经网络模型,虽说训练时要一来一回 : (来:)需要前向传播计算loss,grad ; (回:)需要反向传播时修正模型中的参数
- #但显然,通过前想传播就可以构造出计算图了(计算的流程图了) , 所以 ,反向传播写在神经网络类的定以外就可以了(而且反响传播人家pytorch已经集装好了,两条函数调用就可以了)
- def forward(self,x):
- output = self.module1(x)
- return output
-
-
- #引入(下载)torch官方已经整理好的数据集CIFAR10
- train_dataset = torchvision.datasets.CIFAR10("dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是训练数据集;
- test_dataset = torchvision.datasets.CIFAR10("dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是测试数据集;
- #展示train_dataset 、 test_dataset 的长度
- print( len( train_dataset ) )
- print( len( test_dataset ) )
-
- #通过DataLoader类实例化训练集数据和测试集数据的Dataloader数据加载器
- train_dataloader = DataLoader(train_dataset,batch_size=64)
- test_dataloader = DataLoader(test_dataset,batch_size=64)
-
- #定义训练的设备:
- device_cpu = torch.device("cpu")
- device_gpu = torch.device("cuda:0")
-
-
- z1 = Zch() # 实例化模型,我们得把训练的数据塞到一个实例出来的模型中去
- z1 = z1.to(device_gpu) # 将模型发送到device上执行
-
- loss_fn = nn.CrossEntropyLoss() # 定义(实例化) 损失函数,由于CIFAR10是一个10分类问题,所以将损失函数实例化为一个交叉熵计算工具,用于计算预测值和真实值之间的差距loss , 并可以通过调用.backward()来根据loss计算出模型中的各个参数的梯度grad
- loss_fn = loss_fn.to(device_gpu) # 将损失函数发送到device上执行
-
- learning_rate = 1e-2 # 1e-2 就是0.01的意思,这样更好看、直观。并且,learning_rate是一个学习是比较重要的参数,所以,但提出来,方便查找和修改
- optim = torch.optim.SGD(z1.parameters() , lr=learning_rate) #定义(实例化)一个优化器,把模型的实例z1的参数与optim绑定,好让优化器知道 该通过loss_fn.backward()计算出的grad 来去修正谁
-
- #一般会训练多个epoch (1个epoch就是一个全数据集走一遍)
- epoch = 10 # 训练的轮数
- train_step = 0
- test_step = 0
-
- #计算训练时间
- start_time = time.time()
-
- for idx in range(epoch):
- #训练开始:
- z1.train() #对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
- for data in train_dataloader :
- imgs,labels = data #由于CIFAR10是一个10分类问题,所以对于每个图片他都是输出一个数值代表一个类别。由于我们设置batch_size=64 , 所以,labels就算一个长度为64的1维度tensor向量
- imgs = imgs.to(device_gpu) #对于数据来说就必须得赋值了,无法略写为 imgs.cuda() 或 labels.cuda()
- labels = labels.to(device_gpu) #labels同理
-
- outputs = z1(imgs)
- loss = loss_fn(outputs , labels) # 计算得到loss
- #接下来准备用优化器根据loss调用backward()函数 求出的 grad 来对模型参数进行更新 。
- #【注意】由于我们是在一套循环里面反复调用优化器对模型参数进行更新,为了避免上一轮的干扰,每次在loss计算相应的grad前,先将优化器的内容清空
- optim.zero_grad()
- loss.backward() #根据计算得到的loss计算出对应的grad
- optim.step() #调用优化器,根据 loss.backward()求得的grad 对模型参数进行更新
- train_step += 1
- tt_time = time.time()
- if train_step % 100 == 0 :
- print("第",train_step,"次训练迭代时,loss为:",loss.item()) #loss.item()和loss的区别在于:区别不大,略
- print("到第", train_step, "次训练迭代时,耗时:", tt_time-start_time)
-
- #测试开始 :
- #如何确认训练的模型是否有效呢? -- 通过测试数据集:测试集数据 传入 刚刚在训练的模型 ,查看其准确率,毕竟loss没有准确率来的直观
- z1.eval() # 对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
- with torch.no_grad() : #在测试的时候就不需要对模型进行调优了,所以我们需要写明no_grad()
- test_total_loss = 0
- test_total_accuracy = 0 #在一轮epoch中可以正确预测多少个图片分类
- for data in test_dataloader :
- imgs , targets = data
- imgs = imgs.to(device_gpu)
- targets = targets.to(device_gpu)
-
- outputs = z1(imgs)
- #计算loss
- loss = loss_fn(outputs , targets)
- test_total_loss += loss
- #计算accuracy
- #labels是一个1维的64元素的tensor,我们的outputs是一个2维的64*10的tensor,64是batchsize大小,而10是因为我们的输出是经网络训练后,该张图片是10分类中的各个分类的概率
- outputs = outputs.argmax(1) #找到一维array中的最大值,并返回该最大值所在的array的下标 ; 参数为0意味着一列列对比,参数为1意味着一行行对比
- accuracy = (outputs == targets).sum()
- test_total_accuracy += accuracy
-
- print("第",idx,"轮测试集上的总loss是:",test_total_loss.item()) #不加.item()输出是:tensor(311.6063) 而非 311.6063 就很乱
- print("第", idx, "轮测试集上的总accuracy是:", test_total_accuracy.item())
-
-
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。