単語の出現頻度を求める

--- キーワードの抽出は簡単じゃありませんよ ---


単語の出現頻度を求める


 日本語文章から、単語の出現数を数えるためには、文章から単語を抽出しなくてはいけません。すなわち分かち書き(単語の間に空白などを入れる)しないといけません。

 本来ならば、分かち書きは大変な作業ですが、MeCab (和布蕪)Chasen(茶筌)などといった形態素解析ソフトがありますので、これの出力を使うと簡単です。形態素解析(ソフト)は、入力文を単語単位に分割し、かつその品詞を与えてくれます。

 PerlやRubyなどのスクリプト言語のモジュールとして、提供されていることもあります。ですが、たいていの場合そのようなモジュールを使わなくても、簡潔さを損なうことなく記述することができます。(*1)

(*1) 本格的に解析している人は除きます。多くの人が「分かち書き+品詞を知りたいくらい」だろうと想定しています。


まず分かち書き


 まず、日本語文章を分かち書き形式に変換しないといけません。分かち書きするのはMeCabがやってくれるので簡単です。

mecab <テキストファイル>
と入力すると、以下のように、分かち書きをして、かつ品詞情報を添えて出力してくれます。
単語	名詞,一般,*,*,*,*,単語,タンゴ,タンゴ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
出現	名詞,サ変接続,*,*,*,*,出現,シュツゲン,シュツゲン
頻度	名詞,一般,*,*,*,*,頻度,ヒンド,ヒンド
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
求める	動詞,自立,*,*,一段,基本形,求める,モトメル,モトメル
EOS
EOS
 	記号,空白,*,*,*,*, , , 
日本語	名詞,一般,*,*,*,*,日本語,ニホンゴ,ニホンゴ
分かち書きだけしたいとき(品詞情報がいらないとき)は、以下のように「-O wakati」オプションをつけて実行します。
mecab -O wakati <テキストファイル>
すると、以下のような出力が得られます。
 単語 の 出現 頻度 を 求める 

  日本語 文章 から 、 単語 の 出現 数 を 数える ため に は 、 文章 から 単語 を ...

  本来 なら ば 、 分かち書き は 大変 な 作業 です が 、 MeCab ( 和布 蕪 ) や Chasen ( 茶筌 ) など ...

プログラム1(単語の数を数える)


 分かち書きが終われば単語の出現数を数えるだけです。連想配列(ハッシュ)がある言語だと簡単にプログラムが書けます。

#!/usr/bin/perl

while ( <> ) {
        @words = split(" ");
        $wc{@words[0]} += 1;
}
foreach $key (keys %wc) {
        print "$wc{$key} $key\n";
}
上記のプログラムをwordcountという名前で保存したとすると、以下のように実行すれば良いです。出現回数の多い順に並び替えをするためにsortプログラムに渡しています。
mecab <テキストファイル> | ./wordcount | sort -r -n
実はこの程度ならば、プログラムを書く必要すらありません。以下のコマンドを実行すると、出現回数の多い単語数から順に、出現単語数と出現単語が表示されます。
mecab <テキストファイル> | cut -f 1 | sort | uniq -c | sort -r -n
実行例を示します(完全な結果はこちら)。
    159 EOS
     58 、
     57 の
     48 を
     43 。
     36 て
     34 が
     33 に
     30 は
     27 ます
     25 単語
     25 ,
     21 と
     20 し
     16 です
     16 で
     15 出現
     15  
     13 する
     13 -
     12 分かち書き
     12 )
     12 (

プログラム2(単語(名詞のみ)の数を数える)


 上記の結果では、「の」とか「ます」とか、文章を構成するのに良く出てくる単語が上位に来てしまって上手くいかないことに気づきます。次に思いつく解決策は、名詞のみの数を数えればよいのではないかということです。これを実現するのは「if @words[1] =~ m/名詞/」を付け加えるだけです。

#!/usr/bin/perl

while ( <> ) {
        @words = split(" ");
        $wc{@words[0]}++ if @words[1] =~ m/名詞/;
}

foreach $key (keys %wc ) {
        print "$wc{$key} $key\n";
}

 先ほどと同様に、これもプログラムを書かなくても実現できます。パイプに「grep "名詞" 」を追加するだけです。

mecab <テキストファイル> | grep "名詞" | cut -f 1 | sort | uniq -c | sort -r -n

 実行例を示します。7回以上出現する単語を列挙してみました(完全な結果はこちら)。

     25 単語
     25 ,
     15 出現
     13 -
     12 分かち書き
     12 の
     11 数
     11 |
     11 )
     10 名詞
     10 こと
      9 プログラム
      9 よう
      9 1
      9 (
      8 抽出
      7 文章
      7 簡単
      7 ため
      7 $
単純に単語を数え上げるだけでは、上手くいかないことが分かります。

閑話休題(キーワードの抽出は簡単じゃありませんよ)


「アイデアを試してみる」について

 最近、Googleの検索で必要な情報が検索の上位に表示されたり、Amazonで、閲覧者向けのお勧め本が紹介されたりするので、「推奨」が簡単にできると思っている学生がいます。

例えばamazonは、個人の興味を抽出しているのでしょうか。数多くの顧客が一緒に買う本をリストアップし、「この本を買った人は、こんな本も買っています」と勧めているだけで、個人がプログラミングに興味があるのか、自転車に興味があるのか、は解析していないのではないでしょうか(日々進化しているので、今は解析しているかもしれません)。

「個人の興味の抽出」と、「個人が購入しそうな品を勧める」のとでは、似ているようでアプローチの仕方は大きく異なるのです。

 そのためか、例えば「ある人が閲覧したWebサイトのテキスト情報を集めて、その中に含まれる単語の出現単語数を数えることによって、その人の興味が抽出できる」と思う学生が増えています。そして実際に、卒研テーマに選ぼうとします。

 このようなことが思いつくのは非常に良いことです。ですが実際に試してみれば、そんな簡単ではないことがすぐ分かります。しかし、今の本学の学生にのレベルでは、このアイデアを試すのが精一杯のようです。このWebページは、そういった学生に、

思いつきはうまくいきませんよ。自分のアイデアを色々試してみてください
と促すために書かれています。また、このWebページには「単語数の数え上げは短時間でできるようになってください。そして、もっと他のアイデアも取り入れて、立派な卒研になるように目指してください」というメッセージをこめています。
「関連研究の調査」について
 例えば、このWebページならば、「MeCab」や「分かち書き」などが重要な単語です。ですが、この文章の特徴を表す重要な単語(特徴語)は、1度しか出てきません。

こういったときは先人の知恵を借りる(関連研究を調査する)のが良い方法です。例えば、特徴語を抽出する方法で有名なものに、IDF法(TF-IDF法)があります。早くこういった既存研究で培われたテクニックに行き着いて卒研を進めて欲しいと願っています。