Вопрос

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

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

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

Должен ли я просто тренировать классификатор по 5 категориям за раз и запускать все 150 тыс. Документов через классификатор, чтобы увидеть, есть ли совпадения? Похоже, что это сработает, за исключением того, что было бы много ложных срабатываний, где документы, которые на самом деле не соответствуют ни одной из категорий, впадают в обувную классификатор только потому, что это лучшее, что можно ... Способ иметь вариант «ни одного из вышеперечисленных» для классификатора на случай, если документ не вписывается ни в какую категории?

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

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

Решение

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

Другое решение состоит в том, чтобы использовать ABS (хэш (термин)), например, в качестве положительных целочисленных ключей. Затем вы используете векторы Scipy.sparse, которые более удобны и эффективны для выполнения линейной работы алгебры, чем Python DICT.

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

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

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

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

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

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

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

Точность - это плохой выбор для оценки классификатора. Вы должны скорее использовать точность VS, отзыв, точный отзыв о безубыточной точке (PRBP), F1, AUC и должен смотреть на кривую точность и отзыв, где отзыв (x) нанесен на график против точности (y) на основе значения вашей достоверности-напорош. (Документ относится к категории или нет). Обычно вы создаете один двоичный классификатор по категории (положительные примеры обучения одной категории против всех других учебных заведений, которые не принадлежат вашей текущей категории). Вам придется выбрать оптимальный порог достоверности в соответствии с категорией. Если вы хотите объединить эти единственные меры по категории в глобальную меру эффективности, вам придется микро (суммировать все истинные позитивы, ложные срабатывания, ложные отрицательные и истинные негативы и комбинированные оценки) или макрос (оценка по категории и категории и затем средние эти оценки по всем категориям) в среднем.

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

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

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

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

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