传统遗传算法流程介绍
1. 创建初始种群
遗传算法的第一步是随机选择一组初始解(个体),这些个体通常由一组随机生成的染色体表示。每个染色体由基因组成,而每个基因则对应问题的一个变量或参数。
2. 计算适应度
针对每个个体,计算其适应度值。适应度函数用于评估个体解决问题的质量。在优化问题中,适应度函数的设计直接影响算法的收敛性和效率。
3. 选择、交叉和变异
-
选择(Selection):选择操作根据个体的适应度值从当前种群中选出有优势的个体,以便作为下一代的父母个体。通常使用轮盘赌选择或竞赛选择等方法。
-
交叉(Crossover):选定的父母个体根据某种规则(如单点交叉、多点交叉)交换染色体的一部分,生成新的后代染色体。
-
变异(Mutation):对新生成的后代染色体进行变异操作,以增加种群的多样性。变异通常以较低的概率在随机基因位置上进行,通过引入新的基因值。
4. 算法终止条件
遗传算法需要定义一个或多个终止条件,以确定何时停止迭代优化过程,例如:
- 达到预设的最大迭代次数。
- 最佳解的适应度值已经足够接近最优解(收敛判据)。
- 算法运行时间超过预定的时间限制等。
变种版本的遗传算法特点和应用
特点:
-
浮点数编码:将问题变量表示为浮点数,而不是传统的二进制编码。这种编码更直观且适用于实值问题。
-
固定比例交叉:每一代中,选择一部分个体作为父母个体,然后固定比例(如前10个作为父代,后40个作为交叉的子代)生成后代。这种方式可能有助于保留较优的个体和探索新的解空间。
-
随机组合交叉:在交叉操作中,选择两个父母个体随机组合其前后部分基因片段,而不是简单地按照染色体的中点进行交叉。这种方法增加了种群的多样性,有助于更全面地探索解空间。
应用:
-
复杂实值优化问题:适用于那些解空间连续、多变量和需要高效全局搜索的问题,如机器学习模型的参数优化。
-
参数优化:对于需要调整多个参数以获得最优结果的任务,例如深度学习模型的超参数优化。
-
探索性问题:对于需要在多个可能解之间进行快速探索的问题,这种方法可以有效地发现潜在的优化路径。
代码样例:
import numpy as np
import random
import matplotlib.pyplot as plt
# 定义目标函数(适应度函数),计算每个个体的适应度值
def objective_function(x):
return np.sum(100.0 * (x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)
# 随机生成一组候选解
def initialize_population(pop_size, dim):
# 初始化种群列表
population = []
# 循环生成每个个体
for _ in range(pop_size):
# 生成一个随机个体,每个基因值在[-5, 5]范围内
individual = np.random.uniform(-5, 5, dim)
# 将生成的个体添加到种群列表中
population.append(individual)
# 返回包含所有个体的种群数组
return np.array(population)
# 计算适应度
def calculate_fitness(population):
# 计算种群中每个个体的适应度值,并返回适应度数组
return np.array([objective_function(individual) for individual in population])
# 选择适应度值最小(最好)的个体作为父母。
def selection(population, fitness, num_parents):
# 初始化父母数组,大小为(num_parents, 个体维度)
parents = np.empty((num_parents, population.shape[1]))
# 循环选择父母个体
for i in range(num_parents):
# 找到适应度最小的个体索引
max_fitness_idx = np.where(fitness == np.min(fitness))
# 获取具体的索引值
max_fitness_idx = max_fitness_idx[0][0]
# 将选择的个体添加到父母数组中
parents[i, :] = population[max_fitness_idx, :]
# 将选中的个体适应度设置为无穷大,避免重复选择
fitness[max_fitness_idx] = float('inf')
# 返回选择的父母数组
return parents
# 从父母生成后代,通过交叉点互换基因片段
def crossover(parents, offspring_size):
# 初始化后代数组,大小为offspring_size
offspring = np.empty(offspring_size)
# 确定交叉点位置,通常为中点
crossover_point = np.uint8(offspring_size[1] / 2)
# 循环生成每个后代个体
for k in range(offspring_size[0]):
# 随机选择两个父母
parent1_idx = np.random.randint(0, parents.shape[0])
parent2_idx = np.random.randint(0, parents.shape[0])
# 从第一个父母获取前半部分基因
offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point]
# 从第二个父母获取后半部分基因
offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:]
# 返回生成的后代数组
return offspring
# 后代变异
def mutation(offspring, mutation_rate=0.1):
# 循环处理每个后代个体
for idx in range(offspring.shape[0]):
# 以一定概率进行变异
if random.random() < mutation_rate:
# 随机选择一个基因位置
gene_idx = np.random.randint(0, offspring.shape[1])
# 生成一个随机值
random_value = np.random.uniform(-5.0, 5.0)
# 将随机值添加到基因位置上,进行变异
offspring[idx, gene_idx] += random_value
# 返回变异后的后代数组
return offspring
def genetic_algorithm(pop_size, dim, num_generations, num_parents_mating):
# 初始化种群
population = initialize_population(pop_size, dim)
# 存储每代的最佳适应度值
best_outputs = []
# 循环迭代每一代
for generation in range(num_generations):
# 计算当前种群的适应度值
fitness = calculate_fitness(population)
# 存储当前代的最佳适应度值
best_outputs.append(np.min(fitness))
# 选择父母个体
parents = selection(population, fitness, num_parents_mating)
# 生成交叉后的后代
offspring_crossover = crossover(parents, (pop_size - parents.shape[0], dim))
# 对后代进行变异
offspring_mutation = mutation(offspring_crossover)
# 用父母个体替换种群中的前部分个体
population[0:parents.shape[0], :] = parents
# 用变异后的后代替换种群中的后部分个体
population[parents.shape[0]:, :] = offspring_mutation
# 输出当前代的最佳适应度值
if (generation+1) % 200 == 0:
print(f"Generation {generation+1}: Best Fitness = {np.min(fitness)}")
# 绘制每代的最佳适应度值
plt.plot(best_outputs)
# 设置x轴标签
plt.xlabel("Generation")
# 设置y轴标签
plt.ylabel("Best Fitness")
# 显示绘图结果
plt.show()
# 返回最佳个体
return population[np.argmin(fitness)]
# 运行遗传算法,设置种群大小为50,个体维度为10,迭代2000代,选择20个父母
best_solution = genetic_algorithm(pop_size=100, dim=10, num_generations=2000, num_parents_mating=20)
# 输出最佳解决方案
print("Best solution found:", best_solution)
# 输出最佳解决方案的适应度值
print("Best solution fitness:", objective_function(best_solution))