Stan のデータ型についてまとめてみた


[Stan: Modeling Language Manual](http://mc-stan.org/manual.html) の 3 章と 4 章をもとに Stan のデータ型についてまとめてみました。

## 1. 基本的な型

<table>
<tr><th colspan="3">プリミティブ型 (Primitive Type)</th></tr>
<tr><td><code>real x;</code></td><td>実数</td><td rowspan="2">最も基本的な型</td></tr>
<tr><td><code>int N;</code></td><td>整数</td></tr>
<tr><th colspan="3">ベクトルと行列 (Vector and Matrix)</th></tr>
<tr><td><code>vector[10] v;</code></td><td>列ベクトル</td><td rowspan=2>一次元。要素の型は real</td></tr>
<tr><td><code>row_vector[10] rv;</code></td><td>行ベクトル</td></tr>
<tr><td><code>matrix[2, 3] m;</code></td><td>行列</td><td>二次元。要素の型は real</td></tr>
<tr><th colspan="3">配列 (Array)</th></tr>
<tr><td><code>real x[5];</code></td><td>real の配列</td><td></td></tr>
<tr><td><code>int N[5];</code></td><td>int の配列</td><td></td></tr>
<tr><td><code>vector[10] v[5];</code></td><td>vector の配列</td><td>要素一つ一つが vector</td></tr>
<tr><td><code>matrix[2, 3] v[5];</code></td><td>matrix の配列</td><td>要素一つ一つが matrix</td></tr>
<tr><td><code>real x[5, 10];</code></td><td>real の二次元配列</td><td></td></tr>
<tr><td><code>real x[5, 10, 7];</code></td><td>real の三次元配列</td><td></td></tr>
<tr><td><code>vector[10] v[5, 10];</code></td><td>vector の二次元配列</td><td>要素一つ一つが vector</td></tr>
<tr><td><code>matrix[2, 3] v[5, 10];</code></td><td>matrix の二次元配列</td><td>要素一つ一つが matrix</td></tr>
</table>

### 1-1. 配列(array)について

配列は任意の型を要素に持つことのできるコンテナです。
したがって、real と int の配列だけでなく、vector や matrix を要素として持つ配列を作ることができます。
二次元配列は、実際は一次元配列を要素に持つ配列です。
`real x[M, N]` という配列があったとき、`x[m, n]` は `x[m][n]` の簡易的な書き方です。

### 1-2. 行列(matrix)と配列(array)の違い

Stan において、matrix と array は明確に異なる役割を持っています。
matrix は数学の行列を表現するためのもので、array は複数の要素を持つためのコンテナです。
したがって、matrix に対しては行列演算(行列積など)を行うことができますが、array に対してはこれを行うことはできません。
また、matrix は線形代数関数(固有値や行列式など)および多変量関数(多変量正規分布など)の引数として使用します。
一方、array は離散確率分布の引数に使用されることがあります。
array を matrix に代入することはできません。また、逆に matrix を array へ代入することもできません。
matrix は要素として real しか持つことができませんが、array は任意の型を要素として持つことができるので、int の二次元配列を作ることが可能です。

## 2. 制限付きデータ型

上記の基本的なデータ型に対して、上限と下限を指定することによって変数の取る値を制限することができます。
これは、意図しないデータが変数に入ることを防止する効果があります。
また、良く使われる制限付きの型は特別な名前で定義されています。
これらは単に基本的な型に特別な制限を加えただけのものです。

<table>
<tr><th colspan="3">制限付きデータ型 (Constrained Data Type)</th></tr>
<tr><td><code>int&lt;lower=1&gt; N;</code></td><td>1 以上の整数</td><td></td></tr>
<tr><td><code>real&lt;upper=0&gt; log_p;</code></td><td>0 以下の実数</td><td></td></tr>
<tr><td><code>matrix&lt;lower=-1, upper=1&gt;[M, N] m;</code></td><td>-1～1の範囲の値を取る行列</td><td></td></tr>
<tr><td><code>ordered[N] ov;</code></td><td>昇順ベクトル</td><td>(<a href="http://ito-hi.blog.so-net.ne.jp/2014-07-16" target="_blank">参考</a>)</td></tr>
<tr><td><code>positive_ordered[N] pov;</code></td><td>正数昇順ベクトル</td><td></td></tr>
<tr><td><code>simplex[N] s;</code></td><td>非負で合計が 1 となるベクトル</td><td>ディリクレ分布に使われる(<a href="http://heartruptcy.blog.fc2.com/blog-entry-124.html" target="_blank">参考</a>)</td></tr>
<tr><td><code>unit_vector[N] uv;</code></td><td>二乗和が 1 となるベクトル</td><td></td></tr>
<tr><td><code>cov_matrix[N] cm;</code></td><td>正定値対称行列</td><td>分散共分散行列に使われる</td></tr>
<tr><td><code>corr_matrix[N] cm;</code></td><td>対角要素が 1 の正定値対称行列</td><td>相関行列に使われる</td></tr>
<tr><td><code>cholesky_factor_cov[N] cfc;</code></td><td>下三角正定値対称行列</td><td>コレスキー分解に使われる</td></tr>
<tr><td><code>cholesky_factor_corr[N] cfc;</code></td><td>下三角正定値対称行列</td><td>相関行列のコレスキー分解</td></tr>
</table>

※コレスキー分解は高速化のために使用されるテクニックです。詳しくは下記が参考になります。

- [ガウス過程シリーズ 2 高速化＆フルベイズ](http://heartruptcy.blog.fc2.com/blog-entry-143.html)

## 3. 補足

### 3-1. matrix と 2 次元 array どっちを使えばいいのか？

メモリ的には、2 次元 array よりも matrix の方が有利です。
matrix の方が省メモリで、連続的した領域を確保します。
速度的には、matrix は列ベースの繰り返しに有利です。
例えば次のような繰り返しをしたい場合は matrix が最適です。

```stan:Stan
matrix[M, N] a;
// ...
for (n in 1:N)
  for (m in 1:M)
    // ... a[m, n] を使った計算 ...
```

一方、array は行ベースの繰り返しに有利です。
次のような繰り返しをしたい場合は array が最適です。

```stan:Stan
real a[M, N];
// ...
for (m in 1:M)
  for (n in 1:N)
    // ... a[m, n] を使った計算 ...
```

これらはコンテナとして見たときの違いであり、matrix と array は根本的に異なります。
詳しくは [1-2](http://qiita.com/hoxo_m/items/e4dab11fed062689eff2#1-2-%E8%A1%8C%E5%88%97matrix%E3%81%A8%E9%85%8D%E5%88%97array%E3%81%AE%E9%81%95%E3%81%84) を参照して下さい。

### 3-2. vector と 1 次元 array どっちを使えばいいのか？

コンテナとして使う場合、どちらを使っても大差ありません。
違いは、vector は real しか保持できませんが、array は int を保持することができるというくらいです。

## 4. 参考

- [Stan: Modeling Language Manual](http://mc-stan.org/manual.html)
- [俺俺Stan manual翻訳:3章](http://qiita.com/siero5335/items/08242574b88e198fbdab)
- [俺俺Stan manual翻訳:4章](http://qiita.com/siero5335/items/055d4a82cae24d4379a6)