2012-04-11 22 views
23

Básicamente tengo el same question as this guy .. El example in the NLTK book para el clasificador Naive Bayes considera solo si una palabra ocurre en un documento como una característica ... no considera la frecuencia de las palabras como la característica a mirar ("bolsa de palabras").Implementando el clasificador Naive-Bayes de Bag-of-Words en NLTK

One of the answers parece sugerir que esto no se puede hacer con los clasificadores NLTK incorporados. Es ese el caso? ¿Cómo puedo hacer la clasificación NB de frecuencia/bolsa de palabras con NLTK?

Respuesta

31

scikit-learn tiene an implementation of multinomial naive Bayes, que es la variante correcta de ingenuo Bayes en esta situación. Sin embargo, una máquina de vectores de soporte (SVM) probablemente funcione mejor.

Como señaló Ken en los comentarios, NLTK tiene a nice wrapper for scikit-learn classifiers. Modificado a partir de los documentos, este es un tanto complicado que hace la ponderación TF-IDF, elige las 1000 mejores características basadas en una estadística chi2, y luego las pasa a un clasificador Bayes ingenuo multinomial. (. Apuesto a que esto es algo torpe, ya que no estoy muy familiarizado con cualquiera NLTK o scikit-learn)

import numpy as np 
from nltk.probability import FreqDist 
from nltk.classify import SklearnClassifier 
from sklearn.feature_extraction.text import TfidfTransformer 
from sklearn.feature_selection import SelectKBest, chi2 
from sklearn.naive_bayes import MultinomialNB 
from sklearn.pipeline import Pipeline 

pipeline = Pipeline([('tfidf', TfidfTransformer()), 
        ('chi2', SelectKBest(chi2, k=1000)), 
        ('nb', MultinomialNB())]) 
classif = SklearnClassifier(pipeline) 

from nltk.corpus import movie_reviews 
pos = [FreqDist(movie_reviews.words(i)) for i in movie_reviews.fileids('pos')] 
neg = [FreqDist(movie_reviews.words(i)) for i in movie_reviews.fileids('neg')] 
add_label = lambda lst, lab: [(x, lab) for x in lst] 
classif.train(add_label(pos[:100], 'pos') + add_label(neg[:100], 'neg')) 

l_pos = np.array(classif.classify_many(pos[100:])) 
l_neg = np.array(classif.classify_many(neg[100:])) 
print "Confusion matrix:\n%d\t%d\n%d\t%d" % (
      (l_pos == 'pos').sum(), (l_pos == 'neg').sum(), 
      (l_neg == 'pos').sum(), (l_neg == 'neg').sum()) 

Este impreso para mí:

Confusion matrix: 
524  376 
202  698 

No es perfecto, pero decente, teniendo en cuenta no es un problema súper fácil y solo está entrenado en 100/100.

+1

En realidad, probablemente quiera los modelos scikit-learn de Support Vector Machine. NLTK tiene un buen contenedor 'nltk.classify.scikitlearn.SklearnClassifier' que hace que estos clasificadores se adapten bien a su API. –

+0

@KenBloom Sí, SVM probablemente sería mejor, pero sí preguntó específicamente sobre el ingenuo Bayes.:) Esa envoltura es agradable, y me di cuenta de que también hay un ingenuo multinomial de Bayes en scikit-learn, así que cambiaré mi respuesta para usar eso. – Dougal

+1

que luce brillantemente simple. Ojalá hubiera aprendido Python cuando estaba haciendo mi Ph.D. en esto. Hice un montón de trabajo envolviendo clasificadores en Ruby que hubieran sido totalmente innecesarios. –

6

Las características en el clasificador bayes NLTK son "nominales", no numéricas. Esto significa que pueden tomar un número finito de valores discretos (etiquetas), pero no pueden tratarse como frecuencias.

Así que con el clasificador de Bayes, no se puede directamente uso de frecuencia de palabras como feature-- que podría hacer algo así como utilizar las 50 palabras más frecuentes de cada texto como su conjunto de características, pero eso es una cosa muy diferente

Pero quizás haya otros clasificadores en el NLTK que dependen de la frecuencia. No lo sabría, pero ¿has mirado? Yo diría que vale la pena echarle un vistazo.

3
  • poner la cadena que está buscando en en una lista, dividida en palabras
  • para cada elemento de la lista, pregunte: este artículo es una característica que tengo en la lista de características.
  • Si es así, agregue el problema de registro como de costumbre, de lo contrario, ignórelo.

Si su oración tiene la misma palabra varias veces, simplemente agregará los problemas varias veces. Si la palabra aparece varias veces en la misma clase, los datos de tu entrenamiento deberían reflejar eso en el conteo de palabras.

Para mayor precisión, cuente todos los bi-gramos, tri-gramos, etc. como características separadas.

Ayuda escribir manualmente sus propios clasificadores para que comprenda exactamente lo que está sucediendo y lo que debe hacer para mejorar la precisión. Si usa una solución preempaquetada y no funciona lo suficientemente bien, no hay mucho que pueda hacer al respecto.

Cuestiones relacionadas