【人工智能】遗传算法(二)

简介: 【人工智能】遗传算法

2.2.1归一化


使用种群中最小适应度值的个体作为归一化的最小值。这被称为“最小-最大规范化”(Min-Max Normalization)或“线性比例缩放”(Linear Proportional Scaling)。具体地,对于一个种群,可以通过以下步骤进行归一化:


image.png

:其中f(x)是个体的原始适应度值。

:这样得到的归一化适应度值f’(x)会被限制在[0, 1]之间,并且种群中适应度值最小的个体的归一化适应度值将为0


问题:在使用最小-最大规范化对适应度进行归一化时,如果存在某个个体的适应度值为0,则它的归一化适应度值也将为0。这可能会导致一些问题,因为在选择过程中,只有归一化适应度值比较大的个体才会被选中,而归一化适应度值为0的个体则无法被选中。

解决方法:有一种解决方案是添加一个非零的偏移量例如,在计算f’(x)时,我们可以使用以下公式:

image.png

其中epsilon是一个足够小的正数,用来避免出现分母为0的情况。通过添加epsilon,所有的适应度值都可以被成功归一化,而且可以继续使用遗传算法等选择方法。


需要注意的是,选择过程不仅依赖于适应度值的大小,还涉及到其他因素,如选择操作的参数、选择算子的类型等。因此,在使用归一化适应度值进行选择时,需要谨慎地选择合适的方法,并进行实验测试和验证。


上面代码略
上面的代码在文章上面
def roulette_wheel_selection(population, fitness_values):
    # 计算总适应度
    total_fitness = sum(fitness_values)
    # 计算适应度最大值的偏移量
    offset = abs(min(fitness_values))
    # 计算相对适应度
    relative_fitness = [(f + offset) / total_fitness for f in fitness_values]
    # 计算累积概率
    probabilities = [sum(relative_fitness[:i + 1]) for i in range(len(relative_fitness))]
    # 选择个体
    selected = []
    for i in range(len(population)):
        r = random.random()
        for j, p in enumerate(probabilities):
            if r <= p:
                selected.append(population[j])
                break
    return selected
def normalize_fitness(fitness_list, population):
    # Calculate the minimum and maximum fitness values
    min_f = min(fitness_list)
    max_f = max(fitness_list)
    # Add a small constant to avoid division by zero
    epsilon = 1e-8
    # Normalize the fitness values for each individual in the population
    normalized_fitness = []
    for i in range(len(population)):
        fitness = fitness_list[i]
        norm_fitness = (fitness - min_f + epsilon) / (max_f - min_f + epsilon)
        normalized_fitness.append(norm_fitness)
    return normalized_fitness
# 归一化适应度
fitness_values_nor = normalize_fitness(fitness_values,population_2)
print("归一化的适应度值",fitness_values_nor)
# 轮盘赌选择父代
select = roulette_wheel_selection(population_2, fitness_values_nor)
print(select)

输出:

e2a6831f0522b3d7f2554d13c7a6437b_1ef7777badfd4c6a95e390b93c7c3102.png

重要知识点:在轮盘赌选择算法中,每个个体在被选中的概率与其适应度成正比。因此,如果得到的个体重复出现,那么它们必须被视为不同的个体,并分别参与下一代的繁殖。

一般来讲,我们选择种群的个数和初始种群个数保持一致


3.交叉操作


交叉操作是遗传算法中的一种重要操作,用于产生新的个体。其原理是通过对两个或多个个体的某些基因位点进行交换,从而产生具有不同基因组合的新个体。


3.1单点交叉


20191202151959116.gif

图片来自: 博客:遗传算法中的一些交叉算子



单点交叉是其中一种常见的交叉方式,它是指在随机选择的一个交叉点处将两个个体的染色体分为两段,然后将这两段互换,产生两个新个体。

由上面选择操作,选择到了种群一些优秀个体作为父代基因,将这些优秀个体随机两两交叉。

这样做的好处是:


在使用已经选择出来的父代个体进行交叉操作时,通常是随机选取两个不同的父代进行交叉操作。这样可以增加交叉的随机性,从而更好地避免陷入局部最优解。


