Stan Advent Boot Camp 第一日目; Stanの導入


はじめに

気がついたら12月だなんて信じらんない!今年はイベントが少なかったから,何もしてないうちに一年が終わろうとしている・・・。
でも12月はやっぱりちょっとウキウキする月でもありますね。だってアドベントカレンダーがあるんだから。

さて,このカレンダーを開設した私@kosugittiは,とある大学の教員をしておりますが,同時に広島ベイズ塾という読書会のメンバーでもあります。ベイズ塾はベイズ統計を勉強する読書会。具体的な研究への応用については,はほとんどStanを使ったものになっています。Stanのおかげで今の私たちがあると言っても過言じゃない。
ということで,今日から10日ほど集中的に,塾生によるStanをつかった入門講座をやっていきますので,興味がある人は是非毎日の記事を楽しみにしてください。

あ,別に塾生でないとこのアドカレを書いてはいけないというわけではないんですよ。むしろもっといろんな人に協力してもらいたいのですが,11月25日の段階で結構空きがあったから,空っぽにしておくのもさみしいので,シリーズ物で楽しんでいただこうということで,塾生に声をかけたというだけですので。このキャンプは10-11日ぐらいで終わるので,そのあとは例年通りのカレンダーとして,インターネット民のみなさんで作って楽しんでいってください。

ちなみにベイズ塾のアドカレもあります。どんなやつらが何をやってるんだろ,と興味を持ったら覗いてみてください。

内容概略

この記事は初日ということで,そもそもStanってなんだろうというところから語っていきます。五年前に書いたものがたまに今でもファボられたと言う通知が来たりするんですが,流石にちょっと説明が古くなっているところもありますので,この記事で情報のアップデートとさせていただきます。

対象者として次のような人を想定して記事を書いています。

  • 統計は学んでいる・学んだことがあるけどベイズ統計は聞いたことがある
  • パソコンは持っててアプリは使うけど,プログラミングは経験したことない
  • ベイズ統計を実際やるにはどうしたらいいんだろうと思っている

そして,この記事の目次はこんな感じです。

  1. Stanとは確率的プログラミング言語のことである
  2. Stanはコンパイラ言語である
  3. Stanの使い方-rstanのセットアップは一苦労
  4. rstanのセットアップの苦労から逃げたいあなたは
  5. Stanを書く前に知っておきたい書き方のマナー

ということで,初日はStanのイロハ,確率モデルの入り口にも入りません。その周辺をウロウロするだけです。まあでも,基礎知識として,準備体操だと思って読んでくれれば幸いです。

それではスタート。

Stanとは確率的プログラミング言語のことである。

はいきたー。わからない単語をわからない単語で説明するやーつ。なんやねんな,というところを一つ一つ解説していきましょう。

右辺?の「プログラミング言語」ですが,これはコンピュータに計算させるための言葉だと思ってください。「線を引け」と日本語でPCに語りかけても画面に直線が引かれることはありませんが,PCがわかる言葉で伝えてやれば,線も引けるし計算もできるわけです。PCがわかる言葉といえば0/1のビットになってしまいますが,そこはもう少し人間に歩み寄ってもらって,自然言語ではないけど機械に通じる程度の文法を持った「言語」なのです。プログラミング言語としては,他にPythonやRなどがあります。古くはFortran, Pascal, Basic, C, C++, Java, 統計が得意なRなどなど,いろいろあるんですねこれが。

そういった「機械に計算させるための言葉」がプログラミング言語なのですが,確率的プログラミングに特化しているのがStanです。確率的プログラミングとは,確率モデルをプログラミング言語で書いて計算させるもの。統計モデルは発展していくと,確率モデルになっていきますから,そこでつながってくるんですね。

