19
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MATLABで学ぶベイズ最適化入門~数式とコードで理解するパラメータチューニング~

19
Posted at

1. はじめに

機械学習やデータサイエンスの分野では、「良い予測結果を得るために、どのパラメータをどう設定すればよいのか?」という課題に頻繁に直面します。例えば、ニューラルネットワークの学習率や層の数といったパラメータは無数の組み合わせが考えられ、最適な値の組を力任せに見つけ出そうとすると膨大な時間がかかってしまいます。

このような「パラメータ最適化」の問題に対して非常に有効なのが、ベイズ最適化という手法です。この手法は一見難しそうに聞こえるかもしれませんが、実際に、パラメータ探索を含む様々な分野で応用されている便利なツールです。

本記事では、ベイズ最適化の基礎から応用例までを、MATLABのコードを交えてわかりやすく解説します。まず二次関数を例に基本的な流れを掴み、次にその核心技術である「ガウス過程」と「獲得関数」を学びます。最後に、Irisデータセットの分類問題を通して、実際に機械学習モデルのパラメータチューニングを行い、最適化の様子を可視化します。

2. 機械学習とベイズ最適化

ベイズ最適化は様々な分野で使われていますが、特に機械学習モデルのハイパーパラメータ探索でよく利用される手法です。ハイパーパラメータとは学習過程で自動的に決まるのではなく、事前に人間が設定する必要があるパラメータのことです。例えば、決定木アルゴリズムにおける木の深さや、リッジ回帰での正則化強度などがハイパーパラメータです。これらハイパーパラメータの良し悪しはモデルの性能に大きく影響しますが、手動で最適な値を探すのは困難です。

この探索を自動化する従来手法として、グリッドサーチやランダムサーチがあります。しかし、これらの手法には効率の面で課題がありました。ベイズ最適化は、よりスマートなアプローチでこの課題を解決します。下の図は、これら3つの手法が2つのハイパーパラメータ空間(背景の青い領域が最適解)をどのように探索するかを視覚的に比較したものです。

Hyperparameter_Optimization.gif

従来よく用いられる手法にグリッドサーチがあります。グリッドサーチではあらかじめ候補となるパラメータ値の組み合わせを格子状(グリッド)に列挙し、全ての組み合わせでモデルを評価して最も良い組み合わせを見つけます。
この様子は、上図の「1. Grid Search」を見ると一目瞭然です。候補となる点(Sampled Points)が格子状に整然と並べられ、順番に評価されます。確実な方法ですが、図が示すように有望でない領域(図の黄色い部分)にも多くの計算コストを費やしてしまい非効率です。また、パラメータの数や候補が増えると組み合わせが爆発的に増え、計算コストが非常に高くなります。

この問題への一つの対策がランダムサーチです。「2. Random Search」の図では、探索点がランダムに散らばっているのがわかります。このアプローチはグリッドサーチより効率的な場合もありますが、過去の評価結果を全く考慮しないため、戦略性に欠けるという課題が残ります。

これに対しベイズ最適化は、過去の評価結果を基に次に試すべき最も有望な点を予測し、効率的に最適値を探します。

3. Bayesian Optimization」の図が、その賢い探索の様子をよく表しています。初期の数点(図中の番号1〜5)は、有望な領域を探すために空間を広く「探索 (Exploration)」しています。そして、有望な領域(図の青い部分)が見つかると、その後の探索はそのデータを「活用 (Exploitation)」し、重点的に近くの領域を調べます。そのようにして効率的に最適値(赤い星)へと収束していきます。このように、一部の有望な点のみに絞って探索するため、グリッドサーチやランダムサーチに比べて必要な評価回数を大幅に削減できるのです。

ベイズ最適化を用いれば、人手に頼らず統計的な手法で最適なハイパーパラメータを効率よく見つけることができます。実験では他の手法と比較しても少ない試行で高い精度を出せることが多く、近年は機械学習ライブラリでもベイズ最適化によるハイパーパラメータチューニングがサポートされています。例えば、Scikit-learnやTensorFlowのラッパー、Optunaなどの専用ライブラリがベイズ最適化に基づくチューニング機能を提供しています。これらを利用すれば、ユーザは「最適化したいスコア(例えば検証データの正確度)」と「調整したいハイパーパラメータの範囲」を指定するだけで、自動的にベイズ最適化が走り最良のパラメータを提案してくれます。特にディープラーニングの分野では一回の試行に時間がかかるため、効率的に探索できるベイズ最適化は強力な助っ人となっています。

