Фон
Веб-приложения становятся умнее. Прошли те времена, когда, чтобы воспользоваться услугой с сайта, пользователю пришлось заполнить гигантскую форму. Допустим, у вас есть веб-сайт для любителей книг. До появления веб 2.0 такие сайты, как эти, задавали пользователю все вопросы в форме, например, возраст, книги, которые они читают, типы книг, которые им нравятся, языковые предпочтения, предпочтения авторов и т. Д. В наши дни принято задавать вопросы пользователю: написать абзац на себя (профиль). В этой заметке пользователь выражает некоторые подробности, но проблема в том, как мы извлекаем полезную информацию из такого текста в свободной форме, и более того, как мы находим пользователя, который имеет аналогичный интерес?
Этот вариант использования стал настолько распространенным, что каждый Java-разработчик должен знать некоторые хитрости по извлечению информации из текста. В этой статье я расскажу вам об одном простом, но эффективном способе сделать это.
Процессы извлечения информации из текста
- Фильтр слов : читать текстовое содержание слово за словом и удалять ненужные слова. Как часть этого состояния фильтрации, удалите все часто используемые английские слова. Можно также применять правила цензуры и удалять откровенно сексуальные слова или ненавистнические высказывания и т. Д.
- Выполнить Stemming: слова типа «поиск» или «поиск» или «поиск», которые все означают «поиск». Этот процесс приведения слова к своему корню называется stemming.
- Вычислить сходство : после первых двух шагов у нас теперь есть набор ключевых слов, которые действительно представляют оригинальный текст (профиль пользователя в этом примере). Мы можем рассматривать эти ключевые слова как набор уникальных слов. Чтобы вычислить сходство между двумя пользовательскими профилями, было бы лучше, если бы мы представили сходство в виде числа, которое представляет, насколько сходны два содержимого в масштабе от 0 (не похоже) до 1 (полностью похоже). Одним из способов достижения этого является вычисление индекса Жакара, который используется для вычисления сходства или разнообразия множеств.
1
|
Jaccard index J(A,B) = |A∩B|/| A⋃B| |
где A и B — множества, а J (A, B) лежит в диапазоне от 0 до 1.
Детали реализации
Исходя из изложенных выше моментов, можно разработать библиотеку для извлечения ключевых слов и вычисления сходства. Однако Apache Lucene — это java-библиотека, которая имеет множество API для выполнения извлечения ключевых слов. Вот краткое описание различных важных областей этого API.
Tokenizer
Tokenizer разбивает ваш текст на куски. Существуют разные токенизаторы, и в зависимости от того, какой токенайзер вы используете, вы можете получать разные потоки выходных токенов ( последовательности фрагментов текста).
парадигматические
Стеммеры используются, чтобы получить основу для рассматриваемого слова. Это сильно зависит от используемого языка. Такие слова, как «моряк», «поиск», «поиск» и т. Д. Происходят от корневого слова «поиск». В поле поиска информации очень полезно, если мы доберемся до корневых слов, так как они уменьшают шум, и с меньшим количеством слов мы все еще можем нести цель документа. Одним из известных алгоритмов стеммера является алгоритм Портера Стеммера.
TokenFilter
Tokenfilter может быть применен к выходу токенайзера для нормализации или фильтрации токенов. Как и LowerCaseFilter, который нормализует текст токена в нижний регистр или стоп-фильтр, который подавляет наиболее часто встречающиеся и почти бесполезные слова. Опять же, это сильно зависит от языка. Для английского языка эти стоп-слова — «а», «я», «быть», «иметь» и т. Д.
анализатор
Анализатор — это класс более высокого уровня, который использует токены для получения токенов из входных данных, использует стеммеры для уменьшения токена, использует фильтры для подавления / нормализации токенов. Это класс, который склеивает остальные три основных компонента. Разные анализаторы используют разные комбинации токенизаторов и фильтров. Например, StandardAnalyzer использует StandardTokenizer для извлечения токенов из строки, передает их через LowerCaseFilter для преобразования токенов в нижний регистр, а затем передает поток токенов через StopFilter для удаления наиболее часто используемых английских слов. Он не выполняет стемминг по умолчанию. Можно разработать собственный анализатор, смешивая и подбирая токенизатор и токен-фильтры по необходимости.
Код пройти через
Исходный код этого примера можно получить по адресу https://github.com/shamikm/simility . Ниже приведено описание шагов:
- Создайте собственный анализатор, который выполняет следующие шаги:
- Токенизируйте английские слова на основе пробела, запятой, точки и т. Д. Используйте StandardTokenizer для этой задачи.
- Преобразуйте токены в нижний регистр, используя LowerCaseFilter
- Остановите общие английские слова, используя StopFilter
- Английские слова в стебле с помощью Porter Stemmer
Из класса StemmAnalyzer:
12345678@Override
public
TokenStream tokenStream(String fieldName, Reader reader) {
(a)..
final
StandardTokenizer src =
new
StandardTokenizer(matchVersion, reader);
TokenStream tok =
new
StandardFilter(matchVersion, src);
(b).. tok =
new
LowerCaseFilter(matchVersion, tok);
(c).. tok =
new
StopFilter(matchVersion, tok, getStopWords());
(d)..
return
new
PorterStemFilter(tok);
}
- Когда у нас есть набор слов, легко вычислить сходство между двумя наборами.
Из класса JaccardIndexBasedSogeneity:
12345678public
double
calculateSimilarity(String oneContent, String otherContet) {
Set<String> keyWords1 = keywordGenerator.generateKeyWords(oneContent);
Set<String> keyWords2 = keywordGenerator.generateKeyWords(otherContet);
Set<String> denominator = Sets.union(keyWords1,keyWords2);
Set<String> numerator = Sets.intersection(keyWords1,keyWords2);
return
denominator.size()>
0
? (
double
)numerator.size()/(
double
)denominator.size() :
0
;
}
Вот пример тестового примера, чтобы продемонстрировать, как работает код:
1
2
3
4
5
6
7
8
|
@Test public void calculateSim(){ SimilarityCalculator calculator = new JaccardIndexBasedSimilarity(); Assert.assertEquals(calculator.calculateSimilarity( "They Licked the platter clean" , "Jack Sprat could eat no fat" ), 0.0 ); //1(lamb) out of 6(littl,lamb,mari,had,go,sure) words are same Assert.assertEquals(calculator.calculateSimilarity( "Mary had a little lamb" , "The lamb was sure to go." ), 0.16 , 0.02 ); Assert.assertEquals(calculator.calculateSimilarity( "Mary had a little lamb" , "Mary had a little lamb" ), 1.0 ); } |
Вы можете запустить этот процесс в автономном режиме и узнать, как один профиль пользователя похож на других пользователей в вашей базе данных, и начать рекомендовать пользователей на основе того, что читают подобные пользователи.
Вывод
Извлечение информации из текста является распространенным случаем в наши дни. Наличие базовых знаний в этой критической области полезно для любого разработчика, и в этой статье мы рассмотрели, как можно эффективно использовать API Apache Lucene для извлечения ключевых слов и вычисления сходства текста.