-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathARS20GramOpt_2.py
185 lines (155 loc) · 6.56 KB
/
ARS20GramOpt_2.py
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
import numpy as np
import random
from collections import defaultdict
from scipy.stats import pearsonr
from math import sqrt
# Beispielhafte empirische Daten
terminal_strings = [
"KBG VBG KBBd VBBd KBA VBA KBBd VBBd KBA VAA KAA VAV KAV",
"VBG KBBd VBBd VAA KAA VBG KBBd VAA KAA",
"KBBd VBBd VAA KAA",
"KBBd VBBd KBA VBA KBBd VBA KAE VAE KAA VAV KAV",
"KAV KBBd VBBd KBBd VAA KAV",
"KBG VBG KBBd VBBd KAA",
"KBBd VBBd KBA VAA KAA",
"KBG VBBd KBBd VBA VAA KAA VAV KAV"
]
# Zähle Häufigkeiten der Terminalzeichen
def count_terminal_frequencies(strings):
terminal_frequencies = defaultdict(int)
total_count = 0
for line in strings:
terms = line.split()
for term in terms:
terminal_frequencies[term] += 1
total_count += 1
# Normalisieren (relative Häufigkeit)
for term in terminal_frequencies:
terminal_frequencies[term] /= total_count
return terminal_frequencies
# Zähle Übergänge und berechne Übergangswahrscheinlichkeiten
def count_transitions(strings):
transition_counts = defaultdict(lambda: defaultdict(int))
for line in strings:
terms = line.split()
for i in range(len(terms) - 1):
from_term = terms[i]
to_term = terms[i + 1]
transition_counts[from_term][to_term] += 1
# Normalisiere die Übergänge zu Wahrscheinlichkeiten
normalized_matrix = {}
for from_term, transitions in transition_counts.items():
total = sum(transitions.values())
normalized_matrix[from_term] = {to_term: count / total for to_term, count in transitions.items()}
return normalized_matrix
# Erzeuge eine Terminalzeichenkette basierend auf den Übergangswahrscheinlichkeiten
def generate_from_cfg(grammar, start_symbol='KBG', max_depth=10):
current_symbol = start_symbol
generated_chain = []
for _ in range(max_depth):
if current_symbol not in grammar:
break
rules = grammar[current_symbol]
rule = random.choices(rules, weights=[float(r.split('P=')[-1][:-1]) for r in rules])[0]
rhs = rule.split('->')[-1].strip()
generated_chain.append(rhs)
current_symbol = rhs.split()[-1] # Wähle das letzte Symbol der rechten Seite der Regel
return " ".join(generated_chain)
# Berechne die Korrelation zwischen den empirischen Häufigkeiten und den generierten Häufigkeiten
def calculate_correlation(empirical_freqs, generated_freqs):
common_terms = set(empirical_freqs.keys()).intersection(generated_freqs.keys())
empirical_values = [empirical_freqs[term] for term in common_terms]
generated_values = [generated_freqs[term] for term in common_terms]
if len(empirical_values) > 1:
corr, p_value = pearsonr(empirical_values, generated_values)
return corr, p_value
return 0, 1 # Rückgabe der Korrelation und des p-Werts (1 für keine Korrelation)
# Berechne den Standardfehler der Korrelation
def standard_error(correlation, n):
return sqrt((1 - correlation**2) / (n - 2))
# Optimierung der Übergangswahrscheinlichkeiten
def optimize_grammar(terminal_strings, num_iterations=100, max_depth=10, tolerance=0.95):
# Initialisiere die Häufigkeiten und Übergangswahrscheinlichkeiten
empirical_freqs = count_terminal_frequencies(terminal_strings)
transition_counts = count_transitions(terminal_strings)
# Erstelle die Grammatik aus den Übergangszählungen
grammar = {}
for from_term, transitions in transition_counts.items():
rules = [f"{from_term} -> {to_term} [P={prob:.4f}]" for to_term, prob in transitions.items()]
grammar[from_term] = rules
# Iterative Optimierung
correlations = []
p_values = []
for iteration in range(num_iterations):
# Generiere eine Kette basierend auf der aktuellen Grammatik
generated_chain = generate_from_cfg(grammar, start_symbol="KBG", max_depth=max_depth)
generated_freqs = count_terminal_frequencies(generated_chain.split())
# Berechne die Korrelation zwischen den Häufigkeiten
correlation, p_value = calculate_correlation(empirical_freqs, generated_freqs)
correlations.append(correlation)
p_values.append(p_value)
# Berechne den Standardfehler der Korrelation
se = standard_error(correlation, len(empirical_freqs))
# Wenn die Korrelation die Toleranz erreicht und der p-Wert signifikant ist, abbrechen
if correlation > tolerance and p_value < 0.05:
break
# Optimiere die Übergangswahrscheinlichkeiten basierend auf der Korrelation
for from_term, transitions in transition_counts.items():
total_transitions = sum(transitions.values())
for to_term in transitions:
# Ändere die Übergangswahrscheinlichkeit basierend auf der Korrelation
transition_counts[from_term][to_term] *= 1 + 0.1 * (correlation - 0.5) # stärkere Anpassung
# Normalisiere die Übergangswahrscheinlichkeiten nach jeder Iteration
transition_counts = count_transitions(terminal_strings) # Normalisieren
# Berechne die finale Korrelation und den p-Wert
final_corr, final_p_value = calculate_correlation(empirical_freqs, generated_freqs)
return grammar, final_corr, final_p_value
# Optimierung durchführen
grammar, correlation, p_value = optimize_grammar(terminal_strings)
# Ausgabe der optimierten Grammatik, Korrelation und p-Wert
print("Optimierte Grammatik:")
for non_terminal, rules in grammar.items():
print(f"{non_terminal}:")
for rule in rules:
print(f" {rule}")
print("\nKorrelationskoeffizient:", correlation)
print("p-Wert:", p_value)
Optimierte Grammatik:
#KBG:
# KBG -> VBG [P=0.6667]
# KBG -> VBBd [P=0.3333]
#VBG:
# VBG -> KBBd [P=1.0000]
#KBBd:
# KBBd -> VBBd [P=0.6667]
# KBBd -> VAA [P=0.1667]
# KBBd -> VBA [P=0.1667]
#VBBd:
# VBBd -> KBA [P=0.4444]
# VBBd -> VAA [P=0.2222]
# VBBd -> KBBd [P=0.2222]
# VBBd -> KAA [P=0.1111]
#KBA:
# KBA -> VBA [P=0.5000]
# KBA -> VAA [P=0.5000]
#VBA:
# VBA -> KBBd [P=0.5000]
# VBA -> KAE [P=0.2500]
# VBA -> VAA [P=0.2500]
#VAA:
# VAA -> KAA [P=0.8571]
# VAA -> KAV [P=0.1429]
#KAA:
# KAA -> VAV [P=0.7500]
# KAA -> VBG [P=0.2500]
#VAV:
# VAV -> KAV [P=1.0000]
#KAE:
# KAE -> VAE [P=1.0000]
#VAE:
# VAE -> KAA [P=1.0000]
#KAV:
# KAV -> KBBd [P=1.0000]
#
#Korrelationskoeffizient: 0
#p-Wert: 1