这个文章是上班摸鱼的时候随便写的笔记,不成体系,仅供参考!
- SpaCy介绍
- SpaCy工具库中的类别(Class)们
- 分词(Tokenization)
- 向SpaCy分词工具中添加新词
- 自定义分词工具
- 意图识别
SpaCy是著名的NLP开源工具包,自带超过60种语言的预训练语言模型和词向量。SpaCy侧重NLP工业界应用,针对部署和计算速度进行了优化。
https://explosion.ai/demos/displacy 网站提供SpaCy的可视化,也可以用Python画Dependency Tree。
SpaCy文本处理流程示意图:
SpaCy的结构图:
Python调用SpaCy的常见代码:
import spacy
nlp = spacy.load("en_core_web_md") # load the pipeline
doc = nlp("I went there")
# print the tokenization result
print ([token.text for token in doc])
上面的doc变量包含句子的标记、分词和实体等。
SpaCy工具库中的类别(Class)们- Doc 类别代表文本,它包括该文本的分词、实体等信息。
- Token 类别代表字。
- Span 类别代表文本中连续的一部分。
分词是第一步,也是重要的一步,因为后续的所有操作(实体命名等)都是基于分词的结果。
分词是把一个句子分成最小的语法单元。
SpaCy的分词不基于统计模型而是基于特定语言的语法规则。
可以向SpaCy分词规则中添加专业词汇
doc = nlp("lemme that")
print([w.text for w in doc]) # ['lemme', 'that']
# now add special cases
special_case = [{ORTH: "lem"}, {ORTH: "me"}]
nlp.tokenizer.add_special_case("lemme", special_case)
print([w.text for w in nlp("lemme that")]) # ['lem', 'me', 'that']
自定义分词工具
def custom_tokenizer(text):
tokens = []
# your existing code to fill the list with tokens
......
# with this:
return Doc(nlp.vocab, tokens)
nlp.tokenizer = custom_tokenizer # 替换分词工具
上述的tokenizer是接收纯文本输出Doc对象的函数。
意图识别动词是句子中重要的部分,及物动词会有影响的对象。对象又分为直接对象和简介对象,如下例:
He loved his cat. He loved who? - his cat (直接对象) He gave me his book. He gave his book to whom? - me (间接对象)
这样的动词-对象组合可以帮助我们识别“意图”。Intent Recognition经常被用在对话机器人中。
SpaCy在进行依存语法解析后,我们可以识别出其中的动宾关系。【图】比如dobj就是直接宾语。
Find a flight from Washington to SF.
更复杂一些的句子拥有多个对象:
Show all flights and fares from Denver to SF.
这个时候flights 和 fares是conj关系:
import spacy
nlp = spacy.load("en_core_web_md")
doc = nlp("show all flights and fares from denver to san francisco")
for token in doc:
if token.dep_ == "dobj":
dobj = token.text
conj = [t.text for t in token.conjuncts]
verb = donj.head
print(verb, dobj, conj)
show flights ['fares']
再复杂一下,动词和对象可能没有直接的语法关联,比如
I want to make a reservation for a flight.
doc = nlp("i want to make a reservation for a flight")
dObj =None
tVerb = None
# Extract the direct object and its transitive verb
for token in doc:
If token.dep_ == "dobj":
dObj = token
tVerb = token.head
# Extract the helper verb
intentVerb = None
verbList = ["want", "like", "need", "order"]
if tVerb.text in verbList:
intentVerb = tVerb
else:
if tVerb.head.dep_ == "ROOT":
helperVerb = tVerb.head
# Extract the object of the intent
intentObj = None
objList = ["flight", "meal", "booking"]
if dObj.text in objList:
intentObj = dObj
else:
for child in dObj.children:
if child.dep_ == "prep":
intentObj = list(child.children)[0]
break
elif child.dep_ == "compound":
intentObj = child
break
print(intentVerb.text + intentObj.text.capitalize()) # wantFlight
参考资料:
Duygu Altinok. (2021). Mastering spaCy. Packt Publishing.
https://stackoverflow.com/a/53596275/11180198