3. ベイズ最適化の概要

ベイズ最適化(Bayesian Optimization)とは、ブラックボックス関数(中身が不明な関数)の最大値または最小値を、できるだけ少ない試行回数で効率よく見つけるための手法です。ブラックボックス関数とは内部の仕組みや数式が不明な関数のことで、入力に対し出力は得られるものの、その形状や性質が分からない関数を指します。ベイズ最適化ではまずブラックボックス関数に対していくつか試行を行いデータを集め、その観測データから統計モデルを構築して関数の形を推定します。

統計モデルには後述するガウス過程回帰(Gaussian Process Regression)と呼ばれる手法を用い、過去のデータから推定される関数の挙動(平均と不確かさ)を表現します。次に獲得関数(Acquisition Function)と呼ばれる指標を計算し、それを最大化する入力値を“次に試すべき点”として選びます。選んだ点でブラックボックス関数を評価し、新しいデータを得たらモデルを更新するという、この一連の流れを繰り返すことで、効率よく最適解に近づくことができます。

ベイズ最適化ステップをブラックボックス関数が以下の2次関数であった場合を例に取り、解説していきます。以下の関数がわかっていない場合に、観測値から以下の関数の形とその最小値を効率よく推定します。

$$
f(x) = 0.1(x - 3)^2
$$

  1. 初期データの収集

    まず適当に選んだいくつかの点で関数を評価し、観測データを取得します。

    ここでは$x=9$の時$f(x) =3.6$であることが観測したとします。

  2. モデル構築:

    得られたデータをもとに、ガウス過程などを用いて目的関数の推定モデル(代理モデル)を構築します。

    $x=9$の時$f(x) =3.6$であることが観測されており、その値から関数の形を推定します。すると、以下の図のように関数の概形が推定されます。詳細については後述します。青色線が関数の平均値、薄い青い領域はこの範囲に真の関数が入る確率が 95 % と考えている領域を示しています。赤の点線で示される関数がブラックボックスとなっている2次関数を示しています。

    image.png

  3. 次の試行点の決定

    構築したモデルから 獲得関数 を計算し、その値を最小化(※最小化問題の場合)する点を次の評価候補とします。獲得関数は「その点を評価すればどれだけ良い結果が得られそうか」を表す指標で、未知の領域を探索する効果と既知の良い領域を活用する効果のバランスを取るよう設計されています。

    ここではLCBという最小値が存在しそうな場所を評価する関数を用います。先ほどの推定した関数の概形に基づいて計算すると以下のようになります。図中でピンク色で表される区間内で最小値を取るx=10を次の試行点とします。
    image 1.png

  4. 新しいデータの取得

    ステップ3で選んだ点で実際に関数を評価し、新たな観測データを得ます。

    $x=10$の時に$f(x)=4.9$という値が観測されます。

  5. モデルの更新

    手に入れた新しいデータを加えて、ガウス過程モデルなどの代理モデルを更新します。

    先ほどの観測値を含めて関数を再評価すると以下の図のようになります。
    image 2.png

  6. 繰り返し: ステップ3~5を繰り返し行い、十分良い解が得られるか探索を続けます。

    以下の画像のように繰り返し行うことで関数の形が明確になっていくと同時に最小値を推定することができます。
    bayes_opt.gif

このような流れによって、「最適解が得られる見込みの高い点を順番に評価することで、少ない試行回数で最適解を見つける」ことが可能になるのです。このような仕組みを用いることで、ベイズ最適化は効率的な探索を実現しています。

4. ベイズの定理とベイズ最適化

ベイズ最適化は、その名称が示す通り、統計学における基本定理の一つである「ベイズの定理」をその計算原理の中核に据えています。

ベイズの定理とは、ある事象に対する事前の確率(事前確率)が、新たな観測データを取得することにより、より確からしい事後の確率(事後確率)へと合理的に更新されるプロセスを数学的に記述したものです。

この定理は、以下の数式によって表現されます。

$$
P(H \mid D) = \frac{P(D \mid H) \cdot P(H)}{P(D)}
$$
この式の各要素は、それぞれ以下の意味を持ちます。

  • $P(H|D)$
    事後確率 (Posterior)を表します。データDを観測したという条件下で、仮説Hが真である確率です。観測を通じて更新された、より確度の高い確率を指します。

  • $P(H)$
    事前確率 (Prior)を表します。
    データを観測する前に持っていた、仮説Hが真であるという初期の確率です。

  • $P(D|H)$
    尤度 (Likelihood) を表します。仮説Hが真であると仮定した場合に、データDが観測される確率です。その仮説の下でデータが観測される「もっともらしさ」を示します。

  • $P(D)$
    証拠 (Evidence)を表します。事後確率の値を正規化するための定数項です。

