Pytorch笔记02:构建神经网络—以CIFA-10数据集分类为例

    科技2024-07-09  68

    Pytorch笔记02:构建神经网络—以CIFA-10数据集分类为例

    1、pytorch加载内置数据集

    在Pytorch的torchvision中集成了很多常用的数据集,例如MNIST、CIFA-10、COCO等,使用的方法就是在torchvision.dataset内直接使用,如torchvision.datasets.cifa10(),一般加载数据集有这样几个参数:

    root(str): 表示数据集文件的路径train(bool): 如果是True表示从train set中创建,否则从test set中创建transform: 用于数据转换操作,是一个transforms对象, 接受一个PIL image输入,返回转换后的数据(如tensor)download(bool): 表示是否从网上下载数据集,True表示下载。 import torch import torchvision import torchvision.transforms as transforms import torch.optim as optim #transforms.Compose([transform_list])可以将多个数据转换操作串联 #transforms.ToTensor()会将0-255的灰度图转化为0-1的tensor #transforms.Normalize(mean_tuple, std_tuple) 进行 data = (data - mean) / std #范围(0,1)经过变换会得到(-1,1) transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))]) #num_workers表示使用多少个进程来导入数据, 0代表使用主进程, 2表示使用两个子进程 trainset = torchvision.datasets.CIFAR10(root='.\data',train=True, download=True, transform = transform) trainloder = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='.\data',train=False, download=True, transform = transform) testloder = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=True, num_workers=2) Files already downloaded and verified Files already downloaded and verified

    2、定义训练模型

    Pytorch自定义模型时,所有的模型均要继承自torch.nn.Module,并且需要重写以下两个方法:

    __int__():初始化函数, 需要调用super(Model, self).__init__()完成父类(nn.Module)部分的初始化,而后需要定义网络结构,nn模块的层结构都是可以直接使用layer(x)获得层输出。另外, 也可以采用nn.Sequential([layer1, layer2,…])对多个层进行串联forward(): 定义前向传播:返回一个前向传播的结果 #Pytorch 神经网络 #torch.nn import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): #自定义模型,继承自nn.Module def __init__(self): super(Net, self).__init__() #在模型初始化中调用父类初始化 #定义模型结构 layer self.conv1 = nn.Conv2d(3, 6, 5) self.conv2 = nn.Conv2d(6, 16, 5) #定义结构时需要考虑已经pooling对Feature map的维度影响 self.fc1 = nn.Linear(16*5*5, 120) self.fc2 = nn.Linear(120,84) self.fc3 = nn.Linear(84,10) def num_flat_feature(self,x): size = x.size()[1:] num_feature = 1 for dim in size: num_feature *= dim return num_feature def forward(self, x): #定义前向传播 x = F.max_pool2d(F.relu(self.conv1(x)),(2,2)) x = F.max_pool2d(F.relu(self.conv2(x)), (2,2)) x = x.reshape(-1,self.num_flat_feature(x)) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x

    3、进行模型训练

    net = Net() device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # Assume that we are on a CUDA machine, then this should print a CUDA device: print(device) net.to(device) #将模型迁移到指定设备 lossFunc = torch.nn.CrossEntropyLoss() #交叉熵损失 optimizer = optim.SGD(params=net.parameters(),lr = 0.001, momentum=0.9) #SGD + momentum优化器 epoch = 5 print('start training...') for e in range(epoch): running_loss = 0 for i, data in enumerate(trainloder, 0): inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) #将数据迁移到指定设备 optimizer.zero_grad() #清空当前梯度 output = net(inputs) #获得一个batch的输出 loss = lossFunc(output, labels) #将predict的输出与labels进行损失计算 loss.backward() #损失反向传播获得参数梯度 optimizer.step() #优化器更新权重 running_loss += loss.item() if i % 2000 == 1999: print('[%d, %5d] loss:%3f' % (e+1, i+1, running_loss / 2000)) running_loss = 0 print('end training...') cpu start training... [1, 2000] loss:0.000814 [1, 4000] loss:0.000621 [1, 6000] loss:0.000846 [1, 8000] loss:0.001207 [1, 10000] loss:0.000526 [1, 12000] loss:0.000386 [2, 2000] loss:0.000481 [2, 4000] loss:0.000669 [2, 6000] loss:0.000915 [2, 8000] loss:0.000854 [2, 10000] loss:0.000292 [2, 12000] loss:0.000676 .... .... end training...

    4、对测试数据集中的第一个batch进行可视化,并预测结果

    import matplotlib.pyplot as plt import numpy as np def imshow(img): img = img / 2 +0.5 #(-1,1) => (0,1) arr = img.numpy() plt.imshow(np.transpose(arr, (1,2,0))) plt.show() #输出测试数据中第一个batch的标签 test_dataiter = iter(testloder) #迭代器 test_image, test_label = test_dataiter.next() imshow(torchvision.utils.make_grid(test_image)) print('labels: '.join('%5s' % classes[test_label[j]] for j in range(4))) #预测输出 predict_out = net(test_image) _, predict_classes = torch.max(predict_out, 1) #torch.max(tensor, axis)返回tensor在维度axis上的最大值v,及其index(v, index) print('predict: '.join('%5s' % classes[predict_classes[j]] for j in range(4)))

    labels: cat dear ship dog predict: cat dear ship cat

    5、在测试集上测试分类准确性

    #在测试集上测试性能 total = 0 correct = 0 with torch.no_grad(): #测试时在no_grad()状态下 for data in testloder: images, labels = data out = net(images) _, predict = torch.max(out, 1) total += labels.size(0) correct += (labels == predict).sum().item() print('Accuracy: %s' % (100*correct / total)) Accuracy: 65.584

    6、Reference

    完整代码:Github

    Processed: 0.009, SQL: 8