Comment effectuer une analyse de sentiment dans Python 3 à l’aide de la trousse à outils en langage naturel (NLTK)

L'auteur a choisi le fondsOpen Internet/Free Speech pour recevoir un don dans le cadre du programmeWrite for DOnations.

introduction

Une grande quantité de données générées aujourd'hui estunstructured, ce qui nécessite un traitement pour générer des informations. Des exemples de données non structurées sont les articles de presse, les publications sur les médias sociaux et l'historique des recherches. Le processus d’analyse du langage naturel et de sa compréhension relève du domaine du traitement du langage naturel (PNL). L'analyse des sentiments est une tâche courante de la PNL, qui consiste à classer des textes ou des parties de textes en un sentiment prédéfini. Vous utiliserezthe Natural Language Toolkit (NLTK), une bibliothèque NLP couramment utilisée en Python, pour analyser les données textuelles.

Dans ce didacticiel, vous allez préparer un ensemble de données contenant des exemples de tweets issus du package NLTK pour NLP avec différentes méthodes de nettoyage des données. Une fois que le jeu de données est prêt pour le traitement, vous allez former un modèle sur les tweets préclassés et utiliser le modèle pour classer les exemples de tweets en sentiments négatifs et positifs.

Cet article suppose que vous êtes familiarisé avec les bases dePython (voir nosHow To Code in Python 3 series), principalement l'utilisation de structures de données, de classes et de méthodes. Le didacticiel suppose que vous n'avez aucune expérience en PNL etnltk, bien que certaines connaissances à ce sujet soient un avantage supplémentaire.

Conditions préalables

[[step-1 -—- installation-nltk-and-download-the-data]] == Étape 1 - Installation de NLTK et téléchargement des données

Vous utiliserez le package NLTK en Python pour toutes les tâches NLP de ce tutoriel. Dans cette étape, vous allez installer NLTK et télécharger les exemples de tweets que vous utiliserez pour former et tester votre modèle.

Tout d'abord,install the NLTK package avec le gestionnaire de packagespip:

pip install nltk==3.3

Ce tutoriel utilisera des exemples de tweets faisant partie du package NLTK. Commencez par démarrer une session interactive Python en exécutant la commande suivante:

python3

Ensuite, importez le modulenltk dans l'interpréteur python.

import nltk

Téléchargez les exemples de tweets à partir du package NLTK:

nltk.download('twitter_samples')

L'exécution de cette commande à partir de l'interpréteur Python télécharge et stocke les tweets localement. Une fois les échantillons téléchargés, ils sont disponibles pour votre utilisation.

Vous utiliserez les tweets négatifs et positifs pour former votre modèle à l'analyse des sentiments plus tard dans le didacticiel. Les tweets sans sentiments seront utilisés pour tester votre modèle.

Si vous souhaitez utiliser votre propre ensemble de données, vous pouvez collecter des tweets d'une période, d'un utilisateur ou d'un hashtag spécifiques en utilisant lesTwitter API.

Maintenant que vous avez importé NLTK et téléchargé les exemples de tweets, quittez la session interactive en saisissantexit(). Vous êtes prêt à importer les tweets et à commencer à traiter les données.

[[step-2 -—- tokenizing-the-data]] == Étape 2 - Tokenizing the Data

La langue dans sa forme originale ne peut pas être traitée avec précision par une machine. Vous devez donc la traiter pour la rendre plus facile à comprendre. La première partie de la compréhension des données consiste à utiliser un processus appelétokenization, ou à diviser des chaînes en parties plus petites appeléestokens.

Un jeton est une séquence de caractères dans le texte qui sert d'unité. Selon la manière dont vous créez les jetons, ceux-ci peuvent être constitués de mots, d'émoticônes, de hashtags, de liens ou même de caractères individuels. Un moyen simple de diviser le langage en jetons consiste à scinder le texte en fonction des espaces et de la ponctuation.

Pour commencer, créez un nouveau fichier.py pour contenir votre script. Ce tutoriel utiliseranlp_test.py:

nano nlp_test.py

Dans ce fichier, vous importerez d'abord lestwitter_samples afin de pouvoir travailler avec ces données:

nlp_test.py

from nltk.corpus import twitter_samples

Cela importera trois jeux de données de NLTK contenant plusieurs tweets pour former et tester le modèle:

  • negative_tweets.json: 5000 tweets avec des sentiments négatifs

  • positive_tweets.json: 5000 tweets avec des sentiments positifs

  • tweets.20150430-223406.json: 20000 tweets sans sentiments

