- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
有时,当您使用常见数据类型(例如 double 据)进行概率非常小的计算时,数值不准确会叠加多次计算并导致不正确的结果。因此,建议使用 log probabilities , 这提高了数值稳定性。我已经在 Java 中实现了对数概率并且我的实现有效,但是它的数值稳定性比使用原始 double 差。我的实现有什么问题?在 Java 中执行许多小概率连续计算的准确有效方法是什么?
我无法提供这个问题的完整演示,因为许多计算都存在不准确之处。但是,这里证明存在问题:this由于数字准确性,提交给 CodeForces 竞赛失败。运行测试 #7 并添加调试打印清楚地表明,从第 1774 天开始,数字错误开始级联,直到概率总和下降到 0(当它应该是 1 时)。在用 double 的简单包装器替换我的 Prob 类后 the exact same solution passes tests .
我对乘法概率的实现:
a * b = Math.log(a) + Math.log(b)
我的加法实现:
a + b = Math.log(a) + Math.log(1 + Math.exp(Math.log(b) - Math.log(a)))
稳定性问题很可能包含在这两行中,但这是我的整个实现:
class Prob {
/** Math explained: https://en.wikipedia.org/wiki/Log_probability
* Quick start:
* - Instantiate probabilities, eg. Prob a = new Prob(0.75)
* - add(), multiply() return new objects, can perform on nulls & NaNs.
* - get() returns probability as a readable double */
/** Logarithmized probability. Note: 0% represented by logP NaN. */
private double logP;
/** Construct instance with real probability. */
public Prob(double real) {
if (real > 0) this.logP = Math.log(real);
else this.logP = Double.NaN;
}
/** Construct instance with already logarithmized value. */
static boolean dontLogAgain = true;
public Prob(double logP, boolean anyBooleanHereToChooseThisConstructor) {
this.logP = logP;
}
/** Returns real probability as a double. */
public double get() {
return Math.exp(logP);
}
@Override
public String toString() {
return ""+get();
}
/***************** STATIC METHODS BELOW ********************/
/** Note: returns NaN only when a && b are both NaN/null. */
public static Prob add(Prob a, Prob b) {
if (nullOrNaN(a) && nullOrNaN(b)) return new Prob(Double.NaN, dontLogAgain);
if (nullOrNaN(a)) return copy(b);
if (nullOrNaN(b)) return copy(a);
double x = a.logP;
double y = b.logP;
double sum = x + Math.log(1 + Math.exp(y - x));
return new Prob(sum, dontLogAgain);
}
/** Note: multiplying by null or NaN produces NaN (repping 0% real prob). */
public static Prob multiply(Prob a, Prob b) {
if (nullOrNaN(a) || nullOrNaN(b)) return new Prob(Double.NaN, dontLogAgain);
return new Prob(a.logP + b.logP, dontLogAgain);
}
/** Returns true if p is null or NaN. */
private static boolean nullOrNaN(Prob p) {
return (p == null || Double.isNaN(p.logP));
}
/** Returns a new instance with the same value as original. */
private static Prob copy(Prob original) {
return new Prob(original.logP, dontLogAgain);
}
}
最佳答案
问题是由方式引起的Math.exp(z)
用于此行:
a + b = Math.log(a) + Math.log(1 + Math.exp(Math.log(b) - Math.log(a)))
当 z
达到极值时,double 的数值精度不足以满足 Math.exp(z)
的输出.这会导致我们丢失信息,产生不准确的结果,然后这些结果会级联多次计算。
当 z >= 710
然后 Math.exp(z) = Infinity
当 z <= -746
然后 Math.exp(z) = 0
在原始代码中,我用 y - x
调用 Math.exp并任意选择哪个是 x 以及哪个是原因。让我们选择 y
和 x
基于哪个更大,所以 z
是消极的而不是积极的。我们溢出的点更偏向于负数(746 而不是 710),更重要的是,当我们溢出时,我们最终到达 0 而不是无穷大。这就是我们想要的可能性很小。
double x = Math.max(a.logP, b.logP);
double y = Math.min(a.logP, b.logP);
double sum = x + Math.log(1 + Math.exp(y - x));
关于java - 具有对数概率 Java 实现的数值精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42355196/
接下来是我的代码: with open("test.txt") as f_in: for line in f_in: for char in line:
我们有一个六面骰子,面编号为 1 到 6。随着 n 的增加,在第 n 卷中第一次看到 1 的概率降低。我想找到最小的卷数,使得这个概率小于某个给定的限制。 def probTest(limit):
我只是想知道为什么运行下面的代码时出现错误。我正在尝试使用 numpy 为基于文本的游戏计算概率。下面的代码不是游戏本身的代码。这仅用于测试目的和学习。感谢您提前的答复,请对我宽容一点。 from n
我目前正在创建一个与多个arduino板通信的服务器软件。由于硬件原因,我使用UDP协议(protocol)。我有一个非常简单的机制,在大多数情况下,当包裹丢失时,它会重新发送包裹。我现在有两个问题:
我想在 LinearLayout 上添加一个 fling Action 。为此,我使用了以下代码。 public class NewsActivity extends Activity { .
下面是其中一个 facebook 谜题:我无法理解如何进行此操作。 你有 C 个容器、B 个黑球和无限数量的白球。您希望以一种方式在容器之间分配球,即每个容器至少包含一个球,并且选择白球的概率大于或等
我有一个希伯来语文本,就像 "×گض¸×¨ض´×™×،ض°×کוض¹×ں",我想将它转换为可读的 unicode 希伯来语字符。 我试过这段代码: const string Str = "×گض¸×
我正在尝试使用 Random.nextDouble() 获取 1.0 和 10.0 之间的随机双数: double number = 1.0 + (10.0-1.0) * Random.nextDou
我目前已经为二进制类实现了概率(至少我这么认为)。现在我想扩展这种回归方法,并尝试将其用于波士顿数据集。不幸的是,我的算法似乎被卡住了,我当前运行的代码如下所示: from sklearn impor
我在 2D 空间中有一小组数据点(大约 10 个),每个数据点都有一个类别标签。我希望根据现有数据点标签对新数据点进行分类,并关联属于任何特定标签类别的“概率”。 基于最近邻的标签来标记新点是否合适(
我正在做我的第一个 tensorflow 项目。 我需要获得给定输入和预期序列的 ctc 概率(不是 ctc 损失)。 在 python 或 c++ 中是否有任何 api 或方法可以做到这一点? 我更
我正在尝试通过 assignment 1斯坦福 cs244n 类(class)。问题 1b 强烈建议对 Softmax 函数进行优化。我设法得到了N维向量的Softmax。我还得到了 MxN 维矩阵的
我有一个预测算法的想法,该算法可以根据所选项目先前出现的顺序准确预测随机值,并分析模式以提高准确性。 基本上是一种接受两个参数的算法,一个是一组可能的选择;另一个是这些数字的历史,分析该模式并预测序列
自 HOURS 以来,我一直在努力思考这个 TopCoder 问题,但无法找到一个完美的解决方案,并找到了下面给出的一个使用得非常漂亮的解决方案! 我想弄清楚这个解决方案如何适用于给定的问题?而我当初
我只知道如何生成随机 boolean 值(真/假)。默认概率为 50:50 但是我怎样才能用我自己的概率生成真假值呢?假设它以 40:60 或 20:80 等的概率返回 true... 最佳答案 一种
对于以下示例,我如何计算 julia 中的百分位数/概率值/尾部区域 Example : N(1100, 200) #Normally distributed with mean 1100 & st
我正在尝试修改标准 kNN 算法来获取属于某个类别的概率,而不仅仅是通常的分类。我还没有找到太多关于概率 kNN 的信息,但据我了解,它的工作原理与 kNN 类似,不同之处在于它计算给定半径内每个类的
我正在使用 PostgreSQL 为我所有数据中的变量对计算经验概率密度函数。我试图确定在计算 PDF 之前索引是否/何时更有效。我像这样运行 EXPLAIN CREATE INDEX, EXPLAI
有谁知道当查询有偏移时如何在 MySql 中请求“实时结果集”(例如:select * from table limit 10 offset 20;)。它正在经历类似 的错误 'invalid use
unsigned long long int first( int b , int c){ int h=b; //int k; for(int k=b-1;k>c;k--){ b=b*k;
我是一名优秀的程序员,十分优秀!