生活随笔
收集整理的這篇文章主要介紹了
NSGA2算法详解
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
目錄
預(yù)備知識(shí)多目標(biāo)優(yōu)化問(wèn)題的解NSGA-II 簡(jiǎn)介快速非支配排序擁擠度精英策略部分代碼展示
1.預(yù)備知識(shí)
多目標(biāo)優(yōu)化的相關(guān)知識(shí):https://blog.csdn.net/haha0332/article/details/88634378
支配:假設(shè)小明9歲,50斤,小紅8歲,45斤,小明無(wú)論是歲數(shù)還是體重都比小紅大,所以小明支配小紅。
互不支配:假設(shè)小明7歲,50斤,小紅8歲,45斤,小明歲數(shù)比小紅小,但體重比小紅大,所以小明和小紅互不支配。
帕累托集:在這個(gè)集合中,任意兩個(gè)解互不支配。
非支配排序:將一組解分成n個(gè)集合:rank1,rank2…rankn,每個(gè)集合中所有的解都互不支配,但ranki中的任意解支配rankj中的任意解(i<j).
2.多目標(biāo)優(yōu)化問(wèn)題的解
在單目標(biāo)優(yōu)化問(wèn)題中,通常最優(yōu)解只有一個(gè),而且能用比較簡(jiǎn)單和常用的數(shù)學(xué)方法求出其最優(yōu)解。而在多目標(biāo)優(yōu)化問(wèn)題中,各個(gè)目標(biāo)之間相互制約,可能使得一個(gè)目標(biāo)性能的改善往往是以損失其他目標(biāo)性能為代價(jià),不可能存在一個(gè)使所有目標(biāo)性能都達(dá)到最優(yōu)的解(這就意味著這兩個(gè)目標(biāo)可能存在較大的負(fù)相關(guān)性),所以對(duì)于多目標(biāo)優(yōu)化問(wèn)題,其解通常是一個(gè)非劣解的集合–帕累托解集。
在存在多個(gè)帕累托最優(yōu)解的情況下,如果沒(méi)有關(guān)于問(wèn)題更多的信息,那么很難選擇哪個(gè)解更可取,因此所有的帕累托最優(yōu)解都可以被認(rèn)為使同等重要的。由此可知,對(duì)于多目標(biāo)優(yōu)化問(wèn)題,最重要的任務(wù)使找到盡可能多的關(guān)于該優(yōu)化問(wèn)題的帕累托最優(yōu)解。因而,在多目標(biāo)優(yōu)化中主要完成以下兩個(gè)任務(wù):
(1)找到一組盡可能接近帕累托最優(yōu)域的解
(2)找到一組盡可能不同的解
第一個(gè)任務(wù)使在任何優(yōu)化工作中都必須做到的,收斂不到接近真正帕累托最優(yōu)解集的解是不可取的,只有當(dāng)一組解收斂到接近真正帕累托最優(yōu)解,才能確保該組解近似最優(yōu)的這一特性。
除了要求優(yōu)化問(wèn)題的解要收斂到近似帕累托最優(yōu)域,求得的解也必須均勻的分布在帕累托最優(yōu)域上。一組在多個(gè)目標(biāo)之間好的協(xié)議解是建立在一組多樣解的基礎(chǔ)上。簡(jiǎn)單來(lái)說(shuō)就是一組解中的差異性越大,這組解視為越好。
3.NSGA2算法的簡(jiǎn)介
多目標(biāo)遺傳算法是用來(lái)分析和解決多目標(biāo)優(yōu)化問(wèn)題的一種進(jìn)化算法,其核心就是協(xié)調(diào)各個(gè)目標(biāo)函數(shù)之間的關(guān)系,找出使得各個(gè)目標(biāo)函數(shù)都盡可能達(dá)到比較大的(或者比較小的)函數(shù)值的最優(yōu)解集。在眾多目標(biāo)優(yōu)化的遺傳算法中,NSGA2算法是影響最大和應(yīng)用范圍最廣的一種多目標(biāo)遺傳算法。在其出現(xiàn)后,由于它簡(jiǎn)單有效以及比較明顯的優(yōu)越性,使得該算法已經(jīng)成為多目標(biāo)優(yōu)化問(wèn)題中的基本算法之一。
介紹NSGA2,首先來(lái)介紹以下NSGA算法。
NSGA通過(guò)基于非支配排序的方法保留了種群中的優(yōu)良個(gè)體,并且利用適應(yīng)度共享函數(shù)保持了群體的多樣性,取得了非常良好的效果。但實(shí)際工程領(lǐng)域中發(fā)現(xiàn)NSGA算法存在明顯不足,這主要體現(xiàn)在如下3個(gè)方面:
(1)非支配排序的高計(jì)算復(fù)雜性。非支配排序算法一般要進(jìn)行mN^3次搜索(m是目標(biāo)函數(shù)的數(shù)目,體重和年齡可以被視為兩個(gè)目標(biāo)函數(shù),N是一組解的大小),搜索的次數(shù)隨著目標(biāo)函數(shù)數(shù)量和種群大小的增加而增多。
(2)缺少精英策略。研究結(jié)果表明,引用精英策略可以加快遺傳算法的執(zhí)行,并且還助于防止優(yōu)秀的個(gè)體丟失。
(3)需要指定共享參數(shù)share,在NSGA算法中保持種群和解的多樣性方法都是依賴于共享的概念,共享的主要問(wèn)題之一就是需要人為指定一個(gè)共享參數(shù)share。
為了克服非支配排序遺傳算法(NSGA)的上述不足,印度科學(xué)家Deb于2002年在NSGA算法的基礎(chǔ)上進(jìn)行了改進(jìn),提出了帶精英策略的非支配排序遺傳算法(Elitist Non-Dominated Sorting Genetic Algorithm,NSGA-II),NSGA-II 算法針對(duì)NSGA的缺陷通過(guò)以下三個(gè)方面進(jìn)行了改進(jìn)[16]:
提出了快速非支配的排序算法,降低了計(jì)算非支配序的復(fù)雜度,使得優(yōu)化算法的復(fù)雜度由原來(lái)的 降為 ( 為目標(biāo)函數(shù)的個(gè)數(shù), 為種群的大小)。引入了精英策略,擴(kuò)大了采樣空間。將父代種群與其產(chǎn)生的子代種群組合在一起,共同通過(guò)競(jìng)爭(zhēng)來(lái)產(chǎn)生下一代種群,這有利于是父代中的優(yōu)良個(gè)體得以保持,保證那些優(yōu)良的個(gè)體在進(jìn)化過(guò)程中不被丟棄,從而提高優(yōu)化結(jié)果的準(zhǔn)確度。并且通過(guò)對(duì)種群所有個(gè)體分層存放,使得最佳個(gè)體不會(huì)丟失,能夠迅速提高種群水平。引入擁擠度和擁擠度比較算子,這不但克服了NSGA算法中需要人為指定共享參數(shù) 的缺陷,而且將擁擠度作為種群中個(gè)體之間的比較準(zhǔn)則,使得準(zhǔn)Pareto域中的種群個(gè)體能均勻擴(kuò)展到整個(gè)Pareto域,從而保證了種群的多樣性。
4.快速非支配排序
在NSGA算法中采用的是非支配排序方法,該方法的計(jì)算復(fù)雜度是O( mN^3),而在NSGA-II算法中采用快速非支配排序的方法,其計(jì)算復(fù)雜度僅O(mN2)。下面,簡(jiǎn)要說(shuō)明二者計(jì)算復(fù)雜度的由來(lái):
(1) 非支配排序算法的計(jì)算復(fù)雜度:
為了對(duì)優(yōu)化對(duì)象的個(gè)數(shù)為m,種群規(guī)模大小為N的種群進(jìn)行非支配排序,每一個(gè)個(gè)體都必須和種群中其它的個(gè)體進(jìn)行比較,從而得出該個(gè)體是否被支配,這樣每個(gè)個(gè)體就總共需要 次的比較,需要O(mN )的計(jì)算復(fù)雜度。當(dāng)這一步驟完成之后,繼續(xù)找出第一個(gè)非支配層上的所有個(gè)體,這需要遍歷整個(gè)種群,其總的計(jì)算復(fù)雜度就是O( mN^2)。在這一步中,所有在第一個(gè)非支配層中的個(gè)體都被尋找到,為了找到隨后各個(gè)等級(jí)中的個(gè)體,重復(fù)前面的操作。可以看到,在最壞的情況下(每一層級(jí)上只有一個(gè)個(gè)體),完成對(duì)整個(gè)種群所有個(gè)體的分級(jí),這種算法的計(jì)算復(fù)雜度為O( mN3)。
(2) 快速非支配排序算法的計(jì)算復(fù)雜度:
對(duì)于種群中每一個(gè)個(gè)體 i,都設(shè)有兩個(gè)參數(shù)ni和Si,ni是種群中支配個(gè)體i的解的個(gè)體數(shù)量,Si是被個(gè)體i 支配的解的個(gè)體的集合。
找出種群中所有ni=0的個(gè)體,將它們存入當(dāng)前非支配集合rank1中;對(duì)于當(dāng)前非支配集合rank1中的每一個(gè)個(gè)體 j,遍歷它所支配的個(gè)體集合Sj,將集合Sj中每一個(gè)個(gè)體 t的 nt都減去1,即支配個(gè)體t的解的個(gè)體數(shù)量減1(因?yàn)橹鋫€(gè)體 的個(gè)體j已經(jīng)存入當(dāng)前非支配集 中),如果 nt-1=0,則將個(gè)體t存入另一個(gè)集H;把rank1作為第一級(jí)非支配個(gè)體的集合,所以在rank1中的解個(gè)體是最優(yōu)的。它只支配個(gè)體,而不受其他任何個(gè)體所支配,對(duì)該集合內(nèi)所有個(gè)體都賦予相同的非支配序 ,然后繼續(xù)對(duì)集合H作上述分級(jí)操作,并也賦予相應(yīng)的非支配序,直到所有的個(gè)體都被分級(jí),即都被賦予賦予相應(yīng)的非支配序。
每一次迭代操作,即上述快速非支配排序算法步驟的1)和2)需要N次計(jì)算。于是,整個(gè)迭代過(guò)程的計(jì)算復(fù)雜度最大是N^2。這樣,整個(gè)快速非支配排序算法的計(jì)算復(fù)雜度就是: mN2
5.擁擠度
手打好痛苦,還有各種公式不讓我打,直接用word打了復(fù)制上來(lái)吧。
6.精英策略
NSGA-II算法引入了精英策略,以防止在種群的進(jìn)化過(guò)程中優(yōu)秀個(gè)體的流失,通過(guò)將父代種群與其產(chǎn)生的子代種群混合后進(jìn)行非支配排序的方法,能夠有較好地避免父代種群中優(yōu)秀個(gè)體的流失。精英策略的執(zhí)行步驟如圖3-2所示:
**7.部分代碼展示**
```java
/** nsga2的選擇部分*/public static Population nsga2(Population father, Population child) { // 兩代種群的所有個(gè)體都參與篩選HashMap<Integer, Individual> fatherAndChild = new HashMap<Integer, Individual>();//father.map放入的是父代的所有個(gè)體fatherAndChild.putAll(father.map);Population.MAXSIZE是該種群的最大大小for (int i = 0; i < Population.MAXSIZE; i++) {//父代和子代一起進(jìn)行篩選fatherAndChild.put(i + father.map.size(), child.map.get(i));}// 對(duì)每個(gè)個(gè)體進(jìn)行處理,找出被它支配和支配它的個(gè)體fatherAndChild.forEach((key,in)->{//n是該個(gè)體被多少個(gè)體支配in.n=0;//dominate是該個(gè)體支配多少個(gè)體in.dominate.clear();});fatherAndChild.forEach((key1,in)->{fatherAndChild.forEach((key, o) -> {if (((in.fitness1 < o.fitness1) && (in.fitness2 <o.fitness2))||((in.fitness1 <=o.fitness1) && (in.fitness2 < o.fitness2))||((in.fitness1 < o.fitness1) && (in.fitness2 <= o.fitness2)))// 找出in支配的個(gè)體放入dominate中{in.dominate.add(o); }elseif (((in.fitness1 > o.fitness1) && (in.fitness2 > o.fitness2))||((in.fitness1 >= o.fitness1) && (in.fitness2 > o.fitness2))||((in.fitness1 > o.fitness1) && (in.fitness2 >= o.fitness2)))// 碰上一個(gè)支配in的個(gè)體就++n{in.n++;}});});ArrayList<ArrayList<Individual>> rank = new ArrayList<ArrayList<Individual>>();// 對(duì)種群進(jìn)行分級(jí)別// 外層的ArrayList是存放每一個(gè)rank,內(nèi)層的ArrayList是存放該rank對(duì)應(yīng)的個(gè)體while (!fatherAndChild.isEmpty())// 本函數(shù)將所有個(gè)體進(jìn)行分級(jí),分級(jí)后放入rank數(shù)組中{ArrayList<Individual> po = new ArrayList<Individual>();// 用來(lái)存放第x rank的個(gè)體,這里的x是while的第x個(gè)循環(huán)for (int i = 0; i < Population.MAXSIZE * 2; i++)// 對(duì)哈希表中的每個(gè)個(gè)體進(jìn)行遍歷{Individual indi = fatherAndChild.get(i);if (indi == null)continue;if (indi.n == 0)// 如果發(fā)現(xiàn)該個(gè)體的n為0,即沒(méi)有支配該個(gè)體的其他個(gè)體{po.add(indi);// 將該個(gè)體放入第n rank的集合中fatherAndChild.remove(i);// 把該個(gè)體從哈希表中去除// for (Individual in : indi.dominate) {
// --in.n;
// }}}for(Individual indi:po)for(Individual in:indi.dominate){in.n--;}rank.add(po);// 該rank的所有個(gè)體都放入ArrayList后將該ArrayList放入對(duì)應(yīng)rank的位置}// int t=0;
// for(ArrayList<Individual> arr:rank)
// {
// System.out.println(++t);
// for(Individual indi:arr)
// {
// System.out.println(indi.fitness1+" "+indi.fitness2);
// }
// }// 查找哪個(gè)rank放入新生一代之后會(huì)超出MAXSIZEint num = Population.MAXSIZE;int index = 0;// 這是用來(lái)指示第幾rank的while (true) {if (num - rank.get(index).size() > 0) {num = num - rank.get(index).size();++index;} else {break;}}// 找出該rankArrayList<Individual> po = rank.get(index);//System.out.println("最后一層有"+po.size()+"個(gè)");// 對(duì)該rank根據(jù)fitness1的大小進(jìn)行排序,根據(jù)fitness2也可以po.sort((Individual o1, Individual o2) -> { // TODO Auto-generated method stub
// int i = o1.fitness1 > o2.fitness1 ? 1 : -1;
// return i;if(o1.fitness1>o2.fitness1) return 1;else if(o1.fitness1<o2.fitness1)return -1;return 0;});//歸一化double fitness1sum=0,fitness2sum=0;int numSum=0;for(Individual o:po){fitness1sum+=o.fitness1;fitness2sum+=o.fitness2;numSum+=o.uav.size();}// 對(duì)該rank的每一個(gè)個(gè)體計(jì)算其distancefor (int i = 0; i < po.size(); i++) {if (i == 0 || i == po.size() - 1) {po.get(i).distance = (float) Double.MAX_VALUE;} else {po.get(i).distance = (float) (Math.abs((po.get(i - 1).fitness1 - po.get(i + 1).fitness1)/fitness1sum)+ Math.abs(po.get(i - 1).fitness2 - po.get(i + 1).fitness2)/fitness2sum);}}// 對(duì)該rank根據(jù)distance大小進(jìn)行排序po.sort((Individual o1, Individual o2) -> {// TODO Auto-generated method stub
// int i = o1.distance > o2.distance ? -1 : 1;
// return i;if(o1.distance>o2.distance)return -1;else if(o1.distance<o2.distance)return 1;return 0;});// 將所有選中的個(gè)體放入新的ArrayList中ArrayList<Individual> newpo = new ArrayList<Individual>();for (int i = 0; i < index; i++) {newpo.addAll(rank.get(i));}// 同上for (int i = 0; i < num; i++) {newpo.add(po.get(i));}//System.out.println("放入"+num+"個(gè)");// 創(chuàng)建一個(gè)種群,將剛才篩選出的所有個(gè)體作為該種群的組成部分Population pp = new Population();for (int i = 0; i < Population.MAXSIZE; i++) {pp.map.put(i, newpo.get(i));}return pp;// 返回該種群}
總結(jié)
以上是生活随笔為你收集整理的NSGA2算法详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。