Ensuite, créez des variables pourpositive_tweets,negative_tweets ettext:

nlp_test.py

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')

La méthodestrings() detwitter_samples imprimera tous les tweets d'un ensemble de données sous forme de chaînes. Définir les différentes collections de tweets comme variable facilitera le traitement et les tests.

Avant d'utiliser un tokenizer dans NLTK, vous devez télécharger une ressource supplémentaire,punkt. Le modulepunkt est un modèle pré-entraîné qui vous aide à tokeniser des mots et des phrases. Par exemple, ce modèle sait qu’un nom peut contenir un point (comme «S. Daityari ”) et la présence de cette période dans une phrase ne la termine pas nécessairement. Commencez par démarrer une session interactive Python:

python3

Exécutez les commandes suivantes dans la session pour télécharger la ressourcepunkt:

import nltk
nltk.download('punkt')

Une fois le téléchargement terminé, vous êtes prêt à utiliser les tokenizer de NLTK. NLTK fournit un tokenizer par défaut pour les tweets avec la méthode.tokenized(). Ajoutez une ligne pour créer un objet qui tokenise l'ensemble de donnéespositive_tweets.json:

nlp_test.py

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')

Si vous souhaitez tester le script pour voir la méthode.tokenized en action, ajoutez le contenu en surbrillance à votre scriptnlp_test.py. Cela va tokeniser un seul tweet de l'ensemble de donnéespositive_tweets.json:

nlp_test.py

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

print(tweet_tokens[0])

Enregistrez et fermez le fichier, puis exécutez le script:

python3 nlp_test.py

Le processus de création de jetons prend un certain temps car il ne s’agit pas d’une simple scission sur un espace blanc. Après quelques instants de traitement, vous verrez ce qui suit:

Output['#FollowFriday',
 '@France_Inte',
 '@PKuchly57',
 '@Milipol_Paris',
 'for',
 'being',
 'top',
 'engaged',
 'members',
 'in',
 'my',
 'community',
 'this',
 'week',
 ':)']

Ici, la méthode.tokenized() renvoie des caractères spéciaux tels que@ et_. Ces caractères seront supprimés par les expressions régulières plus loin dans ce tutoriel.

Maintenant que vous avez vu comment la méthode.tokenized() fonctionne, assurez-vous de commenter ou de supprimer la dernière ligne pour imprimer le tweet tokenisé du script en ajoutant un# au début de la ligne:

nlp_test.py

from nltk.corpus import twitter_samples

positive_tweets = twitter_samples.strings('positive_tweets.json')
negative_tweets = twitter_samples.strings('negative_tweets.json')
text = twitter_samples.strings('tweets.20150430-223406.json')
tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

#print(tweet_tokens[0])

Votre script est maintenant configuré pour effectuer une tokenisation des données. Dans l'étape suivante, vous allez mettre à jour le script pour normaliser les données.

[[step-3 -—- normalizing-the-data]] == Étape 3 - Normalisation des données

Les mots ont des formes différentes - par exemple, «couru», «court» et «courant» sont diverses formes du même verbe, «courir». Selon les exigences de votre analyse, il peut être nécessaire de convertir toutes ces versions dans le même formulaire, "Exécuter". Normalization en NLP est le processus de conversion d'un mot en sa forme canonique.

La normalisation permet de regrouper des mots ayant la même signification mais des formes différentes. Sans normalisation, les termes «exécuté», «exécuté» et «exécuté» seraient traités comme des mots différents, même si vous souhaitiez qu'ils soient traités comme le même mot. Dans cette section, vous explorezstemming etlemmatization, qui sont deux techniques de normalisation populaires.

La recherche de racine est un processus consistant à supprimer des affixes d'un mot. Stemming, qui utilise uniquement des formes verbales simples, est un processus heuristique qui supprime la fin des mots.

Dans ce tutoriel, vous utiliserez le processus de lemmatisation, qui normalise un mot avec le contexte du vocabulaire et desmorphological analysis de mots dans le texte. L'algorithme de lemmatisation analyse la structure du mot et son contexte pour le convertir en une forme normalisée. Par conséquent, cela a un coût de rapidité. Une comparaison entre l’arrêt et la lemmatisation revient finalement à un compromis entre vitesse et précision.

