naive machine learning classifying bayes python nlp nltk sentiment-analysis textblob

python - machine - Nltk NaiveBayesClassifier training para el análisis de sentimientos



python naive bayes text classification (3)

El tutorial de @ 275365 sobre la estructura de datos para el clasificador bayesiano de NLTK es excelente. Desde un nivel más alto, podemos verlo como,

Tenemos oraciones de entrada con etiquetas de sentimiento:

training_data = [(''I love this sandwich.'', ''pos''), (''This is an amazing place!'', ''pos''), (''I feel very good about these beers.'', ''pos''), (''This is my best work.'', ''pos''), ("What an awesome view", ''pos''), (''I do not like this restaurant'', ''neg''), (''I am tired of this stuff.'', ''neg''), ("I can''t deal with this", ''neg''), (''He is my sworn enemy!'', ''neg''), (''My boss is horrible.'', ''neg'')]

Consideremos que nuestros conjuntos de características son palabras individuales, por lo que extraemos una lista de todas las palabras posibles de los datos de entrenamiento (llamémoslo vocabulario) como tal:

from nltk.tokenize import word_tokenize from itertools import chain vocabulary = set(chain(*[word_tokenize(i[0].lower()) for i in training_data]))

Esencialmente, el vocabulary aquí es el mismo @_ de all_word

>>> all_words = set(word.lower() for passage in training_data for word in word_tokenize(passage[0])) >>> vocabulary = set(chain(*[word_tokenize(i[0].lower()) for i in training_data])) >>> print vocabulary == all_words True

Desde cada punto de datos (es decir, cada oración y la etiqueta pos / neg), queremos decir si existe una característica (es decir, una palabra del vocabulario) o no.

>>> sentence = word_tokenize(''I love this sandwich.''.lower()) >>> print {i:True for i in vocabulary if i in sentence} {''this'': True, ''i'': True, ''sandwich'': True, ''love'': True, ''.'': True}

Pero también queremos decirle al clasificador qué palabra no existe en la oración pero en el vocabulario, así que para cada punto de datos, enumeramos todas las palabras posibles en el vocabulario y decimos si existe una palabra o no:

>>> sentence = word_tokenize(''I love this sandwich.''.lower()) >>> x = {i:True for i in vocabulary if i in sentence} >>> y = {i:False for i in vocabulary if i not in sentence} >>> x.update(y) >>> print x {''love'': True, ''deal'': False, ''tired'': False, ''feel'': False, ''is'': False, ''am'': False, ''an'': False, ''good'': False, ''best'': False, ''!'': False, ''these'': False, ''what'': False, ''.'': True, ''amazing'': False, ''horrible'': False, ''sworn'': False, ''ca'': False, ''do'': False, ''sandwich'': True, ''very'': False, ''boss'': False, ''beers'': False, ''not'': False, ''with'': False, ''he'': False, ''enemy'': False, ''about'': False, ''like'': False, ''restaurant'': False, ''this'': True, ''of'': False, ''work'': False, "n''t": False, ''i'': True, ''stuff'': False, ''place'': False, ''my'': False, ''awesome'': False, ''view'': False}

Pero como esto recorre el vocabulario dos veces, es más eficiente hacer esto:

>>> sentence = word_tokenize(''I love this sandwich.''.lower()) >>> x = {i:(i in sentence) for i in vocabulary} {''love'': True, ''deal'': False, ''tired'': False, ''feel'': False, ''is'': False, ''am'': False, ''an'': False, ''good'': False, ''best'': False, ''!'': False, ''these'': False, ''what'': False, ''.'': True, ''amazing'': False, ''horrible'': False, ''sworn'': False, ''ca'': False, ''do'': False, ''sandwich'': True, ''very'': False, ''boss'': False, ''beers'': False, ''not'': False, ''with'': False, ''he'': False, ''enemy'': False, ''about'': False, ''like'': False, ''restaurant'': False, ''this'': True, ''of'': False, ''work'': False, "n''t": False, ''i'': True, ''stuff'': False, ''place'': False, ''my'': False, ''awesome'': False, ''view'': False}

Entonces, para cada oración, queremos decirle al clasificador de cada oración qué palabra existe y qué palabra no, y también asignarle la etiqueta pos / neg. Podemos llamarlo un feature_set , es una tupla compuesta de una x (como se muestra arriba) y su etiqueta.

>>> feature_set = [({i:(i in word_tokenize(sentence.lower())) for i in vocabulary},tag) for sentence, tag in training_data] [({''this'': True, ''love'': True, ''deal'': False, ''tired'': False, ''feel'': False, ''is'': False, ''am'': False, ''an'': False, ''sandwich'': True, ''ca'': False, ''best'': False, ''!'': False, ''what'': False, ''.'': True, ''amazing'': False, ''horrible'': False, ''sworn'': False, ''awesome'': False, ''do'': False, ''good'': False, ''very'': False, ''boss'': False, ''beers'': False, ''not'': False, ''with'': False, ''he'': False, ''enemy'': False, ''about'': False, ''like'': False, ''restaurant'': False, ''these'': False, ''of'': False, ''work'': False, "n''t": False, ''i'': False, ''stuff'': False, ''place'': False, ''my'': False, ''view'': False}, ''pos''), ...]

