Статьи

Модификация Lucene Snowball Stemmer

Этот пост написан для опытных пользователей. Если вы не знаете, что такое SVN (Subversion) или не готовы испачкать руки, возможно, в Википедии есть что-то более интересное для чтения . По-прежнему. Это введение в работу среды разработки Lucene, среды Solr и, наконец, создание собственного механизма запуска Snowball. Продолжайте читать, если это кажется интересным. Рецепт регенерации стеблера Snowball (я вернусь к этому …) предполагает, что вы работаете в Linux. Пожалуйста, оставьте комментарий, если вы сгенерировали класс stemmer под другой операционной системой.

При индексации данных в Lucene (библиотека полнотекстового поиска документов) и Solr (которая использует Lucene) вы можете предоставить стеммер (фрагмент кода, отвечающий за «нормализацию» слов в их общей форме (horses => horse, indexing => index) и т. д.), чтобы дать вашим пользователям лучшие и более релевантные результаты при поиске По умолчанию в Lucene and Solr используется библиотека под названием Snowball, которая была создана именно для этого. Snowball использует собственный небольшой язык определения для генерации синтаксических анализаторов, которые другие приложения могут внедрять для обеспечения правильной основы.

Используя Snowball, Lucene может предоставить хорошую коллекцию стемеров по умолчанию для нескольких языков, и они работают так, как должны для большинства выборов. У меня, однако, была проблема с норвежским родословным, так как он игнорирует полную категорию слов, где базовая форма оканчивается теми же буквами, что и множественные версии других слов. Пример:

один: электрикер
несколько: электрикер
те: электрикерен

Базовая форма — «электрикер», в то время как «электрикер» и «электрикерен» — множественные варианты одного и того же слова (слово означает «электрик», кстати).

Давайте сравним это с другим словом, таким как «Автобус»:

один: buss
несколько: busser
те: bussene

Здесь базовая форма — «шина», а две другие — во множественном числе. Давайте применим одинаковые правила ко всем шести словам:

buss => buss
busser => buss [strips «er»]
bussene => buss [strips «ene»]

elektrikerene => «elektriker» [полоски «ен»]
elektrikere => «elektriker» [полоски «е»]

Пока все прошло как запланировано. Мы можем искать «электрикерен» и получать хиты с «электрикер», как и планировалось. Все не идеально, хотя. Мы забыли одно слово, и злые силы скажут, что я специально его забыл:

электрикер =>?

Проблема в том, что «электрикер» (единственная форма слова) оканчивается на -er. Правило, определенное для слова в классе «buss», гласит, что -er следует удалить (и это верно для большинства слов). Результат тогда становится:

elektriker => «elektrik» [полоски «er»]
elektrikere => «elektriker» [полоски «e»]
elektrikerene => «elektriker» [полоски «ен»]

Как вы можете видеть, существует несоответствие между формой, к которой сводится множественное число, и единственным словом.

Мое решение, хотя и не идеальное, просто добавляет еще несколько терминов, чтобы мы могли привести все эти слова к одной и той же форме:

elektriker => «elektrik» [полоски «er»]
elektrikere => «elektrik» [полоски «ere»]
elektrikerene => «elektrik» [полоски «erene»]

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

Чтобы решить эту проблему, мы изменим парсер Snowball и создадим новую версию стеммера, которую мы можем использовать в Lucene и Solr.

Получение Снежка

Чтобы сгенерировать класс Java, который Lucene использует при попытке создать фразу (например, NorwegianStemmer, EnglishStemmer и т. Д.), Вам потребуется дистрибутив Snowball . Это распределение также включает в себя примеры алгоритмов стемминга (которые использовались для генерации текущих стеммеров в Lucene).

Вам необходимо скачать приложение со страницы загрузки в снежный ком, в частности, версию «Snowball, алгоритм и библиотека libstemmer» [ прямая ссылка ].

После извлечения файла у вас будет каталог с именем snowball_code, который содержит среди других файлов двоичный файл снежного кома и каталог с именем алгоритмов. Директория алгоритмов содержит все различные исходные элементы по умолчанию, и именно здесь вы найдете хорошую отправную точку для изменений, которые вы собираетесь сделать.

Но сначала мы позаботимся о том, чтобы у нас была установлена ​​и готова к запуску версия разработки Lucene.

Получение Lucene

Вы можете проверить текущий ствол SVN Lucene, выполнив:

    svn checkout http://svn.apache.org/repos/asf/lucene/java/trunk lucene/java/trunk

