wordnetsimilarity在大型数据集中的应用



我使用wordnet similarity java api来度量两个同义词集之间的相似性,如下所示:

 public class WordNetSimalarity {
 private static ILexicalDatabase db = new NictWordNet();
 private static RelatednessCalculator[] rcs = {
                 new HirstStOnge(db), new LeacockChodorow(db), new Lesk(db),  new WuPalmer(db), 
                 new Resnik(db), new JiangConrath(db), new Lin(db), new Path(db)
                 };
 public static double computeSimilarity( String word1, String word2 ) {
         WS4JConfiguration.getInstance().setMFS(true);
         double s=0;
         for ( RelatednessCalculator rc : rcs ) {
                 s = rc.calcRelatednessOfWords(word1, word2);
                // System.out.println( rc.getClass().getName()+"t"+s );
         }
        return s;
 } 

主类

      public static void main(String[] args) {
         long t0 = System.currentTimeMillis();
         File source = new File ("TagsFiltered.txt");
         File target = new File ("fich4.txt");
         ArrayList<String> sList= new ArrayList<>();
         try {
             if (!target.exists()) target.createNewFile();
            Scanner scanner = new Scanner(source);
            PrintStream psStream= new PrintStream(target);
            while (scanner.hasNext()) {
                sList.add(scanner.nextLine());                  
            }
            for (int i = 0; i < sList.size(); i++) {
            for (int j = i+1; j < sList.size(); j++) {
                psStream.println(sList.get(i)+" "+sList.get(j)+" "+WordNetSimalarity.computeSimilarity(sList.get(i), sList.get(j)));
            }
        }   
            psStream.close();
        } catch (Exception e) {e.printStackTrace();
        }

         long t1 = System.currentTimeMillis();
         System.out.println( "Done in "+(t1-t0)+" msec." );
 }

我的数据库包含595个synsets,这意味着方法computeSimilarity将被调用(595*594/2)次为了计算两个词之间的相似度,它花费了超过5000 ms !所以完成我的任务我至少需要一个星期!!

我的问题是如何缩短这个周期!

如何改善性能??

我不认为语言是你的问题。

你可以帮助自己的并行。我认为这将是map reduce和Hadoop的一个很好的候选。

你试过MatrixCalculator吗?

我不知道是否有可能优化这个算法。

但是你肯定可以跑得更快。在我的机器上,这个操作花费的时间减少了两倍,所以如果您有8个i7内核,则需要15个小时来处理所有内容(如果并行处理循环)

你可以在Amazon Web Services上获得虚拟机。因此,如果你有几台机器,并在每台机器上对不同的数据块运行多线程处理,你将在几个小时内完成。

从技术上讲,使用Hadoop是可能的,但如果你只需要运行一次,在我看来,使计算并行并在几台机器上启动会更简单。

Perl在线程/分叉方面与许多其他语言不同。

Perl线程与其他线程不同的一个关键因素是默认情况下数据不共享。这使得线程更容易和更安全,您不必担心库或大多数代码的线程安全,只需担心线程部分。然而,它可能是一个性能拖累和内存消耗,因为Perl必须将解释器和所有加载模块的副本放入每个线程中。

当谈到分叉时,我将只谈论Unix。Perl在Windows上使用线程模拟fork,它可以工作,但是它可能很慢而且有bug。

分叉优势

  • 创建fork非常快
  • 非常健壮的

分叉缺点

  • 进程之间的通信可能是缓慢和尴尬的

线程优势

    线程协调和数据交换是相当容易的
  • 线程相当容易使用

线程缺点

  • 每个线程占用大量内存
  • 线程启动缓慢
  • 线程可能有bug(你的perl越新越好)
  • 数据库连接不能跨线程共享

一般来说,要从Perl线程中获得良好的性能,最好启动一个线程池并重用它们。fork可以更容易地创建、使用和丢弃。

对于任何一种情况,您都可能需要一些东西来管理您的工作池。对于分叉,您将需要使用Parallel::ForkManager或Child。子进程特别好,因为它内置了进程间通信。

对于你想要使用Thread:: shared, Thread::Queue和read perlthrtut的线程。此外,线程的数量将取决于计算机的核心数量。如果您有四个内核,那么创建3个以上的线程并不是很有帮助(对于主程序来说是3 + 1)。

老实说,虽然,线程/分叉可能不是要走的路。事实上,在很多情况下,它们甚至会因为开销而减慢速度。如果你真的需要速度,最好的方法就是通过分布式计算。我建议您研究某种分布式计算平台,以使您的运行时更好。如果你可以将搜索/比较空间的维度降低到小于n^2,那么map reduce或Hadoop可能是一个不错的选择;否则,你只会有一堆开销,而不会使用Hadoop提供的真正的可伸缩性(@Thomas Jungblut)。

最新更新