Что является хорошей мерой для классификации текстовых документов?

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

Вот пример с двумя текстовыми статьями:

  • Статья I) «Лиса перепрыгивает через другую лису».
  • Статья II) «Охотник увидел лису».

Статья I разбивается на слова (после выделения и удаления стоп-слов):

  • ["лиса", "прыжок", "другая", "лиса"].

Статья II разбивается на слова:

  • ["охотник", "см.", "лиса"].

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

  • fox (частота слов: 3, частота документов: 2)
  • jump (частота слов: 1, частота документов: 1)
  • another (частота слов: 1, частота документов: 1)
  • hunter (частота слов: 1, частота документов: 1)
  • see (частота слов: 1, частота документов: 1)

Учитывая новую текстовую статью, как мне измерить, насколько эта статья похожа на предыдущие статьи?

Я читал о мере df-idf, но здесь она не применяется, так как я пропускаю стоп-слова, поэтому такие слова, как «a» и «the», не отображаются в счетчиках.

Например, у меня есть новая текстовая статья, в которой говорится, что «охотники любят лис», как мне придумать показатель, который говорит, что эта статья очень похожа на предыдущие?

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

Я предполагаю, что мне каким-то образом нужно суммировать значения частотомера слов и частоты документов, но какую хорошую формулу использовать?


person bodacydo    schedule 10.05.2018    source источник


Ответы (7)


Стандартным решением является применение наивного байесовского классификатора, который оценивает апостериорную вероятность класса C для данного документа D, обозначаемого как P(C=k|D ) (для задачи бинарной классификации k=0 и 1).

Это оценивается путем вычисления априорных значений из обучающего набора документов с пометкой класса, где для документа D мы знаем его класс C.

P(C|D) = P(D|C) * P(D)              (1)

Наивный Байес предполагает, что члены независимы, и в этом случае вы можете написать P (D | C) как

P(D|C) = \prod_{t \in D} P(t|C)     (2)

P(t|C) можно просто вычислить, подсчитав, сколько раз термин встречается в данном классе, например, вы ожидаете, что слово футбол будет встречаться большое количество раз в документах, относящихся к классу (категории) спорт.

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

В уравнение (1) очень легко включить такие факторы, как важность термина (idf) или зависимость термина. Для idf вы добавляете его как событие выборки терминов из коллекции (независимо от класса). Для зависимости от термина вы должны добавить вероятности в форме P(u|C)*P(u|t), что означает, что вы выбираете другой термин u и изменить (преобразовать) его на t.

Стандартные реализации наивного байесовского классификатора можно найти в Пакет Stanford NLP, Weka и < href="http://scikit-learn.org/stable/modules/naive_bayes.html" rel="noreferrer">Scipy среди многих других.

person Debasis    schedule 10.05.2018
comment
Отличный ответ! Интересно, если бы у меня был только один класс, что бы тогда изменилось. Мне нужно будет установить пороговое значение для P(D|C), которое будет определять, принадлежит ли документ этому единственному классу C. Это правильно? - person bodacydo; 11.05.2018
comment
да, пороговое значение было бы одним из способов сделать это ... даже если у вас есть только один класс (например, спорт), вы можете рассматривать другой как дополнительный класс (например, не спорт) - и затем во время теста вы определяете, какие из них принадлежат к классу и какие из них являются выбросами... - person Debasis; 11.05.2018
comment
Я реализовал это решение, но есть некоторые серьезные проблемы. Не могли бы вы помочь их решить? Первая проблема заключается в том, что я использую только TF и ​​не использую DF, поэтому я использую только частичную информацию. Как я могу включить DF в уравнение (без использования IDF)? Возможно, сумма TF * DF? Вторая проблема заключается в том, как мне нормализовать эту оценку между 0 и 1. В моем случае, когда я умножаю все TF вместе, она увеличивается до чего-то вроде 8900 или 11854 — очень большое число для более длинных документов. Третья проблема длинная. документы соответствуют всем словам, поэтому окончательное значение является астрономическим, поскольку оно является продуктом всех TF. Также аналогичная проблема для коротких документов. - person bodacydo; 12.05.2018
comment
Для первой проблемы - определите P(t|C) = lambda * tf(t,d)/длина документа(d) + (1-лямбда) * частота сбора (t)/общее количество токенов в коллекции... вы можете замените частоту сбора на частоту документа (DF), и это даст вам аналогичные результаты... Это решает вашу вторую проблему, потому что эти значения находятся между [0,1] (и их линейная комбинация). - person Debasis; 13.05.2018
comment
Об умножении - вместо вычисления P(D|C) - вычислить log(P(D|C)), и в этом случае умножения будут преобразованы в логарифмические суммирования, и не будет переполнения... - person Debasis; 13.05.2018
comment
Третья проблема будет решена с нормализацией df.... чтобы облегчить проблему, рассмотрите возможность дальнейшего удаления стоп-слов (слов с очень высокими значениями df, потому что они, вероятно, не будут информативными)... - person Debasis; 13.05.2018
comment
Спасибо за ваш ответ @Debasis. Я реализую это. Последний вопрос, который у меня есть, заключается в том, что такое лямбда в формуле P(t|C)? - person bodacydo; 13.05.2018
comment
lambda - это параметр линейной комбинации - относительная важность, которую вы хотите придать tf по сравнению с idf... - person Debasis; 14.05.2018

