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