オーストラリアで勉強してきたMLデザイナーの口語自由詩

主に、データ分析・機械学習・ベイズ・統計について自由に書く。

アーキテクチャをPyMC3からPyMC4へ [e334115, d07338e, 93bc07b] - pymc4のソースコード読んでみた

f:id:yukinagae:20171122095115p:plain

TL;DR

  • 今までのコミットの ModelRandomVariable は削除され、アーキテクチャも変更されています。削除されたコードはpymc3とほぼ同等だったので、試しに書いたコードだったようです汗。ほとんど0から読み進める感じになるので、焦らず読みやすそうな箇所から辿っていきます。

コミット

2018/06/09から2018/06/11の間のコミットです。

以下のファイルが追加・変更・削除されています。多いので少しづつ読んでいきます。

  • pymc4/init.py
  • pymc4/distributions/base.py
  • pymc4/inference/init.py
  • pymc4/inference/sampling/sample.py
  • pymc4/model.py
  • pymc4/random_variable.py
  • pymc4/sample.py → pymc4/sampling.py
  • pymc4/util/init.py
  • pymc4/util/graph.py
  • pymc4/util/interceptors.py
  • tests/test_model.py
  • test/test_nothing.py → tests/test_nothing.py
  • requirements.txt

どこから読むか?

他ドキュメントやブログ記事を読んでいると、とりあず以下のように Model クラスのインスタンスを作成することがわかっているので、 pymc4/model パッケージ内のファイルから読み進めてみます。

model = pm4.Model([引数])

pymc4/modelパッケージ

対象パッケージ内には以下2ファイルが存在します。

  • init.py
  • base.py

init.py

base.py 内の Model クラスと inline 関数をimportしているだけです。

from .base import (
    Model,
    inline
)

base.py

base.py 内では以下3つが定義されています。

  • Configクラス( __all__ に含まれていないのでexportされていない)
  • Modelクラス
  • inline関数

まずは簡単な Config クラスから読みます。

Config - base.py

dict を継承したコンフィグ用のクラスを定義しているだけです。exportされていないので、 Model クラス内でしか使用されないことがわかります。

class Config(dict):
    def __getattr__(self, item):
        try:
            return self.__getitem__(item)
        except KeyError as e:
            error = KeyError(item, '"{i}" is not found in configuration for the model, '
                             'you probably need to pass "{i}" in model definition as '
                             '\n`model = pm.Model(..., {i}=value)`'
                             '\nor'
                             '\n'
                             '\n@pm.inline(..., {i}=value)'
                             '\ndef model(cfg):'
                             '\n    # your model starts here'
                             '\n    ...'.format(i=item))
            raise error from e

__getattr__ が呼ばれた際に、 __get__item を代わりに呼んでいるだけです。

  • 例)c.a => c['a']

また __getitem__KeyError が発生する恐れがあるので、エラー情報にusageを含めています。

"{i}" is not found in configuration for the model,
you probably need to pass "{i}" in model definition as
`model = pm.Model(..., {i}=value)`
or

@pm.inline(..., {i}=value)
def model(cfg):
# your model starts here'
...

使い方として以下の2パターンがあることがわかります。

  • pm.Model を使う場合
model = pm.Model(..., {i}=value)
  • @pm.inline を使う場合
@pm.inline(..., {i}=value)
def model(cfg):
    ...

次回はModelクラスを読んでいきます。

参考資料