【卷积层、BN层(Batch Normalization)、激活函数理解】

一、卷积层

1. 卷积核

卷积层的功能:对数据进行特征提取。
卷积层由输出特征面组成,每个特征面有无数个神经元(像素点)组成。其中输出特征面的每个神经元是通过卷积核对输入特征面中的每个神经元进行卷积操作得到的。
一个卷积核产生一张特征图,n个卷积核产生n个特征图。卷积核的设置规则如下:
用二维来举例。输入一个128 * 128 * 3(长、宽、通道数)的图片则卷积核的大小可设为n * n * 3,个数为m。卷积核的3对应的输入图片的通道数3。代表此卷积核一共有三层,分别对应输入图片的三个通道,进行卷积后产生三张特征图,再进行通道融合为一张。一共有m个n * n * 3的卷积核,即产生m个特征图。卷积核的深度要和输入一致。也就是和通道数一致。

1.1 卷积操作

在这里插入图片描述
上图中的蓝色矩阵为输入的图像,维度为[5, 5, 3],经过0值填充后(灰色值为0部分),维度变为[7, 7, 3],粉色矩阵为卷积层的神经元,这里有两个神经元(w0, w1),每个神经元的维度为[3, 3, 3],步长设置为2,即每个窗口滑动的长度。

蓝色矩阵的输入数据,与filter(粉色矩阵)的权重数据进行矩阵内积计算,将结果与偏置值bias相加,得到的结果为绿色输出矩阵中的一个值。

以第一个窗口计算为例:

[0x1+0x1+0x(-1)+0x(-1)+0x0+1x1+0x(-1)+0x(-1)+1x0] +[0x(-1)+0x0+0x(-1)+0x0+1x0+1x(-1)+0x1+0x(-1)+2x0] + [0x0+0x1+0x0+0x1+2x0+0x1+0x0+0x(-1)+0x1] + 1 = 1

2. 输出层计算公式

若输入数据维度为WxW,填充值P,卷积核Filter大小FxF,步长S,输出数据维度为NxN,则有如下计算公式:
N = [( W - F + 2P)/ S ]+ 1 [*]表示向下取整
[(640-3+2*0)/2]+1=320

3.计算量分析

输入图像C×H×W,卷积核为Cf× K1×K2,N表示卷积核的个数。
计算量= C×H×W×Cf×K1×K2
有bias
计算量 = C×H×W×(Cf×K1×K2 +1)

4.参数量计算

参数量= Cf×K1×K2×C
bias参数量Cout
总参数量 = Cf×K1×K2×C +Cout

二、BN层

1. 为什么要进行BN?

为了训练参数更好更有效地向前传播
为什么参数会出现不好传播的情况呢?主要原因是激活函数的使用。为了增加模型的非线性表达能力,在层与层之间常常加上一层激活函数。而这层激活函数的存在会使得数据分布产生变化,大部分激活函数都会有一个敏感区间,而非敏感区间的数据有可能就在多层的参数传递后丢失了。尤其是在层数特别深的情况下,未经过标准化的数据起到的作用相当有限。

所以,BN层的作用是把一个mini-batch内的所有数据,从不规范的分布拉到正态分布。这样做的好处是使得数据能够分布在激活函数的梯度较大的区域,因此也提高了泛化能力,可以在一定程度上解决梯度消失的问题,同时可以减少dropout的使用。

当参数更好地向前传播后,梯度的下降会更加稳定,可以使用更大的学习率来加快学习。对数据分布的不断调整也减轻了对参数初始化的依赖,利于整体调参。

2.BN操作步骤

在这里插入图片描述

  • 计算mini-batch中的均值
  • 计算mini-batch内的方差
  • 对每一个元素进行归一化(normalize)
  • 进行尺度缩放与偏移操作(scale and shift):偏移和尺度为参数,通过训练来学习,目的是为了补偿网络的非线性表达能力。

2.1 为什么是mini-batch?

主要是由于目前主流的梯度更新方式是mini-batch gradient decent,小批的梯度下降,这种方法把数据分为若干个批,按批来更新参数,这样,一个批中的一组数据共同决定了本次梯度的方向,下降起来就不容易跑偏,减少了随机性。另一方面因为批的样本数与整个数据集相比小了很多,计算量也不是很大。

