1. 程式人生 > >Python遺傳演算法框架使用例項(二)多目標優化問題Geatpy for Python與Matlab的對比學習

Python遺傳演算法框架使用例項(二)多目標優化問題Geatpy for Python與Matlab的對比學習

在前面幾篇文章中,我們已經介紹了高效能Python遺傳和進化演算法框架——Geatpy的使用及一些案例。

本篇就一個多目標優化例項進行展開講述,並且與使用Matlab工具箱得到相近效果進行一些對比:

Geatpy已於2018.09.20更新至1.0.6版本,提供了全新的多目標進化優化的模板函式,並且解決了之前版本出現的版權問題。因此需要執行以下命令更新:

pip install --upgrade geatpy

下面對一個兩個目標的最小化問題進行求解:

先用Geatpy嘗試求解,直接套用內建的nsga2_templet進化演算法模板:

# -*- coding: utf-8 -*-
"""main.py"""
import numpy as np
import geatpy as ga

def aimfuc(x): # define the aim function
    x1 = x[:, 0]; x2 = x[:, 1]
    fun1 = x1**4-10*x1**2+x1*x2+x2**4-x1**2*x2**2
    fun2 = x2**4-x1**2*x2**2+x1**4+x1*x2
    return np.vstack([fun1, fun2]).T # 對矩陣進行轉置使得目標函式矩陣符合Geatpy資料結構

if __name__ == "__main__":
    AIM_M = __import__('main') # 獲取函式介面所在檔案的地址
    # 變數設定
    ranges = np.array([[-5, -5], [5, 5]])  # 生成自變數的範圍矩陣
    borders = np.array([[1, 1], [1, 1]])   # 生成自變數的邊界矩陣(1表示變數的區間是閉區間)
    precisions = [1, 1] # 因為變數範圍都是閉區間,而且nsga2_templet進化演算法模板採用的是實數編碼,因此precisions不起作用,隨便設定均可
    FieldDR = ga.crtfld(ranges, borders, precisions) # 生成區域描述器
    # 呼叫進化演算法模板
    [ObjV, NDSet, NDSetObjV, times] = ga.nsga2_templet(AIM_M, 'aimfuc', None, None, FieldDR, 'R', maxormin = 1, MAXGEN = 1000, MAXSIZE = 200, NIND = 200, SUBPOP = 1, GGAP = 1, selectStyle = 'tour', recombinStyle = 'xovdp', recopt = 0.9, pm = 0.6, distribute = True, drawing = 1)
    

執行結果:

這裡設定了MAXSIZE為200,表示當搜尋到的帕累託前沿點超過200個時就停止搜尋。設定進化最大代數為1000,種群規模為200。這裡是為了和後面的Matlab程式碼設定一樣,實際上Geatpy的nsga2演算法模板不需要很大的種群規模。並且,由於nsga2演算法是將父子兩代合併進行進化選擇的,因此變異概率可以設定大一些,不會對影響演算法的收斂性產生太大影響。

problem = 'R'是nsga2_templet演算法模板的一個輸入引數,表示當前問題是一個連續性問題;假若研究離散性問題,那麼problem = 'I'。maxormin也是一個輸入引數,其值為1表示當前是最小化目標;若改成-1,則表示這是一個最大化目標的優化問題。最後的drawing = 1表示只輸出最後結果的圖片;若設為0,表示不進行繪圖;若設為2,程式將繪製帕累託非支配解集的搜尋過程的動畫。

當前Geatpy內建的nsga2_templet演算法模板中並沒有嚴格約束帕累託解的均勻分佈,在後面的版本中將提供一些帕累託前沿嚴格均分的演算法模板。nsga2的演算法模板原始碼可以參見:

下面將用Matlab的遺傳演算法工具箱進行對比實驗:

clc,clear
% 定義目標函式
fun1 = @(x) x(1)^4-10*x(1)^2+x(1)*x(2)+x(2)^4-x(1)^2*x(2)^2; %min f1(x1,x2)
fun2 = @(x) x(2)^4-x(1)^2*x(2)^2+x(1)^4+x(1)*x(2); %min f2(x1,x2)

aimfuc = @(x) [fun1(x) fun2(x)]; %獲取目標函式控制代碼
nvars=2;      %變數個數
lb=[-5,-5];   %下限
ub=[5,5];     %上限
A=[];b=[];    %線性不等式約束
Aeq=[];beq=[];%線性等式約束
tic           %開始計時
options=gaoptimset('paretoFraction',1,'populationsize',200,'generations',1000,'stallGenLimit',200,'TolFun',1e-100);
[x,fval] = gamultiobj(aimfuc,nvars,A,b,Aeq,beq,lb,ub,options);
time = toc    %結束計時
plot(fval(:,1),fval(:,2),'k.') %繪圖
fprintf('找到的前沿點數: %d\n', size(fval,1));
fprintf('平均每秒找到的前沿點數: %f\n', size(fval,1)/time);

執行結果如下:

對比發現Geatpy的效率比Matlab高出不少。嘗試增大所需要搜尋的帕累託前沿點的數量,Matlab變慢了一個數量級,而Geatpy的耗時基本穩定。

在Matlab的遺傳演算法工具箱中,是通過種群規模和"paretoFraction"的引數來控制帕累托最優解的數量的。當需要搜尋大量的帕累托最優解時,Matlab的遺傳演算法工具箱就會變得極慢。這是因為種群規模太大的緣故。而Geatpy很好地解決了這個問題。Geatpy的許多進化演算法模板都是採用一個全域性帕累托最優解集來指導搜尋過程的,種群規模不會因需要搜尋更多的解而爆炸性增長。

Geatpy核心呼叫的是高效能mkl矩陣庫,因此執行速度極快。

除了nsga-II演算法外,Geatpy還支援適應性權法重法(awGA)、隨機權重法(rwGA)、互動式適應性權重法(i-awGA)、基於快速非支配排序的多目標進化優化演算法。相應的演算法均整合在演算法模板內,原始碼參見:

仔細研究Geatpy的模板函式發現,這些內建的模板函式為了相容多種情況,設定了較多的if語句去判定。因此,假如要達到更高的效能,可以模仿這些模板自定義一些新的模板。在前面的文章中我也初步談到如何自定義進化演算法模板。在下一篇,我將更加詳細地講解怎樣把自創的多目標進化演算法寫成一個進化演算法模板。歡迎繼續跟進,感謝!