本文基于python-pytorch框架,编写CNN网络,并采用CNN手写数字数据集训练、测试网络。

网络的构建

以LeNet-5 网络为例

类定义

首先先了解一下网络的最基本框架

  • 一般而言,首先创建一个类class,创建时,继承nn.Module父类,注意,在该类的构造函数中__init__中,显示的调用其父类的构造函数super(...).__init__()
  • 网络的结构,例如卷积层、线性层等,一般在其构造函数中定义。
  • 对于一些不带参数的网络结构,也可以在forward方法中直接调用,而不定义,但不推荐。
  • 每一个网络类必须显示的定义forward方法,编写程序时需要在该函数中编写运算,实现对输入张量(tensor)的运算,并最后给予返回值;通常forward函数的返回值也为张量(tensor)。
import torch.nn as nn

class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
''' Definition of Network Structure ''' def forward(self, x):
# x = f(x)
return x

卷积模块/特征提取器

self.features = nn.Sequential(
nn.Conv2d(1, 6, kernel_size=5, stride=1, padding=2), # 28x28x1 -> 28x28x6
nn.Tanh(),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5, stride=1), # 14x14x6 -> 10x10x16
nn.Tanh(),
nn.MaxPool2d(kernel_size=2, stride=2)
)
卷积层

nn.Conv2d 是 PyTorch 中用于定义二维卷积层的一个模块。其参数配置的含义如下:

  1. in_channels (1): 输入图像的通道数。对于单通道的灰度图像,值为 1;对于 RGB 图像,则为 3。

  2. out_channels (6): 卷积层输出的通道数,即卷积核的数量。每个卷积核会产生一个输出通道。这里设置为 6,意味着该卷积层会生成 6 个特征图(feature maps)。

  3. kernel_size (5): 卷积核的尺寸。这里的 5 表示使用 5x5 的卷积核。这是一个正方形的卷积核大小,但也可以设置成不相等的高度和宽度,比如 (5, 3)

  4. stride (1): 卷积操作的步幅。步幅决定了卷积核在输入图像上滑动的速度。步幅为 1 表示卷积核每次滑动一个像素。

  5. padding (2): 输入图像的边界填充。填充用于控制输出特征图的空间尺寸,通常用于保持特征图的尺寸不变或减少尺寸。这里的 2 表示在每一边填充 2 个像素。

综上,nn.Conv2d(1, 6, kernel_size=5, stride=1, padding=2) 的设置表示从单通道的输入图像中提取 6 个特征图,每个特征图通过一个 5x5 大小的卷积核生成,卷积操作的步幅为 1,并且在输入图像的每一边填充 2 个像素以控制输出尺寸。

激活函数

nn.Tanh() 是 PyTorch 中的一个激活函数层,它实现了双曲正切函数(tanh)。激活函数在神经网络中用于引入非线性特性,从而使网络能够学习更复杂的模式和特征。

双曲正切函数的数学形式是:

\[\text{tanh}(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}
\]

该函数的输出范围是 ([-1, 1]),具有以下特点:

  1. 非线性:tanh 是一个非线性函数,使得神经网络能够处理更复杂的任务。

  2. 输出范围:输出值范围在 -1 到 1 之间,零中心化,使得均值接近零,这可以帮助加快训练过程和提高模型的收敛速度。

  3. 梯度:tanh 函数的导数在输入接近 0 时最大(为 1),而在输入较大或较小时梯度逐渐变小,这意味着它在大输入值时可能会遇到梯度消失的问题。

在 PyTorch 中,nn.Tanh() 可以作为模型的一个层来应用于网络的前向传播中:

nn.MaxPool2d 是 PyTorch 中的一个池化层,用于对二维输入数据进行最大池化操作。池化操作常用于卷积神经网络(CNN)中,以减少特征图的空间尺寸,减少计算量和过拟合的风险,并提高模型的鲁棒性。

池化层

nn.MaxPool2d(kernel_size=2, stride=2) 的参数含义如下:

  1. kernel_size (2): 池化窗口的尺寸。这里的 2 表示池化窗口是 2x2 的正方形区域。池化操作将在每个 2x2 的区域内选取最大值。

  2. stride (2): 池化窗口在输入特征图上滑动的步幅。步幅为 2 表示池化窗口每次滑动 2 个像素。这意味着池化操作会将特征图的空间尺寸缩小为原来的一半。

具体功能:

  • 最大池化:在池化窗口(2x2 区域)内选择最大值,并用该最大值替代整个窗口区域中的所有值。这样,池化层能够保留特征图中的重要信息,同时减少空间尺寸。

作用:

  • 降维:通过池化操作减少特征图的空间尺寸(宽度和高度),从而减少计算量和内存消耗。

  • 提高鲁棒性:池化操作可以使网络对位置的微小变化更具鲁棒性,因为它只保留局部区域的最大值。

  • 防止过拟合:通过减少特征图的尺寸,可以降低模型的复杂性,从而减少过拟合的风险。

解释:

