Pytorch:经典卷积神经网络LeNet实现

1:前言
入门pytoch也有一段时间了,但是似乎基本上都是阅读别人的demo或者相关论文的源码,对框架的布局有了一定的认识,但是对于很多细节的问题仍然不是特别清楚,因此想通过一个小实践来过一遍流程,一是寻找遗漏的细节,二是通过对小项目的文件分割来建立一个相对可扩展的框架,而不是通过一个流水线下来,这样能够对每一个对象和类起到的作用有一个更加直观的把握。

2:原理

本次博客主要实现最早的卷积神经网络LeNet,相比于AlexNet,ResNet,GoogleNet等目前大火的经典网络,LeNet基本已经退出实践舞台,不过正因为它的简单,对于我们入门卷积神经网络框架提供了很大的便利。它具有以下特点:

1)每个卷积层只包含三个部分:卷积(Conv)、池化(ave-pooling)、非线性激活函数(sigmoid)
2)全连接层作为最后的分类结果,训练和测试阶段的网络没有差别,这也有别于一些在测试阶段需要提取feature map的方式
3)层与层之间稀疏连接减少计算复杂度

网络结构如下:
在这里插入图片描述

3:实现

在基本的方法上,进行了一些小改进,一般对于这种类型的小网络,常用方法是整套流程在一个文件中书写,但是对于一些较大的网络或者一些相对复杂的试验,集中到一个文件就很非常繁杂。虽然没什么必要,不过我们在实践过程中最后能够将各个模块区别开来,也能够帮助我们初学者对各个模块有一个很好的认识。

首先当然是model模块

import torch
import torchvision
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision import transforms
from torch.autograd import Variable
from torch import optim
import torch.nn as nn
import torch.nn.functional as F

class LeNet(nn.Module):
def init(self):
super(LeNet, self).init()
self.conv = nn.Sequential(
nn.Conv2d(1, 6, 3, stride=1, padding=1),
nn.MaxPool2d(2, 2),
nn.Conv2d(6, 16, 5, stride=1, padding=0),
nn.MaxPool2d(2, 2)
)

    self.fc = nn.Sequential(
        nn.Linear(400, 120),
        nn.Linear(120, 84),
        nn.Linear(84, 10)
    )


def forward(self, x):
    out = self.conv(x)
    out = out.view(out.size(0), -1)

    out = self.fc(out)
    return out

我们再次新建一个类Trainer,将训练过程进行简单封装,把optimizer,criterion等作为参数传递,这对于相对大一点的深度学习试验是个很好的方式。

Trainer模块

import numpy as np
import torch
from torchvision.datasets import MNIST
from torch.autograd import Variable

class Trainer(object):
def init(self, model, criterion):
super(Trainer, self).init()
self.model = model
self.criterion = criterion

def train(self,epoch,dataloader,optimizer):
    self.model.train()

    for i in range(epoch):
        sum=0
        runloss=0
        correct=0
        for _,batch in enumerate(dataloader):

            input,target=batch

            sum+=len(target)

            input=Variable(input)
            target=Variable(target)
            output=self.model(input)
            loss=self.criterion(output,target)
            optimizer.zero_grad()

            loss.backward()
            optimizer.step()
            runloss+=loss.data[0]
            _,predict=torch.max(output,1)
            correctnum=(predict==target).sum()
            correct+=correctnum.data[0]

        epoch_loss=runloss/sum
        epoch_correct=correct/sum
        print("epoch {:d}  epoch loss {:f}   epoch_correct {:f}".format(i,epoch_loss,epoch_correct))

接下来就是main函数的模块

import torch
import torchvision
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision import transforms
from torch.autograd import Variable
from torch import optim
import torch.nn as nn
import torch.nn.functional as F
from model import LeNet
from trainer import Trainer
import time

learning_rate = 1e-3
batch_size = 64
epoches = 50

trans_img = transforms.ToTensor()

trainset = MNIST(’./data’, train=True,download=False ,transform=trans_img)
testset = MNIST(’./data’, train=False,download=False, transform=trans_img)

trainloader = DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=4)
testloader = DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=4)

lenet=LeNet()

criterion = nn.CrossEntropyLoss(size_average=False)
optimizer = optim.SGD(lenet.parameters(), lr=learning_rate)

trainer=Trainer(lenet,criterion)
print(‘starting train…’)
trainer.train(10,trainloader,optimizer)

print(‘finish train…’)
print()
print()
sum = 0
runloss = 0
correct = 0
for _, batch in enumerate(testloader):
input, target = batch

sum += len(target)

input = Variable(input)
target = Variable(target)
output = lenet(input)
loss = criterion(output, target)

runloss += loss.data[0]
_, predict = torch.max(output, 1)
correctnum = (predict == target).sum()
correct += correctnum.data[0]

epoch_loss = runloss / sum
epoch_correct = correct / sum
print(“test: epoch loss {:f} epoch_correct {:f}”.format(epoch_loss, epoch_correct))
                                                                                        
在这里进行了简化,我们还能够将test,或者evaluation的过程封装成一个Evaluator的类,尤其是对于验证阶段还需要提取网络中间结果进行相关转化的试验,在Evaluator中实现相关特征提取和距离度量,只为主函数提供最终结果的接口即可。

4:小结

本次试验非常简单,但是能够帮我们寻找到一些容易犯错的细节,对于pytorch或者其他框架的入门者来说,花点时间实践一套流程,还是很有必要的。

由于本人知识有限,相关领域还是初学者阶段,如果存在错误和不足的地方,欢迎指正。

作者:Tian_city
来源:CSDN
原文:https://blog.csdn.net/weixin_41526905/article/details/80107781
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值