NLP中Subword算法:WordPiece、BPE、BBPE、SentencePiece詳解以及代碼實現

本文將介紹以下內容:

  • 1. Subword與傳統tokenization技術的對比
  • 2. WordPiece
  • 3. Byte Pair Encoding (BPE)
  • 4. Byte-level BPE(BBPE)
  • 5. SentencePiece 以及各Subword算法代碼實現

一、Subword與傳統tokenization技術的對比

1. 傳統tokenization技術

傳統tokenization技術一般有兩種方法:word(詞)粒度、char(字符)粒度

1.1 word(詞)粒度

傳統構造詞表的方法,是先對各個句子進行分詞,然后再統計并選出頻數最高的前N個詞組成詞表。通常訓練集中包含了大量的詞匯,以英語為例,總的單詞數量在17萬到100萬左右。對于英文來說,word級別分詞實現很簡單,因為本身就有分隔符號。在中文里面word粒度,需要使用一些分詞工具比如jieba、ltp等。該方案優劣勢如下:

  • 優點:

    • 語義明確: 以詞為粒度進行分詞可以更好地保留每個詞的語義,使得文本在后續處理中能夠更準確地表達含義。
    • 上下文理解: 以詞為粒度進行分詞有助于保留詞語之間的關聯性和上下文信息,從而在語義分析和理解時能夠更好地捕捉句子的意圖。
  • 缺點:

    • OOV(Out-of-Vocabulary): 分詞模型只能夠使用詞表中的詞進行處理,無法處理詞表之外的詞匯。
    • 長尾效應和稀有詞問題: 詞表可能變的巨大,包含很多不常見的詞匯,增加存儲和訓練成本,稀有詞的訓練數據有限,無法得到充分訓練,進而模型不能充分理解這些詞的語義。
    • 形態關系和詞綴關系: 無法捕捉同一詞的不同形態,也無法學習詞綴在不同詞匯之間的共通性,限制了模型的語言理解能力。比如look和looks在詞表中將會是兩個詞。一方面增加了訓練冗余,另一方面也造成了大詞匯量問題。
1.2 char(字符)粒度

以字符為單位進行分詞,就是把文本拆分成一個個單獨的字符作為最小的基本單元,這種對多種語言都比較適用,比如英文、中文、印尼語等。英文就是26個字母以及其他的一些符號,中文常見、次常用字大約共有 6000多個。該方案優劣勢如下:

  • 優點:
    • 通用性: 字符粒度的分詞方法使用與不同的語言,不需要設計不同的規則和工具。
    • 避免OOV問題: 這種粒度的分詞能夠處理任何字符,無需維護詞表,因此可以很好地處理一些新的詞匯、專有名詞等。
  • 缺點:
    • 語義信息不明確: 這種粒度的分詞無法直接表達詞的語義,可能在一些語義分析任務中效果比較差。
    • 效率極低: 由于文本被拆分成字符,處理粒度較小,增加了后續處理的計算成本和時間。
2. Subword(子詞)粒度

目前有三種主流的Subword算法,它們分別是:Byte Pair Encoding (BPE), WordPiece和Unigram Language Model。

針對上述問題,Subword(子詞)模型方法橫空出世。它的劃分粒度介于詞與字符之間,比如可以將”looking”劃分為”look”和”ing”兩個子詞,而劃分出來的"look",”ing”又能夠用來構造其它詞,如"look"和"ed"子詞可組成單詞"looked",因而Subword方法能夠大大降低詞典的大小,同時對相近詞能更好地處理。

接下來將分別詳細介紹:WordPiece、BPE、BBPE、ULM。

二、WordPiece

請見筆者之前文章:NLP Subword 之 WordPiece 算法原理

三、Byte Pair Encoding (BPE)

請見筆者之前文章:NLP Subword 之 BPE(Byte Pair Encoding) 算法原理

四、Byte-level BPE(BBPE)

請見筆者之前文章:NLP Subword 之 BBPE(Byte-level BPE) 算法原理

五、SentencePiece 以及各Subword算法代碼實現

1. 什么是 SentencePiece?

在自然語言處理(NLP)中,分詞(tokenization) 是一個極為關鍵的步驟。傳統的分詞方法往往依賴語言特定的規則(比如英文依靠空格,中文依靠分詞工具),而在多語言任務或需要統一處理的場景下,這種方式就顯得繁瑣且不夠通用。

