外部ライブラリの統合#
saealibは、外部の機械学習ライブラリおよび進化計算ライブラリを、独自の抽象基底クラスの背後に薄くラップしたアダプタを提供します。
アダプタが翻訳するのはProblem/Population/ctxといったsaealib側のデータ表現だけで、学習アルゴリズムや探索演算子そのものは外部ライブラリの実装をそのまま使います。
現時点では、サロゲートモデルのアダプター(scikit-learn、XGBoost、LightGBM、PyTorch)と、pymooアダプター(Crossover/Mutation/Algorithm/Problem)を実装しています。外部の進化計算ライブラリへのランタイム依存を取り除きたい場合は、saealibネイティブなコードへの演算子の移植で、pymooやDEAP風の演算子をネイティブなCrossover/Mutationサブクラスとして書き直す方法を扱います。
このページでできるようになること
このページを終えると、外部ライブラリの依存関係を導入し、saealibのアダプター経由でモデルや演算子を利用できます。
ビルトインのモデルや演算子で足りる場合は高レベルAPIを使い、独自実装へ移植する場合は独自コンポーネントを参照してください。
アダプター追加機能のインストール#
各アダプタは、対応するextraを指定してインストールしたときだけ使えます。
pip install "saealib[sklearn]"
インストール方法とextra一覧の詳細はインストールを参照してください。
対応するextraをインストールしていない状態でアダプタをインポートすると、ImportErrorになります。
サロゲートアダプターを使う#
各アダプタはsaealibのSurrogate基底クラスを実装しており、組み込みのRBFSurrogateと同じようにsurrogate引数へ渡せます。
クラス |
対応する |
ラップするモデル |
|---|---|---|
|
|
ガウス過程回帰 |
|
|
ランダムフォレスト回帰 |
|
|
サポートベクター回帰 |
|
|
多層パーセプトロン |
|
|
XGBoost回帰 |
|
|
LightGBM回帰 |
|
|
任意のPyTorch |
コンストラクタへのキーワード引数は、そのまま対応するライブラリのモデルへ渡されます。
import numpy as np
from saealib import minimize, SklearnGPRSurrogate
def expensive_func(x):
return np.sum(x**2)
DIM = 10
result = minimize(
expensive_func,
dim=DIM,
lb=[-5.0] * DIM,
ub=[5.0] * DIM,
surrogate=SklearnGPRSurrogate(),
max_fe=300,
seed=0,
)
Surrogateインスタンスを minimize(..., surrogate=...) に渡すと、内部で LocalSurrogateManager にラップされます。
分類問題向けのアダプタ(実行可能性分類など)や、各アダプタの詳細な引数はSurrogateを参照してください。
pymooアダプターを使う#
各アダプタは構築済みのpymooオブジェクトをラップし、対応するsaealibの基底クラスを実装しているため、その基底クラスが期待される場所ならどこにでも渡せます。
Class |
ラップする対象 |
|---|---|
|
pymooの |
|
pymooの |
|
pymooの |
|
pymooの |
PymooCrossover/PymooMutationは、そのままGAに組み込めます。
import numpy as np
from pymoo.operators.crossover.sbx import SBX
from pymoo.operators.mutation.pm import PM
from saealib import GA, TournamentSelection, TruncationSelection, minimize
from saealib.operators import PymooCrossover, PymooMutation
def expensive_func(x):
return np.sum(x**2)
DIM = 10
result = minimize(
expensive_func,
dim=DIM,
lb=[-5.0] * DIM,
ub=[5.0] * DIM,
algorithm=GA(
crossover=PymooCrossover(SBX(eta=15)),
mutation=PymooMutation(PM(eta=20)),
parent_selection=TournamentSelection(2),
survivor_selection=TruncationSelection(),
),
surrogate="rbf",
max_fe=300,
seed=0,
)
PymooAlgorithmはpymooアルゴリズム全体の探索・生存選択ロジックをそのまま再利用し、PymooProblemは既存のpymoo問題定義をそのまま再利用します。
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.problems import get_problem
from saealib import minimize, PymooProblem
from saealib.algorithms import PymooAlgorithm
from saealib.strategies import DirectStrategy
problem = PymooProblem(get_problem("zdt1"))
result = minimize(
problem,
algorithm=PymooAlgorithm(NSGA2(pop_size=20)),
surrogate="rbf",
strategy=DirectStrategy(),
max_fe=200,
pop_size=20,
seed=0,
)
PymooAlgorithmは「エンジンモード」で動作します。
ラップしたpymooアルゴリズムが自身の個体群と内部の生存選択状態を保持し、ctx.populationは基準となるデータではなく、各世代後にそこから更新されます。実際の意味(チェックポイントと再開には非対応、n_offspringは無視される、PreSelectionStrategyの部分的なtell()には明示的なオプトインが必要)についてはAlgorithmを参照してください。