2012-04-11 29 views
23

Zasadniczo mam same question as this guy .. example in the NLTK book dla klasyfikatora Naive Bayes uwzględnia tylko to, czy słowo występuje w dokumencie jako funkcja .. nie bierze pod uwagę częstotliwości słów jako funkcji do obejrzenia ("bag-of-words").Implementacja klasyfikatora naive-bayesa w języku NLTK

One of the answers sugeruje, że nie można tego zrobić za pomocą wbudowanych klasyfikatorów NLTK. Czy tak jest? Jak mogę zrobić klasyfikację NB/częstotliwości słów z NLTK?

Odpowiedz

31

scikit-learn ma an implementation of multinomial naive Bayes, który jest właściwym wariantem naiwnych Bayes w tej sytuacji. Maszyna do obsługi wektora nośnego (SVM) prawdopodobnie zapewne działałaby lepiej.

Jak zauważył Ken w komentarzach, NLTK ma a nice wrapper for scikit-learn classifiers. Zmodyfikowane z dokumentów, tutaj jest nieco skomplikowane, które dokonuje ważenia TF-IDF, wybiera 1000 najlepszych funkcji na podstawie statystyki chi2, a następnie przekazuje je do wielomianowego naiwnego klasyfikatora Bayesa. (. Założę się, to jest nieco niezdarny, jak nie jestem bardzo obeznany z obu NLTK lub 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()) 

Ten wydrukowany dla mnie:

Confusion matrix: 
524  376 
202  698 

Nie idealne, ale przyzwoity, biorąc pod uwagę nie jest to bardzo łatwy problem i jest wyszkolony tylko na 100/100.

+1

Właściwie to prawdopodobnie chce modeli maszyn obsługi wektorów nauczyć się scikit. NLTK ma ładny wrapper 'nltk.classify.scikitlearn.SklearnClassifier', który sprawia, że ​​te klasyfikatory dobrze pasują do jego API. –

+0

@KenBloom Tak, SVMs byłoby prawdopodobnie lepsze, ale specjalnie zapytał o naiwne Bayes.:) To opakowanie jest miłe, i właśnie zdałem sobie sprawę, że istnieje również wielomianowa naiwna Bayes w nauce scikita, więc zmienię odpowiedź, aby to wykorzystać. – Dougal

+1

, który wygląda świetnie. Szkoda, że ​​nie nauczyłem się Pythona, kiedy robiłem mój doktorat. w tym. Zrobiłem wiele zawinięć do pracy w Ruby, które byłyby zupełnie niepotrzebne. –

6

Funkcje w klasyfikatorze bayes NLTK są "nominalne", a nie numeryczne. Oznacza to, że mogą przyjąć skończoną liczbę dyskretnych wartości (etykiet), ale nie mogą być traktowane jako częstotliwości.

Więc z klasyfikatora Bayesa, nie można bezpośrednio użytkowanie częstotliwości słowo jako feature-- można zrobić coś takiego użyć częstszych słowa 50 z każdego tekstu jako zestaw funkcji, ale to już zupełnie inna sprawa

Ale być może istnieją inne klasyfikatory w NLTK, które zależą od częstotliwości. Nie wiedziałbym, ale czy wyglądałeś? Powiedziałbym, że warto to sprawdzić.

3
  • umieścić ciąg patrzysz na listę, w podziale na słowa
  • dla każdej pozycji na liście, zapytać: czy jest to pozycja cechą mam w liście funkcji.
  • Jeśli tak, dodaj dziennik tak jak zwykle, jeśli nie, zignoruj ​​go.

Jeśli twoje zdanie ma to samo słowo wiele razy, po prostu doda je kilka razy. Jeśli słowo pojawia się wiele razy w tej samej klasie, twoje dane treningowe powinny odzwierciedlać to w liczbie słów.

Aby zwiększyć dokładność, należy odliczyć wszystkie dwójki, trójki, itd. Jako osobne funkcje.

Pomaga ręcznie napisać własne klasyfikatory, aby dokładnie zrozumieć, co się dzieje i co należy zrobić, aby zachować dokładność. Jeśli używasz paczkowanego rozwiązania i nie działa ono wystarczająco dobrze, niewiele możesz z tym zrobić.

Powiązane problemy