SentencePiece 是 Google 開源的一個 語言無關(language-agnostic)子詞建模工具。它的“工具屬性”主要體現在:

  • 端到端訓練:直接基于原始語料,無需預分詞或去掉空格,輸出模型文件(.model)和詞表(.vocab)。
  • 多算法統一接口:同一套命令/接口支持 Unigram(ULM)、BPE、Char、Word 等模型類型。
  • 推理一致性:同一模型可用于編碼(encode)與解碼(decode),避免預處理不一致的問題。
  • OOV 友好:支持 --byte_fallback,可以在詞表未登錄時回退為字節級 token,實現 Byte-level BPE(BBPE) 的效果。

需要特別說明的是:

  • SentencePiece 并沒有直接提供 WordPiece 類型
  • 在實踐中,通常使用 Unigram 模型近似/替代 WordPiece

2. 使用 Python SentencePiece 庫分別實現 ULM、BPE、BBPE

下面通過 3 個獨立的 Demo,完整展示 訓練 + 推理 全流程。每個 Demo 都會:

  1. 生成一份 demo 語料;
  2. 調用 sentencepiece 訓練模型;
  3. 加載模型進行推理(encode/decode);

2.1 Unigram Language Model(ULM)

Unigram 是 SentencePiece 默認與推薦的算法之一,常作為 WordPiece 的替代實現

# demo_ulm.py
import os
import sentencepiece as spm# 0) 準備語料
workdir = "./sp_ulm_work"
os.makedirs(workdir, exist_ok=True)
corpus = os.path.join(workdir, "corpus.txt")lines = ["我愛自然語言處理。","自然語言處理是人工智能的重要分支。","Hello world! This is a tiny corpus for subword training.","Emoji 測試:🙂🚀🌍,以及混合文本 NLP。",
]
with open(corpus, "w", encoding="utf-8") as f:f.write("\n".join(lines))# 1) 訓練 Unigram 模型
model_prefix = os.path.join(workdir, "uni")
spm.SentencePieceTrainer.Train(input=corpus,model_prefix=model_prefix,vocab_size=800,          # demo 用小詞表model_type="unigram",    # ★ 關鍵:Unigramcharacter_coverage=1.0
)# 2) 推理
sp = spm.SentencePieceProcessor(model_file=f"{model_prefix}.model")
test_text = "我愛NLP🚀!"
pieces = sp.encode(test_text, out_type=str)
ids = sp.encode(test_text, out_type=int)
back = sp.decode(ids)print("INPUT :", test_text)
print("PIECES:", pieces)
print("IDS   :", ids)
print("DECODE:", back)

2.2 Byte Pair Encoding(BPE)

BPE 是另一種常見的子詞算法,原理是迭代合并語料中頻率最高的相鄰 token 對。

# demo_bpe.py
import os
import sentencepiece as spm# 0) 準備語料
workdir = "./sp_bpe_work"
os.makedirs(workdir, exist_ok=True)
corpus = os.path.join(workdir, "corpus.txt")lines = ["BPE merges rules are learned from frequent pairs.","Hello world! Byte Pair Encoding is simple and effective.","中文測試:分詞、子詞建模。",
]
with open(corpus, "w", encoding="utf-8") as f:f.write("\n".join(lines))# 1) 訓練 BPE 模型
model_prefix = os.path.join(workdir, "bpe")
spm.SentencePieceTrainer.Train(input=corpus,model_prefix=model_prefix,vocab_size=800,model_type="bpe",        # ★ 關鍵:BPEcharacter_coverage=1.0
)# 2) 推理
sp = spm.SentencePieceProcessor(model_file=f"{model_prefix}.model")
test_text = "BPE 的分詞效果如何?😊"
pieces = sp.encode(test_text, out_type=str)
ids = sp.encode(test_text, out_type=int)
back = sp.decode(ids)print("INPUT :", test_text)
print("PIECES:", pieces)
print("IDS   :", ids)
print("DECODE:", back)

2.3 Byte-level BPE(BBPE)

BBPE 的核心思想是 在 BPE 上增加字節級回退(byte fallback),保證任何輸入都能被編碼。

