TensorFlow模型训练结果异常,500万轮未拟合如何解决?
模型训练异常的修正方案
1. 数据层面的核心问题与修正
- 输入维度完全搞反:原代码里
input_data是[2,12]的结构(2个特征,12个样本),但TensorFlow要求输入格式是[样本数, 特征数],也就是每个样本是[温度, 湿度]的组合,必须把数组转成[[温度1,湿度1], [温度2,湿度2], ...]的12行2列结构,否则模型会把2个特征当成2个样本,完全无法学习。 - 异常数据必须处理:温度数据里的
281是明显错误值(正常环境温度不可能这么高),直接保留会彻底打乱模型的拟合逻辑,建议修正为合理值(比如推测是28.1的笔误)或直接删除该样本。 - 特征必须做归一化:温度(范围-2.4281)和湿度(范围5274)数值跨度差异极大,不做归一化会导致模型梯度更新失衡,难以收敛。建议把特征缩放到
[0,1]区间或做Z-score标准化。
2. 模型结构的优化
原模型只有1个神经元的全连接层,结构过于简单,无法拟合温度、湿度和功率之间的非线性关联。可以增加隐藏层提升模型表达能力:
var X = tf.input({ shape: [2] }); // 增加两层带ReLU激活的隐藏层 var hidden1 = tf.layers.dense({ units: 8, activation: 'relu' }).apply(X); var hidden2 = tf.layers.dense({ units: 4, activation: 'relu' }).apply(hidden1); var Y = tf.layers.dense({ units: 1 }).apply(hidden2); var model = tf.model({ inputs: X, outputs: Y });
3. 训练配置的合理调整
- 训练轮数完全没必要500万:不仅浪费算力,还会导致过拟合。建议设置早停回调,当验证集损失连续多轮不下降时自动停止训练,同时保留最优权重。
- 损失函数写法修正:原代码直接传
tf.losses.meanSquaredError存在调用风险,改用字符串'meanSquaredError'更稳妥,也可以指定优化器的学习率提升收敛效率。
完整修正后的代码示例
// 修正输入结构,同时处理异常值(假设281是28.1的笔误) var input_data = [ [-2.4, 58], [2.7, 56], [9, 63], [14.2, 54], [17.1, 68], [22.8, 73], [28.1, 71], [25.9, 74], [22.6, 71], [15.6, 70], [8.2, 68], [0.6, 62] ]; var power_data = [239,224,189,189,179,192,243,317,224,190,189,202]; // 特征归一化工具函数:缩放到[0,1]区间 function normalizeData(data) { const tensor = tf.tensor2d(data); const min = tensor.min(0); const max = tensor.max(0); const normalized = tensor.sub(min).div(max.sub(min)); return { normalized, min, max }; } // 处理输入输出张量,输出要转成[样本数,1]的二维格式 const { normalized: reason_data, min: inputMin, max: inputMax } = normalizeData(input_data); const result_data = tf.tensor2d(power_data, [power_data.length, 1]); // 构建带隐藏层的模型 var X = tf.input({ shape: [2] }); var hidden1 = tf.layers.dense({ units: 8, activation: 'relu' }).apply(X); var hidden2 = tf.layers.dense({ units: 4, activation: 'relu' }).apply(hidden1); var Y = tf.layers.dense({ units: 1 }).apply(hidden2); var model = tf.model({ inputs: X, outputs: Y }); // 编译模型:指定学习率,用字符串形式的损失函数 var compileParam = { optimizer: tf.train.adam(0.001), loss: 'meanSquaredError' }; model.compile(compileParam); // 训练配置:早停+验证集,每50轮打印一次日志 var fitParam = { epochs: 1000, validationSplit: 0.2, // 拿20%数据做验证 callbacks: [ tf.callbacks.earlyStopping({ monitor: 'val_loss', patience: 20, restoreBestWeights: true }), { onEpochEnd: function (epoch, logs) { if (epoch % 50 === 0) { console.log(`epoch ${epoch} - loss: ${logs.loss.toFixed(4)} - val_loss: ${logs.val_loss.toFixed(4)} - RMSE: ${Math.sqrt(logs.loss).toFixed(2)}`); } } } ] }; // 启动训练并查看结果 model.fit(reason_data, result_data, fitParam).then(function (result) { var final_result = model.predict(reason_data); console.log('预测结果:'); final_result.print(); console.log('真实结果:'); result_data.print(); model.save('file:///path/'); });
内容的提问来源于stack exchange,提问作者user2458645
相关产品推荐
相关产品推荐

