Accéder au contenu principal

Modèle de sac de mots Python : Un guide complet

Explorez tout ce que vous devez savoir sur la mise en œuvre du modèle de sac de mots en Python.
Actualisé 14 févr. 2025  · 12 min de lecture

Le sac de mots (BoW) est une technique de traitement du langage naturel (NLP). Il est largement utilisé pour transformer des données textuelles en format lisible par une machine, en particulier des valeurs numériques, sans tenir compte de la grammaire et de l'ordre des mots. Il est important pour toute personne travaillant avec des données textuelles de comprendre le BoW. Python fournit de multiples outils et bibliothèques pour mettre en œuvre efficacement le sac de mots.

Dans ce tutoriel, nous allons nous plonger dans BoW, présenter ses concepts, couvrir ses utilisations et nous pencher sur une implémentation détaillée en Python. À la fin de ce didacticiel, vous serez en mesure d'appliquer le modèle du sac de mots à des problèmes concrets. Si vous débutez dans le domaine du traitement du langage naturel, consultez notre parcours de compétences Traitement du langage naturel en cursus Python pour en savoir plus.

Qu'est-ce que le sac de mots ?

Le sac de mots est une technique permettant d'extraire des caractéristiques de données textuelles pour des tâches d'apprentissage automatique, telles que la classification de textes et l'analyse de sentiments. Ceci est important car les algorithmes d'apprentissage automatique ne peuvent pas traiter les données textuelles. Le processus de conversion du texte en nombres est connu sous le nom d'extraction ou d'encodage des caractéristiques.

Un sac de mots est basé sur l'occurrence des mots dans un document. Le processus commence par l'identification du vocabulaire dans le texte et la mesure de son occurrence. On parle de sac parce que l'ordre et la structure des mots ne sont pas pris en compte, mais seulement leur occurrence. 

Le modèle de sac de mots est différent du modèle de sac de mots continu (CBOW) qui apprend à intégrer des mots denses en utilisant les mots environnants pour prédire un mot cible, capturant ainsi les relations sémantiques entre les mots. CBOW nécessite une formation sur un grand corpus et produit des vecteurs à faible dimension qui sont utiles pour les applications NLP complexes où le contexte des mots est important.

Aspect

BOW

CBOW

Objectif

Compte les occurrences de chaque mot

Prédire le mot cible en fonction du contexte

Type de sortie

Vecteur clairsemé à haute dimension

Enchâssement dense et de faible dimension

Prise en compte du contexte

