前言
本文是手写BP神经网络的第三篇文章,也是接续上一篇文章,细致地介绍如何完成BP神经网络这一程序。在上一篇文章之中,作者搭好了一个深度学习框架:如果读者朋友们将那几个具体的计算的函数当做一个实现功能的黑盒,那么在上一篇文章中已经清楚网络是怎么训练,推理,优化的。具体的链接见下:
手写感知器的反向传播算法 Part2:基于理论推导的代码实践:如何实现自己的第一个神经网络完成手写体识别?(上)-优快云博客
那么在这一文章之中,作者将把上一篇文章中的黑盒子打开,具体介绍运算部分的代码是什么样的。而这个部分主要就是“BP_foward_for_classification”类。
Part0:准备阶段
1.copy函数:
这个部分作者写了一个用来复制矩阵的函数。其目的是为了将一个矩阵或者一个列向量保持形状地复制到另一个矩阵之中。代码如下:
def copy(tuple1, tuple2):
if tuple2.ndim != 1:
x = np.size(tuple2, 0)
y = np.size(tuple2, 1)
if tuple1.ndim!=1:
for i in range(x):
for j in range(y):
tuple1[i][j] = tuple2[i][j]
else:
if np.size(tuple2,1) == 1:
for i in range(x):
tuple1[i] = tuple2[i][0]
else:
raise RuntimeError("problem arouse")
# for i in range(x):
# tuple1[i] = tuple2[i][0]
# 这里只能是列向量
elif tuple2.ndim == 1 and tuple1.ndim == 1:
x = np.size(tuple2, 0)
for i in range(x):
tuple1[i] = tuple2[i]
else:
x = np.size(tuple2, 0)
for i in range(x):
tuple1[i][0] = tuple2[i]
保存原有形状地copy和保存是在整个程序中相当重要的一个特性。
2.ReLU函数
def relu(x):
t = np.size(x, 0)
for i in range(t):
x[i] = 0 if x[i]<=0 else x[i]
return x
Part1:“BP_foward_for_classification”类
1.构造函数
先给出代码:
def __init__(self, layer_num, neuron_sit, learning_rate, last_weight = None, last_bias = None):
self.layer_num = layer_num
self.neuron_sit = neuron_sit
self.weight_para = np.zeros((np.max(neuron_sit), np.max(neuron_sit), layer_num + 1), dtype=float)
# 首先,按照输入的最大的神经元个数构建存放权重的矩阵。其中前两维为存放矩阵系数,第三维是存放不同的层数的结果
self.bias_para = np.zeros((np.max(neuron_sit), layer_num + 1), dtype=float)
# 其次,对于偏置矩阵来说只要构建二维矩阵即可。
self.loss_matrix = np.zeros((np.max(neuron_sit), layer_num + 1), dtype=float)
self.weight_grad = np.zeros((np.max(neuron_sit), np.max(neuron_sit), layer_num + 1), dtype=float)
self