Кажется, вы пытаетесь ответить на несколько связанных вопросов:

  1. Как измерить сходство между документами A и B? (метрическое обучение)
  2. Как измерить, насколько необычен документ C по сравнению с некоторой коллекцией документов? (Обнаружение аномалии)
  3. Как разбить коллекцию документов на группы похожих? (кластеризация)
  4. Как предсказать, к какому классу относится документ? (Классификация)

Все эти проблемы обычно решаются в 2 этапа:

  1. Извлеките функции: Документ --> Представление (обычно числовой вектор)
  2. Примените модель: Представление --> Результат (обычно одно число)

Существует множество вариантов как для разработки функций, так и для моделирования. Здесь только несколько.

Извлечение признаков

  1. Пакет слов: документ --> количество вхождений каждого отдельного слова (то есть частота терминов). Это базовый вариант, но не единственный.
  2. Сумка n-грамм (на уровне слов или символов): учитывается совместное появление нескольких токенов.
  3. Набор слов + грамматические особенности (например, POS-теги)
  4. Набор вложений слов (изучаемых внешней моделью, например word2vec). Вы можете использовать встраивание как последовательность или взять их средневзвешенное значение.
  5. Все, что вы можете изобрести (например, правила, основанные на поиске по словарю)...

Объекты могут быть предварительно обработаны, чтобы уменьшить относительное количество шума в них. Некоторые варианты предварительной обработки:

  • деление на IDF, если у вас нет жесткого списка стоп-слов или вы считаете, что слова могут быть более или менее «стоп-словами»
  • нормализация каждого столбца (например, количество слов), чтобы иметь нулевое среднее значение и единичную дисперсию
  • вести журналы подсчета слов, чтобы уменьшить шум
  • нормализация каждой строки, чтобы иметь норму L2, равную 1

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

Теперь вы можете построить модель машинного обучения. Каждая из 4 проблем имеет свои хорошие решения.

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

Большинство этих моделей могут использовать практически любые функции. Однако KNN и SVM на основе ядра требуют, чтобы ваши функции имели особую структуру: представления документов одного класса должны быть близки друг к другу в смысле метрики евклидова расстояния. Иногда этого можно добиться простой линейной и/или логарифмической нормализацией (см. выше). Более сложные случаи требуют нелинейных преобразований, которые в принципе могут быть изучены нейронными сетями. Изучение этих преобразований это то, что люди называют метрическим обучением, и в целом это проблема, которая еще не решена.

Самая обычная метрика расстояния действительно евклидова. Однако возможны и другие метрики расстояния (например, манхэттенское расстояние) или другие подходы, не основанные на векторных представлениях текстов. Например, вы можете попытаться вычислить расстояние Левенштейна между текстами на основе подсчета количества операций, необходимых для преобразования одного текста в другой. Или вы можете рассчитать «расстояние перемещения слов» - сумму расстояний пар слов с ближайшими вложениями.

Для кластеризации основными параметрами являются K-средние и DBScan. Обе эти модели требуют, чтобы ваше функциональное пространство обладало этим евклидовым свойством.

Для обнаружения аномалий можно использовать оценки плотности, полученные с помощью различных вероятностных алгоритмов: классификации (например, наивного Байеса или нейронных сетей), кластеризации (например, смеси гауссовых моделей) или других неконтролируемых методов (например, вероятностных). СПС). Для текстов вы можете использовать последовательную языковую структуру, оценивая вероятность каждого слова в зависимости от предыдущих слов (используя n-граммы или сверточные/рекуррентные нейронные сети) — это называется языковыми моделями, и это обычно более эффективен, чем предположение Наивного Байеса о наборе слов, которое игнорирует порядок слов. Несколько языковых моделей (по одной на каждый класс) могут быть объединены в один классификатор.

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

Если у вас нет ресурсов или желания проводить несколько экспериментов, я бы рекомендовал выбрать один из следующих подходов для оценки сходства между текстами:

  • количество слов + нормализация idf + нормализация L2 (эквивалентно решению @mcoav) + евклидово расстояние
  • среднее вложение word2vec по всем словам в тексте (словарь встраивания можно найти в Google и скачать) + евклидово расстояние

