Jieba 與 CKIP 斷詞系統:繁體中文自然語言處理雙雄

在中文自然語言處理(NLP)領域,斷詞(Word Segmentation)是所有任務的基石。而對於繁體中文使用者而言,Jieba(結巴)與中研院詞庫小組(CKIP)的斷詞系統是兩大主流工具。它們各有優勢,但在核心技術、使用方式和適用情境上卻有著顯著的差異。本篇文章將深入探討這兩者的特性、實作方式,並提供選擇指南。

Jieba(結巴):快速、彈性、開源

Jieba 是一個廣受歡迎的開源中文斷詞工具,由中國開發者撰寫,因其速度快、安裝簡單而聞名。它的核心優勢在於高度的彈性,允許使用者根據自己的需求進行客製化,例如新增自訂詞彙或調整詞頻。

Jieba 支援三種主要的斷詞模式:

  • 精確模式: 試圖將句子最精確地切開,適合文本分析。
  • 全模式: 將句子中所有可能成詞的詞語都掃描出來,速度最快但可能產生冗餘。
  • 搜尋引擎模式: 在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜尋引擎。

CKIP 斷詞工具:高準度、學術驅動

中研院詞庫小組(CKIP)的斷詞系統擁有深厚的學術背景,是繁體中文 NLP 領域的權威。其核心優勢在於高準確性全面的詞性標註,特別擅長處理繁體中文的語言特性,並能精準辨識專有名詞。

CKIP 的斷詞系統以多種模型為基礎,近年來更結合了神經網路技術,開發了開源的 ckip-transformers 套件,提供了包含斷詞、詞性標註(POS Tagging)和命名實體辨識(NER)在內的一站式解決方案。雖然模型檔案較大,但其提供的豐富功能與高準確度,使其成為許多嚴謹學術研究和企業應用的首選。

核心技術與設計理念差異

Jieba 與 CKIP 在技術路線上採取了不同的策略:

  • Jieba: 採用基於詞典和統計的方法。它會建立一個詞圖(DAG),然後使用動態規劃找到概率最大的切分路徑。對於未出現在詞典中的詞語,則使用**隱藏式馬可夫模型(HMM)**來進行新詞發現。其設計理念是「快速且夠用」。
  • CKIP: 傳統上基於語法規則和機器學習,而新版則依賴於預訓練的神經網路模型(如 BERT)。這使得它在斷詞的同時,也能利用上下文資訊進行更精確的詞性標註與實體辨識。其設計理念是「全面且準確」。

Python 實作:Jieba 基礎斷詞

在開始之前,請確保您已安裝 Jieba:pip install jieba

以下範例展示了 Jieba 的基本使用方法,包括精確模式、全模式,以及如何載入繁體中文詞典和自訂詞典。

Jieba 斷詞實作範例

import jieba
import jieba.posseg as pseg
import os

# --- 準備繁體中文詞典(這一步非常重要,確保斷詞結果更符合繁體中文習慣)---
# 您需要從網路上找到繁體中文詞典,例如:https://github.com/fxsjy/jieba/issues/509
# 假設您已下載並將詞典檔案命名為 'dict.txt.big'
# 如果檔案不存在,Jieba 仍會使用預設詞典,但準確度可能較低
if os.path.exists('dict.txt.big'):
    jieba.set_dictionary('dict.txt.big')
    print("已載入繁體中文詞典...")

# --- 載入自訂詞典 ---
# 建立一個 'user_dict.txt' 檔案,內容格式為:詞彙 詞頻 詞性
# 例如:
# 人工智慧 3 n
# 中研院 5 org
# 深度學習 4 n
# 自訂詞彙 6 n
jieba.load_userdict('user_dict.txt')
print("已載入自訂詞典...")


# 待斷詞的繁體中文句子
sentence = "結巴斷詞工具和中研院詞庫小組的斷詞系統都有其優勢,深度學習技術也廣泛應用。"

# 1. 精確模式斷詞 (預設)
seg_list_exact = jieba.lcut(sentence, cut_all=False)
print("精確模式斷詞:", " / ".join(seg_list_exact))

