MiniMind学习笔记(零)--基础概念

一,分词器(Tokenizer)

分词器的作用是切分用户输入。

比如用户输入 "今天天气怎么样",分词器可能会将其分成数组:"今", "天", "天", "气", "怎", "么", "样"。根据词汇表不同,不同的模型可能有不同的切法。

注意,分词器切分存在子词的概念,比如:"playing"切成"play","ing"

二,词汇表

词汇表是分词器通过扫描海量文本(语料库)训练出来的一个映射表,里面记录了从Token到id的映射,每个token都能在这里找到唯一的id。词汇表一般是固定的,即使模型经过训练,词汇表也不会改动。

不同的模型使用的词汇表不同,格式也不同:

1,BERT(基于WordPiece):简单的文本文件,每个Token占一行。

2,GPT系列(基于BPE):JSON格式的文件,例如 {"the": 55, "cat": 656, ...}

3,SentencePiece:通常输出两个文件,一个 .model(二进制模型文件)和一个 .vocab(可读的词汇表文件)

三,Token和TokenId

分词器切分用户输入后的每个词都是一个Token,每个Token都能在词汇表里找到一个唯一的TokenId。

大语言模型输出的回复文案,本质上也是一个一个Token组合起来的。很多大语言模型会按输入+输出的Token数量来计费。

TokenId是从0开始的整数,最大值是词汇表中单词数量-1。

四,嵌入向量和嵌入矩阵

嵌入向量是一个浮点数数组(比如 0.12, -0.56, ..., 0.78),它是Token语义的数值化表示。数组的每个元素往往没有具体含义,它们是组合在一起表达语义的。

嵌入向量在不同的模型中的长度(即数组中元素个数,d_model)不同,比如BERT-base和GPT-2 small中都是768,BERT-large和GPT-2 medium都是1024。

嵌入向量长度越长,代表携带的信息越丰富,但计算时耗时越长,每个模型的嵌入向量长度都是设计者平衡利弊之后的选择。

每个TokenId对应的嵌入向量,组合形成嵌入矩阵,矩阵行号就是TokenId,用TokenId作为行号可以快速找到Token对应的嵌入向量。

embedding_vector = embedding_matrixtoken_id # embedding_matrix是嵌入矩阵,embedding_vector是得到的嵌入向量。

所以,矩阵行数就是词汇表大小(vocab_size),列数就是嵌入向量的长度(d_model)。嵌入矩阵在训练结束后就不变了,每次训练后其中的值会发生改变。

另外,两个TokenId数字接近,不代表两个Token语义接近,Token语义是否接近由嵌入向量决定。

五,键矩阵、查询矩阵、值矩阵

直接使用嵌入矩阵里的嵌入向量去和其他词交互不够灵活,所以嵌入向量进行线性变换后得到得到了键向量、查询向量、值向量。

就像嵌入向量组合成嵌入矩阵一样,键向量、查询向量、值向量分别组合后形成了键矩阵、查询矩阵、值矩阵。

所谓KQV自注意力机制,就是由键矩阵K、查询矩阵Q、值矩阵V为基础进行计算的一种机制。

也有文章中的KQV分别代表键向量、查询向量、值向量,本质上是一回事。

1,键矩阵K,与Q计算注意力权重,决定被关注的程度。

2,查询矩阵Q,与K计算注意力权重,决定关注哪里。

3,值矩阵V,提供最终要被加权求和的内容。

六,嵌入矩阵的线性变换

定义三个线性变换矩阵,分别给嵌入矩阵做乘法,得到键矩阵、查询矩阵、值矩阵。这个过程就是矩阵的线性变换。

线性变换矩阵的形状:(d_model, d_k),即行数=嵌入向量长度,宽度d_k可以自己定义为正整数,Transformer的论文中设定:d_k=嵌入向量长度/多头并行数,Transformer这么设计是为了在多头并行时,所有头的维度和等于d_model,方便后面做残差连接。

小结,值矩阵生成过程

用户输入文字后,生成键矩阵、查询矩阵、值矩阵的具体步骤是:

步骤1:用户输入原始字符串

python 复制代码
user_input = "今天天气怎么样"

步骤2:分词(tokenization)

python 复制代码
# 切分用户输入得到Token列表,可能是这样的:["今", "天", "天", "气", "怎", "么", "样"]
tokens = tokenizer.tokenize(user_input)   

# 每个Token查询TokenId,TokenId列表可能是这样的:[101, 234, 234, 345, ...]
input_ids = tokenizer.convert_tokens_to_ids(tokens)  

步骤3:生成嵌入矩阵

python 复制代码
# 读取总嵌入矩阵,词汇表包含5000个Token,所以总嵌入矩阵有5000行,自定义嵌入向量宽度=768
embedding_layer = nn.Embedding(vocab_size=5000, embedding_dim=768)   

# 从总嵌入矩阵中查询本次7个Token的嵌入向量,组成新的嵌入矩阵X,形状是(7, 768),即7行768列
X = embedding_layer(torch.tensor(input_ids))  

步骤4:线性变换生成值矩阵

下面的代码生成了值矩阵,另外键矩阵、查询矩阵生成方式相同。

python 复制代码
# 初始化可训练的权重矩阵,d_k=64
W_V = nn.Linear(in_features=768, out_features=64, bias=False)   

# 线性变换得到值矩阵V,形状是(7, 64),即7行64列。
V = W_V(X)   
相关推荐
ZHW_AI课题组11 分钟前
腾讯云调用IP定位
人工智能·python·机器学习
Wch1G0z8A23 分钟前
Google 开源了啥,让 AI Agent 碰数据库不再是定时炸弹
数据库·人工智能·开源
武子康25 分钟前
调查研究-151 Slack vs Jira:区别、使用指南与团队选择方法
人工智能·科技·深度学习·ai·职场和发展·jira·slack
米小虾27 分钟前
黄仁勋GTC 2026宣告Agent AI时代:从生成式到代理式的范式转移
人工智能·aigc·agent
IT_陈寒28 分钟前
Python闭包里藏的这个坑,差点让我加班到凌晨
前端·人工智能·后端
IT_陈寒28 分钟前
Java注解空指针?这个坑我踩得莫名其妙
前端·人工智能·后端
暴躁小师兄数据学院39 分钟前
【AI大数据工程师特训笔记】第14讲:Linux操作系统与shell脚本
大数据·人工智能·笔记
8Qi844 分钟前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·
tedcloud1231 小时前
cc-switch评测:多AI Coding Agent管理工具详解
数据库·人工智能·sql·学习·自动化