Avant de continuer à utiliser la lemmatisation, téléchargez les ressources nécessaires en entrant les informations suivantes dans une session interactive Python:

python3

Exécutez les commandes suivantes dans la session pour télécharger les ressources:

import nltk
nltk.download('wordnet')
nltk.download('averaged_perceptron_tagger')

wordnet est une base de données lexicale pour la langue anglaise qui aide le script à déterminer le mot de base. Vous avez besoin de la ressourceaveraged_perceptron_tagger pour déterminer le contexte d'un mot dans une phrase.

Une fois téléchargé, vous êtes presque prêt à utiliser le lemmatiseur. Avant d'exécuter un lemmatiseur, vous devez déterminer le contexte de chaque mot de votre texte. Ceci est réalisé par un algorithme de marquage, qui évalue la position relative d'un mot dans une phrase. Dans une session Python, importez la fonctionpos_tag et fournissez une liste de jetons comme argument pour obtenir les balises. Essayons cela en Python:

from nltk.tag import pos_tag
from nltk.corpus import twitter_samples

tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
print(pos_tag(tweet_tokens[0]))

Voici la sortie de la fonctionpos_tag.

Output[('#FollowFriday', 'JJ'),
 ('@France_Inte', 'NNP'),
 ('@PKuchly57', 'NNP'),
 ('@Milipol_Paris', 'NNP'),
 ('for', 'IN'),
 ('being', 'VBG'),
 ('top', 'JJ'),
 ('engaged', 'VBN'),
 ('members', 'NNS'),
 ('in', 'IN'),
 ('my', 'PRP$'),
 ('community', 'NN'),
 ('this', 'DT'),
 ('week', 'NN'),
 (':)', 'NN')]

Dans la liste des tags, voici la liste des éléments les plus courants et leur signification:

  • NNP: nom propre, singulier

  • NN: nom, commun, singulier ou masse

  • IN: préposition ou conjonction, subordination

  • VBG: verbe, gérondif ou participe présent

  • VBN: Verbe, participe passé

En général, si une balise commence parNN, le mot est un nom et s'il est étoile avecVB, le mot est un verbe. Après avoir examiné les balises, quittez la session Python en entrantexit().

Pour incorporer cela dans une fonction qui normalise une phrase, vous devez d'abord générer les balises pour chaque jeton dans le texte, puis lemmatiser chaque mot à l'aide de la balise.

Mettez à jour le fichiernlp_test.py avec la fonction suivante qui lemmatise une phrase:

nlp_test.py

...

from nltk.tag import pos_tag
from nltk.stem.wordnet import WordNetLemmatizer

def lemmatize_sentence(tokens):
    lemmatizer = WordNetLemmatizer()
    lemmatized_sentence = []
    for word, tag in pos_tag(tokens):
        if tag.startswith('NN'):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'
        lemmatized_sentence.append(lemmatizer.lemmatize(word, pos))
    return lemmatized_sentence

print(lemmatize_sentence(tweet_tokens[0]))

Ce code importe la classeWordNetLemmatizer et l'initialise à une variable,lemmatizer.

La fonctionlemmatize_sentence obtient d'abord la balise de position de chaque jeton d'un tweet. Dans l'instructionif, si la balise commence parNN, le jeton est attribué en tant que nom. De même, si la balise commence parVB, le jeton est attribué en tant que verbe.

Enregistrez et fermez le fichier, puis exécutez le script:

python3 nlp_test.py

Voici la sortie:

Output['#FollowFriday',
 '@France_Inte',
 '@PKuchly57',
 '@Milipol_Paris',
 'for',
 'be',
 'top',
 'engage',
 'member',
 'in',
 'my',
 'community',
 'this',
 'week',
 ':)']

Vous remarquerez que le verbebeing prend sa forme racine,be, et le nommembers devientmember. Avant de poursuivre, commentez la dernière ligne imprimant le tweet exemple du script.

Maintenant que vous avez créé avec succès une fonction de normalisation des mots, vous êtes prêt à passer à la suppression du bruit.

[[step-4 -—- remove-noise-from-the-data]] == Étape 4 - Suppression du bruit des données

Dans cette étape, vous allez supprimer le bruit du jeu de données. Noise est toute partie du texte qui n'ajoute pas de signification ou d'information aux données.

