我试图在带有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
为什么我的总和不等于一? 代码中是否存在一些问题? 或者仅仅因为我的数字太小而且有一些近似的双打?
答案 0 :(得分:1)
如上所述,这是一个常见问题,如果您要使用浮点二进制算法,那么您将不得不处理这个问题。当你想比较两个浮点二进制数是否相等时,问题大多就会出现。由于应用于达到值的操作可能不相同,因此它们的二进制表示也不相同。
至少有一些策略可以考虑处理这种情况。第一种方法是比较两个浮点数x
和y
之间的绝对差值,而不是严格相等,并将它们与一些小值ϵ>0
进行比较。这看起来像
if (Math.abs(y-x) < epsilon) {
// Assume x == y
} else {
// Assume x != y
}
当x
和y
的可能值对其指数具有相对紧密的界限时,这很有效。如果不是这种情况,则x
和y
的值可能会使差异始终支配您选择的ϵ
(如果指数过大)或ϵ
支配差异(例如x
和y
的可能指数很小时)。要解决此问题,您可以改为比较x
和y
与1.0
的比率,而不是比较绝对差异,看看该比率是否与{{1}有绝对差异超过1.0
。那看起来像是:
ϵ
您可能需要添加另一项检查以确保if (Math.abs(x/y-1.0) < epsilon) {
// Assume x == y
} else {
// Assume x != y
}
避免被零除,但这是一般的想法。
其他选项包括使用fixed point library for Java或rational number library for Java。不过,我没有这方面的建议。