You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TensorFlow.js求解方程系数时损失趋于无穷并出现NaN问题求助

解决TensorFlow.js拟合三次方程时损失爆NaN的问题

嘿,我之前也碰到过类似的情况,咱们一步步来排查你遇到的问题:

首先看你的代码片段和描述,损失快速趋近无穷然后变成NaN,主要有几个常见的原因,我给你逐一分析并给出解决办法:

1. 输入/输出数值范围过大,引发梯度爆炸

你的输入xs是从-100到99的整数,计算三次方后数值会达到百万级别(比如99³≈970299),对应的ys数值也会非常大。模型在反向传播计算梯度时,这么大的数值会导致梯度急剧膨胀,权重更新一步就可能溢出变成NaN。

解决办法:归一化数据

把输入和输出都缩放到小范围(比如[-1,1]或[0,1]),示例代码如下:

// 归一化xs到[-1, 1]区间
const minX = Math.min(...xs);
const maxX = Math.max(...xs);
const normalizedXs = xs.map(x => (x - minX) / (maxX - minX) * 2 - 1);

// 归一化ys到[0, 1]区间
const minY = Math.min(...ys);
const maxY = Math.max(...ys);
const normalizedYs = ys.map(y => (y - minY) / (maxY - minY));

之后用normalizedXs和normalizedYs来训练模型,训练完成后如果需要还原真实系数,再做反归一化处理即可。

2. 模型结构无法表达三次函数

看你代码的隐含逻辑,应该是想用模型拟合a*x³ + b*x² + c*x + d,但如果你的模型是单层全连接(比如tf.layers.dense({units:1, inputShape:[1]})),这本质是个线性模型,只能拟合y = w*x + b这样的一次函数,完全没有能力表达三次多项式的非线性关系。这种情况下模型根本无法收敛,损失会越来越大直到溢出。

解决办法:构造多项式特征或使用非线性模型

方案一:手动构造多项式特征(推荐,更高效)

把每个输入x转换成包含x、x²、x³的特征向量,这样模型就能学习到三次多项式的系数:

// 构造特征:每个样本是 [x, x², x³]
const features = normalizedXs.map(x => [x, Math.pow(x, 2), Math.pow(x, 3)]);

// 构建模型,输入形状对应3个特征
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [3]}));

此时模型的输出就是w1*x + w2*x² + w3*x³ + b,正好对应你要拟合的三次方程(注意归一化会影响系数的对应关系,后续需要反归一化还原真实值)。

方案二:使用带非线性激活的神经网络

如果不想手动构造特征,可以用多层网络加非线性激活函数来拟合:

const model = tf.sequential();
model.add(tf.layers.dense({units: 16, inputShape: [1], activation: 'relu'}));
model.add(tf.layers.dense({units: 16, activation: 'relu'}));
model.add(tf.layers.dense({units: 1}));

3. 学习率设置过高

如果学习率太大,哪怕数据归一化了,权重更新的步长也可能超出合理范围,导致损失突然飙升到NaN。建议降低学习率,比如:

// 把Adam优化器的学习率从默认的0.01调低到0.001甚至更小
const optimizer = tf.train.adam(0.001);
model.compile({optimizer: optimizer, loss: 'meanSquaredError'});

4. 检查代码完整性

你的代码片段里ys.push(...)的部分没写完,要确保没有语法错误,比如应该补全闭合的括号:

ys.push(aReal*Math.pow(i, 3) + bReal*Math.pow(i, 2) + cReal*i + dReal);

完整修正示例代码

这里给你一个可以直接运行的完整示例,包含数据生成、归一化、模型构建和训练:

// 生成真实数据
let xs = [];
let ys = [];
const aReal = Math.random();
const bReal = Math.random();
const cReal = Math.random();
const dReal = Math.random();

for (let i = -100; i < 100; i += 1) {
  xs.push(i);
  ys.push(aReal * Math.pow(i, 3) + bReal * Math.pow(i, 2) + cReal * i + dReal);
}

// 归一化数据
const minX = Math.min(...xs);
const maxX = Math.max(...xs);
const normalizedXs = xs.map(x => (x - minX) / (maxX - minX) * 2 - 1);

const minY = Math.min(...ys);
const maxY = Math.max(...ys);
const normalizedYs = ys.map(y => (y - minY) / (maxY - minY));

// 转换为TensorFlow张量
const xsTensor = tf.tensor2d(normalizedXs.map(x => [x, Math.pow(x,2), Math.pow(x,3)]));
const ysTensor = tf.tensor2d(normalizedYs, [normalizedYs.length, 1]);

// 构建模型
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [3]}));

// 编译模型
model.compile({optimizer: tf.train.adam(0.001), loss: 'meanSquaredError'});

// 训练模型
async function train() {
  await model.fit(xsTensor, ysTensor, {
    epochs: 100,
    batchSize: 8,
    callbacks: {
      onEpochEnd: (epoch, logs) => {
        console.log(`Epoch ${epoch}: loss = ${logs.loss}`);
      }
    }
  });

  // 查看模型权重
  model.getWeights().forEach(w => {
    w.print();
  });
}

train();

内容的提问来源于stack exchange,提问作者Em Eldar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:01:10