PyTorch torchtext

Obwohl das PyTorch-Ökosystem übertorchvisiondie Verarbeitung von Bilddaten,torchaudiodie Verarbeitung von Audiodaten verfügt, aber im Bereich der Textverarbeitung die offiziell bereitgestelltetorchtextBibliothek hat einige Änderungen erfahren. In diesem Abschnitt wird gezeigt, wie Textdatenvorverarbeitung, Vokabularaufbau, Datenladen und andere Operationen mit verschiedenen Methoden durchgeführt werden.

Hinweis: Die torchtext-Bibliothek wurde teilweise umgestaltet. Es wird empfohlen,torchtext.legacyzu verwenden oder eine eigene Textverarbeitungspipeline zu erstellen. Die neueste torchtext-Version ist zurück und bietet eine modernere API.


1. Grundlagen der Textdatenvorverarbeitung

Textvorverarbeitung ist der erste Schritt in NLP-Aufgaben, einschließlich Tokenisierung, Vokabularaufbau, Kodierung und anderer Operationen.

1.1 Grundlegende Textverarbeitungspipeline

Beispiel

import re
from collections import Counter

class SimpleTokenizer:
    """
Einfacher Tokenizer: Tokenisierung nach Leerzeichen und Interpunktion
    """

    def __init__(self):
        # Interpunktionszuordnung
        self.punctuation = str.maketrans('', '', '.,!?;:"\'-()[]{}')

    def tokenize(self, text):
        # In Kleinbuchstaben umwandeln
        text = text.lower()
        # Interpunktion entfernen
        text = text.translate(self.punctuation)
        # Tokenisieren
        tokens = text.split()
        return tokens


class Vocabulary:
    """
Wortschatzaufbau
    """

    def __init__(self, min_freq=2, max_size=10000):
        self.min_freq = min_freq
        self.max_size = max_size
        self.word2idx = {'<PAD>': 0, '<UNK>': 1}
        self.idx2word = {0: '<PAD>', 1: '<UNK>'}
        self.word_count = Counter()

    def build_vocab(self, texts):
        """Vokabular aus einer Liste von Texten aufbauen"""
        tokenizer = SimpleTokenizer()

        # Worthäufigkeiten zählen
        for text in texts:
            tokens = tokenizer.tokenize(text)
            self.word_count.update(tokens)

        # Vokabular erstellen
        for word, count in self.word_count.most_common(self.max_size):
            if count < self.min_freq:
                break
            if word not in self.word2idx:
                idx = len(self.word2idx)
                self.word2idx[word] = idx
                self.idx2word[idx] = word

        print(f"Vokabulargröße: {len(self.word2idx)}")

    def encode(self, text, max_len=50):
        """Kodiere Text als eine Folge von Indizes"""
        tokenizer = SimpleTokenizer()
        tokens = tokenizer.tokenize(text)[:max_len]

        # Kodieren
        indices = [
            self.word2idx.get(token, self.word2idx['<UNK>'])
            for token in tokens
        ]

        # Mit Nullen auffüllen
        if len(indices) < max_len:
            indices += [self.word2idx['<PAD>']] * (max_len - len(indices))

        return indices

    def decode(self, indices):
        """Dekodiere eine Sequenz von Indizes in Text"""
        tokens = [self.idx2word.get(idx, '<UNK>') for idx in indices]
        return ' '.join(tokens)


# Verwendungsbeispiel
texts = [
    "Hallo Welt",
    "Das ist ein Test",
    "PyTorch ist großartig für Deep Learning",
    "Die Verarbeitung natürlicher Sprache macht Spaß",
    "Deep Learning ermöglicht viele Anwendungen",
]

vocab = Vocabulary(min_freq=1, max_size=100)
vocab.build_vocab(texts)

# Kodieren
encoded = vocab.encode("Hallo Deep-Learning-Welt!", max_len=10)
print(f"Kodiertes Ergebnis: {encoded}")

# Dekodieren
decoded = vocab.decode(encoded)
print(f"Decodiertes Ergebnis: {decoded}")

2. Verwendung von torchtext (Legacy)

Wenn torchtext installiert ist, können Sie das Legacy-Modul für die Textverarbeitung verwenden.

2.1 Installation und Import

Beispiel

# torchtext installieren
# pip install torchtext

# Legacy-Modul importieren
try:
    import torchtext
    from torchtext.legacy import data
    from torchtext.legacy import datasets
    print(f"torchtext-Version: {torchtext.__version__}")
    TORCHTEXT_AVAILABLE = True
