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

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

少し間が空いたけれど、2章の続き。

(1)/(2)

2.4 語彙資源

語彙資源とは

品詞や語義定義のような関連情報を含んだ単語や句のコレクションのことを語彙目録、あるいは語彙資源と呼ぶ(p62)

語彙リストコーパス

def unusual_words(text):
    text_vocab = set(w.lower() for w in text if w.isalpha()) # テキストの単語集合
    english_vocab = set(w.lower() for w in nltk.corpus.words.words()) # 英語の語彙リストに入っている単語集合
    unusual = text_vocab.difference(english_vocab) # 集合の差(一般的でない単語やスペルミス)を取る
    return sorted(unusual) # 集合の差をソートして返す

from nltk.corpus import gutenberg
unusual_words(nltk.corpus.gutenberg.words('austen-sense.txt'))

ストップワード(theとかaとか高頻度で出現する単語)のコーパスもある。これらは大して意味がないので、前処理として単語リストから取り除くことが多い、らしい。

from nltk.corpus import stopwords
def content_fraction(text):
    stopwords = nltk.corpus.stopwords.words('english') # ストップワードを読み込む
    content = [w for w in text if w.lower() not in stopwords] # ストップワード以外の単語を抽出
    return float(len(content)) / len(text)

名前についての分析

names = nltk.corpus.names
cfd = nltk.ConditionalFreqDist(
      (fileid, name[-1]) # 条件はfileid、事象は名前の後ろ1文字
      for fileid in names.fileids() # fileidはmale.txtとfemale.txt
      for name in names.words(fileid)) # 名前を抽出
cfd.plot() # グラフを描画

発音辞書

NLTKには「CMU Pronouncing Dictionary」というカーネギーメロン大学によるアメリカ英語の発音辞書が含まれている。nltk.corpus.cmudict

比較語彙リスト

Swadesh語彙リストという比較語彙リストがある。これを使えば複数言語間で同じ意味をもつ単語を調べられる。from nltk.corpus import swadesh

ShoeboxとToolbox

Toolbox

言語学者がデータを管理する際に用いるツールとして、おそらくもっとも人気のあるものだ。(p70)

使う場面がいまいち想像できない。

2.5 WordNet

synsets(<word>)が属する同義語集合を調べる。motorcarは1つに限定されるが、carはいっぱいある。

from nltk.corpus import wordnet as wn
wn.synsets('motorcar')
# [Synset('car.n.01')]
wn.synset('car.n.01').lemma_names
# ['car', 'auto', 'automobile', 'machine', 'motorcar']
wn.synset('car.n.01').definition # 定義
# 'a motor vehicle with four wheels; usually propelled by an internal combustion engine'
wn.synset('car.n.01').examples
# ['he needs a car to get to work']
wn.synsets('car')
# [Synset('car.n.01'), Synset('car.n.02'), Synset('car.n.03'), Synset('car.n.04'), Synset('cable_car.n.01')]

階層構造

上の[Synset('car.n.01')]はmotorcarやcarが属するカテゴリを示す。階層構造になっていて、hyponums()で直接の下位概念を、hypernyms()で直接の上位概念を得られる。最上位概念までの経路はhypernym_paths()、最上位概念はroot_hypernyms()で得られる。

motorcar = wn.synset('car.n.01')
types_of_motorcar = motorcar.hyponyms()
sorted([lemma.name for synset in types_of_motorcar for lemma in synset.lemmas])
# ['Model_T', 'S.U.V.', ...]
motorcar.hypernyms
# <bound method Synset.hypernyms of Synset('car.n.01')>

他の関係

  • メロニム: part_meronyms(), substance_meronyms()
    • ある要素からそれを含む要素への関係
    • 木→幹・枝
  • ホロニム: member_holonyms()
    • 構成要素とそれを含む要素
    • 木→森
  • entailments()
  • antonyms()
wn.synset('tree.n.01').part_meronyms()
# [Synset('burl.n.02'), Synset('crown.n.07'), Synset('stump.n.01'), Synset('trunk.n.01'), Synset('limb.n.02')]
wn.synset('tree.n.01').substance_meronyms()
# [Synset('heartwood.n.01'), Synset('sapwood.n.01')]
wn.synset('tree.n.01').member_holonyms()
# [Synset('forest.n.01')]

意味類似性

lowest_common_hypernyms()で共通の上位集合のうち最も下位の集合を出す。これを見て単語の関連の度合いを観察できる。以下はright whale(セミクジラらしい)との比較の例:

right = wn.synset('right_whale.n.01')
right.lowest_common_hypernyms(wn.synset('orca.n.01'))
# [Synset('whale.n.02')]
right.lowest_common_hypernyms(wn.synset('minke_whale.n.01'))
# [Synset('baleen_whale.n.01')]
right.lowest_common_hypernyms(wn.synset('tortoise.n.01'))
# [Synset('vertebrate.n.01')]
right.lowest_common_hypernyms(wn.synset('novel.n.01'))
# [Synset('entity.n.01')] # novelとは関連が無さそう

ある集合の階層の深さはmin_depth()で取得できる。浅ければより一般的な概念ということ。path_similarity()はこの考え方から類似性を算出する。

right.path_similarity(wn.synset('minke_whale.n.01'))
# 0.25
right.path_similarity(wn.synset('novel.n.01'))
# 0.043478260869565216

小説よりもミンククジラとの類似性が高いことがわかる。

類似性算出は以下のようなメソッドもある:

  • jcn_similarity()
  • lch_similarity()
  • lin_similarity()
  • res_similarity()
  • wup_similarity()

参考文献

コーパスについてのリンク