12
8

More than 3 years have passed since last update.

physboを使って多目的最適化問題をベイズ最適化で解いてみた

Last updated at Posted at 2021-03-27
  • 製造業出身のデータサイエンティストがお送りする記事
  • 今回はphysboを使って多目的最適化問題をベイズ最適化で解いてみました。

はじめに

過去に多目的最適化問題については、記事を何個か書いておりますので参考にして頂けますと幸いです。

使用するライブラリー(physbo)

今回は最適化ライブラリphysboを使って実装したいと思います。

physboの実装

今回は実装サンプルを試してみました。

# 必要なライブラリーのインストール
import numpy as np
import matplotlib.pyplot as plt
import physbo
import itertools
%matplotlib inline

次にテスト関数を作成します。

def vlmop2_minus(x):
    n = x.shape[1]
    y1 = 1 - np.exp(-1 * np.sum((x - 1/np.sqrt(n)) ** 2, axis = 1))
    y2 = 1 - np.exp(-1 * np.sum((x + 1/np.sqrt(n)) ** 2, axis = 1))

    return np.c_[-y1, -y2]

探索範囲を指定します。

a = np.linspace(-2, 2, 101)
test_X = np.array(list(itertools.product(a, a)))

シミュレータを定義します。

class simulator(object):
    def __init__(self, X):
        self.t = vlmop2_minus(X)

    def __call__( self, action):
        return self.t[action]

simu = simulator(test_X)

今回の設定した関数は、1つは右上にピークがあり、1つは左下にピークがある関数です。
可視化すると以下のような感じです。

# plot objective 1
plt.figure()
plt.imshow(simu.t[:,0].reshape((101,101)),
           vmin=-1.0,
           vmax=0.0,
           origin="lower",
           extent=[-2.0, 2.0, -2.0, 2.0]
          )
plt.title("objective 1")
plt.colorbar()
plt.plot([1.0/np.sqrt(2.0)],
         [1.0/np.sqrt(2.0)],
         '*'
        )
plt.show()

image.png

# plot objective 2
plt.figure()
plt.imshow(simu.t[:,1].reshape((101,101)),
           vmin=-1.0,
           vmax=0.0,
           origin="lower",
           extent=[-2.0, 2.0, -2.0, 2.0]
          )
plt.title("objective 2")
plt.colorbar()
plt.plot([-1.0/np.sqrt(2.0)],
         [-1.0/np.sqrt(2.0)],
         '*'
        )
plt.show()

image.png

次に最適化を実行していきます。
* policyのセット
* 多目的最適化用のphysbo.search.discrete_multi.policyを利用
* num_objectivesに目的関数の数を指定

policy = physbo.search.discrete_multi.policy(test_X=test_X,
                                             num_objectives=2
                                            )
policy.set_seed(0)

ベイズ最適化は、下記3パターンの方法があるそうです。
* HVPI (Hypervolume-based Probability of Improvement)
* EHVI (Expected Hyper-Volume Improvement)
* TS (Thompson Sampling)

今回はHVPIを使用してみたいと思います。

HVPI (Hypervolume-based Probability of Improvement)は、多次元の目的関数空間における非劣解領域 (non-dominated region) の改善確率をscoreとして算出する手法だそうです。

policy = physbo.search.discrete_multi.policy(test_X=test_X,
                                             num_objectives=2
                                            )
policy.set_seed(0)

policy.random_search(max_num_probes=10,
                     simulator=simu
                    )
res_HVPI = policy.bayes_search(max_num_probes=40,
                               simulator=simu,
                               score='HVPI',
                               interval=10
                              )

パレート解の取得は以下のコードでできます。

front, front_num = res_HVPI.export_pareto_front()
front, front_num

結果はこんな感じで返ってきます。
各目的変数の値と対象のインデックス番号が得られます。

