原教程链接点击这里。
import torch
import torchvision
import torchvision.transforms as transforms
import ssl
ssl._create_default_https_context = ssl._create_unverified_context#全局关闭证书验证
Note:
ssl._create_default_https_context = ssl._create_unverified_context
因为使用pytorch下载数据集会报错:证书过期,无法下载数据集,该语句设置全局关闭证书验证,注意要包含包,其他证书过期的错误也可使用该方法。
对于图像任务,torchvision,包含了处理一些基本图像数据集的方法。这些数据集包括 Imagenet, CIFAR10, MNIST 等。除了数据加载以外,torchvision 还包含了图像转换器,torchvision.datasets 和 torch.utils.data.DataLoader。torchvision包含了目前流行的数据集,模型结构和常用的图片转换工具。
torchvision.datasets: 一些加载数据的函数及常用的数据集接口;
torchvision.models:包含常用的模型结构(含预训练模型),例如AlexNet、VGG、ResNet等;
torchvision.transforms:常用的图片变换,例如裁剪、旋转等;
torchvision.utils:其他的一些有用的方法。
一. 数据
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
trainset = torchvision.datasets.CIFAR10(root="./data",train=True,download=True,transform=transform)
trainloader = 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)
testloader=torch.utils.data.DataLoader(testset,batch_size=4,shuffle=True,num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
Note:
此处我运行时的代码会报错
Traceback (most recent call last): File
"D:\anaconda\envs\pytorch\lib\multiprocessing\popen_spawn_win32.py", line 93, in init reduction.dump(process_obj, to_child) File
"D:\anaconda\envs\pytorch\lib\multiprocessing\reduction.py", line 60, in dump ForkingPickler(file, protocol).dump(obj) OSError: [Errno 22] Invalid argument 修改代码 num_workers=2 值改为0
修改代码 num_workers=2 值改为0解决,分析原因dataloader一次性创建num_worker个工作进程,可能与本人硬件有关。
torchvision.transforms.Compose()
这个类的主要作用是串联多个图片变换的操作
先由HWC转置为CHW格式;
再转为float类型;
最后,每个像素除以255。
数据标准化——transforms.normalize()
逐channel的对图像进行标准化,可以加快模型的收敛。
output = (input - mean) / std
mean:各通道的均值
std:各通道的标准差
inplace:是否原地操作
import matplotlib.pyplot as plt
import numpy as np
# 展示图像的函数
def imshow(img):
img = img / 2 + 0.5# unnormalize
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))#此处图片个数与BatchSize一致
# 显示图像标签
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
二. 构建网络模型
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1 = nn.Conv2d(3,6,5)
self.pool = nn.MaxPool2d(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)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1,16*5*5)#4*400
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
print(net)
Net(
(conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
三. 损失和优化器
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)
四. 训练
for epoch in range(2):
running_loss = 0.0
for i,data in enumerate(trainloader,0):#enumerate(sequence, [start=0])
inputs,labels = data
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs,labels)
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
print('Finished Training')
[1, 2000] loss: 2.215
[1, 4000] loss: 1.875
[1, 6000] loss: 1.698
[1, 8000] loss: 1.612
[1, 10000] loss: 1.563
[1, 12000] loss: 1.523
[2, 2000] loss: 1.473
[2, 4000] loss: 1.424
[2, 6000] loss: 1.395
[2, 8000] loss: 1.404
[2, 10000] loss: 1.382
[2, 12000] loss: 1.341
Finished Training
五. 测试集结果
dataiter = iter(testloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
oututs = net(images)
_,predicted = torch.max(outputs,1)
print('predicted:',' '.join('%5s' % classes[predicted[j]] for j in range(4)))
#join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
predicted: ship deer car frog
Note:
output = torch.max(input, dim)
输入
input是softmax函数输出的一个tensor
dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值
输出
函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。
整体的准确率
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))
Accuracy of the network on the 10000 test images: 51 %
类准确率
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
outputs = net(images)
_, predicted = torch.max(outputs, 1)
c = (predicted == labels).squeeze()#从数组的形状中删除单维度条目,即把shape中为1的维度去掉
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]))
Accuracy of plane : 61 %
Accuracy of car : 61 %
Accuracy of bird : 39 %
Accuracy of cat : 20 %
Accuracy of deer : 47 %
Accuracy of dog : 60 %
Accuracy of frog : 55 %
Accuracy of horse : 63 %
Accuracy of ship : 51 %
Accuracy of truck : 53 %
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 确认我们的电脑支持CUDA,然后显示CUDA信息:
print(device)
Note
output = torch.max(input, dim)
input是softmax函数输出的一个tensor
dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值
函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。