Это даст вам самую лучшую версию Lucene, чтобы немного поиграть. Если вы решили собрать Solr 1.4 из SVN (как мы сделаем дальше), вам не нужно собирать Lucene 2.9 из SVN — так как он уже включен в сборку.

Если вам нужно собрать полную версию Lucene (и всех компонентов), вы можете сделать это, переместившись в ствол Lucene:

    cd lucene/java/trunk/
    ant dist (this will also create .zip and .tgz distributions)

Если у вас уже есть Lucene 2.9 (или какая-либо другая версия, на которой вы читаете этот текст), вы можете просто скомпилировать вклад в Lucene для создания снежного кома из lucene / java / trunk /:

    cd contrib/snowball/
    ant jar

Это создаст (если все работает как надо) файл с именем lucene-snowball-2.9-dev.jar (.. или другой номер версии, в зависимости от вашей версии Lucene). Файл будет расположен в подкаталоге каталога сборки в корне проверки Lucene (.. и путь будет показан после запуска ant jar): lucene / java / trunk / build / contrib / snowball / ,

Если вы получили файл lucene-snowball-2.9-dev.jar, все выглядит хорошо! Давайте перейдем к началу работы над новейшей версией Solr (если у вас есть существующая версия Solr, которую вы используете и не хотите обновлять, пропустите следующие шаги … но не забудьте знать, что вы делаете. что по совпадению вы также должны знать, если вы создаете вещи из SVN, как мы. О радость!).

Получение Solr

Получить и собрать Solr из SVN очень просто. Во-первых, проверьте это из Subversion:

svn co http://svn.apache.org/repos/asf/lucene/solr/trunk/ solr/trunk/

А затем просто создайте файл войны для вашего любимого контейнера:

    cd solr/trunk/
    ant dist

Вуаля — теперь у вас должен быть apache-solr-1.4-dev.war (или что-то похожее) в каталоге build /. Вы можете проверить, что это работает, заменив обычную установку Solr (… сначала сделайте резервную копию …) и перезапустив сервер приложений.

Редактирование определения стеммера

После извлечения дистрибутива Snowball у вас останется каталог snowball_code, который содержит алгоритмы, а затем норвежский (в дополнение к нескольким другим языкам стеммера). Мой пример здесь расширяет определение, используемое в норвежском стемере, но примеры будут работать со всеми включенными стеммерами.

Откройте один из файлов (я выбрал версию iso-8859-1, но мне, возможно, придется настроить ее, чтобы она работала для UTF-8/16 позже. Я постараюсь опубликовать обновление по этому поводу) и возьму осмотреться. Язык снежного кома интересен, и вы можете найти больше информации об этом на
сайте Snowball .

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

    define main_suffix as (
        setlimit tomark p1 for ([substring])
        among(
            'a' 'e' 'ede' 'ande' 'ende' 'ane' 'ene' 'hetene' 'en' 'heten' 'ar'          
            'er' 'heter' 'as' 'es' 'edes' 'endes' 'enes' 'hetenes' 'ens'
            'hetens' 'ers' 'ets' 'et' 'het' 'ast'
                (delete)
            's'
                (s_ending or ('k' non-v) delete)
            'erte' 'ert'
                (<-'er')
        )
    )

Это просто означает, что любое слово, оканчивающееся любым из суффиксов в трех первых строках, будет удалено (задано командой (delete) за определениями). Проблема в нашем примере выше состоит в том, что ни одна из линий не захватит окончание «ere» или «erene» — что нам действительно нужно для решения проблемы.

