| |
|
| |
|
| | import neat
|
| | import numpy as np
|
| | import os
|
| | import logging
|
| | import pickle
|
| | import random
|
| | import math
|
| | import datetime
|
| |
|
| |
|
| |
|
| | log_filename = f"quanta_log_v2_input_dep_{datetime.datetime.now():%Y%m%d_%H%M%S}.log"
|
| | logging.basicConfig(
|
| | level=logging.INFO,
|
| | format='%(asctime)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s',
|
| | handlers=[
|
| | logging.FileHandler(log_filename),
|
| | logging.StreamHandler()
|
| | ]
|
| | )
|
| | logger = logging.getLogger(__name__)
|
| |
|
| | logger.info("="*50)
|
| | logger.info("Quanta Simülatörü Başlatılıyor (Sürüm 2 - Girdiye Bağlı Olasılık)")
|
| | logger.info("="*50)
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | NUM_TEST_INPUTS = 6
|
| | NUM_TRIALS_PER_INPUT = 20
|
| |
|
| |
|
| | MAX_GENERATIONS = 100
|
| | FITNESS_THRESHOLD = 0.98
|
| |
|
| | logger.info(f"Test Edilecek Girdi Sayısı: {NUM_TEST_INPUTS}")
|
| | logger.info(f"Girdi Başına Deneme Sayısı: {NUM_TRIALS_PER_INPUT}")
|
| | logger.info(f"Toplam Değerlendirme Denemesi/Genom: {NUM_TEST_INPUTS * NUM_TRIALS_PER_INPUT}")
|
| | logger.info(f"Maksimum Nesil Sayısı: {MAX_GENERATIONS}")
|
| | logger.info(f"Fitness Eşiği: {FITNESS_THRESHOLD}")
|
| |
|
| |
|
| | def calculate_target_prob0(input_value):
|
| | """
|
| | Verilen girdiye göre hedef P(0) olasılığını hesaplar.
|
| | Lineer Fonksiyon: target_P0(x) = 0.1 + 0.8 * x
|
| | """
|
| | return 0.1 + 0.8 * input_value
|
| |
|
| | logger.info(f"Hedef P(0) Fonksiyonu: P(0|x) = 0.1 + 0.8 * x")
|
| |
|
| |
|
| |
|
| | def eval_genomes(genomes, config):
|
| | """
|
| | Popülasyondaki tüm genomların fitness değerlerini hesaplar.
|
| | Fitness, ağın farklı girdiler için hedeflenen olasılıkları
|
| | ne kadar iyi üretebildiğine göre belirlenir.
|
| | """
|
| |
|
| | test_inputs = np.linspace(0.0, 1.0, NUM_TEST_INPUTS)
|
| |
|
| |
|
| | for genome_id, genome in genomes:
|
| | genome.fitness = 0.0
|
| | try:
|
| | net = neat.nn.FeedForwardNetwork.create(genome, config)
|
| | except Exception as e:
|
| | logger.error(f"Genome {genome_id} için ağ oluşturulamadı: {e}")
|
| | genome.fitness = -10.0
|
| | continue
|
| |
|
| | total_squared_error = 0.0
|
| |
|
| |
|
| | for net_input_val in test_inputs:
|
| | net_input = (net_input_val,)
|
| | target_prob_0 = calculate_target_prob0(net_input_val)
|
| |
|
| | count_0 = 0
|
| |
|
| | for _ in range(NUM_TRIALS_PER_INPUT):
|
| | try:
|
| | output = net.activate(net_input)
|
| |
|
| | if output[0] < 0.5:
|
| | count_0 += 1
|
| | except Exception as e:
|
| | logger.warning(f"Genome {genome_id}, Input {net_input_val:.2f} ağ aktivasyonunda hata: {e}")
|
| |
|
| | pass
|
| |
|
| |
|
| | if NUM_TRIALS_PER_INPUT > 0:
|
| | observed_prob_0 = count_0 / NUM_TRIALS_PER_INPUT
|
| | else:
|
| | observed_prob_0 = 0.5
|
| |
|
| |
|
| | error = (observed_prob_0 - target_prob_0) ** 2
|
| | total_squared_error += error
|
| |
|
| |
|
| |
|
| |
|
| | average_squared_error = total_squared_error / NUM_TEST_INPUTS
|
| |
|
| |
|
| |
|
| | fitness = max(0.0, 1.0 - math.sqrt(average_squared_error))
|
| |
|
| | genome.fitness = fitness
|
| |
|
| |
|
| |
|
| |
|
| | def run_neat(config_file):
|
| | """
|
| | NEAT evrimini başlatır ve yönetir.
|
| | """
|
| | logger.info(f"NEAT yapılandırması yükleniyor: {config_file}")
|
| | try:
|
| | config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
|
| | neat.DefaultSpeciesSet, neat.DefaultStagnation,
|
| | config_file)
|
| |
|
| | config.fitness_threshold = FITNESS_THRESHOLD
|
| | logger.info(f"Yapılandırma yüklendi. Fitness Eşiği: {config.fitness_threshold}")
|
| |
|
| | except Exception as e:
|
| | logger.critical(f"Yapılandırma dosyası yüklenemedi veya geçersiz: {config_file} - Hata: {e}")
|
| | return None
|
| |
|
| | logger.info("Yeni popülasyon oluşturuluyor...")
|
| | p = neat.Population(config)
|
| |
|
| |
|
| | p.add_reporter(neat.StdOutReporter(True))
|
| |
|
| |
|
| |
|
| |
|
| | checkpoint_prefix = 'neat-checkpoint-v2-'
|
| | p.add_reporter(neat.Checkpointer(10, filename_prefix=checkpoint_prefix))
|
| | logger.info(f"Checkpoint dosyaları '{checkpoint_prefix}*' olarak kaydedilecek.")
|
| |
|
| | logger.info(f"Evrim başlıyor (Maksimum {MAX_GENERATIONS} nesil)...")
|
| | try:
|
| | winner = p.run(eval_genomes, MAX_GENERATIONS)
|
| | logger.info(' ' + "="*20 + " Evrim Tamamlandı " + "="*20)
|
| | except Exception as e:
|
| | logger.critical(f"Evrim sırasında kritik bir hata oluştu: {e}")
|
| | return None
|
| |
|
| |
|
| | if winner:
|
| | logger.info(f'En iyi genom bulundu (Fitness: {winner.fitness:.6f}):')
|
| | logger.info(f' {winner}')
|
| |
|
| |
|
| | winner_filename = "winner_genome_v2.pkl"
|
| | try:
|
| | with open(winner_filename, 'wb') as f:
|
| | pickle.dump(winner, f)
|
| | logger.info(f"En iyi genom '{winner_filename}' dosyasına başarıyla kaydedildi.")
|
| | except Exception as e:
|
| | logger.error(f"En iyi genom kaydedilemedi: {e}")
|
| |
|
| |
|
| | logger.info(" " + "="*20 + " En İyi Genom Detaylı Testi " + "="*20)
|
| | try:
|
| | winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
|
| | test_trials_final = 1000
|
| | logger.info(f"En iyi ağ, farklı girdilerle {test_trials_final} kez test ediliyor...")
|
| |
|
| | test_inputs_final = np.linspace(0.0, 1.0, 11)
|
| | final_total_error_sq = 0.0
|
| | results = []
|
| |
|
| | for net_input_val in test_inputs_final:
|
| | target_p0 = calculate_target_prob0(net_input_val)
|
| | net_input = (net_input_val,)
|
| | count_0 = 0
|
| | for _ in range(test_trials_final):
|
| | output = winner_net.activate(net_input)
|
| | if output[0] < 0.5:
|
| | count_0 += 1
|
| |
|
| | observed_p0 = count_0 / test_trials_final
|
| | error_sq = (observed_p0 - target_p0) ** 2
|
| | final_total_error_sq += error_sq
|
| | results.append({
|
| | "input": net_input_val,
|
| | "target_p0": target_p0,
|
| | "observed_p0": observed_p0,
|
| | "error_sq": error_sq
|
| | })
|
| | 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}")
|
| |
|
| | final_avg_error_sq = final_total_error_sq / len(test_inputs_final)
|
| | final_rmse = math.sqrt(final_avg_error_sq)
|
| | logger.info("-" * 40)
|
| | logger.info(f"Final Ortalama Karesel Hata (MSE): {final_avg_error_sq:.6f}")
|
| | logger.info(f"Final Kök Ortalama Karesel Hata (RMSE): {final_rmse:.6f}")
|
| | logger.info(f"Final Fitness Yaklaşımı (1 - RMSE): {1.0 - final_rmse:.6f}")
|
| | logger.info("-" * 40)
|
| |
|
| | except Exception as e:
|
| | logger.error(f"En iyi genom test edilirken hata oluştu: {e}")
|
| |
|
| | else:
|
| | logger.warning("Test edilecek bir kazanan genom bulunamadı.")
|
| |
|
| | logger.info("="*50)
|
| | logger.info("Quanta Simülatörü Adım 2 (Girdiye Bağlı Olasılık) tamamlandı.")
|
| | logger.info("="*50)
|
| | return winner
|
| |
|
| |
|
| | if __name__ == '__main__':
|
| |
|
| | local_dir = os.path.dirname(__file__)
|
| |
|
| | config_path = os.path.join(local_dir, 'config-feedforward.txt')
|
| |
|
| | if not os.path.exists(config_path):
|
| | logger.critical(f"Yapılandırma dosyası bulunamadı: {config_path}")
|
| | logger.critical("Lütfen 'config-feedforward.txt' dosyasını Python betiğiyle aynı klasöre koyun.")
|
| | else:
|
| |
|
| | run_neat(config_path) |