中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

自然言語解析 in MONMO(前編)

前回MONMOちゃんの紹介の続き。

今回は(日本語)自然言語解析の第一歩であるトークンナイズ(tokenize)を行う。


形態素解析

日本語の解析で一般的に使われるtokenize手法で、辞書を使った文脈解析。

メジャーな形態素解析ライブラリは以下の様なものがある。

mecab
https://code.google.com/p/mecab/
lucene-gosen
http://code.google.com/p/lucene-gosen/
ちょっと説明

ラテン語圏だと大抵の文章はスペース区切りで表記される。

I want to read it.

これをプログラムで扱う場合は、単純にスペースの部分で切れば良い。

  • I
  • want
  • to
  • read
  • it
  • .

しかし日本語ではそうは行かない。
どの品詞(+活用形)の後に何が接続できるのか?
などを判断しながら以下の様に分割する。

私はそれを読みたい。

  • 私 (名詞)
  • は (助詞)
  • それ(名詞)
  • を (助詞)
  • 読み(動詞-連用形)
  • たい(助動詞)

実は英語でも

Iwanttoreadit.

と書いても、大抵の人は理解できる。
この時、頭の中で行っている作業が、形態素解析という訳だ!


そんな訳で

今回は、これをMONMOちゃんのMAPジョブを使って大量(?)のドキュメントを並列に処理する。



monmo-NLProcessing/tokenize

tokenize
https://github.com/monmo/monmo-NLProcessing/blob/master/tokenize/README

形態素解析の処理はそれなりに複雑であるが、主に以下の理由からMONMO用に形態素解析エンジンを新しく作った。
 1. 既存のライブラリは辞書を専用コンパイルする必要があったりして、辞書の取り回しが面倒。
    MongoDBで処理する以上、辞書もMongoDBにあるべきだ。
 2. 同様にインプット、アウトプットもMongoDBに直接行った方がいい。
 3. 既存ライブラリはJSではないので、MONMOの仕組みを使ってJOB実装を叩きつける設計には向かない。
 4. 解析精度に納得がいかなかった時にチューニングする際JSの方が楽だ。(V8速いし)


形態素解析環境、構築手順

 0. 前回の手順でMONMOを構築
  https://github.com/monmo/monmo/blob/master/README
 1. プロジェクトをgit clone

git clone git@github.com:monmo/monmo-NLProcessing.git
cd monmo-NLProcessing/tokenize

 2. IPA辞書をDL

pushd ./data
wget http://iij.dl.sourceforge.jp/ipadic/24435/ipadic-2.7.0.tar.gz
tar xzf ipadic-2.7.0.tar.gz
popd

 3.辞書をビルド(2,3分かかる)

IPA辞書を解析し、修正とインデックス用のデータを補完して、MongoDBへ入れる。
./gendic.sh -i data/ipadic-2.7.0

 4.動作確認(形態素解析結果が出力される)

./test.jp.sh -i "私はそれを読みたい。"
1 : 私
2 : は
3 : それ
4 : を
5 : 読み
6 : たい

お手軽でしょ?


並列解析

さて、いよいよ、多数のドキュメントを扱っていく。

 1.テストデータをMongoDBに投入(73件:wikipediaから抽出)

mongoimport --drop -d test -c sampledoc --file ../sample/sampledocs.json

 2.複数ドキュメントを一気に解析(MAPジョブ)

./tokenizer.jp.sh -s test.sampledoc -f body -o test.token.sampledoc

 3.結果コレクションを確認

mongo test <<<'db.token.sampledoc.find().sort({docid:1,idx:1})'

 4.(結果を使って)キーワード検索
   『ペーパー』を含むドキュメント:

『ペーパー』を含むドキュメント:
./keyword_search.sh -s test.token.sampledoc -w 'ペーパー' -V
= META =
{
        "dic" : "analysis.dictionary",
        "doc" : "test.sampledoc",
        "doc_field" : "body",
        "token" : "test.s",
        "type" : "TOKEN"
}
= QUERY =
{ "w" : "ペーパー" }
= DOCS =
[
        {
                "d" : "51e64d60c507ed1f43d213d4",
                "n" : 19,
                "w" : {
                        "ペーパー" : 19
                }
        }
]
= VERBOSE =
 * 51e64d60c507ed1f43d213d4 : 電子ペーパー出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索iLiad電子ペーパー(でんしペーパー)とは、紙の長所とされる視認性や携
