BoTorchの実装を追っていた自分が知識整理のためにまとめた記事です。
理論については別シリーズでまとめていきたいです(つもりです)。
BoTorch 入門 1.
BoTorch 入門 2.
BoTorch 入門 3.
BoTorch 実践 3. ノイズの扱い
BoTorch 実践4. 制約付きベイズ最適化
はじめに
今回がBoTorchの紹介とチュートリアルです。細かいところは立ち入りません。
BoTorch
BoTorch(ボートーチ)はFacebook社が開発するPyTorchをベースとしたベイズ最適化のフレームワークです。主な利用者は研究者やハイレベルな実務者で、実務でベイズ最適化を行う際は同じくFaecbook社が開発しているAxを使うことが推奨されています。BoTorchの主なモジュールはPyTorchのtorch.nn.Module
であり、自動微分やGPUなどPyTorchがもつ利点を活かすことができます。
ベイズ最適化は主にSurrogate Modelの更新と獲得関数の最大化という2つのプロセスが鍵となります。BoTorchではSurrogate Modelにガウス過程を利用しますが、これはGPyTorchを利用しているため高度なガウス過程(例えばSVGPやKISS-GP)も利用可能です.また獲得関数の最大化については、reparametrization-trickと準モンテカルロ法の利用により解析的に表現できない獲得関数でも最適化を行うことが可能です。
公式ドキュメントのIntrodunctionに載っているBoTorchの特徴について簡単に説明します
-
Improved Developer Efficiency
BoTorchはModel,posterior,Acquisition Function, Optimizerといったコンポーネントで構成されており,拡張が比較的容易な設計になっています。例えばBoTorchの開発者は研究者でもあり、最新の研究が次々に実装されていきます。BoTorchが実装している査読前の論文の一部こちらにあります。この記事を書いている2022年12月現在でも今年の論文が多くあります。
-
State-of-the-art Modeling
前述したようにガウス過程はGPyTorchを利用しているため多くの高度なガウス過程を簡単にBoTorchから使うことができます。
-
Harnessing the Features of PyTorch
これも前述したようにBoTorchはPyTorchを利用しているためその恩恵を多く受けることができます。例えばガウス過程のハイパーパラメータの最適化や獲得関数の最大化は自動微分やバックプロパゲーションを利用しています。またGPUによる並列計算なども大きなメリットです。
チュートリアル
まずは公式docに従ってやってみましょう。
適宜コメント等を入れてます。
-
Fit a Gaussian Process model to data
最初はデータを準備してガウス過程によるフィッティングを行います。少し気をつけることはX
の形状が[data_num, dim]
に対してY
の形状が[data_num]
ではなく[data_num, 1]
であることです。詳細はまた先にも話しますがこのSingleTaskGP
は複数の出力にも対応しているため出力の次元を1と明示してやる必要があります。import torch from botorch.models import SingleTaskGP from botorch.fit import fit_gpytorch_mll from gpytorch.mlls import ExactMarginalLogLikelihood train_X = torch.rand(10, 2) Y = 1 - (train_X - 0.5).norm(dim=-1, keepdim=True) # explicit output dimension Y += 0.1 * torch.rand_like(Y) train_Y = (Y - Y.mean()) / Y.std() gp = SingleTaskGP(train_X, train_Y) #ガウス過程のモデルを定義 mll = ExactMarginalLogLikelihood(gp.likelihood, gp) #周辺尤度を定義 fit_gpytorch_mll(mll); #モデルのハイパーパラメータを最適化
-
Construct an acquisition function
獲得関数を定義します。この場合はUCBですね。from botorch.acquisition import UpperConfidenceBound UCB = UpperConfidenceBound(gp, beta=0.1)
-
Optimize the acquisition function
獲得関数を最大化します。
candidates
には獲得関数を最大化したことによって得られる次の候補点が格納されます。from botorch.optim import optimize_acqf bounds = torch.stack([torch.zeros(2), torch.ones(2)]) candidate, acq_value = optimize_acqf( UCB, bounds=bounds, q=1, num_restarts=5, raw_samples=20, )
チュートリアルはここで終了していますが、これだけでは一回しか更新していません。実際はこの1~3のプロセスを数回~数百回と回して最適解を逐次的に探索していきます.
とっつきにくい書き方ですね。ちなみにAxだとこんな感じです。
from ax import optimize
from ax.utils.measurement.synthetic_functions import branin
best_parameters, values, experiment, model = optimize(
parameters=[
{
"name": "x1",
"type": "range",
"bounds": [-5.0, 10.0],
},
{
"name": "x2",
"type": "range",
"bounds": [0.0, 10.0],
},
],
evaluation_function=lambda p: (branin(p["x1"], p["x2"]), 0.0),
minimize=True,
)
BoTorchの公式ドキュメントを見た人の何割が理解できることやら。。研究者向けなのでしかたないかもしれませんが