神经网络隐藏层节点数超30时输出全为1无法正常工作问题
问题成因
- 权重初始化不合理:当前使用
np.random.random()生成0~1区间的随机权重,随着隐藏层节点数增加,输入与权重矩阵的点积结果方差会同步增大,当节点数≥30时,点积结果很容易落入sigmoid函数的饱和区,此时sigmoid输出趋近于1,导数值趋近于0,发生梯度消失,参数更新完全失效。 - 缺少学习率控制:权重更新时未设置学习率约束步长,隐藏层节点数较大时计算得到的梯度累加值远高于小节点场景,会直接将权重参数推到极端值,最终前向传播时所有输出都被sigmoid函数映射为1。
修复方案
调整权重初始化逻辑为适配sigmoid的Xavier初始化,添加学习率控制参数,修复后代码如下:
import numpy as np l1, l2, l3 = 0, 0, 0 lr = 0.1 # 新增学习率控制更新步长 hidden_size = 50 # 隐藏层节点数可自由调整,≥30也可正常运行 x = [[0, 1, 1], [1, 0, 0], [0, 0, 0], [1, 1, 0]] y = [[1], [0], [0], [1]] # 修改权重初始化逻辑,避免初始点积结果过大进入sigmoid饱和区 w0 = np.random.randn(3, hidden_size) * np.sqrt(1 / 3) w1 = np.random.randn(hidden_size, 1) * np.sqrt(1 / hidden_size) def predict(x): global l0, l1, l2 l0 = np.array(x) l1 = np.array(sigmoid(np.dot(l0, w0))) l2 = np.array(sigmoid(np.dot(l1, w1))) return l2 def train(iterations): global w0, w1 for iteration in range(iterations): error_2 = y - predict(x) delta_2 = error_2 * sigmoid(l2, True) error_1 = np.dot(delta_2, w1.T) delta_1 = error_1 * sigmoid(l1, True) # 权重更新引入学习率,避免参数更新幅度过大 w1 += lr * np.dot(l1.T, delta_2) w0 += lr * np.dot(l0.T, delta_1) def sigmoid(x, deriv = False): if(deriv): return x*(1-x) return 1/(1+np.exp(-x)) train(1000) # 可适当增加迭代次数保证收敛 print(predict(x))
修复后隐藏层节点数调整到100也可以正常收敛输出预期结果。
内容的提问来源于stack exchange,提问作者Gavin
相关产品推荐
相关产品推荐

