从认识AI开始-----反向传播

一、反向传播(Backpropagation,BP)

BP算法是训练神经网络中非常核心的一步,它的作用是通过链式求导法则来计算每个参数对最终损失的影响(梯度),然后配合梯度下降算法来进行更新。

简单来说,整个神经网络参数更新流程包括四步:

  1. 正向输入:输入数据——>计算输出——>得到预测值
  2. 计算损失:(预测值 vs 真实值) ——>损失函数
  3. 反向传播:从输出层向输入层,逐层反向计算梯度
  4. 参数更新:使用梯度下降算法(即优化器)更新权重

反向传播的本质是梯度计算,配合梯度下降优化算法学习到更好的参数,从而进行模型的学习和推导


二、为什么BP这么重要?

在深度学习中,一个模型的参数可能有数十万、上百万参数甚至上亿参数,如果我们手动去计算这些参数的梯度,几乎是不可能完成的,因此,必须借助自动化的梯度计算机制来完成庞大的计算量。

BP正是完成这件事的核心算法,它能够帮助我们:

  1. 自动求导每个参数的梯度
  2. 高效地训练深度神经网络
  3. 快速收敛损失,使模型学到有效特征

随着深度学习的发展,模型的层数越来越深,如果没有BP算法,我们无法训练多层神经网络


三、举个例子来理解BP

我们以一个最简单的神经网络为例

输入 —> 权重 —> 线性计算  —> 激活函数 —>  —> 损失 

假设:

  • 输入
  • 权重 (待学习)
  • 真实值

1. 正向传播

x , w, t = 2.0, 1.0, 4.0

y = x * w
z = y ** 2
L = (z -t) ** 2

    2. 反向传播(链式法则)

    我们的目标是求:,也就是损失对权重的导数。

    通过链式法则:

    分别计算

    所以

    这个例子中损失为0,所以梯度也为0,当然现实中模型的预测值和真实值肯定会有细微差别,损失很难为0,但通过该例子清晰展示了反向传播的链式求导过程

    四、计算图与BP:自动求导的核心机制

    1. 什么是计算图?

    在深度学习中,我们会把模型的前向过程表示为一个有向图,这个图计叫做计算图(Computation Graph):

    • 节点(node):表示变量或操作(加法、乘法、ReLU等)
    • 边(edge):表示依赖关系(函数关系),数据在节点之间流动

    举个例子,假设函数为:

    则其计算图张这样:

    2.计算图与反向传播的关系?

    当我们做正向传播时,实际上是在构建计算图并记录每一步操作的输出与依赖。

    而反向传播就是:从计算图的输出节点开始,沿着图反向一次应用链式法则,计算每个节点对最终损失的导数(梯度)

    计算图有以下优点:

    • 自动化:可以自动生成导数公式
    • 高效:只计算需要的梯度(不产生冗余)
    • 灵活:支持动态图结构(Pytorch的核心特性)

    3.Pytroch是怎么用计算图呢?

    Pytorch使用的是动态计算图

    • 在每次前向传播时即时构建计算图
    • 每个Tensor会记录它是由哪些操作生成的
    • 调用.backward()时会自动沿图回溯求梯度

    下面我将使用Pytorch来展示具体示例:

    import torch
    x = torch.tensor(2.0, requires_grad=True)
    w = torch.tensor(3.0, requires_grad=True)
    
    y = x * w
    z = y ** 2
    loss = z
    
    loss.backward() #自动构建计算图并反向传播
    print(x.grad) #输出x的梯度值
    print(w.grad) #输出w的梯度值

    五、手动实现一个简单的神经网络的反向传播

    下面我将用Python手写一个两层的神经网络的反向传播:

    import numpy as np
    
    #初始化输入、权重w、偏置b
    x = np.array([1.0, 2.0])
    #第一层权重和偏置
    w1 = np.random.randn(2, 3)
    b1 = np.zeros(1, 3)
    #第二层权重和偏置
    w2 = np.random.randn(3, 1)
    b2 = np.zeros(1, 1)
    #真实标签
    y_true = np.array([[1,0]])
    
    #正向传播
    z1 = x.dot(w1) + b1
    #relu激活函数
    a1 = np.maximum(0,z1)
    z2 = z1.dot(w2) + b2
    
    y_pred = z2
    
    #计算损失
    loss = 0.5 * (y_pred - y_true) ** 2
    
    #反向传播
    
    #损失对输出梯度
    dL_dy = y_pred - y_true
    dy_dz2 = 1
    #第二层输出梯度、权重梯度
    dL_dz2 = dL_dy * dy_dz2
    dL_dw2 = a1.T.dot(dL_dz2)
    dL_db2 = dL_dz2
    
    dL_da1 = dL_dz2.dot(w2.T)
    da1_dz1 = (z1 > 0).astype(float) #relu激活函数导数
    dL_dz1 = dL_da1 * da1_dz1
    dL_dw1 = x.T(dL_dz1)
    
    dL_db1 = dL_dz1
    
    #手动更新参数(学习率 0.01)
    lr = 0.01
    w1 -= lr * dL_dw1
    b1 -= lr * dL_db1
    w2 -= lr * dL_dw2
    b2 -= lr * dL_db2
    
    

    六、用 PyTorch 实现并自动求梯度

    第五章我们使用Python实现了两层神经网络的反向传播过程,虽然仅有两层,但是代码量还是很大的。接下来,我们来看看Pytroch内置的动态计算图来自动求导进行反向传播的代码,Pytorch 的 autograd会自动完成反向传播:

    import torch
    import torch.nn as nn
    
    # 输入和标签
    x = torch.tensor([[1.0, 2.0]], requires_grad=True)
    y_true = torch.tensor([[1.0]])
    
    # 定义模型
    model = nn.Sequential(
        nn.Linear(2, 3),
        nn.ReLU(),
        nn.Linear(3, 1)
    )
    
    # 损失函数
    criterion = nn.MSELoss()
    
    # 优化器
    optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
    
    # 前向传播
    y_pred = model(x)
    loss = criterion(y_pred, y_true)
    
    # 反向传播 + 更新
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    七、写在最后

    以上就是BP的全部原理和具体实现。读到这里,相信小伙伴们都已经对BP有了很深的理解:BP就是利用链式规则自动计算梯度,来训练神经网络,进行参数更新,这是当前所有深度神经网络模型的参数优化规则,pytorch的计算图能够自动计算各参数梯度,更具模块化并且高效。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值