第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- 直传函数,即没有激活处理SigmoidTanhRelu
Classification Layer⚓︎
分类函数,包括:
Sigmoid二分类Softmax多分类
#### Parameters
基本神经网络运行参数:
- 学习率
- 最大
epoch batch size- 损失函数定义
- 初始化方法
- 优化器类型
- 停止条件
- 正则类型和条件
LossFunction⚓︎
损失函数及帮助方法:
- 均方差函数
- 交叉熵函数二分类
- 交叉熵函数多分类
- 记录损失函数
- 显示损失函数历史记录
- 获得最小函数值时的权重参数
Optimizer⚓︎
优化器:
SGDMomentumNagAdaGradAdaDeltaRMSPropAdam
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数据