【遗传算法】——更高级的猜猜法

【遗传算法】——更高级的猜猜法

学习遗传算法有2个月了,最近也开始读汪民乐、高晓光、范阳涛三位先生编著的《先进遗传算法及其工程应用》,记录这几个月我对遗传算法的浅显理解。

1. 何为猜猜?如何理解遗传算法

我理解的遗传算法:无非是高级点的猜猜法

先随机生成一堆方案,在迭代中随机更改这些方案的部分举措;

如果发现更好了(或更坏了),就随机保留或抛弃。在迭代最后选择一个最好的结果。

既然是猜猜法,那自然可以用在很多地方:物资调度、决策排序、选址、指派、路径规划等等。这些都是现阶段遗传算法适用的领域。

  • 举个例子:

你要写一份5道选择题的试卷,你不知道答案,但是你可以反复提交这份试卷获得你的分数。

现在你在答题卡上随机写上AAAAA,获得分数2分。

这里的答案AAAAA,就是染色体的编码,这里的2分,对应着染色体的适应度

你再改成AAAAB,分数高了1分。(染色体的遗传操作——变异

这时候你知道,下次再改答案需要从AAAAB开始改了,就因为这个答案的分数高。

从遗传算法上看,这个染色体的适应度更高。我们通过选择留下适应度更高的染色体。

当然,和你一起答题的不止一人,恰如我们一开始给出的染色体数量不止一个

有个同学随机的答案是CCCCC,你参考了他的前两个答案,得到一个新答案CCAAB,分数又高了1分。

这就是不同染色体之间的交叉操作。

就这么猜上100次,就会有极大的概率获得5分。

(最后我会给出源代码复现该场景)

至此,整合书中内容,我愿给出如下定义:

遗传算法是一种全局优化的自适应概率搜索算法,模拟自然选择和遗传进化的计算模型。

2. 为何高级?遗传算法的理论基础

和一般的猜猜法不同,遗传算法具有一定的数学基础理论,它可以得到一种模式定理

遗传算法中,在选择、交叉、变异运算作用下,具有低阶、短定义长度、平均适应度高于种族适应度值的模式在子代中呈指数级增长。

通俗理解,就是物竞天择,适者生存。这可以确保遗传算法寻求最优样本的可能性。

但模式定理并不表明遗传算法一定能够找到最优样本,积木块假设却可以:

个体的基因通过选择、交叉、变异等遗传算法的作用,能够相互拼接在一起,形成适应度更高的个体编码串,最终接近最优样本。

由书中给出遗传算法隐含并行性原理推出可能存活的模式数目:
n = c M 3 = O ( M 3 ) n = cM^3 = O(M^3) n=cM3=O(M3)
其中M是我们给出的染色体数目,也就是一开始的方案数。故我们可以得到结论:

虽然在进化过程中遗传算法只处理了M个个体,但实际上并行处理了与M的二次方成正比例的模式数。这种并行性使得遗传算法可以快速搜索到一些比较好的模式。

总结:遗传算法比猜猜法高级。

3. 遗传算法的问题

当然,遗传算法也有其致命的问题,那就是欺骗性问题收敛速度

  • 欺骗性问题:若评估适应度时存在多峰值,是有可能会陷入一个局部最优解,变得骄傲自大无法自拔。

    措施:人们一般会综合其他智能算法,比如蚁群、粒子群、模拟退火等算法,尽量确保得到的结果是接近全局最优解的。

  • 收敛问题:遗传算法的何时收敛也是人们关注的一个问题。
    过早收敛——那叫“早熟”。过晚收敛——那叫“效率低下”。

    措施:人们一般根据具体的算法模型去调整最大迭代次数等参数,从而优化遗传算法的收敛速度。

4. 遗传算法框架代码(情景复现)

仅需引入一个random库,运行的结果多半是5分或者4分。
一起答题的同学越多,迭代次数越大,满分的概率就越大。

import random

# 试卷题目数量
num_questions = 5

# 每个染色体的长度:我们给出的答案长度
chromosome_length = num_questions

# 种群数量:一起答题的同学数量
population_size = 20

# 最大迭代次数:重复提交答案,校对修改的次数
max_iterations = 200

# 变异率:随机修改自己答案的概率
mutation_rate = 0.1

# 试卷答案:仅用于计算适应度,这里的染色体(每个同学)一开始并不知道答案
answers = "BCDAB"

# 适应度函数:计算答案的评分
# 实际问题中,我们一般采取路径的长度,成本的高低,执行的时间来作为适应度的评判标准。
def fitness(chromosome):
    score = 0
    for i in range(num_questions):
        if chromosome[i] == answers[i]:
            score += 1
    return score

# 初始化种群:一开始随便写答案
population = []
for i in range(population_size):
    chromosome = ""
    for j in range(chromosome_length):
        chromosome += random.choice(["A", "B", "C","D"])
    population.append(chromosome)
    # print("开始答案:" + chromosome)


# 遗传算法主循环
for iteration in range(max_iterations):
    # 计算每个染色体的适应度:提交试卷得到分数
    fitness_values = []
    for chromosome in population:
        fitness_values.append(fitness(chromosome))

    # 选择操作,选择适应度高的染色体:尽量选择分数更大的试卷
    total_fitness = sum(fitness_values)
    selection_probabilities = [fitness_value / total_fitness for fitness_value in fitness_values]
    selected_population = []
    for i in range(population_size):
        selected_chromosome = random.choices(population, weights=selection_probabilities)[0]
        selected_population.append(selected_chromosome)

    # 交叉操作,随机选取两个染色体进行交叉:这里随机选择两份试卷,随机抄答案
    # 也可以设一个交叉概率限制一下
    offspring_population = []
    for i in range(population_size):
        parent1 = random.choice(selected_population)
        parent2 = random.choice(selected_population)
        offspring = ""
        for j in range(chromosome_length):
            if random.random() < 0.5:
                offspring += parent1[j]
            else:
                offspring += parent2[j]
        offspring_population.append(offspring)

    # 变异操作,对每个染色体按照一定概率进行变异:随机修改自己的答案
    mutated_population = []
    for chromosome in offspring_population:
        mutated_chromosome = ""
        for j in range(chromosome_length):
            if random.random() < mutation_rate:
                mutated_chromosome += random.choice(["A", "B", "C","D"])
            else:
                mutated_chromosome += chromosome[j]
        mutated_population.append(mutated_chromosome)

    # 更新种群:得到了一群新的答案,它们平均分数会趋向更高。
    population = mutated_population

# 输出最终结果
best_chromosome = max(population, key=fitness)
best_fitness = fitness(best_chromosome)
print("Best Paper:", best_chromosome)
print("Best score:", best_fitness)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如果皮卡会coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值