1、卷积
前向过程
Convolution概念
既然叫卷积神经网络,那么就先了解这里的卷积是什么,对于卷积神经网络一般使用离散数据,离散形式的函数 f , g f,g f,g卷积定义如下:
( f ∗ g ) [ n ] = ∑ m = − ∞ ∞ f [ m ] g [ n − m ] (f*g)[n] = \sum_{m=-\infty}^{\infty} f[m]g[n-m] (f∗g)[n]=m=−∞∑∞f[m]g[n−m]
而在卷积神经网络中使用的卷积则规定了卷积的范围不再是 [ − ∞ , ∞ ] [-\infty, \infty] [−∞,∞]而是由被卷积数据size决定,假设有如下原始数据和卷积函数:
原始数据:
卷积函数:
单点卷积结果(即对应位置相乘再求和):
卷积结果:
根据卷积过程我们可知,设原始数据为 ( m , n ) (m,n) (m,n),卷积函数为 ( f , f ) (f,f) (f,f),卷积步长为 s s s,那么得到的卷积结果为 ( f l o o r ( m − f s ) + 1 , f l o o r ( n − f s ) + 1 ) (floor(\frac{m-f}{s}) + 1, floor(\frac{n-f}{s}) + 1) (floor(sm−f)+1,floor(sn−f)+1)。(在深度学习中卷积矩阵基本为方阵)
Padding
可以看到卷积会所见数据尺寸,在卷积神经网络中我们有时需要数据尺寸不要减小太快,这时使用的手段就是“Padding”,通过在原始数据上增加padding数据来扩展数据然后再进行卷积计算。
进行“Padding”示意如下,使用元素“1”进行填充,填充尺寸 p = 1 p=1 p=1:
原本形状为 ( m , n ) (m, n) (m,n)的数据进行尺寸为 p p p的填充后形状为 ( m + 2 p , n + 2 p ) (m+2p, n+2p) (m+2p,n+2p)。
Valid&Same
有了“Padding”手段后我们可以先进行数据填充,然后在进行卷积运算,实际使用较多的为两种:
- Valid Convolution: 即不进行数据填充直接进行卷积运算
- Same Convolution: 首先以进行卷积后数据尺寸不变的目的进行填充,然后进行卷积运算
2D&3D
- 前面用来描述卷积概念的例子实际就是2D维度的卷积,一维卷积则更加简单,如最开始的数学描述,只是更改求和域。
- 3D维度的卷积则如下图所示,其中卷积函数与被卷积数据第三维度必须相同,卷积计算结果则需要进行3个维度的全部元素的求和。
后向过程
d A p r e v : dA_{prev}: dAprev:
这里的求解过程全部以前向过程引入了多少变化权重此处就需传播多少的角度来理解就直观很多,如下图计算卷积过程中每一个卷积窗与卷积核对应相乘后再相加得到一步卷积结果,那么卷积窗中元素变化能被传播到后层的大小即为卷积核对应位置的系数,所以在前向传播中我们只需要将 d Z dZ dZ的每个元素与卷积核相乘放入卷积窗的位置最后得到即为前一层输入的后向传播结果 d A p r e v dA_{prev} dAprev。
z = ∑ i = 1 3 ∑ j = 1 3 x i j w i j z = \sum_{i=1}^{3} \sum_{j=1}^{3} x_{ij}w_{ij} z=i=1∑3j=1∑3xijwij
d z d x = W \frac{dz}{dx} = W dxdz=W
以上为一步卷积的前向传播推导,整个卷积其实就是重复这个过程,知道将全部卷积窗计算完成。
d W : dW: dW:
根据前面的计算结果,可以得出
d z d W = x \frac{dz}{dW} = x dWdz=x
计算W的前向传播我们只需要将对应后一层误差的对应的卷积结果位置与卷积核的元素相乘放入对应位置即可。
d b : db: db:
d z d b = 1 \frac{dz}{db} = 1 dbdz=1
由于在相对与一组数据和卷积核的计算过程中只使用一个标量的偏置,也就是所谓的“权值共享”,即将偏置广播倒每一个卷积结果中,那么求解 d b db db时其实就是将与 b b b对应的卷积结果位置的误差求和。
2、Pooling
前向过程
单步"Pooling"操作如图所示是一个下采样过程,不同模式下以不同的规则对范围内特征进行采样,常用的有“Max”和“Mean”两种:
这里将原始数据的形状记为 ( n h , n w , n c ) (n_h, n_w, n_c) (nh,nw,nc),采样窗口的形状记为 ( n f h , n f w ) (n_{fh}, n_{fw}) (nfh,nfw), s s s为采样步长, n c n_c nc表示数据深度(例如图片即可为其不同颜色通道),不同深度的采样单独进行,采样结束后的结果形状为 ( n h − n f h s + 1 , n w − n f w s + 1 , n c ) (\frac{n_h - n_{fh}}{s} + 1, \frac{n_w - n_{fw}}{s} + 1, n_c) (snh−nfh+1,snw−nfw+1,nc)
后向过程
如前所述“Pooling”的前向过程为一个采样操作,那么后向过程我们来计算这个采样过程引入的误差:
-
Max
根据前向过程,我们只取了采样窗中的最大值作为采样结果,那么在后向传播误差的过程中也就只有采样位置的最大值起到了作用,所以其他部分填0,采样结果位置填最大值,即为传播因子。 -
Mean
根据前向过程,我们只取了采样窗中的全部样本均值作为采样结果,那么在后向传播误差的过程中每个位置起到的作用也就是采样结果对采样窗口的尺寸求平均,所以采样窗口位置填前向结果与采样窗口尺寸的比值。
3、FC
前向传播
“full-conection”的存在其实就是为了将多维数据转换为单维数据,然后进行如基本神经网络一样的非线性变化 ,
FC层前一般会存在一个Flatten层将多维数据转化为[bz, n]形式的数据,
"fully-connection"进行的主要是输出维度的变化,其中根据不同任务数据使用不同的激活函数, (后续理解了1x1卷积之后会发现在很多任务中使用1x1卷积会是更好的选择),
此处介绍的模型使用“softmax”函数,具体过程如下,对应到代码就是numpy中的flatten操作接使用“softmax”函数的FC层,下图仅为“flatten”操作示意:
后向传播
“flatten”操作只将数据进行了变形,所以求解这一步的反向过程只需将后一层的误差根据原始数据的形状进行排列即可。
FC层则根据使用的函数不同进行求导得出,后续给出了“softmax”函数的相关介绍。
4、softmax
这是直接给出softmax的表达式,至于为何使用softmax而不是直接对数据进行归一化的讨论话题很多不再赘述,一个比较明显的优势就在于指数形式更便于做计算优化。
y
=
s
o
f
t
m
a
x
(
x
)
y = softmax(x)
y=softmax(x)
y
i
=
e
x
i
∑
j
=
1
n
e
j
y_i = \frac{e^{x_i}}{\sum_{j=1}^{n} e^j}
yi=∑j=1nejexi
这里同时给出softmax函数的求导结果,
d y d x = [ d y 1 d x 1 ⋯ d y 1 d x n ⋮ ⋱ ⋮ d y n d x 1 ⋯ d y n d x n ] \frac{dy}{dx} = \begin{bmatrix} \frac{dy_1}{dx_1} & \cdots & \frac{dy_1}{dx_n} \\ \vdots & \ddots & \vdots \\ \frac{dy_n}{dx_1} & \cdots & \frac{dy_n}{dx_n} \end{bmatrix} dxdy=⎣⎢⎡dx1dy1⋮dx1dyn⋯⋱⋯dxndy1⋮dxndyn⎦⎥⎤
设 s = ∑ j = 1 n e x j s = \sum_{j=1}^{n} e^{x_j} s=∑j=1nexj,则 y i = e x i s y_i = \frac{e^{x_i}}{s} yi=sexi,
d
y
i
d
x
j
=
d
d
x
j
e
x
i
s
\frac{dy_i}{dx_j} = \frac{d}{dx_j} \frac{e^{x_i}}{s}
dxjdyi=dxjdsexi
=
d
d
x
j
e
x
i
s
= \frac{d}{dx_j} \frac{e^{x_i}}{s}
=dxjdsexi
=
(
e
x
i
)
′
s
−
e
x
i
s
′
s
2
= \frac{(e^{x_i})^{'}s - e^{x_i}s^{'}}{s^2}
=s2(exi)′s−exis′
当 i = j i = j i=j时:
=
(
e
x
i
)
s
−
e
x
i
e
x
i
s
2
= \frac{(e^{x_i})s - e^{x_i}e^{x_i}}{s^2}
=s2(exi)s−exiexi
=
e
x
i
s
(
1
−
e
x
i
s
)
= \frac{e^{x_i}}{s} (1 - \frac{e^{x_i}}{s})
=sexi(1−sexi)
当 i ≠ j i \ne j i̸=j时:
=
0
−
e
x
i
e
x
j
s
2
= \frac{0 - e^{x_i}e^{x_j}}{s^2}
=s20−exiexj
=
−
e
x
i
s
e
x
j
s
= -\frac{e^{x_i}}{s} \frac{e^{x_j}}{s}
=−sexisexj
d y d x = [ y 1 ( 1 − y 1 ) − y 1 y 2 ⋯ − y 1 y n − y 2 y 1 y 2 ( 1 − y 2 ) ⋯ − y 2 y n ⋮ ⋮ ⋱ ⋮ − y n y 1 − y n y 2 ⋯ y n ( 1 − y n ) ] \frac{dy}{dx} = \begin{bmatrix} y_1(1-y_1) & -y_1y_2 & \cdots & -y_1y_n \\ -y_2y_1 & y_2(1-y_2) & \cdots & -y_2y_n \\ \vdots & \vdots &\ddots & \vdots \\ -y_ny_1 & -y_ny_2 & \cdots & y_n(1-y_n) \end{bmatrix} dxdy=⎣⎢⎢⎢⎡y1(1−y1)−y2y1⋮−yny1−y1y2y2(1−y2)⋮−yny2⋯⋯⋱⋯−y1yn−y2yn⋮yn(1−yn)⎦⎥⎥⎥⎤
1、以上为卷积神经网络的基本概念,更具体描述待补充
2、具体实现见:https://github.com/Alnlll/ML/tree/master/CNN(反向传播待实现但全部基本功能函数已完成并测试)