Notes on NNDL(Neural Networks and Deep Learning)

  1. 关于代价函数的假设:
    (1) 代价函数可以被写成一个 在每个训练样本 x 上的代价函数Cx的均值 C=1nxCx . 反向传播实际上是对一个独立的训练样本计算了 Cxω Cxb . 然后通过在所有训练样本上进行平均化得到 Cω Cb . 实际上,有了这个假设,我们会认为训练样本 x 已经被固定住了,丢掉其下标,将代价函数Cx看作 C .
    (2) 代价可以写成神经网络输出的函数costC=C(aL)

  2. 反向传播的四个基本方程

    反向传播其实是对权重和偏差变化影响代价函数过程的理解,最终的目的就是计算偏导数 Cωljk Cblj . 引入一个中间量, δlj ,定义它为 lth 层第 jth 个神经元上的误差.

    假设,我们对 lth 层的第 jth 个神经元的操作进行一些变化,比如,在神经元的带权输入上增加很小的变化 Δzlj ,使得神经元输出由 δ(zlj) 变为 δ(zlj+Δzlj) . 这个变化将会向后面的层进行传播,最终导致整个代价函数产生 CzljΔzlj 的变化(可以从微分的数学定义进行验证). 此时,如果 Czlj 有一个很大的值(或正或负),则可以通过选择与 Czlj 符号相反的 Δzlj 来降低代价。相反的,如果 Czlj 接近 0 ,那么无法通过更改Δzlj来降低代价,此时可以认为神经元已经很接近最优了(这两种假设只能在 Δzlj 很小的时候才能够满足)。因此,可以有一种启发式的认识: Czlj 是神经元误差的度量。根据以上这些描述,定义 l 层的第jth个神经元上的误差 δlj 为:

    δljCzlj

    这样,我们就可以使用 δl 表示关联于 l 层的误差向量。反向传播算法会告诉我们如何计算每层的δl,然后将这些误差和最终我们需要的量 Cωljk Cblj 联系起来.

    • 输出层误差的方程

      δLj=CaLjσ(zLj)

      这是一个很自然的表达式。右边第一项 CaLj 表示代价随着 jth 输出激活值的变化而变化的速度。如果 C 不太依赖一个特定的输出神经元j,那么 δLj 就会很小。第二项 σ(zLj) 刻画了在 zLj 处激活函数 σ 变化的速度.

      证明:

      δLj=CzLj=kCaLkaLkzLj
      ,这里的求和是对输出层中的所有神经元 k 进行的. 当然,第k个神经元的输出激活 aLk 只依赖于第 j 个神经元的加权输入(当k==j), 因此,当 kj 时, zLkzLj 消失。从而有:
      δLj=CzLj=kCaLkaLkzLj=CaLjaLjzLj
      .
      同时,我们有 aLj=σ(zLj) , 则 aLjzLj=σ(zLj) . 最终我们有:
      δLj=CaLjσ(zLj)
      证毕.

    • 使用下一层的误差 δl+1 来表示当前层的误差 δl

      δL=((ωL+1)TδL+1)σ(zL)

      其中 (ωL+1)T (L+1)th 层的权重矩阵 ωL+1 的转置. 有了这个方程与第一个方程,我们就可以计算任何层的误差了:首先使用第一个方程计计算 δL ,然后使用第二个方程来计算 δL1 ,然后不断使用第二个方程,就可以一步一步地反向传播完整个网络.
      证明:因为 δLj=CzLj ,则有 δL+1k=CzL+1k
      δLj=CzLj=kCzL+1kzL+1kzlj=kzL+1kzLjδL+1k

      根据定义,我们有
      zL+1kjωL+1kj+bL+1k=jωL+1kjσ(zLJ)+bL+1k
      则可以得到
      zL+1kzLj=ωL+1kjσ(zLj)

      因此,
      δLj=kωL+1kjδL+1kσ(zLj)

      证毕.

    • 代价函数关于网络中任意偏差的改变率

      CbLj=δLj

    • 代价函数关于任何一个权重的改变率

      CωLjk=aL1kδLj

  3. 反向传播算法
    反向传播方程给出了一种计算代价函数梯度的方法,其显示描述如下:
    (1) 输入 x :为输入层设置对应的激活值aL
    (2) 前向传播:对每个 l=2,3,...,L , 计算相应的 Zl=ωlal1+bl al=σ(zl)
    (3) 输出层误差 δL : 计算向量 δL=aCσ(zL)
    (4) 反向误差传播:对每个 l=L1,L2,...,2 , 计算 δl=((ωl+1)Tδl+1)σ(zl)
    (5) 输出: 代价函数的梯度由 Cωljk=al1kδlj Cblj=δlj .

  4. 反向传播代码注释

    def backprop(self, 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
        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 # weighted input
            zs.append(z)
            activation = sigmoid(z) $ activations
            activations.append(activation)
# 反向传播
        delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1]) # cost_derivative是代价函数对激活值的导数. 此处的delta是第L层的输出误差.
        nabla_b[-1] = delta # 第L层的代价相对于偏置的导数
        nabla_w[-1] = np.dot(delta, activations[-2].transpose()) # 第L层的代价相对于权重的导数

        #进行反向传播,计算L-1,L-2,...,2的导数
        for l in xrange(2, self.num_layers):
            z = zs[-l] # 加权输入
            sp = sigmoid_prime(z) # 加权输入的导数
            delta = np.dot(self.weights[-l+1].transpose(), delta) * sp # 当前层的delta(输出误差)
            nabla_b[-l] = delta #当前层的导数(相对于偏置)
            nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())#当前层的导数(相对于权重)
        return (nabla_b, nabla_w)
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值