向量 [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
为什么我的总和不等于一?
代码中是否存在一些问题?
还是因为我的数字太小,双打有一些近似值?
如上所述,这是一个常见问题,如果您要使用浮点二进制算术,您将不得不处理这个问题。当您想要比较两个浮点二进制数是否相等时,问题通常会出现。由于用于得出值的操作可能不相同,因此它们的二进制表示也不相同。
您至少可以考虑两种策略来处理这种情况。第一个涉及比较两个浮点数 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
的比率,看看该比率是否与 [=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。不过,我对此没有任何建议。
我正在尝试对具有 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
为什么我的总和不等于一? 代码中是否存在一些问题? 还是因为我的数字太小,双打有一些近似值?
如上所述,这是一个常见问题,如果您要使用浮点二进制算术,您将不得不处理这个问题。当您想要比较两个浮点二进制数是否相等时,问题通常会出现。由于用于得出值的操作可能不相同,因此它们的二进制表示也不相同。
您至少可以考虑两种策略来处理这种情况。第一个涉及比较两个浮点数 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
的比率,看看该比率是否与 [=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。不过,我对此没有任何建议。