curso
Modelo de bolsa de palabras Python: Guía completa
La Bolsa de Palabras (BoW) es una técnica del Procesamiento del Lenguaje Natural (PLN). Se utiliza ampliamente para transformar datos textuales en formato legible por máquina, concretamente valores numéricos, sin tener en cuenta la gramática ni el orden de las palabras. Comprender el BoW es importante para cualquiera que trabaje con datos de texto. Python proporciona múltiples herramientas y bibliotecas para implementar eficazmente la Bolsa de Palabras.
En este tutorial, nos sumergiremos en BoW, introduciremos sus conceptos, cubriremos sus usos y recorreremos una implementación detallada en Python. Al final de este tutorial, serás capaz de aplicar el modelo de la Bolsa de Palabras a problemas del mundo real. Si eres nuevo en PNL, echa un vistazo a nuestro Procesamiento del Lenguaje Natural en Python para aprender más.
¿Qué es Bolsa de Palabras?
La Bolsa de Palabras es una técnica para extraer características de datos de texto para tareas de aprendizaje automático, como la clasificación de textos y el análisis de sentimientos. Esto es importante porque los algoritmos de aprendizaje automático no pueden procesar datos textuales. El proceso de convertir el texto en números se conoce como extracción de rasgos o codificación de rasgos.
Una Bolsa de Palabras se basa en la aparición de palabras en un documento. El proceso comienza con la búsqueda del vocabulario en el texto y la medición de su aparición. Se llama bolsa porque no se tienen en cuenta el orden ni la estructura de las palabras, sólo su aparición.
El modelo de bolsa de palabras es diferente del modelo de bolsa de palabras continua (CBOW), que aprende incrustaciones densas de palabras utilizando las palabras circundantes para predecir una palabra objetivo, capturando las relaciones semánticas entre las palabras. El CBOW requiere entrenamiento en un corpus grande y produce vectores de baja dimensión que son valiosos para aplicaciones complejas de PNL en las que el contexto de las palabras es importante.
Aspecto |
ARCO |
CBOW |
Propósito |
Cuenta las apariciones de cada palabra |
Predice la palabra objetivo basándose en el contexto |
Tipo de salida |
Vector disperso de alta dimensión |
Incrustación densa de baja dimensión |
Considera el contexto |
No (ignora el orden de las palabras) |
Sí (utiliza palabras circundantes) |
Representación |
Vector de frecuencias disperso |
Semántica de captura de vectores densos |
Complejidad |
Bajo (no requiere formación) |
Alta (requiere entrenamiento en corpus grandes) |
Aplicaciones típicas |
Clasificación de textos, análisis de sentimientos |
Incrustación de palabras, tareas de PNL que necesitan contexto |
¿Por qué utilizar la Bolsa de Palabras?
La Bolsa de Palabras es útil en muchas tareas de PNLalgunas razones para su uso
- Extracción de rasgos: Convierte datos de texto no estructurados en datos estructurados, que pueden utilizarse como entrada para diversos algoritmos de aprendizaje automático.
- Sencillez y eficacia: La aplicación de BoW es sencilla desde el punto de vista informático y funciona bien con corpus de texto de tamaño pequeño o mediano.
- Similitud de documentos: Puede utilizarse para calcular la similitud entre documentos de texto mediante técnicas como la similitud del coseno.
- Clasificación de textos: Cuando se combina con técnicas como Naive Bayes, BoW es eficaz para tareas de clasificación de texto, como la clasificación de spam, y análisis de sentimientos.
Sin embargo, también tiene inconvenientes, como no tener en cuenta la semántica, la estructura de las palabras o su ordenación.
Pasos para implementar la bolsa de palabras en Python
Para crear un modelo de bolsa de palabras, tomamos todas las palabras de un corpus y creamos una columna con cada palabra. Las filas representan las frases. Si una palabra determinada existe en la frase, se representa con un 1, y si la palabra no existe, se representa con un 0. Cada palabra de la columna representa una única característica.
Al final, obtenemos una matriz dispersa. Una matriz dispersa es una matriz con muchos ceros.
Preprocesamiento de datos
Para crear un modelo de Bolsa de Palabras en Python, tenemos que seguir unos pasos de preprocesamiento. Estos pasos incluyen la tokenización y la eliminación de palabras clave.
La tokenización es el proceso de descomponer un texto en unidades más pequeñas, normalmente palabras. Puedes realizar la tokenización utilizando NLTK.
Las stop words son palabras comunes en inglés, como "the", "that" y "a", que no contribuyen a la polaridad de una frase.
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)
Salida:
example showing remove stop words sentence.
Crear un vocabulario
Un vocabulario es una colección de palabras únicas que se encuentran en un corpus de texto. Construir un vocabulario implica reunir todas las palabras únicas del corpus y contar sus apariciones. Este vocabulario es útil para diversas tareas de PNL, como el modelado del lenguaje, la incrustación de palabras y la clasificación de textos.
Este código crea una sencilla distribución de frecuencias de las palabras del corpus, útil para tareas básicas de PNL, como construir un vocabulario o comprender el contenido de un texto:
- La variablecorpus contiene algunas frases de ejemplo. En aplicaciones reales, contendría datos de texto más grandes y variados.
- vocab =
defaultdict(int)
simplifica el recuento de frecuencia de palabras, inicializando automáticamente cualquier palabra nueva con un recuento de 0, lo que permite el incremento directo sin comprobaciones. - Cada frase se tokeniza convirtiéndola a minúsculas y extrayendo palabras mediante expresiones regulares. El patrón
\b\w+\b
identifica sólo palabras con caracteres alfanuméricos, ignorando la puntuación y otros símbolos. - El recuento de cada palabra se actualiza en vocabulario del diccionario.
- El vocabulario se clasifica por frecuencia en orden descendente, lo que facilita ver las palabras más comunes en la parte superior, y se muestra como referencia.
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)
Salida:
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}
Construir manualmente un vocabulario puede llevar mucho tiempo, sobre todo en el caso de corpus grandes. El CountVectorizer de Scikit-learn automatiza este proceso y permite un tratamiento más flexible del texto, como veremos más adelante.
Implementación de la bolsa de palabras con Python (desde cero)
Empecemos con una sencilla implementación de Bolsa de Palabras desde cero en Python. Esto te ayudará a entender los bloques de construcción y la mecánica de cómo funciona bajo el capó.
Aplicación manual
Paso 1: Preprocesamiento de los datos de texto
Empezaremos definiendo una función sencilla para procesar texto, incluyendo la tokenización, el uso de minúsculas y la eliminación de signos de puntuación.
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)
Salida:
[['python', 'is', 'amazing', 'and', 'fun'], ['python', 'is', 'not', 'just', 'fun', 'but', 'also', 'powerful'], ['learning', 'python', 'is', 'fun']]
Paso 2: Construye vocabulario
Ahora, tenemos que escanear todos los documentos y construir una lista completa de palabras únicas, que es nuestro vocabulario.
# 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)
Paso 3: Calcular frecuencias de palabras y vectorizar
Ahora calcularemos la frecuencia de cada palabra del vocabulario para cada documento del corpus procesado.
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
Llegados a este punto, habrás creado una representación de Bolsa de Palabras para cada documento de tu 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)
Salida:
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]
Utilizar el CountVectorizer de Scikit-learn
Construir un modelo de Bolsa de Palabras manualmente es bueno para aprender, pero para aplicaciones de producción, querrás utilizar bibliotecas eficientes y optimizadas como Scikit-learn.
La función de Python que utilizamos para la tokenización es ContarVectorizadorque se importa de sklearn.feature_extraction.text
. Una de las características de CountVectorizer
es max_features
, que representa el número máximo de palabras que te gustaría tener en el modelo de bolsa de palabras. En este caso, utilizamos Ninguno, lo que significa que se utilizarán todas las características.
Tras crear una instancia de CountVectorizer
, utiliza el método .fit_transform(
) para crear el modelo de bolsa de palabras. A continuación, utiliza .toarray()
para convertir el modelo de bolsa de palabras en matrices numpy que puedan alimentar un modelo de aprendizaje automático.
Una vez ajustado, CountVectorizer ha construido un diccionario de índices de características. El valor del índice de una palabra del vocabulario está vinculado a su frecuencia en todo el corpus de entrenamiento.
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())
Salida:
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]]
Ejemplo: Aplicar Bolsa de Palabras
Apliquemos ahora el modelo BoW a un pequeño corpus de texto formado por tres críticas de películas para ilustrar todo el proceso.
Utilizaremos el CountVectorizer de Scikit-learn para aplicar el modelo BoW a este pequeño corpus de texto.
Estos son los pasos que vamos a dar:
CountVectorizer
tokeniza el texto, elimina la puntuación y escribe las palabras en minúsculas automáticamente..fit_transform(corpus)
convierte el corpus en una matriz documento-término, donde cada fila representa un documento y cada columna representa una palabra del vocabulario.X_dense
es la matriz densa que representa la frecuencia de cada palabra en cada documento.
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)
Salida:
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."
Así es como podemos interpretar el resultado anterior:
- A cada palabra única del corpus se le asigna un índice, y las palabras se ordenan alfabéticamente. Por ejemplo, "pero" está en el índice 0, "fantástico" está en el índice 1, "película" está en el índice 6, etc.
- Cada fila de la matriz de documentos representa una crítica de película, y cada columna corresponde a una palabra del vocabulario. Los valores de la matriz representan la frecuencia de cada palabra en ese documento concreto.
- Primera Revisión: [0 1 0 0 1 1 1 0 0 0 1 1] indica que:
- La palabra "fantástico" aparece una vez (1 en el índice 1),
- La palabra "amado" aparece una vez (1 en el índice 5),
- La palabra "película" aparece una vez (1 en el índice 6),
- La palabra "ello" aparece una vez (1 en el índice 4),
- Y así sucesivamente.
El vector BoW puede interpretarse del siguiente modo:
- Cada documento es un vector de números que representan el recuento de palabras. Las dimensiones del vector son iguales al tamaño del vocabulario. En este caso, el vocabulario tiene 12 palabras, por lo que cada reseña se transforma en un vector de 12 dimensiones.
- La mayoría de las palabras de cada fila son ceros, porque no todos los documentos contienen todas las palabras del vocabulario. Por eso, los modelos BoW suelen ser dispersos, es decir, tienen muchos ceros.
Ventajas y limitaciones de la Bolsa de Palabras
Veamos ahora algunas de las ventajas y limitaciones del modelo de la Bolsa de Palabras.
Ventajas
- Fácil de aplicar e interpretar: El modelo de Bolsa de Palabras es una de las técnicas de representación de texto más sencillas, por lo que es ideal para principiantes. Su sencillez permite una aplicación rápida sin necesidad de preprocesamientos complejos ni modelos especializados.
- Fácil de usar para tareas de clasificación de textos: La Bolsa de Palabras es muy adecuada para tareas básicas como la clasificación de textos, el análisis de sentimientos y la detección de spam. Estas tareas no suelen requerir modelos lingüísticos sofisticados, por lo que una representación BOW es suficiente y eficaz.
Limitaciones
- El tamaño del vocabulario afecta a la escasez de representaciones: Cuanto mayor sea el vocabulario, más dispersa y tridimensional será la representación. Esta dispersión puede dificultar el aprendizaje eficaz de los modelos y exige un ajuste cuidadoso del tamaño del vocabulario para evitar costes computacionales excesivos.
- Produce matrices dispersas que son costosas desde el punto de vista informático: Como cada documento está representado por la frecuencia de cada palabra de un vocabulario potencialmente amplio, las matrices resultantes suelen ser en su mayoría ceros, lo que puede resultar ineficaz para almacenar y procesar en pipelines de aprendizaje automático. Las matrices dispersas consumen mucha memoria y a menudo requieren herramientas y bibliotecas especializadas para un almacenamiento y cálculo eficientes, especialmente con grandes conjuntos de datos.
- Pierde sentido y contexto: BOW ignora el orden de las palabras y la estructura de las frases, lo que provoca la pérdida de relaciones gramaticales y de significado. Esta limitación lo hace menos adecuado para tareas en las que importan el contexto, el matiz y el orden de las palabras, como la traducción o la detección de sentimientos en frases complejas.
Se pueden utilizar las siguientes estrategias para reducir el tamaño del vocabulario de la Bolsa de Palabras:
- Ignorando el caso.
- Eliminar puntuaciones.
- Eliminar las stopwords, es decir, palabras comunes como la y la a.
- Asegurarse de que todas las palabras están bien escritas.
- Utilizar técnicas de stemming para reducir las palabras a su forma raíz.
Próximos pasos: Más allá de la bolsa de palabras
Una limitación del modelo de la Bolsa de Palabras es que trata todas las palabras por igual. Desgraciadamente, esto puede dar lugar a problemas en los que se da más importancia a algunas palabras simplemente porque aparecen con frecuencia.
TF-IDF (Term Frequency-Inverse Document Frequency) es una solución a este problema, ya que ajusta el peso de las palabras en función de la frecuencia con que aparecen en todos los documentos.
TF-IDF: Una ampliación de Bolsa de Palabras
La frecuencia de términos (TF) representa la frecuencia de un término en un documento. La Frecuencia Inversa de Documentos (FID) reduce el impacto de las palabras que aparecen comúnmente en varios documentos. La puntuación TF-IDF se calcula multiplicando las dos métricas.
Considera un documento de 200 palabras, en el que la palabra amor aparece 5 veces. La TF del amor es entonces (5 / 200) = 0,025. Suponiendo que tuviéramos un millón de documentos y la palabra amor apareciera en mil de ellos, la frecuencia inversa del documento (es decir, FID) se calcula como log(1000000 / 1000) = 3. El peso TF-IDF es el producto de estas cantidades: 0.025 * 3 = 0.075.
En Scikit-learn, esto es relativamente fácil de calcular utilizando la clase 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())
Salida:
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 matriz TF-IDF implementada anteriormente te proporciona una medida ponderada en lugar de frecuencias brutas.
Aunque el modelo de Bolsa de Palabras tiene sus limitaciones, sobre todo para conjuntos de datos más grandes y complejos, sigue siendo un elemento esencial en muchas aplicaciones de PNL. Comprenderlo te ayudará a la hora de explorar modelos más avanzados, como la incrustación de palabras y los Transformadores.
A partir de aquí, podrías experimentar con BoW en tus proyectos, incluyendo la detección de spam, el análisis de sentimientos, la agrupación de documentos y mucho más.
Si quieres mejorar más allá de la Bolsa de Palabras, puedes explorar métodos como Word2Vec, y GloVe, o modelos de aprendizaje profundo como BERT.
Reflexiones finales
La técnica de la Bolsa de Palabras es una técnica fundamental utilizada en el Procesamiento del Lenguaje Natural. Sirve como una forma sencilla pero eficaz de convertir texto no estructurado en características numéricas utilizables por algoritmos de aprendizaje automático. En este tutorial, hemos cubierto:
- ¿Qué es el modelo de la Bolsa de Palabras (BdP)?
- Las ventajas del modelo Bolsa de Palabras en la construcción de modelos de aprendizaje automático.
- Cómo implementar el modelo de la Bolsa de Palabras en Python.
- Ventajas y limitaciones de la Bolsa de Palabras.
- Teoría y motivación del modelo Bolsa de Palabras.
- Introducción del TF-IDF como mejora del enfoque tradicional de la Bolsa de Palabras.
Echa un vistazo a nuestra pista de habilidades de Procesamiento del Lenguaje Natural en Python, para profundizar en el procesamiento del lenguaje natural.
Los mejores cursos de DataCamp
programa
Natural Language Processing
curso
Feature Engineering for NLP in Python
tutorial
Tutorial de Generación de nubes de palabras en Python
tutorial
Stemming y lematización en Python
tutorial
Clasificación de textos en Python
tutorial
Tutorial de análisis NLTK del sentimiento para principiantes
tutorial
Tutorial de pandas en Python: la guía definitiva para principiantes
tutorial
Desarrollo de backend en Python: Guía completa para principiantes
Oluseye Jeremiah
26 min