pytorch官方demo(Lenet)
1、首先,我们定义LeNet网络模型,构建的模型如下:
model
import torch.nn as nn
import torch.nn.functional as F #导入pytorch的两个包
#在pytorch中搭建模型,首先定义一个类,类继承与nn.module这个父类
class LeNet(nn.Module):
def __init__(self): #定义初始化函数,在初始化过程中,搭建我们所使用的网络层结构
super(LeNet, self).__init__() #涉及到多继承,一般使用super函数
self.conv1 = nn.Conv2d(3, 16, 5) #按住ctrl键,鼠标左键点击函数,进入函数里面,输入的彩色图片,深度3,(输入的深度,卷积核个数也就是输出的深度,卷积核大小)
self.pool1 = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(16, 32, 5)
self.pool2 = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(32*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x): #,forward函数定义正向传播的过程,x指的是输入的数据
x = F.relu(self.conv1(x)) # 输入的数据先经过卷积层,再经过激活函数。input(3, 32, 32) output(16, 28, 28)
x = self.pool1(x) # 经过下采样,得到输出。output(16, 14, 14)
x = F.relu(self.conv2(x)) # output(32, 10, 10)
x = self.pool2(x) # output(32, 5, 5)
x = x.view(-1, 32*5*5) # 全连接层将特征矩阵展平成一维向量。-1代表第一个维度batch,第二个维度为展平后节点的个数,自动推理output(32*5*5)
x = F.relu(self.fc1(x)) # output(120)
x = F.relu(self.fc2(x)) # output(84)
x = self.fc3(x) # output(10)
return x
#输入测试网络模型的代码段
import torch
input1 = torch.rand([32,3,32,32])
model = LeNet()
print(model)
output = model(input1)
输入代码段,运行这个网络模型,运行结果如下:
2、输入训练脚本:
train
import torch
import torchvision
import torch.nn as nn
from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
#transform是对图像进行预处理的函数,normalize标准化函数
#transforms.Compose方法将使用的预处理方法打包成为一个整体、
#ToTensor将(H,W,C),像素值[0,255]转换成(C,H,W),(0,1)
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
# 50000张训练图片
# 第一次使用时要将download设置为True才会自动去下载数据集,将数据集下载到当前目录的data文件夹下
#torchvision中的datasets下有很多的数据集
train_set = torchvision.datasets.CIFAR10(root='./data', train=True,
download=False, transform=transform)
#torch.utils.data.DataLoader将训练集导入进来,并且分成一个一个批次的,num_workers载入数据的线程数,window下必须设置成0
train_loader = torch.utils.data.DataLoader(train_set, batch_size=36,
shuffle=True, num_workers=0)
# # 10000张验证图片
# # 第一次使用时要将download设置为True才会自动去下载数据集
val_set = torchvision.datasets.CIFAR10(root='./data', train=False,
download=False, transform=transform)
val_loader = torch.utils.data.DataLoader(val_set, batch_size=10000 ,
shuffle=False, num_workers=0)
val_data_iter = iter(val_loader) #iter将val_loader转化为可迭代的迭代器
val_image, val_label = val_data_iter.next() #通过next方法获取测试的图像和标签值,提取验证集
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck') #元组类型,值不可改变
net = LeNet() #实例化模型
loss_function = nn.CrossEntropyLoss() #定义损失函数和优化器,交叉熵损失,Adam优化器
optimizer = optim.Adam(net.parameters(), lr=0.001) #parameters将LeNet所有可训练的参数都进行优化,lr学习率
for epoch in range(5): # loop over the dataset multiple times,训练集迭代5次
running_loss = 0.0 #累加训练中的损失
for step, data in enumerate(train_loader, start=0): #通过enumerate函数不仅返回每一批的数据data,还会返回data所对应的步数,从0开始
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data #将数据分离成对应的图像以及分类所对应的标签
# zero the parameter gradients
optimizer.zero_grad() #历史梯度会累加,将历史损失梯度清零
# forward + backward + optimize
outputs = net(inputs) #预测输出
loss = loss_function(outputs, labels) #计算损失
loss.backward() #将loss反向传播,参数更新
optimizer.step()
# print statistics
running_loss += loss.item() #累加损失
if step % 500 == 499: # print every 500 mini-batches,每隔500步计算一次损失
with torch.no_grad(): #在接下来的过程中,不计算每个节点的误差损失梯度,不使用这个函数会占用更多的内存资源
outputs = net(val_image) # [batch, 10] 正向传播
predict_y = torch.max(outputs, dim=1)[1] #输出的最大的index,最可能是哪个类别,在维度1也就是十个类别去寻找
#通过值是否相等torch.eq()和求和函数sum()求预测对了多少样本,在tensor中计算,得到的是tensor,通过item()方法拿到数值,再除以测试样本的数目得到准确率
accuracy = torch.eq(predict_y, val_label).sum().item() / val_label.size(0)
print('[%d, %5d] train_loss: %.3f test_accuracy: %.3f' %
(epoch + 1, step + 1, running_loss / 500, accuracy)) #每500步求一个平均损失
running_loss = 0.0 #下一次500步迭代的过程中损失从0开始
print('Finished Training')
save_path = './Lenet.pth' #设置保存路径
torch.save(net.state_dict(), save_path) #通过torch.save将网络中所有参数保存,保存的路径是save_path
# if __name__ == '__main__':
# main()
训练结果如下:
3、输入预测脚本:
predict
import torch
import torchvision.transforms as transforms
from PIL import Image #,导入PIL的image模块,PIL模块载入图像
from model import LeNet
def main():
transform = transforms.Compose(
[transforms.Resize((32, 32)),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) #预处理,将图像大小设置为32*32,并且将其转化为tensor,标准化处理
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
net = LeNet() #实例化LeNet
net.load_state_dict(torch.load('Lenet.pth')) #通过 net.load_state_dict载入刚刚保存的权重文件
im = Image.open('2.jpeg') #image模块载入图像
im = transform(im) # 预处理之后得到一个[C, H, W]的格式
im = torch.unsqueeze(im, dim=0) # [N, C, H, W],torch.unsqueeze增加一个新的维度
with torch.no_grad(): #不需要求损失梯度
outputs = net(im)
predict = torch.max(outputs, dim=1)[1].data.numpy() #找到最大值对应的index
print(classes[int(predict)]) #将index传入到类别当中
# predict = torch.softmax((outputs,dim=1)
# print(predict)
if __name__ == '__main__':
main()
从网上随机下载一个类别中的图片,使用此模型进行预测,预测的结果如下:
从结果的值,预测的类别是ship