Premiers pas avec la bibliothèque NLTK de Python – Real Python

By | janvier 13, 2021

trouver un expert Python

Une fois que vous aurez compris les bases de Python, vous familiariser avec ses packages les plus populaires augmentera non seulement votre maîtrise du langage, mais augmentera également rapidement votre polyvalence. Dans ce didacticiel, vous découvrirez les incroyables fonctionnalités du Natural Language Toolkit (NLTK) pour le traitement et l'analyse de texte, des fonctions de base à l'analyse des sentiments grâce à l'apprentissage automatique!

Analyse des sentiments peut vous aider à déterminer le rapport entre les engagements positifs et négatifs sur un sujet spécifique. Vous pouvez analyser des corps de texte, tels que des commentaires, des tweets et des critiques de produits, pour obtenir des informations de votre public. Dans ce didacticiel, vous découvrirez les fonctionnalités importantes de NLTK pour le traitement des données textuelles et les différentes approches que vous pouvez utiliser pour effectuer une analyse des sentiments sur vos données.

À la fin de ce didacticiel, vous serez prêt à:

  • Divisé et filtre données textuelles en préparation pour l'analyse
  • Analyser fréquence des mots
  • Trouver concordance et collocations en utilisant différentes méthodes
  • Effectuer rapidement analyse des sentiments avec le classificateur intégré de NLTK
  • Définir les fonctionnalités pour classification personnalisée
  • Utiliser et comparer classificateurs pour l'analyse des sentiments avec NLTK

Premiers pas avec NLTK

La bibliothèque NLTK contient divers utilitaires qui vous permettent de manipuler et d'analyser efficacement les données linguistiques. Parmi ses fonctionnalités avancées figurent classificateurs de texte que vous pouvez utiliser pour de nombreux types de classification, y compris l'analyse des sentiments.

Analyse des sentiments est la pratique consistant à utiliser des algorithmes pour classer divers échantillons de texte apparenté en catégories globales positives et négatives. Avec NLTK, vous pouvez utiliser ces algorithmes via de puissantes opérations d'apprentissage automatique intégrées pour obtenir des informations à partir de données linguistiques.

Installation et importation

Vous allez commencer par installer certains prérequis, notamment NLTK lui-même ainsi que les ressources spécifiques dont vous aurez besoin tout au long de ce didacticiel.

Première utilisation pépin pour installer NLTK:

$ python3 -m pip installer nltk

Bien que cela installera le module NLTK, vous devrez toujours obtenir quelques ressources supplémentaires. Certains d'entre eux sont des échantillons de texte et d'autres sont des modèles de données requis par certaines fonctions NLTK.

Pour obtenir les ressources dont vous aurez besoin, utilisez nltk.download ():

importer nltk

nltk.Télécharger()

NLTK affichera un gestionnaire de téléchargement montrant toutes les ressources disponibles et installées. Voici ceux que vous devrez télécharger pour ce didacticiel:

  • noms: Une liste de noms anglais courants compilée par Mark Kantrowitz
  • mots vides: Une liste de mots très courants, comme des articles, des pronoms, des prépositions et des conjonctions
  • state_union: Un échantillon des discours sur l'état de l'Union transcrits par différents présidents américains, compilé par Kathleen Ahrens
  • twitter_samples: Une liste d'expressions de médias sociaux publiées sur Twitter
  • critiques de films: Deux mille critiques de films classées par Bo Pang et Lillian Lee
  • average_perceptron_tagger: Un modèle de données que NLTK utilise pour catégoriser les mots dans leur partie du discours
  • vader_lexicon: Une liste de mots et de jargon auxquels NLTK fait référence lors de l'analyse des sentiments, créée par C.J. Hutto et Eric Gilbert
  • punkt: Un modèle de données créé par Jan Strunk que NLTK utilise pour diviser les textes complets en listes de mots

Un moyen rapide de télécharger des ressources spécifiques directement à partir de la console consiste à transmettre une liste à nltk.download ():

>>>

>>> importer nltk

