【问题标题】:Customized tag and lemmas for URLs using spaCy使用 spaCy 的 URL 的自定义标记和引理
【发布时间】:2018-01-05 10:51:35
【问题描述】:

考虑句子

msg = 'I got this URL https://stackoverflow.com/questions/47637005/handmade-estimator-modifies-parameters-in-init/47637293?noredirect=1#comment82268544_47637293 freed'

接下来,我使用开箱即用的spaCy 处理英文句子:

import spacy
nlp = spacy.load('en')
doc = nlp(msg)

让我们回顾一下[(t, t.lemma_, t.pos_, t.tag_, t.dep_) for t in doc]的输出:

[(I, '-PRON-', 'PRON', 'PRP', 'nsubj'),
 (got, 'get', 'VERB', 'VBD', 'ROOT'),
 (this, 'this', 'DET', 'DT', 'det'),
 (URL, 'url', 'NOUN', 'NN', 'compound'),
 (https://stackoverflow.com/questions/47637005/handmade-estimator-modifies-parameters-in-init/47637293?noredirect=1#comment82268544_47637293,
  'https://stackoverflow.com/questions/47637005/handmade-estimator-modifies-parameters-in-init/47637293?noredirect=1#comment82268544_47637293',
  'NOUN',
  'NN',
  'nsubj'),
 (freed, 'free', 'VERB', 'VBN', 'ccomp')]

我想改进对 URL 片段的处理。特别是,我想:

  1. 将其lemma 设置为stackoverflow.com
  2. tag 设置为URL

我怎样才能使用spaCy 做到这一点?我想使用正则表达式(如建议的here)来确定字符串是否为 URL 并获取域。到目前为止,我还没有找到方法。

EDIT 我想我需要一个自定义组件。但是,似乎没有办法将基于正则表达式(或任何其他)的可调用对象设置为 patterns

【问题讨论】:

  • 我建议使用 urlparse.urlsplit 进行 URL 处理和解析。您在此处称为 lemma 的内容将存储在 netloc 属性中的结果中。
  • @TomášLinhart 感谢您的指点。尽管如此,我还是不明白如何丰富sapCy产生的Doc类型
  • 要么创建一个包含 URL 解析的包装器,要么创建一个 URL 解析的第二遍。 sPacy 英语模型是用人类语言训练的。 URL 规范是人为的。可以使用其他库有效地解析它们。
  • 要么创建一个包含 URL 解析的包装器,要么创建一个 URL 解析的第二遍。 sPacy 英语模型是用人类语言训练的。 URL 规范是人为的。可以使用其他库有效地解析它们。

标签: python nlp spacy


【解决方案1】:

为 URL 自定义正则表达式

您可以使用自定义标记器指定 URL 正则表达式,例如来自https://spacy.io/usage/linguistic-features#native-tokenizers

import regex as re
from spacy.tokenizer import Tokenizer

prefix_re = re.compile(r'''^[\[\("']''')
suffix_re = re.compile(r'''[\]\)"']$''')
infix_re = re.compile(r'''[-~]''')
simple_url_re = re.compile(r'''^https?://''')

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=simple_url_re.match)

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

msg = 'I got this URL https://stackoverflow.com/questions/47637005/handmade-estimator-modifies-parameters-in-init/47637293?noredirect=1#comment82268544_47637293 freed'

for i, token in enumerate(nlp(msg)):
    print(i, ':\t', token)

[出]:

0 :  I
1 :  got
2 :  this
3 :  URL
4 :  https://stackoverflow.com/questions/47637005/handmade-estimator-modifies-parameters-in-init/47637293?noredirect=1#comment82268544_47637293
5 :  freed

检查token是否为URL

您可以检查令牌是否类似于 URL,例如

for i, token in enumerate(nlp(msg)):
    print(token.like_url, ':\t', token.lemma_)

[出]:

False :  -PRON-
False :  get
False :  this
False :  url
True :   https://stackoverflow.com/questions/47637005/handmade-estimator-modifies-parameters-in-init/47637293?noredirect=1#comment82268544_47637293
False :  free

如果 LIKE_URL 则更改标签

doc = nlp(msg)

for i, token in enumerate(doc):
    if token.like_url:
        token.tag_ = 'URL'

print([token.tag_ for token in doc])

[出]:

['PRP', 'VBD', 'DT', 'NN', 'URL', 'VBN']

用自定义的引理替换 URL 的引理

使用正则表达式https://regex101.com/r/KfjQ1G/1

doc = nlp(msg)

for i, token in enumerate(doc):
    if re.match(r'(?:http[s]:\/\/)stackoverflow.com.*', token.lemma_):
        token.lemma_ = 'stackoverflow.com'

print([token.lemma_ for token in doc])

[出]:

['-PRON-', 'get', 'this', 'url', 'stackoverflow.com', 'free']

【讨论】:

  • 第一部分,您定义了一个自定义标记器,非常棒!然而,其余的都是手动的,并没有集成到spaCy 的管道中。如何自定义管道,以便使用基于 regex 的规则处理 URL 实例?
  • 也许您必须覆盖nlp = spacy.load('en'); nlp.lemmatizernlp.tagger
  • 我猜是这样,但我不知道如何。
猜你喜欢
  • 1970-01-01
  • 2021-09-21
  • 2021-06-03
  • 1970-01-01
  • 2016-03-10
  • 2022-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多