Классификация документов в категории

Я имею о 300k документах, хранивших в базе данных Postgres, которые отмечены с категориями темы (существует приблизительно 150 категорий всего). У меня есть другой 150k документы, которые еще не имеют категорий. Я пытаюсь найти, что лучший способ к programmaticly категоризирует их.

Я исследовал NLTK и его наивный классификатор Байеса. Походит на хорошую начальную точку (если можно предложить лучший алгоритм классификации для этой задачи, я внимательно слушаю).

Моя проблема состоит в том, что у меня нет достаточного количества RAM для обучения NaiveBayesClassifier на всех 150 categoies/300k документах сразу (обучение на 5 категориях использовало 8 ГБ). Кроме того, точность классификатора, кажется, отбрасывает, поскольку я обучаюсь на большем количестве категорий (90%-я точность с 2 категориями, 81% с 5, 61% с 10).

Я должен просто обучить классификатор на 5 категориях за один раз и выполнить все 150k документы через классификатор, чтобы видеть, существуют ли соответствия? Кажется, что это работало бы, за исключением того, что будет много ложных положительных сторон, где документы, которые действительно не соответствуют ни одной из категорий, становятся с рогами обуви в на классификатором просто, потому что это - лучшее доступное соответствие... Существует ли способ не иметь "ни одной из вышеупомянутой" опции для классификатора на всякий случай, документ не вписывается ни в одну из категорий?

Вот является мой тестовый класс http://gist.github.com/451880

32
задан merv 10 April 2019 в 21:32
поделиться

3 ответа

Вы должны начать с преобразования ваших документов в TF-log(1 + IDF) векторы: частоты терминов разрежены, поэтому вы должны использовать python dict с term в качестве ключей и count в качестве значений, а затем разделить на общее количество, чтобы получить глобальные частоты.

Другое решение - использовать, например, abs(hash(term)) в качестве положительных целочисленных ключей. Тогда вы можете использовать scipy.sparse vectors, которые более удобны и эффективны для выполнения операций линейной алгебры, чем python dict.

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

Если этого недостаточно, то вам следует попробовать обучить модель логистической регрессии, используя штраф L1, как объясняется в этом примере из scikit-learn (это обертка для liblinear, как объяснил @ephes). Векторы, используемые для обучения вашей модели логистической регрессии, должны быть векторами TD-log(1+IDF), представленными ранее, чтобы получить хорошую производительность (точность и отзыв). Либ scikit learn предлагает модуль sklearn.metrics с процедурами для вычисления этих показателей для данной модели и данного набора данных.

Для больших наборов данных: вам стоит попробовать vowpal wabbit, который, вероятно, является самым быстрым кроликом на земле для решения крупномасштабных задач классификации документов (но для него не так просто использовать обертку из python, AFAIK).

32
ответ дан 27 November 2019 в 21:00
поделиться

Есть ли способ, чтобы выше "вариант для классификатора просто в случае, если документ не помещается в любой из категорий?

Вы можете получить этот эффект, просто тренируя псевдокатегорию «ничего из вышеперечисленного» каждый раз. Если максимум, который вы можете обучить, составляет 5 категорий (хотя я не уверен, почему он съедает так много оперативной памяти), тренируйте 4 фактические категории из их фактических документов размером 2 КБ каждая и одну «ни одну из вышеперечисленных» с ее документами 2 КБ. взяты случайным образом из всех остальных 146 категорий (примерно по 13-14 из каждой, если вам нужен подход «стратифицированной выборки», который может быть более разумным).

По-прежнему кажется немного запутанным, и вам может быть лучше использовать совершенно другой подход - найдите многомерный документ, который определяет ваши 300K предварительно помеченные документы в 150 разумно разделимых кластеров, а затем просто назначьте каждый из другие, еще не помеченные документы, в соответствующий кластер, как определено таким образом. Я не думаю, что у NLTK есть что-то прямо доступное для поддержки такого рода вещей, но, эй, NLTK растет так быстро, что я вполне мог что-то пропустить ...; -)

2
ответ дан 27 November 2019 в 21:00
поделиться

Насколько велики (количество слов) ваши документы? Потребление памяти при 150K учебных документов не должно быть проблемой.

Naive Bayes - хороший выбор, особенно когда у вас много категорий с небольшим количеством обучающих примеров или очень шумные обучающие данные. Но в целом линейные машины с опорными векторами работают гораздо лучше.

Является ли ваша проблема многоклассовой (документ принадлежит только одной категории) или многопометной (документ принадлежит одной или нескольким категориям)?

Точность - плохой выбор для оценки работы классификатора. Лучше использовать кривые precision vs recall, precision recall breakeven point (prbp), f1, auc и посмотреть на кривую precision vs recall, где recall (x) строится против precision (y) на основе значения порога доверия (принадлежит ли документ к категории или нет). Обычно вы строите один бинарный классификатор для каждой категории (положительные обучающие примеры одной категории против всех остальных обучающих примеров, которые не принадлежат к текущей категории). Вам придется выбрать оптимальный порог доверия для каждой категории. Если вы хотите объединить эти отдельные показатели по категориям в глобальный показатель эффективности, вам придется провести микро- (суммировать все истинно положительные, ложно положительные, ложно отрицательные и истинно отрицательные результаты и рассчитать комбинированные показатели) или макро- (рассчитать показатели по каждой категории, а затем усреднить их по всем категориям) усреднение.

У нас есть корпус из десятков миллионов документов, миллионы обучающих примеров и тысячи категорий (multilabel). Поскольку мы сталкиваемся с серьезными проблемами времени обучения (количество новых, обновленных или удаленных документов в день довольно велико), мы используем модифицированную версию liblinear. Но для решения небольших задач вполне подойдет одна из python-оберток вокруг liblinear (liblinear2scipy или scikit-learn).

11
ответ дан 27 November 2019 в 21:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: