見出し画像

テキスト分析の大通り#15: LDA、Scikit-learn編

今回ご紹介するのはLDA(Latent Dirichlet Allocation: 潜在的ディリクレ配分法)という分類手法です。ナイーブベイズは正解となるカテゴリーが与えられ、それを学習してモデル化することによって、未知のデータに直面した際にそれがどのカテゴリーなのかを判別するという流れで、いわゆる教師あり学習というものです。
一方LDAは与えられたデータの性質に応じてモデル化を試みるため、教師なし学習というものに分類されます。LDAはトピックモデルと呼ばれる手法の1つで、文章は複数のトピックを内包しているとみなします。トピックは特定の単語群やその組み合わせからなる、例えば「音楽」とか「映画」とか、そういったものです。なので文章の中に潜在(latent)する複数トピックへの所属の度合いを、ある分布(dirichlet: 数学者の名前であり分布の名前)に基づいて配分(allocation)指標化するするということでLDAです、多分。そして「複数トピック」という部分、例えばエミネムの「8 Mile」に関するさまざまな文書は、音楽について100%説いているものから映画について100%語っている記述の間で、グラデーションがあるかと思います。LDAはこのグラデーションの度合いを配分として与えるものです。
代表的な教師なし学習の手法であるk-Meansクラスタリングでは、クラスターの数kを人間が与える必要がありますが、LDAにおいてもこれは同様で、ここら辺がちょっと難しいところです。また各トピックに対する配分はしてくれますが、そのトピックが何であるかは人間が追加的に確認の上、解釈を加える必要があります。


LDAの処理

まずは以下に処理スクリプトを。

使っているライブラリはScikit-learnのLDAです。ナイーブベイズ同様データをダウンロードし、CountVectorizerに突っ込み、ベクトル変換しています。今回は学習用評価用にデータを分割せず、全部モデリングに利用しています。

次にトピック数の決定部分ですが、これは一旦トピック数を1から10まで順にパラメータとして与え、モデルを作り、Perplexityという指標を取り出しています。この値が小さいほどトピック数としては適切です。今回の例では1ですが、正直今回はデータが少ないため、あまり良いPerplexityの遷移となっていません。トピック数が大きくなればPerplexityが低減していくのを期待しましたが、そうはなっていません。本来は、トピック数が少なすぎても、多すぎても見晴らしはよくないため、ある程度Perplexityが等しく低い中でトピック数を決めるということになるかと思います。今回に関して言うと、トピック数を1つ2つにしてもやる意味がないので、3つにとりあえず決め、モデリングとスコアリングをしていきます。

そしてlda.components_の部分で、各トピック(3つ、0,1,2)に対する単語の出現確率を配列で出力しています。標準化もできるようですが、まあこのままで良いのならと処理をメモ書きしただけで使ってません。データフレームに変換し、テーブルとして扱いやすいよう縦持ちし、データベースに送っておきます。

続いてスコアリング。こちらも縦持ちしてデータベースに。なぜか配列や横持ちのデータには気持ち悪さを感じ、縦持ちにしなきゃという強迫観念に駆られます。


結果の確認

データベースに格納したモデル、スコアのデータを確認します。まずスコアデータは以下です。SQLと結果のCSVファイルを。

見やすいので結局横持ちしました..。上から7行、9行、4行とトピック0,1,2に高い確率が割り当てられています。トピック0はピンク、トピック1はボケとバスケットボールが目立ちます。トピック2はいまいちわかりません。もしかしたらノイズ、その他みたいな扱いなのでしょうか。

単語の力関係を見たいのでモデルデータの方ものぞいてみましょう。取得SQLは以下。

そして結果をグラフにしました。

モデル内の各単語

各トピックごとに順位付けを行い、順位ごとに横並びにしています。色はラスタカラーにしました。まず見て欲しいのは、各モデル間の力関係です。トピック0のランクトップprobが4を超えているのに対して、トピック1は3、トピック2は2超え程度です。

そして各トピックごとに見ていくと、トピック0はピンクが大きな値となっています。そしてこれに引っ張られる形で、「ベスト」、「トゥース」が、上位にいます。一方で直接的には所沢出身、ピンクベストのトゥースさんとは関係のなさそうな「入船」、「出身」という単語が含まれています。これはdocid19番の「トゥース」と連なっている「人」という単語からつながっているようです(合わせてスコアの表を参照ください)。
次にトピック1では、ボケ、ツッコミの漫才における担当を示す単語が上位に並びます。そしてトピック2では最上位の「ない」でもトピック1の「ない」よりも値が低いことが分かります。結果的にトピック2はその他、ノイズトピックと言ってもあながち間違いではないのかもしれません。
あえて各トピックに名前を付けるならトピック0=ピンクベストのトゥースさん、トピック1=漫才の役割分担、トピック2=その他ノイズとなるでしょうか。残念ながら文書が少ないせいで、入船の若様は泣き別れの餌食になってしまっています。このように単語主導で分類がなされるため、あらかじめ与えられたクラスとは異なる分類になることも十分起こり得ます。また、今回はワードの発生件数、種類ともに少ないため、各トピックの所属配分は明確に分かれていますが、複数のトピックどちらとも言えないような配分の文書も起こり得ます。

とまあ、こんな感じで解釈を行い、新たに出現したデータがあったらこのモデルに突っ込むと、文書を読まずしてどのようなトピックについて触れているか判断できるようになります。

次回は同じLDAのライブラリであるgensimを試してみます。

(TeradataやPython、およびPythonライブラリのインストールや環境構築、辞書登録、参考にしたページ等は以下にまとめています)

///

#analytics #bow #lda #text #nlp #データ #分析 #teradata #sql #python

この記事が気に入ったらサポートをしてみませんか?