机器学习|遗传算法与matlab实现 Genetic Algorithm

遗传算法与matlab实现 介绍
遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
其主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有内在的隐并行性和更好的全局寻优能力;采用概率化的寻优方法,不需要确定的规则就能自动获取和指导优化的搜索空间,自适应地调整搜索方向。
流程图解
机器学习|遗传算法与matlab实现 Genetic Algorithm
文章图片

(摘自百度百科)
编码
常用的编码方式有二进制编码法、浮点编码法、符号编码法。
这里采用的是二进制编码法。规定染色体长度为17,则一个个体的编码示例如下:
00001111000011110
初始化
【机器学习|遗传算法与matlab实现 Genetic Algorithm】首先定义种群大小、染色体长度等基本量:

elitism = true; % 选择精英操作 population_size = 100; % 种群大小 chromosome_size = 17; % 染色体长度 generation_size = 200; % 最大迭代次数 cross_rate = 0.6; % 交叉概率 mutate_rate = 0.01; % 变异概率

对种群中的每一个个体进行初始化,这里随机产生0与1对种群population数组进行幅值。
function init(population_size, chromosome_size) global population; for i=1:population_size for j=1:chromosome_size % 给population的i行j列赋值 population(i,j) = round(rand); % rand产生(0,1)之间的随机数,round()是四舍五入函数 end end

迭代过程
迭代次数已在初始化中给定 generation_size = 200(即流程图中的GEN)。
for G=1:generation_size fitness(population_size, chromosome_size); % 计算适应度 rank(population_size, chromosome_size); % 对个体按适应度大小进行排序 selection(population_size, chromosome_size, elitism); % 选择操作 crossover(population_size, chromosome_size, cross_rate); % 交叉操作 mutation(population_size, chromosome_size, mutate_rate); % 变异操作 end

计算适应度
进化论中的适应度,是表示某一个体对环境的适应能力,也表示该个体繁殖后代的能力。遗传算法的适应度函数也叫评价函数,是用来判断群体中的个体的优劣程度的指标,它是根据所求问题的目标函数来进行评估的。
在每次计算前将初始化为0,注意这里使用浮点数进行初始化:
for i=1:population_size fitness_value(i) = 0.; end

计算适应度的函数假定为 f(x) = -x-10sin(5x)-7cos(4x)
遍历每一个个体的每一个基因,首先将二进制转换为十进制,再将十进制数映射到自定义的变量区间里,比如这此程序中,就将0 - (2^17 - 1) 映射到了区间 (0,9) 中。
最后根据区间映射的值计算适应度。
在使用中,如果没有需求,其实可以不必映射到特定区间,修改适应度函数后直接使用十进制数计算适应度即可。
for i=1:population_size for j=1:chromosome_size if population(i,j) == 1 fitness_value(i) = fitness_value(i)+2^(j-1); % population[i]染色体串和实际的自变量xi二进制串顺序是相反的 end end fitness_value(i) = lower_bound + fitness_value(i)*(upper_bound-lower_bound)/(2^chromosome_size-1); % 自变量xi二进制转十进制 fitness_value(i) = fitness_value(i) + 10*sin(5*fitness_value(i)) + 7*cos(4*fitness_value(i)); % 计算自变量xi的适应度函数值 end

按适应度进行个体排序
在每一次计算完适应度之后都要挑选出适应度最高的个体信息。
遍历种群,使用冒泡排序法,使得population(i)的适应度随i递增而递增,population(1)最小,population(population_size)最大。
for i=1:population_size min_index = i; for j = i+1:population_size if fitness_value(j) < fitness_value(min_index); min_index = j; end endif min_index ~= i % 交换 fitness_value(i) 和 fitness_value(min_index) 的值 temp = fitness_value(i); fitness_value(i) = fitness_value(min_index); fitness_value(min_index) = temp; % 此时 fitness_value(i) 的适应度在[i,population_size]上最小% 交换 population(i) 和 population(min_index) 的染色体串 for k = 1:chromosome_size temp_chromosome(k) = population(i,k); population(i,k) = population(min_index,k); population(min_index,k) = temp_chromosome(k); end end end

计算前i个个体的适应度之和fitness_sum(i),在后续选择操作中会用到。
for i=1:population_size if i==1 fitness_sum(i) = fitness_sum(i) + fitness_value(i); else fitness_sum(i) = fitness_sum(i-1) + fitness_value(i); end end

