LLM基础2_语言模型如何文本编码

基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn

字节对编码(BPE)

上一篇博文说到

为什么GPT模型不需要[PAD][UNK]

GPT使用更先进的字节对编码(BPE),总能将词语拆分成已知子词

为什么需要BPE?

  • 简单分词器的问题:遇到新词就卡住(如"Hello")

  • BPE的解决方案:把陌生词拆成已知的小零件

BPE如何工作?

就像拼乐高:

  1. 基础零件:先准备256个基础字符(a-z, A-Z, 标点等)

  2. 拼装训练:统计哪些字符组合常出现

  3. 创建新零件:把高频组合变成新"积木块"

# 使用GPT-2的BPE分词器
import tiktoken
tokenizer = tiktoken.get_encoding("gpt2")text = "Akwirw ier"  # 模型没见过的词
integers = tokenizer.encode(text)  # [33901, 86, 343, 86, 220, 959]# 查看每个部分的含义
for i in integers:print(f"{i} -> {tokenizer.decode([i])}")
# 33901 -> Ak
# 86 -> w
# 343 -> ir
# 86 -> w
# 220 -> (空格)
# 959 -> ier

举例:

陌生词BPE分解计算机理解
AkwirwAk + w + ir + w"Ak"是已知前缀,"w"是字母,"ir"是常见组合
someunknownPlacesome + unknown + Place拆成三个已知部分

滑动窗口 - 文本的"记忆训练法"

语言模型的核心任务:根据上文预测下一个词。比如:“白日依山_",语言模型会根据上文推测出下文可能是“尽”,“水”……等,最终经过对比,选取最可能的词填上,得到“白日依山尽”。

#用滑动窗口创建训练数据
文本:"I had a cat" → 分词后:[40, 367, 2885, 1464]# 滑动窗口(窗口大小=4)
输入(x)       目标(y)        训练内容
[40]        → [367]        看到"I"预测"had"
[40, 367]   → [2885]       看到"I had"预测"a"
[40,367,2885]→[1464]      看到"I had a"预测"cat"

 使用举例:

from torch.utils.data import Dataset
from transformers import GPT2Tokenizerclass GPTDatasetV1(Dataset):def __init__(self, txt, max_length=256, stride=128):    #stride控制相邻片段间的重叠长度self.tokenizer = GPT2Tokenizer.from_pretrained('gpt2')    #使用GPT-2原生分词器self.tokenizer.pad_token = self.tokenizer.eos_token    #用结束符代替填充符# 分词得到ID序列,自动添加特殊标记(默认添加<|endoftext|>),但不会添加BOS(开始符)token_ids = self.tokenizer.encode(txt)# 用滑动窗口创建多个训练片段self.examples = []for i in range(0, len(token_ids) - max_length, stride):input_ids = token_ids[i:i + max_length]target_ids = token_ids[i + 1:i + max_length + 1]self.examples.append((input_ids, target_ids))# 假设 token_ids = [1,2,3,4,5], max_length=3, stride=2# 窗口1:i=0 → input=[1,2,3], target=[2,3,4]# 窗口2:i=2 → input=[3,4,5], target=[4,5]def __len__(self):return len(self.examples)def __getitem__(self, idx):input_ids, target_ids = self.examples[idx]return input_ids, target_ids

i + max_length +1超过数组长度时,target_ids会自动截断(可能产生短序列)

优化方向建议:

  1. 动态填充:使用attention_mask区分真实token与填充
  2. 缓存机制:对大型文本文件进行分块处理
  3. 长度统计:添加样本长度分布分析功能
  4. 批处理优化:结合collate_fn处理变长序列

参数选择指南

  1. 短文本(<1k tokens):max_length=64-128stride=32-64
  2. 长文本(>10k tokens):max_length=512-1024stride=256-512
# 示例使用方式
text = "Self-explanatory knowledge, human intelligence, personal knowledge..."  # 你的长文本数据
dataset = GPTDatasetV1(text)# 获取第一个样本
input_seq, target_seq = dataset[0]

词元嵌入

之前的ID只是编号,没有含义。嵌入层给每个词从多个维度作向量表示

# 创建嵌入层(词汇表大小=6,向量维度=3)
embedding = torch.nn.Embedding(6, 3)# 查看权重矩阵
print(embedding.weight)
"""
tensor([[ 0.3374, -0.1778, -0.1690],  # ID=0的向量[ 0.9178,  1.5810,  1.3010],  # ID=1的向量...                           # 以此类推], requires_grad=True)         # 可学习!
"""

嵌入层的本质:

相当于高效版的"独热编码+矩阵乘法":

独热编码:[0,0,0,0,1] → 矩阵乘法 → [0.1, -0.5, 0.8]
嵌入层:直接取矩阵的第5行 → [0.1, -0.5, 0.8]

