向量 [Java] 上的 l2 归一化错误

Error with l2 normalization on a vector [Java]

我正在尝试对具有 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

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

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

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

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

xy 的可能值在它们的指数上有相对严格的界限时,这很有效。如果不是这种情况,xy 的值可能会导致差异始终支配您选择的 ϵ(如果指数太大)或 ϵ支配差异(例如当 xy 的可能指数很小时)。为了解决这个问题,您可以不比较绝对差异,而是比较 xy1.0 的比率,看看该比率是否与 [=25= 有绝对差异] 超过 ϵ。看起来像:

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

您可能需要添加另一项检查以确保 y!=0 避免被零除,但这是一般的想法。

其他选项包括使用 fixed point library for Java or a rational number library for Java。不过,我对此没有任何建议。