[神经网络这次真的搞懂了!] (8) 使用神经网络识别手写数字 - 反向传播(3)

英文原文:http://neuralnetworksanddeeplearning.com/
对原文的表达有部分改动

反向传播方程为我们提供了一种计算代价函数梯度的方法。让我们以算法的形式总结一下:

  1. 输入 x:设置输入层 a^1
  2. 前馈:对于每个 l=2,3,…,L 计算 z^l=w^la^{l−1}+b^la^l=σ(z^l)
  3. 输出误差 δ^L:计算向量 δ^L=∇_aC⊙σ^′(z^L)
  4. 反向传播误差:对于每个 l=L−1,L−2,…,2 计算 δ^l=((w^{l+1})^Tδ^{l+1})⊙σ^′(z^l)
  5. 输出:代价函数的梯度由 \frac {∂C}{∂w^l_{jk}}=a^{l−1}_kδ^l_j\frac {∂C}{∂b^l_j} = δ^l_j 给出。

了解上述的算法,您会明白为什么它被称为反向传播。我们从最后一层开始往回计算误差向量 δ^l。逐步了解了代价如何随早期权重和偏差而变化,通过往前追溯以获得可用的表达式。

正如我上面所描述的,反向传播算法计算单个训练示例的代价函数的梯度,C=C_x。在实践中,通常将反向传播与随机梯度下降等学习算法相结合,在这种算法中,我们为许多训练示例计算梯度。特别是,给定 mini-batch m 训练示例,以下算法应用基于该 mini-batch 的梯度下降学习步骤:

  1. 输入训练样本中的一组
  2. 对于每个训练样例 x:设置对应的输入激活 a^{x,1},执行以下步骤:
  • 前馈:对于每个 l=2,3,…,L 计算 z^{x,l}=w^la^{x,l−1}+b^la^{x,l}=σ(z^{x,l})
  • 输出误差δ^{x,L}:计算向量δ^{x,L}=∇_aC_x⊙σ^′(z^{x,L})
  • 反向传播误差:对于每个 l=L−1,L−2,…,2 计算 δ^{x,l}=((w^{l+1})^Tδ^{x,l+1})⊙σ^′(z^{x,l})
  1. 梯度下降:对于每个 l=L,L−1,…,2 根据规则更新权重 w^l→w^l−\frac {η} {m}\sum_xδ^{x,l}(a^{x,l−1})^T ,以及根据规则 更新偏差b^l→b^l−\frac {η} {m}\sum_xδ^{x,l} 的。

反向传播的代码

在抽象地理解了反向传播之后,我们现在可以理解上一章中用于实现反向传播的代码。回忆那一章,代码包含在 Network 类的 update_mini_batch 和 backprop 方法中。这些方法的代码是上述算法的直接翻译。特别是,update_mini_batch 方法通过计算当前 mini_batch 训练示例的梯度来更新网络的权重和偏差:

class Network(object):
    def update_mini_batch(self, mini_batch, eta):
        """Update the network's weights and biases by applying
        gradient descent using backpropagation to a single mini batch.
        The ``mini_batch`` is a list of tuples ``(x, y)``, and ``eta``
        is the learning rate."""
        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:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y)
            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)]

反向传播的大部分工作由 delta_nabla_b, delta_nabla_w = self.backprop(x, y) 完成,它使用反向传播方法计算偏导数\frac {∂C_x}{∂b^l_j}\frac {∂C_x}{∂w^l_{jk}}。反向传播方法紧密遵循上一节中的算法。有一个小的变化 - 我们使用稍微不同的方法来索引层。进行此更改是为了利用 Python 的一个特性,即使用列表负数索引从列表的末尾往前计数,例如,l[-3] 是列表 l 中的倒数第三个条目。反向传播的代码如下,以及一些辅助函数,用于计算 σ 函数、导数 σ^′ 和代价函数的导数。有了这些内容,您应该能够以一种自包含的方式理解代码。

class Network(object):
    def backprop(self, x, y):
        """Return a tuple ``(nabla_b, nabla_w)`` representing the
        gradient for the cost function C_x.  ``nabla_b`` and
        ``nabla_w`` are layer-by-layer lists of numpy arrays, similar
        to ``self.biases`` and ``self.weights``."""
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # feedforward
        activation = x
        activations = [x] # list to store all the activations, layer by layer
        zs = [] # list to store all the z vectors, layer by layer
        for b, w in zip(self.biases, self.weights):
            z = np.dot(w, activation)+b
            zs.append(z)
            activation = sigmoid(z)
            activations.append(activation)
        # backward pass
        # BP1
        delta = self.cost_derivative(activations[-1], y) * \
            sigmoid_prime(zs[-1])
        # BP3
        nabla_b[-1] = delta
        # BP4
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        # Note that the variable l in the loop below is used a little
        # differently to the notation in Chapter 2 of the book.  Here,
        # l = 1 means the last layer of neurons, l = 2 is the
        # second-last layer, and so on.  It's a renumbering of the
        # scheme in the book, used here to take advantage of the fact
        # that Python can use negative indices in lists.
        for l in range(2, self.num_layers):
            z = zs[-l]
            sp = sigmoid_prime(z)
            # BP2
            delta = np.dot(self.weights[-l+1].transpose(), delta) * sp
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())
        return (nabla_b, nabla_w)

    def cost_derivative(self, output_activations, y):
        """Return the vector of partial derivatives \partial C_x /
        \partial a for the output activations."""
        return (output_activations-y)

#### Miscellaneous functions
def sigmoid(z):
    """The sigmoid function."""
    return 1.0/(1.0+np.exp(-z))

def sigmoid_prime(z):
    """Derivative of the sigmoid function."""
    return sigmoid(z)*(1-sigmoid(z))
  1. Network.cost_derivative 是代价函数的代数形式,因为代价函数为 C = \frac {1}{2} (y - a^L)^2,其导数形式为 \frac {∂C}{∂a^L} = a^L - y
  2. sigmoid 是激活函数的代码实现,可以支持向量参数
  3. sigmoid_prime 是 sigmoid 函数的导数,\frac {∂σ}{∂z} = σ(z)(1-σ(z))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容