対数正規分布 (log-normal distribution) の可視化

0よりも大きい値しかとらない確率変数*1について、その事前分布を設定するときに、対数正規分布 (log-normal distribution) を用いることがある。

定義

対数正規分布とは、ある確率変数  x について、その対数  \log x の分布が正規分布に従うような分布のことである。以下の確率密度関数を持つ。

\displaystyle
\mathcal{LN}(x \mid \mu, \sigma^{2} ) = \frac{1}{x} \cdot \frac{1}{\sqrt{2 \pi \sigma^{2}}} \cdot \exp \left\{ - \frac{ ( \log x - \mu )^{2} }{2 \sigma^{2} } \right\}

ただし、  x \in \mathbb{R}_{> 0}, \mu \in \mathbb{R}, \sigma \in \mathbb{R}_{> 0} である。

性質

以下の性質を持つ。

  • meanは  \exp(\mu + \sigma^{2} / 2) で表される。
  • medianは  \exp(\mu) で表される
  • modeは  \exp(\mu - \sigma^{2}) で表される

直感的には、  \sigma^{2} が比較的小さいとき、mean、median、modeはいずれも  \exp(\mu) に近くなり、これを中心とした左右対称に近い分布になっていると思われる。逆に  \sigma^{2} を大きくしていくと、mean(つまり重心)は  \exp(\mu) よりも大きい方にずれ、mode(つまり最大をとる値)は  \exp(\mu) よりも小さい方にずれていく。

可視化

対数正規分布の形は少し想像が難しい。以下に可視化例を示す。

f:id:yuki-koyama:20190728094015p:plain
対数正規分布 (log-normal distribution) の可視化(  \mu を固定)

f:id:yuki-koyama:20190728094242p:plain
対数正規分布 (log-normal distribution) の可視化(  \sigma^{2} を固定)

以下に可視化に用いたPythonコードを示す。

おまけ:対数正規分布の対数

MAP推定などの統計的推定では、計算上対象とする分布の対数を扱うことが多い。対数正規分布の対数をとったものは

\displaystyle
\log \left\{ \mathcal{LN}(x \mid \mu, \sigma^{2} ) \right\} = - \log x - \frac{1}{2} \log(2 \pi \sigma^{2}) - \frac{ (\log x - \mu)^{2} }{2 \sigma^{2}}

となり、その微分

\displaystyle
\frac{d}{dx} \log \left\{ \mathcal{LN}(x \mid \mu, \sigma^{2} ) \right\} = - \frac{1}{x} \left(1 + \frac{\log x - \mu}{\sigma^{2}} \right)

となる。

*1:例えば分散  \sigma^{2} を確率変数とみなして統計的推定を行う場合など。

CMakeで管理するプロジェクトでEigen 3.Xを使うときのTips

Eigen 3.3以降

Eigen 3.3以降は

find_package(Eigen3 REQUIRED)

として、

target_link_libraries(mylibrary Eigen3::Eigen)

とすれば良い。

Eigen 3.3以降に関する公式ドキュメント: eigen.tuxfamily.org

なおmacOSのHomebrewで

brew install eigen

とすると、2019年3月15日現在、Eigen 3.3.7が入るので、この方法で良い。

Eigen 3.2以前

Eigen 3.2以前やEigen 3.3-betaなどは

find_package(Eigen3 REQUIRED)

としても、EIGEN3_INCLUDE_DIRなどの変数はセットされるが、上述のようなEigen3::Eigenというtargetは生成されない。そこで、

target_include_directories(mylibrary PUBLIC ${EIGEN3_INCLUDE_DIR})

などとしてヘッダーへのパスを通す必要がある。

なお、この方法だとmylibraryとEigenとの依存関係が直接的には指定できていないので、その後階層的に依存関係を構築したりする際にもしかするとどこかで弊害があるかもしれない(要確認)し、見た目にも依存関係が分かりにくい(主観)。

なおUbuntuのaptで

sudo apt install libeigen3-dev

