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.
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. –
@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
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. –