CmdStanPy試用記
StanをWindowsで利用するためにCmdStanPyをインストールしたが、動作しなかった。WindowsにインストールしたUbuntu上でCmdStanPyをインストールすると、Ubuntu上では利用できた。以下は、その備忘録である。なお、CmdStanPyのサンプルスクリプトを、サンプル1,サンプル2などに用意している。
なお、WSLでは他のOS、例えばFedoraを試してみることもできる。FedoraをWSLでインストールする方法は、後半で説明している。
WSLにインストールしたLinuxのメモリ容量が足りないときの1つの対策法をSwapメモリの利用で説明した。
1つのOSの下でCmdStanPyによりコンパイルしたとき、コンパイルの結果がファイルに残されている。この状態で、同じスクリプトを別のOSの下でCmdStanPyによる実行を行おうとするとエラーが出る。先のOSの下でコンパイルした結果を削除すれば、エラーは出なくなる。削除するファイル名は、Stanスクリプトファイル名から拡張子を除いたものである。bin_model.stanであれば、bin_modelである。
あるいは、削除せずに、強制的にコンパイルすることもできる。強制的にコンパイルするときは、「force_compile=True」パラメータを付ければよい。例えば、
model =
CmdStanModel(stan_file="bin_model.stan", force_compile=True)
である。強制的にコンパイルすれば、そのとき使用している環境に合わせてコンパイルされ、実行できる。コンパイル・実行ができたら、2回目からは強制的にコンパイルする必要はないので、パラメータ「force_compile=True」を外せばよい。
WindowsへのUbuntuのインストール
WindowsへのUbuntuのインストールについては、このウェブサイトでも説明している。
インストールしたUbuntuにMiniCondaをインストールする。このウェブサイトではAnacondaが説明されているが、MiniCondaも同様である。
UbuntuでのCmdStanPyのインストール
CmdStanPyのインストールの前に、g++が使えることを確認しておく。
Ubuntuの端末において、コマンドg++を入力したときに、入力ファイル名が指定されていませんというようなメッセージが返ってきたらOKである。コマンドg++はありませんというようなメッセージが返ってきたときは、メッセージとともにインストールコマンドも示されているので、それを実行する。簡単なコマンドでg++のインストールができる。
CmdStanPyを、MiniCondaの仮想環境としてmystanという名前の仮想環境を用意して、mystanにCmdStanPyをインストールするときは、次のコマンドを実行すればよい。
(base)
yasuh@pcyo:/$ conda create -n mystan -c conda-forge cmdstanpy
仮想環境mystanが作成されたら、次のコマンドでmystanをアクティブにした後、アップデートを行う。
(base) yasuh@pcyo:/$ conda activate
mystan
(mystan) yasuh@pcyo:/$ conda update
--all
アップデートが終了したら、ライブラリarvizを追加インストールしておく。
(mystan)
yasuh@pcyo:/$ conda install arviz
以上の準備で、次のサンプルスクリプトが実行できる。
Stanスクリプトのファイルbin_model.stanと、それを用いてMCMCサンプリングを行うPythonスクリプトのファイルbin_model.pyを同じフォルダ内に作成する。
リスト1 Stanスクリプトファイル(bin_model.stan)
data {
int k;
int n;
}
parameters {
real<lower=0, upper=1>
p;
}
model {
p ~ beta(1,1);
k ~ binomial(n, p);
}
リスト1のStanスクリプトのファイルbin_model.stanを用いるPythonスクリプトをリスト2のように用意した。
リスト2 Stanスクリプトファイルを実行するPythonスクリプト(bin_model.py)
from cmdstanpy import CmdStanModel
import arviz as az
import matplotlib.pyplot as plt
model =
CmdStanModel(stan_file="bin_model.stan") # コンパイル
fit = model.sample(data={'n':10,
'k':7})
# サンプリング
print(fit.summary())
dframe = fit.draws_pd()
# Pandas DataFrameへ変換
print('\nPandas DataFrame
format\n',dframe)
inf_data = az.from_cmdstanpy(fit)
# Arviz(az)用のデータに変換
az.plot_trace(inf_data,
figsize=(10,3))
# トレースプロット
plt.tight_layout()
plt.show()
リスト1とリスト2のスクリプトbin_model.pyの格納されているフォルダにカレントディレクトリを移して、次のコマンドで実行する。
(mystan)
*****/samplefiles$ python bin_model.py
リスト1のStanスクリプトがコンパイルされ(多少時間が掛かる)、実行されると、図1のようにトレース図が表示される。

図1
トレース図の右上のX印アイコンをクリックして閉じると、スクリプトの実行終了となる(図2)。

図2
WSLではいろいろなOSが用意されている。コマンドwsl --list --onlineを実行すると以下のリストが表示される。
PS C:\Users\yasuh> wsl --list --online
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl.exe
--install <Distro>' を使用してインストールします。
NAME
FRIENDLY NAME
AlmaLinux-8
AlmaLinux OS 8
AlmaLinux-9
AlmaLinux OS 9
AlmaLinux-Kitten-10
AlmaLinux OS Kitten 10
AlmaLinux-10
AlmaLinux OS 10
Debian
Debian GNU/Linux
FedoraLinux-42
Fedora Linux 42
SUSE-Linux-Enterprise-15-SP6 SUSE Linux Enterprise 15 SP6
SUSE-Linux-Enterprise-15-SP7 SUSE Linux Enterprise 15 SP7
Ubuntu
Ubuntu
Ubuntu-24.04
Ubuntu 24.04 LTS
archlinux
Arch Linux
kali-linux
Kali Linux Rolling
openSUSE-Tumbleweed
openSUSE Tumbleweed
openSUSE-Leap-16.0
openSUSE Leap 16.0
Ubuntu-20.04
Ubuntu 20.04 LTS
Ubuntu-22.04
Ubuntu 22.04 LTS
OracleLinux_7_9
Oracle Linux 7.9
OracleLinux_8_10
Oracle Linux 8.10
OracleLinux_9_5
Oracle Linux 9.5
openSUSE-Leap-15.6
openSUSE Leap 15.6
PS C:\Users\yasuh>
Fedoraをインストールするときは、次のコマンドを実行すればよい。
wsl.exe --install FedoraLinux-42
インストールの途中で、画面に何の変化も無く長時間待たされたときは、Enterキーを押すと次に進むようである。
インストール後、再起動してアップデートするときは、コマンド
sudo dnf
update
である。再起動は、コマンドexitで一旦端末を閉じてから、WindowsのスタートメニューでFedoraLinux-42を選べばよい。
他は、Ubuntuのときと同じ要領である。
試用しているPCの場合、メモリ構成は以下のようである。
(base) yasuharu@pcyo:~$ sudo swapon -s
Filename
Type
Size
Used
Priority
/dev/sdc
partition
2097152
0
-2
(base) yasuharu@pcyo:~$ sudo free -h
total
used
free
shared buff/cache available
Mem:
7.6Gi
497Mi
6.9Gi
3.5Mi
383Mi
7.1Gi
Swap:
2.0Gi
0B
2.0Gi
(base) yasuharu@pcyo:~$
この状態で、次のスクリプトを実行してみる。
import numpy as np
s = 1_000_000_000
n = 2
XX = []
for i in range(n):
x =
np.random.uniform(low=0.0, high=1.0, size=s)
print(x[:5])
mn = np.mean(x)
print(mn)
XX.append([mn,x])
input('OK?')
実行結果は、以下のようになる。
(py312)
yasuharu@pcyo:/mnt/c/WorkSpace/temp$ python check.py
[0.14370422 0.48088377 0.40278804
0.36061043 0.51716028]
0.4999906101749073
Killed
(py312)
yasuharu@pcyo:/mnt/c/WorkSpace/temp$
「Killed」で、終了している。
上のスクリプトを、次の環境で実行してみる。
(base) yasuh@pcyo:~$ sudo swapon -s
Filename
Type
Size
Used
Priority
/dev/sdc
partition
2097152
0
-2
/home/swapfile
file
10239996
0
-3
(base) yasuh@pcyo:~$ sudo free -h
total
used
free
shared buff/cache available
Mem:
7.6Gi
487Mi
6.7Gi
3.5Mi
516Mi
7.1Gi
Swap:
11Gi
0B
11Gi
(base) yasuh@pcyo:~$
実行すると、以下のような出力となり、問題なく実行出来たことが分かる。
(py312)
yasuh@pcyo:/mnt/c/WorkSpace/temp$ python check.py
[0.52181698 0.38987926 0.42528752
0.00524283 0.21780301]
0.4999878463705383
[3.27675508e-02 3.19905922e-01
3.26551148e-04 7.67658546e-01
9.08998493e-01]
0.4999873339159528
OK?
(py312)
yasuh@pcyo:/mnt/c/WorkSpace/temp$
Swapファイルを設定しても、再起動すると設定が設定前の状態に戻っていることがある。
Swapファイルは残っているので、swaponコマンドで再度Swapファイルとして設定することができる。
(py312)
yasuh@pcyo:/mnt/c/WorkSpace/temp$ sudo swapon -s
Filename
Type
Size
Used
Priority
/dev/sdc
partition
2097152
3792
-2
(py312)
yasuh@pcyo:/mnt/c/WorkSpace/temp$ sudo free -h
total
used
free
shared buff/cache available
Mem:
7.6Gi
452Mi
7.2Gi
3.2Mi
73Mi
7.1Gi
Swap:
2.0Gi
3.7Mi
2.0Gi
(py312)
yasuh@pcyo:/mnt/c/WorkSpace/temp$ cd /home
(py312) yasuh@pcyo:/home$ ls
swapfile yasuh
(py312) yasuh@pcyo:/home$ sudo swapon
/home/swapfile
(py312) yasuh@pcyo:/home$ sudo swapon
-s
Filename
Type
Size
Used
Priority
/dev/sdc
partition
2097152
3792
-2
/home/swapfile
file
10239996
0
-3
(py312) yasuh@pcyo:/home$ sudo free -h
total
used
free
shared buff/cache available
Mem:
7.6Gi
460Mi
7.2Gi
3.2Mi
74Mi
7.1Gi
Swap:
11Gi
3.7Mi
11Gi
(py312) yasuh@pcyo:/home$