本文将介绍以下内容:

  • 1. BPE 算法核心原理
  • 2. BPE 算法流程
  • 3. BPE 算法源码实现Demo

BPE最早是一种数据压缩算法,由Sennrich等人于2015年引入到NLP领域并很快得到推广。该算法简单有效,因而目前它是最流行的方法。GPT-2和RoBERTa使用的Subword算法都是BPE。

1. BPE 算法核心原理:

它的主要思想是:

  • 使用频率统计来逐步合并高频的字符/子词对。
  • 从最小的单位(字符)开始,逐渐学习得到一套子词词表,使模型能够兼顾 常见词的完整表示 和 罕见词的组合表示。

在大语言模型时代,最常用的分词方法是Byte-Pair Encoding(BPE)和Byte-level BPE(BBPE)。该算法的核心思想是逐步合并出频率最高的子词对而不是像wordpiece一样通过计算合并分数。

2. BPE 算法流程:

(1)计算初始词表:通过训练语料获得或者最初的英文种26个字母加上各种符号以及常见中文字符,这些作为初始词表。
(2)构建频率统计:统计所有子词单元对在文本中的出现频率。
(3)合并频率最高的子词对:选择出现频率最高的子词对,将它们合并成一个新的子词单元,并更新词汇表。
(4)重复合并步骤:不断重复步骤2和步骤3,直到达到预定的词汇表大小、合并次数。
(5)分词:使用训练得到的词汇表对文本进行分词。

3. 算法源码实现Demo

import re
from collections import defaultdictclass BPE:def __init__(self, vocab_size=100):self.vocab_size = vocab_sizeself.vocab = {}       # word -> frequencyself.merges = []      # list of mergesself.bpe_ranks = {}   # pair -> rank# ---------- 构建初始词表 ----------def build_vocab(self, corpus):"""corpus: list[str],输入语料英文: 用空格分词中文: 逐字处理"""vocab = defaultdict(int)for line in corpus:words = line.strip().split()for word in words:chars = list(word) + ["</w>"]   # 加上词边界vocab[tuple(chars)] += 1self.vocab = dict(vocab)# ---------- 统计 pair ----------def get_stats(self):"""统计 pair 的频率"""pairs = defaultdict(int)for word, freq in self.vocab.items():for i in range(len(word)-1):pairs[(word[i], word[i+1])] += freqreturn pairs# ---------- 合并 ----------def merge_vocab(self, pair):"""执行一次合并"""new_vocab = {}bigram = re.escape(" ".join(pair))pattern = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')for word, freq in self.vocab.items():word_str = " ".join(word)new_word = tuple(pattern.sub("".join(pair), word_str).split())new_vocab[new_word] = freqself.vocab = new_vocab# ---------- 训练 ----------def train(self, save_merges="merges.txt", save_vocab="vocab.txt"):# 初始 alphabet 大小alphabet = set(ch for word in self.vocab for ch in word)num_merges = self.vocab_size - len(alphabet)print(f"初始alphabet大小={len(alphabet)},目标vocab_size={self.vocab_size},合并次数≈{num_merges}")for i in range(num_merges):pairs = self.get_stats()if not pairs:breakbest = max(pairs, key=pairs.get)self.merges.append(best)self.merge_vocab(best)# 构建 bpe_ranksself.bpe_ranks = dict(zip(self.merges, range(len(self.merges))))print(f"self.bpe_ranks:{self.bpe_ranks}")# 保存 mergeswith open(save_merges, "w", encoding="utf-8") as f:for a, b in self.merges:f.write(f"{a} {b}\n")# 保存 vocabvocab_tokens = set()for word in self.vocab:for token in word:vocab_tokens.add(token)with open(save_vocab, "w", encoding="utf-8") as f:for token in sorted(vocab_tokens):f.write(token + "\n")print(f"✅ merges 保存到 {save_merges}, vocab 保存到 {save_vocab}")# ---------- 推理 ----------def get_pairs(self, word):"""获取当前词的所有pair"""pairs = set()prev_char = word[0]for char in word[1:]:pairs.add((prev_char, char))prev_char = charreturn pairsdef encode_word(self, word):"""BPE 编码单个词"""word = tuple(list(word) + ["</w>"])pairs = self.get_pairs(word)if not pairs:return [word]while True:# 找到rank最小的pairbigram = min(pairs, key=lambda p: self.bpe_ranks.get(p, float("inf")))if bigram not in self.bpe_ranks:breaknew_word = []i = 0while i < len(word):if i < len(word)-1 and word[i] == bigram[0] and word[i+1] == bigram[1]:new_word.append(word[i] + word[i+1])i += 2else:new_word.append(word[i])i += 1word = tuple(new_word)if len(word) == 1:breakpairs = self.get_pairs(word)return list(word)def decode_word(self, tokens):"""还原单词"""word = "".join(tokens)if word.endswith("</w>"):word = word[:-4]return worddef encode_sentence(self, sentence):"""BPE 编码整句"""return [self.encode_word(w) for w in sentence.strip().split()]def decode_sentence(self, tokens_list):"""解码整句"""return " ".join(self.decode_word(toks) for toks in tokens_list)# ================== 示例 ==================
if __name__ == "__main__":corpus = ["deep learning is the future of ai","see my eyes first","see my dogs","you are the best","you are the fast","machine learning can be applied to natural language processing","深度学习是人工智能的未来","机器学习可以应用于自然语言处理","人工智能改变世界","学习深度神经网络在图像识别中表现优秀"]# 训练bpe = BPE(vocab_size=100)bpe.build_vocab(corpus)bpe.train("merges.txt", "vocab.txt")# 测试推理print("\n=== 单词测试 ===")for w in ["lowest", "newer", "人工智能", "深度学习"]:tokens = bpe.encode_word(w)print(f"{w} -> {tokens} -> {bpe.decode_word(tokens)}")print("\n=== 句子测试 ===")sentence = "lowest newer 人工智能深度学习"tokens_list = bpe.encode_sentence(sentence)print(tokens_list)print(bpe.decode_sentence(tokens_list))# === 单词测试 ===
# lowest -> ['l', 'o', 'w', 'e', 's', 't', '</w>'] -> lowest
# newer -> ['n', 'e', 'w', 'e', 'r', '</w>'] -> newer
# 人工智能 -> ['人工智能', '</w>'] -> 人工智能
# 深度学习 -> ['深度', '学习', '</w>'] -> 深度学习# === 句子测试 ===
# [['l', 'o', 'w', 'e', 's', 't', '</w>'], ['n', 'e', 'w', 'e', 'r', '</w>'], ['人工智能', '王', '赞', '深度', '学习', '</w>']]
# lowest newer 人工智能深度学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96694.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96694.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/96694.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS 伪类选择器

