遺傳算法簡(jiǎn)單介紹與MATLAB實(shí)現(xiàn)(二)

遺傳算法簡(jiǎn)單介紹與MATLAB實(shí)現(xiàn)(二)

引入題目一

上一篇文章中我們簡(jiǎn)單的介紹了一了一下遺傳算法二汛,其中提到了多元函數(shù)$f=f(x, y)$极谊,所以在這里我們就定義一個(gè)二元函數(shù)罕拂,作為第一個(gè)練手的程序颠焦。

我們?cè)谶@里令

$$z = \sin{x}+\cos{y}+0.1(x+y)$$

通過使用MATLAB作圖可以看到下圖

可以看出這是一個(gè)存在很多區(qū)域極大值法精,有很多“坑”沛厨。這正是遺傳算法的缺陷之一——求出來的最優(yōu)解可能并不是全局最優(yōu)解而是局部最優(yōu)解刚照。

從圖中可以看出全局最大值在$(10, 10)$附近刑巧。所以接下來我們就開始編程解決這個(gè)問題喧兄。


遺傳算法MATLAB程序

設(shè)定參數(shù)

首先我們要確定一系列參數(shù)

N = 100;  %種群內(nèi)個(gè)體數(shù)目
N_chrom = 2; %染色體節(jié)點(diǎn)數(shù)
iter = 2000; %迭代次數(shù)
mut = 0.2;  %突變概率
acr = 0.2; %交叉概率

其中突變概率指的是某個(gè)個(gè)體的染色體發(fā)生突變的概率。因?yàn)閷?shí)際中并不可能每一個(gè)個(gè)體都會(huì)發(fā)生突變啊楚,而是存在一定的概率吠冤,因此我們?cè)谶@里定義每一個(gè)個(gè)體突變發(fā)生的概率為0.2。

同理恭理,交叉概率指的就是某個(gè)個(gè)體與另一個(gè)個(gè)體發(fā)生染色體交叉的概率拯辙。

迭代次數(shù)指的是整個(gè)種群迭代2000多次。

一般來說颜价,并不是突變概率涯保、交叉概率越小或者越大越好。比如說突變概率特別高的話周伦,會(huì)讓整個(gè)種群的最優(yōu)適應(yīng)度飄忽不定夕春。如果特別小的話,會(huì)讓種群迭代的速度特別慢专挪,很難找到最優(yōu)適應(yīng)度及志。這里取0.2是我經(jīng)過多次試驗(yàn)以后,覺得0.2是一個(gè)比較穩(wěn)定不會(huì)亂飄且適應(yīng)度收斂也不錯(cuò)的一個(gè)值寨腔。

迭代次數(shù)也同理速侈,如果一個(gè)特別簡(jiǎn)單的模型去求最優(yōu)解,可能五六次迭代就求出來了迫卢,那么2000次迭代純屬浪費(fèi)時(shí)間倚搬。但是如果是一個(gè)特別復(fù)雜的模型,那么2000次迭代就有可能不夠乾蛤。具體迭代次數(shù)可以自己靈活決定每界。

chrom_range = [-10 -10; 10 10];%每個(gè)節(jié)點(diǎn)的值的區(qū)間
chrom = zeros(N, N_chrom);%存放染色體的矩陣
fitness = zeros(N, 1);%存放染色體的適應(yīng)度
fitness_ave = zeros(1, iter);%存放每一代的平均適應(yīng)度
fitness_best = zeros(1, iter);%存放每一代的最優(yōu)適應(yīng)度
chrom_best = zeros(1, N_chrom+1);%存放當(dāng)前代的最優(yōu)染色體與適應(yīng)度

其中的chrom_range指的是每個(gè)節(jié)點(diǎn)值的區(qū)間。在我們的這個(gè)模型中幻捏,$x\in [-10, 10], y\in[-10, 10]$。第一行放的是兩個(gè)變量的區(qū)間下限命咐,第二行放的是區(qū)間上限篡九。

chrom和fitness兩個(gè)矩陣你們可以自己理解一下為什么這樣子寫。

fitness_ave用來存放每一代的平均適應(yīng)度醋奠,主要是用來最后畫圖榛臼,觀察種群在每一次迭代中適應(yīng)度的變化情況。fitness_best同理窜司。

chrom_best用來存放最優(yōu)適應(yīng)度對(duì)應(yīng)的最優(yōu)染色體與適應(yīng)度沛善,可以回想一下上一章染色體變異中需要最優(yōu)適應(yīng)度,優(yōu)勝劣汰中需要最優(yōu)染色體塞祈,這個(gè)矩陣作用就是如此金刁。

初始化種群

接下來開始初始化參數(shù)

