Keras模型训练出现NaN Loss问题求助(附代码)
多分类任务Loss变NaN的调试方案
问题根源及修复步骤:
输出层配置错误
你做的是4分类任务,输出层必须输出对应4个类别的概率分布,当前用Dense(1, activation="relu")完全不符合要求:relu无法输出概率分布,和sparse_categorical_crossentropy损失函数不兼容,计算时会直接出现NaN。必须改成Dense(4, activation="softmax")。输入数据未标准化
你的特征值量级差异极大(比如有-1.77这种量级,也有1e-03的小值),未标准化会导致梯度爆炸,直接让Loss变成NaN。必须对训练集和测试集做标准化处理,注意测试集要使用训练集的均值和标准差,避免数据泄露。标签维度冗余
你的标签values是二维数组(shape=(694,1)),但sparse_categorical_crossentropy要求标签是一维数组(shape=(694,)),需要做降维处理。Dropout层参数多余
Dropout层不需要重复写input_shape,只需要接在上一层输出后面即可。
修改后的完整代码:
import pyreadr from sklearn.model_selection import train_test_split import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers import numpy as np from sklearn.preprocessing import StandardScaler # 读取并处理数据 result = pyreadr.read_r("/home/ignat/Downloads/Telegram Desktop/TMS_coefficients.RData") dataset = [] values = [] for i in range(694): dataset.append((result['tms.coef']['bs0'][i], result['tms.coef']['bs'][i], result['tms.coef']['bi0'][i], result['tms.coef']['bi'][i], result['tms.coef']['b0'][i], result['tms.coef']['b1'][i], result['tms.coef']['b2'][i], result['tms.coef']['a0'][i], result['tms.coef']['a1'][i])) # 处理标签,直接生成一维数组 y_label = 0.0 if result['tms.coef']['Y'][i] == "НС" \ else 1.0 if result['tms.coef']['Y'][i] == "AD" \ else 2.0 if result['tms.coef']['Y'][i] == "DLB" \ else 3.0 values.append(y_label) dataset = np.array(dataset, dtype="float") values = np.array(values, dtype="float") # 拆分数据集 (trainX, testX, trainY, testY) = train_test_split(dataset, values, test_size=0.25, random_state=42) # 标准化输入数据 scaler = StandardScaler() trainX = scaler.fit_transform(trainX) testX = scaler.transform(testX) # 构建模型 visible = layers.Input(shape=(9,)) drop1 = layers.Dropout(0.5)(visible) hidden1 = layers.Dense(32, activation="relu")(drop1) drop2 = layers.Dropout(0.5)(hidden1) # 输出层改为4个神经元+softmax output = layers.Dense(4, activation="softmax")(drop2) model = tf.keras.Model(inputs=visible, outputs=output) # 编译模型 model.compile(optimizer=tf.keras.optimizers.Adam(0.001), # 适当调小学习率避免震荡 loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(trainX, trainY, validation_data=(testX, testY), epochs=100) model.save('my_model') # 预测示例 for i in range(1, 10): # predict返回每个类别的概率,取argmax得到预测类别 pred = np.argmax(model.predict(dataset[i-1:i], verbose=0), axis=1) print(f"预测类别: {pred[0]}, 真实类别: {values[-i]}")
内容的提问来源于stack exchange,提问作者ishao
相关产品推荐
相关产品推荐

