spaCy 第二篇:語言模型


spaCy處理文本的過程是模塊化的,當調用nlp處理文本時,spaCy首先將文本標記化以生成Doc對象,然后,依次在幾個不同的組件中處理Doc,這也稱為處理管道。語言模型默認的處理管道依次是:tagger、parser、ner等,每個管道組件返回已處理的Doc,然后將其傳遞給下一個組件。

一,加載語言模型

spaCy使用的語言模型是預先訓練的統計模型,能夠預測語言特征,對於英語,共有en_core_web_sm、en_core_web_md和en_core_web_lg三種語言模型,還有一種語言模型:en,需要以管理員權限運行以下命令來安裝en模型:

python -m spacy download en

使用spacy.load()函數來加載語言模型

spacy.load(name,disable)

其中,name參數是語言模型的名詞,disable參數是禁用的處理管道列表,例如,創建en_core_web_sm語言模型,並禁用ner:

nlp = spacy.load("en_core_web_sm", disable=['ner'])

語言模型中不僅預先定義了Language管道,還定義了處理文本數據的處理管道(pipeline),其中分詞器是一個特殊的管道,它是由Language管道確定的,不屬於pipeline。

{
  "lang": "en",
  "name": "core_web_sm",
  "description": "Example model for spaCy",
  "pipeline": ["tagger", "parser", "ner"]
}

在加載語言模型nlp之后,可以查看該語言模型預先定義的處理管道,也就是說,處理管道依賴於統計模型。

1,查看nlp對象的管道

>>> nlp.pipe_names
['tagger', 'parser', 'ner']

2,移除nlp的管道

nlp.remove_pipe(name)

3,向nlp的處理管道中增加管道

nlp.add_pipe(component, name=None, before=None, after=None, first=None, last=None)

二,語言管道和分詞器管道

Language管道是一個特殊的管道,當調用spacy.load()加載語言模型時,spaCy自動創建Lanuage管道,用於存儲共享的詞匯表、分詞規則(Tokenization Rule)和文本注釋。

分詞器管道是跟Language管道息息相關的一個管道,當創建Language管道之后,spaCy根據Language管道提供的詞匯表來創建分詞器。分詞器用於把文本分為單詞,標點符號,空格等標記,除了使用默認的分詞器之外,spaCy允許用戶根據需要對分詞器進行調整:

from spacy.tokenizer import Tokenizer
tokenizer = Tokenizer(vocab=nlp.vocab,rules,prefix_search, suffix_search, infix_search, token_match)

參數注釋:

  • vocab:詞匯表
  • rules:dict類型,分詞器的特殊規則,把匹配到特殊規則的單詞作為一個token,主要是用於設置token的注釋(annotation);
  • prefix_search、suffix_search:類型是re.compile(string).search
  • infix_finditer:類型是re.compile(string).finditer,把匹配到這前綴、后綴或中綴的字符串作為一個token;
  • token_match:返回boolean值的函數類型,把匹配到的字符串識別為一個token;

在文本處理的過程中,spaCy首先對文本分詞,原始文本在空格處分割,類似於text.split(' '),然后分詞器(Tokenizer)從左向右依次處理token,在處理token時,spaCy做了兩個check:

  • 是否匹配特殊規則(execption rule)
  • 是否前綴、中綴或后綴可以分割

一個可選的布爾函數token_match,它匹配的字符串不會被拆分,覆蓋以前的規則,對URL或數字之類的東西很有用。

三,擴展語言

每一種語言都是不同的,通常充滿異常和特殊情況,尤其是最常見的單詞。 其中一些例外是跨語言共享的,而其他例外則完全具體,通常非常具體,需要進行硬編碼。 spaCy.lang模塊包含所有特定於語言的數據,以簡單的Python文件組織,這使得數據易於更新和擴展。

 

每一個單獨的組件可以在語言模塊種導入遍歷,並添加到語言的Defaults對象種,某些組件(如標點符號規則)通常不需要自定義,可以從全局規則中導入。 其他組件,比如tokenizer和norm例外,則非常具體,會對spaCy在特定語言上的表現和訓練語言模型產生重大影響。

例如,導入English模塊,查看該模塊的幫助:

from spacy.lang.en import English
help(English)

通過這些模塊來擴展語言,處理特殊的語法,通常在分詞器(Tokenizer)中添加特殊規則和Token_Match函數來實現。

1,向分詞器中添加特殊的規則

import spacy
from spacy.symbols import ORTH, LEMMA, POS, TAG

nlp = spacy.load("en_core_web_sm")

# add special case rule
special_case = [{ORTH: u"gim", LEMMA: u"give", POS: u"VERB"}, {ORTH: u"me"}]
nlp.tokenizer.add_special_case(u"gimme", special_case)

2,設置特殊的規則來匹配token

創建一個自定義的分詞器,使分詞把https作為一個token:

import re
import spacy
from spacy.lang.en import English

def my_en_tokenizer(nlp):
    prefix_re = spacy.util.compile_prefix_regex(English.Defaults.prefixes)
    suffix_re = spacy.util.compile_suffix_regex(English.Defaults.suffixes)
    infix_re = spacy.util.compile_infix_regex(English.Defaults.infixes)
    pattern_re = re.compile(r'^https?://')
    return spacy.tokenizer.Tokenizer(nlp.vocab,
                                     English.Defaults.tokenizer_exceptions,
                                     prefix_re.search,
                                     suffix_re.search,
                                     infix_re.finditer,
                                     token_match=pattern_re.match)

在處理文本時調用該分詞器,把匹配到正則的文本作為一個token來處理:

nlp = spacy.load("en_core_web_sm")
nlp.tokenizer = my_en_tokenizer(nlp)
doc = nlp(u"Spacy is breaking when combining custom tokenizer's token_match, access https://github.com/explosion/spaCy to get details")
print([t.text for t in doc])

3,自定義分詞器

預先定義的分詞器是按照空格來分詞的,用於可以自定義分詞器

### customer tokenizer

class myTokenizer(object):
    def __init__(self, vocab):
        self.vocab = vocab

    def __call__(self, text):
        words=[]
        re_search=my_token_match(text)
        if re_search:
            for start,end in re_search.regs:
                if start >=0 and end>=0:
                    words.append(text[start:end])
        text=my_token_replace(text)
        split_words=my_token_split(text)
        print(split_words)

        words.extend([w for w in split_words if w!=''])

        # All tokens 'own' a subsequent space character in this tokenizer
        spaces = [True] * len(words)
        return Doc(self.vocab, words=words, spaces=spaces)

### parse the synonyms
RE_SYNONYMS=parse_synonyms()

def my_token_match(text):
    global  RE_SYNONYMS

    return re.compile(RE_SYNONYMS).search(text)

def my_token_replace(text):
    global  RE_SYNONYMS

    return re.compile(RE_SYNONYMS).sub('',text)


def my_token_split(text):

    #return re.compile('\s+|\W+|_+').split(text)
    return re.compile('\s+|\\+|_+').split(text)

引用自定義的分詞器

nlp=spacy.load("en_core_web_sm")
nlp.tokenizer = myTokenizer(nlp.vocab)

 

 

 

參考文檔:

Linguistic Features-Tokenization

Pipeline

Processing Pipelines

Adding Languages


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM