MLP训练时Loss计算为NaN问题排查求助
MLP训练Loss始终为NaN的排查与解决
场景概述
- 模型架构:适配时序数据的Sequential结构MLP
- 隐藏层:1个含100节点的全连接层,输入维度为扁平化后的
10*2,激活函数为ReLU - 输出层:仅1节点的全连接层
- 编译配置:Adam优化器,MSE损失函数
- 隐藏层:1个含100节点的全连接层,输入维度为扁平化后的
- 数据细节:
- 形状:
X=(2581654, 10, 2),y=(2581654,) - 数据类型:已确认是
float64 - 问题现象:训练全程Loss输出为NaN,无有效数值更新
- 形状:
可能原因及对应解决方案
1. 数据中存在NaN/无穷值
即使数据类型正确,原始数据里的隐式NaN或无穷值会直接导致MSE计算失效,输出NaN。
排查与解决:
import numpy as np # 检查异常值 print("X含NaN:", np.isnan(X).any()) print("X含无穷值:", np.isinf(X).any()) print("y含NaN:", np.isnan(y).any()) print("y含无穷值:", np.isinf(y).any()) # 若存在异常值,用均值填充或删除样本 X = np.nan_to_num(X, nan=np.nanmean(X), posinf=np.nanmean(X), neginf=np.nanmean(X)) y = np.nan_to_num(y, nan=np.nanmean(y), posinf=np.nanmean(y), neginf=np.nanmean(y))
2. 特征未做归一化/标准化
你的输入是双特征,第一个特征数值范围65-72,第二个0.5-3.8,特征间范围差异大;输出y的数值在62-225之间,和输入范围不匹配。这种差异会导致梯度爆炸/消失,引发NaN。单变量场景无问题是因为不存在跨特征的范围差异。
解决:
对输入和输出做标准化处理:
from sklearn.preprocessing import StandardScaler # 输入扁平化后标准化 scaler_X = StandardScaler() X_flat = X.reshape((X.shape[0], -1)) X_scaled = scaler_X.fit_transform(X_flat) # 输出标准化 scaler_y = StandardScaler() y_scaled = scaler_y.fit_transform(y.reshape(-1, 1)).flatten() # 用标准化后的数据训练 model.fit(X_scaled, y_scaled, epochs=100, verbose='auto') # 预测时反转换回原始尺度 y_pred = model.predict(X_scaled) y_pred = scaler_y.inverse_transform(y_pred)
3. 学习率过高
Adam默认学习率0.001,若数据分布特殊,过高的学习率会导致参数更新幅度过大,出现NaN。
解决:
降低学习率重新编译模型:
from tensorflow.keras.optimizers import Adam model.compile(optimizer=Adam(learning_rate=1e-4), loss='mse')
4. 权重初始化过于激进
虽然Dense层默认初始化一般没问题,但极端情况下过大的初始权重会导致ReLU激活值异常,进而引发NaN。
解决:
改用更保守的初始化方式:
model = Sequential() model.add(Dense(100, activation='relu', input_dim=n_input, kernel_initializer='he_normal')) model.add(Dense(1, kernel_initializer='he_normal')) model.compile(optimizer='adam', loss='mse')
5. 批量大小适配问题
样本量过大时,默认批量大小可能导致损失计算时异常值的影响被放大,可尝试调整批量大小。
解决:
model.fit(X_scaled, y_scaled, epochs=100, batch_size=64, verbose='auto')
内容的提问来源于stack exchange,提问作者HOSSAM
相关产品推荐
相关产品推荐