except ImportError:
    print("torchtext ist nicht installiert, benutzerdefinierte Implementierung wird verwendet")
    TORCHTEXT_AVAILABLE = False

# Oder die neue Version ausprobieren
try:
    from torchtext import transforms
    from torchtext.datasets import AG_NEWS
    print("Neue Version von torchtext ist verfügbar")
except ImportError:
    print("Neue Version von torchtext ist nicht verfügbar")

2.2 Field und Dataset

Beispiel

# torchtext.legacy verwenden
from torchtext.legacy import data
from torchtext.legacy import datasets
from torchtext.legacy.data import Field, TabularDataset, BucketIterator

# Felder definieren
TEXT = Field(
    tokenize='spacy',           # spacy zur Tokenisierung verwenden
    tokenizer_language='en_core_web_sm',
    lower=True,                 # In Kleinbuchstaben umwandeln
    include_lengths=True,       # Sequenzlänge zurückgeben
    batch_first=True            # Batch-Dimension zuerst
)

LABEL = Field(
    sequential=False,
    use_vocab=False,
    dtype=torch.long
)

# Dataset definieren
# Von CSV-Dateiformat ausgehen: label,text
# 1,Das ist eine positive Bewertung
# 0,Dies ist eine negative Bewertung

# Oder einen integrierten Datensatz verwenden (z. B. IMDB)
# train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)

print("Field- und Dataset-Konfiguration abgeschlossen")

2.3 Vokabularaufbau und Iteratoren

Beispiel

# Vokabular erstellen
# TEXT.build_vocab(train_data, vectors="glove.6B.100d", max_size=10000)

# Iterator erstellen
# train_iterator, test_iterator = BucketIterator.splits(
# (train_data, test_data),
# batch_size=32,
# sort_within_batch=True,
# device=torch.device('cuda')
# )

# Training iterieren
# for batch in train_iterator:
#     text, lengths = batch.text
#     labels = batch.label
# # Trainingscode

print("Vokabular- und Iterator-Konfiguration abgeschlossen")

3. Benutzerdefinierte NLP-Datenpipeline

Es wird empfohlen, einen flexibleren benutzerdefinierten Ansatz zur Datenverarbeitung zu verwenden, der nicht von torchtext abhängt.

3.1 Implementierung der Dataset-Klasse

Beispiel

import torch
from torch.utils.data import Dataset, DataLoader
from collections import Counter
import re

class TextDataset(Dataset):
    """
Textdatensatz
    """

    def __init__(self, texts, labels, vocab=None, max_len=128, min_freq=2):
        self.texts = texts
        self.labels = labels
        self.max_len = max_len

        # Vokabular erstellen oder vorhandenes verwenden
        if vocab is None:
            self.vocab = self._build_vocab(texts, min_freq)
        else:
            self.vocab = vocab

    def _build_vocab(self, texts, min_freq):
        """Vokabular aufbauen"""
        word_counts = Counter()

        for text in texts:
            tokens = self._tokenize(text)
            word_counts.update(tokens)

        # Vokabular erstellen
        word2idx = {'<PAD>': 0, '<UNK>': 1}
        for word, count in word_counts.items():
            if count >= min_freq:
                word2idx[word] = len(word2idx)

        return word2idx

    def _tokenize(self, text):
        """Einfache Tokenisierung"""
        # In Kleinbuchstaben umwandeln
        text = text.lower()
        # Sonderzeichen entfernen, alphanumerische Zeichen und Leerzeichen beibehalten
        text = re.sub(r'[^a-z0-9\s]', ' ', text)
        # Tokenisieren
        tokens = text.split()
        return tokens

    def _encode(self, text):
        """Text kodieren"""
        tokens = self._tokenize(text)[:self.max_len]
        indices = [
            self.vocab.get(token, self.vocab['<UNK>'])
            for token in tokens
        ]

        # Mit Nullen auffüllen
        if len(indices) < self.max_len:
            indices += [self.vocab['<PAD>']] * (self.max_len - len(indices))

        return indices

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        text = self.texts[idx]
        label = self.labels[idx]

        encoded = self._encode(text)
        return torch.tensor(encoded, dtype=torch.long), torch.tensor(label, dtype=torch.long)


