模型实际已正常训练,但评估时使用了错误的x取值范围([0,1)而非[-2,2]),导致预测曲线严重失真,误判为“未学习”。
模型实际已正常训练,但评估时使用了错误的x取值范围([0,1)而非[-2,2]),导致预测曲线严重失真,误判为“未学习”。
在PyTorch回归任务中,模型“不学习”的表象往往并非源于训练逻辑缺陷,而更常来自**数据流的一致性断裂**——尤其是训练与推理阶段输入分布不匹配。您提供的代码中,`start_train()` 的训练数据正确覆盖区间 $[-2, 2]$(通过 `TestDataset.__getitem__` 构造 `x = func_min + index * unit`),但后续 `comparison()` 函数却完全脱离该分布:# ❌ 错误:x 被硬编码为 [0, 1) 区间(i / sample_num),与训练域严重偏离
for i in range(sample_num):
train_feature = tensor([0, 0, 0, 0, 0, i / sample_num], dtype=float32)
这导致模型在从未见过的、极小且偏置的输入区域(接近0)上被测试,而神经网络(尤其含多层Tanh)在输入远离训练域时极易输出饱和、平坦的响应——恰好对应您观察到的“flat line”现象。损失曲线缓慢下降也符合此解释:模型确实在拟合 $y=x^2$,但评估方式掩盖了其真实能力。
✅ 正确做法是严格复现训练时的x采样逻辑。修改 comparison() 如下:
def comparison(model: ANN, sample_num: int) -> None:
model.eval()
prediction_list = []
target_list = generate_targets(sample_num) # 复用相同生成逻辑
# ✅ 正确:与 TestDataset.__getitem__ 保持完全一致的x构造方式
func_max, func_min = 2.0, -2.0
unit = (func_max - func_min) / sample_num
for i in range(sample_num):
x = func_min + i * unit # 关键修正:x ∈ [-2, 2]
train_feature = tensor([0, 0, 0, 0, 0, x], dtype=float32)
prediction = model(train_feature)
prediction_list.append(prediction.item())
# 绘图x轴坐标也需同步修正为 [-2, 2]
x_list = [func_min + i * unit for i in range(sample_num)]
plt.plot(x_list, target_list, marker='o', label='Target (y=x²)')
plt.plot(x_list, prediction_list, marker='x', label='Prediction')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Prediction vs Target (x ∈ [-2, 2])')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('Debugger_Comparison_Fixed.png')
plt.close()
此外,建议补充以下最佳实践以增强鲁棒性:
- 启用梯度检查:在训练循环中加入 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0) 防止梯度爆炸;
- 验证数据一致性:打印 train_feature[:, -1].min().item() 和 .max().item() 确认训练x范围;
- 使用 torch.no_grad():comparison() 中明确包裹前向计算,避免意外梯度累积;
- 初始化诊断:首次迭代前用 model(torch.zeros(1, 6)) 检查初始输出是否合理(如非全零或极大值)。
修正后,您将看到预测曲线紧密贴合 $y=x^2$ 抛物线——这证实模型本身具备学习能力,问题纯粹出在评估环节的数据对齐缺失。记住:训练与推理的输入空间必须严格同构,这是深度学习调试的第一铁律。











