GA遺傳算法Matlab版本實例註釋

關於我對GA遺傳算法的理解:

剛開始只聽說過遺傳算法的時候,聽到這個名字就感覺好牛掰的樣子。然後看了一本叫做《MATLAB智能算法30個案例分析》的書,學習了GA遺傳算法,然而學完了之後知道我的第一感覺是什麼?那就是真特麼扯淡,哈哈哈!這特麼不就是瞎碰,瞎貓碰上死耗子,碰上了最優解就碰上了,碰不上不就得到個不知道差多少的解嗎?不過存在即合理仔細想想能發明這個算法的人還是很值得尊敬的。好了來說說我的理解,首先遺傳算法當然是模擬生物進化優勝劣汰的法則了,它最大的優點就是不要你去尋找解,而只需要你作爲上帝去否決那些你認爲不好的解,最終留下來的就是最優解(或者次優解)了

首先來解釋一下幾個名詞:

1. 染色體,一條染色體對應的就是你需要求的一個解,例如你需要求一個三元四次的複雜方程的極小值,那麼你的一個結當然包含三個數(因爲是三元嘛,當然是三個未知 數啦),假設是x,y,z。那麼你的一條染色體就包含三個數,類似於一個向量[x  y  z]。類似的如果你的一個解只有一個數,那麼一條染色體就只包含一個數。

2. 基因,咱們都是理科生,當然知道染色體是由基因組成的,上面說到了[x  y  z]對應的是一條染色體,那麼自然組成x  , y , z的就是基因嘍,這裏我們就要說到編碼了,一般 我們會將染色體進行編碼,假設使用的是二進制編碼,那麼我們用二進制0和1將[x  y  z]橫着寫成一排,那麼是不是就是遺傳0和1。那麼這些0和1就是基因了。

3. 交叉,交叉也是跟生物裏面學的一樣,就是兩條染色體並排的時候相對應的那一段交叉接起來

4. 變異,變異就是基因中某個bit的0變成了1,或者1變成了0,機率很小。當然在算法中是我們讓它變異的。

5. 壓差,在下面的例子中,有個詞語叫“壓差”,之前網上都沒找到明白的解釋,其實說的那麼高端,壓差就是指你把本來0~255之間的數按照某種算法映射到1~10的話,那麼 壓差就是指這個1~10了,其實就是歸一化之後的範圍。

6. 適應度,上面說到優勝劣汰,我們作爲上帝需要指定一個規則,怎麼樣的算是優秀,什麼樣的算是劣質,說讓誰淘汰就讓誰淘汰,比如說我們求一個方程的極小值,那麼 我們當然是將每條染色體的值帶入到方程中,求得的值越小就越優秀,越大就越劣質嘍。那麼我們就要淘汰那些使得方程值大的染色體,通過交叉編譯來補充那些被淘汰 染色體的位置。

7. 適應度函數,適應度函數顧名思義就是用來計算適應度的函數,這個函數的定義很重要,但是總得來說只要保證越符合我們要求的,得出來的值(適應度)越大理論上就 可以接受,至於好不好另說。

8. 種羣,就是若干個染色體組成種羣。


接下來就說說GA遺傳算法的步驟:

下面這個用matlab寫的例子就是一個求極值問題,求方程y = sin(10*pi*x)/x , x屬於[1,2] , 的極值


clc;

clear all;
close all;
figure(1);
hold on;
lb = 1; ub = 2; %這個值是自變量的範圍,在這個範圍內求解
ezplot('sin(10*pi*X)/X',[lb,ub]); %第一個參數表示的是方程,y的計算公式,畫出圖像
xlabel('自變量/X');
ylabel('函數值/Y');


NIND = 40;  %初始化40個解,每一個解代表的是一條染色體,這條染色體就代表的是一個x的值
MAXGEN = 20; %最大遺傳代數
PRECT = 20; %染色體精度,也就是一個個體的基因數(2進制數長度),也就是用多少個bit表示一個x的值
GGAP = 0.95; %代溝,表示每一代從種羣中選擇多少個體到下一代
px = 0.7;   %染色體交叉機率,具體自己寫的話不知道這個概率怎麼用的,不過matlab中作爲參數直接帶入就好了
pm = 0.01;  %染色體變異機率,具體自己寫的話不知道這個概率怎麼用的,不過matlab中作爲參數直接帶入就好了
trace = zeros(2,MAXGEN);%初始化爲0
FieldD = [PRECT;lb;ub;1;0;1;1]; % PRECT:2進制位數 lb:範圍下限 ub:表示範圍上限 
                                % 1:二進制編碼 0:表示用算術刻度 1:表示包含左邊界 1:表示包含右邊界
Chrom = crtbp(NIND,PRECT); %隨機產生初始解


