从人工神经元到神经网络实战:前向传播与反向传播算法详解及实现

1次阅读
没有评论

共计 2541 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

人工神经元:神经网络的基础构建块

人工神经元是神经网络的基本单元,其数学模型模仿了生物神经元的工作原理。一个典型的人工神经元包含三个主要部分:

从人工神经元到神经网络实战:前向传播与反向传播算法详解及实现

  1. 输入:接收来自其他神经元或外部环境的信号(x₁, x₂, …, xn)
  2. 权重:每个输入都有一个对应的权重(w₁, w₂, …, wn),表示该输入的重要性
  3. 激活函数:对加权和进行非线性变换的函数(如 Sigmoid、ReLU 等)

数学表达式为:

z = w₁x₁ + w₂x₂ + ... + wnxn + b
a = f(z)

其中 b 是偏置项,f 是激活函数。

前向传播:信息流动的方向

前向传播是神经网络进行预测的核心过程,其步骤可以概括为:

  1. 输入数据通过输入层进入网络
  2. 每一层的神经元计算加权和并应用激活函数
  3. 结果传递到下一层,直到输出层产生最终预测

以一个简单的 3 层网络(输入层、隐藏层、输出层)为例:

  1. 输入层到隐藏层:
    z^[1] = W^[1]X + b^[1]
    a^[1] = f^[1](z^[1])
  2. 隐藏层到输出层:
    z^[2] = W^[2]a^[1] + b^[2]
    a^[2] = f^[2](z^[2])

反向传播算法:神经网络的学习引擎

反向传播(Backpropagation,简称 BP)是神经网络训练的核心算法,其目的是通过调整权重来最小化损失函数。BP 算法可以分为四个主要步骤:

  1. 前向传播 计算预测值和损失
  2. 计算输出层误差
    δ^[L] = ∂L/∂a^[L] ⊙ f'^[L](z^[L])
  3. 反向传播误差 到各层:
    δ^[l] = (W^[l+1]T δ^[l+1]) ⊙ f'^[l](z^[l])
  4. 计算梯度并更新参数
    ∂L/∂W^[l] = δ^[l] a^[l-1]T
    ∂L/∂b^[l] = δ^[l]
    W^[l] = W^[l] - α ∂L/∂W^[l]
    b^[l] = b^[l] - α ∂L/∂b^[l]

Python 实现:从零搭建神经网络

下面是一个简单的全连接神经网络的 Python 实现:

import numpy as np

class NeuralNetwork:
    def __init__(self, layer_sizes):
        self.weights = [np.random.randn(y, x) * 0.1 
                        for x, y in zip(layer_sizes[:-1], layer_sizes[1:])]
        self.biases = [np.zeros((y, 1)) for y in layer_sizes[1:]]

    def forward(self, x):
        a = x
        for w, b in zip(self.weights, self.biases):
            z = np.dot(w, a) + b
            a = self.sigmoid(z)
        return a

    def backward(self, x, y):
        # 前向传播
        activations = [x]
        zs = []
        for w, b in zip(self.weights, self.biases):
            z = np.dot(w, activations[-1]) + b
            zs.append(z)
            activations.append(self.sigmoid(z))

        # 反向传播
        delta = (activations[-1] - y) * self.sigmoid_prime(zs[-1])
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        nabla_b = [np.zeros(b.shape) for b in self.biases]

        nabla_w[-1] = np.dot(delta, activations[-2].T)
        nabla_b[-1] = delta

        for l in range(2, len(self.weights)+1):
            z = zs[-l]
            sp = self.sigmoid_prime(z)
            delta = np.dot(self.weights[-l+1].T, delta) * sp
            nabla_w[-l] = np.dot(delta, activations[-l-1].T)
            nabla_b[-l] = delta

        return nabla_w, nabla_b

    def sigmoid(self, z):
        return 1.0/(1.0 + np.exp(-z))

    def sigmoid_prime(self, z):
        return self.sigmoid(z) * (1 - self.sigmoid(z))

激活函数对比与选择

常见的激活函数包括:

  1. Sigmoid
  2. 优点:输出在 (0,1) 之间,适合二分类问题
  3. 缺点:容易出现梯度消失,计算成本高
  4. 公式:σ(z) = 1/(1 + e^-z)

  5. ReLU(Rectified Linear Unit):

  6. 优点:计算简单,缓解梯度消失
  7. 缺点:可能出现神经元 ” 死亡 ” 问题
  8. 公式:ReLU(z) = max(0, z)

  9. Tanh

  10. 优点:输出在 (-1,1) 之间,中心对称
  11. 缺点:同样存在梯度消失问题
  12. 公式:tanh(z) = (e^z – e^-z)/(e^z + e^-z)

  13. Leaky ReLU

  14. 优点:解决了 ReLU 的神经元死亡问题
  15. 缺点:需要调参
  16. 公式:LReLU(z) = max(αz, z),通常 α =0.01

优化算法选择策略

  1. 随机梯度下降(SGD)
  2. 最简单的优化方法
  3. 容易陷入局部最优
  4. 学习率需要仔细调整

  5. 动量法(Momentum)

  6. 引入速度概念,加速收敛
  7. 减少震荡
  8. 公式:v = γv + η∇J(θ)
    θ = θ – v

  9. Adam

  10. 结合了动量法和 RMSProp
  11. 自适应学习率
  12. 实践中表现优异

生产环境注意事项

  1. 梯度消失 / 爆炸
  2. 使用 ReLU 等激活函数
  3. 实施梯度裁剪(gradient clipping)
  4. 使用批归一化(Batch Normalization)

  5. 过拟合

  6. 使用 L1/L2 正则化
  7. 实施 Dropout
  8. 增加训练数据

  9. 学习率调优

  10. 使用学习率衰减
  11. 实施学习率预热
  12. 考虑使用周期性学习率

思考题

  1. 如何修改我们的神经网络实现来支持多种不同的激活函数?
  2. 除了均方误差和交叉熵,还有哪些损失函数适合神经网络?它们各有什么特点?
  3. 批处理(batch processing)对神经网络训练有什么影响?如何选择合适的 batch size?

总结

本文从人工神经元的基本原理出发,详细讲解了神经网络的前向传播和反向传播算法,并提供了完整的 Python 实现。我们还比较了不同激活函数和优化算法的特点,并讨论了生产环境中需要注意的问题。神经网络虽然强大,但也需要仔细调参和优化才能发挥最佳性能。希望这篇文章能帮助你更好地理解和应用神经网络技术。

正文完
 0
评论(没有评论)