You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyGad GA调用适应度函数次数超预期问题求助

问题:PyGad中fitness函数额外调用次数的原因与优化方法

我正在用PyGad的GA函数优化神经网络,测试调试阶段在fitness函数里加了保存每个解及其准确率的代码。设置了initial_population=10,sol_per_pop=10。

原本以为fitness函数的调用次数是10减去keep_elitism=2和keep_parents=2保留的解的数量,但实际第一代调用了26次,后续每代16次。第一代多的10次应该是PyGad初始化导致的。

因为fitness函数耗时极长,想限制每代的调用次数,求解释额外调用的原因,以及减少次数的方法。我的GA实例代码如下:

ga_instance = pg.GA(initial_population=initial_population,
                    num_generations=100,
                    num_parents_mating=2,
                    fitness_func=fitness,
                    sol_per_pop=10,
                    num_genes=18,
                    gene_type=GENE_TYPE,
                    gene_space=GENE_SPACE,
                    parent_selection_type='tournament',
                    K_tournament=5,
                    keep_parents=2,
                    keep_elitism=2,
                    save_solutions=True,
                    save_best_solutions=True,
                    crossover_type='single_point',
                    mutation_type='adaptive',
                    allow_duplicate_genes=True,
                    mutation_num_genes=[4,2],
                    stop_criteria='saturate_5',
                    on_generation=callback_gen,
                    suppress_warnings=False)

原因分析与解决方法

一、额外调用次数的核心原因

1. 第一代26次调用的拆解

第一代的调用次数由两部分组成:

  • 初始种群计算:你传入了initial_population=10,PyGad会先对这10个初始解执行fitness计算,这是10次调用。
  • 第一代进化流程调用:和后续每代的进化逻辑一致,这部分占16次,累计后就是26次。

2. 后续每代16次调用的根源

这16次主要来自两个环节:

  • 锦标赛选择的重复计算:你使用了tournament选择策略,且K_tournament=5、num_parents_mating=2。每次选父代需要进行2轮锦标赛,每轮随机抽取5个个体。如果PyGad内部的适应度缓存未生效(或因设置导致失效),会重复计算这些已存在个体的fitness,这部分就占了10次调用。
  • 新个体的计算:每代需要生成sol_per_pop - keep_parents - keep_elitism = 10-2-2=6个新个体,每个都要执行一次fitness计算,这是6次调用。
    两者相加10+6=16,刚好对应后续每代的调用次数。

另外,你使用的adaptive变异类型,可能会因需要根据适应度调整变异概率,触发少量额外调用,但不是核心原因。

二、减少fitness调用次数的实用方法

1. 手动实现适应度缓存(最有效)

在fitness函数内部加一个缓存字典,把已经计算过的解的结果存起来,避免重复计算。因为解是数组,要转成可哈希的元组当键:

fitness_cache = {}

def fitness(solution, solution_idx):
    solution_key = tuple(solution)
    if solution_key in fitness_cache:
        return fitness_cache[solution_key]
    
    # 你的神经网络评估逻辑
    accuracy = ... 
    fitness_val = accuracy  # 假设适应度直接用准确率
    
    # 存入缓存
    fitness_cache[solution_key] = fitness_val
    # 保存解和准确率的代码
    ...
    return fitness_val

不管PyGad因什么原因重复调用同一个解,都只会计算一次,能大幅降低调用次数。

2. 调整选择策略或参数

  • 若坚持用锦标赛选择:减小K_tournament的值(比如设为2或3),减少每轮锦标赛涉及的个体数,从而降低重复计算次数。
  • 更换选择策略:改用sss(稳态选择)或rws(轮盘赌选择),这些策略直接用已计算好的适应度值,不会重复触发fitness调用。

3. 简化变异策略

如果自适应变异不是必须的,换成普通的random变异类型,避免因调整变异概率带来的额外fitness调用。

4. 验证PyGad内部缓存

PyGad本身应该会缓存适应度,但可能因allow_duplicate_genes=True等设置导致缓存失效。手动缓存是最可靠的兜底方案,不用依赖内部机制。

内容的提问来源于stack exchange,提问作者whichedge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:54:51