Соответствие по ключевому слову и его дочернему пространству - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть набор ключевых слов, по которым я уже соответствую.Это медицинский контекст, поэтому я создал эквивалентный сценарий, по крайней мере, для анализа, который я пытаюсь выполнить:

У меня есть машина с хромированными 1000-дюймовыми ободами.

Допустим, я хочу вернуть как фразу все дочерние слова / токены ключевого слова rims , где rims уже помечено SpaCy как сущность как CARPART.

В Python это то, что я делаю:

test_phrases = nlp("""I have a car with chrome 100-inch rims.""")
print(test_phrases.cats)
for t in test_phrases:
    print('Token: {} || POS: {} || DEP: {} CHILDREN: {} || ent_type: {}'.format(t,t.pos_,t.dep_,[c for c in t.children],t.ent_type_))

Token: I || POS: PRON || DEP: nsubj CHILDREN: [] || ent_type: 
Token: have || POS: VERB || DEP: ROOT CHILDREN: [I, car, .] || 
ent_type: 
Token: a || POS: DET || DEP: det CHILDREN: [] || ent_type: 
Token: car || POS: NOUN || DEP: dobj CHILDREN: [a, with] || ent_type: 
Token: with || POS: ADP || DEP: prep CHILDREN: [rims] || ent_type: 
Token: chrome || POS: ADJ || DEP: amod CHILDREN: [] || ent_type: 
Token: 100-inch || POS: NOUN || DEP: compound CHILDREN: [] || ent_type: 
Token: rims || POS: NOUN || DEP: pobj CHILDREN: [chrome, 100-inch] || 
ent_type: 
Token: . || POS: PUNCT || DEP: punct CHILDREN: [] || ent_type: CARPART

Итак, я хочу использовать что-то вроде:

test_matcher = Matcher(nlp.vocab)

test_phrase = ['']
patterns = [[{'ENT':'CARPART',????}] for kp in test_phrase]
test_matcher.add('CARPHRASE', None, *patterns)

вызов test_matcher on test_doc вернуть его:

chrome 100-inch rims

1 Ответ

0 голосов
/ 21 ноября 2018

Я думаю, что нашел удовлетворительное решение, которое будет работать при создании объекта Spacy Class.Вы можете проверить это, чтобы убедиться, что оно работает с вашим решением, а затем добавить что-то вроде this в конвейере Spacy:

from spacy.matcher import Matcher

keyword_list = ['rims']
patterns = [[{'LOWER':kw}] for kw in keyword_list]

test_matcher.add('TESTPHRASE',None, *patterns)


 def add_children_matches(doc,keyword_matcher):
     '''Add children to match on original single-token keyword.'''
    matches = keyword_matcher(doc)
    for match_id, start, end in matches:
        tokens = doc[start:end]
        print('keyword:',tokens)
        # Since we are getting children for keyword, there should only be one token
        if len(tokens) != 1:
            print('Skipping {}. Too many tokens to match.'.format(tokens))
            continue
        keyword_token = tokens[0]
        sorted_children = sorted([c.i for c in keyword_token.children] + [keyword_token.i],reverse=False)
        print('keyphrase:',doc[min(sorted_children):max(sorted_children)+1])



doc = nlp("""I have a car with chrome 1000-inch rims.""")
add_children_matches(doc,test_matcher)

Это дает:

keyword: rims
keyphrase: chrome 1000-inch rims

Изменить: Чтобы полностью ответить на мой собственный вопрос, вы должны использовать что-то вроде:

 def add_children_matches(doc,keyword_matcher):
     '''Add children to match on original single-token keyword.'''
    matches = keyword_matcher(doc)
    spans = []
    for match_id, start, end in matches:
        tokens = doc[start:end]
        print('keyword:',tokens)
        # Since we are getting children for keyword, there should only be one token
        if len(tokens) != 1:
            print('Skipping {}. Too many tokens to match.'.format(tokens))
            continue
        keyword_token = tokens[0]
        sorted_children = sorted([c.i for c in keyword_token.children] + [keyword_token.i],reverse=False)
        print('keyphrase:',doc[min(sorted_children):max(sorted_children)+1])


    start_char = doc[min(sorted_children):max(sorted_children)+1].start_char
    end_char = doc[min(sorted_children):max(sorted_children)+1].end_char

    span = doc.char_span(start_char, end_char,label='CARPHRASE')
    if span != None:
        spans.append(span)

    return doc
...