Le bruit étant spécifique à chaque projet, il est donc possible que le bruit d’un projet ne soit pas différent d’un projet à l’autre. Par exemple, les mots les plus courants dans une langue sont appelésstop words. Quelques exemples de mots vides sont «est», «le» et «a». Ils ne sont généralement pas pertinents lors du traitement d'une langue, sauf si un cas d'utilisation spécifique justifie leur inclusion.

Dans ce didacticiel, vous devrezuse regular expressions in Python rechercher et supprimer ces éléments:

  • Hyperlinks - Tous les hyperliens de Twitter sont convertis en raccourcisseur d'URLt.co. Par conséquent, les conserver dans le traitement de texte n’ajouterait aucune valeur à l’analyse.

  • Twitter handles in replies - Ces noms d'utilisateur Twitter sont précédés d'un symbole@, qui ne transmet aucune signification.

  • Punctuation and special characters - Bien que ceux-ci fournissent souvent un contexte aux données textuelles, ce contexte est souvent difficile à traiter. Pour plus de simplicité, vous supprimerez tous les signes de ponctuation et les caractères spéciaux des tweets.

Pour supprimer les hyperliens, vous devez d'abord rechercher une sous-chaîne qui correspond à une URL commençant parhttp:// ouhttps://, suivie de lettres, de chiffres ou de caractères spéciaux. Une fois qu'un modèle correspond, la méthode.sub() le remplace par une chaîne vide.

Puisque nous normaliserons les formes de mots dans la fonctionremove_noise(), vous pouvez commenter la fonctionlemmatize_sentence() du script.

Ajoutez le code suivant à votre fichiernlp_test.py pour supprimer le bruit de l'ensemble de données:

nlp_test.py

...

import re, string

def remove_noise(tweet_tokens, stop_words = ()):

    cleaned_tokens = []

    for token, tag in pos_tag(tweet_tokens):
        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
        token = re.sub("(@[A-Za-z0-9_]+)","", token)

        if tag.startswith("NN"):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'

        lemmatizer = WordNetLemmatizer()
        token = lemmatizer.lemmatize(token, pos)

        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
            cleaned_tokens.append(token.lower())
    return cleaned_tokens

Ce code crée une fonctionremove_noise() qui supprime le bruit et intègre la normalisation et la lemmatisation mentionnées dans la section précédente. Le code prend deux arguments: les jetons de tweet et le tuple de mots vides.

Le code utilise ensuite une boucle pour supprimer le bruit de l'ensemble de données. Pour supprimer les hyperliens, le code recherche d'abord une sous-chaîne qui correspond à une URL commençant parhttp:// ouhttps://, suivie de lettres, de chiffres ou de caractères spéciaux. Une fois qu'un modèle correspond, la méthode.sub() le remplace par une chaîne vide ou''.

De même, pour supprimer les mentions@, le code substitue la partie appropriée du texte à l'aide d'expressions régulières. Le code utilise la bibliothèquere pour rechercher les symboles@, suivis de chiffres, lettres ou_, et les remplace par une chaîne vide.

Enfin, vous pouvez supprimer la ponctuation en utilisant la bibliothèquestring.

En plus de cela, vous supprimerez également les mots vides à l'aide d'un ensemble intégré de mots vides dans NLTK, qui doit être téléchargé séparément.

Exécutez la commande suivante depuis une session interactive Python pour télécharger cette ressource:

nltk.download('stopwords')

Une fois la ressource téléchargée, quittez la session interactive.

Vous pouvez utiliser la méthode.words() pour obtenir une liste de mots vides en anglais. Pour tester la fonction, laissez-nous l'exécuter sur notre exemple de tweet. Ajoutez les lignes suivantes à la fin du fichiernlp_test.py:

nlp_test.py

...
from nltk.corpus import stopwords
stop_words = stopwords.words('english')

print(remove_noise(tweet_tokens[0], stop_words))

Après avoir enregistré et fermé le fichier, réexécutez le script pour recevoir une sortie similaire à celle-ci:

Output['#followfriday', 'top', 'engage', 'member', 'community', 'week', ':)']

Notez que la fonction supprime toutes les mentions@, les mots vides et convertit les mots en minuscules.

Avant de passer à l'exercice de modélisation à l'étape suivante, utilisez la fonctionremove_noise() pour nettoyer les tweets positifs et négatifs. Commentez la ligne pour imprimer la sortie deremove_noise() sur l'exemple de tweet et ajoutez ce qui suit au scriptnlp_test.py:

nlp_test.py

...
from nltk.corpus import stopwords
stop_words = stopwords.words('english')