別の見方をすると,Stanは乱数発生機である,ともいえます。乱数,それは乱れた数。というかなんの規則性もない数の列です。いや,ただの乱数ではなくて,確率分布に従う乱数を発生させます。確率分布といえば正規分布とかポアソン分布とか,いろいろなものが知られていますが,そういったものはもちろん,名前のついていないものまでー例えばあなたが書いた確率モデルとデータから考えられる,一般名のついてないオリジナルな(事後)分布からでも,乱数を発生させることができます。この最後のところが次回以降のポイントなのですが,ここでは乱数発生機であること,そしてその確率分布を自由にデザインすることができる言語だ,と理解してください。確率モデルがどんどん発展していくと,複数の確率分布が幾重にも畳み込まれたものが出てきます。それを解析的に計算するのはとても難しいのですが,そこから乱数を発生させることができれば,その乱数の記述統計でもって分布を近似させることができる,というのが解法へのブレイクスルーだったのです。

まだピンとこない,というひとはここで私が大好きな,Stan誕生のPR動画を見て見ましょう。
Stanが生まれるまではものすごく悩んでいた高次元(たくさんパラメータがある)モデルの解析に困っていたのが,Stanのおかげで効率よくサンプリング=乱数を取り出すことができているのが,映画の予告編のように描かれています!

Stanはコンパイラ言語である

さて次のセクションですが,これまたきたきた,意味不明語。コンパイラなんて言葉,日常では使いませんわな。それでは説明していきましょう。

プログラミング言語には2種類,インタプリタ型とコンパイラ型というのがあります。

例えば統計言語のRはインタプリタ型。Rに1+2と書いてやると,すぐコンソールに答えが[1] 3と出てきますよね(ここで[1]はベクトルの要素として,をあらわしています)。この「人が命令文を書いたらすぐに答えが出る」のがインタプリタ型。Pythonもそうですね。要は人間の命令文を即座に通訳(interpret)するのでインタプリタなのです。

対してコンパイラは,一連の命令文セットをまとめて(compileは集める,編集する,集約する)機械語に翻訳し,実行ファイルを作ります。全て翻訳済みの命令文セットがあるので,実行速度が早くなります。C言語やJavaなどがこちらのスタイル。

ところで,windowsユーザの人は,実行ファイルの拡張子(ファイルの最後にひっついてるファイルの種類を決める文字列)が.exeなのはご存知でしょうか。WordやExcelも.exeファイルを呼び出して使っています。要するに,PCを直接操作してるのがこの形式のファイルなのですが,例えばメールに.exeのファイルが添付されてるとヤバイのはおわかりだと思います。PCを直接操作されるので,ウイルスか何かかもしれんわけです。

ということで,PCの側から見ればそんなファイルを作り出すような危険な操作は素人にはやって欲しくないですね。ライトなユーザは,商品として安全性・堅牢性が認められているであろう,アプリケーションソフトを使っておいてくれたほうが安心なんです。知らぬが仏ですよ,ということです。

Stanは実行ファイルをこそ作り出しはしませんが,コンパイラ言語としてPCと直接・PCの母語(に近いもの)で書いてあるファイルを生み出します。Stanに手を出そうというあなたはすでに,ライトなPCユーザではなくて,すこーしマニアックな技術を使うことになるのです。このあと説明しますが,Stanを使うときには,ウイルス対策ソフトなどが入っているとうまくいかないことがあるかもしれません。それは「おいおい,素人がその領域に手を出したらダメだぜ?」と言われているようなものなので,その静止を振り切って,一歩足を踏み出す勇気が必要です。

Stanの使い方-rstanのセットアップは一苦労

Stanを使うとすごく簡単に確率モデルを解くことができる!というところでモチベーションが上がってきたあなた。さてではどうやって使うのかな,というところに進みました。

Stanはコンピュータ言語ですが確率モデルの乱数発生しかできませんので,統計解析のその他の作業,たとえばデータの整形や可視化などは他の言語・環境にお任せすることになります。なのでRやPythonから呼び出して使うことが多いです(そのほかにも,MATLABやJulia,Stataから呼び出すことができます)。

