当前位置: 首页 > news >正文

【多模态学习】QA2:Tokenize和Embedding?BPE算法?交叉熵损失函数?

Q&A

    • Tokenize和Embedding生成分别指代的是什么步骤?
      • 1. Tokenize:输入序列预处理
        • (1)文本分词(Tokenization)
        • (2)Token到ID的映射
        • (3)序列填充/截断(Padding/Truncation)
      • 2. Embedding生成
        • (1)Token Embedding(词嵌入)
        • (2)位置编码(Positional Encoding)
        • (3)Segment Embedding(可选)
        • (4)Embedding相加与归一化
        • (5)输出结果
    • Tokenize中提到的BPE算法具体是什么?
      • 1. 是什么?
      • 2. 为什么需要?(解决的问题)
      • 3. 算法步骤(训练阶段)
      • 4. 编码(推理阶段)
      • 5. 优势与劣势
      • 6. 变体与相关算法
      • 7. 总结
    • LLM最常见的损失函数是交叉熵损失函数吗?具体是什么?
      • 1. 它在计算什么?
      • 2. 数学公式与计算
      • 3. 为什么交叉熵是LLM的理想选择?
      • 4. 在LLM训练中的具体应用:因果语言建模
      • 5. 总结:Cross-Entropy in a Nutshell

Tokenize和Embedding生成分别指代的是什么步骤?

1. Tokenize:输入序列预处理

(1)文本分词(Tokenization)
  • 目的:将原始文本拆分为模型可处理的离散单元(Token)。
  • 方法
    • 使用预定义的词表(如BERT的WordPiece、GPT的Byte-Pair Encoding)进行分词。
    • 示例:输入句子 "Hello, world!" → Tokens ["Hello", ",", "world", "!"]
  • 特殊Token添加
    • 添加任务相关的控制Token(如[CLS][SEP]用于BERT的分类或句子分隔)。
    • 可能包含起始符<s>、结束符</s>等。
(2)Token到ID的映射
  • 根据词表将Token转换为对应的整数ID。
    • 示例:假设词表中"Hello"=5","=3,则映射为 [5, 3, ...]
(3)序列填充/截断(Padding/Truncation)
  • 统一序列长度(如512):
    • 短序列:填充[PAD](通常ID=0)。
    • 长序列:截断到最大长度。

2. Embedding生成

(1)Token Embedding(词嵌入)
  • 查找表(Lookup Table)
    • 通过嵌入矩阵(Embedding Matrix)将每个Token ID转换为固定维度的向量。
    • 矩阵维度:[词表大小V, 隐藏维度d_model](如[50257, 768])。
    • 示例:ID=5 → 查找矩阵第5行,得到向量 [0.2, -0.5, ..., 0.7](维度=d_model)。
(2)位置编码(Positional Encoding)
  • 目的:为序列中的每个位置注入顺序信息。
  • 方法
    • 绝对位置编码:使用正弦/余弦函数(原始Transformer)或可学习的位置嵌入(如BERT)。
    • 公式(正弦版本):
      PE(pos,2i)=sin⁡(pos/100002i/dmodel)PE(pos,2i+1)=cos⁡(pos/100002i/dmodel)PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d_{model}}) \\ PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)
    • 相对位置编码:某些模型(如T5)使用更复杂的位置表示。
(3)Segment Embedding(可选)
  • 用于区分多个输入片段(如句子对任务)。
    • 示例:BERT中[SEP]分隔的句子A/B分别用Embedding E_AE_B标记。
(4)Embedding相加与归一化
  • 相加:将Token Embedding、Positional Encoding、Segment Embedding逐元素相加。
    • 公式:Final_Embedding = Token_Embed + Position_Embed + Segment_Embed
  • 层归一化(LayerNorm):某些模型(如BERT)在Embedding后应用归一化。
(5)输出结果
  • 最终得到形状为 [序列长度, d_model] 的Embedding矩阵,可直接输入到Transformer的编码器层。
    • 示例:输入序列长度=10,d_model=768 → 输出矩阵形状 [10, 768]

Tokenize中提到的BPE算法具体是什么?

BPE算法是一种非常经典且广泛使用的子词分割(Subword Tokenization)算法,几乎是当前所有大型语言模型(如GPT、BERT、LLaMA)的标配预处理步骤。

1. 是什么?

  • 全称:Byte Pair Encoding(字节对编码)
  • 核心思想迭代地合并最频繁出现的相邻字节对(或字符对),从而将单词分解为更常见的、可管理的子词单元。
  • 目标:在“字符级”和“单词级”之间找到一个平衡点,解决自然语言处理中的未登录词(OOV, Out-Of-Vocabulary) 问题。

