2016/02/03更新

[自然言語] Wordnet × Pythonで類義語を抽出する

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
最近はブログがご無沙汰になってしまっていたのでそろそろ書き出そうと思う今日この頃。本日は最近激勉強中の機械学習や自然言語処理からブログを書きます。Wordnetと呼ばれる自然言語の分類体系を用いて、指定した単語の類義語を取得する方法を書きたいと思います。

画像


目次




Wordnetとは

Wordnet(日本語版)シソーラス(言葉を同義語や意味上の類似関係、包含関係などによって分類した辞書)で単語間の関係を保持しています。この関係性を利用することで、ある単語の類義語を得ることができます。


シソーラスのイメージ

引用:http://astamuse.com/ja/published/JP/No/2010129025



このシソーラスを持つWordnetを、今回はPythonから利用して、類義語を出してみたいと思います。



Wordnetのセットアップ

Wordnetの情報はいくつかの形態で公開されていますが、今回はsqlite3のDBで公開されているものを使います。以下のサイトからデータをダウンロードします。
http://compling.hss.ntu.edu.sg/wnja/

ダウンロードしたDBファイルをpythonから読み込むことで、Wordnetを利用することができます。



PythonでWordnetを使う

Pythonから上記のsqlite3内のデータにアクセスすることで、類義語を取得することができます。日本語WordNetのフロントエンドを弄るよりソースコードをかなり参考にしながら、Python3に書き直して、必要な部分を実装しました。ソースコードはGithubにもアップしました。
# -*- coding: utf-8 -*-
# Wordnet via Python3
# 
# ref:
#   WordList_JP: http://compling.hss.ntu.edu.sg/wnja/
#   python3: http://sucrose.hatenablog.com/entry/20120305/p1
import sys, sqlite3
from collections import namedtuple
from pprint import pprint

conn = sqlite3.connect("./wnjpn.db")

Word = namedtuple('Word', 'wordid lang lemma pron pos')

def getWords(lemma):
  cur = conn.execute("select * from word where lemma=?", (lemma,))
  return [Word(*row) for row in cur]

 
Sense = namedtuple('Sense', 'synset wordid lang rank lexid freq src')

def getSenses(word):
  cur = conn.execute("select * from sense where wordid=?", (word.wordid,))
  return [Sense(*row) for row in cur]

Synset = namedtuple('Synset', 'synset pos name src')

def getSynset(synset):
  cur = conn.execute("select * from synset where synset=?", (synset,))
  return Synset(*cur.fetchone())

def getWordsFromSynset(synset, lang):
  cur = conn.execute("select word.* from sense, word where synset=? and word.lang=? and sense.wordid = word.wordid;", (synset,lang))
  return [Word(*row) for row in cur]

def getWordsFromSenses(sense, lang="jpn"):
  synonym = {}
  for s in sense:
    lemmas = []
    syns = getWordsFromSynset(s.synset, lang)
    for sy in syns:
      lemmas.append(sy.lemma)
    synonym[getSynset(s.synset).name] = lemmas
  return synonym

def getSynonym (word):
    synonym = {}
    words = getWords(word)
    if words:
        for w in words:
            sense = getSenses(w)
            s = getWordsFromSenses(sense)
            synonym = dict(list(synonym.items()) + list(s.items()))
    return synonym


if __name__ == '__main__':
    if len(sys.argv) >= 2:
        synonym = getSynonym(sys.argv[1])
        pprint(synonym)
    else:
        print("You need at least 1 argument as a word like below.\nExample:\n  $ python3 wordnet_jp 楽しい")
上記を実装した後に、ターミナルから以下のように利用することで類義語を表示することができます。
$ python3 wordnet_jp.py 楽しい
{'delicious': ['楽しい',
               'おもろい',
               '愉快',
               'おもしろい',
               '悦ばしい',
               '小気味好い',
               '心嬉しい',
               '愉しい',
               '喜ばしい',
               '心うれしい',
               '小気味よい',
               '面白い'],
 'entertaining': ['可笑しい', '楽しい', '面白い'],
 'good': ['楽しい'],
 'gratifying': ['楽しい',
                '愉快',
                'おもしろい',
                '悦ばしい',
                '満足',
                '心嬉しい',
                '痛快',
                '愉しい',
                '心うれしい',
                '面白い'],
 'happy': ['うれしい',
           '愉しげ',
           '楽しい',
           '明るい',
           '仕合わせ',
           'ご機嫌',
           '楽しげ',
           '悦ばしい',
           '御機嫌',
           'ハッピー',
           '心嬉しい',
           '大喜び',
           '幸福',
           '幸せ',
           '喜ばしい',
           '仕合せ',
           '嬉しい',
           '心うれしい',
           '嬉々たる'],
 'merry': ['楽しい', '楽しげ', '賑やか', '面白い'],
 'pleasant': ['愉しげ',
              '心地良い',
              '楽しい',
              'よい',
              '好い',
              '快然たる',
              '愉快',
              '気持ち良い',
              '楽しげ',
              '快い',
              '麗しい',
              '快適',
              'いい',
              '好いたらしい',
              '良い',
              '心地よい',
              '善い',
              '愉しい',
              '嬉しい',
              '心地好い']}
こんな感じで類義語を表示することができます。



最後に

本日は無料で使えるシソーラスのWordnetを用いた、類義語取得をブログに書きました。自然言語処理は絶賛勉強中ですが、こーゆうことなどできることが増えるのは楽しいなぁと思う今日この頃です。勉強したことは定期的にブログに書いていければと思います。

本ブログでは、フロントエンドに関する情報を中心に発信していきます。気になった方はぜひ、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。