Recherche de site Web

Comment effectuer une analyse de sentiment en Python 3 en utilisant le Natural Language Toolkit (NLTK)


L'auteur a choisi le fonds Open Internet/Free Speech pour recevoir un don dans le cadre du programme Write for DOnations.

Introduction

Une grande quantité de données générées aujourd'hui est non structurée, ce qui nécessite un traitement pour en tirer des idées. Parmi les exemples de données non structurées, on trouve des articles de presse, des publications sur les réseaux sociaux et l'historique de recherche. Le processus d'analyse du langage naturel et de compréhension de celui-ci relève du domaine du traitement du langage naturel (NLP). L'analyse de sentiment est une tâche courante en NLP, qui consiste à classer des textes ou des parties de textes en un sentiment pré-défini. Vous utiliserez le Natural Language Toolkit (NLTK), une bibliothèque NLP couramment utilisée en Python, pour analyser des données textuelles.

Dans ce tutoriel, vous préparerez un ensemble de données d'exemples de tweets provenant du package NLTK pour le traitement du langage naturel (NLP) en utilisant différentes méthodes de nettoyage des données. Une fois l'ensemble de données prêt pour le traitement, vous entraînerez un modèle sur des tweets pré-classés et utiliserez le modèle pour classer les tweets d'exemple en sentiments négatifs et positifs.

Cet article suppose que vous êtes familiarisé avec les bases de Python (voir notre série Comment coder en Python 3), principalement l'utilisation des structures de données, des classes et des méthodes. Le tutoriel suppose que vous n'avez aucune connaissance en NLP et nltk, bien qu'une certaine connaissance à ce sujet soit un atout.

Conditions préalables

  • Ce tutoriel est basé sur la version 3.6.5 de Python. Si vous n'avez pas Python 3 installé, voici un guide pour installer et configurer un environnement de programmation local pour Python 3.
  • Il est recommandé d'avoir de l'expérience dans le travail avec des données linguistiques. Si vous êtes nouveau dans l'utilisation de NLTK, consultez le guide Comment travailler avec des données linguistiques en Python 3 en utilisant le Natural Language Toolkit (NLTK).

Étape 1 — Installer NLTK et télécharger les données

Vous utiliserez le package NLTK en Python pour toutes les tâches de traitement du langage naturel dans ce tutoriel. Dans cette étape, vous allez installer NLTK et télécharger les tweets d'exemple que vous utiliserez pour entraîner et tester votre modèle.

Tout d'abord, installez le package NLTK avec le gestionnaire de packages pip :

  1. pip install nltk==3.3

Ce tutoriel utilisera des tweets d'exemple qui font partie du package NLTK. Tout d'abord, démarrez une session interactive Python en exécutant la commande suivante :

  1. python3

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

  1. import nltk

Téléchargez les tweets d'exemple du package NLTK :

  1. nltk.download('twitter_samples')

L'exécution de cette commande depuis 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 entraîner votre modèle sur l'analyse de sentiment plus tard dans le tutoriel. Les tweets sans sentiments seront utilisés pour tester votre modèle.

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

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

Étape 2 — Tokeniser les données

La langue sous sa forme originale ne peut pas être traitée avec précision par une machine, il est donc nécessaire de traiter la langue pour qu'elle soit plus facile à comprendre par la machine. La première étape pour comprendre les données consiste en un processus appelé tokenisation, ou la division de chaînes en parties plus petites appelées tokens.

Un jeton est une séquence de caractères dans un texte qui sert d'unité. En fonction de la manière dont vous créez les jetons, ils peuvent consister en mots, émoticônes, hashtags, liens, ou même des caractères individuels. Une façon de base de diviser le langage en jetons est de diviser le texte en fonction des espaces et de la ponctuation.

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

  1. nano nlp_test.py

Dans ce fichier, vous allez d'abord importer le twitter_samples afin de pouvoir travailler avec ces données :

from nltk.corpus import twitter_samples