2. 为什么需要?(解决的问题)

  • 词表过大:如果使用单词级词表,模型需要处理数十万甚至上百万个单词,其中很多是长尾词(出现次数极少),这会导致计算和存储的低效。
  • 未登录词(OOV)问题:在测试阶段遇到训练时没见过的单词时,模型无法处理。例如,训练时见过“looked”和“looking”,但没见过“looker”,单词级模型就会失败。
  • 数据稀疏性:罕见词由于缺乏足够的上下文,难以学习到好的表示。

BPE的解决方案:通过将未知的、复杂的单词分解为已知的、简单的子词(如词根、前缀、后缀),模型就能理解和生成它们。

3. 算法步骤(训练阶段)

BPE训练的目的是从一个初始词表构建一个最终的子词词表。其过程是一个贪婪的迭代合并过程:

  1. 初始化

    • 将文本中所有单词拆分为字符(bytes) 序列,并在每个单词末尾添加一个特殊的结束符(如 </w>)以标记单词边界。
    • 初始词表就是所有字符加上结束符。
    • 统计所有单词中每个字符对的频率。

    示例:假设语料库很小:“low lower newest widest”*

    • 初始状态(添加 </w>):
      {'l o w </w>': 2, 'n e w e s t </w>': 1, 'w i d e s t </w>': 1}
    • 初始词表:{'l', 'o', 'w', '</w>', 'n', 'e', 's', 't', 'i', 'd'}
  2. 迭代合并

    • 找出频率最高的相邻字节对(bigram)。
    • 将这个字节对合并成一个新的“符号”(symbol),并加入到词表中。
    • 更新语料库中所有出现该字节对的地方,用新的合并符号替换它们。
    • 重复此过程,直到达到预定的合并次数(即最终词表大小)。

    接上例

    • 第1轮:最高频对是 es(在"newest"和"widest"中各出现1次,但注意"low"和"lower"中没有)。合并 e s -> es。更新语料:
      {'l o w </w>': 2, 'n e w es t </w>': 1, 'w i d es t </w>': 1}
      词表新增:es
    • 第2轮:最高频对是 est(出现了2次)。合并 es t -> est。更新语料:
      {'l o w </w>': 2, 'n e w est </w>': 1, 'w i d est </w>': 1}
      词表新增:est
    • 第3轮:最高频对是 lo(在"low"和"lower"中出现了2次)。合并 l o -> lo。更新语料:
      {'lo w </w>': 2, 'n e w est </w>': 1, 'w i d est </w>': 1}
      词表新增:lo
    • …(继续合并,比如下一步可能合并 low -> low
  3. 停止:当达到了预设的合并操作次数(例如,10,000次)后停止。最终得到一个包含所有字符和所有合并后的子词的词表

4. 编码(推理阶段)

如何用训练好的BPE词表对一个新单词进行分词?

  1. 将新单词拆分为字符序列,并加上结束符 </w>
  2. 从左到右,贪婪地寻找词表中存在的最长可能子词
  3. 不断迭代,直到整个单词被分解为词表中的子词。

示例:假设我们的最终词表包含了 low, er, </w>, est, new 等。

  • 对未知词 lower 进行编码:
    • 初始:l o w e r </w>
    • 最长匹配:词表中有 low,所以匹配 -> low e r </w>
    • 下一步:e 不在词表中,但 er 在 -> low er </w>
    • 结果:["low", "er"]

5. 优势与劣势

优势劣势
1. 有效解决OOV问题:通过子词组合,几乎可以表示任何新词。1. 编码不唯一:一个单词有时可能有多种分割方式(尽管贪婪算法通常能保证唯一性)。
2. 极大的压缩词表:用较小的子词词表(典型值3万-10万)即可表示极大的词汇空间。2. 可能产生反直觉分割:例如,“asked”可能被分割为 asked,这虽然语义上合理,但破坏了原始单词形态。
3. 更好的泛化能力:共享子词表示(如“##ing”)有助于模型学习词形变化和构词法。3. 增加序列长度:一个单词可能被分成多个token,增加了模型需要处理的序列长度。
4. 多语言友好:不依赖空格,对德语(复合词)、中文(字符)、阿拉伯语(黏着语)等都有效。4. 解码麻烦:生成文本后,需要将子词拼接回完整的单词。

6. 变体与相关算法

  • WordPiece:被BERT采用。与BPE类似,但合并策略不同:BPE合并最高频的对,而WordPiece合并能最大程度提升语言模型概率的对。
  • SentencePiece:将文本直接视为原始字节流,无需预处理(如空格分词),尤其适合处理多种语言混合且没有空格的文本(如中文、日文)。
  • Unigram LM:与BPE方向相反,从一个大的种子词表开始,逐步移除最不重要的子词,直到达到目标词表大小。

7. 总结

BPE是一种巧妙的数据压缩技术在NLP中的应用。它通过统计迭代合并,找到了词汇表示的最佳平衡点,使其成为支撑现代大语言模型处理海量词汇的基石技术。理解了BPE,就理解了为什么GPT等模型能如此流畅地生成和理解它们从未“见过”的单词。

LLM最常见的损失函数是交叉熵损失函数吗?具体是什么?

是的,交叉熵(Cross-Entropy) 是大型语言模型(LLM)训练中最核心、最常用的损失函数。它直接衡量的是模型预测的概率分布与真实的概率分布(即目标答案)之间的“距离”。

1. 它在计算什么?

想象一下LLM的核心任务:预测下一个词

  • 输入:“The capital of France is”
  • 期望输出:“Paris”
  • 模型输出:一个在整个词表上的概率分布。例如,它可能给"Paris"分配了0.85的概率,给"Lyon"分配了0.1的概率,给"Rome"分配了0.02的概率,等等。

交叉熵损失的目标是:惩罚模型为错误词分配的高概率和为目标词分配的低概率。

  • 如果模型对"Paris"的预测概率是 1.0,损失为 0(完美)。
  • 如果模型对"Paris"的预测概率是 0.1,而给"Rome"分配了0.9,损失会 非常大

核心思想:损失值越高,说明模型的预测分布与真实分布相差越远。

2. 数学公式与计算

对于一个具体的例子(一个token),交叉熵损失的公式为:

L=−∑i=1Vyilog⁡(pi)L = -\sum_{i=1}^{V} y_i \log(p_i)L=i=1Vyilog(pi)

其中:

  • VVV 是词表的大小。
  • yiy_iyi 是真实标签的 one-hot 编码。只有目标词对应的位置是1,其他全是0。
    • 例如,如果目标词是"Paris"(假设它在词表中的索引是第12345位),那么 y12345=1y_{12345} = 1y12345=1,其余 yi=0y_i = 0yi=0
  • pip_ipi 是模型预测的整个词表上第 iii 个词的概率。

由于真实分布 yyy 是one-hot形式,这个求和公式实际上简化为了只计算目标词那一项的负对数概率

L=−log⁡(ptarget)L = -\log(p_{\text{target}})L=log(ptarget)

计算示例

  • 如果模型预测目标词"Paris"的概率 ptarget=0.85p_{\text{target}} = 0.85ptarget=0.85,则损失 L=−log⁡(0.85)≈0.16L = -\log(0.85) \approx 0.16L=log(0.85)0.16
  • 如果模型预测的概率很低,比如 ptarget=0.1p_{\text{target}} = 0.1ptarget=0.1,则损失 L=−log⁡(0.1)≈2.3L = -\log(0.1) \approx 2.3L=log(0.1)2.3

在实际训练中,我们计算一个批次(batch)中所有序列的所有token的损失,然后求平均,称为 平均交叉熵损失

3. 为什么交叉熵是LLM的理想选择?

  1. 与最大似然估计(MLE)完美契合
    LLM的训练本质是最大似然估计——寻找能使训练数据出现的概率最大的模型参数。最大化似然概率等价于最小化负对数似然损失,而交叉熵损失正是负对数似然损失在分类问题中的形式。

  2. 梯度行为友好

    • 交叉熵损失的梯度计算非常干净和高效。对于目标类别,梯度为 (pi−1)(p_i - 1)(pi1),对于非目标类别,梯度为 pip_ipi
    • 这意味着当模型预测错误时(ptargetp_{\text{target}}ptarget 很小),梯度幅度会很大,从而推动模型参数进行快速修正。当预测接近正确时,梯度变小,更新放缓,训练趋于稳定。
  3. 衡量分布差异
    交叉熵源于信息论,它衡量的是用模型分布 PPP 来编码真实分布 QQQ 所需的额外比特数。我们希望通过训练,这个“额外开销”降为0,即两个分布完全一致。

  4. 实践有效性
    在大量的实践中,使用交叉熵损失训练的模型收敛稳定,并能产生出色的结果,这使其成为了一个可靠的标准。

4. 在LLM训练中的具体应用:因果语言建模

在GPT等自回归模型中,训练过程如下:

  1. 输入一个序列:"The capital of France is Paris"
  2. 模型的任务是预测下一个token。它的输入和标签分别是:
    • 输入 (Input): "The capital of France is"
    • 标签 (Target): "capital of France is Paris" (即输入向右偏移一位)
  3. 模型会为序列中的每一个位置(除了第一个)计算一个预测分布。
  4. 计算每个位置预测的交叉熵损失(将“前一个词”的预测与“当前词”的标签对比),然后对所有位置的损失求平均。

这个过程确保了模型学会根据上文来预测下一个词。

5. 总结:Cross-Entropy in a Nutshell

方面解释
是什么衡量模型预测概率分布与真实分布之间差异的函数。
在LLM中的作用作为训练阶段的损失函数,指导模型参数更新的方向。
核心计算L=−log⁡(ptarget)L = -\log(p_{\text{target}})L=log(ptarget),即目标词预测概率的负对数。
为何有效与最大似然估计等价,梯度性质优秀,能有效推动模型学习正确的预测。
别名因其普遍性,常直接被称为语言建模损失(Language Modeling Loss)

可以说,没有交叉熵损失,就没有现代LLM的成功。它是连接模型输出与学习目标的桥梁,是驱动LLM从海量文本中学习知识的引擎


文章转载自:

http://2Krc818h.jzsgn.cn
http://RxTxnYKs.jzsgn.cn
http://q4MTBVxs.jzsgn.cn
http://SkginHxe.jzsgn.cn
http://Zi3HL6U6.jzsgn.cn
http://90gJXxdi.jzsgn.cn
http://cWtjoJHV.jzsgn.cn
http://Xhr1nnVl.jzsgn.cn
http://jy45TBCz.jzsgn.cn
http://gVpiYJRz.jzsgn.cn
http://uqdjfQoW.jzsgn.cn
http://JS7SnQeZ.jzsgn.cn
http://b6Ci6kLP.jzsgn.cn
http://v0K0qaUe.jzsgn.cn
http://LBBxfxsj.jzsgn.cn
http://9ZaphzYB.jzsgn.cn
http://dPVAxS77.jzsgn.cn
http://rTc7CKPV.jzsgn.cn
http://zX18lW6q.jzsgn.cn
http://RIKOS4LS.jzsgn.cn
http://jWJbIRmU.jzsgn.cn
http://ykpTpxE5.jzsgn.cn
http://6QWtQucA.jzsgn.cn
http://uK8fUNlw.jzsgn.cn
http://KEnW6f6E.jzsgn.cn
http://2R1yKEHt.jzsgn.cn
http://fnWU8UuP.jzsgn.cn
http://rosBJgDG.jzsgn.cn
http://9TUSKMmi.jzsgn.cn
http://tqVzJoV9.jzsgn.cn
http://www.dtcms.com/a/372377.html

相关文章:

  • ViT学习
  • 【Java实战㉚】深入MyBatis:从动态SQL到缓存机制的进阶之旅
  • 腾讯云EdgeOne免费套餐:零成本开启网站加速与安全防护
  • Cookie-Session 认证模式与Token认证模式
  • Redis哨兵模式在Spring Boot项目中的使用与实践
  • [工作表控件13] 签名控件在合同审批中的应用
  • 【图像理解进阶】MobileViT-v3核心技术解析和应用场景说明
  • 前端拖拽功能实现全攻略
  • AI赋能软件开发|智能化编程实战与未来机会有哪些?
  • 335章:使用Scrapy框架构建分布式爬虫
  • Docker|“ssh: connect to host xxx.xxx.xxx.xxx port 8000: Connection refused“问题解决
  • OneCode 可视化揭秘系列(三):AI MCP驱动的智能工作流逻辑编排
  • 数据结构深度解析:二叉树的基本原理
  • Supabase02-速通
  • LLM学习:大模型基础——视觉大模型以及autodl使用
  • 嵌入式Secure Boot安全启动详解
  • 【倍增】P3901 数列找不同|普及+
  • 数据结构:堆
  • 继续优化基于树状数组的cuda前缀和
  • 数组常见算法
  • 数仓建模理论
  • 致远A8V5 9.0授权文件
  • 【New Phytologist】​​单细胞多组学揭示根毛对盐胁迫的特异性响应文献分享
  • MyBatis 拦截器让搞定监控、脱敏和权限控制
  • 20250907-0101:LangChain 核心价值补充
  • 论CMD、.NET、PowerShell、cmdlet四者关系
  • 从IFA展会看MOVA的“全维进阶”如何重新定义智能家居边界
  • SpringBoot 数据脱敏实战: 构建企业级敏感信息保护体系
  • 公链分析报告 - 模块化区块链1
  • 20250907-01:理解 LangChain 是什么 为什么诞生