# Verwendungsbeispiel
texts = [
    "Das ist ein großartiger Film",
    "Ich habe diesen Film gehasst",
    "Großartige Leistung",
    "Schreckliche Schauspielerei",
    "Sehr empfehlenswert",
]

labels = [1, 0, 1, 0, 1]

dataset = TextDataset(texts, labels, max_len=10)
print(f"Datensatzgröße: {len(dataset)}")
print(f"Vokabulargröße: {len(dataset.vocab)}")

# Ein Beispiel abrufen
text, label = dataset[0]
print(f"Textkodierung: {text[:5]}...")
print(f"Label: {label}")

3.2 Fortgeschrittene Tokenizer

Beispiel

# spacy für fortgeschrittene Tokenisierung verwenden
def tokenize_with_spacy(text):
    """Mit spacy tokenisieren"""
    try:
        import spacy
        nlp = spacy.load("en_core_web_sm")
        doc = nlp(text)
        return [token.text for token in doc]
    except ImportError:
        print("spacy ist nicht installiert, einfache Tokenisierung wird verwendet")
        return text.lower().split()


# nltk für Tokenisierung und Stemming verwenden
def tokenize_with_nltk(text):
    """Mit nltk tokenisieren"""
    try:
        import nltk
        from nltk.tokenize import word_tokenize
        from nltk.stem import PorterStemmer

        # Tokenisieren
        tokens = word_tokenize(text.lower())

        # Optional: Stemming
        stemmer = PorterStemmer()
        tokens = [stemmer.stem(token) for token in tokens if token.isalnum()]

        return tokens
    except ImportError:
        return text.lower().split()


# SentencePiece für Subword-Tokenisierung verwenden
class SentencePieceTokenizer:
    """
SentencePiece für Subword-Tokenisierung verwenden
    """

    def __init__(self, model_path=None):
        self.model_path = model_path
        self.sp = None

    def train(self, texts, vocab_size=10000):
        """SentencePiece-Modell trainieren"""
        try:
            import sentencepiece as spm
            import tempfile

            # In eine temporäre Datei schreiben
            with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
                for text in texts:
                    f.write(text + '\n')
                temp_file = f.name

            # Trainieren
            spm.SentencePieceTrainer.train(
                input=temp_file,
                model_prefix='spm_model',
                vocab_size=vocab_size,
                character_coverage=1.0,
                model_type='unigram',
            )

            self.sp = spm.SentencePieceProcessor()
            self.sp.load('spm_model.model')

        except ImportError:
            print("sentencepiece ist nicht installiert")

    def encode(self, text):
        if self.sp:
            return self.sp.encode(text, out_type=str)
        return text.split()

    def decode(self, ids):
        if self.sp:
            return self.sp.decode(ids)
        return ' '.join(ids)

3.3 Vollständiger Data Loader

Beispiel

import torch
from torch.utils.data import Dataset, DataLoader
from collections import Counter

class NLPDataset(Dataset):
    """
Vollständige NLP-Dataset-Klasse
Unterstützt Sequenzen variabler Länge, Vokabularaufbau und Batch-Padding
    """

    def __init__(self, texts, labels, min_freq=2, max_vocab=30000):
        self.texts = texts
        self.labels = labels
        self.min_freq = min_freq

        # Vokabular erstellen
        self.word2idx, self.idx2word = self._build_vocab(texts, max_vocab)
        self.pad_idx = self.word2idx['<PAD>']
        self.unk_idx = self.word2idx['<UNK>']

    def _tokenize(self, text):
        text = text.lower()
        text = re.sub(r'[^a-z0-9\s]', ' ', text)
        return text.split()

    def _build_vocab(self, texts, max_vocab):
        """Vokabular aufbauen"""
        counter = Counter()
        for text in texts:
            tokens = self._tokenize(text)
            counter.update(tokens)

        # Vokabular erstellen
        word2idx = {'<PAD>': 0, '<UNK>': 1}
        idx2word = {0: '<PAD>', 1: '<UNK>'}

        for word, count in counter.most_common(max_vocab):
            if count >= self.min_freq and word not in word2idx:
                idx = len(word2idx)
                word2idx[word] = idx
                idx2word[idx] = word

        return word2idx, idx2word

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        text = self.texts[idx]
        tokens = self._tokenize(text)
        indices = [self.word2idx.get(t, self.unk_idx) for t in tokens]

        return {
            'input': indices,
            'label': self.labels[idx],
            'length': len(indices)
        }


