#配置库
import torch
from torch import nn,optim
import torch.nn.functional as F
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim # 优化器
import torchvision
me v 15563370935
#配置参数
torch.manual_seed(1)#设置随机数种子,确保结果可重复
# batch_size=128 #批处理大小
learning_rate=0.001 #学习率
num_epoches=10 #训练次数
#加载CIFAR-10数据
#(ToTensor():把一个PIL.Image转换成Tensor,Normalize():标准化,即减均值,除以标准差)
transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
#训练集
trainset=datasets.CIFAR10(root='./data', train=True,download=True, transform=transform)
#测试集
testset=datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)
trainloader=DataLoader(trainset, batch_size=64,shuffle=True, num_workers=0)
testloader=DataLoader(testset, batch_size=64,shuffle=False, num_workers=0)
#显示部分图像数据
classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')
def imshow(img):
img = img / 2 + 0.5
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
dataiter = iter(trainloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
#创建CNN模型
class LeNet(nn.Module):
def __init__(self):
super(LeNet,self).__init__()
# 卷积层1:输入图像深度=3,输出图像深度=16,卷积核大小=5*5,卷积步长=1;16表示输出维度,也表示卷积核个数
self.conv1 = nn.Conv2d(in_channels=3,out_channels=16,kernel_size=5,stride=1)
# 池化层1:采用最大池化,区域集大小=2*2.池化步长=2
self.pool1 = nn.MaxPool2d(kernel_size=2,stride=2)
# 卷积层2
self.conv2 = nn.Conv2d(in_channels=16,out_channels=32,kernel_size=5,stride=1)
# 池化层2
self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
# 全连接层1:输入大小=32*5*5,输出大小=120
self.fc1 = nn.Linear(32*5*5,120)
# 全连接层2
self.fc2 = nn.Linear(120,84)
# 全连接层3
self.fc3 = nn.Linear(84,10)
def forward(self,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) # 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
#模型训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = LeNet()
net=net.to(device)
#定义loss和optimizer
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=learning_rate)
#开始训练
for epoch in range(10): # 整个迭代10轮
running_loss = 0.0 # 初始化损失函数值loss=0
for i, data in enumerate(trainloader, start=0):
# 获取训练数据
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device) # 将数据及标签传入GPU/CPU
# 权重参数梯度清零
optimizer.zero_grad()
# 正向及反向传播
outputs = net(inputs)
loss = loss_function(outputs, labels)
loss.backward()
optimizer.step()
# 显示损失值
running_loss += loss.item()
if i % 2000 == 1999: # print every 2000 mini-batches
print('[%d, %5d] loss: %.3f' %(epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
'''测试模型'''
correct = 0
total = 0
# with是一个上下文管理器
# with torch.no_grad()表示其包括的内容不需要计算梯度,也不会进行反向传播,节省内存
with torch.no_grad():
for data in testloader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = net(images)
# torch.max(outputs.data, 1)返回outputs每一行中最大值的那个元素,且返回其索引
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))
# 打印10个分类的准确率
class_correct = list(0. for i in range(10)) #class_correct=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
class_total = list(0. for i in range(10)) #class_total=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
with torch.no_grad():
for data in testloader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = net(images) # outputs的维度是:4*10
# torch.max(outputs.data, 1)返回outputs每一行中最大值的那个元素,且返回其索引
# 此时predicted的维度是:4*1
_, predicted = torch.max(outputs, 1)
# 此时c的维度:4将预测值与实际标签进行比较,且进行降维
c = (predicted == labels).squeeze()
for i in range(4):
label = labels[i]
class_correct[label] += c[i].item()
class_total[label] += 1
for i in range(10):
print('Accuracy of %5s : %2d %%' % (classes[i], 100 * class_correct[i] / class_total[i]))