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
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
# 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
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
# 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
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
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
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 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
"""
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.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
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
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
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.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.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
# 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_fnWeitere Erweiterungen