表格数据Autoencoder训练损失异常及欠拟合问题求助
分析你的表格数据自编码器训练问题
首先明确:表格数据集完全可以训练有效的自编码器,你的问题不是数据类型导致的,而是几个关键训练设置和模型结构细节没踩对,咱们一步步拆解:
1. 损失函数选择错误是核心问题
你用了MeanAbsolutePercentageError()(MAPE)作为损失函数,但你的数据已经做了归一化处理(数值应该在0-1左右)。MAPE的计算公式是:
MAPE = 100 * |(y_true - y_pred)/y_true|
当y_true接近0时,这个值会直接爆炸(比如y_true=0.001,预测差0.001的话,MAPE就是100%),这就是你看到损失高达几万的直接原因。
解决方案:换成更适合归一化数据的损失函数,比如MeanSquaredError()(MSE)或者MeanAbsoluteError()(MAE),这两个损失对小范围数值的拟合更稳定。
2. 输出层激活函数不匹配输入数据分布
你最后一层用了LeakyReLU,但归一化后的输入数据应该是在0-1区间(假设你用的是MinMaxScaler),而LeakyReLU的输出范围是(-∞, +∞),这会导致模型输出的数值和输入分布不匹配,进一步放大损失。
解决方案:如果输入是0-1归一化,输出层改用sigmoid激活函数(把输出限制在0-1);如果是标准化(均值0方差1),改用linear激活。
3. 模型结构与训练参数的小问题
- Batch Size过大:你的数据集总样本量是1460,而你设置的
batch_size=3000,这相当于每次训练都把整个训练集喂进去,模型更新频率极低,收敛速度会很慢。建议调小到64、128这类常规值。 - 激活函数组合可能导致梯度问题:你交替使用
tanh和LeakyReLU,tanh在输入绝对值较大时梯度会趋近于0,可能导致梯度消失,影响模型学习。可以尝试全用LeakyReLU,或者减少tanh的使用。 - 正则化强度可能不合适:你用的
regularizers.l1(10e-5)强度太弱,几乎起不到正则化作用;如果担心过拟合,可以适当调高(比如1e-4),或者换成L2正则化。
修改后的代码示例
这里给你调整了关键部分的代码:
from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense from tensorflow.keras.callbacks import ModelCheckpoint, TensorBoard from tensorflow.keras import regularizers, losses import tensorflow as tf input_dim = X.shape[1] encoding_dim = 30 input_layer = Input(shape=(input_dim, )) # 调整激活函数,全用LeakyReLU避免梯度消失 encoder = Dense(int(input_dim / 2), activation=tf.keras.layers.LeakyReLU(alpha=0.01), activity_regularizer=regularizers.l2(1e-4))(input_layer) encoder = Dense(int(input_dim / 2), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(encoder) encoder = Dense(int(input_dim / 4), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(encoder) encoder = Dense(int(input_dim / 4), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(encoder) encoder = Dense(encoding_dim, activation=tf.keras.layers.LeakyReLU(alpha=0.01))(encoder) # 解码器同样调整激活函数 decoder = Dense(int(input_dim / 4), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(encoder) decoder = Dense(int(input_dim / 4), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(decoder) decoder = Dense(int(input_dim / 2), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(decoder) decoder = Dense(int(input_dim / 2), activation=tf.keras.layers.LeakyReLU(alpha=0.01))(decoder) # 输出层用sigmoid匹配0-1归一化的输入 output_layer = Dense(input_dim, activation='sigmoid')(decoder) autoencoder = Model(inputs=input_layer, outputs=output_layer) # 换成MSE损失 autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError(), metrics=["mae"]) # 调小batch_size history = autoencoder.fit(X_train, X_train, epochs=100, batch_size=128, shuffle=True, validation_data=(X_test, X_test), verbose=1).history
额外小建议
- 确认你的归一化是否正确:如果用的是
StandardScaler,输出层要换成linear激活,同时损失函数用MSE/MAE依然合适。 - 可以尝试调整编码维度:比如把
encoding_dim调到50或者20,看看模型拟合效果的变化,找到最优的压缩维度。
内容的提问来源于stack exchange,提问作者ocdelightful
相关产品推荐
相关产品推荐