# 2. 全模式斷詞
seg_list_all = jieba.lcut(sentence, cut_all=True)
print("全模式斷詞:", " / ".join(seg_list_all))

# 3. 詞性標註斷詞
# 使用 jieba.posseg 模組來進行詞性標註
words_with_pos = pseg.cut(sentence)
pos_list = [f"{word.word}({word.flag})" for word in words_with_pos]
print("詞性標註斷詞:", " / ".join(pos_list))

Python 實作:中研院 CKIP 基礎斷詞

要使用中研院的斷詞工具,最推薦的是 ckip-transformers。請先安裝必要的套件:pip install ckip-transformers,並確保您的環境支援 TensorFlow。

以下範例展示了如何載入模型並進行斷詞、詞性標註與命名實體辨識。由於模型檔案較大,初次執行會需要一些時間進行下載。

CKIP 斷詞實作範例

from transformers import AutoTokenizer, AutoModelForTokenClassification
from ckiptagger import data_utils, WS, POS, NER
import os

# --- 下載模型 ---
# 首次執行需下載模型,之後會從本地載入
# 如果資料夾不存在,請執行 data_utils.download_data_url(url)
# 這裡假設模型檔案已存在
# try:
#     data_utils.download_data_url(url_file='http://....')
# except Exception as e:
#     print(f"模型下載失敗,請手動下載: {e}")

# --- 載入模型 ---
# 這裡使用 ckiptagger 提供的模型,支援斷詞 (WS), 詞性標註 (POS), 命名實體辨識 (NER)
# disable_cuda=True 表示不使用 GPU,若有 GPU 可設為 False
print("正在載入 CKIP 模型...")
ws = WS("./data", disable_cuda=True)
pos = POS("./data", disable_cuda=True)
ner = NER("./data", disable_cuda=True)
print("CKIP 模型載入完成!")

# 待處理的繁體中文句子
sentence_list = [
    "中研院詞庫小組開發的斷詞系統,結合深度學習技術,能夠精準辨識專有名詞。",
    "結巴斷詞工具由中國開發,以速度快而聞名。"
]

# 執行斷詞、詞性標註和命名實體辨識
word_sentence_list = ws(sentence_list)
pos_sentence_list = pos(word_sentence_list)
ner_sentence_list = ner(word_sentence_list, pos_sentence_list)

# 輸出結果
for i, sentence in enumerate(sentence_list):
    print(f"\n--- 原始句子 {i+1} ---")
    print(sentence)

    # 斷詞結果
    print("斷詞結果:", word_sentence_list[i])

    # 詞性標註結果
    print("詞性標註:", pos_sentence_list[i])
    
    # 命名實體辨識結果 (NER)
    print("命名實體辨識:")
    for entity in ner_sentence_list[i]:
        print(f"  {entity[0]}: {entity[1]} ({entity[2]})")

# --- 載入自訂詞典 ---
# CKIP 也支援自訂詞典,需將詞彙和詞性以特定格式儲存
# user_dict = {
#     "深度學習": "Na",
#     "結巴斷詞": "Na"
# }
# ws_with_dict = WS("./data", disable_cuda=True, user_dict=user_dict)
# print("\n已載入包含自訂詞典的 CKIP 模型。")

如何根據專案需求選擇工具

  • 專注於速度和彈性?選擇 Jieba。 如果您的專案需要處理大量的非正式文本(如社群媒體貼文),並且需要頻繁地加入專門術語,Jieba 的輕量級特性和彈性會是更好的選擇。
  • 追求最高準確度和深度分析?選擇 CKIP。 如果您的專案屬於學術研究、需要處理嚴謹的公文或新聞語料,並且需要精準的詞性、命名實體等資訊,CKIP 能夠提供更可靠的分析結果。

結論:速度與準確度的權衡

Jieba 和中研院 CKIP 斷詞系統沒有絕對的優劣,它們代表了兩種不同的開發哲學。Jieba 以其簡單、快速、彈性的特性,讓中文斷詞在開發者社群中普及。而 CKIP 則以其準確、全面、學術的優勢,為需要嚴謹分析的專案提供了強大的基石。選擇哪一個工具,取決於您的專案對速度與準確度之間的權衡,以及您處理的是哪一種中文語料。