如果您采用逐一对每一对父代进行交叉操作,则可能会导致某些父代个体之间没有交叉,或者某些个体交叉的次数过多,从而影响算法效果。因此,随机选择两个不同的父代进行交叉是比较合适的做法。


代码:

# 单点交叉
def single_point_crossover(parents):
    # 随机选择两个不同的父代基因进行交叉,并产生相应数量的子代基因
    children = []
    for i in range(int(len(parents) / 2)):
        parent1, parent2 = random.sample(parents, 2)
        crossover_point = random.randint(1, len(parent1) - 1)
        parent1_left, parent1_right = parent1[:crossover_point], parent1[crossover_point:]
        parent2_left, parent2_right = parent2[:crossover_point], parent2[crossover_point:]
        child1 = parent1_left + parent2_right
        child2 = parent2_left + parent1_right
        children.append(child1)
        children.append(child2)
    # 返回交叉后的子代基因
    return children
 # 轮盘赌选择父代
children = single_point_crossover(select)
print(children)


输出:

fede12206f15be2505e4cb85d4c60737_b1d807a19a264bec9af9844283ad73e5.png


3.2 多点交叉


看图就能理解吧,就不解读了=========

3.gif

4.gif


3.3部分交叉


看这篇博客吧:遗传算法一些交叉算子


4.变异操作


变异操作是遗传算法中的一种重要操作,它可以引入新的基因组合,帮助种群避免局部最优解并提高全局搜索能力。在遗传算法中,变异操作通常通过以下三个步骤来实现:


  1. 随机选择一个个体:从当前种群中随机选择一个个体作为变异对象。
  2. 选择一个基因位点:从该个体的染色体序列中随机选择一个基因位点(即染色体上的一个基因)。
  3. 改变基因值:根据预定义的概率将该基因值进行改变。这个概率通常很小,通常设置为0.1或更小,以确保变异不会太频繁影响种群稳定性。


变异操作的实现方式有很多种,具体取决于问题的特性和目标函数的形式。例如,在二进制编码的问题中,变异操作可以通过随机翻转某些基因位来实现;在实数编码的问题中,变异操作可以通过对染色体上的某些基因进行随机加减来实现。


需要注意的是,变异操作应该谨慎使用,以防止过度变异导致种群的多样性降低。同时,由于变异操作通常会增加种群的多样性,因此应该控制变异概率,以确保种群能够平衡地进行探索和利用。

# 变异操作
def mutation(population, mutation_rate):
    mutated_population = []
    for individual in population:
        if random.random() < mutation_rate:
            mutated_individual = list(individual)
            gene_index = random.randint(0, len(mutated_individual) - 1)
            mutated_individual[gene_index] ^= 1
            mutated_population.append(mutated_individual)
        else:
            mutated_population.append(individual)
    return mutated_population
mutated_children = mutation(children,0.01)
print("变异后的子代种群", mutated_children)


输出:

438758bd0e1e8c1d770db1f28fe89645_88e45edc1f914ee0a61e759d93d37c73.png


5.评估操作


这一步很简单,就是将子代的适应度求一下。

看到这了,其实你已经掌握了90%的遗传算法了,

我们将上面的操作进行一下可视化,看一下我们第一次迭代得到的效果:

这里,我把之前的代码中的种群个数修改为20个,提高可视化的可读性


# Generate data for the fitness function curve
x_fit = np.linspace(-5, 5, 100)
y_fit = [fitness(x) for x in x_fit]
# Plot the fitness function curve
plt.plot(x_fit, y_fit, label='Fitness Function')
# Plot the population and offspring
for i, population in enumerate([population_2, mutated_children]):
    x = binary_to_x(population, -5, 5, n)
    x = [round(num, 1) for num in x]
    fitness_values = [fitness(x) for x in x]
    if i == 0:
        label = 'Population'
        color = 'blue'
    else:
        label = 'Offspring'
        color = 'red'
    plt.scatter(x, fitness_values, c=color, label=label)
plt.legend()
plt.xlabel('x')
plt.ylabel('Fitness')
plt.show()

输出:

69eff1eb6a1d13832dffe571bb2ca20e_79ade81febc04011afc3a921c691cfbc.png

