一、这个算法有点意思!
大家有没有遇到过这样的情况——想找一个复杂函数的最高点,用常规方法试了半天就是找不到?(举个手让我看看🙋)今天要介绍的遗传算法(Genetic Algorithm),就像生物进化一样神奇,能帮我们找到函数的最优解!
先给大家看个例子:假设我们要找函数 f(x) = x² 在 [0,31] 区间的最大值。传统方法可能需要遍历所有整数,但遗传算法只需要几代"进化"就能找到正确答案!(后面会揭晓具体实现)
二、遗传算法的核心四步走
1. 编码:把问题装进DNA里
- 二进制编码:把x值转成5位二进制(比如15→01111)
- 重要技巧:编码长度决定精度,这里5位对应32种可能值
- (新手注意!)编码方案直接影响算法效率
2. 初始种群:随机生成第一代
import random
def create_population(size):
return [random.randint(0, 31) for _ in range(size)]
population = create_population(10) # 初始10个个体
3. 选择:优胜劣汰的时刻到了!
- 轮盘赌选择法:适应度高的个体有更大存活概率
def selection(population):
fitness = [x**2 for x in population]
total = sum(fitness)
return random.choices(population, weights=fitness, k=len(population))
4. 交叉:基因交换产生新生命
- 单点交叉:随机选个位置交换父母基因
def crossover(parent1, parent2):
point = random.randint(1,4)
mask = (0b11111 >> point) << point
child1 = (parent1 & mask) | (parent2 & ~mask)
child2 = (parent2 & mask) | (parent1 & ~mask)
return child1, child2
5. 变异:给进化加点意外
def mutation(child):
if random.random() < 0.1: # 10%变异概率
bit = 1 << random.randint(0,4)
return child ^ bit
return child
三、参数调校的三大黄金法则
- 种群数量:20-100是常用范围(太小容易早熟,太大计算慢)
- 变异概率:0.001-0.1之间(太高会破坏优秀基因)
- 停止条件的三种设置方式:
- 固定迭代次数(比如100代)
- 连续N代没有改进
- 达到目标适应度
(实测发现!)对于我们的x²问题,以下参数组合效果最佳:
- 种群大小:20
- 交叉概率:0.8
- 变异概率:0.05
- 迭代次数:50
四、你可能遇到的三大坑(附解决方案)
1. 早熟收敛(整个种群过早趋同)
- 对策:增加变异概率,使用精英保留策略
2. 收敛速度慢
- 对策:采用自适应交叉/变异概率
3. 陷入局部最优
# 解决方法:引入移民策略
def immigration(population, rate=0.1):
new_blood = [random.randint(0,31) for _ in range(int(len(population)*rate))]
return population[:-len(new_blood)] + new_blood
五、完整代码大公开
def genetic_algorithm():
population = create_population(20)
for _ in range(50):
# 选择
selected = selection(population)
# 交叉
new_pop = []
for i in range(0, len(selected), 2):
p1, p2 = selected[i], selected[i+1]
c1, c2 = crossover(p1, p2)
new_pop.extend([mutation(c1), mutation(c2)])
# 移民
population = immigration(new_pop)
# 记录最佳
best = max(population, key=lambda x: x**2)
return best
print(f"找到的最大值是:{genetic_algorithm()}") # 应该输出31!
六、升级你的算法装备
想要更上一层楼?试试这些进阶技巧:
- 实数编码:适合连续函数优化
- NSGA-II:多目标优化神器
- 并行计算:用多核加速进化过程
(个人经验分享)在实际项目中,建议先用简单参数快速测试,找到大致方向后再精细调参。记得保存每代的进化数据,这对分析算法行为超有帮助!
七、总结
通过这个案例,我们发现:
- 遗传算法特别适合复杂、多峰的函数优化
- 参数设置需要平衡探索与开发的矛盾
- 生物进化思想在计算机领域的完美应用
下次遇到棘手的优化问题,不妨试试这个"仿生算法"。说不定它会给你带来意想不到的惊喜!(就像我当年第一次用它优化神经网络参数时的震撼😉)
最后留个思考题:如果把x的范围扩展到[0,1023],需要多少位二进制编码?欢迎在评论区讨论!