変数変換の手法

一般的に、QA-BBO で活用するイジングマシンは、バイナリ決定変数のみを直接考慮可能です。一方で、一般のブラックボックス最適化問題では、バイナリ変数だけでなく、整数決定変数や実数決定変数、そしてこれらの混合が考慮されることが有ります。このように、非バイナリ決定変数に対応するために、Amplify-BBOptは必要に応じて変数変換を内部的に実施します。

変数変換のタイミング

変数変換が必要な場合(決定変数に整数や実数変数が含まれる場合)、以下に説明する 2 つのタイミング、pre-encoding および post-encoding、のいずれかで実施されます。どのタイミングで変数変換を実施するかは、Optimizer() のインスタンス化時に、pre_encoding 引数を指定する形で、次のように指定できます。デフォルトは、pre_encoding = True です。

from amplify_bbopt import Optimizer

# 最適化クラスのインスタンス化 (pre-encoding を採用する場合 (デフォルト))
optimizer = Optimizer(
    blackbox_func,
    trainer,
    client,
    pre_encoding=True,
)

# 最適化クラスのインスタンス化 (post-encoding を採用する場合)
optimizer = Optimizer(
    blackbox_func,
    trainer,
    client,
    pre_encoding=False,
)

Note

上記コード内の blackbox_func, trainer 及び client, はそれぞれ、事前に定義したブラックボックス関数、サロゲートモデル関数、Amplify SDK ソルバークライアントとなります。これらの準備については「最適化の実行」を参照してください。

Pre-encoding(プリ・エンコーディング、デフォルト)

Pre-encoding は、サロゲートモデル関数の構築よりにエンコーディングを行う変数変換方法です。サロゲートモデルの構築には、エンコーディング後の学習データが考慮されるため、サロゲートモデルへの入力はバイナリ値のみとなります。エンコーディングの副次的な効果で、サロゲートモデル関数の次数以上の表現が可能という特徴があります。

Pre-encoding による変数変換は、Amplify-BBOpt 内で実施します。以下の図は、pre-encodingに係る処理フローです。

_images/pre_encoding.drawio.svg

Post-encoding(ポスト・エンコーディング)

Post-encoding は、サロゲートモデル関数の構築よりにエンコーディングを行う変数変換方法です。サロゲートモデルの構築にはユーザーから与えられた元々の学習データがそのまま使われるため、サロゲートモデルへの入力は、元の入力データの内容に依存します。サロゲートモデルが表現可能な関数形は、サロゲートモデルで考慮される多項式の次数(通常は 2 次)となります。

Post-encoding による変数変換は、Amplify-BBOpt内または Amplify SDK の内部処理で実施します。以下の図は、post-encodingに係る処理フローです。EncodingMethod は、次に説明するエンコーディングに関するクラスです。

_images/post_encoding.drawio.svg

エンコーディングの種類と設定

Pre-encoding と併用できるエンコーディング手法

Pre-encoding で使えるエンコーディングの種類は、domain-wall(デフォルト)と one-hot エンコーディングです。これらのエンコーディング方法は、EncodingMethod クラスを使い指定します。

  • EncodingMethod クラス

    エンコーディングに関するクラスで、アトリビュートとして DomainWall (domain-wall) と OneHot (one-hot) を選択可能です(デフォルトは domain-wall)。決定変数の定義時に次のように指定します。

    例:整数変数と実数変数に対してエンコーディング手法を選択

    >>> from amplify_bbopt import EncodingMethod, IntegerVariable, RealVariable
    
    >>> z_0 = IntegerVariable(bounds=(0, 5), encoding=EncodingMethod.OneHot)
    >>> x_0 = RealVariable(bounds=(0, 1.5), encoding=EncodingMethod.OneHot)
    >>> print(z_0.encoding.method)
    EncodingMethod.OneHot
    >>> print(x_0.encoding.method)
    EncodingMethod.OneHot
    

    例:整数変数と実数変数に対してエンコーディング手法を選択

    >>> from amplify_bbopt import EncodingMethod, IntegerVariable, RealVariable
    
    >>> z_1 = IntegerVariable(bounds=(0, 5))
    >>> x_1 = RealVariable(bounds=(0, 1.5))
    >>> print(z_1.encoding.method)
    EncodingMethod.DomainWall
    >>> print(x_1.encoding.method)
    EncodingMethod.DomainWall
    

また、実数決定変数の場合、bounds で指定された値域を離散点で離散化する必要があります。このような離散化に関する設定は、以下の表に示す DiscretizationSpec クラス と DiscretizationMethod クラスにより行います。

  • DiscretizationSpec クラス

    離散化に関するクラスで、アトリビュートとして method(離散化手法)と num_bins(離散点)を設定することができます。デフォルトでは、method=DiscretizationMethod.Uniform および num_bins=11 が考慮されます。つまり、11 点の離散点により等間隔に離散化された離散値を実数と見なして最適化を行います。

    ここで、DiscretizationMethod は、離散化手法を表すクラスで、Uniform(等間隔な離散化)または LogUniform(対数一様な離散化)を選択可能です。

    例:実数変数に対して、離散点数を設定する場合

    >>> from amplify_bbopt import DiscretizationSpec, RealVariable
    
    >>> x_2 = RealVariable(
    ...     bounds=(1.0, 4.0),
    ...     discretization_spec=DiscretizationSpec(num_bins=7),
    ... )
    >>> print(x_2.possible_values)
    [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
    

    例:実数変数に対して、離散点数と離散化手法を設定する場合

    >>> from amplify_bbopt import RealVariable, DiscretizationSpec, DiscretizationMethod
    
    >>> x_3 = RealVariable(
    ...     bounds=(1.0, 4.0),
    ...     discretization_spec=DiscretizationSpec(
    ...         method=DiscretizationMethod.LogUniform,
    ...         num_bins=7,
    ...     ),
    ... )
    >>> print(x_3.possible_values)
    [1.0, 1.2599210498948732, 1.5874010519681994, 2.0, 2.5198420997897464, 3.174802103936399, 4.0]
    

    Caution

    離散化手法として、対数一様な離散化 DiscretizationMethod.LogUniform を選択する場合、実数変数の値域は正である必要があります。

    >>> from amplify_bbopt import RealVariable, DiscretizationSpec, DiscretizationMethod
    
    >>> x_3 = RealVariable(
    ...     bounds=(0.0, 4.0),
    ...     discretization_spec=DiscretizationSpec(
    ...         method=DiscretizationMethod.LogUniform
    ...     ),
    ... )
    Traceback (most recent call last):
        ...
    ValueError: Lower bound must be greater than 0 for `LogUniform` discretization.
    

Post-encoding と併用できるエンコーディング手法

Post-encoding で使えるエンコーディングの種類は、EncodingMethod.AmplifyEncodingMethod.Amplify に加え、EncodingMethod.Amplify です。EncodingMethod.Amplify をエンコーディング手法として選択した場合は、Amplify SDK 内部で、Amplify SDK のデフォルトの手法に基づき、変数変換が実施されます。

Amplify SDK 内部での変数変換の詳細は、Amplify SDK のドキュメントページ、整数変数からバイナリ変数への変換 および 実数変数からバイナリ変数への変換 を参照してください。