設問1:トークンの出現頻度を集計してみよう!
CodeIQで作成した設問1
Pythonの自然言語処理パッケージNLTKをインストールすること。以下のURLを参照して下さい。
http://www.nltk.org/NLTKにはフリーの電子書籍を有する「グーテンベルク電子出版アーカイブ」プロジェクト
のデータが含まれています。nltkによるgutenbergのデータのダウンロードが必要です。
http://www.gutenberg.org/gutenbergに収録されているジェーン・オースティンの「分別と多感」のテキストausten-sense.txtを読み込んで、テキスト内のトークン(単語)の出現頻度の一覧を作成してください。
トークンには、カンマ「,」、ピリオド「.」などの記号が含まれているため、アルファベット文字でのみ構成されるトークンだけを出力対象とします。アルファベットは全て小文字に置き換えて、NLTKのFreqDist関数を使って、トークンの頻度を集計してください。
出力ファイルはカンマ区切りのCSV形式で以下の通り。
頻度順(降順)で出力すること。
1カラム目 トークン
2カラム目 頻度
3カラム目 全体に占めるパーセンテージ(出力形式は%f)to,4116,3.40918
the,4105,3.40006
of,3572,2.95859
(以下省略)参考文献
・Steven Bird 「入門 自然言語処理」オライリー・ジャパン
http://www.amazon.co.jp/gp/product/4873114705
・上記の書籍の英語版はオンラインで読めます。
Natural Language Processing with Python --- Analyzing Text with the Natural Language Toolkit
Steven Bird, Ewan Klein, and Edward Loper
O'Reilly Media, 2009.
http://nltk.org/book/
Kindle版
http://www.amazon.co.jp/gp/product/B0043D2E22
解答例1
[プログラム]
問題のプログラムのポイントは以下の3点です。
1. NLTKのインストールとデータのダウンロード
2. トークンの条件による絞り込み
3. DistFreqオブジェクトの使い方
NLTKからausten-sense.txtをダウンロードできたでしょうか。
トークンのリストを取得できたら、以下の様にアルファベットのみを含むトークンに
絞り、小文字化します。
text = [w.lower() for w in text0 if w.isalpha()]
Pythonでは、集合の数学記号 {x|x in A}
等のように1行でデータの抜き出しと変換を行う事できます。私も何年もPythonをやってきましたが、こんなにエレガントに書けるなんて長い間知りませんでした。
この書記法に慣れていきましょう。
トークンリストからFreqDistオブジェクトを生成し、ループを回して頻度を出力すれば終わりです。
問題では頻度順ソートについては書きませんでしたが、FreqDistオブジェクトの keys() メソッドは頻度の降順でキーのリストを出してくれるので、わざわざソートする必要はあ
りません。便利ですね。
プログラムの解答例は以下の通りです。
#!/usr/bin/python # -*- coding: utf-8 -*- # # gutenberg.py # import nltk i_file, o_file = 'austen-sense.txt', 'austen-sense.out' ### データのダウンロード ### text0 = nltk.corpus.gutenberg.words(i_file) ### アルファベットのみを含むトークンを小文字化する ### text = [w.lower() for w in text0 if w.isalpha()] ### FreqDistオブジェクト ### fdist1 = nltk.FreqDist(text) o_handle = open(o_file, 'w') words = len(text) for k in fdist1.keys(): w = '%s,%d,%f\n' % (k, fdist1[k], 100.0*float(fdist1[k])/words) o_handle.write(w)
[出力結果で気づいた点]
出力結果は以下の通りです。
to,4116,3.40918 the,4105,3.40006 of,3572,2.95859 and,3491,2.89150 her,2551,2.11293 a,2092,1.73275 i,2004,1.65986 in,1979,1.63915 was,1861,1.54142 it,1757,1.45528 she,1613,1.33601 that,1385,1.14716 be,1305,1.08090 for,1262,1.04528 not,1248,1.03369 as,1221,1.01132 you,1191,0.98647 he,1108,0.91773 his,1021,0.84567 had,998,0.82662 with,992,0.82165 but,886,0.73385 at,839,0.69492 have,819,0.67836 is,760,0.62949 by,750,0.62121 s,701,0.58062 on,696,0.57648 elinor,685,0.56737 all,656,0.54335 so,644,0.53341 him,642,0.53175 my,628,0.52016 which,593,0.49117 could,578,0.47874 no,568,0.47046 marianne,566,0.46880 from,541,0.44810 mrs,530,0.43899 they,521,0.43153
目で見てみると、ほとんど英語ではto, the, and等の高頻度のトークンは意味を担う語ではなく、文法的な語が多い事に気づきます。。ElinorとMarianneはこの小説にでてくる登場人物の名前です。呼びかけや説明文で、人名がでてくるは当然かもしれません。
人名以外に、この小説の特徴を表すトークンを見つけるのにはもう少し解析が必要なようですね。
トップ50の累積頻度をfdist1.plot(50, cumulative=True)で表示してみると、以下の様に
なります。
テキストの全語数が120733なので60000/120733=50.0%となり、たった50の語が半数を占めている事になります。