如何在TensorFlow.js中以日期为X序列实现线性回归?
问题根源与解决方案
为什么会返回NaN?
你的代码出现NaN的核心原因是输入数值量级过大:日期转成getTime()后是1e12级别的超大数,而输出是个位数,这种极端的量级差异会导致模型训练时权重更新异常,最终引发数值溢出,出现NaN。
当你用1、2、3这类小数值做输入时,输入和输出的量级匹配,模型的权重更新能正常进行,所以不会出现NaN,只是因为单神经元模型能力有限,预测结果不够准确。
修复方案
你需要对输入的日期数据做量级缩放,把超大的时间戳转换成小数值,常见的两种方式:
方式1:转换为相对天数(最适合你的场景)
以第一个日期为基准,计算后续日期与它的天数差,这样输入会变成0、1、2、3、4这类小数值,和你之前的乘法表示例量级一致:
const model = tf.sequential() model.add(tf.layers.dense({ units: 1, inputShape: [1] })) // 输入是小数值,可适当调大学习率加速收敛 model.compile({ loss: 'meanSquaredError', optimizer: tf.train.sgd(0.001) }) // 转换为相对天数,以第一个日期为基准 const baseDate = parseISO('2023-01-01'); const inputs = ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05'].map(dateStr => { const date = parseISO(dateStr); // 计算天数差 return (date - baseDate) / (1000 * 60 * 60 * 24); }) const outputs = [2, 4, 5, 8, 10] const xs = tf.tensor2d(inputs, [inputs.length, 1]) const ys = tf.tensor2d(outputs, [outputs.length, 1]) await model.fit(xs, ys, { epochs: 200 }) // 预测2023-01-06,对应的天数差是5 const predictions = [5] const result = model.predict(tf.tensor2d(predictions, [predictions.length, 1])).dataSync(); console.log(result); // 输出合理的预测值
方式2:对时间戳做归一化(缩放至0-1区间)
如果需要保留时间戳的原始时序信息,可以将其缩放到0-1的范围,避免量级问题:
const model = tf.sequential() model.add(tf.layers.dense({ units: 1, inputShape: [1] })) model.compile({ loss: 'meanSquaredError', optimizer: tf.train.sgd(0.001) }) const inputDates = ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05']; const timestamps = inputDates.map(x => parseISO(x).getTime()); // 归一化:将时间戳缩放到0-1区间 const minTs = Math.min(...timestamps); const maxTs = Math.max(...timestamps); const inputs = timestamps.map(ts => (ts - minTs) / (maxTs - minTs)); const outputs = [2, 4, 5, 8, 10] const xs = tf.tensor2d(inputs, [inputs.length, 1]) const ys = tf.tensor2d(outputs, [outputs.length, 1]) await model.fit(xs, ys, { epochs: 200 }) // 预测下一天,先转换时间戳再归一化 const nextTs = parseISO('2023-01-06').getTime(); const normalizedNext = (nextTs - minTs) / (maxTs - minTs); const predictions = [normalizedNext] const result = model.predict(tf.tensor2d(predictions, [predictions.length, 1])).dataSync(); console.log(result);
后续优化建议
- 你的最终目标是预测累积值,单神经元的全连接层能力有限,后续可以尝试使用LSTM这类专门处理时间序列的模型,能更好地捕捉时序规律。
- 训练时可以增加
epochs数量(比如500-1000),或者调整学习率,观察模型收敛情况。
内容的提问来源于stack exchange,提问作者Hard-Boiled Wonderland
相关产品推荐
相关产品推荐