对于一个 4x4 的输入特征图,使用 2x2 的池化窗口和步幅为 2,池化操作会将特征图缩小为 2x2 的尺寸,每个池化窗口选择区域内的最大值。例如,在 2x2 的池化窗口内,[[1, 2], [5, 6]] 会变成 6,依此类推。

总之,nn.MaxPool2d 是卷积神经网络中常用的池化层,用于减少特征图的尺寸和计算复杂度,同时保留重要的特征信息。

线性层/分类器

self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(16 * 5 * 5, 120), # 全连接层1
nn.Tanh(),
nn.Linear(120, 84), # 全连接层2
nn.Tanh(),
nn.Linear(84, 10) # 输出层
)
展平函数

nn.Flatten() 是 PyTorch 中用于将多维张量展平成一维张量的模块。这个操作通常在卷积层(Convolutional Layers)和线性层(Linear Layers)之间使用,以便将卷积层输出的多维特征图转换成适合于线性层处理的一维特征向量。

nn.Flatten() 的主要作用是将输入张量从多维转换为一维。例如,对于形状为 (N, C, H, W) 的输入张量,使用 nn.Flatten() 后,输出的张量将变为形状为 (N, C * H * W) 的一维张量。

为什么在卷积层和线性层之间使用 nn.Flatten()

  1. 卷积层的输出是多维的:卷积层生成的输出通常是一个四维张量,表示批量的特征图,其中包含多个通道的二维特征图。为了将这些特征图传递到线性层,必须将其展平成一维张量,因为线性层要求输入为一维特征向量。

  2. 线性层的输入是一维的:线性层(也称全连接层)只能处理一维的输入数据。通过 nn.Flatten(),可以将卷积层的多维输出展平为一维,从而可以将其作为线性层的输入。

  3. 连接卷积和线性层:卷积层通常用于提取特征,而线性层则用于对这些特征进行分类或回归等任务。在这些任务中,线性层处理的是扁平化的特征向量,因此需要将卷积层的输出展平。

总结

nn.Flatten() 在卷积神经网络(CNN)的前向传播中充当了重要的角色,它将卷积层的多维特征图展平为线性层所需的一维特征向量。这使得卷积层提取的复杂特征可以被线性层进一步处理,从而完成分类、回归等任务。

nn.Linear 的基本概念

nn.Linear 是 PyTorch 中的一个模块,用于实现线性变换,也称为全连接层(Fully Connected Layer,FC Layer)。它将输入的特征通过一个线性变换映射到输出特征。

参数解释

  1. 输入特征的数量 (in_features):

    • nn.Linear(16 * 5 * 5, 120) 中,第一个参数 16 * 5 * 5 表示输入特征的数量。
    • 16 通常表示通道数,5 * 5 是特征图的高度和宽度。这里的计算表示输入的特征总数为 16 * 5 * 5 = 400
    • 卷积层的输出经过 Flatten 层处理后,变为一维向量。
  2. 输出特征的数量 (out_features):

    • 第二个参数 120 表示输出特征的数量。在这个例子中,模型将输出一个长度为 120 的一维向量。

线性层的功能

线性层的功能可以用数学公式表示为:

\[y = Ax + b
\]
  • 其中 \(y\) 是输出,\(A\) 是权重矩阵,\(x\) 是输入,\(b\) 是偏差项。

在使用 nn.Linear(16 * 5 * 5, 120) 时,PyTorch 会自动创建一个形状为 (120, 400) 的权重矩阵和一个形状为 (120,) 的偏差向量。权重和偏差会在训练过程中进行学习和优化。

总结

  • nn.Linear(16 * 5 * 5, 120)用于定义一个线性层,它将输入的 400 维特征向量映射到 120 维输出向量。
  • 此层通常用于将卷积层提取的特征连接到分类器或其他层,以形成完整的神经网络架构。

代码汇总

import torch.nn as nn

# LeNet-5
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 6, kernel_size=5, stride=1, padding=2), # 28x28x1 -> 28x28x6
nn.Tanh(),
nn.MaxPool2d(kernel_size=2, stride=2), # 池化层
nn.Conv2d(6, 16, kernel_size=5, stride=1), # 14x14x6 -> 10x10x16
nn.Tanh(),
nn.MaxPool2d(kernel_size=2, stride=2) # 池化层
)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(16 * 5 * 5, 120), # 全连接层1
nn.Tanh(),
nn.Linear(120, 84), # 全连接层2
nn.Tanh(),
nn.Linear(84, 10) # 输出层
) def forward(self, x):
x = self.features(x)
x = self.classifier(x)
return x