def collate_fn(batch, pad_idx=0):
    """
Benutzerdefinierte Collate-Funktion: Umgang mit Sequenzen variabler Länge
    """

    # Nach Länge in absteigender Reihenfolge sortieren
    batch.sort(key=lambda x: x['length'], reverse=True)

    texts = [item['input'] for item in batch]
    labels = [item['label'] for item in batch]
    lengths = [item['length'] for item in batch]

    # Auf dieselbe Länge auffüllen
    max_len = max(lengths)
    padded = [text + [pad_idx] * (max_len - len(text)) for text in texts]

    return {
        'input': torch.tensor(padded, dtype=torch.long),
        'labels': torch.tensor(labels, dtype=torch.long),
        'lengths': torch.tensor(lengths, dtype=torch.long)
    }


# DataLoader verwenden
def create_dataloader(texts, labels, batch_size=32, shuffle=True):
    """Datenlader erstellen"""
    dataset = NLPDataset(texts, labels)
    pad_idx = dataset.pad_idx

    dataloader = DataLoader(
        dataset,
        batch_size=batch_size,
        shuffle=shuffle,
        collate_fn=lambda b: collate_fn(b, pad_idx)
    )

    return dataloader, dataset


# Daten simulieren
texts = [
    "Ich liebe diesen Film",
    "Das ist ein schlechter Film",
    "Toller Film",
    "Schreckliche Schauspielerei",
    "Ich empfehle das",
    "Nicht sehenswert",
]

labels = [1, 0, 1, 0, 1, 0]

dataloader, dataset = create_dataloader(texts, labels, batch_size=2)

for batch in dataloader:
    print("Eingabeform:", batch['input'].shape)
    print("Etiketten:", batch['labels'])
    print("Längen:", batch['lengths'])
    print("---")

4. Laden von vortrainierten Wortvektoren

Die Verwendung von vortrainierten Wortvektoren kann die Modellleistung verbessern.

4.1 GloVe-Wortvektoren

Beispiel

import torch
import numpy as np

def load_glove_vectors(filepath, word2idx, embedding_dim=300):
    """
GloVe-vortrainierte Wortvektoren laden

Parameter:
filepath: GloVe-Dateipfad
word2idx: Vokabelwörterbuch
embedding_dim: Dimension des Wortvektors
    """

    print("Lade GloVe-Wortvektoren...")

    # Embedding-Matrix initialisieren
    num_words = len(word2idx)
    embeddings = np.random.randn(num_words, embedding_dim).astype(np.float32)
    embeddings[word2idx['<PAD>']] = np.zeros(embedding_dim)  # PAD-Vektor auf null setzen

    words_loaded = 0

    with open(filepath, 'r', encoding='utf-8') as f:
        for line in f:
            values = line.strip().split()
            word = values[0]

            if word in word2idx:
                idx = word2idx[word]
                vector = np.asarray(values[1:], dtype=np.float32)
                if len(vector) == embedding_dim:
                    embeddings[idx] = vector
                    words_loaded += 1

    print(f"Geladen {words_loaded}/{num_words} Wortvektoren")

    return torch.from_numpy(embeddings)


# Simuliertes Laden
def create_pretrained_embedding(word2idx, embedding_dim=300, pretrained_path=Keine):
    """
Vortrainierte Embedding-Schicht erstellen
    """

    if pretrained_path and False:  # Auf True setzen und einen gültigen Pfad angeben
        weights = load_glove_vectors(pretrained_path, word2idx, embedding_dim)
    else:
        # Zufällige Initialisierung verwenden
        num_words = len(word2idx)
        weights = torch.randn(num_words, embedding_dim) * 0.1

    embedding = torch.nn.Embedding.from_pretrained(weights, padding_idx=0)
    return embedding


# Beispiel
word2idx = {'<PAD>': 0, '<UNK>': 1, 'hello': 2, 'world': 3, 'test': 4}
embedding = create_pretrained_embedding(word2idx, embedding_dim=100)

print(f"Form der Embedding-Schicht: {embedding.weight.shape}")

4.2 Word2Vec mit gensim laden

Beispiel

