入門 自然言語処理 第一章
February 13, 2011 - 入門 自然言語処理
入門 自然言語処理は11月に購入してから寝かせたままでしたが、本日より読み始めることにしました。
本日は第一章です。内容は大きく以下2点。
- pythonとnltkでの簡単なテキスト処理方法
- 自然言語処理を俯瞰する
問題文は簡潔に記述するため、本書に記載されているものとは異なる表記をしています。
納得いかない問題
ひとつだけ納得いかない問題がありました。 「17. text9からtext.9.index()を使って’sunset’を含む一文を抜き出す」です。解答をググっても、こちらしか出てこず。 1-15. bで始まる単語抽出 — 入門自然言語処理
たしかに、
>>> text9.index(‘sunset’) 629と帰ってきます。でも、実際には’sunset’を含む一文は複数あるわけです。 確認するとこんな感じ。
>>> [t for t in text9 if t==‘sunset’] [‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’, ‘sunset’]複数ある一文を抽出しなくていいの?という疑問が出てきました。すべての文を抽出する方法はさておき、今回はひとつだけ抽出する解答だけを書きました。
演習問題
準備
nltkとmatplotlibがインポートできていれば、以下コードだけですみます。from nltk.book import *以下が、すべての問題の解答です。 (私個人の解答であり、正解の保証はどこにもありません。)
1. Pythonインタプリタを電卓として、12 / (4 + 1)のような計算を入力してみよう
>>> 12 / 4 + 1 2.3999999999999999
2. 26文字のアルファベットが与えられたとき、10字の文字列は26の10乗(あるいは26**10)種類も作ることができるが、100文字だったら何種類か。
>>> 26 ** 100 3142930641582938830174357788501626427282669988762475256374173175398995908420104023465432599069702289330964075081611719197835869803511992549376L
3. [‘Monty’, ‘Python’] * 20や 3 * sent1を実行すると何が起こるか
>>> [‘Monty’, ‘Python’] * 3 [‘Monty’, ‘Python’, ‘Monty’, ‘Python’, ‘Monty’, ‘Python’]
4. text2には単語がいくつ含まれているか。また重複を除くといくつか。
>>> #単語数 >>> len(text2) 141576 >>> #重複除いた単語数 >>> len(set(text2)) 6833
5. ユーモア小説とロマンス小説の間で、どちらが語彙の多様性が高いか。
- ユーモア小説:多様性=6.9
- ロマンス小説:多様性=8.3
6. Sense and Sensibilityのなかで、エリナ、マリアン、エドワード、ウィロビーの分散プロットを表示してみよう。
名前まで日本語表記されていて元の綴りがわからない… なのでまず探すところから。>>>[t for t in set(text2) if t.startswith(‘El’)] [‘Elinor’, ‘Eliza’]な感じで4人分探します。 で、プロットする
>>> text2.dispersion_plot([‘Elinor’, ‘Mrianne’, ‘Edward’, ‘Willoughbys’])※ここでプロットウインドウが表示される
男女の役割の違い
女性が高頻度に出現カップルの特定は可能か
できない。どうしろと…7. text5のコロケーションを探してみよう。
>>> text5.collocations() Building collocations list wanna chat; PART JOIN; MODE #14-19teens; JOIN PART; PART PART; cute.-ass MP3; MP3 player; JOIN JOIN; times .. .; ACTION watches; guys wanna; song lasts; last night; ACTION sits; -…)…- S.M.R.; Lime Player; Player 12%; dont know; lez gurls; long time
8. len(set(text4))の目的
単語のユニーク数を求める9. リストと文字列
(a) 変数の定義と2種類の出力を試してみよう
>>> my_string = ‘My String’ >>> my_string My String >>> print my_string My String
(b). 連結と演算
>>> my_string + my_string ‘My StringMyString’ >>> my_string * 3 ‘My StringMy StringMy String’
10. 単語のリストを保持するmy_sentという変数を定義しよう
(a) ‘ ‘.joiin(my_sent)を使ってリストを文字列に変換してみよう。
>>> ‘ ‘.join(my_string.split(’ ‘)) ‘My String’
(b) split()を使ってできた
>>> my_sent = [‘My’, ‘Sent’] >>> ‘ ‘.join(my_sent) ‘My Sent’ >>> ‘ ‘.join(‘hoge moge’.split(’ ‘)) ‘My Sent’
11. リストの連結
>>> phrase1 = [‘hoge’] >>> phrase1 += [‘moge’] >>> phrase2 = [‘foo’] >>> phrase2 += [‘bar’] >>> phrase1 + phrase2 [‘hoge’, ‘moge’, ‘foo’, ‘bar’]
len(phrase1 + phrase2)とlen(phrase1) + len(phrase2)の違いはなにか。
連結した後の長さと、それぞれの長さの加算12. NLPと関連あるものはどれか。
- [‘Monty Python’][6:12]
- [‘Monty’, ‘Python’][1]
13. sent1[2][2]はなにを表しているだろうか。
2要素目の2文字目14. 要素のインデックス取得
微妙だけど。>>> i = 0 >>> for t in sent3: … if t==‘the’: … print i … i += 1 … 1 5 8
15. bから始まる単語の取得
>>> sorted(set([t for t in text5 if t.startswith(‘b’)])) [‘b’, ‘b-day’, ‘b/c’, ‘b4’,……
16. range()について
>>> range(10) [1,2,3….9] >>> range(10,20) [10,11,12,…., 20] >>> range(10,20,2) [10, 12, …, 18] >>> range(20,10,-2) [20, 18, …, 12]
17. text9からtext.9.index()を使って’sunset’を含む一文を抜き出す
これで良いのかわかりませんが、ひとまずの解答として。dot_pre = 0 # 直前の’.‘の位置 dot_aft = 0 # 直後の’.‘の位置 found = False # ‘.‘が見つかったかどうか i = 0 # 現在位置 for t in text9: if t==‘sunset’: found = True if t==‘.’: if found==True: dot_aft = i break else: dot_pre = i i += 1‘sunset’を含む一文を生成する。
’ ‘.join([text9[t] for t in range(dot_pre+1, dot_aft+1)])
‘CHAPTER I THE TWO POETS OF SAFFRON PARK THE suburb of Saffron Park lay on the sunset side of London , as red and ragged as a cloud of sunset .’
18. sent1からsent8までに含まれる語彙を計算
len(set(sent1 + sent2 + sent3 + sent4 + sent5 + sent6 + sent7 + sent8))
19. 以下2行の違いは何か。
sorted(set([w.lower() for w in text1])) sorted([w.lower() for w in set(text1)])
sorted(set([w.lower() for w in text1]))
小文字のリストを作ってからユニークにしてソートsorted([w.lower() for w in set(text1)])
ユニークリストから小文字にしてソート こちらが大きい。重複をふくんでいるので。20. w.isupper()とw.islower()の違いは何か
大文字ならTrueと小文字ならTrue21. 最後の2単語を取り出すスライス式を書いてみよう。
>>> text2[-2:]
21. 4文字の単語のうち、頻度の高い順に取得してみよう。
>>> FreqDist([t for t in text4 if len(t)==4]).keys()
21. 大文字の単語を一行ずつ表示
>>> for str in [t for t in text6 if t.isupper()]: >>> print str
24. 条件にあったものを含むリスト
a: izeで終わる
[t for t in text6 if t.endswith(‘ize’)]
b: zを含む
[t for t in text6 if ‘z’ in t]
c: ptを含む
[t for t in text6 if ‘pt’ in t]
d: 先頭大文字あと小文字(=タイトルケース)
[t for t in text6 if t.isalpha()==True and t==t.title()]
25. listed = [‘she’, ‘sells’, ‘sea’, ‘shells’, ‘by’, ‘the’, ‘sea’, ‘shore’]
shではじまる単語
[t for t in listed if t.startswith(‘sh’)]
4文字より大きい単語
[t for t in listed if len(t)>=4]
26. sum([len(w) for w in text1])について
どんな処理?
リスト中のすべての単語長の合計これをつかって平均はだせる?
>>> sum([len(w) for w in text1])/len(text1) 3.8304111280236488
27. 語彙サイズを返すvocab_size(text)を定義
>>> def vocab_size(text): … return len(set(text)) … >>> vocab(text1) 19317
28. percent(word, text)を定義
>>> def percent(word, text): … return len([t for t in text if t==word]) / len(text)
29. set(sent3) < set(text1)について
実行してみる
True
29. 異なるテキストで実行して何が起こるか
>>> set(sent3) < set(text3) True