检查点¶
在本教程中,我们将介绍如何在您的进化过程中实现持久性。唯一需要的工具是一个简单的 字典
和一个序列化方法。重要数据将被插入字典并序列化到文件中,以便在出现问题时,可以从最后一个保存的检查点恢复进化。它还可以用于在预设的终止条件之外继续进化。
在标准算法如eaSimple、eaMuPlus/CommaLambda和eaGenerateUpdate中不提供检查点功能。您必须创建自己的算法(或复制现有的算法)并自行引入此功能。
从一个非常基础的例子开始,我们将涵盖所有必要的步骤来检查点化所需的一切以恢复进化。我们跳过类定义和工具箱中的工具注册,直接进入算法和主函数。我们的主函数接收一个可选的字符串参数,该参数包含要恢复的检查点文件的路径。:
import pickle
def main(checkpoint=None):
if checkpoint:
# A file name has been given, then load the data from the file
with open(checkpoint, "rb") as cp_file:
cp = pickle.load(cp_file)
population = cp["population"]
start_gen = cp["generation"]
halloffame = cp["halloffame"]
logbook = cp["logbook"]
random.setstate(cp["rndstate"])
else:
# Start a new evolution
population = toolbox.population(n=300)
start_gen = 0
halloffame = tools.HallOfFame(maxsize=1)
logbook = tools.Logbook()
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", numpy.mean)
stats.register("max", numpy.max)
for gen in range(start_gen, NGEN):
population = algorithms.varAnd(population, toolbox, cxpb=CXPB, mutpb=MUTPB)
# Evaluate the individuals with an invalid fitness
invalid_ind = [ind for ind in population if not ind.fitness.valid]
fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
ind.fitness.values = fit
halloffame.update(population)
record = stats.compile(population)
logbook.record(gen=gen, evals=len(invalid_ind), **record)
population = toolbox.select(population, k=len(population))
if gen % FREQ == 0:
# Fill the dictionary using the dict(key=value[, ...]) constructor
cp = dict(population=population, generation=gen, halloffame=halloffame,
logbook=logbook, rndstate=random.getstate())
with open("checkpoint_name.pkl", "wb") as cp_file:
pickle.dump(cp, cp_file)
现在,整个数据将在每 FREQ 代写入一个序列化的字典中。如果主函数给定了一个检查点文件的路径,则会加载检查点。在这种情况下,进化将从最后一个检查点继续。它将产生与未停止并重新加载时完全相同的结果,因为我们还恢复了随机模块的状态。如果你使用 numpy 的随机数,别忘了保存和重新加载它们的状态。