Использование разреженных матриц/онлайн-обучения в Наивном Байесе (Python, scikit)

Я пытаюсь использовать Наивный Байес для набора данных, который содержит более 6 000 000 записей, и каждая запись содержит 150 тыс. функций. Я попытался реализовать код по следующей ссылке: Реализация Классификатор Bag-of-Words Naive-Bayes в NLTK

Проблема в том (насколько я понимаю), что когда я пытаюсь запустить метод поезда с параметром dok_matrix, он не может найти iterkeys (я соединил строки с OrderedDict в качестве меток):

Traceback (most recent call last):
  File "skitest.py", line 96, in <module>
    classif.train(add_label(matr, labels))
  File "/usr/lib/pymodules/python2.6/nltk/classify/scikitlearn.py", line 92, in train
    for f in fs.iterkeys():
  File "/usr/lib/python2.6/dist-packages/scipy/sparse/csr.py", line 88, in __getattr__
    return _cs_matrix.__getattr__(self, attr)
  File "/usr/lib/python2.6/dist-packages/scipy/sparse/base.py", line 429, in __getattr__
    raise AttributeError, attr + " not found"
AttributeError: iterkeys not found

Мой вопрос: есть ли способ избежать использования разреженной матрицы, обучая запись классификатора за записью (онлайн), или есть формат разреженной матрицы, который я мог бы эффективно использовать в этом случае вместо dok_matrix? Или я упускаю что-то очевидное?

Спасибо за чье-то время. :)

РЕДАКТИРОВАТЬ, 6 сентября:

Нашел iterkeys, так что по крайней мере код работает. Это все еще слишком медленно, так как потребовалось несколько часов с набором данных размером 32 КБ и до сих пор не завершено. Вот что я получил на данный момент:

matr = dok_matrix((6000000, 150000), dtype=float32)
labels = OrderedDict()

#collect the data into the matrix

pipeline = Pipeline([('nb', MultinomialNB())])
classif = SklearnClassifier(pipeline)

add_label = lambda lst, lab: [(lst.getrow(x).todok(), lab[x])
                              for x in xrange(lentweets-foldsize)] 

classif.train(add_label(matr[:(lentweets-foldsize),0], labels))
readrow = [matr.getrow(x + foldsize).todok() for x in xrange(lentweets-foldsize)]
data = np.array(classif.batch_classify(readrow))

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


person user1638859    schedule 31.08.2012    source источник
comment
Возможно, вы сможете более эффективно кодировать свои функции или уменьшить их размер?   -  person piokuc    schedule 01.09.2012
comment
правда, но сколько бы ни было функций, боюсь, мне все равно придется управлять размером матрицы. Набор данных состоит из слов твитов.   -  person user1638859    schedule 01.09.2012
comment
По крайней мере, нашел iterkeys, теперь проблема в том, что код слишком медленный.   -  person user1638859    schedule 06.09.2012
comment
Вам нужно сделать это в Python? Взгляните на MALLET: mallet.cs.umass.edu, это довольно быстро.   -  person piokuc    schedule 06.09.2012
comment
Python как таковой не нужен, но у нас есть люди, знакомые с ним. спасибо, я проверю это. Тем не менее, я полагаю, что было бы неплохо получить окончательное решение для больших наборов данных, чтобы любой, кто загуглит эту проблему, нашел здесь ответ.   -  person user1638859    schedule 07.09.2012
comment
Конечно. Кстати, есть интерфейс NLTK для MALLET, поищите его в Google. Я никогда не использовал его, маллет прост в использовании как инструмент командной строки, вы просто подготавливаете ввод (текст) в файлах, используете инструмент командной строки для импорта данных во внутренний формат Маллета, а затем запускаете сам Маллет с подходящие параметры и получать результаты в текстовом формате, но я думаю, что интерфейс Python также полезен.   -  person piokuc    schedule 07.09.2012
comment
Похоже, вы имеете дело с документами длиной в твиты, вы видели libshorttext еще? Я только начал использовать его для классификации корпуса документов размером ~ 10 миллионов твитов, и он очень быстрый и точный (я получаю точность 80-90% с 6 категориями и обучающим набором из около 400 документов). И это написано на Python/C в качестве бонуса! РЕДАКТИРОВАТЬ: и я только что понял, что этой теме почти год   -  person sbrother    schedule 15.05.2013
comment
Эта ссылка может быть полезной: Классификация текста и хэширование функций   -  person ely    schedule 09.10.2013


Ответы (1)


Ознакомьтесь с примером классификации документов в наука-учиться. Хитрость заключается в том, чтобы позволить библиотеке выполнять извлечение функций за вас. Пропустите оболочку NLTK, так как она не предназначена для таких больших наборов данных.(*)

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

from sklearn.feature_extraction.text import TfidfVectorizer
vect = TfidfVectorizer(input='filename')
X = vect.fit_transform(list_of_filenames)

Теперь у вас есть обучающий набор X в формате разреженной матрицы CSR, который вы можете передать в наивный байесовский классификатор, если у вас также есть список меток y (возможно, полученный из имен файлов, если вы закодировали в них класс):

from sklearn.naive_bayes import MultinomialNB
nb = MultinomialNB()
nb.fit(X, y)

Если выяснится, что это не работает, потому что набор документов слишком велик (маловероятно, поскольку TfidfVectorizer был оптимизирован именно для такого количества документов), посмотрите нестандартная классификация документов, демонстрирующий HashingVectorizer и partial_fit API для мини-пакетного обучения. Для этого вам понадобится scikit-learn 0.14.

(*) Я знаю, потому что я написал эту обертку. Как и остальная часть NLTK, он предназначен для образовательных целей. Я также работал над улучшением производительности в scikit-learn, и часть кода, который я рекламирую, принадлежит мне.

person Fred Foo    schedule 09.10.2013
comment
Первая ссылка не работает - person Kosaro; 15.04.2020