spaCy處理文字的過程是模組化的,當呼叫nlp處理文字時,spaCy首先將文字標記化以生成Doc物件,然後,依次在幾個不同的元件中處理Doc,這也稱為處理管道。語言模型預設的處理管道依次是:tagger、parser、ner等,每個管道元件返回已處理的Doc,然後將其傳遞給下一個元件。
一,載入語言模型
spaCy使用的語言模型是預先訓練的統計模型,能夠預測語言特徵,對於英語,共有en_core_web_sm、en_core_web_md和en_core_web_lg三種語言模型,使用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)
參考文件: