人工智能与机器学习原理精解【14】

遗传算法

什么是遗传算法

遗传算法(Genetic Algorithm, GA)是一种模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。遗传算法最早由美国的John Holland于20世纪70年代提出,其基本思想源于生物进化论中的“物竞天择,适者生存”的原理,以及遗传学中的基因遗传原理。

基本概念

  • 种群(Population):遗传算法从一个代表问题可能潜在解集的种群开始,种群由经过基因编码的一定数目的个体组成。
  • 个体(Individual):种群中的每一个元素称为个体,个体实际上是带有特征的染色体(Chromosome)的实体。
  • 染色体(Chromosome):作为遗传物质的主要载体,是多个基因的集合,其内部表现(即基因型)是某种基因组合,它决定了个体的外部表现(即表现型)。

主要特点

  1. 直接对结构对象进行操作:遗传算法不是对参数本身进行操作,而是对参数集进行了编码的个体进行操作,从而不存在求导和函数连续性的限定。
  2. 内在并行性:遗传算法本质上是一种并行算法,易于并行实现,可以显著提高算法的计算效率。
  3. 全局寻优能力强:遗传算法在搜索过程中不容易陷入局部最优解,而是能够跳出局部最优解,继续寻找全局最优解。
  4. 概率化寻优方法:遗传算法采用概率化的寻优方法,不需要确定的规则就能自动获取和指导优化的搜索空间,自适应地调整搜索方向。

基本操作

遗传算法主要包括选择(Selection)、交叉(Crossover)和变异(Mutation)三种基本操作。

  1. 选择:以一定的概率从种群中选择若干个个体,一般选择过程是一种基于适应度的优胜劣汰的过程。适应度高的个体被选中的概率高,适应度低的个体被淘汰。
  2. 交叉:又称基因重组或杂交,两个染色体的某一相同位置处DNA被切断,前后两串分别交叉组合形成两个新的染色体。交叉操作有助于维持种群的多样性,并将更好的特征融合在一起。
  3. 变异:复制时可能(很小的概率)产生某些复制差错,变异产生新的染色体,表现出新的性状。变异操作可以在进化中发挥重要作用,通过引入偶然性的变化,增加种群的多样性。

应用领域

遗传算法已被广泛应用于组合优化、机器学习、信号处理、自适应控制和人工生命等领域。在处理复杂问题和缺乏数学表达的问题时,遗传算法具有其他算法所不具备的优势。

综上所述,遗传算法是一种模拟自然进化过程的计算模型,通过选择、交叉和变异等操作搜索最优解。其直接对结构对象进行操作、具有内在并行性和全局寻优能力强等特点使得遗传算法在多个领域得到了广泛的应用。

遗传算法过程

遗传算法(Genetic Algorithm, GA)是一种模拟生物进化过程的优化算法,它通过模拟自然选择和遗传学机制来搜索问题的最优解或近似最优解。以下是对遗传算法的详细解释:

一、基本原理

遗传算法借鉴了达尔文的进化论和孟德尔的遗传学说,通过模拟自然界中生物的进化过程来解决问题。算法从代表问题可能潜在解集的一个种群开始,这个种群由经过基因编码的一定数目的个体组成。每个个体实际上是染色体带有特征的实体,染色体作为遗传物质的主要载体,其内部表现(即基因型)是某种基因组合,它决定了个体的外部表现(即表现型)。

二、主要特点

  1. 直接对结构对象进行操作:遗传算法不是对参数本身进行操作,而是对参数集进行了编码的个体进行操作,从而避免了求导和函数连续性的限定。
  2. 内在并行性:遗传算法在搜索过程中同时处理多个解,具有潜在的并行性,可以显著提高算法的计算效率。
  3. 全局寻优能力强:遗传算法在搜索过程中能够跳出局部最优解,继续寻找全局最优解,表现出良好的全局搜索能力。
  4. 概率化寻优方法:遗传算法采用概率化的寻优方法,通过适应度函数评价个体的优劣,并自适应地调整搜索方向,不需要确定的规则就能自动获取和指导优化的搜索空间。