Luego introducimos estas características y etiquetas en el feature_set en el clasificador para entrenarlo:

from nltk import NaiveBayesClassifier as nbc classifier = nbc.train(feature_set)

Ahora tiene un clasificador capacitado y cuando quiere etiquetar una nueva oración, tiene que "caracterizar" la nueva oración para ver cuál de las palabras de la nueva oración están en el vocabulario en el que se entrenó al clasificador:

>>> test_sentence = "This is the best band I''ve ever heard! foobar" >>> featurized_test_sentence = {i:(i in word_tokenize(test_sentence.lower())) for i in vocabulary}

NOTA: Como puede ver en el paso anterior, el clasificador ingenuo de bayes no puede manejar palabras de vocabulario ya que el token de foobar desaparece después de caracterizarlo.

Luego introduce la oración de prueba caracterizada en el clasificador y le pide que clasifique:

>>> classifier.classify(featurized_test_sentence) ''pos''

Esperemos que esto proporcione una imagen más clara de cómo introducir datos en el clasificador de bayes ingenuo de NLTK para el análisis sentimental. Aquí está el código completo sin los comentarios y el tutorial:

from nltk import NaiveBayesClassifier as nbc from nltk.tokenize import word_tokenize from itertools import chain training_data = [(''I love this sandwich.'', ''pos''), (''This is an amazing place!'', ''pos''), (''I feel very good about these beers.'', ''pos''), (''This is my best work.'', ''pos''), ("What an awesome view", ''pos''), (''I do not like this restaurant'', ''neg''), (''I am tired of this stuff.'', ''neg''), ("I can''t deal with this", ''neg''), (''He is my sworn enemy!'', ''neg''), (''My boss is horrible.'', ''neg'')] vocabulary = set(chain(*[word_tokenize(i[0].lower()) for i in training_data])) feature_set = [({i:(i in word_tokenize(sentence.lower())) for i in vocabulary},tag) for sentence, tag in training_data] classifier = nbc.train(feature_set) test_sentence = "This is the best band I''ve ever heard!" featurized_test_sentence = {i:(i in word_tokenize(test_sentence.lower())) for i in vocabulary} print "test_sent:",test_sentence print "tag:",classifier.classify(featurized_test_sentence)

Estoy entrenando el NaiveBayesClassifier en Python usando oraciones, y me da el error a continuación. No entiendo cuál podría ser el error, y cualquier ayuda sería buena.

He intentado muchos otros formatos de entrada, pero el error permanece. El código que figura a continuación:

from text.classifiers import NaiveBayesClassifier from text.blob import TextBlob train = [(''I love this sandwich.'', ''pos''), (''This is an amazing place!'', ''pos''), (''I feel very good about these beers.'', ''pos''), (''This is my best work.'', ''pos''), ("What an awesome view", ''pos''), (''I do not like this restaurant'', ''neg''), (''I am tired of this stuff.'', ''neg''), ("I can''t deal with this", ''neg''), (''He is my sworn enemy!'', ''neg''), (''My boss is horrible.'', ''neg'') ] test = [(''The beer was good.'', ''pos''), (''I do not enjoy my job'', ''neg''), ("I ain''t feeling dandy today.", ''neg''), ("I feel amazing!", ''pos''), (''Gary is a friend of mine.'', ''pos''), ("I can''t believe I''m doing this.", ''neg'') ] classifier = nltk.NaiveBayesClassifier.train(train)

Incluyo el rastreo a continuación.