伪类选择器&#xff08;pseudo-class selector&#xff09;是一种用于选择HTML元素特定状态或特征的关键字&#xff0c;它允许开发者基于文档树之外的信息&#xff08;如用户交互、元素位置或状态变化&#xff09;来选择元素并应用样式。伪类选择器以冒号(:)开头&#xff0c;附…

Electron 新特性:2025 版本更新解读

引言&#xff1a;Electron 新特性在 2025 版本更新中的解读核心价值与必要性 在 Electron 框架的持续演进中&#xff0c;新特性的引入是推动桌面开发创新的核心动力&#xff0c;特别是 2025 年的版本更新&#xff0c;更是 Electron 项目从成熟生态到前沿技术的跃进之钥。它不仅…

MyBatis从入门到面试:掌握持久层框架的精髓

MyBatis从入门到面试&#xff1a;掌握持久层框架的精髓 前言 在Java企业级应用开发中&#xff0c;持久层框架的选择至关重要。MyBatis作为一款优秀的半自动化ORM框架&#xff0c;以其灵活的SQL定制能力和良好的性能表现&#xff0c;成为了众多开发者的首选。本文将带你从MyBa…

5.Three.js 学习(基础+实践)

Three.js 是 “WebGL 的封装库”&#xff0c;帮你屏蔽了底层的着色器 / 缓冲区细节&#xff0c;专注于 “3D 场景搭建”&#xff0c;开发效率高&#xff0c;是通用 3D 开发的首选。他的核心是 “场景 - 相机 - 渲染器” 的联动逻辑&#xff0c;先掌握基础组件&#xff0c;再学进…

消火栓设备工程量计算 -【图形识别】秒计量

消火栓设备工程量计算 -【图形识别】秒计量 消防系统的消火栓设备水枪、水带和消火栓组成&#xff0c;根据清单定额规则计算消火栓设备工程量。通过CAD快速看图的图形识别框选图纸就能自动数出消火栓数量&#xff0c;省时又准确&#xff0c;是工程人做消防算量的好帮手。 一、…

Docker 与 VSCode 远程容器连接问题深度排查与解决指南

Docker 与 VSCode 远程容器连接问题深度排查与解决指南 引言 Visual Studio Code 的 Remote - Containers 扩展极大地提升了开发体验&#xff0c;它将开发环境容器化&#xff0c;保证了环境的一致性&#xff0c;并允许开发者像在本地一样在容器内进行编码、调试和运行。然而&…

爱图表:镝数科技推出的智能数据可视化平台

本文转载自&#xff1a;https://www.hello123.com/aitubiao ** 一、✨ AI 图表&#xff1a;智能数据可视化好帮手 爱图表是镝数科技旗下的一款智能数据可视化工具&#xff0c;它能让复杂的数字和报表变得直观又好懂。接入了先进的DeepSeek 系列 AI 模型&#xff0c;它不仅会做…