とすると、Eigen 3.2やEigen 3.3-betaがインストールされる環境が存在するので、その場合はこのような方法をとる必要がある。

両方のケースに対応するCMake

両者に対応し、依存関係も直接指定するには、

find_package(Eigen3 REQUIRED)
if((NOT TARGET Eigen3::Eigen) AND (DEFINED EIGEN3_INCLUDE_DIR))
    add_library(AliasEigen3 INTERFACE)
    target_include_directories(AliasEigen3 INTERFACE ${EIGEN3_INCLUDE_DIR})
    add_library(Eigen3::Eigen ALIAS AliasEigen3)
endif()

とした上で

target_link_libraries(mylibrary Eigen3::Eigen)

とすれば良い。

Eigenはheader-only libraryなので、INTERFACEキーワードでtargetを設定した上で、ALIASキーワードを使ってEigen3::Eigenで指せるようにしている。

cmake.org

参考レポジトリ

下記のレポジトリの2019年3月15日現在の最新版では、上のような方法で両者のケースに対応している。

github.com github.com

CMakeでビルドした実行プログラムのあるディレクトリにリソースファイルをコピーする

やりたいこと

CMakeを用いてプロジェクトを管理しているときに、ビルドした実行ファイルと同じディレクトリ(またはそこから相対的に定義されるディレクトリ)に画像データ等のリソースデータをコピーしたいという状況を考える。

リソースファイルは、例えば次のように定義されているとする。

