y_uti のブログ

統計、機械学習、自然言語処理などに興味を持つエンジニアの技術ブログです

潜在ディリクレ配分法 (社内勉強会発表資料)

勤め先の社内勉強会で潜在ディリクレ配分法 (Latent Dirichlet Allocation; LDA) について発表するので、資料を公開します。前半では gensim を利用して LDA を実際に試してみることに主眼をおき、後半で LDA の内容を説明したうえで gensim の LDA との対応を確認する構成にしました。プログラマ機械学習アルゴリズムを学ぶときには、教科書や論文と既存のライブラリを照らし合わせながら読んでいくのが近道だと思っています。

www.slideshare.net

資料では、パラメータ推定に関する説明は思い切ってすべて省略しました。主な理由は二つです。一つは、数式を一つ一つ確認する形の説明に終始してしまいそうで、それは各自で教科書を読めばよいと考えたためです。もう一つは、LDA を使う側にとっての重要度は低いと考えたためです。既存のライブラリを利用する立場であれば、パラメータや戻り値の意味を理解することがまず重要で、内部でどのように計算が行われているかは、もう一歩詳細に踏み込んだ話だろうと判断しました。

ところで、LDA の名前の由来にもなっているディリクレ分布は、パラメータを色々と変えながら可視化してみると分かりやすいと思います。可視化というのは意外に面倒で投げ出しがちだと思うのですが、今回 Plotly の Graphing Library を用いてディリクレ分布の可視化を簡単に実現できたので、紹介します。
plot.ly

次のコードで、ディリクレ分布の確率密度を描画できます*1。alpha をディリクレ分布のパラメータとして、単体上の点列 xs それぞれでの確率密度を ys に計算します。これを create_ternary_contour 関数に渡せば、三角等高線グラフを描いてくれます。

import numpy as np
from plotly.figure_factory import create_ternary_contour
from scipy.stats import dirichlet

alpha = [2.0, 1.6, 1.2]

ticks = 100
xs = np.array([[i1 / ticks, i2 / ticks, (ticks - i1 - i2) / ticks]
               for i1 in range(1, ticks) for i2 in range(1, ticks - i1)])

distribution = dirichlet(alpha)
ys = np.array([distribution.pdf(x) for x in xs])

fig = create_ternary_contour(xs.T, ys,
                             pole_labels=['x1', 'x2', 'x3'],
                             ncontours=32,
                             colorscale='Jet')
fig.show()

実行結果は以下のとおりです。グラフにマウスカーソルを当てると値がポップアップ表示されたり*2、画像保存機能やズーム機能が付いていたりして便利です。
f:id:y_uti:20200118164017p:plain

*1:Jupyter Notebook での実行を想定しています。最後の fig.show() は実行環境に応じて変更してください。

*2:スクリーンショットではマウスカーソルが消えていますが、吹き出しの場所を指しています。