#print(remove_noise(tweet_tokens[0], stop_words))

positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')

positive_cleaned_tokens_list = []
negative_cleaned_tokens_list = []

for tokens in positive_tweet_tokens:
    positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

for tokens in negative_tweet_tokens:
    negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

Maintenant que vous avez ajouté le code pour nettoyer les exemples de tweets, vous pouvez comparer les jetons d'origine aux jetons nettoyés pour un exemple de tweet. Si vous souhaitez tester cela, ajoutez le code suivant au fichier pour comparer les deux versions du 500ème tweet de la liste:

nlp_test.py

...
print(positive_tweet_tokens[500])
print(positive_cleaned_tokens_list[500])

Enregistrez et fermez le fichier et exécutez le script. Dans la sortie, vous verrez que la ponctuation et les liens ont été supprimés et que les mots ont été convertis en minuscules.

Output['Dang', 'that', 'is', 'some', 'rad', '@AbzuGame', '#fanart', '!', ':D', 'https://t.co/bI8k8tb9ht']
['dang', 'rad', '#fanart', ':d']

Certains problèmes peuvent survenir lors du prétraitement du texte. Par exemple, les mots sans espaces (“iLoveYou”) seront traités comme un seul mot et il peut être difficile de séparer ces mots. De plus, les scripts "Hi", "Hii" et "Hiiiii" seront traités différemment par le script, sauf si vous écrivez quelque chose de spécifique pour résoudre le problème. Il est courant d’affiner le processus de suppression du bruit pour vos données spécifiques.

Maintenant que vous avez vu la fonctionremove_noise() en action, assurez-vous de commenter ou de supprimer les deux dernières lignes du script afin de pouvoir y ajouter davantage:

nlp_test.py

...
#print(positive_tweet_tokens[500])
#print(positive_cleaned_tokens_list[500])

Dans cette étape, vous avez supprimé le bruit des données pour rendre l'analyse plus efficace. Dans l'étape suivante, vous analyserez les données pour rechercher les mots les plus courants dans votre exemple de données.

[[step-5 -—- Determination-Word-Density]] == Étape 5 - Détermination de la densité des mots

La forme la plus élémentaire d'analyse des données textuelles consiste à supprimer le mot fréquence. Un simple tweet est une entité trop petite pour connaître la distribution des mots. Par conséquent, l'analyse de la fréquence des mots serait effectuée sur tous les tweets positifs.

L'extrait de code suivant définita generator function, nomméget_all_words, qui prend une liste de tweets comme argument pour fournir une liste de mots dans tous les jetons de tweet joints. Ajoutez le code suivant à votre fichiernlp_test.py:

nlp_test.py

...

def get_all_words(cleaned_tokens_list):
    for tokens in cleaned_tokens_list:
        for token in tokens:
            yield token

all_pos_words = get_all_words(positive_cleaned_tokens_list)

Maintenant que vous avez compilé tous les mots de l'échantillon de tweets, vous pouvez découvrir quels sont les mots les plus courants en utilisant la classeFreqDist de NLTK. Ajout du code suivant au fichiernlp_test.py:

nlp_test.py

from nltk import FreqDist

freq_dist_pos = FreqDist(all_pos_words)
print(freq_dist_pos.most_common(10))

La méthode.most_common() répertorie les mots les plus fréquents dans les données. Enregistrez et fermez le fichier après avoir apporté ces modifications.

Lorsque vous exécutez le fichier maintenant, vous trouverez les termes les plus courants dans les données:

Output[(':)', 3691),
 (':-)', 701),
 (':d', 658),
 ('thanks', 388),
 ('follow', 357),
 ('love', 333),
 ('...', 290),
 ('good', 283),
 ('get', 263),
 ('thank', 253)]

À partir de ces données, vous pouvez voir que les entités émoticônes forment certaines des parties les plus courantes des tweets positifs. Avant de passer à l'étape suivante, veillez à commenter la dernière ligne du script qui imprime les dix principaux jetons.

Pour résumer, vous avez extrait les tweets denltk, les avez tokenisés, normalisés et nettoyés les tweets à utiliser dans le modèle. Enfin, vous avez également examiné les fréquences des jetons dans les données et vérifié les fréquences des dix premiers jetons.

Dans l'étape suivante, vous préparerez les données pour l'analyse des sentiments.

[[step-6 -—- preparation-data-for-the-model]] == Étape 6 - Préparation des données pour le modèle

