gpt4 book ai didi

Java代码优化会导致数值不正确和错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:20:07 25 4
gpt4 key购买 nike

我正在尝试在Java中实现 Fuzzy C-Means algorithm 的版本,并且试图通过仅计算一次就可以计算一次的所有内容来进行一些优化。

这是一个迭代算法,关于矩阵的更新,像素x聚类隶属矩阵U(一行中的值之和必须为1.0),这是我要优化的更新规则:

其中x是矩阵X(像素x特征)的元素,而v属于矩阵V(簇x特征)。 m是范围从1.1infinity的参数,而c是簇的数量。使用的距离是欧几里得范数。

如果我必须以平庸的方式来实现此公式,则可以执行以下操作:

    for(int i = 0; i < X.length; i++)
{
int count = 0;
for(int j = 0; j < V.length; j++)
{
double num = D[i][j];
double sumTerms = 0;
for(int k = 0; k < V.length; k++)
{
double thisDistance = D[i][k];
sumTerms += Math.pow(num / thisDistance, (1.0 / (m - 1.0)));
}
U[i][j] = (float) (1f / sumTerms);
}
}

这样就已经完成了一些优化,我预先计算了 XV之间的所有可能的平方距离,并将它们存储在矩阵 D中,但这还不够,因为我循环遍历 V元素两次,导致两个嵌套循环。
查看公式,分数的分子与和无关,因此我可以独立计算分子和分母,并且每个像素只能计算一次分母。
所以我得出了这样的解决方案:
    int nClusters = V.length;
double exp = (1.0 / (m - 1.0));
for(int i = 0; i < X.length; i++)
{
int count = 0;
for(int j = 0; j < nClusters; j++)
{
double distance = D[i][j];
double denominator = D[i][nClusters];
double numerator = Math.pow(distance, exp);
U[i][j] = (float) (1f / (numerator * denominator));
}
}

在计算距离时,将分母预先计算到矩阵 D的另一列中:
    for (int i = 0; i < X.length; i++)
{
for (int j = 0; j < V.length; j++)
{
double sum = 0;
for (int k = 0; k < nDims; k++)
{
final double d = X[i][k] - V[j][k];
sum += d * d;
}

D[i][j] = sum;
D[i][B.length] += Math.pow(1 / D[i][j], exp);
}
}

这样,我遇到了“普通”计算和第二个计算之间的数值差异,这导致 U中的数值不同(第一个不是迭代,但很快就实现了)。我猜是问题在于,将很小的数字乘以高值( U的元素范围可以从0.0到1.0, exp的范围为 m = 1.1,是 10)会导致很小的值,而通过将分子,分母和 除THEN 对结果求幂似乎在数值上更好。问题在于它涉及更多的操作。

更新

我在 ITERATION 0 上得到的一些值:

这是未优化的矩阵 D的第一行:
384.6632 44482.727 17379.088 1245.4205
这是优化格式 D的第一行(请注意,最后一个值是预先计算的分母):
384.6657 44482.7215 17379.0847 1245.4225 1.4098E-26
这是 U的第一行未优化:
0.99999213 2.3382613E-21 2.8218658E-17 7.900302E-6
这是 U优化的第一行:
0.9999921 2.338395E-21 2.822035E-17 7.900674E-6
ITERATION 1 :

这是未优化的矩阵 D的第一行:
414.3861 44469.39 17300.092 1197.7633
这是优化格式 D的第一行(请注意,最后一个值是预先计算的分母):
414.3880 44469.38 17300.090 1197.7657 2.0796E-26
这是 U的第一行未优化:
0.99997544 4.9366603E-21 6.216704E-17 2.4565863E-5
这是 U优化的第一行:
0.3220644 1.5900239E-21 2.0023086E-17 7.912171E-6
最后一组值表明,由于传播错误(我仍然希望做一些错误),它们之间存在很大差异,甚至违反了这些值之和必须为1.0的约束。

难道我做错了什么?是否有可能使代码既优化又数值稳定的解决方案?任何建议或批评将不胜感激。

最佳答案

此问题与浮点稳定性无关。

您在第二次及之后的迭代中得到的分母值不正确,因为您在累积总和之前忘记清除其单元格。

迭代1的右分母是6.697905e-27,几乎是2.0796E-26 - 1.4098E-26

关于Java代码优化会导致数值不正确和错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4638554/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com