在NaïveBayes中乘以大量概率会导致浮点下溢。
"central deployment"
使用下面给出的公式更可行/更好,而不是使用上面的公式(导致浮点下溢)?或者它会截断信息吗?
P(x_1,….,x_n│c) = P(x_1│c).P(x_2│c).P(x_3│c)… … P(x_n |c)
答案 0 :(得分:2)
在发生下溢或溢出之前,浮点乘法是浮点运算的最佳表现。此外,在你的公式中,一旦达到下溢,就会知道最终值很小,因为未处理的因子小于1.0,只能使最终结果变小。
使用对数似乎只会降低整体的准确性,首先是因为对数本身和第二,因为不同大小的数字的浮点加法不表现良好。
除非你关心2 -1024 的概率与由于某种原因你的问题没有说明的零概率之间的差异,否则我不明白你为什么要改变这个井 - 第一个公式中的乘法乘以第二个公式中的危险加法。
注意:你必须拥有20个因素,每个数量级为2 -50 ,以下流IEEE 754的binary64格式。如果这是您期望并希望准确处理的数据类型,那么如果您的编译器使此类型可用(例如,如果您使用long double
,则可以考虑使用80位双扩展格式) C),或MPFR,我认为它使用一个完整的词来表示指数。
答案 1 :(得分:2)
假设所有概率都在合理的范围内,比如[2 ^ { - 63},2 ^ {63}],你可以像这样积累产品:
double prod(double *d, int n, int64_t *expo) {
*expo = 0;
double ans = 1;
for (int i = 0; i < n; i++) {
ans *= d[i];
if (!(i % 16)) {
int foo = 0;
ans = frexp(ans, &foo);
expo += foo;
}
}
}
然后该产品在返回值的n / 2 ulp内乘以2 ^ {*expo
}。这段代码非常容易实现矢量化,并且为这种特殊情况写一个替代的,更快的frexp
也很容易,这种情况只是稍微麻烦并忽略了NaNs / infinities / zeroes / subnormals。
如果您的平台支持捕获浮点运算并且您的输入已知位于合理但未知的范围内,则可以通过添加陷阱处理程序来自适应地选择步幅,同时对大n
的性能影响最小。溢出和下溢。如果用平台的汇编语言编写产品例程和陷阱处理程序,最简单的方法就是这样做。
如果你改为添加对数,你会失去相当多的精度,首先是取对数,然后是求和,你可能会或可能不会关心。更糟糕的是,通过计算这么多的对数,你也会失去相当多的速度。