流程总结:原始文本->BPE分词->ID序列->滑动窗口->训练样本->嵌入层->词向量

单词位置编码

 为什么需要位置编码?

简单词嵌入的局限:

  • 词嵌入只表示词语含义,不包含位置信息

  • 模型会把所有词语当作无序集合处理

比如"猫追老鼠"和"老鼠追猫",虽然词语相同但意思完全相反!

 位置编码的解决方案

就像给教室座位编号:每个词语有"含义身份证"(词嵌入)->再加个"座位号"(位置编码)

词嵌入层实现

import torch
import torch.nn as nn# 定义词嵌入层
token_embedding = nn.Embedding(num_embeddings=50257, embedding_dim=256)#num_embeddings参数表示嵌入字典的大小
#embedding_dim参数控制输出向量的维度

位置嵌入层实现

# 定义位置嵌入层(假设序列最大长度为4)
pos_embedding = nn.Embedding(num_embeddings=4, embedding_dim=256)

生成位置编码向量

# 生成位置编号0-3的序列
position_ids = torch.arange(4)  # tensor([0, 1, 2, 3])# 获取位置向量(形状为[4, 256])
position_vectors = pos_embedding(position_ids)

组合词嵌入与位置嵌入

# 假设输入的token_ids形状为[batch_size, seq_len]
token_vectors = token_embedding(token_ids)
final_embeddings = token_vectors + position_vectors.unsqueeze(0)

#广播机制
position_vectors扩展为(batch_size, seq_len, embedding_dim),与token_vectors维度对齐  

假设参数:
batch_size = 4    #4个样本
seq_len = 16    #每个样本有16个tokens
embedding_dim = 512    #词嵌入为512维向量操作流程:
Token IDs形状      : (4, 16)
↓ 经过嵌入层
Token向量形状      : (4, 16, 512)
Position向量原始形状 : (16, 512)
↓ unsqueeze(0)
Position向量调整后  : (1, 16, 512)
↓ 广播相加
Final嵌入形状      : (4, 16, 512)
  • 位置嵌入通常需要扩展到与词嵌入相同的维度
  • 在Transformer架构中,位置嵌入可以是可学习的(如本例)或使用固定公式计算

 为什么用加法而不是拼接?

        维度一致:保持向量维度不变(256维)

        计算高效:加法比拼接更省资源

        信息融合:位置和语义自然融合

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

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

相关文章

监控升级:可视化如何让每一个细节 “说话”

你有没有遇到过这样的情况&#xff1f; 监控画面里明明有“异常”&#xff0c;但值班人员愣是没发现&#xff1b; 报警响起却不知道具体发生了什么&#xff0c;只能靠猜、靠翻录像&#xff1b; 出了事回看录像&#xff0c;才发现线索早就在眼前&#xff0c;只是没人注意到………

单片机bootloader(APP的自我复制)

文章目录 Bootloader 中 APP 的自我复制与启动机制解析一、为什么要进行自我复制?二、程序整体结构概述三、汇编启动代码分析重点解释:四、C 语言部分分析核心功能:五、start\_app 函数:手动启动指定 APP六、总结七、适用场景Bootloader 中 APP 的自我复制与启动机制解析 …

