深入浅出神经网络与深度学习 第一章:用神经网络识别手写数字

神经网络的基本构成

  1. 神经元(Neurons):

    • 神经网络的基本单位是神经元,也称为节点或单元。每个神经元接收多个输入信号,并通过一个激活函数生成输出信号。

    • 感知机(我称之为单细胞生物),条件jwjxj=ωx\sum_{j}{w_j}{x_j} = \omega\cdot x其规则可以写为:

      输出={1,ωx+b00,ωx+b>0 输出 = \begin{cases} 1,若\omega\cdot x+b\leq0 \\ 0,若\omega\cdot x+b>0 \\ \end{cases}

    • 本章程序使用的是sigmoid神经元.sigmoid神经元对每个输入有权重w1,w2,w_1,w_2,\cdots和一个总的偏置b,但是输出不是0或1,而是σ(ωx+b)\sigma(\omega\cdot x+b),其中σ\sigma被称之为sigmoid函数,定义如下:

      σ(x)=11+ez=11+exp(jwjxjb)\large \sigma(x) = \frac{1}{1+e^{-z}} = \frac{1}{1+exp(-\sum_j{w_j}{x_j}-b)}

  2. 层(Layers):

    • 神经网络由多个层组成。通常包括输入层、隐藏层和输出层。输入层接收外部数据,隐藏层进行数据处理和特征提取,输出层生成最终结果。
  3. 权重(Weights)和偏置(Biases):

    • 每个连接(即神经元之间的连接)都有一个权重 w,表示该连接的强度。每个神经元还有一个偏置 b,用于调节激活函数的输出。

激活函数

激活函数是将输入信号转换为输出信号的函数。常见的激活函数有:

  • Sigmoid函数
  • ReLU(Rectified Linear Unit)
  • Tanh(双曲正切函数)

神经网络的工作原理

  1. 前向传播(Forward Propagation):

    • 输入数据通过输入层传递到隐藏层,经过加权求和和激活函数处理,再传递到输出层生成最终结果。
  2. 损失函数(代价函数或目标函数)(Loss Function):

    • 用于衡量神经网络输出结果与实际结果之间的差异。常用的损失函数有均方误差(MSE)和交叉熵(Cross-Entropy)。

    • 本章使用的函数为:

      C(w,b)12nxy(x)a2C(w,b)\equiv\frac{1}{2n}\sum_x{||y(x)-a||^2}

  3. 反向传播(Backpropagation):

    • 通过反向传播算法计算损失函数相对于每个权重的梯度,从而更新权重以减少损失。反向传播结合梯度下降算法来优化网络。

梯度下降算法

梯度下降是一种优化算法,通过计算损失函数的梯度,沿着梯度的反方向更新权重,使损失函数值逐渐减小。常见的梯度下降算法有:

  • 批量梯度下降(Batch Gradient Descent)
  • 随机梯度下降(Stochastic Gradient Descent, SGD)
  • 小批量梯度下降(Mini-Batch Gradient Descent)

训练神经网络

  1. 初始化:
    • 随机初始化神经网络的权重和偏置。
  2. 前向传播:
    • 将输入数据通过神经网络进行前向传播,计算输出结果。
  3. 计算损失:
    • 使用损失函数计算输出结果与实际结果之间的差异。
  4. 反向传播和权重更新:
    • 通过反向传播计算梯度,并使用梯度下降算法更新权重。
  5. 迭代训练:
    • 重复前向传播、计算损失、反向传播和权重更新过程,直到损失函数值收敛或达到设定的训练次数。

手写数字识别示例

第一章以手写数字识别为例,通过MNIST数据集训练一个简单的神经网络,演示了神经网络的基本构建和训练过程。可以使用Git克隆代码仓库:

1
git clone https://github.com/Margit-Arachne/My-little-AI.git

该示例可以通过Python Shell来启动,包括以下步骤:

  1. 加载MNIST数据集

    1
    2
    3
    4
    5
    import sys
    #此处为mnist_loader.py等文件具体位置
    sys.path.append(r'D:\git-ai\neural-networks-and-deep-learning\src')
    import mnist_loader
    training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
  2. 初始化神经网络

    1
    2
    3
    4
    5
    import network
    #[]中数字依次代表:输入神经元数, 隐藏神经元数, 输出神经元数
    net = network.Network([784, 30, 10])
    #()中数字依次代表:学习轮数, 小批量大小, 学习率
    net.SGD(training_data, 30, 10, 3.0, test_data=test_data)
  3. 使用前向传播计算输出结果

  4. 计算损失并进行反向传播

  5. 使用梯度下降算法更新权重

  6. 评估神经网络的性能

本章使用代码为mnist_loader.py 和 network.py

当没有隐藏层,只有输入输出层,最佳学习结果的学习率大概为0.0015左右,结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Epoch 0: 1135 / 10000
Epoch 1: 1135 / 10000
Epoch 2: 1135 / 10000
Epoch 3: 1135 / 10000
Epoch 4: 1135 / 10000
Epoch 5: 1135 / 10000
Epoch 6: 1135 / 10000
Epoch 7: 1135 / 10000
Epoch 8: 1135 / 10000
Epoch 9: 1135 / 10000
Epoch 10: 1135 / 10000
Epoch 11: 1135 / 10000
Epoch 12: 1135 / 10000
Epoch 13: 1135 / 10000
Epoch 14: 1135 / 10000
Epoch 15: 1135 / 10000
Epoch 16: 1135 / 10000
Epoch 17: 1135 / 10000
Epoch 18: 1135 / 10000
Epoch 19: 1135 / 10000
Epoch 20: 1135 / 10000
Epoch 21: 1135 / 10000
Epoch 22: 1135 / 10000
Epoch 23: 1135 / 10000
Epoch 24: 1135 / 10000
Epoch 25: 1135 / 10000
Epoch 26: 1135 / 10000
Epoch 27: 1135 / 10000
Epoch 28: 1135 / 10000
Epoch 29: 1135 / 10000