WordNetの上位語を取得する方法

投稿者: | 2018-03-10

ImageNetのクラス名はWordNetという概念辞書を使って定義されています。

ILSVRC2012(ImageNet Large Scale Visual Recognition Challenge 2012)というImageNetから作られたDatasetでは

  • dalmatian(ダルメシアン)
  • Staffordshire bullterrier(スタッフォードシャー・ブル・テリア)
  • Bouvier des Flandres(ブービエ・デ・フランダース)

など結構細かなクラス(いずれも犬種の名前)が設定されています。「犬」「動物」などもう少し上位の概念で整理したかったのでクラス名のWordNetIDから上位語を取得する方法を調べました。

環境・事前準備

Mac(OS: High Sierra)にAnaconda(version 4.3.30)をインストールして実行しています。Anacondaがインストールしている環境であればOSに関係なく動くと思います。

WordNetのデータを使うにはnltkパッケージを使います。初めて使う際にはデータをダウンロードする必要があるので

import nltk
nltk.download()

を実行します。GUIが表示されるので

左下の「download」というボタンを押下してデータをダウンロードしましょう。

上位語の取得方法

WordNetでは「dalmatian」(ダルメシアン)などの概念をsynsetと呼び、synset間に上位/下位/同族といった関係が定義されています。

例えば、「dalmatian」(ダルメシアン)というsynsetからは「dog」(犬)という上位語が定義されており、「liver spotted dalmetian」という下位語が定義されています。上位語が同じになるsynsetを同族語と呼び、「poodle」(プードル)などは上位語が「dog」になるので「dalmatian」(ダルメシアン)の同族語になります。

synsetと1対1に対応するWordNetID(例:n02110341)が定義されており

  • 先頭1文字目: 品詞を表す(posと呼ぶ)
  • 2文字目以降: 品詞辞書の何番目かを表す(offsetと呼ぶ)

というフォーマットになっています。

pos, offsetから対応するsynsetを返す関数がnltkパッケージに用意されており

import nltk
from nltk.corpus import wordnet as wn

wn.synset_from_pos_and_offset(pos, offset)

です。pos, offsetを与えるとSynsetオブジェクトを返します。例えば

>>> synset = wn.synset_from_pos_and_offset('n', 2110341)
>>> synset
Synset('dalmatian.n.02')

となります。

synsetの上位語はSynsetオブジェクトのhypernyms関数で取得できます。例えば、先ほどの例で

>>> synset.hypernyms()
[Synset('dog.n.01')]

と「dalmatian」(ダルメシアン)の上位語は「dog」(犬)だとがわかります。なお、上位語は複数存在することがあるためhypernyms関数は「Synsetオブジェクトのリスト」を返す仕様になっています。

上位語をたどっていくことで階層関係を知ることもでき

def GetHypernymsList(wordnet_id):
    pos = wordnet_id[0]
    offset = int(wordnet_id[1:])
    
    synset = wn.synset_from_pos_and_offset(pos, offset)
    synset_list = [synset]

    while True:
        if len(synset.hypernyms()) == 0:
            break

        synset = synset.hypernyms()[0]
        synset_list.insert(0, synset)
    
    return synset_list

を定義して

>>> GetHypernymsList('n02110341')

を実行すると

[Synset('entity.n.01'),
 Synset('physical_entity.n.01'),
 Synset('object.n.01'),
 Synset('whole.n.02'),
 Synset('living_thing.n.01'),
 Synset('organism.n.01'),
 Synset('animal.n.01'),
 Synset('chordate.n.01'),
 Synset('vertebrate.n.01'),
 Synset('mammal.n.01'),
 Synset('placental.n.01'),
 Synset('carnivore.n.01'),
 Synset('canine.n.02'),
 Synset('dog.n.01'),
 Synset('dalmatian.n.02')]

と「entity」(エンティティ)から「dalmatian」(ダルメシアン)まで15もの階層があることがわかります。

スポンサーリンク


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です