浏览器工作原理11 [#] this:从JavaScript执行上下文视角讲this

引用 《浏览器工作原理与实践》 在上篇文章中&#xff0c;我们讲了词法作用域、作用域链以及闭包&#xff0c;并在最后思考题中留了下面这样一段代码 var bar {myName:"time.geekbang.com",printName: function () {console.log(myName)} } function foo() {le…

【C语言】-递归

1、递归概念 递归&#xff08;Recursion&#xff09;是编程中一种重要的解决问题的方法&#xff0c;其核心思想是函数通过调用自身来解决规模更小的子问题&#xff0c;直到达到最小的、可以直接解决的基准情形&#xff08;Base Case&#xff09;。 核心&#xff1a;自己调用…

12.5Swing控件3Jpanel JOptionPane

JPanel JPanel是一个轻量级容器组件&#xff0c;用于组织和管理其他 GUI 组件。它继承自JComponent类&#xff0c;属于javax.swing包&#xff0c;可以容纳按钮、文本框、标签等控件 JPanel 默认使用的布局管理器是 FlowLayout&#xff0c;也可以嵌套其他面板&#xff0c;以便…

MIPI信号为什么不能进行长距离传输

1.关于MIPI信号传输 MIPI信号是不适合长距离传输的。 2.MIPI的信号摆幅小&#xff0c;抗干扰能力比较弱 MIPI信号的差分摆幅比较小&#xff0c;通常只有100mV~200mV,远远低于LVDS的350mV的摆幅 小摆幅信号在长线缆上传输的时候更容易被噪声淹没&#xff0c;信噪比下降&#xf…

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …

Windows11+VS2019配置Libigl-2.4.1

Windows11VS2019配置Libigl-2.4.1 由于课题需要&#xff0c;所以出一篇配置Libigl的博客&#xff0c;制作不易&#xff0c;请多多点赞 一、官网下载 官网&#xff1a;https://libigl.github.io/ GitHub下载地址&#xff1a;https://github.com/libigl/libigl 这里我们选择…

地球科学方向(Geoscience and Remote Sensing),1天见刊,当月可检索!

CSP科学出版社&#xff0c;旨在通过为研究人员提供最佳环境来发表、参考、阅读和引用他们的作品&#xff0c;从而为科学界服务。现已与科检易学术达成出版战略合作&#xff0c;现在联合共同出版高质量学术水平的期刊&#xff0c;为方便广大科研学者投稿方便&#xff0c;现已经建…

基于 Three.js 的 3D 模型快照生成方案

基于 Three.js 的 3D 模型快照生成方案 此方案通过 Three.js 渲染场景并异步生成图像数据&#xff0c;同时支持分辨率缩放和 Blob 格式输出&#xff0c;为模型预览、截图保存等需求提供完整解决方案。 问题分析&#xff1a; 使用html2canvas 生成的快照画布显示为空&#xff…

「Java基本语法」变量的使用

变量定义 变量是程序中存储数据的容器&#xff0c;用于保存可变的数据值。在Java中&#xff0c;变量必须先声明后使用&#xff0c;声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例&#xff1a;声明与初始化 public class VariableDemo {publi…

SpringCloud学习笔记-2

说明&#xff1a;来源于网络&#xff0c;如有侵权请联系我删除 1.提问&#xff1a;如果注册中心宕机&#xff0c;远程调用还能成功吗 答&#xff1a;当微服务发起请求时&#xff0c;会向注册中心请求所有的微服务地址&#xff0c;然后在向指定的微服务地址发起请求。在设计实…

Hac - NBh标准JSON协议使用说明文档

Hac - NBh 标准 JSON 协议使用说明文档 一、协议概述 Hac - NBh 标准 JSON 协议是专为物联网设备与服务器数据交互设计的通信协议。以 JSON 格式为基础,采用键值对(KV 值)组织数据,支持灵活选取数据项,通过 CBOR 格式实现高效传输,并利用 AES 128 加密保障数据安全。 …

k8s从入门到放弃之Service负载均衡

k8s从入门到放弃之Service负载均衡 在 Kubernetes (K8s) 中&#xff0c;Service 是一种抽象&#xff0c;它定义了一组逻辑上的 Pod 和访问它们的策略。Service 的主要目的是提供一种可靠的方式来访问一组具有相同标签&#xff08;Label&#xff09;的 Pod&#xff0c;即使这些…

【题解-洛谷】P10480 可达性统计

题目&#xff1a;P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图&#xff0c;分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M&#xff0c;接下来 M M M 行每行两个整数 x , y x,y x,y&#xff0c;表示从 …

SpringCloud2025+SpringBoot3.5.0+gateway+webflux子服务路由报503

文章目录 前言一、问题二、原因1.分析2.配置静态路由再试3.定位 总结 前言 本来昨天就应该也记录下&#xff0c;免得忘记的&#xff0c;但是有点晚了&#xff0c;酒没写&#xff0c;真的是被坑惨了。 当然这也是追求最新的代价&#xff0c;也是对新技术、老知识点的重温…

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…

RAG 文档解析难点1:多栏布局的 PDF 如何解析

写在前面 在构建检索增强生成 (Retrieval-Augmented Generation, RAG) 应用时,高质量的数据源是成功的基石。PDF 作为一种广泛使用的文档格式,承载着海量的知识。然而,许多 PDF 文档,特别是学术论文、期刊、杂志和一些报告,都采用了多栏布局 (multi-column layout)。 直…

全面掌握Pandas时间序列处理:从基础到实战

时间序列数据在金融分析、物联网、商业智能等领域无处不在。作为Python数据分析的核心库&#xff0c;Pandas提供了强大而全面的时间序列处理功能。本文将系统介绍Pandas时间序列处理的各个方面&#xff0c;从基础概念到高级应用&#xff0c;帮助您在实际工作中高效处理时间序列…

vscode 离线安装第三方库跳转库

我安装的是C/C的函数跳转 下载的离线库&#xff1a; 项目首页 - vscode代码自动补全跳转插件离线安装包:cpptools-win32.vsix是一款专为VSCode设计的离线安装插件&#xff0c;特别适合无法连接网络的电脑环境。通过安装此插件&#xff0c;您的VSCode将获得强大的代码自动跳转…