spaCy V3.0 基于规则匹配(2)----高效的短语匹配器和依存句法匹配器
1 短語匹配器(PhraseMatcher)
1.1 基本用法
對于需要匹配大型術語列表的情況,可以通過PhraseMatcher和創建Doc對象來代替詞符匹配模式(token patterns),可以獲得總體上更高的效率。Doc模式可以包含單個或多個詞符。
import spacy from spacy.matcher import PhraseMatchernlp = spacy.load("zh_core_web_sm") matcher = PhraseMatcher(nlp.vocab) terms = ['失速區','喘振區','油膜破壞','電機漏磁']# 注意:只有使用 nlp.make_doc 才能加速patterns = [nlp.make_doc(text) for text in terms] matcher.add("TerminologyList", patterns)doc = nlp("軸承絕緣擊穿,電機漏磁電流通過軸承造成油膜破壞。二次風系統擋板誤關,引起系統阻力增大,造成風壓與進入的風量不匹配,使風機進入喘振區。") matches = matcher(doc) for match_id, start, end in matches:span = doc[start:end]print(span.text)注意:patterns 是一個Doc列表。
創建patterns,每個短語都必須使用nlp對象進行處理。如果加載了預訓練模型,則在循環或列表中執行此操作很容易變得低效和費時。如果您只需要分詞和詞法屬性,那么可以運行nlp.make_doc,它只使用了分詞器(tokenizer)。當然還可以使用nlp.tokenizer.pipe方法,將文本作為流進行處理,以得到進一步的速度提升。
錯誤用法:
- patterns = [nlp(term) for term in LOTS_OF_TERMS]
正確用法:
- patterns = [nlp.make_doc(term) for term in LOTS_OF_TERMS]
- patterns = list(nlp.tokenizer.pipe(LOTS_OF_TERMS))
1.2 匹配其他Token屬性
默認情況下,PhraseMatcher將逐字匹配Token的文本,Token.text. 但通過在初始化時設置attr參數,可以更改匹配器(PhraseMatcher)在將短語模式(patterns)與文檔進行比較時使用的Token屬性。
注意:在前面的例子中,生成patterns列表用的是nlp.make_doc,它只使用了分詞器(tokenizer)。對于本節需要匹配其他Token屬性的情況,就要根據需要加入相應的組件。你可以直接使用nlp或通過 nlp.select_pipes()選擇性的禁用某些組件。
比如:根據形狀匹配數字Token(如IP地址)。使用Token的Shape屬性將不必擔心這些字符串如何分詞,并且能夠根據幾個示例找到Tokens及其組合。下面我們將匹配形狀ddd.d.d.d和ddd.ddd.d.d:
matcher = PhraseMatcher(nlp.vocab, attr="SHAPE") matcher.add("IP", [nlp("127.0.0.1"), nlp("127.127.0.0")])doc = nlp("通常路由器有像'192.168.1.1'或'192.168.2.1'這樣的IP地址。") for match_id, start, end in matcher(doc):print("Matched based on token shape:", doc[start:end])當然從理論上講,此方法對POS等屬性也同樣適用。例如,基于詞性標簽(tag)匹配的模式nlp(“我喜歡花”)將返回“我愛狗”的匹配。還可以匹配像IS_PUNCT這樣的布爾屬性,以匹配具有與模式相同的標點符號和非標點符號序列的短語。但是這么做很容易讓人迷惑,且與編寫一個或兩個Token模式相比也沒有太大的優勢。
2 依存句法匹配器
DependencyMatcher使用Semgrex操作符匹配依存句法分析中的模式。它需要一個包含依存句法解析器的模型,比如DependencParser。DependencMatcher模式沒有定義Matcher patterns中相鄰Token的列表,而是匹配依存關系分析中的Roken并指定它們之間的關系。
依存句法匹配器的patterns由字典列表組成,每個字典描述要匹配的Token及其與patterns中現有Token的關系。除了第一個字典(它僅使用RIGHT_ID和RIGHT_ATTRS定義anchor token)之外,每個pattern 都應該具有以下4個鍵:
| LEFT_ID | 關系符左邊的節點名稱,該節點此前要出現在patters字典列表 str |
| REL_OP | 表明左右兩節點關系的操作符 str |
| RIGHT_ID | 關系符右側節點名稱(該名稱不能重復) str |
| RIGHT_ATTRS | 要匹配的關系符右側節點的屬性,其格式與Token Matcher中的patters相同 Dict[str, Any] |
添加到patterns中的每個附加Token,都通過關系操作符REL_OP鏈接到現有名稱為LEFT_ID的Token。新Token被命名為RIGHT_ID并由具有RIGHT_ATTRS描述的屬性。
重要提示:由于用LEFT_ID和RIGHT_ID來作為識別Token的唯一名稱,patters字典列表中的順序就非常重要。所有作為LEFT_ID出現的節點,必須在前面的字典中作為RIGHT_ID被定義過!!!!
依存句法匹配器可用的操作符
| A < B | A是B的直接子節點 |
| A > B | A是B的直接頭節點 |
| A << B | A能夠通過多個子節點到頭節點關系跳轉路徑到達B |
| A >> B | A能夠通過多個頭節點到子節點關系跳轉路徑到達B |
| A . B | A是B的位置左鄰節點, 即:A.i == B.i - 1 (A、B在同一依存解析樹中,i是其Doc中的位置索引。 下同) |
| A .* B | A是B的位置前序節點, 即:A.i < B.i |
| A ; B | A是B的位置右鄰節點, 即:A.i == B.i + 1 |
| A ;* B | A是B的位置后序節點, 即:A.i > B.i |
| A $+ B | B是A的右鄰同級節點, 即:A.head == B.head and A.i == B.i - 1 |
| A $- B | B是A的左鄰同級節點, 即:A.head == B.head and A.i == B.i + 1 |
| A $++ B | B是A的位置后序同級節點, 即:A.head == B.head and A.i < B.i |
| A $-- B | B是A的位置前序同級節點, 即:A.head == B.head and A.i > B.i |
- 依存句法匹配器的patterns
如果要從以下句子中找出“造成”什么后果:
1 “軸承絕緣擊穿,電機漏磁電流通過軸承造成油膜破壞。”
2 “冷渣器內部冷卻水管泄漏造成灰渣板結。”
我們要找到以下關系:
- 造成的直接賓語(dobj)
- 直接賓語(dobj)的復合名詞修飾或形容詞修飾(也可以沒有修飾)
運行結果:
[(4851363122962674176, [5, 7, 6]), (4851363122962674176, [19, 21, 20])] anchor_word: 造成 w_object: 板結 object_modifier: 灰渣 anchor_word: 造成 w_object: 破壞 object_modifier: 油膜提高匹配速度的重要提示:
當token patterns能夠潛在匹配句子中的許多token,或者當關系運算符在依存關系解析中的路徑較長時(如<<、>>、*以及;*關系運算符),匹配速度可能會比較慢。
為了提高匹配速度,操作符盡可能具體。例如,盡量使用 > 而不是 >> ,使用包含語義標簽和其他Token屬性,而不是像 {} 匹配句子中任何Token。
總結
以上是生活随笔為你收集整理的spaCy V3.0 基于规则匹配(2)----高效的短语匹配器和依存句法匹配器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【51单片机】开关状态检测
- 下一篇: 不容错过的BT-474细胞传代实验心得分