L'analyse des sentiments est un processus d'identification d'une attitude de l'auteur sur un sujet qui est en train d'être écrit. Vous allez créer un jeu de données d'apprentissage pour former un modèle. Il s'agit d'un processus d'apprentissage machine d'apprentissage supervisé, qui nécessite d'associer chaque ensemble de données à un «sentiment» de formation. Dans ce tutoriel, votre modèle utilisera les sentiments «positif» et «négatif».

L'analyse des sentiments peut être utilisée pour classer le texte en une variété de sentiments. Pour des raisons de simplicité et de disponibilité du jeu de données de formation, ce didacticiel vous aide à former votre modèle dans deux catégories seulement, positive et négative.

Un modèle est une description d'un système utilisant des règles et des équations. Cela peut être aussi simple qu'une équation qui prédit le poids d'une personne, compte tenu de sa taille. Un modèle d'analyse des sentiments que vous construirez associerait les tweets à un sentiment positif ou négatif. Vous devrez diviser votre jeu de données en deux parties. Le but de la première partie est de construire le modèle, tandis que la prochaine partie teste les performances du modèle.

Au cours de l'étape de préparation des données, vous allez préparer les données pour l'analyse des sentiments en convertissant les jetons en formulaire de dictionnaire, puis en les scindant à des fins de formation et de test.

Conversion de jetons en dictionnaire

Tout d'abord, vous allez préparer les données à intégrer au modèle. Vous utiliserez lesNaive Bayes classifier dans NLTK pour effectuer l'exercice de modélisation. Notez que le modèle nécessite non seulement une liste de mots dans un tweet, mais un dictionnaire Python avec des mots comme clés etTrue comme valeurs. La fonction suivante crée une fonction de générateur pour changer le format des données nettoyées.

Ajoutez le code suivant pour convertir les tweets d'une liste de jetons nettoyés en dictionnaires avec des clés comme jetons etTrue comme valeurs. Les dictionnaires correspondants sont stockés danspositive_tokens_for_model etnegative_tokens_for_model.

nlp_test.py

...
def get_tweets_for_model(cleaned_tokens_list):
    for tweet_tokens in cleaned_tokens_list:
        yield dict([token, True] for token in tweet_tokens)

positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

Division du jeu de données pour la formation et le test du modèle

Ensuite, vous devez préparer les données pour l'entraînement de la classeNaiveBayesClassifier. Ajoutez le code suivant au fichier pour préparer les données:

nlp_test.py

...
import random

positive_dataset = [(tweet_dict, "Positive")
                     for tweet_dict in positive_tokens_for_model]

negative_dataset = [(tweet_dict, "Negative")
                     for tweet_dict in negative_tokens_for_model]

dataset = positive_dataset + negative_dataset

random.shuffle(dataset)

train_data = dataset[:7000]
test_data = dataset[7000:]

Ce code attache une étiquettePositive ouNegative à chaque tweet. Il crée ensuite undataset en joignant les tweets positifs et négatifs.

Par défaut, les données contiennent tous les tweets positifs suivis de tous les tweets négatifs en séquence. Lors de la formation du modèle, vous devez fournir un échantillon de vos données qui ne contient aucun biais. Pour éviter les biais, vous avez ajouté du code pour organiser les données de manière aléatoire à l'aide de la méthode.shuffle() derandom.

Enfin, le code divise les données mélangées dans un rapport de 70:30 pour la formation et les tests, respectivement. Étant donné que le nombre de tweets est 10 000, vous pouvez utiliser les 7 000 premiers tweets du jeu de données brassé pour la formation du modèle et les 3 000 derniers pour le test du modèle.

Au cours de cette étape, vous avez converti les jetons nettoyés en une forme de dictionnaire, mélangé de manière aléatoire l'ensemble de données et l'avez divisé en données d'apprentissage et de test.

[[step-7 -—- building-and-testing-the-model]] == Étape 7 - Construction et test du modèle

Enfin, vous pouvez utiliser la classeNaiveBayesClassifier pour créer le modèle. Utilisez la méthode.train() pour entraîner le modèle et la méthode.accuracy() pour tester le modèle sur les données de test.

nlp_test.py

...
from nltk import classify
from nltk import NaiveBayesClassifier
classifier = NaiveBayesClassifier.train(train_data)

print("Accuracy is:", classify.accuracy(classifier, test_data))

