美文网首页
spaCy文档-02:新手入门

spaCy文档-02:新手入门

作者: 3b899188980c | 来源:发表于2018-01-17 20:36 被阅读1072次

    语言特征

    注意以下代码示例都需要导入spacy

    import spacy
    nlp = spacy.load('en')
    #导入模型库
    

    使用 spaCy提取语言特征,比如说词性标签,语义依赖标签,命名实体,定制tokenizer并与基于规则的matcher一起工作。

    处理原始文本是很困难的:大多数单词都是很少见的,而对于有些看起来完全不同的单词来说,它们的意思可能是一样的。相同的词在不同的顺序可以意味着完全不同的东西。在很多语言中将文本分割成类单词单元都是困难的。虽然从原始字符开始解决一些问题是可能的,但是最好使用语言知识来添加有用的信息。这正是spaCy的设计目的:您输入原始文本,然后返回一个Doc对象,它带有各种注释。

    词性标注(PoS)

    在标记化之后,spaCy可以解析和标记给定的Doc。这就是统计模型出现的地方,它使得spaCy能够预测在这个上下文中最有可能应用的标签或标签。一个模型由二进制数据组成,它通过显示一个系统足够的例子来进行预测,从而在整个语言中进行预测——例如,在英语中“the”后面的单词最有可能是名词。

    语言标注可以作为Token的属性,与许多NLP库一样,spaCy将所有字符串编码为散列值,以减少内存使用量并提高效率。为了获得属性的可读字符串表示,我们需要在其名称中添加一个_:

    doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion')
    
    for token in doc:
        print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
              token.shape_, token.is_alpha, token.is_stop)
    
    TEXT LEMMA POS TAG DEP SHAPE ALPHA STOP
    Apple apple PROPN NNP nsubj Xxxxx True False
    is be VERB VBZ aux xx True True
    at at ADP IN prep xx True True

    使用spaCy's的内建可视化工具,还可以看到示例中的依存句法结构(这里不添加附图啦)

    依存句法分析(Dependency parsing)

    spaCy具有快速和准确的语法依赖解析器,并且有一个用于构建句法树的强大API。解析器有检测句子边界的强大能力,并允许您遍历基本名词短语或“块”。您可以检查Doc对象是否已经被is_parsed属性解析了,它(is_parsed)返回一个布尔值。如果此属性为False,则默认语句迭代器将引发异常。

    名词块(Noun chunks)

    名词块是“基本名词短语”——用名词作头部的扁平短语。你可以把名词块当作名词,再加上描述名词的词,例如“奢侈的绿草”或“世界上最大的科技基金”。要获取文档中的名词块,只需遍历Doc.noun_chunks。

    nlp = spacy.load('en')
    doc = nlp(u'Autonomous cars shift insurance liability toward manufacturers')
    for chunk in doc.noun_chunks:
        print(chunk.text, chunk.root.text, chunk.root.dep_,
              chunk.root.head.text)
    

    tips

    text:原始的名词块文本
    root text:名词的块的核心部分(见example)


    QQ20180117-230252.png

    命名实体识别(NER)

    一个被命名的实体是一个“现实世界的对象”,它被赋予一个名字——例如,一个人,一个国家,一个产品或者一个书名。spaCy可以通过询问模型来识别文档中的各种类型的命名实体。因为模型是统计的,并且非常依赖于他们所接受的示例,所以这并不总是完美的,并且可能需要稍后进行一些调整,这取决于您的用例。

    命名实体可以doc的ents中获取

    doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion')
    
    for ent in doc.ents:
        print(ent.text, ent.start_char, ent.end_char, ent.label_)
    
    1.png

    运用可视化工具可以看到如下效果:


    2.png

    规则匹配

    spaCy有一个规则匹配引擎,即Matcher,它通过token进行操作,类似于正则表达式。规则可以参考token注释(例如,token文本或标记,以及标记(例如IS_PUNCT)。规则matcher还允许您通过自定义回调来执行匹配操作——例如,合并实体并应用自定义标签。您还可以将模式与实体id关联起来,以允许一些基本的实体链接或消除歧义。为了匹配大型术语表,可以使用PhraseMatcher,它接受Doc对象作为匹配模式。

    添加模型(adding patterns)

    假设我们想找到由以下三个token组成的字段:
    1、以小写形式匹配‘hello’,例如:‘Hello’,‘HELLO’
    2、is_punct 标签为真的token,例如:任何标点
    3、以小写形式匹配‘world’,例如:‘World’,‘WORLD’

    [{'LOWER': 'hello'}, {'IS_PUNCT': True}, {'LOWER': 'world'}]
    

    首先,我们用vocab初始化Matcher。matcher必须始终与它将操作的文档共享同一个vocab。我们现在可以调用matcher.add()和一个ID和我们的定制模式。第二个参数允许您传递一个可选的回调函数,以调用成功的匹配。现在,我们将它设置为None。

    import spacy
    from spacy.matcher import Matcher
    
    nlp = spacy.load('en')
    matcher = Matcher(nlp.vocab)
    # add match ID "HelloWorld" with no callback and one pattern
    pattern = [{'LOWER': 'hello'}, {'IS_PUNCT': True}, {'LOWER': 'world'}]
    matcher.add('HelloWorld', None, pattern)
    #这里的“helloworld”可以理解为一种代号,和索引,可以取其他任何名字
    doc = nlp(u'Hello, world! Hello world!')
    matches = matcher(doc)
    

    matcher返回一个(match_id, start, end)元组列表——在本例中,[(HelloWorld', 0,2)],映射到我们原始文档的span doc[0:2]。我们还可以选择添加多个模式,例如在“hello”和“world”之间不加标点的匹配序列。

    matcher.add('HelloWorld', None,
                [{'LOWER': 'hello'}, {'IS_PUNCT': True}, {'LOWER': 'world'}],
                [{'LOWER': 'hello'}, {'LOWER': 'world'}])
    

    默认情况下,matcher只会返回匹配项,而不会执行其他操作,比如合并实体或分配标签。这一切都取决于您,可以为每个模式单独定义,通过传入一个回调函数作为add()的on_match参数。这是有用的,因为它允许您编写完全自定义和模式特定的逻辑。例如,您可能希望将一些模式合并到一个令牌中,同时为其他模式类型添加实体标签。您不应该为每个流程创建不同的匹配器。

    可获取的token属性

    attribute description
    ORTH token精确的文本
    LOWER, UPPER token文本的大小写形式
    IS_ALPHA, IS_ASCII, IS_DIGIT token文本由字母数字字符、ASCII字符、数字组成
    IS_LOWER, IS_UPPER, IS_TITLE token文本为大写,小写,标题格式
    IS_PUNCT, IS_SPACE, IS_STOP token文本是标点,空白,停用词
    LIKE_NUM, LIKE_URL, LIKE_EMAIL token文本类似于数字,网址,邮件地址
    POS, TAG, DEP, LEMMA, SHAPE token文本的词性之类的……

    可获取的pattern就是大写的token属性,和匹配相关的大部分属性如下:

    attribute description
    ORTH token精确的文本
    LOWER, UPPER token文本的大小写形式
    IS_ALPHA, IS_ASCII, IS_DIGIT token文本由字母数字字符、ASCII字符、数字组成
    IS_LOWER, IS_UPPER, IS_TITLE token文本为大写,小写,标题格式
    IS_PUNCT, IS_SPACE, IS_STOP token文本是标点,空白,停用词
    LIKE_NUM, LIKE_URL, LIKE_EMAIL token文本类似于数字,网址,邮件地址
    POS, TAG, DEP, LEMMA, SHAPE token文本的词性之类的……

    使用通配符token样式

    虽然token属性提供了许多选项来编写高度特定的模式,但您也可以使用空的字典({})作为表示任何标记的通配符。如果你知道你想要匹配的内容的上下文,但是对于特定的token和它的字符非常少,那么通配符就显得很有用了。例如,假设您试图从数据中提取用户的用户名。您只知道它们被列为“用户名:{用户名}”。名称本身可能包含任何字符,但没有空格——因此您将知道它将作为一个token处理。

    [{'ORTH': 'User'}, {'ORTH': 'name'}, {'ORTH': ':'}, {}]
    

    使用类似正则表达式一样的通配符号

    待补充

    添加短语样式

    如果您需要匹配大型术语表,您还可以使用PhraseMatcher并创建Doc对象,而不是token模式,这在总体上更有效。Doc模式可以包含单个或多个token。

    import spacy
    from spacy.matcher import PhraseMatcher
    
    nlp = spacy.load('en')
    matcher = PhraseMatcher(nlp.vocab)
    terminology_list = ['Barack Obama', 'Angela Merkel', 'Washington, D.C.']
    patterns = [nlp(text) for text in terminology_list]
    matcher.add('TerminologyList', None, *patterns)
    
    doc = nlp(u"German Chancellor Angela Merkel and US President Barack Obama "
              u"converse in the Oval Office inside the White House in Washington, D.C.")
    matches = matcher(doc)
    

    由于spaCy用于处理模式和匹配的文本,因此您不必担心特定的标记化——例如,您可以简单地通过nlp(u“Washington, D.C.”),而不必编写一个复杂的token模式来覆盖术语的确切标记。

    添加on-match规则

    为了实现一个更现实的例子,假设您正在处理大量的博客文章,您想要匹配所有提到的"Google I/O"(spaCy将其标记为['Google', 'I', '/', 'O'])。为了安全起见,您只匹配大写版本,以防有人将其写成"Google i/o"。您还添加了一个附加的{IS_DIGIT: True}标记的第二个模式——这将确保您也匹配"Google I/O 2017"。如果您的模式匹配,spaCy应该执行您的自定义回调函数add_event_ent。

    import spacy
    from spacy.matcher import Matcher
    
    nlp = spacy.load('en')
    matcher = Matcher(nlp.vocab)
    
    # Get the ID of the 'EVENT' entity type. This is required to set an entity.
    EVENT = nlp.vocab.strings['EVENT']
    
    def add_event_ent(matcher, doc, i, matches):
        # Get the current match and create tuple of entity label, start and end.
        # Append entity to the doc's entity. (Don't overwrite doc.ents!)
        match_id, start, end = matches[i]
        doc.ents += ((EVENT, start, end),)
    
    matcher.add('GoogleIO', add_event_ent,
                [{'ORTH': 'Google'}, {'UPPER': 'I'}, {'ORTH': '/'}, {'UPPER': 'O'}],
                [{'ORTH': 'Google'}, {'UPPER': 'I'}, {'ORTH': '/'}, {'UPPER': 'O'}, {'IS_DIGIT': True}])
    

    除了提到“谷歌I/O”之外,你的数据还包含一些恼人的预处理程序,比如剩下的HTML行中断(例如: <br>或<br />)。当您在它的时候,您希望将它们合并到一个标记中并标记它们,以确保您稍后可以轻松地忽略它们。因此,添加第二个模式并传入函数merge_and_flag:

    BAD_HTML_FLAG = nlp.vocab.add_flag(lambda text: False)
    
    def merge_and_flag(matcher, doc, i, matches):
        match_id, start, end = matches[i]
        span = doc[start : end]
        span.merge(is_stop=True) # merge (and mark it as a stop word, just in case)
        span.set_flag(BAD_HTML_FLAG, True) # set BAD_HTML_FLAG
    
    matcher.add('BAD_HTML', merge_and_flag,
                [{'ORTH': '<'}, {'LOWER': 'br'}, {'ORTH': '>'}],
                [{'ORTH': '<'}, {'LOWER': 'br/'}, {'ORTH': '>'}])
    

    我们现在可以在文档上调用matcher。模式将按照它们在文本中出现的顺序进行匹配。然后,matcher将迭代匹配,查找匹配的匹配ID的回调,并调用它。

    doc = nlp(LOTS_OF_TEXT)
    matcher(doc)
    

    当调用回调时,它会传递四个参数:matcher本身、文档、当前匹配的位置和匹配的总列表。这让您可以编写回调函数来考虑所有匹配的短语,这样您就可以以您喜欢的方式解决重叠和其他冲突。

    正则表达式

    待补充

    例子-01

    假设你正在分析用户评论,你想知道人们对Facebook的看法。你想从“脸书”或“脸书”这样的形容词入手。这显然是一个非常简单的解决方案,但是它会很快,而且很好地理解了数据中的内容。你的模式可能是这样的:

    [{'LOWER': 'facebook'}, {'LEMMA': 'be'}, {'POS': 'ADV', 'OP': '*'}, {'POS': 'ADJ'}]
    

    这就转化为一个标记,它的小写形式与“facebook”(如facebook、facebook或facebook)相匹配,然后是一个带有引理“be”(例如,是,或者是)的标记,后面跟着一个可选的副词,后面跟着一个形容词。使用这里的语言注释特别有用,因为你可以告诉spaCy匹配“Facebook的烦人”,而不是“Facebook烦人的广告”。可选的副词确保你不会漏掉形容词,比如“pretty awful”或“very nice”。
    为了快速了解结果,您可以收集包含匹配的所有句子,并使用displaCy可视化工具呈现它们。在回调函数中,您将访问每个匹配的开始和结束,以及父文档。这让您可以确定包含匹配的语句,doc[start: end]。发送,并计算在句子中匹配跨度的开始和结束。在“手动”模式中使用displaCy可以让您传入包含文本和实体的字典列表。

    相关文章

      网友评论

          本文标题:spaCy文档-02:新手入门

          本文链接:https://www.haomeiwen.com/subject/rutpoxtx.html