神经网络技术
神经网络概念与术语
感知机与神经元
前馈神经网络
卷积神经网络 CNN
CNN,即卷积神经网络(Convolutional Neural Network),是一种特别为处理具有类似网格结构(比如,图片)的数据而设计的深度学习算法,最典型的应用是图像识别和处理,其中数据可以被视为2D网格。CNN通过卷积层、池化层和全连接层的组合来自动并有效地提取图像中的特征,用于分类、检测等任务。
这是CNN的标准定义,卷积神经网络,这个翻译至少给理解它加深了一个难度。Convolutional 解释为盘旋,缠绕,估计就好很多。配合下面这张gif图,就彻底搞明白了。本质上,是使用了一个卷积核(过滤器,或者叫matrix),类似盘旋的方式,依次从左到右,从上到下,跟输入数据做加减乘除
运算。
CNN的由来
CNN的基础理念可以追溯到Hubel和Wiesel在1960年代对猫的视觉皮层的研究,他们发现视觉皮层包含专门对光斑、边缘等简单模式敏感的神经元。
基于这一发现,Fukushima在1980年提出了一个层次化的、无监督学习的神经网络模型,称为“Neocognitron”,可以看作是现代CNN的雏形。CNN在1998年由Yann LeCun及其合作者提出,提出CNN最初的目的是为了解决全连接神经网络在处理数据时的局限性。
图像数据具有一种固有的空间结构 - 相邻的像素点在空间上是相连的,并携带着相似的局部模式和特征。例如一个像素及其周围的像素很可能属于同一个边缘或物体的一部分。
传统的全连接神经网络,将图像数据直接展平作为输入,把图像转化为1维向量,这意味着图像中相邻像素之间的空间邻近性信息丢失,破坏了图像的局部连续性特征,也不能有效地利用图像中的平移不变性。
网络在处理这个向量时,等同对待所有特征(像素值),无法识别哪些特征是相邻并可能具有相关性的。比如,识别图片中是否有一只猫,我们希望的是,猫在图片的左边,或者右边(相当于做了图像的平移),都能够识别出来,全连接神经网络并不能很好地解决。
CNN网络结构如下,接下来,我们来讲讲理解CNN网络结构,必须要了解的知识点。
什么是卷积核(filter)
卷积核(或过滤器)在卷积神经网络(CNN)中是用于提取特征的关键组件。每个卷积核由一系列可学习的权重组成,以帮助模型识别输入数据中的特定模式或特征,这些核通过在输入数据上滑动(盘旋
操作)来应用,从而产生特征图(feature map),这个过程能够捕获输入数据中的空间和模式信息。
每个卷积核仅与输入图像的一个小区域(即局部感知域)进行运算,这意味着网络的每个神经元不需要一次性处理整个图像,而是只处理一小块区域。这种机制使得卷积核能够捕捉到局部的特征,如边缘、角点、纹理等。
卷积操作的另一个关键特性是权重共享,即网络中的卷积核在整个输入图像上滑动时使用相同的权重集。这不仅显著减少了模型的参数数量,提高了训练效率,而且意味着一旦卷积核学会了在图像的某一部分识别特定特征,它就可以在图像的任何其他部分识别同样的特征。这种平移不变性(即特征不论位于图像何处都能被相同方式识别的能力)是卷积神经网络特别适合图像处理任务的关键原因之一。
核的大小会影响模型捕捉输入数据特征的能力:
小核尺寸(如1x1,3x3):能够捕捉到细粒度特征,对于捕获局部信息非常有效。3x3尺寸的核特别流行,因为它们在提取特征时提供了良好的平衡,既能捕获重要信息,又能保持计算效率。多个3x3的卷积层堆叠在一起,可以有效地增加网络的深度,而不会显著增加参数数量和计算复杂度。
大核尺寸(如5x5,7x7):可以捕捉更广泛的空间信息,对于提取更大范围的特征很有帮助。但是,大核尺寸会增加模型的参数数量,从而增加计算负担和过拟合的风险。
实际应用中,核大小的选择取决于具体任务和输入数据的特性。一般来说,3x3的核被广泛认为是效率和效果之间的一个好平衡,并且是很多现代CNN架构的首选。
卷积核与输入层的Channel
channels 该如何理解?先看一看不同框架中的解释文档。
首先,是 tensorflow 中给出的,对于输入样本中 channels 的含义。一般的RGB图片,channels 数量是 3 (红、绿、蓝);而monochrome图片,channels 数量是 1 。channels : Number of color channels in the example images. For color images, the number of channels is 3 (red, green, blue). For monochrome images, there is just 1 channel (black). ——tensorflow
其次,mxnet 中提到的,一般 channels 的含义是,每个卷积层中卷积核的数量。channels (int) : The dimensionality of the output space, i.e. the number of output channels (filters) in the convolution. ——mxnet
为了更直观的理解,看下面的例子,图片使用自吴恩达老师的深度学习课程。
如下图,假设现有一个为 6×6×3的图片样本,使用 3×3×3的卷积核(filter)进行卷积操作。此时输入图片的 channels 为 3,而卷积核中的 in_channels 与 需要进行卷积操作的数据的 channels 一致(这里就是图片样本,为3)。
接下来,进行卷积操作,卷积核中的27个数字分别与样本对应相乘后,再进行求和,得到第一个结果。依次进行,最终得到 4×4的结果。
上面步骤完成后,由于只有一个卷积核,所以最终得到的结果为 4×4×1,out_channels 为 1。
在实际应用中,都会使用多个卷积核。这里如果再加一个卷积核,就会得到 4×4×2的结果。
总结一下,把上面提到的 channels 分为三种:
最初输入的图片样本的 channels ,取决于图片类型,比如RGB;
卷积操作完成后输出的 out_channels ,取决于卷积核的数量。此时的 out_channels 也会作为下一次卷积时的卷积核的 in_channels;
卷积核中的 in_channels ,刚刚2中已经说了,就是上一次卷积的 out_channels ,如果是第一次做卷积,就是1中样本图片的 channels 。
在CNN中,想搞清楚每一层的传递关系,主要就是 height,width 的变化情况,和 channels 的变化情况。
卷积核是如何跟输入做计算的,为什么要做padding?
卷积运算的基本过程是:卷积核(也叫滤波器kernel)在输入数据(如图像)上滑动,对与卷积核覆盖的局部数据区域进行元素级别的加权求和运算(就是小学学的加减乘除
四则运算),得到一个卷积后的特征映射。
如下面这个例子,假设输入数据是个二维矩阵,卷积核也是一个二维矩阵(当然也可以是三维的用于彩色图像),卷积核在输入数据上按stride(步长)大小滑动,在每个位置,将卷积核与输入数据的对应区域进行元素级别乘法、求和运算,得到一个新的像素值,最终就得到了一个新的特征映射层。
或者这样理解,卷积核3x3的矩阵,覆盖在原来输入的数据上,也就得到两个重叠在一起的九宫格,九宫格中重叠位置的元素做乘法运算,运算的结果做加法,然后输出到对应的位置。
那为什么还要做padding呢?核心原因有三个:
提升数据边缘特征信号的有效性,如果观察卷积操作的过程,我们可以发现,边缘数据参与卷积的次数要小于中间区域,在处理图像等空间数据时,边缘区域包含有用的信息,尤其是对于图像识别、边缘检测等任务。不使用padding可能会导致边缘信息在每次卷积操作后逐渐减少,特别是在深层网络中,这可能会损害模型的性能。
支持深层次的网络结构,在设计深层网络时,可能需要多个卷积层叠加。如果每次卷积都减小特征图的尺寸,会限制网络深度,因为特征图的尺寸不能无限缩小。通过使用padding保持尺寸不变,可以构建更深的网络结构,而不必担心输入尺寸的快速减少。
便于后续做特征融合。
那么,如何做Padding呢?通用做法是给原来的输入扩展出边缘
,使得卷积核能从边缘处开始计算。padding和计算过程可以看下面这个gif图。
什么是子采样,池化(pooling)
本文子采样(Subsampling)和池化(Pooling)是卷积神经网络(CNN)中常用的操作,用于减小特征图的尺寸,从而减少计算量和模型参数的数量。这两种操作有助于提高模型的泛化能力,通过减少过拟合的风险来提升模型性能。
子采样和池化还是有一些区别,接下来分别讲解。
- subsampling(子采样)
子采样是一种减少数据维度和复杂度的过程,旨在降低后续层的计算需求并提高模型的效率。在图像处理和深度学习中,子采样通常意味着减小图像或特征图的尺寸,同时尽量保留重要信息。子采样的方法包括但不限于:
调整卷积核的stride:卷积核默认是一次挪一步,可以改成2步,减少采样
池化操作,也就是下面要讲的pooling
- 池化(pooling)
池化是子采样的一种特殊形式,专门用于深度学习中。它通过对特征图的邻近像素进行聚合操作来减小尺寸,最常见的池化操作是最大池化(Max Pooling,取区域内的最大值)和平均池化(Average Pooling,取区域内的平均值)。
池化层的引入是基于这样一个观察:在图像中,一旦一个特征被检测到,其确切的位置相对于周围的像素来说就不那么重要。通过池化,CNN能够检测到特征的存在,并对图像中的小变化(如平移)保持不变性。此外,池化层通过减少特征图的尺寸,帮助减少计算量和模型的过拟合风险。
maxpooling
pooling翻译成池化,也是有故意提升难度的嫌疑。pooling,本质是提取某一个区域内,最显著的特征,比如做max pooling,我们就可以理解为,在做指定的区域内(pool,想象成泳池的形状,框住一片数据),图像如果出现平移,我们提取的特征都是一样的,因为不管最大值在上下左右的哪个位置,那片区域的最大值都是一样的。
什么是dropout,它有什么作用
Dropout是一种在训练深度神经网络时广泛使用的正则化技术,由Srivastava等人在2014年提出。它的核心思想非常直观:在网络的训练过程中,随机丢弃(以一定的概率,不计算某些神经元)网络中的一部分神经元(以及它们的连接),从而防止模型对训练数据的过拟合。
这意味着在每次训练迭代中,每个神经元都有一定概率不被包含在前向和后向传播过程中,这个概率由dropout率控制,通常设置为0.5(即50%的概率被丢弃)。
在实践中,应用dropout非常简单。只有在神经网络的训练过程中,在全连接层或卷积层之后加入dropout层。在测试或评估模型时,关闭dropout(即保留所有的神经元),确保所有的特征都被用于决策。
pytorch实现CNN示例
用pytorch实现一个简单的CNN网络架构:
- 第一个卷积层:使用32个3x3的卷积核,步长为1,激活函数为ReLU。
- 第一个池化层:使用2x2的最大池化。
- 第二个卷积层:使用64个3x3的卷积核,步长为1,激活函数为ReLU。
- 第二个池化层:使用2x2的最大池化。
- 一个全连接层:将前一层的输出平坦化后,连接到一个具有128个神经元的全连接层,激活函数为ReLU。
- 输出层:一个具有10个神经元的全连接层,对应于10个类别的输出,使用Softmax函数作为激活函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import torch
import torch.nn as nn
import torch.nn.functional as F
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(7*7*64, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 7*7*64)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return F.log_softmax(x, dim=1)
# 实例化模型
model = SimpleCNN()
print(model)
循环神经网络(RNN)
- 循环神经网络(recurrent neural network):时间上的展开,处理的是序列结构的信息,是有环图
- 递归神经网络(recursive neural network):空间上的展开,处理的是树状结构的信息,是无环图
二者简称都是 RNN,但是一般提到的RNN指的是循环神经网络(recurrent neural network)
循环神经网络是一类用于处理序列数据的神经网络,就像卷积神经网络是专门用于处理网格化数据(如一张图像)的神经网络,循环神经网络时专门用于处理序列 x^{(1)},…,x^{(T)} 的神经网络。
深度信念网络
生成对抗网络
持续完善中