Inhalt

Aktueller Ordner: /
📓 Jupyter Notebook - Kernel: Python (Pyodide)
📝 Markdown Zelle #1
Das linguistische Korpus in diesem Beispiel: Die Worte des Korpus sind durch Leerzeichen getrennt. Die Worte des Korpus sind Kategorien, die bei einer qualitativen Interpretation des Transkriptes eines Verkaufsgespräches den wechselnden Interakten von Käufer und Verkäufer zugeordnet 1993, 1994 wurden. Die Tondateien, die Transkripte, die Interpretationen und die erstellten Quellcodes (Induktor Scheme, Parser Pascal, Transduktor Lisp sind an dem Ort zum download frei verfügbar, an dem sich diese Jupyter Notebook Datei befindet).
📝 Markdown Zelle #2
Das Programm liest den Korpus aus einer Datei ein und extrahiert die Terminalsymbole, indem es alle Substrings sucht, die mit "K" oder "V" beginnen und aus mindestens einem Großbuchstaben bestehen. Die vorangestellten "K" oder "V" werden aus den Terminalsymbolen entfernt, um die Nonterminalsymbole zu erhalten. Dann werden die Regelproduktionen erstellt, indem für jedes Nonterminalsymbol alle Terminalsymbole gesammelt werden, die diesem Symbol entsprechen. Schließlich gibt das Programm die Grammatikregeln und das Startsymbol aus.
🧩 Code Zelle #3 [In [5]]
import re

# Lesen des Korpus aus einer Datei
#with open("VKGKORPUS.TXT", "r") as f:
#    korpus = f.read()
korpus = "KBG VBG KBBD VBBD KBA VBA KAE VAE KAA VAA KBBD VBBD KBA VBA KBBD VBBD KBA VBA KBBD VBBD KBA VBA KAE VAE KAA VAA KAV VAV"
# Extrahieren der Terminalsymbole aus dem Korpus
terminals = re.findall(r"[KV][A-Z]+", korpus)

# Entfernen der vorangestellten K- oder V-Zeichen aus den Terminalsymbolen
non_terminals = list(set([t[1:] for t in terminals]))

# Erzeugen der Regelproduktionen
productions = []
for nt in non_terminals:
    rhs = [t for t in terminals if t[1:] == nt]
    productions.append((nt, rhs))

# Ausgabe der Grammatikregeln
print("Regeln:")
for nt, rhs in productions:
    print(nt + " -> " + " | ".join(rhs))

# Ausgabe der Startsymbol
print("Startsymbol: VKG")
Output:
Regeln:
AV -> KAV | VAV
BG -> KBG | VBG
AA -> KAA | VAA | KAA | VAA
AE -> KAE | VAE | KAE | VAE
BA -> KBA | VBA | KBA | VBA | KBA | VBA | KBA | VBA
BBD -> KBBD | VBBD | KBBD | VBBD | KBBD | VBBD | KBBD | VBBD
Startsymbol: VKG
🧩 Code Zelle #4
📝 Markdown Zelle #5
Die Nonterminalsymbole sind hier jeweils die ersten Buchstaben der Terminalsymbole ohne das vorangestellte "K" oder "V". Die Startregel ist 'VK', was bedeutet, dass der Verkäufer (V) die Konversation beginnt und der Käufer (K) antwortet. Beachten Sie, dass die Produktionsregeln in beide Richtungen funktionieren, da die Konversation zwischen Verkäufer und Käufer wechselseitig ist.
🧩 Code Zelle #6 [In [6]]
import re
from collections import defaultdict

corpus = "KBG VBG KBBD VBBD KBA VBA KAE VAE KAA VAA KBBD VBBD KBA VBA KBBD VBBD KBA VBA KBBD VBBD KBA VBA KAE VAE KAA VAA KAV VAV"

# Erstellen eines Wörterbuchs, um die Anzahl der Vorkommen von Terminalsymbolden zu zählen.
vocab = defaultdict(int)
for word in corpus.split():
    vocab[word] += 1

# Entfernen von Präfixen K und V von Terminalsymbolen.
terminals = list(set([re.sub(r'^[KV]', '', w) for w in vocab.keys()]))

# Erstellen der Produktionen für die Grammatik.
productions = []
for w in vocab.keys():
    if re.match(r'^K', w):
        lhs = 'K'
    elif re.match(r'^V', w):
        lhs = 'V'
    else:
        lhs = re.sub(r'^[KV]', '', w)
    rhs = w
    productions.append((lhs, [rhs]))

# Erstellen der Startregel der Grammatik.
start = 'VK'

# Ausgabe der Grammatik.
print(f'Start: {start}')
for lhs, rhs in productions:
    print(f'{lhs} -> {" ".join(rhs)}')
