首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

深度学习与图像识别 VGG16实现Cifar10分类

Cifar10数据集

Cifar10是一个由彩色图像组成的分类的数据集(MNIST是黑白数据集),其中包含了飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船、卡车10个类别(如图3所示),且每个类中包含了1000张图片。整个数据集中包含了60000张32×32的彩色图片。该数据集被分成50000和10000两部分,50000是training set,用来做训练;10000是test set,用来做验证。

图3Cifar10数据集示例

整体架构上,VGG的一大特点是在卷积层中统一使用了3×3的小卷积核和2×2大小的小池化核,层数更深,特征图更宽,证明了多个小卷积核的堆叠比单一大卷积核带来了精度提升,同时也降低了计算量。以VGG-16网络为基础疯狂调参,最终达到了90.97%的准确率。

训练代码

#####################################

# 第一步 载入数据

import torch

import torch.nn as nn

import math

import os

import torchvision

import torchvision.models as models

import torchvision.datasets as dsets

import torchvision.transforms as transforms

#使用torchvision可以方便的下载Cifar10数据集 而torchvision下载的数据集为[0,1]的

#PILImage格式 我们需要将张量Tensor归一化到[-1,1]

transform = transforms.Compose([

transforms.ToTensor(), #将PILImage转换为张量

transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)) ])

train_dataset = dsets.CIFAR10(root='/ml/pycifar', # 选择数据的根目录

train=True, # 选择训练集

transform=transform,

download=True)

test_dataset = dsets.CIFAR10(root='/ml/pycifar',

train=False,# 选择测试集

transform=transform,

download=True)

trainloader = DataLoader(train_dataset,

batch_size=4, # 每个batch载入的图片数量

shuffle=True,

num_workers=2) #载入训练数据所需的子任务数

testloader = DataLoader(test_dataset,

batch_size=4, # 每个batch载入的图片数量

shuffle=False,

num_workers=2) #载入训练数据所需的子任务数

cifar10_classes = ('plane','car','bird','cat','deer',

'dog','frog','horse','ship','truck')

# #####################################

# # 查看训练数据

# # 备注:该部分代码可以不放入主函数

# #####################################

# import numpy as np

# if __name__ == '__main__':

# dataiter = iter(trainloader) #从训练数据中随机取一些数据

# images,labels = dataiter.next()

# print(images.shape)

# for j in cifar10_classes:

# print(labels[0])

#####################################

# 第二步 构建卷积神经网络

#####################################

cfg = {'VGG16':[64,64,'M',128,128,'M',256,256,256,'M',512,512,512,'M',512,512,512,'M']}

class VGG(nn.Module):

def __init__(self,net_name):

super(VGG,self).__init__()

#构建卷积网络的卷积层和池化层 最终输出命名features,原因是通常认为经过这些惭怍的输出

#为包含图像空间信息的特征层

self.features = self._make_layers(cfg[net_name])

# 构建卷积层之后的全连接层及分类器

self.classifier = nn.Sequential(

nn.Dropout(),

nn.Linear(512,512),#fc1

nn.ReLU(True),

nn.Dropout(),

nn.Linear(512,512),#fc2

nn.ReLU(True),

nn.Linear(512, 10), # fc3 最终cifar10 输出的是10类

)

#初始化权重

for m in self.modules():

if isinstance(m,nn.Conv2d): #判断某个模块是否是某种类型

n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels

def forward(self, x):

x = self.features(x) # 前向传播时先经过卷积层和池化层

x = x.view(-1,512)

x = self.classifier(x)

return x

def _make_layers(self,cfg):

layers = []

in_channels = 3

for v in cfg:

if v == 'M':

layers += [nn.MaxPool2d(kernel_size=2,stride=2)]

else:

layers += [nn.Conv2d(in_channels, v, kernel_size=3, padding=1),

nn.BatchNorm2d(v),

nn.ReLU(inplace=True)]

in_channels = v

return nn.Sequential(*layers)

net = VGG('VGG16')

net = net.cuda() #使用gpu

#####################################

# 第三步 定义损失函数和优化方法

#####################################

criterion = nn.CrossEntropyLoss() #定义损失函数 交叉熵

optimizer = torch.optim.SGD(net.parameters(),lr=0.001,momentum=0.9) # 定义优化方法 随机梯度下降

#####################################

# 第四步 卷积神经网络的训练

#####################################

def train():

for epoch in range(5):

train_loss = 0.0

for batch_idx,data in enumerate(trainloader,0):

#初始化

inputs,labels = data #获取数据

optimizer.zero_grad() # 先将梯度设为0

#优化过程

inputs = inputs.cuda()

labels = labels.cuda()

outputs = net(inputs) #将数据输入到网络 得到第一轮网络前向传播的预测结果outputs

loss = criterion(outputs,labels) #预测结果outputs和labels通过之前定义的交叉熵计算损失

loss.backward() #误差反向传播

optimizer.step() #随机梯度下降方法(之前定义的)优化权重

#查看网络训练状态

train_loss += loss.item()

if batch_idx % 2000 ==1999: #每迭代2000个batch打印一次以查看当前网络的收敛情况

print('[%d,%5d] loss:%.3f'%(epoch+1,batch_idx+1,train_loss/2000))

train_loss = 0.0

print('Saving epoch %d model'%(epoch+1))

state = {

'net':net.state_dict(), # 模型的网络参数

'epoch':epoch + 1

}

os.mkdir('checkpoint')

torch.save(state,'./checkpoint/cifar10_epoch_%d.ckpt' %(epoch+1))

print('Finishef Training')

def test():

net = VGG('VGG16')

modelpath = 'F:\PythonProject\checkpoint\ew_model\cifar10_epoch_5.ckpt'

checkpoint = torch.load(modelpath)

net.load_state_dict(checkpoint['net'])

net = net.cuda()

net.eval()

correct = 0

total = 0

with torch.no_grad():

for data in testloader:

images, labels = data

images, labels = images.cuda(), labels.cuda()

outputs = net(images)

_, predicted = torch.max(outputs.data, 1)

total += labels.size(0)

correct += (predicted == labels).cpu().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))# 定义一个存储每类中测试正确的个数的 列表,初始化为0

class_total = list(0. for i in range(10)) # 定义一个存储每类中测试总数的个数的 列表,初始化为0

with torch.no_grad():

for data in testloader:

images, labels = data

images, labels = images.cuda(), labels.cuda()

outputs = net(images)

_, predicted = torch.max(outputs.data, 1)

c = (predicted == labels).squeeze()

for i in range(4): # 因为每个batch都有4张图片,所以还需要一个4的小循环

label = labels[i] # 对各个类的进行各自累加

class_correct[label] += c[i].item()

class_total[label] += 1

for i in range(10):

print('Accuracy of %5s : %2d %%' % (

cifar10_classes[i], 100 * class_correct[i] / class_total[i]))

if __name__ == '__main__':

test()

'''

在加载模型测试的时候 出现并解决的问题:

1:net.load_state_dict('net_params.pkl') #你训练好的模型文件好像字典键值有很多个,包括epoch等,但我们只需要模型参数文件。

报错的原因是因为载入模型文件的键值太多了。pytorch识别不了。

2. modelpath = 'F:\PythonProject\checkpoint\ew_model # 这样会有权限错误 因为打开的是文件夹 并非文件,

所以要在后面加上要打开的文件名

'''

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O2XCgbwjKPmvoxXV6894F9VQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com