print(classifier.show_most_informative_features(10))

Enregistrez, fermez et exécutez le fichier après avoir ajouté le code. La sortie du code sera la suivante:

OutputAccuracy is: 0.9956666666666667

Most Informative Features
                      :( = True           Negati : Positi =   2085.6 : 1.0
                      :) = True           Positi : Negati =    986.0 : 1.0
                 welcome = True           Positi : Negati =     37.2 : 1.0
                  arrive = True           Positi : Negati =     31.3 : 1.0
                     sad = True           Negati : Positi =     25.9 : 1.0
                follower = True           Positi : Negati =     21.1 : 1.0
                     bam = True           Positi : Negati =     20.7 : 1.0
                    glad = True           Positi : Negati =     18.1 : 1.0
                     x15 = True           Negati : Positi =     15.9 : 1.0
               community = True           Positi : Negati =     14.1 : 1.0

La précision est définie comme le pourcentage de tweets dans le jeu de données de test pour lequel le modèle a pu correctement prédire le sentiment. Une précision de 99,5{}ur l'ensemble de test est plutôt bonne.

Dans le tableau qui présente les fonctionnalités les plus informatives, chaque ligne de la sortie indique le rapport entre l'occurrence d'un jeton dans les tweets balisés positifs et négatifs du jeu de données d'apprentissage. La première ligne des données signifie que dans tous les tweets contenant le jeton:(, le rapport des tweets négatifs aux tweets positifs était de2085.6 à1. Fait intéressant, il semble qu'il y ait un jeton avec:( dans les ensembles de données positifs. Vous pouvez voir que les deux éléments les plus discriminants du texte sont les émoticônes. De plus, des mots tels quesad conduisent à des sentiments négatifs, tandis quewelcome etglad sont associés à des sentiments positifs.

Ensuite, vous pouvez vérifier comment le modèle fonctionne sur les tweets aléatoires de Twitter. Ajoutez ce code au fichier:

nlp_test.py

...
from nltk.tokenize import word_tokenize

custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."

custom_tokens = remove_noise(word_tokenize(custom_tweet))

print(classifier.classify(dict([token, True] for token in custom_tokens)))

Ce code vous permettra de tester des tweets personnalisés en mettant à jour la chaîne associée à la variablecustom_tweet. Enregistrez et fermez le fichier après avoir apporté ces modifications.

Exécutez le script pour analyser le texte personnalisé. Voici la sortie pour le texte personnalisé dans l'exemple:

Output'Negative'

Vous pouvez également vérifier si elle caractérise correctement les tweets positifs:

nlp_test.py

...
custom_tweet = 'Congrats #SportStar on your 7th best goal from last season winning goal of the year :) #Baller #Topbin #oneofmanyworldies'

Voici la sortie:

Output'Positive'

Maintenant que vous avez testé les sentiments positifs et négatifs, mettez à jour la variable pour tester un sentiment plus complexe tel que le sarcasme.

nlp_test.py

...
custom_tweet = 'Thank you for sending my baggage to CityX and flying me to CityY at the same time. Brilliant service. #thanksGenericAirline'

Voici la sortie:

Output'Positive'

Le modèle a classé cet exemple comme positif. En effet, les données de formation n’étaient pas assez complètes pour classer les tweets sarcastiques comme négatifs. Si vous souhaitez que votre modèle prédit le sarcasme, vous devez fournir suffisamment de données de formation pour le former en conséquence.

Dans cette étape, vous avez construit et testé le modèle. Vous avez également exploré certaines de ses limites, telles que l'absence de détection du sarcasme dans certains exemples. Votre code terminé contient toujours des artefacts après avoir suivi le didacticiel. Par conséquent, la prochaine étape vous guidera pour aligner le code sur les meilleures pratiques de Python.

[[step-8 -—- cleaning-up-the-code-optional]] == Étape 8 - Nettoyage du code (optionnel)

Bien que vous ayez terminé le didacticiel, il est recommandé de réorganiser le code dans le fichiernlp_test.py pour suivre les meilleures pratiques de programmation. Selon les meilleures pratiques, votre code devrait répondre à ces critères:

  • Toutes les importations doivent figurer en haut du fichier. Les importations de la même bibliothèque doivent être regroupées dans une seule instruction.

  • Toutes les fonctions doivent être définies après les importations.

  • Toutes les instructions du fichier doivent être hébergées sous une conditionif __name__ == "__main__":. Cela garantit que les instructions ne sont pas exécutées si vous importez les fonctions du fichier dans un autre fichier.

Nous supprimerons également le code qui a été commenté en suivant le tutoriel, ainsi que la fonctionlemmatize_sentence, car la lemmatisation est complétée par la nouvelle fonctionremove_noise.

Voici la version nettoyée denlp_test.py:

from nltk.stem.wordnet import WordNetLemmatizer
from nltk.corpus import twitter_samples, stopwords
from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize
from nltk import FreqDist, classify, NaiveBayesClassifier

import re, string, random

def remove_noise(tweet_tokens, stop_words = ()):

    cleaned_tokens = []

    for token, tag in pos_tag(tweet_tokens):
        token = re.sub('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|'\
                       '(?:%[0-9a-fA-F][0-9a-fA-F]))+','', token)
        token = re.sub("(@[A-Za-z0-9_]+)","", token)

        if tag.startswith("NN"):
            pos = 'n'
        elif tag.startswith('VB'):
            pos = 'v'
        else:
            pos = 'a'

        lemmatizer = WordNetLemmatizer()
        token = lemmatizer.lemmatize(token, pos)

        if len(token) > 0 and token not in string.punctuation and token.lower() not in stop_words:
            cleaned_tokens.append(token.lower())
    return cleaned_tokens

def get_all_words(cleaned_tokens_list):
    for tokens in cleaned_tokens_list:
        for token in tokens:
            yield token

def get_tweets_for_model(cleaned_tokens_list):
    for tweet_tokens in cleaned_tokens_list:
        yield dict([token, True] for token in tweet_tokens)

if __name__ == "__main__":

    positive_tweets = twitter_samples.strings('positive_tweets.json')
    negative_tweets = twitter_samples.strings('negative_tweets.json')
    text = twitter_samples.strings('tweets.20150430-223406.json')
    tweet_tokens = twitter_samples.tokenized('positive_tweets.json')[0]

    stop_words = stopwords.words('english')

    positive_tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
    negative_tweet_tokens = twitter_samples.tokenized('negative_tweets.json')

    positive_cleaned_tokens_list = []
    negative_cleaned_tokens_list = []

    for tokens in positive_tweet_tokens:
        positive_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

    for tokens in negative_tweet_tokens:
        negative_cleaned_tokens_list.append(remove_noise(tokens, stop_words))

    all_pos_words = get_all_words(positive_cleaned_tokens_list)

    freq_dist_pos = FreqDist(all_pos_words)
    print(freq_dist_pos.most_common(10))

    positive_tokens_for_model = get_tweets_for_model(positive_cleaned_tokens_list)
    negative_tokens_for_model = get_tweets_for_model(negative_cleaned_tokens_list)

    positive_dataset = [(tweet_dict, "Positive")
                         for tweet_dict in positive_tokens_for_model]

    negative_dataset = [(tweet_dict, "Negative")
                         for tweet_dict in negative_tokens_for_model]

    dataset = positive_dataset + negative_dataset

    random.shuffle(dataset)

    train_data = dataset[:7000]
    test_data = dataset[7000:]

    classifier = NaiveBayesClassifier.train(train_data)

    print("Accuracy is:", classify.accuracy(classifier, test_data))

    print(classifier.show_most_informative_features(10))

    custom_tweet = "I ordered just once from TerribleCo, they screwed up, never used the app again."

    custom_tokens = remove_noise(word_tokenize(custom_tweet))

    print(custom_tweet, classifier.classify(dict([token, True] for token in custom_tokens)))

Conclusion

Ce didacticiel vous a présenté un modèle d'analyse de sentiment de base utilisant la bibliothèquenltk dans Python 3. Tout d'abord, vous avez effectué un pré-traitement sur les tweets en créant un tweet, en normalisant les mots et en supprimant le bruit. Ensuite, vous avez visualisé les éléments fréquemment présents dans les données. Enfin, vous avez créé un modèle pour associer des tweets à un sentiment particulier.

Un modèle d'apprentissage supervisé ne vaut que par ses données d'apprentissage. Pour renforcer davantage le modèle, vous pouvez envisager d’ajouter davantage de catégories telles que l’excitation et la colère. Dans ce tutoriel, vous n’avez fait qu’effleurer la surface en construisant un modèle rudimentaire. Voici lesa detailed guide on various considerations dont il faut tenir compte lors de l'analyse des sentiments.