Output:
Start: VK
K -> KBG
V -> VBG
K -> KBBD
V -> VBBD
K -> KBA
V -> VBA
K -> KAE
V -> VAE
K -> KAA
V -> VAA
K -> KAV
V -> VAV
📝 Markdown Zelle #7
Das Programm liest das gegebene Korpus ein und extrahiert die nicht-terminalen Symbole, indem es alle Symbole entfernt, die mit "K" oder "V" beginnen. Dann iteriert es über das Korpus und zählt die Produktionsregeln, indem es für jedes Vorkommen eines nicht-terminalen Symbols den nachfolgenden Terminalsymbol zählt. Schließlich berechnet es die Wahrscheinlichkeiten der Produktionsregeln, indem es die Häufigkeit jedes rechten Seiten eines nicht-terminalen Symbols durch die Gesamtanzahl der Vorkommen des linken Symbols dividiert.

Das Programm gibt dann die induzierte Grammatik aus, wobei die Wahrscheinlichkeiten der Produktionsregeln angezeigt werden.
🧩 Code Zelle #8 [In [7]]
from collections import defaultdict
import random

# define the grammar production rules
grammar = defaultdict(list)

# read in the corpus
corpus = "KBG VBG KBBD VBBD KBA VBA KAE VAE KAA VAA KBBD VBBD KBA VBA KBBD VBBD KBA VBA KBBD VBBD KBA VBA KAE VAE KAA VAA KAV VAV".split()

# get the non-terminal symbols
nonterminals = set([symbol[1:] for symbol in corpus if symbol.startswith("K") or symbol.startswith("V")])

# iterate over the corpus and count the production rules
for i in range(1, len(corpus)):
    curr_symbol = corpus[i]
    prev_symbol = corpus[i-1]
    if prev_symbol.startswith("K") or prev_symbol.startswith("V"):
        grammar[prev_symbol[1:]].append(curr_symbol)

# calculate the probabilities for the production rules
for lhs in grammar.keys():
    productions = grammar[lhs]
    total_count = len(productions)
    probabilities = defaultdict(float)
    for rhs in productions:
        probabilities[rhs] += 1.0
    for rhs in probabilities.keys():
        probabilities[rhs] /= total_count
    grammar[lhs] = probabilities

# print the grammar
print("Grammar:")
for lhs in grammar.keys():
    print(lhs + " ->")
    for rhs in grammar[lhs].keys():
        print("  " + rhs + " : " + str(grammar[lhs][rhs]))
Output:
Grammar:
BG ->
  VBG : 0.5
  KBBD : 0.5
BBD ->
  VBBD : 0.5
  KBA : 0.5
BA ->
  VBA : 0.5
  KAE : 0.25
  KBBD : 0.25
AE ->
  VAE : 0.5
  KAA : 0.5
AA ->
  VAA : 0.5
  KBBD : 0.25
  KAV : 0.25
AV ->
  VAV : 1.0
📝 Markdown Zelle #9
Hier ist ein Beispielprogramm in Python, das die gegebene probabilistische Grammatik nutzt, um das gegebene Korpus zu parsen:
🧩 Code Zelle #10
import random

# Die gegebene probabilistische Grammatik
grammar = {
    'BG': {'VBG': 0.5, 'KBBD': 0.5},
    'BBD': {'VBBD': 0.5, 'KBA': 0.5},
    'BA': {'VBA': 0.5, 'KAE': 0.25, 'KBBD': 0.25},
    'AE': {'VAE': 0.5, 'KAA': 0.5},
    'AA': {'VAA': 0.5, 'KAV': 0.25, 'KBBD': 0.25},
    'AV': {'VAV': 1.0},
}

# Das zu parsende Korpus
corpus = ['KBG', 'VBG', 'KBBG', 'VBBD', 'KAE', 'VBA', 'KAE', 'VAA', 'KBBG', 'VBBD', 'KBA', 'VBA', 'KBBG', 'VBBD', 'KBA', 'VBA', 'KAE', 'VAE', 'KAA', 'VAA', 'KAV', 'VAV']

# Initialisiere die Tabelle mit leeren Einträgen
chart = [[{} for i in range(len(corpus) + 1)] for j in range(len(corpus) + 1)]

# Fülle die Tabelle mit den Terminalsymbolen und den Wahrscheinlichkeiten
for i in range(len(corpus)):
    for lhs, rhs_probs in grammar.items():
        for rhs, prob in rhs_probs.items():
            if rhs == corpus[i]:
                chart[i][i+1][lhs] = {'prob': prob, 'prev': None}

# Fülle die Tabelle mit den Nichtterminalsymbolen und den Wahrscheinlichkeiten
for span in range(2, len(corpus) + 1):
    for start in range(len(corpus) - span + 1):
        end = start + span
        for split in range(start + 1, end):
            for lhs, rhs_probs in grammar.items():
                for rhs, prob in rhs_probs.items():
                    if len(rhs) == 2:
                        left, right = rhs
                        if left in chart[start][split] and right in chart[split][end]:
                            prod_prob = prob * chart[start][split][left]['prob'] * chart[split][end][right]['prob']
                            if lhs not in chart[start][end] or prod_prob > chart[start][end][lhs]['prob']:
                                chart[start][end][lhs] = {'prob': prod_prob, 'prev': (split, left, right)}

