入門 自然言語処理(O'Reilly) 2章 (1)

『入門 自然言語処理』2章 テキストコーパスと語彙資源へのアクセス (1)

入門 自然言語処理

入門 自然言語処理

コーパス(corpus)を扱う。コーパスってなんやねん。

コーパス(corpus)とは、言語学において、自然言語処理の研究に用いるため、自然言語の文章を構造化し大規模に集積したもの。構造化では言語的な情報(品詞、統語構造など)が付与される。 コーパス - Wikipedia

コーパスには生データだけではなく、品詞などのデータが付与されてたりする。

2.1 テキストコーパスへのアクセス

グーテンベルクコーパス

import nltk
nltk.corpus.gutenberg.fileids()

コーパス内のファイル識別子を一覧表示する。

emma = nltk.corpus.gutenberg.words('austen-emma.txt')
len(emma)
# 192427

長いのでモジュール名を省略:

from nltk.corpus import gutenberg

コーパスに含まれるテキストの単語の平均長、文の平均長、単語の平均出現回数とテキスト名を表示する:

for fileid in gutenberg.fileids():
    num_chars = len(gutenberg.raw(fileid))
    num_words = len(gutenberg.words(fileid))
    num_sents = len(gutenberg.sents(fileid))
    num_vocab = len(set([w.lower() for w in gutenberg.words(fileid)]))
    print int(num_chars/num_words), int(num_words/num_sents), int(num_words/num_vocab), fileid

単語の平均長は英語の一般的な特性と同様に「4」となる。ここで、raw()は生データへのアクセス。words()sents()はそれぞれ単語と文へのアクセス。

…あまり整っていない言語データを扱うことも重要である。NLTKにはウェブテキストもわずかながら含まれており、そこにはFirefoxフォーラムでの議論や、ニューヨークの街で耳にするような会話、『パイレーツ・オブ・カリビアン』の台本、個人による広告、そしてワインのレビューから得られた文章などが含まれている。(p44)

すごい。以下は米国海軍大学院がインターネット犯罪の自動検出のために収集したウェブチャットのログ:

from nltk.corpus import nps_chat
chatroom = nps_chat.posts('10-19-20s_706posts.xml')
chatroom[123]
# ['i', 'do', "n't", 'want', 'hot', 'pics', 'of', 'a', 'female', ',', 'I', 'can', 'look', 'in', 'a', 'mirror', '.']

いい文章。

バリエーション:ブラウンコーパス(brown)

1961年にブラウン大学で作成された初の電子コーパスブラウンコーパスも利用できる。いくつかのジャンルに分けられている:

brown.categories()
# ['adventure', 'belles_lettres', 'editorial', 'fiction', 'government', 'hobbies', 'humor', 'learned', 'lore', 'mystery', 'news', 'religion', 'reviews', 'romance', 'science_fiction']
brown.words(categories='news')
# ['The', 'Fulton', 'County', 'Grand', 'Jury', 'said', ...]
brown.words(fileids=['cg22'])
# ['Does', 'our', 'society', 'have', 'a', 'runaway', ',', ...]
brown.words(fileids=['cg22', 'ch15'])
# ['Does', 'our', 'society', 'have', 'a', 'runaway', ',', ...]
brown.sents(categories=['news', 'editorial', 'reviews'])
# [['The', ... , '.'], ...] # 長いので省略

ブラウンコーパスは、ジャンルの系統的な差異の研究(文体論として知られている一種の言語学研究)をするためには便利な資源である。(p45)

from nltk.corpus import brown
news_text = brown.words(categories='news')
fdist = nltk.FreqDist([w.lower() for w in news_text])
modals = ['can', 'could', 'may', 'might', 'must', 'will']
for m in modals:
    print m + ':', fdist[m],
# can: 94 could: 87 may: 93 might: 38 must: 53 will: 389

ブラウンコーパスをソースにして法助動詞(modal verb)の数を調べてみる。canやmustなどを、助動詞(auxiliary verb)の中でも区別して法助動詞と呼ぶことを初めて知った。(参考: 英語の文法のことで質問です。 modal verb(法助動詞)とauxiliary verb(助動詞)はど... - Yahoo!知恵袋

cfd = nltk.ConditionalFreqDist(
      (genre, word)
      for genre in brown.categories()
      for word in brown.words(categories=genre))
genres = ['news', 'religion', 'hobbies', 'science_fiction', 'romance', 'humor']
modals = ['can', 'could', 'may', 'might', 'will']
cfd.tabulate(conditions=genres, samples=modals)
# 結果は省略

ジャンルごとの法助動詞の数。Romanceでcouldとmightが多いのは仮定法的な曖昧なニュアンスの文が多いから?面白い。

バリエーション:ロイターニュース(reuters)

ロイターニュースのコーパスもある。trainingとtestという2つのグループに分けられている:

from nltk.corpus import reuters
reuters.categories('training/9865')
# ['barley', 'corn', 'grain', 'wheat']
reuters.words('training/9865')[:14]
# ['FRENCH', 'FREE', 'MARKET', 'CEREAL', 'EXPORT', 'BIDS', 'DETAILED', 'French', 'operators', 'have', 'requested', 'licences', 'to', 'export']

ニュース記事なので、1つのファイルが複数のカテゴリーを持つことがある。タイトルは大文字。

バリエーション:就任演説(inaugural)

アメリカ大統領の就任演説には年号が振ってある:

from nltk.corpus import inaugural
inaugural.fileids()
# ['1789-Washington.txt', ... , '2009-Obama.txt'] # 途中省略

americaとcitizenで始まる単語の数の変遷を見る:

cfd = nltk.ConditionalFreqDist(
      (target, fileid[:4])                   # 縦軸はカウント、横軸は年号
      for fileid in inaugural.fileids()      # テキストの名前(はじめの4文字は年号)を取ってくる
      for w in inaugural.words(fileid)       # それぞれのテキストの単語を取ってくる→あとで使う
      for target in ['america', 'citizen']   # americaとcitizenについて調べることにする
      if w.lower().startswith(target))       # americaとcitizenで始まっている単語を数える?(よくわからない)
cfd.plot()

コーパスはウェブからダウンロード可能

品詞情報や固有表現などの言語学的注釈付けがされたコーパスをさらにいろいろ使用できる、らしい。www.nltk.org/dataを参照。

他の言語のコーパス

文字コードに注意が必要らしい:

nltk.corpus.cess_esp.words()

cess_espがないと言われた:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/nltk-2.0.4-py2.7.egg/nltk/corpus/util.py", line 68, in __getattr__
    self.__load()
  File "/usr/local/lib/python2.7/dist-packages/nltk-2.0.4-py2.7.egg/nltk/corpus/util.py", line 56, in __load
    except LookupError: raise e
LookupError: 
**********************************************************************
  Resource 'corpora/cess_esp' not found.  Please use the NLTK
  Downloader to obtain the resource:  >>> nltk.download()
  Searched in:
    - '/home/****/nltk_data'
    - '/usr/share/nltk_data'
    - '/usr/local/share/nltk_data'
    - '/usr/lib/nltk_data'
    - '/usr/local/lib/nltk_data'
**********************************************************************

指示に従ってnltk.download()を使ってcorpora/cess_espをダウンロード。

nltk.corpus.cess_esp.words()
['El', 'grupo', 'estatal', 'Electricit\xe9_de_France', ...]

同じ調子でcorpora/florestacorpora/indianをダウンロードした。

udhrは300以上の言語の世界人権宣言が入っている。

自作のコーパスを読む

当分使わなそうなので、キーワードだけ書いておく:PlaintextCorpusReaderBracketParseCorpusReader

今日はここまで。