在自然语言处理领域,分词(Tokenization)和嵌入(Embedding)是大型语言模型(LLM)处理文本的两大核心技术。它们共同构成了机器理解人类语言的基石,将人类可读的文本转化为机器可处理的数学表示。
分词是将文本转换为模型可理解的离散符号的过程。想象一下,当你学习一门外语时,首先要学会将句子拆分成单词或词组。对于机器而言,这个过程同样重要,但更加复杂。
直接处理原始文本对计算机来说效率极低。分词的主要目的包括:
早期的分词方法主要有两种极端:
现代LLM普遍采用介于两者之间的子词切分(Subword-level)方案,它结合了两者的优点:
目前主流的大模型主要使用以下三种算法的变体:
BPE是一种基于统计的压缩算法,被GPT系列模型广泛采用。其核心思想是:
BPE的优势在于:
WordPiece是BERT等模型采用的分词算法,与BPE类似但合并依据不同:
这使得WordPiece:
SentencePiece采用自顶向下的策略:
其独特优势包括:
随着模型发展,分词技术也在不断演进:
分词将文本转换为ID序列后,嵌入层负责将这些离散符号映射到连续的向量空间,为模型提供丰富的语义表示。
嵌入过程可分为三个阶段:
嵌入层本质上是一个可学习的查找表:
现代大模型的嵌入维度通常在768到4096之间,远小于词表大小,实现了高效的维度压缩。
嵌入空间最神奇的特性是其几何关系反映语义关系:
嵌入可分为两种类型:
静态嵌入(如Word2Vec):
上下文嵌入(如BERT):
通过计算向量间的余弦相似度,可以:
使用t-SNE或UMAP等降维技术,可以将高维嵌入投影到2D/3D空间,直观展示:
TikToken是OpenAI开源的高性能分词库,特别适合处理GPT系列模型的文本。
python复制import tiktoken
# 获取编码器
enc = tiktoken.encoding_for_model("gpt-4")
# 编码文本
text = "Hello, world! 我爱大模型"
token_ids = enc.encode(text)
tokens = [enc.decode_single_token_bytes(tid) for tid in token_ids]
print(f"Token IDs: {token_ids}")
print(f"Tokens: {tokens}")
不同语言的Token化效率差异很大:
基于嵌入的语义搜索是RAG系统的核心组件。
python复制from sentence_transformers import SentenceTransformer, util
# 加载预训练模型
model = SentenceTransformer('all-MiniLM-L6-v2')
# 准备语料库
corpus = ["A man is eating food.",
"A man is eating a piece of bread.",
"The girl is carrying a baby."]
# 生成嵌入
corpus_embeddings = model.encode(corpus, convert_to_tensor=True)
# 处理查询
query = "Someone is having a meal"
query_embedding = model.encode(query, convert_to_tensor=True)
# 计算相似度
cos_scores = util.cos_sim(query_embedding, corpus_embeddings)[0]
# 排序结果
results = sorted(zip(cos_scores, corpus), key=lambda x: x[0], reverse=True)
for score, text in results:
print(f"{score:.4f}\t{text}")
可视化嵌入空间有助于理解模型的语义表示。
python复制from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
# 准备词汇
words = ["king", "queen", "man", "woman", "cat", "dog"]
# 获取嵌入(假设已有嵌入矩阵)
embeddings = model.encode(words)
# t-SNE降维
tsne = TSNE(n_components=2, random_state=42)
vis_data = tsne.fit_transform(embeddings)
# 可视化
plt.figure(figsize=(10,8))
for i, word in enumerate(words):
plt.scatter(vis_data[i,0], vis_data[i,1])
plt.text(vis_data[i,0], vis_data[i,1], word, fontsize=12)
plt.show()
选择分词器时需要考虑:
对于中文场景,建议:
对于大规模应用,可以考虑:
减少嵌入存储和计算成本:
当文本超过模型限制时:
分词和嵌入技术仍在快速发展,值得关注的方向包括:
在实际应用中,理解分词和嵌入的原理对于优化模型性能、降低计算成本、提高结果质量都至关重要。随着技术的发展,这些基础组件将继续演进,为更强大的语言模型奠定基础。