chrom = Initialize(N, N_chrom, chrom_range); %初始化染色體
fitness = CalFitness(chrom, N, N_chrom); %計(jì)算適應(yīng)度
chrom_best = FindBest(chrom, fitness, N_chrom); %尋找最優(yōu)染色體
fitness_best(1) = chrom_best(end); %將當(dāng)前最優(yōu)存入矩陣當(dāng)中
fitness_ave(1) = CalAveFitness(fitness); %將當(dāng)前平均適應(yīng)度存入矩陣當(dāng)中

Initialize函數(shù)是我自定義的一個(gè)函數(shù),用于初始化染色體。具體操作就是用一個(gè)for循環(huán)對(duì)每個(gè)個(gè)體的染色體進(jìn)行隨機(jī)賦值尤蛮,并利用chrom_range將其限定在變量規(guī)定的區(qū)間之內(nèi)媳友。

function chrom_new = Initialize(N, N_chrom, chrom_range)
chrom_new = rand(N, N_chrom);
for i = 1:N_chrom %每一列乘上范圍
    chrom_new(:, i) = chrom_new(:, i)*(chrom_range(2, i)-chrom_range(1, i))+chrom_range(1, i);
end

CalFitness函數(shù)則是計(jì)算chrom內(nèi)每個(gè)個(gè)體的適應(yīng)度,并將其保存在fitness中产捞。這個(gè)函數(shù)很重要醇锚,請(qǐng)著重理解這個(gè)函數(shù)的用法

function fitness = CalFitness(chrom, N, N_chrom)
fitness = zeros(N, 1);
%開始計(jì)算適應(yīng)度
for i = 1:N
    x = chrom(i, 1);
    y = chrom(i, 2);
    fitness(i) = sin(x)+cos(y)+0.1*x+0.1*y;
end

FindBest函數(shù)尋找出當(dāng)前種群中的最優(yōu)染色體,并將其保存在chrom_best坯临。

function chrom_best = FindBest(chrom, fitness, N_chrom)
chrom_best = zeros(1, N_chrom+1);
[maxNum, maxCorr] = max(fitness);
chrom_best(1:N_chrom) =chrom(maxCorr, :);
chrom_best(end) = maxNum;

CalAveFitness函數(shù)用于計(jì)算當(dāng)前種群中的平均適應(yīng)度焊唬。

function fitness_ave = CalAveFitness(fitness)
[N ,~] = size(fitness);
fitness_ave = sum(fitness)/N;

迭代開始

初始化完以后就開始迭代,為了保證迭代次數(shù)和iter一致看靠,這里我們就直接令t從2開始迭代赶促。

再一次迭代過程中,一個(gè)種群執(zhí)行操作順序?yàn)椋喝旧w變異衷笋,染色體交叉芳杏,計(jì)算適應(yīng)度,尋找最優(yōu)染色體辟宗,替換當(dāng)前存儲(chǔ)的最優(yōu)染色體爵赵,優(yōu)勝劣汰。

需要注意的是這里替換當(dāng)前最優(yōu)染色體泊脐。因?yàn)槲覀儗⑦@個(gè)種群的個(gè)個(gè)個(gè)體的染色體重新變異空幻、交叉過了,所以最優(yōu)染色體也會(huì)變化容客。但是這一代的最優(yōu)染色體不一定比上一次迭代的最優(yōu)染色體好秕铛,所以需要判定是否將最優(yōu)染色體這個(gè)位置給換掉。

因此迭代過程中的代碼為

for t = 2:iter
    chrom = MutChrom(chrom, mut, N, N_chrom, chrom_range, t, iter); %變異
    chrom = AcrChrom(chrom, acr, N, N_chrom); %交叉
    fitness = CalFitness(chrom, N, N_chrom); %計(jì)算適應(yīng)度
    chrom_best_temp = FindBest(chrom, fitness, N_chrom); %尋找最優(yōu)染色體
    if chrom_best_temp(end)>chrom_best(end) %替換掉當(dāng)前儲(chǔ)存的最優(yōu)
        chrom_best = chrom_best_temp;
    end
    %%替換掉最劣
    [chrom, fitness] = ReplaceWorse(chrom, chrom_best, fitness);
    fitness_best(t) = chrom_best(end); %將當(dāng)前最優(yōu)存入矩陣當(dāng)中
    fitness_ave(t) = CalAveFitness(fitness); %將當(dāng)前平均適應(yīng)度存入矩陣當(dāng)中
end

其中MutChrom函數(shù)用來對(duì)種群進(jìn)行染色體變異操作缩挑。這里面的操作比較多但两,主要可以分為三步:

  1. 判斷某節(jié)點(diǎn)是否變異;
  2. 判斷變異是增加還是減少供置;
  3. 判斷變異后的值是否越界谨湘。

