为何我的神经网络val_accuracy始终保持不变?
解决二分类模型训练Loss为NaN、验证准确率固定的问题
核心问题定位
训练过程中出现NaN损失、验证集准确率固定,本质是数值不稳定或数据分布/预处理异常导致模型无法有效学习。结合你1000维特征的二分类场景,从以下方向逐一排查:
1. 数据层面排查与修复
清理异常值与特征归一化
首先确认TSV数据中是否存在缺失值、无穷大值,或特征量级差异过大:
# 检查训练集缺失值总数 print(train_data.isna().sum().sum()) # 查看特征统计分布,确认是否有极端值 print(train_data.describe())
- 若存在缺失值:用均值/中位数填充,或删除对应样本;
- 若特征量级差异大:确保归一化层用训练数据适配,或替换为标准化层:
normalize = keras.layers.Normalization(axis=-1) normalize.adapt(train_data) # 必须用训练数据适配归一化层
检查类别分布
验证集准确率固定为0.1786,大概率是验证集类别严重不平衡(比如100个样本中仅18个正例,随机猜测就能达到该准确率)。检查标签分布:
import numpy as np # 查看训练集标签分布 print(np.bincount(train_labels)) # 拆分验证集后查看分布 val_split_idx = int(len(train_data)*0.8) val_labels = train_labels[val_split_idx:] print(np.bincount(val_labels))
若类别不平衡,可通过以下方式处理:
- 过采样少数类/欠采样多数类;
- 在编译模型时添加类别权重:
model.compile( optimizer='adam', loss=keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'], class_weight={0: 1, 1: 5} # 根据实际分布调整权重比例 )
2. 模型结构与训练策略调整
解决梯度爆炸问题
1000维特征直接连接1000个神经元的Dense层,极易引发梯度爆炸:
- 添加梯度裁剪,限制梯度范围:
optimizer = keras.optimizers.Adam(clipnorm=1.0) # 按梯度范数裁剪 model.compile(optimizer=optimizer, loss=..., metrics=['accuracy']) - 缩小网络规模,从更简单的结构开始验证:
model = keras.Sequential([ keras.Input((1000,)), normalize, keras.layers.Dense(256, activation='relu', kernel_initializer='he_normal'), keras.layers.Dropout(0.2), # 添加Dropout抑制过拟合 keras.layers.Dense(64, activation='relu', kernel_initializer='he_normal'), keras.layers.Dense(1) ])
优化激活函数与权重初始化
- 替换ReLU为LeakyReLU,避免神经元死亡:
keras.layers.Dense(256, activation=keras.layers.LeakyReLU(alpha=0.1)) - 使用He初始化,适配ReLU类激活函数的权重分布:
keras.layers.Dense(256, activation='relu', kernel_initializer='he_normal')
3. 训练过程调试
- 降低学习率:Adam默认学习率0.001,尝试调小至
1e-4:optimizer = keras.optimizers.Adam(learning_rate=1e-4) - 监控训练初期loss:若前几个epoch就出现NaN,优先排查数据异常;若后期出现,重点解决梯度爆炸问题;
- 用
model.summary()确认网络参数规模,避免参数过多导致训练不稳定。
内容的提问来源于stack exchange,提问作者Ivan_Solaris
相关产品推荐
相关产品推荐

