Python神经网络代码实现流程(三):反向传播与梯度下降
2017-11-06 12:36
826 查看
前向传播为输入的矩阵经过计算到输出层,而反向传播与梯度下降则是训练神经网络的核心步骤.
梯度下降算法的代码如下:
以下是每次更新所有参数的代码:
反向传播代码如下:
梯度下降算法的代码如下:
def SGD(self, training_data, epochs, mini_batch_size, eta, test_data = None): if test_data: n_test = len(test_data) n = len(training_data) for j in range(epochs): #自动定义的循环次数,也就是训练神经网络的循环次数 random.shuffle(training_data) #shuffle为将训练接随机打乱重排,保证训练的数据的随机性 mini_batches = [training_data[k:k+mini_batch_size] for k in range(0, n, mini_batch_size)] #这里形成了一个列表,列表的每一个元素为一个矩阵,一个矩阵就是一次循环的小型数据集.更新神经网络的时候,利用的并不是一个数据(一张图片),而是利用的一个小型矩阵.这样的向量化处理大大提高了代码的执行效率. for mini_batch in mini_batches: self.update_mini_batch(mini_batch, eta) #这里就是利用小型的矩阵对神经网络的所有参数进行一次全面的更新(下面的代码会详细讲解) if test_data: print ("Epoch {0}: {1} / {2}". format(j, self.evaluate(test_data), n_test)) #使用了测试集的数据,进行打印显示(evaluate函数后面详述) else: print ("Epoch {0} complete".format(j))
以下是每次更新所有参数的代码:
def update_mini_batch(self, mini_batch, eta): nabla_b = [np.zeros(b.shape) for b in self.biases] #在更新所有的权重和偏置之前,需要先生成与原先权重和偏置相同维数的空矩阵用来保存更新后的参数 nabla_w = [np.zeros(w.shape) for w in self.weights] for x, y in mini_batch: #mini_batch为784行,mini_batch_size列的矩阵 delta_nabla_b, delta_nabla_w = self.backprop(x, y) #这里是反向传播的函数,是神经网络的核心.以下的代码就是对权重和偏置的更新 #由下面的bp代码可以得到神经网络的所有参数的偏导数矩阵 nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)] nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)] self.weights = [w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)] self.biases = [b-(eta/len(mini_batch))*nb for b, nb in zip(self.biases, nabla_b)] #以上的代码是将没每个小型训练集的矩阵的道得到的权重和偏置都平均,然后再更新权重和偏置.这样可以避免权重和偏置因为某一个训练集数据的错误而过度的更新.
反向传播代码如下:
def backprop(self, x, y): #这里的(x,y)为传入的一个输入和测试集中的一个输出 nabla_b = [np.zeros(b.shape) for b in self.biases] nabla_w = [np.zeros(w.shape) for w in self.weights] activation = x #activation为输入层的数据 activations = [x] #actications为经过激活函数处理后的输出矩阵 zs = [] #zs为每个层未经过激活函数处理的矩阵 for b, w in zip(self.biases, self.weights): #for循环后,得到了两个矩阵,其中zs矩阵是未经过激活的矩阵,列数和神经网络的层数相同(不包括输入层),activations为经过激活后的矩阵,也就是每层的神经网络的输出(包括输入层),其中第一列为输入层,最后一列为神经网络的输出. z = np.dot(w, activation)+b zs.append(z) activation = sigmoid(z) activations.append(activation) delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1]) #由于求导的公式推出的偏导数公式,每一层偏置的偏导数等于(a L − y) ⊙ σ ′ (z L ),因此得到的delta就是输出层偏置的偏导数 nabla_b[-1] = delta #这是偏置偏导数矩阵的赋值,在上面已经进行了矩阵的初始化 nabla_w[-1] = np.dot(delta, activations[-2].transpose()) for l in range(2, self.num_layers): #以上是最后一层权重和偏置的偏导数赋值,下面的for循环会依次将每一层的权重和偏置的偏导数进行计算得到. z = zs[-l] sp = sigmoid_prime(z) delta = np.dot(self.weights[-l+1].transpose(), delta) * sp #因为只有最后一层有输出y,所以前面的层数不能够再利用输出求偏导数,利用下一层的偏导数求上一层的偏导数: δ l = ((w l+1 ) T δ l+1 ) ⊙ σ ′ (z l ),这里,用到了下一层权重,和下一层已经求出来的偏导数. nabla_b[-l] = delta nabla_w[-l] = np.dot(delta, activations[-l-1].transpose()) return (nabla_b, nabla_w) #当循环结束,每一次的权重和偏置的偏导数矩阵都已经得到.
相关文章推荐
- 神经网络之梯度下降与反向传播(下)
- 十一行Python代码实现一个误差逆传播(BP)神经网络
- Python神经网络代码识别手写字的实现流程(一):加载mnist数据
- Python神经网络代码识别手写字具体流程(二):矩阵的前向传播
- 神经网络之梯度下降法和反向传播BP
- 神经网络中的反向传播法算法推导及matlab代码实现
- 神经网络中的反向传播的推导和python实现
- 神经网络之梯度下降与反向传播(上)
- [置顶] 基于梯度下降法的三层神经网络的C++实现(支持保存和读取)
- 13行Python代码实现一个神经网络(Part 2 - 梯度下降法)
- 一个 11 行 Python 代码实现的神经网络
- 一个 11 行 Python 代码实现的神经网络
- 机器学习与神经网络(四):BP神经网络的介绍和Python代码实现
- 机器学习与神经网络(二):感知器的介绍和Python代码实现
- 梯度下降原理及线性回归代码实现(python/java/c++)
- 十一行Python代码实现一个神经网络(第一部分)
- 十一行Python代码实现一个神经网络(第一部分)
- 【神经网络】11行Python代码实现的神经网络
- 梯度下降实现案例(含python代码)
- 一个 11 行 Python 代码实现的神经网络