PyTorch ANN回归模型:不同输入输出相同预测问题求助
解决PyTorch ANN输出全相同预测值的问题
问题诊断
你的模型对所有输入输出相同预测值,核心原因集中在以下几点:
- 缺失激活函数依赖:代码中使用
F.relu但未导入torch.nn.functional,导致无法正常激活神经元 - 输入特征未标准化:不同特征(如年龄、身高、运动时长)数值范围差异过大,模型梯度更新异常,容易陷入预测均值的局部最优
- 模型与优化器适配性差:3层隐藏层搭配SGD优化器,在未归一化的数据上难以有效更新权重
- 全量数据训练:直接用所有数据训练,模型易快速拟合整体均值而非学习特征关联
修复代码与步骤
1. 补全缺失库导入
import numpy as np import pandas as pd import torch import torch.nn as nn import torch.nn.functional as F # 新增:导入ReLU依赖
2. 数据预处理:添加特征标准化
calories = pd.read_csv("calories.csv") excercise = pd.read_csv("exercise.csv") df = pd.concat([excercise,calories],axis=1,join="outer") df = df.drop('User_ID',axis=1) data = pd.get_dummies(df,drop_first=True) # 新增:标准化特征,消除量纲差异 from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(data.drop("Calories",axis=1)) X = torch.tensor(X_scaled).float() y = torch.tensor(data['Calories'],dtype=torch.float).reshape(-1,1)
3. 调整模型结构与优化器
class Ann_Predictor(nn.Module): def __init__(self, n_layers, n_units): super().__init__() self.n_layers = n_layers self.layers = nn.ModuleDict() self.layers["input"] = nn.Linear(7,n_units) for i in range(n_layers): self.layers[f"hidden{i}"] = nn.Linear(n_units,n_units) self.layers["output"] = nn.Linear(n_units,1) def forward(self, x): # 修正:输入层后直接添加ReLU激活 x = F.relu(self.layers['input'](x)) for i in range(self.n_layers): x = F.relu(self.layers[f"hidden{i}"](x)) x = self.layers["output"](x) return x def create_model(): ann = Ann_Predictor(2, 16) # 简化隐藏层数量,增加单元数提升拟合能力 loss_func = nn.MSELoss() learning_rate = 0.001 optimizer = torch.optim.Adam(ann.parameters(), lr=learning_rate) # 改用Adam自适应优化器 return ann, loss_func, optimizer
4. 拆分数据集并优化训练流程
from sklearn.model_selection import train_test_split # 新增:拆分训练/验证集 # 拆分数据,避免全量训练拟合均值 X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42) numepochs = 1000 train_losses = torch.zeros(numepochs) val_losses = torch.zeros(numepochs) ann, loss_func, optimizer = create_model() for epoch in range(numepochs): # 训练模式 ann.train() y_hat = ann(X_train) loss = loss_func(y_hat, y_train) train_losses[epoch] = loss optimizer.zero_grad() loss.backward() optimizer.step() # 验证模式,监控泛化能力 ann.eval() with torch.no_grad(): val_y_hat = ann(X_val) val_loss = loss_func(val_y_hat, y_val) val_losses[epoch] = val_loss # 每50轮打印训练日志 if (epoch+1) % 50 == 0: print(f"Epoch {epoch+1}/{numepochs}, Train Loss: {loss.item():.2f}, Val Loss: {val_loss.item():.2f}") # 生成预测结果 ann.eval() with torch.no_grad(): predictions = ann(X) print(predictions[:10]) # 打印前10个预测值验证差异
核心修复逻辑说明
- 标准化:统一特征尺度,确保梯度更新方向稳定,避免大数值特征主导训练
- 激活函数修正:输入层后添加ReLU,让模型具备学习非线性特征的能力
- 优化器替换:Adam自带自适应学习率,比SGD更适合处理复杂数据和模型
- 数据集拆分:验证集可监控模型是否过拟合,避免全量数据训练导致的均值拟合
内容的提问来源于stack exchange,提问作者Ethan Kho
相关产品推荐
相关产品推荐

