アイソモカ

知の遊牧民の開発記録

開発記録 200128 Tue (100本ノック #056)

前回 の続き。

 

言語処理100本ノック #056 続き

56. 共参照解析

Stanford Core NLPの共参照解析の結果に基づき,文中の参照表現(mention)を代表参照表現(representative mention)に置換せよ.ただし,置換するときは,「代表参照表現(参照表現)」のように,元の参照表現が分かるように配慮せよ.

解答

まず、coreference 部分に記述されている共参照解析結果から、(代表参照表現でない)を取り出し、key = (センテンスID, トークンID), value = Mention クラスのオブジェクトとなる辞書に格納する。Mention クラスでは、置換された部分が分かりやすいように、置換する表現を [代表参照表現](参照表現) とする。

その後で、sentences 部分を読んでいく。参照表現の置換が行われる場合には、参照表現の終わり(end)まで読み飛ばす。

語(token) ごとにスペースで区切り、カンマとピリオドの前にはスペースを入れない(関数 print_word() で指定)。文ごとに改行して出力するようにした。

# knock_054.py
import xml.etree.ElementTree as ET
xmlfile = 'nlp.txt.xml'


class Mention:
    def __init__(self, mention, rep):
        self.sentence = int(mention.find('sentence').text)
        self.start = int(mention.find('start').text)
        self.end = int(mention.find('end').text)
        self.text = mention.find('text').text
        self.rep = rep
    def __str__(self):
        return '[%s](%s)' % (self.rep, self.text)


def get_mention(root):
    for coreference in root.findall('./document/coreference/coreference'):
        for mention in coreference.findall('./mention'):
            if mention.get('representative') == 'true':
                rep = mention.find('text').text
            else:
                m = Mention(mention, rep)
                yield m


def print_word(word, t_id):
    if word in [',', '.'] or t_id == 1:
        print(word, end='')
    else:
        print('', word, end='')


def replace_sentence(root, mention_dict):
    for sentence in root.findall('./document/sentences/sentence'):
        end = 0
        s_id = int(sentence.get('id'))
        for token in sentence.findall('./tokens/token'):
            t_id = int(token.get('id'))
            
            if t_id < end:
                continue

            if (s_id, t_id) in mention_dict.keys():
                end = mention_dict[(s_id, t_id)].end
                print_word(mention_dict[(s_id, t_id)], t_id)
            else:
                print_word(token.find('word').text, t_id)
        print('\n', end='')


if __name__ == '__main__':
    tree = ET.parse(xmlfile)
    root = tree.getroot()

    mention_dict = {}
    for m in get_mention(root):
        mention_dict[(m.sentence, m.start)] = m

    replace_sentence(root, mention_dict)

結果

# python knock_056.py >> knock_056.txt の41行目
Such models have the advantage that [Such models](they) can express the relative certainty of many different possible answers rather than only one, producing more reliable results when such a model is included as a component of a larger system.