实现了全连接层的简单神经网络之后,这期进行卷积神经网络的实现,代码没有太大的变化,只需做一点改动就可以了
import torch
import torch.nn as nn
import time
from torch import optim
from torch.autograd import variable
from torch.utils.data.dataloader import DataLoader
from torchvision import datasets,transforms
epoch=10
batch_num=64
lr_rate=0.01
sum_loss=0.0
class CNN(nn.Module):
def __init__(self):
super().__init__()
self.cov1=nn.Sequential(
nn.Conv2d(in_channels=1,out_channels=64,kernel_size=(3,3),stride=1,padding=1),
nn.ReLU(),
nn.Conv2d(in_channels=64,out_channels=128,kernel_size=(3,3),stride=1,padding=1),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.layer=nn.Sequential(
nn.Linear(in_features=25088, out_features=1024, bias=True),
nn.ReLU(),
nn.Linear(in_features=1024, out_features=10, bias=True)
)
def forward(self,x):
x=self.cov1(x)
x=x.view(-1,14*14*128)
x=self.layer(x)
return x
data_tf=transforms.ToTensor()
train_set=datasets.MNIST(root='data',train=True,transform=data_tf,download=True)
test_set=datasets.MNIST(root='data',train=False,transform=data_tf,download=True)
train_loader=DataLoader(train_set,batch_size=batch_num,shuffle=True)
test_loader=DataLoader(test_set,batch_size=batch_num,shuffle=True)
since = time.time()
net=CNN()
if torch.cuda.is_available():
net = net.cuda()
sum_true=0.0
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=lr_rate)
for e in range(epoch):
for data in train_loader:
img,label=data
if torch.cuda.is_available():
img = img.cuda()
label = label.cuda()
img=variable(img)
label=variable(label)
output=net(img)
loss=criterion(output,label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
sum_loss+=loss.item()
print('loss is :{:.16f}'.format(sum_loss/len(train_set)))
sum_loss=0.0
sum_true=0
for data in test_loader:
img,label=data
if torch.cuda.is_available():
img = img.cuda()
label = label.cuda()
out=net(img)
_,predict=torch.max(out,1)
num_true=(predict==label).sum()
sum_true+=num_true.item()
print('accuracy rate is :{:.4f}'.format(sum_true/len(test_set)))
time_elapsed = time.time() - since
print('Training complete in {:.0f}s'.format(time_elapsed) )
和上一篇的全连接的网络相比,主要的改动地方就是在类的定义中加入了卷积层和池化层,具体的参数设置本文并没有仔细研究过,把上其他人设置的参数直接拿来用了,例如卷积核的大小,步长等,这些应该都挺有讲究的。主要是为了先实现这个网络,和只有全连接的对比一下效果。除了类定义有不同外,还有在刚开始输入样本时不需要将样本展开成一维了,这也是卷积神经网络的优势,可以获取三维的信息,但是在完成卷积层池化层的运算之后,还是需要将样本展开为一维向量然后再传入全连接层进行计算,卷积神经网络事实上就是在全连接层的网络前面加入了一系列卷积和池化的操作
这是训练10轮的结果,可以看到训练同样的轮数,识别的准确率相比只有全链接层的网络提高了很多,上一篇中的全连接网络训练10轮准确率是94%多一点,这回的接近98%了,另外,在上一次的计算中,我并没有看到CPU计算和GPU有很多差别,训练一个epoch,GPU大概比CPU快了4秒,但在面对加入卷积层并加深网络之后,GPU的计算优势相当明显
同样是训练1个epoch,CPU用了509s,接近9分钟,而GPU只用了半分钟多,况且我的GPU还只是1650,比1060还差一些,中端性能的GPU,而我的CPU是i7-9750H,应该说是较好的CPU了,因此对深度学习而言,利用GPU加速计算相当重要。在一下一期中,我将继续探索深度神经网络,争取实现几个有代表性的深度网络,比如VGGNet什么的。