三、基本操作

遗传算法的核心操作包括选择、交叉和变异。

  1. 选择(Selection):以一定的概率从种群中选择若干个个体作为父代,一般选择过程是基于适应度的优胜劣汰过程。适应度高的个体被选中的概率大,从而有机会将其优良基因遗传给下一代。
  2. 交叉(Crossover):又称基因重组或杂交,是遗传算法中产生新个体的主要手段。两个父代个体的染色体在某一位置进行交叉,交换部分基因,从而生成两个新的子代个体。交叉操作有助于维持种群的多样性,并将父代的优良特征融合在一起。
  3. 变异(Mutation):在复制过程中以很小的概率对个体的某些基因进行变异操作,即改变其基因值。变异操作是遗传算法中产生新个体的辅助手段,它可以在一定程度上避免算法早熟收敛,并增加种群的多样性。

四、算法流程

遗传算法的一般流程包括:

  1. 初始化:设置种群大小、最大迭代次数、搜索空间维度等参数,并随机生成初始种群。
  2. 解码与适应度计算:对种群中的个体进行解码操作,将其从基因型转换为表现型,并计算每个个体的适应度值。
  3. 选择操作:根据适应度值从种群中选择若干个个体作为父代。
  4. 交叉操作:对选中的父代个体进行交叉操作,生成新的子代个体。
  5. 变异操作:以一定的概率对子代个体的某些基因进行变异操作。
  6. 迭代进化:重复选择、交叉和变异操作,不断生成新的种群,直到满足结束条件(如达到最大迭代次数或找到满意的解)。
  7. 输出最优解:从末代种群中选择适应度最高的个体作为问题的最优解或近似最优解。

五、应用领域

遗传算法具有广泛的应用领域,包括但不限于:

  • 工程优化:如结构设计、电路设计、热交换器设计等,以找到最佳设计方案。
  • 机器学习:用于特征选择、模型参数优化、神经网络训练等,以提高模型的性能和预测能力。
  • 经济调度:在电力系统中解决经济调度问题,优化发电机组的负荷分配。
  • 调度问题:在生产和物流领域解决作业车间调度、车辆路径问题、人员排班等。
  • 自动化设计:在机器人路径规划、控制器设计等方面提高自动化系统的性能和可靠性。
  • 生物信息学:用于DNA序列分析、蛋白质结构预测、基因表达数据分析等。
  • 金融优化:在资产组合优化、风险管理、市场预测等方面提高投资回报和控制风险。

综上所述,遗传算法是一种模拟生物进化过程的优化算法,通过选择、交叉和变异等操作搜索问题的最优解或近似最优解。其直接对结构对象进行操作、具有内在并行性和全局寻优能力强等特点使得遗传算法在多个领域得到了广泛的应用。

遗传算法(Genetic Algorithm, GA)例子

可以通过一个具体的例子来详细描述。以下是一个使用遗传算法求解函数最大值问题的步骤示例:

问题定义

假设我们需要求解函数 f ( x ) = x 2 f(x) = x^2 f(x)=x2在区间 [ 0 , 31 ] [0, 31] [0,31]上的最大值,并且要求解的精度为整数解。这个问题虽然简单,但足以展示遗传算法的基本流程。

算法步骤

1. 初始化
  • 种群大小:设定种群中个体的数量为N,例如N=50。
  • 编码:采用二进制编码方式,根据精度要求和区间范围确定编码长度。在这个例子中,由于要求整数解且区间为 [ 0 , 31 ] [0, 31] [0,31],因此至少需要5位二进制数来表示( 2 4 = 16 < 32 < 2 5 = 32 2^4=16<32<2^5=32 24=16<32<25=32)。
  • 初始种群:随机生成N个5位二进制数的个体作为初始种群。
