Python優(yōu)化算法之遺傳算法案例代碼
一、前言
優(yōu)化算法,尤其是啟發(fā)式的仿生智能算法在最近很火,它適用于解決管理學(xué),運(yùn)籌學(xué),統(tǒng)計(jì)學(xué)里面的一些優(yōu)化問(wèn)題。比如線性規(guī)劃,整數(shù)規(guī)劃,動(dòng)態(tài)規(guī)劃,非線性約束規(guī)劃,甚至是超參數(shù)搜索等等方向的問(wèn)題。
但是一般的優(yōu)化算法還是matlab里面用的多,Python相關(guān)代碼較少。
我在參考了一些文章的代碼和模塊之后,決定學(xué)習(xí)scikit-opt
這個(gè)模塊。這個(gè)優(yōu)化算法模塊對(duì)新手很友好,代碼簡(jiǎn)潔,上手簡(jiǎn)單。而且代碼和官方文檔是中國(guó)人寫(xiě)的,還有很多案例,學(xué)起來(lái)就沒(méi)什么壓力。
缺點(diǎn)是包裝的算法種類(lèi)目前還不算多,只有七種:(差分進(jìn)化算法、遺傳算法、粒子群算法、模擬退火算法、蟻群算法、魚(yú)群算法、免疫優(yōu)化算法)
本次帶來(lái)的是數(shù)學(xué)建模里面經(jīng)常使用的遺傳算法的使用演示。
二、安裝
首先安裝模塊,在cmd
里面或者anaconda prompt
里面輸入:
pip install scikit-opt
對(duì)于當(dāng)前開(kāi)發(fā)人員版本:
git clone git@github.com:guofei9987/scikit-opt.git cd scikit-opt pip install .
三、遺傳算法
3.1 自定義函數(shù)
UDF(用戶定義函數(shù))現(xiàn)已推出!
例如,您剛剛制定了一種新型函數(shù)?,F(xiàn)在,你的函數(shù)是這樣的:
該函數(shù)有大量的局部最小值,具有很強(qiáng)的沖擊力,在(0,0) 處的全局最小值,值為 0。
import numpy as np def schaffer(p): x1, x2 = p x = np.square(x1) + np.square(x2) return 0.5 + (np.square(np.sin(x)) - 0.5) / np.square(1 + 0.001 * x)
導(dǎo)入和構(gòu)建 ga :(遺傳算法)
from sko.GA import GA ga = GA(func=schaffer, n_dim = 2, size_pop = 100, max_iter = 800, prob_mut = 0.001, lb = [-1, -1], ub = [1, 1], precision = 1e-7) best_x, best_y = ga.run() print('best_x:', best_x, '\n', 'best_y:', best_y)
運(yùn)行結(jié)果為:
可以看到基本找到了全局最小值和對(duì)應(yīng)的x 。
畫(huà)出迭代次數(shù)的圖:
import pandas as pd import matplotlib.pyplot as plt Y_history = pd.DataFrame(ga.all_history_Y) fig, ax = plt.subplots(2, 1) ax[0].plot(Y_history.index, Y_history.values, '.', color = 'red') Y_history.min(axis = 1).cummin().plot(kind = 'line') plt.show()
GA算法的參數(shù)詳解:
輸入?yún)?shù):
輸入?yún)?shù) | 默認(rèn)值 | 參數(shù)的意義 |
---|---|---|
func | - | 目標(biāo)函數(shù) |
n_dim | - | 目標(biāo)函數(shù)的維度 |
size_pop | 50 | 種群規(guī)模 |
max_iter | 200 | 最大迭代次數(shù) |
prob_mut | 0.001 | 變異概率 |
lb | -1 | 每個(gè)自變量的最小值 |
ub | 1 | 每個(gè)自變量的最大值 |
constraint_eq | 空元組 | 等式約束 |
constraint_ueq | 空元組 | 不等式約束 |
precision | 1e-7 | 精確度,int / float或者它們組成的列表 |
輸出參數(shù):
GA & GA_TSP
輸出參數(shù) | 參數(shù)的意義 |
---|---|
ga.generation_best_X | 每一代的最優(yōu)函數(shù)值對(duì)應(yīng)的輸入值 |
ga.generation_best_Y | 每一代的最優(yōu)函數(shù)值 |
ga.all_history_FitV | 每一代的每個(gè)個(gè)體的適應(yīng)度 |
ga.all_history_Y | 每一代每個(gè)個(gè)體的函數(shù)值 |
3.2 遺傳算法進(jìn)行整數(shù)規(guī)劃
在多維優(yōu)化時(shí),想讓哪個(gè)變量限制為整數(shù),就設(shè)定 precision 為 整數(shù) 即可。
例如,我想讓我的自定義函數(shù)的某些變量限制為整數(shù)+浮點(diǎn)數(shù)(分別是整數(shù),整數(shù),浮點(diǎn)數(shù)),那么就設(shè)定 precision=[1, 1, 1e-7]
例子如下:
from sko.GA import GA demo_func = lambda x: (x[0] - 1) ** 2 + (x[1] - 0.05) ** 2 + x[2] ** 2 ga = GA(func = demo_func, n_dim = 3, max_iter = 500, lb = [-1, -1, -1], ub = [5, 1, 1], precision = [1,1,1e-7]) best_x, best_y = ga.run() print('best_x:', best_x, '\n', 'best_y:', best_y)
可以看到第一個(gè)、第二個(gè)變量都是整數(shù),第三個(gè)就是浮點(diǎn)數(shù)了 。
3.3 遺傳算法用于旅行商問(wèn)題
商旅問(wèn)題(TSP)就是路徑規(guī)劃的問(wèn)題,比如有很多城市,你都要跑一遍,那么先去哪個(gè)城市再去哪個(gè)城市可以讓你的總路程最小。
實(shí)際問(wèn)題需要一個(gè)城市坐標(biāo)數(shù)據(jù),比如你的出發(fā)點(diǎn)位置為(0,0),第一個(gè)城市離位置為 ( x 1 , y 1 ) (x_1,y_1) (x1?,y1?),第二個(gè)為 ( x 2 , y 2 ) (x_2,y_2) (x2?,y2?)…這里沒(méi)有實(shí)際數(shù)據(jù),就直接隨機(jī)生成了。
import numpy as np from scipy import spatial import matplotlib.pyplot as plt num_points = 50 points_coordinate = np.random.rand(num_points, 2) # generate coordinate of points points_coordinate
這里定義的是50個(gè)城市,每個(gè)城市的坐標(biāo)都在是上圖隨機(jī)生成的矩陣。
然后我們把它變成類(lèi)似相關(guān)系數(shù)里面的矩陣:
distance_matrix = spatial.distance.cdist(points_coordinate, points_coordinate, metric='euclidean') distance_matrix.shape
(50, 50)
這個(gè)矩陣就能得出每個(gè)城市之間的距離,算上自己和自己的距離(0),總共有2500個(gè)數(shù)。
定義問(wèn)題:
def cal_total_distance(routine): num_points, = routine.shape return sum([distance_matrix[routine[i % num_points], routine[(i + 1) % num_points]] for i in range(num_points)])
求解問(wèn)題:
from sko.GA import GA_TSP ga_tsp = GA_TSP(func = cal_total_distance, n_dim = num_points, size_pop = 50, max_iter = 500, prob_mut = 1) best_points, best_distance = ga_tsp.run()
我們展示一下結(jié)果:
best_distance
畫(huà)圖查看計(jì)算出來(lái)的路徑,還有迭代次數(shù)和y的關(guān)系:
fig, ax = plt.subplots(1, 2,figsize = (12, 8)) best_points_ = np.concatenate([best_points, [best_points[0]]]) best_points_coordinate = points_coordinate[best_points_, :] ax[0].plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r') ax[1].plot(ga_tsp.generation_best_Y) plt.show()
3.4 使用遺傳算法進(jìn)行曲線擬合
構(gòu)建數(shù)據(jù)集:
import numpy as np import matplotlib.pyplot as plt from sko.GA import GA x_true = np.linspace(-1.2, 1.2, 30) y_true = x_true ** 3 - x_true + 0.4 * np.random.rand(30) plt.plot(x_true, y_true, 'o')
構(gòu)建的數(shù)據(jù)是 y = x 3 − x + 0.4 y=x^3-x+0.4 y=x3−x+0.4,然后加上了隨機(jī)擾動(dòng)項(xiàng)。如圖:
定義需要擬合的函數(shù)(三次函數(shù)),然后將殘差作為目標(biāo)函數(shù)去求解:
def f_fun(x, a, b, c, d): return a * x ** 3 + b * x ** 2 + c * x + d #三次函數(shù) def obj_fun(p): a, b, c, d = p residuals = np.square(f_fun(x_true, a, b, c, d) - y_true).sum() return residuals
求解:
ga = GA(func = obj_fun, n_dim = 4, size_pop = 100, max_iter = 500, lb = [-2] * 4, ub = [2] * 4) best_params, residuals = ga.run() print('best_x:', best_params, '\n', 'best_y:', residuals)
可以看到擬合出來(lái)的方程為 y = 0.9656 x 3 − 0.0065 x 2 − 1.0162 x + 0.2162 y=0.9656x^{3}-0.0065x^{2}-1.0162x+0.2162 y=0.9656x3−0.0065x2−1.0162x+0.2162
畫(huà)出擬合線:
y_predict = f_fun(x_true, *best_params) fig, ax = plt.subplots() ax.plot(x_true, y_true, 'o') ax.plot(x_true, y_predict, '-') plt.show()
到此這篇關(guān)于Python優(yōu)化算法—遺傳算法的文章就介紹到這了,更多相關(guān)Python遺傳算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pygame實(shí)戰(zhàn)之經(jīng)典泡泡龍小游戲
Python版的消除類(lèi)的游戲還是很多的,今天就出一個(gè)消除類(lèi)——泡泡龍小游戲。文中的示例代碼很詳細(xì),感興趣的小伙伴快來(lái)跟隨小編一起學(xué)習(xí)一下吧2021-12-12Playwright元素截圖并保存至allure的實(shí)現(xiàn)示例
在UI自動(dòng)化測(cè)試中,我們經(jīng)常需要獲取屏幕截圖,本文就介紹一下Playwright元素截圖并保存至allure的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12夯實(shí)基礎(chǔ)python集合的應(yīng)用場(chǎng)景及字符串定義和表示
這篇文章主要為大家介紹了python集合的應(yīng)用場(chǎng)景及字符串定義和表示,來(lái)幫大家夯實(shí)基礎(chǔ),有需要的朋友可以借鑒參考下,希望能夠有所幫助2023-10-10Python實(shí)現(xiàn)將圖片轉(zhuǎn)換為ASCII字符畫(huà)
這篇文章主要介紹了Python實(shí)現(xiàn)將圖片轉(zhuǎn)換為ASCII字符畫(huà),要將圖片轉(zhuǎn)換為字符圖其實(shí)很簡(jiǎn)單,我們首先將圖片轉(zhuǎn)換為灰度圖像,這樣圖片的每個(gè)像素點(diǎn)的顏色值都是0到255,然后我們選用一些在文字矩形框內(nèi)占用面積從大到小的ASCII碼字符2022-08-08