遗传算法的名字听着玄,其实思路很朴素:先随机撒一堆积木(个体),让表现好的多留后代,后代在父母基础上稍微变一点点,反复几十轮,最后剩下的就离最优解不远了。
例子:找使 f(x)=x·sin(10πx)+2 最大的 x
限定 x 在 [-1, 2] 之间,取 1000 个点画图会发现曲线起伏很多,有好几个局部高点。这正是遗传算法擅长的场景:不用求导,也不需要知道函数长什么样。
四个核心步骤
- 编码:把 x 表示成二进制串,比如用 16 位表示,000...0 对应 -1,111...1 对应 2,中间等分。
- 适应度:直接把 f(x) 的值当分数。分数越高,越有资格留后代。
- 选择:用轮盘赌。每个个体按分数占比分一块扇形,转盘两次选出两个父母。分数高的被选中概率大,但分数低的也不是完全没有机会,这保证了多样性。
- 交叉与变异:两个父母串在随机位置剪开互换尾巴,生成子代;再以很小的概率(比如 0.01)把某一位翻转。交叉负责在已有解附近搜索,变异负责跳出局部最优。
跑一轮长什么样
第 0 代是 100 个随机串,适应度参差不齐。大约到 20 代,大部分个体都聚集在最高那个峰附近;到 100 代,最优 x 的值基本稳定,图上能看到种群从散点变成一根竖线。中间也会出现「早熟」:整群都挤在一个不高的局部峰上,这时候提高变异率就有效。
几个参数怎么定
- 种群规模:50 到 200 之间,太小容易早熟,太大算得慢。
- 交叉率:0.7 到 0.9,太低了探索不够。
- 变异率:一般 0.001 到 0.05,凭经验调。
- 迭代次数:看适应度曲线是否已经平稳,不必死记固定值。
什么时候别用它
目标函数简单、能直接求导或者穷举的,老老实实解就行,用遗传算法是给自己找麻烦。它真正有用的场合是:目标函数写不出解析式、变量很多、搜索空间大、还允许近似解。比如排课、路径优化、参数调优。
写代码时先跑小规模验证能不能收敛,别一上来就几十万次迭代。