Какие проверенные и правдивые алгоритмы для предложения связанных статей существуют?

StackOverflow https://stackoverflow.com/questions/1254627

Вопрос

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

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

Как вы находите, возможно, связанные документы?

Меня довольно заинтересован в реальном алгоритме, не готовых решениях, хотя я был бы в порядке с взглядом на что -то реализованное в Ruby или Python, или полагаться на MySQL или PGSQL.

редактировать: Текущий ответ довольно хороший, но я хотел бы увидеть больше. Может быть, какой -то действительно голый пример кода для вещи или двух.

Это было полезно?

Решение

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

Самый простой подход называется пакет слов. Анкет Каждый документ сводится к редкому вектору {word: wordcount} Пары, и вы можете бросить Naivebayes (или какой-то другой) классификатор на наборе векторов, который представляет ваш набор документов, или вычислить оценки сходства между каждой сумкой и любой другой сумкой (это называется классификацией K-nearest-neighbour). KNN быстро для поиска, но требует o (n^2) хранения для матрицы счетов; Однако для блога N не очень большой. Для чего-то размера большой газеты KNN быстро становится непрактичным, поэтому алгоритм классификации на лету иногда лучше. В этом случае вы можете рассмотреть векторная машина ранжирования. Анкет SVM являются аккуратными, потому что они не ограничивают вас линейными показателями сходства и все еще довольно быстро.

Stemming является общим шагом предварительной обработки для методов сумки слоя; Это включает в себя уменьшение морфологически связанных слов, таких как «кошка» и «кошки», «Боб» и «Боба» или «похожие» и «аналогично», вплоть до их корней, прежде чем вычислять мешок слов. Есть куча разных алгоритмов Stemming там; На странице Википедии есть ссылки на несколько реализаций.

Если сходство пакета слов недостаточно, вы можете абстрагировать его слой с сходством сумки-n-грамма, где вы создаете вектор, который представляет документ, основанный на парах или тройках слов. (Вы можете использовать 4-й или даже более крупные кортежи, но на практике это мало помогает.) Это имеет недостаток в создании гораздо больших векторов, а классификация, соответственно, займет больше работы, но матчи, которые вы получаете, будут намного ближе синтаксически. OTOH, вам, вероятно, не нужно это для семантического сходства; Это лучше для таких вещей, как обнаружение плагиата. Канкинг, или уменьшение документа до легких деревьев разбора, также можно использовать (есть алгоритмы классификации для деревьев), но это более полезно для таких вещей, как проблема авторства («Учитывая документ неизвестного происхождения, кто его написал?») Анкет

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

Наконец, есть Дискурс анализация, который включает в себя диапазон документов для их семантической структуры; Вы можете запускать классификаторы сходства на деревьях дискурса так же, как и в документах.

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

Другие советы

Это типичный случай Классификация документов который изучается в каждом классе машинного обучения. Если вам нравится статистика, математика и компьютерные науки, я рекомендую вам взглянуть на неконтролируемые методы, такие как Kmeans ++, Байесовские методы а также LDA. Анкет В частности, байесовские методы вполне нормально На что вы ищете, их единственная проблема - медленная (но если вы не запускаете очень большой сайт, это не должно вас беспокоить).

При более практичном и менее теоретическом подходе я рекомендую вам посмотреть это а также это другое Отличные примеры кода.

Вам следует прочитать книгу «Коллективный интеллект программирования: создание приложений Smart Web 2.0» (ISBN 0596529325)!

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

Видеть Кластерный анализ / раздельная кластеризация.

Очень простой (но теоретический и медленный) метод для поиска непосредственный сходство будет:

Предварительная обработка:

  1. Храните список плоских слов за статью (не удаляйте дублирующие слова).
  2. «Крест присоединиться» Статьи: количество слов в статье A, которые соответствуют тем же словам в статье B. У вас теперь есть матрица int word_matches[narticles][narticles] (Вы не должны хранить это так, сходство A-> B-это то же самое, что B-> a, поэтому разреженная матрица спасает почти половину пространства).
  3. Нормализуйте счет word_matches до диапазона 0..1! (Найдите Макс Подсчет, затем разделите любое количество за этим) - вы должны хранить поплавки, а не INT;)

Найдите подобные статьи:

  1. Выберите X статьи с самыми высокими совпадениями из Word_Matches

Небольшая поисковая система вектора-пространственно-модели в Ruby. Основная идея заключается в том, что два документа связаны, если они содержат одинаковые слова. Таким образом, мы подсчитываем возникновение слов в каждом документе, а затем вычисляем косинус между этими векторами (каждый термин имеет фиксированный индекс, если кажется, есть 1 в этом индексе, если не ноль). Косинус будет 1,0, если два документа имеют все общие условия, и 0,0, если у них нет общих терминов. Вы можете напрямую перевести это на % значений.

terms = Hash.new{|h,k|h[k]=h.size}
docs = DATA.collect { |line| 
  name = line.match(/^\d+/)
  words = line.downcase.scan(/[a-z]+/)
  vector = [] 
  words.each { |word| vector[terms[word]] = 1 }
  {:name=>name,:vector=>vector}
}
current = docs.first # or any other
docs.sort_by { |doc| 
  # assume we have defined cosine on arrays
  doc[:vector].cosine(current[:vector]) 
}
related = docs[1..5].collect{|doc|doc[:name]}

puts related

__END__
0 Human machine interface for Lab ABC computer applications
1 A survey of user opinion of computer system response time
2 The EPS user interface management system
3 System and human system engineering testing of EPS
4 Relation of user-perceived response time to error measurement
5 The generation of random, binary, unordered trees
6 The intersection graph of paths in trees
7 Graph minors IV: Widths of trees and well-quasi-ordering
8 Graph minors: A survey

Определение Array#cosine остается в качестве упражнения для читателя (должен иметь дело с значениями NIL и различными длины, но хорошо для этого мы получили Array#zip Правильно?)

Кстати, примеры документов взяты из бумаги SVD Deerwester et al :)

Некоторое время назад я реализовал что -то похожее. Может быть, эта идея теперь устарела, но я надеюсь, что это может помочь.

Я запустил веб -сайт ASP 3.0 для программирования общих задач и начал с этого принципа: пользователь имеет сомнения и останусь на веб -сайте, пока он/она может найти интересный контент по этому вопросу.

Когда прибыл пользователь, я запустил ASP 3.0 Session Объект и записал всю навигацию пользователей, как связанный список. В Session.OnEnd Событие, я беру первую ссылку, ищу следующую ссылку и увеличил столбец, такой как:

<Article Title="Cookie problem A">
    <NextPage Title="Cookie problem B" Count="5" />
    <NextPage Title="Cookie problem C" Count="2" />
</Article>

Итак, чтобы проверить связанные статьи, мне просто пришлось перечислить топ не NextPage сущности, упорядоченные с нисходящим столбцом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top