#0 質問のアイデア
(コンテストの質問が出たらすぐに CSDN で共有します)
https://blog.csdn.net/dc_sinor?type=blog
1 粒子群アルゴリズムとは何ですか?
Particle Swarm Optimization (PSO) は、鳥や魚の群れの採餌行動を模倣して開発された進化的なアルゴリズムです。そのコンセプトはシンプルで、プログラムと実装が簡単で、操作効率が高く、パラメータが比較的少なく、広く使用されています。粒子群アルゴリズムは1995年に提案され、24年前(2019年)の歴史があります。
粒子群アルゴリズムにおける各粒子の位置は、解決すべき問題に対する解決策の候補を表します。空間内の各粒子の位置の品質は、解決される問題における粒子の位置の適合度値によって決まります。次の世代における各粒子の位置は、この世代における位置とそれ自体の速度ベクトルによって決定され、その速度によって粒子の各飛行の方向と距離が決まります。飛行中に、粒子は訪れた最適な位置 P を記録し、グループもまた、グループが訪れた最適な位置 G を更新します。粒子の飛行速度は、粒子の現在位置、粒子自体が行った最適な位置、グループが行った最適な位置、およびこのときの粒子の速度によって決まります。
2 例を挙げてみましょう
湖の中に 2 人の人間がいて、互いに通信でき、自分たちの位置の最低点を検出できます。初期位置は上の写真の通りですが、右側の方が深いので左側の人がボートを右に動かします。
今度は左側が深くなったので、右側の人がボートを左側に動かします。
このプロセスを最後まで繰り返し、最終的に 2 つのボートが合流します。
局所的な最適解を求めると、
各個人が粒子として表現されます。ある瞬間における各個体の位置をx(t)、方向をv(t)で表す。
p(t) は時刻 t における x 個体の最適解、g(t) は時刻 t におけるすべての個体の最適解、v(t) は時刻 t における個体の方向、x(t) は個体時刻tの位置
上の図に示すように、次の位置は x、p、g によって決定されます。
集団内の粒子は、自身と集団の履歴情報から継続的に学習することで、問題に対する最適な解決策を見つけることができます。
3はまだ一例です
粒子群アルゴリズムは、鳥の採餌行動から派生したアルゴリズムです。さて、私たちの主人公は鳥の群れです。
鳥たちの目的はシンプルです。この地域で一番餌が豊富な場所を見つけて、落ち着いて回復することです。この場所での彼らの捜索戦略は次のとおりです。
1. 各鳥はランダムに場所を見つけ、その場所にある餌の量を評価します。
2. 全鳥が集合し、餌が最も多い場所を定住候補点Gとして選択した。
3. 各鳥はその旅を振り返り、これまで訪れた中で最も餌が豊富な場所 P を思い出します。
4. より多くの餌のある場所を見つけるために、それぞれの鳥はGに向かって飛んでいきます。しかし、選択の難しさのためか、Pへの郷愁からか、Gへの不信感によるものなのかはわかりません。Pに向かって飛んでいきます。実際、G に向かって飛んでいるのか、P に向かって飛んでいるのかはわかりません。
5. 再び会議の時間です。鳥が探すのをやめると決めた場合は、現在の G を選択して落ち着きます。そうでない場合は、2->3->4->5 を続けて生息地を見つけます。
上の図で説明した戦略 4 の場合、鳥は点 A におり、点 G は鳥が最も多くの餌を見つけた場所、点 P は鳥が最も多くの餌を見つけた場所です。V は現在の飛行速度 (速度はベクトルであり、方向と大きさを表します) で、今度は P と G に向かって飛ぶことを決定しますが、これは仏教の鳥であり、どの程度飛ぶかは状況によって異なります。速度 V がなければ点 B に飛行するはずです。速度 V の影響を受けて、その合成速度により最終的に次の目的地である点 C に飛行します。C が P より優れている場合は、次回は C が P になり、C が G より優れている場合は、次回は G になります。
アルゴリズム処理
アルゴリズムの実装
ここでは、先輩が Python を使用して、粒子群解関数を使用した最適解をデモンストレーションします。
import numpy as np
import matplotlib.pyplot as plt
import random
# 定义“粒子”类
class parti(object):
def __init__(self, v, x):
self.v = v # 粒子当前速度
self.x = x # 粒子当前位置
self.pbest = x # 粒子历史最优位置
class PSO(object):
def __init__(self, interval, tab='min', partisNum=10, iterMax=1000, w=1, c1=2, c2=2):
self.interval = interval # 给定状态空间 - 即待求解空间
self.tab = tab.strip() # 求解最大值还是最小值的标签: 'min' - 最小值;'max' - 最大值
self.iterMax = iterMax # 迭代求解次数
self.w = w # 惯性因子
self.c1, self.c2 = c1, c2 # 学习因子
self.v_max = (interval[1] - interval[0]) * 0.1 # 设置最大迁移速度
#####################################################################
self.partis_list, self.gbest = self.initPartis(partisNum) # 完成粒子群的初始化,并提取群体历史最优位置
self.x_seeds = np.array(list(parti_.x for parti_ in self.partis_list)) # 提取粒子群的种子状态 ###
self.solve() # 完成主体的求解过程
self.display() # 数据可视化展示
def initPartis(self, partisNum):
partis_list = list()
for i in range(partisNum):
v_seed = random.uniform(-self.v_max, self.v_max)
x_seed = random.uniform(*self.interval)
partis_list.append(parti(v_seed, x_seed))
temp = 'find_' + self.tab
if hasattr(self, temp): # 采用反射方法提取对应的函数
gbest = getattr(self, temp)(partis_list)
else:
exit('>>>tab标签传参有误:"min"|"max"<<<')
return partis_list, gbest
def solve(self):
for i in range(self.iterMax):
for parti_c in self.partis_list:
f1 = self.func(parti_c.x)
# 更新粒子速度,并限制在最大迁移速度之内
parti_c.v = self.w * parti_c.v + self.c1 * random.random() * (parti_c.pbest - parti_c.x) + self.c2 * random.random() * (self.gbest - parti_c.x)
if parti_c.v > self.v_max: parti_c.v = self.v_max
elif parti_c.v < -self.v_max: parti_c.v = -self.v_max
# 更新粒子位置,并限制在待解空间之内
if self.interval[0] <= parti_c.x + parti_c.v <=self.interval[1]:
parti_c.x = parti_c.x + parti_c.v
else:
parti_c.x = parti_c.x - parti_c.v
f2 = self.func(parti_c.x)
getattr(self, 'deal_'+self.tab)(f1, f2, parti_c) # 更新粒子历史最优位置与群体历史最优位置
def func(self, x): # 状态产生函数 - 即待求解函数
value = np.sin(x**2) * (x**2 - 5*x)
return value
def find_min(self, partis_list): # 按状态函数最小值找到粒子群初始化的历史最优位置
parti = min(partis_list, key=lambda parti: self.func(parti.pbest))
return parti.pbest
def find_max(self, partis_list):
parti = max(partis_list, key=lambda parti: self.func(parti.pbest)) # 按状态函数最大值找到粒子群初始化的历史最优位置
return parti.pbest
def deal_min(self, f1, f2, parti_):
if f2 < f1: # 更新粒子历史最优位置
parti_.pbest = parti_.x
if f2 < self.func(self.gbest):
self.gbest = parti_.x # 更新群体历史最优位置
def deal_max(self, f1, f2, parti_):
if f2 > f1: # 更新粒子历史最优位置
parti_.pbest = parti_.x
if f2 > self.func(self.gbest):
self.gbest = parti_.x # 更新群体历史最优位置
def display(self):
print('solution: {}'.format(self.gbest))
plt.figure(figsize=(8, 4))
x = np.linspace(self.interval[0], self.interval[1], 300)
y = self.func(x)
plt.plot(x, y, 'g-', label='function')
plt.plot(self.x_seeds, self.func(self.x_seeds), 'b.', label='seeds')
plt.plot(self.gbest, self.func(self.gbest), 'r*', label='solution')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('solution = {}'.format(self.gbest))
plt.legend()
plt.savefig('PSO.png', dpi=500)
plt.show()
plt.close()
if __name__ == '__main__':
PSO([-9, 5], 'max')
効果
モデリング情報
データ共有: 最強のモデリングデータ