もくじ
形態素解析とは?
形態素解析とは、「日本語などの自然言語の文章を単語ごとに区切り、それぞれの品詞を判別する」技術のことです。
なんだか難しく聞こえるかもしれませんが、実行結果を見れば一発でなんのことかわかるはず。
例えば、このブログのタイトル「スタバでマック広げてるヤツのブログ」を形態素解析すると、以下のようになります。
スタバ => 名詞,一般,*,*,*,*,*
で => 助詞,格助詞,一般,*,*,*,で,デ,デ
マック => 名詞,固有名詞,一般,*,*,*,マック,マック,マック
広げ => 動詞,自立,*,*,一段,連用形,広げる,ヒロゲ,ヒロゲ
てる => 動詞,非自立,*,*,一段,基本形,てる,テル,テル
ヤツ => 名詞,代名詞,一般,*,*,*,ヤツ,ヤツ,ヤツ
の => 助詞,連体化,*,*,*,*,の,ノ,ノ
ブログ => 名詞,一般,*,*,*,*,*
形態素解析ツールMeCabのインストール
形態素解析にはいくつか便利なライブラリが提供されていますが、今回は「MeCab(和布蕪)」を使用します。
MeCabはオープンソースの形態素解析エンジンで、誰でも無料で使用できます。
ちなみに、MeCabの読み方は「めかぶ」。作者さまの好物だそうです。
MeCabを使って形態素解析をするためには、MeCab本体と辞書データの双方をインストールする必要があります。
使える辞書は何種類かありますが、IPA製のものが推奨されているので素直にこれを使用します。
Mac OS X へのMeCabのインストールはHomebrewを使うと楽です。
Windowsの人は自分でググってください。
1 2 |
$ brew install mecab $ brew install mecab-ipadic |
ついでに、非同期にMeCabを利用できるモジュール”mecab-async”もインストールしておきます。
1 |
$ npm install mecab-async |
コマンドラインでMeCabを使ってみる
MeCabがインストールできたら、コンソールで”mecab”と入力すると、コマンドライン上で試すことができます。
1 2 3 4 5 6 7 8 9 10 11 |
$ mecab > mecab スタバでマック広げてるヤツのブログ スタバ 名詞,一般,*,*,*,*,* で 助詞,格助詞,一般,*,*,*,で,デ,デ マック 名詞,固有名詞,一般,*,*,*,マック,マック,マック 広げ 動詞,自立,*,*,一段,連用形,広げる,ヒロゲ,ヒロゲ てる 動詞,非自立,*,*,一段,基本形,てる,テル,テル ヤツ 名詞,代名詞,一般,*,*,*,ヤツ,ヤツ,ヤツ の 助詞,連体化,*,*,*,*,の,ノ,ノ ブログ 名詞,一般,*,*,*,*,* |
こんな感じで、入力値を形態素解析して結果を表示してくれます。
node.jsでMeCab(mecab.async)を使って形態素解析
では、node.jsからMeCabを使ってみます。
今回はとりあえず、解析対象の文字列はコマンドラインから取得するものとします。
ソース
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// モジュールの取り込み var MeCab = new require('mecab-async') , mecab = new MeCab() ; // コマンドライン引数を取得 var args = process.argv.pop(); // 処理開始 mecab.parse(args, function(err, result) { if (err) throw err; console.log(result); }); |
*2017/4/14追記 - 使用してないモジュール”async”を読み込んでいたので当該箇所を削除。
入力値
1 |
$ node mecab.js "スタバでマック広げてるヤツのブログ" |
実行結果
1 2 3 4 5 6 7 8 |
[ [ 'スタバ', '名詞', '一般', '*', '*', '*', '*', '*' ], [ 'で', '助詞', '格助詞', '一般', '*', '*', '*', 'で', 'デ', 'デ' ], [ 'マック', '名詞', '固有名詞', '一般', '*', '*', '*', 'マック', 'マック', 'マック' ], [ '広げ', '動詞', '自立', '*', '*', '一段', '連用形', '広げる', 'ヒロゲ', 'ヒロゲ' ], [ 'てる', '動詞', '非自立', '*', '*', '一段', '基本形', 'てる', 'テル', 'テル' ], [ 'ヤツ', '名詞', '代名詞', '一般', '*', '*', '*', 'ヤツ', 'ヤツ', 'ヤツ' ], [ 'の', '助詞', '連体化', '*', '*', '*', '*', 'の', 'ノ', 'ノ' ], [ 'ブログ', '名詞', '一般', '*', '*', '*', '*', '*' ] ] |
ちゃんと単語ごとに区切られて、品詞とか活用まで表示してくれてますね。すげえ。
単語の出現頻度を調べてみる
さて、ただ形態素解析するだけじゃあまり使い道がない(し、面白くない)ので、形態素解析を利用して、その文章に含まれる単語の出現頻度を調べるプログラムを作ってみます。
ソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// モジュールの取り込み var MeCab = new require('mecab-async') , mecab = new MeCab() ; // コマンドライン引数を取得 var args = process.argv.pop(); var keywords_frequencies = []; // 処理開始 mecab.parse(args, function(err, result) { if (err) throw err; keywords_frequencies = check_frequency(result); console.log("result of check_frequency"); console.log(keywords_frequencies); }); function check_frequency(items){ var words = {}; for (var i in items){ var it = items[i]; var w = it[0]; var h = it[1]; // いらない単語を品詞でフィルター if(h != ("名詞" || "動詞" || "形容詞")) continue; if(words[w] == undefined){ words[w] = 1; }else{ words[w]++; } } // 出現頻度順にソートするため配列にコピー var list = []; for (var key in words){ list.push({ "word":key, "count":words[key] }); } // sort list.sort(function(a,b){ return b.count - a.count; }); return list; } |
たぶん、reduce,map,filterとかでもっとスマート&関数っぽく書ける気がしますね。いつか直す。かも。
入力値
入力する文字列は、wikipediaの「メカブ」の本文を使用します。
https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%AB%E3%83%96
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
result of check_frequency [ { word: 'メカブ', count: 5 }, { word: 'ワカメ', count: 4 }, { word: '部分', count: 4 }, { word: 'もの', count: 3 }, { word: '根', count: 3 }, { word: '海藻', count: 3 }, { word: 'こと', count: 3 }, { word: '葉状', count: 2 }, { word: '部', count: 2 }, { word: '葉', count: 2 }, { word: 'ひだ', count: 2 }, { word: '成分', count: 2 }, { word: 'ため', count: 2 }, { word: '状', count: 2 }, { word: 'その他', count: 2 }, { word: '的', count: 2 }, { word: '品', count: 2 }, { word: '調理', count: 2 }, { word: '湯通し', count: 2 } (略) done. |
感想とか
形態素解析と聞くとなんだか大変そうでとっつきにくい印象ですが、素晴らしい先輩方が便利なモジュール、ライブラリを用意してくださっているので、意外と楽に実装できました。
単純に形態素解析するだけだと、「、」「。」「〜の」「〜が」「〜は」みたいな意味のない記号や副詞・接続詞なんかが出現頻度ランキングの上位を独占するので、適宜品詞でフィルターして弾いてあげるのがキモのようです。
今回紹介したコード単体では大して使いどころはありませんが、クローラーなんかと組み合わせて、とあるキーワードで検索上位にいるページの単語の出現頻度なんか調べてみると面白そうですね。
ただ、node.jsしばらく触ってみたけど、非同期処理の実行順序制御とか色々面倒でよくわからんからぶっちゃけしんどかったです。
RubyかPythonに浮気を検討中…。
参考にしたサイト、本
MeCab(和布蕪)
http://taku910.github.io/mecab/
npm mecab-async
https://www.npmjs.com/package/mecab-async