この数式の本質は、「更新後の確率は、更新前の確率と尤度の積に比例する」という関係性にあり、観測データに基づいて確率的推論を逐次的に更新していくための数学的な枠組みを提供します。

ベイズ最適化は、この「確率をデータに基づいて更新する」という原理を、「未知の関数の形状を予測し、最適値を探す」という問題に適用します。

ベイズの定理の各要素は、ベイズ最適化の文脈で以下のように対応します。

  • 仮説 (H):
    「評価対象の関数の形状は、特定の形をしている」という確率的な予測。

  • データ (D)
    「あるハイパーパラメータxを試した結果、スコアyが得られた」という実際の評価結果(観測点)。

5. ベイズ最適化のアルゴリズム

ベイズ最適化で用いられる代表的な統計モデルが ガウス過程回帰 (Gaussian Process Regression) です。ガウス過程とは「どの部分集合の点を取ってきてもそれらの関数値が共に正規分布に従う」という仮定に基づくモデルで、ブラックボックス関数の分布を表現するのに適しています。平たく言えば、ガウス過程回帰を使うと「これまで観測した点を踏まえ、まだ評価していない地点での値」を平均分散付きで予測することができます。平均はその点での予測値、分散は予測の不確実性(不確かさ)を表します。この不確実性の情報こそがベイズ最適化の強みであり、探索すべき領域を判断する手掛かりになります。

5.1. カーネル関数 (Kernel Function)

ガウス過程では、任意の2点 $x_i,x_j$ の「近さ」や「相関の強さ」を定義するためにカーネル関数 $k(x_i,x_j)$ を用います。ここでは2乗指数カーネル (RBFカーネル) を使用します。

$$
k(x_i, x_j) = \exp\left(-\frac{1}{2l^2} |x_i - x_j|^2\right)
$$

  • l は kernel_length_scale で、関数がどれだけ滑らかに変化するかを制御します。
  • このカーネル関数は、squared_exponential_kernel というローカル関数で実装されています。
function K = squared_exponential_kernel(X1, X2, length_scale)
    % Squared Exponential (RBF) Kernel
    % K(x1, x2) = exp(-0.5 * ||x1 - x2||^2 / l^2)
    % 入力:
    %   X1: (n1 x d) の行列
    %   X2: (n2 x d) の行列
    %   length_scale: カーネルのハイパーパラメータ (l)
    % 出力:
    %   K: (n1 x n2) のカーネル行列
    
    % dists = pdist2(X1, X2) を使わずに実装
    n1 = size(X1, 1);
    n2 = size(X2, 1);
    dists_sq = zeros(n1, n2);
    for i = 1:n1
        for j = 1:n2
            dists_sq(i, j) = sum((X1(i,:) - X2(j,:)).^2);
        end
    end
    
    K = exp(-0.5 * dists_sq / length_scale^2);
end

【補足】2乗指数カーネル関数の概形について

ベイズ最適化の代理モデルであるガウス過程では、「2つの入力点 x と x′ がどれだけ似ているか」を測る尺度としてカーネル関数 (Kernel Function) を用います。このカーネル関数が、予測される関数の性質(滑らかさなど)を決定づける重要な役割を担います。

「2つの点が近ければ、その出力(yの値)も似ているはずだ」という直感を数学的に表現するもので、この「近さ」の定義の仕方によって、様々なカーネル関数が存在します。

以下の図は、2乗指数カーネル関数を可視化したものです。以下のことがわかります。

  • 対角線上が最大値: グラフを斜め上から見ると、対角線、つまり $x_i=x_j$ となるラインでZ軸の値が最大 (1) になっているのがわかります。これは、「基準点と比較点が同じであれば、類似度は最大になる」という関数の性質をそのまま表しています。
  • 対角線から離れると値が減少: 対角線のラインから離れるにつれて、地表(z=0)に向かってなだらかな尾根が下りていくのが見えます。これは、基準点 $x_i$ と比較点 $x_j$ の差が大きくなるほど、類似度が0に近づいていく様子を示しています。
  • 対称性: この尾根の形は、対角線 $x_i=x_j$ に関して完全に対称です。これは、$k(x_i,x_j)=k(x_j,x_i)$ というカーネルの対称的な性質を反映しています。

