Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Deep Learning für Named Entity Recognition: BLSTM mit GloVe & CNN (CSCI544 HW4 Tutorial)

Lerne, wie du mit PyTorch ein bidirektionales LSTM für NER auf dem CoNLL-2003 Korpus baust, GloVe Embeddings integrierst und mit einem CNN-Modul Charakter-Level-Informationen nutzt – inklusive Hyperparameter-Tuning und Evaluierung.

Named Entity Recognition Tutorial BLSTM NER PyTorch GloVe Embeddings NER CoNLL-2003 NER CSCI544 Homework 4 Lösung bidirektionales LSTM NER NER mit CNN Zeichenebene Deep Learning NER Deutsch PyTorch NER Modell GloVe vs Embedding NER NER Hyperparameter Tuning F1 Score NER verbessern NER für Chatbots NER in der Praxis Sequenzlabeling mit LSTM NER mit vortrainierten Embeddings

Deep Learning für Named Entity Recognition: Ein praxisnahes Tutorial

Named Entity Recognition (NER) ist eine zentrale Aufgabe der Computerlinguistik – sie extrahiert Personen, Orte, Organisationen und andere Entitäten aus Text. In diesem Tutorial zeige ich dir Schritt für Schritt, wie du ein neuronales Netzwerk für NER auf dem CoNLL-2003 Korpus baust. Das Vorgehen orientiert sich an typischen Aufgaben aus Hochschulkursen wie CSCI544. Der Fokus liegt auf einem bidirektionalen LSTM (BLSTM), der Integration von GloVe-Embeddings und einem optionalen CNN-Modul für Zeichenebene. Du erhältst eine klare Anleitung, die du direkt in PyTorch umsetzen kannst.

Warum NER? Ein aktuelles Beispiel

Stell dir vor, du entwickelst einen Chatbot für eine Banking-App, der Kundenanfragen versteht. Wenn ein Kunde schreibt: „Ich möchte meine Überweisung an die XYZ Bank stornieren“, muss der Bot „XYZ Bank“ als Organisation erkennen – genau das leistet NER. Oder in sozialen Medien: Ein Tool, das automatisch Erwähnungen von Spitzensportlern wie „Lena Oberdorf“ oder „LeBron James“ markiert. NER ist die Basis für viele KI-Anwendungen.

Datenformat und Vorbereitung

Der CoNLL-2003 Datensatz liegt im typischen Format vor: Jede Zeile enthält Wortindex, Wortform und NER-Tag (z. B. B-PER, I-LOC). Leere Zeilen trennen Sätze. Für das Training verwendest du die Dateien train und dev. Die Testdaten enthalten nur Rohsätze. Ein wichtiger Schritt: Du musst die Wörter indizieren und die Tags in numerische Labels umwandeln. Nutze dafür Python-Dictionaries. Achte auf Groß-/Kleinschreibung – sie ist für NER entscheidend.

Daten laden und aufbereiten

def load_data(filepath):
    sentences, tags = [], []
    with open(filepath, 'r', encoding='utf-8') as f:
        words, labels = [], []
        for line in f:
            if line.strip() == '':
                if words:
                    sentences.append(words)
                    tags.append(labels)
                    words, labels = [], []
            else:
                idx, word, tag = line.strip().split()
                words.append(word)
                labels.append(tag)
    return sentences, tags

Aufgabe 1: Einfaches bidirektionales LSTM (BLSTM)

Das Grundmodell besteht aus: Embedding-Schicht → BLSTM → Lineare Schicht → ELU → Klassifikator. Die Embedding-Dimension ist 100, die BLSTM-Hidden-Dimension 256, Dropout 0.33 und die lineare Ausgabedimension 128. Verwende SGD als Optimierer und stimme Batchgröße, Lernrate und Lernratenplanung ab. Ein guter F1-Wert auf dem Dev-Set liegt bei etwa 77 %.

Modellarchitektur in PyTorch

class BLSTMNER(nn.Module):
    def __init__(self, vocab_size, tagset_size, embedding_dim=100, hidden_dim=256, dropout=0.33):
        super().__init__()
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim, hidden_dim, bidirectional=True, batch_first=True, dropout=dropout)
        self.linear = nn.Linear(hidden_dim*2, 128)
        self.elu = nn.ELU()
        self.classifier = nn.Linear(128, tagset_size)

    def forward(self, x):
        emb = self.embeddings(x)
        lstm_out, _ = self.lstm(emb)
        linear_out = self.elu(self.linear(lstm_out))
        logits = self.classifier(linear_out)
        return logits

Training und Evaluierung

Wähle eine Batchgröße von 32 oder 64. Starte mit einer Lernrate von 0.01 und reduziere sie per StepLR alle 5 Epochen um den Faktor 0.5. Trainiere ca. 20 Epochen. Berechne Precision, Recall und F1 mit der conll03eval.pl-Datei. Exportiere die Vorhersagen im Format: idx word gold pred.

