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

Java实现逻辑回归时对数似然计算返回NaN问题排查

解决Java逻辑回归中对数似然计算返回NaN的问题

你碰到的NaN问题根源很明确:当sigmoid输出无限接近0或1时,Math.log(0)会返回负无穷,而0乘以负无穷在Java中会得到NaN。举个具体场景:

  • 如果模型预测的概率prob几乎为0,且样本类别cat=0,那么cat * Math.log(prob)就是0 * (-∞),结果就是NaN;
  • 如果prob几乎为1,且cat=1,那么(1 - cat) * Math.log(1 - prob)就是0 * (-∞),同样会得到NaN。

结合你的代码,这里有两个简洁的解决方案:

方案1:限制概率值范围(推荐)

在findProbability方法中,给sigmoid的结果加一个极小的偏移量(epsilon),把概率牢牢限制在[epsilon, 1-epsilon]区间内,从根源上避免log(0)的情况:

public double findProbability(double[] x){
    double s = 0;
    for(int i = 0; i < this.weights.length; i++){
        if(i >= x.length) break;
        s += this.weights[i] * x[i];
    }
    double prob = sigmoid(s);
    // 用1e-10作为epsilon,既不影响模型精度,又能避免边界值
    double epsilon = 1e-10;
    return Math.max(epsilon, Math.min(1 - epsilon, prob));
}

方案2:在对数计算时做边界判断

如果不想修改原始概率值,也可以在计算对数时单独处理极端情况:

private double getLogLikelihood(double cat, double[] x) {
    double prob = findProbability(x);
    
    // 处理log(prob)的边界情况
    double logProb = prob < 1e-10 ? -23.02585093 : Math.log(prob);
    // 处理log(1-prob)的边界情况
    double log1MinusProb = (1 - prob) < 1e-10 ? -23.02585093 : Math.log(1 - prob);
    
    return cat * logProb + (1 - cat) * log1MinusProb;
}

注:-23.02585093是log(1e-10)的近似值,也可以用-1e20这类极小值代替。

额外说明

你初始化的权重里有不少绝对值较大的值(比如-2.732、-2.062),这会导致s = sum(w*x)的绝对值非常大,进而让sigmoid输出无限接近0或1——这也是为什么换随机权重后问题依然存在的原因。上面的两种方案都能有效解决这个问题,其中方案1更简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:00:25