2.2为什么BN层一般用在线性层和卷积层后面,而不是放在非线性单元后

因为非线性单元的输出分布形状会在训练过程中变化,归一化无法消除它的方差偏移,相反的,全连接和卷积层的输出一般是一个对称,非稀疏的一个分布,更加类似高斯分布,对他们进行归一化会产生更加稳定的分布。

3. Batch Normalization 优缺点

3.1 Batch Normalization 优点

  • 可以加快模型收敛速度 ,不再依赖精细的参数初始化过程。

  • 可以调大学习率,控制梯度爆炸,防止梯度消失等。

  • 同时引入的随机噪声 能够起到对模型参数进行正则化的作用,有利于增强模型泛化能力,防止过拟合。

  • 不仅仅极大提升了训练速度,收敛过程大大加快,还能增加分类效果,一种解释是这是类似于Dropout的一种防止过拟合的正则化表达方式,所以不用Dropout也能达到相当的效果。另外调参过程也简单多了,对于初始化要求没那么高,而且可以使用大的学习率等。总而言之,经过这么简单的变换,带来的好处多得很,这也是为何现在BN这么快流行起来的原因。

3.2 Batch Normalization 不足

  • 如果 Batch Size 太小,则 BN 效果明显下降。因为在小的 BatchSize 意味着数据样本少,因而得不到有效统计量,也就是说噪音太大。
  • 对于有些像素级图片生成任务来说,BN 效果不佳;对于图片分类等任务,只要能够找出关键特征,就能正确分类,这算是一种粗粒度的任务,因为在 Mini-Batch 内多张无关的图片之间计算统计量,弱化了单张图片本身特有的一些细节信息
  • RNN 等动态网络使用 BN 效果不佳且使用起来不方便
  • 训练时和推理时统计量不一致

链接: 批量标准化
链接: 批量标准化和激活函数应用解释

三、激活函数

1.激活函数定义?

激活函数 (Activation functions) 对于人工神经网络模型去学习、理解非常复杂和非线性的函数来说具有十分重要的作用。

2.激活函数必要性

没有激活函数的每层都相当于矩阵相乘,神经网络的每层都只做线性变换,多层输入的叠加也还是线性变换。引入激活函数是为了增加神经网络模型的非线性。
链接: 解释引入激活函数增加非线性的好处

3.常用激活函数

3.1 Sigmoid 函数

sigmoid函数形式为:
f ( x ) = t a n h ( x ) = 1 1 + e − x f(x)=tanh(x)=\frac{1}{1+e^{-x}} f(x)=tanh(x)=1+ex1

其导数形式:
f ′ ( x ) = f ( x ) ( 1 − f ( x ) ) f'(x)=f(x)(1-f(x)) f(x)=f(x)(1f(x))

函数与导数图像如下:
在这里插入图片描述
优点:
1.输出值再(0,1)之间,输出的范围在稳定的范围内,可以用作输出层。实际上sigmoid经常用作输出层来表征概率做二分类问题。
2.函数连续,求导简单高效。
缺点:
1.如果x取值绝对值非常大,输出会饱和,表现为函数图像的两端都很平,此时对输入的变化不敏感。
2.其导数值再函数值很大或者很小的时候都趋近与0,反向传播求导时,很容易梯度消失。
3.因为是指数形式,计算复杂度较高。
4.输出不是0均值,会导致后层的神经元的输入是非0均值的信号,会对梯度产生影响。

3.2 正切函数

正切函数形式如下:
f ( x ) = t a n h ( x ) = e x − e − x e x + e − x f(x)=tanh(x)=\frac{e ^{x}-e^{-x}}{e ^{x}+e^{-x}} f(x)=tanh(x)=ex+exexex
其导数形式为:
f ′ ( x ) = 1 − ( f ( x ) ) 2 f'(x)=1-(f(x))^{2} f(x)=1(f(x))2
函数与导数图像如下:
在这里插入图片描述
与sigmoid函数相比,tanhx是0均值的。但是其导数在两端也存在饱和的现象,导致反向传播无法进行。

