[Python]テキストの機械学習で相互情報量を使った特徴ベクトル選定

今回は、ドキュメント群から生成したベクトルから、機械学習で重要な特徴ベクトルを抽出する内容です。テキストをベクトル化したものは何万次元にもなりますが、中には10000個あるドキュメントの中で1回しか出てこない単語など学習に必要のないデータが大量にあります。また、次元数が多いと学習時間が長くなり、メモリの消費量も増えます。
そのため、今回は相互情報量に基づいて、学習に本当に必要な特徴ベクトルの抽出の仕方を考えます。

目次

 

相互情報量とは

 相互情報量とは、ざっくりいうと2つの事象(の集合)がどれだけ互いに関連性があるかを表す数値です。定義は以下のとおりです。
こちらにより詳しいことが載ってます。相互情報量とは

$$I(X;Y) = \sum_{y\in{Y}}\sum_{x\in{X}}p(x,y)\log_2\frac{p(x,y)}{p(x)p(y)}$$

 

実装するアルゴリズム

ドキュメントから生成した単語の頻度を表すベクトルとラベルにおいての相互情報量は以下のようになります。Classesはドキュメントに紐付いたラベルの集合で、Wordsはベクトル化されている単語の出現頻度を表す集合です。

$$I(Words;Classes) = \sum_{word\in{Words}}\sum_{class\in{Classes}}p(word, class)\log_2\frac{p(word,class)}{p(word)p(class)}$$

今回は単語ごとのすべてのラベルの相互情報量の中で最大の数値を比較して、機械学習に使うデータを選択します。
相互情報量を用いた以下の式を単語ごとの関連度の指標として、すべての単語でこの数値を計算します。相互情報量の特性上、値が大きいとラベルと単語の出現頻度の関連性が高いことがわかるため、値が大きければ大きいほど学習に重要な単語であると判断できます。

$$Output(word) = MAX\Bigl(p(word, Classes)\log_2\frac{p(word,Classes)}{p(word)p(Classes)}\Bigl)$$

 

実装

先ほど説明したアルゴリズムを実装していきます。式を展開してまとめると以下のようになります。c(〜)は該当する事象の出現数を意味します。
単純に値を比較するだけのため、単語の出現頻度、ラベルの数に依存しない数値は定数とみなして省略してあります。

$$Output(word) = MAX\Bigl(c(word, Classes)\log_2\frac{c(doc)c(word,Classes)}{c(word)c(Classes)}\Bigl)$$

必要なパラメータは以下のとおりです。

c(word, class) ラベルがclassの全ドキュメント中のwordの出現数
c(class) ラベルがclassのドキュメントの数
c(word) 全ドキュメント上のwordの出現数
c(doc) ドキュメントの総数

 

以下が単語ごとの相互情報量を保管したリストを返す関数です。extract_wordsメソッドは前回の記事に乗っています。
vectorsはドキュメントをベクトル化したもののリスト、doc_listはドキュメントのリスト、label_listはドキュメントに対応するラベルのリスト、label_numはラベルの種類の数です。

実装は難しいことは無いですが、注意点はlogの中身が0以下だとNaNが返るため if not math.isnan(~)をする必要があるという点です。
返ってきた相互情報量のリストに基づいて学習対象のデータを選定することで学習に重要な特徴ベクトルを抽出できます。