2. 适应度评估
  • 适应度函数:将目标函数 f ( x ) f(x) f(x)直接作为适应度函数,即个体的适应度值为其对应的 x 2 x^2 x2值。
  • 计算适应度:将每个个体的二进制编码解码为对应的整数x,然后计算 f ( x ) f(x) f(x)得到适应度值。
3. 选择
  • 选择方法:采用轮盘赌选择法。首先计算所有个体的适应度总和,然后为每个个体分配一个选择概率,选择概率与其适应度值成正比。
  • 执行选择:通过生成随机数的方式,根据个体的选择概率从当前种群中选择个体进入下一代种群。
4. 交叉
  • 交叉方法:采用单点交叉。随机选择种群中的个体进行配对,然后在每个配对的个体染色体上随机选择一个交叉点,交换交叉点之后的基因片段。
  • 执行交叉:以一定的交叉概率(如0.8)执行交叉操作,生成新的子代个体。
5. 变异
  • 变异方法:采用基本位变异。随机选择种群中的个体和个体染色体上的基因位,以一定的变异概率(如0.1)将选中的基因位取反(0变1,1变0)。
  • 执行变异:对种群中的个体执行变异操作,增加种群的多样性。
6. 迭代
  • 终止条件:设定最大迭代次数(如100次)或适应度阈值作为终止条件。
  • 重复执行:重复执行适应度评估、选择、交叉和变异步骤,直到满足终止条件。
7. 输出结果
  • 最优解:迭代结束后,从最终种群中选择适应度最高的个体作为最优解输出。

示例说明

假设经过多轮迭代后,最终种群中的一个个体为二进制编码[11111],解码后对应的整数为 x = 31 x=31 x=31,此时适应度函数值为 f ( 31 ) = 3 1 2 = 961 f(31)=31^2=961 f(31)=312=961,为当前种群中的最大值。因此,算法输出最优解为 x = 31 x=31 x=31,最大值为961。

这个过程展示了遗传算法如何通过模拟自然选择和遗传学原理来搜索问题的最优解。遗传算法具有全局搜索能力强、易于实现并行计算等优点,在解决复杂优化问题时表现出色。

julia实现

遗传算法(Genetic Algorithm, GA)是一种模拟生物进化过程的搜索算法,通常用于解决优化和搜索问题。以下是一个简单的遗传算法实现,使用Julia语言。这个例子将解决一个简单的优化问题:寻找一个二进制串,使得该串中1的数量最大化。

首先,你需要安装Julia环境。你可以从Julia的官方网站下载并安装。

接下来是遗传算法的Julia实现代码:

using Random

# 参数设置
population_size = 100
chromosome_length = 20
generations = 100
crossover_rate = 0.7
mutation_rate = 0.01

# 生成初始种群
function create_population(size, length)
    return [rand(0:1, length) for _ in 1:size]
end

# 计算适应度
function calculate_fitness(chromosome)
    return sum(chromosome)
end

# 选择过程
function selection(population, fitnesses)
    sorted_population = sort(collect(zip(population, fitnesses)), by=x->x[2], rev=true)
    return [p[1] for p in sorted_population]
end

# 交叉过程
function crossover(parent1, parent2)
    if rand() < crossover_rate
        point = rand(1:chromosome_length-1)
        return [parent1[1:point]; parent2[point+1:end]], [parent2[1:point]; parent1[point+1:end]]
    else
        return parent1, parent2
    end
end

# 变异过程
function mutation(chromosome)
    return [if rand() > mutation_rate bit else 1-bit end for bit in chromosome]
end

# 遗传算法主函数
function genetic_algorithm()
    population = create_population(population_size, chromosome_length)
    for generation in 1:generations
        fitnesses = calculate_fitness.(population)
        population = selection(population, fitnesses)
        children = []
        for i in 1:2:population_size
            parent1, parent2 = population[i], population[min(i+1, population_size)]
            child1, child2 = crossover(parent1, parent2)
            child1 = mutation(child1)
            child2 = mutation(child2)
            push!(children, child1)
            if length(children) < population_size
                push!(children, child2)
            end
        end
        population = children
    end
    fitnesses = calculate_fitness.(population)
    best_index = argmax(fitnesses)
    return population[best_index], fitnesses[best_index]