下面代碼表示為

function chrom_new = MutChrom(chrom, mut, N, N_chrom, chrom_range, t, iter)
for i = 1:N
    for j = 1:N_chrom
        mut_rand = rand; %是否變異
        if mut_rand <=mut
            mut_pm = rand; %增加還是減少
            mut_num = rand*(1-t/iter)^2;
            if mut_pm<=0.5
                chrom(i, j)= chrom(i, j)*(1-mut_num);
            else
                chrom(i, j)= chrom(i, j)*(1+mut_num);
            end
            chrom(i, j) = IfOut(chrom(i, j), chrom_range(:, j)); %檢驗(yàn)是否越界
        end
    end
end
chrom_new = chrom;

越界函數(shù)IfOut函數(shù)我們看它是左越界還是右越界,如果是左越界芥丧,則讓節(jié)點(diǎn)值等于區(qū)間下限紧阔;如果是右越界,則讓節(jié)點(diǎn)值等于區(qū)間上限续担。

function c_new = IfOut(c, range)
if c<range(1) || c>range(2)
    if abs(c-range(1))<abs(c-range(2))
        c_new = range(1);
    else
        c_new = range(2);
    end
else
    c_new = c;
end

AcrChrom函數(shù)是染色體交叉函數(shù)擅耽。邏輯相較染色體變異來說比較簡(jiǎn)單,大致可以分為以下幾點(diǎn)

  1. 判斷該節(jié)點(diǎn)是否交叉物遇;
  2. 隨機(jī)尋找一個(gè)與其交叉的節(jié)點(diǎn)乖仇;
  3. 對(duì)兩個(gè)節(jié)點(diǎn)進(jìn)行交叉憾儒。
function chrom_new = AcrChrom(chrom, acr, N, N_chrom)
for i = 1:N
    acr_rand = rand;
    if acr_rand<acr %如果交叉
        acr_chrom = floor((N-1)*rand+1); %要交叉的染色體
        acr_node = floor((N_chrom-1)*rand+1); %要交叉的節(jié)點(diǎn)
        %交叉開始
        temp = chrom(i, acr_node);
        chrom(i, acr_node) = chrom(acr_chrom, acr_node); 
        chrom(acr_chrom, acr_node) = temp;
    end
end
chrom_new = chrom;

ReplaceWorse函數(shù)則是優(yōu)勝劣汰這個(gè)過程,將種群中的最劣染色體替換掉这敬。這里是直接用最優(yōu)染色體替換航夺,并且替換掉的是最后幾個(gè)染色體,目的是加快收斂速度崔涂,但可能會(huì)陷入局部最優(yōu)解阳掐。

function [chrom_new, fitness_new] = ReplaceWorse(chrom, chrom_best, fitness)

max_num = max(fitness);
min_num = min(fitness);
limit = (max_num-min_num)*0.2+min_num;

replace_corr = fitness<limit;

replace_num = sum(replace_corr);
chrom(replace_corr, :) = ones(replace_num, 1)*chrom_best(1:end-1);
fitness(replace_corr) = ones(replace_num, 1)*chrom_best(end);
chrom_new = chrom;
fitness_new = fitness;

end

輸出遺傳算法迭代圖

在這里我們只輸出一個(gè)標(biāo)準(zhǔn)圖為迭代過程中種群的平均適應(yīng)度與最優(yōu)適應(yīng)度

在之前我們已經(jīng)得到了每一代的平均適應(yīng)度fitness_ave與最優(yōu)適應(yīng)度fitness_best冷蚂,所以可以直接輸出圖像

figure(1)
plot(1:iter, fitness_ave, 'r', 1:iter, fitness_best, 'b')
grid on
legend('平均適應(yīng)度', '最優(yōu)適應(yīng)度')

之后我們還想要看得出的點(diǎn)在實(shí)際圖像中哪個(gè)位置缭保,所以我們可以增加一個(gè)用來作圖的函數(shù)PlotModel

function y = PlotModel(chrom)
x = chrom(1);
y = chrom(2);
z = chrom(3);
figure(2)
scatter3(x, y, z, 'ko')
hold on
[X, Y] = meshgrid(-10:0.1:10);
Z =sin(X)+cos(Y)+0.1*X+0.1*Y;
mesh(X, Y, Z)
y=1;

遺傳算法主程序

上面就是所有程序片段,因此把主程序的代碼聯(lián)立起來為

clc, clear, close all

%%基礎(chǔ)參數(shù)
N = 100;  %種群內(nèi)個(gè)體數(shù)目
N_chrom = 2; %染色體節(jié)點(diǎn)數(shù)
iter = 2000; %迭代次數(shù)
mut = 0.2;  %突變概率
acr = 0.2; %交叉概率
best = 1;

