web-dev-qa-db-ja.com

Infix正規表現を使用してトークンとしてハイフン単語のみを含めるSpacyカスタムトークナイザー

たとえば、ハイフンの単語を1つのトークンとしてSpacyに含めたいと思います:長期、自尊心など。 Stackoverflow、 Github 、その documentation および elsewhere に関するいくつかの同様の投稿を見た後、以下のようにカスタムトークナイザーも作成しました。

import re
from spacy.tokenizer import Tokenizer

prefix_re = re.compile(r'''^[\[\("']''')
suffix_re = re.compile(r'''[\]\)"']$''')
infix_re = re.compile(r'''[.\,\?\:\;\...\‘\’\`\“\”\"\'~]''')

def custom_tokenizer(nlp):
    return Tokenizer(nlp.vocab, prefix_search=prefix_re.search,
                                suffix_search=suffix_re.search,
                                infix_finditer=infix_re.finditer,
                                token_match=None)

nlp = spacy.load('en_core_web_lg')
nlp.tokenizer = custom_tokenizer(nlp)

doc = nlp(u'Note: Since the fourteenth century the practice of “medicine” has become a profession; and more importantly, it\'s a male-dominated profession.')
[token.text for token in doc]

したがって、この文については次のようになります。 '注:14世紀以降、「医学」の実践は職業になりました。そしてもっと重要なことに、それは男性が支配する職業です。」

これで、カスタムSpacy Tokenizerを組み込んだ後のトークンは次のとおりです:

'注'、 ':'、 '以来'、 ''、 '14世紀'、 '世紀'、 ''、 '実践'、 'の'、 '"医学'、 ''、 'has'、 ';'、 'become'、 'a'、 'profession' 、 '、'、 'および'、 'more'、 '重要な'、 '、'、 "it's"、 'a'、 '男性優位 '、'職業 '、'。 '

以前は、この変更前のトークンは次のとおりでした:

'注'、 ':'、 '以来'、 ''、 '14世紀'、 '世紀'、 ''、 '実践'、 'の'、 ' " '、'medicine '、' '、'は '、'になる '、' a '、'職業 '、'; '、'および '、'もっと '、'重要な '、'、 '、'it '、 "' s"、 'a'、 'male '、'- '、'支配的'、 '職業'、 '。'

そして、期待されるトークンは次のようになります:

'注'、 ':'、 '以来'、 ''、 '14世紀'、 '世紀'、 ''、 '実践'、 'の'、 ' " '、'medicine '、' '、'は '、'になる '、' a '、'職業 '、'; '、'および '、'もっと '、'重要な '、'、 '、'it '、 "' s"、 'a'、 '男性優位 '、'職業 '、'。 '

ハイフンの単語が含まれていることがわかるように、二重引用符とアポストロフィを除く他の句読点も含まれています。しかし、現在、アポストロフィと二重引用符は、以前の、または期待された動作をしていません。 Infixの正規表現コンパイルでさまざまな順列と組み合わせを試しましたが、この問題を修正するための進捗はありません。したがって、どんな助けでも大歓迎です。

6
Vishal

デフォルトのprefix_reとsuffix_reを使用すると、期待される出力が得られます。

import re
import spacy
from spacy.tokenizer import Tokenizer
from spacy.util import compile_prefix_regex, compile_infix_regex, compile_suffix_regex

def custom_tokenizer(nlp):
    infix_re = re.compile(r'''[.\,\?\:\;\...\‘\’\`\“\”\"\'~]''')
    prefix_re = compile_prefix_regex(nlp.Defaults.prefixes)
    suffix_re = compile_suffix_regex(nlp.Defaults.suffixes)

    return Tokenizer(nlp.vocab, prefix_search=prefix_re.search,
                                suffix_search=suffix_re.search,
                                infix_finditer=infix_re.finditer,
                                token_match=None)

nlp = spacy.load('en')
nlp.tokenizer = custom_tokenizer(nlp)

doc = nlp(u'Note: Since the fourteenth century the practice of “medicine” has become a profession; and more importantly, it\'s a male-dominated profession.')
[token.text for token in doc]

['Note'、 ':'、 'Since'、 'the'、 '14th'、 'century'、 'the'、 'practice'、 'of'、 '"'、 'medicine'、 '"'、 ' '、'になる '、' a '、'職業 '、'; '、'および '、'もっと '、'重要な '、'、 '、' it '、 "' s"、 'a'、 '男性-支配的な '、'職業 '、'。 ']

正規表現がSpaCyのように機能しなかった理由を詳しく知りたい場合は、関連するソースコードへのリンクを次に示します。

ここで定義されているプレフィックスとサフィックス:

https://github.com/explosion/spaCy/blob/master/spacy/lang/punctuation.py

ここで定義されている文字(引用符、ハイフンなど)を参照して:

https://github.com/explosion/spaCy/blob/master/spacy/lang/char_classes.py

そして、それらをコンパイルするために使用される関数(例:compile_prefix_regex):

https://github.com/explosion/spaCy/blob/master/spacy/util.py

15
Nicholas Morley