def load_word2vec(word2idx, model_path=None):
    """
Word2Vec mit gensim laden
    """

    try:
        from gensim.models import KeyedVectors

        # Modell laden
        # model = KeyedVectors.load_word2vec_format(model_path, binary=True)

        # Einbettungsmatrix erstellen
        embedding_dim = 300
        num_words = len(word2idx)
        embeddings = np.random.randn(num_words, embedding_dim).astype(np.float32)

        # Wortvektoren eintragen
        embeddings[word2idx['<PAD>']] = np.zeros(embedding_dim)

        # Wortvektoren laden
        # for word, idx in word2idx.items():
        # if word in model:
        # embeddings[idx] = model[word]

        return torch.from_numpy(embeddings)

    except ImportError:
        print("gensim ist nicht installiert")
        return None

4.3 Benutzerdefinierte vortrainierte Embeddings

Beispiel

import torch
import torch.nn as nn

class PretrainedEmbedding(nn.Module):
    """
Embedding-Schicht, die das Laden vortrainierter Wortvektoren unterstützt
    """

    def __init__(self, vocab_size, embed_dim, pretrained_weights=Keine,
                 padding_idx=0, freeze=False):
        super().__init__()

        self.embedding = nn.Embedding(
            vocab_size,
            embed_dim,
            padding_idx=padding_idx
        )

        # Vortrainierte Gewichte laden
        if pretrained_weights is not None:
            self.embedding.weight.data.copy_(pretrained_weights)

        # Ob eingefroren werden soll
        if freeze:
            self.embedding.weight.requires_grad = False

    def forward(self, x):
        return self.embedding(x)


# Verwendungsbeispiel
vocab_size = 10000
embed_dim = 300
pretrained = torch.randn(vocab_size, embed_dim) * 0.1

embedding_layer = PretrainedEmbedding(
    vocab_size,
    embed_dim,
    pretrained_weights=pretrained,
    padding_idx=0,
    freeze=False  # Auf True setzen, um die Embedding-Schicht einzufrieren
)

# Test
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
output = embedding_layer(x)
print(f"Form der Eingabe: {x.shape}")
print(f"Ausgabeform: {output.shape}")

5. Textdaten-Augmentierung

Daten-Augmentierung kann die Generalisierungsfähigkeit des Modells verbessern.

5.1 Back-Translation-Augmentierung

Beispiel

# Back-Translation-Augmentierung erfordert eine Übersetzungs-API; das Folgende ist ein konzeptionelles Beispiel

def back_translation_augment(text, translator):
    """
Back-Translation-Augmentierung: Text in eine andere Sprache übersetzen und dann zurückübersetzen
    """

    # In die Zielsprache übersetzen
    translated = translator.translate(text, dest='fr')
    # Zurück in die Ausgangssprache übersetzen
    back_translated = translator.translate(translated.text, dest='en')
    return back_translated.text

# Verwendungsbeispiel
# from googletrans import Translator
# translator = Translator()
# augmented_text = back_translation_augment("Ich liebe diesen Film", translator)

5.2 Synonym-Ersetzung

Beispiel

import random

def synonym_replacement(text, n=1, stop_words=None):
    """
Synonymersetzung
    """

    if stop_words is None:
        stop_words = {'a', 'an', 'the', 'is', 'are', 'was', 'were'}

    words = text.lower().split()
    replaceable = [i for i, w in enumerate(words) if w not in stop_words]

    if not replaceable:
        return text

    n = min(n, len(replaceable))
    replace_idx = random.sample(replaceable, n)

    # Vereinfachte Synonymzuordnung (sollte eigentlich WordNet verwenden)
    synonym_map = {
        'good': ['great', 'excellent', 'nice'],
        'bad': ['poor', 'terrible', 'awful'],
        'Film': ['Film', 'Kino'],
        'liebte': ['verehrte', 'genoss'],
    }

    for idx in replace_idx:
        word = words[idx]
        if word in synonym_map:
            words[idx] = random.choice(synonym_map[word])

    return ' '.join(words)


# Verwendungsbeispiel
text = "Ich liebte diesen guten Film"
augmented = synonym_replacement(text, n=2)
print(f"Ursprünglicher Satz: {text}")
print(f"Augmentiert: {augmented}")

5.3 Zufälliges Einfügen und Löschen

Beispiel

import random

def random_insertion(text, n=1):
    """
Zufälliges Einfügen: Wörter zufällig in den Text einfügen
    """

    words = text.lower().split()
    for _ in range(n):
        if len(words) > 1:
            idx = random.randint(0, len(words) - 1)
            # Vereinfachte eingefügte Wörter
            insert_words = ['really', 'very', 'quite', 'actually']
            words.insert(idx, random.choice(insert_words))
    return ' '.join(words)


