本文是参照官方教程https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py
pytorch中提供了一个名为torchvision,其中包含了一些常用的数据集。
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
mean=(0.5, 0.5, 0.5),
std=(0.5, 0.5, 0.5))])
transforms.Compose()用于将多个转换组合在一起。
trainset = torchvision.datasets.CIFAR10(root='./data',
train=True,
download=True,
transform=transform)
# root 用于指定数据集在下载之后的存放路径
# transform 用于指定导入数据集需要对数据进行那种变化操作
# train是指定在数据集下载完成后需要载入那部分数据,
# 如果设置为True 则说明载入的是该数据集的训练集部分
# 如果设置为FALSE 则说明载入的是该数据集的测试集部分
trainloader = torch.utils.data.DataLoader(trainset,
batch_size=4,
shuffle=True,
num_workers=0)
# 下面对数据进行装载,我们可以将数据的载入理解为对图片的处理,
# 在处理完成后,我们就需要将这些图片打包好送给我们的模型进行训练 了 而装载就是这个打包的过程
# dataset 参数用于指定我们载入的数据集名称
# batch_size参数设置了每个包中的图片数据个数
# shuffle决定是否会在装载的过程会将数据随机打乱顺序并进打包
# num_workers要使用多少子进程来加载数据。0表示数据将在主进程中加载。(默认值:0)
testset = torchvision.datasets.CIFAR10(root='./data',
train=False,
download=True,
transform=transform)
testloader = torch.utils.data.DataLoader(testset,
batch_size=4,
shuffle=False,
num_workers=0)
#构建模型
class CNN(torch.nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = torch.nn.Sequential(
torch.nn.Conv2d(3, 6, 5),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
# kernel_size表示池化窗口大小2*2
# stride表示池化窗口移动步长
)
self.conv2 = torch.nn.Sequential(
torch.nn.Conv2d(6, 16, 5),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
)
self.fc1 = torch.nn.Sequential(
torch.nn.Linear(16 * 5 * 5, 120),
torch.nn.ReLU()
)
self.fc2 = torch.nn.Sequential(
torch.nn.Linear(120, 84),
torch.nn.ReLU()
)
self.fc3 = torch.nn.Sequential(
torch.nn.Linear(84, 10)
# 注意此处无激活函数
)
def forward(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = x.view(-1, 16 * 5 * 5)
# 对参数实现扁平化,否则全连接层的实际输
# 出的参数维度和其定义输入的维度不匹配,程序报错
x = self.fc1(x)
x = self.fc2(x)
x = self.fc3(x)
return x
- 训练前的准备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
cnn = CNN()
cnn.to(device)
#或者直接cnn=cnn.cuda(),(前提是你的电脑装了cuda)训练中的代码要做出变化
learning_rate = 0.001
epoch_n = 2
loss_fc = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(params=cnn.parameters(), lr=learning_rate, momentum=0.9)
这里强烈建议安装CUDA,速度提升的不是一点。。。
在调用cuda时,可以使用以上方法,也可以使用例如:
cnn=cnn.cuda()
也可以应用另外一种方法:
cnn = torch.cuda(cnn)
但是前提是计算机中安装过了,否则可以用torch.cuda.is_available()判断一下。
# 训练
for epoch in range(epoch_n):
running_loss = 0.0 # 累积损失
for i, data in enumerate(trainloader, 0):
#input, label=data
#input=input.cude()
#label=label.cuda()
input, label = data[0].to(device), data[1].to(device)
output = cnn(input)
loss = loss_fc(output, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0 # 2000次归零一次
print('Finished Training')
# 整体准确率
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data[0].to(device), data[1].to(device)
outputs = cnn(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))
# 各个类的准确率
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
for data in testloader:
# images, labels = data
images, labels = data[0].to(device), data[1].to(device)
outputs = cnn(images)
_, predicted = torch.max(outputs, 1)
c = (predicted == labels).squeeze()
for i in range(4): # range里面是4,是因为batch_size=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]))
整体的代码结构
import torch
import torch.nn
import torch.optim
import torch.utils.data
import torchvision
from torch.autograd import Variable
from torchvision import datasets
from torchvision import transforms
#数据处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
mean=(0.5, 0.5, 0.5),
std=(0.5, 0.5, 0.5))])
# transforms.Compose用于将多个转换组合在一起
trainset = torchvision.datasets.CIFAR10(root='./data',
train=True,
download=True,
transform=transform)
# root 用于指定数据集在下载之后的存放路径
# transform 用于指定导入数据集需要对数据进行那种变化操作
# train是指定在数据集下载完成后需要载入那部分数据,
# 如果设置为True 则说明载入的是该数据集的训练集部分
# 如果设置为FALSE 则说明载入的是该数据集的测试集部分
trainloader = torch.utils.data.DataLoader(trainset,
batch_size=4,
shuffle=True,
num_workers=0)
# 下面对数据进行装载,我们可以将数据的载入理解为对图片的处理,
# 在处理完成后,我们就需要将这些图片打包好送给我们的模型进行训练 了 而装载就是这个打包的过程
# dataset 参数用于指定我们载入的数据集名称
# batch_size参数设置了每个包中的图片数据个数
# shuffle决定是否会在装载的过程会将数据随机打乱顺序并进打包
# num_workers要使用多少子进程来加载数据。0表示数据将在主进程中加载。(默认值:0)
testset = torchvision.datasets.CIFAR10(root='./data',
train=False,
download=True,
transform=transform)
testloader = torch.utils.data.DataLoader(testset,
batch_size=4,
shuffle=False,
num_workers=0)
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
#构建模型
class CNN(torch.nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = torch.nn.Sequential(
torch.nn.Conv2d(3, 6, 5),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
# kernel_size表示池化窗口大小2*2
# stride表示池化窗口移动步长
)
self.conv2 = torch.nn.Sequential(
torch.nn.Conv2d(6, 16, 5),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
)
self.fc1 = torch.nn.Sequential(
torch.nn.Linear(16 * 5 * 5, 120),
torch.nn.ReLU()
)
self.fc2 = torch.nn.Sequential(
torch.nn.Linear(120, 84),
torch.nn.ReLU()
)
self.fc3 = torch.nn.Sequential(
torch.nn.Linear(84, 10)
# 注意此处无激活函数
)
def forward(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = x.view(-1, 16 * 5 * 5)
# 对参数实现扁平化,否则全连接层的实际输
# 出的参数维度和其定义输入的维度不匹配,程序报错
x = self.fc1(x)
x = self.fc2(x)
x = self.fc3(x)
return x
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
cnn = CNN()
cnn.to(device)
#或者直接cnn=cnn.cuda(),(前提是你的电脑装了cuda)训练中的代码要做出变化
learning_rate = 0.001
epoch_n = 2
loss_fc = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(params=cnn.parameters(), lr=learning_rate, momentum=0.9)
# 训练
for epoch in range(epoch_n):
running_loss = 0.0 # 累积损失
for i, data in enumerate(trainloader, 0):
#input, label=data
#input=input.cude()
#label=label.cuda()
input, label = data[0].to(device), data[1].to(device)
output = cnn(input)
loss = loss_fc(output, label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 1999:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0 # 2000次归零一次
print('Finished Training')
# 整体准确率
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data[0].to(device), data[1].to(device)
outputs = cnn(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))
# 各个类的准确率
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
for data in testloader:
# images, labels = data
images, labels = data[0].to(device), data[1].to(device)
outputs = cnn(images)
_, predicted = torch.max(outputs, 1)
c = (predicted == labels).squeeze()
for i in range(4): # range里面是4,是因为batch_size=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]))
以上便是官方教程中关于CIFAR10的代码,教程有些问题,如果完全按照教程写,则会出现BrokenPipeError: [Errno 32] Broken pipe的错误提示,这是因为windows中多进程的问题,解决方法是将torch.utils.data.DataLoader()中的num_workers赋值为0(原教程中为2)
如下所以:
trainloader = torch.utils.data.DataLoader(trainset,
batch_size=4,
shuffle=True,
num_workers=0)
测试集和训练集都要更改。
以上便是的在学习官方教程中的过程,如有错误请直接评论或联系qq:1932859223,谢谢!!!