Traceback (most recent call last): File "C:/Users/5460/Desktop/train01.py", line 15, in <module> all_words = set(word.lower() for passage in train for word in word_tokenize(passage[0])) File "C:/Users/5460/Desktop/train01.py", line 15, in <genexpr> all_words = set(word.lower() for passage in train for word in word_tokenize(passage[0])) File "C:/Python27/lib/site-packages/nltk/tokenize/__init__.py", line 87, in word_tokenize return _word_tokenize(text) File "C:/Python27/lib/site-packages/nltk/tokenize/treebank.py", line 67, in tokenize text = re.sub(r''^/"'', r''``'', text) File "C:/Python27/lib/re.py", line 151, in sub return _compile(pattern, flags).sub(repl, string, count) TypeError: expected string or buffer


Necesitas cambiar tu estructura de datos. Aquí está su lista de train como está actualmente:

>>> train = [(''I love this sandwich.'', ''pos''), (''This is an amazing place!'', ''pos''), (''I feel very good about these beers.'', ''pos''), (''This is my best work.'', ''pos''), ("What an awesome view", ''pos''), (''I do not like this restaurant'', ''neg''), (''I am tired of this stuff.'', ''neg''), ("I can''t deal with this", ''neg''), (''He is my sworn enemy!'', ''neg''), (''My boss is horrible.'', ''neg'')]

Sin embargo, el problema es que el primer elemento de cada tupla debe ser un diccionario de características. Así que cambiaré su lista a una estructura de datos con la que el clasificador pueda trabajar:

>>> from nltk.tokenize import word_tokenize # or use some other tokenizer >>> all_words = set(word.lower() for passage in train for word in word_tokenize(passage[0])) >>> t = [({word: (word in word_tokenize(x[0])) for word in all_words}, x[1]) for x in train]

Tus datos ahora deberían estar estructurados así:

>>> t [({''this'': True, ''love'': True, ''deal'': False, ''tired'': False, ''feel'': False, ''is'': False, ''am'': False, ''an'': False, ''sandwich'': True, ''ca'': False, ''best'': False, ''!'': False, ''what'': False, ''.'': True, ''amazing'': False, ''horrible'': False, ''sworn'': False, ''awesome'': False, ''do'': False, ''good'': False, ''very'': False, ''boss'': False, ''beers'': False, ''not'': False, ''with'': False, ''he'': False, ''enemy'': False, ''about'': False, ''like'': False, ''restaurant'': False, ''these'': False, ''of'': False, ''work'': False, "n''t": False, ''i'': False, ''stuff'': False, ''place'': False, ''my'': False, ''view'': False}, ''pos''), . . .]

Tenga en cuenta que el primer elemento de cada tupla ahora es un diccionario. Ahora que sus datos están en su lugar y que el primer elemento de cada tupla es un diccionario, puede entrenar al clasificador de la siguiente manera:

>>> import nltk >>> classifier = nltk.NaiveBayesClassifier.train(t) >>> classifier.show_most_informative_features() Most Informative Features this = True neg : pos = 2.3 : 1.0 this = False pos : neg = 1.8 : 1.0 an = False neg : pos = 1.6 : 1.0 . = True pos : neg = 1.4 : 1.0 . = False neg : pos = 1.4 : 1.0 awesome = False neg : pos = 1.2 : 1.0 of = False pos : neg = 1.2 : 1.0 feel = False neg : pos = 1.2 : 1.0 place = False neg : pos = 1.2 : 1.0 horrible = False pos : neg = 1.2 : 1.0

Si quieres usar el clasificador, puedes hacerlo así. Primero, comienzas con una oración de prueba:

>>> test_sentence = "This is the best band I''ve ever heard!"

Luego, tokeniza la oración y averigua qué palabras comparte la oración con all_words. Estas constituyen las características de la oración.

>>> test_sent_features = {word.lower(): (word in word_tokenize(test_sentence.lower())) for word in all_words}

Sus características ahora se verán así:

>>> test_sent_features {''love'': False, ''deal'': False, ''tired'': False, ''feel'': False, ''is'': True, ''am'': False, ''an'': False, ''sandwich'': False, ''ca'': False, ''best'': True, ''!'': True, ''what'': False, ''i'': True, ''.'': False, ''amazing'': False, ''horrible'': False, ''sworn'': False, ''awesome'': False, ''do'': False, ''good'': False, ''very'': False, ''boss'': False, ''beers'': False, ''not'': False, ''with'': False, ''he'': False, ''enemy'': False, ''about'': False, ''like'': False, ''restaurant'': False, ''this'': True, ''of'': False, ''work'': False, "n''t": False, ''these'': False, ''stuff'': False, ''place'': False, ''my'': False, ''view'': False}

Entonces simplemente clasifica esas características:

>>> classifier.classify(test_sent_features) ''pos'' # note ''best'' == True in the sentence features above

Esta oración de prueba parece ser positiva.


Parece que está intentando usar TextBlob pero está entrenando el NLTK NaiveBayesClassifier, que, como se señaló en otras respuestas, debe pasar un diccionario de características.

TextBlob tiene un extractor de características predeterminado que indica qué palabras del conjunto de capacitación se incluyen en el documento (como se muestra en las otras respuestas). Por lo tanto, TextBlob le permite pasar sus datos como están.

from textblob.classifiers import NaiveBayesClassifier train = [(''This is an amazing place!'', ''pos''), (''I feel very good about these beers.'', ''pos''), (''This is my best work.'', ''pos''), ("What an awesome view", ''pos''), (''I do not like this restaurant'', ''neg''), (''I am tired of this stuff.'', ''neg''), ("I can''t deal with this", ''neg''), (''He is my sworn enemy!'', ''neg''), (''My boss is horrible.'', ''neg'') ] test = [ (''The beer was good.'', ''pos''), (''I do not enjoy my job'', ''neg''), ("I ain''t feeling dandy today.", ''neg''), ("I feel amazing!", ''pos''), (''Gary is a friend of mine.'', ''pos''), ("I can''t believe I''m doing this.", ''neg'') ] classifier = NaiveBayesClassifier(train) # Pass in data as is # When classifying text, features are extracted automatically classifier.classify("This is an amazing library!") # => ''pos''

Por supuesto, el simple extractor predeterminado no es apropiado para todos los problemas. Si desea conocer cómo se extraen las funciones, simplemente escriba una función que tome una cadena de texto como entrada y produzca el diccionario de características y se lo pase al clasificador.

classifier = NaiveBayesClassifier(train, feature_extractor=my_extractor_func)

Le animo a consultar el breve tutorial de clasificador de TextBlob aquí: http://textblob.readthedocs.org/en/latest/classifiers.html