chrom_range = [-10 -10;10 10];%每個(gè)節(jié)點(diǎn)的值的區(qū)間
chrom = zeros(N, N_chrom);%存放染色體的矩陣
fitness = zeros(N, 1);%存放染色體的適應(yīng)度
fitness_ave = zeros(1, iter);%存放每一代的平均適應(yīng)度
fitness_best = zeros(1, iter);%存放每一代的最優(yōu)適應(yīng)度
chrom_best = zeros(1, N_chrom+1);%存放當(dāng)前代的最優(yōu)染色體與適應(yīng)度

%%初始化
chrom = Initialize(N, N_chrom, chrom_range); %初始化染色體
fitness = CalFitness(chrom, N, N_chrom); %計(jì)算適應(yīng)度
chrom_best = FindBest(chrom, fitness, N_chrom); %尋找最優(yōu)染色體
fitness_best(1) = chrom_best(end); %將當(dāng)前最優(yōu)存入矩陣當(dāng)中
fitness_ave(1) = CalAveFitness(fitness); %將當(dāng)前平均適應(yīng)度存入矩陣當(dāng)中

for t = 2:iter
    chrom = MutChrom(chrom, mut, N, N_chrom, chrom_range, t, iter); %變異
    chrom = AcrChrom(chrom, acr, N, N_chrom); %交叉
    fitness = CalFitness(chrom, N, N_chrom); %計(jì)算適應(yīng)度
    chrom_best_temp = FindBest(chrom, fitness, N_chrom); %尋找最優(yōu)染色體
    if chrom_best_temp(end)>chrom_best(end) %替換掉當(dāng)前儲(chǔ)存的最優(yōu)
        chrom_best = chrom_best_temp;
    end
    %%替換掉最劣
    [chrom, fitness] = ReplaceWorse(chrom, chrom_best, fitness);
    fitness_best(t) = chrom_best(end); %將當(dāng)前最優(yōu)存入矩陣當(dāng)中
    fitness_ave(t) = CalAveFitness(fitness); %將當(dāng)前平均適應(yīng)度存入矩陣當(dāng)中
end

%%作圖
figure(1)
plot(1:iter, fitness_ave, 'r', 1:iter, fitness_best, 'b')
grid on
legend('平均適應(yīng)度', '最優(yōu)適應(yīng)度')
e = PlotModel(chrom_best)

%%輸出結(jié)果
disp(['最優(yōu)染色體為', num2str(chrom_best(1:end-1))])
disp(['最優(yōu)適應(yīng)度為', num2str(chrom_best(end))])

輸出結(jié)果

我們運(yùn)行一下蝙茶, 可以得到最大點(diǎn)為$(7.9541, 6.3834)$艺骂,最大值為3.4237。

可以做出最大值點(diǎn)在空間中的位置如圖所示隆夯。證明我們的結(jié)論比較正確钳恕,起碼沒有落到周圍的極大值的峰上。


下章預(yù)告

本章只是求解了一個(gè)二元函數(shù)蹄衷,下一章我們將來解決一個(gè)實(shí)際模型忧额,來看一下遺傳算法怎么求解不同的模型。

喜歡的話麻煩點(diǎn)個(gè)喜歡哦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愧口,一起剝皮案震驚了整個(gè)濱河市睦番,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耍属,老刑警劉巖托嚣,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異厚骗,居然都是意外死亡示启,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門领舰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夫嗓,“玉大人,你說我怎么就攤上這事提揍∑≡拢” “怎么了煮仇?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵劳跃,是天一觀的道長。 經(jīng)常有香客問我浙垫,道長刨仑,這世上最難降的妖魔是什么郑诺? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮杉武,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己聋迎,他們只是感情好嫌褪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祈搜,像睡著了一般较店。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上容燕,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天梁呈,我揣著相機(jī)與錄音,去河邊找鬼蘸秘。 笑死官卡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的醋虏。 我是一名探鬼主播寻咒,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼灰粮!你這毒婦竟也來了仔涩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤粘舟,失蹤者是張志新(化名)和其女友劉穎熔脂,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柑肴,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霞揉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晰骑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片适秩。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖硕舆,靈堂內(nèi)的尸體忽然破棺而出秽荞,到底是詐尸還是另有隱情,我是刑警寧澤抚官,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布扬跋,位于F島的核電站,受9級(jí)特大地震影響凌节,放射性物質(zhì)發(fā)生泄漏钦听。R本人自食惡果不足惜洒试,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朴上。 院中可真熱鬧垒棋,春花似錦、人聲如沸痪宰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衣撬。三九已至碉碉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淮韭,已是汗流浹背垢粮。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留靠粪,地道東北人蜡吧。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像占键,于是被迫代替她去往敵國和親昔善。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容