RBF1.png

また以下の図はlの値を3と大きくした時の様子を表しています。このようにlの値を増やすことで、対角線から離れた時の値の減少具合がなだらかになることがわかります。

RBF.png

【補足】その他主なカーネル関数の種類

この図は、機械学習のカーネル法でよく用いられる代表的な4つのカーネル関数を、基準点からの距離 r に対してプロットしたものです。それぞれのカーネルがデータの類似性をどのように捉え、距離に応じてその類似度(カーネル関数の出力)がどのように変化するかを比較することができます。

4つの主要なカーネル関数の比較.png

  • 2乗指数カーネル(RBFカーネル)(青色の実線):最も一般的なカーネルの一つで、距離が離れるにつれて滑らかに、そして急速に類似度が減少する特徴を持ちます。非常に滑らかな関数を仮定する際に適しています。
  • マターンカーネル(nu=5/2)(オレンジ色の実線):RBFカーネルよりもわずかに鋭い形状を持ち、より現実的な、滑らかすぎない関数を仮定できます。物理現象のモデリングなど、有限回の微分可能性が重要な場合に好まれます。
  • 有理2次カーネル(alpha=1)(黄色の実線):RBFカーネルと比較して、距離が離れても類似度の減衰が緩やかで、「裾が長い」形状をしています。これは、複数の異なるスケールの特徴を持つデータを捉えるのに有効です。
  • 周期カーネル(p=4)(紫色の実線):その名の通り、周期的なパターンを持つ関数をモデル化するために使用されます。ここでは周期 p=4 に設定しており、距離に応じてカーネルの出力が周期的に変動する様子が確認できます。季節性のあるデータなど、周期的な構造を持つデータに対して有効です。

5.2. ガウス過程による予測分布

本セクションでは、ガウス過程における予測の仕組みを解説します。ガウス過程は、手元にある観測データを用いて、未知の点における値を予測する手法です。

その大きな特徴は、単一の予測値を提示するだけでなく、予測の平均(最も確からしい値)と分散(不確かさの度合い)を同時に算出する点にあります。これにより、予測値とその信頼度を定量的に評価できます。

以下の図は、ガウス過程回帰を適用した典型的な結果を示しています。既知の観測データ(赤丸)を用いて、未知の関数(黒の破線)の形状を予測しています。
ガウス過程.png
この図から、ガウス過程の主要な特徴を視覚的に理解することができます。

  • 予測平均(青い実線): ガウス過程モデルが予測する関数値の期待値(最も確からしい値)を表します。観測データが存在する領域では、この線はデータ点に沿うように滑らかに引かれます。
  • 95%信頼区間(水色の帯): 予測の不確かさを定量的に表現したものです。真の関数は95%の確率でこの帯の中に存在すると期待されます。
  • 観測データ(赤い丸): モデルの学習に用いた、ノイズを含む測定値です。

特に注目すべきは、観測データの有無と信頼区間の幅の関係です。

観測データが存在する領域では、モデルは予測に対する高い確信度を持つため、信頼区間の幅は狭くなります。一方で、観測データが存在しない領域、特にグラフの両端では、利用できる情報が少ないためにモデルの不確かさが増大し、信頼区間の幅が著しく広がっていることが確認できます。

このように、ガウス過程は単に予測値を提示するだけでなく、その予測がどの程度の信頼性を持つのかを「不確かさ」として同時に可視化できる強力な手法です。

n 個の観測点 $Xobs=[x_1,…,x_n]^T$ とその観測値 $Yobs=[y_1,…,y_n]^T$ があるとき、新しい点 $x_∗$ における関数値 $f(x_∗)$ の予測分布は、以下の正規分布に従います。

p(f(x_*) | \mathcal{D}_n, x_*) = \mathcal{N}(\mu_{pred}(x_*), \sigma^2_{pred}(x_*))

この式は、予測結果が「予測平均」と「予測分散」によって特徴づけられる正規分布で与えられることを示しています。以下では、これらの計算方法について具体的に説明します。

予測分布を計算する2つの主要な式

予測分布は、予測平均と予測分散を求めることで得られます。これらは以下の2つの式によって計算されます。各々の式が持つ意味を順に解説します。

予測平均 $μ_{pred}$:

\mu_{pred}(x_*) = \mathbf{k}_*^T (\mathbf{K} + \sigma_n^2 \mathbf{I})^{-1} Y_{obs}

