神经网络代码--反向传播计算梯度

def gradient(self, x, t):
    # === 1. 前向传播,计算当前输入下的损失值(开启训练模式) ===
    self.loss(x, t, train_flg=True)

    # === 2. 从最后一层(通常是 SoftmaxWithLoss)开始反向传播 ===
    dout = 1  # 损失函数的导数对自身为 1,作为反向传播的起点
    dout = self.last_layer.backward(dout)  # 计算最后一层的反向传播输出

    # === 3. 将隐藏层和其他中间层按反向顺序反向传播 ===
    layers = list(self.layers.values())  # 获取所有层的列表
    layers.reverse()  # 将层顺序反转,便于从后往前传播
    for layer in layers:
        dout = layer.backward(dout)  # 依次对每一层执行反向传播

    # === 4. 设定梯度字典 grads,用于保存每个参数的梯度 ===
    grads = {}
    for idx in range(1, self.hidden_layer_num + 2):  # 遍历每一层(含输出层)
        # 获取第 idx 层的 Affine 层的权重和偏置的梯度,并加上权重衰减(L2正则化)项
        grads['W' + str(idx)] = self.layers['Affine' + str(idx)].dW + \
                                self.weight_decay_lambda * self.params['W' + str(idx)]
        grads['b' + str(idx)] = self.layers['Affine' + str(idx)].db

        # 如果使用了批归一化(BatchNorm),并且当前不是输出层
        if self.use_batchnorm and idx != self.hidden_layer_num + 1:
            # 提取 BatchNorm 层的缩放参数 gamma 和偏移参数 beta 的梯度
            grads['gamma' + str(idx)] = self.layers['BatchNorm' + str(idx)].dgamma
            grads['beta' + str(idx)] = self.layers['BatchNorm' + str(idx)].dbeta

    # === 5. 返回包含所有参数梯度的字典,用于优化器更新权重 ===
    return grads

这段代码是一个神经网络中用于反向传播计算梯度的函数 gradient(self, x, t),属于某个类(如 MultiLayerNetExtend)的方法。该方法执行以下步骤:


✅ 1. 前向传播(Forward)

self.loss(x, t, train_flg=True)

  • 使用输入 x 和标签 t 执行前向传播,并计算损失(包括正则化项)。

  • train_flg=True 表明这是训练过程(例如 BatchNorm 会区分训练和推理模式)。


✅ 2. 反向传播起点

dout = 1

dout = self.last_layer.backward(dout)

  • self.last_layer 通常是损失函数层(比如 SoftmaxWithLoss),backward() 返回对前一层的梯度。

  • 这个 1 表示对损失函数的导数(标量)开始反向传播。


✅ 3. 逐层反向传播

layers = list(self.layers.values())
layers.reverse()
for layer in layers:
    dout = layer.backward(dout)

  • self.layers 是一个 OrderedDict,按顺序存储所有的网络层。

  • .reverse() 后,按从输出层到输入层的顺序反向传播。

  • 每一层都使用 backward() 方法计算梯度并更新 dout


✅ 4. 收集所有梯度到 grads 字典中

grads = {}
for idx in range(1, self.hidden_layer_num+2):

对于每一层(包含隐藏层和输出层):

🧠 权重和偏置项:
grads['W' + str(idx)] = self.layers['Affine' + str(idx)].dW + self.weight_decay_lambda * self.params['W' + str(idx)]
grads['b' + str(idx)] = self.layers['Affine' + str(idx)].db
  • 从每个 Affine 层中提取梯度:

    • dW:权重的梯度,加上 L2 正则化项(weight_decay_lambda * W)。

    • db:偏置项的梯度。

🧪 如果使用了 BatchNorm,还要收集 gamma 和 beta 的梯度:
if self.use_batchnorm and idx != self.hidden_layer_num+1:
    grads['gamma' + str(idx)] = self.layers['BatchNorm' + str(idx)].dgamma
    grads['beta' + str(idx)] = self.layers['BatchNorm' + str(idx)].dbeta
  • 对于除了输出层的各层(因为输出层不使用 BatchNorm):

    • gammabeta 是 BatchNorm 层的缩放和平移参数。

    • 它们也有各自的反向传播梯度:dgamma, dbeta


✅ 5. 返回梯度字典

return grads
  • grads 是一个包含所有参数梯度的字典,结构如下:

{
    'W1': ..., 'b1': ..., 'gamma1': ..., 'beta1': ...,
    'W2': ..., 'b2': ..., ...
}

📌 总结

这个函数的作用是:

给定输入 x 和标签 t,通过前向传播计算损失,反向传播得到每层的梯度,并将所有参数的梯度打包进一个字典返回,用于后续的权重更新(如 SGD、Adam)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值