首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java代码优化会导致数值不准确和错误。

Java代码优化会导致数值不准确和错误。
EN

Stack Overflow用户
提问于 2011-01-09 09:44:35
回答 1查看 1.3K关注 0票数 9

我试图在Java中实现模糊C-均值算法的一个版本,并试图通过只计算一次所有可以计算的内容来进行一些优化。

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

其中x是矩阵X (像素x特征)的元素,v属于矩阵V (集群x特征)。m是一个从1.1infinity的参数,c是集群的数量。使用的距离是欧氏范数。

如果我必须以平庸的方式实现这个公式,我会这样做:

代码语言:javascript
复制
    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的元素两次,导致两个嵌套循环。看看这个公式,分数的分子与和无关,所以我可以独立计算分子和分母,分母可以对每个像素计算一次。所以我想出了这样的解决方案:

代码语言:javascript
复制
    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的另一列:

代码语言:javascript
复制
    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)导致非常小的值,而通过除以分子、分母和指数在数值上似乎更好。问题是它涉及更多的操作。

更新

我在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的约束,所以它们是非常不同的。

我做错了什么吗?是否有可能得到优化和数值稳定的代码的解决方案?如有任何建议或批评,将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-09 18:54:28

这个问题与浮点稳定性无关。

在第二次迭代和随后的迭代中,您得到了错误的分母值,因为在累积和之前忘记清除它的单元格。

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

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4638554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档