AI人工智能 使用遗传算法实现解决方案

You are here:
← All Topics

本节向您介绍使用遗传算法实现解决方案。

生成位模式

以下示例显示了如何根据 One Max 问题生成一个包含15个字符串的位串。

如下所示导入必要的软件包 -


import randomfrom deap import base, creator, tools

定义评估函数。 这是创建遗传算法的第一步。


def eval_func(individual):   target_sum = 15 return len(individual) - abs(sum(individual) - target_sum)

现在,使用正确的参数创建工具箱 -


def _toolbox(num_bits):   creator.("FitnessMax", base.Fitness, weights=(1.0,))   creator.("Individual", list, fitness=creator.FitnessMax)

初始化工具箱


toolbox = base.Toolbox()toolbox.register("attr_bool", random.randint, 0, 1)toolbox.register("individual", tools.initRepeat, creator.Individual,   toolbox.attr_bool, num_bits)toolbox.register("population", tools.initRepeat, list, toolbox.individual)

注册计算操作符 -


toolbox.register("evaluate", eval_func)

现在,注册交叉运算符 -


toolbox.register("mate", tools.cxTwoPoint)

注册一个可变运算符 -


toolbox.register("mutate", tools.mutFlipBit, indpb = 0.05)

定义育种操作符 -


toolbox.register("choose", tools.selTournament, tournsize = 3)return toolboxif __name__ == "__main__":   num_bits = 45   toolbox = _toolbox(num_bits)   random.seed(7)   population = toolbox.population(n = 500)   probab_crossing, probab_mutating = 0.5, 0.2   num_generations = 10 print('\nEvolution process starts')

评估整个人口 -


fitnesses = list(map(toolbox.evaluate, population))for ind, fit in zip(population, fitnesses):   ind.fitness.values = fitprint('\nEvaluated', len(population), 'individuals')

经过几代人的创建和迭代 -


for g in range(num_generations): print("\n- Generation", g)

选择下一代个人 -


offspring = toolbox.choose(population, len(population))

现在,克隆选定的个人 -


offspring = list(map(toolbox.clone, offspring))

对后代应用交叉和变异 -


for child1, child2 in zip(offspring[::2], offspring[1::2]): if random.random() < probab_crossing:   toolbox.mate(child1, child2)

删除孩子的适应值


del child1.fitness.valuesdel child2.fitness.values

现在,应用突变 -


for mutant in offspring: if random.random() < probab_mutating:   toolbox.mutate(mutant) del mutant.fitness.values

评估与无效的健身个体 -


invalid_ind = [ind for ind in offspring if not ind.fitness.valid]fitnesses = map(toolbox.evaluate, invalid_ind)for ind, fit in zip(invalid_ind, fitnesses):   ind.fitness.values = fitprint('Evaluated', len(invalid_ind), 'individuals')

现在,用下一代个体替代人口 -


population[:] = offspring

打印当代人的统计数据 -


fits = [ind.fitness.values[0] for ind in population]length = len(population)mean = sum(fits) / lengthsum2 = sum(x*x for x in fits)std = abs(sum2 / length - mean**2)**0.5print('Min =', min(fits), ', Max =', max(fits))print('Average =', round(mean, 2), ', Standard deviation =',round(std, 2))print("\n- Evolution ends")

打印最终输出 -


   best_ind = tools.selBest(population, 1)[0] print('\nBest individual:\n', best_ind) print('\nNumber of ones:', sum(best_ind))Following would be the output:Evolution process startsEvaluated 500 individuals- Generation 0Evaluated 295 individualsMin = 32.0 , Max = 45.0Average = 40.29 , Standard deviation = 2.61- Generation 1Evaluated 292 individualsMin = 34.0 , Max = 45.0Average = 42.35 , Standard deviation = 1.91- Generation 2Evaluated 277 individualsMin = 37.0 , Max = 45.0Average = 43.39 , Standard deviation = 1.46… … … …- Generation 9Evaluated 299 individualsMin = 40.0 , Max = 45.0Average = 44.12 , Standard deviation = 1.11- Evolution endsBest individual:[0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1,  1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1]Number of ones: 15

符号回归问题

这是遗传编程中最著名的问题之一。 所有符号回归问题都使用任意数据分布,并尝试用符号公式来拟合最准确的数据。 通常,像 RMSE (均方根误差)这样的度量用于度量个体的适应度。 这是一个经典的回归问题,这里我们使用方程: 5x3-6x2 + 8x = 1。 我们需要按照上述示例中的所有步骤进行操作,但主要部分是创建基元集,因为它们是个人的构建基块,因此可以开始评估。 这里将使用经典的基元集。

以下 Python 代码详细解释了这一点 -


import operatorimport mathimport randomimport numpy as npfrom deap import algorithms, base, creator, tools, gpdef division_operator(numerator, denominator): if denominator == 0: return 1 return numerator / denominatordef eval_func(individual, points):   func = toolbox.compile(expr=individual) return math.fsum(mse) / len(points),def _toolbox():   pset = gp.PrimitiveSet("MAIN", 1)   pset.addPrimitive(operator.add, 2)   pset.addPrimitive(operator.sub, 2)   pset.addPrimitive(operator.mul, 2)   pset.addPrimitive(division_operator, 2)   pset.addPrimitive(operator.neg, 1)   pset.addPrimitive(math.cos, 1)   pset.addPrimitive(math.sin, 1)   pset.addEphemeralConstant("rand101", lambda: random.randint(-1,1))   pset.renameArguments(ARG0 = 'x')   creator.("FitnessMin", base.Fitness, weights = (-1.0,))   creator.("Individual",gp.PrimitiveTree,fitness=creator.FitnessMin)   toolbox = base.Toolbox()   toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=2)   toolbox.expr)   toolbox.register("population",tools.initRepeat,list, toolbox.individual)   toolbox.register("compile", gp.compile, pset = pset)   toolbox.register("evaluate", eval_func, points = [x/10. for x in range(-10,10)])   toolbox.register("choose", tools.selTournament, tournsize = 3)   toolbox.register("mate", gp.cxOnePoint)   toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)   toolbox.register("mutate", gp.mutUniform, expr = toolbox.expr_mut, pset = pset)   toolbox.decorate("mate", gp.staticLimit(key = operator.attrgetter("height"), max_value = 17))   toolbox.decorate("mutate", gp.staticLimit(key = operator.attrgetter("height"), max_value = 17)) return toolboxif __name__ == "__main__":   random.seed(7)   toolbox = _toolbox()   population = toolbox.population(n = 450)   hall_of_fame = tools.HallOfFame(1)   stats_fit = tools.Statistics(lambda x: x.fitness.values)   stats_size = tools.Statistics(len)   mstats = tools.MultiStatistics(fitness=stats_fit, size = stats_size)   mstats.register("avg", np.mean)   mstats.register("std", np.std)   mstats.register("min", np.min)   mstats.register("max", np.max)   probab_crossover = 0.4   probab_mutate = 0.2   number_gen = 10   population, log = algorithms.eaSimple(population, toolbox,      probab_crossover, probab_mutate, number_gen,      stats = mstats, halloffame = hall_of_fame, verbose = True)