この式は、新しい点 $x_∗$ における予測平均値が、観測値 $Y_{obs}$ の重み付き線形結合で表されることを示しています。

ここで、予測に用いる「重み」を決定しているのが$\mathbf{k}_*^T (\mathbf{K} + \sigma_n^2 \mathbf{I})^{-1}$の部分です。この重みは、①新しい点と各観測点の類似度 $(k_∗)$ と、②観測点同士の相互的な類似度 $(K)$ の両方を考慮して算出されます。

結果として、新しい点 $x_∗$ に近い観測点ほど、その観測値が予測平均へ与える影響は大きくなります。逆行列の計算は、観測点同士の関係性を踏まえて、この重みを最適化する役割を担っています。

予測共分散 $\sigma_{pred}$ (分散はその対角成分):

\sigma_{pred}(x_*) = k(x_*, x_*) - \mathbf{k}_*^T (\mathbf{K} + \sigma_n^2 \mathbf{I})^{-1} \mathbf{k}_*

この式は、予測の不確かさ(分散)が、事前の分散から観測データによって削減される分散を引くことで計算されることを示しています。

  • $k(x_∗,x_∗)$: 第1項は、データを観測する前の事前分散に相当します。これは、モデルが元々持っている不確かさの上限と解釈できます(通常、カーネルの設計により1となります)
  • 以下の式で表される第2項は、観測データを得たことによって減少する分散量を表します。予測したい点 $x_∗$ の近くに多くの観測点があれば、この項の値は大きくなり、結果として全体の予測分散は小さくなります(予測の確信度が高まる)。逆に、観測点が周囲にないと、この項は小さくなり、予測分散は大きいままとなります(確信度が低い)。
\mathbf{k}_{*}^T (\mathbf{K} + \sigma_n^2 \mathbf{I})^{-1} \mathbf{k}_{*}

予測平均と予測共分散に対応するコードは以下のとおりです。

K = K + observation_noise * eye(n_obs); % ノイズ項を追加
% 数式: (K + σ_n^2 * I)^-1
K_inv = inv(K);
% 数式: k_*^T * (K + σ_n^2 * I)^-1 * Y_obs
mu_pred = Ks' * K_inv * Y_obs;
% 数式: k(x_*, x_*) - k_*^T * (K + σ_n^2 * I)^-1 * k_*
cov_pred = Kss - Ks' * K_inv * Ks;

予測平均や予測共分散の計算に用いる変数の意味とコードの対応は以下の通りです。

  • $\mathbf{K}$ (K): 観測点同士のカーネル行列 (n×n)

    • K は、与えられた観測点同士の類似度を要素とする (n×n) 次元の共分散行列です。カーネル関数を用いて、全ての観測点のペアに対して類似度を計算し、行列を構築します。これは、観測点間の相関関係を行列形式で表現したものです。
    K = squared_exponential_kernel(X_obs, X_obs, kernel_length_scale);
    
  • $\mathbf{k}_*$ (Ks): 予測したい点 x_plot と全観測点 X_obs との間のカーネル行列。

    • k∗ は、予測対象である新しい点 x∗ と、全ての観測点 Xobs との間の類似度を格納したベクトルです。このベクトルは、新しい点と各観測点の関連性の強さを示します。
    Ks = squared_exponential_kernel(X_obs, x_plot, kernel_length_scale);
    
  • $k(x_*, x_*)$ (Kss): 予測したい点同士のカーネル行列。

    • $k(x_*, x_*)$ は、予測対象点 x∗の自身との類似度を表すスカラー値です。これは観測データを利用する前の、当該点における事前分散に相当し、通常は1となります。
    Kss = squared_exponential_kernel(x_plot, x_plot, kernel_length_scale);
    
  • $\sigma_n^2 \mathbf{I}$: 観測ノイズ。observation_noise * eye(n_obs) に相当します。これを $\mathbf{K}$ に加えることで、モデルがデータに過剰適合するのを防ぎます。

    • 現実のデータには通常、測定誤差などのノイズが含まれます。σn2はそのノイズの分散を表すパラメータです。この項を単位行列 I と乗算し、共分散行列 K の対角成分に加えることで、モデルがデータに対して過剰適合することを抑制し、より汎化性能の高い予測を可能にします。

var_pred = diag(cov_pred) で共分散行列の対角成分を取り出し、各予測点での分散を計算しています。

5.3 獲得関数による次の評価点の決定

