别再死磕数学公式了!用Python 3.11手把手带你复现遗传算法(附完整代码)
用Python 3.11实战遗传算法:从零构建到函数优化
在算法学习的道路上,遗传算法(Genetic Algorithm, GA)常常因为涉及生物进化理论而让初学者望而生畏。但今天,我们将用Python 3.11和NumPy库,通过不到150行代码实现一个完整的遗传算法框架,并应用于经典的Rastrigin函数优化问题。这种方法完全跳过了复杂的数学推导,让你在代码编写和运行结果中直观理解种群进化、自然选择的精髓。
1. 环境准备与问题定义
首先确保你的Python环境已安装3.11版本,这是目前执行效率最高的Python版本之一。我们将使用以下库:
pip install numpy matplotlib
Rastrigin函数是优化算法常用的测试函数,其特点是具有大量局部极小值点,全局最小值在原点(0,0)。在二维情况下,函数定义为:
import numpy as np
def rastrigin(x):
"""二维Rastrigin函数"""
A = 10
return A*2 + (x[0]**2 - A*np.cos(2*np.pi*x[0])) + (x[1]**2 - A*np.cos(2*np.pi*x[1]))
为什么选择这个函数? 因为它的多模态特性能够很好地测试算法是否陷入局部最优。我们的目标是找到使函数值最小的(x,y)组合。
2. 遗传算法核心组件实现
2.1 种群初始化与编码设计
遗传算法的第一步是创建初始种群。我们采用实数编码而非二进制编码,这更适合连续函数优化问题:
def initialize_population(pop_size, x_bound, y_bound):
"""初始化种群"""
population = np.zeros((pop_size, 2))
population[:, 0] = np.random.uniform(x_bound[0], x_bound[1], size=pop_size)
population[:, 1] = np.random.uniform(y_bound[0], y_bound[1], size=pop_size)
return population
参数说明:
pop_size: 种群规模,通常20-100x_bound,y_bound: 变量取值范围,如([-5.12, 5.12], [-5.12, 5.12])
2.2 适应度评估与选择机制
适应度函数决定了个体被选择的概率。对于最小化问题,我们采用以下转换:
def evaluate_fitness(population):
"""计算种群中每个个体的适应度"""
fitness = 1 / (1 + rastrigin(population.T))
return fitness / np.sum(fitness) # 归一化
赌轮盘选择实现如下:
def selection(population, fitness, elite_size=2):
"""赌轮盘选择"""
elite_indices = np.argsort(fitness)[-elite_size:]
selected = population[elite_indices]
# 轮盘赌选择剩余个体
indices = np.random.choice(len(population), size=len(population)-elite_size,
p=fitness, replace=True)
selected = np.vstack([selected, population[indices]])
return selected
注意:保留精英(elite_size)可以确保最优个体不被随机选择淘汰
2.3 交叉与变异操作
单点交叉和均匀变异是实现种群多样性的关键:
def crossover(parents, offspring_size):
"""单点交叉"""
offspring = np.zeros(offspring_size)
crossover_point = np.random.randint(1, offspring_size[1])
for i in range(offspring_size[0]):
parent1_idx = i % len(parents)
parent2_idx = (i+1) % len(parents)
offspring[i, :crossover_point] = parents[parent1_idx, :crossover_point]
offspring[i, crossover_point:] = parents[parent2_idx, crossover_point:]
return offspring
def mutation(offspring, mutation_rate=0.1, mutation_scale=0.5):
"""均匀变异"""
for i in range(len(offspring)):
if np.random.random() < mutation_rate:
offspring[i] += np.random.normal(0, mutation_scale, size=2)
return offspring
参数对比实验表明:
| 参数 | 推荐范围 | 影响效果 |
|---|---|---|
| mutation_rate | 0.05-0.2 | 过高导致随机游走,过低丧失多样性 |
| mutation_scale | 0.1-1.0 | 控制变异幅度,应与搜索空间匹配 |
3. 完整算法流程与可视化
将上述组件整合成完整遗传算法:
def genetic_algorithm(pop_size=50, generations=100, elite_size=2,
mutation_rate=0.1, bounds=([-5.12,5.12],[-5.12,5.12])):
# 初始化
population = initialize_population(pop_size, *bounds)
best_fitness = []
for gen in range(generations):
# 评估
fitness = evaluate_fitness(population)
best_idx = np.argmax(fitness)
best_fitness.append(rastrigin(population[best_idx]))
# 选择
selected = selection(population, fitness, elite_size)
# 交叉变异
offspring = crossover(selected, (pop_size-elite_size, 2))
offspring = mutation(offspring, mutation_rate)
# 新一代种群
population[:elite_size] = selected[:elite_size]
population[elite_size:] = offspring
return population, best_fitness
可视化收敛过程:
import matplotlib.pyplot as plt
def plot_results(best_fitness):
plt.figure(figsize=(10,6))
plt.plot(best_fitness, 'b', linewidth=2)
plt.title('Genetic Algorithm Convergence')
plt.xlabel('Generation')
plt.ylabel('Best Fitness (Rastrigin Value)')
plt.grid(True)
plt.show()
4. 参数调优与实战技巧
通过多次实验,我们发现以下经验法则:
-
种群规模 :
- 太小(<20):多样性不足,易早熟收敛
- 太大(>100):计算开销大,收敛慢
- 推荐:30-50
-
变异策略优化 :
- 自适应变异率:随着代数增加逐渐降低
def adaptive_mutation_rate(gen, max_gen, base_rate=0.2): return base_rate * (1 - gen/max_gen) -
约束处理 :
- 当变量超出边界时,可采用反射或随机重置
def apply_bounds(population, bounds): for i in range(population.shape[1]): population[:,i] = np.clip(population[:,i], bounds[i][0], bounds[i][1]) return population -
并行评估 :
- 利用多核加速适应度计算
from multiprocessing import Pool def parallel_evaluate(population): with Pool() as p: results = p.map(rastrigin, population) return 1 / (1 + np.array(results))
5. 进阶扩展与工程实践
在实际项目中应用遗传算法时,还需要考虑:
-
混合策略 :将GA与局部搜索(如梯度下降)结合
def hybrid_optimize(individual, lr=0.01, steps=50): """用梯度下降微调GA结果""" x = individual.copy() for _ in range(steps): grad = numerical_gradient(rastrigin, x) x -= lr * grad return x -
多目标优化 :使用NSGA-II等算法处理多个目标函数
-
早停机制 :当连续多代没有改进时终止迭代
if len(best_fitness) > 20 and (np.min(best_fitness[-20:]) - np.min(best_fitness[-10:])) < 1e-6: break -
日志记录 :保存每代种群信息供后续分析
import pandas as pd def save_generation_log(population, gen, filename): df = pd.DataFrame(population, columns=['x', 'y']) df['generation'] = gen df['fitness'] = evaluate_fitness(population) df.to_csv(filename, mode='a', header=not os.path.exists(filename))
在电商推荐系统优化项目中,我们曾用类似方法调整排序算法参数,相比网格搜索效率提升近10倍。关键是将业务指标(如转化率)巧妙设计为适应度函数,并通过限制参数范围确保解的可行性。
更多推荐


所有评论(0)