Pytorch:LeNet

Pytorch:LeNet(Mnist数据集)

一、实验环境:

  • Python 3.6
  • Pytorch 0.4.0
  • torchvision 0.2.1

二、Mnist说明:

MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员. 测试集(test set) 也是同样比例的手写数字数据.

MNIST是深度学习的经典入门demo,他是由6万张训练图片和1万张测试图片构成的,每张图片都是28*28大小(如下图),而且都是黑白色构成(这里的黑色是一个0-1的浮点数,黑色越深表示数值越靠近1),这些图片是采集的不同的人手写从0到9的数字。

MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取, 它包含了四个部分:

  • Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)
  • Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)
  • Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)
  • Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)

三、LeNet5模型

  • INPUT → C1

        图像原始为28*28,但我们进行卷积操作的时候会设置padding = 2,即将图像填充为28+2*2 = 32的图像,所以C1的输入其实是  32*32,这样卷积后的特征图还是28*28。C1层共有6个卷积核,卷积核大小为5*5,经过6个卷积核的操作,生成六个feature maps ,也就是输出6*28*28。

  • C1 → S2

        采用一个最大池化,对输入的特征图进行压缩,一方面使特征图变小,简化网络计算复杂度;一方面进行特征压缩,提取主要特征,生成6个14*14的feature maps

  • S2 → C3难点

        C3中的每个特征map是连接到S2中的所有6个或者几个特征map的,表示本层的特征map是上一层提取到的特征map的不同组合。

        存在的一个方式是:C3的前6个特征图以S2中3个相邻的特征图子集为输入。接下来6个特征图以S2中4个相邻特征图子集为输入。然后的3个以不相邻的4个特征图子集为输入。最后一个将S2中所有特征图为输入。则:可训练参数:6*(3*5*5+1)+6*(4*5*5+1)+3*(4*5*5+1)+1*(6*5*5+1)=1516

        连接数:10*10*1516=151600

        详细说明:第一次池化之后是第二次卷积,第二次卷积的输出是C3,16个10x10的特征图,卷积核大小是 5*5. 我们知道S2 有6个 14*14 的特征图,怎么从6 个特征图得到 16个特征图了? 这里是通过对S2 的特征图特殊组合计算得到的16个特征图。具体如下:

        C3的前6个feature map(对应上图第一个红框的6列)与S2层相连的3个feature map相连接(上图第一个红框),后面6个feature map与S2层相连的4个feature map相连接(上图第二个红框),后面3个feature map与S2层部分不相连的4个feature map相连接,最后一个与S2层的所有feature map相连。卷积核大小依然为5*5,所以总共有6*(3*5*5+1)+6*(4*5*5+1)+3*(4*5*5+1)+1*(6*5*5+1)=1516个参数。而图像大小为10*10,所以共有151600个连接。

C3与S2中前3个图相连的卷积结构如下图所示:

        上图对应的参数为 3*5*5+1,一共进行6次卷积得到6个特征图,所以有6*(3*5*5+1)参数。 为什么采用上述这样的组合了?论文中说有两个原因:1)减少参数,2)这种不对称的组合连接的方式有利于提取多种组合特征。

  • C3 S4

同上,采用一个最大池化,下采样,从16个10*10的feature maps传化层16个5*5的feature maps。

  • S4 C5

C5层是一个卷积层。由于S4层的16个图的大小为5x5,与卷积核的大小相同,所以卷积后形成的图的大小为1x1。

  • C5  F6

输入是120维向量,计算方式:计算输入向量和权重向量之间的点积,再加上一个偏置,结果通过sigmoid函数输出。一共有84个节点。

  • F6 OUTPUT

Output层也是全连接层,共有10个节点,分别代表数字0到9,且如果节点i的值为0,则网络识别的结果是数字i。

Pytorch训练代码:

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")   #若检测到GPU环境则使用GPU,否则使用CPU。