def random_deletion(text, p=0.1):
    """
Zufälliges Löschen: Wörter mit Wahrscheinlichkeit p löschen
    """

    words = text.lower().split()
    if len(words) == 1:
        return text

    remaining = [w for w in words if random.random() > p]
    if len(remaining) == 0:
        return random.choice(words)

    return ' '.join(remaining)


def random_swap(text, n=1):
    """
Zufälliger Tausch: zufällig die Positionen zweier Wörter vertauschen
    """

    words = text.lower().split()
    if len(words) < 2:
        return text

    for _ in range(n):
        idx1, idx2 = random.sample(range(len(words)), 2)
        words[idx1], words[idx2] = words[idx2], words[idx1]

    return ' '.join(words)


# Verwendungsbeispiel
text = "Das ist ein großartiger Film über Liebe und Glück"

print("Original:", text)
print("Eingefügt:", random_insertion(text, n=2))
print("Gelöscht:", random_deletion(text, p=0.2))
print("Vertauscht:", random_swap(text, n=2))

6. Gängige Beispiele für NLP-Aufgaben

6.1 Vollständige Textklassifikations-Pipeline

Beispiel

import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader

# 1. Datenvorbereitung
texts = [
    "Ich liebe dieses Produkt, es ist fantastisch!",
    "Schreckliche Qualität, Geldverschwendung.",
    "Tolles Preis-Leistungs-Verhältnis.",
    "Nicht zufrieden mit dem Kauf.",
    "Bester Kauf, den ich je gemacht habe!",
    "Sehr enttäuscht von diesem Artikel.",
]

labels = [1, 0, 1, 0, 1, 0]  # 1: positiv, 0: negativ

# 2. Datensatz
class TextClassificationDataset(Dataset):
    def __init__(self, texts, labels, max_len=50):
        self.texts = texts
        self.labels = labels
        self.max_len = max_len
        self.vocab = self._build_vocab(texts)

    def _build_vocab(self, texts):
        vocab = {'<PAD>': 0, '<UNK>': 1}
        for text in texts:
            for word in text.lower().split():
                if word not in vocab:
                    vocab[word] = len(vocab)
        return vocab

    def __len__(self):
        return len(self.texts)

    def __getitem__(self, idx):
        text = self.texts[idx]
        label = self.labels[idx]

        # Einfache Kodierung
        tokens = text.lower().split()[:self.max_len]
        indices = [self.vocab.get(t, 1) for t in tokens]

        # Auffüllen
        if len(indices) < self.max_len:
            indices += [0] * (self.max_len - len(indices))

        return torch.tensor(indices, dtype=torch.long), torch.tensor(label, dtype=torch.long)

# 3. Modell
class TextClassifier(nn.Module):
    def __init__(self, vocab_size, embed_dim=128, hidden_dim=64, num_classes=2):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
        self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, num_classes)

    def forward(self, x):
        embedded = self.embedding(x)
        _, (hidden, _) = self.lstm(embedded)
        output = self.fc(hidden.squeeze(0))
        return output

# 4. Training
dataset = TextClassificationDataset(texts, labels)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)

model = TextClassifier(vocab_size=len(dataset.vocab))
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

# Trainiere für ein paar Epochen
model.train()
for epoch in range(10):
    total_loss = 0
    for texts_batch, labels_batch in dataloader:
        optimizer.zero_grad()
        outputs = model(texts_batch)
        loss = criterion(outputs, labels_batch)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()

    print(f"Epoche {epoch+1}, Verlust: {total_loss/len(dataloader):.4f}")

print("Training abgeschlossen!")

6.2 Beispiel für Sequenzkennzeichnung (NER)

Beispiel

import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader

# Datensatz für Sequenzkennzeichnung
class NERDataset(Dataset):
    """
Datensatz zur Erkennung benannter Entitäten
Format: [(word, tag), ...]
    """

    def __init__(self, sentences_tags, word2idx, tag2idx, max_len=50):
        self.sentences_tags = sentences_tags
        self.word2idx = word2idx
        self.tag2idx = tag2idx
        self.max_len = max_len

    def __len__(self):
        return len(self.sentences_tags)

    def __getitem__(self, idx):
        sentence_tags = self.sentences_tags[idx]
        words = [wt[0] for wt in sentence_tags]
        tags = [wt[1] for wt in sentence_tags]

        # Kodierung
        word_ids = [self.word2idx.get(w.lower(), 1) for w in words[:self.max_len]]
        tag_ids = [self.tag2idx[t] for t in tags[:self.max_len]]

        # Auffüllen
        if len(word_ids) < self.max_len:
            word_ids += [0] * (self.max_len - len(word_ids))
            tag_ids += [0] * (self.max_len - len(tag_ids))

        return {
            'words': torch.tensor(word_ids, dtype=torch.long),
            'tags': torch.tensor(tag_ids, dtype=torch.long)
        }