(array([[-9.82978321e-01, -3.32414921e-04],
        [-9.71056940e-01, -3.45637262e-02],
        [-9.50786244e-01, -6.76228653e-02],
        [-9.34458810e-01, -1.15668709e-01],
        [-9.13824628e-01, -1.71906452e-01],
        [-8.88492700e-01, -2.36876025e-01],
        [-8.68576210e-01, -2.82707709e-01],
        [-8.57549341e-01, -3.05692550e-01],
        [-8.33710080e-01, -3.53626320e-01],
        [-8.20907701e-01, -3.78330099e-01],
        [-7.92933832e-01, -4.26778524e-01],
        [-7.77704642e-01, -4.50447880e-01],
        [-7.62117827e-01, -4.74823143e-01],
        [-7.45438101e-01, -4.98117246e-01],
        [-7.28459156e-01, -5.21910482e-01],
        [-7.14031659e-01, -5.50368010e-01],
        [-6.92015440e-01, -5.67552511e-01],
        [-6.72522879e-01, -5.89370083e-01],
        [-6.52909089e-01, -6.11332656e-01],
        [-6.32120559e-01, -6.32120559e-01],
        [-6.11332656e-01, -6.52909089e-01],
        [-5.89370083e-01, -6.72522879e-01],
        [-5.70311337e-01, -6.93980247e-01],
        [-5.44575729e-01, -7.10347737e-01],
        [-5.21910482e-01, -7.28459156e-01],
        [-4.98117246e-01, -7.45438101e-01],
        [-4.74823143e-01, -7.62117827e-01],
        [-4.26778524e-01, -7.92933832e-01],
        [-4.02089723e-01, -8.07119688e-01],
        [-3.90152305e-01, -8.24313473e-01],
        [-3.53626320e-01, -8.33710080e-01],
        [-3.05692550e-01, -8.57549341e-01],
        [-2.58961961e-01, -8.78749507e-01],
        [-2.16642598e-01, -8.97780597e-01],
        [-1.71906452e-01, -9.13824628e-01],
        [-1.15668709e-01, -9.34458810e-01],
        [-6.76228653e-02, -9.50786244e-01],
        [-3.51124618e-02, -9.67608404e-01],
        [-1.46847591e-03, -9.78680443e-01]]),
 array([21, 15, 35, 26, 32, 18, 43, 27, 40, 16, 31, 49, 23, 47, 33, 12, 34,
        45, 22, 44, 28, 41, 13, 42, 29, 48, 19, 30, 46, 10, 37, 24, 38, 17,
        36, 25, 39, 11, 20]))

パレート解の可視化は以下のような感じでできます。

def plot_pareto_front(res):
    front, front_num = res.export_pareto_front()
    dominated = [i for i in range(res.num_runs) if i not in front_num]
    points = res.fx[dominated, :]

    plt.figure(figsize=(7, 7))
    plt.scatter(res.fx[dominated,0], res.fx[dominated,1], c = "blue")
    plt.scatter(front[:, 0], front[:, 1], c = "red")
    plt.title('Pareto front')
    plt.xlabel('Objective 1')
    plt.ylabel('Objective 2')
    plt.xlim([-1.0, 0.0])
    plt.ylim([-1.0, 0.0])

plot_pareto_front(res_HVPI)

image.png

ちなみに全探索もできます。

policy = physbo.search.discrete_multi.policy(test_X=test_X,
                                             num_objectives=2
                                            )
policy.set_seed(0)

N = test_X.shape[0]
res_all = policy.random_search(max_num_probes=N,
                               simulator=simu
                              )

plot_pareto_front(res_all)

image.png

さいごに

最後まで読んで頂き、ありがとうございました。
今回は、physboを使って多目的最適化問題をベイズ最適化を使って解きました。
今回は単純な問題だったので時間はかかりませんでしたが、複雑な問題となった場合、実行時間がどこまでかかるのかは気になりました。
時間がある時に試してみようと思います。

訂正要望がありましたら、ご連絡頂けますと幸いです。

12
8
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
12
8