1. 从零理解AI中的文本处理基石
作为一名长期奋战在AI一线的算法工程师,我经常遇到刚入门的同学对Embedding这个概念感到困惑。今天我们就来彻底拆解这个NLP(自然语言处理)领域的核心组件,让你不仅明白它的原理,还能亲手实现一个简易版本。
1.1 为什么需要文本向量化?
人类语言和计算机之间存在着一道天然的鸿沟。我们日常交流的文字对机器来说只是一串毫无意义的符号。想象一下你要教一个完全不懂中文的外国人理解"我喜欢你"这句话:
- 首先需要把句子拆解成基本单元(我/喜欢/你)
- 然后为每个单元建立对应的外语翻译
- 最后还要考虑词语在不同语境下的含义变化
这就是Tokenizer和Embedding在AI系统中扮演的角色。它们共同完成了从原始文本到数值表示的转换过程,让机器能够"理解"人类语言。
关键认知:Embedding不是孤立存在的,它建立在Tokenizer的输出基础上,两者共同构成NLP模型的前置处理管道。
1.2 处理流程全景图
一个完整的文本处理流程通常包含以下阶段:
code复制原始文本 → Tokenizer → 索引序列 → Embedding → 向量矩阵 → 神经网络
以"我喜欢你"为例:
- Tokenizer将其转换为[0,1,2]
- Embedding将每个索引映射为512维向量
- 最终输出形状为[1,3,512]的三维张量
这个张量才是神经网络真正"看得懂"的输入格式。接下来我们就深入这两个核心组件。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文本分词器(Tokenizer)深度解析
2.1 三大分词策略对比
在实际工程中,我们主要使用三种粒度的分词方法:
| 分词类型 | 示例 | 优点 | 缺点 | 典型应用 |
|---|---|---|---|---|
| 词级别(Word) | "机器学习"→["机器","学习"] | 语义明确 | 词表膨胀 | 早期Word2Vec |
| 子词级别(Subword) | "unhappy"→["un","happy"] | 平衡粒度 | 实现复杂 | BERT/GPT |
| 字符级别(Char) | "AI"→["A","I"] | 词表极小 | 序列过长 | 拼音文字处理 |
现代大模型普遍采用子词分词法,它完美折衷了另外两种方案的优缺点。以"unhappy"为例:
- 词级别:需要将整个词存入词表
- 子词级别:只需存储"un"和"happy",可以组合出新词
- 字符级别:虽然灵活但信息密度太低
2.2 手写一个工业级Tokenizer
让我们用Python实现一个支持高频词缓存的增强版Tokenizer:
python复制import re
from collections import Counter, defaultdict
import pickle
class EnhancedTokenizer:
def __init__(self, vocab_size=30000):
# 初始化特殊token和缓存
self.specials = {"<PAD>":0, "<UNK>":1, "<SOS>":2, "<EOS>":3}
self.word2idx = self.specials.copy()
self.idx2word = {v:k for k,v in self.specials.items()}
self.vocab_size = vocab_size
self.word_freq = defaultdict(int)
self.cache = {} # 高频词缓存
def preprocess(self, text):
"""文本预处理流水线"""
text = text.lower().strip()
text = re.sub(r'[^\w\s]', '', text) # 移除非字母数字字符
return text
def train(self, corpus, min_freq=5):
"""训练词表并建立映射"""
counter = Counter()
for text in corpus:
tokens = self.preprocess(text).split()
counter.update(tokens)
# 过滤低频词
