第14章 搭建深度神经网络框架⚓︎
14.0 深度神经网络框架设计⚓︎
14.0.1 功能/模式分析⚓︎
比较第12章中的三层神经网络的代码,我们可以看到大量的重复之处,比如前向计算中:
def forward3(X, dict_Param):
...
# layer 1
Z1 = np.dot(W1,X) + B1
A1 = Sigmoid(Z1)
# layer 2
Z2 = np.dot(W2,A1) + B2
A2 = Tanh(Z2)
# layer 3
Z3 = np.dot(W3,A2) + B3
A3 = Softmax(Z3)
...
1,2,3三层的模式完全一样:矩阵运算+激活/分类函数。
再看看反向传播:
def backward3(dict_Param,cache,X,Y):
...
# layer 3
dZ3= A3 - Y
dW3 = np.dot(dZ3, A2.T)
dB3 = np.sum(dZ3, axis=1, keepdims=True)
# layer 2
dZ2 = np.dot(W3.T, dZ3) * (1-A2*A2) # tanh
dW2 = np.dot(dZ2, A1.T)
dB2 = np.sum(dZ2, axis=1, keepdims=True)
# layer 1
dZ1 = np.dot(W2.T, dZ2) * A1 * (1-A1) #sigmoid
dW1 = np.dot(dZ1, X.T)
dB1 = np.sum(dZ1, axis=1, keepdims=True)
...
dZ
,再根据dZ
计算dW
和dB
。
因为三层网络比两层网络多了一层,所以会在初始化、前向、反向、更新参数等四个环节有所不同,但却是有规律的。再加上前面章节中,为了实现一些辅助功能,我们已经写了很多类。所以,现在可以动手搭建一个深度学习的迷你框架了。
14.0.2 抽象与设计⚓︎
图14-1是迷你框架的模块化设计,下面对各个模块做功能点上的解释。
图14-1 迷你框架设计
NeuralNet⚓︎
首先需要一个NeuralNet
类,来包装基本的神经网络结构和功能:
Layers
- 神经网络各层的容器,按添加顺序维护一个列表Parameters
- 基本参数,包括普通参数和超参Loss Function
- 提供计算损失函数值,存储历史记录并最后绘图的功能LayerManagement()
- 添加神经网络层ForwardCalculation()
- 调用各层的前向计算方法BackPropagation()
- 调用各层的反向传播方法PreUpdateWeights()
- 预更新各层的权重参数UpdateWeights()
- 更新各层的权重参数Train()
- 训练SaveWeights()
- 保存各层的权重参数LoadWeights()
- 加载各层的权重参数
Layer⚓︎
是一个抽象类,以及更加需要增加的实际类,包括:
- Fully Connected Layer
- Classification Layer
- Activator Layer
- Dropout Layer
- Batch Norm Layer
将来还会包括:
- Convolution Layer
- Max Pool Layer
每个Layer都包括以下基本方法:
- ForwardCalculation()
- 调用本层的前向计算方法
- BackPropagation()
- 调用本层的反向传播方法
- PreUpdateWeights()
- 预更新本层的权重参数
- UpdateWeights()
- 更新本层的权重参数
- SaveWeights()
- 保存本层的权重参数
- LoadWeights()
- 加载本层的权重参数
Activator Layer⚓︎
激活函数和分类函数:
Identity
- 直传函数,即没有激活处理Sigmoid
Tanh
Relu
Classification Layer⚓︎
分类函数,包括:
Sigmoid
二分类Softmax
多分类
#### Parameters
基本神经网络运行参数:
- 学习率
- 最大
epoch
batch size
- 损失函数定义
- 初始化方法
- 优化器类型
- 停止条件
- 正则类型和条件
LossFunction⚓︎
损失函数及帮助方法:
- 均方差函数
- 交叉熵函数二分类
- 交叉熵函数多分类
- 记录损失函数
- 显示损失函数历史记录
- 获得最小函数值时的权重参数
Optimizer⚓︎
优化器:
SGD
Momentum
Nag
AdaGrad
AdaDelta
RMSProp
Adam
WeightsBias⚓︎
权重矩阵,仅供全连接层使用:
- 初始化
Zero
,Normal
,MSRA
(HE
),Xavier
- 保存初始化值
- 加载初始化值
Pre_Update
- 预更新Update
- 更新Save
- 保存训练结果值Load
- 加载训练结果值
DataReader⚓︎
样本数据读取器:
ReadData
- 从文件中读取数据NormalizeX
- 归一化样本值NormalizeY
- 归一化标签值GetBatchSamples
- 获得批数据ToOneHot
- 标签值变成OneHot编码用于多分类ToZeroOne
- 标签值变成0/1编码用于二分类Shuffle
- 打乱样本顺序
从中派生出两个数据读取器:
MnistImageDataReader
- 读取MNIST数据CifarImageReader
- 读取Cifar10数据