深度学习---卷积神经网络之LeNet5(TensorFlow 代码实现)

一、前言

1.1 使用全连接神经网络对图像进行处理存在的问题

1、需要处理的数据量大,效率低

现在的图像都有着极高的像素,假设一张需要处理的图片像素是 1000 * 1000 * 3(彩色图片,具有 RGB 3 个通道),使用具有 100 个隐藏单元的单隐藏层 MLP,模型就有 1000 * 1000 * 3 * 100 = 3 亿个参数,这个模型需要训练的参数数量是巨大的,使用全连接网络训练效率极为低下。

2、图像在维度调整过程中难以保留原有的特征,导致图像处理的准确度不高

回想一下,之前我们将多层感知机模型应用于MNIST数据集中的手写数字图片。 为了能够应用多层感知机,我们首先将每个大小为 28×28 的图像展平为一个 784 维的固定长度的一维向量,然后用全连接层对其进行处理。

当我们对图像进行 Flatten 处理时,很可能改变了图像所表示的信息。举例如下:

假如有圆形是1,没有圆形是0,那么圆形的位置不同就会产生完全不同的数据表达。但从图像的角度来看,图像的内容(本质)并没有发生变化,只是位置发生了变化。

1.2 卷积神经网络(CNN)的构成

CNN 网络主要有三部分构成: 卷积层、池化层(汇聚层)和全连接层组成,其中卷积层负责提取图像中的局部特征;池化层用来降低参数数量(降维);全连接层类似人工神经网络的部分,用来输出想要的结果。

了解卷积操作可参考这篇文章: 卷积神经网络(CNN)——图像卷积_HS_zhangjiong的博客-CSDN博客_图卷积神经网络实现

本文介绍卷积神经网络中的开山之作---LeNet

参考论文---《Handwritten Digit Recognition with a Back-Propagation Network》、《Gradient-Based Learning Applied to Document Recognition》 

二、LeNet 介绍

LeNet 是一系列网络结构,包括 LeNet1-LeNet5。它最早发布的卷积神经网络之一,因其在计算机视觉任务中的高效性能而受到广泛关注。 这个模型是由贝尔实验室的研究员Yann LeCun在1989年提出的(并以其命名),目的是识别图像中的手写数字。

总体来看,LeNet(LeNet-5)由两个部分组成:

  • 卷积编码器: 由两个卷积层组成;

  • 全连接层密集块: 由三个全连接层组成

如下图所示:

论文中的 LeNet-5 网络架构图如下:

 

每个卷积块中的基本单元是一个卷积层、一个 sigmoid 激活函数和平均汇聚层。每个卷积层使用 5×5 卷积核和一个 sigmoid 激活函数。这些层将输入映射到多个二维特征输出,通常同时增加通道的数量。第一个卷积层有6个输出通道,而第二个卷积层有16个输出通道。每个 2×2 池化操作(strides = 2)通过空间下采样将维数减少4倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。

为了将卷积块的输出传递给稠密块,我们必须在小批量中展平每个样本。换言之,我们将这个四维输入(batch_size, height, width, channel)转换成全连接层所期望的二维输入。这里的二维表示的第一个维度索引小批量中的样本,第二个维度给出每个样本的平面向量表示。LeNet 的稠密块有三个全连接层,分别有120、84和10个输出。因为我们在执行分类任务,所以输出层的10维对应于最后输出结果的数量。

三、LeNet-5 代码实现(TensorFlow)

本文使用的 tensorflow 版本为 2.10.0。

论文中 LeNet 池化层使用的是平均池化层,后续证明最大池化更有效,所以本文使用最大池化层。

同时本文的数据集是 MNIST 数据集。

import tensorflow as tf
# 数据集
from tensorflow.keras.datasets import mnist

1. 数据集加载

# 数据集加载
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
test_labels.shape

2. 数据处理

卷积神经网络的输入要求是: B, H, W, C

批量大小、图片高度、宽度、通道数

