You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sigmoid导数在反向传播中的应用及Python神经网络权重更新问题

一、sigmoid导数在反向传播中的应用位置

你实现的sigmoid_derr函数核心作用是计算每层的误差敏感度delta,也就是当前层的输出变化会多大程度影响最终的总误差,它是反向传播里每层必须用到的计算因子:

  • 输出层:先算出预测值和真实值的误差,再乘sigmoid_derr(当前层输出),得到输出层的delta,作为输出层权重调整的核心参考
  • 隐藏层:先拿到后一层传递过来的误差,同样乘sigmoid_derr(当前层输出)得到隐藏层自身的delta
    你可以简单理解为:sigmoid导数是给每层的误差打“调整系数”,因为sigmoid输出接近0或1的时候导数值非常小,代表这个位置的神经元输出已经接近饱和,不需要大幅调整对应权重。

二、神经网络权重的更新逻辑

权重更新的核心目标是让总误差不断变小,所以调整方向要和误差方向相反,还要乘以学习率控制每次调整的幅度,避免调整幅度过大错过最优值。
简化的可直接套用的权重更新公式(不需要额外微积分知识):
新权重 = 旧权重 - 学习率 * (当前层输入矩阵转置 点乘 当前层的delta)

三、现有代码的错误点和修正方案

主要问题:

  1. 权重更新方向错误:你当前代码用了+=直接加调整量,相当于往误差变大的方向调整权重,所以输出会卡在固定的异常值
  2. 权重更新的计算参数错误:不应该用层.output.T参与矩阵乘,应该用层.input.T,因为权重是连接输入和当前层的,调整量要和输入的大小挂钩
  3. 权重初始化维度不匹配:原代码的权重维度设置反了,会导致矩阵乘法逻辑和反向传播的维度适配出错
  4. 输入的维度没有统一:单样本输入是一维数组,容易触发numpy的广播机制导致计算偏差

修正后的可运行代码

import numpy as np

INPUT = 'INPUT'
HIDDEN = 'HIDDEN'
OUTPUT = 'OUTPUT'

class Layer:
    def __init__(self, neurons, connections, type):
        self.neurons = neurons
        self.connections = connections
        # 权重维度调整为[输入特征数, 输出神经元数],适配矩阵乘法逻辑
        self.weights = np.random.randn(connections, neurons) * 0.01
        self.type = type
        self.learning_rate = 0.1

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

    def sigmoid_derr(self, value):
        return value * (1 - value)

    def feed_forward(self, input):
        # 输入统一转为二维矩阵,避免维度广播错误
        self.input = np.array(input, ndmin=2)
        self.pre_activation = np.dot(self.input, self.weights)
        self.output = self.sigmoid(self.pre_activation)
        return self.output

    def backprop(self, expected=[], prevError=None):
        if self.type == OUTPUT:
            self.error = np.subtract(expected, self.output)
            self.delta = np.multiply(self.error, self.sigmoid_derr(self.output))
            self.error = np.dot(self.delta, self.weights.T)
        else:
            self.delta = np.multiply(prevError, self.sigmoid_derr(self.output))
            self.error = np.dot(self.delta, self.weights.T)

# 层初始化参数:第一个参数为当前层输出神经元数,第二个为输入特征数
l1 = Layer(3, 2, type=INPUT)
l2 = Layer(4, 3, type=HIDDEN)
l3 = Layer(2, 4, type=OUTPUT)

for i in range(50000):
    # 前向传播
    l1.feed_forward([0.26, 0.87])
    l2.feed_forward(l1.output)
    l3.feed_forward(l2.output)

    # 反向传播
    l3.backprop(expected=[0.12, 0.92])
    l2.backprop(prevError=l3.error)
    l1.backprop(prevError=l2.error)

    # 权重更新
    l3.weights -= l3.learning_rate * np.dot(l3.input.T, l3.delta)
    l2.weights -= l2.learning_rate * np.dot(l2.input.T, l2.delta)
    l1.weights -= l1.learning_rate * np.dot(l1.input.T, l1.delta)

    if i % 5000 == 0:
        print(f"迭代次数{i},输出:{l3.output}")

运行后可以看到输出会逐渐收敛到你设定的目标值[0.12, 0.92]。

内容的提问来源于stack exchange,提问作者IRL135

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:48:00