Rから呼び出すにはrstan,Pythonから呼び出すにはpystanというパッケージを導入することで,Stan本体との橋渡しをしてくれます。パッケージをインストールすると,stan本体と関連パッケージがいろいろ読み込まれます。Stanは,実はC++言語の力を借りてコンパイルしていくので,皆さんのPCにC++言語によるコンパイル環境を導入することになります。

各種言語のインストールについては,公式サイトをご覧ください。
以下,私がよく使うR環境で説明していきます。
rstanパッケージをインストールすると,同時にRcppやinlineパッケージなどが読み込まれます。これが実は,RでC言語を使うためのパッケージなのですね。それに加えてStanHeaderやrstanといったstan本体にかかわるパッケージが次々とインストールされます。

ところが残念なことにこれですんなりrstanが使える,とはいかないことがよくあります。それは,いろいろな依存パッケージがあることによるバージョン不一致の問題や,C言語によるコンパイル環境が,Mac/Win/Linuxなど各種環境で統一されていないことに起因します。そこで,rstanの公式サイトでは,OSごとにコンパイル環境を整えるToolchainというアプリが準備されるようになりました。

その記事にあるように

  1. 以前の環境があったらそれを取り除き
  2. Rのバージョンを最新にして
  3. rstanパッケージのバージョンも最新にしたうえで,
  4. Toolchainで環境に合った設定を施した上で,

インストールしてやるとまあまあ大丈夫なのですが,そのほかにもつまづきポイントはあります。私が見てきた例で言うと,次のような点に気をつけ,対応してやる必要があります。

  • ウイルス対策ソフトがパッケージ群やコンパイルされたものをウイルスだと判断して実行を止めてやしないか?
  • インストールする権限のあるアカウント(管理人権限)で作業がなされていないんじゃないか?
  • Rやパッケージのインストール先に全角文字が含まれるフォルダがある(ユーザ名が日本語など)んじゃないか?
  • Windowsの場合,インストール先がOneDrive(クラウド)になっていてアクセスできなくなってたりしないか?
  • Windowsの場合,フォルダ名にスペースが含まれる(「Program Files」とか)ために文字化けしてるんじゃないか?
  • Macの場合,コンパイル環境(Xcode)のバージョンが上がってrstanパッケージの開発が追いついていないんじゃないか?
  • Macの場合,コンパイル環境(Xcode)をOSのアップデートと共にアップデートしただけで,アクティベートしていないんじゃないか?
  • Linuxの場合,パッケージが利用するライブラリが環境にないんじゃないか?(これは不足分を調べて追加でインストールするだけでOK。最近はV8周りのライブラリを必要とし始めました)

特にrstanを動かすときは,.Rという隠しフォルダの中にMakevarsというファイルを用意することになります。これはC++でコンパイルするときのオプションを記載したファイルです。これが環境と合致していなければうまくコンパイルできません。「隠しフォルダis何」というひともいると思うのですが(その名の通り特殊な操作をしないと画面に出てこないフォルダのことなんですけど),その辺はキーワードでググってください・・・。本当にそれぞれの環境に深く関わっているので,一概に言えないことがいっぱいあるんですよ。もしどうしても困っている,と言う人がいたら,このエントリにコメントをつけてくれれば,私をはじめベイズ塾塾生がヒントをお答えするぐらいはできるかもしれません。

基本は,「コンパイラが入っている」「コンパイラが必要とするファイルも入っている」「コンパイラが必要とするファイルをPCが見つけることができる」という条件が整っていればいい,と言うことなんです。これをチェックするには,

fx <- inline::cxxfunction(signature(x = "integer", y = "numeric"), "return ScalarReal( INTEGER(x)[0] * REAL(y)[0] ) ;")
fx(2L, 5)  # should be 10

とこの二行をR側で実行して,10という答えが表示されるかどうか,です。10が表示されれば「コンパイラ周りはOK」で,それでもrstanがうまくいかなければstan周りの問題です(そしてそれはバージョン管理の問題が多いです,経験則として)。

実は,この記事を書くにあたって私のよく使っているMacOSをBig Surにアップデートしてみました。恐々でしたが,とりあえず問題なく以前の環境を引き継ぎ,rstanが問題なく動いています。