# demo_bbpe.py
import os
import sentencepiece as spm# 0) 準備語料
workdir = "./sp_bbpe_work"
os.makedirs(workdir, exist_ok=True)
corpus = os.path.join(workdir, "corpus.txt")lines = ["Byte-level BPE ensures any input is representable.","Emoji 測試:🙂🚀🌍。","混合語言測試:NLP 和 數據。",
]
with open(corpus, "w", encoding="utf-8") as f:f.write("\n".join(lines))# 1) 訓練 BBPE 模型(本質是 BPE + byte_fallback)
model_prefix = os.path.join(workdir, "bbpe")
spm.SentencePieceTrainer.Train(input=corpus,model_prefix=model_prefix,vocab_size=800,model_type="bpe",          # 仍然是 BPEcharacter_coverage=1.0,byte_fallback=True         # ★ 關鍵:開啟字節回退
)# 2) 推理
sp = spm.SentencePieceProcessor(model_file=f"{model_prefix}.model")
test_text = "未登錄字符𝔘𝔫𝔦𝔠𝔬𝔡𝔢😊"
pieces = sp.encode(test_text, out_type=str)
ids = sp.encode(test_text, out_type=int)
back = sp.decode(ids)print("INPUT :", test_text)
print("PIECES:", pieces)
print("IDS   :", ids)
print("DECODE:", back)

3. 小結
  1. SentencePiece 是一個通用的子詞建模工具,它屏蔽了語言差異,讓我們直接在原始語料上訓練子詞模型。
  2. 它支持 Unigram(ULM)、BPE、Char、Word 等模型類型,但 沒有直接的 WordPiece;通常用 Unigram 來近似/替代 WordPiece。
  3. 通過 byte_fallback 參數,SentencePiece 可以在 BPE 模型上實現 BBPE 的能力,從而覆蓋任意輸入字符(如 emoji、稀有符號)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/97912.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/97912.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/97912.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

十一章 無界面壓測

一、采用無界面壓測的原因1.節約系統資源。 2.更快捷,只需要啟動命令即可進行壓測 3.主要是用于性能壓測集成.無界面壓測命令參數: -n 表示無界面壓測 -t 制定你的 jmx 腳本 -l 生成 jtl 測試報告二、注意配置文件設置:輸出為xml jmeter.save.s…

從零實現 Qiankun 微前端:基座應用控制子應用路由與信息交互

隨著前端業務的快速發展,單體應用模式(Monolith)越來越難以支撐復雜業務場景。微前端(Micro Frontends)應運而生,它將大型應用拆解成多個子應用(Micro App),通過主應用進行統一調度和集成。 在微前端技術棧中,Qiankun(乾坤)是一個廣泛使用的解決方案,基于 single…

在業務應用中集成 go-commons,實現應用+系統雙指標監控

在日常 Go 服務開發中,我們通常需要同時監控 業務指標(比如 QPS、請求延遲、錯誤率),也需要關注 系統指標(CPU、內存、磁盤占用情況)。 過去這類場景通常要引入多個庫:一個負責業務指標采集&…

容器化部署番外篇之docker網絡通信06

一、四種網絡模式 Bridge模式:容器的默認網關,默認新建容器的網絡模式Host模式:容器和宿主機共用一個 Network,使用主機的IP:PORT就可以訪問容器,但安全性不高,用得少Container模式:這個模式指定…

Linux 線程的概念

序言: 在這篇博客中我們將講解線程的概念,如何理解線程,線程和進程的區別,線程的優缺點等,我相信你看完這篇博客后會以別樣的視角重新理解線程,下面的內容全部是基于Linux操作系統的。 一、線程的概念 1…

vscode 中通義靈碼顯示登錄過期

本文主要分享:vscode 中通義靈碼顯示登錄過期的解決辦法。vscode 中的小插件通義靈碼,用的好好的,突然提示:登錄過期,嘗試訪問網頁版阿里云,登錄后,關閉 vscode 重新打開,通義靈碼還…

ESP32C3-MINI-1開發板踩坑記錄

某東買了一個ESP32C3-MINI-1開發板,名字跟ESP官網的很像,想著應該差不多的,價格便宜17塊,而官網的就貴了60還不包郵,買來才發現是巨坑。 看結論,直接到最后,前面都是我的踩坑過程。第一塊板子發…

基于粒子群算法的山地環境無人機最短路徑規劃研究(含危險區域約束的三維優化方法)

