この記事について
メタファー系の最後、 Manta Ray Foraging Optimization(MRFO:マンタ採餌最適化) です。オニイトマキエイ(マンタ)の3つの採餌行動 ──「 鎖採餌 」「 サイクロン採餌(らせん) 」「 宙返り採餌 」── を模した手法です。
3つの戦略を組み合わせる点が特徴的で、性能も良好です。一方で、これまで(⑥〜⑩)見てきた 原点バイアス の問題からは逃れられていません。シリーズ手法の最後として、その辺もしっかり見ます。
メタヒューリスティクス図鑑シリーズの記事一覧はこちら。
| 記事 | 内容 |
|---|---|
| ⓪〜⑤ | 入門・地図/PSO・ACO・CMA-ES・GA・Cuckoo |
| ⑥〜⑩ | GWO/HHO/MFO/GOA/GJO |
| ⑪(本記事) | Manta Ray Foraging(MRFO) |
| ⑫ | まとめ:メタファー系の正体と使い分け |
MRFOとは
2020年に Zhao、Wang、Zhang が提案しました。
W. Zhao, Z. Zhang, and L. Wang, "Manta ray foraging optimization: An effective bio-inspired optimizer for engineering applications,"
Engineering Applications of Artificial Intelligence, vol. 87, 103300, 2020.
マンタはプランクトンを効率よく食べるために、状況に応じて泳ぎ方を変えます。MRFO はその3つの行動を最適化の更新式にしています。
核心:3つの採餌戦略
記号の整理
先に登場する記号をまとめておきます。$t$ は現在の反復回数、$T$ は最大反復回数です。
| 記号 | 意味 | 実装(後述)での対応 |
|---|---|---|
| $X_i$ | 更新する個体 $i$ の現在位置 | X[i] |
| $X_{i-1}$ | 列の ひとつ前の個体 。先頭($i=1$)には前がいないので、実装では自分自身にして前を追う項を消している | prev |
| $X_{\text{best}}$ | これまでに見つかった 最良解 | best |
| $X_{\text{ref}}$ | サイクロン採餌の 基準点 。ランダムな点か最良解のどちらか(後述) | ref |
| $r, r_1, r_2, r_3$ | それぞれ独立な $[0, 1]$ の一様乱数。使うたびに引き直す | rng.random() |
| $\alpha$ | 鎖採餌で 最良解へ引く強さ 。$\alpha = 2r\sqrt{\vert \log r\vert}$ | alpha |
| $\beta$ | サイクロン採餌で 基準点へ引く強さ 。正にも負にもなり、らせん状の動きを作る | beta |
| $S$ | 宙返りの 飛ぶ幅 (somersault factor)。原論文どおり $S=2$ | S |
1反復の流れは次のとおりです。
- 各個体について、 確率 1/2 で「① 鎖採餌」か「② サイクロン採餌」のどちらか で位置を更新する
- 全個体を更新し終わったら、 全員に「③ 宙返り採餌」 をかける
- その都度、良い解が見つかれば $X_{\text{best}}$ を更新する
① 鎖採餌(Chain Foraging)
マンタが一列に連なって泳ぐ様子。各個体は 前の個体 と 最良解 の両方を参照して動きます。
X_i \leftarrow X_i + \underbrace{r\,(X_{i-1} - X_i)}_{\text{前の個体へ寄る}} + \underbrace{\alpha\,(X_{\text{best}} - X_i)}_{\text{最良解へ寄る}},
\qquad \alpha = 2r\sqrt{|\log r|}
右辺の2つの項は、どちらも「相手との差 × 係数」、つまり相手の方向へ一部だけ近づく動きです。前の個体の背中を追いつつ最良解にも寄るので、全体として 数珠つなぎの隊列 になります。
② サイクロン採餌(Cyclone Foraging)
渦を巻いて泳ぐ様子。 らせん運動 で基準点に近づきます。
X_i \leftarrow X_{\text{ref}} + \underbrace{r\,(X_{i-1} - X_i)}_{\text{前の個体へ寄る}} + \underbrace{\beta\,(X_{\text{ref}} - X_i)}_{\text{基準点まわりの渦}},
\qquad \beta = 2e^{r_1\frac{T-t}{T}}\sin(2\pi r_1)
鎖採餌との違いは、出発点が自分の位置 $X_i$ ではなく 基準点 $X_{\text{ref}}$ になっていることです。係数 $\beta$ には $\sin(2\pi r_1)$ が入っているので、正にも負にもなります。そのため基準点の手前にも向こう側にも着地し、これが「渦を巻く」動きになります。
基準点 $X_{\text{ref}}$ の選び方がうまい工夫です。
X_{\text{ref}} =
\begin{cases}
\text{探索範囲内のランダムな点} & (t/T < r \text{ のとき:序盤ほど起きやすい}) \\
X_{\text{best}} & (\text{それ以外:終盤ほど起きやすい})
\end{cases}
$t/T$ は 0 から 1 へ増えていくので、序盤は $t/T < r$ になりやすく ランダムな点を中心に探索 し、終盤は 最良解を中心に活用 するようになります。これが探索→活用のつまみです。
③ 宙返り採餌(Somersault Foraging)
その場でくるりと宙返りして、餌の周りを行き来する動き。 最良解を中心に対称な位置へ飛ぶ ことで、局所最適からの揺さぶりをかけます。
X_i \leftarrow X_i + S\,(r_2\,X_{\text{best}} - r_3\,X_i)
$r_2 = r_3 = 1$ のときを考えると、$X_i + 2(X_{\text{best}} - X_i) = 2X_{\text{best}} - X_i$ となり、 最良解をはさんでちょうど反対側 の点になります。実際には $r_2, r_3$ がランダムなので、自分の位置から「最良解の反対側」あたりまでの範囲のどこかへ飛ぶわけです。
図で見る
3つの動きを並べるとこうなります。
- ①(左)鎖採餌 :各個体は「 ひとつ前の個体 (青)」と「 最良解 (赤)」の両方に引かれます。先頭の $X_1$ は最良解だけを見て動き、後続はその背中を追う ── これで 数珠つなぎの隊列 ができます。前を追う項があるぶん、全員が最良解へ直行するより 列がばらけにくい のがポイントです
- ②(中)サイクロン採餌 :基準点のまわりを 渦を巻きながら 近づきます。ミソは基準点 $X_{\text{ref}}$ の選び方で、 序盤はランダムな点(探索)、終盤は最良解(活用) に切り替わります。⑧のMFOのらせんと似ていますが、あちらは「炎の数」で、こちらは「基準点の選び方」で探索と活用を切り替えています
- ③(右)宙返り採餌 :$X_i + S(r_2 X_{\text{best}} - r_3 X_i)$ の飛び先を300回ぶん描いたものです。 最良解をはさんで反対側まで飛ぶ 候補が普通に出てくるのがわかります。局所最適にはまりかけたときに、 わざと向こう側へ跳ね飛ばす ための仕掛けです
3戦略とも、結局は $X_{\text{best}}$(最良解)を基準に係数つきで動く という骨格③に乗っています。マンタは戦略が3つに分かれているぶん、GWO や GJO より多様性を保ちやすい設計になっています。
Python実装
import numpy as np
from math import pi
def mrfo(func, dim, lb, ub, n_agents=30, n_iter=500, seed=0, S=2.0):
rng = np.random.default_rng(seed)
X = rng.uniform(lb, ub, (n_agents, dim))
fit = np.array([func(x) for x in X])
best = X[np.argmin(fit)].copy(); fbest = fit.min()
history = []
for t in range(n_iter):
for i in range(n_agents):
if rng.random() < 0.5: # サイクロン採餌(らせん)
r1 = rng.random()
beta = 2 * np.exp(r1 * (n_iter - t) / n_iter) * np.sin(2 * pi * r1)
ref = rng.uniform(lb, ub, dim) if t / n_iter < rng.random() else best
prev = X[i - 1] if i > 0 else X[i]
X[i] = ref + rng.random() * (prev - X[i]) + beta * (ref - X[i])
else: # 鎖採餌
alpha = 2 * rng.random() * np.sqrt(abs(np.log(rng.random() + 1e-12)))
prev = X[i - 1] if i > 0 else X[i]
X[i] = X[i] + rng.random() * (prev - X[i]) + alpha * (best - X[i])
X[i] = np.clip(X[i], lb, ub)
f = func(X[i])
if f < fbest:
fbest, best = f, X[i].copy()
for i in range(n_agents): # 宙返り採餌
X[i] = np.clip(X[i] + S * (rng.random() * best - rng.random() * X[i]), lb, ub)
f = func(X[i])
if f < fbest:
fbest, best = f, X[i].copy()
history.append(fbest)
return best, fbest, history
Rastrigin(2次元)で実行します。
_, best_f, history = mrfo(rastrigin, dim=2, lb=-5.12, ub=5.12, seed=0)
print(f'MRFO 最良値 f = {best_f:.6e} (初期 {history[0]:.3f} → 最終 {history[-1]:.3e})')
MRFO 最良値 f = 0.000000e+00 (初期 2.731 → 最終 0.000e+00)
大域最適に到達しました。
10次元・10シード平均でも Rastrigin で $0.0$ (全シードで大域最適)、Ackley で $1.3\times10^{-14}$ と、HHO(⑦)と並ぶ最強クラスでした。3つの採餌戦略を混ぜることで、高次元でも多様性を保てているのが効いているようです。
やはり原点バイアスはある
MRFO も例外ではありません。⑫で最適解を原点から $+2$ ずらすと、$0.0 \to 7.39$ と大きく悪化します。宙返り採餌の $S(r_2 X_{\text{best}} - r_3 X_i)$ など、やはり 原点方向への引力 を内包しているためです。
「3戦略でよくできているが、原点最適のベンチマークでの数字は割り引いて見るべき」── これがメタファー系全体に通じる教訓で、次の⑫で総括します。
まとめ
- MRFO はマンタの3つの採餌行動( 鎖・サイクロン(らせん)・宙返り )を組み合わせた手法
- サイクロン採餌で基準点をランダム→最良解と切り替えて探索→活用を制御
- 3戦略のおかげで多様性を保ちやすく、 高次元でも最強クラス (Rastrigin 10次元で全シード $f=0$)
- それでも 原点バイアス からは逃れられず、最適解をずらすと悪化する
- 3戦略とも骨格は「最良解を基準に係数つきで動く」── メタファー系共通の型
次回はいよいよシリーズ総括、 「メタファー系の正体と使い分け」 です。ここまでの全手法を横並びで比較し、原点バイアスの正体に迫ります。
参考にした記事や本、論文等
- W. Zhao, Z. Zhang, and L. Wang, "Manta ray foraging optimization: An effective bio-inspired optimizer for engineering applications," Engineering Applications of Artificial Intelligence, vol. 87, 103300, 2020.

