Python神经网络训练停滞求助:大卫之星点分类任务
大卫之星坐标分类神经网络训练问题解决方案
针对你开发的2层/4层神经网络训练仅首轮有效、后续权重更新停滞的问题,以下是具体的修复建议:
1. 输入数据归一化
你的输入坐标是0-1000的数值,直接传入sigmoid会导致激活函数饱和(sigmoid在|x|>5时梯度趋近于0),反向传播时梯度消失,权重无法更新。
修改方案:将输入缩放到0-1区间:
def normalize_points(points): return np.array(points) / 1000.0 # 把0-1000的坐标缩放到0-1 # 生成数据后执行归一化 points = set_of_points(1000) normalized_points = normalize_points(points) points_train = normalized_points[:800] # 增大训练集 points_test = normalized_points[800:] labels_train = np.array(labels[:800]) labels_test = np.array(labels[800:])
2. 修正权重初始化
4层网络的权重用np.random.randint(0,1000)生成了过大的初始值,导致前向传播的输入直接触发sigmoid饱和,梯度消失。
修改方案:使用小范围正态分布或Xavier初始化:
# 替换NeuralNetwork类__init__中的权重初始化代码 self.weights = np.random.normal(0, 0.1, (2, 1)) # 2层网络权重 # 4层网络权重(Xavier初始化,适合sigmoid) def xavier_init(in_dim, out_dim): scale = np.sqrt(1.0 / (in_dim + out_dim)) return np.random.uniform(-scale, scale, (in_dim, out_dim)) self.weights1 = xavier_init(2, 6) self.weights2 = xavier_init(6, 2) self.weights3 = xavier_init(2, 1)
3. 修复反向传播逻辑
2层网络反向传播
原代码手动循环易出错,改用向量运算简化:
def back_prop1(self, learning_rate, output, label, input): error = output - label delta = error * sigmoid_derivative(output) # 向量形式更新权重,避免循环错误 self.weights -= learning_rate * delta * input.reshape(-1, 1)
4层网络反向传播
原代码存在矩阵维度错误、中间值复用初始化数据、循环逻辑混乱的问题,修复后如下:
# 先修改forward2,保存前向传播的中间结果 def forward2(self, input): self.z1 = np.dot(input, self.weights1) self.a1 = sigmoid(self.z1) self.z2 = np.dot(self.a1, self.weights2) self.a2 = sigmoid(self.z2) self.z3 = np.dot(self.a2, self.weights3) self.a3 = sigmoid(self.z3) return self.a3 # 修正反向传播 def back_prop2(self, learning_rate, output, label, input): error = output - label # 输出层梯度 delta3 = error * sigmoid_derivative(output) self.weights3 -= learning_rate * self.a2.reshape(-1, 1) * delta3 # 第二层梯度 delta2 = np.dot(delta3, self.weights3.T) * sigmoid_derivative(self.a2) self.weights2 -= learning_rate * self.a1.reshape(-1, 1) * delta2 # 第一层梯度 delta1 = np.dot(delta2, self.weights2.T) * sigmoid_derivative(self.a1) self.weights1 -= learning_rate * input.reshape(-1, 1) * delta1
4. 修正预测阈值
原test函数中用output > 500/output > 800作为判断条件完全错误——sigmoid的输出范围是0-1,导致预测全为0,准确率固定。
修改方案:
# test函数中替换预测判断逻辑 # 2层网络 if output > 0.5: prediction = 1 else: prediction = 0 # 4层网络同理 if output > 0.5: prediction = 1 else: prediction = 0
5. 调整训练参数
- 增大训练集:原训练集仅10个样本,模型无法学习到足够模式,改为800个样本(如上)。
- 降低学习率:原learning_rate=26过大,会导致权重震荡或发散,改为
learning_rate=0.1,可根据训练情况微调。 - 打乱训练集:每轮epoch前打乱样本顺序,避免模型陷入局部最优:
def train(network, inputs, labels, epochs, learning_rate, quest): loss = [] for j in range(epochs): # 打乱训练集顺序 perm = np.random.permutation(len(inputs)) shuffled_inputs = inputs[perm] shuffled_labels = labels[perm] errors_in_epoch = [] # 后续用shuffled_inputs和shuffled_labels遍历训练 # ...(原训练逻辑不变,替换样本集即可)
内容的提问来源于stack exchange,提问作者Ido Hass
相关产品推荐
相关产品推荐