Non (ignore l'ordre des mots)

Oui (utilise les mots environnants)

Représentation

Vecteur de fréquence clairsemé

Sémantique de la capture de vecteurs denses

Complexité

Faible (pas de formation requise)

Élevé (nécessite une formation sur un large corpus)

Applications typiques

Classification des textes, analyse des sentiments

Intégration de mots, tâches NLP nécessitant un contexte

Pourquoi utiliser le sac de mots ?

Le sac de mots est utile dans de nombreuses NLPParmi les raisons de son utilisation, on peut citer

  • Extraction des caractéristiques: Il convertit les données textuelles non structurées en données structurées, qui peuvent être utilisées comme données d'entrée pour divers algorithmes d'apprentissage automatique.
  • Simplicité et efficacité: BoW est simple à mettre en œuvre sur le plan informatique et fonctionne bien pour les corpus de textes de taille petite à moyenne.
  • Similitude des documents: Il peut être utilisé pour calculer la similarité entre des documents textuels à l'aide de techniques telles que la similarité cosinusoïdale.
  • Classification des textes: Combiné à des techniques telles que Naive Bayes, BoW est efficace pour les tâches de classification de texte telles que la classification des spams et l'analyse des sentiments. l'analyse des sentiments.

Cependant, il y a aussi des inconvénients, comme le fait de ne pas tenir compte de la sémantique, de la structure des mots ou de l'ordre des mots.

Etapes pour implémenter un sac de mots en Python

Pour créer un modèle de sac de mots, nous prenons tous les mots d'un corpus et créons une colonne pour chaque mot. Les lignes représentent les phrases. Si un certain mot existe dans la phrase, il est représenté par un 1, et si le mot n'existe pas, il est représenté par un 0. Chaque mot de la colonne représente une seule caractéristique.

Au final, nous obtenons une matrice peu dense. Une matrice peu dense est une matrice comportant de nombreux zéros. 

Prétraitement des données

Pour créer un modèle de sac de mots en Python, nous devons effectuer quelques étapes de prétraitement. Ces étapes comprennent la tokenisation et la suppression des mots vides.

La tokenisation est le processus de décomposition d'un texte en unités plus petites, généralement des mots. Vous pouvez effectuer la tokenisation à l'aide de NLTK.

Les "stop words" sont des mots courants en anglais, tels que "the", "that" et "a", qui ne contribuent pas à la polarité d'une phrase.

import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

# Download stopwords and tokenizer if you haven't already
nltk.download("punkt")
nltk.download("stopwords")

# Example sentence
sentence = "This is an example showing how to remove stop words from a sentence."

# Tokenize the sentence into words
words = word_tokenize(sentence)

# Get the list of stop words in English
stop_words = set(stopwords.words("english"))

# Remove stop words from the sentence
filtered_sentence = [word for word in words if word.lower() not in stop_words]

# Join the words back into a sentence
filtered_sentence = " ".join(filtered_sentence)
print(filtered_sentence)

Sortie :

example showing remove stop words sentence.

Créer un vocabulaire

Un vocabulaire est une collection de mots uniques trouvés dans un corpus de textes. La constitution d'un vocabulaire implique de rassembler tous les mots uniques du corpus et de compter leurs occurrences. Ce vocabulaire est utile pour diverses tâches NLP telles que la modélisation du langage, l'intégration de mots et la classification de textes.

Le code ci-dessous crée une simple distribution de fréquence des mots du corpus, utile pour les tâches NLP de base telles que la construction d'un vocabulaire ou la compréhension du contenu d'un texte :

  • La variablecorpus contient quelques exemples de phrases. Dans les applications réelles, il s'agirait de données textuelles plus volumineuses et plus variées.
  • vocab = defaultdict(int) simplifie le comptage de la fréquence des mots, en initialisant automatiquement tout nouveau mot avec un compte de 0, ce qui permet une incrémentation directe sans vérification.
  • Chaque phrase est codée en la convertissant en minuscules et en extrayant les mots à l'aide d'expressions régulières. Le modèle \b\w+\b identifie les mots contenant uniquement des caractères alphanumériques, sans tenir compte de la ponctuation et des autres symboles.
  • Le décompte de chaque mot est mis à jour dans la base de données vocabulaire dans le dictionnaire.
  • Le vocabulaire est trié par fréquence dans l'ordre décroissant, ce qui permet de voir facilement les mots les plus courants en haut de l'écran.
import re  
# Import the regular expressions module to help with text processing
from collections import (
    defaultdict,
)  

# Import defaultdict to easily handle word frequency counting

# Sample corpus of text - a small dataset of sentences to analyze
corpus = [
    "Tokenization is the process of breaking text into words.",
    "Vocabulary is the collection of unique words.",
    "The process of tokenizing is essential in NLP.",
]

# Initialize a defaultdict with integer values to store word frequencies

# defaultdict(int) initializes each new key with a default integer value of 0
vocab = defaultdict(int)

# Loop through each sentence in the corpus to tokenize and normalize
for sentence in corpus:
    # Convert the sentence to lowercase to ensure consistency in counting (e.g., 'Tokenization' and 'tokenization' are treated as the same word)
    # Use regular expressions to find words composed of alphanumeric characters only
    words = re.findall(r"\b\w+\b", sentence.lower())
    # For each word found, increment its count in the vocab dictionary
    for word in words:
        vocab[word] += 1

# Convert the defaultdict vocab to a regular dictionary for easier handling and sorting

# Sort the dictionary by word frequency in descending order and convert it to a new dictionary
sorted_vocab = dict(sorted(vocab.items(), key=lambda x: x[1], reverse=True))

# Display the sorted vocabulary with each word and its frequency count
print("Vocabulary with Frequencies:", sorted_vocab)

Sortie :

Vocabulary with Frequencies: {'is': 3, 'the': 3, 'of': 3, 'process': 2, 'words': 2, 'tokenization': 1, 'breaking': 1, 'text': 1, 'into': 1, 'vocabulary': 1, 'collection': 1, 'unique': 1, 'tokenizing': 1, 'essential': 1, 'in': 1, 'nlp': 1}

La construction manuelle d'un vocabulaire peut prendre beaucoup de temps, en particulier pour les grands corpus. Le CountVectorizer de Scikit-learn automatise ce processus et permet un traitement plus souple du texte, comme nous le verrons plus loin. 

Implémentation d'un sac de mots avec Python (From Scratch)

Commençons par une implémentation simple du sac de mots à partir de zéro en Python. Cela vous aidera à comprendre les éléments constitutifs et les mécanismes de fonctionnement sous le capot.

Mise en œuvre manuelle

Étape 1 : Prétraitement des données textuelles

Nous commencerons par définir une fonction simple pour traiter le texte, y compris la tokenisation, la mise en minuscules et la suppression de la ponctuation.

from collections import defaultdict
import string

# Sample text data: sentences
corpus = [
    "Python is amazing and fun.",
    "Python is not just fun but also powerful.",
    "Learning Python is fun!",
]
# Function to preprocess text
def preprocess(text):
    # Convert to lowercase
    text = text.lower()
    # Remove punctuation
    text = text.translate(str.maketrans("", "", string.punctuation))
    # Tokenize: split the text into words
    tokens = text.split()
    return tokens

# Apply preprocessing to the sample corpus
processed_corpus = [preprocess(sentence) for sentence in corpus]
print(processed_corpus)

Sortie :

[['python', 'is', 'amazing', 'and', 'fun'], ['python', 'is', 'not', 'just', 'fun', 'but', 'also', 'powerful'], ['learning', 'python', 'is', 'fun']]

Étape 2 : Développer le vocabulaire

Nous devons maintenant parcourir tous les documents et établir une liste complète de mots uniques, c'est-à-dire notre vocabulaire.

# Initialize an empty set for the vocabulary
vocabulary = set()

# Build the vocabulary
for sentence in processed_corpus:
    vocabulary.update(sentence)

# Convert to a sorted list
vocabulary = sorted(list(vocabulary))
print("Vocabulary:", vocabulary)

Étape 3 : Calculer les fréquences des mots et les vectoriser

Nous allons maintenant calculer la fréquence de chaque mot du vocabulaire pour chaque document du corpus traité.

def create_bow_vector(sentence, vocab):
    vector = [0] * len(vocab)  # Initialize a vector of zeros
    for word in sentence:
        if word in vocab:
            idx = vocab.index(word)  # Find the index of the word in the vocabulary
            vector[idx] += 1  # Increment the count at that index
    return vector

À ce stade, vous aurez créé une représentation du sac de mots pour chaque document de votre corpus.

# Create BoW vector for each sentence in the processed corpus
bow_vectors = [create_bow_vector(sentence, vocabulary) for sentence in processed_corpus]
print("Bag of Words Vectors:")
for vector in bow_vectors:
    print(vector)

Sortie :

Bag of Words Vectors:
[0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1]
[1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1]
[0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1]

Utilisation du CountVectorizer de Scikit-learn

Construire un modèle de sac de mots manuellement est une bonne chose pour l'apprentissage, mais pour les applications de production, vous voudrez utiliser des bibliothèques efficaces et optimisées comme Scikit-learn.

La fonction Python que nous utilisons pour la tokenisation est CountVectorizerqui est importée du site sklearn.feature_extraction.text. L'une des caractéristiques de CountVectorizer est max_features, qui représente le nombre maximum de mots que vous souhaitez avoir dans le modèle de sac de mots. Dans ce cas, nous utilisons None, ce qui signifie que toutes les fonctionnalités seront utilisées. 

Après avoir créé une instance de CountVectorizer, utilisez la méthode .fit_transform() pour créer le modèle de sac de mots. Ensuite, utilisez le site .toarray() pour convertir le modèle de sac de mots en tableaux numpy qui peuvent être introduits dans un modèle d'apprentissage automatique.

Une fois ajusté, CountVectorizer a construit un dictionnaire d'indices de caractéristiques. La valeur de l'indice d'un mot dans le vocabulaire est liée à sa fréquence dans l'ensemble du corpus de formation.

from sklearn.feature_extraction.text import CountVectorizer
# Original corpus
corpus = [
    "Python is amazing and fun.",
    "Python is not just fun but also powerful.",
    "Learning Python is fun!",
]
# Create a CountVectorizer Object
vectorizer = CountVectorizer()
# Fit and transform the corpus
X = vectorizer.fit_transform(corpus)
# Print the generated vocabulary
print("Vocabulary:", vectorizer.get_feature_names_out())
# Print the Bag-of-Words matrix
print("BoW Representation:")
print(X.toarray())

Sortie :

markdownVocabulary: ['also' 'amazing' 'and' 'but' 'fun' 'is' 'just' 'learning' 'not'

 'powerful' 'python']

BoW Representation:

[[0 1 1 0 1 1 0 0 0 0 1]

 [1 0 0 1 1 1 1 0 1 1 1]

 [0 0 0 0 1 1 0 1 0 0 1]]

Exemple : Application du sac de mots

Appliquons maintenant le modèle BoW à un petit corpus textuel composé de trois critiques de films afin d'illustrer l'ensemble du processus. 

Nous utiliserons le CountVectorizer de Scikit-learn pour appliquer le modèle BoW à ce petit corpus de texte.

Voici les mesures que nous allons prendre :

  • CountVectorizer tokenise le texte, supprime la ponctuation et met les mots en minuscules automatiquement.
  • .fit_transform(corpus) convertit le corpus en une matrice document-terme, où chaque ligne représente un document et chaque colonne un mot du vocabulaire.
  • X_dense est la matrice dense qui représente la fréquence de chaque mot dans chaque document.
from sklearn.feature_extraction.text import CountVectorizer
# Sample corpus of movie reviews
corpus = [
    "I loved the movie, it was fantastic!",
    "The movie was okay, but not great.",
    "I hated the movie, it was terrible.",
]

# Initialize the CountVectorizer
vectorizer = CountVectorizer()

# Fit and transform the corpus to a document-term matrix
X = vectorizer.fit_transform(corpus)

# Convert the document-term matrix into a dense format (optional for visualization)
X_dense = X.toarray()

# Get the vocabulary (mapping of words to index positions)
vocab = vectorizer.get_feature_names_out()

# Print the vocabulary and document-term matrix
print("Vocabulary:", vocab)
print("Document-Term Matrix:\n", X_dense)

Sortie :

Vocabulary: ['but' 'fantastic' 'great' 'hated' 'it' 'loved' 'movie' 'not' 'okay' 'terrible' 'the' 'was']
Document-Term Matrix:
 [[0 1 0 0 1 1 1 0 0 0 1 1]  # First review: "I loved the movie, it was fantastic!"
  [1 0 1 0 1 0 1 1 1 0 1 1]  # Second review: "The movie was okay, but not great."
  [0 0 0 1 1 0 1 0 0 1 1 1]] # Third review: "I hated the movie, it was terrible."

Voici comment nous pouvons interpréter le résultat ci-dessus :

  • Un index est attribué à chaque mot unique du corpus et les mots sont classés par ordre alphabétique. Par exemple, "but" est à l'index 0, "fantastic" est à l'index 1, "movie" est à l'index 6, etc.
  •  Chaque ligne de la matrice de documents représente une critique de film et chaque colonne correspond à un mot du vocabulaire. Les valeurs de la matrice représentent la fréquence de chaque mot dans ce document particulier.
    • Premier examen : [0 1 0 0 1 1 1 0 0 0 1 1] indique que :
      • Le mot "fantastique" apparaît une fois (1 à l'indice 1),
      • Le mot "aimé" apparaît une fois (1 à l'indice 5),
      • Le mot "film" apparaît une fois (1 à l'indice 6),
      • Le mot "il" apparaît une fois (1 à l'indice 4),
      • Et ainsi de suite.

Le vecteur BoW peut être interprété comme suit :

  • Chaque document est un vecteur de nombres représentant le nombre de mots. Les dimensions du vecteur sont égales à la taille du vocabulaire. Dans ce cas, le vocabulaire comporte 12 mots, de sorte que chaque examen est transformé en un vecteur à 12 dimensions.
  • La plupart des mots de chaque ligne sont des zéros car chaque document ne contient pas tous les mots du vocabulaire. Par conséquent, les modèles BoW sont souvent épars, c'est-à-dire qu'ils comportent de nombreux zéros.

Avantages et limites du sac de mots

Examinons maintenant quelques-uns des avantages et des limites du modèle du sac de mots.

Avantages

  1. Simple à mettre en œuvre et à interpréter: Le modèle du sac de mots est l'une des techniques de représentation de texte les plus simples, ce qui en fait un outil idéal pour les débutants. Sa simplicité permet une mise en œuvre rapide sans nécessiter de prétraitement complexe ou de modèles spécialisés.
  2. Facile à utiliser pour les tâches de classification de textes: Le sac de mots est bien adapté aux tâches de base telles que la classification des textes, l'analyse des sentiments et la détection des spams. Souvent, ces tâches ne nécessitent pas de modèles linguistiques sophistiqués, de sorte qu'une représentation BOW est suffisante et efficace.

Limites

  1. La taille du vocabulaire influe sur la rareté des représentations: Plus le vocabulaire est étendu, plus la représentation est éparse et de haute dimension. Cette rareté peut rendre plus difficile l'apprentissage efficace des modèles et nécessite un réglage minutieux de la taille du vocabulaire afin d'éviter des coûts de calcul excessifs.
  2. Produit des matrices éparses qui sont coûteuses en temps de calcul: Étant donné que chaque document est représenté par la fréquence de chaque mot dans un vocabulaire potentiellement vaste, les matrices résultantes sont souvent composées en grande partie de zéros, ce qui peut être inefficace à stocker et à traiter dans les pipelines d'apprentissage automatique. Les matrices éparses consomment beaucoup de mémoire et nécessitent souvent des outils et des bibliothèques spécialisés pour un stockage et un calcul efficaces, en particulier pour les grands ensembles de données.
  3. Perte de sens et de contexte: BOW ne tient pas compte de l'ordre des mots et de la structure des phrases, ce qui entraîne une perte des relations grammaticales et du sens. Cette limitation la rend moins adaptée aux tâches où le contexte, la nuance et l'ordre des mots sont importants, comme la traduction ou la détection de sentiments dans des phrases complexes.

Les stratégies suivantes peuvent être utilisées pour réduire la taille du vocabulaire dans le sac de mots :

  • Ignorer l'affaire. 
  • Suppression des ponctuations.
  • Suppression des mots vides, c'est-à-dire des mots courants tels que le et a. 
  • Veiller à ce que tous les mots soient correctement orthographiés. 
  • Utiliser des techniques de troncature pour réduire les mots à leur forme racine.

Prochaines étapes : Au-delà du sac de mots

L'une des limites du modèle du sac de mots est qu'il traite tous les mots de la même manière. Malheureusement, cela peut conduire à des problèmes où certains mots se voient accorder plus d'importance simplement parce qu'ils apparaissent fréquemment. 

Le TF-IDF (Term Frequency-Inverse Document Frequency) est une solution à ce problème, car il ajuste le poids des mots en fonction de leur fréquence d'apparition dans l'ensemble des documents.

TF-IDF : Une extension du sac de mots

La fréquence des termes (TF) représente la fréquence d'un terme dans un document. La fréquence inverse des documents (IDF) réduit l'impact des mots qui reviennent le plus souvent dans plusieurs documents. Le score TF-IDF est calculé en multipliant les deux mesures. 

Considérons un document contenant 200 mots, dans lequel le mot "amour" apparaît 5 fois. Le TF pour l'amour est alors de (5 / 200) = 0,025. En supposant que nous disposions d'un million de documents et que le mot "amour" apparaisse dans un millier d'entre eux, la fréquence inverse des documents (IDF) est calculée comme suit : log(1000000 / 1000) = 3. Le poids TF-IDF est le produit de ces quantités : 0.025 * 3 = 0.075.

Dans Scikit-learn, il est relativement facile de calculer cette valeur en utilisant la classe TfidfVectorizer.

from sklearn.feature_extraction.text import TfidfVectorizer
# Sample corpus
corpus = [
    "Python is amazing and fun.",
    "Python is not just fun but also powerful.",
    "Learning Python is fun!",
]

# Create the Tf-idf vectorizer
tfidf_vectorizer = TfidfVectorizer()

# Fit and transform the corpus
X_tfidf = tfidf_vectorizer.fit_transform(corpus)

# Show the Vocabulary
print("Vocabulary:", tfidf_vectorizer.get_feature_names_out())

# Show the TF-IDF Matrix
print("TF-IDF Representation:")
print(X_tfidf.toarray())

Sortie :

Vocabulary: ['also' 'amazing' 'and' 'but' 'fun' 'is' 'just' 'learning' 'not'
 'powerful' 'python']
TF-IDF Representation:
[[0.         0.57292883 0.57292883 0.         0.338381   0.338381
  0.         0.         0.         0.         0.338381  ]
 [0.40667606 0.         0.         0.40667606 0.24018943 0.24018943
  0.40667606 0.         0.40667606 0.40667606 0.24018943]
 [0.         0.         0.         0.         0.41285857 0.41285857
  0.         0.69903033 0.         0.         0.41285857]]

La matrice TF-IDF mise en œuvre ci-dessus vous donne une mesure pondérée au lieu des fréquences brutes.

Bien que le modèle du sac de mots ait ses limites, en particulier pour les ensembles de données plus vastes et plus complexes, il reste un élément essentiel dans de nombreuses applications NLP. Sa compréhension vous aidera à explorer des modèles plus avancés tels que les enchâssements de mots et les transformateurs.

À partir de là, vous pouvez expérimenter BoW dans vos projets, y compris la détection des spams, l'analyse des sentiments, le regroupement de documents, etc.

Si vous souhaitez obtenir des améliorations au-delà du sac de mots, vous pouvez explorer des méthodes telles que Word2Vec et GloVe, ou des modèles d'apprentissage profond tels que BERT.

Réflexions finales

La technique du sac de mots est une technique fondamentale utilisée dans le traitement du langage naturel. Il s'agit d'un moyen simple mais efficace de convertir un texte non structuré en caractéristiques numériques utilisables par des algorithmes d'apprentissage automatique. Dans ce tutoriel, nous avons abordé les sujets suivants :

  • Qu'est-ce que le modèle du sac de mots ?
  • Les avantages du modèle de sac de mots dans la construction de modèles d'apprentissage automatique.
  • Comment mettre en œuvre le modèle du sac de mots en Python.
  •  Avantages et limites du sac de mots.
  • La théorie et la motivation derrière le modèle du sac de mots.
  • Introduction du TF-IDF en tant qu'amélioration de l'approche traditionnelle du sac de mots.

Consultez notre cursus Traitement du langage naturel en Python, pour plonger en profondeur dans le traitement du langage naturel. 


Derrick Mwiti's photo
Author
Derrick Mwiti
Sujets

Les meilleurs cours de DataCamp

Certification disponible

cours

Text Mining avec Bag-of-Words en R

4 hr
43.2K
Apprenez la technique du sac de mots pour l'exploration de texte avec R.
Afficher les détailsRight Arrow
Commencer le cours
Voir plusRight Arrow