file(GLOB RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/*.png)

問題点

ビルド環境ごとにビルドした実行プログラムが配置されるディレクトリは異なる可能性がある。

例えば、Makefileを生成してmakeとした場合には${CMAKE_CURRENT_BINARY_DIR}に実行プログラムが配置されるが、Xcodeを用いてビルドすると、例えばDebugモードでビルドすると${CMAKE_CURRENT_BINARY_DIR}/Debugに配置される。

更に、macOS.appバンドルを生成する場合は、実行ファイルの本体は[...].app/Contents/MacOSに配置される。

したがって、リソースファイルを実行ファイルのあるディレクトリにコピーしたい場合、単にfileコマンドを使って

file(COPY ${RESOURCE_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

としても、ビルド環境によっては意図通りにコピーされないことがある。

解決策:Generator Expression

Generator Expressionを用いれば良い。これは、CMakeのドキュメントに

Generator expressions are evaluated during build system generation to produce information specific to each build configuration.

と説明にあるように、ビルド環境に応じて評価される式ということらしい。

したがって、ビルド環境依存の部分は、generator expressionsを用いることで統一的に記述することができるようになる。

CMakeに定義されているgenerator expressionsのうち、特に

$<TARGET_FILE_DIR:my-program>

という式を用いると、ビルドした実行プログラムが配置されるディレクトリを得ることができる。ただしmy-programの部分にはそれぞれのターゲット名が入る。

リソースファイルをコピーするには、これを用いて

add_custom_command(TARGET my-program POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${resources} $<TARGET_FILE_DIR:my-program>)

などと記述すれば良い。

オイラー角による回転行列の表現まとめ

免責・注意:本記事は、その正しさを一切保証しない。できるだけ出典を記すようにするが、特に、要出典・要確認等と書かれただけの箇所は注意が必要である。また、現時点では未完成で、随時追記・更新していくつもりである。

右手系・左手系について

座標系を考えるとき、右手系と左手系のどちらかを用いることになる。本記事では右手系のことしか考えない。左手系について知りたい人は、以下の内容を全て自分で変換し直して考えるか、別の記事を当たる必要がある。

右手系の採用例

左手系の採用例

世界座標系とモデル座標系のどちらの座標系を基準とみるか:Extrinsic (Fixed) vs. Intrinsic (Mobile)

本記事では extrinsic (fixed) なオイラー角表現のことしか考えない。Intrinsic (mobile) なオイラー角表現を暗黙的に採用しているシステムもあるので注意が必要である。

Extrinsic (fixed) な表現では世界座標系 (world coordinates) の座標軸を基準に回転することを考える。

Extrinsic rotations are elemental rotations that occur about the axes of the fixed coordinate system xyz. The XYZ system rotates, while xyz is fixed.

引用元:Wikipedia. Euler angles. https://en.wikipedia.org/wiki/Euler_angles

一方で、intrinsic (mobile) な表現ではモデル座標系 (model coordinates; local coordinates) の座標軸を基準に回転することを考える。そのため、回転を適用する度に次に回転する際の基準軸が世界座標系から見たときに変わる点で注意が必要である。

Intrinsic rotations are elemental rotations that occur about the axes of a coordinate system XYZ attached to a moving body.

引用元:Wikipedia. Euler angles. https://en.wikipedia.org/wiki/Euler_angles

Extrinsic (fixed) でも intrinsic (mobile) でも、どちらも同等な回転を表現することができる。

For example, the fixed XYZ Euler angle convention is described by the x→y→z sequence, while the mobile ZYX Euler angle convention is described by the z'→y'→x' sequence, but both are equivalent, as we will see later.

引用元:How is orientation in space represented with Euler angles? https://www.mecademic.com/resources/Euler-angles/Euler-angles

また、extrinsic (fixed) な回転と intrinsic (mobile) な回転を混ぜて考えることも可能である。ただし実際にこれが有益になることは少ないと思われる。

That said, each of the twelve combinations is equivalent to three other sequences. In other words, each Euler angle convention can be described in four different ways. For example, the ZYX convention is equivalent to the sequences z→y→x, x'→y'→z', y→z'→x and y→x→z'.

引用元:Mecademic, Inc. How is orientation in space represented with Euler angles? https://www.mecademic.com/resources/Euler-angles/Euler-angles

Extrinsic (Fixed) Euler XYZ

世界座標系の  x 軸周りに  \theta_x 回転させ、続いて世界座標系の  y 軸周りに  \theta_y 回転させ、続いて世界座標系の  z 軸周りに  \theta_z 回転させるような回転について、そのような記述の方法を extrinsic (fixed) Euler XYZ と表現したい。実際には単に Euler XYZ と呼ばれることも多いが、extrinsic と intrinsic の違いについて常に意識しておいた方が安全である。

そのような回転は以下の回転行列で与えられる。

\displaystyle{
\mathbf{R} = \mathbf{R}_z(\theta_z) \mathbf{R}_y(\theta_y) \mathbf{R}_x(\theta_x) \in \mathbb{R}^{3 \times 3}
}

あるモデル座標系の点  \mathbf{x}^\text{model} \in \mathbb{R}^{3 \times 1} を、上のような extrinsic (fixed) Euler XYZ によって世界座標系に配置する際には、世界座標系上での座標  \mathbf{x}^\text{world} \in \mathbb{R}^{3 \times 1}

\displaystyle{
\mathbf{x}^\text{world} = \mathbf{R}_z(\theta_z) \mathbf{R}_y(\theta_y) \mathbf{R}_x(\theta_x) \mathbf{x}^\text{model}
}

で与えられる。

XYZ とは回転行列を適用する順番を表現している。OpenGL の Legacy APIs では post-multiplication が採用されているため、記述するときには

glRotated(theta_z, 0.0, 0.0, 1.0);
glRotated(theta_y, 0.0, 1.0, 0.0);
glRotated(theta_x, 1.0, 0.0, 0.0);

という順番になると思われる。

Extrinsic (Fixed) Euler XYZ の採用例

  • Maya のデフォルト(TODO:要出典)

オイラー角を三次元ベクトルで表現する際の注意

変数の格納順に注意が必要である。名前が XYZ となっていても、

vec3 euler_angles = { theta_x, theta_y, theta_z };

のような順序で変数を格納するのが必ずしも唯一の方法ではない。例えば、回転行列の掛け算の式に現れる順に

vec3 euler_angles = { theta_z, theta_y, theta_x };

と変数を格納する実装もあり得る。これは Eigen の eulerAngles() で採用されている(TODO:要確認)。