保存最佳个体的信息
% fitness_average(G) = 第G次迭代 个体的平均适应度 fitness_average(G) = fitness_sum(population_size)/population_size; % 更新最大适应度和对应的迭代次数,保存最佳个体(最佳个体的适应度最大) if fitness_value(population_size) > best_fitness best_fitness = fitness_value(population_size); best_generation = G; for j=1:chromosome_size best_individual(j) = population(population_size,j); end end

选择
从群体中选择优胜的个体,淘汰劣质个体的操作叫选择。选择的目的是把优化的个体(或解)直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。
遗传算法中的选择操作就是用来确定如何从父代群体中按某种方法选取那些个体,以便遗传到下一代群体。选择方法有很多,本程序中策略如下:
遍历种群。每次遍历中:
首先生成一个随机数,在[0,总适应度]之间。在适应度排序中,我们已经计算出了计算前i个个体的适应度之和fitness_sum(i),接下来就可以用排中法选择适应度之和最接近次随机数的个体的位置。
取得此个体位置后,根据此个体的基因产生一个新的个体。
在遍历结束后,用population_new更新所有个体。选择操作完成。
通过这种选择操作,每次生成的随机数在[0,总适应度]之间,而population(i)的适应度随i递增而递增,因此用排中法选择的population(idx)总体数值会靠近中间值,适应度低的个体会被淘汰。
在程序中还加入了精英选择的选项,如果进行精英选择,则每次选择时都会将最优的个体保留。
for i=1:population_size r = rand * fitness_sum(population_size); % 生成一个随机数,在[0,总适应度]之间 first = 1; last = population_size; mid = round((last+first)/2); idx = -1; % 排中法选择个体 while (first <= last) && (idx == -1) if r > fitness_sum(mid) first = mid; elseif r < fitness_sum(mid) last = mid; else idx = mid; break; end mid = round((last+first)/2); if (last - first) == 1 idx = last; break; end end% 产生新一代个体 for j=1:chromosome_size population_new(i,j) = population(idx,j); end end% 是否精英选择 if elitism p = population_size-1; else p = population_size; endfor i=1:p for j=1:chromosome_size % 如果精英选择,将population中前population_size-1个个体更新,最后一个最优个体保留 population(i,j) = population_new(i,j); end end

交叉
在自然界生物进化过程中起核心作用的是生物遗传基因的重组。同样,遗传算法中起核心作用的是遗传操作的交叉算子。遗传算法的交叉操作,是指对两个相互配对的染色体按某种方式相互交换其部分基因,从而形成两个新的个体。通过交叉,遗传算法的搜索能力得以飞跃提高。
给定交叉概率cross_rate,以步长为2遍历种群,如果随机生成的(0,1)的数小于交叉概率,则对相邻的个体进行交叉操作。
交叉算子的选择有很多,此程序选择较简单的做法,具体操作是:在染色体长度范围内随机选择一个位置cross_position,交换相邻个体此位置后所有的基因片段。
for i=1:2:population_size % rand<交叉概率,对两个个体的染色体串进行交叉操作 if(rand < cross_rate) cross_position = round(rand * chromosome_size); if (cross_position == 0 || cross_position == 1) continue; end % 对 cross_position及之后的二进制串进行交换 for j=cross_position:chromosome_size temp = population(i,j); population(i,j) = population(i+1,j); population(i+1,j) = temp; end end end

变异
遗传算法中的变异运算,是指将个体染色体编码串中的某些基因座上的基因值用该基因座上的其它等位基因来替换,从而形成新的个体。
随机选择变异位置,对该位置的基因进行取反。
for i=1:population_size if rand < mutate_rate mutate_position = round(rand*chromosome_size); % 变异位置 if mutate_position == 0 % 若变异位置为0,不变异 continue; end population(i,mutate_position) = 1 - population(i, mutate_position); end end

结束
主循环结束后,即可获得最优个体和适应度等结果,输出即可。
disp 最优个体: best_individual disp 最优适应度: best_fitness disp 最优个体对应自变量值: x disp 达到最优结果的迭代次数: iterations

matlab源代码见我个人空间或前往链接。

    推荐阅读