ガウス過程

PHYSBOではガウス過程回帰を実行しながらベイズ最適化を行なっています。

そのため、学習データが与えられた際にガウス過程回帰を実行することもでき、学習済みモデルを利用したテストデータの予測も行うことができます。

ここでは、その手順について紹介します。

探索候補データの準備

本チュートリアルでは例として、Cuの安定した界面構造の探索問題を扱います。 目的関数の評価にあたる構造緩和計算には、実際には1回あたり数時間といったオーダーの時間を要しますが、本チュートリアルでは既に評価済みの値を使用します。問題設定については、以下の文献を参照してください。 S. Kiyohara, H. Oda, K. Tsuda and T. Mizoguchi, “Acceleration of stable interface structure searching using a kriging approach”, Jpn. J. Appl. Phys. 55, 045502 (2016).

データセットファイル s5-210.csvdata ディレクトリ以下に保存し、次のように読み出します。

[1]:
import physbo

import numpy as np

def load_data():
    A =  np.asarray(np.loadtxt('data/s5-210.csv',skiprows=1, delimiter=',') )
    X = A[:,0:3]
    t  = -A[:,3]
    return X, t

X, t = load_data()
X = physbo.misc.centering( X )

学習データの定義

対象データのうち、ランダムに選んだ1割をトレーニングデータとして利用し、別のランダムに選んだ1割をテストデータとして利用します。

[2]:
N = len(t)
Ntrain = int(N*0.1)
Ntest = min(int(N*0.1), N-Ntrain)

id_all   = np.random.choice(N, N, replace=False)
id_train  = id_all[0:Ntrain]
id_test = id_all[Ntrain:Ntrain+Ntest]

X_train = X[id_train]
X_test = X[id_test]

t_train = t[id_train]
t_test = t[id_test]

print("Ntrain =", Ntrain)
print("Ntest =", Ntest)
Ntrain = 1798
Ntest = 1798

ガウス過程の学習と予測

以下のプロセスでガウス過程を学習し、テストデータの予測を行います。

  1. ガウス過程のモデルを生成します。

  2. X_train(学習データのパラメータ), t_train(学習データの目的関数値)を用いてモデルを学習します。

  3. 学習されたモデルを用いてテストデータ(X_test)に対する予測を実行します。

共分散の定義(ガウシアン)

[3]:
cov = physbo.gp.cov.gauss( X_train.shape[1],ard = False )

平均の定義

[4]:
mean = physbo.gp.mean.const()

尤度関数の定義(ガウシアン)

[5]:
lik = physbo.gp.lik.gauss()

ガウス過程モデルの生成

[6]:
gp = physbo.gp.model(lik=lik,mean=mean,cov=cov)
config = physbo.misc.set_config()

ガウス過程モデルを学習

[7]:
gp.fit(X_train, t_train, config)
Start the initial hyper parameter searching ...
Done

Start the hyper parameter learning ...
0 -th epoch marginal likelihood 16051.69452976001
50 -th epoch marginal likelihood 4551.39626443153
100 -th epoch marginal likelihood 2141.377872729846
150 -th epoch marginal likelihood 595.8361411907399
200 -th epoch marginal likelihood -373.23922309413774
250 -th epoch marginal likelihood -929.2472009209496
300 -th epoch marginal likelihood -1273.8727959019732
350 -th epoch marginal likelihood -1413.2553901394206
400 -th epoch marginal likelihood -1477.3889625983586
450 -th epoch marginal likelihood -1525.339082571432
500 -th epoch marginal likelihood -1539.787541261617
Done

学習されたガウス過程におけるパラメタを出力

[8]:
gp.print_params()


likelihood parameter =   [-2.57036368]
mean parameter in GP prior:  [-1.0654197]
covariance parameter in GP prior:  [-0.59460765 -2.4232173 ]


テストデータの平均値(予測値)および分散を計算

[9]:
gp.prepare(X_train, t_train)
fmean = gp.get_post_fmean(X_train, X_test)
fcov = gp.get_post_fcov(X_train, X_test)

予測の結果

[10]:
fmean
[10]:
array([-1.01865696, -0.98356729, -0.97797072, ..., -0.99978278,
       -0.98145533, -0.9956255 ])

分散の結果

[11]:
fcov
[11]:
array([0.00046688, 0.0010622 , 0.0006136 , ..., 0.00043492, 0.0005969 ,
       0.00053435])

予測値の平均二乗誤差の出力

[12]:
np.mean((fmean-t_test)**2)
[12]:
0.004179032574484333

訓練済みモデルによる予測

学習済みモデルのパラメタをgp_paramsとして読み出し、これを用いた予測を行います。

gp_paramsおよび学習データ(X_train, t_train)を記憶しておくことで、訓練済みモデルによる予測が可能となります。

学習されたパラメタを準備(学習の直後に行う必要あり)

[13]:
#学習したパラメタを1次元配列として準備
gp_params =  np.append(np.append(gp.lik.params, gp.prior.mean.params), gp.prior.cov.params)

gp_params
[13]:
array([-2.57036368, -1.0654197 , -0.59460765, -2.4232173 ])

学習に利用したモデルと同様のモデルをgpとして準備

[14]:
#共分散の定義 (ガウシアン)
cov = physbo.gp.cov.gauss( X_train.shape[1],ard = False )

#平均の定義
mean = physbo.gp.mean.const()

#尤度関数の定義 (ガウシアン)
lik = physbo.gp.lik.gauss()

#ガウス過程モデルの生成
gp = physbo.gp.model(lik=lik,mean=mean,cov=cov)

学習済みのパラメタをモデルに入力し予測を実行

[15]:
#学習済みのパラメタをガウス過程に入力
gp.set_params(gp_params)


#テストデータの平均値(予測値)および分散を計算
gp.prepare(X_train, t_train)
fmean = gp.get_post_fmean(X_train, X_test)
fcov = gp.get_post_fcov(X_train, X_test)

予測の結果

[16]:
fmean
[16]:
array([-1.01865696, -0.98356729, -0.97797072, ..., -0.99978278,
       -0.98145533, -0.9956255 ])

分散の結果

[17]:
fcov
[17]:
array([0.00046688, 0.0010622 , 0.0006136 , ..., 0.00043492, 0.0005969 ,
       0.00053435])

予測値の平均二乗誤差の出力

[18]:
np.mean((fmean-t_test)**2)
[18]:
0.004179032574484333

(注) 上の例では事前に登録されているXと同じものを利用して予測を行いました。 学習済みのモデルを利用してXに含まれていないパラメータ X_new に対して予測をしたい場合には、 学習モデルで使用したデータXの平均(X_{mean})と標準偏差(X_{std})を求めていただいたうえで、 X_{new} = (X_{new} - X_{mean}) / X_{std} の変形を行うことで予測を行うことができます。 また、渡す際のデータ形式はndarray形式になっています。 そのため、X_{new}が一つのデータの場合には事前に変換する必要があります。 例えば、X_{new}が実数である場合には、 X_new = np.array(X_new).reshape(1) などとして変換する必要があります。