ベイズ最適化では、ガウス過程によって得られた予測モデル(予測平均と不確かさ)を基に、次にどの入力値(x)を試すべきかを決定します。その判断基準となるのが獲得関数 (Acquisition Function) です。獲得関数は、予測モデルから計算される「次点の候補としてどれほど有望か」を示すスコアであり、このスコアを最適化(最小化または最大化)する点を次の探索点として選びます。

今回のように関数の最小値を見つけることが目的の場合、代表的な獲得関数の一つである LCB (Lower Confidence Bound) が用いられます。LCBは以下の式で定義されます。

\alpha_{LCB}(x) = \mu_{pred}(x) - \kappa \sigma_{pred}(x)
  • $μ_pred(x)$: 予測平均。この値が小さいほど、有望な最小値候補です (活用: Exploitation)。
  • σpred(x): 予測標準偏差(不確かさ)。この値が大きいほど、まだよく調べていない未知の領域です (探索: Exploration)。
  • κ (kappa): 活用と探索のバランスを調整するパラメータ。

コードでは以下のように計算されます。

acquisition_func = mu_pred - kappa * sigma_pred;

そして、この獲得関数 αLCB(x) を最小化する点 xnext を次の探索点として選びます。

$$
x_{next} = \arg\min_{x} \alpha_{LCB}(x)
$$

[~, min_idx] = min(acquisition_func);
x_next = x_plot(min_idx);

この xnext で真の関数 true_func を評価し、得られた (x_next, y_next) を観測データセット (X_obs, Y_obs) に加えて、次のイテレーションに進みます。

このプロセスを繰り返すことで、モデルは徐々に関数の谷の形状を正確に学習し、最小値へと収束していきます。

以下に、ガウス過程予測と共に獲得関数をプロットした図を示しました。
獲得関数.png
図(獲得関数)の緑色の線が、各入力点 x におけるLCBの値をプロットしたものです。そして、このLCBの値が最も小さくなった点(星印)が、ベイズ最適化が「次に観測すべき」と判断した候補点 x_next です。

今回の図の例では、x = -10 の点が次の候補として選ばれています。上の図でこの点を確認すると、ここは既に観測されたデータ(赤い点)がある場所です。この点では不確かさ(σpred)はほぼゼロですが、予測平均(μpred)が非常に低いため、結果的にLCBの値が最も小さくなっています。これは、モデルが「現時点での情報では、観測済みの点の付近である x = -10 こそが最も確からしい最小値を与える点である」と判断していることを示しており、「活用」が強く働いた例と言えます。

このように、獲得関数は「既知の情報から最も有望そうな点(活用)」と「まだよくわからないが大きな可能性を秘めていそうな点(探索)」を天秤にかけ、次に試すべき最も効率的な一点を合理的に提案してくれます。

【補足】ベイズ最適化における獲得関数

ベイズ最適化の効率性は、次に評価すべき点を合理的に選択する戦略に依存します。この戦略を数学的に定式化したものが獲得関数 (Acquisition Function) です。

獲得関数は、代理モデル(ガウス過程)が算出した予測平均予測分散の両方を考慮し、目的関数の値を最大化(または最小化)する可能性が最も高い点を評価するための指標です。獲得関数の値が最大となる点が、次の評価点として選択されます。

獲得関数は、本質的に以下の2つの相反する目的のバランスを取るように設計されています。

  • 活用 (Exploitation): 代理モデルの予測に基づき、現時点で最良の性能を示すと期待される領域を重点的に探索する戦略。
  • 探索 (Exploration): まだ評価点が少なく、予測の不確かさが大きい未知の領域を探索する戦略。これにより、局所最適解を避け、大域的な最適解を発見する可能性が高まります。

この「活用」と「探索」のバランスをどのように調整するかによって、いくつかの種類の獲得関数が存在します。

主な獲得関数の種類

以下に、代表的な獲得関数を挙げます。

  • LCB (Lower Confidence Bound)

「信頼区間の下限」を評価指標とする手法です。最小化問題において、予測平均が小さく(活用)、かつ予測分散が大きい(探索)点ほど評価値が低くなり、次の探索点として選ばれやすくなります。数式では一般的に μ(x)−κσ(x) と表現され、パラメータ κ によって探索の度合いを調整します。

  • EI (Expected Improvement)

「期待改善量」と訳され、最も広く利用される獲得関数の一つです。現時点での最良値に対し、次に評価する点が「どれだけ改善するか」の期待値を計算します。活用と探索のバランスに優れ、多くの場合で安定した性能を示します。MATLABの例で用いられる 'expected-improvement-plus' もこの一種です。

  • PI (Probability of Improvement)

