数模 05遗传算法(Genetic Algorithm GA)

一种仿真优化算法

遗传算法(Genetic Algorithm, GA)起源于对生物系统所进行的计算机模拟研究。它是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法,借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种高效、并行、全局搜索的方法,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最佳解。

核心思想:物竞天择,适者生存(适应度函数 Fitness Function)

标准遗传算法的基本流程:

数模 05遗传算法(Genetic Algorithm GA)_第1张图片

       遗传算法中每一条染色体,对应着遗传算法的一个解决方案,一般我们用适应性函数(fitness function)来衡量这个解决方案的优劣。所以从一个基因组到其解的适应度形成一个映射。可以把遗传算法的过程看作是一个在多元函数里面求最优解的过程。可以这样想象,这个多维曲面里面有数不清的“山峰”,而这些山峰所对应的就是局部最优解。而其中也会有一个“山峰”的海拔最高的,那么这个就是全局最优解。而遗传算法的任务就是尽量爬到最高峰,而不是陷落在一些小山峰。(另外,值得注意的是遗传算法不一定要找“最高的山峰”,如果问题的适应度评价越小越好的话,那么全局最优解就是函数的最小值,对应的,遗传算法所要找的就是“最深的谷底”)

在这里的概念可以类比梯度下降算法。

下面有一个很好的例子去分辨梯度上升算法(爬山法)、模拟退火算法与遗传算法

“袋鼠跳”问题

        既然我们把函数曲线理解成一个一个山峰和山谷组成的山脉。那么我们可以设想所得到的每一个解就是一只袋鼠,我们希望它们不断的向着更高处跳去,直到跳到最高的山峰(尽管袋鼠本身不见得愿意那么做)。所以求最大值的过程就转化成一个“袋鼠跳”的过程。

 1. 爬山法(最速上升爬山法):

      从搜索空间中随机产生邻近的点,从中选择对应解最优的个体,替换原来的个体,不断重复上述过程。因为爬山法只对“邻近”的点作比较,所以目光比较“短浅”,常常只能收敛到离开初始位置比较近的局部最优解上面。对于存在很多局部最优点的问题,通过一个简单的迭代找出全局最优解的机会非常渺茫。(在爬山法中,袋鼠最有希望到达最靠近它出发点的山顶,但不能保证该山顶是珠穆朗玛峰,或者是一个非常高的山峰。因为一路上它只顾上坡,没有下坡。)

2. 模拟退火:

     这个方法来自金属热加工过程的启发。在金属热加工过程中,当金属的温度超过它的熔点(Melting Point)时,原子就会激烈地随机运动。与所有的其它的物理系统相类似,原子的这种运动趋向于寻找其能量的极小状态。在这个能量的变迁过程中,开始时,温度非常高, 使得原子具有很高的能量。随着温度不断降低,金属逐渐冷却,金属中的原子的能量就越来越小,最后达到所有可能的最低点。利用模拟退火的时候,让算法从较大的跳跃开始,使到它有足够的“能量”逃离可能“路过”的局部最优解而不至于限制在其中,当它停在全局最优解附近的时候,逐渐的减小跳跃量,以便使其“落脚 ”到全局最优解上。(在模拟退火中,袋鼠喝醉了,而且随机地大跳跃了很长时间。运气好的话,它从一个山峰跳过山谷,到了另外一个更高的山峰上。但最后,它渐渐清醒了并朝着它所在的峰顶跳去。)

3. 遗传算法:

    模拟物竞天择的生物进化过程,通过维护一个潜在解的群体执行了多方向的搜索,并支持这些方向上的信息构成和交换。是以面为单位的搜索,比以点为单位的搜索,更能发现全局最优解。(在遗传算法中,有很多袋鼠,它们降落到喜玛拉雅山脉的任意地方。这些袋鼠并不知道它们的任务是寻找珠穆朗玛峰。但每过几年,就在一些海拔高度较低的地方射杀一些袋鼠,并希望存活下来的袋鼠是多产的,在它们所处的地方生儿育女)(或者换个说法。从前,有一大群袋鼠,它们被莫名其妙的零散地遗弃于喜马拉雅山脉。于是只好在那里艰苦的生活。海拔低的地方弥漫着一种无色无味的毒气,海拔越高毒气越稀薄。可是可怜的袋鼠们对此全然不觉,还是习惯于活蹦乱跳。于是,不断有袋鼠死于海拔较低的地方,而越是在海拔高的袋鼠越是能活得更久,也越有机会生儿育女。就这样经过许多年,这些袋鼠们竟然都不自觉地聚拢到了一个个的山峰上,可是在所有的袋鼠中,只有聚拢到珠穆朗玛峰的袋鼠被带回了美丽的澳洲。)

