Repository navigation
Expand file tree
/
Copy pathARS_XAI_CL_Ger.tex
More file actions
1866 lines (1515 loc) · 68.4 KB
/
Copy pathARS_XAI_CL_Ger.tex
File metadata and controls
1866 lines (1515 loc) · 68.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% Options for packages loaded elsewhere
\PassOptionsToPackage{unicode}{hyperref}
\PassOptionsToPackage{hyphens}{url}
\documentclass[
12pt,
a4paper,
oneside,
titlepage
]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{amsmath,amssymb}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{hyperref}
\usepackage{geometry}
\geometry{a4paper, left=3cm, right=3cm, top=3cm, bottom=3cm}
\usepackage{setspace}
\onehalfspacing
\usepackage{parskip}
\usepackage[ngerman]{babel}
\usepackage{csquotes}
\usepackage{microtype}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{array}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{float}
\usepackage{url}
\usepackage{natbib}
\usepackage{titling}
\usepackage{amsmath}
\usepackage{amssymb}
% Listing-Style für Python
\lstset{
language=Python,
basicstyle=\ttfamily\small,
keywordstyle=\color{blue},
commentstyle=\color{green!40!black},
stringstyle=\color{red},
showstringspaces=false,
numbers=left,
numberstyle=\tiny,
numbersep=5pt,
breaklines=true,
frame=single,
backgroundcolor=\color{gray!5},
tabsize=2,
captionpos=b
}
% Titel
\title{\Huge\textbf{Zwischen Interpretation und Berechnung} \\
\LARGE Didaktische Exploration computerlinguistischer Verfahren \\
\LARGE mit augmentierten Transkripten von Verkaufsgesprächen}
\author{
\large
\begin{tabular}{c}
Paul Koop
\end{tabular}
}
\date{\large Lehr- und Lernmaterial 2026}
\begin{document}
\maketitle
\begin{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.
\end{abstract}
\newpage
\tableofcontents
\newpage
\section{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.
\textbf{Dieses Dokument ist als Lehr- und Lernmaterial konzipiert.} Es verfolgt folgende didaktische Ziele:
\begin{enumerate}
\item \textbf{Verständnis neuronaler Architekturen}: Wie funktionieren Transformer, LSTM-Netze und Attention-Mechanismen auf Sequenzdaten?
\item \textbf{Data Augmentation als Technik}: Wie kann man mit kleinen Datensätzen umgehen, um die Funktionsweise von Verfahren zu demonstrieren?
\item \textbf{Vergleich verschiedener Modellierungsebenen}: Welche Unterschiede bestehen zwischen rein computerlinguistischen (C) und hybriden (D) Ansätzen?
\item \textbf{Methodologische Reflexion}: Wo liegen die Grenzen automatischer Verfahren im Vergleich zur interpretativen Kategorienbildung?
\end{enumerate}
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.
\section{Die acht Transkripte: Rohdaten und Terminalzeichen}
\subsection{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.
\subsubsection{Transkript 1 - Metzgerei}
\textbf{Datum:} 28. Juni 1994, \textbf{Ort:} Metzgerei, Aachen, 11:00 Uhr
\begin{lstlisting}[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!
\end{lstlisting}
\subsubsection{Transkript 2 - Marktplatz (Kirschen)}
\textbf{Datum:} 28. Juni 1994, \textbf{Ort:} Marktplatz, Aachen
\begin{lstlisting}[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!
\end{lstlisting}
\subsubsection{Transkript 3 - Fischstand}
\textbf{Datum:} 28. Juni 1994, \textbf{Ort:} Fischstand, Marktplatz, Aachen
\begin{lstlisting}[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!
\end{lstlisting}
\subsubsection{Transkript 4 - Gemüsestand (ausführlich)}
\textbf{Datum:} 28. Juni 1994, \textbf{Ort:} Gemüsestand, Aachen, Marktplatz, 11:00 Uhr
\begin{lstlisting}[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!
\end{lstlisting}
\subsubsection{Transkript 5 - Gemüsestand (mit KAV zu Beginn)}
\textbf{Datum:} 26. Juni 1994, \textbf{Ort:} Gemüsestand, Aachen, Marktplatz, 11:00 Uhr
\begin{lstlisting}[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!
\end{lstlisting}
\subsubsection{Transkript 6 - Käseverkaufsstand}
\textbf{Datum:} 28. Juni 1994, \textbf{Ort:} Käseverkaufsstand, Aachen, Marktplatz
\begin{lstlisting}[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.
\end{lstlisting}
\subsubsection{Transkript 7 - Bonbonstand}
\textbf{Datum:} 28. Juni 1994, \textbf{Ort:} Bonbonstand, Aachen, Marktplatz, 11:30 Uhr
\begin{lstlisting}[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!
\end{lstlisting}
\subsubsection{Transkript 8 - Bäckerei}
\textbf{Datum:} 9. Juli 1994, \textbf{Ort:} Bäckerei, Aachen, 12:00 Uhr
\begin{lstlisting}[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!
\end{lstlisting}
\subsection{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:
\begin{table}[h]
\centering
\caption{Terminalzeichenketten der acht Transkripte}
\label{tab:terminal_chains}
\begin{tabular}{@{} l l @{}}
\toprule
\textbf{Transkript} & \textbf{Terminalzeichenkette} \\
\midrule
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 \\
\bottomrule
\end{tabular}
\end{table}
Die Bedeutung der Terminalzeichen:
\begin{itemize}
\item \textbf{KBG}: Kunden-Gruß
\item \textbf{VBG}: Verkäufer-Gruß
\item \textbf{KBBd}: Kunden-Bedarf (konkret)
\item \textbf{VBBd}: Verkäufer-Nachfrage
\item \textbf{KBA}: Kunden-Antwort
\item \textbf{VBA}: Verkäufer-Reaktion
\item \textbf{KAE}: Kunden-Erkundigung
\item \textbf{VAE}: Verkäufer-Auskunft
\item \textbf{KAA}: Kunden-Abschluss
\item \textbf{VAA}: Verkäufer-Abschluss
\item \textbf{KAV}: Kunden-Verabschiedung
\item \textbf{VAV}: Verkäufer-Verabschiedung
\end{itemize}
\section{Szenario C: Computerlinguistische Integration}
Szenario C realisiert eine vollständig computerlinguistische Modellierung der acht Transkripte. Es umfasst vier Komponenten:
\begin{enumerate}
\item \textbf{Speech Act Recognition}: Automatische Erkennung der Sprechakte aus den Rohdaten
\item \textbf{Word Embeddings}: Vektorielle Repräsentation der Äußerungen
\item \textbf{Topic Modeling}: Identifikation thematischer Verschiebungen
\item \textbf{Rhetorical Structure Theory (RST)}: Analyse der argumentativen Struktur
\end{enumerate}
\subsection{Didaktische Augmentierung}
Da neuronale Netze für ihr Training große Datenmengen benötigen, werden die acht Transkripte zu Demonstrationszwecken augmentiert:
\begin{lstlisting}[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
\end{lstlisting}
\subsection{Speech Act Recognition mit Transformer-Modellen}
Die automatische Erkennung der Sprechakte erfolgt mit einem feinabgestimmten BERT-Modell:
\begin{lstlisting}[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")
\end{lstlisting}
\subsection{Word Embeddings und semantische Ähnlichkeit}
Für die Quantifizierung semantischer Ähnlichkeit werden vortrainierte Word Embeddings verwendet:
\begin{lstlisting}[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.")
\end{lstlisting}
\subsection{Topic Modeling mit BERTopic}
Für die Identifikation thematischer Verschiebungen wird BERTopic verwendet:
\begin{lstlisting}[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.")
\end{lstlisting}
\subsection{Rhetorical Structure Theory (RST)}
Für die Analyse der argumentativen Struktur wird ein RST-Parser implementiert:
\begin{lstlisting}[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")
\end{lstlisting}
\subsection{Integration der Komponenten in Szenario C}
Die vollständige Integration aller Komponenten in Szenario C:
\begin{lstlisting}[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'],