На основе одного из этих представлений вы можете строить модели для других задач, например. KNN для классификаций или k-средних для кластеризации.

person David Dale    schedule 17.05.2018

Я бы предложил tf-idf и подобие косинуса.

Вы по-прежнему можете использовать tf-idf, если не используете стоп-слова. Возможно даже, что то, включаете вы стоп-слова или нет, не будет иметь такого значения: мера обратной частоты документа автоматически занижает стоп-слова, поскольку они очень часты и появляются в большинстве документов.

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

person mcoav    schedule 10.05.2018
comment
Дело в том, что если я использую IDF в своем исходном примере, то слово fox становится бессмысленным (пониженным), но это очень важный термин в моем примере, а не стоп-слово. Вот почему я задавался вопросом о IDF. - person bodacydo; 11.05.2018
comment
Наивный Байес может работать с нормализованными подсчетами tf-tdf, а не только с нормализованными подсчетами tf... - person Debasis; 11.05.2018
comment
ЦАХАЛ будет иметь больше смысла в большом сборнике статей/документов. Он наказывает термины, которые встречаются в большинстве документов: на практике эти термины в основном являются стоп-словами. Если ваша коллекция достаточно велика, IDF fox будет намного выше, чем в вашем игрушечном примере (добавьте к вашему примеру 10 документов, не содержащих fox, и fox не будет занижен). - person mcoav; 11.05.2018
comment
Спасибо @mcoav. Я реализовал решение, которое представляет собой сумму tf * df - оно умножает количество терминов на количество документов. Есть идеи, хорошо это или нет? Я вообще не использую idf, так как у меня нет стоп-слов, а часто встречающиеся термины важны, поэтому нет необходимости менять их вес. - person bodacydo; 12.05.2018
comment
Я не думаю, что умножение на DF (в отличие от использования только TF) поможет на этом этапе, так как часто встречающиеся слова уже подчеркнуты TF, опять же, лучший способ убедиться в этом — попробовать оба метода. - person mcoav; 14.05.2018

Когда я ищу по df-idf, я ничего не нахожу.

tf-idf с косинусное сходство является общепринятой и общепринятой практикой.

Фильтрация стоп-слов не нарушает его. Для общих слов idf в любом случае придает им низкий вес.

tf-idf используется Lucene< /а>.

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

Не понимаю, почему вы думаете, что сумма df idf является мерой сходства.

Для классификации у вас есть какие-то предопределенные классы и образцы документов, на которых можно учиться? Если это так, можно использовать Наивный Байес. С tf-idf.

Если у вас нет предопределенных классов, вы можете использовать k означает кластеризацию. С tf-idf.

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

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

person paparazzo    schedule 18.05.2018
comment
@AlexOtt Вот почему я сказал tf-idf, так как не был уверен в сходстве. Мой основной аргумент остается прежним. Используйте то, что является стандартной практикой, а не начинайте сначала. Они не используют tf-idf? - person paparazzo; 18.05.2018

Вы оценили sent2vec или doc2vec подходы? Вы можете поиграть с векторами, чтобы увидеть, насколько близки предложения. Просто идея. Не проверенное решение вашего вопроса.

person rishi    schedule 19.05.2018

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

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

Вам нужно найти самые важные слова в тексте. Затем нужно отловить их возможные синонимы.

В этом может помочь следующий api. Можно создать что-то подобное с некоторыми словарями.

synonyms("complex")

function synonyms(me){
  var url = 'https://api.datamuse.com/words?ml=' + me;
  fetch(url).then(v => v.json()).then((function(v){
    syn = JSON.stringify(v)
    syn = JSON.parse(syn)
    for(var k in syn){
      document.body.innerHTML += "<span>"+syn[k].word+"</span> "
      }
    })
  )
}

Оттуда сравнение массивов даст гораздо большую точность, гораздо меньше ложных срабатываний.

person NVRM    schedule 18.05.2018

Достаточное решение, возможно, в аналогичной задаче:

  • Использование подхода бинарного набора слов (BOW) для векторного представления (часто встречающиеся слова не имеют более высокого веса, чем редко встречающиеся слова), а не реальный подход TF.

  • Подход встраивания "word2vec" чувствителен к эффектам последовательности и расстояний. В зависимости от ваших гиперпараметров это может привести к разнице между «охотник увидел лису» и «лиса увидел прыгающего охотника»… так что вы должны решить, означает ли это добавление шума к вашей задаче — или, в качестве альтернативы, чтобы использовать его только как усредненный вектор по всему вашему тексту

  • Извлечение слов с высокой корреляцией внутри предложения (например, с помощью переменных-средних-нормализованных-косинусных сходств)

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

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

person Roland Bischof    schedule 18.05.2018