>>> nltk.Télécharger([[[[
...     "noms",
...     "mots vides",
...     "state_union",
...     "twitter_samples",
...     "critiques de films",
...     "average_perceptron_tagger",
...     "vader_lexicon",
...     "punkt",
... ])
[nltk_data]    Téléchargement des noms de paquet dans / home / user / nltk_data ...
[nltk_data]            Décompression de corpus / names.zip.
[nltk_data]    Téléchargement des mots vides du paquet dans / home / user / nltk_data ...
[nltk_data]            Décompression corpora / stopwords.zip.
[nltk_data]    Téléchargement du package state_union vers
[nltk_data]                    / home / utilisateur / nltk_data ...
[nltk_data]            Décompression de corpus / state_union.zip.
[nltk_data]    Téléchargement du package twitter_samples sur
[nltk_data]                    / home / utilisateur / nltk_data ...
[nltk_data]            Décompression de corpus / twitter_samples.zip.
[nltk_data]    Téléchargement du package movie_reviews sur
[nltk_data]                    / home / utilisateur / nltk_data ...
[nltk_data]            Décompressez corpora / movie_reviews.zip.
[nltk_data]    Téléchargement du package averaged_perceptron_tagger vers
[nltk_data]                    / home / utilisateur / nltk_data ...
[nltk_data]            Décompression des taggers / averaged_perceptron_tagger.zip.
[nltk_data]    Téléchargement du package vader_lexicon sur
[nltk_data]                    / home / utilisateur / nltk_data ...
[nltk_data]    Téléchargement du paquet punkt dans / home / user / nltk_data ...
[nltk_data]            Décompression des jetons / punkt.zip.
Vrai

Cela indiquera à NLTK de rechercher et de télécharger chaque ressource en fonction de son identifiant.

Si NLTK nécessite des ressources supplémentaires que vous n'avez pas installées, vous verrez un message utile LookupError avec des détails et des instructions pour télécharger la ressource:

>>>

>>> importer nltk

>>> w = nltk.corpus.Shakespeare.mots()
...
LookupError:
************************************************** ********************
        Ressource shakespeare introuvable.
        Veuillez utiliser le téléchargeur NLTK pour obtenir la ressource:

        >>> importer nltk
        >>> nltk.download ('shakespeare')
...

le LookupError spécifie quelle ressource est nécessaire pour l'opération demandée ainsi que des instructions pour la télécharger à l'aide de son identifiant.

Compilation des données

NLTK fournit un certain nombre de fonctions que vous pouvez appeler avec peu ou pas d'arguments qui vous aideront à analyser le texte de manière significative avant même de toucher ses capacités d'apprentissage automatique. De nombreux utilitaires de NLTK sont utiles pour préparer vos données pour une analyse plus avancée.

Bientôt, vous en apprendrez davantage sur les distributions de fréquences, la concordance et les colocations. Mais d'abord, vous avez besoin de quelques données.

Commencez par charger le corpus sur l'état de l'Union que vous avez téléchargé précédemment:

mots = [[[[w pour w dans nltk.corpus.state_union.mots() si w.isalpha()]

Notez que vous créez une liste de mots individuels avec le corpus .mots() méthode, mais vous utilisez str.isalpha () pour n'inclure que les mots composés de lettres. Sinon, votre liste de mots peut se retrouver avec des «mots» qui ne sont que des signes de ponctuation.

Jetez un œil à votre liste. Vous remarquerez de nombreux petits mots tels que «de», «a», «le», etc. Ces mots communs sont appelés mots d'arrêt, et ils peuvent avoir un effet négatif sur votre analyse car ils apparaissent si souvent dans le texte. Heureusement, il existe un moyen pratique de les filtrer.

NLTK fournit un petit corpus de mots vides que vous pouvez charger dans une liste:

mots vides = nltk.corpus.mots vides.mots("Anglais")

Assurez-vous de spécifier Anglais comme langue souhaitée puisque ce corpus contient des mots vides dans différentes langues.

Vous pouvez maintenant supprimer les mots vides de votre liste de mots d'origine:

mots = [[[[w pour w dans mots si w.inférieur() ne pas dans mots vides]

Puisque tous les mots du mots vides liste sont en minuscules, et ceux de la liste d'origine peuvent ne pas l'être, vous utilisez str.lower () pour tenir compte de tout écart. Sinon, vous risquez de vous retrouver avec des mots vides mixtes ou en majuscules dans votre liste.

Bien que vous utilisiez des corpus fournis par NLTK pour ce didacticiel, il est possible de créer vos propres corpus de texte à partir de n'importe quelle source. Construire un corpus peut être aussi simple que de charger du texte brut ou aussi complexe que d'étiqueter et de catégoriser chaque phrase. Reportez-vous à la documentation de NLTK pour plus d’informations sur la façon de travailler avec les lecteurs de corpus.

Pour une analyse rapide, créer un corpus peut être excessif. Si vous n'avez besoin que d'une liste de mots, il existe des moyens plus simples d'atteindre cet objectif. Au-delà des propres méthodes de manipulation de chaînes de Python, NLTK fournit nltk.word_tokenize (), une fonction qui divise le texte brut en mots individuels. Tandis que tokenisation est en soi un sujet plus important (et probablement l’une des étapes que vous suivrez lors de la création d’un corpus personnalisé), ce tokenizer fournit très bien des listes de mots simples.

Pour l'utiliser, appelez word_tokenize () avec le texte brut que vous souhaitez fractionner:

>>>

>>> de impression importer impression

>>> texte = "" "
... Pour une analyse rapide, créer un corpus peut être excessif.
... Si vous n'avez besoin que d'une liste de mots,
... il existe des moyens plus simples d'atteindre cet objectif. "" "
>>> impression(nltk.word_tokenize(texte), largeur=79, compact=Vrai)
['Pour''un''quick''analyse''''créer''un''corpus''pourrait''['Pour''un''quick''analyse''''créer''un''corpus''pourrait''['For''some''quick''analysis''''creating''a''corpus''could'['For''some''quick''analysis''''creating''a''corpus''could'
    'be', 'overkill', '.', 'If', 'all', 'you', 'need', 'is', 'a', 'word', 'list',
    ',', 'là', 'sont', 'plus simples', 'moyens', 'à', 'atteindre', 'cela', 'objectif', '.']

Vous avez maintenant une liste de mots exploitable! N'oubliez pas que la ponctuation sera comptée comme des mots individuels, alors utilisez str.isalpha () pour les filtrer plus tard.

Création de distributions de fréquences

Vous êtes maintenant prêt pour fréquence des distributions. Une distribution de fréquence est essentiellement un tableau qui vous indique combien de fois chaque mot apparaît dans un texte donné. En NLTK, les distributions de fréquences sont un type d'objet spécifique implémenté en tant que classe distincte appelée FreqDist. Cette classe fournit des opérations utiles pour l'analyse de la fréquence des mots.

Pour créer une distribution de fréquence avec NLTK, construisez le nltk.FreqDist classe avec une liste de mots:

mots: liste[[[[str] = nltk.word_tokenize(texte)
fd = nltk.FreqDist(mots)

Cela créera un objet de distribution de fréquence similaire à un dictionnaire Python mais avec des fonctionnalités supplémentaires.

Après avoir construit l'objet, vous pouvez utiliser des méthodes telles que .Le plus commun() et .tabuler() pour commencer à visualiser les informations:

>>>

>>> fd.Le plus commun(3)
[('must', 1568), ('people', 1291), ('world', 1128)]
>>> fd.tabuler(3)
        doit les gens du monde
        1568 1291 1128

Ces méthodes vous permettent de déterminer rapidement les mots fréquemment utilisés dans un échantillon. Avec .Le plus commun(), vous obtenez une liste de tuples contenant chaque mot et combien de fois il apparaît dans votre texte. Vous pouvez obtenir les mêmes informations dans un format plus lisible avec .tabuler().

En plus de ces deux méthodes, vous pouvez utiliser des distributions de fréquences pour interroger des mots particuliers. Vous pouvez également les utiliser comme itérateurs pour effectuer une analyse personnalisée des propriétés des mots.

Par exemple, pour découvrir les différences de casse, vous pouvez rechercher différentes variantes du même mot:

>>>

>>> fd[[[["Amérique"]
1076
>>> fd[[[["Amérique"]  # Notez que cela n'entraîne pas une KeyError
0
>>> fd[[[["AMÉRIQUE"]
3

Ces valeurs de retour indiquent le nombre de fois où chaque mot se produit exactement comme indiqué.

Étant donné que les objets de distribution de fréquence sont itérables, vous pouvez les utiliser dans les compréhensions de liste pour créer des sous-ensembles de la distribution initiale. Vous pouvez concentrer ces sous-ensembles sur des propriétés utiles pour votre propre analyse.

Essayez de créer une nouvelle distribution de fréquences basée sur la distribution initiale mais qui normalise tous les mots en minuscules:

lower_fd = nltk.FreqDist([[[[w.inférieur() pour w dans fd])

Vous disposez désormais d'une représentation plus précise de l'utilisation des mots, quelle que soit la casse.

Pensez aux possibilités: vous pouvez créer des distributions de fréquences de mots commençant par une lettre particulière, ou d'une longueur particulière, ou contenant certaines lettres. La limite, c'est votre imagination!

Extraction de la concordance et des collocations

Dans le contexte de la PNL, un concordance est une collection d'emplacements de mots avec leur contexte. Vous pouvez utiliser des concordances pour trouver:

  1. Combien de fois un mot apparaît
  2. Où chaque occurrence apparaît
  3. Quels mots entourent chaque occurrence

Dans NLTK, vous pouvez le faire en appelant .concordance(). Pour l'utiliser, vous avez besoin d'une instance du nltk.Text class, qui peut également être construite avec une liste de mots.

Avant d'invoquer .concordance(), construisez une nouvelle liste de mots à partir du texte du corpus original afin que tout le contexte, même les mots vides, y soit:

>>>

>>> texte = nltk.Texte(nltk.corpus.state_union.mots())
>>> texte.concordance("Amérique", lignes=5)
Affichage de 5 sur 1079 résultats:
    voudrait que nous fassions. C'est ce que fera l'Amérique. Tant de sang a déjà
oui, le monde entier se tourne vers l'Amérique pour un leadership éclairé vers la paix
sans l'ombre d'un doute, que l'Amérique continuera le combat pour la liberté
    pour s'assurer de la victoire complète, l'Amérique ne deviendra jamais partie à aucun pl
seulement en droit et en justice. Ici en Amérique, nous avons travaillé longtemps et dur pour

Notez que .concordance() ignore déjà la casse, ce qui vous permet de voir le contexte de toutes les variantes de casse d'un mot par ordre d'apparition. Notez également que cette fonction ne vous montre pas l'emplacement de chaque mot dans le texte.

De plus, depuis .concordance() n'imprime que des informations sur la console, ce n'est pas idéal pour la manipulation de données. Pour obtenir une liste utilisable qui vous donnera également des informations sur l'emplacement de chaque occurrence, utilisez .concordance_list ():

>>>

>>> concordance_list = texte.concordance_list("Amérique", lignes=2)
>>> pour entrée dans concordance_list:
...     impression(entrée.ligne)
...
    voudrait que nous fassions. C'est ce que fera l'Amérique. Tant de sang a déjà
oui, le monde entier se tourne vers l'Amérique pour un leadership éclairé vers la paix

.concordance_list () vous donne une liste de ConcordanceLine objets, qui contiennent des informations sur l'emplacement de chaque mot ainsi que quelques propriétés supplémentaires à explorer. La liste est également triée par ordre d'apparition.

le nltk.Text la classe elle-même a quelques autres fonctionnalités intéressantes. L'un d'eux est .vocab (), ce qui vaut la peine d'être mentionné car il crée une distribution de fréquence pour un texte donné.

Revisiter nltk.word_tokenize (), découvrez à quelle vitesse vous pouvez créer une nltk.Text instance et une distribution de fréquence associée:

>>>

>>> mots: liste[[[[str] = nltk.word_tokenize(
...     "" "Beau est mieux que laid.
...                 L'explicite vaut mieux que l'implicite.
...                 Le simple vaut mieux que le complexe. "" "
... )
>>> texte = nltk.Texte(mots)
>>> fd = texte.vocabulaire()  # Équivalent à fd = nltk.FreqDist (mots)
>>> fd.tabuler(3)
                est mieux que
                    3 3 3

.vocab () est essentiellement un raccourci pour créer une distribution de fréquence à partir d'une instance de nltk.Text. De cette façon, vous n'avez pas besoin de passer un appel séparé pour instancier un nouveau nltk.FreqDist objet.

Une autre caractéristique puissante de NLTK est sa capacité à trouver rapidement collocations avec des appels de fonction simples. Les collocations sont des séries de mots qui apparaissent fréquemment ensemble dans un texte donné. Dans le corpus sur l’état de l’Union, par exemple, vous vous attendez à trouver les mots Uni et États apparaissant très souvent côte à côte. Ces deux mots apparaissant ensemble sont une collocation.

Les collocations peuvent être constituées de deux mots ou plus. NLTK fournit des classes pour gérer plusieurs types de collocations:

  • Bigrammes: Combinaisons fréquentes de deux mots
  • Trigrammes: Combinaisons fréquentes de trois mots
  • Quadgrammes: Combinaisons fréquentes de quatre mots

NLTK fournit des classes spécifiques pour vous permettre de trouver des collocations dans votre texte. Suivant le modèle que vous avez vu jusqu'à présent, ces classes sont également construites à partir de listes de mots:

mots = [[[[w pour w dans nltk.corpus.state_union.mots() si w.isalpha()]
chercheur = nltk.collocations.TrigramCollocationFinder.from_words(mots)

le TrigramCollocationFinder instance recherchera spécifiquement les trigrammes. Comme vous l'avez peut-être deviné, NLTK a également le BigramCollocationFinder et QuadgramCollocationFinder classes pour les bigrammes et les quadgrammes, respectivement. Toutes ces classes ont un certain nombre d'utilitaires pour vous donner des informations sur toutes les colocations identifiées.

L'un de leurs outils les plus utiles est le ngram_fd propriété. Cette propriété contient une distribution de fréquence créée pour chaque collocation plutôt que pour des mots individuels.

En utilisant ngram_fd, vous pouvez trouver les collocations les plus courantes dans le texte fourni:

>>>

>>> chercheur.ngram_fd.Le plus commun(2)
[(('the', 'United', 'States'), 294), (('the', 'American', 'people'), 185)]
>>> chercheur.ngram_fd.tabuler(2)
        ('le', 'United', 'States') ('the', 'American', 'people')
                                                                                                        294 185

Vous n'avez même pas besoin de créer la distribution de fréquences, car il s'agit déjà d'une propriété de l'instance de recherche de collocation.

Maintenant que vous avez découvert certains des outils les plus utiles de NLTK, il est temps de vous lancer dans l'analyse des sentiments!

Utilisation de l’analyseur de sentiments pré-formé de NLTK

NLTK dispose déjà d'un analyseur de sentiments pré-entraîné intégré appelé VADER (Valence UNEarticles ictionary et sEntiment Reasoner).

Étant donné que VADER est pré-entraîné, vous pouvez obtenir des résultats plus rapidement qu'avec de nombreux autres analyseurs. Cependant, VADER est le mieux adapté au langage utilisé dans les médias sociaux, comme les phrases courtes avec un peu d'argot et des abréviations. Il est moins précis de noter des phrases plus longues et structurées, mais c'est souvent un bon point de départ.

Pour utiliser VADER, créez d'abord une instance de nltk.sentiment.SentimentIntensityAnalyzer, puis utilisez .polarity_scores () sur une chaîne brute:

>>>

>>> de nltk.sentiment importer SentimentIntensityAnalyzer
>>> sia = SentimentIntensityAnalyzer()
>>> sia.polarity_scores("Wow, NLTK est vraiment puissant!")
'neg': 0,0, 'neu': 0,295, 'pos': 0,705, 'composé': 0.8012

Vous obtiendrez un dictionnaire des différentes partitions. Les scores négatifs, neutres et positifs sont liés: ils totalisent tous 1 et ne peuvent pas être négatifs. Le score composé est calculé différemment. Il ne s’agit pas seulement d’une moyenne et elle peut aller de -1 à 1.

Vous allez maintenant le tester par rapport à des données réelles en utilisant deux corpus différents. Commencez par charger le twitter_samples corpus dans une liste de chaînes, ce qui en fait un remplacement pour rendre les URL inactives pour éviter les clics accidentels:

tweets = [[[[t.remplacer(": //", "//") pour t dans nltk.corpus.twitter_samples.cordes()]

Notez que vous utilisez une méthode de corpus différente, .strings (), au lieu de .mots(). Cela vous donne une liste de tweets bruts sous forme de chaînes.

Différents corpus ont des fonctionnalités différentes, vous devrez donc peut-être utiliser Python Aidez-moi(), un péché aide (nltk.corpus.tweet_samples), ou consultez la documentation de NLTK pour savoir comment utiliser un corpus donné.

Maintenant, utilisez le .polarity_scores () fonction de votre SentimentIntensityAnalyzer instance pour classer les tweets:

de Aléatoire importer mélanger

def est_positif(tweeter: str) -> booléen:
    "" "Vrai si le tweet a un sentiment composé positif, Faux dans le cas contraire." ""
    revenir sia.polarity_scores(tweeter)[[[["composé"] > 0

mélanger(tweets)
pour tweeter dans tweets[:[:[:[:dix]:
    impression(">", est_positif(tweeter), tweeter)

Dans ce cas, is_positive () utilise uniquement la positivité du score composé pour effectuer l'appel. Vous pouvez choisir n'importe quelle combinaison de scores VADER pour adapter la classification à vos besoins.

Jetez maintenant un œil au deuxième corpus, critiques de films. Comme son nom l'indique, il s'agit d'une collection de critiques de films. La particularité de ce corpus est qu’il a déjà été classé. Par conséquent, vous pouvez l'utiliser pour juger de la précision des algorithmes que vous choisissez lors de l'évaluation de textes similaires.

Gardez à l'esprit que VADER est probablement meilleur pour évaluer les tweets que pour évaluer les critiques de longs films. Pour obtenir de meilleurs résultats, vous allez configurer VADER pour qu'il évalue des phrases individuelles dans la révision plutôt que le texte entier.

Étant donné que VADER a besoin de chaînes brutes pour sa notation, vous ne pouvez pas utiliser .mots() comme vous l'avez fait plus tôt. À la place, faites une liste des ID de fichier utilisés par le corpus, que vous pourrez utiliser plus tard pour référencer des avis individuels:

positive_review_ids = nltk.corpus.critiques de films.fileids(catégories=[[[["pos"])
negatif_review_ids = nltk.corpus.critiques de films.fileids(catégories=[[[["nég"])
all_review_ids = positive_review_ids + negatif_review_ids

.fileids () existe dans la plupart des corpus, sinon dans tous. Dans le cas de critiques de films, chaque dossier correspond à une seule revue. Notez également que vous pouvez filtrer la liste des ID de fichier en spécifiant des catégories. Cette catégorisation est une fonctionnalité propre à ce corpus et à d'autres du même type.

Ensuite, redéfinissez is_positive () pour travailler sur une revue entière. Vous devrez obtenir cet avis spécifique à l'aide de son ID de fichier, puis le diviser en phrases avant de procéder à la notation:

de statistiques importer signifier

def est_positif(review_id: str) -> booléen:
    "" "Vrai si la moyenne de tous les scores composés de phrases est positive." ""
    texte = nltk.corpus.critiques de films.brut(review_id)
    scores = [[[[
        sia.polarity_scores(phrase)[[[["composé"]
        pour phrase dans nltk.sent_tokenize(texte)
    ]
    revenir signifier(scores) > 0

.brut() est une autre méthode qui existe dans la plupart des corpus. En spécifiant un ID de fichier ou une liste d'ID de fichier, vous pouvez obtenir des données spécifiques du corpus. Ici, vous obtenez un seul avis, puis utilisez nltk.sent_tokenize () pour obtenir une liste de phrases de la revue. Finalement, is_positive () calcule le score composé moyen pour toutes les phrases et associe un résultat positif à une critique positive.

Vous pouvez profiter de l'occasion pour évaluer tous les avis et voir à quel point VADER est précis avec cette configuration:

>>>

>>> mélanger(all_review_ids)
>>> correct = 0
>>> pour review_id dans all_review_ids:
...     si est_positif(review_id):
...         si la revue dans positive_review_ids:
...             correct + = 1
...     autre:
...         si la revue dans negatif_review_ids:
...             correct + = 1
...
>>> impression(F"correct / len(all_review_ids):0,2%    correct")
64,00% correct

Après avoir noté tous les avis, vous pouvez voir que seuls 64% ont été correctement classés par VADER en utilisant la logique définie dans is_positive ().

Un taux de précision de 64% n'est pas génial, mais c'est un début. Amusez-vous un peu à peaufiner is_positive () pour voir si vous pouvez augmenter la précision.

Dans la section suivante, vous allez créer un classificateur personnalisé qui vous permet d'utiliser des fonctionnalités supplémentaires pour la classification et éventuellement d'augmenter sa précision à un niveau acceptable.

Personnalisation de l'analyse des sentiments de NLTK

NLTK propose quelques classificateurs intégrés qui conviennent à divers types d'analyses, y compris l'analyse des sentiments. L'astuce consiste à déterminer quelles propriétés de votre ensemble de données sont utiles pour classer chaque élément de données dans les catégories souhaitées.

Dans le monde de l'apprentissage automatique, ces propriétés de données sont appelées fonctionnalités, que vous devez révéler et sélectionner lorsque vous travaillez avec vos données. Bien que ce didacticiel ne vous plongera pas trop dans la sélection des fonctionnalités et l'ingénierie des fonctionnalités, vous serez en mesure de voir leurs effets sur la précision des classificateurs.

Sélection de fonctionnalités utiles

Puisque vous avez appris à utiliser les distributions de fréquences, pourquoi ne pas les utiliser comme point de départ pour une fonctionnalité supplémentaire?

En utilisant les catégories prédéfinies dans le critiques de films corpus, vous pouvez créer des ensembles de mots positifs et négatifs, puis déterminer ceux qui apparaissent le plus fréquemment dans chaque ensemble. Commencez par exclure les mots indésirables et construisez les groupes de catégories initiaux:

    1indésirable = nltk.corpus.mots vides.mots("Anglais")
    2indésirable.étendre([[[[w.inférieur() pour w dans nltk.corpus.noms.mots()])
    3
    4def skip_unwanted(pos_tuple):
    5    mot, marque = pos_tuple
    6    si ne pas mot.isalpha() ou mot dans indésirable:
    sept        revenir Faux
    8    si marque.commence avec("NN"):
    9        revenir Faux
dix    revenir Vrai
11
12mots_ positifs = [[[[mot pour mot, marque dans filtre(
13    skip_unwanted,
14    nltk.pos_tag(nltk.corpus.critiques de films.mots(catégories=[[[["pos"]))
15)]
16mots_ négatifs = [[[[mot pour mot, marque dans filtre(
17    skip_unwanted,
18    nltk.pos_tag(nltk.corpus.critiques de films.mots(catégories=[[[["nég"]))
19)]

Cette fois, vous ajoutez également des mots du noms corpus au indésirable liste à la ligne 2, car les critiques de films sont susceptibles de comporter de nombreux noms d'acteurs, qui ne devraient pas faire partie de vos ensembles de fonctionnalités. Remarquer pos_tag () aux lignes 14 et 18, qui identifie les mots par leur partie du discours.

Il est important d'appeler pos_tag () avant filtrer vos listes de mots afin que NLTK puisse baliser plus précisément tous les mots. skip_unwanted (), défini à la ligne 4, utilise ensuite ces balises pour exclure les noms, conformément au jeu de balises par défaut de NLTK.

Vous êtes maintenant prêt à créer les distributions de fréquences pour votre fonctionnalité personnalisée. Étant donné que de nombreux mots sont présents dans les ensembles positifs et négatifs, commencez par trouver l'ensemble commun afin de pouvoir le supprimer des objets de distribution:

positive_fd = nltk.FreqDist(mots_ positifs)
negatif_fd = nltk.FreqDist(mots_ négatifs)

common_set = ensemble(positive_fd).intersection(negatif_fd)

pour mot dans common_set:
    del positive_fd[[[[mot]
    del negatif_fd[[[[mot]

top_100_positive = mot pour mot, compter dans positive_fd.Le plus commun(100)
top_100_negative = mot pour mot, compter dans negatif_fd.Le plus commun(100)

Une fois qu'il vous reste des mots positifs et négatifs uniques dans chaque objet de distribution de fréquence, vous pouvez enfin créer des ensembles à partir des mots les plus courants dans chaque distribution. La quantité de mots dans chaque ensemble est quelque chose que vous pouvez modifier afin de déterminer son effet sur l'analyse des sentiments.

Voici un exemple de fonctionnalité que vous pouvez extraire de vos données, et il est loin d’être parfait. En regardant de près ces ensembles, vous remarquerez des noms et des mots inhabituels qui ne sont pas nécessairement positifs ou négatifs. En outre, les autres outils NLTK que vous avez appris jusqu'à présent peuvent être utiles pour créer davantage de fonctionnalités. Une possibilité est de tirer parti des collocations qui ont une signification positive, comme le bigramme «thumbs up!»

Voici comment configurer les moteurs de recherche de bigrammes positifs et négatifs:

indésirable = nltk.corpus.mots vides.mots("Anglais")
indésirable.étendre([[[[w.inférieur() pour w dans nltk.corpus.noms.mots()])

positive_bigram_finder = nltk.collocations.BigramCollocationFinder.from_words([[[[
    w pour w dans nltk.corpus.critiques de films.mots(catégories=[[[["pos"])
    si w.isalpha() et w ne pas dans indésirable
])
negatif_bigram_finder = nltk.collocations.BigramCollocationFinder.from_words([[[[
    w pour w dans nltk.corpus.critiques de films.mots(catégories=[[[["nég"])
    si w.isalpha() et w ne pas dans indésirable
])

Le reste dépend de toi! Essayez différentes combinaisons de fonctionnalités, réfléchissez à des moyens d'utiliser les scores VADER négatifs, créez des ratios, polissez les distributions de fréquences. Les possibilités sont infinies!

Formation et utilisation d'un classificateur

Avec votre nouvel ensemble de fonctionnalités prêt à être utilisé, la première condition préalable à la formation d'un classificateur est de définir une fonction qui extraira les fonctionnalités d'une donnée donnée.

Puisque vous recherchez des critiques de films positives, concentrez-vous sur les fonctionnalités qui indiquent la positivité, y compris les scores VADER:

def extract_features(texte):
    fonctionnalités = dict()
    nombre de mots = 0
    scores_composés = liste()
    scores_ positifs = liste()

    pour phrase dans nltk.sent_tokenize(texte):
        pour mot dans nltk.word_tokenize(phrase):
            si mot.inférieur() dans top_100_positive:
                nombre de mots + = 1
        scores_composés.ajouter(sia.polarity_scores(phrase)[[[["composé"])
        scores_ positifs.ajouter(sia.polarity_scores(phrase)[[[["pos"])

    # Ajout de 1 au score composé final pour toujours avoir des nombres positifs
    # puisque certains classificateurs que vous utiliserez plus tard ne fonctionnent pas avec des nombres négatifs.
    fonctionnalités[[[["mean_compound"] = signifier(scores_composés) + 1
    fonctionnalités[[[["mean_positive"] = signifier(scores_ positifs)
    fonctionnalités[[[["wordcount"] = nombre de mots

    revenir fonctionnalités

extract_features () devrait renvoyer un dictionnaire, et il créera trois fonctionnalités pour chaque morceau de texte:

  1. Le score moyen composé
  2. Le score positif moyen
  3. Le nombre de mots dans le texte qui font également partie des 100 premiers mots de toutes les critiques positives

Pour former et évaluer un classificateur, vous devez créer une liste de fonctionnalités pour chaque texte que vous analysez:

fonctionnalités = [[[[
    (extract_features(nltk.corpus.critiques de films.brut(la revue)), "pos")
    pour la revue dans nltk.corpus.critiques de films.fileids(catégories=[[[["pos"])
]
fonctionnalités.étendre([[[[
    (extract_features(nltk.corpus.critiques de films.brut(la revue)), "nég")
    pour la revue dans nltk.corpus.critiques de films.fileids(catégories=[[[["nég"])
])

Chaque élément de cette liste de fonctionnalités doit être un tuple dont le premier élément est le dictionnaire renvoyé par extract_features et dont le deuxième élément est la catégorie prédéfinie pour le texte. Après avoir initialement formé le classificateur avec certaines données qui ont déjà été catégorisées (telles que critiques de films corpus), vous pourrez classer les nouvelles données.

L'entraînement du classificateur consiste à diviser l'ensemble de fonctionnalités afin qu'une partie puisse être utilisée pour l'apprentissage et l'autre pour l'évaluation, puis appeler .train():

>>>

>>> # Utilisez 1/4 de l'ensemble pour l'entraînement
>>> train_count = len(fonctionnalités) // 4
>>> mélanger(fonctionnalités)
>>> classificateur = nltk.NaiveBayesClassifier.train(fonctionnalités[:[:[:[:train_count])
>>> classificateur.show_most_informative_features(dix)
Caractéristiques les plus informatives
                                                            wordcount = 2 pos: neg = 4.1: 1.0
                                                            wordcount = 3 pos: neg = 3,8: 1,0
                                                            wordcount = 0 nég: pos = 1,6: 1,0
                                                            wordcount = 1 pos: neg = 1,5: 1,0
>>> nltk.classer.précision(classificateur, fonctionnalités[[[[train_count:])
0,668

Puisque vous mélangez la liste des fonctionnalités, chaque exécution vous donnera des résultats différents. En fait, il est important de mélanger la liste pour éviter de regrouper accidentellement des avis classés de la même manière dans le premier quart de la liste.

L'ajout d'une seule fonctionnalité a légèrement amélioré la précision initiale de VADER, de 64% à 67%. Plus de fonctionnalités pourraient aider, à condition qu'elles indiquent vraiment à quel point un avis est positif. Vous pouvez utiliser classifier.show_most_informative_features () pour déterminer quelles caractéristiques sont les plus représentatives d'une propriété spécifique.

Pour classer de nouvelles données, recherchez une critique de film quelque part et transmettez-la à classifier.classify (). Vous pouvez aussi utiliser extract_features () pour vous dire exactement comment il a été noté:

>>>

>>> new_review = ...
>>> classificateur.classer(new_review)
>>> extract_features(new_review)

Était-ce correct? Sur la base de la sortie de score de extract_features (), que pouvez-vous améliorer?

L'ingénierie des fonctionnalités est un élément important de l'amélioration de la précision d'un algorithme donné, mais ce n'est pas toute l'histoire. Une autre stratégie consiste à utiliser et à comparer différents classificateurs.

Comparaison de classificateurs supplémentaires

NLTK fournit une classe qui peut utiliser la plupart des classificateurs du populaire framework d'apprentissage automatique scikit-learn.

Beaucoup des classificateurs fournis par scikit-learn peuvent être instanciés rapidement car ils ont des valeurs par défaut qui fonctionnent souvent bien. Dans cette section, vous apprendrez à les intégrer dans NLTK pour classer les données linguistiques.

Installation et importation de scikit-learn

Comme NLTK, scikit-learn est une bibliothèque Python tierce, vous devrez donc l'installer avec pépin:

$ python3 -m pip installer scikit-learn

Après avoir installé scikit-learn, vous pourrez utiliser ses classificateurs directement dans NLTK.

Les classificateurs suivants sont un sous-ensemble de tous les classificateurs disponibles. Ceux-ci fonctionneront dans NLTK pour l'analyse des sentiments:

de sklearn.naive_bayes importer (
    BernoulliNB,
    ComplémentNB,
    MultinomialNB,
)
de sklearn.neighbors importer KNeighborsClassifier
de sklearn.tree importer DecisionTreeClassifier
de sklearn.ensemble importer RandomForestClassifier, AdaBoostClassifier
de sklearn.linear_model importer Régression logistique
de sklearn.neural_network importer MLPClassifier
de sklearn.discriminant_analysis importer Analyse QuadratiqueDiscriminante

Une fois ces classificateurs importés, vous devrez d'abord instancier chacun d'eux. Heureusement, tous ces éléments ont de très bons paramètres par défaut et ne nécessitent pas beaucoup de réglages.

Pour faciliter l'évaluation de la précision, il est utile de disposer d'un mappage des noms de classificateurs et de leurs instances:

classificateurs = 
    «BernoulliNB»: BernoulliNB(),
    "ComplémentNB": ComplémentNB(),
    "MultinomialNB": MultinomialNB(),
    "KNeighborsClassifier": KNeighborsClassifier(),
    "DecisionTreeClassifier": DecisionTreeClassifier(),
    "RandomForestClassifier": RandomForestClassifier(),
    "Régression logistique": Régression logistique(),
    "MLPClassifier": MLPClassifier(max_iter=1000),
    "AdaBoostClassifier": AdaBoostClassifier(),

Vous pouvez désormais utiliser ces instances pour la formation et l'évaluation de la précision.

Utilisation des classificateurs scikit-learn avec NLTK

Puisque NLTK vous permet d'intégrer des classificateurs scikit-learn directement dans sa propre classe de classificateurs, les processus de formation et de classification utiliseront les mêmes méthodes que vous avez déjà vues, .train() et .classer().

Vous pourrez également en tirer parti fonctionnalités liste que vous avez créée précédemment au moyen de extract_features (). Pour vous rafraîchir la mémoire, voici comment vous avez construit le fonctionnalités liste:

fonctionnalités = [[[[
    (extract_features(nltk.corpus.critiques de films.brut(la revue)), "pos")
    pour la revue dans nltk.corpus.critiques de films.fileids(catégories=[[[["pos"])
]
fonctionnalités.étendre([[[[
    (extract_features(nltk.corpus.critiques de films.brut(la revue)), "nég")
    pour la revue dans nltk.corpus.critiques de films.fileids(catégories=[[[["nég"])
])

le fonctionnalités liste contient des tuples dont le premier élément est un ensemble de fonctionnalités données par extract_features (), et dont le deuxième élément est l'étiquette de classification des données préclassifiées dans le critiques de films corpus.

Étant donné que la première moitié de la liste ne contient que des critiques positives, commencez par la mélanger, puis parcourez tous les classificateurs pour former et évaluer chacun d'eux:

>>>

>>> # Utilisez 1/4 de l'ensemble pour l'entraînement
>>> train_count = len(fonctionnalités) // 4
>>> mélanger(fonctionnalités)
>>> pour Nom, sklearn_classifier dans classificateurs.articles():
...     classificateur = nltk.classer.SklearnClassifier(sklearn_classifier)
...     classificateur.train(fonctionnalités[:[:[:[:train_count])
...     précision = nltk.classer.précision(classificateur, fonctionnalités[[[[train_count:])
...     impression(F"précision:0,2%    - Nom")
...
67,00% - BernoulliNB
66,80% - Complément NB
66,33% - Multinomial NB
69,07% - KNeighborsClassifier
62,73% - DecisionTreeClassifier
66,60% - RandomForestClassifier
72,20% - Régression logistique
73,13% - MLPClassifier
69,40% - AdaBoostClassifier

Pour chaque classificateur scikit-learn, appelez nltk.classify.SklearnClassifier pour créer un classificateur NLTK utilisable qui peut être entraîné et évalué exactement comme vous l'avez vu auparavant avec nltk.NaiveBayesClassifier et ses autres classificateurs intégrés. le .train() et .précision() les méthodes doivent recevoir différentes parties de la même liste de fonctionnalités.

Vous avez maintenant atteint une précision de plus de 73% avant même d'ajouter une deuxième fonctionnalité! Bien que cela ne signifie pas que le MLPClassifier continuera à être le meilleur à mesure que vous concevrez de nouvelles fonctionnalités, il est clairement avantageux de disposer d'algorithmes de classification supplémentaires.

Conclusion

Vous connaissez désormais les fonctionnalités de NTLK qui vous permettent de transformer du texte en objets que vous pouvez filtrer et manipuler, ce qui vous permet d’analyser des données de texte pour obtenir des informations sur ses propriétés. Vous pouvez également utiliser différents classificateurs pour effectuer une analyse des sentiments sur vos données et obtenir des informations sur la façon dont votre public réagit au contenu.

Dans ce didacticiel, vous avez appris à:

  • Divisé et filtre données textuelles en préparation pour l'analyse
  • Analyser fréquence des mots
  • Trouver concordance et collocations en utilisant différentes méthodes
  • Effectuer analyse rapide des sentiments avec le VADER intégré de NLTK
  • Définir les fonctionnalités pour classification personnalisée
  • Utiliser et comparer classificateurs de scikit-learn pour l'analyse des sentiments dans NLTK

Avec ces outils, vous pouvez commencer à utiliser NLTK dans vos propres projets. Pour vous inspirer, jetez un œil à un visualiseur d'analyse des sentiments ou essayez d'augmenter le traitement de texte dans une application Web Python tout en découvrant d'autres packages populaires!