卷积神经网络CNN实战:MINST手写数字识别——网络定义的更多相关文章

  1. 卷积神经网络应用于tensorflow手写数字识别(第三版)

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_dat ...

  2. MINST手写数字识别(三)—— 使用antirectifier替换ReLU激活函数

    这是一个来自官网的示例:https://github.com/keras-team/keras/blob/master/examples/antirectifier.py 与之前的MINST手写数字识 ...

  3. keras和tensorflow搭建DNN、CNN、RNN手写数字识别

    MNIST手写数字集 MNIST是一个由美国由美国邮政系统开发的手写数字识别数据集.手写内容是0~9,一共有60000个图片样本,我们可以到MNIST官网免费下载,总共4个.gz后缀的压缩文件,该文件 ...

  4. [Python]基于CNN的MNIST手写数字识别

    目录 一.背景介绍 1.1 卷积神经网络 1.2 深度学习框架 1.3 MNIST 数据集 二.方法和原理 2.1 部署网络模型 (1)权重初始化 (2)卷积和池化 (3)搭建卷积层1 (4)搭建卷积 ...

  5. 第三节,CNN案例-mnist手写数字识别

    卷积:神经网络不再是对每个像素做处理,而是对一小块区域的处理,这种做法加强了图像信息的连续性,使得神经网络看到的是一个图像,而非一个点,同时也加深了神经网络对图像的理解,卷积神经网络有一个批量过滤器, ...

  6. MINST手写数字识别(一)—— 全连接网络

    这是一个简单快速入门教程——用Keras搭建神经网络实现手写数字识别,它大部分基于Keras的源代码示例 minst_mlp.py. 1.安装依赖库 首先,你需要安装最近版本的Python,再加上一些 ...

  7. MINST手写数字识别(二)—— 卷积神经网络(CNN)

    今天我们的主角是keras,其简洁性和易用性简直出乎David 9我的预期.大家都知道keras是在TensorFlow上又包装了一层,向简洁易用的深度学习又迈出了坚实的一步. 所以,今天就来带大家写 ...

  8. 【TensorFlow-windows】(四) CNN(卷积神经网络)进行手写数字识别(mnist)

    主要内容: 1.基于CNN的mnist手写数字识别(详细代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3-4.2.0-Windows-x86_64. ...

  9. MindSpore手写数字识别初体验,深度学习也没那么神秘嘛

    摘要:想了解深度学习却又无从下手,不如从手写数字识别模型训练开始吧! 深度学习作为机器学习分支之一,应用日益广泛.语音识别.自动机器翻译.即时视觉翻译.刷脸支付.人脸考勤--不知不觉,深度学习已经渗入 ...

  10. 【深度学习系列】手写数字识别卷积神经--卷积神经网络CNN原理详解(一)

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

随机推荐

  1. 2020-2021 ICPC, NERC, Northern Eurasia Onsite BEIJ 题解

    B. Button lock 题意:有 \(d\) 个 01 按键以及一个 reset 按键,你需要把所有题目给定的 \(n\) 个密码全部表示一遍.只有按下 reset 按键后才能使所有 01 按键 ...

  2. Mysql 使用(一)

    一.数据库的种类 关系型数据库 非关系型数据库 二.常见关系型数据库 oracle:在以前的大型项目中使用,银行,电信等项目 mysql:web时代使用最广泛的关系型数据库 ms sql server ...

  3. 在Linux驱动中使用timer定时器

    在Linux驱动中使用timer定时器 原文(有删改): https://www.cnblogs.com/chen-farsight/p/6226562.html 介绍 内核定时器是内核用来控制在未来 ...

  4. Zynq 7000的3种IO

    概念 MIO MIO:多功能IO接口(分配在 GPIO 的 Bank0 和Bank1),属于Zynq的PS部分,在芯片外部有54个引脚.这些引脚可以用在GPIO.SPI.UART.TIMER.Ethe ...

  5. Oracle 三种分页方法

    Oracle的三层分页指的是在进行分页查询时,使用三种不同的方式来实现分页效果,分别是使用ROWNUM.使用OFFSET和FETCH.使用ROW_NUMBER() OVER() 1.使用ROWNUM ...

  6. Advanced .Net Debugging 10:事后调试

    一.介绍 这是我的<Advanced .Net Debugging>这个系列的第十篇文章.这篇文章的内容是原书的第三部分的[高级主题]的第八章[事后调试].前面几篇文章,我们介绍了很多工具 ...

  7. 阿里云服务器Docket安装RabbitMQ 3.8.12

    DocketMQ安装RabbitMQ 地址:https://hub.docker.com/ 拉取镜像 docker pull rabbitmq:3.8.12-management-alpine 运行 ...

  8. 基于 Vagrant 手动部署多个 Redis Server

    环境准备 宿主机环境:Windows 10 虚拟机环境:Vagrant + VirtualBox Vagrantfile 配置 首先,我们需要编写一个 Vagrantfile 来定义我们的虚拟机配置. ...

  9. C语言基础要点

    C语言基础 C语言基础 C程序编译过程 C程序编译步骤 汇编语言 32关键字 数据类型 常量 size程序 类型限定 goto语句 指针 指针和字符串 作用域 函数 内存 进程内存结构 可执行文件结构 ...

  10. RHCA rh442 009 磁盘算法 RAID相关 磁盘压力测试

    磁盘 一个数据在磁盘A位置,一个数据在磁盘B位置,他们如果隔着很远.这对磁盘来说性能很差 (机械盘,磁头来回移动) 一个数据写进来,他会把数据放到缓存中,经过磁盘调度算法来调度,最后写到硬盘 io读写 ...