2012-08-31 26 views
5

Estoy tratando de hacer Naive Bayes en un conjunto de datos que tiene más de 6,000,000 de entradas y cada entrada contiene 150k. He tratado de poner en práctica el código desde el siguiente enlace: Implementing Bag-of-Words Naive-Bayes classifier in NLTKUso de matrices dispersas/aprendizaje en línea en Naive Bayes (Python, scikit)

El problema es (como yo lo entiendo), que cuando trato de ejecutar el tren-método con una dok_matrix ya que es el parámetro, no puede encontrar iterkeys (he emparejado con las filas OrderedDict como etiquetas):

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 

Mi pregunta es, ¿hay una manera de evitar su utilización de una matriz dispersa mediante la enseñanza de la entrada clasificador por la entrada (en línea), o hay una escasa formato de matriz que podría usar en este caso de manera eficiente en lugar de dok_matrix? ¿O me estoy perdiendo algo obvio?

Gracias por el tiempo de cualquier persona. :)

EDITAR, 6 de septiembre:

encontrado la iterkeys, por lo que al menos el código se ejecuta. Todavía es demasiado lento, ya que ha tardado varias horas con un conjunto de datos del tamaño de 32k, y aún no ha terminado. Aquí es lo que tengo en este momento:

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)) 

El problema podría ser que cada fila que se toma no utiliza la poca densidad del vector, sino que va a través de cada uno de la entrada 150k. Como una continuación para el problema, ¿alguien sabe cómo utilizar este Naive Bayes con matrices dispersas, o hay alguna otra forma de optimizar el código anterior?

+0

¿Quizás pueda codificar sus funciones de manera más eficiente o reducir su tamaño? – piokuc

+0

cierto, pero sea cual sea el número de características, me temo que todavía necesitaré gestionar el tamaño de la matriz. El conjunto de datos consiste en palabras de tweets. – user1638859

+0

Encontré las iterkeys al menos, ahora el problema es que el código es demasiado lento. – user1638859

Respuesta

3

Eche un vistazo a document classification example en scikit-learn. El truco es dejar que la biblioteca maneje la extracción de características por usted. Omita el contenedor NLTK, ya que no está destinado a conjuntos de datos tan grandes. (*)

Si tiene los documentos en archivos de texto, puede simplemente entregar esos archivos de texto al TfidfVectorizer, que crea una matriz dispersa de ellos:

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

ya ha configurado una formación X en el formato de matriz dispersa RSE, que se puede alimentar a un clasificador de Bayes ingenuo si también tiene una lista de etiquetas y (quizás derivadas de los nombres de archivo, si la codificación del clase en ellos):

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

Si resulta que esto no funciona porque el conjunto de documentos es demasiado grande (improbable ya que el TfidfVectorizer se optimizó solo para esta cantidad de documentos), consulte el ejemplo out-of-core document classification, que muestra la API HashingVectorizer y partial_fit para minibatch aprendizaje. Necesitarás scikit-learn 0.14 para que esto funcione.

(*) Lo sé, porque escribí esa envoltura. Al igual que el resto de NLTK, está destinado a fines educativos. También trabajé en mejoras de rendimiento en scikit-learn, y parte del código que estoy publicitando es mío.

Cuestiones relacionadas