WordNetSimalarity в большом наборе данных synsets

Я использую сходство Wordnet 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 наборов синонимов computeSimilarity будет называться (595*594/2) время, чтобы вычислить сходство между двумя словами, которые он тратит более 5000 ms! так что для завершения моей задачи мне нужна как минимум одна неделя!!

Мой вопрос, как сократить этот период!

Как улучшить выступления?

4 ответа

Я не думаю, что язык это ваша проблема.

Вы можете помочь себе с параллелизмом. Я думаю, что это был бы хороший кандидат на сокращение карты и Hadoop.

Perl отличается от многих других языков в том, что касается потоков / разветвления.

Одна из ключевых вещей, которая отличает потоки Perl от других потоков, заключается в том, что данные не являются общими по умолчанию. Это делает потоки намного проще и безопаснее в работе, вам не нужно беспокоиться о безопасности потоков библиотек или большей части вашего кода, а только о потоке. Однако это может привести к снижению производительности и потере памяти, поскольку Perl должен поместить копию интерпретатора и всех загруженных модулей в каждый поток.

Когда дело доходит до разветвления, я буду говорить только о Unix. Perl эмулирует fork в Windows с помощью потоков, он работает, но он может быть медленным и глючным.

Преимущества Форкинг

  • Очень быстро создать вилку
  • Очень крепкий

Недостатки форкинг

  • Общение между процессами может быть медленным и неловким

Преимущества темы

  • Координация потоков и обмен данными довольно просты
  • Темы довольно просты в использовании

Недостатки темы

  • Каждый поток занимает много памяти
  • Потоки могут быть медленными, чтобы начать
  • Темы могут быть глючными (тем лучше ваш последний Perl)
  • Соединения с базой данных не разделяются между потоками

В общем, для получения хорошей производительности от потоков Perl лучше всего запустить пул потоков и использовать их повторно. Вилы легче создавать, использовать и выбрасывать.

В любом случае вы, вероятно, захотите, чтобы что-то управляло вашей рабочей группой. Для разветвления вы захотите использовать Parallel::ForkManager или Child. Ребенок особенно хорош, поскольку он встроил межпроцессное общение.

Для потоков вы захотите использовать потоки::shared, Thread::Queue и читать perlthrtut. Кроме того, количество потоков будет зависеть от количества ядер на вашем компьютере. Если у вас четыре ядра, создание более 3-х потоков не очень поможет (3 + 1 для вашей основной программы).

Честно говоря, тем не менее, темы / разветвления могут не быть подходящим способом. Фактически, во многих ситуациях они могут даже замедлить работу из-за накладных расходов. Если вам действительно нужна скорость, лучший способ получить ее - распределенные вычисления. Я бы посоветовал вам взглянуть на какую-то распределенную вычислительную платформу, чтобы улучшить время выполнения. Если вы можете уменьшить размерность вашего пространства поиска / сравнения до менее чем n^2, тогда карта Reduce или Hadoop могут быть хорошим вариантом; в противном случае у вас просто будет куча накладных расходов, и вы не будете использовать реальную масштабируемость, которую предлагает Hadoop (@Thomas Jungblut).

Я не знаю, возможно ли оптимизировать этот алгоритм.

Но определенно вы можете запустить это намного быстрее. На моей машине эта операция занимает вдвое меньше времени, поэтому, если у вас восемь ядер i7, вам потребуется 15 часов для обработки всего (если вы обрабатываете цикл параллельно)

Вы можете получить виртуальные машины в Amazon Web Services. Таким образом, если вы получаете несколько машин и запускаете многопоточную обработку для разных блоков данных на каждой машине - вы завершите работу за несколько часов.

Технически для этого можно использовать Hadoop, но если вам нужно выполнить это только один раз - по моему мнению, параллельное выполнение вычислений и запуск на нескольких машинах будет проще.

Вы пробовали MatrixCalculator?

Другие вопросы по тегам