『ペーパー』から始まる単語を含むドキュメント:
./keyword_search.sh -s test.token.sampledoc -w 'ペーパー' -F -V
※1:下部に添付


2.の段階でこの様に複数のWORKERがMAPジョブを同時に処理し
サンプルドキュメント達を手分けして解析している。


熟語解析(β版)

ついでに形態素解析結果からの、(C-VALUE)熟語解析も作ってみた。
基本はTFをベースに処理するが、色々試した結果DFを使った方が良さそうなので、そちらを採用。

 1.熟語解析

./phrase.sh -s test.token.sampledoc

 2.熟語解析結果

cvフィールドが大きい程、熟語の確率が高い:
mongo test <<<'db.phrase.token.sampledoc.find({cv:{$gt:0}}).sort({cv:-1})'

 3.結果をどう使えば良いのか?を検討中・・・


まとめ

こんな感じで簡単に形態素解析が出来る様になったMONMOちゃん

次回はより複雑な検索に対応する為のベクタライズ(ベクトル化)を予定!!



添付

※1
= META =
{
        "dic" : "analysis.dictionary",
        "doc" : "test.sampledoc",
        "doc_field" : "body",
        "token" : "test.s",
        "type" : "TOKEN"
}
= QUERY =
{ "w" : /^ペーパー/ }
= DOCS =
[
        {
                "d" : "51e64d60c507ed1f43d213d4",
                "n" : 20,
                "w" : {
                        "ペーパー" : 19,
                        "ペーパーコンソーシアム" : 1
                }
        },
        {
                "d" : "51e64d60c507ed1f43d213dc",
                "n" : 13,
                "w" : {
                        "ペーパーナイフ" : 13
                }
        },
        {
                "d" : "51e64d60c507ed1f43d213d9",
                "n" : 7,
                "w" : {
                        "ペーパークラフト" : 7
                }
        },
        {
                "d" : "51e64d60c507ed1f43d213f5",
                "n" : 6,
                "w" : {
                        "ペーパークラフトペーパー" : 1,
                        "ペーパーナイフ" : 1,
                        "ペーパーバルカナイズドファイバーシュレッダー" : 1,
                        "ペーパーレス" : 2,
                        "ペーパーロード" : 1
                }
        },
        {
                "d" : "51e64d60c507ed1f43d213e4",
                "n" : 1,
                "w" : {
                        "ペーパークラフト" : 1
                }
        },
        {
                "d" : "51e64d60c507ed1f43d21400",
                "n" : 1,
                "w" : {
                        "ペーパークラフト" : 1
                }
        },
        {
                "d" : "51e64d60c507ed1f43d213e6",
                "n" : 1,
                "w" : {
                        "ペーパークリップ" : 1
                }
        },
        {
                "d" : "51e64d60c507ed1f43d213dd",
                "n" : 1,
                "w" : {
                        "ペーパープロダクツ" : 1
                }
        }
]
= VERBOSE =
 * 51e64d60c507ed1f43d213d4 : 電子ペーパー出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索iLiad電子ペーパー(でんしペーパー)とは、紙の長所とされる視認性や携
 * 51e64d60c507ed1f43d213d9 : ペーパークラフト出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索ペーパークラフトとは、紙を素材としてつくる模型で、「カードモデル」と
 * 51e64d60c507ed1f43d213dc : ペーパーナイフ出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索この記事は検証可能な参考文献や出典が全く示されていないか、不十分です。
 * 51e64d60c507ed1f43d213dd : 日本の企業一覧(パルプ・紙)出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索日本の企業一覧(パルプ・紙)(にほんのきぎょういちらんパ
 * 51e64d60c507ed1f43d213e4 : アポロ計画出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索アポロ計画(アポロけいかく、Apolloprogram)とは、アメリカ航空
 * 51e64d60c507ed1f43d213e6 : 宇宙開発競争出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索宇宙開発競争(うちゅうかいはつきょうそう、SpaceRace、宇宙開発レ
 * 51e64d60c507ed1f43d213f5 : 紙出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索紙(かみ)とは、植物などの繊維を絡ませながら薄く平(たいら)に成形したもの。日本工
 * 51e64d60c507ed1f43d21400 : 折り紙出典:フリー百科事典『ウィキペディア(Wikipedia)』移動:案内、検索この項目では、紙を折る遊びについて記述しています。"折紙"、"折り紙"の他の用