Boîte à outils en langage naturel - Classification de texte

Qu'est-ce que la classification de texte?

La classification de texte, comme son nom l'indique, est le moyen de catégoriser des morceaux de texte ou des documents. Mais ici se pose la question de savoir pourquoi nous devons utiliser des classificateurs de texte? Après avoir examiné l'utilisation des mots dans un document ou un morceau de texte, les classificateurs seront en mesure de décider quelle étiquette de classe devrait lui être attribuée.

Classificateur binaire

Comme son nom l'indique, le classificateur binaire décidera entre deux étiquettes. Par exemple, positif ou négatif. Dans ce cas, le texte ou le document peut être une étiquette ou une autre, mais pas les deux.

Classificateur multi-étiquettes

Contrairement au classificateur binaire, le classificateur multi-étiquettes peut attribuer une ou plusieurs étiquettes à un morceau de texte ou de document.

Ensemble de fonctionnalités étiquetées vs non étiquetées

Un mappage clé-valeur des noms d'entités aux valeurs d'entités est appelé un ensemble d'entités. Les ensembles de fonctionnalités étiquetés ou les données d'entraînement sont très importants pour l'apprentissage de la classification afin de pouvoir classer ultérieurement les ensembles de fonctionnalités non étiquetés.

Ensemble de fonctionnalités étiqueté Ensemble de fonctionnalités sans étiquette
C'est un tuple qui ressemble à (feat, label). C'est un exploit en soi.
C'est une instance avec une étiquette de classe connue. Sans étiquette associée, nous pouvons l'appeler une instance.
Utilisé pour entraîner un algorithme de classification. Une fois entraîné, l'algorithme de classification peut classer un ensemble de fonctionnalités sans étiquette.

Extraction d'entités de texte

L'extraction d'entités textuelles, comme son nom l'indique, est le processus de transformation d'une liste de mots en un ensemble d'entités utilisables par un classificateur. Nous devons transformer notre texte en‘dict’ ensembles de fonctionnalités de style, car Natural Language Tool Kit (NLTK) attend ‘dict’ ensembles de fonctionnalités de style.

Modèle Bag of Words (BoW)

BoW, l'un des modèles les plus simples de la PNL, est utilisé pour extraire les caractéristiques d'un morceau de texte ou d'un document afin qu'il puisse être utilisé dans la modélisation comme dans les algorithmes de ML. Il construit essentiellement un ensemble de fonctionnalités de présence de mots à partir de tous les mots d'une instance. Le concept derrière cette méthode est qu'elle ne se soucie pas du nombre de fois où un mot apparaît ou de l'ordre des mots, elle ne se soucie que de la présence ou non du mot dans une liste de mots.

Exemple

Pour cet exemple, nous allons définir une fonction nommée bow () -

def bow(words):
   return dict([(word, True) for word in words])

Maintenant, appelons bow()fonction sur les mots. Nous avons enregistré ces fonctions dans un fichier nommé bagwords.py.

from bagwords import bow
bow(['we', 'are', 'using', 'tutorialspoint'])

Production

{'we': True, 'are': True, 'using': True, 'tutorialspoint': True}

Classificateurs de formation

Dans les sections précédentes, nous avons appris à extraire des fonctionnalités du texte. Alors maintenant, nous pouvons former un classificateur. Le premier et le plus simple classificateur estNaiveBayesClassifier classe.

Classificateur Naïve Bayes

Pour prédire la probabilité qu'un ensemble d'entités donné appartienne à une étiquette particulière, il utilise le théorème de Bayes. La formule du théorème de Bayes est la suivante.

$$ P (A | B) = \ frac {P (B | A) P (A)} {P (B)} $$

Ici,

P(A|B) - On l'appelle aussi la probabilité postérieure, c'est-à-dire la probabilité que le premier événement, c'est-à-dire A, se produise étant donné que le deuxième événement, c'est-à-dire B, s'est produit.

P(B|A) - C'est la probabilité que le deuxième événement, c'est-à-dire B, se produise après le premier événement, c'est-à-dire que A s'est produit.

P(A), P(B) - On l'appelle aussi probabilité a priori, c'est-à-dire la probabilité qu'un premier événement, c'est-à-dire A ou un deuxième événement, c'est-à-dire B, se produise.

Pour former le classificateur Naïve Bayes, nous utiliserons le movie_reviewscorpus de NLTK. Ce corpus comprend deux catégories de texte, à savoir:pos et neg. Ces catégories font d'un classificateur formé sur elles un classificateur binaire. Chaque fichier du corpus est composé de deux fichiers, l'un est une critique de film positive et l'autre une critique de film négative. Dans notre exemple, nous allons utiliser chaque fichier comme une seule instance à la fois pour l'entraînement et le test du classificateur.

