DEAP框架下如何高效获取每一代最优个体以实现动画展示?
优化DEAP获取每代最优个体的方法
你的代码耗时的核心问题是重复计算了个体的适应度(tspDistance),而且自定义的过滤逻辑效率低下。以下是两种更高效的实现方式:
方法一:优化Statistics统计逻辑,复用已计算的适应度
利用DEAP内置的tools.selBest直接从种群中选择最优个体,避免重复计算适应度:
import numpy as np from deap import tools, algorithms # 初始化适应度统计 stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register('min', np.min) stats.register('mean', np.mean) # 初始化最优个体统计:用selBest直接选种群中最优的1个个体 history = tools.Statistics(lambda ind: ind) # 注意:如果你的TSP是求最小距离,需确保适应度是负数(因为DEAP默认最大化适应度) # 若适应度已经是最小化的(比如直接返回距离),则需要修改selBest的排序逻辑: # history.register('best_ind', lambda pop: tools.selBest(pop, 1, fit_func=lambda ind: -ind.fitness.values[0])[0]) history.register('best_ind', lambda pop: tools.selBest(pop, 1)[0]) mstats = tools.MultiStatistics(fitness=stats, history=history) hof = tools.HallOfFame(consts.HALL_OF_FAME_SIZE) population, logbook = algorithms.eaSimple(population, toolbox, cxpb=consts.P_CROSSOVER, mutpb=consts.P_MUTATION, ngen=consts.MAX_GENERATIONS, stats=mstats, halloffame=hof, verbose=True) # 从logbook中提取每一代的最优个体 best_individuals = [record['history']['best_ind'] for record in logbook]
方法二:利用HallOfFame+自定义钩子函数
HallOfFame会自动维护每一代的最优个体,你可以在每代结束后直接记录其中的最优个体:
from deap import tools, algorithms hof = tools.HallOfFame(consts.HALL_OF_FAME_SIZE) best_individuals = [] # 定义每代结束后的回调函数 def log_best(population, *args, **kwargs): # HallOfFame的第一个元素就是当前全局最优,若要每代的种群最优则用selBest best_individuals.append(hof[0]) # 自定义eaSimple的循环(替代原algorithms.eaSimple调用) population = toolbox.population(n=consts.POPULATION_SIZE) logbook = tools.Logbook() logbook.header = ['gen', 'nevals'] + (stats.fields if stats else []) for gen in range(consts.MAX_GENERATIONS): # 选择、交叉、变异 offspring = algorithms.varAnd(population, toolbox, cxpb=consts.P_CROSSOVER, mutpb=consts.P_MUTATION) # 评估后代 fits = toolbox.map(toolbox.evaluate, offspring) for fit, ind in zip(fits, offspring): ind.fitness.values = fit # 更新HallOfFame hof.update(offspring) # 记录当前最优 log_best(offspring) # 替换种群 population = offspring # 编译统计数据 record = stats.compile(population) if stats else {} logbook.record(gen=gen, nevals=len(offspring), **record) if verbose: print(logbook.stream)
关键优化点
- 避免重复计算适应度:不要在统计函数中再次调用
tspDistance,直接使用个体已存储的ind.fitness.values,这是最影响性能的点。 - 使用内置高效函数:
tools.selBest是DEAP优化过的选择函数,比自定义的filter+lambda逻辑快得多。 - 合理利用HallOfFame:它会自动维护历史最优个体,无需手动遍历种群查找。
内容的提问来源于stack exchange,提问作者Vya4eslav
相关产品推荐
相关产品推荐

