深度学习框架的一般流程:
1.数据加载和处理
2.定义一个模型(包括网络、损失函数和优化器)
3.在训练集上进行训练
4.在测试集上测试模型的性能
(步骤1、2可以调换)
步骤一:使用Torchvision加载和规范化CIFAR10训练集和测试集
torchvision模块可以加载数据,也可以处理数据等等
import torch
import torchvision
import torchvision.transforms as tranforms
#步骤一:使用Torchvision加载和规范化CIFAR10训练集和测试集
#torchvision数据集的输出是范围[0, 1]的PILImage图像。需要将它们转换为归一化范围[-1, 1]的tensor。
#定义一个变换transform 利用transforms模块中的Compose()函数把ToTensor和Normalize组合在一起
transform = transforms.Compose(
[tranforms.ToTensor(),
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
batch_size = 4
#数据集
trainset = torchvision.datasets.CIFAR10(
root='./data',
train=True,
download=True,
transform=transform#上面定义的转换数据方式
)
testset = torchvision.datasets.CIFAR10(
root='./data',
train=False,
download=True,
transform=transform#上面定义的转换数据方式
)
#加载数据
trainloader = torch.utils.data.DataLoader(trainset,batch_size=batch_size,
shuffle=True,num_workers=2)
testloader = torch.utils.data.DataLoader(testset,batch_size=batch_size,
shuffle=False,num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
步骤二:定义一个模型(包括网络、损失函数和优化器)
1.定义卷积神经网络模型主要用到torch.nn和torch.nn.functional两个模块
torch.nn大多数的layer在functional中都有函数与之对应,但是不同之处在于functional中的函数只进行计算,不管参数更新啥的。所以如果模型有可学习的参数就放用nn定义,否则二者都可以没啥区别。比如这里的卷积、池化等是用nn定义的(有需要学习的参数),而Relu就是用function定义的(因为没有可学习的参数,就是一个简单的运算)
2.定义优化器用到torch.optim模块,定义损失函数用到nn模块
#定义一个卷积神经网络
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
#定义神经网络
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3,6,5)#输入通道数为3 输出通道数为6 ,kernel_size为5*5
self.pool = nn.MaxPool2d(2,2)#2*2的最大池化,也可以直接写2
self.conv2 = nn.Conv2d(6,16,5)
self.fc1 = nn.Linear(16*5*5,120)
self.fc2 = nn.Linear(120,84)
self.fc3 = nn.Linear(84,10)
def forward(self,x):
x = self.pool(F.relu(self.conv1(x)))#functional定义的Relu
x = self.pool(F.relu(self.conv2(x)))
x = torch.flatten(x,1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
#定义损失函数和优化器
criterion = nn.CrossEntropyLoss() #交叉熵损失函数
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) #随机梯度下降
步骤三:在训练集上进行训练
#训练网络
for epoch in range(2): #数据集循环两次
runing_loss = 0.0
for i,data in enumerate(trainloader,0):
#得到输入,数据是一个列表[inputs,labels]
inputs,labels = data
#将参数的梯度值归零
optimizer.zero_grad()
#正向传播+反向传播+优化器
outputs = net(inputs)
loss = criterion(outputs,labels)
loss.backward()
optimizer.step()
#输出结果
runing_loss += loss.item()
if i%2000 == 1999:
print('[%d %5d] loss: %.3f' %
(epoch + 1,i+1,runing_loss / 2000))
runing_loss = 0.0
print('Finish Training!')
步骤四:在测试集上测试模型的性能
#测试一个batch_size的图片
dataiter = iter(testloader) # 创建一个python迭代器,读入已经加载好的testloader
images, labels = dataiter.next() # 迭代器用.next()访问.返回batch_size=4张的图片
# print images
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
#用网络进行预测
outputs = net(images)
_, predicted = torch.max(outputs.data, 1) #获得最大值的索引(第几类)
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))
#在整个测试集上进行测试
correct = 0
total = 0
# 在测试时不需要计算梯度
with torch.no_grad():
for data in testloader:
images, labels = data
#计算正向传播预测的结果
outputs = net(images)
#最大值的索引
_, 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))