gen = 0;%遺傳代數
X = bs2rv(Chrom , FieldD); %根據區域描述器,自動將2進制編碼轉化成指定範圍內的實數值
                        %得出的X是一個長度爲40的列向量


ObjV = sin(10*pi*X)./X ;%“./”表示爲陣列操作,非矩陣運算,得出的也是一個長度爲40的列向量,適應度值
                        %經過上一步,X已經爲列向量,所以ObjV也是列向量了
while gen<MAXGEN
    
    %ranking : 根據適應度值,使用ranking()得出各自的入選率(適應度)
    %第一個參數:注意ObjV必須是列向量(這是ranking函數要求的),表示需要計算適應度的種羣,
    %第二個參數:一個有兩個標量的向量,第一個標量可以認爲總爲2,同時代表壓差的上限
    %           第二個標量有兩重意義,如果爲0表示線性排序,如果爲1表示非線性排序,
    %           同時它代表壓差的下限。返回得到的FitnV會是一個長度跟ObjV相同的列向量
    %           ,他們之間的值是一一對應的,FitnV中較大的表示適應度的值對應ObjV中較
    %           較小的值。但是FitnV中的順序並非是有序的,順序跟ObjV中的每個值得順序
    %           是一樣的。
    %第三個參數:表示種羣中子種羣的數量
    FitnV = ranking(ObjV,[2,0],1);
    
    %select : 通過計算得到的適應度值,從原始種羣Chrom中篩選一些不符合要求的個體得到
    %           新的種羣返回個SelCh
    %第一個參數:表示選擇篩選的策略,sus表示隨機平均選擇 ,還可以是rws表示輪盤賭選擇
    %第二個參數:表示原始的需要被篩選的種羣
    %第三個參數:表示這個種羣對應的適應度
    %第四個參數:表示代溝,也就是說從Chrom中選擇多少百分比的個體到下一代,這裏爲0.95
    %           也就是說從Chrom中選擇Chrom*0.95個個體進入下一代,有0.05的染色體被淘汰
    SelCh = select('sus',Chrom,FitnV,GGAP); %這就是優勝劣汰的過程
                                            
    SelCh = recombin('xovsp',SelCh,px); %交叉基因函數 ,xovsp或者recdis表示交叉策略 , px表示染色體交叉機率
    SelCh = mut(SelCh,pm);              %變異函數 ,pm表示編譯機率
    X = bs2rv(SelCh , FieldD);
    ObjVSel = sin(10*pi*X)./X;
    
    %reins : 將子代個體插入到父代種羣中,代替那些不合適的父代個體
    %第一個參數:表示父代種羣
    %第二個參數:子代種羣
    %第三個參數:指明Chrom,SelCh中子種羣個數,每個子種羣必須有相同的大小
    %第四個參數:其實是一個有兩個元素的向量,在這裏相當於[1,1] ,第一個標量表示用什麼策略將子代
    %           將子代插入父代種羣,如果爲0表示用隨機均勻選擇,如果爲1表示根據適應度進行選擇;
    %           第二個標量表示子代種羣插入父代,佔百分比,可以是[0,1]之間的標量,如果缺省表示
    %           默認值爲1
    %第五個參數:基於適應度重插入(也就是第四個參數爲1)的時候這個參數是必須的,Objv包含Chrom中
    %           個體的目標值(也就是根據公式計算得到的值比如上面的sin(10*pi*X)./X得到的值)。
    %           這是因爲基於適應度的方法,得到適應度必須是根據目標值來確定適應度,所以這裏必須
    %           要帶入目標值。
    %第六個參數:如果子代的個體數量大於將要插入父代的個體數量,那麼這個參數是必須的,因爲待插入
    %           的個數多餘需要插入的個數,那麼必然存在有一部分不能插入,那麼淘汰那一部分個體,是
    %           根據子代種羣的個體適應度來決定的,淘汰掉適應度底的個體,那麼得到個體的適應度就需
    %           要子種羣的各個個體的目標值來計算。
    [Chrom,ObjV] = reins(Chrom , SelCh , 1 , 1 , ObjV , ObjVSel)
                              
    X = bs2rv(Chrom , FieldD);
    gen = gen + 1;
    
    %min : 返回向量ObjV的最小值,Y記錄ObjV中每一列的最小值,I記錄每一列的最小值的行號
    [Y,I] = min(ObjV)
    trace(1,gen) = X(I);
    trace(2,gen) = Y;
end


plot(trace(1,:),trace(2,:),'bo');
grid on;
plot(X,ObjV,'b*');
hold off;
figure(2);
plot(1:MAXGEN,trace(2,:));
grid on;
xlabel('遺傳代數');
ylabel('解的變化');
title('進化過程');
bestY = trace(2,end);
bestX = trace(1,end);
fprintf(['最優解:\nX = ', num2str(bestX), '\nY = ' , num2str(bestY) , '\n']);





發佈了39 篇原創文章 · 獲贊 30 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章