Comparación de FeatureHasher y DictVectorizer

Machine LearningMachine LearningBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, exploraremos la vectorización de texto, que es el proceso de representar datos de entrada no numéricos (como diccionarios o documentos de texto) como vectores de números reales. Compararemos dos métodos, FeatureHasher y DictVectorizer, mediante el uso de ambos métodos para vectorizar documentos de texto que se han preprocesado (tokenizados) con la ayuda de una función personalizada de Python.

Consejos sobre la VM

Una vez finalizada la inicialización de la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.

A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.

Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje su retroalimentación después de la sesión y le resolveremos el problema inmediatamente.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/feature_extraction("Feature Extraction") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/feature_extraction -.-> lab-49158{{"Comparación de FeatureHasher y DictVectorizer"}} sklearn/datasets -.-> lab-49158{{"Comparación de FeatureHasher y DictVectorizer"}} ml/sklearn -.-> lab-49158{{"Comparación de FeatureHasher y DictVectorizer"}} end

Cargar datos

Cargaremos datos del 20newsgroups_dataset, que comprende alrededor de 18000 publicaciones de grupos de noticias en 20 temas divididos en dos subconjuntos: uno para el entrenamiento y otro para la prueba. Por simplicidad y para reducir el costo computacional, seleccionamos un subconjunto de 7 temas y usamos solo el conjunto de entrenamiento.

from sklearn.datasets import fetch_20newsgroups

categories = [
    "alt.atheism",
    "comp.graphics",
    "comp.sys.ibm.pc.hardware",
    "misc.forsale",
    "rec.autos",
    "sci.space",
    "talk.religion.misc",
]

print("Loading 20 newsgroups training data")
raw_data, _ = fetch_20newsgroups(subset="train", categories=categories, return_X_y=True)
data_size_mb = sum(len(s.encode("utf-8")) for s in raw_data) / 1e6
print(f"{len(raw_data)} documents - {data_size_mb:.3f}MB")

Definir funciones de preprocesamiento

Un token puede ser una palabra, una parte de una palabra o cualquier cosa comprendida entre espacios o símbolos en una cadena. Aquí definimos una función que extrae los tokens utilizando una expresión regular simple (regex) que coincide con los caracteres de palabras Unicode. Esto incluye la mayoría de los caracteres que pueden ser parte de una palabra en cualquier idioma, así como números y el subrayado:

import re

def tokenize(doc):
    """Extraer tokens de doc.

    Esto utiliza una regex simple que coincide con los caracteres de palabras para dividir las cadenas
    en tokens. Para un enfoque más sistemático, consulte CountVectorizer o
    TfidfVectorizer.
    """
    return (tok.lower() for tok in re.findall(r"\w+", doc))

Definimos una función adicional que cuenta la (frecuencia de) ocurrencia de cada token en un documento dado. Devuelve un diccionario de frecuencias para ser utilizado por los vectorizadores.

from collections import defaultdict

def token_freqs(doc):
    """Extraer un diccionario que mapea tokens de doc a sus ocurrencias."""

    freq = defaultdict(int)
    for tok in tokenize(doc):
        freq[tok] += 1
    return freq

DictVectorizer

Evaluaremos el DictVectorizer, que es un método que recibe diccionarios como entrada.

from sklearn.feature_extraction import DictVectorizer
from time import time

t0 = time()
vectorizer = DictVectorizer()
vectorizer.fit_transform(token_freqs(d) for d in raw_data)
duration = time() - t0
print(f"hecho en {duration:.3f} s")
print(f"Encontrados {len(vectorizer.get_feature_names_out())} términos únicos")

FeatureHasher

Evaluaremos el FeatureHasher, que es un método que construye un vector de longitud predefinida aplicando una función de hash a las características (por ejemplo, tokens), luego utilizando los valores de hash directamente como índices de características y actualizando el vector resultante en esos índices.

from sklearn.feature_extraction import FeatureHasher
import numpy as np

t0 = time()
hasher = FeatureHasher(n_features=2**18)
X = hasher.transform(token_freqs(d) for d in raw_data)
duration = time() - t0
print(f"hecho en {duration:.3f} s")
print(f"Encontrados {len(np.unique(X.nonzero()[1]))} tokens únicos")

Comparación con vectorizadores de texto con fines especiales

Compararemos los métodos anteriores con el CountVectorizer y el HashingVectorizer.

from sklearn.feature_extraction.text import CountVectorizer, HashingVectorizer, TfidfVectorizer

t0 = time()
vectorizer = CountVectorizer()
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"hecho en {duration:.3f} s")
print(f"Encontrados {len(vectorizer.get_feature_names_out())} términos únicos")

t0 = time()
vectorizer = HashingVectorizer(n_features=2**18)
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"hecho en {duration:.3f} s")

t0 = time()
vectorizer = TfidfVectorizer()
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"hecho en {duration:.3f} s")
print(f"Encontrados {len(vectorizer.get_feature_names_out())} términos únicos")

Graficar los resultados

Graficaremos la velocidad de los métodos anteriores para vectorizar.

import matplotlib.pyplot as plt

dict_count_vectorizers = {
    "vectorizer": [
        "DictVectorizer\nen diccionarios no de frecuencia",
        "FeatureHasher\nen diccionarios no de frecuencia",
        "FeatureHasher\nen tokens sin procesar",
        "CountVectorizer",
        "HashingVectorizer",
        "TfidfVectorizer"
    ],
    "speed": [
        2.4, 4.4, 7.2, 5.1, 11.7, 2.9
    ]
}

fig, ax = plt.subplots(figsize=(12, 6))

y_pos = np.arange(len(dict_count_vectorizers["vectorizer"]))
ax.barh(y_pos, dict_count_vectorizers["speed"], align="center")
ax.set_yticks(y_pos)
ax.set_yticklabels(dict_count_vectorizers["vectorizer"])
ax.invert_yaxis()
_ = ax.set_xlabel("velocidad (MB/s)")

Resumen

En este laboratorio, exploramos la vectorización de texto al comparar dos métodos, FeatureHasher y DictVectorizer, y cuatro vectorizadores de texto con fines especiales, CountVectorizer, HashingVectorizer y TfidfVectorizer. Evaluamos los métodos de vectorización y graficamos los resultados. Concluimos que HashingVectorizer tiene un mejor rendimiento que CountVectorizer a expensas de la inversibilidad de la transformación debido a las colisiones de hash. Además, DictVectorizer y FeatureHasher tienen un mejor rendimiento que sus equivalentes de vectorización de texto en documentos con tokenización manual, ya que el paso de tokenización interno de los primeros vectorizadores compila una expresión regular una vez y luego la reutiliza para todos los documentos.