Exemple

Pour le classificateur de formation, nous avons besoin d'une liste d'ensembles de fonctionnalités étiquetés, qui seront sous la forme [(featureset, label)]. Ici lefeatureset variable est une dict et label est le label de classe connu pour le featureset. Nous allons créer une fonction nomméelabel_corpus() qui prendra un corpus nommé movie_reviewset aussi une fonction nommée feature_detector, qui est par défaut bag of words. Il construira et retournera un mappage de la forme, {label: [featureset]}. Ensuite, nous utiliserons ce mappage pour créer une liste d'instances d'entraînement et d'instances de test étiquetées.

import collections

def label_corpus(corp, feature_detector=bow):
   label_feats = collections.defaultdict(list)
   for label in corp.categories():
      for fileid in corp.fileids(categories=[label]):
         feats = feature_detector(corp.words(fileids=[fileid]))
         label_feats[label].append(feats)
   return label_feats

Avec l'aide de la fonction ci-dessus, nous obtiendrons un mappage {label:fetaureset}. Nous allons maintenant définir une autre fonction nomméesplit qui prendra un mappage retourné de label_corpus() et divise chaque liste d'ensembles de fonctionnalités en formations étiquetées ainsi qu'en instances de test.

def split(lfeats, split=0.75):
   train_feats = []
   test_feats = []
   for label, feats in lfeats.items():
      cutoff = int(len(feats) * split)
      train_feats.extend([(feat, label) for feat in feats[:cutoff]])
      test_feats.extend([(feat, label) for feat in feats[cutoff:]])
   return train_feats, test_feats

Maintenant, utilisons ces fonctions sur notre corpus, ie movie_reviews -

from nltk.corpus import movie_reviews
from featx import label_feats_from_corpus, split_label_feats
movie_reviews.categories()

Production

['neg', 'pos']

Exemple

lfeats = label_feats_from_corpus(movie_reviews)
lfeats.keys()

Production

dict_keys(['neg', 'pos'])

Exemple

train_feats, test_feats = split_label_feats(lfeats, split = 0.75)
len(train_feats)

Production

1500

Exemple

len(test_feats)

Production

500

Nous avons vu cela dans movie_reviewscorpus, il y a 1000 fichiers pos et 1000 fichiers neg. Nous nous retrouvons également avec 1500 instances de formation étiquetées et 500 instances de test étiquetées.

Maintenant, entraînons-nous NaïveBayesClassifier en utilisant son train() méthode de classe -

from nltk.classify import NaiveBayesClassifier
NBC = NaiveBayesClassifier.train(train_feats)
NBC.labels()

Production

['neg', 'pos']

Classificateur d'arbre de décision

Un autre classificateur important est le classificateur d'arbre de décision. Ici pour l'entraîner leDecisionTreeClassifierclass créera une structure arborescente. Dans cette arborescence, chaque nœud correspond à un nom d'entité et les branches correspondent aux valeurs d'entités. Et en bas des branches, nous arriverons aux feuilles de l'arbre, c'est-à-dire aux étiquettes de classification.

Pour former le classificateur d'arbre de décision, nous utiliserons les mêmes fonctionnalités de formation et de test, c'est-à-dire train_feats et test_feats, variables que nous avons créées à partir de movie_reviews corpus.

Exemple

Pour former ce classificateur, nous appellerons DecisionTreeClassifier.train() méthode de classe comme suit -

from nltk.classify import DecisionTreeClassifier
decisiont_classifier = DecisionTreeClassifier.train(
   train_feats, binary = True, entropy_cutoff = 0.8, 
   depth_cutoff = 5, support_cutoff = 30
)
accuracy(decisiont_classifier, test_feats)

Production

0.725

Classificateur d'entropie maximum

Un autre classificateur important est MaxentClassifier qui est également connu comme un conditional exponential classifier ou logistic regression classifier. Ici pour l'entraîner, leMaxentClassifier class convertira les ensembles d'entités étiquetés en vecteurs à l'aide du codage.

Pour former le classificateur d'arbre de décision, nous utiliserons les mêmes fonctionnalités de formation et de test, c'est-à-dire train_featset test_feats, variables que nous avons créées à partir de movie_reviews corpus.

Exemple

Pour former ce classificateur, nous appellerons MaxentClassifier.train() méthode de classe comme suit -

from nltk.classify import MaxentClassifier
maxent_classifier = MaxentClassifier
.train(train_feats,algorithm = 'gis', trace = 0, max_iter = 10, min_lldelta = 0.5)
accuracy(maxent_classifier, test_feats)

Production

0.786

Classificateur Scikit-learn

