深度学习--实战 LeNet5
数据集
数据集选用CIFAR-10的数据集,Cifar-10 是由 Hinton 的学生 Alex Krizhevsky、Ilya Sutskever 收集的一个用于普适物体识别的计算机视觉数据集,它包含 60000 张 32 X 32 的 RGB 彩色图片,总共 10 个分类。其中,包括 50000 张用于训练集,10000 张用于测试集。
模型实现
模型需要继承nn.module
import torch from torch import nn class Lenet5(nn.Module): """ for cifar10 dataset. """ def __init__(self): super(Lenet5,self).__init__() self.conv_unit = nn.Sequential( #input:[b,3,32,32] ===> output:[b,6,x,x] #Conv2d(Input_channel:输入的通道数,kernel_channels:卷积核的数量,输出的通道数,kernel_size:卷积核的大小,stride:步长,padding:边缘补足) nn.Conv2d(3,6,kernel_size=5,stride=1,padding=0), #池化 nn.MaxPool2d(kernel_size=2,stride=2,padding=0), #卷积层 nn.Conv2d(6,16,kernel_size=5,stride=1,padding=0), #池化 nn.AvgPool2d(kernel_size=2,stride=2,padding=0) #output:[b,16,5,5] ) #flatten #Linear层 self.fc_unit=nn.Sequential( nn.Linear(16*5*5,120), nn.ReLU(), nn.Linear(120,84), nn.ReLU(), nn.Linear(84,10) ) #测试卷积输出到全连接层的输入 #tmp = torch.rand(2,3,32,32) #out = self.conv_unit(tmp) #print("conv_out:",out.shape) #Loss评价 Cross Entropy Loss 分类 在其中包含一个softmax()操作 #self.criteon = nn.MSELoss() 回归 #self.criteon = nn.CrossEntropyLoss() def forward(self,x): """ :param x:[b,3,32,32] :return: """ batchsz = x.size(0) #[b,3,32,32]=>[b,16,5,5] x = self.conv_unit(x) #[b,16,5,5]=>[b,16*5*5] x = x.view(batchsz,16*5*5) #[b,16*5*5]=>[b,10] logits = self.fc_unit(x) return logits # [b,10] # pred = F.softmax(logits,dim=1) 这步在CEL中包含了,所以不需要再写一次 #loss = self.criteon(logits,y) def main(): net = Lenet5() tmp = torch.rand(2,3,32,32) out = net(tmp) print("lenet_out:",out.shape) if __name__ == '__main__': main()
训练与测试
import torch from torchvision import datasets from torchvision import transforms from torch.utils.data import DataLoader from lenet5 import Lenet5 import torch.nn.functional as F from torch import nn,optim def main(): batch_size = 32 epochs = 1000 learn_rate = 1e-3 #导入图片,一次只导入一张 cifer_train = datasets.CIFAR10('cifar',train=True,transform=transforms.Compose([ transforms.Resize((32,32)), transforms.ToTensor() ]),download=True) #加载图 cifer_train = DataLoader(cifer_train,batch_size=batch_size,shuffle=True) #导入图片,一次只导入一张 cifer_test = datasets.CIFAR10('cifar',train=False,transform=transforms.Compose([ transforms.Resize((32,32)), transforms.ToTensor() ]),download=True) #加载图 cifer_test = DataLoader(cifer_test,batch_size=batch_size,shuffle=True) #iter迭代器,__next__()方法可以获得数据 x, label = iter(cifer_train).__next__() print("x:",x.shape,"label:",label.shape) #x: torch.Size([32, 3, 32, 32]) label: torch.Size([32]) device = torch.device('cuda') model = Lenet5().to(device) print(model) criteon = nn.CrossEntropyLoss().to(device) optimizer = optim.Adam(model.parameters(),lr=learn_rate) for epoch in range(epochs): model.train() for batchidx,(x,label) in enumerate(cifer_train): x,label = x.to(device),label.to(device) logits = model(x) #logits:[b,10] loss = criteon(logits,label) #backprop optimizer.zero_grad() #梯度清零 loss.backward() optimizer.step() #梯度更新 # print(epoch,loss.item()) model.eval() with torch.no_grad(): #test total_correct = 0 total_num = 0 for x,label in cifer_test: x,label = x.to(device),label.to(device) #[b,10] logits = model(x) #[b] pred =logits.argmax(dim=1) #[b] vs [b] => scalar tensor total_correct += torch.eq(pred,label).float().sum().item() total_num += x.size(0) acc = total_correct/total_num print("epoch:",epoch,"acc:",acc) if __name__ == '__main__': main()