# 维度调整
train_images = tf.reshape(train_images, (train_images.shape[0], train_images.shape[1], train_images.shape[2], 1))
print(train_images.shape)
test_images = tf.reshape(test_images, (test_images.shape[0], test_images.shape[1], test_images.shape[2], 1))
print(test_images.shape)

3. 模型搭建 

LeNet-5 模型输入得是二维图像,先经过两次卷积层,两次池化层,再经过全连接层,最后用 softmax 分类作为输出结果。

# 模型构建
net = tf.keras.models.Sequential([
    # 卷积层: 6 个 5*5 的卷积核,激活函数是 sigmoid
    tf.keras.layers.Conv2D(filters=6, kernel_size=(5, 5), padding='same', activation='sigmoid', input_shape=(28, 28, 1)),
    # max pooling
    tf.keras.layers.MaxPool2D(pool_size=2, strides=2),
    # 卷积层: 16 5 * 5 sigmoid
    tf.keras.layers.Conv2D(filters=16, kernel_size=(5, 5), activation='sigmoid'),
    # max pooling
    tf.keras.layers.MaxPool2D(pool_size=2, strides=2),
    # 维度调整 将 feature map 拉成一个向量
    tf.keras.layers.Flatten(),
    # 全连接层 sigmoid
    tf.keras.layers.Dense(120, activation='sigmoid'),
    # 全连接层 sigmoid
    tf.keras.layers.Dense(84, activation='sigmoid'),
    # 输出层 softmax
    tf.keras.layers.Dense(10, activation='softmax')
])

使用 net.summary() 查看网络结构

4. 模型编译

设置优化器和损失函数

# 优化器和损失函数
net.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.6), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])

5. 模型训练

# 指明训练数据和验证集
net.fit(train_images, train_labels, epochs=10, batch_size=128, validation_split=0.1)

训练过程如下:

6. 模型评估

score = net.evaluate(test_images, test_labels, verbose=1)
print(f'Test accuracy: {score[1]}')

本文训练后的 LeNet-5 对手写数字数据集的测试精度达到了 97.8%,还是不错的。 

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeNet-5神经网络 C源代码,这个写的比较好,可以用gcc编译去跑,结合理论可以对深度学习有更深刻的了解 介绍 根据YANN LECUN的论文《Gradient-based Learning Applied To Document Recognition》设计的LeNet-5神经网络,C语言写成,不依赖任何第三方库。 MNIST手写字符集初代训练识别率97%,多代训练识别率98%。 DEMO main.c文件为MNIST数据集的识别DEMO,直接编译即可运行,训练集60000张,测试集10000张。 项目环境 该项目为VISUAL STUDIO 2015项目,用VISUAL STUDIO 2015 UPDATE1及以上直接打开即可编译。采用ANSI C编写,因此源码无须修改即可在其它平台上编译。 如果因缺少openmp无法编译,请将lenet.c中的#include和#pragma omp parallel for删除掉即可。 API #####批量训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 inputs: 要训练的多个图片对应unsigned char二维数组的数组,指向的二维数组的batchSize倍大小内存空间指针。在MNIST测试DEMO中二维数组为28x28,每个二维数组数值分别为对应位置图像像素灰度值 resMat:结果向量矩阵 labels:要训练的多个图片分别对应的标签数组。大小为batchSize batchSize:批量训练输入图像(二维数组)的数量 void TrainBatch(LeNet5 *lenet, image *inputs, const char(*resMat)[OUTPUT],uint8 *labels, int batchSize); #####单个训练 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 要训练的图片对应二维数组 resMat:结果向量矩阵 label: 要训练的图片对应的标签 void Train(LeNet5 *lenet, image input, const char(*resMat)[OUTPUT],uint8 label); #####预测 lenet: LeNet5的权值的指针,LeNet5神经网络的核心 input: 输入的图像的数据 labels: 结果向量矩阵指针 count: 结果向量个数 return 返回值为预测的结果 int Predict(LeNet5 *lenet, image input, const char(*labels)[LAYER6], int count); #####初始化 lenet: LeNet5的权值的指针,LeNet5神经网络的核心

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值