『入門 ソーシャルデータ』で日本語を扱うために
追記(2012/09/17):macab-pythonをMac OSX 10.7 Lion, Python2.7にインストールする。
入門 ソーシャルデータ ―データマイニング、分析、可視化のテクニック
- 作者: Matthew A. Russell,奥野陽(監訳),佐藤敏紀(監訳),瀬戸口光宏(監訳),原川浩一(監訳),水野貴明(監訳),長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/11/26
- メディア: 大型本
- 購入: 18人 クリック: 779回
- この商品を含むブログ (42件) を見る
本書の内容だけでは、「英語は文章が単語ごとにスペースで区切られているが、日本語はそうではない」という特性を処理できないのです。
まずぶちあたった問題はMac 0S X 10.6のコンソールでのPython対話型インタプリタで日本語が入力できない問題でした。
これは、macのpythonのインタラクティブシェルで日本語入力できないよ(解決) - kakatofu’s note http://d.hatena.ne.jp/kakatofu/20100825/python を参考に
$ easy_install readline
を実行するだけで解決しました。
これでp.6でtwitter_search.search(q="SNL"の部分に日本語を入力できるようになる。今回は、q="消費税"で試した。
この結果のうち、ツイートのテキスト部分のみをtweetsに格納するコードがp.8にあります。
>>> tweets = [ r['text'] for result in search_results for r in result['results']]
ここで、print tweets とやると、\u3060\u3002\u8a02...といったエンコードされていない文字列が延々と表示されて訳がわからない。しかし、エンコードを指定しようとすると、
>>>print tweets.encode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> Attribute Error: 'list' object has no attribute 'encode'
と怒られてしまう。配列にはエンコードって属性ないようです。
しょうがないから、配列からひとつひとつ要素を取り出してエンコードするように書き換える。
>>>for t in tweets: ... print t.encode('utf-8')
これでやっと読める形で結果が表示されました。
次に、この結果を単語レベルに分けなければいけない(トークン化っていうの?)のだが、これが難しかったです。
参考にしたのは、Python による日本語自然言語処理 http://nltk.googlecode.com/svn/trunk/doc/book-jp/ch12.html です。これはオライリー『入門 自然言語処理』の訳者の方が書かれているものです。
まず、この検索結果をUTF-8形式のテキストファイルに保存します。
保存先は、説明が前後してしまいますが、NLTKのコーパスファイルのあるディレクトリ(私の場合、'nltk_data/corpora/')です。
>>>import codecs >>>f = codecs.open('nltk_data/corpora/tweets.txt', 'w', 'utf-8') >>>for t in tweets: ... f.write(t) >>>f.close()
ここまでできたら、一度Pythonを閉じて、$easy_install nltk を実行後Pythonを起動します。
そして、 import nltk とした後、 nltk.download() で表示される画面で選択し、 "all" というコレクション中の "jeita" という識別子を持つコーパスをインストールする。ホームディレクトリにnltk_dataというディレクトリが生成され、そのなかにあるzipファイルを解凍後、ファイルをnltk_data/corpora/下に移動します。
で、ここからが日本語のトークン化処理に入ります。
>>> import nltk >>> from nltk.corpus.reader import * >>> from nltk.corpus.reader.util import * >>> from nltk.text import Text
をまず実行する。
これ以降は Python による日本語自然言語処理 http://nltk.googlecode.com/svn/trunk/doc/book-jp/ch12.html を参考に、
各行を各パラグラフとして読み込むためには、 PlaintextCorpusReader オブジェクト生成時にコンストラクタの para_block_reader 引数に read_line_block を渡せばよい。また、「。」、「!」、「?」で終わる一連の文字列を文として認識し分割するために、以下の RegexpTokenizer を定義しよう。
>>> jp_sent_tokenizer = nltk.RegexpTokenizer(u'[^ 「」!?。]*[!?。]')
また、文字種はそれぞれ Unicode の範囲(ひらがなについては [ぁ-ん] 、カタカナについては [ァ-ン] 、漢字については U+4E00 〜 U+9FFF )を指定することによって検出できる。これらを RegexpTokenizer に渡す正規表現として以下のように書くことができる。
>>> jp_chartype_tokenizer = nltk.RegexpTokenizer(u'([ぁ-んー]+|[ァ-ンー]+|[\u4e00-\u9FFF]+|[^ぁ-んァ-ンー\u4e00-\u9FFF]+)')以上の各パラメータを使って、平文コーパスを読み込む PlaintextCorpusReader は以下のように宣言できる( /path/to/dir には、実際にコーパスファイルが置かれているディレクトリを指定する必要がある)。
を実行した後、
>>>word = PlaintextCorpusReader("nltk_data/corpora/", r'tweets.txt', encoding='utf-8', para_block_reader=read_line_block, sent_tokenizer=jp_sent_tokenizer, word_tokenizer=jp_chartype_tokenizer)
を実行します。
そのあと、print word.raw()で、ちゃんと文字列が日本語で表示されるか確認してみてください。
そしたら、print '/'.join(word.words())で、品詞で区切られているか確かめる。
この結果が気に入らない場合は、上記サイトを読み込んで他の方法を試してみてください(私は挫折しました…)。
そしてついに、『入門 ソーシャルデータ』p.8の1.2.2に進みます。
>>>tweets_t = '/'.join(word.words()) >>>words =[] >>>words = tweets_t.split('/')
これが、例1-7の最初の4行の代わりとなります。wordsの中身を確かめるには、
>>>for t in words: ... print t.encode(''utf-8')
を実行します。
繰り返しますが、配列には.encode('utf-8')の属性を指定できません。for文で配列の中身を1つずつtに移して、そこにエンコードを指定するというやり方をとらないといけません。
そして、
>>> len(words) 23232 >>> len(set(words)) 2948
といった結果がやっと得られました。
最初の一歩が重かった…。
私はPythonも自然言語処理も初心者で、この本で初めて取り組みました。
至らない所などたくさんあると思いますので、補足等、コメントいただけたら幸いです。