rstanのセットアップの苦労から逃げたいあなたは

ここでだいぶん敷居が高いように感じた方もいるかと思います。これまでの経験上,一発でインストールができて実行に至るのは80%ぐらいの割合です。残りは「なんだかよくわからない!」理由でうまくいきません(機械のやることなので,理由はちゃんとあるのですが,どこに問題があるのか切り分けたり言語化したり,というのが初心者には厳しいわけで)。

そんなときの解決方法は二つ。1つはrstanじゃなくてcmdstanrをつかうというもの。これもstanをRからつかう別パッケージなのですが,cmd(コマンド)とあるようにコマンドプロンプト(端末/terminal)から呼び出すstanで,stanへのルートにRの様々な依存パッケージを使わないルートを取るものなのです。利点として「計算がrstanより速い」と言うのがあります。欠点?として「出力結果をRで処理するために結果の読み込み等が必要」というところでしょうか。これの導入方法は公式サイトや,cmdstanrでググったら出てくるサイト(こちらとかこちらとか。記事の日付等に注意してくださいね)を参考にしてみてください。

もうひとつは,R/RStudioの環境ごと完成品を取り込んできて使うこと。これにはDockerという仮想環境ツールが必要ですが,それさえクリアすればものの5分で安定した環境が手に入ります。何それ最高じゃない?そう,最高です。導入方法は去年のアドカレにあるこちらの記事や,同じ著者によるこちらの記事が参考になると思います(この著者も塾生ですゾ)。

本当にね,この導入のあたりがスムーズになったらずいぶんと楽になるんですけどね。明日からはstanを使った記事が始まりますから,頑張って今日のうちに環境を整えちゃってください!

Stanを書く前に知っておきたい書き方のマナー

君がStanを
使う前に
言っておきたい
ことがある

かなり厳しい
話もするが
おれの忠告を
聞いてくれ

ということで,環境が整って「さあ書いてみよう」というところまできていると思うのですが,最後にいくつか忠告を。プログラミングを初めてやる,という人にむけた,一般的なメッセージです。以下のポイントを心に留めながら,コードを書くようにしてください。何これ面倒だ!こんな面倒なことをやるぐらいならSピーSSでいい!という気持ちが湧いてくるかもしれませんが,stan技術を手に入れるととても面白くて楽しい世界が広がっていることはお約束できますから,年寄りからの小言だと思って頭の片隅に置いといていただければ。

  1. プログラムは思った通りに動かない。書いた通りに動く。大文字,小文字,スペルミス。細部まで気をつけて。
  2. 書き間違えないための工夫は美しさ。綺麗に書くことを心がけて。
  3. コードの一言一句すべてに意味がある。ただの写経をするのではなく,意味を考えながら書く。
  4. 「遊び心」をもって!ここを変えたらどうなるか,を少しずつ「やってみる」が大事。大丈夫,それでPCが爆発するわけじゃないし。
  5. 自分なりにカスタマイズするのは少しずつ。一気に変えるとどこが変わったかわからなくなるから。

2.の点についての補足ですが,綺麗に書くというのは「必要なところにはスペースを開ける」とか「インデントする」といった工夫です。こちらなどにコーディングスタイルガイドがありますし,アヒル本にもp.32にコーディング規約といって,こういうルールでコードを書こうね,というガイドラインがあります。こうした「ちょっとした工夫」は見やすいコードになり,見やすい=間違いが見分けやすい,ということになります。まずはルールに従って,綺麗なコードを心がけるor何を綺麗なコードと感じるか,その審美眼を養うようにして行ってください。これは簡単なことで,動けば同じでしょ,と言うのではなく「同じ動くコードなら読み直したときにわかりやすい綺麗なコードがいいよね」と思っていただくだけでいいんです。

さあ,これで環境の準備,心の準備はよろしいでしょうか。
それでは明日からのトレーニングメニュー,をお楽しみください!

Enjoy!