遺傳算法
記錄學習matlab的過程防止忘記。本文參考《智能優化算法及其matlab實例第二版》
遺傳算法簡介
遺傳算法利用羣體搜索技術,將種羣代表一組問題解,對種羣進行選擇,交叉,變異,複製等生物學上的進化操作產生新一代的種羣。
- 羣體 :可行解集(一開始羣體是隨機生成的,然後通過自然選擇,優勝略汰);
- 個體:可行解(組成羣體的單個生物體);
- 染色體 :可行解的編碼(包含生物體信息的遺傳物質);
- 基因:可行解編碼的分量(控制生物體的遺傳信息的基本單位) ;
- 適應度:可行解在具體問題中跟最優解的差值(個體對當前環境的適應能力)
舉個例子
我們創建一個數值在0~10的3行5列的矩陣
randi([0,10],3,5);
結果爲
ans =
7 4 7 0 7
8 7 0 1 3
8 1 3 9 10
通常用一列作爲一個個體即這個矩陣代表了5了個體
每一列中的三個實數編碼代表了每個個體的遺傳物質
比如說第一個個體的遺傳信息是 7 8 8
遺傳算法怎麼解決問題
我覺得一個難點就是怎麼把解轉換爲編碼的個體,上面介紹過常用的編碼方式有二進制編碼跟實數編碼,那麼怎麼編 ?
二進制編碼
如果最優解是一個實數的話,像找函數的極大值極小值這些,就可以用到二進制編碼,一列二進制編碼代表的一個解就代表了一個實數。
實數編碼
如果最優解是多個實數的話,像在一組數據中找出最合適的幾個,就可以用實數編碼。
遺傳算法流程
1.初始化:設定最大進化次數,隨機生成一個種羣(一個矩陣,維數看實際問題)。
2.個體評價:計算種羣中每個個體的適應度。
3.進化運算:對種羣進行選擇運算,交叉運算,變異運算。
4.終止條件判斷:如果進化次數大於最大進化次數則終止。
遺傳算法中關鍵參數
1.羣體規模NP:NP太小時優化性能不太好,NP太大計算複雜度高。一般NP取10-200.
2.交叉概率Pc:Pc太小時可能會使遺傳算法太過於遲鈍,Pc較大時雖然可以擴大搜索區域,但穩定性不高。Pc一般取0.25-1.00
3.變異概率Pm:Pm在算法中起了一種輔助作用,不可以太高,太高會讓算法變成隨機的搜索。一般取0.001-0.1.
4.算法進化次數:一般100-1000之間。問題不大,能算不了就好。
簡單的實例
用標準遺傳算法求函數 f(x) = x+10sin(5x)+7cos(4x)的最大值
%遺傳算法
clear ;
funcl =@(x) x+10*sin(5*x)+7*cos(4*x);
NP = 50; %種羣數量
L = 20 ; %二進制編碼長度
Pc = 0.8; %交叉率
Pm = 0.1 ;%變異率
G = 100 ;%最大迭代次數
Xs = 10; % X取值的上下限
Xx = 0;
f = randi([0,1],NP,L); %隨機獲得初始種羣
fit =zeros(1,50);
x = zeros(1,50);
trace = zeros(1,100);
xtrace = zeros(1,100); %預先分配內存
for k = 1:G
for i = 1:NP
U = f(i,:);
m = 0;
for j = 1:L
m = U(j)*2^(j-1)+m;
end
x(i) = Xx +m*(Xs - Xx)/ (2^L-1); %把二進制編碼變成實數
fit(i) = funcl(x(i)); %計算適應度
end
maxfit = max(fit);
minfit = min(fit);
rr = find(fit == maxfit);
fbest = f(rr(1,1),:);
xbest = x(rr(1,1)); %歷代最優個體
fit = (fit - minfit )/(maxfit-minfit); %歸一化適應度
%複製操作
sum_fit = sum(fit);
fitvalue = fit./sum_fit;
fitvalue = cumsum(fitvalue);
ms = sort(rand(NP,1));
fiti = 1;
newi = 1;
while newi <= NP
if (ms(newi))<=fitvalue(fiti)
nf(newi,:) = f(fiti,:);
newi = newi +1;
else
fiti = fiti+1;
end
end
%交叉操作
for i = 1:2:NP
p = rand;
if p < Pc
q = randi(1,L);
for j = 1:L
if q(j) == 1
temp = nf(i+1,j);
nf(i+1,j) = nf(i,j);
nf(i,j) = temp;
end
end
end
end
%變異操作
i = 1;
while i <= round(NP*Pm)
h =randi([1,NP],1,1);
for j = 1:round(L*Pm)
g = randi([1,L],1,1);
nf(h,g) =~nf(h,g);
end
i = i+1;
end
f = nf;
f(1,:) = fbest;
trace(k) = maxfit;
xtrace(k) =xbest;
end
figure;
subplot(3,1,1);
plot(trace);
xlabel('迭代次數');
ylabel('進化曲線');
title("適應度進化曲線");
hold on;
subplot(3,1,2);
plot(xtrace);
xlabel('迭代次數');
ylabel('進化曲線');
title("適應度進化曲線");
subplot(3,1,3);
fplot(funcl,[0,10]);
xlabel('x');
ylabel('y');
title("函數曲線");
代碼運行結果
可以看到算法收斂得很快。