Преобразователи Левенштейна принимают термин запроса и возвращают все термины в словаре, которые находятся в пределах n орфографических ошибок от него. Они представляют собой высокоэффективный (пространственно - временной) класс корректоров орфографии, которые очень хорошо работают, когда вам не нужен контекст при внесении предложений. Забудьте о линейном сканировании вашего словаря, чтобы найти все термины, которые достаточно близки к запросу пользователя, используя квадратичную реализацию расстояния Левенштейна или расстояния Дамерау-Левенштейна, эти дети находят все термины из вашего словаря за линейное время длина термина запроса (не от размера словаря, а от длины термина запроса).
Если вам нужен контекст, возьмите кандидатов, сгенерированных преобразователем, в качестве отправной точки и подключите их к любой модели, которую вы используете для контекста (например, выбрав последовательность терминов, которые имеют наибольшую вероятность появления вместе).
Для быстрой демонстрации посетите страницу Github здесь. Также имеется интерфейс командной строки liblevenshtein-java-cli. Пожалуйста, ознакомьтесь с README.md для получения информации о приобретении и использовании.
В настоящее время библиотека написана на Java, CoffeeScript и JavaScript, но в ближайшее время я буду портировать ее на другие языки. Если у вас есть конкретный язык, на котором вы хотели бы его увидеть, или система управления пакетами, в которой вы хотели бы его развернуть, дайте мне знать.
Ветвь | Описание |
---|---|
владелец | Последний, источник разработки |
выпускать | Последний, источник выпуска |
релиз-3.x | Последний исходный код версии 3.x. |
релиз-2.x | Последний исходный код версии 2.x. |
Проблемы решаются на сайте waffle.io. Ниже вы найдете график скорости, с которой я их закрывал.
Пожалуйста, посетите Bountysource, чтобы пообещать свою поддержку в решении текущих проблем.
Когда дело доходит до документации, у вас есть несколько вариантов:
Вики
Javadoc
Исходный код
Либлевенштейн был разработан для Java ≥ 1.8. Он не будет работать с предыдущими версиями.
Добавьте зависимость Maven от Artifactory. Например, в проекте Gradle вы можете изменить свои repositories
следующим образом:
репозитории { знаток { URL-адрес «https://oss.jfrog.org/artifactory/oss-release-local» } }
Добавьте зависимость Maven от одного из следующих:
Мавен Центральный
JЦентр
Бинтрей
<зависимость> <groupId>com.github.universal-automata</groupId> <artifactId>либлевенштейн</artifactId> <версия>3.0.0</версия> </зависимость>
'com.github.universal-automata:liblevenshtein:jar:3.0.0'
<dependent org="com.github.universal-automata" name="liblevenshtein" rev="3.0.0" />
@Виноград( @Grab(group='com.github.universal-automata', модуль='liblevenshtein', version='3.0.0') )
скомпилировать 'com.github.universal-automata:liblevenshtein:3.0.0'
LibraryDependities += "com.github.universal-automata" % "liblevenshtein" % "3.0.0"
[com.github.universal-automata/liblevenshtein "3.0.0"]
% git clone --progress [email protected]:universal-automata/liblevenshtein-java.git Cloning into 'liblevenshtein-java'... remote: Counting objects: 8117, done. remote: Compressing objects: 100% (472/472), done. remote: Total 8117 (delta 352), reused 0 (delta 0), pack-reused 7619 Receiving objects: 100% (8117/8117), 5.52 MiB | 289.00 KiB/s, done. Resolving deltas: 100% (5366/5366), done. Checking connectivity... done. % cd liblevenshtein-java % git pull --progress Already up-to-date. % git fetch --progress --tags % git checkout --progress 3.0.0 Note: checking out '3.0.0'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at 4f0f172... pushd and popd silently % git submodule init % git submodule update
Допустим, у вас есть следующий контент в текстовом файле с именем top-20-most-common-english-words.txt (обратите внимание, что в каждой строке файла содержится один термин):
the be to of and a in that have I it for not on with he as you do at
Следующее предоставляет вам способ запроса его содержимого:
импортировать java.io.InputStream;импортировать java.io.OutputStream;импортировать java.nio.file.Files;импортировать java.nio.file.Path;импортировать java.nio.file.Paths;импортировать com.github.liblevenshtein.collection. словарь.SortedDawg;импорт com.github.liblevenshtein.serialization.PlainTextSerializer;импорт com.github.liblevenshtein.serialization.ProtobufSerializer;импорт com.github.liblevenshtein.serialization.Serializer;импорт com.github.liblevenshtein.transducer.Algorithm;импорт com.github.liblevenshtein.transducer.Candidate;импорт com.github.liblevenshtein.transducer.ITransducer;import com.github.liblevenshtein.transducer.factory.TransducerBuilder;// ...final SortedDawg словарь;final Path словарьPath = Paths.get("/path/to/top-20- Most-common-english-words.txt"); попробуйте (окончательный поток InputStream = Files.newInputStream(dictionaryPath)) { // Конструктор PlainTextSerializer принимает необязательное логическое значение, определяющее // отсортирован ли словарь уже лексикографически, по возрастанию // заказ. Если он отсортирован, то передача true оптимизирует конструкцию. // словаря; вы можете передать false независимо от того, отсортирован ли словарь или // нет (это поведение по умолчанию и самое безопасное, если вы не знаете, // словарь отсортирован). окончательный сериализатор сериализатора = новый PlainTextSerializer(false); словарь = сериализатор.десериализация(SortedDawg.class, поток); } окончательный преобразователь ITransducer<Candidate> = новый TransducerBuilder() .dictionary(словарь) .алгоритм(Алгоритм.ТРАНСПОЗИЦИЯ) .defaultMaxDistance(2) .includeDistance(истина) .build();for (последняя строка queryTerm: new String[] {"foo", "bar"}) { System.out.println("+---------------- -------------------------------------------------- -------------"); System.out.printf("| Варианты написания термина запроса: "%s"%n", queryTerm); System.out.println("+------------------------------------------ -------------------------------------"); for (окончательный кандидат-кандидат: transducer.transduce(queryTerm)) {System.out.printf("| d("%s", "%s") = [%d]%n", queryTerm, Candidate.term() , кандидат.расстояние()); } }// +---------------------------------------------- ---------------------------------// | Варианты написания термина запроса: "foo"// +-------------------------------------- -----------------------------------------// | d("foo", "do") = [2]// | d("foo", "of") = [2]// | d("foo", "on") = [2]// | d("foo", "to") = [2]// | d("foo", "for") = [1]// | d("foo", "не") = [2]// | d("foo", "ты") = [2]// +---------------------------------- ----------------------------------------------// | Варианты написания термина запроса: "bar"// +-------------------------------------- -----------------------------------------// | d("бар", "а") = [2]// | d("бар", "as") = [2]// | d("бар", "at") = [2]// | d("бар", "быть") = [2]// | d("бар", "за") = [2]// ...
Если вы хотите сериализовать свой словарь в формат, который будет легко читать позже, сделайте следующее:
окончательный путь сериализованныйDictionaryPath = Paths.get("/path/to/top-20-most-common-english-words.protobuf.bytes");try (окончательный поток OutputStream = Files.newOutputStream(serializedDictionaryPath)) { окончательный сериализатор Serializer = новый ProtobufSerializer(); сериализатор.serialize(словарь, поток); }
Затем вы сможете прочитать словарь позже, почти так же, как вы читаете текстовую версию:
окончательный SortedDawg deserializedDictionary; попробуйте (окончательный поток InputStream = Files.newInputStream(serializedDictionaryPath)) { окончательный сериализатор Serializer = новый ProtobufSerializer(); deserializedDictionary = seriesizer.deserialize(SortedDawg.class, поток); }
Сериализация не ограничивается словарями, вы также можете (де) сериализовать преобразователи.
Пожалуйста, смотрите вики для более подробной информации.
Эта библиотека во многом основана на работе Стояна Михова, Клауса Шульца и Петра Николаева Митанкина: Быстрая коррекция струн с помощью автоматов Левенштейна. Для получения дополнительной информации, пожалуйста, посетите вики.
liblevenshtein-java поддерживается @dylon ([email protected]).