2012-08-31 11 views
5

Sto provando a eseguire Naive Bayes su un set di dati che contiene oltre 6.000.000 di voci e ogni voce di 150k. Ho cercato di implementare il codice dal seguente link: Implementing Bag-of-Words Naive-Bayes classifier in NLTKUtilizzo di matrici sparse/apprendimento online in Naive Bayes (Python, scikit)

Il problema è (mi pare di capire), che quando provo a fare funzionare il metodo treno con un dok_matrix come è parametro, non riesce a trovare iterkeys (ho abbinato le righe con OrderedDict come etichette):

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 

la mia domanda è: esiste un modo per evitare di utilizzare una matrice sparsa insegnando l'entrata classificatore da ingresso (on-line), o c'è una rada formato matrice che potrei usare in questo caso in modo efficiente invece di dok_matrix? O mi manca qualcosa di ovvio?

Grazie per il tempo di chiunque. :)

EDIT, 6 settembre:

trovato le iterkeys, così atleast il codice viene eseguito. È ancora troppo lento, poiché ha impiegato diverse ore con un set di dati della dimensione di 32k e non è ancora terminato. Ecco quello che ho ottenuto in questo 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)) 

Il problema potrebbe essere che ogni riga che viene assunto non utilizza la scarsità del vettore, ma passa attraverso ciascuna della voce 150k. Come una continuazione per il problema, qualcuno sa come utilizzare questo Naive Bayes con matrici sparse o esiste un altro modo per ottimizzare il codice precedente?

+0

Forse è possibile codificare le funzionalità in modo più efficiente o ridurne le dimensioni? – piokuc

+0

true, ma qualunque sia il numero di funzionalità che temo avrò ancora bisogno di gestire la dimensione della matrice. Il set di dati comprende le parole dei tweet. – user1638859

+0

Trovato il iterkeys atleast, ora il problema è che il codice è troppo lento. – user1638859

risposta

3

Controlla lo document classification example in scikit-learn. Il trucco è lasciare che la libreria gestisca l'estrazione della funzione per te. Salta il wrapper NLTK, poiché non è destinato a insiemi di dati di grandi dimensioni. (*)

Se i documenti sono presenti in file di testo, è possibile passare tali file di testo allo TfidfVectorizer, che crea da essi una matrice sparsa:

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

ora avete un training set X nel formato matrice sparsa CSR, che si può nutrire per un classificatore bayesiano se hai anche un elenco di etichette y (forse derivati ​​dai nomi dei file, se hai codificato il classe in loro):

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

Se risulta che questo non funziona perché il set di documenti è troppo grande (improbabile dal momento che il TfidfVectorizer è stato ottimizzato per questo numero di documenti), guarda l'esempio out-of-core document classification, che dimostra l'API HashingVectorizer e partial_fit per minibatch apprendimento. Avrai bisogno di scikit-learn 0.14 perché funzioni.

(*) Lo so, perché ho scritto quell'involucro. Come il resto di NLTK, è destinato a scopi didattici. Ho anche lavorato su miglioramenti delle prestazioni in scikit-learn, e parte del codice che sto pubblicizzando è mio.