Как найти основное, неотраженное слово для поиска? - PullRequest
2 голосов
/ 31 мая 2011

У меня проблемы с попыткой написать поисковую систему, которая рассматривает все перегибы слова как одно и то же основное слово.

  1. Так что для глаголов это все одно и то же корневое слово, be :
    • число / человек (например, утра; есть; являются )
    • время / настроение, подобное прошедшему или будущему времени ( например, было; было; будет )
    • прошедших причастий ( например было ; было )
    • настоящее причастие и герунды ( например, в ; не в смешном; в рано * менее важно, чем , будучи правильным)
    • сослагательных наклонений ( например, можетбыть ; критическим, чтобы что-то было закончено; мне бы хотелось, чтобы были ) ⁠ ⁠ ⁠

  2. Тогда для существительные , и форма единственного и множественного числа должны считаться одним и тем же основным словом [ ᴇᴅɪᴛᴏʀ's ɴᴏᴛᴇ: это часто упоминается как цитата Форма слова. ]

Например, с « enable » я не хочу, чтобы « enable » и« enabled » напечатано как отдельные записи.Все три из них должны считаться одним и тем же основным словом, глагол enable .

Я могу запретить печать дубликатов, используя хеш-код:

unless ($seenmatches{ $headmatches[$l] }++)
  1. Может кто-нибудь объяснить это?Объясняется в комментариях ниже.

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

Я не могу изменить слово с помощьюподстановка, потому что тогда печать не будет распечатываться правильно.Хотя я еще не на стадии, в конце концов я бы хотел включить нерегулярные прошедшие времена [ ᴇᴅɪᴛᴏʀ's: и нерегулярные существительные тоже? ]

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

Ответы [ 4 ]

5 голосов
/ 31 мая 2011

Типичная поисковая система работает следующим образом:

  • Входная строка маркируется, разбивается на границах слов - начало / конец смещения символов связывается с каждым токеном
  • Каждый жетон затем останавливается - я бы использовал Lingua::Stem (или, лучше, Lingua::Stem::Snowball), которые являются слегка обновленными версиями стеммера Портера
  • Каждый жетон с его исходным смещением символов начало / конецсохраняется и индексируется, как правило, вместе с копией исходного текста до его токенизации.По сути, это таблица, которая связывает термин «текст» с исходным документом (обычно в качестве идентификатора).

Теперь, когда приходит запрос, он тоже токенизируется, и каждый токен связан, но мы этого не делаем.заботиться о позициях на этот раз.Мы сравниваем каждый токен с индексированными, чтобы найти записи (соответствующие идентификаторы документа).Теперь мы можем извлечь сохраненные начальные / конечные смещения, чтобы определить, где термины были в исходном тексте.

Таким образом, вы теряете суффиксы для index (что и использовалось для поиска подходящих документов), но вы сохраняете исходный текст и смещения для этих документов, поэтому вы можете выполнить запросПодсветка и приятный дисплей, если вам нужно.

Стебминг, безусловно, является подходящим инструментом для этой работы.Основной трюк заключается в том, чтобы вы относились к запросу и документам одинаково.Вы можете изменить исходный документ, но на самом деле вы хотите преобразовать его во что-то вроде заднего указателя книги, а не в строку, на которой вы используете регулярные выражения - если вы действительно делаете вещи для поисковых систем, то есть.Проверьте отличный модуль KinoSearch на CPAN, если хотите, или посмотрите на проект Apache Lucene, из которого он изначально был получен.

1 голос
/ 08 июня 2011

Проверьте verbTenseChanger.pl (http://cogcomp.cs.illinois.edu/page/tools_view/1) Вот readme:

##codes for the various tenses are:
#0 - Base Form
#1 - Past Simple
#2 - Past Participle
#3 - 3rd Person Singular
#4 - Present Participle

##Example use:
##my $newTense = changeVerbForm("see",0,4);
##changes tense from base form to the present participle

Я использовал это (я думаю, что включает в себя стеммер), создавая различные формы:

my @changeverbforms = map changeVerbForm( $search_key, 0, $_ ), 1..4;
my @verbforms;
push (@verbforms, $changeverbforms[0]) unless ($changeverbforms[0] eq "");
push (@verbforms, $changeverbforms[1]) unless ($changeverbforms[1] eq "");
push (@verbforms, $changeverbforms[2]) unless ($changeverbforms[2] eq "");
push (@verbforms, $changeverbforms[3]) unless ($changeverbforms[3] eq "");

, а затем перебирая @verbforms (вокруг всего кода Perl поисковой системы) и везде, где у меня был $search_key, я также поставил or $verbform. Было несколько дополнительных вещей, которые нужно исправить, но это общая реализация (хотя ив моих конкретных обстоятельствах)

Для некоторой отладки неисправного онлайн-кода, см .: https://stackoverflow.com/questions/6459085/need-help-understanding-this-verb-tense-changing-code-please

1 голос
/ 31 мая 2011

Модуль Text :: English включает в себя модуль портера, который является обычным методом обработки различных форм одного и того же слова как идентичных для сопоставления.

0 голосов
/ 31 мая 2015

Я попробовал Lingua :: Stem, Lingua :: Stem :: Snowball и WordNet :: stem, и все они не в состоянии найти наиболее распространенные слова. Чтобы получить эти простые слова, вы можете запустить этот простой стеммер, который использует файлы .exc (исключение?) WordNet:

1. Download and install WordNet.
2. export WNHOME='/usr/lib/wnres' (if that is the directory containing the dict directory; that's where Cygwin puts it. You'll need that to install Wordnet::QueryData.)
3. cat $WNHOME/dict/*.exc > wordnet.exc  (combine all the .exc files)
4. Make this perl file:

$ cat > stem.pl
use strict;
use warnings;

# Read in WordNet exception files
my $ExcFile = "wordnet.exc";
my %Stems;
open(my $FILE, "<$ExcFile") or die "Could not read $ExcFile: $!";
while (my $line = <$FILE>) {
        chomp($line);
        my ($word, $stem) = split(/\s+/, $line);
        $Stems{$word} = $stem;
}
close($FILE);

while (defined(my $in = <>)) {
        chomp($in); $in =~ s/\r$//;
        $in =~ s/^\s+//;
        $in =~ s/\s+$//;
        next if $in eq '';
        my @words = split(/\s+/, $in);
        foreach my $w (@words) {
                $w = $Stems{$w} if $Stems{$w};
        }
        print "@words\n";
}
<ctrl-D>

Тогда вы можете остановить foo.txt с помощью

perl stem.pl < foo.txt

Возможно, вы захотите запускать другие стеммеры до, а не после этого шага, потому что, если они умны и используют контекст слова для определения (хотя я сомневаюсь, что они это делают), им понадобится полная незаполненная строка для работы, тогда как stem.pl работает пословно.

...