算法代码

反向传播算法代码

给定一个大小为mm的小批量数据,在小批量数据的基础上应用梯度下降学习算法:

  1. 输入训练样本的集合

  2. 对于每个训练样本xx:设置对应的输入激活ax,1a^{x,1},并执行下面的步骤 1. 前向传播:对于每一个l=2,3,...,Ll=2,3,...,L,计算zx,l=wlax,l1+blz^{x,l}=w^l a^{x,l-1} + b^lax,l=σ(zx,l)a^{x,l}=\sigma(z^{x,l})

    1. 输出误差δx,L\delta^{x,L}:计算向量δx,L=aCxσ(zx,L)\delta^{x,L}=\nabla_a C_x \odot \sigma'(z^{x,L})

    2. 反向传播误差:对于每一个l=L1,L2,...,2l=L-1,L-2,...,2计算δx,l=((wl+1)Tδx,l+1)σ(zx,l)\delta^{x,l}=((w^{l+1})^T \delta^{x, l+1}) \odot \sigma'(z^{x,l})

  3. 梯度下降:对于每一个l=L1,L2,...,2l=L-1, L-2, ..., 2根据wlwlηmxδx,l(ax,l1)Tw^l\to w^l - \frac{\eta}{m}\displaystyle\sum_{x}\delta^{x,l} (a^{x,l-1})^Tblblηmxδx,lb^l\to b^l - \frac{\eta}{m}\displaystyle\sum_{x}\delta^{x,l}更新权重和偏置。

二次代价函数及sigmoid函数

如果使用二次代价函数,则每个训练样本的成本函数是Cx=12y(x)aL(x)2C_x=\frac{1}{2}||y(x)-a^L(x)||^2,则aCx=y(x)a(x)\nabla_a C_x = y(x)-a(x)

sigmoid 激活函数σ(z)=11+ez\sigma(z) = \frac{1}{1+e^{-z}}的导数σ(z)=11+ez(111+ez)=σ(z)(1σ(z))\sigma'(z) = \frac{1}{1+e^{-z}}(1-\frac{1}{1+e^{-z}})=\sigma(z) (1-\sigma(z))

Python 代码

这里的代码来自 https://github.com/mnielsen/neural-networks-and-deep-learning

"""
mnist_loader
~~~~~~~~~~~~

A library to load the MNIST image data.  For details of the data
structures that are returned, see the doc strings for ``load_data``
and ``load_data_wrapper``.  In practice, ``load_data_wrapper`` is the
function usually called by our neural network code.
"""

#### Libraries
# Standard library
import cPickle
import gzip

# Third-party libraries
import numpy as np

def load_data():
    """Return the MNIST data as a tuple containing the training data,
    the validation data, and the test data.

    The ``training_data`` is returned as a tuple with two entries.
    The first entry contains the actual training images.  This is a
    numpy ndarray with 50,000 entries.  Each entry is, in turn, a
    numpy ndarray with 784 values, representing the 28 * 28 = 784
    pixels in a single MNIST image.

    The second entry in the ``training_data`` tuple is a numpy ndarray
    containing 50,000 entries.  Those entries are just the digit
    values (0...9) for the corresponding images contained in the first
    entry of the tuple.

    The ``validation_data`` and ``test_data`` are similar, except
    each contains only 10,000 images.

    This is a nice data format, but for use in neural networks it's
    helpful to modify the format of the ``training_data`` a little.
    That's done in the wrapper function ``load_data_wrapper()``, see
    below.
    """
    f = gzip.open('../data/mnist.pkl.gz', 'rb')
    training_data, validation_data, test_data = cPickle.load(f)
    f.close()
    return (training_data, validation_data, test_data)

def load_data_wrapper():
    """Return a tuple containing ``(training_data, validation_data,
    test_data)``. Based on ``load_data``, but the format is more
    convenient for use in our implementation of neural networks.

    In particular, ``training_data`` is a list containing 50,000
    2-tuples ``(x, y)``.  ``x`` is a 784-dimensional numpy.ndarray
    containing the input image.  ``y`` is a 10-dimensional
    numpy.ndarray representing the unit vector corresponding to the
    correct digit for ``x``.

    ``validation_data`` and ``test_data`` are lists containing 10,000
    2-tuples ``(x, y)``.  In each case, ``x`` is a 784-dimensional
    numpy.ndarry containing the input image, and ``y`` is the
    corresponding classification, i.e., the digit values (integers)
    corresponding to ``x``.

    Obviously, this means we're using slightly different formats for
    the training data and the validation / test data.  These formats
    turn out to be the most convenient for use in our neural network
    code."""
    tr_d, va_d, te_d = load_data()
    training_inputs = [np.reshape(x, (784, 1)) for x in tr_d[0]]
    training_results = [vectorized_result(y) for y in tr_d[1]]
    training_data = zip(training_inputs, training_results)
    validation_inputs = [np.reshape(x, (784, 1)) for x in va_d[0]]
    validation_data = zip(validation_inputs, va_d[1])
    test_inputs = [np.reshape(x, (784, 1)) for x in te_d[0]]
    test_data = zip(test_inputs, te_d[1])
    # training_data 是一个 list 包含 5000 个元素,每个元素是一个 tuple (x, y),其中
    # x 是一个 784 * 1 的向量
    # y 是一个 10 * 1 的向量,向量中某个位置为非 0 表示的是0-9的某个数字
    # validation_data 和 test_data 都是 list 包含 1000 个元素,每个元素是一个 tuple (x, y),其中
    # x 是一个 784 * 1 的向量
    # y 是一个 0-9 的数字
    return (training_data, validation_data, test_data)

def vectorized_result(j):
    """Return a 10-dimensional unit vector with a 1.0 in the jth
    position and zeroes elsewhere.  This is used to convert a digit
    (0...9) into a corresponding desired output from the neural
    network."""
    e = np.zeros((10, 1))
    e[j] = 1.0
    return e

执行算法:

输出:

Last updated