LXCF ソース (lxcf-0.11.tar.gz) | 2014-11-14 12:01 |
LXCF DEB パッケージ (lxcf_0.11_amd64.deb) | 2014-11-14 11:52 |
LXCF RPM パッケージ (lxcf-0.11-1.x86_64.rpm ) | 2014-11-14 11:58 |
specfiles (lxcf.spec-0.11-1) | 2014-11-14 12:03 |
LXCFでHadoopが使えるようになりました。
人として、良く切れる太刀が手に入れば試し斬りがしたくなります。
鉄砲が手に入れば撃ってみたくなるものです。
そこでHadoopを使って、実際にBig Dataの処理の実例を示しましょう。
今回はFedora 20を使います。
- 文量のある日本語文書を対象とする → 青空文庫の小説を対象にする
- 日本語の形態素解析を行う → MeCabを使う
- Javaではなく、一般的なシェルスクリプトやAWKスクリプトでプログラムする → streaming処理を使う
- 日本語の名詞を抜き出して、ワードカウントを行う
分量のある日本語文書として、小説を一冊対象としましょう。
青空文庫ではありがたいことに、著作権切れの小説を多数公開しています。
この中で有名な夏目漱石の「坊ちゃん」を例題の対象としたいと思います。
青空文庫: 坊っちゃん (新字新仮名、作品ID:752)
http://www.aozora.gr.jp/cards/000148/card752.html
日本語は英語と違って、単語が分かち書きされているわけではないので文章の解析をするのが難しいです。
そこで、日本語の文章を名詞や動詞といった品詞に分解してくれる形態素解析を行ってくれるソフトを使います。
いろいろとあるのですが今回はFedora20にもパッケージが含まれるMeCab ( https://code.google.com/p/mecab/ )をインストールして使います。
MeCab本体と、形態素解析に必要な辞書をインストールします。
HOSTにだけインストールするだけでなく、すでにHadoop用にコンテナを作ってある場合にはそれらにもすべてインストールしなければなりません。
そのような場合には、LXCFのupdateコマンドを使います。
# lxcf update yum install -y mecab mecab-ipadic mecab-jumandicこのインストールにはかなり時間(数十分)がかかるかもしれません。 気長にまってください。すべてのコンテナとHOSTの両方にMeCabと辞書がインストールされます。
MeCabに日本語文を入力してみましょう。
$ echo "これはペンです" | mecab これ 指示詞,名詞形態指示詞,*,*,これ,これ,* は 助詞,副助詞,*,*,は,は,* ペン 名詞,普通名詞,*,*,ペン,ぺん,代表表記:ペン です 判定詞,*,判定詞,デス列基本形,だ,です,* EOS
Hadoopの大きな特徴であるMapReduce処理を使います。
もともとのHadoopは、ビッグデータの大量データをMapReduce処理を使い複数の並列サーバで分担してデータ処理することでスケールアウトするシステムでした。
最近のHadoopはMapReduce処理以外にも手を伸ばしているようです。
しかし、やはり大規模なMapReduce処理を簡単に実現できるのがHadoopのもっとも魅力的なところであると私は思います。
なお、ここでは、説明しきれないのでMapReduce処理自体の説明は行いません。
Web上または書籍上で多くのMapReduce処理の情報がありますのでそれらを参考にしてください。
Hadoopの場合、MapReduce処理を実現するためには、JAVAでプログラムするのが本来は正当派です。
しかし、それでは小回りが効きにくく、また自分の慣れたプログラム言語が使えません。
Python, Ruby, Awk, デカルト言語、Perl, Scala, クロージャ言語など自分の使い慣れたプログラム言語でMapReduce処理を行うためには、HadoopではStreaming処理で実行できるようになります。
今回は日本語処理のためにMeCabを使いますので、BashとAwk言語を使うことにします。
Hadoop Streaming処理のためのjarファイルは以下にあります。
/usr/share/java/hadoop/hadoop-streaming.jar
Hadoopコマンドの引数にして使うことによって、標準入出力を経由してMapReduce処理を行うことができるようになります。
hadoop jar \ /usr/share/java/hadoop/hadoop-streaming.jar \ -input 入力データ -output 出力データ \ -file map処理プログラム \ -mapper map処理プログラム \ -file reduce処理プログラム \ -reducer reduce処理ファイル
-file 引数は、map処理プログラムやreduce処理プログラムを、並列演算するDataNodeに送って実行させます。
streamingのmapプログラムは、標準入力(stdin)からデータを受け取り、それを処理して、標準出力(stdout)に(Key value)の組を出力しなければなりません。
標準入力からのデータはHadoopによって各DataNodeのコンテナに分散して配布されます。DataNodeは受けとったデータを分担して処理します。
では、実際のプログラムを見てみましょう。
このプログラムを"map_step-j.sh"という名前で保存して実行権を付けておきます。
簡単ですね。1行だけです。
こんなに簡単に実現できるのは、MeCabが日本語の単語の切り出しを行ってくれることが大きな理由です。
このプログラムには、Hadoopから入力データが標準入力から入ります。
それを、まずmecabプログラムで品詞に分解します。
次にその結果から、第2引数に"名詞"が含まれている場合、"名詞のワード 1"を標準出力に出します。
この出力がmapプログラムからの(key, value)の値となります。
次はreduce処理プログラムです。
streamingのreduceプログラムは、mapプログラムと同様に標準入力(stdin)からデータを受け取り、それを処理して、標準出力(stdout)に(Key value)の組を出力しなければなりません。
reduceプログラムに入力されるデータは、Hadoopによって、Keyでソートされたデータが順に入力されます。
では、実際のプログラムを見てみましょう。
今回はawkでプログラムしました。
1行目の"#!/usr/bin/awk -f"がそれを示します。
このプログラムを"reduce_step.awk"という名前で保存して実行権を付けておきます。
#!/usr/bin/awk -f BEGIN { word="" count=0 } { if (word == $1) { count += $2 } else { if (count > 0) { printf "%s %d\n", word, count } word = $1 count = $2 } } END { printf "%s %d\n", word, count }
このプログラムは、map処理で出力されSortされたKeyのワードを数えて(key, ワードカウント数)の組にして出力します。
簡単にプログラム内容について説明します。
awk言語では、BEGINの処理を実行してから、入力データを処理し、入力データがなくなるとENDの処理を実行します。
まず、BEGIN処理では、変数wordとcountを初期化します。
次の処理では、一つ前のデータと入力されたKeyが一致すれば、加算して合計します。一致しなければ、Keyのカウント数を"word count"として出力します。
HadoopのSort処理によって同じKeyは連続して入力されてくるのでこのような簡単な処理でワードカウント数をまとめて合計することができます。
最後にデータが尽きたら、最後に残ったデータをENDの処理で出力します。
map処理とreduce処理のプログラムがそろいました。実際にHadoopで実行してみましょう。
手で1行ずつ実行していくのは面倒なので次のようなshスクリプトを作りました。
Data_mining-j.shという名前で保存して実行権を付けてください。
- #!/bin/sh
- if [ $# -lt 1 ]; then
- echo "usage: Data_mining-j.sh input_text"
- exit 1
- fi
- rm -rf out
- mkdir -p in
- cp $1 in/.
- hdfs dfs -rm -r out
- hdfs dfs -rm -r in
- hdfs dfs -copyFromLocal in in
- hadoop jar \
- /usr/share/java/hadoop/hadoop-streaming.jar \
- -input in -output out \
- -file map_step-j.sh \
- -mapper map_step-j.sh \
- -file reduce_step.awk \
- -reducer reduce_step.awk
- hdfs dfs -copyToLocal out out
- if [ -d out ]; then
- sort -g -r -k 2 out/* > outputs
- fi
このshスクリプトでは最初にデータの入出力のディレクトリを作成し、Hadoopで処理実行して、最後にワードカウント数でソートしなおしています。
実行は、次のように入力データを引数に指定して実行します。
入力データは、UTF-8コードの文書にしてください。
./Data_mining-j.sh 入力データ
「2. 日本語文書」でダウンロードしておいた「坊ちゃん」をデータマイニングします。(ワードカウントするだけですが)
青空文庫よりもってきた坊ちゃんのデータファイルは、SJISコードでした。まずUTF-8に変換しておきましょう。
$ iconv -f SJIS -t UTF-8 bocchan.txt > bocchan-utf8.txt
Hadoopクラスタを立ち上げて、実行します!
# ./Data_mining-j.sh bocchan-utf8.txt
結果はoutputsファイルに出力されます。
出力結果 : outputs
上位100カウント以上のデータを見てみましょう。
おれ 471 の 374 事 291 もの 218 ん 216 人 213 君 184 赤 178 一 176 よう 173 シャツ 170 山嵐 155 何 145 お 145 二 120 方 115 時 107 それ 102
ダントツで「おれ」が1番多いです。主人公の1人称で話が進められているためです。
次にワードとして目立つのは「シャツ」です。これは何でしょうか?
元の小説の中でシャツを検索してみると、これは「赤シャツ」のことだとわかります。ワード上位には「シャツ」とともに「赤」もあります。これらが別のワードとして計上されてしまったのでしょう。赤シャツというのは教頭先生のことでした。
また、「山嵐」も同様に目立ちます。この人は確か同僚です。
これらより、作者の夏目漱石は、坊ちゃんでは上司と同僚との職場での話を中心に書きたかったのだろうと推測できます。
生徒の名前などは見当たりません。「学校」は91で、「生徒」は77です。
主人公が教師であるので教育や学校生活が大きなテーマのように感じられるのですが、それらは実際は主題ではないと言えるでしょう。
有名な「マドンナ」は29カウントでした。(だからきっと恋愛物語でもありませんね)
実際に「坊ちゃん」を読み込んだ人にはかないませんが、単純なワードカウントからでも出力されたデータを解釈することによりいろいろと見えてくることもあります。
「ある朝、グレゴール・ザムザが気がかりな夢から目ざめたとき、自分がベッドの上で一匹の巨大な毒虫に変ってしまっているのに気づいた。」の出だしで有名な話です。
やはり、これも青空文庫からダウンロードさせてもらい、LXCF上に構築したHadoopクラスタでデータマイニングしてみましょう。
SJISテキストからUTF-8に変換しておきます。
$ iconv -f SJIS -t UTF-8 henshin.txt > henshin-utf8.txt
Hadoopクラスタを立ち上げて、実行します。
# ./Data_mining-j.sh henshin-utf8.txt
結果はoutputsファイルに出力されます。
出力結果 : outputs
上位のデータを見てみましょう。
の 402 こと 397 ゴール 219 彼 206 よう 186 妹 165 自分 145 人 118 父親 116 部屋 108 ドア 106 母親 103 身体 100
上位に「妹」、「父親」、「母親」が出ていることから、家族の話だろうと推測できます。
「ゴール」が出ていますが、これは何かと本文で検索してみると、主人公グレーゴールからゴールだけが切り離されて出力されているようなのでとりあえず無視します。
また、「彼」は本文で検索するとやはり主人公を指しています。
「部屋」、「ドア」とあるのは、自分の部屋とそのドアのことを示していました。
毒虫に変身するというショッキングな話ですが、主題としては主人公の部屋の中での家族と主人公との関わり合いを描いているのだろうと解りました。
[PageInfo]
LastUpdate: 2014-07-21 11:28:15, ModifiedBy: niwa-hideyuki
[Permissions]
view:all, edit:members, delete/config:members