3.3 Relu激活函数

ReLU函数,全称为Rectified linear unit,直译过来称为整流线性单元,是目前使用最广泛的激活函数之一。
Relu函数形式:
f ( x ) = m a x ( 0 , x ) f(x)=max(0,x) f(x)=max(0,x)
函数与导数图像如下:
在这里插入图片描述
对比sigmoid,tanh函数,relu有明显的优点:
1.x>0时,不会有梯度消息的现象,反向传播可以顺利进行。
2.没有指数运行,计算简单。
3.收敛速度比上面的激活函数要快。
缺点: Dead ReLU Problem(神经元坏死现象)。
如果参数初始化不当,或者learning rate太高导致在训练过程中参数更新太大,当x<0时候,梯度为0,那么这个神经元以及后面的神经元梯度一直为0,所有的数据将不再被更新。

一般可以采用Xavier初始化方法,同时将learning rate设置为合理的范围,可以避免Dead ReLU Problem现象。

3.4 Leaky ReLU函数

Leaky ReLU函数形式:
f ( x ) = m a x ( α x , x ) f(x)=max(\alpha{x},x) f(x)=max(αx,x)
函数与导数图像如下:
在这里插入图片描述
因为α的存在,从而使得ReLU在负数区域更偏向于激活而不是死掉,因此可以避免出现Dead ReLU Problem的问题。

3.4 ELU(Exponential Linear Units)函数

函数表达式:

f ( x ) = { x , x > 0 α ( e 2 − 1 ) , o t h e r w i s e f(x) = \begin{cases} x , & x>0 \\ \alpha (e^2 -1), &otherwise \\ \end{cases} f(x)={x,α(e21,x>0otherwise
函数与导数图像如下:
在这里插入图片描述
ELU也是为解决ReLU存在的问题而提出,显然,ELU有ReLU的基本所有优点,以及不会有Dead ReLU问题和输出的均值接近0,zero-centered。

  • 9
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
斐波那契查找算法是一种基于二分查找算法的查找算法,它利用了斐波那契数列的特性来确定查找的位置。下面是斐波那契查找算法的设计步骤: 1. 首先,需要确定斐波那契数列的长度,使得它大于等于待查找数组的长度。假设斐波那契数列的长度为n,那么有:F(n) = F(n-1) + F(n-2),其中F(0) = 0,F(1) = 1。 2. 然后,需要将待查找数组扩展到长度为n,扩展的部分用原数组的最后一个元素填充。 3. 接着,需要定义两个指针:low和high。初始时,low指向待查找数组的第一个元素,high指向斐波那契数列中第一个大于等于n的元素的下标减1。 4. 然后,需要计算mid的值,mid的值为low加上斐波那契数列中第k-1个元素的值,其中k为满足F(k)-1 >= n的最小值。 5. 然后,比较待查找数组中第mid个元素和要查找的元素的大小。如果待查找数组中第mid个元素小于要查找的元素,则将low指向mid+1;如果待查找数组中第mid个元素大于要查找的元素,则将high指向mid-1;否则,找到了要查找的元素,返回mid。 6. 重复步骤4和步骤5,直到low大于high为止。 下面是一个Python实现的斐波那契查找算法的例子: ```python def fibonacci_search(arr, x): n = len(arr) fib_k2 = 0 # F(k-2) fib_k1 = 1 # F(k-1) fib_k = fib_k1 + fib_k2 # F(k) while fib_k < n: fib_k2 = fib_k1 fib_k1 = fib_k fib_k = fib_k1 + fib_k2 offset = -1 while fib_k > 1: i = min(offset+fib_k2, n-1) if arr[i] < x: fib_k = fib_k1 fib_k1 = fib_k2 fib_k2 = fib_k - fib_k1 offset = i elif arr[i] > x: fib_k = fib_k2 fib_k1 = fib_k1 - fib_k2 fib_k2 = fib_k - fib_k1 else: return i if fib_k1 and arr[offset+1] == x: return offset+1 return -1 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值