「改善確率」と訳されます。現時点での最良値を超える改善が得られる「確率」を評価指標とします。この手法は改善の「量」を考慮しないため、わずかな改善であっても確率が高ければその点を選択する傾向があり、比較的、活用に偏りやすい特性を持ちます。

6. パラメータチューニングの実装例(MATLAB実装)

本セクションでは、MATLABに組み込まれている bayesopt 関数を用いて、サポートベクターマシン(SVM)のハイパーパラメータを自動で最適化する実装例を解説します。題材として、有名な fisheriris (アヤメ) データセットの分類問題を使用します。

6.1. 準備:データの読み込みと設定

まず、モデルの学習と評価に必要なデータを準備します。

% MATLABに組み込まれている 'fisheriris' データセットを読み込み
load fisheriris;

% 特徴量 (X) とラベル (Y) にデータを分割
X = meas;
Y = species;

% 再現性のための乱数シード設定
rng default;

  • load fisheriris: 3種類のアヤメ(setosa, versicolor, virginica)を4つの特徴量(がく片・花びらの長さと幅)から分類するためのデータを読み込みます。
  • X, Y: meas(測定値)を特徴量Xに、species(種)を正解ラベルYに格納します。
  • rng default: 乱数生成器を初期状態に戻し、実行するたびに同じ結果が得られるようにします(再現性の確保)。

6.2. 最適化するハイパーパラメータの定義

次に、ベイズ最適化で探索するハイパーパラメータとその範囲を定義します。今回はSVM(RBFカーネル)の主要な2つのハイパーパラメータを対象とします。

vars = [
    optimizableVariable('BoxConstraint', [1e-3, 1e3], 'Transform', 'log')
    optimizableVariable('KernelScale', [1e-3, 1e3], 'Transform', 'log')
];

  • optimizableVariable: bayesopt で使用する変数を定義する関数です。
    • BoxConstraint (C): 誤分類に対するペナルティの大きさを制御します。
    • KernelScale (σ): RBFカーネルの影響範囲を制御します。
  • [1e-3, 1e3]: 各ハイパーパラメータの探索範囲を10^{-3}$から$10^3までとします。
  • 'Transform', 'log': 探索空間を対数スケールに変換します。これにより、0.01や0.1といった小さい値から、10や100といった大きい値まで、桁が異なる範囲を効率的に探索できます。

6.3. 目的関数の定義

ベイズ最適化の核となるのが、評価指標を計算する「目的関数」です。最適化アルゴリズムは、この関数の出力(戻り値)を最小化(または最大化)することを目指します。

% 5分割交差検証の準備
cvp = cvpartition(Y, 'KFold', 5);

% 目的関数を無名関数として定義
objFun = @(params) kfoldLoss(fitcecoc(X, Y, ...
    'Learners', templateSVM(...
        'KernelFunction', 'rbf', ...
        'BoxConstraint', params.BoxConstraint, ...
        'KernelScale', params.KernelScale, ...
        'Standardize', true), ...
    'CVPartition', cvp));

  • objFun = @(params) ...: params という入力引数(bayesoptが自動で生成するハイパーパラメータの組み合わせ)を受け取る無名関数を定義します。
  • fitcecoc: fisheriris データセットは3クラス分類のため、多クラス分類に対応したこの関数を使用します。内部では、複数の2クラスSVMを組み合わせて多クラス問題に対応します。
  • templateSVM(...): fitcecocが使用する学習器(この場合はSVM)のテンプレートを定義します。ここでbayesoptから渡されたparams.BoxConstraintparams.KernelScaleが使用されます。
  • kfoldLoss(...): 5分割交差検証(5-fold Cross-Validation)を行い、その際の平均分類誤差(損失)を計算します。この損失が目的関数の戻り値となり、最小化の対象となります。

6.4. ベイズ最適化の実行

定義した目的関数とハイパーパラメータ変数を使って、bayesopt を実行します。