遗传算法的实现过程

        遗传算法的实现过程实际上就像自然界的进化过程那样。首先寻找一种对问题潜在解进行“数字化”编码的方案。(建立表现型和基因型的映射关系)然后用随机数初始化一个种群(那么第一批袋鼠就被随意地分散在山脉上),种群里面的个体就是这些数字化的编码。接下来,通过适当的解码过程之后(得到袋鼠的位置坐标),用适应性函数对每一个基因个体作一次适应度评估(袋鼠爬得越高,越是受我们的喜爱,所以适应度相应越高)。用选择函数按照某种规定择优选择(我们要每隔一段时间,在山上射杀一些所在海拔较低的袋鼠,以保证袋鼠总体数目持平。)。让个体基因变异(让袋鼠随机地跳一跳)。然后产生子代(希望存活下来的袋鼠是多产的,并在那里生儿育女)。遗传算法并不保证你能获得问题的最优解,但是使用遗传算法的最大优点在于你不必去了解和操心如何去“找”最优解。(你不必去指导袋鼠向那边跳,跳多远。)而只要简单的“否定”一些表现不好的个体就行了。(把那些总是爱走下坡路的袋鼠射杀,这就是遗传算法的精粹!)

具体关于袋鼠跳的问题参考博客:https://blog.csdn.net/qq_31805821/article/details/79763326

遗传算法并不保证你能获得问题的最优解,但是使用遗传算法的最大优点在于你不必去了解和操心如何去“找”最优解。(你不必去指导袋鼠向那边跳,跳多远。)而只要简单的“否定”一些表现不好的个体就行了。(把那些总是爱走下坡路的袋鼠射杀,这就是遗传算法的精粹!)

 

数模 05遗传算法(Genetic Algorithm GA)_第2张图片

下面,才是重点,实战 开始! 

利用遗传算法求解区间[0,31]上的二次函数y=x2的最大值,精度要求达到个位

原问题可转化为在区间[0, 31]中搜索能使y取最大值的点a的问题。那么,[0, 31] 中的点x就是个体, 函数值f(x)恰好就可以作为x的适应度,区间[0, 31]就是一个()空间 。这样, 只要能给出个体x的适当染色体编码, 该问题就可以用遗传算法来解决 

步骤如下:

(1) 设定种群规模,编码染色体,产生初始种群。

    将种群规模设定为4;用5位二进制数编码染色体;取下列个体组成初始种群S1:

                     s1= 13 (01101),  s2= 24 (11000)

                     s3= 8 (01000),    s4= 19 (10011)

 (2) 定义适应度函数,

               取适应度函数:f (x)=x2          

(3) 计算各代种群中的各个体的适应度, 并对其染色体进行遗传操作,直到适应度最高的个体(3111111)出现为止。

首先计算种群S1中各个体

              s1= 13(01101),    s2= 24(11000)                     

                   s3= 8(01000),      s4= 19(10011)

的适应度f (si)

容易求得:      f (s1) = f(13) = 132 = 169

                       f (s2) = f(24) = 242 = 576

                       f (s3) = f(8) = 82 = 64

                       f (s4) = f(19) = 192 = 361

再计算种群S1中各个体的选择概率。

选择概率的计算公式为

数模 05遗传算法(Genetic Algorithm GA)_第3张图片

由此可求得

                      P(s1) = P(13) = 0.14

                       P(s2) = P(24) = 0.49

                       P(s3) = P(8) = 0.06

                       P(s4) = P(19) = 0.31

数模 05遗传算法(Genetic Algorithm GA)_第4张图片

数模 05遗传算法(Genetic Algorithm GA)_第5张图片

交叉

    设交叉率pc=100%,即S1中的全体染色体都参加交叉运算。

    设s1s2配对,s3s4配对。分别交换后两位基因,得新染色体:

   s1’’=1100125s2’’=0110012

   s3’’=1101127s4’’=1000016

 

变异

        设变异率pm=0.001。这样,群体S1中共有

                               5×4×0.001=0.02

位基因可以变异。0.02位显然不足1位,所以本轮遗传操作不做变异。

       于是,得到第二代种群S2

     s1=1100125, s2=0110012

     s3=1101127, s4=1000016

数模 05遗传算法(Genetic Algorithm GA)_第6张图片

数模 05遗传算法(Genetic Algorithm GA)_第7张图片

设这一轮的选择-复制结果为:

                    s1=1110028s2=1110028

                    s3=1100024s4=1001119

    做交叉运算,让s1s4s2s3 分别交换后两位基因,得

 

   s1’’=1111131, s2’’=1110028

   s3’’=1100024, s4’’=1000016

这一轮仍然不会发生变异。

于是,得第四代种群S4

          s1=1111131s2=1110028

         s3=1100024s4=1000016

显然,在这一代种群中已经出现了适应度最高的染色体s1=11111。于是,遗传操作终止,将染色体11111作为最终结果输出。

  然后,将染色体11111”解码为表现型,即得所求的最优解:31

    将31代入函数y=x2中,即得原问题的解,即函数y=x2的最大值为961

数模 05遗传算法(Genetic Algorithm GA)_第8张图片

 我不打算继续下去了,自我感觉遗传算法像有病一样。我去!

利用小批量随机梯度下降不是更好???

