Upload 11 files
Browse files- config-classification-v6.txt +74 -0
- config-feedforward-v3.txt +73 -0
- config-feedforward-v4.txt +55 -0
- config-feedforward-v5.txt +74 -0
- config-feedforward.txt +71 -0
- quanta_classifier_v6.py +235 -0
- quanta_sim_v1_no_viz.py +189 -0
- quanta_sim_v2_input_dep.py +237 -0
- quanta_sim_v3_multi_input.py +235 -0
- quanta_sim_v4_correlated_outputs.py +287 -0
- quanta_sim_v5_nonlinear_simple.py +290 -0
config-classification-v6.txt
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# config-classification-v6.txt - Quanta Classifier V6 için Yapılandırma
|
| 2 |
+
# Veri Seti Üzerinde Sınıflandırma
|
| 3 |
+
|
| 4 |
+
[NEAT]
|
| 5 |
+
fitness_criterion = max
|
| 6 |
+
fitness_threshold = 0.98 # Hedef doğruluk oranı (%98) - Veriye göre ayarlanabilir
|
| 7 |
+
pop_size = 300 # Daha zor görev ve iyi CPU için artırıldı
|
| 8 |
+
reset_on_extinction = False
|
| 9 |
+
|
| 10 |
+
[DefaultGenome]
|
| 11 |
+
# node activation options
|
| 12 |
+
activation_default = sigmoid # Çıkış katmanı dahil sigmoid uygun
|
| 13 |
+
activation_mutate_rate = 0.1 # Aktivasyon mutasyonunu hafifçe açabiliriz (isteğe bağlı)
|
| 14 |
+
activation_options = sigmoid relu tanh clamped # Daha fazla seçenek ekleyebiliriz
|
| 15 |
+
|
| 16 |
+
# node aggregation options
|
| 17 |
+
aggregation_default = sum
|
| 18 |
+
aggregation_mutate_rate = 0.0
|
| 19 |
+
aggregation_options = sum
|
| 20 |
+
|
| 21 |
+
# node bias options (önceki gibi)
|
| 22 |
+
bias_init_mean = 0.0
|
| 23 |
+
bias_init_stdev = 1.0
|
| 24 |
+
bias_max_value = 30.0
|
| 25 |
+
bias_min_value = -30.0
|
| 26 |
+
bias_mutate_power = 0.5
|
| 27 |
+
bias_mutate_rate = 0.7
|
| 28 |
+
bias_replace_rate = 0.1
|
| 29 |
+
|
| 30 |
+
# genome compatibility options (önceki gibi)
|
| 31 |
+
compatibility_disjoint_coefficient = 1.0
|
| 32 |
+
compatibility_weight_coefficient = 0.5
|
| 33 |
+
|
| 34 |
+
# connection add/remove rates (önceki gibi)
|
| 35 |
+
conn_add_prob = 0.5
|
| 36 |
+
conn_delete_prob = 0.5
|
| 37 |
+
|
| 38 |
+
# connection enable options (önceki gibi)
|
| 39 |
+
enabled_default = True
|
| 40 |
+
enabled_mutate_rate = 0.01
|
| 41 |
+
|
| 42 |
+
feed_forward = True
|
| 43 |
+
initial_connection = full_nodirect
|
| 44 |
+
|
| 45 |
+
# node add/remove rates (önceki gibi)
|
| 46 |
+
node_add_prob = 0.2
|
| 47 |
+
node_delete_prob = 0.2
|
| 48 |
+
|
| 49 |
+
# network parameters
|
| 50 |
+
num_hidden = 0
|
| 51 |
+
num_inputs = 2 # Örnek veri setimiz için 2 özellik (feature)
|
| 52 |
+
num_outputs = 1 # Binary sınıflandırma için 1 sigmoid çıktı
|
| 53 |
+
|
| 54 |
+
# species options (önceki gibi)
|
| 55 |
+
species_fitness_func = max
|
| 56 |
+
max_stagnation = 25 # Stagnasyonu biraz artırabiliriz
|
| 57 |
+
species_set_size = 40 # Tür sayısını artırabiliriz
|
| 58 |
+
|
| 59 |
+
# weight options (önceki gibi)
|
| 60 |
+
weight_init_mean = 0.0
|
| 61 |
+
weight_init_stdev = 1.0
|
| 62 |
+
weight_max_value = 30
|
| 63 |
+
weight_min_value = -30
|
| 64 |
+
weight_mutate_power = 0.5
|
| 65 |
+
weight_mutate_rate = 0.8
|
| 66 |
+
weight_replace_rate = 0.1
|
| 67 |
+
|
| 68 |
+
[DefaultSpeciesSet]
|
| 69 |
+
compatibility_threshold = 3.0
|
| 70 |
+
|
| 71 |
+
[DefaultStagnation]
|
| 72 |
+
species_fitness_func = max
|
| 73 |
+
max_stagnation = 20 # Türler için stagnasyon (globalden farklı)
|
| 74 |
+
species_elitism = 2
|
config-feedforward-v3.txt
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# config-feedforward-v3.txt
|
| 2 |
+
|
| 3 |
+
[NEAT]
|
| 4 |
+
fitness_criterion = max
|
| 5 |
+
fitness_threshold = 0.98 # V3 için eşik, ayarlanabilir
|
| 6 |
+
pop_size = 150
|
| 7 |
+
reset_on_extinction = False
|
| 8 |
+
|
| 9 |
+
[DefaultGenome]
|
| 10 |
+
# node activation options
|
| 11 |
+
activation_default = sigmoid
|
| 12 |
+
activation_mutate_rate = 0.0
|
| 13 |
+
activation_options = sigmoid
|
| 14 |
+
|
| 15 |
+
# node aggregation options
|
| 16 |
+
aggregation_default = sum
|
| 17 |
+
aggregation_mutate_rate = 0.0
|
| 18 |
+
aggregation_options = sum
|
| 19 |
+
|
| 20 |
+
# node bias options
|
| 21 |
+
bias_init_mean = 0.0
|
| 22 |
+
bias_init_stdev = 1.0
|
| 23 |
+
bias_max_value = 30.0
|
| 24 |
+
bias_min_value = -30.0
|
| 25 |
+
bias_mutate_power = 0.5
|
| 26 |
+
bias_mutate_rate = 0.7
|
| 27 |
+
bias_replace_rate = 0.1
|
| 28 |
+
|
| 29 |
+
# genome compatibility options
|
| 30 |
+
compatibility_disjoint_coefficient = 1.0
|
| 31 |
+
compatibility_weight_coefficient = 0.5
|
| 32 |
+
|
| 33 |
+
# connection add/remove rates
|
| 34 |
+
conn_add_prob = 0.5
|
| 35 |
+
conn_delete_prob = 0.5
|
| 36 |
+
|
| 37 |
+
# connection enable options
|
| 38 |
+
enabled_default = True
|
| 39 |
+
enabled_mutate_rate = 0.01
|
| 40 |
+
|
| 41 |
+
feed_forward = True
|
| 42 |
+
initial_connection = full_nodirect # Başlangıçta girdilerle çıktılar arası bağlantı
|
| 43 |
+
|
| 44 |
+
# node add/remove rates
|
| 45 |
+
node_add_prob = 0.2
|
| 46 |
+
node_delete_prob = 0.2
|
| 47 |
+
|
| 48 |
+
# network parameters
|
| 49 |
+
num_hidden = 0
|
| 50 |
+
num_inputs = 2 # <-- YENİ DEĞER: Artık 2 girdimiz var
|
| 51 |
+
num_outputs = 1
|
| 52 |
+
|
| 53 |
+
# species options
|
| 54 |
+
species_fitness_func = max
|
| 55 |
+
max_stagnation = 20
|
| 56 |
+
species_set_size = 30
|
| 57 |
+
|
| 58 |
+
# weight options
|
| 59 |
+
weight_init_mean = 0.0
|
| 60 |
+
weight_init_stdev = 1.0
|
| 61 |
+
weight_max_value = 30
|
| 62 |
+
weight_min_value = -30
|
| 63 |
+
weight_mutate_power = 0.5
|
| 64 |
+
weight_mutate_rate = 0.8
|
| 65 |
+
weight_replace_rate = 0.1
|
| 66 |
+
|
| 67 |
+
[DefaultSpeciesSet]
|
| 68 |
+
compatibility_threshold = 3.0
|
| 69 |
+
|
| 70 |
+
[DefaultStagnation]
|
| 71 |
+
species_fitness_func = max
|
| 72 |
+
max_stagnation = 15
|
| 73 |
+
species_elitism = 2
|
config-feedforward-v4.txt
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# config-feedforward-v4.txt
|
| 2 |
+
|
| 3 |
+
[NEAT]
|
| 4 |
+
fitness_criterion = max
|
| 5 |
+
fitness_threshold = 0.96 # V4 için eşik, zorluk arttı, ayarlanabilir
|
| 6 |
+
pop_size = 200 # Daha zor problem için popülasyonu artırabiliriz
|
| 7 |
+
reset_on_extinction = False
|
| 8 |
+
|
| 9 |
+
[DefaultGenome]
|
| 10 |
+
# ... (V3'teki bias, activation, aggregation, compatibility, connection, enabled ayarları aynı kalabilir) ...
|
| 11 |
+
bias_init_mean = 0.0
|
| 12 |
+
bias_init_stdev = 1.0
|
| 13 |
+
bias_max_value = 30.0
|
| 14 |
+
bias_min_value = -30.0
|
| 15 |
+
bias_mutate_power = 0.5
|
| 16 |
+
bias_mutate_rate = 0.7
|
| 17 |
+
bias_replace_rate = 0.1
|
| 18 |
+
compatibility_disjoint_coefficient = 1.0
|
| 19 |
+
compatibility_weight_coefficient = 0.5
|
| 20 |
+
conn_add_prob = 0.5
|
| 21 |
+
conn_delete_prob = 0.5
|
| 22 |
+
enabled_default = True
|
| 23 |
+
enabled_mutate_rate = 0.01
|
| 24 |
+
feed_forward = True
|
| 25 |
+
initial_connection = full_nodirect
|
| 26 |
+
|
| 27 |
+
# node add/remove rates
|
| 28 |
+
node_add_prob = 0.3 # Biraz daha fazla yapısal çeşitlilik için artırılabilir
|
| 29 |
+
node_delete_prob = 0.2
|
| 30 |
+
|
| 31 |
+
# network parameters
|
| 32 |
+
num_hidden = 0
|
| 33 |
+
num_inputs = 2 # V3'teki gibi
|
| 34 |
+
num_outputs = 2 # <-- YENİ DEĞER: Artık 2 çıktımız var
|
| 35 |
+
|
| 36 |
+
# ... (V3'teki species, stagnation, weight ayarları aynı kalabilir) ...
|
| 37 |
+
species_fitness_func = max
|
| 38 |
+
max_stagnation = 20
|
| 39 |
+
species_set_size = 30
|
| 40 |
+
weight_init_mean = 0.0
|
| 41 |
+
weight_init_stdev = 1.0
|
| 42 |
+
weight_max_value = 30
|
| 43 |
+
weight_min_value = -30
|
| 44 |
+
weight_mutate_power = 0.5
|
| 45 |
+
weight_mutate_rate = 0.8
|
| 46 |
+
weight_replace_rate = 0.1
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
[DefaultSpeciesSet]
|
| 50 |
+
compatibility_threshold = 3.0
|
| 51 |
+
|
| 52 |
+
[DefaultStagnation]
|
| 53 |
+
species_fitness_func = max
|
| 54 |
+
max_stagnation = 15
|
| 55 |
+
species_elitism = 2
|
config-feedforward-v5.txt
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# config-feedforward-v5.txt - Quanta Simulator V5 için Yapılandırma
|
| 2 |
+
# Non-Linear Hedefler + Karmaşıklık Cezası
|
| 3 |
+
|
| 4 |
+
[NEAT]
|
| 5 |
+
fitness_criterion = max
|
| 6 |
+
fitness_threshold = 0.95 # V5 için hedef eşik (zorluk nedeniyle biraz düşük)
|
| 7 |
+
pop_size = 250 # Donanım (i7-12700H) için artırılmış popülasyon
|
| 8 |
+
reset_on_extinction = False
|
| 9 |
+
|
| 10 |
+
[DefaultGenome]
|
| 11 |
+
# node activation options
|
| 12 |
+
activation_default = sigmoid
|
| 13 |
+
activation_mutate_rate = 0.0
|
| 14 |
+
activation_options = sigmoid
|
| 15 |
+
|
| 16 |
+
# node aggregation options
|
| 17 |
+
aggregation_default = sum
|
| 18 |
+
aggregation_mutate_rate = 0.0
|
| 19 |
+
aggregation_options = sum
|
| 20 |
+
|
| 21 |
+
# node bias options
|
| 22 |
+
bias_init_mean = 0.0
|
| 23 |
+
bias_init_stdev = 1.0
|
| 24 |
+
bias_max_value = 30.0
|
| 25 |
+
bias_min_value = -30.0
|
| 26 |
+
bias_mutate_power = 0.5
|
| 27 |
+
bias_mutate_rate = 0.7
|
| 28 |
+
bias_replace_rate = 0.1
|
| 29 |
+
|
| 30 |
+
# genome compatibility options
|
| 31 |
+
compatibility_disjoint_coefficient = 1.0
|
| 32 |
+
compatibility_weight_coefficient = 0.5
|
| 33 |
+
|
| 34 |
+
# connection add/remove rates
|
| 35 |
+
conn_add_prob = 0.5
|
| 36 |
+
conn_delete_prob = 0.5
|
| 37 |
+
|
| 38 |
+
# connection enable options
|
| 39 |
+
enabled_default = True
|
| 40 |
+
enabled_mutate_rate = 0.01
|
| 41 |
+
|
| 42 |
+
feed_forward = True
|
| 43 |
+
initial_connection = full_nodirect
|
| 44 |
+
|
| 45 |
+
# node add/remove rates
|
| 46 |
+
node_add_prob = 0.3 # Yapısal çeşitlilik için biraz artırıldı
|
| 47 |
+
node_delete_prob = 0.2
|
| 48 |
+
|
| 49 |
+
# network parameters
|
| 50 |
+
num_hidden = 0 # Başlangıçta gizli düğüm yok
|
| 51 |
+
num_inputs = 2 # V5 için 2 girdi
|
| 52 |
+
num_outputs = 2 # V5 için 2 çıktı
|
| 53 |
+
|
| 54 |
+
# species options
|
| 55 |
+
species_fitness_func = max
|
| 56 |
+
max_stagnation = 20 # Türlerin gelişmeden kalabileceği max nesil
|
| 57 |
+
species_set_size = 30
|
| 58 |
+
|
| 59 |
+
# weight options
|
| 60 |
+
weight_init_mean = 0.0
|
| 61 |
+
weight_init_stdev = 1.0
|
| 62 |
+
weight_max_value = 30
|
| 63 |
+
weight_min_value = -30
|
| 64 |
+
weight_mutate_power = 0.5
|
| 65 |
+
weight_mutate_rate = 0.8
|
| 66 |
+
weight_replace_rate = 0.1
|
| 67 |
+
|
| 68 |
+
[DefaultSpeciesSet]
|
| 69 |
+
compatibility_threshold = 3.0
|
| 70 |
+
|
| 71 |
+
[DefaultStagnation]
|
| 72 |
+
species_fitness_func = max
|
| 73 |
+
max_stagnation = 15 # Türler için max_stagnation (globalden farklı olabilir)
|
| 74 |
+
species_elitism = 2 # Her türden sonraki nesle aktarılacak en iyi birey sayısı
|
config-feedforward.txt
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[NEAT]
|
| 2 |
+
fitness_criterion = max
|
| 3 |
+
fitness_threshold = 0.99 # Hedef fitness değeri (1.0'a ne kadar yakınsa o kadar iyi)
|
| 4 |
+
pop_size = 150 # Popülasyon büyüklüğü (Donanımına göre artırılabilir)
|
| 5 |
+
reset_on_extinction = False
|
| 6 |
+
|
| 7 |
+
[DefaultGenome]
|
| 8 |
+
# node activation options
|
| 9 |
+
activation_default = sigmoid
|
| 10 |
+
activation_mutate_rate = 0.0
|
| 11 |
+
activation_options = sigmoid
|
| 12 |
+
|
| 13 |
+
# node aggregation options
|
| 14 |
+
aggregation_default = sum
|
| 15 |
+
aggregation_mutate_rate = 0.0
|
| 16 |
+
aggregation_options = sum
|
| 17 |
+
|
| 18 |
+
# node bias options
|
| 19 |
+
bias_init_mean = 0.0
|
| 20 |
+
bias_init_stdev = 1.0
|
| 21 |
+
bias_max_value = 30.0
|
| 22 |
+
bias_min_value = -30.0
|
| 23 |
+
bias_mutate_power = 0.5
|
| 24 |
+
bias_mutate_rate = 0.7
|
| 25 |
+
bias_replace_rate = 0.1
|
| 26 |
+
|
| 27 |
+
# genome compatibility options
|
| 28 |
+
compatibility_disjoint_coefficient = 1.0
|
| 29 |
+
compatibility_weight_coefficient = 0.5
|
| 30 |
+
|
| 31 |
+
# connection add/remove rates
|
| 32 |
+
conn_add_prob = 0.5
|
| 33 |
+
conn_delete_prob = 0.5
|
| 34 |
+
|
| 35 |
+
# connection enable options
|
| 36 |
+
enabled_default = True
|
| 37 |
+
enabled_mutate_rate = 0.01
|
| 38 |
+
|
| 39 |
+
feed_forward = True # İleri beslemeli ağ
|
| 40 |
+
initial_connection = full_nodirect # Başlangıçta tam bağlı (girdi-çıktı arası)
|
| 41 |
+
|
| 42 |
+
# node add/remove rates
|
| 43 |
+
node_add_prob = 0.2 # Yeni düğüm ekleme olasılığı
|
| 44 |
+
node_delete_prob = 0.2 # Düğüm silme olasılığı
|
| 45 |
+
|
| 46 |
+
# network parameters
|
| 47 |
+
num_hidden = 0 # Başlangıçta gizli katman yok
|
| 48 |
+
num_inputs = 1 # Ağ girdisi sayısı (Şimdilik basit, tek sabit girdi)
|
| 49 |
+
num_outputs = 1 # Ağ çıktısı sayısı (Olasılığı temsil eden tek bir değer)
|
| 50 |
+
|
| 51 |
+
# species options
|
| 52 |
+
species_fitness_func = max
|
| 53 |
+
max_stagnation = 20 # Türlerin gelişmeden kalabileceği maksimum nesil sayısı
|
| 54 |
+
species_set_size = 30
|
| 55 |
+
|
| 56 |
+
# weight options
|
| 57 |
+
weight_init_mean = 0.0
|
| 58 |
+
weight_init_stdev = 1.0
|
| 59 |
+
weight_max_value = 30
|
| 60 |
+
weight_min_value = -30
|
| 61 |
+
weight_mutate_power = 0.5 # Mutasyonun ağırlığı ne kadar değiştireceği
|
| 62 |
+
weight_mutate_rate = 0.8 # Ağırlıkların mutasyona uğrama olasılığı
|
| 63 |
+
weight_replace_rate = 0.1 # Ağırlığın tamamen yeni bir değerle değişme olasılığı
|
| 64 |
+
|
| 65 |
+
[DefaultSpeciesSet]
|
| 66 |
+
compatibility_threshold = 3.0
|
| 67 |
+
|
| 68 |
+
[DefaultStagnation]
|
| 69 |
+
species_fitness_func = max
|
| 70 |
+
max_stagnation = 15
|
| 71 |
+
species_elitism = 2 # Her türden sonraki nesle aktarılacak en iyi birey sayısı
|
quanta_classifier_v6.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# quanta_classifier_v6.py
|
| 2 |
+
|
| 3 |
+
import neat
|
| 4 |
+
import numpy as np
|
| 5 |
+
import os
|
| 6 |
+
import logging
|
| 7 |
+
import pickle
|
| 8 |
+
import datetime
|
| 9 |
+
import traceback
|
| 10 |
+
|
| 11 |
+
# --- YENİ: Scikit-learn importları ---
|
| 12 |
+
from sklearn.datasets import make_classification
|
| 13 |
+
from sklearn.model_selection import train_test_split
|
| 14 |
+
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
|
| 15 |
+
|
| 16 |
+
# --- Loglama Ayarları ---
|
| 17 |
+
log_filename = f"quanta_log_v6_classifier_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
|
| 18 |
+
logging.basicConfig(
|
| 19 |
+
level=logging.INFO,
|
| 20 |
+
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
| 21 |
+
handlers=[
|
| 22 |
+
logging.FileHandler(log_filename),
|
| 23 |
+
logging.StreamHandler()
|
| 24 |
+
]
|
| 25 |
+
)
|
| 26 |
+
logger = logging.getLogger(__name__)
|
| 27 |
+
|
| 28 |
+
logger.info("="*70)
|
| 29 |
+
logger.info("Quanta Classifier Başlatılıyor (Sürüm 6 - Veri Seti ile Sınıflandırma)")
|
| 30 |
+
logger.info(f"Başlangıç Zamanı: {datetime.datetime.now()}")
|
| 31 |
+
logger.info("="*70)
|
| 32 |
+
|
| 33 |
+
# --- Global Değişkenler (Veri Seti) ---
|
| 34 |
+
# Not: Global değişkenler büyük projelerde önerilmez, ancak NEAT'in
|
| 35 |
+
# fitness fonksiyonuna kolayca veri aktarmak için bu örnekte kullanılmıştır.
|
| 36 |
+
# Daha büyük projelerde sınıf yapısı veya functools.partial tercih edilebilir.
|
| 37 |
+
X_train, X_test, y_train, y_test = None, None, None, None
|
| 38 |
+
|
| 39 |
+
# --- Veri Seti Oluşturma ve Hazırlama ---
|
| 40 |
+
def prepare_data(n_samples=500, n_features=2, n_informative=2, n_redundant=0, random_state=42):
|
| 41 |
+
"""
|
| 42 |
+
Scikit-learn kullanarak sentetik bir sınıflandırma veri seti oluşturur ve böler.
|
| 43 |
+
"""
|
| 44 |
+
global X_train, X_test, y_train, y_test
|
| 45 |
+
logger.info(f"{n_samples} örnekli, {n_features} özellikli sentetik veri seti oluşturuluyor...")
|
| 46 |
+
|
| 47 |
+
X, y = make_classification(
|
| 48 |
+
n_samples=n_samples,
|
| 49 |
+
n_features=n_features,
|
| 50 |
+
n_informative=n_informative,
|
| 51 |
+
n_redundant=n_redundant,
|
| 52 |
+
n_clusters_per_class=1, # Sınıf başına küme sayısı
|
| 53 |
+
flip_y=0.05, # Gürültü ekle (etiketlerin %5'ini ters çevir)
|
| 54 |
+
random_state=random_state
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
X_train, X_test, y_train, y_test = train_test_split(
|
| 58 |
+
X, y, test_size=0.3, random_state=random_state, stratify=y # Sınıf oranlarını koru
|
| 59 |
+
)
|
| 60 |
+
logger.info(f"Veri seti bölündü: {len(X_train)} eğitim, {len(X_test)} test örneği.")
|
| 61 |
+
logger.info(f"Girdi Boyutu (Özellik Sayısı): {X_train.shape[1]}")
|
| 62 |
+
logger.info(f"Sınıf Dağılımı (Eğitim): {np.bincount(y_train)}")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
# --- NEAT Fitness Fonksiyonu (Sınıflandırma için) ---
|
| 66 |
+
def eval_genomes_classification(genomes, config):
|
| 67 |
+
"""
|
| 68 |
+
Genomları eğitim verisi üzerindeki sınıflandırma doğruluğuna göre değerlendirir.
|
| 69 |
+
"""
|
| 70 |
+
global X_train, y_train # Global eğitim verisini kullan
|
| 71 |
+
|
| 72 |
+
if X_train is None or y_train is None:
|
| 73 |
+
logger.error("Eğitim verisi yüklenmemiş! Fitness hesaplanamıyor.")
|
| 74 |
+
# Tüm genomlara düşük fitness ver
|
| 75 |
+
for genome_id, genome in genomes:
|
| 76 |
+
genome.fitness = -1.0
|
| 77 |
+
return
|
| 78 |
+
|
| 79 |
+
for genome_id, genome in genomes:
|
| 80 |
+
genome.fitness = 0.0 # Başlangıç fitness
|
| 81 |
+
try:
|
| 82 |
+
net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| 83 |
+
except Exception as e:
|
| 84 |
+
logger.error(f"Genome {genome_id} ağ oluşturma hatası: {e}")
|
| 85 |
+
genome.fitness = -1.0 # Ceza
|
| 86 |
+
continue
|
| 87 |
+
|
| 88 |
+
correct_predictions = 0
|
| 89 |
+
# Eğitim verisi üzerinde tahmin yap
|
| 90 |
+
for xi, yi in zip(X_train, y_train):
|
| 91 |
+
try:
|
| 92 |
+
output = net.activate(xi)
|
| 93 |
+
# Binary sınıflandırma: Tek sigmoid çıkışı 0.5 eşiği ile yorumla
|
| 94 |
+
prediction = 1 if output[0] >= 0.5 else 0
|
| 95 |
+
if prediction == yi:
|
| 96 |
+
correct_predictions += 1
|
| 97 |
+
except Exception as e:
|
| 98 |
+
# logger.warning(f"G:{genome_id} Aktivasyon hatası: {e}")
|
| 99 |
+
pass # Hatalı aktivasyonları sayma
|
| 100 |
+
|
| 101 |
+
# Fitness = Doğruluk Oranı (Accuracy)
|
| 102 |
+
accuracy = correct_predictions / len(y_train)
|
| 103 |
+
genome.fitness = accuracy
|
| 104 |
+
# logger.debug(f"Genome {genome_id}: Accuracy = {accuracy:.4f}, Fitness = {genome.fitness:.4f}")
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
# --- NEAT Çalıştırma Fonksiyonu ---
|
| 108 |
+
def run_neat(config_file, generations=100):
|
| 109 |
+
"""
|
| 110 |
+
NEAT evrimini başlatır, yönetir ve sonucu değerlendirir.
|
| 111 |
+
"""
|
| 112 |
+
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| 113 |
+
config = None
|
| 114 |
+
try:
|
| 115 |
+
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| 116 |
+
neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| 117 |
+
config_file)
|
| 118 |
+
logger.info(f"Yapılandırma: Giriş={config.genome_config.num_inputs}, Çıkış={config.genome_config.num_outputs}, Pop={config.pop_size}, Eşik={config.fitness_threshold}")
|
| 119 |
+
# Yapılandırmadaki girdi sayısı ile veri setinin özellik sayısını kontrol et
|
| 120 |
+
if config.genome_config.num_inputs != X_train.shape[1]:
|
| 121 |
+
logger.error(f"Yapılandırma hatası: Config'deki girdi sayısı ({config.genome_config.num_inputs}) veri özelliği sayısı ({X_train.shape[1]}) ile eşleşmiyor!")
|
| 122 |
+
return None
|
| 123 |
+
# Binary sınıflandırma için çıktı sayısını kontrol et
|
| 124 |
+
if config.genome_config.num_outputs != 1:
|
| 125 |
+
logger.warning(f"Yapılandırma uyarısı: Binary sınıflandırma için çıktı sayısı ({config.genome_config.num_outputs}) genellikle 1 olmalıdır.")
|
| 126 |
+
|
| 127 |
+
except Exception as e:
|
| 128 |
+
logger.critical(f"Yapılandırma dosyası yüklenemedi: {config_file} - Hata: {e}")
|
| 129 |
+
return None
|
| 130 |
+
|
| 131 |
+
logger.info("Yeni popülasyon oluşturuluyor...")
|
| 132 |
+
p = neat.Population(config)
|
| 133 |
+
|
| 134 |
+
# Raporlayıcılar
|
| 135 |
+
p.add_reporter(neat.StdOutReporter(True)) # Konsola detaylı raporlama
|
| 136 |
+
stats = neat.StatisticsReporter() # İstatistikleri toplar (ileride görselleştirme için)
|
| 137 |
+
p.add_reporter(stats)
|
| 138 |
+
checkpoint_prefix = 'neat-checkpoint-v6-'
|
| 139 |
+
p.add_reporter(neat.Checkpointer(generation_interval=20, filename_prefix=checkpoint_prefix)) # 20 nesilde bir checkpoint
|
| 140 |
+
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| 141 |
+
|
| 142 |
+
logger.info(f"Evrim başlıyor (Maksimum {generations} nesil)...")
|
| 143 |
+
winner = None
|
| 144 |
+
try:
|
| 145 |
+
# Fitness fonksiyonunu (eval_genomes_classification) çalıştır
|
| 146 |
+
winner = p.run(eval_genomes_classification, generations)
|
| 147 |
+
logger.info(' ' + "="*30 + " Evrim Tamamlandı " + "="*30)
|
| 148 |
+
except Exception as e:
|
| 149 |
+
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| 150 |
+
logger.error(traceback.format_exc())
|
| 151 |
+
if not winner and p and p.best_genome:
|
| 152 |
+
logger.warning("Evrim hata ile durdu, bulunan son en iyi genom kullanılıyor.")
|
| 153 |
+
winner = p.best_genome
|
| 154 |
+
|
| 155 |
+
# En iyi genomu işle
|
| 156 |
+
if winner:
|
| 157 |
+
logger.info(f'En iyi genom bulundu/kullanıldı (Fitness - Eğitim Doğruluğu: {winner.fitness:.6f}):')
|
| 158 |
+
num_nodes = len(winner.nodes)
|
| 159 |
+
num_connections = len(winner.connections)
|
| 160 |
+
logger.info(f'Kazanan Karmaşıklığı: {num_nodes} Düğüm, {num_connections} Bağlantı')
|
| 161 |
+
|
| 162 |
+
# En iyi genomu kaydet
|
| 163 |
+
winner_filename = "winner_classifier_v6.pkl"
|
| 164 |
+
try:
|
| 165 |
+
with open(winner_filename, 'wb') as f:
|
| 166 |
+
pickle.dump(winner, f)
|
| 167 |
+
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| 168 |
+
except Exception as e:
|
| 169 |
+
logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| 170 |
+
|
| 171 |
+
# --- YENİ: En İyi Genomun TEST SETİ Üzerinde Değerlendirilmesi ---
|
| 172 |
+
logger.info(" " + "="*20 + " En İyi Genomun Test Seti Performansı " + "="*20)
|
| 173 |
+
try:
|
| 174 |
+
if config is None:
|
| 175 |
+
logger.error("Yapılandırma yüklenemediği için final test atlanıyor.")
|
| 176 |
+
raise RuntimeError("Config object is None.")
|
| 177 |
+
|
| 178 |
+
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| 179 |
+
|
| 180 |
+
# Test seti üzerinde tahmin yap
|
| 181 |
+
y_pred = []
|
| 182 |
+
logger.info(f"Test seti ({len(X_test)} örnek) üzerinde tahminler yapılıyor...")
|
| 183 |
+
for xi in X_test:
|
| 184 |
+
output = winner_net.activate(xi)
|
| 185 |
+
prediction = 1 if output[0] >= 0.5 else 0
|
| 186 |
+
y_pred.append(prediction)
|
| 187 |
+
|
| 188 |
+
# Performans metriklerini hesapla ve raporla
|
| 189 |
+
accuracy_test = accuracy_score(y_test, y_pred)
|
| 190 |
+
conf_matrix = confusion_matrix(y_test, y_pred)
|
| 191 |
+
class_report = classification_report(y_test, y_pred)
|
| 192 |
+
|
| 193 |
+
logger.info(f"\n--- Test Seti Sonuçları ---")
|
| 194 |
+
logger.info(f"Doğruluk (Accuracy): {accuracy_test:.4f}")
|
| 195 |
+
logger.info(f"\nKarışıklık Matrisi (Confusion Matrix):\n{conf_matrix}")
|
| 196 |
+
logger.info(f"\nSınıflandırma Raporu:\n{class_report}")
|
| 197 |
+
logger.info("---------------------------\n")
|
| 198 |
+
|
| 199 |
+
except Exception as e:
|
| 200 |
+
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| 201 |
+
logger.error(traceback.format_exc())
|
| 202 |
+
else:
|
| 203 |
+
logger.warning("Evrim sonunda test edilecek bir kazanan genom bulunamadı.")
|
| 204 |
+
|
| 205 |
+
logger.info("="*70)
|
| 206 |
+
logger.info("Quanta Classifier Adım 6 (Veri Seti ile Sınıflandırma) tamamlandı.")
|
| 207 |
+
logger.info(f"Bitiş Zamanı: {datetime.datetime.now()}")
|
| 208 |
+
logger.info("="*70)
|
| 209 |
+
# return winner
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
if __name__ == '__main__':
|
| 213 |
+
# Betiğin bulunduğu dizini al
|
| 214 |
+
local_dir = os.path.dirname(os.path.abspath(__file__))
|
| 215 |
+
# V6 config dosyasının tam yolunu oluştur
|
| 216 |
+
config_path = os.path.join(local_dir, 'config-classification-v6.txt')
|
| 217 |
+
|
| 218 |
+
if not os.path.exists(config_path):
|
| 219 |
+
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| 220 |
+
else:
|
| 221 |
+
try:
|
| 222 |
+
# 1. Veri setini hazırla
|
| 223 |
+
prepare_data(n_samples=1000, n_features=2, n_informative=2, random_state=123)
|
| 224 |
+
|
| 225 |
+
# 2. NEAT evrimini çalıştır (Config'deki eşiğe ulaşana kadar veya max nesil)
|
| 226 |
+
# MAX_GENERATIONS sabitini burada da tanımlayabiliriz:
|
| 227 |
+
MAX_GENERATIONS_RUN = 150 # Deneme için 150 nesil, gerekirse artırılır
|
| 228 |
+
run_neat(config_path, generations=MAX_GENERATIONS_RUN)
|
| 229 |
+
|
| 230 |
+
except ImportError as ie:
|
| 231 |
+
logger.critical(f"Gerekli kütüphane bulunamadı: {ie}")
|
| 232 |
+
logger.critical("Lütfen 'pip install scikit-learn numpy neat-python' komutu ile kurun.")
|
| 233 |
+
except Exception as main_e:
|
| 234 |
+
logger.critical(f"Ana program akışında beklenmedik bir hata oluştu: {main_e}")
|
| 235 |
+
logger.error(traceback.format_exc())
|
quanta_sim_v1_no_viz.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import neat
|
| 2 |
+
import numpy as np
|
| 3 |
+
import os
|
| 4 |
+
import logging
|
| 5 |
+
import pickle # En iyi genomu kaydetmek/yüklemek için
|
| 6 |
+
import random
|
| 7 |
+
import math
|
| 8 |
+
import datetime # Log dosyası ismi için
|
| 9 |
+
|
| 10 |
+
# --- Loglama Ayarları ---
|
| 11 |
+
log_filename = f"quanta_log_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
|
| 12 |
+
logging.basicConfig(
|
| 13 |
+
level=logging.INFO, # Log seviyesi (INFO, DEBUG, WARNING, ERROR, CRITICAL)
|
| 14 |
+
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s', # Log formatı
|
| 15 |
+
handlers=[
|
| 16 |
+
logging.FileHandler(log_filename), # Dosyaya loglama
|
| 17 |
+
logging.StreamHandler() # Konsola (ekrana) loglama
|
| 18 |
+
]
|
| 19 |
+
)
|
| 20 |
+
logger = logging.getLogger(__name__)
|
| 21 |
+
|
| 22 |
+
logger.info("="*50)
|
| 23 |
+
logger.info("Quanta Simülatörü Başlatılıyor (Görselleştirme Olmadan)")
|
| 24 |
+
logger.info("="*50)
|
| 25 |
+
|
| 26 |
+
# --- Simülasyon Parametreleri ---
|
| 27 |
+
TARGET_PROB_0 = 0.7 # Hedef: %70 olasılıkla 0 üretmek
|
| 28 |
+
TARGET_PROB_1 = 1.0 - TARGET_PROB_0 # Hedef: %30 olasılıkla 1 üretmek
|
| 29 |
+
NUM_TRIALS_PER_GENOME = 100 # Her genomu değerlendirmek için yapılacak deneme sayısı
|
| 30 |
+
MAX_GENERATIONS = 50 # Maksimum evrim nesli (Donanımınıza göre artırılabilir)
|
| 31 |
+
FITNESS_THRESHOLD = 0.99 # Evrimin durması için ulaşılması gereken minimum fitness
|
| 32 |
+
|
| 33 |
+
logger.info(f"Hedef P(0): {TARGET_PROB_0:.2f}, Hedef P(1): {TARGET_PROB_1:.2f}")
|
| 34 |
+
logger.info(f"Genom Başına Deneme Sayısı: {NUM_TRIALS_PER_GENOME}")
|
| 35 |
+
logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
|
| 36 |
+
logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
|
| 37 |
+
|
| 38 |
+
# --- Basit Kuantum Benzeri Davranış (Taklit) ---
|
| 39 |
+
# Bu fonksiyon, kuantum ölçümünün olasılıksal sonucunu basitçe taklit eder.
|
| 40 |
+
def simulate_simple_qubit_measurement(prob0=TARGET_PROB_0):
|
| 41 |
+
if random.random() < prob0:
|
| 42 |
+
return 0
|
| 43 |
+
else:
|
| 44 |
+
return 1
|
| 45 |
+
|
| 46 |
+
# --- NEAT Fitness Fonksiyonu ---
|
| 47 |
+
# Genomları (sinir ağlarını) değerlendirir.
|
| 48 |
+
# Hedef: Ağın çıktısı TARGET_PROB_0'a yakın olasılıkla 0 olmalı.
|
| 49 |
+
def eval_genomes(genomes, config):
|
| 50 |
+
"""
|
| 51 |
+
Popülasyondaki tüm genomların fitness değerlerini hesaplar.
|
| 52 |
+
"""
|
| 53 |
+
for genome_id, genome in genomes:
|
| 54 |
+
genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
|
| 55 |
+
try:
|
| 56 |
+
net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| 57 |
+
except Exception as e:
|
| 58 |
+
logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
|
| 59 |
+
genome.fitness = -1.0 # Geçersiz genomları cezalandır
|
| 60 |
+
continue
|
| 61 |
+
|
| 62 |
+
count_0 = 0
|
| 63 |
+
# Her genomu N kez test ederek istatistiksel olarak değerlendir
|
| 64 |
+
for _ in range(NUM_TRIALS_PER_GENOME):
|
| 65 |
+
# Ağ Girdisi: Şimdilik sabit bir değer (1.0) kullanıyoruz.
|
| 66 |
+
# Gelecekte bu girdi, simülasyonun durumunu veya kontrol parametrelerini yansıtabilir.
|
| 67 |
+
net_input = (1.0,)
|
| 68 |
+
try:
|
| 69 |
+
output = net.activate(net_input)
|
| 70 |
+
# Ağın çıktısını (genellikle 0-1 arası) yorumla
|
| 71 |
+
# Çıktı < 0.5 ise 0, >= 0.5 ise 1 kabul edelim
|
| 72 |
+
if output[0] < 0.5:
|
| 73 |
+
count_0 += 1
|
| 74 |
+
except Exception as e:
|
| 75 |
+
logger.warning(f"Genome {genome_id} ağ aktivasyonunda hata: {e}")
|
| 76 |
+
# Hata durumunda bu denemeyi atla veya penaltı ver
|
| 77 |
+
pass # Şimdilik sadece atlıyoruz
|
| 78 |
+
|
| 79 |
+
# Gözlemlenen olasılıkları hesapla
|
| 80 |
+
observed_prob_0 = count_0 / NUM_TRIALS_PER_GENOME
|
| 81 |
+
|
| 82 |
+
# Fitness Hesaplama: Hedef olasılıklara ne kadar yakın?
|
| 83 |
+
# Ortalama Karesel Hata (MSE) benzeri bir yaklaşım, ama ters çevrilmiş.
|
| 84 |
+
# Hata ne kadar küçükse, fitness o kadar yüksek olmalı.
|
| 85 |
+
error = (observed_prob_0 - TARGET_PROB_0) ** 2
|
| 86 |
+
# Fitness = 1 / (hata + epsilon) -> Hata sıfıra yaklaştıkça fitness sonsuza yaklaşır.
|
| 87 |
+
# Daha stabil bir fitness için: Fitness = 1.0 - hata (0 ile 1 arasında)
|
| 88 |
+
# Veya hedef eşiğe göre normalize edilebilir. Şimdilik basit tutalım:
|
| 89 |
+
fitness = max(0.0, 1.0 - math.sqrt(error)) # Hatanın karekökünü 1'den çıkaralım (0-1 arası)
|
| 90 |
+
|
| 91 |
+
genome.fitness = fitness
|
| 92 |
+
# logger.debug(f"Genome {genome_id}: Fitness = {fitness:.4f}, Gözlenen P(0) = {observed_prob_0:.2f}")
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
# --- NEAT Çalıştırma Fonksiyonu ---
|
| 96 |
+
def run_neat(config_file):
|
| 97 |
+
"""
|
| 98 |
+
NEAT evrimini başlatır ve yönetir.
|
| 99 |
+
"""
|
| 100 |
+
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| 101 |
+
try:
|
| 102 |
+
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| 103 |
+
neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| 104 |
+
config_file)
|
| 105 |
+
# Fitness eşiğini config dosyasından değil, koddan alalım
|
| 106 |
+
config.fitness_threshold = FITNESS_THRESHOLD
|
| 107 |
+
logger.info(f"Yapılandırma yüklendi. Fitness Eşiği: {config.fitness_threshold}")
|
| 108 |
+
|
| 109 |
+
except Exception as e:
|
| 110 |
+
logger.critical(f"Yapılandırma dosyası y��klenemedi veya geçersiz: {config_file} - Hata: {e}")
|
| 111 |
+
return None # Hata durumunda None döndür
|
| 112 |
+
|
| 113 |
+
logger.info("Yeni popülasyon oluşturuluyor...")
|
| 114 |
+
p = neat.Population(config)
|
| 115 |
+
|
| 116 |
+
# İstatistikleri ve loglamayı ayarlama (Sadece konsol çıktısı)
|
| 117 |
+
p.add_reporter(neat.StdOutReporter(True))
|
| 118 |
+
# Görselleştirme için istatistik toplayıcıya gerek yok.
|
| 119 |
+
# stats = neat.StatisticsReporter()
|
| 120 |
+
# p.add_reporter(stats)
|
| 121 |
+
|
| 122 |
+
# Periyodik olarak checkpoint (yedek) alma
|
| 123 |
+
checkpoint_prefix = 'neat-checkpoint-'
|
| 124 |
+
p.add_reporter(neat.Checkpointer(10, filename_prefix=checkpoint_prefix)) # Her 10 nesilde bir kaydet
|
| 125 |
+
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| 126 |
+
|
| 127 |
+
logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
|
| 128 |
+
try:
|
| 129 |
+
winner = p.run(eval_genomes, MAX_GENERATIONS)
|
| 130 |
+
logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
|
| 131 |
+
except Exception as e:
|
| 132 |
+
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| 133 |
+
# Belki son checkpoint'ten devam etme mantığı eklenebilir.
|
| 134 |
+
return None
|
| 135 |
+
|
| 136 |
+
# En iyi genomu göster/kaydet
|
| 137 |
+
logger.info(f'En iyi genom bulundu:')
|
| 138 |
+
logger.info(f' {winner}') # Konsola detaylı genom bilgisini yazdırır
|
| 139 |
+
|
| 140 |
+
# En iyi genomu dosyaya kaydet (pickle ile)
|
| 141 |
+
winner_filename = "winner_genome.pkl"
|
| 142 |
+
try:
|
| 143 |
+
with open(winner_filename, 'wb') as f:
|
| 144 |
+
pickle.dump(winner, f)
|
| 145 |
+
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| 146 |
+
except Exception as e:
|
| 147 |
+
logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| 148 |
+
|
| 149 |
+
# En iyi genomdan ağı oluştur ve son bir kez test et
|
| 150 |
+
logger.info(" " + "="*20 + " En İyi Genom Testi " + "="*20)
|
| 151 |
+
if winner:
|
| 152 |
+
try:
|
| 153 |
+
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| 154 |
+
test_count_0 = 0
|
| 155 |
+
test_trials = 1000 # Daha fazla deneme ile güvenilirliği artır
|
| 156 |
+
logger.info(f"En iyi ağ {test_trials} kez test ediliyor...")
|
| 157 |
+
for _ in range(test_trials):
|
| 158 |
+
net_input = (1.0,)
|
| 159 |
+
output = winner_net.activate(net_input)
|
| 160 |
+
if output[0] < 0.5:
|
| 161 |
+
test_count_0 += 1
|
| 162 |
+
|
| 163 |
+
observed_prob_0 = test_count_0 / test_trials
|
| 164 |
+
logger.info(f"Final Test Sonucu: Gözlenen P(0) = {observed_prob_0:.4f} (Hedef: {TARGET_PROB_0:.3f})")
|
| 165 |
+
logger.info(f"Final Test Sonucu: Gözlenen P(1) = {1.0 - observed_prob_0:.4f} (Hedef: {TARGET_PROB_1:.3f})")
|
| 166 |
+
final_error = (observed_prob_0 - TARGET_PROB_0) ** 2
|
| 167 |
+
logger.info(f"Final Test Hatası (Karesel): {final_error:.6f}")
|
| 168 |
+
except Exception as e:
|
| 169 |
+
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| 170 |
+
else:
|
| 171 |
+
logger.warning("Test edilecek bir kazanan genom bulunamadı.")
|
| 172 |
+
|
| 173 |
+
logger.info("="*50)
|
| 174 |
+
logger.info("Quanta Simülatörü Adım 1 (Görselleştirmesiz) tamamlandı.")
|
| 175 |
+
logger.info("="*50)
|
| 176 |
+
return winner # Kazanan genomu döndür
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
if __name__ == '__main__':
|
| 180 |
+
# Yapılandırma dosyasının yolu (Python betiği ile aynı klasörde olduğunu varsayar)
|
| 181 |
+
local_dir = os.path.dirname(__file__)
|
| 182 |
+
config_path = os.path.join(local_dir, 'config-feedforward.txt')
|
| 183 |
+
|
| 184 |
+
if not os.path.exists(config_path):
|
| 185 |
+
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| 186 |
+
logger.critical("Lütfen 'config-feedforward.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
|
| 187 |
+
else:
|
| 188 |
+
# NEAT'i çalıştır
|
| 189 |
+
run_neat(config_path)
|
quanta_sim_v2_input_dep.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# quanta_sim_v2_input_dep.py
|
| 2 |
+
|
| 3 |
+
import neat
|
| 4 |
+
import numpy as np
|
| 5 |
+
import os
|
| 6 |
+
import logging
|
| 7 |
+
import pickle
|
| 8 |
+
import random
|
| 9 |
+
import math
|
| 10 |
+
import datetime
|
| 11 |
+
# Görselleştirme importları YOKTUR.
|
| 12 |
+
|
| 13 |
+
# --- Loglama Ayarları ---
|
| 14 |
+
log_filename = f"quanta_log_v2_input_dep_{datetime.datetime.now():%Y%m%d_%H%M%S}.log" # <-- V2 için dosya adı
|
| 15 |
+
logging.basicConfig(
|
| 16 |
+
level=logging.INFO,
|
| 17 |
+
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
| 18 |
+
handlers=[
|
| 19 |
+
logging.FileHandler(log_filename),
|
| 20 |
+
logging.StreamHandler()
|
| 21 |
+
]
|
| 22 |
+
)
|
| 23 |
+
logger = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
logger.info("="*50)
|
| 26 |
+
logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 2 - Girdiye Bağlı Olasılık)") # <-- GÜNCELLENDİ
|
| 27 |
+
logger.info("="*50)
|
| 28 |
+
|
| 29 |
+
# --- Simülasyon Parametreleri ---
|
| 30 |
+
# TARGET_PROB_0 artık sabit değil, girdiye göre hesaplanacak.
|
| 31 |
+
# Bu yüzden aşağıdaki satırları kaldırabilir veya yorum satırı yapabiliriz.
|
| 32 |
+
# TARGET_PROB_0 = 0.7
|
| 33 |
+
# TARGET_PROB_1 = 1.0 - TARGET_PROB_0
|
| 34 |
+
|
| 35 |
+
NUM_TEST_INPUTS = 6 # Farklı girdi değerlerini test etmek için kullanılacak girdi sayısı
|
| 36 |
+
NUM_TRIALS_PER_INPUT = 20 # Her bir girdi değeri için yapılacak deneme sayısı
|
| 37 |
+
# Toplam deneme sayısı = NUM_TEST_INPUTS * NUM_TRIALS_PER_INPUT (örn: 6 * 20 = 120)
|
| 38 |
+
|
| 39 |
+
MAX_GENERATIONS = 100 # <-- Gerekirse artırılabilir, problem biraz daha zorlaştı.
|
| 40 |
+
FITNESS_THRESHOLD = 0.98 # <-- Hedef biraz daha zor olduğu için eşiği hafifçe düşürebiliriz (isteğe bağlı)
|
| 41 |
+
|
| 42 |
+
logger.info(f"Test Edilecek Girdi Sayısı: {NUM_TEST_INPUTS}")
|
| 43 |
+
logger.info(f"Girdi Başına Deneme Sayısı: {NUM_TRIALS_PER_INPUT}")
|
| 44 |
+
logger.info(f"Toplam Değerlendirme Denemesi/Genom: {NUM_TEST_INPUTS * NUM_TRIALS_PER_INPUT}")
|
| 45 |
+
logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
|
| 46 |
+
logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
|
| 47 |
+
|
| 48 |
+
# --- YENİ: Hedef Olasılık Fonksiyonu ---
|
| 49 |
+
def calculate_target_prob0(input_value):
|
| 50 |
+
"""
|
| 51 |
+
Verilen girdiye göre hedef P(0) olasılığını hesaplar.
|
| 52 |
+
Lineer Fonksiyon: target_P0(x) = 0.1 + 0.8 * x
|
| 53 |
+
"""
|
| 54 |
+
return 0.1 + 0.8 * input_value
|
| 55 |
+
|
| 56 |
+
logger.info(f"Hedef P(0) Fonksiyonu: P(0|x) = 0.1 + 0.8 * x")
|
| 57 |
+
|
| 58 |
+
# --- NEAT Fitness Fonksiyonu ---
|
| 59 |
+
# (Bu fonksiyon Sürüm 2 için önemli ölçüde güncellendi)
|
| 60 |
+
def eval_genomes(genomes, config):
|
| 61 |
+
"""
|
| 62 |
+
Popülasyondaki tüm genomların fitness değerlerini hesaplar.
|
| 63 |
+
Fitness, ağın farklı girdiler için hedeflenen olasılıkları
|
| 64 |
+
ne kadar iyi üretebildiğine göre belirlenir.
|
| 65 |
+
"""
|
| 66 |
+
# Test edilecek girdi değerlerini belirleyelim (0 ile 1 arasında eşit aralıklı)
|
| 67 |
+
test_inputs = np.linspace(0.0, 1.0, NUM_TEST_INPUTS)
|
| 68 |
+
# Örnek: NUM_TEST_INPUTS=6 ise -> [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
|
| 69 |
+
|
| 70 |
+
for genome_id, genome in genomes:
|
| 71 |
+
genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
|
| 72 |
+
try:
|
| 73 |
+
net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| 74 |
+
except Exception as e:
|
| 75 |
+
logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
|
| 76 |
+
genome.fitness = -10.0 # Daha büyük ceza verilebilir
|
| 77 |
+
continue
|
| 78 |
+
|
| 79 |
+
total_squared_error = 0.0
|
| 80 |
+
|
| 81 |
+
# Her bir test girdisi için ağı değerlendir
|
| 82 |
+
for net_input_val in test_inputs:
|
| 83 |
+
net_input = (net_input_val,) # Girdiyi tuple formatına getir
|
| 84 |
+
target_prob_0 = calculate_target_prob0(net_input_val) # Bu girdi için hedef P(0)
|
| 85 |
+
|
| 86 |
+
count_0 = 0
|
| 87 |
+
# Her girdi için N kez test et
|
| 88 |
+
for _ in range(NUM_TRIALS_PER_INPUT):
|
| 89 |
+
try:
|
| 90 |
+
output = net.activate(net_input)
|
| 91 |
+
# Ağın çıktısını yorumla (< 0.5 ise 0)
|
| 92 |
+
if output[0] < 0.5:
|
| 93 |
+
count_0 += 1
|
| 94 |
+
except Exception as e:
|
| 95 |
+
logger.warning(f"Genome {genome_id}, Input {net_input_val:.2f} ağ aktivasyonunda hata: {e}")
|
| 96 |
+
# Hata durumunda bu denemeyi atla veya penaltı ver
|
| 97 |
+
pass # Şimdilik sadece atlıyoruz
|
| 98 |
+
|
| 99 |
+
# Gözlemlenen olasılığı hesapla
|
| 100 |
+
if NUM_TRIALS_PER_INPUT > 0:
|
| 101 |
+
observed_prob_0 = count_0 / NUM_TRIALS_PER_INPUT
|
| 102 |
+
else:
|
| 103 |
+
observed_prob_0 = 0.5 # Sıfıra bölme hatasını önle (pek olası değil ama güvenli)
|
| 104 |
+
|
| 105 |
+
# Bu girdi için hatanın karesini hesapla
|
| 106 |
+
error = (observed_prob_0 - target_prob_0) ** 2
|
| 107 |
+
total_squared_error += error
|
| 108 |
+
|
| 109 |
+
# logger.debug(f" Genome {genome_id}, Input {net_input_val:.2f}: TargetP0={target_prob_0:.3f}, ObsP0={observed_prob_0:.3f}, Error^2={error:.4f}")
|
| 110 |
+
|
| 111 |
+
# Ortalama Karesel Hatayı (Mean Squared Error - MSE) hesapla
|
| 112 |
+
average_squared_error = total_squared_error / NUM_TEST_INPUTS
|
| 113 |
+
|
| 114 |
+
# Fitness'ı hesapla: Hata ne kadar küçükse, fitness o kadar yüksek (Maks 1.0)
|
| 115 |
+
# Hatanın karekökünü (RMSE gibi) 1'den çıkaralım
|
| 116 |
+
fitness = max(0.0, 1.0 - math.sqrt(average_squared_error))
|
| 117 |
+
|
| 118 |
+
genome.fitness = fitness
|
| 119 |
+
# logger.info(f"Genome {genome_id}: AvgError^2 = {average_squared_error:.4f}, Fitness = {fitness:.4f}")
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
# --- NEAT Çalıştırma Fonksiyonu ---
|
| 123 |
+
def run_neat(config_file):
|
| 124 |
+
"""
|
| 125 |
+
NEAT evrimini başlatır ve yönetir.
|
| 126 |
+
"""
|
| 127 |
+
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| 128 |
+
try:
|
| 129 |
+
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| 130 |
+
neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| 131 |
+
config_file)
|
| 132 |
+
# Fitness eşiğini config dosyasından değil, koddan alalım
|
| 133 |
+
config.fitness_threshold = FITNESS_THRESHOLD # <-- V2 için güncel eşik
|
| 134 |
+
logger.info(f"Yapılandırma yüklendi. Fitness Eşiği: {config.fitness_threshold}")
|
| 135 |
+
|
| 136 |
+
except Exception as e:
|
| 137 |
+
logger.critical(f"Yapılandırma dosyası yüklenemedi veya geçersiz: {config_file} - Hata: {e}")
|
| 138 |
+
return None
|
| 139 |
+
|
| 140 |
+
logger.info("Yeni popülasyon oluşturuluyor...")
|
| 141 |
+
p = neat.Population(config)
|
| 142 |
+
|
| 143 |
+
# İstatistikleri ve loglamayı ayarlama
|
| 144 |
+
p.add_reporter(neat.StdOutReporter(True)) # Konsola raporlama
|
| 145 |
+
# stats = neat.StatisticsReporter() # Görselleştirme YOK, bu yüzden buna gerek yok
|
| 146 |
+
# p.add_reporter(stats)
|
| 147 |
+
|
| 148 |
+
# Checkpoint (yedek) alma
|
| 149 |
+
checkpoint_prefix = 'neat-checkpoint-v2-' # <-- V2 için farklı prefix
|
| 150 |
+
p.add_reporter(neat.Checkpointer(10, filename_prefix=checkpoint_prefix))
|
| 151 |
+
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| 152 |
+
|
| 153 |
+
logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
|
| 154 |
+
try:
|
| 155 |
+
winner = p.run(eval_genomes, MAX_GENERATIONS)
|
| 156 |
+
logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
|
| 157 |
+
except Exception as e:
|
| 158 |
+
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| 159 |
+
return None
|
| 160 |
+
|
| 161 |
+
# En iyi genomu göster/kaydet
|
| 162 |
+
if winner:
|
| 163 |
+
logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
|
| 164 |
+
logger.info(f' {winner}') # Konsola detaylı genom bilgisini yazdırır
|
| 165 |
+
|
| 166 |
+
# En iyi genomu dosyaya kaydet (pickle ile)
|
| 167 |
+
winner_filename = "winner_genome_v2.pkl" # <-- V2 için farklı dosya adı
|
| 168 |
+
try:
|
| 169 |
+
with open(winner_filename, 'wb') as f:
|
| 170 |
+
pickle.dump(winner, f)
|
| 171 |
+
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| 172 |
+
except Exception as e:
|
| 173 |
+
logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| 174 |
+
|
| 175 |
+
# --- YENİ: En İyi Genomu Farklı Girdilerle Test Etme ---
|
| 176 |
+
logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi " + "="*20)
|
| 177 |
+
try:
|
| 178 |
+
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| 179 |
+
test_trials_final = 1000 # Her girdi için final test deneme sayısı
|
| 180 |
+
logger.info(f"En iyi ağ, farklı girdilerle {test_trials_final} kez test ediliyor...")
|
| 181 |
+
|
| 182 |
+
test_inputs_final = np.linspace(0.0, 1.0, 11) # Daha fazla ara noktayla test edelim (0.0, 0.1, ..., 1.0)
|
| 183 |
+
final_total_error_sq = 0.0
|
| 184 |
+
results = []
|
| 185 |
+
|
| 186 |
+
for net_input_val in test_inputs_final:
|
| 187 |
+
target_p0 = calculate_target_prob0(net_input_val)
|
| 188 |
+
net_input = (net_input_val,)
|
| 189 |
+
count_0 = 0
|
| 190 |
+
for _ in range(test_trials_final):
|
| 191 |
+
output = winner_net.activate(net_input)
|
| 192 |
+
if output[0] < 0.5:
|
| 193 |
+
count_0 += 1
|
| 194 |
+
|
| 195 |
+
observed_p0 = count_0 / test_trials_final
|
| 196 |
+
error_sq = (observed_p0 - target_p0) ** 2
|
| 197 |
+
final_total_error_sq += error_sq
|
| 198 |
+
results.append({
|
| 199 |
+
"input": net_input_val,
|
| 200 |
+
"target_p0": target_p0,
|
| 201 |
+
"observed_p0": observed_p0,
|
| 202 |
+
"error_sq": error_sq
|
| 203 |
+
})
|
| 204 |
+
logger.info(f" Input={net_input_val: <4.2f} -> TargetP(0)={target_p0: <5.3f}, ObservedP(0)={observed_p0: <5.3f}, Error^2={error_sq:.5f}")
|
| 205 |
+
|
| 206 |
+
final_avg_error_sq = final_total_error_sq / len(test_inputs_final)
|
| 207 |
+
final_rmse = math.sqrt(final_avg_error_sq)
|
| 208 |
+
logger.info("-" * 40)
|
| 209 |
+
logger.info(f"Final Ortalama Karesel Hata (MSE): {final_avg_error_sq:.6f}")
|
| 210 |
+
logger.info(f"Final Kök Ortalama Karesel Hata (RMSE): {final_rmse:.6f}")
|
| 211 |
+
logger.info(f"Final Fitness Yaklaşımı (1 - RMSE): {1.0 - final_rmse:.6f}")
|
| 212 |
+
logger.info("-" * 40)
|
| 213 |
+
|
| 214 |
+
except Exception as e:
|
| 215 |
+
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| 216 |
+
|
| 217 |
+
else:
|
| 218 |
+
logger.warning("Test edilecek bir kazanan genom bulunamadı.")
|
| 219 |
+
|
| 220 |
+
logger.info("="*50)
|
| 221 |
+
logger.info("Quanta Simülatörü Adım 2 (Girdiye Bağlı Olasılık) tamamlandı.")
|
| 222 |
+
logger.info("="*50)
|
| 223 |
+
return winner
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
if __name__ == '__main__':
|
| 227 |
+
# Yapılandırma dosyasının yolu (Python betiği ile aynı klasörde olduğunu varsayar)
|
| 228 |
+
local_dir = os.path.dirname(__file__)
|
| 229 |
+
# V1'deki config dosyasını kullanıyoruz, ismi aynı kalabilir.
|
| 230 |
+
config_path = os.path.join(local_dir, 'config-feedforward.txt')
|
| 231 |
+
|
| 232 |
+
if not os.path.exists(config_path):
|
| 233 |
+
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| 234 |
+
logger.critical("Lütfen 'config-feedforward.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
|
| 235 |
+
else:
|
| 236 |
+
# NEAT'i çalıştır
|
| 237 |
+
run_neat(config_path)
|
quanta_sim_v3_multi_input.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# quanta_sim_v3_multi_input.py
|
| 2 |
+
|
| 3 |
+
import neat
|
| 4 |
+
import numpy as np
|
| 5 |
+
import os
|
| 6 |
+
import logging
|
| 7 |
+
import pickle
|
| 8 |
+
import random
|
| 9 |
+
import math
|
| 10 |
+
import datetime
|
| 11 |
+
import itertools # <-- YENİ: Girdi kombinasyonları için
|
| 12 |
+
|
| 13 |
+
# --- Loglama Ayarları ---
|
| 14 |
+
log_filename = f"quanta_log_v3_multi_input_{datetime.datetime.now():%Y%m%d_%H%M%S}.log" # <-- V3 için dosya adı
|
| 15 |
+
logging.basicConfig(
|
| 16 |
+
level=logging.INFO,
|
| 17 |
+
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
| 18 |
+
handlers=[
|
| 19 |
+
logging.FileHandler(log_filename),
|
| 20 |
+
logging.StreamHandler()
|
| 21 |
+
]
|
| 22 |
+
)
|
| 23 |
+
logger = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
logger.info("="*50)
|
| 26 |
+
logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 3 - Çoklu Girdi)") # <-- GÜNCELLENDİ
|
| 27 |
+
logger.info("="*50)
|
| 28 |
+
|
| 29 |
+
# --- Simülasyon Parametreleri ---
|
| 30 |
+
NUM_TEST_VALUES_PER_AXIS = 3 # Her bir girdi ekseni için test edilecek değer sayısı (örn: 0.0, 0.5, 1.0)
|
| 31 |
+
NUM_TRIALS_PER_INPUT_PAIR = 20 # Her bir girdi çifti için yapılacak deneme sayısı
|
| 32 |
+
# Toplam test noktası sayısı = NUM_TEST_VALUES_PER_AXIS * NUM_TEST_VALUES_PER_AXIS
|
| 33 |
+
# Toplam değerlendirme denemesi/Genom = NUM_TEST_POINTS * NUM_TRIALS_PER_INPUT_PAIR
|
| 34 |
+
|
| 35 |
+
MAX_GENERATIONS = 150 # <-- Problem zorlaştığı için artırılabilir
|
| 36 |
+
FITNESS_THRESHOLD = 0.97 # <-- Hedef zorlaştığı için eşik ayarlanabilir
|
| 37 |
+
|
| 38 |
+
num_test_points = NUM_TEST_VALUES_PER_AXIS ** 2 # İki girdi olduğu için karesi
|
| 39 |
+
total_trials_per_genome = num_test_points * NUM_TRIALS_PER_INPUT_PAIR
|
| 40 |
+
|
| 41 |
+
logger.info(f"Eksen Başına Test Değeri Sayısı: {NUM_TEST_VALUES_PER_AXIS}")
|
| 42 |
+
logger.info(f"Toplam Test Girdi Çifti Sayısı: {num_test_points}")
|
| 43 |
+
logger.info(f"Girdi Çifti Başına Deneme Sayısı: {NUM_TRIALS_PER_INPUT_PAIR}")
|
| 44 |
+
logger.info(f"Toplam Değerlendirme Denemesi/Genom: {total_trials_per_genome}")
|
| 45 |
+
logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
|
| 46 |
+
logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
|
| 47 |
+
|
| 48 |
+
# --- YENİ: İki Girdi İçin Hedef Olasılık Fonksiyonu ---
|
| 49 |
+
def calculate_target_prob0(input1, input2):
|
| 50 |
+
"""
|
| 51 |
+
Verilen iki girdiye göre hedef P(0) olasılığını hesaplar.
|
| 52 |
+
Lineer Fonksiyon: target_P0(x1, x2) = 0.1 + 0.5*x1 + 0.3*x2
|
| 53 |
+
"""
|
| 54 |
+
# Değerlerin 0-1 aralığında kalmasını sağlayalım (isteğe bağlı, fonksiyona göre)
|
| 55 |
+
target = 0.1 + 0.5 * input1 + 0.3 * input2
|
| 56 |
+
return max(0.0, min(1.0, target)) # Güvenlik önlemi
|
| 57 |
+
|
| 58 |
+
logger.info(f"Hedef P(0) Fonksiyonu: P(0|x1, x2) = 0.1 + 0.5*x1 + 0.3*x2")
|
| 59 |
+
|
| 60 |
+
# --- NEAT Fitness Fonksiyonu ---
|
| 61 |
+
# (Bu fonksiyon Sürüm 3 için önemli ölçüde güncellendi)
|
| 62 |
+
def eval_genomes(genomes, config):
|
| 63 |
+
"""
|
| 64 |
+
Popülasyondaki tüm genomların fitness değerlerini hesaplar.
|
| 65 |
+
Fitness, ağın farklı girdi çiftleri için hedeflenen olasılıkları
|
| 66 |
+
ne kadar iyi üretebildiğine göre belirlenir.
|
| 67 |
+
"""
|
| 68 |
+
# Test edilecek girdi değerlerini her eksen için belirleyelim
|
| 69 |
+
axis_values = np.linspace(0.0, 1.0, NUM_TEST_VALUES_PER_AXIS)
|
| 70 |
+
# Örnek: NUM_TEST_VALUES_PER_AXIS=3 ise -> [0.0, 0.5, 1.0]
|
| 71 |
+
|
| 72 |
+
# Tüm girdi çiftlerini (kombinasyonlarını) oluşturalım
|
| 73 |
+
# Örnek: [(0.0, 0.0), (0.0, 0.5), (0.0, 1.0), (0.5, 0.0), ..., (1.0, 1.0)]
|
| 74 |
+
test_input_pairs = list(itertools.product(axis_values, repeat=2))
|
| 75 |
+
|
| 76 |
+
for genome_id, genome in genomes:
|
| 77 |
+
genome.fitness = 0.0 # Başlangıç fitness'ı sıfırla
|
| 78 |
+
try:
|
| 79 |
+
# İki girdili config ile ağı oluştur
|
| 80 |
+
net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| 81 |
+
except Exception as e:
|
| 82 |
+
logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
|
| 83 |
+
genome.fitness = -10.0
|
| 84 |
+
continue
|
| 85 |
+
|
| 86 |
+
total_squared_error = 0.0
|
| 87 |
+
|
| 88 |
+
# Her bir test girdi çifti için ağı değerlendir
|
| 89 |
+
for input_pair in test_input_pairs:
|
| 90 |
+
x1, x2 = input_pair # Girdi çiftini ayır
|
| 91 |
+
target_prob_0 = calculate_target_prob0(x1, x2) # Bu çift için hedef P(0)
|
| 92 |
+
|
| 93 |
+
count_0 = 0
|
| 94 |
+
# Her girdi çifti için N kez test et
|
| 95 |
+
for _ in range(NUM_TRIALS_PER_INPUT_PAIR):
|
| 96 |
+
try:
|
| 97 |
+
# Ağı iki girdi ile aktive et
|
| 98 |
+
output = net.activate(input_pair)
|
| 99 |
+
# Ağın çıktısını yorumla (< 0.5 ise 0)
|
| 100 |
+
if output[0] < 0.5:
|
| 101 |
+
count_0 += 1
|
| 102 |
+
except Exception as e:
|
| 103 |
+
logger.warning(f"Genome {genome_id}, Input {input_pair} ağ aktivasyonunda hata: {e}")
|
| 104 |
+
pass
|
| 105 |
+
|
| 106 |
+
# Gözlemlenen olasılığı hesapla
|
| 107 |
+
if NUM_TRIALS_PER_INPUT_PAIR > 0:
|
| 108 |
+
observed_prob_0 = count_0 / NUM_TRIALS_PER_INPUT_PAIR
|
| 109 |
+
else:
|
| 110 |
+
observed_prob_0 = 0.5
|
| 111 |
+
|
| 112 |
+
# Bu girdi çifti için hatanın karesini hesapla
|
| 113 |
+
error = (observed_prob_0 - target_prob_0) ** 2
|
| 114 |
+
total_squared_error += error
|
| 115 |
+
|
| 116 |
+
# Ortalama Karesel Hatayı (Mean Squared Error - MSE) hesapla
|
| 117 |
+
average_squared_error = total_squared_error / len(test_input_pairs)
|
| 118 |
+
|
| 119 |
+
# Fitness'ı hesapla (1 - RMSE)
|
| 120 |
+
fitness = max(0.0, 1.0 - math.sqrt(average_squared_error))
|
| 121 |
+
genome.fitness = fitness
|
| 122 |
+
# logger.info(f"Genome {genome_id}: AvgError^2 = {average_squared_error:.4f}, Fitness = {fitness:.4f}")
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
# --- NEAT Çalıştırma Fonksiyonu ---
|
| 126 |
+
def run_neat(config_file):
|
| 127 |
+
"""
|
| 128 |
+
NEAT evrimini başlatır ve yönetir.
|
| 129 |
+
"""
|
| 130 |
+
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| 131 |
+
try:
|
| 132 |
+
# V3 config dosyasını kullanarak config nesnesini oluştur
|
| 133 |
+
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| 134 |
+
neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| 135 |
+
config_file) # <-- config_file şimdi v3 dosyasını gösteriyor
|
| 136 |
+
config.fitness_threshold = FITNESS_THRESHOLD
|
| 137 |
+
logger.info(f"Yapılandırma yüklendi. Giriş Sayısı: {config.genome_config.num_inputs}, Fitness Eşiği: {config.fitness_threshold}")
|
| 138 |
+
|
| 139 |
+
except Exception as e:
|
| 140 |
+
logger.critical(f"Yapılandırma dosyası yüklenemedi veya geçersiz: {config_file} - Hata: {e}")
|
| 141 |
+
return None
|
| 142 |
+
|
| 143 |
+
logger.info("Yeni popülasyon oluşturuluyor...")
|
| 144 |
+
p = neat.Population(config)
|
| 145 |
+
|
| 146 |
+
# Raporlayıcılar
|
| 147 |
+
p.add_reporter(neat.StdOutReporter(True))
|
| 148 |
+
# Checkpoint
|
| 149 |
+
checkpoint_prefix = 'neat-checkpoint-v3-' # <-- V3 için prefix
|
| 150 |
+
p.add_reporter(neat.Checkpointer(15, filename_prefix=checkpoint_prefix)) # Daha seyrek kaydedilebilir
|
| 151 |
+
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| 152 |
+
|
| 153 |
+
logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
|
| 154 |
+
try:
|
| 155 |
+
winner = p.run(eval_genomes, MAX_GENERATIONS)
|
| 156 |
+
logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
|
| 157 |
+
except Exception as e:
|
| 158 |
+
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| 159 |
+
return None
|
| 160 |
+
|
| 161 |
+
# En iyi genomu işle
|
| 162 |
+
if winner:
|
| 163 |
+
logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
|
| 164 |
+
logger.info(f' {winner}')
|
| 165 |
+
|
| 166 |
+
# En iyi genomu kaydet
|
| 167 |
+
winner_filename = "winner_genome_v3.pkl" # <-- V3 için dosya adı
|
| 168 |
+
try:
|
| 169 |
+
with open(winner_filename, 'wb') as f:
|
| 170 |
+
pickle.dump(winner, f)
|
| 171 |
+
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| 172 |
+
except Exception as e:
|
| 173 |
+
logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| 174 |
+
|
| 175 |
+
# --- YENİ: En İyi Genomu Çoklu Girdi İle Detaylı Test Etme ---
|
| 176 |
+
logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi (Çoklu Girdi) " + "="*20)
|
| 177 |
+
try:
|
| 178 |
+
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| 179 |
+
test_trials_final = 500 # Final test için deneme sayısı
|
| 180 |
+
logger.info(f"En iyi ağ, farklı girdi çiftleriyle {test_trials_final} kez test ediliyor...")
|
| 181 |
+
|
| 182 |
+
# Daha hassas bir girdi ızgarası oluşturalım (örn: 5x5 = 25 nokta)
|
| 183 |
+
final_axis_values = np.linspace(0.0, 1.0, 5)
|
| 184 |
+
final_test_pairs = list(itertools.product(final_axis_values, repeat=2))
|
| 185 |
+
final_total_error_sq = 0.0
|
| 186 |
+
|
| 187 |
+
logger.info(f"{'Input (x1,x2)': <15} {'Target P(0)': <12} {'Observed P(0)': <14} {'Error^2': <10}")
|
| 188 |
+
logger.info("-" * 60)
|
| 189 |
+
|
| 190 |
+
for input_pair in final_test_pairs:
|
| 191 |
+
x1, x2 = input_pair
|
| 192 |
+
target_p0 = calculate_target_prob0(x1, x2)
|
| 193 |
+
count_0 = 0
|
| 194 |
+
for _ in range(test_trials_final):
|
| 195 |
+
output = winner_net.activate(input_pair)
|
| 196 |
+
if output[0] < 0.5:
|
| 197 |
+
count_0 += 1
|
| 198 |
+
|
| 199 |
+
observed_p0 = count_0 / test_trials_final
|
| 200 |
+
error_sq = (observed_p0 - target_p0) ** 2
|
| 201 |
+
final_total_error_sq += error_sq
|
| 202 |
+
|
| 203 |
+
logger.info(f"({x1:.2f}, {x2:.2f}) {target_p0:<12.3f} {observed_p0:<14.3f} {error_sq:<10.5f}")
|
| 204 |
+
|
| 205 |
+
final_avg_error_sq = final_total_error_sq / len(final_test_pairs)
|
| 206 |
+
final_rmse = math.sqrt(final_avg_error_sq)
|
| 207 |
+
logger.info("-" * 60)
|
| 208 |
+
logger.info(f"Final Ortalama Karesel Hata (MSE): {final_avg_error_sq:.6f}")
|
| 209 |
+
logger.info(f"Final Kök Ortalama Karesel Hata (RMSE): {final_rmse:.6f}")
|
| 210 |
+
logger.info(f"Final Fitness Yaklaşımı (1 - RMSE): {1.0 - final_rmse:.6f}")
|
| 211 |
+
logger.info("-" * 60)
|
| 212 |
+
|
| 213 |
+
except Exception as e:
|
| 214 |
+
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| 215 |
+
|
| 216 |
+
else:
|
| 217 |
+
logger.warning("Test edilecek bir kazanan genom bulunamadı.")
|
| 218 |
+
|
| 219 |
+
logger.info("="*50)
|
| 220 |
+
logger.info("Quanta Simülatörü Adım 3 (Çoklu Girdi) tamamlandı.")
|
| 221 |
+
logger.info("="*50)
|
| 222 |
+
return winner
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
if __name__ == '__main__':
|
| 226 |
+
# V3 için yeni yapılandırma dosyasının yolu
|
| 227 |
+
local_dir = os.path.dirname(__file__)
|
| 228 |
+
config_path = os.path.join(local_dir, 'config-feedforward-v3.txt') # <-- YENİ Config Dosyası
|
| 229 |
+
|
| 230 |
+
if not os.path.exists(config_path):
|
| 231 |
+
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| 232 |
+
logger.critical("Lütfen 'config-feedforward-v3.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
|
| 233 |
+
else:
|
| 234 |
+
# NEAT'i çalıştır
|
| 235 |
+
run_neat(config_path)
|
quanta_sim_v4_correlated_outputs.py
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# quanta_sim_v4_correlated_outputs.py
|
| 2 |
+
|
| 3 |
+
import neat
|
| 4 |
+
import numpy as np
|
| 5 |
+
import os
|
| 6 |
+
import logging
|
| 7 |
+
import pickle
|
| 8 |
+
import random
|
| 9 |
+
import math
|
| 10 |
+
import datetime
|
| 11 |
+
import itertools
|
| 12 |
+
|
| 13 |
+
# --- Loglama Ayarları ---
|
| 14 |
+
log_filename = f"quanta_log_v4_corr_{datetime.datetime.now():%Y%m%d_%H%M%S}.log" # <-- V4 için dosya adı
|
| 15 |
+
logging.basicConfig(
|
| 16 |
+
level=logging.INFO, # DEBUG seviyesi daha fazla bilgi verir ama yavaşlatabilir
|
| 17 |
+
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
| 18 |
+
handlers=[
|
| 19 |
+
logging.FileHandler(log_filename),
|
| 20 |
+
logging.StreamHandler()
|
| 21 |
+
]
|
| 22 |
+
)
|
| 23 |
+
logger = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
logger.info("="*70)
|
| 26 |
+
logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 4 - Korelasyonlu Çıktılar)") # <-- GÜNCELLENDİ
|
| 27 |
+
logger.info("="*70)
|
| 28 |
+
|
| 29 |
+
# --- Simülasyon Parametreleri ---
|
| 30 |
+
NUM_TEST_VALUES_PER_AXIS = 3 # Değerlendirme için ızgara boyutu (3x3=9 nokta)
|
| 31 |
+
NUM_TRIALS_PER_PAIR = 30 # Her girdi çifti için deneme sayısı (artırıldı)
|
| 32 |
+
|
| 33 |
+
MAX_GENERATIONS = 250 # <-- Problem çok daha zor, nesil sayısı artırıldı
|
| 34 |
+
FITNESS_THRESHOLD = 0.97 # <-- Hedef zor, eşik ayarlanabilir
|
| 35 |
+
|
| 36 |
+
num_test_points = NUM_TEST_VALUES_PER_AXIS ** 2
|
| 37 |
+
total_trials_per_genome = num_test_points * NUM_TRIALS_PER_PAIR
|
| 38 |
+
|
| 39 |
+
# Fitness fonksiyonundaki hata ağırlıkları
|
| 40 |
+
W_PA0 = 1.0 # P(A=0) hatasının ağırlığı
|
| 41 |
+
W_PB0 = 1.0 # P(B=0) hatasının ağırlığı
|
| 42 |
+
W_CORR = 1.5 # Korelasyon hatasının ağırlığı (genellikle daha zordur, ağırlığı artırılabilir)
|
| 43 |
+
TOTAL_WEIGHT = W_PA0 + W_PB0 + W_CORR
|
| 44 |
+
|
| 45 |
+
logger.info(f"Eksen Başına Test Değeri: {NUM_TEST_VALUES_PER_AXIS} ({num_test_points} test noktası)")
|
| 46 |
+
logger.info(f"Girdi Çifti Başına Deneme: {NUM_TRIALS_PER_PAIR} (Toplam {total_trials_per_genome} deneme/genom)")
|
| 47 |
+
logger.info(f"Maksimum Nesil: {MAX_GENERATIONS}")
|
| 48 |
+
logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
|
| 49 |
+
logger.info(f"Fitness Hata Ağırlıkları: P(A=0)={W_PA0:.1f}, P(B=0)={W_PB0:.1f}, Corr={W_CORR:.1f}")
|
| 50 |
+
|
| 51 |
+
# --- YENİ: Hedef Fonksiyonları (P(A=0), P(B=0), Korelasyon) ---
|
| 52 |
+
def target_PA0(x1, x2):
|
| 53 |
+
return 0.2 + 0.6 * x1
|
| 54 |
+
|
| 55 |
+
def target_PB0(x1, x2):
|
| 56 |
+
return 0.7 - 0.5 * x2
|
| 57 |
+
|
| 58 |
+
def target_Corr(x1, x2):
|
| 59 |
+
# Hedef korelasyon (-1 ile +1 arasında olmalı)
|
| 60 |
+
return -0.8 * x1 * x2
|
| 61 |
+
|
| 62 |
+
logger.info(f"Hedef P(A=0|x1,x2) = 0.2 + 0.6*x1")
|
| 63 |
+
logger.info(f"Hedef P(B=0|x1,x2) = 0.7 - 0.5*x2")
|
| 64 |
+
logger.info(f"Hedef Corr(A,B|x1,x2) = -0.8 * x1 * x2")
|
| 65 |
+
|
| 66 |
+
# --- Korelasyon Hesaplama Yardımcı Fonksiyonu ---
|
| 67 |
+
def calculate_correlation(pA0, pB0, pA0B0, epsilon=1e-9):
|
| 68 |
+
""" Verilen olasılıklardan korelasyonu hesaplar. """
|
| 69 |
+
pA1 = 1.0 - pA0
|
| 70 |
+
pB1 = 1.0 - pB0
|
| 71 |
+
|
| 72 |
+
# Kovaryans = P(A=0,B=0) - P(A=0)*P(B=0)
|
| 73 |
+
covariance = pA0B0 - pA0 * pB0
|
| 74 |
+
|
| 75 |
+
# Standart sapmaların karesi (varyanslar)
|
| 76 |
+
varA = pA0 * pA1
|
| 77 |
+
varB = pB0 * pB1
|
| 78 |
+
|
| 79 |
+
# Sıfıra bölme hatasını önlemek için epsilon ekle
|
| 80 |
+
denominator = math.sqrt((varA + epsilon) * (varB + epsilon))
|
| 81 |
+
|
| 82 |
+
if denominator < epsilon: # Eğer varyans çok küçükse (olasılıklar 0 veya 1'e çok yakınsa)
|
| 83 |
+
return 0.0 # Korelasyon anlamsızdır veya sıfırdır
|
| 84 |
+
|
| 85 |
+
correlation = covariance / denominator
|
| 86 |
+
# Korelasyonun teorik olarak -1 ile 1 arasında kalmasını sağla (küçük hatalar olabilir)
|
| 87 |
+
return max(-1.0, min(1.0, correlation))
|
| 88 |
+
|
| 89 |
+
# --- NEAT Fitness Fonksiyonu ---
|
| 90 |
+
# (Bu fonksiyon Sürüm 4 için önemli ölçüde güncellendi)
|
| 91 |
+
def eval_genomes(genomes, config):
|
| 92 |
+
"""
|
| 93 |
+
Popülasyondaki genomların fitness'ını hesaplar. Fitness, ağın
|
| 94 |
+
P(A=0), P(B=0) ve Corr(A,B) hedeflerini farklı girdilerde
|
| 95 |
+
ne kadar iyi yakaladığına göre belirlenir.
|
| 96 |
+
"""
|
| 97 |
+
axis_values = np.linspace(0.0, 1.0, NUM_TEST_VALUES_PER_AXIS)
|
| 98 |
+
test_input_pairs = list(itertools.product(axis_values, repeat=2))
|
| 99 |
+
|
| 100 |
+
for genome_id, genome in genomes:
|
| 101 |
+
genome.fitness = 0.0
|
| 102 |
+
try:
|
| 103 |
+
net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| 104 |
+
except Exception as e:
|
| 105 |
+
logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
|
| 106 |
+
genome.fitness = -20.0 # Daha büyük ceza
|
| 107 |
+
continue
|
| 108 |
+
|
| 109 |
+
total_weighted_error_sum = 0.0
|
| 110 |
+
|
| 111 |
+
for input_pair in test_input_pairs:
|
| 112 |
+
x1, x2 = input_pair
|
| 113 |
+
targ_pA0 = target_PA0(x1, x2)
|
| 114 |
+
targ_pB0 = target_PB0(x1, x2)
|
| 115 |
+
targ_corr = target_Corr(x1, x2)
|
| 116 |
+
|
| 117 |
+
count_A0 = 0
|
| 118 |
+
count_B0 = 0
|
| 119 |
+
count_A0B0 = 0 # Hem A=0 hem B=0 olan durumların sayısı
|
| 120 |
+
|
| 121 |
+
# Denemeleri yap
|
| 122 |
+
for _ in range(NUM_TRIALS_PER_PAIR):
|
| 123 |
+
try:
|
| 124 |
+
output1, output2 = net.activate(input_pair)
|
| 125 |
+
# Çıktıları ikili sonuçlara çevir
|
| 126 |
+
res_A = 1 if output1 >= 0.5 else 0 # A=0 veya A=1
|
| 127 |
+
res_B = 1 if output2 >= 0.5 else 0 # B=0 veya B=1
|
| 128 |
+
|
| 129 |
+
if res_A == 0: count_A0 += 1
|
| 130 |
+
if res_B == 0: count_B0 += 1
|
| 131 |
+
if res_A == 0 and res_B == 0: count_A0B0 += 1
|
| 132 |
+
|
| 133 |
+
except Exception as e:
|
| 134 |
+
logger.warning(f"Genome {genome_id}, Input {input_pair} aktivasyon hatası: {e}")
|
| 135 |
+
# Hata durumunda bu denemeyi geçebiliriz veya penaltı verebiliriz
|
| 136 |
+
pass
|
| 137 |
+
|
| 138 |
+
# Gözlemlenen olasılıkları hesapla
|
| 139 |
+
if NUM_TRIALS_PER_PAIR > 0:
|
| 140 |
+
obs_pA0 = count_A0 / NUM_TRIALS_PER_PAIR
|
| 141 |
+
obs_pB0 = count_B0 / NUM_TRIALS_PER_PAIR
|
| 142 |
+
obs_pA0B0 = count_A0B0 / NUM_TRIALS_PER_PAIR
|
| 143 |
+
else:
|
| 144 |
+
obs_pA0, obs_pB0, obs_pA0B0 = 0.5, 0.5, 0.25 # Varsayılan
|
| 145 |
+
|
| 146 |
+
# Gözlemlenen korelasyonu hesapla
|
| 147 |
+
obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
|
| 148 |
+
|
| 149 |
+
# Hataları hesapla
|
| 150 |
+
error_pA0 = (obs_pA0 - targ_pA0) ** 2
|
| 151 |
+
error_pB0 = (obs_pB0 - targ_pB0) ** 2
|
| 152 |
+
error_corr = (obs_corr - targ_corr) ** 2
|
| 153 |
+
|
| 154 |
+
# Ağırlıklı toplam hatayı hesapla
|
| 155 |
+
weighted_error = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
|
| 156 |
+
total_weighted_error_sum += weighted_error
|
| 157 |
+
|
| 158 |
+
# logger.debug(f" G:{genome_id} In:{input_pair} Tgt:({targ_pA0:.2f},{targ_pB0:.2f},{targ_corr:.2f}) Obs:({obs_pA0:.2f},{obs_pB0:.2f},{obs_corr:.2f}) Err:{weighted_error:.4f}")
|
| 159 |
+
|
| 160 |
+
# Ortalama ağırlıklı hatayı hesapla
|
| 161 |
+
average_weighted_error = total_weighted_error_sum / len(test_input_pairs)
|
| 162 |
+
|
| 163 |
+
# Fitness (1 - sqrt(AvgError))
|
| 164 |
+
fitness = max(0.0, 1.0 - math.sqrt(average_weighted_error))
|
| 165 |
+
genome.fitness = fitness
|
| 166 |
+
# logger.info(f"Genome {genome_id}: AvgWeightedError = {average_weighted_error:.4f}, Fitness = {fitness:.4f}")
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
# --- NEAT Çalıştırma Fonksiyonu ---
|
| 170 |
+
def run_neat(config_file):
|
| 171 |
+
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| 172 |
+
try:
|
| 173 |
+
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| 174 |
+
neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| 175 |
+
config_file)
|
| 176 |
+
config.fitness_threshold = FITNESS_THRESHOLD
|
| 177 |
+
logger.info(f"Yapılandırma: Giriş={config.genome_config.num_inputs}, Çıkış={config.genome_config.num_outputs}, Pop={config.pop_size}, Eşik={config.fitness_threshold}")
|
| 178 |
+
except Exception as e:
|
| 179 |
+
logger.critical(f"Yapılandırma dosyası yüklenemedi: {config_file} - Hata: {e}")
|
| 180 |
+
return None
|
| 181 |
+
|
| 182 |
+
logger.info("Yeni popülasyon oluşturuluyor...")
|
| 183 |
+
p = neat.Population(config)
|
| 184 |
+
|
| 185 |
+
# Raporlayıcılar
|
| 186 |
+
p.add_reporter(neat.StdOutReporter(True))
|
| 187 |
+
checkpoint_prefix = 'neat-checkpoint-v4-'
|
| 188 |
+
p.add_reporter(neat.Checkpointer(20, filename_prefix=checkpoint_prefix)) # Daha seyrek checkpoint
|
| 189 |
+
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| 190 |
+
|
| 191 |
+
logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
|
| 192 |
+
try:
|
| 193 |
+
winner = p.run(eval_genomes, MAX_GENERATIONS)
|
| 194 |
+
logger.info(' ' + "="*30 + " Evrim Tamamlandı " + "="*30)
|
| 195 |
+
except Exception as e:
|
| 196 |
+
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| 197 |
+
# Hata durumunda son checkpoint'i yüklemeyi deneyebiliriz (ileriki sürüm?)
|
| 198 |
+
return None # Şimdilik None dönelim
|
| 199 |
+
|
| 200 |
+
# En iyi genomu işle
|
| 201 |
+
if winner:
|
| 202 |
+
logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
|
| 203 |
+
# logger.info(f' {winner}') # Çok uzun olabilir, log dosyasında kalsın
|
| 204 |
+
|
| 205 |
+
# En iyi genomu kaydet
|
| 206 |
+
winner_filename = "winner_genome_v4.pkl"
|
| 207 |
+
try:
|
| 208 |
+
with open(winner_filename, 'wb') as f:
|
| 209 |
+
pickle.dump(winner, f)
|
| 210 |
+
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| 211 |
+
except Exception as e:
|
| 212 |
+
logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| 213 |
+
|
| 214 |
+
# --- YENİ: En İyi Genomu Korelasyon İçin Detaylı Test Etme ---
|
| 215 |
+
logger.info(" " + "="*25 + " En İyi Genom Detaylı Testi (Korelasyon) " + "="*25)
|
| 216 |
+
try:
|
| 217 |
+
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| 218 |
+
test_trials_final = 1000 # Final test için daha fazla deneme
|
| 219 |
+
logger.info(f"En iyi ağ, farklı girdi çiftleriyle {test_trials_final} kez test ediliyor...")
|
| 220 |
+
|
| 221 |
+
final_axis_values = np.linspace(0.0, 1.0, 5) # 5x5 = 25 nokta
|
| 222 |
+
final_test_pairs = list(itertools.product(final_axis_values, repeat=2))
|
| 223 |
+
final_total_weighted_error_sq_sum = 0.0
|
| 224 |
+
|
| 225 |
+
hdr = f"{'Input (x1,x2)': <14} {'Tgt(PA0,PB0,Corr)': <22} {'Obs(PA0,PB0,Corr)': <22} {'Err^2(Comb)': <10}"
|
| 226 |
+
logger.info(hdr)
|
| 227 |
+
logger.info("-" * len(hdr))
|
| 228 |
+
|
| 229 |
+
for input_pair in final_test_pairs:
|
| 230 |
+
x1, x2 = input_pair
|
| 231 |
+
targ_pA0 = target_PA0(x1, x2)
|
| 232 |
+
targ_pB0 = target_PB0(x1, x2)
|
| 233 |
+
targ_corr = target_Corr(x1, x2)
|
| 234 |
+
|
| 235 |
+
count_A0, count_B0, count_A0B0 = 0, 0, 0
|
| 236 |
+
for _ in range(test_trials_final):
|
| 237 |
+
output1, output2 = winner_net.activate(input_pair)
|
| 238 |
+
res_A = 0 if output1 < 0.5 else 1
|
| 239 |
+
res_B = 0 if output2 < 0.5 else 1
|
| 240 |
+
if res_A == 0: count_A0 += 1
|
| 241 |
+
if res_B == 0: count_B0 += 1
|
| 242 |
+
if res_A == 0 and res_B == 0: count_A0B0 += 1
|
| 243 |
+
|
| 244 |
+
obs_pA0 = count_A0 / test_trials_final
|
| 245 |
+
obs_pB0 = count_B0 / test_trials_final
|
| 246 |
+
obs_pA0B0 = count_A0B0 / test_trials_final
|
| 247 |
+
obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
|
| 248 |
+
|
| 249 |
+
error_pA0 = (obs_pA0 - targ_pA0) ** 2
|
| 250 |
+
error_pB0 = (obs_pB0 - targ_pB0) ** 2
|
| 251 |
+
error_corr = (obs_corr - targ_corr) ** 2
|
| 252 |
+
weighted_error_sq = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
|
| 253 |
+
final_total_weighted_error_sq_sum += weighted_error_sq
|
| 254 |
+
|
| 255 |
+
tgt_str = f"({targ_pA0:.2f},{targ_pB0:.2f},{targ_corr:.2f})"
|
| 256 |
+
obs_str = f"({obs_pA0:.2f},{obs_pB0:.2f},{obs_corr:.2f})"
|
| 257 |
+
logger.info(f"({x1:.2f}, {x2:.2f}) {tgt_str: <22} {obs_str: <22} {weighted_error_sq:<10.5f}")
|
| 258 |
+
|
| 259 |
+
final_avg_weighted_error_sq = final_total_weighted_error_sq_sum / len(final_test_pairs)
|
| 260 |
+
final_rmse_equivalent = math.sqrt(final_avg_weighted_error_sq)
|
| 261 |
+
logger.info("-" * len(hdr))
|
| 262 |
+
logger.info(f"Final Ortalama Ağırlıklı Karesel Hata (MSE ~): {final_avg_weighted_error_sq:.6f}")
|
| 263 |
+
logger.info(f"Final Kök Ort. Karesel Hata (~RMSE): {final_rmse_equivalent:.6f}")
|
| 264 |
+
logger.info(f"Final Fitness Yaklaşımı (1 - ~RMSE): {1.0 - final_rmse_equivalent:.6f}")
|
| 265 |
+
logger.info("-" * len(hdr))
|
| 266 |
+
|
| 267 |
+
except Exception as e:
|
| 268 |
+
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| 269 |
+
import traceback
|
| 270 |
+
logger.error(traceback.format_exc()) # Hatanın detayını logla
|
| 271 |
+
else:
|
| 272 |
+
logger.warning("Test edilecek bir kazanan genom bulunamadı.")
|
| 273 |
+
|
| 274 |
+
logger.info("="*70)
|
| 275 |
+
logger.info("Quanta Simülatörü Adım 4 (Korelasyonlu Çıktılar) tamamlandı.")
|
| 276 |
+
logger.info("="*70)
|
| 277 |
+
return winner
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
if __name__ == '__main__':
|
| 281 |
+
local_dir = os.path.dirname(os.path.abspath(__file__)) # Daha sağlam yol bulma
|
| 282 |
+
config_path = os.path.join(local_dir, 'config-feedforward-v4.txt') # <-- V4 Config Dosyası
|
| 283 |
+
|
| 284 |
+
if not os.path.exists(config_path):
|
| 285 |
+
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| 286 |
+
else:
|
| 287 |
+
run_neat(config_path)
|
quanta_sim_v5_nonlinear_simple.py
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# quanta_sim_v5_nonlinear_simple.py
|
| 2 |
+
|
| 3 |
+
import neat
|
| 4 |
+
import numpy as np
|
| 5 |
+
import os
|
| 6 |
+
import logging
|
| 7 |
+
import pickle
|
| 8 |
+
import random
|
| 9 |
+
import math
|
| 10 |
+
import datetime
|
| 11 |
+
import itertools
|
| 12 |
+
import traceback # Hata ayıklama için
|
| 13 |
+
|
| 14 |
+
# --- Loglama Ayarları ---
|
| 15 |
+
log_filename = f"quanta_log_v5_nonsimple_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
|
| 16 |
+
logging.basicConfig(
|
| 17 |
+
level=logging.INFO,
|
| 18 |
+
format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
| 19 |
+
handlers=[
|
| 20 |
+
logging.FileHandler(log_filename),
|
| 21 |
+
logging.StreamHandler()
|
| 22 |
+
]
|
| 23 |
+
)
|
| 24 |
+
logger = logging.getLogger(__name__)
|
| 25 |
+
|
| 26 |
+
logger.info("="*70)
|
| 27 |
+
logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 5 - Non-Linear Hedefler + Basitlik)")
|
| 28 |
+
logger.info(f"Başlangıç Zamanı: {datetime.datetime.now()}")
|
| 29 |
+
logger.info("="*70)
|
| 30 |
+
|
| 31 |
+
# --- Simülasyon Parametreleri ---
|
| 32 |
+
NUM_TEST_VALUES_PER_AXIS = 4 # Değerlendirme için ızgara boyutu (4x4=16 nokta)
|
| 33 |
+
NUM_TRIALS_PER_PAIR = 30 # Her girdi çifti için deneme sayısı
|
| 34 |
+
|
| 35 |
+
MAX_GENERATIONS = 300 # Zor problem için artırılmış nesil sayısı
|
| 36 |
+
|
| 37 |
+
# Fitness fonksiyonundaki hata ağırlıkları
|
| 38 |
+
W_PA0 = 1.0
|
| 39 |
+
W_PB0 = 1.0
|
| 40 |
+
W_CORR = 1.5 # Korelasyon genellikle daha zordur
|
| 41 |
+
TOTAL_WEIGHT = W_PA0 + W_PB0 + W_CORR
|
| 42 |
+
|
| 43 |
+
# Karmaşıklık Cezası Ağırlıkları (Deneme yanılma ile ayarlanabilir!)
|
| 44 |
+
COMPLEXITY_PENALTY_WEIGHT_NODE = 0.001
|
| 45 |
+
COMPLEXITY_PENALTY_WEIGHT_CONN = 0.0005
|
| 46 |
+
|
| 47 |
+
num_test_points = NUM_TEST_VALUES_PER_AXIS ** 2
|
| 48 |
+
total_trials_per_genome = num_test_points * NUM_TRIALS_PER_PAIR
|
| 49 |
+
|
| 50 |
+
logger.info(f"Eksen Başına Test Değeri: {NUM_TEST_VALUES_PER_AXIS} ({num_test_points} test noktası)")
|
| 51 |
+
logger.info(f"Girdi Çifti Başına Deneme: {NUM_TRIALS_PER_PAIR} (Toplam {total_trials_per_genome} deneme/genom)")
|
| 52 |
+
logger.info(f"Maksimum Nesil: {MAX_GENERATIONS}")
|
| 53 |
+
logger.info(f"Fitness Hata Ağırlıkları: P(A0)={W_PA0:.1f}, P(B0)={W_PB0:.1f}, Corr={W_CORR:.1f}")
|
| 54 |
+
logger.info(f"Karmaşıklık Ceza Ağırlıkları: Düğüm={COMPLEXITY_PENALTY_WEIGHT_NODE}, Bağlantı={COMPLEXITY_PENALTY_WEIGHT_CONN}")
|
| 55 |
+
|
| 56 |
+
# --- Doğrusal Olmayan Hedef Fonksiyonları ---
|
| 57 |
+
def target_PA0(x1, x2):
|
| 58 |
+
# P(A=0) hedefi (0.1 ile 0.9 arasında salınır)
|
| 59 |
+
return 0.5 + 0.4 * math.sin(math.pi * x1)
|
| 60 |
+
|
| 61 |
+
def target_PB0(x1, x2):
|
| 62 |
+
# P(B=0) hedefi (0.1 ile 0.9 arasında salınır)
|
| 63 |
+
return 0.5 + 0.4 * math.cos(math.pi * x2)
|
| 64 |
+
|
| 65 |
+
def target_Corr(x1, x2):
|
| 66 |
+
# Hedef Korelasyon (0 ile -0.8 arasında salınır)
|
| 67 |
+
return -0.8 * math.sin(math.pi * x1 * x2)
|
| 68 |
+
|
| 69 |
+
logger.info(f"Hedef P(A=0|x1,x2) = 0.5 + 0.4*sin(pi*x1)")
|
| 70 |
+
logger.info(f"Hedef P(B=0|x1,x2) = 0.5 + 0.4*cos(pi*x2)")
|
| 71 |
+
logger.info(f"Hedef Corr(A,B|x1,x2) = -0.8*sin(pi*x1*x2)")
|
| 72 |
+
|
| 73 |
+
# --- Korelasyon Hesaplama Yardımcı Fonksiyonu ---
|
| 74 |
+
def calculate_correlation(pA0, pB0, pA0B0, epsilon=1e-9):
|
| 75 |
+
pA1 = 1.0 - pA0
|
| 76 |
+
pB1 = 1.0 - pB0
|
| 77 |
+
covariance = pA0B0 - pA0 * pB0
|
| 78 |
+
varA = pA0 * pA1
|
| 79 |
+
varB = pB0 * pB1
|
| 80 |
+
denominator = math.sqrt((varA + epsilon) * (varB + epsilon))
|
| 81 |
+
if denominator < epsilon: return 0.0
|
| 82 |
+
correlation = covariance / denominator
|
| 83 |
+
return max(-1.0, min(1.0, correlation))
|
| 84 |
+
|
| 85 |
+
# --- NEAT Fitness Fonksiyonu ---
|
| 86 |
+
def eval_genomes(genomes, config):
|
| 87 |
+
axis_values = np.linspace(0.0, 1.0, NUM_TEST_VALUES_PER_AXIS)
|
| 88 |
+
test_input_pairs = list(itertools.product(axis_values, repeat=2))
|
| 89 |
+
|
| 90 |
+
for genome_id, genome in genomes:
|
| 91 |
+
genome.fitness = 0.0 # Başlangıç fitness
|
| 92 |
+
try:
|
| 93 |
+
net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| 94 |
+
except Exception as e:
|
| 95 |
+
logger.error(f"Genome {genome_id} ağ oluşturma hatası: {e}")
|
| 96 |
+
genome.fitness = -30.0
|
| 97 |
+
continue
|
| 98 |
+
|
| 99 |
+
total_weighted_error_sum = 0.0
|
| 100 |
+
|
| 101 |
+
# Performans Değerlendirme
|
| 102 |
+
for input_pair in test_input_pairs:
|
| 103 |
+
x1, x2 = input_pair
|
| 104 |
+
targ_pA0 = target_PA0(x1, x2)
|
| 105 |
+
targ_pB0 = target_PB0(x1, x2)
|
| 106 |
+
targ_corr = target_Corr(x1, x2)
|
| 107 |
+
|
| 108 |
+
count_A0, count_B0, count_A0B0 = 0, 0, 0
|
| 109 |
+
for _ in range(NUM_TRIALS_PER_PAIR):
|
| 110 |
+
try:
|
| 111 |
+
output1, output2 = net.activate(input_pair)
|
| 112 |
+
res_A = 0 if output1 < 0.5 else 1
|
| 113 |
+
res_B = 0 if output2 < 0.5 else 1
|
| 114 |
+
if res_A == 0: count_A0 += 1
|
| 115 |
+
if res_B == 0: count_B0 += 1
|
| 116 |
+
if res_A == 0 and res_B == 0: count_A0B0 += 1
|
| 117 |
+
except Exception as e:
|
| 118 |
+
# Aktivasyon hatalarını loglamak çok fazla çıktı üretebilir
|
| 119 |
+
pass
|
| 120 |
+
|
| 121 |
+
# Gözlemlenen değerler
|
| 122 |
+
if NUM_TRIALS_PER_PAIR > 0:
|
| 123 |
+
obs_pA0 = count_A0 / NUM_TRIALS_PER_PAIR
|
| 124 |
+
obs_pB0 = count_B0 / NUM_TRIALS_PER_PAIR
|
| 125 |
+
obs_pA0B0 = count_A0B0 / NUM_TRIALS_PER_PAIR
|
| 126 |
+
else:
|
| 127 |
+
obs_pA0, obs_pB0, obs_pA0B0 = 0.5, 0.5, 0.25
|
| 128 |
+
|
| 129 |
+
obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
|
| 130 |
+
|
| 131 |
+
# Hatalar
|
| 132 |
+
error_pA0 = (obs_pA0 - targ_pA0) ** 2
|
| 133 |
+
error_pB0 = (obs_pB0 - targ_pB0) ** 2
|
| 134 |
+
error_corr = (obs_corr - targ_corr) ** 2
|
| 135 |
+
weighted_error = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
|
| 136 |
+
total_weighted_error_sum += weighted_error
|
| 137 |
+
|
| 138 |
+
# Temel fitness
|
| 139 |
+
average_weighted_error = total_weighted_error_sum / len(test_input_pairs)
|
| 140 |
+
base_fitness = max(0.0, 1.0 - math.sqrt(average_weighted_error))
|
| 141 |
+
|
| 142 |
+
# Karmaşıklık Cezası
|
| 143 |
+
num_nodes = len(genome.nodes)
|
| 144 |
+
num_connections = len(genome.connections)
|
| 145 |
+
complexity_penalty = (COMPLEXITY_PENALTY_WEIGHT_NODE * num_nodes +
|
| 146 |
+
COMPLEXITY_PENALTY_WEIGHT_CONN * num_connections)
|
| 147 |
+
|
| 148 |
+
# Final fitness
|
| 149 |
+
final_fitness = max(0.0, base_fitness - complexity_penalty)
|
| 150 |
+
genome.fitness = final_fitness
|
| 151 |
+
|
| 152 |
+
# --- NEAT Çalıştırma Fonksiyonu ---
|
| 153 |
+
def run_neat(config_file):
|
| 154 |
+
logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| 155 |
+
config = None # Önce None olarak tanımla
|
| 156 |
+
try:
|
| 157 |
+
config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| 158 |
+
neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| 159 |
+
config_file)
|
| 160 |
+
logger.info(f"Yapılandırma: Giriş={config.genome_config.num_inputs}, Çıkış={config.genome_config.num_outputs}, Pop={config.pop_size}, Eşik={config.fitness_threshold}")
|
| 161 |
+
except Exception as e:
|
| 162 |
+
logger.critical(f"Yapılandırma dosyası yüklenemedi: {config_file} - Hata: {e}")
|
| 163 |
+
return None
|
| 164 |
+
|
| 165 |
+
logger.info("Yeni popülasyon oluşturuluyor...")
|
| 166 |
+
p = neat.Population(config)
|
| 167 |
+
|
| 168 |
+
# Raporlayıcılar
|
| 169 |
+
p.add_reporter(neat.StdOutReporter(True))
|
| 170 |
+
checkpoint_prefix = 'neat-checkpoint-v5-'
|
| 171 |
+
# Checkpointer her 25 nesilde bir kaydetsin
|
| 172 |
+
p.add_reporter(neat.Checkpointer(25, filename_prefix=checkpoint_prefix))
|
| 173 |
+
logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| 174 |
+
|
| 175 |
+
logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
|
| 176 |
+
winner = None # Önce None olarak tanımla
|
| 177 |
+
try:
|
| 178 |
+
winner = p.run(eval_genomes, MAX_GENERATIONS)
|
| 179 |
+
logger.info(' ' + "="*30 + " Evrim Tamamlandı " + "="*30)
|
| 180 |
+
except Exception as e:
|
| 181 |
+
logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| 182 |
+
logger.error(traceback.format_exc()) # Tam hata izini logla
|
| 183 |
+
# Hata durumunda bile popülasyonun en iyisini almayı deneyebiliriz (checkpoint yoksa)
|
| 184 |
+
if not winner and p and p.best_genome:
|
| 185 |
+
logger.warning("Evrim hata ile durdu, bulunan son en iyi genom kullanılıyor.")
|
| 186 |
+
winner = p.best_genome
|
| 187 |
+
# return None # Hata durumunda çıkmak yerine devam etmeyi deneyelim
|
| 188 |
+
|
| 189 |
+
# En iyi genomu işle (hata olsa bile 'winner' dolu olabilir)
|
| 190 |
+
if winner:
|
| 191 |
+
logger.info(f'En iyi genom bulundu/kullanıldı (Final Fitness: {winner.fitness:.6f}):')
|
| 192 |
+
num_nodes = len(winner.nodes)
|
| 193 |
+
num_connections = len(winner.connections)
|
| 194 |
+
logger.info(f'Kazanan Karmaşıklığı: {num_nodes} Düğüm, {num_connections} Bağlantı')
|
| 195 |
+
|
| 196 |
+
# En iyi genomu kaydet
|
| 197 |
+
winner_filename = "winner_genome_v5.pkl"
|
| 198 |
+
try:
|
| 199 |
+
with open(winner_filename, 'wb') as f:
|
| 200 |
+
pickle.dump(winner, f)
|
| 201 |
+
logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| 202 |
+
except Exception as e:
|
| 203 |
+
logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| 204 |
+
|
| 205 |
+
# --- Final Test ---
|
| 206 |
+
logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi (Non-Linear) " + "="*20)
|
| 207 |
+
try:
|
| 208 |
+
# Eğer config yüklenmemişse (ilk hatada), testi atla
|
| 209 |
+
if config is None:
|
| 210 |
+
logger.error("Yapılandırma yüklenemediği için final test atlanıyor.")
|
| 211 |
+
raise RuntimeError("Config object is None, cannot create network.")
|
| 212 |
+
|
| 213 |
+
winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| 214 |
+
test_trials_final = 1000 # Final test için deneme sayısı
|
| 215 |
+
logger.info(f"En iyi ağ, farklı girdi çiftleriyle {test_trials_final} kez test ediliyor...")
|
| 216 |
+
|
| 217 |
+
final_axis_values = np.linspace(0.0, 1.0, 6) # 6x6 = 36 nokta test
|
| 218 |
+
final_test_pairs = list(itertools.product(final_axis_values, repeat=2))
|
| 219 |
+
final_total_weighted_error_sq_sum = 0.0
|
| 220 |
+
|
| 221 |
+
hdr = f"{'Input (x1,x2)': <14} {'Tgt(PA0,PB0,Corr)': <22} {'Obs(PA0,PB0,Corr)': <22} {'Err^2(Comb)': <10}"
|
| 222 |
+
logger.info(hdr)
|
| 223 |
+
logger.info("-" * len(hdr))
|
| 224 |
+
|
| 225 |
+
for input_pair in final_test_pairs:
|
| 226 |
+
x1, x2 = input_pair
|
| 227 |
+
targ_pA0 = target_PA0(x1, x2)
|
| 228 |
+
targ_pB0 = target_PB0(x1, x2)
|
| 229 |
+
targ_corr = target_Corr(x1, x2)
|
| 230 |
+
|
| 231 |
+
count_A0, count_B0, count_A0B0 = 0, 0, 0
|
| 232 |
+
for _ in range(test_trials_final):
|
| 233 |
+
output1, output2 = winner_net.activate(input_pair)
|
| 234 |
+
res_A = 0 if output1 < 0.5 else 1
|
| 235 |
+
res_B = 0 if output2 < 0.5 else 1
|
| 236 |
+
if res_A == 0: count_A0 += 1
|
| 237 |
+
if res_B == 0: count_B0 += 1
|
| 238 |
+
if res_A == 0 and res_B == 0: count_A0B0 += 1
|
| 239 |
+
|
| 240 |
+
obs_pA0 = count_A0 / test_trials_final
|
| 241 |
+
obs_pB0 = count_B0 / test_trials_final
|
| 242 |
+
obs_pA0B0 = count_A0B0 / test_trials_final
|
| 243 |
+
obs_corr = calculate_correlation(obs_pA0, obs_pB0, obs_pA0B0)
|
| 244 |
+
|
| 245 |
+
error_pA0 = (obs_pA0 - targ_pA0) ** 2
|
| 246 |
+
error_pB0 = (obs_pB0 - targ_pB0) ** 2
|
| 247 |
+
error_corr = (obs_corr - targ_corr) ** 2
|
| 248 |
+
weighted_error_sq = (W_PA0 * error_pA0 + W_PB0 * error_pB0 + W_CORR * error_corr) / TOTAL_WEIGHT
|
| 249 |
+
final_total_weighted_error_sq_sum += weighted_error_sq
|
| 250 |
+
|
| 251 |
+
tgt_str = f"({targ_pA0:.2f},{targ_pB0:.2f},{targ_corr:.2f})"
|
| 252 |
+
obs_str = f"({obs_pA0:.2f},{obs_pB0:.2f},{obs_corr:.2f})"
|
| 253 |
+
logger.info(f"({x1:.2f}, {x2:.2f}) {tgt_str: <22} {obs_str: <22} {weighted_error_sq:<10.5f}")
|
| 254 |
+
|
| 255 |
+
final_avg_weighted_error_sq = final_total_weighted_error_sq_sum / len(final_test_pairs)
|
| 256 |
+
final_rmse_equivalent = math.sqrt(final_avg_weighted_error_sq)
|
| 257 |
+
logger.info("-" * len(hdr))
|
| 258 |
+
logger.info(f"Final Ortalama Ağırlıklı Karesel Hata (MSE ~): {final_avg_weighted_error_sq:.6f}")
|
| 259 |
+
logger.info(f"Final Kök Ort. Karesel Hata (~RMSE): {final_rmse_equivalent:.6f}")
|
| 260 |
+
logger.info(f"Not: Bu RMSE, karmaşıklık cezasını içermez, sadece performans ölçümüdür.")
|
| 261 |
+
logger.info("-" * len(hdr))
|
| 262 |
+
|
| 263 |
+
except Exception as e:
|
| 264 |
+
logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| 265 |
+
logger.error(traceback.format_exc())
|
| 266 |
+
else:
|
| 267 |
+
logger.warning("Evrim sonunda test edilecek bir kazanan genom bulunamadı.")
|
| 268 |
+
|
| 269 |
+
logger.info("="*70)
|
| 270 |
+
logger.info("Quanta Simülatörü Adım 5 (Non-Linear + Basitlik) tamamlandı.")
|
| 271 |
+
logger.info(f"Bitiş Zamanı: {datetime.datetime.now()}")
|
| 272 |
+
logger.info("="*70)
|
| 273 |
+
# return winner # Fonksiyondan bir şey döndürmeye gerek yoksa kaldırılabilir
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
if __name__ == '__main__':
|
| 277 |
+
# Betiğin bulunduğu dizini al
|
| 278 |
+
local_dir = os.path.dirname(os.path.abspath(__file__))
|
| 279 |
+
# V5 config dosyasının tam yolunu oluştur
|
| 280 |
+
config_path = os.path.join(local_dir, 'config-feedforward-v5.txt')
|
| 281 |
+
|
| 282 |
+
if not os.path.exists(config_path):
|
| 283 |
+
logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| 284 |
+
logger.critical(f"Lütfen '{os.path.basename(config_path)}' dosyasını betikle aynı klasöre koyun.")
|
| 285 |
+
else:
|
| 286 |
+
try:
|
| 287 |
+
run_neat(config_path)
|
| 288 |
+
except Exception as main_e:
|
| 289 |
+
logger.critical(f"Ana program akışında beklenmedik bir hata oluştu: {main_e}")
|
| 290 |
+
logger.error(traceback.format_exc())
|