深入理解前向传播、反向传播和计算图

6 篇文章 0 订阅
2 篇文章 1 订阅

1. 什么是前向传播?

前向传播(Forward Propagation)是神经网络的推理过程。它将输入数据逐层传递,通过每一层的神经元计算,最终生成输出。

前向传播的公式

假设我们有一个简单的三层神经网络(输入层、一个隐藏层和输出层),网络的每一层计算如下:

z ( 1 ) = W ( 1 ) ⋅ X + b ( 1 ) z^{(1)} = W^{(1)} \cdot X + b^{(1)} z(1)=W(1)X+b(1)
a ( 1 ) = σ ( z ( 1 ) ) a^{(1)} = \sigma(z^{(1)}) a(1)=σ(z(1))
z ( 2 ) = W ( 2 ) ⋅ a ( 1 ) + b ( 2 ) z^{(2)} = W^{(2)} \cdot a^{(1)} + b^{(2)} z(2)=W(2)a(1)+b(2)
y ^ = a ( 2 ) = softmax ( z ( 2 ) ) \hat{y} = a^{(2)} = \text{softmax}(z^{(2)}) y^=a(2)=softmax(z(2))

其中,(W) 和 (b) 分别是权重矩阵和偏置,(\sigma) 是激活函数,(\hat{y}) 是网络的输出。

代码示例

我们用 Python 和 NumPy 来实现前向传播的过程:

import numpy as np

# 输入数据和网络参数
X = np.array([[0.5, 1.2]])
W1 = np.array([[0.4, 0.3], [0.2, 0.7]])
b1 = np.array([[0.1, 0.2]])
W2 = np.array([[0.6], [0.8]])
b2 = np.array([[0.3]])

# 激活函数
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

# 前向传播
z1 = np.dot(X, W1) + b1
a1 = sigmoid(z1)
z2 = np.dot(a1, W2) + b2
output = sigmoid(z2)

print("网络输出:", output)

2. 什么是反向传播?

反向传播(Backpropagation)是神经网络的训练过程,它通过计算损失函数的梯度来更新权重,从而最小化损失。

反向传播的原理

反向传播通过链式法则计算梯度。假设我们的损失函数是均方误差(MSE):

L = 1 2 ( y ^ − y ) 2 L = \frac{1}{2} (\hat{y} - y)^2 L=21(y^y)2

对于每个权重 (W),梯度更新规则为:

∂ L ∂ W ( 2 ) = δ ( 2 ) ⋅ a ( 1 ) \frac{\partial L}{\partial W^{(2)}} = \delta^{(2)} \cdot a^{(1)} W(2)L=δ(2)a(1)

其中,(\delta^{(2)}) 是输出层的误差:

δ ( 2 ) = y ^ − y \delta^{(2)} = \hat{y} - y δ(2)=y^y

代码示例

我们可以用 Python 代码实现一个简单的反向传播:

# 假设真实标签
y = np.array([[1]])

# 计算损失
loss = 0.5 * (output - y) ** 2

# 反向传播
d_output = output - y
d_z2 = d_output * output * (1 - output)
d_W2 = np.dot(a1.T, d_z2)

d_a1 = np.dot(d_z2, W2.T)
d_z1 = d_a1 * a1 * (1 - a1)
d_W1 = np.dot(X.T, d_z1)

# 更新权重
learning_rate = 0.1
W2 -= learning_rate * d_W2
W1 -= learning_rate * d_W1

print("更新后的 W1:", W1)
print("更新后的 W2:", W2)

3. 理解计算图

计算图(Computational Graph)是表示神经网络中计算过程的图形结构。通过计算图,我们可以直观地理解前向传播和反向传播。

在计算图中,节点表示操作(如加法、乘法、激活函数)或变量(如输入、权重),边表示数据流动。通过前向传播,计算图中的数据从输入流向输出;通过反向传播,梯度从输出反向传播到输入。

4. 实战案例:手写数字识别

让我们用一个简单的手写数字识别的案例来巩固这些概念。我们将使用一个小型的神经网络,通过前向传播预测数字,通过反向传播调整权重。

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder

# 加载数据
digits = load_digits()
X = digits.data / 16.0
y = digits.target.reshape(-1, 1)

# 独热编码标签
encoder = OneHotEncoder(sparse=False)
y_onehot = encoder.fit_transform(y)

# 分割数据
X_train, X_test, y_train, y_test = train_test_split(X, y_onehot, test_size=0.3)

# 初始化网络参数
input_size = X_train.shape[1]
hidden_size = 64
output_size = y_train.shape[1]

W1 = np.random.randn(input_size, hidden_size)
b1 = np.zeros((1, hidden_size))
W2 = np.random.randn(hidden_size, output_size)
b2 = np.zeros((1, output_size))

# 训练过程
epochs = 1000
learning_rate = 0.01

for epoch in range(epochs):
    # 前向传播
    z1 = np.dot(X_train, W1) + b1
    a1 = sigmoid(z1)
    z2 = np.dot(a1, W2) + b2
    output = sigmoid(z2)
    
    # 计算损失
    loss = np.mean(0.5 * (output - y_train) ** 2)
    
    # 反向传播
    d_output = output - y_train
    d_z2 = d_output * output * (1 - output)
    d_W2 = np.dot(a1.T, d_z2)
    
    d_a1 = np.dot(d_z2, W2.T)
    d_z1 = d_a1 * a1 * (1 - a1)
    d_W1 = np.dot(X_train.T, d_z1)
    
    # 更新权重
    W2 -= learning_rate * d_W2
    W1 -= learning_rate * d_W1
    
    if epoch % 100 == 0:
        print(f"Epoch {epoch}, Loss: {loss:.4f}")

通过上述代码,我们可以训练一个简单的神经网络来识别手写数字。在每个训练周期,网络通过前向传播计算输出,通过反向传播调整权重。

5. 总结

在本文中,我们深入探讨了前向传播、反向传播和计算图的概念,并通过代码示例和图示帮助理解这些复杂的过程。希望这些内容能帮助你更好地理解神经网络的工作原理。


通过这些详细的解释、代码示例和图示,你的读者应该能够深入理解前向传播、反向传播和计算图在神经网络中的作用。如果需要进一步调整内容,随时可以进行修改。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello.Reader

请我喝杯咖啡吧😊

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值