向量上的l2规范化错误[Java]

时间:2015-06-25 14:35:24

标签: java vector floating-point normalization floating-point-precision

我试图在带有Java的双向量上使用l2规范化。

double[] vector = {0.00423823948, 0.00000000000823285934, 0.0000342523505342, 0.000040240234023423, 0, 0};

现在,如果我使用l2标准化

for(double i : vector){
    squareVectorSum += i * i;
}

normalizationFactor = Math.sqrt(squareVectorSum);
// System.out.println(squareVectorSum+" "+normalizationFactor);
for(int i = 0; i < vector.length; i++){
    double normalizedFeature = vector[i] / normalizationFactor;
    vector_result[i] = normalizedFeature;
}

我的标准化向量就像这样

Normalized vector (l2 normalization)
0.9999222784309146 1.9423676996312713E-9 0.008081112110203743 0.009493825603572155 0.0 0.0

现在,如果将所有规范化矢量分量的平方和加起来,我得到一个等于1的和,而不是我的平方和

for(double i : vector_result){
    sum += i*i;
}
Squared sum of the normalized-vector
1.0000000000000004

为什么我的总和不等于一? 代码中是否存在一些问题? 或者仅仅因为我的数字太小而且有一些近似的双打?

1 个答案:

答案 0 :(得分:1)

如上所述,这是一个常见问题,如果您要使用浮点二进制算法,那么您将不得不处理这个问题。当你想比较两个浮点二进制数是否相等时,问题大多就会出现。由于应用于达到值的操作可能不相同,因此它们的二进制表示也不相同。

至少有一些策略可以考虑处理这种情况。第一种方法是比较两个浮点数xy之间的绝对差值,而不是严格相等,并将它们与一些小值ϵ>0进行比较。这看起来像

if (Math.abs(y-x) < epsilon) {
    // Assume x == y
} else {
    // Assume x != y
}

xy的可能值对其指数具有相对紧密的界限时,这很有效。如果不是这种情况,则xy的值可能会使差异始终支配您选择的ϵ(如果指数过大)或ϵ支配差异(例如xy的可能指数很小时)。要解决此问题,您可以改为比较xy1.0的比率,而不是比较绝对差异,看看该比率是否与{{1}有绝对差异超过1.0。那看起来像是:

ϵ

您可能需要添加另一项检查以确保if (Math.abs(x/y-1.0) < epsilon) { // Assume x == y } else { // Assume x != y } 避免被零除,但这是一般的想法。

其他选项包括使用fixed point library for Javarational number library for Java。不过,我没有这方面的建议。

相关问题