Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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

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