results = bayesopt(objFun, vars, ...
    'MaxObjectiveEvaluations', 30, ...
    'AcquisitionFunctionName', 'expected-improvement-plus', ...
    'PlotFcn', {@plotObjectiveEvaluation, @plotMinObjective});

  • bayesopt(objFun, vars, ...): ベイズ最適化を実行するメイン関数です。
  • 'MaxObjectiveEvaluations', 30: 目的関数の評価回数(試行回数)の上限を30回に設定します。
  • 'AcquisitionFunctionName', 'expected-improvement-plus': 次に試すべきハイパーパラメータを決定するための獲得関数を指定します。
  • 'PlotFcn', {...}: 最適化の過程をリアルタイムでプロットします。ここでは「各試行での目的関数の値」と「その時点までの最小値の推移」の2つを可視化します。

6.5. 結果の確認

最適化が完了したら、得られた最良の結果を確認します。

% 最良のハイパーパラメータと、その時の最小誤差を取得
bestParams = results.XAtMinObjective;
minLoss = results.MinObjective;

fprintf('最小交差検証誤差: %.4f\n', minLoss);
fprintf('最適なBoxConstraint: %.4f\n', bestParams.BoxConstraint);
fprintf('最適なKernelScale: %.4f\n', bestParams.KernelScale);

% 最適なパラメータで最終モデルを学習
finalModel = fitcecoc(X, Y, 'Learners', ...);

  • results.XAtMinObjective: 30回の試行の中で、目的関数(交差検証誤差)が最小となった時点のハイパーパラメータの組み合わせが格納されています。
  • results.MinObjective: その時の最小誤差の値です。
  • 最終的に、見つかった最適なハイパーパラメータ bestParams を使って、データ全体で最終的なモデルを再学習します。

以下に示すGIFアニメーションは、30回のイテレーションを通じて最適化がどのように進んでいくかを示しています。
BayesOpt_SVM.gif

このアニメーションは2つの3Dプロットから構成されています。

  • 左図:代理モデル (Surrogate Model)
    左図は、これまでに観測された点(赤点)に基づき構築された、目的関数の予測形状(代理モデル)を示します。青色で示される谷状の領域は、目的関数の値が低い(すなわち、性能が良い)と予測される領域です。イテレーション(繰り返し計算)が進むにつれて観測点が増加し、この代理モデルが真の目的関数の形状へと近似していく過程を見て取れます。

  • 右図:獲得関数 (Acquisition Function)
    右図は、次に評価すべき点を決定するための獲得関数(本例ではLCB: Lower Confidence Bound)を示します。この関数値が最小となる点(紫色の星印)が、次に評価すべき最も有望な候補点として選出されます。この点は、予測される目的関数の値と、その予測の不確実性を考慮した結果であり、アルゴリズムは各イテレーションでこの点を新たな評価点として選択します。

アニメーション全体を通して、最初は広範囲に点が打たれ(探索)、有望な領域が見つかるとその谷底周辺を集中的に探索していく(活用)という、ベイズ最適化の振る舞いが視覚的に確認できます。

次に、イテレーションごとの最小損失の推移を見てみます。以下のグラフは、探索が進むにつれて見つかった最良の交差検証誤差がどのように更新されていったかを示しています。

グラフからわかるように、最初の数回のイテレーションで損失は急激に低下し、その後は緩やかに収束に向かっています。これは、ベイズ最適化が効率的に有望な領域を見つけ出し、少ない試行回数で質の高い解に到達できることを示唆しています。 20回という限られた評価回数の中で、モデルの性能が大きく改善されていることが見て取れます。

mincvl.png

7. まとめ

本記事では、ブラックボックス関数の最適値を効率的に探索するベイズ最適化について、その理論的な背景から実践的な応用までを解説しました。

はじめに探索手法の比較を通じてベイズ最適化の立ち位置を示し、次にガウス過程と獲得関数という内部メカニズムを説明しました。後半では、SVMのハイパーパラメータチューニングという具体的な課題に対し、ベイズ最適化の探索過程を3Dアニメーションで可視化することで、代理モデルと獲得関数が連携して「探索」と「活用」のバランスを取りながら最適解に収束していく様子を明らかにしました。最小誤差の推移グラフも、本手法が少ない試行回数で優れた解を発見できる効率性を示しています。
このように、ベイズ最適化はデータ駆動で次の探索点を効率よく決定するため、評価にコストがかかる問題において非常に強力なツールとなります。

8. 参考文献

  1. Gaussian Processes for Machine Learning

  2. A Tutorial on Bayesian Optimization

  3. Practical Bayesian Optimization of Machine Learning Algorithms

  4. Random Search for Hyper-Parameter Optimization

  5. Bayesian Optimization Algorithm - MATLAB Documentation

  6. Optuna: A Next-generation Hyperparameter Optimization Framework

19
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?