end

# 运行算法
best_chromosome, best_fitness = genetic_algorithm()
println("Best Chromosome: ", best_chromosome)
println("Best Fitness: ", best_fitness)

这段代码首先定义了一些基本的遗传算法函数,包括创建种群、计算适应度、选择、交叉和变异。然后在genetic_algorithm函数中组合这些步骤,并运行指定的代数。最后输出最优的染色体和它的适应度。

遗传算法解决线性规划对偶问题

线性规划对偶问题

对偶问题构造涉及到原问题的约束条件和目标函数的系数。

对于一个标准的线性规划问题:
maximize  c T x \text{maximize } c^T x maximize cTx subject to  A x ≤ b ,   x ≥ 0 \text{subject to } Ax \leq b, \, x \geq 0 subject to Axb,x0

其对偶问题为: minimize  b T y \text{minimize } b^T y minimize bTy subject to  A T y ≥ c ,   y ≥ 0 \text{subject to } A^T y \geq c, \, y \geq 0 subject to ATyc,y0

具体见凸分析与凸优化精解【2】

julia实现

  • 以直接计算其对偶问题为例
    m i n : 35 y 1 + 71 y 2 − 16 y 3 s u b j e c t t o : 22 y 1 + 7 y 2 + 6 y 3 ≥ 37 , 9 y 1 + 11 y 2 + 3 y 3 ≥ 21 , 2 y 1 + 7 y 2 + 5 y 3 ≥ 13 y 1 , y 2 , y 3 ≥ 0 min:35y_1+71y_2-16y_3 \\subject\quad to: \\22y_1+7y_2+6y_3\ge 37, \\9y_1+11y_2+3y_3\ge 21, \\2y_1+7y_2+5y_3\ge13 \\y_1,y_2,y_3 \ge 0 min:35y1+71y216y3subjectto:22y1+7y2+6y337,9y1+11y2+3y321,2y1+7y2+5y313y1,y2,y30
    b = [ 35 , 71 , − 16 ] A = [ 22 7 6 9 11 3 2 7 5 ] c = [ 37 , 21 , 13 ] b=[35,71,-16] \\A=\begin{bmatrix} 22 & 7 & 6\\ 9 & 11 & 3\\ 2 & 7 & 5 \end{bmatrix} \\c=[37,21,13] b=[35,71,16]A= 22927117635 c=[37,21,13]
using Random
#coding:https://blog.csdn.net/sakura_sea

function initParam()
    b=[35,71,-16]
    A=[[22 7 6];[9 11 3];[2 7 5]]
    c=[37,21,13]
    x_0=[rand(1:100),rand(1:100),rand(1:100)]
    T_0=10000000.0
    a=0.98
    step=2
    T_end=100
    population_size = 200
    chromosome_length = 8
    independent_variable_counts=3
    generations = 500
    crossover_rate = 0.7
    mutation_rate = 0.01
    return (b,c,A,x_0,T_0,a,step,T_end,population_size,chromosome_length,independent_variable_counts,generations,crossover_rate,mutation_rate)
end
function getObjectiveFun(y::Vector{Int64},b::Vector{Int64})
    return b'*y
end
function gt_ab(a,b)
    return all((a-b).>=0)
end
function binaryArrayToInt(binary_array)
    binary_str = join(string.(binary_array), "") 
    decimal_num = parse(Int, binary_str, base=2)  
    return decimal_num
end
# 生成初始种群
function create_population(size, length,independent_variable_counts)::Vector{Matrix{Int64}}
    population_data=[rand(0:1, (independent_variable_counts,length)) for _ in 1:size]
    while true  
        if all(is_valid.( population_data))
            break
        else
            print("+")
        end
        population_data=[rand(0:1, (independent_variable_counts,length)) for _ in 1:size]
    end
    return  population_data
