記事ディレクトリ
序文
この記事は、インテリジェント アルゴリズム (Python 再現)コラムの 4 回目の記事であり、主に粒子群最適化アルゴリズムとシミュレーテッド アニーリング アルゴリズムを組み合わせて、それぞれのアルゴリズムの欠点を補う方法を紹介します。
前回のブログ【インテリジェントアルゴリズムシリーズの粒子群最適化アルゴリズム】では、粒子を更新した後に得られた新しい粒子などを、シミュレーテッドアニーリングの考え方を用いて次の粒子群を受け入れるかどうかを決定するハイブリッド粒子群最適化アルゴリズムを紹介しました。世代の反復。ただし、この記事はハイブリッド粒子群最適化アルゴリズムとみなすことができ、シミュレーテッド アニーリング アルゴリズムを粒子群最適化アルゴリズムに適用するのではなく、粒子群最適化をシミュレート アニーリング アルゴリズムに適用することに焦点を当てています。
1. アイデアとアルゴリズムを組み合わせる
このブログ「インテリジェントアルゴリズムシリーズのシミュレーテッドアニーリングアルゴリズム」で紹介しているシミュレーテッドアニーリングアルゴリズムは最適化が可能で、例えば初期解の選択においてデフォルトではランダムに解が初期解として選択されるため、次のようなアイデアを思いつきまし た。初期解が局所最適解であり、これに基づいてシミュレーテッド アニーリング アルゴリズムが適用される場合、結果はランダムな初期解よりも確実に優れたものになります。
初期解と局所最適解を選択するにはどうすればよいですか? アルゴリズムは多数ありますが、遺伝的アルゴリズムと前に紹介した粒子群最適化アルゴリズムの両方を使用できます。この記事では粒子群最適化を使用して初期解を選択します。
将来的には、初期解を選択するための遺伝的アルゴリズムの使用についてもこの記事で更新する予定ですが、このアルゴリズムの記事を更新する予定はありません。詳細については、 IALibライブラリ コード を参照してください。
上で述べたように、この記事では各世代(この場合は混合粒子群)にシミュレーテッド アニーリング アルゴリズムを適用しませんが、次のようになります。
2. 問題のシナリオ
これは依然として最大値問題ですが、元の単項関数の最大値問題は二項関数の最大値問題に置き換えられています [主に視覚化の便宜のため、複雑さはそれほど増加していません]。今回は、3 つの古典的な関数の最大値が解決されます。
2.1 球体
f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2f ( x ,y )=バツ2+y2
2.2 スカイブルー
f ( x , y ) = ( x 2 + y − 11 ) 2 + ( x + y 2 − 7 ) 2 f(x, y) = (x^2 + y - 11)^2 + (x + y^ 2 - 7)^2f ( x ,y )=( ×2+y−11 )2+( ×+y2−7 )2
2.3 アクリー
f ( x , y ) = − a ∗ exp [ − bx 2 + y 2 2 ] − exp [ cos ( cx ) + cos ( cy ) 2 ] + a + ef(x, y) = -a * exp\bigg [{ -b\sqrt{\frac {x^2 + y^2} {2}} }\bigg] -exp\bigg[ \frac {cos(cx) + cos(cy)} {2} \bigg] + a + ef ( x ,y )=− _∗e x p [ − b2バツ2+y2】−e × p [2cos ( c x )+cos ( cy )】+ある+e 其中, a = 20 , b = 0.2 , c = 2 π , e = 2.71282 a=20, b=0.2, c=2\pi, e=2.71282 ある=20 、b=0.2 、c=2P 、_e=2.71282。
2.4 機能の可視化
# -*- coding:utf-8 -*-
# Author: xiayouran
# Email: [email protected]
# Datetime: 2023/3/30 14:22
# Filename: visu_func.py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
class Visu3DFunc(object):
def __init__(self, func_name='Sphere'):
self.func_name = func_name
self.X = np.linspace(-5, 5, num=200)
self.Y = np.linspace(-5, 5, num=200)
@classmethod
def sphere(cls, x, y):
"""Sphere"""
return x**2 + y**2
@classmethod
def himmelblau(cls, x, y):
"""Himmelblau"""
return (x**2 + y - 11)**2 + (x + y**2 - 7)**2
@classmethod
def ackley(cls, x, y, a=20, b=0.2, c=2*np.pi):
"""Ackley"""
term1 = -a * np.exp(-b * np.sqrt((x**2 + y**2)/2))
term2 = -np.exp((np.cos(c*x) + np.cos(c*y))/2)
return term1 + term2 + a + np.exp(1)
def draw(self):
fig = plt.figure()
# ax = fig.gca(projection='3d')
ax = Axes3D(fig)
X, Y = np.meshgrid(self.X, self.Y)
if self.func_name == 'Sphere':
Z = self.sphere(X, Y)
elif self.func_name == 'Himmelblau':
Z = self.himmelblau(X, Y)
else:
Z = self.ackley(X, Y)
ax.plot_surface(X, Y, Z, cmap=plt.cm.cool)
ax.contour(X, Y, Z, levels=5, offset=0)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('{} Function'.format(self.func_name))
# ax.scatter3D(0, 0, self.sphere(0, 0), s=100, lw=0, c='green', alpha=0.7)
plt.savefig(self.func_name)
plt.show()
if __name__ == '__main__':
# Sphere, Himmelblau, Ackley
visu_obj = Visu3DFunc(func_name='Sphere')
visu_obj.draw()
3. アルゴリズムの実装
# -*- coding:utf-8 -*-
# Author: xiayouran
# Email: [email protected]
# Datetime: 2023/3/30 15:50
# Filename: pso_saa.py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from IALib.base_algorithm import BaseAlgorithm
from IALib.particle_swarm_optimization import ParticleSwarmOptimization, Particle
from IALib.simulate_anneal_algorithm import SimulateAnnealAlgorithm
from IALib.mixup.visu_func import Visu3DFunc
__all__ = ['PSO_SAA']
class PSO_SAA(BaseAlgorithm):
def __init__(self, population_size=100, p_dim=1, v_dim=1, max_iter=500, x_range=(0, 5),
t_max=1.0, t_min=1e-3, coldrate=0.9, seed=10086):
super(PSO_SAA, self).__init__()
self.__population_size = population_size # 种群大小
self.__p_dim = p_dim # 粒子位置维度
self.__v_dim = v_dim # 粒子速度维度
self.__max_iter = max_iter # 最大迭代次数
self.__t_max = t_max # 初始温度
self.__t_min = t_min # 终止温度
self.__coldrate = coldrate # 降温速率
self.saa_best_particle = None # 模拟退火算法得到的最优解
self.best_particle = None # 最优解
self.__x_range = x_range
self.__seed = seed
self.optimal_solution = None
np.random.seed(self.__seed)
def problem_function(self, x):
if self.__p_dim == 1:
return super().problem_function(x)
else:
return Visu3DFunc.sphere(*x)
def solution(self):
# PSO
algo_pso = ParticleSwarmOptimization(population_size=self.__population_size,
p_dim=self.__p_dim, v_dim=self.__v_dim,
max_iter=self.__max_iter, x_range=self.__x_range)
algo_pso.solution()
# SAA
x = algo_pso.global_best_particle.best_position # 初始解
while self.__t_max > self.__t_min:
for _ in range(self.__max_iter):
x_new = np.clip(x + np.random.randn(), a_min=self.__x_range[0], a_max=self.__x_range[1])
delta = self.problem_function(x_new) - self.problem_function(x) # 计算目标函数的值差
if delta < 0: # 局部最优解
x = x_new # 直接接受更优解
else:
p = np.exp(-delta / self.__t_max) # 粒子在温度T时趋于平衡的概率为exp[-ΔE/(kT)]
r = np.random.uniform(0, 1)
if p > r: # 以一定概率来接受最优解
x = x_new
self.__t_max *= self.__coldrate
# optimal solution
saa_best_particle = Particle()
saa_best_particle.position = x
saa_best_particle.best_position = x
saa_best_particle.fitness = self.problem_function(x)
self.saa_best_particle = saa_best_particle
if saa_best_particle.fitness < algo_pso.global_best_particle.fitness:
self.best_particle = saa_best_particle
else:
self.best_particle = algo_pso.global_best_particle
self.optimal_solution = (self.parse_format(self.best_particle.position),
self.parse_format(self.best_particle.fitness))
print('the optimal solution is', self.optimal_solution)
# print('optimal solution:\nposition: {} \nfitness: {}'.format(self.best_particle.best_position,
# self.best_particle.fitness))
def draw(self):
# PSO
algo_pso = ParticleSwarmOptimization(population_size=self.__population_size,
p_dim=self.__p_dim, v_dim=self.__v_dim,
max_iter=self.__max_iter, x_range=self.__x_range)
algo_pso.draw(mixup=True)
plt.clf()
x = np.linspace(*self.__x_range, 200)
plt.plot(x, self.problem_function(x))
# SAA
x = algo_pso.global_best_particle.best_position # 初始解
while self.__t_max > self.__t_min:
for _ in range(self.__max_iter):
# something about plotting
if 'sca' in globals() or 'sca' in locals():
sca.remove()
sca = plt.scatter(x, self.problem_function(x), s=100, lw=0, c='red', alpha=0.5)
plt.pause(0.01)
x_new = np.clip(x + np.random.randn(), a_min=self.__x_range[0], a_max=self.__x_range[1])
delta = self.problem_function(x_new) - self.problem_function(x) # 计算目标函数的值差
if delta < 0: # 局部最优解
x = x_new # 直接接受更优解
else:
p = np.exp(-delta / self.__t_max) # 粒子在温度T时趋于平衡的概率为exp[-ΔE/(kT)]
r = np.random.uniform(0, 1)
if p > r: # 以一定概率来接受最优解
x = x_new
self.__t_max *= self.__coldrate
# optimal solution
saa_best_particle = Particle()
saa_best_particle.position = x
saa_best_particle.best_position = x
saa_best_particle.fitness = self.problem_function(x)
self.saa_best_particle = saa_best_particle
if saa_best_particle.fitness < algo_pso.global_best_particle.fitness:
self.best_particle = saa_best_particle
else:
self.best_particle = algo_pso.global_best_particle
plt.scatter(self.best_particle.best_position, self.best_particle.fitness, s=100, lw=0, c='green', alpha=0.7)
plt.ioff()
plt.show()
self.optimal_solution = (self.parse_format(self.best_particle.position),
self.parse_format(self.best_particle.fitness))
print('the optimal solution is', self.optimal_solution)
# print('optimal solution:\nposition: {} \nfitness: {}'.format(self.best_particle.best_position,
# self.best_particle.fitness))
def draw3D(self):
# PSO
algo_pso = ParticleSwarmOptimization(population_size=self.__population_size,
p_dim=self.__p_dim, v_dim=self.__v_dim,
max_iter=self.__max_iter, x_range=self.__x_range)
algo_pso.draw3D(mixup=True)
plt.clf()
ax = Axes3D(algo_pso.fig)
x_ = np.linspace(*self.__x_range, num=200)
X, Y = np.meshgrid(x_, x_)
Z = self.problem_function([X, Y])
ax.plot_surface(X, Y, Z, cmap=plt.cm.cool)
ax.contour(X, Y, Z, levels=5, offset=0)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# SAA
x = algo_pso.global_best_particle.best_position # 初始解
while self.__t_max > self.__t_min:
for _ in range(self.__max_iter):
# something about plotting
if 'sca' in globals() or 'sca' in locals():
sca.remove()
sca = ax.scatter3D(*x, self.problem_function(x), s=100, lw=0, c='red', alpha=0.5)
plt.pause(0.01)
x_new = np.clip(x + np.random.randn(), a_min=self.__x_range[0], a_max=self.__x_range[1])
delta = self.problem_function(x_new) - self.problem_function(x) # 计算目标函数的值差
if delta < 0: # 局部最优解
x = x_new # 直接接受更优解
else:
p = np.exp(-delta / self.__t_max) # 粒子在温度T时趋于平衡的概率为exp[-ΔE/(kT)]
r = np.random.uniform(0, 1)
if p > r: # 以一定概率来接受最优解
x = x_new
self.__t_max *= self.__coldrate
# optimal solution
saa_best_particle = Particle()
saa_best_particle.position = x
saa_best_particle.best_position = x
saa_best_particle.fitness = self.problem_function(x)
self.saa_best_particle = saa_best_particle
if saa_best_particle.fitness < algo_pso.global_best_particle.fitness:
self.best_particle = saa_best_particle
else:
self.best_particle = algo_pso.global_best_particle
ax.scatter3D(*self.best_particle.best_position, self.best_particle.fitness, s=100, lw=0, c='green', alpha=0.7)
plt.ioff()
plt.show()
self.optimal_solution = (self.parse_format(self.best_particle.position),
self.parse_format(self.best_particle.fitness))
print('the optimal solution is', self.optimal_solution)
# print('optimal solution:\nposition: {} \nfitness: {}'.format(self.best_particle.best_position,
# self.best_particle.fitness))
if __name__ == '__main__':
algo = PSO_SAA()
# algo.draw()
algo.draw3D()
コードリポジトリ:IALib[GitHub]
この記事のコードは、Python
[スマート アルゴリズム (反復)] 列の専用ウェアハウスに同期されています: IALib
ランタイムライブラリIALib
のPSO-SAA
アルゴリズム:
git clone [email protected]:xiayouran/IALib.git
cd examples
python main.py -algo pso_saa # 2D visu
python main_pro.py -algo pso_saa # 3D visu