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, но если вам нужно выполнить это только один раз - по моему мнению, параллельное выполнение вычислений и запуск на нескольких машинах будет проще.