Мы просто добавляем их в список определенных окончаний:

        among(
            … 'hetene' 'en' 'heten' 'ar' 'ere' 'erene' 'eren'
            …
            …
                (delete)

Я удостоверился, что добавил определения перед более короткими версиями (такими как ‘er’), но я не уверен (.. я не думаю), действительно ли это требуется.

Сохраните файл под новым именем, чтобы у вас все еще были в наличии старые стеммеры.

Компиляция новой версии Snowball Stemmer

После редактирования и сохранения вашего стемера пришло время сгенерировать класс Java, который Lucene будет использовать для генерации базовых форм слов. После извлечения архива снежного кома у вас должен быть бинарный файл с именем снежный ком в каталоге snowball_code. Если вы просто запустите этот файл с snowball_code в качестве текущего рабочего каталога:

./snowball

Вы получите список параметров, которые Snowball может принять при создании класса Stemer. Мы будем использовать только три из них:

    -j[ava] Tell Snowball that we want to generate a Java class
    -n[ame] Tell Snowball the name of the class we want generated
    -o <filename> The filename of the output file. No extension.

Итак, чтобы скомпилировать наш NorwegianExStemmer из нашего измененного файла, мы запускаем:

    ./snowball algorithms/norwegian/stem2_ISO_8859_1.sbl -j -n NorwegianExStemmer -o NorwegianExStemmer

(простите за отличное имя файла stem2…). Это даст вам один новый файл в текущем рабочем каталоге: NorwegianExStemmer.java! Мы на самом деле построили класс-основа! Woohoo! (Вы можете сделать несколько танцевальных движений здесь. Я подожду.)

Теперь мы собираемся вставить новый класс в .jar-файл Lucene contrib.

Перестройте библиотеку Lucene JAR

Скопируйте новый файл класса в версию Lucene, которую вы извлекли из SVN:

    cp NorwegianExStemmer.java <lucenetrunk>/contrib/snowball/src/java/org/tartaru/snowball/ext

Затем нам просто нужно перестроить файл .jar, содержащий все модули:

    cd <lucenetrunk>/contrib/snowball/
    ant jar

Это создаст lucene-snowball-2.9-dev.jar в <lucenetrunk> / build / contrib /. Теперь у вас есть библиотека, содержащая ваш стеммер (и все остальные стеммеры по умолчанию из Lucene)!

В последней части мы просто загружаем обновленную библиотеку stemmer в Solr, и это будет простое копирование и перестройка:

Вставка новой библиотеки Lucene Into Solr

Из каталога build / contrib в Lucene скопируйте файл jar в каталог lib / Solr:

    cp lucene-snowball-2.9-dev.jar <solrtrunk>lib/

Не забудьте перезаписать все существующие файлы (и если у вас есть другая версия Lucene в Solr, выполните полную перестройку и замените все связанные с Lucene файлы в Solr). Восстановить Solr:

    cd <solrtrunk>
    ant dist

Скопируйте новый apache-solr-1.4-dev.war (проверьте правильное имя в каталоге самостоятельно) из каталога build / в Solr на домашние серверы приложений как solr.war (.. если вы используете другое имя, используйте его) , Это веб-приложения / если вы используете Tomcat. Не забудьте сделать резервную копию старого файла .war, просто чтобы быть уверенным, что вы можете восстановить все, если вы что-то испортили.

Добавьте свой новый Stemmer в schema.xml

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

Обычное место для добавления стеммера — это определение ваших текстовых полей в разделах <analyzer> для индекса и запроса (не забудьте изменить его ОБА мест !!):

    <filter class="solr.SnowballPorterFilterFactory" language="NorwegianEx" />

Измените NorwegianEx на имя вашего класса (без части Stemmer, Lucene добавляет это для вас автоматически. После изменения обоих местоположений (или более, если у вас есть пользовательские типы данных и шаги индексации или запроса).

Перезапустите сервер приложений и переиндексируйте!

Если вы используете Tomcat в качестве сервера приложений, это может быть просто (в зависимости от вашей настройки и распространения):

    cd /path/to/tomcat/bin
    ./shutdown.sh
    ./startup.sh

Пожалуйста, обратитесь к документации для вашего сервера приложений для получения информации о том, как сделать правильный перезапуск.

После перезапуска сервера приложений вам нужно будет переиндексировать свою коллекцию, прежде чем все будет работать, как запланировано. Однако вы можете проверить, что ваш стеммер работает так, как вы запланировали уже на этом этапе. Войдите в интерфейс администратора Solr, выберите расширенный / расширенный вид запроса, введите свой запрос (который теперь должен быть обработан иначе, чем раньше), установите флажок «отладка» и отправьте свой поиск. Полученный XML-документ покажет вам результат вашего запроса в элементе parsedquery.

Скачать сгенерированный Stemmer

Если вы просто ищете улучшенный родословный для норвежских слов (с очень, очень простыми изменениями, описанными выше, и которые могут создать проблемы при работе с UTF-8 (… пожалуйста, оставьте комментарий, если это так)), вы можно просто скачать NorwegianExStemmer.java . Следуйте приведенному выше руководству, чтобы добавить его в установку Lucene / Solr.

Пожалуйста, оставьте комментарий, если что-то сбивает с толку или если вам нужна бесплатная помощь. Отправьте мне письмо, если вы ищете консультанта.