# Ausgabe des Parsing-Baums
def print_tree(start, end, symbol):
    if symbol in chart[start][end]:
        if chart[start][end][symbol]['prev'] is None:
            return [symbol]
        split, left, right = chart[start][end][symbol]['prev']
        return [symbol, print_tree(start, split, left), print_tree(split, end, right)]
    else:
        return []

# Parse den Satz und gib den resultierenden Parse-Baum aus
parse_tree = print_tree(0, len(corpus), 'BG')
print(parse_tree)
📝 Markdown Zelle #11
Eine probabilistische Grammatik kann als Bayessches Netz interpretiert werden. In einem Bayesschen Netz werden die Abhängigkeiten zwischen den Variablen durch gerichtete Kanten modelliert, während die Wahrscheinlichkeiten der einzelnen Variablen und Kanten durch Wahrscheinlichkeitsverteilungen dargestellt werden.

In einer probabilistischen Grammatik werden die Produktionsregeln als Variablen und die Terme und Nichtterminale als Zustände modelliert. Jede Produktion hat eine bestimmte Wahrscheinlichkeit, die durch eine Wahrscheinlichkeitsverteilung dargestellt werden kann. Die Wahrscheinlichkeit, einen bestimmten Satz zu generieren, kann dann durch die Produktionsregeln und deren Wahrscheinlichkeiten berechnet werden.

Die Zustände in der probabilistischen Grammatik können als Knoten im Bayesschen Netz interpretiert werden, während die Produktionsregeln als gerichtete Kanten dargestellt werden können. Die Wahrscheinlichkeiten der Produktionsregeln können dann als Kantenbedingungen modelliert werden. Durch die Berechnung der posterior Wahrscheinlichkeit kann dann eine probabilistische Vorhersage getroffen werden, welcher Satz am wahrscheinlichsten ist, gegeben die Beobachtungen.



📝 Markdown Zelle #12
Das Korpus kann als Protokoll der wechselseitigen Interaktion zweier Softwareagenten eines Multiagentensystems verstanden werden. Die Agenten dieses Multiagentensystems haben Zugriff auf das letzte generierte Terminalzeichen und die probabilistische Grammatik, die als Bayerisches Netz interpretiert werden kann. Dieses Wissen nutzen sie zur Generierung des nächsten Terminalzeichens. Ein Agent K generiert die Käufer-Terminalzeichen. Ein Agent V generiert die Verkäufer-Terminalzeichen.
📝 Markdown Zelle #13
Hier ist ein Beispielprogramm, das den Agenten K startet und das Terminalzeichen "KBG" setzt. Der Agent V generiert dann das nächste Terminalzeichen basierend auf der übergebenen Grammatik und dem letzten Terminalzeichen "KBG". Dies wird dann in einer Schleife fortgesetzt, bis eine maximale Anzahl von Terminalzeichen erreicht ist.
🧩 Code Zelle #14
import random

# Grammatik als probabilistisches Bayessches Netz definieren
grammar = {
    "BG": {"VBG": 0.5, "KBBD": 0.5},
    "BBD": {"VBBD": 0.5, "KBA": 0.5},
    "BA": {"VBA": 0.5, "KAE": 0.25, "KBBD": 0.25},
    "AE": {"VAE": 0.5, "KAA": 0.5},
    "AA": {"VAA": 0.5, "KBBD": 0.25, "KAV": 0.25},
    "AV": {"VAV": 1.0}
}

# Funktion zur Generierung des nächsten Terminalzeichens
def generate_next_terminal(grammar, last_terminal):
    # Wähle die Produktion basierend auf dem letzten Terminalzeichen und der Grammatik aus
    productions = grammar[last_terminal]
    production = random.choices(list(productions.keys()), list(productions.values()))[0]
    return production

# Maximale Anzahl von Terminalzeichen
max_length = 10

# Startzeichen für Agent K
last_terminal = "KBG"

# Schleife für Interaktion zwischen Agent K und Agent V
for i in range(max_length):
    # Agent K generiert das nächste Terminalzeichen basierend auf der Grammatik und dem letzten gesetzten Zeichen
    next_terminal = generate_next_terminal(grammar, last_terminal)
    print("Agent K: ", last_terminal)

    # Agent V generiert das nächste Terminalzeichen basierend auf der Grammatik und dem letzten gesetzten Zeichen
    last_terminal = generate_next_terminal(grammar, next_terminal)
    print("Agent V: ", next_terminal)

# Letztes Terminalzeichen ausgeben, das von Agent K generiert wurde
print("Letztes Terminalzeichen: ", last_terminal)
📝 Markdown Zelle #15
Agent K: KBG
Agent V: KBBD
Agent K: KBBD
Agent V: KAE
Agent K: KAE
Agent V: VAE
Agent K: VAE
Agent V: KAA
Agent K: KAA
Agent V: VAA
Agent K: VAA
Letztes Terminalzeichen: VAA