大学の課題でWordNetを触る機会があり,備忘録として残すことにします.
私が作りたかったプログラムとしては,入力を言葉,出力は最上位語までの全ての上位語を出力することです.
WordNetの導入
WordNetの導入や軽く触ってみるのに参考にさせていたいただいた記事はこちらです.
この記事を読む前に見ておくといいと思います.
参考:https://qiita.com/pocket_kyoto/items/f2382b9821d32624e6bc
WordNetは以下のURLの
日本語WordNet:http://compling.hss.ntu.edu.sg/wnja/
のリリースダウンロードページから 「Japanese Wordnet and English WordNet in an sqlite3 database」をダウンロード.
WordNetデータベースのテーブルの内容
WordNetデータベースのテーブルの内容の理解には以下のWebページを参考にしました.
これらのWebページを見ながら,この記事を読むとコードの理解が早いと思います.
参考:
https://blog.apitore.com/2017/05/17/api-wordnet-detail/
https://qiita.com/hiraski/items/50fea4c489bcc4823bc4
上位語を検索する
上位語の検索を行うにあたり,始めに参考にさせていただいた記事はこちらです.
参考:https://qiita.com/pocket_kyoto/items/f2382b9821d32624e6bc
しかし,この方法では入力された言葉の最上位語しか出力されないので,これを元に改良しました.
以下が,そのコードとなります.(まだまだ至らない点があるコードなのでご了承ください.)
今回は,「猫」の上位語を検索しています.
プログラム
import sqlite3
import copy
def dfs(synset_tree):
for synset_root in synset_tree:
#上位語を検索
cur = conn.execute("select synset1 from synlink where synset2='%s' and link='hypo'" % synset_root[len(synset_root)-1])
synsets = []
for result in cur:
synsets.append(result[0])
#上位語が一つもないとき
if len(synsets) == 0:
return
#上位語が一つの場合
elif len(synsets) == 1:
synset_root.append(synsets[0])
dfs(synset_tree)
#上位語が複数の場合
elif len(synsets) > 1:
#現在の道を(上位語の数-1)コ複製する
for i in range(len(synsets)-1):
synset_tree.append(copy.deepcopy(synset_root))
#それぞれ複製した道に複数ある上位語を一つずつ割り当てる
tree_index = 0
for hypernym in synsets:
synset_tree[tree_index].append(hypernym)
tree_index += 1
dfs(synset_tree)
if __name__ == '__main__':
#データベースに接続
conn = sqlite3.connect("wnjpn.db")
#単語からそのWordIDを取得
word = "猫"
cur = conn.execute("select wordid from word where lemma='%s'" % word)
word_id = 99999999 #temp
for row in cur:
word_id = row[0]
#WordNetに存在する語であるかの判定
if word_id==99999999:
print("[%s]は,WordNetに存在しない単語です." % word)
else:
#WordIDからsynsetIDを取得
cur = conn.execute("select synset from sense where wordid='%s'" % word_id)
synset=[]
for row in cur:
synset.append(row[0])
#synsetIDから全ての上位語を検索し,synsetIDのリストとして返す.
#一つの単語に風数の意味がある場合,synsetは複数になりますが,今回は始めに格納されているものを使います
synset_roots=[]
synset_roots.append([synset[0]])
dfs(synset_roots)
#概念に含まれる単語を検索して画面に出力する
no = 1
for root in synset_roots:
for synsetID in root:
cur1 = conn.execute("select name from synset where synset='%s'" % synsetID)
for row1 in cur1:
print("%sつめの概念:%s" %(no, row1[0]))
cur2 = conn.execute("select def from synset_def where (synset='%s' and lang='jpn')" % synsetID)
sub_no = 1
for row2 in cur2:
print("意味%s:%s" %(sub_no, row2[0]))
sub_no += 1
no += 1
print("")
出力
1つめの概念:true_cat
意味1:通常、厚く柔らかい毛皮を持ち、吠えることのできないネコ科の哺乳類:家ネコ
意味2:ヤマネコ
2つめの概念:feline
意味1:しなやかな体で頭の丸い様々な裂脚類の哺乳動物で、多くは引っ込めることのできる鉤爪を持つ
3つめの概念:carnivore
意味1:地上性または水生の食肉哺乳動物
4つめの概念:placental
意味1:胎盤を持つ哺乳動物
意味2:単孔動物と有袋動物以外のすべての哺乳動物
5つめの概念:mammalian
意味1:皮膚がほぼ毛で覆われている、温血脊椎動物
意味2:単孔類の小亜綱を除いて子供は生きたまま生まれミルクで育てられる
6つめの概念:vertebrate
意味1:分割した脊柱と頭蓋骨または頭蓋に包まれた大脳を持つ骨性または軟骨性頭蓋骨を持つ動物
7つめの概念:chordate
意味1:脊索または脊柱を持つ脊索門の動物
8つめの概念:animate_being
意味1:自発的な運動に特徴付けられる、生命を持つ有機体
9つめの概念:being
意味1:独立して行うまたは機能する能力を持つ(またはそのように発達することができる)生き物
10つめの概念:living_thing
意味1:生きている(または一度は生きていたば)実在物
11つめの概念:whole
意味1:1つのものとしてとらえらえる、部分の集合
12つめの概念:physical_object
意味1:触れることができて目に見える実体
意味2:影を落とすことができる実体
13つめの概念:physical_entity
意味1:物理的な存在がある実体
14つめの概念:entity
意味1:(生命がある、あるいは生命がないに関わらず)それ自身の明確な存在を持つと感知される、知られている、あるいは推定される何か