ENVI系列教程(四)——图像几何校正

目录 1 概述 1.1 控制点选择方式 1.2 几何校正模型 1.3 控制点的预测与误差计算 2 详细操作步骤 2.1 扫描地形图的几何校正 2.1.1 第一步:打开并显示图像文件 2.1.2 第二步:启动几何校正模块 2.2 Landsat5 影像几何校正 2.2.1 第一步:打开并显示图像文件 2.2.2 第…

STM32-FreeRTOS操作系统-消息队列

引言在嵌入式开发领域&#xff0c;STM32与FreeRTOS的结合应用极为广泛。本文将探讨如何在STM32上使用FreeRTOS实现消息队列功能&#xff0c;助力高效任务通信与系统协作。消息队列定义消息队列是一种在 FreeRTOS 中用于任务间通信的机制。它允许任务将消息发送到队列中&#xf…

【开题答辩全过程】以 C语言程序设计课程网站为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

手机上有哪些比较好用的待办事项提醒工具

在快节奏的现代工作中&#xff0c;我们每天都要面对大量的任务与事务。从项目截止日期、客户会议&#xff0c;到日常的工作安排&#xff0c;琐碎的事项容易让人顾此失彼。 手机待办事项工具早已突破传统“记事本”的局限&#xff0c;成为移动办公场景下的效率核心。它们通过任务…

Mysql数据库事务全解析:概念、操作与隔离级别

MySQL系列 文章目录MySQL系列一、什么是事务1.1事务的核心概念1.2、 事务的四大属性&#xff08;ACID&#xff09;1.2.1 原子性&#xff08;Atomicity&#xff09;1.2.2 一致性&#xff08;Consistency&#xff09;1.2.3 隔离性&#xff08;Isolation&#xff09;1.2.4 持久性&…

【MCU EEPROM开发教程】

简单来说把eeprom芯片当成一个传感器来使用&#xff0c;通过IIC/SPI等协议对芯片进行读写操作&#xff0c;具体的读写操作涉及到一些算法—怎么样读写更加快速&#xff0c;以及一些异常错误处理。 应用场景&#xff1a; 对于一些掉电也不能丢失的数据要存在eeprom/flash中&…

Docker将镜像搬移到其他服务上的方法

导出/加载镜像&#xff08;保留分层、标签&#xff09;和导出/导入容器快照&#xff08;仅文件系统&#xff0c;丢失镜像历史与标签&#xff09;。 一、把镜像打包带走&#xff08;推荐&#xff09; 适合把一个或多个镜像搬到离线/内网机器&#xff0c;保留分层与标签。 在源服…

Ubuntu 系统安装 Miniconda 完整方法与注意事项

一、完整安装步骤 1. 下载 Miniconda 安装包 Miniconda 安装包为 .sh 格式脚本,下载途径分两种: 方式 1:浏览器下载(适合新手) 访问 Miniconda 官方下载页,选择对应系统版本(Ubuntu 选 Miniconda3-latest-Linux-x86_64.sh),默认保存到用户目录的 ~/Downloads 文件夹…

【后端】数据库四大范式详细解析

梳理一下 MySQL&#xff08;或关系型数据库&#xff09;中的第一、二、三、四范式&#xff0c;这是数据库设计中非常重要的规范化理论。1️⃣ 第一范式 (1NF&#xff1a;First Normal Form)定义&#xff1a;字段具有原子性&#xff0c;不可再分。数据表中每一列都必须是不可分割…

HarmonyOS后台任务调度:JobScheduler与WorkManager实战指南

本文将深入探讨HarmonyOS 5&#xff08;API 12&#xff09;中的后台任务调度机制&#xff0c;重点讲解JobScheduler和WorkManager的使用方法、适用场景及最佳实践&#xff0c;帮助开发者实现高效、智能的后台任务管理。 1. 后台任务调度概述 HarmonyOS提供了两种主要的后台任务…

Prompt工程实践

你在写prompt时候&#xff0c;是不是总觉得大模型它不听话。要么答非所问、要么一堆废话。扒开思考过程仔细阅读时而觉得它聪明绝顶&#xff0c;时而又觉得它愚蠢至极。明明已经对了怎么又推理到错的地方去了&#xff0c;明明在提示词中提醒过了不要这么思考它怎么就瞎想了。这…

基于springboot的毕业旅游一站式定制系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实…

输入1.8V~5.5V 输出28V DCDC升压芯片TLV61046A

今天来一款TI的升压芯片TLV61046A。输入电压范围1.8V~5.5V。最高可以输出28V。开关电流980mA&#xff0c;那具体能输出多大的电流就得看输入输出的电压了。以上面的输入3.6V输出12V为例&#xff0c;效率是85%&#xff0c;那最高可以输出的电流就差不多只有200mA左右。封装也是非…