class LeNet(nn.Module): #定义网络 pytorch定义网络有很多方式,推荐以下方式,结构清晰
    def __init__(self):
        super(LeNet,self).__init__()
        self.conv1 = nn.Sequential(     #input_size=(1*28*28)
            nn.Conv2d(1,6,5,1,2),       #padding=2,图片大小变为 28+2*2 = 32 (两边各加2列0),保证输入输出尺寸相同
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2 ,stride = 2)   #input_size=(6*28*28),output_size=(6*14*14)
        )

        self.conv2 = nn.Sequential(
            nn.Conv2d(6,16,5),                          #input_size=(6*14*14),output_size=16*10*10
            nn.ReLU(),
            nn.MaxPool2d(kernel_size = 2,stride = 2)    ##input_size=(16*10*10),output_size=(16*5*5)
        )

        self.fc1 = nn.Sequential(
            nn.Linear(16*5*5,120),
            nn.ReLU()
        )

        self.fc2 = nn.Sequential(
            nn.Linear(120,84),
            nn.ReLU()
        )

        self.fc3 = nn.Linear(84,10)

    #网络前向传播过程
    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)

        x = x.view(x.size(0), -1) #全连接层均使用的nn.Linear()线性结构,输入输出维度均为一维,故需要把数据拉为一维
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x



#load data
transform = torchvision.transforms.ToTensor()   #定义数据预处理方式:转换 PIL.Image 成 torch.FloatTensor

train_data = torchvision.datasets.MNIST(root="F:/local code/Pytorch Learning/data/",    #数据目录,这里目录结构要注意。
                                        train=True,                                     #是否为训练集
                                        transform=transform,                            #加载数据预处理
                                        download=False)                                 #是否下载,这里下载偏慢
test_data = torchvision.datasets.MNIST(root="F:/local code/Pytorch Learning/data/",
                                        train=False,
                                        transform=transform,
                                        download=False)

train_loader = torch.utils.data.DataLoader(dataset = train_data,batch_size = 64,shuffle = True) #数据加载器:组合数据集和采样器
test_loader = torch.utils.data.DataLoader(dataset = test_data,batch_size = 64,shuffle = False)

#define loss
net = LeNet().to(device)    #实例化网络,有GPU则将网络放入GPU加速
loss_fuc = nn.CrossEntropyLoss()    #多分类问题,选择交叉熵损失函数
optimizer = optim.SGD(net.parameters(),lr = 0.001,momentum = 0.9)   #选择SGd,学习率取0.001

#Star train
EPOCH = 8   #训练总轮数
for epoch in range(EPOCH):
    sum_loss = 0
    #数据读取
    for i,data in enumerate(train_loader):
        inputs,labels = data
        inputs, labels = inputs.to(device), labels.to(device)   #有GPU则将数据置入GPU加速

        # 梯度清零
        optimizer.zero_grad()

        # 传递损失 + 更新参数
        output = net(inputs)
        loss = loss_fuc(output,labels)
        loss.backward()
        optimizer.step()

        # 每训练100个batch打印一次平均loss
        sum_loss += loss.item()
        if i % 100 == 99:
            print('[Epoch:%d, batch:%d] train loss: %.03f' % (epoch + 1, i + 1, sum_loss / 100))
            sum_loss = 0.0

    correct = 0
    total = 0

    for data in test_loader:
        test_inputs, labels = data
        test_inputs, labels = test_inputs.to(device), labels.to(device)
        outputs_test = net(test_inputs)
        _, predicted = torch.max(outputs_test.data, 1)  #输出得分最高的类
        total += labels.size(0) #统计50个batch 图片的总个数
        correct += (predicted == labels).sum()  #统计50个batch 正确分类的个数


    print('第%d个epoch的识别准确率为:%d%%' % (epoch + 1, (100 * correct / total)))

实验结果:

参考文献:

1.https://blog.csdn.net/sunqiande88/article/details/80089941

2.https://cuijiahua.com/blog/2018/01/dl_3.html

 

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值