文章目录
一、这个数学题居然用生物进化来解?
咱们先来看这个经典问题:y = x² 在区间[-10,10]找最大值。正常解法求导找极值点?那太没意思了!(拍桌)今天玩个大的——用遗传算法模拟生物进化来找答案!
遗传算法的神奇之处在于,它把数学问题转化成了生存游戏。想象一群数字生物在解空间里游荡,强的活下来繁衍后代,弱的被淘汰,经过N代进化后,最终找到最优解!
二、算法核心六步走(必考知识点)
- 种群初始化:随机生成20-100个初始解(别太少!)
- 二进制编码:把实数转成二进制,比如5→0101(注意编码长度影响精度)
- 适应度计算:每个解的y值就是它的分数,y越大越优秀
- 选择交配:轮盘赌选父母,概率=个体适应度/总适应度
- 染色体交叉:随机选交叉点交换基因片段(推荐单点交叉)
- 基因变异:按1%-5%概率翻转某个bit(变异率别太高!)
举个🌰:假设初始解是3(0011)和5(0101),交叉后可能变成0011和0101,变异可能变成0010
三、Python代码逐行解析
import random
import matplotlib.pyplot as plt
# 目标函数(这里可以替换成任何函数!)
def target_function(x):
return x ** 2
# 二进制转十进制(注意精度调节)
def decode(binary, lower=-10, upper=10, bit_length=16):
int_val = int(''.join(map(str,binary)),2)
return lower + (upper - lower) * int_val / (2**bit_length -1)
# 生成随机个体
def create_individual(bit_length):
return [random.randint(0,1) for _ in range(bit_length)]
# 交叉操作(这里使用单点交叉)
def crossover(parent1, parent2):
point = random.randint(1,len(parent1)-2)
return parent1[:point]+parent2[point:], parent2[:point]+parent1[point:]
# 变异操作(随机翻转一个bit)
def mutate(child):
index = random.randint(0,len(child)-1)
child[index] ^= 1
return child
# 主程序
population_size = 50
generations = 100
bit_length = 16
mutation_rate = 0.01
history = []
# 初始化种群
population = [create_individual(bit_length) for _ in range(population_size)]
for _ in range(generations):
# 计算适应度
fitness = [target_function(decode(ind)) for ind in population]
history.append(max(fitness))
# 选择
selected = random.choices(
population,
weights=fitness,
k=population_size
)
# 交叉变异
new_population = []
for i in range(0, population_size, 2):
parent1 = selected[i]
parent2 = selected[i+1]
child1, child2 = crossover(parent1, parent2)
if random.random() < mutation_rate:
child1 = mutate(child1)
if random.random() < mutation_rate:
child2 = mutate(child2)
new_population.extend([child1, child2])
population = new_population
# 可视化进化过程
plt.plot(history)
plt.title('进化轨迹(最大值变化曲线)')
plt.xlabel('Generation')
plt.ylabel('Max Value')
plt.show()
四、调参进阶技巧(血泪经验)
- 种群数量:20-200之间,太大会降低效率,太小容易早熟
- 变异率:0.5%-5%是黄金区间(超过10%就成随机搜索了!)
- 编码长度:16位精度可达0.0003,32位精度更高但更耗内存
- 精英保留:每代保留前5%最优个体不参与交叉变异(防退化)
五、常见坑点预警!!
- 早熟收敛:所有个体都一模一样?快检查变异率是不是太低了!
- 收敛过慢:尝试增大选择压力(比如用锦标赛选择代替轮盘赌)
- 精度不够:把二进制编码长度从16位提到32位试试
- 负数处理:记得在解码时转换数值范围(比如-10到10)
六、效果展示与扩展
运行代码后你会看到,算法在约30代时就找到了接近100的最大值(实际理论最大值是10²=100)。如果把目标函数改成其他复杂函数(比如sin(x)+cos(2x)),只需要修改target_function即可!

七、还能怎么玩更刺激?
- 多峰值函数:试试y = x + 10sin(5x) +7cos(4x),看算法能否找到全部极值
- 动态环境:让目标函数随时间变化,考验算法的实时追踪能力
- 多目标优化:同时优化多个目标函数(需要引入Pareto最优解)
八、为什么选遗传算法?
比起梯度下降等传统方法,它有三大优势:
- 不需要目标函数可导(黑箱优化也OK!)
- 全局搜索能力强(不易陷入局部最优)
- 并行性好(种群中的个体可以同时进化)
下次遇到复杂优化问题,别急着求导,试试让计算机帮你"进化"出一个最优解吧!记得调参时多试几次,遗传算法有时候也看"运气"呢~(笑)
&spm=1001.2101.3001.5002&articleId=147981295&d=1&t=3&u=d904153998024536957ccc2e9a2defa2)
22万+

被折叠的 条评论
为什么被折叠?



