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もの階層があることがわかります。