Cela importera trois ensembles de données de NLTK contenant divers tweets pour entraîner et tester le modèle :

  • tweets_négatifs.json: 5000 tweets avec des sentiments négatifs
  • tweets_positifs.json: 5000 tweets avec des sentiments positifs
  • tweets.20150430-223406.json: 20000 tweets sans sentiments

Ensuite, créez des variables pour positive_tweets, negative_tweets et text :

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éthode strings() de twitter_samples affichera tous les tweets d'un ensemble de données sous forme de chaînes. Définir les différentes collections de tweets comme une 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 module punkt 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 ce point dans une phrase ne signifie pas nécessairement qu'elle est terminée. Tout d'abord, lancez une session interactive Python:

  1. python3

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

  1. import nltk
  2. nltk.download('punkt')

Une fois le téléchargement terminé, vous êtes prêt à utiliser les tokenizers 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 tokenize le jeu de données positive_tweets.json:

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 surligné à votre script nlp_test.py. Cela va tokenizer un seul tweet du jeu de données positive_tweets.json :

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 :

  1. python3 nlp_test.py

Le processus de tokenisation prend du temps car ce n'est pas un simple découpage sur les espaces blancs. Après quelques instants de traitement, vous verrez ce qui suit :

['#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 à l'aide d'expressions régulières plus tard dans ce tutoriel.

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

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 tokeniser les données. Dans l'étape suivante, vous mettrez à jour le script pour normaliser les données.

Étape 3 — Normaliser les données

Les mots ont différentes formes—par exemple, « courut », « court » et « courant » sont des formes variées du même verbe, « courir ». Selon le besoin de votre analyse, toutes ces versions peuvent devoir être converties à la même forme, « courir ». La normalisation en NLP est le processus de conversion d'un mot à sa forme canonique.

La normalisation aide à regrouper des mots ayant le même sens mais des formes différentes. Sans normalisation, "couru", "court" et "courant" seraient traités comme des mots différents, même si vous souhaitez qu'ils soient considérés comme le même mot. Dans cette section, vous explorez le racinement et la lemmatisation, qui sont deux techniques populaires de normalisation.

La racine est un processus qui consiste à supprimer des affixes d'un mot. La racine, ne travaillant qu'avec des formes verbales simples, est un processus heuristique qui élimine les terminaisons des mots.

Dans ce tutoriel, vous allez utiliser le processus de lemmatisation, qui normalise un mot en tenant compte du vocabulaire et de l'analyse morphologique des 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 en termes de vitesse. Une comparaison entre le stemming et la lemmatisation revient finalement à un compromis entre vitesse et précision.

Avant de procéder à l'utilisation de la lemmatisation, téléchargez les ressources nécessaires en saisissant ce qui suit dans une session interactive Python :

  1. python3

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

  1. import nltk
  2. nltk.download('wordnet')
  3. 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 ressource averaged_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 de faire fonctionner un lemmatiseur, vous devez déterminer le contexte de chaque mot dans votre texte. Cela se fait par le biais d'un algorithme de balisage, qui évalue la position relative d'un mot dans une phrase. Dans une session Python, importez la fonction pos_tag et fournissez une liste de tokens comme argument pour obtenir les balises. Essayons cela en Python:

  1. from nltk.tag import pos_tag
  2. from nltk.corpus import twitter_samples
  3. tweet_tokens = twitter_samples.tokenized('positive_tweets.json')
  4. print(pos_tag(tweet_tokens[0]))

Voici la sortie de la fonction pos_tag.

[('#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 étiquettes, 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, subordonnée
  • VBG : Verbe, gérondif ou participe présent
  • VBN: Verbe, participe passé

Voici une liste complète de l'ensemble de données.

En général, si une étiquette commence par NN, le mot est un nom, et si elle commence par VB, le mot est un verbe. Après avoir examiné les étiquettes, quittez la session Python en entrant exit().

Pour intégrer cela dans une fonction qui normalise une phrase, vous devez d'abord générer les étiquettes pour chaque jeton dans le texte, puis lemmatiser chaque mot en utilisant l'étiquette.

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

...

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 classe WordNetLemmatizer et l'initialise dans une variable, lemmatizer.

La fonction lemmatize_sentence commence par obtenir le tag de position de chaque jeton d'un tweet. Dans l'instruction if, si le tag commence par NN, le jeton est attribué en tant que nom. De même, si le tag commence par VB, le jeton est attribué en tant que verbe.

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

  1. python3 nlp_test.py

Voici le résultat :

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

Vous remarquerez que le verbe being change pour sa forme racine, be, et le nom members change en member. Avant de continuer, commentez la dernière ligne qui imprime le tweet d'exemple du script.

Maintenant que vous avez réussi à créer une fonction pour normaliser les mots, vous êtes prêt à passer à la suppression du bruit.

Étape 4 — Élimination des bruits des données

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

Le bruit est spécifique à chaque projet, donc ce qui constitue du bruit dans un projet peut ne pas en être dans un autre projet. Par exemple, les mots les plus courants dans une langue sont appelés mots vides. Quelques exemples de mots vides sont « est », « le » et « un ». Ils sont généralement sans pertinence lors du traitement du langage, à moins qu'un cas d'utilisation spécifique ne justifie leur inclusion.

Dans ce tutoriel, vous utiliserez des expressions régulières en Python pour rechercher et supprimer ces éléments :

  • Hyperliens - Tous les hyperliens sur Twitter sont convertis en l'abréviateur d'URL t.co. Par conséquent, les conserver dans le traitement du texte n'ajouterait aucune valeur à l'analyse.
  • Utilisateurs Twitter dans les réponses - Ces noms d'utilisateur Twitter sont précédés d'un @ symbole, qui ne véhicule aucune signification.
  • La ponctuation et les caractères spéciaux - Bien qu'ils fournissent souvent un contexte aux données textuelles, ce contexte est souvent difficile à traiter. Pour simplifier, vous supprimerez toute la 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 par http:// ou https://, suivie de lettres, de chiffres ou de caractères spéciaux. Une fois qu'un motif est correspondant, la méthode .sub() le remplace par une chaîne vide.

Puisque nous normaliserons les formes de mots dans la fonction remove_noise(), vous pouvez commenter la fonction lemmatize_sentence() dans le script.

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

...

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 fonction remove_noise() qui élimine le bruit et intègre la normalisation et la lemmatisation mentionnées dans la section précédente. Le code prend deux arguments : les tokens du tweet et le tuple des mots vides.

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

De même, pour supprimer les mentions @, le code substitue la partie pertinente du texte en utilisant des expressions régulières. Le code utilise la bibliothèque re pour rechercher les symboles @, suivis de chiffres, de lettres ou de _, et les remplace par une chaîne vide.

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

De plus, 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 :

  1. 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, exécutons-la sur notre tweet d'exemple. Ajoutez les lignes suivantes à la fin du fichier 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, exécutez à nouveau le script pour recevoir une sortie similaire à ce qui suit :

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

Remarque 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 fonction remove_noise() pour nettoyer les tweets positifs et négatifs. Commentez la ligne pour imprimer la sortie de remove_noise() sur le tweet d'exemple et ajoutez ce qui suit au script 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 tweets d'échantillons, vous souhaiterez peut-être comparer les jetons originaux avec les jetons nettoyés d'un tweet d'échantillon. Si vous souhaitez tester cela, ajoutez le code suivant au fichier pour comparer les deux versions du 500ème tweet de la liste :

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

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

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

Il y a certains problèmes qui peuvent survenir lors du prétraitement du texte. Par exemple, les mots sans espaces (comme « iLoveYou ») seront considérés comme un seul mot et il peut être difficile de séparer de tels mots. De plus, « Hi », « Hii » et « Hiiiii » seront traités différemment par le script, à moins que vous n'écriviez quelque chose de spécifique pour résoudre ce problème. Il est courant d'affiner le processus de suppression de bruit pour vos données spécifiques.

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

...
#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 la prochaine étape, vous allez analyser les données pour trouver les mots les plus courants dans votre échantillon de données.

Étape 5 — Déterminer la densité des mots

La forme d'analyse la plus basique des données textuelles consiste à déterminer la fréquence des mots. Un seul tweet est trop petit pour analyser la distribution des mots, c'est pourquoi l'analyse de la fréquence des mots sera effectuée sur tous les tweets positifs.

Le snippet suivant définit une fonction génératrice, nommée get_all_words, qui prend une liste de tweets en argument pour fournir une liste de mots dans tous les jetons de tweets réunis. Ajoutez le code suivant à votre fichier 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 dans l'échantillon de tweets, vous pouvez découvrir quels sont les mots les plus communs en utilisant la classe FreqDist de NLTK. Ajoutez le code suivant au fichier 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() liste les mots qui apparaissent le plus fréquemment dans les données. Enregistrez et fermez le fichier après avoir effectué ces modifications.

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

[(':)', 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 d'émoticônes constituent une partie des tweets positifs les plus courants. Avant de passer à l'étape suivante, assurez-vous de commenter la dernière ligne du script qui imprime les dix premiers jetons.

En résumé, vous avez extrait les tweets de nltk, tokenisé, normalisé et nettoyé les tweets pour les utiliser dans le modèle. Enfin, vous avez également examiné la fréquence des tokens dans les données et vérifié la fréquence des dix premiers tokens.

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

Étape 6 — Préparation des données pour le modèle

L'analyse de sentiment est un processus d'identification de l'attitude de l'auteur sur un sujet sur lequel il écrit. Vous allez créer un ensemble de données d'entraînement pour former un modèle. C'est un processus d'apprentissage supervisé en machine learning, qui nécessite d'associer chaque ensemble de données à un « sentiment » pour l'entraînement. Dans ce tutoriel, votre modèle utilisera les sentiments « positif » et « négatif ».

L'analyse des sentiments peut être utilisée pour catégoriser le texte en une variété de sentiments. Par souci de simplicité et de disponibilité de l'ensemble de données d'entraînement, ce tutoriel vous aide à entraîner votre modèle uniquement dans deux catégories : positif et négatif.

Un modèle est une description d'un système utilisant des règles et des équations. Il peut être aussi simple qu'une équation qui prédit le poids d'une personne en fonction de sa taille. Un modèle d'analyse de sentiment que vous allez construire associera des tweets à un sentiment positif ou négatif. Vous devrez diviser votre ensemble de données en deux parties. Le but de la première partie est de construire le modèle, tandis que l'autre partie teste la performance du modèle.

Dans l'étape de préparation des données, vous préparerez les données pour l'analyse des sentiments en convertissant les jetons en forme de dictionnaire, puis en divisant les données pour des fins d'entraînement et de test.

Conversion de jetons en dictionnaire

Tout d'abord, vous préparerez les données à alimenter dans le modèle. Vous utiliserez le classificateur Naive Bayes de 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 aussi un dictionnaire Python avec des mots comme clés et True comme valeurs. La fonction suivante crée une fonction génératrice pour changer le format des données nettoyées.

Ajoutez le code suivant pour convertir les tweets d'une liste de tokens nettoyés en dictionnaires avec des clés comme tokens et True comme valeurs. Les dictionnaires correspondants sont stockés dans positive_tokens_for_model et negative_tokens_for_model.

...
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)

Diviser le jeu de données pour entraîner et tester le modèle

Ensuite, vous devez préparer les données pour entraîner la classe NaiveBayesClassifier. Ajoutez le code suivant au fichier pour préparer les données :

...
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 attribue une étiquette Positive ou Négative à chaque tweet. Il crée ensuite un ensemble de données 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 l'entraînement du modèle, vous devez fournir un échantillon de vos données qui ne contient aucun biais. Pour éviter le biais, vous avez ajouté du code pour organiser les données de manière aléatoire en utilisant la méthode .shuffle() de random.

Enfin, le code divise les données mélangées en un ratio de 70:30 pour l'entraînement et le test, respectivement. Étant donné que le nombre de tweets est de 10 000, vous pouvez utiliser les 7 000 premiers tweets de l'ensemble de données mélangé pour entraîner le modèle et les 3 000 derniers pour tester le modèle.

Dans cette étape, vous avez converti les jetons nettoyés en une forme de dictionnaire, mélangé aléatoirement l'ensemble de données et divisé en données d'entraînement et de test.

Étape 7 — Construction et Test du Modèle

Enfin, vous pouvez utiliser la classe NaiveBayesClassifier pour construire 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.

...
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 :

Accuracy 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 l'ensemble de données de test pour lesquels le modèle a été en mesure de prédire correctement le sentiment. Une précision de 99,5 % sur l'ensemble de test est plutôt bonne.

Dans le tableau qui montre les caractéristiques les plus informatives, chaque ligne dans la sortie montre le ratio d'occurrence d'un token dans les tweets étiquetés positifs et négatifs dans le jeu de données d'entraînement. La première ligne des données indique que dans tous les tweets contenant le token :(, le ratio de tweets négatifs par rapport aux tweets positifs était de 2085.6 à 1. Fait intéressant, il semble qu'il y ait un token avec :( dans les ensembles de données positifs. Vous pouvez voir que les deux principaux éléments discriminants dans le texte sont les émoticônes. De plus, des mots tels que triste conduisent à des sentiments négatifs, tandis que bienvenue et content sont associés à des sentiments positifs.

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

...
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 variable custom_tweet. Enregistrez et fermez le fichier après avoir effectué ces modifications.

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

'Negative'

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

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

Voici la sortie :

'Positive'

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

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

Voici le résultat :

'Positive'

Le modèle a classé cet exemple comme positif. C'est parce que les données d'apprentissage n'étaient pas suffisamment complètes pour classer les tweets sarcastiques comme négatifs. Si vous souhaitez que votre modèle prédit le sarcasme, vous devez fournir une quantité suffisante de données d'apprentissage pour l'entraîner en conséquence.

Dans cette étape, vous avez construit et testé le modèle. Vous avez également exploré certaines de ses limites, comme le fait de ne pas détecter le sarcasme dans des exemples particuliers. Votre code complété contient encore des artefacts laissés par le suivi du tutoriel, donc la prochaine étape vous guidera pour aligner le code sur les meilleures pratiques de Python.

Étape 8 — Nettoyage du code (facultatif)

Bien que vous ayez terminé le tutoriel, il est recommandé de réorganiser le code dans le fichier nlp_test.py pour suivre les meilleures pratiques de programmation. Selon les meilleures pratiques, votre code doit répondre aux critères suivants:

  • Tous les imports doivent être en haut du fichier. Les imports de la même bibliothèque doivent être regroupés dans une seule déclaration.
  • Toutes les fonctions doivent être définies après les importations.
  • Toutes les instructions dans le fichier doivent être enfermées sous une condition if __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 allons également supprimer le code qui a été commenté en suivant le tutoriel, ainsi que la fonction lemmatize_sentence, car la lemmatisation est terminée par la nouvelle fonction remove_noise.

Voici la version nettoyée de nlp_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 tutoriel vous a introduit à un modèle de base d'analyse de sentiments utilisant la bibliothèque nltk en Python 3. Tout d'abord, vous avez effectué un pré-traitement sur des tweets en tokenisant un tweet, en normalisant les mots et en supprimant le bruit. Ensuite, vous avez visualisé les éléments apparaissant fréquemment dans les données. Enfin, vous avez construit un modèle pour associer les tweets à un sentiment particulier.

Un modèle d'apprentissage supervisé n'est aussi bon que ses données d'entraînement. Pour renforcer davantage le modèle, vous pourriez envisager d'ajouter plus de catégories comme l'excitation et la colère. Dans ce tutoriel, vous n'avez qu'effleuré le sujet en construisant un modèle rudimentaire. Voici un guide détaillé sur les diverses considérations dont il faut tenir compte lors de l'analyse des sentiments.