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

自制Python-Numpy简易神经网络权重无法下调问题求助

神经网络权重只增不减问题排查与解决建议

我刚接触神经网络编程,正通过Python结合Numpy编写简易神经网络以学习相关知识。目前网络整体运行尚可,但存在一个问题:权重(至少最后一层的权重)从未下降。网络初始阶段权重大幅增长,跳过了最优值,之后增长速率逐渐放缓,但始终不会下调权重以回归最优状态。调整学习率也无法解决该问题,仅能延缓这一现象,现寻求解决建议。

以下是我实现的批量评估、反向传播、Sigmoid、Sigmoid导数及损失函数代码:

def Sigmoid(self, x):
    return 1.0 / (1.0 + np.exp(-x))

def PrimeSigmoid(self, x):
    return self.Sigmoid(x) * (1.0 - self.Sigmoid(x))

def _OutputCost(self, aResult, tResult):
    return [(a - t)**2 for a, t in zip(aResult, tResult)]

def _BackProp(self, tData, tGoal):
    derB = [np.zeros(b.shape) for b in self.gBiases]
    derW = [np.zeros(w.shape) for w in self.gWeights]

    activation = tData
    activations = [tData]
    zL = []
    for b, w in zip(self.gBiases, self.gWeights):
        z = np.dot(w, activation) + b
        zL.append(z)
        activation = self.Sigmoid(z)
        activations.append(activation)

    cost = self._OutputCost(activations[-1], tGoal)
    ps = self.PrimeSigmoid(zL[-1])
    deltas = cost * ps
    derB[-1] = deltas
    derW[-1] = np.dot(deltas, self.gWeights[-1])

    for l in range(2, self.gLayerCount):
        z = zL[-l]
        sp = self.PrimeSigmoid(z)
        deltas = np.dot(deltas, self.gBiases[-l + 1]) * sp
        derB[-l] = deltas
        derW[-l] = np.dot(deltas, self.gWeights[-l])
    return (derB, derW, np.average(cost, 0))

def _EvalBatch(self, batch, tSpeed):
    derB = [np.zeros(b.shape) for b in self.gBiases]
    derW = [np.zeros(w.shape) for w in self.gWeights]
    costL = []
    for d, g in batch:
        dDerB, dDerW, cost = self._BackProp(d, g)
        costL.append(cost)
        derB = [nb + dnb for nb, dnb in zip(derB, dDerB)]
        derW = [nw + dnw for nw, dnw in zip(derW, dDerW)]
    self.gBiases = [b + (tSpeed / len(batch)) * nb for b, nb in zip(self.gBiases, derB)]
    self.gWeights = [w + (tSpeed / len(batch)) * nw for w, nw in zip(self.gWeights, derW)]
    self.gCost = np.average(np.array(costL), 0)

问题根源与修正方案

你的代码存在几个核心错误,直接导致权重只增不减:

  1. 梯度下降方向完全错误
    梯度下降的核心是权重 = 权重 - 学习率 × 梯度,你当前的代码用+更新权重和偏置,不管梯度正负,权重只会持续增大。必须把更新逻辑中的加号改成减号:

    # 修正_EvalBatch中的更新代码
    self.gBiases = [b - (tSpeed / len(batch)) * nb for b, nb in zip(self.gBiases, derB)]
    self.gWeights = [w - (tSpeed / len(batch)) * nw for w, nw in zip(self.gWeights, derW)]
    
  2. 反向传播的梯度计算逻辑错误

    • 最后一层权重梯度:正确计算是输出层delta与前一层激活值的转置做矩阵乘法,你当前错误地用delta乘自身权重:
      # 替换_BackProp中最后一层derW的计算
      derW[-1] = np.dot(deltas, activations[-2].T)
      
    • 隐藏层delta计算:应该用当前层的权重转置乘以上一层的delta,再乘以Sigmoid导数,你错误地使用了偏置(gBiases)进行矩阵乘法:
      # 替换_BackProp中循环内的delta计算
      deltas = np.dot(self.gWeights[-l + 1].T, deltas) * sp
      
    • 隐藏层权重梯度:同样需要用当前层delta与前一层激活值的转置相乘,你当前用了错误的对象:
      # 替换_BackProp中循环内的derW计算
      derW[-l] = np.dot(deltas, activations[-l - 1].T)
      
  3. 损失函数输出格式错误
    你当前返回的是Python列表,与numpy数组相乘时可能出现维度或运算逻辑问题,改成直接用numpy数组运算:

    def _OutputCost(self, aResult, tResult):
        return (aResult - tResult)**2  # 直接使用numpy数组运算
    

额外优化建议

  • 初始权重不要用过大的值,建议采用正态分布初始化,比如np.random.normal(0, 1/np.sqrt(input_size), size=weight_shape),避免Sigmoid函数过早进入饱和区导致梯度消失。
  • 可以打印每一轮的损失值和权重变化,方便观察训练过程是否正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:14:54