Chainer - 前向和后向传播

Chainer 中的前向传播

Chainer 中的前向传播是指将输入数据通过神经网络层来计算输出的过程。众所周知,Chainer 是一个灵活的深度学习框架,它允许动态计算图,这意味着在数据通过网络向前移动时,图是即时构建的。

在前向传播期间,网络的每一层都会对输入数据应用一组操作(例如矩阵乘法、激活函数等),逐步对其进行转换,直到产生最终输出。此输出可能是分类或回归等任务中的预测。

在 Chainer 中,正向传播通常通过调用模型并以输入数据作为参数来处理,并在发生这种情况时动态构建计算图。

正向传播所涉及的步骤

正向传播是神经网络中的一个基本过程,其中输入数据通过网络层传递以产生输出。该过程涉及应用一系列数学运算,通常涉及矩阵乘法和激活函数以将输入转换为所需的输出。以下是正向传播所涉及的详细步骤 −

  • 输入层:该过程从将原始数据输入网络开始。每个输入特征都被分配一个权重,该权重会影响其对下一层的影响。
  • 加权和(线性变换):对于每一层,网络计算输入的加权和,其计算方式为
    z = W . x + b
    

    其中 z 是加权和,W 是权重矩阵,x 是输入向量,b 是偏差向量。

  • 激活函数:加权和 z 通过激活函数将非线性引入模型。常见函数如 ReLU(整流线性单元)、Sigmoid 和 Tanh。例如,如果我们使用 ReLU,则应用的激活函数将如下所示 −
    a = ReLU(z)
    

    其中 a 是结果,即激活函数的转换输出。

  • 通过层传播:每层的输出作为下一层的输入。此过程迭代应用于所有隐藏层,逐步细化数据表示。
  • 输出层:最后一层产生网络的预测。此处激活函数的选择取决于下面提到的任务 −
    • 分类:Softmax 用于生成类概率。
    • 回归:线性函数用于输出连续值。
  • 最终输出:网络的输出用于进行预测或决策。在训练期间,将此输出与实际目标值进行比较以计算误差,该误差用于通过反向传播更新权重。

示例

以下是 Chainer 中使用简单神经网络进行前向传播的示例。该网络由一个输入层、一个隐藏层和一个输出层组成。以下代码展示了如何执行前向传播并获得网络的输出 −

import chainer
import chainer.functions as F
import chainer.links as L
import numpy as np
from chainer import Variable

# 定义神经网络模型
class SimpleNN(chainer.Chain):
    def __init__(self):
        super(SimpleNN, self).__init__()
        with self.init_scope():
        self.l1 = L.Linear(3, 5) # 输入层到隐藏层
        self.l2 = L.Linear(5, 2) # 隐藏层到输出层

    def forward(self, x):
        # 计算隐藏层输出
        h = self.l1(x)
        print("隐藏层(激活前):", h.data)
        
        # 应用 ReLU 激活函数
        h = F.relu(h)
        print("隐藏层(ReLU 后):", h.data)
        
        # 计算输出层
        y = self.l2(h)
        print("输出层(激活前):", y.data)

		return y

# 创建模型实例
model = SimpleNN()

# 准备输入数据
x = Variable(np.array([[1, 2, 3]], dtype=np.float32)) # 具有 3 个特征的单个样本

# 执行前向传播
output = model.forward(x)

# 显示最终输出
print("最终输出:", output.data)

以下是前向传播的输出 −

隐藏层(激活前):[[-3.2060928 -0.2460978 2.527906 -0.91410434 0.11754721]]
隐藏层(ReLU 后):[[0. 0. 2.527906 0. 0.11754721]]
输出层(激活前):[[ 1.6746329 -0.21084023]]
最终输出:[[ 1.6746329 -0.21084023]]

Chainer 中的反向传播

反向传播是一种用于计算损失函数相对于神经网络参数的梯度的方法。此过程对于通过调整权重来减少损失来训练网络至关重要。

反向传播中的步骤

反向传播过程由几个关键步骤组成,每个步骤对于优化模型的参数和提高其性能都至关重要。让我们逐一详细了解它们 −

  • 前向传递:输入数据通过产生预测输入网络。然后使用损失函数将这些预测与真实目标进行比较,以计算预测误差。
  • 损失计算:损失函数通过提供反映模型性能的标量值来测量预测值与实际目标之间的差异。
  • 后向传递:使用链式法则计算损失函数相对于每个网络参数的梯度。这涉及将梯度从输出层反向传播到输入层。
  • 参数更新:计算出的梯度用于调整网络的参数,例如权重和偏差。这种调整通常由优化器(例如 SGD 或 Adam)执行,优化器会更新参数以最小化损失函数。

示例

以下示例通过在 Chainer Framework − 中打印损失函数来展示反向传播的工作原理

import chainer
import chainer.functions as F
import chainer.links as L
from chainer import Chain, optimizers
import numpy as np

# 定义一个简单的神经网络
class MLP(Chain):
    def __init__(self):
        super(MLP, self).__init__()
        with self.init_scope():
        self.l1 = L.Linear(2, 3) # 输入层到隐藏层
        self.l2 = L.Linear(3, 1) # 隐藏层到输出层
    
    def forward(self, x):
        h = F.relu(self.l1(x)) # 前向传递隐藏层
        y = self.l2(h) # 前向传递输出层
        return y

# 创建模型和优化器
model = MLP()
optimizer = optimizers.SGD()
optimizer.setup(model)

# 样本输入和目标数据
x = chainer.Variable(np.array([[1.0, 2.0]], dtype=np.float32))
t = chainer.Variable(np.array([[1.0]], dtype=np.float32))

# 前向传播
y = model.forward(x)
loss = F.mean_squared_error(y, t) # 计算损失

# 后向传播
model.cleargrads() # 清除之前的梯度
loss.backward() # 计算梯度
optimizer.update() # 使用优化器更新参数

print("Loss:", loss.data)

下面是打印后向传播损失函数输出的示例 −

Loss: 1.0728482