反向传播 - 神经网络的核心

反向传播的目标是优化权重,以便神经网络可以学习如何正确地将任意输入映射到输出。

每一层都有自己的一组权重,必须调整这些权重,以便能够准确预测给定输入的正确输出。

反向传播的高级概述如下:

  1. 正向传递 - 输入转换为某些输出。在每一层,使用输入和权重之间的点积计算激活,然后将结果与偏差相加。最后,该值通过激活函数传递,以激活该层,该层将成为下一层的输入。
  2. 在最后一层中,将输出与对应于该输入的实际标签进行比较,并计算错误。通常,它是均方误差。
  3. 向后传递 - 将步骤 2 中计算的误差传播回内层,并调整所有层的权重以解决此错误。

1.权重初始化

权重初始化的简化示例如下所示:

layers = [784, 64, 10] 
weights = np.array([(np.random.randn(y, x) * np.sqrt(2.0 / (x + y))) for x, y in zip(layers[:-1], layers[1:])])
biases = np.array([np.zeros((y, 1)) for y in layers[1:]])
  • 隐藏层 1 具有尺寸[64,784]的重量和尺寸 64 的偏差。

  • 输出层具有维度[10,64]的权重和维度的偏差

你可能想知道在上面的代码中初始化权重时发生了什么。这称为 Xavier 初始化,它比随机初始化权重矩阵更好一步。是的,初始化确实很重要。根据你的初始化,你可能能够在梯度下降期间找到更好的局部最小值(反向传播是梯度下降的美化版本)。

2.前往通行证

activation = x
hidden_activations = [np.reshape(x, (len(x), 1))]
z_list = []

for w, b in zip(self.weights, self.biases):    
    z = np.dot(w, np.reshape(activation, (len(activation), 1))) + b
    z_list.append(z)
    activation = relu(z)
    hidden_activations.append(activation)

t = hidden_activations[-1] 
hidden_activations[-1] = np.exp(t) / np.sum(np.exp(t))

该代码执行上述转换。hidden_activations[-1] 包含 softmax 概率 - 所有类的预测,其总和为 1.如果我们预测数字,则输出将是维度 10 的概率向量,其总和为 1。

3.后退通行证

weight_gradients = [np.zeros(w.shape) for w in self.weights]
bias_gradients = [np.zeros(b.shape) for b in self.biases]

delta = (hidden_activations[-1] - y) * (z_list[-1] > 0) # relu derivative
weight_gradients[-1] = np.dot(delta, hidden_activations[-2].T)
bias_gradients[-1] = delta

for l in range(2, self.num_layers):
    z = z_list[-l]
    delta = np.dot(self.weights[-l + 1].T, delta) * (z > 0) # relu derivative
    weight_gradients[-l] = np.dot(delta, hidden_activations[-l - 1].T)
    bias_gradients[-l] = delta

前两行初始化渐变。计算这些梯度,并将用于稍后更新权重和偏差。

接下来的 3 行通过从目标中减去预测来计算误差。然后将错误反馈传播到内层。

现在,仔细跟踪循环的工作。第 2 行和第 3 行将错误从 layer[i] 转换为 layer[i - 1]。跟踪乘以矩阵的形状以理解。

4.重量/参数更新

for i in xrange(len(self.weights)):
    self.weights[i] += -self.learning_rate * weight_gradients[i]
    self.biases[i] += -self.learning_rate * bias_gradients[i] 

self.learning_rate 指定网络学习的速率。你不希望它学得太快,因为它可能不会收敛。平稳下降有利于找到一个好的最小值。通常,0.010.1 之间的比率被认为是好的。