1.遺傳算法理論基礎
第一次接觸遺傳算法,覺得這個算法很是神奇啊!遺傳算法模拟自然界中“優勝劣汰,适者生存”的法則,形成了一種随機搜尋最優化方法。本文主要是講遺傳算法用于優化BP算法,BP算法在拟合非線性函數時,雖然可以收斂,但是有可能收斂到局部最小點,這是源于它的搜尋是串行搜尋,而遺傳算法的并行性,能夠使其更容易收斂到全局最小點。在訓練神經網絡時,目的就是通過不斷的優化每一層的權值和偏置值,使最終網絡輸出與期望輸出之間的誤差小到我們所期望的值,而這個優化的過程,就是權值和偏置值不斷“進化”的過程,在每一次疊代過程中,權值與偏置值由于“自然環境”發生選擇,突變,交叉,然後留下優的品種(權值和偏置值使輸出誤差最小),淘汰劣的品種,進而經過多次疊代,權值與偏置值的“基因”會越來越好,進而達到訓練目的。下面介紹幾個概念:
1.種群:一個種群中有許多個體,個體之間有差異,有的個體攜帶的權值和偏置值誤差小,有的個體攜帶的誤差大。進化過程以種群為基本機關。
2.編碼:就是個體攜帶的基因型,在BP網絡中就是權值和偏置值。
3.适應性:個體優劣程度,在BP網絡中,誤差大的适應性差,誤差小的适應性好。
4.選擇:以一定機率在種群中選取若幹個體,模拟優勝劣汰過程。
5.交叉:兩個個體的編碼“基因重組”。
6.變異:個體編碼“基因突變”。
遺傳算法的進化過程如何實作呢?
1.物種初始化
個體編碼攜帶各層權值與偏置值,種群規模自定義。
2.适應性值
每一個個體都有獨特的權值與偏置值,把該個體網絡輸出與期望輸出之間的誤差作為個體的适應性。
3.選擇
輪盤賭選擇法:
f是适應性值的倒數,f越小,适應性越差,p是每個個體被選中的機率,f越大,适應性值越好,被選中的機率也就越大。注意:所有個體機率相加為1,這對了解輪盤賭選擇法很重要。
如上圖,每一個個體都有被選中的機率,機率和為1。随機産生0~1之間的一個數字x,落在上圖哪個區間,哪個個體就被選中,因為0~1數字是随機産生,是以落在區間大的區域的機率更大,區域機率大代表什麼?代表這個個體适應性好,好的個體被多次選中,自然“基因”就好了。
4.交叉
選中的優秀個體,組成了新的種群,新種群之間的“雜交”是必要的,可以産生更優秀的“基因”。随機選中兩個個體的兩個“基因”進行“雜交”(相同段基因)。
5.變異
生物進化隻有“雜交”是不行的,有時候需要“基因突變”。
r是0~1之間的随機數,g是目前疊代次數,Gmax是最大疊代次數。
2.具體程式設計實作Matlab
main.m
clc,clear,close all
%%
%導入資料
data = load('data.mat');
input_data = (data.input)';
output_data = data.output;
%訓練使用資料
input_data_tr = input_data(:,1:1900);
output_data_tr = output_data(:,1:1900);
%測試使用資料
input_data_te = input_data(:,1901:2000);
output_data_te = output_data(:,1901:2000);
%訓練資料歸一化
[input_tr,p] = mapminmax(input_data_tr);
[output_tr,q] = mapminmax(output_data_tr);
%%
%生成網絡
input_number = 2;
hide_number = 5;
output_number = 1;
net = newff(input_tr,output_tr,5);
%%
%遺傳算法
%定義參數
size = 10;%種群規模 10
time = 50;%疊代次數
pcross = 0.4;%交叉機率
pvariation = 0.2;%變異機率
l = hide_number*input_number+output_number*hide_number+hide_number+output_number;%編碼長度
%定義種群結構體
individuals = struct('fitness',zeros(1,size),'chorm',[]);%chorm編碼資訊 fitness适應度
%初始化種群
lenchrom = ones(1,l);
bound = [-3*ones(l,1) 3*ones(l,1)];
for i = 1:size
individuals.chorm(i,:) = Code(lenchrom,bound);
x = individuals.chorm(i,:);
individuals.fitness(1,i) = fitness_fun(x,input_number,hide_number,output_number,net,input_tr,output_tr);
end
best_fitness = 10;%最優個體适應度
best_chorm = zeros(1,l);%最優個體染色體編碼
trace = zeros(1,time);
b = [];
%進化
for i = 1:time
i
%擇優
individuals = Select(individuals,size);
%交叉
individuals = Cross(size,individuals,pcross,l);
%變異
individuals = Variation(size,pvariation,l,i,time,individuals,3,-3);
%進化之後的适應度
for j = 1:size
x = individuals.chorm(j,:);
individuals.fitness(1,j) = fitness_fun(x,input_number,hide_number,output_number,net,input_tr,output_tr);
end
%最優個體
[new_best_fitness,index] = min(individuals.fitness);
new_best_chorm = individuals.chorm(index,:);
%最差個體
[worst_fitness,index] = max(individuals.fitness);
if new_best_fitness<best_fitness
best_fitness = new_best_fitness;
best_chorm = new_best_chorm;
end
b = [b best_fitness];
%淘汰最差個體
individuals.fitness(1,index) = best_fitness;
individuals.chorm(index,:) = best_chorm;
%平均适應度
trace(1,i) = sum(individuals.fitness)/size;
end
%%
%測試
%生成神經網絡權值與偏置值
x = best_chorm;
w1 = x(1,1:input_number*hide_number);
b1 = x(1,input_number*hide_number+1:input_number*hide_number+hide_number);
w2 = x(1,input_number*hide_number+hide_number+1:input_number*hide_number+hide_number+hide_number*output_number);
b2 = x(1,input_number*hide_number+hide_number+hide_number*output_number+1:input_number*hide_number+hide_number+hide_number*output_number+output_number);
%生成神經網絡
net.iw{1,1} = reshape(w1,hide_number,input_number);
net.lw{2,1} = reshape(w2,output_number,hide_number);
net.b{1} = reshape(b1,hide_number,1);
net.b{2} = reshape(b2,output_number,1);
%設定神經網絡參數
net.trainparam.epochs = 100;
net.trainparam.lr = 0.1;%learn rate
net.trainparam.goal = 0.00001;
%訓練神經網絡
net = train(net,input_tr,output_tr);
%歸一化輸入測試資料
input_te = mapminmax('apply',input_data_te,p);
%輸入神經網絡
o = sim(net,input_te);
output = mapminmax('reverse',o,q);
error = output_data_te-output;
plot(error);
1.首先導入資料,根據要拟合的非線性函數,得到2000組輸入輸出資料。其中1900組用于網絡訓練,100組用于網絡測試。訓練資料歸一化。
2.構造神經網絡,輸入變量為2,輸出變量為1,三層網絡結構,設定隐層節點為5。
3.遺傳算法優化BP網絡訓練,定義種群結構體包含編碼與适應性值。初始化種群個體的編碼(權值和偏置值),計算出适應性值。進化過程:每一次疊代過程,都要進行個體選擇,交叉和變異操作。然後計算進化之後的個體适應性值,進行優勝劣汰。
4.疊代完成之後,選取種群中最優的編碼作為網絡參數,測試資料。
code.m
function ret=Code(lenchrom,bound)
%本函數将變量編碼成染色體,用于随機初始化一個種群
% lenchrom input : 染色體長度
% bound input : 變量的取值範圍
% ret output: 染色體的編碼值
pick=rand(1,length(lenchrom));
ret=bound(:,1)'+(bound(:,2)-bound(:,1))'.*pick; %線性插值,編碼結果以實數向量存入ret中
end
fitness_fun.m
function error = fitness_fun(x,input_number,hide_number,output_number,net,input_data,output_data)
%每一個個體都有獨立的權值與偏置值組成的編碼資訊,errer評估目前個體x的适應度
%x 個體
%input_number 輸入層節點個數
%hide_number 隐層節點個數
%output_number 輸出層節點個數
%net
%input_data 資料輸入
%output_data 資料輸出
%從個體編碼資訊中得出權值與偏置值
w1 = x(1,1:input_number*hide_number);
b1 = x(1,input_number*hide_number+1:input_number*hide_number+hide_number);
w2 = x(1,input_number*hide_number+hide_number+1:input_number*hide_number+hide_number+hide_number*output_number);
b2 = x(1,input_number*hide_number+hide_number+hide_number*output_number+1:input_number*hide_number+hide_number+hide_number*output_number+output_number);
net.iw{1,1} = reshape(w1,hide_number,input_number);
net.lw{2,1} = reshape(w2,output_number,hide_number);
net.b{1} = reshape(b1,hide_number,1);
net.b{2} = reshape(b2,output_number,1);
%設定神經網絡參數
net.trainparam.epochs = 20;
net.trainparam.lr = 0.1;%learn rate
net.trainparam.goal = 0.00001;
net.trainparam.show = 100;%
net.trainparam.showWindow = 0;%
%訓練神經網絡
net = train(net,input_data,output_data);
%得出預測值
p_out = sim(net,input_data);
%計算誤差作為目前個體的适應度
error = sum(abs(output_data-p_out));
end
Select.m
function ret = Select(individuals,size)
%輪盤賭法
%individuals 種群
%size 規模大小
%個體被選中的機率
k = 10;
f = k./individuals.fitness;%
p = f./sum(f);
%定義優選序列
select_index = zeros(1,size);
for i = 1:size
p_rand = rand;%産生随機數
while(p_rand == 0)
p_rand = rand;
end
for j = 1:size
p_rand = p_rand-p(1,j);
if p_rand<0
select_index(1,i) = j;%第j個被選中
break;
end
end
end
individuals.chorm = individuals.chorm(select_index,:);%
individuals.fitness = individuals.fitness(1,select_index);
ret = individuals;
end
Cross.m
function ret = Cross(size,individuals,pcross,l)
%染色體交叉
for i = 1:size
%随機産生要交叉的兩個個體序号
index = rand(1,2);
while prod(index) == 0
index = rand(1,2);
end
index = ceil(index.*size);
%是否交叉?
p = rand;
while p == 0
p = rand;
end
if p>pcross
%選擇交叉位置
position = rand;
while position == 0
position = rand;
end
position = ceil(position*l);
%交叉
b = rand;%設定交叉權值
a_adjust = individuals.chorm(index(1,1),position)*(1-b)+individuals.chorm(index(1,2),position)*b;
b_adjust = individuals.chorm(index(1,1),position)*b+individuals.chorm(index(1,2),position)*(1-b);
individuals.chorm(index(1,1),position) = a_adjust;
individuals.chorm(index(1,2),position) = b_adjust;
end
end
ret = individuals;
end
Variation.m
function ret = Variation(size,pvariation,l,g,time,individuals,max,min)
%染色體變異
for i = 1:size
%選擇變異的個體
index = rand;
while index == 0;
index = rand;
end
index = ceil(index*size);
%是否變異
p = rand;
while p==0
p = rand;
end
if p>pvariation
%變異位置
position = rand;
while position == 0
position = rand;
end
position = ceil(position*l);
fg = rand*((1-g/time)^2);
pick = rand;
if pick>0.5
individuals.chorm(index,position) = individuals.chorm(index,position)+(individuals.chorm(index,position)-max)*fg;
else
individuals.chorm(index,position) = individuals.chorm(index,position)+(min-individuals.chorm(index,position))*fg;
end
end
end
ret = individuals;
end
測試結果:
均方誤差:
适應性值:
誤差:
更:仿真源于《MATLAB 神經網絡43個案例分析》,代碼和資料https://download.csdn.net/download/v13910/20036311,也可以去北航出版社搜這本書然後下載下傳免費資源;
pdf書有需要發郵箱;