from transformers import AutoTokenizer, AutoModelForTokenClassification
from ckiptagger import data_utils, WS, POS, NER
import os

# --- 下載模型 ---
# 首次執行需下載模型,之後會從本地載入
# 如果資料夾不存在,請執行 data_utils.download_data_url(url)
# 這裡假設模型檔案已存在
# try:
#     data_utils.download_data_url(url_file='http://....')
# except Exception as e:
#     print(f"模型下載失敗,請手動下載: {e}")

# --- 載入模型 ---
# 這裡使用 ckiptagger 提供的模型,支援斷詞 (WS), 詞性標註 (POS), 命名實體辨識 (NER)
# disable_cuda=True 表示不使用 GPU,若有 GPU 可設為 False
print("正在載入 CKIP 模型...")
ws = WS("./data", disable_cuda=True)
pos = POS("./data", disable_cuda=True)
ner = NER("./data", disable_cuda=True)
print("CKIP 模型載入完成!")

# 待處理的繁體中文句子
sentence_list = [
    "中研院詞庫小組開發的斷詞系統,結合深度學習技術,能夠精準辨識專有名詞。",
    "結巴斷詞工具由中國開發,以速度快而聞名。"
]

# 執行斷詞、詞性標註和命名實體辨識
word_sentence_list = ws(sentence_list)
pos_sentence_list = pos(word_sentence_list)
ner_sentence_list = ner(word_sentence_list, pos_sentence_list)

# 輸出結果
for i, sentence in enumerate(sentence_list):
    print(f"\n--- 原始句子 {i+1} ---")
    print(sentence)

    # 斷詞結果
    print("斷詞結果:", word_sentence_list[i])

    # 詞性標註結果
    print("詞性標註:", pos_sentence_list[i])
    
    # 命名實體辨識結果 (NER)
    print("命名實體辨識:")
    for entity in ner_sentence_list[i]:
        print(f"  {entity[0]}: {entity[1]} ({entity[2]})")

# --- 載入自訂詞典 ---
# CKIP 也支援自訂詞典,需將詞彙和詞性以特定格式儲存
# user_dict = {
#     "深度學習": "Na",
#     "結巴斷詞": "Na"
# }
# ws_with_dict = WS("./data", disable_cuda=True, user_dict=user_dict)
# print("\n已載入包含自訂詞典的 CKIP 模型。")

# --- LLM 如何利用中文斷詞 ---
# 在處理中文文本時,斷詞是LLM理解語義的關鍵前處理步驟。
# 這裡示範如何將斷詞結果格式化為LLM模型可以接受的輸入。
# 通常LLM會將斷詞結果的詞語以空格或特殊符號分隔作為輸入,
# 這樣模型能夠更精準地理解每個詞語的語義。

print("\n--- LLM 應用範例:將斷詞結果格式化為模型輸入 ---")
llm_input_list = [" ".join(words) for words in word_sentence_list]

for i, llm_input in enumerate(llm_input_list):
    print(f"原始句子 {i+1} 的 LLM 輸入:")
    print(llm_input)

# 此外,詞性標註 (POS) 和命名實體辨識 (NER) 也可以作為額外的特徵,
# 幫助LLM在語義理解、摘要生成、問答系統等任務上表現更佳。
# 例如,將NER結果標註為特殊標籤,讓LLM能辨識出句子中的實體。
# llm_ner_input_list = []
# for i, words in enumerate(word_sentence_list):
#     ner_entities = ner_sentence_list[i]
#     llm_ner_input = " ".join(words)
#     for entity_type, entity_text, _ in ner_entities:
#         llm_ner_input = llm_ner_input.replace(
#             entity_text,
#             f"<{entity_type}> {entity_text} </{entity_type}>"
#         )
#     llm_ner_input_list.append(llm_ner_input)

# print("\n--- LLM 應用範例:結合NER標籤作為模型輸入 ---")
# for i, llm_ner_input in enumerate(llm_ner_input_list):
#     print(f"原始句子 {i+1} 的 LLM 輸入 (含NER標籤):")
#     print(llm_ner_input)

*以上文章部份為AI產生內容,無商業用途。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端