--- abstract: | Dieses Lehr- und Lernmaterial dient der didaktischen Exploration computerlinguistischer Verfahren auf der Grundlage der acht Transkripte von Verkaufsgesprächen. Im Unterschied zu den vorangegangenen ARS-Versionen 2.0 und 3.0, die auf interpretativ gebildeten Terminalzeichen basierten, wird hier der Schritt in Richtung automatischer Sprachverarbeitung vollzogen. Die Verfahren werden zu Demonstrationszwecken auf augmentierten Daten trainiert, um ihre Funktionsweise transparent zu machen. Der Fokus liegt auf dem didaktischen Erkenntnisgewinn, nicht auf empirischer Validität. Die Szenarien C (Computerlinguistische Integration) und D (Hybride Modellierung) werden schrittweise entwickelt und miteinander verglichen. author: - Paul Koop date: Lehr- und Lernmaterial 2026 title: | **Zwischen Interpretation und Berechnung**\ Didaktische Exploration computerlinguistischer Verfahren\ mit augmentierten Transkripten von Verkaufsgesprächen --- # Einleitung: Didaktische Ziele und methodologische Reflexion Die vorangegangenen Versionen der Algorithmisch Rekursiven Sequenzanalyse (ARS 2.0 und 3.0) haben gezeigt, wie aus interpretativ gewonnenen Terminalzeichenketten formale Grammatiken induziert werden können. Diese Verfahren bleiben methodologisch kontrolliert: Die Kategorienbildung erfolgt durch qualitative Interpretation, die formalen Modelle explizieren lediglich die beobachtbaren Regularitäten. Die nun folgenden Szenarien C und D wagen einen Schritt über diese methodologische Grenze hinaus. Sie explorieren, wie computerlinguistische Verfahren -- insbesondere neuronale Netze, Word Embeddings und Topic Models -- auf die acht Transkripte angewendet werden könnten, wenn man sie zu Demonstrationszwecken augmentiert. **Dieses Dokument ist als Lehr- und Lernmaterial konzipiert.** Es verfolgt folgende didaktische Ziele: 1. **Verständnis neuronaler Architekturen**: Wie funktionieren Transformer, LSTM-Netze und Attention-Mechanismen auf Sequenzdaten? 2. **Data Augmentation als Technik**: Wie kann man mit kleinen Datensätzen umgehen, um die Funktionsweise von Verfahren zu demonstrieren? 3. **Vergleich verschiedener Modellierungsebenen**: Welche Unterschiede bestehen zwischen rein computerlinguistischen (C) und hybriden (D) Ansätzen? 4. **Methodologische Reflexion**: Wo liegen die Grenzen automatischer Verfahren im Vergleich zur interpretativen Kategorienbildung? Alle hier vorgestellten Implementierungen arbeiten mit augmentierten Daten -- die acht Originaltranskripte wurden künstlich vervielfacht, um das Training neuronaler Netze zu ermöglichen. Die Ergebnisse sind daher nicht empirisch valide, sondern dienen ausschließlich der didaktischen Veranschaulichung. # Die acht Transkripte: Rohdaten und Terminalzeichen ## Die Rohdaten Die folgenden acht Transkripte dokumentieren Verkaufsgespräche auf dem Aachener Marktplatz im Juni/Juli 1994. Sie bilden die empirische Grundlage aller folgenden Analysen. ### Transkript 1 - Metzgerei **Datum:** 28. Juni 1994, **Ort:** Metzgerei, Aachen, 11:00 Uhr ``` {caption="Transkript 1 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Kunde: Guten Tag! Verkäuferin: Guten Tag! Kunde: Einmal von der groben Leberwurst, bitte. Verkäuferin: Wie viel darf's denn sein? Kunde: Zwei hundert Gramm. Verkäuferin: Sonst noch etwas? Kunde: Ja, dann noch ein Stück von dem Schwarzwälder Schinken. Verkäuferin: Wie groß soll das Stück sein? Kunde: So um die dreihundert Gramm. Verkäuferin: Das macht dann acht Mark zwanzig. Kunde: Bitte. Verkäuferin: Danke und einen schönen Tag noch! Kunde: Danke, ebenfalls! ``` ### Transkript 2 - Marktplatz (Kirschen) **Datum:** 28. Juni 1994, **Ort:** Marktplatz, Aachen ``` {caption="Transkript 2 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Verkäufer: Kirschen kann jeder probieren hier! Kunde 1: Ein halbes Kilo Kirschen, bitte. Verkäufer: Ein halbes Kilo? Oder ein Kilo? Verkäufer: Drei Mark, bitte. Kunde 1: Danke schön! Verkäufer: Kirschen kann jeder probieren hier! Kunde 2: Ein halbes Kilo, bitte. Verkäufer: Drei Mark, bitte. Kunde 2: Danke schön! ``` ### Transkript 3 - Fischstand **Datum:** 28. Juni 1994, **Ort:** Fischstand, Marktplatz, Aachen ``` {caption="Transkript 3 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Kunde: Ein Pfund Seelachs, bitte. Verkäufer: Seelachs, alles klar. Verkäufer: Vier Mark neunzehn, bitte. Kunde: Danke schön! ``` ### Transkript 4 - Gemüsestand (ausführlich) **Datum:** 28. Juni 1994, **Ort:** Gemüsestand, Aachen, Marktplatz, 11:00 Uhr ``` {caption="Transkript 4 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Kunde: Hören Sie, ich nehme ein paar Champignons mit. Verkäufer: Braune oder helle? Kunde: Nehmen wir die hellen. Verkäufer: Die sind beide frisch, keine Sorge. Kunde: Wie ist es mit Pfifferlingen? Verkäufer: Ah, die sind super! Kunde: Kann ich die in Reissalat tun? Verkäufer: Eher kurz anbraten in der Pfanne. Kunde: Okay, mache ich. Verkäufer: Schönen Tag noch! Kunde: Gleichfalls! ``` ### Transkript 5 - Gemüsestand (mit KAV zu Beginn) **Datum:** 26. Juni 1994, **Ort:** Gemüsestand, Aachen, Marktplatz, 11:00 Uhr ``` {caption="Transkript 5 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Kunde 1: Auf Wiedersehen! Kunde 2: Ich hätte gern ein Kilo von den Granny Smith Äpfeln hier. Verkäufer: Sonst noch etwas? Kunde 2: Ja, noch ein Kilo Zwiebeln. Verkäufer: Sechs Mark fünfundzwanzig, bitte. Kunde 2: Auf Wiedersehen! ``` ### Transkript 6 - Käseverkaufsstand **Datum:** 28. Juni 1994, **Ort:** Käseverkaufsstand, Aachen, Marktplatz ``` {caption="Transkript 6 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Kunde 1: Guten Morgen! Verkäufer: Guten Morgen! Kunde 1: Ich hätte gerne fünfhundert Gramm holländischen Gouda. Verkäufer: Am Stück? Kunde 1: Ja, am Stück, bitte. ``` ### Transkript 7 - Bonbonstand **Datum:** 28. Juni 1994, **Ort:** Bonbonstand, Aachen, Marktplatz, 11:30 Uhr ``` {caption="Transkript 7 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} Kunde: Von den gemischten hätte ich gerne hundert Gramm. Verkäufer: Für zu Hause oder zum Mitnehmen? Kunde: Zum Mitnehmen, bitte. Verkäufer: Fünfzig Pfennig, bitte. Kunde: Danke! ``` ### Transkript 8 - Bäckerei **Datum:** 9. Juli 1994, **Ort:** Bäckerei, Aachen, 12:00 Uhr ``` {caption="Transkript 8 - Rohdaten" basicstyle="\\ttfamily\\footnotesize"} (Schritte hörbar, Hintergrundgeräusche, teilweise unverständlich) Kunde: Guten Tag! (Unverständliche Begrüßung im Hintergrund) Verkäuferin: Einmal unser bester Kaffee, frisch gemahlen, bitte. (Geräusche der Kaffeemühle, Verpackungsgeräusche) Verkäuferin: Sonst noch etwas? Kunde: Ja, noch zwei Stück Obstsalat und ein Schälchen Sahne. Verkäuferin: In Ordnung! (Geräusche der Kaffeemühle, Papiergeräusche) Verkäuferin: Ein kleines Schälchen Sahne, ja? Kunde: Ja, danke. (Türgeräusch, Lachen, Papiergeräusche) Verkäuferin: Keiner kümmert sich darum, die Türen zu ölen. Kunde: Ja, das ist immer so. (Lachen, Geräusche von Münzen und Verpackung) Verkäuferin: Das macht vierzehn Mark und neunzehn Pfennig, bitte. Kunde: Ich zahle in Kleingeld. (Lachen und Geräusche von Münzen) Verkäuferin: Vielen Dank, schönen Sonntag noch! Kunde: Danke, Ihnen auch! ``` ## Die Terminalzeichenketten (ARS 3.0) Für die ARS 3.0 wurden diese Rohdaten in Terminalzeichenketten überführt, die als Grundlage für die hierarchische Grammatikinduktion dienten: ::: {#tab:terminal_chains} **Transkript** **Terminalzeichenkette** ---------------- --------------------------------------------------------------------- 1 (Metzgerei) KBG, VBG, KBBd, VBBd, KBA, VBA, KBBd, VBBd, KBA, VAA, KAA, VAV, KAV 2 (Kirschen) VBG, KBBd, VBBd, VAA, KAA, VBG, KBBd, VAA, KAA 3 (Fischstand) KBBd, VBBd, VAA, KAA 4 (Gemüse) KBBd, VBBd, KBA, VBA, KBBd, VBA, KAE, VAE, KAA, VAV, KAV 5 (Gemüse KAV) KAV, KBBd, VBBd, KBBd, VAA, KAV 6 (Käse) KBG, VBG, KBBd, VBBd, KAA 7 (Bonbon) KBBd, VBBd, KBA, VAA, KAA 8 (Bäckerei) KBG, VBBd, KBBd, VBA, VAA, KAA, VAV, KAV : Terminalzeichenketten der acht Transkripte ::: Die Bedeutung der Terminalzeichen: - **KBG**: Kunden-Gruß - **VBG**: Verkäufer-Gruß - **KBBd**: Kunden-Bedarf (konkret) - **VBBd**: Verkäufer-Nachfrage - **KBA**: Kunden-Antwort - **VBA**: Verkäufer-Reaktion - **KAE**: Kunden-Erkundigung - **VAE**: Verkäufer-Auskunft - **KAA**: Kunden-Abschluss - **VAA**: Verkäufer-Abschluss - **KAV**: Kunden-Verabschiedung - **VAV**: Verkäufer-Verabschiedung # Szenario C: Computerlinguistische Integration Szenario C realisiert eine vollständig computerlinguistische Modellierung der acht Transkripte. Es umfasst vier Komponenten: 1. **Speech Act Recognition**: Automatische Erkennung der Sprechakte aus den Rohdaten 2. **Word Embeddings**: Vektorielle Repräsentation der Äußerungen 3. **Topic Modeling**: Identifikation thematischer Verschiebungen 4. **Rhetorical Structure Theory (RST)**: Analyse der argumentativen Struktur ## Didaktische Augmentierung Da neuronale Netze für ihr Training große Datenmengen benötigen, werden die acht Transkripte zu Demonstrationszwecken augmentiert: ``` {.python caption="Data Augmentation für Lehrzwecke" language="Python"} def augment_transcripts_for_teaching(transcripts, factor=20): """ Augmentiert die acht Transkripte für didaktische Zwecke. Didaktischer Hinweis: Diese Augmentierung dient ausschließlich der Veranschaulichung der Methodik. Die resultierenden Daten sind nicht empirisch valide, sondern ermöglichen lediglich die Demonstration der Funktionsweise neuronaler Verfahren. """ augmented = [] # 1. Basis-Augmentierung: einfaches Kopieren for _ in range(factor): augmented.extend(transcripts) # 2. Syntaktische Variationen (didaktisch kontrolliert) import copy import random for transcript in transcripts: for _ in range(factor // 4): var = copy.deepcopy(transcript) # Vertausche zwei benachbarte Äußerungen (selten) if len(var) > 3 and random.random() < 0.1: idx = random.randint(0, len(var)-2) var[idx], var[idx+1] = var[idx+1], var[idx] augmented.append(var) # 3. Lexikalische Variationen (Synonyme) synonyms = { 'Guten Tag': ['Guten Morgen', 'Hallo', 'Guten Abend'], 'Danke': ['Vielen Dank', 'Danke schön', 'Merci'], 'Bitte': ['Bitte sehr', 'Gern geschehen'] } # Hier könnten weitere Variationen implementiert werden return augmented ``` ## Speech Act Recognition mit Transformer-Modellen Die automatische Erkennung der Sprechakte erfolgt mit einem feinabgestimmten BERT-Modell: ``` {.python caption="Speech Act Recognition mit BERT" language="Python"} """ Speech Act Recognition mit transformer-basierten Modellen Didaktische Implementierung für Lehrzwecke """ import torch import torch.nn as nn from transformers import BertTokenizer, BertModel import numpy as np from sklearn.preprocessing import LabelEncoder from torch.utils.data import Dataset, DataLoader class SpeechActDataset(Dataset): """Dataset für Speech Act Recognition""" def __init__(self, utterances, labels, tokenizer, max_length=128): self.utterances = utterances self.labels = labels self.tokenizer = tokenizer self.max_length = max_length def __len__(self): return len(self.utterances) def __getitem__(self, idx): utterance = self.utterances[idx] label = self.labels[idx] encoding = self.tokenizer( utterance, truncation=True, padding='max_length', max_length=self.max_length, return_tensors='pt' ) return { 'input_ids': encoding['input_ids'].flatten(), 'attention_mask': encoding['attention_mask'].flatten(), 'label': torch.tensor(label, dtype=torch.long) } class BertSpeechActClassifier(nn.Module): """ BERT-basierter Klassifikator für Sprechakte Didaktisch vereinfachte Architektur """ def __init__(self, num_classes=12, dropout=0.3): super().__init__() self.bert = BertModel.from_pretrained('bert-base-german-cased') self.dropout = nn.Dropout(dropout) self.classifier = nn.Linear(768, num_classes) # Freeze BERT layers für didaktische Zwecke (schnelleres Training) for param in self.bert.parameters(): param.requires_grad = False def forward(self, input_ids, attention_mask): outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask) pooled_output = outputs.pooler_output dropped = self.dropout(pooled_output) logits = self.classifier(dropped) return logits def prepare_speech_act_data(transcripts, terminal_chains): """ Bereitet die Daten für das Speech Act Training vor """ utterances = [] labels = [] # Extrahiere alle Äußerungen aus den Rohdaten # Hier vereinfacht: Mapping der Terminalzeichen auf Sprechakte for trans, chain in zip(transcripts, terminal_chains): # In einer vollständigen Implementierung müssten die Rohdaten geparst werden # Für didaktische Zwecke verwenden wir die Terminalzeichen direkt for symbol in chain: utterances.append(f"Beispieläußerung für {symbol}") labels.append(symbol) # Label-Encoding label_encoder = LabelEncoder() y_encoded = label_encoder.fit_transform(labels) return utterances, y_encoded, label_encoder def train_speech_act_model(utterances, labels, epochs=10): """ Trainiert das Speech Act Recognition Modell """ tokenizer = BertTokenizer.from_pretrained('bert-base-german-cased') dataset = SpeechActDataset(utterances, labels, tokenizer) dataloader = DataLoader(dataset, batch_size=8, shuffle=True) model = BertSpeechActClassifier(num_classes=len(set(labels))) optimizer = torch.optim.Adam(model.parameters(), lr=2e-5) criterion = nn.CrossEntropyLoss() print("\n=== Speech Act Recognition Training (didaktisch) ===") for epoch in range(epochs): total_loss = 0 for batch in dataloader: optimizer.zero_grad() outputs = model(batch['input_ids'], batch['attention_mask']) loss = criterion(outputs, batch['label']) loss.backward() optimizer.step() total_loss += loss.item() print(f"Epoch {epoch+1}: Loss = {total_loss/len(dataloader):.4f}") return model, tokenizer, label_encoder # Didaktischer Hinweis print("\n" + "="*70) print("DIDAKTISCHER HINWEIS ZUR SPEECH ACT RECOGNITION") print("="*70) print("Die hier gezeigte Implementierung verwendet augmentierte") print("Daten und dient ausschließlich Lehrzwecken. Die automatische") print("Erkennung von Sprechakten würde in der Praxis:") print(" • Millionen von annotierten Trainingsdaten benötigen") print(" • Auf spezifische Domänen (Verkaufsgespräche) feinabgestimmt werden") print(" • Mit erheblichen Unsicherheiten behaftet sein") ``` ## Word Embeddings und semantische Ähnlichkeit Für die Quantifizierung semantischer Ähnlichkeit werden vortrainierte Word Embeddings verwendet: ``` {.python caption="Semantische Ähnlichkeit mit Word Embeddings" language="Python"} """ Word Embeddings für semantische Ähnlichkeitsanalysen Didaktische Implementierung mit vortrainierten Modellen """ from sentence_transformers import SentenceTransformer import numpy as np from sklearn.metrics.pairwise import cosine_similarity import matplotlib.pyplot as plt import seaborn as sns class SemanticAnalyzer: """ Analysiert semantische Ähnlichkeiten zwischen Äußerungen """ def __init__(self, model_name='paraphrase-multilingual-MiniLM-L12-v2'): print(f"Lade vortrainiertes Modell: {model_name}") self.model = SentenceTransformer(model_name) self.embeddings = {} def encode_utterances(self, utterances): """ Erzeugt Embeddings für eine Liste von Äußerungen """ embeddings = self.model.encode(utterances) for utt, emb in zip(utterances, embeddings): self.embeddings[utt] = emb return embeddings def similarity_matrix(self, utterances): """ Berechnet die Ähnlichkeitsmatrix für alle Äußerungen """ embeddings = self.encode_utterances(utterances) sim_matrix = cosine_similarity(embeddings) return sim_matrix def find_similar(self, query, utterances, top_k=5): """ Findet die ähnlichsten Äußerungen zu einer Query """ query_emb = self.model.encode([query])[0] utt_embs = self.encode_utterances(utterances) similarities = cosine_similarity([query_emb], utt_embs)[0] top_indices = np.argsort(similarities)[-top_k:][::-1] results = [] for idx in top_indices: results.append({ 'utterance': utterances[idx], 'similarity': similarities[idx] }) return results def visualize_similarity(self, utterances, labels=None): """ Visualisiert die Ähnlichkeitsmatrix als Heatmap """ sim_matrix = self.similarity_matrix(utterances) plt.figure(figsize=(12, 10)) sns.heatmap(sim_matrix, xticklabels=labels if labels else range(len(utterances)), yticklabels=labels if labels else range(len(utterances)), cmap='viridis', vmin=0, vmax=1) plt.title('Semantische Ähnlichkeit zwischen Äußerungen') plt.tight_layout() plt.savefig('semantic_similarity.png', dpi=150) plt.show() # Didaktisches Beispiel def demonstrate_semantic_analysis(): """ Demonstriert die semantische Analyse an Beispielen """ analyzer = SemanticAnalyzer() # Beispiel-Äußerungen aus den Transkripten utterances = [ "Guten Tag!", "Guten Morgen!", "Einmal Leberwurst, bitte.", "Ich hätte gerne Wurst.", "Danke schön!", "Vielen Dank!", "Auf Wiedersehen!", "Tschüss!" ] print("\n=== Semantische Ähnlichkeitsanalyse ===") # Ähnlichkeitsmatrix berechnen sim_matrix = analyzer.similarity_matrix(utterances) # Ähnlichste Äußerungen für "Guten Tag!" similar = analyzer.find_similar("Guten Tag!", utterances, top_k=3) print("\nÄhnlichste zu 'Guten Tag!':") for r in similar: print(f" {r['utterance']}: {r['similarity']:.3f}") # Visualisierung analyzer.visualize_similarity(utterances, utterances) return analyzer # Didaktischer Hinweis print("\n" + "="*70) print("DIDAKTISCHER HINWEIS ZU WORD EMBEDDINGS") print("="*70) print("Die verwendeten Embeddings wurden auf großen Korpora") print("(Wikipedia, Nachrichten, Webtexte) vortrainiert. Sie") print("erfassen allgemeinsprachliche Ähnlichkeiten, nicht die") print("spezifischen Kategorien der Verkaufsgespräche.") ``` ## Topic Modeling mit BERTopic Für die Identifikation thematischer Verschiebungen wird BERTopic verwendet: ``` {.python caption="Topic Modeling mit BERTopic" language="Python"} """ Topic Modeling zur Identifikation thematischer Verschiebungen Didaktische Implementierung mit BERTopic """ from bertopic import BERTopic from sklearn.feature_extraction.text import CountVectorizer import pandas as pd import matplotlib.pyplot as plt class TranscriptTopicModeler: """ Führt Topic Modeling auf den Transkripten durch """ def __init__(self): self.model = None self.topics = None self.probs = None def prepare_documents(self, transcripts): """ Bereitet die Transkripte als Dokumente für Topic Modeling vor """ documents = [] metadata = [] for i, transcript in enumerate(transcripts, 1): # Jedes Transkript als ein Dokument doc = ' '.join(transcript) documents.append(doc) metadata.append(f'Transkript {i}') # Alternativ: Jede Äußerung als Dokument # for j, utterance in enumerate(transcript): # documents.append(utterance) # metadata.append(f'T{i}_U{j}') return documents, metadata def fit_model(self, documents): """ Trainiert das Topic Model """ # Benutzerdefinierte Stopwörter stopwords = ['bitte', 'danke', 'gern', 'mal', 'noch', 'ja', 'nein'] vectorizer = CountVectorizer(stop_words=stopwords) self.model = BERTopic( embedding_model="paraphrase-multilingual-MiniLM-L12-v2", vectorizer_model=vectorizer, verbose=True, nr_topics='auto' ) self.topics, self.probs = self.model.fit_transform(documents) return self.topics, self.probs def visualize_topics(self): """ Visualisiert die gefundenen Themen """ if self.model is None: return fig = self.model.visualize_topics() fig.write_html("topic_visualization.html") # Statistik topic_counts = pd.Series(self.topics).value_counts() print("\n=== Themenverteilung ===") for topic, count in topic_counts.items(): if topic == -1: print(f"Outlier: {count} Dokumente") else: words = self.model.get_topic(topic)[:5] words_str = ', '.join([w for w, _ in words]) print(f"Thema {topic}: {count} Dokumente - {words_str}") def visualize_topics_over_time(self, documents, timestamps): """ Visualisiert Themenentwicklung über die Zeit """ if self.model is None: return topics_over_time = self.model.topics_over_time( documents, timestamps, nr_bins=8 ) fig = self.model.visualize_topics_over_time(topics_over_time) fig.write_html("topics_over_time.html") def demonstrate_topic_modeling(transcripts): """ Demonstriert Topic Modeling an den Transkripten """ modeler = TranscriptTopicModeler() documents, metadata = modeler.prepare_documents(transcripts) print("\n=== Topic Modeling der acht Transkripte ===") topics, probs = modeler.fit_model(documents) for i, (doc, topic, prob, meta) in enumerate(zip(documents, topics, probs, metadata)): if topic != -1: words = modeler.model.get_topic(topic)[:3] words_str = ', '.join([w for w, _ in words]) print(f"{meta}: Thema {topic} (Confidence: {prob:.2f}) - {words_str}") else: print(f"{meta}: Kein klares Thema (Outlier)") modeler.visualize_topics() return modeler # Didaktischer Hinweis print("\n" + "="*70) print("DIDAKTISCHER HINWEIS ZUM TOPIC MODELING") print("="*70) print("Topic Modeling identifiziert latente Themen in Textkorpora.") print("Bei nur acht Dokumenten ist die Themenfindung instabil.") print("Die Ergebnisse dienen daher nur der Veranschaulichung der") print("Methodik, nicht der inhaltlichen Analyse.") ``` ## Rhetorical Structure Theory (RST) Für die Analyse der argumentativen Struktur wird ein RST-Parser implementiert: ``` {.python caption="Rhetorical Structure Theory Parser" language="Python"} """ Rhetorical Structure Theory (RST) Analyse Didaktische Implementierung für Sequenzdaten """ import networkx as nx import matplotlib.pyplot as plt from collections import defaultdict class RSTRelation: """Repräsentiert eine RST-Relation zwischen Textsegmenten""" def __init__(self, type_name, nucleus, satellite, direction='nucleus-satellite'): self.type = type_name # z.B. 'Elaboration', 'Contrast', 'Cause' self.nucleus = nucleus # Zentrales Segment self.satellite = satellite # Unterstützendes Segment self.direction = direction class SimpleRSTParser: """ Einfacher RST-Parser für didaktische Zwecke Basierend auf cue phrases und strukturellen Mustern """ # Cue Phrases für verschiedene Relationen cue_phrases = { 'Elaboration': ['zum Beispiel', 'insbesondere', 'nämlich', 'genauer'], 'Contrast': ['aber', 'jedoch', 'hingegen', 'dagegen'], 'Cause': ['weil', 'da', 'denn', 'deshalb', 'daher'], 'Condition': ['wenn', 'falls', 'sofern'], 'Purpose': ['um zu', 'damit'], 'Sequence': ['dann', 'danach', 'zuerst', 'schließlich'] } def __init__(self): self.relations = [] self.graph = nx.DiGraph() def segment_transcript(self, transcript): """ Segmentiert ein Transkript in elementare Diskurseinheiten (EDUs) Vereinfacht: Jede Äußerung ist eine EDU """ return transcript def identify_relations(self, segments): """ Identifiziert RST-Relationen zwischen Segmenten Didaktisch vereinfachte Implementierung """ relations = [] for i in range(len(segments)-1): current = segments[i] next_seg = segments[i+1] # Prüfe auf Cue Phrases for rel_type, cues in self.cue_phrases.items(): for cue in cues: if cue in current.lower() or cue in next_seg.lower(): relations.append(RSTRelation( type_name=rel_type, nucleus=i, satellite=i+1 )) break # Standard: Sequenz-Relation if i < len(segments)-1: relations.append(RSTRelation( type_name='Sequence', nucleus=i, satellite=i+1 )) return relations def build_tree(self, segments, relations): """ Baut einen RST-Baum aus den identifizierten Relationen """ self.graph.clear() # Knoten hinzufügen for i, seg in enumerate(segments): self.graph.add_node(i, text=seg[:30] + '...' if len(seg) > 30 else seg) # Kanten hinzufügen for rel in relations: self.graph.add_edge(rel.nucleus, rel.satellite, relation=rel.type) return self.graph def parse(self, transcript): """ Vollständige RST-Analyse eines Transkripts """ segments = self.segment_transcript(transcript) relations = self.identify_relations(segments) tree = self.build_tree(segments, relations) return { 'segments': segments, 'relations': relations, 'tree': tree } def visualize(self, title="RST-Struktur"): """ Visualisiert den RST-Baum """ pos = nx.spring_layout(self.graph) plt.figure(figsize=(12, 8)) # Knoten zeichnen nx.draw_networkx_nodes(self.graph, pos, node_color='lightblue', node_size=500) # Kanten zeichnen mit Relationstyp als Label for edge in self.graph.edges(data=True): nx.draw_networkx_edges(self.graph, pos, [(edge[0], edge[1])]) nx.draw_networkx_edge_labels( self.graph, pos, {(edge[0], edge[1]): edge[2]['relation']} ) # Knotenlabels labels = {node: f"{node}: {self.graph.nodes[node]['text']}" for node in self.graph.nodes()} nx.draw_networkx_labels(self.graph, pos, labels, font_size=8) plt.title(title) plt.axis('off') plt.tight_layout() plt.savefig('rst_structure.png', dpi=150) plt.show() def demonstrate_rst_analysis(transcripts): """ Demonstriert RST-Analyse an den Transkripten """ parser = SimpleRSTParser() print("\n=== RST-Analyse der Transkripte ===") for i, transcript in enumerate(transcripts, 1): print(f"\nTranskript {i}:") result = parser.parse(transcript) # Zeige identifizierte Relationen for rel in result['relations'][:5]: # Nur erste 5 seg1 = result['segments'][rel.nucleus][:20] + '...' seg2 = result['segments'][rel.satellite][:20] + '...' print(f" {rel.type}: {seg1} → {seg2}") if i == 1: # Nur erstes Transkript visualisieren parser.visualize(f"RST-Struktur Transkript {i}") return parser # Didaktischer Hinweis print("\n" + "="*70) print("DIDAKTISCHER HINWEIS ZUR RST-ANALYSE") print("="*70) print("Die hier implementierte RST-Analyse ist stark vereinfacht.") print("Ein vollständiger RST-Parser würde:") print(" • Aufwändige manuelle Annotation erfordern") print(" • Mit trainierten neuronalen Modellen arbeiten") print(" • Mehrere Hierarchieebenen von Diskursrelationen berücksichtigen") ``` ## Integration der Komponenten in Szenario C Die vollständige Integration aller Komponenten in Szenario C: ``` {.python caption="Szenario C - Vollständige Integration" language="Python"} """ Szenario C: Vollständige computerlinguistische Integration Didaktische Implementierung für Lehrzwecke """ import os import json from datetime import datetime class ScenarioC: """ Integriert alle computerlinguistischen Komponenten: - Speech Act Recognition - Word Embeddings / Semantische Analyse - Topic Modeling - RST-Analyse """ def __init__(self, transcripts, terminal_chains): self.transcripts = transcripts self.terminal_chains = terminal_chains self.results = {} print("\n" + "="*70) print("SZENARIO C: COMPUTERLINGUISTISCHE INTEGRATION") print("="*70) print("\nDieses Szenario demonstriert die Anwendung") print("computerlinguistischer Verfahren auf die acht") print("Transkripte. Alle Ergebnisse dienen didaktischen") print("Zwecken und sind nicht empirisch valide.\n") def run_speech_act_recognition(self): """ Führt die Speech Act Recognition aus """ print("\n--- Speech Act Recognition ---") utterances, labels, encoder = prepare_speech_act_data( self.transcripts, self.terminal_chains ) model, tokenizer, label_encoder = train_speech_act_model( utterances, labels, epochs=5 ) self.results['speech_act'] = { 'model': model, 'tokenizer': tokenizer, 'label_encoder': label_encoder, 'num_classes': len(label_encoder.classes_) } return self.results['speech_act'] def run_semantic_analysis(self): """ Führt die semantische Ähnlichkeitsanalyse aus """ print("\n--- Semantische Ähnlichkeitsanalyse ---") analyzer = SemanticAnalyzer() # Sammle alle Äußerungen all_utterances = [] for transcript in self.transcripts: all_utterances.extend(transcript) # Ähnlichkeitsmatrix sim_matrix = analyzer.similarity_matrix(all_utterances[:20]) # Nur erste 20 self.results['semantic'] = { 'analyzer': analyzer, 'utterances': all_utterances, 'similarity_matrix': sim_matrix } return self.results['semantic'] def run_topic_modeling(self): """ Führt das Topic Modeling aus """ print("\n--- Topic Modeling ---") modeler = TranscriptTopicModeler() documents, metadata = modeler.prepare_documents(self.transcripts) topics, probs = modeler.fit_model(documents) modeler.visualize_topics() self.results['topic'] = { 'modeler': modeler, 'topics': topics, 'probabilities': probs, 'documents': documents, 'metadata': metadata } return self.results['topic'] def run_rst_analysis(self): """ Führt die RST-Analyse aus """ print("\n--- RST-Analyse ---") parser = SimpleRSTParser() rst_results = [] for i, transcript in enumerate(self.transcripts, 1): result = parser.parse(transcript) rst_results.append({ 'transcript_id': i, 'segments': result['segments'], 'relations': [(r.type, r.nucleus, r.satellite) for r in result['relations']] }) if i == 1: parser.visualize(f"RTS-Struktur Transkript {i}") self.results['rst'] = rst_results return rst_results def run_all(self): """ Führt alle Analysen aus """ self.run_speech_act_recognition() self.run_semantic_analysis() self.run_topic_modeling() self.run_rst_analysis() # Zusammenfassung print("\n" + "="*70) print("ZUSAMMENFASSUNG SZENARIO C") print("="*70) print(f"✓ Speech Act Recognition: {self.results['speech_act']['num_classes']} Klassen") print(f"✓ Semantische Analyse: {len(self.results['semantic']['utterances'])} Äußerungen") print(f"✓ Topic Modeling: {len(set(self.results['topic']['topics']))} Themen") print(f"✓ RST-Analyse: {len(self.results['rst'])} Transkripte analysiert") return self.results # Didaktische Ausführung def run_scenario_c_demonstration(): """ Führt die vollständige Demonstration von Szenario C aus """ # Lade die Transkripte from ars_data import transcripts, terminal_chains # Augmentiere die Daten für didaktische Zwecke augmented_transcripts = augment_transcripts_for_teaching(transcripts, factor=10) augmented_chains = augment_transcripts_for_teaching(terminal_chains, factor=10) print("\n" + "="*70) print("DIDAKTISCHE AUGMENTIERUNG") print("="*70) print(f"Original: {len(transcripts)} Transkripte") print(f"Augmentiert: {len(augmented_transcripts)} Transkripte") # Führe Szenario C aus scenario = ScenarioC(augmented_transcripts, augmented_chains) results = scenario.run_all() # Speichere Ergebnisse with open('scenario_c_results.json', 'w') as f: # Konvertiere nicht-serialisierbare Objekte serializable = { 'speech_act': {'num_classes': results['speech_act']['num_classes']}, 'semantic': {'num_utterances': len(results['semantic']['utterances'])}, 'topic': {'num_topics': len(set(results['topic']['topics']))}, 'rst': results['rst'] } json.dump(serializable, f, indent=2) print("\nErgebnisse gespeichert in 'scenario_c_results.json'") return results if __name__ == "__main__": run_scenario_c_demonstration() ``` # Szenario D: Hybride Modellierung Szenario D integriert computerlinguistische Verfahren mit den interpretativ gebildeten Kategorien der ARS 3.0. Es überspringt die vollständige Automatisierung der Kategorienbildung (Szenario C) und nutzt die neuen Verfahren komplementär. ## CRF für sequenzielle Abhängigkeiten Conditional Random Fields modellieren Abhängigkeiten der Sprechakte vom weiteren Kontext: ``` {.python caption="CRF für sequenzielle Abhängigkeiten" language="Python"} """ Conditional Random Fields (CRF) für sequenzielle Abhängigkeiten Didaktische Implementierung mit sklearn-crfsuite """ import sklearn_crfsuite from sklearn_crfsuite import metrics import numpy as np class CRFSequenceModel: """ CRF-Modell für die Sequenzmodellierung der Terminalzeichen """ def __init__(self): self.crf = sklearn_crfsuite.CRF( algorithm='lbfgs', c1=0.1, # L1-Regularisierung c2=0.1, # L2-Regularisierung max_iterations=100, all_possible_transitions=True ) self.label_encoder = None def word2features(self, tokens, i): """ Erzeugt Features für Position i in der Sequenz """ word = tokens[i] features = { 'bias': 1.0, 'word': word, 'word.is_first': i == 0, 'word.is_last': i == len(tokens) - 1, 'word.prefix_K': word.startswith('K'), 'word.prefix_V': word.startswith('V'), 'word.suffix_A': word.endswith('A'), 'word.suffix_B': word.endswith('B'), 'word.suffix_E': word.endswith('E'), 'word.suffix_G': word.endswith('G'), 'word.suffix_V': word.endswith('V'), } # Kontext-Features if i > 0: word_prev = tokens[i-1] features.update({ '-1:word': word_prev, '-1:word.prefix_K': word_prev.startswith('K'), '-1:word.prefix_V': word_prev.startswith('V'), '-1:word.suffix_A': word_prev.endswith('A'), }) else: features['BOS'] = True if i < len(tokens) - 1: word_next = tokens[i+1] features.update({ '+1:word': word_next, '+1:word.prefix_K': word_next.startswith('K'), '+1:word.prefix_V': word_next.startswith('V'), '+1:word.suffix_A': word_next.endswith('A'), }) else: features['EOS'] = True return features def extract_features(self, sequences): """ Extrahiert Features für alle Sequenzen """ X = [] for seq in sequences: X.append([self.word2features(seq, i) for i in range(len(seq))]) return X def fit(self, sequences, labels): """ Trainiert das CRF-Modell """ X = self.extract_features(sequences) self.crf.fit(X, labels) return self def predict(self, sequences): """ Sagt Labels für neue Sequenzen vorher """ X = self.extract_features(sequences) return self.crf.predict(X) def evaluate(self, test_sequences, test_labels): """ Evaluiert das Modell """ pred = self.predict(test_sequences) # Flatten für Metriken y_true = [label for seq in test_labels for label in seq] y_pred = [label for seq in pred for label in seq] return { 'accuracy': np.mean(np.array(y_true) == np.array(y_pred)), 'classification_report': metrics.flat_classification_report( test_labels, pred, labels=sorted(set(y_true)) ) } def demonstrate_crf(terminal_chains): """ Demonstriert CRF-Modellierung auf den Terminalzeichen """ print("\n=== CRF-Modellierung der Terminalzeichen ===") # Train-Test-Split (didaktisch) train_size = int(len(terminal_chains) * 0.7) train_chains = terminal_chains[:train_size] test_chains = terminal_chains[train_size:] # Features extrahieren model = CRFSequenceModel() X_train = model.extract_features(train_chains) # Training print(f"Trainiere CRF mit {len(train_chains)} Sequenzen...") model.fit(train_chains, train_chains) # Labels sind die Sequenzen selbst # Evaluation results = model.evaluate(test_chains, test_chains) print(f"\nGenauigkeit: {results['accuracy']:.3f}") return model ``` ## Transformer-Embeddings als Ergänzung Transformer-Embeddings werden zusätzlich zu den kategorialen Terminalzeichen verwendet: ``` {.python caption="Transformer-Embeddings für Terminalzeichen" language="Python"} """ Transformer-Embeddings als Ergänzung zu kategorialen Terminalzeichen """ import torch import numpy as np from sentence_transformers import SentenceTransformer class TerminalEmbeddingEnricher: """ Ergänzt Terminalzeichen um semantische Embeddings der zugrundeliegenden Äußerungen """ def __init__(self, model_name='paraphrase-multilingual-MiniLM-L12-v2'): self.model = SentenceTransformer(model_name) self.symbol_to_embedding = {} self.symbol_to_text = self._create_symbol_mapping() def _create_symbol_mapping(self): """ Erstellt eine Mapping von Terminalzeichen zu Beispieltexten """ return { 'KBG': ['Guten Tag', 'Guten Morgen', 'Hallo'], 'VBG': ['Guten Tag', 'Guten Morgen', 'Hallo zurück'], 'KBBd': ['Einmal Leberwurst', 'Ich hätte gerne Käse', 'Ein Kilo Äpfel bitte'], 'VBBd': ['Wie viel darf es sein?', 'Welche Sorte?', 'Sonst noch etwas?'], 'KBA': ['Zweihundert Gramm', 'Die hellen bitte', 'Ja, gerne'], 'VBA': ['In Ordnung', 'Kommt sofort', 'Alles klar'], 'KAE': ['Kann ich das in Salat tun?', 'Woher kommen die?', 'Ist das frisch?'], 'VAE': ['Eher anbraten', 'Aus der Region', 'Ja, ganz frisch'], 'KAA': ['Bitte', 'Danke', 'Ja, danke'], 'VAA': ['Das macht 8 Mark 20', '3 Mark bitte', '14 Mark 19'], 'KAV': ['Auf Wiedersehen', 'Tschüss', 'Einen schönen Tag'], 'VAV': ['Vielen Dank', 'Schönen Tag noch', 'Auf Wiedersehen'] } def get_embedding(self, symbol): """ Gibt das Embedding für ein Terminalzeichen zurück """ if symbol in self.symbol_to_embedding: return self.symbol_to_embedding[symbol] # Durchschnitt der Beispieltext-Embeddings texts = self.symbol_to_text.get(symbol, [symbol]) embeddings = self.model.encode(texts) avg_embedding = np.mean(embeddings, axis=0) self.symbol_to_embedding[symbol] = avg_embedding return avg_embedding def enrich_sequence(self, sequence): """ Erweitert eine Sequenz von Terminalzeichen um Embeddings """ symbols = sequence embeddings = np.array([self.get_embedding(sym) for sym in symbols]) return { 'symbols': symbols, 'embeddings': embeddings, 'combined': np.column_stack([ self._one_hot_encode(symbols), embeddings ]) if len(symbols) > 0 else np.array([]) } def _one_hot_encode(self, symbols): """ One-Hot-Encoding der Terminalzeichen """ unique_symbols = sorted(set(self.symbol_to_text.keys())) symbol_to_idx = {sym: i for i, sym in enumerate(unique_symbols)} one_hot = np.zeros((len(symbols), len(unique_symbols))) for i, sym in enumerate(symbols): if sym in symbol_to_idx: one_hot[i, symbol_to_idx[sym]] = 1 return one_hot def demonstrate_embedding_enrichment(): """ Demonstriert die Anreicherung von Terminalzeichen mit Embeddings """ enricher = TerminalEmbeddingEnricher() print("\n=== Anreicherung der Terminalzeichen mit Embeddings ===") # Beispielsequenz sequence = ['KBG', 'VBG', 'KBBd', 'VBBd', 'KBA'] enriched = enricher.enrich_sequence(sequence) print(f"\nSequenz: {' → '.join(sequence)}") print(f"Embedding-Dimension: {enriched['embeddings'].shape[1]}") print(f"One-Hot-Dimension: {enriched['combined'].shape[1] - enriched['embeddings'].shape[1]}") print(f"Kombinierte Dimension: {enriched['combined'].shape[1]}") return enricher ``` ## Graph Neural Networks für die Nonterminal-Hierarchie Die Nonterminal-Hierarchie wird als Graph Neural Network modelliert: ``` {.python caption="Graph Neural Network für Nonterminal-Hierarchie" language="Python"} """ Graph Neural Network für die Nonterminal-Hierarchie Didaktische Implementierung mit PyTorch Geometric """ import torch import torch.nn as nn import torch.nn.functional as F from torch_geometric.nn import GCNConv, GATConv from torch_geometric.data import Data import networkx as nx class GrammarGNN(nn.Module): """ Graph Neural Network für die Grammatik-Hierarchie """ def __init__(self, input_dim, hidden_dim=64, num_classes=12): super().__init__() self.conv1 = GCNConv(input_dim, hidden_dim) self.conv2 = GCNConv(hidden_dim, hidden_dim) self.classifier = nn.Linear(hidden_dim, num_classes) def forward(self, x, edge_index): x = self.conv1(x, edge_index) x = F.relu(x) x = F.dropout(x, training=self.training) x = self.conv2(x, edge_index) x = F.relu(x) x = self.classifier(x) return F.log_softmax(x, dim=1) class GrammarHierarchyGNN: """ Verwaltet das GNN für die Nonterminal-Hierarchie """ def __init__(self, grammar_rules): self.grammar = grammar_rules self.graph = self._build_graph() self.model = None def _build_graph(self): """ Baut einen Graphen aus der Grammatik-Hierarchie """ G = nx.DiGraph() # Knoten: Terminale und Nonterminale all_symbols = set() # Nonterminale als Knoten for nt, productions in self.grammar.items(): all_symbols.add(nt) for prod, _ in productions: for sym in prod: all_symbols.add(sym) # Kanten: Ableitungsrelationen for nt, productions in self.grammar.items(): for prod, prob in productions: for sym in prod: G.add_edge(nt, sym, weight=prob) return G def prepare_data(self): """ Bereitet die Daten für das GNN vor """ # Knoten-Indizes nodes = list(self.graph.nodes()) node_to_idx = {node: i for i, node in enumerate(nodes)} # Feature-Matrix (vereinfacht: One-Hot) x = torch.eye(len(nodes)) # Kanten-Index edge_index = [] for u, v, data in self.graph.edges(data=True): edge_index.append([node_to_idx[u], node_to_idx[v]]) edge_index = torch.tensor(edge_index, dtype=torch.long).t().contiguous() return Data(x=x, edge_index=edge_index) def train(self, epochs=100): """ Trainiert das GNN """ data = self.prepare_data() self.model = GrammarGNN(input_dim=data.x.shape[1]) optimizer = torch.optim.Adam(self.model.parameters(), lr=0.01) print("\n=== Training des Grammar GNN ===") for epoch in range(epochs): self.model.train() optimizer.zero_grad() out = self.model(data.x, data.edge_index) # Selbstüberwachtes Lernen: Rekonstruktion des Graphen # Vereinfacht: Vorhersage der Nachbarn loss = F.nll_loss(out[data.edge_index[0]], data.edge_index[1]) loss.backward() optimizer.step() if epoch % 20 == 0: print(f"Epoch {epoch}: Loss = {loss.item():.4f}") return self.model def demonstrate_gnn(grammar_rules): """ Demonstriert das GNN für die Grammatik-Hierarchie """ print("\n=== Graph Neural Network für Nonterminal-Hierarchie ===") gnn = GrammarHierarchyGNN(grammar_rules) print(f"Graph: {gnn.graph.number_of_nodes()} Knoten, " f"{gnn.graph.number_of_edges()} Kanten") model = gnn.train(epochs=100) return gnn, model ``` ## Attention-Mechanismen für relevante Vorgänger Attention-Mechanismen identifizieren besonders relevante Vorgänger für aktuelle Entscheidungen: ``` {.python caption="Attention-Mechanismen für Sequenzmodellierung" language="Python"} """ Attention-Mechanismen für die Identifikation relevanter Vorgänger """ import torch import torch.nn as nn import torch.nn.functional as F import numpy as np class SequenceAttention(nn.Module): """ Attention-Mechanismus für Sequenzmodellierung """ def __init__(self, embedding_dim, hidden_dim=64): super().__init__() self.embedding_dim = embedding_dim self.hidden_dim = hidden_dim # Attention-Parameter self.W_q = nn.Linear(embedding_dim, hidden_dim, bias=False) self.W_k = nn.Linear(embedding_dim, hidden_dim, bias=False) self.W_v = nn.Linear(embedding_dim, hidden_dim, bias=False) self.scale = hidden_dim ** 0.5 def forward(self, x, mask=None): """ x: (seq_len, batch, embedding_dim) """ # Query, Key, Value berechnen Q = self.W_q(x) # (seq_len, batch, hidden_dim) K = self.W_k(x) # (seq_len, batch, hidden_dim) V = self.W_v(x) # (seq_len, batch, hidden_dim) # Attention-Scores scores = torch.matmul(Q.transpose(0, 1), K.transpose(0, 1).transpose(1, 2)) scores = scores / self.scale if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) # Attention-Gewichte attention_weights = F.softmax(scores, dim=-1) # Gewichtete Summe context = torch.matmul(attention_weights, V.transpose(0, 1)) return context, attention_weights class SymbolPredictorWithAttention(nn.Module): """ Sagt das nächste Symbol mit Attention auf die Vorgänger vorher """ def __init__(self, num_symbols, embedding_dim=50, hidden_dim=64): super().__init__() self.embedding = nn.Embedding(num_symbols, embedding_dim) self.attention = SequenceAttention(embedding_dim, hidden_dim) self.lstm = nn.LSTM(embedding_dim, hidden_dim, batch_first=True) self.classifier = nn.Linear(hidden_dim + embedding_dim, num_symbols) def forward(self, x): """ x: (batch, seq_len) mit Symbol-Indizes """ # Embeddings embedded = self.embedding(x) # (batch, seq_len, embedding_dim) # LSTM für sequenzielle Abhängigkeiten lstm_out, (hidden, cell) = self.lstm(embedded) # Attention über die Sequenz # Transponieren für Attention (seq_len, batch, embedding_dim) context, attention_weights = self.attention(embedded.transpose(0, 1)) # Kombiniere letzten LSTM-State mit Attention-Context last_hidden = hidden[-1] # (batch, hidden_dim) last_context = context[-1] # (batch, hidden_dim) # Vorhersage combined = torch.cat([last_hidden, last_context], dim=-1) logits = self.classifier(combined) return logits, attention_weights def demonstrate_attention(terminal_chains, symbol_to_idx): """ Demonstriert Attention-Mechanismen auf den Sequenzen """ print("\n=== Attention-Mechanismen für relevante Vorgänger ===") # Daten vorbereiten sequences = [] for chain in terminal_chains: seq = [symbol_to_idx[sym] for sym in chain] sequences.append(seq) # Padding für Batch-Verarbeitung from torch.nn.utils.rnn import pad_sequence sequences_padded = pad_sequence([torch.tensor(seq) for seq in sequences], batch_first=True, padding_value=0) # Modell initialisieren model = SymbolPredictorWithAttention(num_symbols=len(symbol_to_idx)) # Forward-Pass logits, attention_weights = model(sequences_padded[:2]) # Nur erste 2 Sequenzen print(f"\nInput-Shape: {sequences_padded[:2].shape}") print(f"Attention-Weights-Shape: {attention_weights.shape}") print(f"Logits-Shape: {logits.shape}") # Visualisierung der Attention-Gewichte plot_attention_weights(attention_weights[0].detach().numpy(), sequences[0], sequences[0]) return model def plot_attention_weights(attention, source_tokens, target_tokens): """ Visualisiert Attention-Gewichte als Heatmap """ import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(10, 8)) sns.heatmap(attention[:len(target_tokens), :len(source_tokens)], xticklabels=source_tokens, yticklabels=target_tokens, cmap='viridis', annot=True, fmt='.2f') plt.title('Attention-Gewichte zwischen Vorgängern und Vorhersage') plt.xlabel('Vorgänger-Symbole') plt.ylabel('Vorhersage-Position') plt.tight_layout() plt.savefig('attention_weights.png', dpi=150) plt.show() ``` ## Integration der Komponenten in Szenario D Die vollständige Integration aller Komponenten in Szenario D: ``` {.python caption="Szenario D - Vollständige hybride Integration" language="Python"} """ Szenario D: Hybride Modellierung Integration computerlinguistischer Verfahren mit interpretativen Kategorien """ import json import numpy as np class ScenarioD: """ Integriert computerlinguistische Verfahren komplementär zu den interpretativ gebildeten Kategorien der ARS 3.0 """ def __init__(self, terminal_chains, grammar_rules, reflection_log): self.terminal_chains = terminal_chains self.grammar_rules = grammar_rules self.reflection_log = reflection_log self.results = {} print("\n" + "="*70) print("SZENARIO D: HYBRIDE MODELLIERUNG") print("="*70) print("\nDieses Szenario integriert computerlinguistische") print("Verfahren KOMPLEMENTÄR zu den interpretativen") print("Kategorien der ARS 3.0. Die interpretative Basis") print("bleibt erhalten, wird aber durch neue Verfahren") print("angereichert.\n") def run_crf_modeling(self): """ Führt CRF-Modellierung auf den Terminalzeichen durch """ print("\n--- CRF-Modellierung ---") crf_model = demonstrate_crf(self.terminal_chains) self.results['crf'] = {'model': crf_model} return crf_model def run_embedding_enrichment(self): """ Reichert Terminalzeichen mit Transformer-Embeddings an """ print("\n--- Embedding-Anreicherung ---") enricher = demonstrate_embedding_enrichment() # Beispiel für angereicherte Sequenz example_seq = self.terminal_chains[0][:5] enriched = enricher.enrich_sequence(example_seq) self.results['embeddings'] = { 'enricher': enricher, 'example': enriched } return enricher def run_gnn_hierarchy(self): """ Modelliert die Nonterminal-Hierarchie als GNN """ print("\n--- GNN für Nonterminal-Hierarchie ---") gnn, model = demonstrate_gnn(self.grammar_rules) self.results['gnn'] = {'gnn': gnn, 'model': model} return gnn, model def run_attention_analysis(self): """ Analysiert Attention-Mechanismen auf den Sequenzen """ print("\n--- Attention-Analyse ---") # Symbol zu Index Mapping all_symbols = set() for chain in self.terminal_chains: all_symbols.update(chain) symbol_to_idx = {sym: i for i, sym in enumerate(sorted(all_symbols))} model = demonstrate_attention(self.terminal_chains, symbol_to_idx) self.results['attention'] = {'model': model} return model def run_all(self): """ Führt alle Analysen aus (komplementär, nicht ersetzend) """ self.run_crf_modeling() self.run_embedding_enrichment() self.run_gnn_hierarchy() self.run_attention_analysis() # Zusammenfassung print("\n" + "="*70) print("ZUSAMMENFASSUNG SZENARIO D") print("="*70) print("✓ CRF-Modellierung: Sequenzielle Abhängigkeiten modelliert") print("✓ Embedding-Anreicherung: Terminalzeichen semantisch angereichert") print("✓ GNN-Hierarchie: Nonterminal-Struktur als Graph modelliert") print("✓ Attention-Analyse: Relevante Vorgänger identifiziert") print("\nDie interpretativen Kategorien der ARS 3.0 bleiben") print("die Grundlage aller Analysen. Die computerlinguistischen") print("Verfahren dienen der komplementären Erkenntnisgewinnung.") return self.results def run_scenario_d_demonstration(terminal_chains, grammar_rules, reflection_log): """ Führt die vollständige Demonstration von Szenario D aus """ scenario = ScenarioD(terminal_chains, grammar_rules, reflection_log) results = scenario.run_all() # Speichere Ergebnisse with open('scenario_d_results.json', 'w') as f: # Vereinfachte serialisierbare Version serializable = { 'crf': {'status': 'completed'}, 'embeddings': {'status': 'completed'}, 'gnn': {'num_nodes': results['gnn'][0].graph.number_of_nodes()}, 'attention': {'status': 'completed'} } json.dump(serializable, f, indent=2) print("\nErgebnisse gespeichert in 'scenario_d_results.json'") return results # Didaktischer Hinweis print("\n" + "="*70) print("METHODOLOGISCHER HINWEIS ZU SZENARIO D") print("="*70) print("Szenario D behält die interpretative Basis der ARS 3.0 bei.") print("Die computerlinguistischen Verfahren werden KOMPLEMENTÄR") print("eingesetzt, nicht als Ersatz der manuellen Kategorienbildung.") print("Dies entspricht der methodologischen Forderung nach") print("Kontrolle und Transparenz im Sinne der XAI-Kriterien.") ``` # Vergleich der Szenarien und methodologische Reflexion ## Gegenüberstellung der Ansätze ::: {#tab:comparison} **Kriterium** **Szenario C** **Szenario D** ----------------------------------- -------------------------------------- ---------------------------------------------- \*\*Kategorienbildung\*\* Automatisch (Speech Act Recognition) Interpretativ (ARS 3.0) \*\*Datenbasis\*\* Augmentierte Rohdaten Terminalzeichenketten \*\*Repräsentation\*\* Vektorielle Embeddings Diskrete Kategorien + Embeddings \*\*Hierarchie\*\* Automatisch gelernt Explizit induziert (ARS 3.0) \*\*Transparenz\*\* Gering (Black Box) Hoch (dokumentierte Entscheidungen) \*\*Didaktischer Wert\*\* Funktionsweise neuronaler Verfahren Integration alter und neuer Methoden \*\*Empirische Validität\*\* Nicht gegeben Eingeschränkt (basierend auf Interpretation) \*\*Methodologische Kontrolle\*\* Verloren Erhalten : Vergleich der Szenarien C und D ::: ## Didaktische Erkenntnisse aus Szenario C Die Implementierung von Szenario C hat gezeigt: 1. **Notwendigkeit großer Datenmengen**: Neuronale Verfahren benötigen für valide Ergebnisse Datenmengen, die weit über die acht Transkripte hinausgehen. Die Augmentierung ermöglicht zwar die Demonstration der Funktionsweise, ersetzt aber keine echten Daten. 2. **Opazität der Entscheidungen**: Die automatisch gelernten Kategorien und Attention-Gewichte sind für Dritte nicht ohne weiteres nachvollziehbar. Die XAI-Kriterien der Verständlichkeit und Transparenz werden verletzt. 3. **Verlust der interpretativen Basis**: Die automatische Speech Act Recognition bildet nicht die qualitativ gehaltvollen Unterscheidungen der ARS ab (z.B. zwischen KBA und KAA), sondern lernt statistische Korrelationen im Vektorraum. ## Didaktische Erkenntnisse aus Szenario D Die Implementierung von Szenario D hat gezeigt: 1. **Komplementarität statt Substitution**: Die computerlinguistischen Verfahren können wertvolle Zusatzinformationen liefern (z.B. semantische Ähnlichkeiten zwischen verschiedenen Äußerungen), ohne die interpretative Basis zu ersetzen. 2. **Validierungsmöglichkeiten**: Die Embedding-Ähnlichkeiten können zur Validierung der interpretativen Kategorienbildung genutzt werden: Ähnliche Äußerungen sollten ähnliche Terminalzeichen erhalten. 3. **Visualisierung von Abhängigkeiten**: Attention-Mechanismen und CRF-Modelle visualisieren, welche Vorgänger für aktuelle Entscheidungen besonders relevant sind -- dies kann die sequenzielle Struktur der Gespräche veranschaulichen. 4. **Methodologische Kontrolle bleibt erhalten**: Da die interpretativen Kategorien die Grundlage bilden, bleiben alle Ergebnisse an die qualitativen Entscheidungen rückgebunden und intersubjektiv prüfbar. ## Fazit für die Lehrpraxis Die didaktische Exploration der Szenarien C und D führt zu folgenden Schlussfolgerungen: 1. **Szenario C eignet sich zur Demonstration der Funktionsweise** neuronaler Verfahren, sollte aber mit explizitem Hinweis auf die fehlende empirische Validität und die methodologischen Probleme eingesetzt werden. 2. **Szenario D ist methodologisch vorzuziehen**, da es die interpretative Basis erhält und computerlinguistische Verfahren komplementär nutzt. Es vermittelt, wie alte und neue Methoden produktiv verbunden werden können. 3. **Data Augmentation ist ein wertvolles didaktisches Werkzeug**, um mit kleinen Datensätzen die Funktionsweise von Verfahren zu demonstrieren. Der augmentierte Charakter der Daten muss dabei stets transparent gemacht werden. 4. **Die XAI-Kriterien** (Verständlichkeit, Genauigkeit, Wissensgrenzen) bieten einen geeigneten Rahmen, um die verschiedenen Ansätze zu bewerten und ihre Stärken und Schwächen zu reflektieren. # Ausblick Die hier vorgestellten didaktischen Implementierungen können in mehreren Richtungen weiterentwickelt werden: 1. **Erweiterung der Augmentierungsstrategien**: Über einfaches Kopieren hinaus könnten komplexere Augmentierungen (Paraphrasierung, kontrollierte Variation) implementiert werden. 2. **Integration weiterer Verfahren**: z.B. PETRI-Netze für Nebenläufigkeit, Bayessche Netze für Inferenz, oder formale Verifikationsmethoden. 3. **Entwicklung von Vergleichsmetriken**: Wie kann man die Ergebnisse der verschiedenen Szenarien quantitativ vergleichen, ohne die qualitative Basis zu verlieren? 4. **Übertragung auf andere Datensätze**: Die Methodik lässt sich auf andere Interaktionstypen übertragen (Arzt-Patient-Gespräche, Unterrichtsinteraktionen, etc.). Entscheidend bleibt dabei stets die methodologische Kontrolle: Die formalen Verfahren müssen den interpretativen Charakter der Analyse respektieren und dürfen nicht zu dessen Automatisierung führen. ::: thebibliography 99 Barredo Arrieta, A., Díaz-Rodríguez, N., Del Ser, J., Bennetot, A., Tabik, S., Barbado, A., Garcia, S., Gil-Lopez, S., Molina, D., Benjamins, R., Chatila, R., & Herrera, F. (2020). Explainable Artificial Intelligence (XAI): Concepts, taxonomies, opportunities and challenges toward responsible AI. *Information Fusion*, 58, 82-115. Devlin, J., Chang, M.-W., Lee, K., & Toutanova, K. (2019). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. *Proceedings of NAACL-HLT 2019*, 4171-4186. Flick, U. (2019). *Qualitative Sozialforschung: Eine Einführung* (9. Aufl.). Rowohlt. Lafferty, J., McCallum, A., & Pereira, F. (2001). Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data. *Proceedings of ICML 2001*, 282-289. Mann, W. C., & Thompson, S. A. (1988). Rhetorical Structure Theory: Toward a functional theory of text organization. *Text*, 8(3), 243-281. Przyborski, A., & Wohlrab-Sahr, M. (2021). *Qualitative Sozialforschung: Ein Arbeitsbuch* (5. Aufl.). De Gruyter Oldenbourg. Reimers, N., & Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. *Proceedings of EMNLP-IJCNLP 2019*, 3982-3992. Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł., & Polosukhin, I. (2017). Attention Is All You Need. *Advances in Neural Information Processing Systems 30*, 5998-6008. :::