Aufgabe 2: GloVe-Embeddings integrieren

GloVe (Global Vectors for Word Representation) liefert vortrainierte Wortvektoren, die semantische Ähnlichkeiten abbilden. Lade die Datei glove.6B.100d.gz und erstelle ein Embedding-Wörterbuch. Problem: GloVe ist case-insensitiv, NER benötigt aber Groß-/Kleinschreibung. Lösung: Initialisiere die Embedding-Schicht mit GloVe-Vektoren für kleingeschriebene Wörter, lasse sie aber im Modell weiterlernen – so kann das Modell die Großschreibung als Feature nutzen. Erwarteter F1: ca. 88 %.

GloVe einlesen und Embedding-Matrix erstellen

def load_glove(filepath, word2idx, embedding_dim=100):
    embeddings = np.random.uniform(-0.25, 0.25, (len(word2idx), embedding_dim))
    with gzip.open(filepath, 'rt', encoding='utf-8') as f:
        for line in f:
            parts = line.strip().split()
            word = parts[0].lower()
            if word in word2idx:
                vec = np.array(parts[1:], dtype=np.float32)
                embeddings[word2idx[word]] = vec
    return torch.tensor(embeddings, dtype=torch.float32)

Bonus: LSTM-CNN-Modell für Zeichenebene

Um Zeicheninformationen wie Präfixe oder Suffixe zu nutzen, erweiterst du das BLSTM um ein CNN. Definiere eine Zeichen-Embedding-Dimension von 30, einen oder zwei CNN-Layer mit Kernelgröße 3 und Ausgabedimensionen wie 50 oder 100. Das CNN verarbeitet die Zeichen eines Wortes und erzeugt einen Zeichenvektor, der mit dem Wort-Embedding konkateniert wird. So erfasst das Modell Rechtschreibmuster – nützlich für unbekannte Wörter. Der F1 auf dem Testset kann dann über 90 % liegen.

CNN-Modul implementieren

class CharCNN(nn.Module):
    def __init__(self, char_vocab_size, char_emb_dim=30, char_hidden_dim=50):
        super().__init__()
        self.char_embeddings = nn.Embedding(char_vocab_size, char_emb_dim)
        self.conv = nn.Conv1d(char_emb_dim, char_hidden_dim, kernel_size=3, padding=1)
        self.relu = nn.ReLU()
        self.pool = nn.AdaptiveMaxPool1d(1)

    def forward(self, x):
        # x: (batch, word_len)
        emb = self.char_embeddings(x)  # (batch, word_len, char_emb_dim)
        emb = emb.permute(0, 2, 1)     # (batch, char_emb_dim, word_len)
        conv = self.relu(self.conv(emb))  # (batch, char_hidden_dim, word_len)
        pooled = self.pool(conv).squeeze(2)  # (batch, char_hidden_dim)
        return pooled

Hyperparameter-Tuning und Evaluierung

Neben den Vorgaben kannst du folgende Parameter anpassen: Batchgröße (16, 32, 64), Lernrate (0.01, 0.005, 0.001), Lernratenplanung (StepLR, ReduceLROnPlateau), Optimierer (SGD mit Momentum, Adam). Für das Bonus-CNN: Anzahl der Conv1d-Layer (1 oder 2), Kernelgröße (3, 5), Ausgabedimensionen (50, 100). Nutze das Dev-Set zur Validierung und dokumentiere alle Einstellungen im README.

Häufige Fehler und Lösungen

  • Fehlerhafte Datenindizierung: Achte darauf, dass die Wortindizes konsistent sind und unbekannte Wörter einen speziellen Token (z. B. <UNK>) erhalten.
  • Padding von Batches: Verwende pad_sequence mit batch_first=True und setze ignore_index im Loss.
  • GloVe-Konflikt: Initialisiere die Embedding-Matrix mit GloVe-Vektoren für kleingeschriebene Wörter und trainiere sie weiter – das Modell lernt die Großschreibung implizit.
  • Evaluierung: Nutze das offizielle Perl-Skript. Achte auf das exakte Format: Leerzeichen zwischen Spalten, keine zusätzlichen Leerzeichen am Zeilenende.

Zusammenfassung und Ausblick

Du hast nun ein solides Fundament für NER mit Deep Learning. Das BLSTM-Modell mit GloVe-Embeddings und optionalem CNN-Zeichenmodul ist State-of-the-Art für viele Sequenzlabeling-Aufgaben. Die Techniken lassen sich auf andere Bereiche übertragen, z. B. POS-Tagging, Chunking oder sogar die Erkennung von KI-generierten Texten. Experimentiere mit weiteren Architekturen wie Transformer-basierten Modellen (BERT) – sie liefern oft noch bessere Ergebnisse. Viel Erfolg bei deinem Projekt!