¿Cómo resolver un error NotImplemented desde nltk.classify ClassifierI?

Soy nuevo en progtwigción, pero he revisado mi código una y otra vez y no puedo ver ningún error. Ya no sé cómo proceder porque este error aparece, no importa lo que intente. Voy a publicar el código completo aquí.

Cualquier ayuda sería muy apreciada, gracias!

import nltk import random from nltk.corpus import movie_reviews import pickle from nltk.classify.scikitlearn import SklearnClassifier from sklearn.naive_bayes import MultinomialNB,BernoulliNB from sklearn.linear_model import LogisticRegression, SGDClassifier from sklearn.svm import SVC, LinearSVC, NuSVC from nltk.classify import ClassifierI from statistics import mode class VoteClassifier(ClassifierI): def __init__(self, *classifiers): self._classifiers = classifiers def classify(self, features): votes = [] for c in self._classifiers: v = c.classify(features) votes.append(v) return mode(votes) def confidence(self, features): votes = [] for c in self._classifiers: v = c.classify(features) votes.append(v) choice_votes = votes.count(mode(votes)) conf = choice_votes / len(votes) return conf documents = [(list(movie_reviews.words(fileid)), category) for category in movie_reviews.categories() for fileid in movie_reviews.fileids(category)] random.shuffle(documents) all_words = [] for w in movie_reviews.words(): all_words.append(w.lower()) all_words = nltk.FreqDist(all_words) word_features = list(all_words.keys())[:3000] def find_features(document): words = set(document) features = {} for w in word_features: features[w] = (w in words) return features featuresets = [(find_features(rev), category) for (rev, category) in documents] training_set = featuresets[:1900] testing_set = featuresets[1900:] # classifier = nltk.NaiveBayesClassifier.train(training_set) classifier_f = open("naivebayes.pickle", "rb") classifier = pickle.load(classifier_f) classifier_f.close() print("Original NaiveBayes accuracy percent:",(nltk.classify.accuracy(classifier, testing_set))*100) classifier.show_most_informative_features(10) MNB_classifier = SklearnClassifier(MultinomialNB()) MNB_classifier.train(training_set) print("MNB_classifier accuracy percent:", (nltk.classify.accuracy(MNB_classifier, testing_set))*100) BernoulliNB_classifier = SklearnClassifier(BernoulliNB()) BernoulliNB_classifier.train(training_set) print("BernoulliNB_classifier accuracy percent:", (nltk.classify.accuracy(BernoulliNB_classifier, testing_set))*100) LogisticRegression_classifier = SklearnClassifier(LogisticRegression()) LogisticRegression_classifier.train(training_set) print("LogisticRegression_classifier accuracy percent:", (nltk.classify.accuracy(LogisticRegression_classifier, testing_set))*100) SGDClassifier_classifier = SklearnClassifier(SGDClassifier()) SGDClassifier_classifier.train(training_set) print("SGDClassifier_classifier accuracy percent:", (nltk.classify.accuracy(SGDClassifier_classifier, testing_set))*100) ##SVC_classifier = SklearnClassifier(SVC()) ##SVC_classifier.train(training_set) ##print("SVC_classifier accuracy percent:", (nltk.classify.accuracy(SVC_classifier, testing_set))*100) LinearSVC_classifier = SklearnClassifier(LinearSVC()) LinearSVC_classifier.train(training_set) print("LinearSVC_classifier accuracy percent:", (nltk.classify.accuracy(LinearSVC_classifier, testing_set))*100) NuSVC_classifier = SklearnClassifier(NuSVC()) NuSVC_classifier.train(training_set) print("NuSVC_classifier accuracy percent:", (nltk.classify.accuracy(NuSVC_classifier, testing_set))*100) voted_classifier = VoteClassifier(classifier, NuSVC_classifier, LinearSVC_classifier, SGDClassifier_classifier, MNB_classifier, BernoulliNB_classifier, LogisticRegression_classifier) print("voted_classifier accuracy percent:", (nltk.classify.accuracy(voted_classifier, testing_set))*100) 

También intenté elevar una excepción NotImplementedError en la clase en la parte superior, pero no cambió la salida en Python.

Este es el error:

 Traceback (most recent call last): File "code/test.py", line 109, in  print("voted_classifier accuracy percent:", (nltk.classify.accuracy(voted_classifier, testing_set))*100) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/nltk/classify/util.py", line 87, in accuracy results = classifier.classify_many([fs for (fs, l) in gold]) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/nltk/classify/api.py", line 77, in classify_many return [self.classify(fs) for fs in featuresets] File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/nltk/classify/api.py", line 56, in classify raise NotImplementedError() NotImplementedError 

Como se señaló en los comentarios, hay un código de espagueti defectuoso en la API de ClassiferI que classify a classify_many cuando se anula. Puede que no sea algo malo si se considera que ClassifierI está fuertemente vinculado con el objeto NaiveBayesClassifier .

Pero para el uso particular en el OP, el código de espagueti no es bienvenido.

TL; DR

Echa un vistazo a https://www.kaggle.com/alvations/sklearn-nltk-voteclassifier

En largo

Desde el rastreo, el error se inicia desde nltk.classify.util.accuracy() llamando a ClassifierI.classify() .

El ClassifierI.classify() se usa generalmente para clasificar UN documento y la entrada es un diccionario de características con sus valores binarios.

Se supone que ClassifierI.classify_many() clasifica documentos MÚLTIPLES y la entrada es una lista de diccionario de características con sus valores binarios.

Así que el truco rápido es sobreescribir la función de accuracy() para que VotedClassifier no dependa de la definición de VotedClassifier classify() vs classify_many() . Eso también significaría que no heredamos de ClassifierI . En mi humilde opinión, si no necesita otras funciones aparte de classify() , no hay necesidad de heredar el equipaje con el que ClassifierI podría venir:

 def my_accuracy(classifier, gold): documents, labels = zip(*gold) predictions = classifier.classify_documents(documents) correct = [y == y_hat for y, y_hat in zip(labels, predictions)] if correct: return sum(correct) / len(correct) else: return 0 class VotraClassifier: def __init__(self, *classifiers): self._classifiers = classifiers def classify_documents(self, documents): return [self.classify_many(doc) for doc in documents] def classify_many(self, features): votes = [] for c in self._classifiers: v = c.classify(features) votes.append(v) return mode(votes) def confidence(self, features): votes = [] for c in self._classifiers: v = c.classify(features) votes.append(v) choice_votes = votes.count(mode(votes)) conf = choice_votes / len(votes) return conf 

Ahora si llamamos a la nueva my_accuracy() con el nuevo objeto VotedClassifier :

 voted_classifier = VotraClassifier(nltk_nb, NuSVC_classifier, LinearSVC_classifier, SGDClassifier_classifier, MNB_classifier, BernoulliNB_classifier, LogisticRegression_classifier) my_accuracy(voted_classifier, testing_set) 

[afuera]:

 0.86 

Nota: Hay cierta aleatoriedad cuando se trata de barajar el documento y luego sostener un conjunto para probar la precisión del clasificador.

Mi sugerencia es hacer lo siguiente en lugar de random.shuffle(documents) simple random.shuffle(documents)

  • Repite los experimentos con varias semillas aleatorias.
  • Para cada semilla aleatoria, haga una validación cruzada de 10 veces.