眾所周知,史丹福大學自然語言處理組出品了一系列NLP工具包,但是大多數都是用Java寫得,對於Python用戶不是很友好。幾年前我曾基於斯坦福Java工具包和NLTK寫過一個簡單的中文分詞接口:Python自然語言處理實踐: 在NLTK中使用斯坦福中文分詞器,不過用起來也不是很方便。深度學習自然語言處理時代,史丹福大學自然語言處理組開發了一個純Python版本的深度學習NLP工具包:Stanza - A Python NLP Library for Many Human Languages,前段時間,Stanza v1.0.0 版本正式發布,算是一個裡程碑:
Stanza 是一個純Python實現的自然語言處理工具包,這個區別於史丹福大學自然語言處理組之前一直維護的Java實現 CoreNLP 等自然語言處理工具包,對於Python用戶來說,就更方便調用了,並且Stanza還提供了一個Python接口可用於CoreNLP的調用 ,對於一些沒有在Stanza中實現的NLP功能,可以通過這個接口調用 CoreNLP 作為補充。Stanza的深度學習自然語言處理模塊基於PyTorch實現,用戶可以基於自己標註的數據構建更準確的神經網絡模型用於訓練、評估和使用,當然,如果有GPU機器加持,速度可以更快。Stanza目前支持66種語言的文本分析,包括自動斷句、Tokenize(或者分詞)、詞性標註和形態素分析、依存句法分析以及命名實體識別。
To summarize, Stanza features:
Native Python implementation requiring minimal efforts to set up;
Full neural network pipeline for robust text analytics, including tokenization, multi-word token (MWT) expansion, lemmatization, part-of-speech (POS) and morphological features tagging, dependency parsing, and named entity recognition;
Pretrained neural models supporting 66 (human) languages;
A stable, officially maintained Python interface to CoreNLP.
試用了一下Stanza,還是很方便的,官方文檔很清晰,可以直接參考。簡單記錄一下中英文模塊的安裝和使用,以下是在Ubuntu16.04, Python 3.6.8 環境下,請注意,Stanza需要Python3.6及以上的版本,如果低於這個版本,用 pip install stanza 安裝的stanza非史丹福大學NLP組的Stanza。
安裝Stanza的方法有多種,這裡是virtualenv虛擬環境下通過 pip install stanza 安裝stanza及其相關依賴的,具體可以參考Stanza的安裝文檔:https://stanfordnlp.github.io/stanza/installation_usage.html
安裝完成後,可以嘗試使用,不過使用某種語言的NLP工具包時,還需要先下載相關的打包模型,這個在第一次使用時會有提示和操作,以後就無需下載了,我們先從斯坦福官方的例子走起,以英文為例:
In [1]: import stanza
# 這裡因為已經下載過英文模型打包文件,所以可以直接使用,如果沒有下載過,初次使用會有一個下載過程
In [2]: stanza.download('en')
Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.json: 116kB [00:00, 154kB/s]
2020-04-11 23:13:14 INFO: Downloading default packages for language: en (English)...
2020-04-11 23:13:15 INFO: File exists: /home/textminer/stanza_resources/en/default.zip.
2020-04-11 23:13:19 INFO: Finished downloading models and saved to /home/textminer/stanza_resources.
# Pipeline是Stanza裡一個重要的概念
In [3]: en_nlp = stanza.Pipeline('en')
2020-04-11 23:14:27 INFO: Loading these models for language: en (English):
=========================
| Processor | Package |
| tokenize | ewt |
| pos | ewt |
| lemma | ewt |
| depparse | ewt |
| ner | ontonotes |
=========================
2020-04-11 23:14:28 INFO: Use device: gpu
2020-04-11 23:14:28 INFO: Loading: tokenize
2020-04-11 23:14:30 INFO: Loading: pos
2020-04-11 23:14:30 INFO: Loading: lemma
2020-04-11 23:14:30 INFO: Loading: depparse
2020-04-11 23:14:31 INFO: Loading: ner
2020-04-11 23:14:32 INFO: Done loading processors!
In [5]: doc = en_nlp("Barack Obama was born in Hawaii.")
In [6]: print(doc)
[
[
{
"id": "1",
"text": "Barack",
"lemma": "Barack",
"upos": "PROPN",
"xpos": "NNP",
"feats": "Number=Sing",
"head": 4,
"deprel": "nsubj:pass",
"misc": "start_char=0|end_char=6"
},
{
"id": "2",
"text": "Obama",
"lemma": "Obama",
"upos": "PROPN",
"xpos": "NNP",
"feats": "Number=Sing",
"head": 1,
"deprel": "flat",
"misc": "start_char=7|end_char=12"
},
{
"id": "3",
"text": "was",
"lemma": "be",
"upos": "AUX",
"xpos": "VBD",
"feats": "Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin",
"head": 4,
"deprel": "aux:pass",
"misc": "start_char=13|end_char=16"
},
{
"id": "4",
"text": "born",
"lemma": "bear",
"upos": "VERB",
"xpos": "VBN",
"feats": "Tense=Past|VerbForm=Part|Voice=Pass",
"head": 0,
"deprel": "root",
"misc": "start_char=17|end_char=21"
},
{
"id": "5",
"text": "in",
"lemma": "in",
"upos": "ADP",
"xpos": "IN",
"head": 6,
"deprel": "case",
"misc": "start_char=22|end_char=24"
},
{
"id": "6",
"text": "Hawaii",
"lemma": "Hawaii",
"upos": "PROPN",
"xpos": "NNP",
"feats": "Number=Sing",
"head": 4,
"deprel": "obl",
"misc": "start_char=25|end_char=31"
},
{
"id": "7",
"text": ".",
"lemma": ".",
"upos": "PUNCT",
"xpos": ".",
"head": 4,
"deprel": "punct",
"misc": "start_char=31|end_char=32"
}
]
]
In [7]: print(doc.entities)
[{
"text": "Barack Obama",
"type": "PERSON",
"start_char": 0,
"end_char": 12
}, {
"text": "Hawaii",
"type": "GPE",
"start_char": 25,
"end_char": 31
}]
Pipeline是Stanza裡的一個重要概念:
可以通過pipeline預加載不同語言的模型,也可以通過pipeline選擇不同的處理模塊,還可以選擇是否使用GPU,這裡我們再試試中文模型:
In [9]: import stanza
# 測試一下中文模型(因為我這邊中文模型已經下載過了,所以跳過download環節)
In [10]: zh_nlp = stanza.Pipeline('zh')
2020-04-12 11:32:47 INFO: "zh" is an alias for "zh-hans"
2020-04-12 11:32:47 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=========================
| Processor | Package |
| tokenize | gsdsimp |
| pos | gsdsimp |
| lemma | gsdsimp |
| depparse | gsdsimp |
| ner | ontonotes |
=========================
2020-04-12 11:32:48 INFO: Use device: gpu
2020-04-12 11:32:48 INFO: Loading: tokenize
2020-04-12 11:32:49 INFO: Loading: pos
2020-04-12 11:32:51 INFO: Loading: lemma
2020-04-12 11:32:51 INFO: Loading: depparse
2020-04-12 11:32:53 INFO: Loading: ner
2020-04-12 11:32:54 INFO: Done loading processors!
In [11]: text = """英國首相詹森6日晚因病情惡化,被轉入重症監護室治療。英國首相府發言人說,目前約
...: 翰遜意識清晰,將他轉移到重症監護室只是預防性措施。發言人說,詹森被轉移到重症監護室前已
...: 安排英國外交大臣拉布代表他處理有關事務。"""
In [12]: doc = zh_nlp(text)
In [13]: for sent in doc.sentences:
...: print("Sentence:" + sent.text) # 斷句
...: print("Tokenize:" + ' '.join(token.text for token in sent.tokens)) # 中文分詞
...: print("UPOS: " + ' '.join(f'{word.text}/{word.upos}' for word in sent.words)) # 詞性標註(UPOS)
...: print("XPOS: " + ' '.join(f'{word.text}/{word.xpos}' for word in sent.words)) # 詞性標註(XPOS)
...: print("NER: " + ' '.join(f'{ent.text}/{ent.type}' for ent in sent.ents)) # 命名實體識別
...:
Sentence:英國首相詹森6日晚因病情惡化,被轉入重症監護室治療。
Tokenize:英國 首相 詹森 6 日 晚因 病情 惡化 , 被 轉入 重症 監護 室 治療 。
UPOS: 英國/PROPN 首相/NOUN 詹森/PROPN 6/NUM 日/NOUN 晚因/NOUN 病情/NOUN 惡化/VERB ,/PUNCT 被/VERB 轉入/VERB 重症/NOUN 監護/VERB 室/PART 治療/NOUN 。/PUNCT
XPOS: 英國/NNP 首相/NN 詹森/NNP 6/CD 日/NNB 晚因/NN 病情/NN 惡化/VV ,/, 被/BB 轉入/VV 重症/NN 監護/VV 室/SFN 治療/NN 。/.
NER: 英國/GPE 詹森/PERSON 6日/DATE
Sentence:英國首相府發言人說,目前詹森意識清晰,將他轉移到重症監護室只是預防性措施。
Tokenize:英國 首相 府 發言 人 說 , 目前 詹森 意識 清晰 , 將 他 轉移 到 重症 監護 室 只 是 預防 性 措施 。
UPOS: 英國/PROPN 首相/NOUN 府/PART 發言/VERB 人/PART 說/VERB ,/PUNCT 目前/NOUN 詹森/PROPN 意識/NOUN 清晰/ADJ ,/PUNCT 將/ADP 他/PRON 轉移/VERB 到/VERB 重症/NOUN 監護/VERB 室/PART 只/ADV 是/AUX 預防/VERB 性/PART 措施/NOUN 。/PUNCT
XPOS: 英國/NNP 首相/NN 府/SFN 發言/VV 人/SFN 說/VV ,/, 目前/NN 詹森/NNP 意識/NN 清晰/JJ ,/, 將/BB 他/PRP 轉移/VV 到/VV 重症/NN 監護/VV 室/SFN 只/RB 是/VC 預防/VV 性/SFN 措施/NN 。/.
NER: 英國/GPE 詹森/PERSON
Sentence:發言人說,詹森被轉移到重症監護室前已安排英國外交大臣拉布代表他處理有關事務。
Tokenize:發言 人 說 , 詹森 被 轉移 到 重症 監護 室 前 已 安排 英國 外交 大臣 拉布 代表 他 處理 有關 事務 。
UPOS: 發言/VERB 人/PART 說/VERB ,/PUNCT 詹森/PROPN 被/VERB 轉移/VERB 到/VERB 重症/NOUN 監護/VERB 室/PART 前/ADP 已/ADV 安排/VERB 英國/PROPN 外交/NOUN 大臣/NOUN 拉布/PROPN 代表/VERB 他/PRON 處理/VERB 有關/ADJ 事務/NOUN 。/PUNCT
XPOS: 發言/VV 人/SFN 說/VV ,/, 詹森/NNP 被/BB 轉移/VV 到/VV 重症/NN 監護/VV 室/SFN 前/IN 已/RB 安排/VV 英國/NNP 外交/NN 大臣/NN 拉布/NNP 代表/VV 他/PRP 處理/VV 有關/JJ 事務/NN 。/.
NER: 詹森/PERSON 英國/GPE 拉布/PERSON
如果用戶不需要使用命名實體識別、依存句法等功能,可以在模型下載或者預加載階段或者構建Pipeline時選擇自己需要的功能模塊處理器,例如可以只選擇中文分詞和詞性標註,或者單一的中文分詞功能,這裡以「我愛自然語言處理」為例:
# 可以在使用時只選擇自己需要的功能,這樣下載的模型包更小,節約時間,這裡因為之前已經下載過全量的中文模型,所以不再有下載過程,只是用於演示
In [14]: stanza.download('zh', processors='tokenize,pos')
Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.Downloading https://raw.githubusercontent.com/stanfordnlp/stanza-resources/master/resources_1.0.0.json: 116kB [00:00, 554kB/s]
2020-04-15 07:27:38 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:27:38 INFO: Downloading these customized packages for language: zh-hans (Simplified_Chinese)...
=======================
| Processor | Package |
---
| tokenize | gsdsimp |
| pos | gsdsimp |
| pretrain | gsdsimp |
=======================
2020-04-15 07:27:38 INFO: File exists: /home/textminer/stanza_resources/zh-hans/tokenize/gsdsimp.pt.
2020-04-15 07:27:38 INFO: File exists: /home/textminer/stanza_resources/zh-hans/pos/gsdsimp.pt.
2020-04-15 07:27:39 INFO: File exists: /home/textminer/stanza_resources/zh-hans/pretrain/gsdsimp.pt.
2020-04-15 07:27:39 INFO: Finished downloading models and saved to /home/textminer/stanza_resources.
# 構建Pipeline時選擇中文分詞和詞性標註,對其他語言同理
In [15]: zh_nlp = stanza.Pipeline('zh', processors='tokenize,pos')
2020-04-15 07:28:12 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:28:12 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=======================
| Processor | Package |
---
| tokenize | gsdsimp |
| pos | gsdsimp |
=======================
2020-04-15 07:28:13 INFO: Use device: gpu
2020-04-15 07:28:13 INFO: Loading: tokenize
2020-04-15 07:28:15 INFO: Loading: pos
2020-04-15 07:28:17 INFO: Done loading processors!
In [16]: doc = zh_nlp("我愛自然語言處理")
In [17]: print(doc)
[
[
{
"id": "1",
"text": "我",
"upos": "PRON",
"xpos": "PRP",
"feats": "Person=1",
"misc": "start_char=0|end_char=1"
},
{
"id": "2",
"text": "愛",
"upos": "VERB",
"xpos": "VV",
"misc": "start_char=1|end_char=2"
},
{
"id": "3",
"text": "自然",
"upos": "NOUN",
"xpos": "NN",
"misc": "start_char=2|end_char=4"
},
{
"id": "4",
"text": "語言",
"upos": "NOUN",
"xpos": "NN",
"misc": "start_char=4|end_char=6"
},
{
"id": "5",
"text": "處理",
"upos": "VERB",
"xpos": "VV",
"misc": "start_char=6|end_char=8"
}
]
]
# 這裡單獨使用Stanza的中文分詞器
In [18]: zh_nlp = stanza.Pipeline('zh', processors='tokenize')
2020-04-15 07:31:27 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:31:27 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=======================
| Processor | Package |
---
| tokenize | gsdsimp |
=======================
2020-04-15 07:31:27 INFO: Use device: gpu
2020-04-15 07:31:27 INFO: Loading: tokenize
2020-04-15 07:31:27 INFO: Done loading processors!
In [19]: doc = zh_nlp("我愛自然語言處理")
In [20]: print(doc)
[
[
{
"id": "1",
"text": "我",
"misc": "start_char=0|end_char=1"
},
{
"id": "2",
"text": "愛",
"misc": "start_char=1|end_char=2"
},
{
"id": "3",
"text": "自然",
"misc": "start_char=2|end_char=4"
},
{
"id": "4",
"text": "語言",
"misc": "start_char=4|end_char=6"
},
{
"id": "5",
"text": "處理",
"misc": "start_char=6|end_char=8"
}
]
]
在Pipeline構建時,除了選擇不同的功能模塊處理器外,對於有多個模型可以選擇使用的功能模塊,也可以指定需要使用哪個模型,另外也可以指定Log級別,這些可以參考官方文檔。還有一點,如果你覺得使用GPU沒有必要,還可以選擇使用CPU:
In [21]: zh_doc = stanza.Pipeline('zh', use_gpu=False)
2020-04-15 07:44:04 INFO: "zh" is an alias for "zh-hans"
2020-04-15 07:44:04 INFO: Loading these models for language: zh-hans (Simplified_Chinese):
=========================
| Processor | Package |
| tokenize | gsdsimp |
| pos | gsdsimp |
| lemma | gsdsimp |
| depparse | gsdsimp |
| ner | ontonotes |
=========================
2020-04-15 07:44:04 INFO: Use device: cpu
2020-04-15 07:44:04 INFO: Loading: tokenize
2020-04-15 07:44:04 INFO: Loading: pos
2020-04-15 07:44:06 INFO: Loading: lemma
2020-04-15 07:44:06 INFO: Loading: depparse
2020-04-15 07:44:08 INFO: Loading: ner
2020-04-15 07:44:09 INFO: Done loading processors!
我將Stanza的中英文模塊部署在了AINLP的後臺,使用的就是CPU,感興趣的同學可以關注AINLP公眾號,對話測試,Stanza+分析內容觸發,會自動判斷語言選擇不同的Pipeline:
推薦閱讀
AINLP年度閱讀收藏清單
噹噹的羊毛,快薅,這一次要拼手速!
數學之美中盛讚的 Michael Collins 教授,他的NLP課程要不要收藏?
自動作詩機&藏頭詩生成器:五言、七言、絕句、律詩全了
From Word Embeddings To Document Distances 閱讀筆記
模型壓縮實踐系列之——bert-of-theseus,一個非常親民的bert壓縮方法
這門史丹福大學自然語言處理經典入門課,我放到B站了
可解釋性論文閱讀筆記1-Tree Regularization
徵稿啟示 | 稿費+GPU算力+星球嘉賓一個都不少
關於AINLP
AINLP 是一個有趣有AI的自然語言處理社區,專注於 AI、NLP、機器學習、深度學習、推薦算法等相關技術的分享,主題包括文本摘要、智能問答、聊天機器人、機器翻譯、自動生成、知識圖譜、預訓練模型、推薦系統、計算廣告、招聘信息、求職經驗分享等,歡迎關注!加技術交流群請添加AINLPer(id:ainlper),備註工作/研究方向+加群目的。