L'une des meilleures bibliothèques d'apprentissage automatique (ML) est Scikit-learn. Il contient en fait toutes sortes d'algorithmes de ML à des fins diverses, mais ils ont tous le même modèle de conception d'ajustement comme suit -

  • Adapter le modèle aux données
  • Et utilisez ce modèle pour faire des prédictions

Plutôt que d'accéder directement aux modèles scikit-learn, nous allons ici utiliser les NLTK SklearnClassifierclasse. Cette classe est une classe wrapper autour d'un modèle scikit-learn pour le rendre conforme à l'interface Classifier de NLTK.

Nous suivrons les étapes suivantes pour former un SklearnClassifier classe -

Step 1 - Nous allons d'abord créer des fonctionnalités d'entraînement comme nous l'avons fait dans les recettes précédentes.

Step 2 - Maintenant, choisissez et importez un algorithme Scikit-learn.

Step 3 - Ensuite, nous devons construire un SklearnClassifier classe avec l'algorithme choisi.

Step 4 - Enfin, nous nous formerons SklearnClassifier cours avec nos fonctionnalités de formation.

Implémentons ces étapes dans la recette Python ci-dessous -

from nltk.classify.scikitlearn import SklearnClassifier
from sklearn.naive_bayes import MultinomialNB
sklearn_classifier = SklearnClassifier(MultinomialNB())
sklearn_classifier.train(train_feats)
<SklearnClassifier(MultinomialNB(alpha = 1.0,class_prior = None,fit_prior = True))>
accuracy(sk_classifier, test_feats)

Production

0.885

Mesure de la précision et du rappel

Lors de la formation de divers classificateurs, nous avons également mesuré leur précision. Mais en dehors de la précision, il existe un certain nombre d'autres métriques qui sont utilisées pour évaluer les classificateurs. Deux de ces mesures sontprecision et recall.

Exemple

Dans cet exemple, nous allons calculer la précision et le rappel de la classe NaiveBayesClassifier que nous avons formée précédemment. Pour y parvenir, nous allons créer une fonction nommée metrics_PR () qui prendra deux arguments, l'un est le classificateur entraîné et l'autre les fonctionnalités de test étiquetées. Les deux arguments sont les mêmes que ceux que nous avons passés lors du calcul de la précision des classificateurs -

import collections
from nltk import metrics
def metrics_PR(classifier, testfeats):
   refsets = collections.defaultdict(set)
   testsets = collections.defaultdict(set)
   for i, (feats, label) in enumerate(testfeats):
      refsets[label].add(i)
      observed = classifier.classify(feats)
         testsets[observed].add(i)
   precisions = {}
   recalls = {}
   for label in classifier.labels():
   precisions[label] = metrics.precision(refsets[label],testsets[label])
   recalls[label] = metrics.recall(refsets[label], testsets[label])
   return precisions, recalls

Appelons cette fonction pour trouver la précision et rappeler -

from metrics_classification import metrics_PR
nb_precisions, nb_recalls = metrics_PR(nb_classifier,test_feats)
nb_precisions['pos']

Production

0.6713532466435213

Exemple

nb_precisions['neg']

Production

0.9676271186440678

Exemple

nb_recalls['pos']

Production

0.96

Exemple

nb_recalls['neg']

Production

0.478

Combinaison de classificateur et de vote

La combinaison des classificateurs est l'un des meilleurs moyens d'améliorer les performances de classification. Et le vote est l'un des meilleurs moyens de combiner plusieurs classificateurs. Pour voter, nous devons avoir un nombre impair de classificateurs. Dans la recette Python suivante, nous allons combiner trois classificateurs, à savoir la classe NaiveBayesClassifier, la classe DecisionTreeClassifier et la classe MaxentClassifier.

Pour ce faire, nous allons définir une fonction nommée vote_classifiers () comme suit.

import itertools
from nltk.classify import ClassifierI
from nltk.probability import FreqDist
class Voting_classifiers(ClassifierI):
   def __init__(self, *classifiers):
      self._classifiers = classifiers
      self._labels = sorted(set(itertools.chain(*[c.labels() for c in classifiers])))
   def labels(self):
      return self._labels
   def classify(self, feats):
      counts = FreqDist()
      for classifier in self._classifiers:
         counts[classifier.classify(feats)] += 1
      return counts.max()

Appelons cette fonction pour combiner trois classificateurs et trouver la précision -

from vote_classification import Voting_classifiers
combined_classifier = Voting_classifiers(NBC, decisiont_classifier, maxent_classifier)
combined_classifier.labels()

Production

['neg', 'pos']

Exemple

accuracy(combined_classifier, test_feats)

Production

0.948

À partir de la sortie ci-dessus, nous pouvons voir que les classificateurs combinés ont la plus haute précision que les classificateurs individuels.