# Stanza實作課程教學
{%preview https://stanfordnlp.github.io/stanza/tutorials.html %}
---
## 課程概述
**課程名稱**: Stanza - Python自然語言處理實作課程
**適用對象**: 對NLP有基礎了解的研究生和開發者
**先備知識**: Python基礎程式設計、基本NLP概念
----
## 課程目標
1. 理解Stanza的架構和核心概念
2. 熟練使用Stanza進行各種NLP任務
3. 實作完整的文本分析專案
4. 針對中文文本進行專業的語言分析
---
## 第一部分:Stanza簡介
### 1.1 什麼是Stanza?
- Stanford NLP Group開發的Python NLP工具包
- 支援70+種人類語言
- 完全神經網路架構的處理管道
- 支援從分詞、詞性標註到依存句法與實體識別等任務
---
### 1.2 Stanza的核心特色
- **多語言支援**: 統一的API處理多種語言
- **神經網路架構**: 基於PyTorch的深度學習模型
- **模組化設計**: 靈活組合不同的處理器
- **高準確度**: 在多個基準測試中表現優異
---
### 1.3 安裝與設置
```python
# 安裝Stanza
pip install stanza
# 下載語言模型
import stanza
stanza.download('zh-hant') # 繁體中文
stanza.download('zh-hans') # 簡體中文
stanza.download('en') # 英文
```
---
### 1.4 處理管道 (Pipeline) 概念
- 什麼是NLP處理管道?
- 自然語言處理 (NLP) 管道是一種系統化的文本處理方法,它將多個語言分析任務按照邏輯順序連接起來,前一個任務的輸出作為下一個任務的輸入,形成一個完整的處理流程。

---
- 核心概念:
1. 序列化與依賴性:管道以既定順序執行,如 tokenize → pos → lemma → depparse → ner,確保後續任務能利用前一步的結構訊息與標註結果。
2. 模組化處理器:每個子任務是可插拔的處理器,可按需選擇與組合,達成「只開啟需要的任務以換取效能」的配置策略。
4. 資料物件與標註:管道將原始文字轉為文件/句子/詞的資料物件,並在其上附加詞性、形態、依存關係與實體等標註,方便下游程式直接取用。
---
- Stanza管道的組成元件

---
- 主要處理器說明:
1. tokenize (分詞處理器)
- 功能: 將原始文本分割為句子和詞語
- 依賴: 無 (管道的起點)
- 輸出: sentences, tokens
- 重要性: 所有後續處理的基礎
2. pos (詞性標註)
- 功能: 為每個詞語標註詞性 (名詞、動詞、形容詞等)
- 依賴: tokenize, mwt
- 輸出: upos (通用詞性), xpos (語言特定詞性)
----
3. lemma (詞形還原)
- 功能: 找出詞語的原始形式或詞根
- 依賴: tokenize, mwt, pos
- 輸出: lemma (詞根形式)
4. depparse (依存句法分析)
- 功能: 分析詞語間的語法依賴關係,構建句法樹
- 依賴: tokenize, mwt, pos, lemma
- 輸出: head (語法中心詞), deprel (依存關係)
----
5. ner (命名實體識別)
- 功能: 識別文本中的命名實體 (人名、地名、組織名等)
- 依賴: tokenize (可獨立運行)
- 輸出: entities, ner_tags
---
- 處理器 (Processors) 的概念

---
- 可以自由組合需要的處理器
```python
nlp_basic = stanza.Pipeline('zh-hant', processors='tokenize,pos')
nlp_full = stanza.Pipeline('zh-hant', processors='tokenize,pos,lemma,depparse,ner')
nlp_custom = stanza.Pipeline('zh-hant', processors='tokenize,ner') # 只要分詞和實體識別
```
---
## 第二部分:核心功能實作
---
### 2.1 文本分詞與句子分割
**實作目標**: 理解中文分詞的重要性和實現方式
```python
import stanza
# 建立處理管道
nlp = stanza.Pipeline('zh-hant', processors='tokenize')
# 範例文本
text = "自然語言處理是人工智慧的重要分支,它研究如何讓電腦理解人類語言。"
# 處理文本
doc = nlp(text)
# 查看分詞結果
for sentence in doc.sentences:
print("分詞結果:", [token.text for token in sentence.tokens])
```
```
分詞結果: ['自然', '語言', '處理', '是', '人工', '智慧', '的', '重要', '分支', ',', '它', '研究', '如何', '讓', '電腦', '理解', '人類', '語言', '。']
```
---
**重點**:
- 中文分詞的挑戰
- 中文句子沒有像英文單詞之間的空格分隔,詞與詞的邊界全靠機器決定,容易發生分詞歧義(如「全台大停電」可分「全台/大/停電」或「全/台大/停電」)。
----
- 分詞挑戰包含:「分詞標準不一致」(如「還要」分作「還/要」或「還要」)、「同詞多義」以及「新詞無法辨識」等。
- 分詞演算法常用:詞典匹配(基於最大匹配與Trie樹)、統計/機器學習方法(HMM/Viterbi)、深度學習(BiLSTM+CRF序列標註),但皆有歧義、新詞、標準差異的困難。
---
- Token vs Word的區別
- Token指的是模型初步切割的最小單位,可能是詞、字、甚至標點符號。例如在分詞時,「台積電2025年」可以被分成 token:「台積電」、「2025」、「年」。
- Word則更貼近語言學上的「詞語」,是語句真正的語意單位。中文分詞有時 token 和 word 重疊,如「人工智慧」,Token 可能原先是每個字,而Word則是詞組。
- 許多NLP工具會先分出token,再進行詞性標註、句法分析以產生詞(word)的描述。
---
- 句子邊界識別
- 中文句子不像英文一樣靠「.」明確分句,常用標點包含「。」「!」「?」「;」「……」等,甚至逗號在語意上有多重分隔功能。
- 標點符號意涵多元,模型會誤判語意停頓為新句(如台灣口語逗號分句情境)。
- 長句複合結構、引用/省略標點時,模型很難正確斷句。
---
### 2.2 詞性標註 (Part-of-Speech Tagging)
**實作目標**: 識別每個詞的文法角色
```python
# 加入詞性標註
nlp = stanza.Pipeline('zh-hant', processors='tokenize,pos')
text = "小明在陽明交通大學學習電腦科學。"
doc = nlp(text)
print("詞性標註結果:")
for sentence in doc.sentences:
for word in sentence.words:
print(f"{word.text:8} -> {word.upos}")
```
```
詞性標註結果:
小明 -> PROPN
在 -> VERB
陽明 -> PROPN
交通 -> NOUN
大學 -> NOUN
學習 -> VERB
電腦 -> NOUN
科學 -> NOUN
。 -> PUNCT
```
---
**重點**:
- Universal POS標籤系統
- Universal POS (Part-of-Speech) 標籤系統是由 Universal Dependencies 提議的一套語言無關、統一詞性標註集。
- 其目的是為不同語言的NLP工具及語料庫提供一致的詞性標註,是國際主流語言學研究及自動化語言分析的標準。
----
- 常見 Universal POS 標籤有:
- NOUN(名詞)
- VERB(動詞)
- ADJ(形容詞)
- ADV(副詞)
- PRON(代名詞)
- PROPN(專有名詞)、ADP(介詞)
- CONJ(連接詞)、DET(限定詞)
- PUNCT(標點)、NUM(數詞)
- PART(助詞)、INTJ(感嘆詞)
- SYM(符號)、X(其他)。
---
### 中文詞性的特殊性:
- 中文獨特詞性包括:語法助詞(如「的」「了」「著」)、多詞合併(如「正在學習」),使詞性標註在中文應用上比英文更為複雜。
- 中文中的「名詞」、「動詞」通常可重疊使用或互相轉化,存在詞性模糊現象(如「喝水」:水可為名詞/動詞詞組)。
----
- 專有名詞(PROPN)、量詞(NUM/CL)、語氣詞(PART)、成語/固定搭配、複合詞的標註也有特殊標準;中文詞性粒度比英文更細,且口語/書面有差異。
- NLP標註時需考慮語境、詞組邊界及切詞結果對詞性標註的影響。
---
- 詞性標註的應用場景
- 命名實體識別(NER):精確詞性分辨可輔助標註人名地名等類型,提高準確率。
- 關鍵詞提取與摘要:可以根據詞性提取主題詞(名詞、動詞等),產生精準摘要。
- 情感分析:分辨形容詞/副詞等情感強詞,提升評論極性判斷。
---
### 2.3 命名實體識別 (Named Entity Recognition)
**實作目標**: 識別文本中的重要實體
```python
nlp = stanza.Pipeline('zh', processors='tokenize,ner')
text = "蘋果公司的執行長提姆·庫克將於明天訪問台北101大樓。"
doc = nlp(text)
print("命名實體識別結果:")
for sentence in doc.sentences:
for ent in sentence.ents:
print(f"實體: {ent.text:12} 類型: {ent.type}")
```
```
命名實體識別結果:
實體: 蘋果公司 類型: ORG
實體: 提姆 類型: PERSON
實體: 庫克將 類型: PERSON
實體: 於明天 類型: DATE
實體: 台北101大樓 類型: FAC
```
---
- 命名實體包含多種語意類型,常見分類如下:
```
* 人名 (PERSON):「王小明」、「蔡英文」
* 地緣政治 (GPE):「台北」、「美國」
* 地名 (LOC):、「喜馬拉雅山」、「日月潭」
* 組織名 (ORG):「台積電」、「蘋果公司」、「世界衛生組織」
* 日期/時間 (DATE/TIME):「2025年」、「上午九點」、「下週」
* 貨幣、百分比 (MONEY/PERCENT):「新台幣一萬元」、「25%」
* 產品 (PRODUCT):「iPhone 15」
* 事件 (EVENT):「奧運會」、「總統大選」
* 設施 (FAC):「台北101」
* 語言 (LANG):「中文」、「英語」
* 基數(CARDINAL):「一百」、「三十」
* 序數(ORDINAL):「第一」、「第十」
* 數量+單位(QUANTITY):「三十公里」、「五公升」
* 其他:所屬關係、法律、藝術品等
```
中文NER系統可辨識十幾種實體類別,依應用場景可擴充更多領域(如醫療、金融、法律專業術語等)。
---
### NER在資訊抽取中的應用
- 關鍵資訊自動抽取:如新聞中自動標記人物、事件,協助摘要與索引,快速掌握內容核心。
- 問答系統與聊天機器人:精準分類輸入中的實體,讓系統針對人物、地點、產品進行互動、回答或推薦。
- 文本分類/知識圖譜建構:從大量文件中將實體及其關係提取,用於建構知識網絡或知識資料庫。
- 情感分析/大數據分析:針對特定實體自動分析輿情、口碑、消費者回饋等。
---
- 中文NER的挑戰
- 無空格切詞困難:中文句子缺乏明顯詞語界線,NER模型高度依賴分詞準確度。
- 同形異義/合成詞現象:如「台灣高鐵」同時有地名/組織詞性、「小米」可指人名/品牌/產品,辨識困難。
- 新專名/流行語/外來詞:新興品牌、地名、網路用語出現速度快,現有語料庫難及時涵蓋。
----
- 標準語料缺乏/語言知識Domain Gap:高品質中文NER語料少、各大領域有各自標註標準,或特殊專業術語。
- 語法結構複雜/長詞多詞成分重疊:中文多有省略、疊詞、複合詞等句法現象,讓NER模型設計更具挑戰。
---
### 2.4 依存句法分析 (Dependency Parsing)
https://stanza.stanford.edu/
**實作目標**: 分析句子的語法結構
```python
nlp = stanza.Pipeline('zh-hant', processors='tokenize,pos,lemma,depparse')
text = "學生們在圖書館裡認真地讀書。"
doc = nlp(text)
print("依存句法分析:")
for sentence in doc.sentences:
for word in sentence.words:
print(f"{word.text} -> {word.head} ({word.deprel})")
```
```
依存句法分析:
學生 -> 2 (compound)
們 -> 9 (nsubj)
在 -> 5 (case)
圖書 -> 5 (compound)
館 -> 9 (obl)
裡 -> 5 (case)
認真 -> 9 (advmod)
地 -> 7 (mark:adv)
讀書 -> 0 (root)
。 -> 9 (punct)
```
---
### 短語結構語法
- 短語結構語法(Phrase Structure Grammar):以「成分關係」為基礎,將句子分成層層嵌套的短語單位(如名詞短語NP、動詞短語VP等);樹狀結構由自上而下分析句子,是傳統語言學如 Chomsky 句法理論的主流。
- 例:S → NP + VP;NP → DET + N
- 樹上的每個節點都代表短語或其組成部分,句法成分強調「組合關係」。
- “食物非常好吃。”
- 
---
### 依存語法
- 依存語法(Dependency Grammar):強調詞彙之間的依賴關係,不關心短語層級,直接以「詞→詞」為基礎形成樹型結構;每個詞只和另一個詞(其語法中心詞head)有關聯,所有關係都由中心詞主導。
- 例:「小明愛看書」:root(愛),nsubj(愛, 小明),obj(愛, 書)
- 樹上的每個節點是單一詞彙,強調「依賴關係」。
- 例:「食物非常好吃」:
- 
----
- 依存關係的類型
- 主語(nsubj):主語與謂語,例如「我」→「看」。
- 賓語(obj/dobj/pobj):謂語的賓語,如「看」→「書」。
- 修飾語(amod/advmod/nmod):形容詞、副詞、名詞間修飾,如「非常」→「好吃」。
- 時間修飾(nmod:tmod):如「昨天」→「看書」。
- 限定詞(det):如「一本」→「書」。
- 依存句法關係還包括:aux(助動詞)、case(介詞)、conj(並列)、mark(標記)、vocative(呼格)、cc(連詞)、xcomp(補語)、clf(量詞)等。
---
### 句法樹的視覺化
- 短語結構樹:由上而下分解成分,每個分支代表一個短語組成部分,終端為詞彙本身。常用於語言學、翻譯等領域。
- ```
S
├── NP
│ ├── DET
│ └── NN
└── VP
├── VBD
└── PP
└── NP…
```
----
- 依存關係樹:每個詞為節點,箭頭代表語法依賴,標注依存類型(如主語、賓語),使語法結構一目了然,便利於資訊抽取和語意理解。
- 例:「小明昨天在圖書館讀書。」
```
root(讀書)
├── nsubj(小明, 讀書)
├── nmod:tmod(昨天, 讀書)
├── nmod(圖書館, 讀書)
```
---
---
## 第三部分:進階應用與專案實作
---
### 3.1 批量文本處理
**實作目標**: 高效處理大量文檔
```python
# 準備多個文檔
documents = [
"人工智慧將改變未來的工作方式。",
"深度學習在影像識別方面取得重大突破。",
"自然語言處理讓機器能理解人類語言。"
]
# 批量處理
in_docs = [stanza.Document([], text=d) for d in documents]
out_docs = nlp(in_docs)
# 分析結果
for i, doc in enumerate(out_docs):
print(f"文檔 {i+1} 的實體:")
for sent in doc.sentences:
for ent in sent.ents:
print(f" {ent.text} ({ent.type})")
```
---
### 3.2 情感分析實作
**實作目標**: 分析文本的情感傾向
```python
# 英文情感分析
en_nlp = stanza.Pipeline('en', processors='tokenize,sentiment')
reviews = [
"This product is amazing! I love it.",
"The service was terrible and disappointing.",
"It's okay, nothing special but not bad either."
]
sentiment_labels = {0: "負面", 1: "中性", 2: "正面"}
for review in reviews:
doc = en_nlp(review)
for sentence in doc.sentences:
print(f"評論: {sentence.text}")
print(f"情感: {sentiment_labels[sentence.sentiment]}\n")
```
```
評論: This product is amazing!
情感: 正面
評論: I love it.
情感: 正面
評論: The service was terrible and disappointing.
情感: 負面
評論: It's okay, nothing special but not bad either.
情感: 正面
```
---
### 3.3 完整專案:新聞文本分析系統
**實作目標**: 整合所有功能的實際應用
```python
def analyze_news_text(text, nlp_pipeline):
"""完整的新聞文本分析函數"""
doc = nlp_pipeline(text)
analysis_result = {
'entities': [],
'key_words': [],
'sentence_count': len(doc.sentences),
'word_count': sum(len(sent.words) for sent in doc.sentences)
}
for sentence in doc.sentences:
# 收集命名實體
for ent in sentence.ents:
analysis_result['entities'].append({
'text': ent.text,
'type': ent.type
})
# 收集關鍵詞(名詞和動詞)
for word in sentence.words:
if word.upos in ['NOUN', 'VERB'] and len(word.text) > 1:
analysis_result['key_words'].append(word.text)
return analysis_result
# 使用範例
news_text = """
台積電今日宣布,將在美國亞利桑那州建設新的晶圓廠。
這項投資計畫總額高達120億美元,預計將創造1600個就業機會。
台積電董事長劉德音表示,此舉將強化公司在全球半導體產業的領導地位。
"""
nlp = stanza.Pipeline('zh-hans', processors='tokenize,pos,ner')
result = analyze_news_text(news_text, nlp)
print("新聞分析結果:")
print(f"句子數量: {result['sentence_count']}")
print(f"詞彙數量: {result['word_count']}")
print(f"命名實體: {[ent['text'] for ent in result['entities']]}")
print(f"關鍵詞: {list(set(result['key_words']))}")
```
```
新聞分析結果:
句子數量: 3
詞彙數量: 65
命名實體: ['台積電', '今日', '美國', '亞利桑那州', '120億美元', '1600個', '台積電', '劉', '德音']
關鍵詞: ['宣布', '建設', '強化', '今日', '表示', '領導', '公司', '晶圓', '地位', '全球', '董事', '投資']
```
---
## 附錄
### A. 常用處理器列表
- tokenize: 分詞和句子分割
- mwt: 多詞標記展開
- pos: 詞性標註
- lemma: 詞形還原
- depparse: 依存句法分析
- ner: 命名實體識別
- sentiment: 情感分析
----
### B. 語言代碼對照
- zh-hant: 繁體中文
- zh-hans: 簡體中文
- en: 英文
- ja: 日文
- ko: 韓文
----
### C. 實用程式碼片段
```python
# 快速設置
def quick_setup(lang='zh-hant'):
return stanza.Pipeline(lang, processors='tokenize,pos,ner,depparse')
# 實體抽取函數
def extract_entities(text, nlp):
doc = nlp(text)
entities = []
for sent in doc.sentences:
for ent in sent.ents:
entities.append((ent.text, ent.type))
return entities
# 詞性分析函數
def pos_analysis(text, nlp):
doc = nlp(text)
pos_counts = {}
for sent in doc.sentences:
for word in sent.words:
pos_counts[word.upos] = pos_counts.get(word.upos, 0) + 1
return pos_counts
```
---