end

# 计算适应度
function calculate_fitness(population::Matrix{Int64}) 
    y=[binaryArrayToInt(binary_arr_y) for binary_arr_y in eachrow(population)]
    fitness=typemax(Int64)-getObjectiveFun(y,b)       
end

function is_valid(population::Matrix{Int64})
    y=[binaryArrayToInt(binary_arr_y) for binary_arr_y in eachrow(population)]
    if all(y.>0) && gt_ab(A'*y,c)
        return true
    else
        return false
    end   
end

# 选择过程
function selection(population, fitnesses)
    sorted_population = sort(collect(zip(population, fitnesses)), by=x->x[2], rev=true)
    return [p[1] for p in sorted_population ]
end

# 交叉过程
function crossover(parent1, parent2)
    new_parent1= zeros(Int64,size(parent1))
    new_parent2= zeros(Int64,size(parent2))   
    j=0
    while true   
        new_parent1= zeros(Int64,size(parent1))
        new_parent2= zeros(Int64,size(parent2))  
        if rand() < crossover_rate
            for i in 1:size(parent1,1)      
                point = rand(1:chromosome_length-1)
                new_parent1[i,:],new_parent2[i,:]=[parent1[i,1:point]; parent2[i,point+1:end]], [parent2[i,1:point]; parent1[i,point+1:end]]
            end
        else
            new_parent1,new_parent2=parent1, parent2
        end
        if is_valid(new_parent1) && is_valid(new_parent2) 
            break
        else
            print("*")
        end
        j+=1
        if j>200
            sleep(1)
            rng = MersenneTwister()
            j=0
        end    
    end
    return new_parent1,new_parent2
end

# 变异过程
function mutation(chromosome)
    new_chromosome=zeros(Int64,size(chromosome))
    j=0
    while true
        new_chromosome=zeros(Int64,size(chromosome))
        for i in 1:size(new_chromosome,1)
            new_chromosome[i,:]=[if rand() > mutation_rate bit else 1-bit end for bit in chromosome[i,:]]
        end   
        if is_valid(new_chromosome)
            break
        else
            print(".")
        end
        j+=1
        if j>200
            sleep(1)
            rng = MersenneTwister()
            j=0
        end     
    end
    return new_chromosome
end



# 遗传算法主函数
function genetic_algorithm()
    population::Vector{Matrix{Int64}}= create_population(population_size, chromosome_length,independent_variable_counts)
    for generation in 1:generations
        fitnesses = calculate_fitness.(population)
        population = selection(population, fitnesses)       
        children = []
        for i in 1:2:population_size
            parent1, parent2 = population[i], population[min(i+1, population_size)]
            child1, child2 = crossover(parent1, parent2)
            child1 = mutation(child1)
            child2 = mutation(child2)                                    
            push!(children, child1)
            if length(children) < population_size
                push!(children, child2)
            end
        end
        population = children
        print("==>")
    end
    fitnesses = calculate_fitness.(population)
    best_index = argmax(fitnesses)
    return population[best_index], fitnesses[best_index]
end

# 运行算法
# 参数设置
b,c,A,x_0,T_0,a,step,T_end,population_size,chromosome_length,independent_variable_counts,generations,crossover_rate,mutation_rate=initParam()
best_chromosome, best_fitness = genetic_algorithm()
best_y=[binaryArrayToInt(binary_arr_y) for binary_arr_y in eachrow(best_chromosome)]
println("Best Chromosome: ", best_y)
println("Best Fitness: ", typemax(Int64)-best_fitness)
++++++++++++++++++++++++++++***==>*==>==>.*==>==>*==>==>*==>**==>***==>****==>*==>***==>.******==>*******==>*****==>******==>.*****==>*.**==>***==>**==>**==>****.**.==>*==>***==>.==>***==>***==>==>*.==>==>*==>==>.*==>**==>**==>****==>***==>***==>***==>*****==>***==>*==>**==>*.==>*.*==>==>****==>*==>*.**==>**==>*..==>.**==>******.*==>**==>==>***==>.==>**==>**==>*==>*==>==>*==>***==>==>*==>*==>***.==>==>*==>***==>**********==>==>***==>***==>*==>***==>*==>.==>***==>**.==>*.==>**.*==>**==>==>***==>****==>==>.==>*..**.==>****.*==>*==>****==>****==>.==>==>*..==>****==>***==>==>******==>==>**.*==>***.**==>*==>==>==>*==>.*==>.****==>***==>**==>*==>*******==>**==>****==>***==>**.==>.==>******==>*==>*****==>**==>***==>*==>*****==>****==>***==>**==>*****==>*==>****==>****==>.==>*****==>************==>****==>*******==>*==>***==>*.*******==>**==>****==>*==>*.==>*.==>.*==>*********==>*****==>**==>*.==>********==>*==>*==>*==>*==>.==>***==>**.==>*****==>**==>**==>****==>***==>==>**==>*****==>.*==>*.==>***==>.==>.*.*.==>*******==>**==>*****==>*****==>**==>***==>.*==>**==>==>**.*==>*****==>**==>****==>==>.*==>==>==>**==>*==>==>***.==>==>*****==>**==>**==>**==>==>***==>.**==>*****==>*********==>.***==>*==>***==>*==>.**==>*==>**==>.*==>==>*==>*==>**==>*******==>==>****==>****==>*****==>****==>*****==>*.==>***==>*.***==>*==>***==>**==>*****==>*==>****.**==>***==>********==>***==>****==>**==>***==>==>**.*==>***==>*==>.==>*==>*==>==>*****==>==>**==>***==>***.==>*.==>**==>.==>==>**==>*==>.****==>*==>**==>*==>.==>..==>*==>****==>*==>==>*****==>*==>==>*.***..==>*******==>*****==>*********==>==>********.*==>*****==>**==>*****.==>*****==>==>****==>**==>****==>***==>*==>***.**==>******==>**.==>******==>.==>*==>*==>****.***==>***.==>******==>*****==>***==>******==>*******==>.*==>**==>********==>**==>*==>*.**==>*****==>..==>**==>****==>.**==>*..==>**==>*==>.**==>*==>*****==>==>.**==>*==>*==>**==>..****==>.==>*==>*==>*.*==>**==>*==>**.==>.*==>*.==>****==>*==>***==>***==>*****==>==>*.==>.**==>********==>*==>==>*******==>**==>****.==>==>***==>******==>==>****==>*==>***.==>**==>**.==>==>==>**==>*==>==>==>==>*****==>*==>***.==>*==>*==>.*.==>*.==>***==>*==>***==>*==>.==>*****==>***==>*==>*==>*****==>**==>*==>********==>***==>**==>**==>***==>**==>******==>****==>*..***==>***.==>***==>**==>*==>***==>*==>*****==>*==>****==>****==>*.*==>*.*****==>==>*******==>****==>***==>.**==>.*==>**==>*==>***==>==>*****==>********==>==>****==>==>************==>*==>****==>******.**==>*****==>***==>**.******==>*****==>***==>**.==>*******==>*****==>**==>*******==>.==>*==>********==>==>*==>**.==>**==>********==>****==>****==>**==>***==>****==>*==>==>*******==>==>..==>==>*.*==>*==>*****==>.==>.*==>..==>*==>****==>==>***==>***==>==>*==>*==>*==>==>******==>*.==>*********==>.==>.*.==>==>**==>******==>**.*==>***==>==>*==>*****==>**==>*****==>**==>***==>**==>*==>*****==>==>*==>***==>*==>.******==>*==>.==>**==>***==>**==>.==>***==>***==>****==>
Best Chromosome: [79, 14, 234]
Best Fitness: 15

参考文献

1.文心一言
2.chatgpt

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值