無人機在復雜地形與危險環境中的自主路徑規劃是保障任務順利執行的關鍵問題。本文針對山地環境下單無人機三維路徑規劃難題,提出了一種基于粒子群算法(PSO)的優化方法。首先,建立了包含真實地形高程、危險區域和飛行約束條件的三維…

Linux-> UDP 編程2

目錄 本文說明 一:字典程序的幾個問題 1:字典的本質 2:翻譯功能的本質 3:讓服務端和翻譯功能相關聯 二:字典類(Dict.hpp) 1:加載詞典(Load) 2:翻譯單詞(Translate) 三:服務…

輝視養老方案:重塑老年生活的溫馨與安心

在當今社會,隨著老齡化進程的加速,如何為老年人提供更加便捷、舒適且安全的養老環境,成為了全社會共同關注的焦點。輝視養老方案應運而生,它以科技為翼,以關愛為心,通過遠程探望、客控系統、信息服務、IPTV…

SQuAD:機器閱讀理解領域的里程碑數據集

本文由「大千AI助手」原創發布,專注用真話講AI,回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我,一起撕掉過度包裝,學習真實的AI技術! 1 什么是SQuAD? SQuAD(Stanford Question Ans…

【vim,Svelte】怎樣使用 vim 編輯 Svelte 那些奇奇怪怪名字的文件?

當你要使用 vim(或者neovim)來編輯 Svelte 下面的文件時,比如這些文件: page.svelte layout.svelte$ vim page.svelte $ vim "page.svelte" $ vim page.svelte $ vim \page.svelte使用上面的命令,你會遇到這…

深入解析 HTTP 狀態碼

在日常的網絡瀏覽和 Web 開發過程中,我們總會不可避免地遇到各種 HTTP 狀態碼。比如常見的 “404 Not Found”,它意味著我們所請求的頁面不存在;還有 “500 Internal Server Error”,表示服務器端出現了錯誤。這些由三位數字組成的…

【C++】C++類和對象—(中)

前言:在上一篇類和對象(上)的文章中我們已經帶領大家認識了類的概念,定義以及對類和對象的一些基本操作,接下來我們要逐步進入到類和對象(中)的學習。我們將逐步的介紹類和對象的核心——類和對象的六個默認成員函數。(注意:這六個…

使用python-fastApi框架開發一個學校宿舍管理系統-前后端分離項目

今天給大家分享一個我最近做的一個學校宿舍管理系統,python版,這個系統實現的功能有:首頁 | 學校管理 | 宿舍樓管理 | 宿舍管理 | 學生管理 | 學生調宿 | 學生退宿 | 報修等級 | 宿舍衛生評分 | 違紀記錄 | 管理員管理 。一共有11個菜單。 使…

阻塞 vs 非阻塞:程序等待的兩種哲學

當程序需要等待外部操作時,是應該"干等"還是"邊等邊干"?為什么有些程序會卡住不動,而另一些卻能流暢運行?這一切都取決于阻塞與非阻塞的編程選擇!本文將為你揭示這兩種模式的本質區別!…

MySQL 核心操作全解析(用戶 + SHOW+DML+DCL)

MySQL 核心操作全解析(用戶 SHOWDMLDCL) 基于你提供的實操筆記,我們將 MySQL 核心操作拆解為用戶管理、SHOW 查詢命令、DML 數據操作、TRUNCATE 與 DELETE 對比、DCL 權限控制五大模塊,梳理語法邏輯、補充避坑提示,幫…

多語言編碼Agent解決方案(6)-部署和使用指南

部署和使用指南 本指南提供完整的部署和使用說明,幫助您設置后端服務并在VSCode、Eclipse和IntelliJ中使用相應的插件。這個解決方案基于vLLM提供AI編碼輔助,支持英語、中文和日文。 前提條件 操作系統:Linux、macOS或Windows(推薦…

濾波器的三重境界:從信號處理到自動駕駛測試的基石

在自動駕駛的宏大敘事中,我們常常聚焦于人工智能、深度學習、高精地圖等"明星技術"。然而,在這些耀眼的光環背后,有一個低調卻至關重要的"幕后英雄"——濾波器。它不僅是信號處理的工具,更是連接物理世界與數…

Part4.第8章:神經網絡

第8章 激活函數 如果沒有激活函數,不論幾層的神經網絡都是一個線性回歸。激活函數的作用是引入非線性。