Python NEAT库报错AttributeError:'list'对象无'connections'属性
问题
使用Python的NEAT库做音乐生成时,运行代码触发AttributeError: 'list' object has no attribute 'connections',错误指向evaluate_genome函数里的net = neat.nn.FeedForwardNetwork.create(genome, config)行。代码结构参考官方示例,但无法完成世代迭代。
完整代码:
import neat import random import numpy as np import os from midiutil import MIDIFile config_path = "config.txt" num_generations = 10 num_measures = 16 beats_per_measure = 4 num_tracks = 1 beat_duration = 0.25 output_file = "generated_music.mid" def evaluate_genome(genome, config): net = neat.nn.FeedForwardNetwork.create(genome, config) melody = [] for _ in range(num_measures * beats_per_measure): inputs = [random.random()] output = net.activate(inputs) note = int(output[0] * 127) melody.append(note) fitness = calculate_fitness(melody) return fitness def calculate_fitness(melody): melodic_fitness = calculate_melodic_fitness(melody) harmonic_fitness = calculate_harmonic_fitness(melody) rhythmic_fitness = calculate_rhythmic_fitness(melody) overall_fitness = melodic_fitness + harmonic_fitness + rhythmic_fitness return overall_fitness def calculate_melodic_fitness(melody): melodic_fitness = 0.0 # Placeholder value return melodic_fitness def calculate_harmonic_fitness(melody): harmonic_fitness = 0.0 return harmonic_fitness def calculate_rhythmic_fitness(melody): rhythmic_fitness = 0.0 # Placeholder value return rhythmic_fitness def run_neat(): local_dir = os.path.dirname(__file__) config_path = os.path.join(local_dir, "config.txt") config = neat.Config( neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path, ) population = neat.Population(config) reporter = neat.StdOutReporter(True) population.add_reporter(reporter) winner = population.run(evaluate_genome, num_generations) best_genome = winner best_net = neat.nn.FeedForwardNetwork.create(best_genome, config) melody = [] for _ in range(num_measures * beats_per_measure): inputs = [random.random()] output = best_net.activate(inputs) note = int(output[0] * 127) melody.append(note) midi_file = MIDIFile(num_tracks) track = 0 time = 0 for note in melody: midi_file.addNote(track, 0, note, time, beat_duration, 100) time += beat_duration with open(output_file, "wb") as file: midi_file.writeFile(file) print("Generated music saved as", output_file) run_neat()
配置文件config.txt:
[NEAT] fitness_criterion = max fitness_threshold = 400 pop_size = 50 reset_on_extinction = False [DefaultStagnation] species_fitness_func = max max_stagnation = 20 species_elitism = 2 [DefaultReproduction] elitism = 2 survival_threshold = 0.2 [DefaultGenome] # node activation options activation_default = relu activation_mutate_rate = 1.0 activation_options = relu # node aggregation options aggregation_default = sum aggregation_mutate_rate = 0.0 aggregation_options = sum # node bias options bias_init_mean = 3.0 bias_init_stdev = 1.0 bias_max_value = 30.0 bias_min_value = -30.0 bias_mutate_power = 0.5 bias_mutate_rate = 0.7 bias_replace_rate = 0.1 # genome compatibility options compatibility_disjoint_coefficient = 1.0 compatibility_weight_coefficient = 0.5 # connection add/remove rates conn_add_prob = 0.5 conn_delete_prob = 0.5 # connection enable options enabled_default = True enabled_mutate_rate = 0.01 feed_forward = True initial_connection = full_direct # node add/remove rates node_add_prob = 0.2 node_delete_prob = 0.2 # network parameters num_hidden = 1 num_inputs = 1 num_outputs = 1 # node response options response_init_mean = 1.0 response_init_stdev = 0.0 response_max_value = 30.0 response_min_value = -30.0 response_mutate_power = 0.0 response_mutate_rate = 0.0 response_replace_rate = 0.0 # connection weight options weight_init_mean = 0.0 weight_init_stdev = 1.0 weight_max_value = 30 weight_min_value = -30 weight_mutate_power = 0.5 weight_mutate_rate = 0.8 weight_replace_rate = 0.1 [DefaultSpeciesSet] compatibility_threshold = 3.0
解决方案
错误根源是:population.run()默认要求评估函数接收基因组列表作为第一个参数,但你写的evaluate_genome是为单个基因组设计的,导致传入了列表而非单个Genome对象,触发connections属性不存在的错误。
有两种修复方式:
方式1:修改评估函数适配批量处理
把评估函数改成遍历基因组列表的形式,直接给每个基因组赋值适应度:
def evaluate_genomes(genomes, config): for genome_id, genome in genomes: net = neat.nn.FeedForwardNetwork.create(genome, config) melody = [] for _ in range(num_measures * beats_per_measure): inputs = [random.random()] output = net.activate(inputs) note = int(output[0] * 127) melody.append(note) genome.fitness = calculate_fitness(melody)
同时修改population.run()的调用:
winner = population.run(evaluate_genomes, num_generations)
方式2:改用population.evaluate()方法
如果想保留单个基因组的评估逻辑,用evaluate()替代run(),它支持传入单基因组评估函数:
# 保留原有的evaluate_genome函数不变 winner = population.evaluate(evaluate_genome, num_generations)
额外提示
- 当前配置文件的
initial_connection = full_direct设置合理,符合输入输出直接连接的初始网络结构。 - 你的适应度计算函数目前都返回0,后续需要补充实际逻辑,否则所有基因组适应度相同,进化无法推进。
内容的提问来源于stack exchange,提问作者Dummy
相关产品推荐
相关产品推荐

