求助:Python实现的三层神经网络无法正常训练,输出卡在0.5
排查你的三层神经网络训练问题
看起来你的模型输出卡在0.5是因为反向传播和权重更新的逻辑有好几处关键错误,我来一步步帮你梳理:
核心错误点分析
sigmoid导数的使用错误:
你定义的reduce函数其实是sigmoid的导数公式,但你传入的参数是误差值(比如l2_err),而不是sigmoid的激活输出(l2或l1)。sigmoid的导数正确计算方式是σ'(x) = σ(x)*(1-σ(x)),这里的σ(x)是激活后的结果,不是误差。反向传播的误差传递逻辑错误:
- 计算
l2_delta时,应该是误差乘以sigmoid导数,也就是l2_err * reduce(l2),而不是直接对l2_err用reduce。 - 计算
l1_err时,应该是当前层的delta通过权重矩阵反向传递到前一层,正确的矩阵乘法是l2_delta.dot(syn1.T),而不是syn1*l2_delta(这会导致维度不匹配且逻辑错误)。 l1_delta同样需要用l1_err * reduce(l1),而不是对l1_err用reduce。
- 计算
权重更新的逻辑错误:
- 更新
syn1时,应该用前一层(l1)的激活输出乘以当前层的delta(l2_delta),而不是用l0[i](输入层)来计算,正确的更新是syn1 += l1.reshape(-1,1) * l2_delta。 - 更新
syn0时,应该用输入层l0[i]的转置乘以l1_delta,但你之前的转置操作完全没必要,而且计算对象错误。
- 更新
修正后的代码
import numpy as np def sigmoid(x): return 1/(1+np.exp(-x)) def sigmoid_derivative(x): # 重命名函数更清晰,参数是sigmoid的输出 return x*(1-x) # 输入数据,统一转成二维数组更方便 l0 = np.array([ [1,1,0,0], [1,0,1,0], [1,1,1,0], [0,1,0,1], [0,0,1,0] ]) # 输出转成二维数组,匹配后续计算维度 output = np.array([[0,1,1,0,1]]).T # 权重初始化,这里可以用小范围随机值,比0-1更稳定 syn0 = 2*np.random.random((4,4)) - 1 syn1 = 2*np.random.random((4,1)) - 1 for epoch in range(10000): # 增加迭代次数,确保收敛 # 前向传播 l1 = sigmoid(np.dot(l0, syn0)) l2 = sigmoid(np.dot(l1, syn1)) # 反向传播 l2_err = output - l2 l2_delta = l2_err * sigmoid_derivative(l2) l1_err = np.dot(l2_delta, syn1.T) l1_delta = l1_err * sigmoid_derivative(l1) # 更新权重 syn1 += np.dot(l1.T, l2_delta) syn0 += np.dot(l0.T, l1_delta) # 打印最终所有样本的输出 print("最终输出:") print(l2)
额外优化说明
- 数据格式统一:把输入和输出都转成numpy二维数组,避免逐个样本循环(当然你也可以保留逐个样本的方式,但批量计算更高效)。
- 函数重命名:把
reduce改成sigmoid_derivative,语义更清晰,避免混淆。 - 权重初始化优化:用
2*np.random.random(...) -1把权重初始化为-1到1之间的随机值,比0-1的初始化更有利于梯度下降。 - 增加迭代次数:1000次可能不够收敛,改成10000次可以让模型更好地学习。
现在运行修正后的代码,你会看到输出逐渐接近目标值,不再卡在0.5了。
内容的提问来源于stack exchange,提问作者Luca Gervasi
相关产品推荐
相关产品推荐

