Vergleich von FeatureHasher und DictVectorizer

Machine LearningMachine LearningBeginner
Jetzt üben

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

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab werden wir die Textvektorisierung untersuchen, die der Prozess ist, nicht-numerische Eingabedaten (wie Wörterbücher oder Textdokumente) als Vektoren von reellen Zahlen darzustellen. Wir werden zwei Methoden, FeatureHasher und DictVectorizer, vergleichen, indem wir beide Methoden verwenden, um Textdokumente zu vektorisieren, die mit Hilfe einer benutzerdefinierten Python-Funktion vorverarbeitet (tokenisiert) wurden.

Tipps für die VM

Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu öffnen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund von Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) 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{{"Vergleich von FeatureHasher und DictVectorizer"}} sklearn/datasets -.-> lab-49158{{"Vergleich von FeatureHasher und DictVectorizer"}} ml/sklearn -.-> lab-49158{{"Vergleich von FeatureHasher und DictVectorizer"}} end

Daten laden

Wir werden Daten aus 20newsgroups_dataset laden, das aus rund 18.000 Newsgroup-Posts zu 20 Themen besteht, die in zwei Teilmengen unterteilt sind: eine für das Training und eine für das Testing. Aus Gründen der Einfachheit und zur Reduzierung der Rechenkosten wählen wir eine Teilmenge von 7 Themen und verwenden nur den Trainingssatz.

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")

Definiere Vorverarbeitungfunktionen

Ein Token kann ein Wort, ein Teil eines Worts oder alles sein, was zwischen Leerzeichen oder Symbolen in einer Zeichenkette enthalten ist. Hier definieren wir eine Funktion, die die Tokens mit Hilfe eines einfachen regulären Ausdrucks (Regex) extrahiert, der Unicode-Wortzeichen übereinstimmt. Dies umfasst die meisten Zeichen, die Teil eines Worts in jeder Sprache sein können, sowie Zahlen und das Unterstrich-Zeichen:

import re

def tokenize(doc):
    """Extrahiert Tokens aus doc.

    Dies verwendet einen einfachen Regex, der Wortzeichen übereinstimmt, um Zeichenketten
    in Tokens aufzuteilen. Für einen prinzipielleren Ansatz siehe CountVectorizer oder
    TfidfVectorizer.
    """
    return (tok.lower() for tok in re.findall(r"\w+", doc))

Wir definieren eine zusätzliche Funktion, die die Anzahl der Vorkommen (Häufigkeit) jedes Tokens in einem gegebenen Dokument zählt. Sie gibt ein Häufigkeitswörterbuch zurück, das von den Vektorizern verwendet werden soll.

from collections import defaultdict

def token_freqs(doc):
    """Extrahiert ein Dict, das Tokens aus doc auf ihre Vorkommen abbildet."""

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

DictVectorizer

Wir werden den DictVectorizer benchmarken, der eine Methode ist, die Wörterbücher als Eingabe erhält.

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"done in {duration:.3f} s")
print(f"Found {len(vectorizer.get_feature_names_out())} unique terms")

FeatureHasher

Wir werden den FeatureHasher benchmarken, der eine Methode ist, die einen Vektor von vorgegebener Länge erstellt, indem eine Hash-Funktion auf die Merkmale (z.B. Tokens) angewendet wird, und dann die Hash-Werte direkt als Merkmalseindizes verwendet und der resultierende Vektor an diesen Indizes aktualisiert wird.

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"done in {duration:.3f} s")
print(f"Found {len(np.unique(X.nonzero()[1]))} unique tokens")

Vergleich mit speziellen Textvektorisierern

Wir werden die vorherigen Methoden mit dem CountVectorizer und HashingVectorizer vergleichen.

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

t0 = time()
vectorizer = CountVectorizer()
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
print(f"Found {len(vectorizer.get_feature_names_out())} unique terms")

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

t0 = time()
vectorizer = TfidfVectorizer()
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
print(f"Found {len(vectorizer.get_feature_names_out())} unique terms")

Zeichne die Ergebnisse

Wir werden die Geschwindigkeit der oben genannten Methoden für die Vektorisierung darstellen.

import matplotlib.pyplot as plt

dict_count_vectorizers = {
    "vectorizer": [
        "DictVectorizer\nauf nicht frequenten Wörterbüchern",
        "FeatureHasher\nauf nicht frequenten Wörterbüchern",
        "FeatureHasher\nauf rohen Tokens",
        "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("Geschwindigkeit (MB/s)")

Zusammenfassung

In diesem Lab haben wir die Textvektorisierung untersucht, indem wir zwei Methoden, FeatureHasher und DictVectorizer, und vier speziell auf Text angepasste Vektorisiermethoden, CountVectorizer, HashingVectorizer und TfidfVectorizer, verglichen. Wir haben die Methoden für die Vektorisierung benchmarkt und die Ergebnisse geplottet. Wir kamen zu dem Schluss, dass der HashingVectorizer besser als der CountVectorizer performt, allerdings auf Kosten der Umkehrbarkeit der Transformation aufgrund von Hash-Kollisionen. Darüber hinaus performen DictVectorizer und FeatureHasher besser als ihre textbasierten Entsprechungen bei manuell tokenisierten Dokumenten, da der interne Tokenisierungsschritt der ersteren Vektorisiermethoden eine reguläre Expression einmal kompiliert und dann für alle Dokumente wiederverwendet.