gensim パッケージに Phrases というクラスがあります。word2vec と少し関わりがあるようですが、使い方を調べてみました。
Phrases とは
そもそも何をするものかというと、文書を読み込み、前後する単語のペア(つまり、バイグラム)の出現頻度をカウント、頻度が高いペアは単一のフレーズとみなして1つの単語にまとめて文書変換してくれます。
たとえば、「機械学習」 を MeCab かなにかで分かち書きすると 、辞書登録されていない環境では「機械」と 「学習」の2つに分解されます。でも、実際には1つの単語として扱いたいはずです。
Phrases は、頻出する単語のペアを文書から読み取り、「_」でつないで一単語にしてくれます。

同一文書を何度も変換することで トリグラム や 4-グラム も扱え、もちろんそれ以上 10-グラム や 100-グラム も可能です。
仕組み
Phrases は 「学習」 と 「変換」 の 2 段階にわかれます。
学習
文書を読み込み、単語の出現頻度を調べます。その際、前後する単語の対(バイグラム)の出現頻度も調べます。各単語の出現回数は ボキャブラリ として保持されます。

変換
文書を読み込み、学習した ボキャブラリ と照らし合わせます。出現頻度の高い バイグラム はフレーズとみなして一単語に置き換えます。

インストール
pip が使え、複雑な環境でなければ
で入ると思います。
使ってみる
例文
テスト用に文を作ってみました。

入力も出力も文字列の配列
入力する文書は文字列の配列です。原文を下記のように変換してから Phrases に渡します。

英語の場合は 原文を split() するだけですが、日本語の場合は、分かち書きしてから split() することになります。
出力結果も文字列の配列です。
バイグラム
文字列の配列に変換した文章を Phrases に渡します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from gensim.models import Phrases original = [ ['私', 'の', '機械', '学習', '入門'], ['機械', '学習', 'の', '勉強', 'を', 'はじめ', 'た', '。', 'まず', '機械', '学習', '入門', 'から', '。', 'でも', '学習', 'する', '時間', 'を', 'なかなか', '確保', 'でき', 'ない', '。', '機械', '的', 'に', '本', 'を', '読ん', 'で', 'も', '身', 'に', 'つか', 'ない', '。', 'この', 'あいだ', 'は', '機械', '学習', 'と', '機械', '工学', 'の', '本', 'を', '間違え', 'て', '購入', 'し', 'そう', 'に', 'なっ', 'た', '。', '危ない', '危ない', '。'], ['そもそも', '機械', '学習', 'という', 'ネーミング', 'は', 'いかが', 'な', 'もの', 'か', '。', 'あと', '深層', '学習', 'とか', '、', 'なんか', '怖い', 'ん', 'だ', 'けど', '。'], ['いや', '、', '学習', 'に', '集中', 'しよ', 'う', '。', '黄色い', 'この', '本', '、', '何だ', 'これ', '。', 'ぶ厚い', 'ぞ', '。', 'まあ', 'いい', '、', 'とにかく', '読破', 'だ', '。', '第', '一', '章', ' ', '序論', '、', '第', '二', '章', ' ', '確率', '分布', '・', '・', '・', 'ふ', 'ふ', '・', '・', '・', 'やっぱ', '無理', '!', 'パターン', '認識', 'と', '機械', '学習', '?', 'タイトル', 'から', 'し', 'て', '難しい', '。', 'ガウス', '分布', 'が', 'なん', 'だって', '?', '初心者', 'です', 'けど', '、', 'こっち', 'は', '。', 'さては', '理解', 'でき', 'ず', 'に', '落ち込ま', 'せる', 'の', 'が', '目的', 'か', '。', 'しかも', '上下', '巻', 'で', 'いい', 'お', '値段', '。'], ['じゃあ', '、', 'これ', 'なら', 'どう', 'だ', '。', 'IT', 'エンジニア', 'の', 'ため', 'の', '機械', '学習', '入門', '。', 'なんか', 'ついていける', 'かも', '。', 'でも', '装丁', 'が', '斬新', 'すぎる', '気', 'が', '。'] ] # 学習 phrases_bi = Phrases(original, min_count=4, threshold=9.0) # 変換 transformed_bi = phrases_bi[original] for words in transformed_bi: for w in words: print w, print '' |
結果
トリグラム
バイグラムで変換した文書 transformed_bi を入力として使い、トリグラムの変換を行います。
1 2 3 4 5 6 7 8 9 10 11 |
# 学習 phrases_tri = Phrases(transformed_bi, min_count=2, threshold=2.0) # 変換 transformed_tri = phrases_tri[transformed_bi] for words in transformed_tri: for w in words: print w, print '' |
結果
フレーズの判定法
上のソースの中に min_count と threshold というパラメータが出てきます。この 2 つの値は デフォルトがそれぞれ
- min_count : 5
- threshold : 10.0
です。
何を指示するパラメータかというと、「前後する単語はフレーズか」 を判定するための数値です。
たとえば 単語A 単語B と続いた場合、以下の計算を行います。
(単語A 単語B のペアが出現した回数 – min_count)
÷ 単語A の出現回数
÷ 単語B の出現回数
× ボキャブラリ数
この値が threshold より大きければ 単語A単語Bのペアはフレーズと判定されます。
上のソースでは、置き換えが発生しやすいように “ゆるい” 値をわざと指定しています。
ボキャブラリの中身
Phrases インスタンスの vocab がボキャブラリです。
一部を表示してみます。
1 2 3 |
for k,v in phrases_tri.vocab.items(): if k.find('_') > 0 and v >= 3: print k, v |
1 2 |
機械_学習_入門 3 機械_学習 7 |
補足
上の例では、学習に使う文書と変換する文書が同一ですが、同じである必要はありません。『吾輩は猫である』を学習して『坊ちゃん』を変換するという使い方もありです。
また、add_vocab というメソッドを使えば、複数文書で学習することも可能なようです。
kaitsuburi says:
Phrasesというクラスがあるのですね。
実際に手を動かしていると、前処理って地味に手間がかかるので、こういう情報があると非常に助かります!