PickleとStan
Pickleを使うとStanを用いたPythonスクリプトの開発の効率が上がる。簡単なStanスクリプトの場合は、Pickleを用いるとその分Pythonスクリプトの量が増えるだけであるが、Stanスクリプトのコンパイル・ビルドに時間が掛かる場合とかStanによるサンプリングに時間が掛かるときは、Stanスクリプトが一応出来上がった後は、そのコンパイル・ビルド結果をファイルに保存しておけば、その後はそのファイルを読み込むだけでサンプリングの実行ができるので、コンパイル・ビルドの時間を省くことができる。また、Stanによるサンプリング結果をファイルに保存しておけば、サンプリングに基づく分析のPythonスクリプトの開発は、ファイルに保存したサンプルを読み出して行うことができるので、サンプリングが長時間掛かる場合には、分析のPythonスクリプトの開発の効率向上になる。Pickleを使った簡単な例を以下に説明する。
なお、岡本安晴(著)「いまさら聞けないPythonでデータ分析―多変量解析,ベイズ統計分析(PyStan,PyMC)―」でStanの説明を行っている。
次のStanスクリプトを用いる。
========== sample.stan ==========
data {
int<lower = 2> N;
real X[N];
}
parameters {
real mu;
real<lower = 0.0>
sigma;
}
model {
for (i in 1:N)
X[i]
~ normal(mu, sigma);
}
===========================
上のStanスクリプトを次のPythonスクリプトで実行する。
===========================
import pystan;
X = [3, 7, 5]
N = 3
Data = {'N': N, 'X': X}
fit = pystan.stan(file =
'sample.stan', data = Data, seed = 123, n_jobs = 1)
print(fit)
===========================
実行結果は図1のようになる。
図1
次にpickleを用いた次のスクリプトを用意する。
=========================================
import pystan;
from pystan import StanModel
import pickle
X = [3, 7, 5]
N = 3
Data = {'N': N, 'X': X}
sm = StanModel(file = 'sample.stan')
with open('model.pkl', 'wb') as f:
pickle.dump(sm, f)
fit = sm.sampling(data = Data, seed =
123, n_jobs = 1)
with open('fit.pkl', 'wb') as g:
pickle.dump(fit, g)
print(fit)
==========================================
Stanスクリプトをコンパイル・ビルドしてsmで表し、pickle.dumpでファイルmodel.pklに保存するスクリプトは以下のようになる。
sm = StanModel(file = 'sample.stan')
with open('model.pkl', 'wb') as f:
pickle.dump(sm, f)
コンパイル・ビルドされたsmによりサンプリングを行い、その結果をfitで表して、pickle.dumpによってファイルfit.pklに保存するスクリプトは以下のようになる。
fit = sm.sampling(data = Data, seed = 123, n_jobs = 1)
with open('fit.pkl', 'wb') as g:
pickle.dump(fit, g)
モデルsmによるサンプリング結果fitは
print(fit)
によって出力されているが(図2)、図1と同じサンプリング結果である。
図2
上のスクリプトの実行により、Stanモデルはファイルmodel.pklに、サンプリング結果はファイルfit.pklに保存されている。まず、model.pklを読みだして使う次のスクリプトを作成した。
=====================================
import pystan;
from pystan import StanModel
import pickle
X = [3, 7, 5]
N = 3
Data = {'N': N, 'X': X}
sm1 = pickle.load(open('model.pkl',
'rb'))
fit = sm1.sampling(data = Data, seed =
123, n_jobs = 1)
print(fit)
========================================
実行結果は図3に示すように、図2と同じである。
図3
次に、サンプリング結果の保存ファイルfit.pklを読み出すスクリプトを以下のように用意した。
================================
import pystan;
from pystan import StanModel
import pickle
sm2 = pickle.load(open('model.pkl',
'rb'))
fit = pickle.load(open('fit.pkl',
'rb'))
print(fit)
================================
サンプリングを行ったモデルのファイルmodel.pklが、fit.pklの読み込みの前に読み込まれていることに注意。
サンプリング結果をfitに読み込み、print関数によって出力したものを図4に示す。図3と同じである。
図4
保存されたモデルは、読み込んで他のデータに対して使うことができる。例を次に示す。
=======================================
import pystan;
from pystan import StanModel
import pickle
X = [30, 70, 50]
N = 3
Data = {'N': N, 'X': X}
sm3 = pickle.load(open('model.pkl',
'rb'))
fit = sm3.sampling(data = Data, seed =
123, n_jobs = 1)
print(fit)
=======================================
実行結果を図5に示す。
図5