草庐IT

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

coder 2024-03-07 原文

我正在尝试在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/

有关Java代码优化会导致数值不正确和错误的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  4. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