概述
2018.09.17遗传算法研究日志
2018.09.17主要是了解遗传算法的背景和解决何种问题。大概了解遗传算法的步骤,对该算法有初步印象。
遗传算法的介绍
概念
遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
遗传算法是从代表问题可能潜在的解集的一个种群(population)开始的,而一个种群则由经过基因(gene)编码的一定数目的个体(individual)组成。
初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代(generation)演化产生出越来越好的近似解。
在每一代,根据问题域中个体的适应度(fitness)大小选择(selection)个体,并借助于自然遗传学的遗传算子(genetic operators)进行组合、交叉(crossover)和变异(mutation),产生出代表新的解集的种群。末代种群中的最优个体经过解码(decoding),可以作为问题近似最优解。
遗传算法也是计算机科学人工智能领域中用于解决最优化的一种搜索启发式算法,是进化算法的一种。
算法步骤
- 初始化:设置进化代数计数器t=0,设置最大进化代数T,随机生成M个个体作为初始群体P(0)。
- 个体评价:计算群体P(t)中各个个体的适应度。
- 选择运算:将选择算子作用于群体。选择的目的是把优化的个体直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。选择操作是建立在群体中个体的适应度评估基础上的。
- 交叉运算:将交叉算子作用于群体。遗传算法中起核心作用的就是交叉算子。
- 变异运算:将变异算子作用于群体。即是对群体中的个体串的某些基因座上的基因值作变动。群体P(t)经过选择、交叉、变异运算之后得到下一代群体P(t+1)。
- 终止条件判断:若t=T,则以进化过程中所得到的具有最大适应度个体作为最优解输出,终止计算。
流程图如下:
遗传算法的独特特点
- 遗传算法从问题解的串集开始搜索,而不是从单个解开始。所以不容易陷入局部最优解。
- 遗传算法采用概率的变迁规则来指导他的搜索方向。
基本框架
首先构建基本框架,包括:编码、适应度函数和初始群体选取。
编码
评估编码策略常采用以下3个规范:
- 完备性completeness
- 健全性soundness
- 非冗余性nonredundancy
我们常用二进制编码实现遗传算法的编码过程。
二进制编码的优点:
- 简单易行
- 符合最小字符集编码原则
- 便于用模式定理进行分析
评价个体——适应度函数
遗传算法的适应度函数也叫评价函数,是用来判断群体中的个体的优劣程度的指标。完成优胜劣汰的过程。
注意:遗传算法中,适应度函数要比较排序并在此基础上计算选择概率,所以适应度函数的值取正值是合适的。
评价个体适应度的一般过程为:
- 对个体编码串进行解码处理后,可得到个体的表现型。
- 由个体的表现型可计算出对应个体的目标函数值。
- 根据最优化问题的类型,由目标函数值按一定的转换规则求出个体的适应度。
初始群体选取——选择函数
遗传算法中初始群体中的个体是随机产生的。一般来讲,初始群体的设定可采取如下的策略:
- 根据问题把握最优解所占空间在整个问题空间中的分布范围,然后,在此分布范围内设定初始群体。
- 先随机生成一定数目的个体,然后从中挑出符合适应度函数的个体加到初始群体中。将这种过程不断迭代,直到初始群体中个体数达到了预先设定的规模。
2018.09.18研究日志
今天继续研究遗传算法,查看他人博客,总结自己经验并着手构建数据结构。
选择、交叉、变异算子的运算过程
选择算子
包括适应度比例方法、随机遍历抽样法、局部选择法。
这里介绍一下最简单常用的轮盘赌选择法(roulette wheel selection):
在该方法中,各个个体的选择概率和其适应度值成比例。设群体大小为n,其中个体i的适应度为f,则i被选择的概率:
P i = f i / ∑ j = 1 n f j P_i=f_i/sum^n_{j=1}f_j Pi=fi/j=1∑nfj
上式表明,个体适应度越大,其被选择的概率就越高,反之亦然。
概率算出来后需要进行多轮选择交配个体。每一轮产生一个[0,1]之间均匀随机数,将该随机数作为选择指针来确定被选个体。个体被选后,可随机地组成交配对。
例如:
假如有5条染色体,他们的适应度分别为5、8、3、7、2。
那么总的适应度为:F = 5 + 8 + 3 + 7 + 2 = 25。
那么各个个体的被选中的概率为:
α1 = ( 5 / 25 ) * 100% = 20%
α2 = ( 8 / 25 ) * 100% = 32%
α3 = ( 3 / 25 ) * 100% = 12%
α4 = ( 7 / 25 ) * 100% = 28%
α5 = ( 2 / 25 ) * 100% = 8%
所以他的转盘如下:
还有一种方法是无回放随机选择(也叫期望值选择Excepted Value Selection):
根据每个个体在下一代群体中的生存期望来进行随机选择运算。方法如下:
- 计算群体中每个个体在下一代群体中的生存期望数目N。
- 若某一个体被选中参与交叉运算,则它在下一代中的生存期望数目减去0.5,若某一个体未被选中参与交叉运算,则它在下一代中的生存期望数目减去1.0。
- 随着选择过程的进行,若某一个体的生存期望数目小于0时,则该个体就不再有机会被选中。
交叉算子
遗传算法中起核心作用的是遗传操作的交叉算子。
交叉算子根据交叉率将种群中的两个个体随机地交换某些基因,能够产生新的基因组合,期望将有益基因组合在一起。
最常用的交叉算子为单点交叉(one-point crossover)。具体操作是:在个体串中随机设定一个交叉点,实行交叉时,该点前或后的两个个体的部分结构进行互换,并生成两个新个体。
下面给出了单点交叉的一个例子:
个体A:1 0 0 1 ↑1 1 1 → 1 0 0 1 0 0 0 新个体
个体B:0 0 1 1 ↑0 0 0 → 0 0 1 1 1 1 1 新个体
变异算子
一般来说,变异算子操作的基本步骤如下:
- 对群中所有个体以事先设定的变异概率判断是否进行变异;
- 对进行变异的个体随机选择变异位进行变异。
遗传算法引入变异的目的有两个:
- 使遗传算法具有局部的随机搜索能力;
- 使遗传算法可维持群体多样性。
基本变异算子方法:对群体中的个体码串随机挑选一个或多个基因座并对这些基因座的基因值做变动(以变异概率P做变动)。
例如将标记为*号的基因进行修改(如1变为0,0变为1)。
变异率通常选取很小的值,一般取0.001-0.1。
终止条件
当最优个体的适应度达到给定的阈值,
或者最优个体的适应度和群体适应度不再上升时,
或者迭代次数达到预设的代数时,算法终止。
预设的代数一般设置为100-500代。
以下是实例:(语言:Java)
f ( x ) = x ∗ sin ( 10 ∗ π ∗ x ) + 2 , x ∈ [ − 1 , 2 ] f(x)=x*sin(10*pi*x)+2,qquad xin[-1,2] f(x)=x∗sin(10∗π∗x)+2,x∈[−1,2]
求其区间内最大值。
其函数图像如下:
例子来源: https://blog.csdn.net/emiyasstar__/article/details/6938608/
首先是编码类Genome.class
import java.util.Random;
public class Genome {
//编码部分
public int[] Genome(){
//随机生成二进制数
int[] genome = new int[9];
for (int i=0;i<9;i++){
Random rand = new Random();
genome[i]=rand.nextInt(2);
//二进制随机数
}
return genome;
}
//解码部分
public double GeneEncode(int genome[]){
int num=0;
double e = 0.01;
//求解精度e
for (int i=0,j=8; i<9; i++,j--){
num += genome[i]*(Math.pow(2,j));
}
double e_true = 3/(Math.pow(2,9));
//实际精度
double x = (num * e_true) - 1;
return x;
}
}
种群类Population.java:
public class Population {
//初始化种群
public int[][] Initialize(){
int genes[][] = new int[5][9];
Genome gene = new Genome();
int[] a = new int[9];
double[] population = new double[5];
for (int i=0;i<5;i++){
a = gene.Genome();
population[i] = gene.GeneEncode(a);
for (int j=0;j<9;j++){
//存储二进制码用于之后的选择、交叉、变异
genes[i][j] = a[j];
}
}
return genes;
}
//打印基因
public void print_genes(int genes[][]){
for (int i=0;i<5;i++){
for (int j=0;j<9;j++){
System.out.print(genes[i][j]);
}
System.out.print("t");
}
}
//打印种群(即表现型)
public void print_population(int genes[][]){
Genome gen = new Genome();
double population[] = new double[5];
for (int i=0;i<5;i++){
population[i]=gen.GeneEncode(genes[i]);
}
System.out.println("第1代:");
for (int i=0;i<5;i++){
System.out.print(i+1+":t"+population[i]+"t");
}
System.out.println();
}
}
最后
以上就是凶狠柚子为你收集整理的2018.09.17遗传算法研究日志2018.09.17遗传算法研究日志2018.09.18研究日志的全部内容,希望文章能够帮你解决2018.09.17遗传算法研究日志2018.09.17遗传算法研究日志2018.09.18研究日志所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复