使用Deap库eaSimple函数时遇'int'对象无len()方法错误求助
问题:Deap遗传算法调用eaSimple时报错"object 'int' has no len()"
使用Python和Deap库开发基础遗传算法,调用eaSimple函数进行种群演化时,持续触发错误:"object 'int' has no len()"。代码大多参考课程示例(据称可正常运行),其中MyError函数已调试确认返回int类型,相关代码片段如下:
def safediv (dividend, divisor): if divisor != 0: return dividend / divisor else: return dividend #select the primitives pset = gp.PrimitiveSet("main", 6) #arity is 6 because as we'll see, the primitiveset 's function is calculated over 6 param (f12,d12, f1, etc..)' pset.addPrimitive(operator.add, 2) pset.addPrimitive(operator.mul, 2) pset.addPrimitive(operator.sub, 2) pset.addPrimitive(safediv,2) creator.create ("MyFitness", base.Fitness, weights=(-1.0,)) creator.create ("Individual", gp.PrimitiveTree, fitness = creator.MyFitness) toolbox = base.Toolbox() toolbox.register("expr", gp.genGrow, pset=pset, min_ = 1, # minimum depth of primitivetree max_ = 4) # maximum depth of primitivetree (max of nested primitive calls) toolbox.register("individual", #function for creating the single individual tools.initIterate, #initIterate takes the first arg (creator.Individual) and builds it with the structur coming from the second creator.Individual, # (tools.expr) toolbox.expr) toolbox.register ("compile", gp.compile, pset = pset) toolbox.register("population", tools.initRepeat, list, toolbox.individual) #parameters to pass to the eaSimple algorithm toolbox.register("evaluate", MyError,y_train = y_train_set, x_train_ambo = x_train_set_ambo, x_train_extract =x_train_set_extract ) toolbox.register("mate",tools.cxUniform , indpb = 0.3) #Uniform swaps individual bits between the two parents, rather than segments #(see book) toolbox.register("expr_mut", gp.genFull, min_=0,max_=2) toolbox.register("mutate",gp.mutUniform, expr=toolbox.expr_mut,pset= pset) toolbox.register("select", tools.selTournament, tournSize = 3) #tournaments allow to distribute the selection between multiple processors #as picking individuals by 3 at a time can have each #tournament performed #on a different cpu and then the selection parallelized #decorators to limit the growth of the PrimitiveTree toolbox.decorate("mate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17)) toolbox.decorate("mutate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17)) pop = toolbox.population(n=300) hof = tools.HallOfFame(1) stat_fit = tools.Statistics (key=lambda ind: ind.fitness.values) stat_size = tools.Statistics ( key=len) mstats = tools.MultiStatistics(fitness = stat_fit, size = stat_size) mstats.register ("min", np.min) mstats.register ("max", np.max) mstats.register ("avg", np.mean) mstats.register ("std", np.std) pop, log = algorithms.eaSimple(population = pop, toolbox = toolbox, cxpb = 0.5, mutpb = 0.1, ngen = num_gen, stats= mstats, halloffame=hof , verbose=True )
错误原因
核心问题在于Deap框架对适应度值的格式要求:
- Deap的
Fitness类强制要求values属性必须是元组类型,哪怕是单目标优化场景,也需要用元组包裹单个值。 - 你的
MyError函数返回int类型,而注册的evaluate函数直接将这个int返回,导致个体的fitness.values被赋值为int而非元组。后续框架内部(或统计模块)尝试调用len()获取适应度值的长度时,就会触发"object 'int' has no len()"错误。
解决方法
有两种简单的修正方式:
- 修改
MyError函数的返回值,将int包装为元组:# 假设原MyError返回语句为return error_val return (error_val,) - 或者在注册
evaluate时,用lambda函数将MyError的返回值包装为元组,无需修改原函数:toolbox.register("evaluate", lambda *args, **kwargs: (MyError(*args, **kwargs),), y_train=y_train_set, x_train_ambo=x_train_set_ambo, x_train_extract=x_train_set_extract)
内容的提问来源于stack exchange,提问作者Booji Boy
相关产品推荐
相关产品推荐

