Ubuntu 16.04 で pystan を動かす

MCMC サンプラー Stan を Python から呼び出すためのライブラリ pystan を使ってみようとしたら ABI 問題のせいでちょっと嵌ったのでここにメモしておく。

Anaconda3-4.3.0-Linux-x86_64 をインストールした。 そして pystan を pip でインストールした。

pip install pystan

この状態で pystan を使ってみたところ、モデルをコンパイルするところで以下のようなエラーが出た。

>>> stanmodel = StanModel(file='model/model5-3.stan')
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-5-4435d7d1dfc2> in <module>()
----> 1 stanmodel = StanModel(file='model/model5-3.stan')
      2 stanmodel

/home/nojima/anaconda3/lib/python3.6/site-packages/pystan/model.py in __init__(self, file, charset, model_name, model_code, stanc_ret, boost_lib, eigen_lib, verbose, obfuscate_model_name, extra_compile_args)
    313                 os.dup2(orig_stderr, sys.stderr.fileno())
    314 
--> 315         self.module = load_module(self.module_name, lib_dir)
    316         self.module_filename = os.path.basename(self.module.__file__)
    317         # once the module is in memory, we no longer need the file on disk

/home/nojima/anaconda3/lib/python3.6/site-packages/pystan/model.py in load_module(module_name, module_path)
     48         pyximport.install()
     49         sys.path.append(module_path)
---> 50         return __import__(module_name)
     51     else:
     52         import imp

ImportError: /tmp/tmppaa8t0sa/stanfit4anon_model_d6577da659c87ba489087107d1a725f1_1731976423115490565.cpython-36m-x86_64-linux-gnu.so: undefined symbol: _ZTVNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE

これは、最近 libstdc++ の ABI の変更があり、Ubuntu 16.04 デフォルトの gcc に同梱されている libstdc++ は新しい ABI のものだが、Anaconda に同梱されているライブラリは古い ABI を使っており、うまくリンクできないのが理由っぽい。

ということで、Anaconda が利用しているバージョンである gcc-4.8 をインストールする。 幸いなことに Ubuntu 16.04 には gcc-4.8 パッケージが存在しているため、それを apt-get するだけでインストールできる。

sudo apt-get install gcc-4.8 g++-4.8

この方法でインストールした gccgcc-4.8 という名前で参照できる。gcc コマンドは依然として 5.4 であることに注意。

次に、Cython が gcc-4.8コンパイルに使うようにしなければならない。このためには CC 環境変数gcc-4.8 を指定すればよいらしい。

するとうまくコンパイルできた。

In [1]: from pystan import StanModel

In [2]: import os

In [3]: os.environ['CC'] = 'gcc-4.8'

In [4]: stanmodel = StanModel(file='model/model5-3.stan')
INFO:pystan:COMPILING THE C++ CODE FOR MODEL anon_model_d6577da659c87ba489087107d1a725f1 NOW.

In [5]:

記念にトレースプロットを貼っておく。

f:id:nojima718:20170304173332p:plain