小批量梯度下降法(Mini-batch梯度下降算法)

 Mini-batch梯度下降综合了batch梯度下降与stochastic梯度下降,在每次更新速度与更新次数中间取得一个平衡,其每次更新从训练集中随机选择b,b

数模 05遗传算法(Genetic Algorithm GA)_第9张图片

代码实现(前一种为批量梯度下降,后一种为小批量梯度下降)

#!/usr/bin/python

#coding=utf-8

import numpy as np

from scipy import stats

import matplotlib.pyplot as plt

 

# 构造训练数据

x = np.arange(0., 10., 0.2)

m = len(x)  # 训练数据点数目

print m

x0 = np.full(m, 1.0)

input_data = np.vstack([x0, x]).T  # 将偏置b作为权向量的第一个分量

target_data = 2 * x + 5 + np.random.randn(m)

 

# 两种终止条件

loop_max = 10000  # 最大迭代次数(防止死循环)

epsilon = 1e-3

 

# 初始化权值

np.random.seed(0)

theta = np.random.randn(2)

 

alpha = 0.001  # 步长(注意取值过大会导致振荡即不收敛,过小收敛速度变慢)

diff = 0.

error = np.zeros(2)

count = 0  # 循环次数

finish = 0  # 终止标志

 

while count < loop_max:

    count += 1

 

    # 标准梯度下降是在权值更新前对所有样例汇总误差,而随机梯度下降的权值是通过考查某个训练样例来更新的

    # 在标准梯度下降中,权值更新的每一步对多个样例求和,需要更多的计算

    sum_m = np.zeros(2)

    for i in range(m):

        dif = (np.dot(theta, input_data[i]) - target_data[i]) * input_data[i]

        sum_m = sum_m + dif  # 当alpha取值过大时,sum_m会在迭代过程中会溢出

 

    theta = theta - alpha * sum_m  # 注意步长alpha的取值,过大会导致振荡

    # theta = theta - 0.005 * sum_m      # alpha取0.005时产生振荡,需要将alpha调小

 

    # 判断是否已收敛

    if np.linalg.norm(theta - error) < epsilon:

        finish = 1

        break

    else:

        error = theta

    print 'loop count = %d' % count, '\tw:',theta

print 'loop count = %d' % count, '\tw:',theta

 

# check with scipy linear regression

slope, intercept, r_value, p_value, slope_std_error = stats.linregress(x, target_data)

print 'intercept = %s slope = %s' % (intercept, slope)

 

plt.plot(x, target_data, 'g*')

plt.plot(x, theta[1] * x + theta[0], 'r')

plt.show()

批量梯度下降算法

 

#!/usr/bin/python

#coding=utf-8

import numpy as np

from scipy importstats

import matplotlib.pyplot as plt

 

# 构造训练数据

x = np.arange(0.,10.,0.2)

m = len(x)  # 训练数据点数目

print m

x0 = np.full(m, 1.0)

input_data = np.vstack([x0, x]).T  # 将偏置b作为权向量的第一个分量

target_data = 2 *x + 5 +np.random.randn(m)

 

# 两种终止条件

loop_max = 10000  #最大迭代次数(防止死循环)

epsilon = 1e-3

 

# 初始化权值

np.random.seed(0)

theta = np.random.randn(2)

 

alpha = 0.001  #步长(注意取值过大会导致振荡即不收敛,过小收敛速度变慢)

diff = 0.

error = np.zeros(2)

count = 0  #循环次数

finish = 0  #终止标志

minibatch_size = 5  #每次更新的样本数

while count < loop_max:

    count += 1

 

    # minibatch梯度下降是在权值更新前对所有样例汇总误差,而随机梯度下降的权值是通过考查某个训练样例来更新的

    # 在minibatch梯度下降中,权值更新的每一步对多个样例求和,需要更多的计算

 

    for i inrange(1,m,minibatch_size):

        sum_m = np.zeros(2)

        for k inrange(i-1,i+minibatch_size-1,1):

            dif = (np.dot(theta, input_data[k]) - target_data[k]) *input_data[k]

            sum_m = sum_m + dif  #当alpha取值过大时,sum_m会在迭代过程中会溢出

 

        theta = theta- alpha * (1.0/minibatch_size) * sum_m #注意步长alpha的取值,过大会导致振荡

 

    # 判断是否已收敛

    if np.linalg.norm(theta- error) < epsilon:

        finish = 1

        break

    else:

        error = theta

    print 'loopcount = %d'% count, '\tw:',theta

print 'loop count = %d'% count, '\tw:',theta

 

# check with scipy linear regression

slope, intercept, r_value, p_value,slope_std_error = stats.linregress(x, target_data)

print 'intercept = %s slope = %s'% (intercept, slope)

 

plt.plot(x, target_data, 'g*')

plt.plot(x, theta[1]* x +theta[0],'r')

plt.show()

Mini-batch梯度下降

 

你可能感兴趣的:(智能算法,数学建模,python,机器学习,数学建模,python,机器学习,遗传算法,梯度下降)