jma*_*gue 5 python tokenize hashtag spacy
在包含主题标签的句子中,例如推文,spacy 的标记器将主题标签拆分为两个标记:
import spacy
nlp = spacy.load('en')
doc = nlp(u'This is a #sentence.')
[t for t in doc]
Run Code Online (Sandbox Code Playgroud)
输出:
[This, is, a, #, sentence, .]
Run Code Online (Sandbox Code Playgroud)
我想按如下方式标记标签,这可能吗?
[This, is, a, #sentence, .]
Run Code Online (Sandbox Code Playgroud)
小智 6
我还尝试了几种方法来防止 spaCy 用“cutting-edge”之类的连字符分割主题标签或单词。我的经验是,之后合并令牌可能会出现问题,因为 pos 标记器和依赖项解析器已经在他们的决定中使用了错误的令牌。触摸中缀、前缀、后缀正则表达式很容易出错/复杂,因为您不想通过更改产生副作用。
正如之前所指出的,最简单的方法确实是修改分词器的 token_match 函数。这是一个 re.match 标识不会被拆分的正则表达式。而不是导入特定的 URL 模式,我宁愿扩展任何 spaCy 的默认值。
from spacy.tokenizer import _get_regex_pattern
nlp = spacy.load('en')
# get default pattern for tokens that don't get split
re_token_match = _get_regex_pattern(nlp.Defaults.token_match)
# add your patterns (here: hashtags and in-word hyphens)
re_token_match = f"({re_token_match}|#\w+|\w+-\w+)"
# overwrite token_match function of the tokenizer
nlp.tokenizer.token_match = re.compile(re_token_match).match
text = "@Pete: choose low-carb #food #eatsmart ;-) "
doc = nlp(text)
Run Code Online (Sandbox Code Playgroud)
这产生:
['@Pete', ':', 'choose', 'low-carb', '#food', '#eatsmart', ';-)', '', '']
Run Code Online (Sandbox Code Playgroud)
这更多的是一种附加由@DhruvPathak和一个伟大的答案无耻副本从下面的链接GitHub的线程(和@csvance的甚至更好的答案)。spaCy 具有(自 V2.0 起)add_pipe方法。这意味着您可以在函数中定义 @DhruvPathak 很好的答案,并将步骤(方便地)添加到您的 nlp 处理管道中,如下所示。
引用从这里开始:
def hashtag_pipe(doc):
merged_hashtag = False
while True:
for token_index,token in enumerate(doc):
if token.text == '#':
if token.head is not None:
start_index = token.idx
end_index = start_index + len(token.head.text) + 1
if doc.merge(start_index, end_index) is not None:
merged_hashtag = True
break
if not merged_hashtag:
break
merged_hashtag = False
return doc
nlp = spacy.load('en')
nlp.add_pipe(hashtag_pipe)
doc = nlp("twitter #hashtag")
assert len(doc) == 2
assert doc[0].text == 'twitter'
assert doc[1].text == '#hashtag'
Run Code Online (Sandbox Code Playgroud)
引文到此结束;查看如何为完整线程的词性标注器 #503 添加主题标签。
PS 阅读代码时很清楚,但对于复制粘贴者,请不要禁用解析器:)
Run Code Online (Sandbox Code Playgroud)> >>> import re > >>> import spacy > >>> nlp = spacy.load('en') > >>> sentence = u'This is my twitter update #MyTopic' > >>> parsed = nlp(sentence) > >>> [token.text for token in parsed]
[u'This', u'is', u'my', u'twitter', u'update', u'#', u'MyTopic']
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)> >>> new_sentence = re.sub(r'#(\w+)',r'ZZZPLACEHOLDERZZZ\1',sentence) > >>> new_sentence u'This is my twitter update ZZZPLACEHOLDERZZZMyTopic' > >>> parsed = nlp(new_sentence) > >>> [token.text for token in parsed]
[u'This', u'is', u'my', u'twitter', u'update', u'ZZZPLACEHOLDERZZZMyTopic']
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)> >>> [x.replace(u'ZZZPLACEHOLDERZZZ','#') for x in [token.text for token in parsed]]
[u'This', u'is', u'my', u'twitter', u'update', u'#MyTopic']
Run Code Online (Sandbox Code Playgroud)
更新:您可以使用正则表达式来查找您希望保留为单个令牌的令牌范围,并使用此处提到的 span.merge 方法重新令牌化: https: //spacy.io/docs/api/span#merge
合并示例:
>>> import spacy
>>> import re
>>> nlp = spacy.load('en')
>>> my_str = u'Tweet hashtags #MyHashOne #MyHashTwo'
>>> parsed = nlp(my_str)
>>> [(x.text,x.pos_) for x in parsed]
[(u'Tweet', u'PROPN'), (u'hashtags', u'NOUN'), (u'#', u'NOUN'), (u'MyHashOne', u'NOUN'), (u'#', u'NOUN'), (u'MyHashTwo', u'PROPN')]
>>> indexes = [m.span() for m in re.finditer('#\w+',my_str,flags=re.IGNORECASE)]
>>> indexes
[(15, 25), (26, 36)]
>>> for start,end in indexes:
... parsed.merge(start_idx=start,end_idx=end)
...
#MyHashOne
#MyHashTwo
>>> [(x.text,x.pos_) for x in parsed]
[(u'Tweet', u'PROPN'), (u'hashtags', u'NOUN'), (u'#MyHashOne', u'NOUN'), (u'#MyHashTwo', u'PROPN')]
>>>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3703 次 |
| 最近记录: |