# NER-Modell
class NERModel(nn.Module):
    def __init__(self, vocab_size, tag_size, embed_dim=128, hidden_dim=256):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
        self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True, bidirectional=True)
        self.fc = nn.Linear(hidden_dim * 2, tag_size)

    def forward(self, x):
        embedded = self.embedding(x)
        lstm_out, _ = self.lstm(embedded)
        logits = self.fc(lstm_out)
        return logits


# Beispieldaten
data = [
    [("John", "B-PER"), ("lebt", "O"), ("in", "O"), ("New", "B-LOC"), ("York", "I-LOC"), (".", "O")],
    [("Apple", "B-ORG"), ("ist", "O"), ("a", "O"), ("Unternehmen", "O"), (".", "O")],
]

# Wortvokabular und Tag-Tabelle erstellen
word2idx = {'<PAD>': 0, '<UNK>': 1}
tag2idx = {'O': 0, 'B-PER': 1, 'I-PER': 2, 'B-LOC': 3, 'I-LOC': 4, 'B-ORG': 5, 'I-ORG': 6}

for sent in data:
    for word, tag in sent:
        if word.lower() not in word2idx:
            word2idx[word.lower()] = len(word2idx)

print(f"Vokabulargröße: {len(word2idx)}")
print(f"Anzahl der Tags: {len(tag2idx)}")

7. Empfohlene Alternativen

7.1 Andere Textverarbeitungsbibliotheken

Bibliotheksname Funktionen Anwendbare Szenarien
HuggingFace Datasets Datenladen und -verarbeitung Allgemeine NLP-Aufgaben
spacy Fortgeschrittene NLP-Werkzeuge Tokenisierung, NER, Dependency-Parsing
NLTK Klassische NLP-Werkzeuge Lehre, Prototyping
textblob Einfach und benutzerfreundlich Schnelle Textverarbeitung

7.2 Verwenden von HuggingFace Datasets

Beispiel

# Verwenden Sie die HuggingFace Datasets-Bibliothek
# pip install datasets

from datasets import load_dataset

# Datensatz laden
# dataset = load_dataset("imdb")
# dataset = load_dataset("squad")

# Datenvorverarbeitung
# def preprocess_function(examples):
# return tokenizer(examples['text'], truncation=True, padding='max_length')

# tokenized_dataset = dataset.map(preprocess_function, batched=True)

print("HuggingFace Datasets Verwendungsbeispiel:")
print("from datasets import load_dataset")
print("dataset = load_dataset('imdb')")

8. API-Kurzreferenz

8.1 Häufige Textverarbeitungsoperationen

Aktion Methode
Tokenisierung text.split(), spacy, nltk, jieba
Wortschatzaufbau Counter, vocab.build_vocab()
Kodierung vocab.encode(), tokenizer.encode()
Dekodierung vocab.decode(), tokenizer.decode()
Innenabstand pad_sequence, collate_fn
Wortvektoren laden Gensim, GloVe direktes Laden

8.2 Methoden zur Daten-Augmentierung

Methode Beschreibung
Synonymersetzung Wörter zufällig durch Synonyme ersetzen
Zufälliges Einfügen Wörter zufällig einfügen
Zufälliges Löschen Wörter zufällig löschen
Zufälliges Vertauschen Wortpositionen zufällig vertauschen
Rückübersetzung Übersetzen und dann zurückübersetzen

8.3 Empfohlene Datenverarbeitungs-Pipeline

1. 数据清洗
   - 去除 HTML 标签、特殊字符
   - 统一编码、大小写

2. 分词
   - 英文: spaCy / NLTK
   - 中文: jieba / pkuseg

3. 词表构建
   - 过滤低频词
   - 设定最大词表大小

4. 序列化
   - 编码为索引
   - 统一长度(填充/截断)

5. 数据增强(可选)
   - 同义词替换、回译

6. 批量加载
   - DataLoader + 自定义 collate_fn
Weitere Erweiterungen