看到了把,子代函数值要大于父代,接近成功了,接下来,我们仅仅需要将上述操作迭代下去,就能逼近那个函数的最大值。


6.终止操作


进行完上述步骤之后,需要检查是否满足终止条件,如达到最大迭代次数或目标函数值足够小等。如果不满足,则继续执行上述步骤,直到满足终止条件为止。


根据终止条件的不同,大致可以分为以下几种终止条件设置方法:


  • 迭代次数:可以设置算法运行的最大迭代次数,超过迭代次数则停止运行。
  • 精度要求:可以设置算法达到一定的精度要求后,停止运行。例如,对于优化问题,当目标函数值变化很小或者收敛到一个特定值时,算法就可以停止。
  • 计算时间:可以设置算法运行的最大时间,当超过这个时间限制时,算法就停止。
  • 变异率:可以根据变异率来判断算法何时停止。如果变异率已经非常小,那么算法就可以停止。
  • 种群适应性:可以设置种群适应性的阈值,当种群适应性达到一定水平时,算法就停止。


需要注意的是,终止条件的设置应该合理,否则可能会导致算法早停或持续运行而无法得到最优解。因此,在实际应用中,需要根据具体情况进行细致的分析和设置。


删除线:基础篇就不写了,有时间的话,放到进阶篇讲


6.1 设置迭代次数


很好理解,就是设置迭代次数,次数到了,自然就结束了。

代码:

# 二进制编码 n位二进制的选择
n = calculate_n(1, -5, 5)
print("n:", n)
# 初始化种群
population_2 = initialize_population(20, n)
print("初始化种群", population_2)
# 方便操作
population = population_2
def xunhuan(population_2, mutation_rate, a, b, n):
    x = binary_to_x(population_2, a, b, n)
    x = [round(num, 1) for num in x]
    fitness_values = [fitness(x) for x in x]
    fitness_values_nor = normalize_fitness(fitness_values, population_2)
    select = roulette_wheel_selection(population_2, fitness_values_nor)
    children = single_point_crossover(select)
    mutated_children = mutation(children, 0.01)
    return mutated_children
stop_flag = False
max_iterations = 1000
iteration_count = 0
while not stop_flag:
    population = xunhuan(population, 0.01, -5, 5, n)
    iteration_count += 1
    if iteration_count >= max_iterations:
        stop_flag = True
mutated_children = population
# Generate data for the fitness function curve
x_fit = np.linspace(-5, 5, 100)
y_fit = [fitness(x) for x in x_fit]
# Plot the fitness function curve
plt.plot(x_fit, y_fit, label='Fitness Function')
# Plot the population and offspring
for i, population in enumerate([population_2, mutated_children]):
    x = binary_to_x(population, -5, 5, n)
    x = [round(num, 1) for num in x]
    fitness_values = [fitness(x) for x in x]
    if i == 0:
        label = 'Population'
        color = 'blue'
    else:
        label = 'Offspring'
        color = 'red'
    plt.scatter(x, fitness_values, c=color, label=label)
plt.legend()
plt.xlabel('x')
plt.ylabel('Fitness')
plt.show()

输出:

605399ff4d3ecbf390140bec82c37081_7f4c660cbe024d7bb1e20a080cb14c99.png

91b14655ce0767d9c165930c6ff90202_1612ca981ce647fc9a3d5cad44446bfc.png

最后看到子代的基因几乎都为一种,恒定。这个就是我们找到的最大解。


剩余两种,可以网上查阅,这里我就不介绍了,不然文章过长,又又没人看了,能看到这里的人应该也会了这个算法。


相关文章
|
12天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
43 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
12天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
44 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
12天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
52 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
1月前
|
人工智能 自然语言处理 算法
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07(下)
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07(下)
22 2
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07(下)
|
1月前
|
机器学习/深度学习 人工智能 算法
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05(下)
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05(下)
28 1
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-05(下)
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-19
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-19
52 3
|
1月前
|
存储 人工智能 算法
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-13(上)
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-13(上)
37 2
|
1月前
|
传感器 自然语言处理 安全
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07(上)
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07(上)
41 2
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-16
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-16
33 1
|
1月前
|
机器学习/深度学习 人工智能 算法
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-15
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-15
48 1
下一篇
无影云桌面