本系列教程分为两部分
- 1 设计一个神经网络库的基本架构设计
- 2 每个组建的具体实现细节
1 神经网络库的基本架构设计
为了项目代码的可扩展性,我们选取面向对象的编码方式。我们设计的基本架构主要包括几个主要模块
- 1.神经网络基本组件(NeuralNetworkNeuralNetwork):主要用于支持神经网络运行的完整流程,其中包括添加网络层,训练网络模型,预测等主要方法。
- 2 .层组件(LayersLayers):主要实现神经网络不同组件层:比如说全连接层(DenseDense),卷积网络层(RNNRNN),卷积层(Conv2DConv2D),批正则化层(BNBN),池化层(PoolingLayerPoolingLayer),DropoutDropout层,激活函数层(ActivationActivation)。层组件主要由层的前向传播,反向传播两个过程组成。
- 3.激活函数组件。主要实现神经网络中不同激活函数:比如说SigmoidSigmoid,ReluRelu。激活函数组件主要有函数的定义以及函数一阶导的定义组成。
- 4 损失函数组件。主要实现神经网络中的不同的损失函数:比如说对于回归问题的平方损失函数,对于分类问题的交叉熵损失函数。损失函数组件主要由函数定义以及函数一阶导定义组成
- 5 优化器组件。主要实现神经网络中不同的优化方法:比如说随机梯度下降法,动量梯度下降法,以及AdamAdam等等。优化器组件主要有更新参数方法组成。
图形化的解释
2 每个组建的具体实现细节
1.神经网络基本组件
主要用于支持神经网络运行的完整流程,其中包括添加网络层,训练网络模型,预测等主要方法。
2.层组件
(1)DenseDense
前向传播:WX+bWX+b
反向传播:
- 首先接收损失函数对于该层输出的导数δδ(可以作为参数传进来),
- 然后通过链式求导法则,▽W=δ∂Z∂W▽W=δ∂Z∂W ▽X=δ∂Z∂X▽X=δ∂Z∂X
- 更新参数权重,并且回传▽X▽X
(2)RNNRNN
前向传播:
for t from 1 to Tfor t from 1 to T:
- stin=XtUT+st−1WTsint=XtUT+st−1WT
- st=Activation(stin)st=Activation(sint)
- ot=stVTot=stVT
反向传播:
- 首先接收损失函数对于该层输出的导数δδ(可以作为参数传进来),形状是(batch_size,timesteps,input_dim)
- 对于每个步长t从1到T,首先计算垂直方向的梯度 ▽V=▽V+δTt∂ot∂V▽V=▽V+δtT∂ot∂V, ▽stin=δTt∂ot∂st∂st∂stin▽sint=δtT∂ot∂st∂st∂sint ▽Xt=▽stin∂stin∂Xt▽Xt=▽sint∂sint∂Xt。然后再计算时间维度的梯度:从t到0,计算▽U=▽U+δTt∂stin∂U▽U=▽U+δtT∂sint∂U ▽W=▽W+δTt∂stin∂W▽W=▽W+δtT∂sint∂W
- 更新参数U,W,VU,W,V,并且回传梯度▽X▽X
(3)Conv2DConv2D
前向传播:
- 将原始的图片矩阵XX(batch_size,channels,image_width,image_height)整理为(batch_size * out_height * out_width,filter_height*filter_width*channels)。将卷积核矩阵(n_filters,channels,filter_height,filter_width)
整理为(n_filters,filter_height*filter_width*channels)。这一步可以理解为卷积操作的准备工作。 - 进行卷积操作,即WXTWXT,然后整理一下形状接着往下传
反向传播:
- 首先接收损失函数对于该层输出的导数δδ(可以作为参数传进来),形状是(batch_size,n_filters,out_height,out_width)
- ▽W=δ∂zt∂W▽W=δ∂zt∂W ▽X=δ∂zt∂X▽X=δ∂zt∂X
- 更新参数W,并且回传▽X▽X(需要整理形状为(batch_size,channels,image_width,image_height))
(3)PoolingLayerPoolingLayer
前向传播:
- 将原始的图片矩阵XX(batch_size,channels,image_width,image_height)整理为(batch_size*channels * out_height * out_width,pool_shape[0]*pool_shape[1])。
- 然后计算池化区域的统计量,比如。然后传入下一层。
反向传播:
- 首先接收损失函数对于该层输出的导数δδ(可以作为参数传进来),形状是(batch_size,n_filters,out_height,out_width)
- 把δδ的所有子矩阵矩阵大小还原成池化之前的大小,然后如果是MAX,则把δδ的所有子矩阵的各个池化局域的值放在之前做前向传播算法得到最大值的位置。如果是Average,则把δδ的所有子矩阵的各个池化局域的值取平均后放在还原后的子矩阵位置。这个过程一般叫做upsampleupsample。
(4)DropoutDropout
前向传播
- 随机以概率p选取部分神经单元置0,并且记录索引。往下传播
反向传播
- 首先接收损失函数对于该层输出的导数δδ(可以作为参数传进来)
- 然后乘以索引。往前传播
(5)ActivationActivation
前向传播:
- 将输入传入激活函数,把输出往传输
后向传播:
- 首先接收损失函数对于该层输出的导数δδ(可以作为参数传进来)
- δ∗σ′(.)δ∗σ′(.),然后接着往下传输。
3 激活函数组件
激活函数的实现以及一阶导的实现
4 损失函数组件
损失函数的实现以及一阶导的实现
5 优化器组件
优化器更新梯度函数的实现