Pytorch实战:CIFAR-10分类

最近在学习Pytorch,先照着别人的代码过一遍,加油!!!

 

加载数据集

# 加载数据集及预处理
import torchvision as tv
import torchvision.transforms as transforms
from torchvision.transforms import ToPILImage
import torch as t
show=ToPILImage() #可以将Tensor转成Image,方便可视化

划分数据集为训练集和测试集

#定义对数据的预处理
transform=transforms.Compose([
    transforms.ToTensor(),  #转为Tensor
    transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)), #归一化
])

#训练集
trainset=tv.datasets.CIFAR10(
    root='/home/cy/data',
    train=True,
    download=True,
    transform=transform
)

trainloader=t.utils.data.DataLoader(
    trainset,
    batch_size=4,
    shuffle=True,
    num_workers=2
)

testset=tv.datasets.CIFAR10(
    '/home/cy/data/',
    train=False,
    download=True,
    transform=transform
)

testloader=t.utils.data.DataLoader(
    testset,
    batch_size=4,
    shuffle=False,
    num_workers=2
)

classes=('plane','car','bird','cat','deer','dog','frog','horse','ship','truck')
Files already downloaded and verified
Files already downloaded and verified

可视化看下图片效果
(data, label)=trainset[100]
print(classes[label])

#(data+1)是为了还原被归一化的数据
show((data+1)/2).resize((100,100))

展示一个mini-batch中的图片

dataiter=iter(trainloader)
images,labels=dataiter.next() #返回4张图片及标签
print(' '.join('%11s'%classes[labels[j]] for j in range(4)))
show(tv.utils.make_grid((images+1)/2)).resize((400,100))

 

定义网络结构,挺方便的

## 定义网络
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.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=F.max_pool2d(F.relu(self.conv1(x)),(2,2))
        x=F.max_pool2d(F.relu(self.conv2(x)),2)
        x=x.view(x.size()[0],-1)
        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))
  (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)
)

定义损失函数和优化器
## 定义损失函数和优化器
from torch import optim
criterion=nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer=optim.SGD(net.parameters(),lr=0.001,momentum=0.9) #随机梯度下降,stochastic gradient descent

开始训练网络

一共有三个步骤。输入数据,前向传播+反向传播,更新参数

from torch.autograd import Variable

for epoch in range(2):
    running_loss=0.0
    for i,data in enumerate(trainloader,0):
        #输入数据
        inputs,labels=data
        inputs,labels=Variable(inputs),Variable(labels)
        
        #梯度清零
        optimizer.zero_grad()
        
        #forward+backward
        outputs=net(inputs)
        loss=criterion(outputs,labels)
        loss.backward()
        
        #更新参数
        optimizer.step()
        
        #打印log信息
        #running_loss +=loss.data[0]
        running_loss +=loss.item()
        if i%2000 ==1999:   #每2000个batch打印一次训练状态
            print('[%d, %5d] loss: %.3f' \
                 %(epoch+1,i+1,running_loss / 2000))
            running_loss=0.0
print('Finished Training')

 

检查一下网络在一个batch内的效果如何

## 检验网络效果
dataiter=iter(testloader)
images,labels=dataiter.next() #一个batch返回4张图片
print('实际的label: ',' '.join(\
            '%08s'%classes[labels[j]] for j in range(4)))
show(tv.utils.make_grid(images/2 -0.5)).resize((400,100))

# 计算网络预测的label
outputs=net(Variable(images))
_,predicted=t.max(outputs.data,1)
print('预测结果: ',' '.join('%5s'\
        % classes[predicted[j]] for j in range(4)))

 

测试集上计算正确率

correct=0
total=0
for data in testloader:
    images,labels=data
    outputs=net(Variable(images))
    _,predicted=t.max(outputs.data,1)
    total +=labels.size(0)
    correct +=(predicted==labels).sum()
    
print('1000张测试集中的准确率为: %d  %%' %(100* correct/total))
1000张测试集中的准确率为: 52  %

 

可以看到,在CIFAR-10上的正确率为52%,网络训练还是有些效果的。

 

上一篇:利用pytorch构建alexnet网络对cifar-10进行分类


下一篇:魔改CNN对cifar-10分类