一、初级分词技术

1. 分词(Tokenization)在NLP工程中的核心地位

  • 定义:将连续文本切分成有语义的“词”或“Token”的过程,是几乎所有NLP任务(搜索、推荐、情感分析、机器翻译、LLM预处理等)的第一步
  • 重要性:分词错误会产生级联效应(Cascading Effect),直接影响下游模型效果。在工业界,高质量分词是提升系统精准度的“性价比最高”的环节之一。
  • 中英文差异:英文靠空格,中文无天然边界 → 需要专门算法。

2. 传统分词主流方法(面试/工作必问)

  • 基于词典 + 规则(jieba默认精确模式)
    • 核心技术:前缀词典 + Trie树 → 构建DAG(有向无环图) → 动态规划找最大概率路径
    • 使用Log概率避免数值下溢。
    • 公式本质:寻找使 ∑ log P(wi) 最大的路径。
    • 优势:速度快、效果稳定、可解释性强。
    • 缺点:依赖词典,OOV(未登录词)问题严重。
  • 统计学习方法(HMM)
    • 把分词转为序列标注(B/M/E/S标签)。
    • jieba中HMM用于二次加工未登录词,能发现新词(如“直聘”)。
    • 优点:一定程度解决OOV;缺点:假设太强,复杂歧义场景弱于CRF。
  • 混合策略(jieba实际采用):
    • 词典DAG + HMM后处理 → 兼顾精度与新词发现。

3. jieba实用技能(就业最常用)

  • 安装与加载:pip install jieba、jieba.load_userdict()
  • 三种模式
    • cut_all=False:精确模式(推荐生产使用)
    • HMM=True/False:控制是否启用HMM识别新词
  • 自定义词典:解决领域专有名词OOV(人名、地名、产品名、黑话等)。
    • 格式:词语 [词频] [词性]
    • 高词频可“强制”分词,低词频可拆分。
  • 词性标注:jieba.posseg(ICTCLAS标记集),业务中常用于实体提取、关键词过滤。

4. 现代分词趋势(大模型时代必知)

  • 字粒度(BERT中文):简单、无OOV,但序列长、丢失词语义。
  • 子词(Subword)(GPT/BPE):当前主流,平衡词表大小与语义表达,是工业界标配。
  • 传统jieba仍广泛用于数据预处理、搜索召回、规则系统等场景。

就业价值

  • 掌握jieba能让你快速处理中文文本清洗、构建领域词典、做Baseline系统。
  • 理解DAG+DP、HMM、OOV处理,是NLP工程师面试常考点。
  • 在搜索、推荐、客服机器人、内容审核等岗位中,直接影响上线效果和迭代速度。

练习

练习1:修改 user_pos_dict.txt 中“九”和“头”的词频

原词典示例:

text

九 10000000 n
头 1000000 n
奔波儿灞 nr

实验结果与解释

  • 高词频(如上面):动态规划时“九”和“头”单独成词的概率远高于“九头”,强制拆分为 ['九', '头', '虫']。
  • 降低词频(例如改成 九 1 n、头 1 n):
    • jieba更倾向于把“九头”当作一个词(如果词典里有或HMM认为合理),或仍按原有路径处理。
    • 若完全删除“九”和“头”的词条,恢复默认行为,可能切成 ['九头', '虫'] 或 ['九头虫'](取决于是否加载其他词)。
  • 结论:词频是“人工干预概率路径”的关键杠杆。生产中常用此技巧处理公司专有名词、品牌名、容易歧义的组合。

练习2:更换不同text短句的输出观察

以下是几个典型例子(使用精确模式 + 加载自定义词典后):

  1. text = "南京市长江大桥"
    • 结果:['南京市', '长江大桥'](正确,避免“南京市长”歧义)
  2. text = "苹果手机销量很好"
    • 结果:['苹果', '手机', '销量', '很', '好'](“苹果”会被识别为公司/水果,上下文决定)
  3. text = "我爱北京天安门"
    • 结果:['我', '爱', '北京', '天安门']
  4. text = "奔波儿灞和九头虫大战"
    • 结果:['奔波儿灞', '和', '九头虫', '大战'](自定义词典生效)
  5. 新词测试:text = "小米SU7汽车发布"
    • 未加词典可能切成 ['小米', 'SU', '7', '汽车', '发布']
    • 加入 小米SU7 nr 后 → ['小米SU7', '汽车', '发布']

二、词向量表示

1. 为什么需要词向量?(面试高频问题)

  • 计算机无法直接处理文本字符串,必须把文本转换为数值向量才能输入机器学习/深度学习模型。
  • 核心目标:弥合符号世界(自然语言)向量空间(数学模型) 之间的鸿沟。
  • 理想词向量要求:
    • 能唯一标识每个词
    • 蕴含语义信息(语义相近的词向量距离近,如“国王”≈“女王”,远于“香蕉”)

就业价值:这是所有NLP任务(文本分类、搜索、推荐、情感分析、LLM微调)的数据预处理基础,理解词向量演进是面试必考点。


2. 传统离散表示(经典机器学习时代)

2.1 独热编码(One-Hot Encoding)
  • 原理:词典大小 = 向量维度,每个词对应位置为1,其余为0。
  • 优点:简单、易实现、无歧义。
  • 致命缺点
    • 维度灾难(词典10万词 → 10万维)
    • 极度稀疏
    • 语义鸿沟:任意两个不同词的向量正交(点积=0),完全无法表达相似性。
2.2 词袋模型(Bag-of-Words, BoW)
  • 核心思想:忽略词序和语法,只统计词的出现频次 → 把文档看成“装满词的袋子”。
  • 实现:对文档中所有词的One-Hot向量进行求和(或直接统计频次)。
  • 相似度计算:常用余弦相似度(Cosine Similarity):

$\text{similarity} = \cos(\theta) = \frac{A \cdot B}{||A|| \cdot ||B||} = \frac{\sum_{i=1}^n A_i B_i}{\sqrt{\sum_{i=1}^n A_i^2} \cdot \sqrt{\sum_{i=1}^n B_i^2}}$

  • 优点:简单有效,适合早期文本分类、垃圾邮件过滤等“看文档里有什么词”的任务。
  • 缺点:完全丢失词序(“我爱你” = “你爱我”),停用词干扰大。
2.3 TF-IDF(最重要传统特征工程)
  • 核心理念:一个词的重要性 = 在当前文档中越频繁 × 在整个语料库中越稀有
  • 公式

$\text{TF-IDF}(t,d,D) = \text{TF}(t,d) \times \text{IDF}(t,D)$

其中:

  • $ \text{TF}(t,d) $:词t在文档d中的词频(常用归一化:次数 / 文档总词数)
  • $ \text{IDF}(t,D) = \log\left(\frac{|D|}{1 + |\{d \in D : t \in d\}|}\right) $:用于衡量一个词的"稀有"程度或"信息量",(log(总文档数/(1+包含词t的文档数量)))越大越稀有

就业应用

  • 关键词提取(jieba.analyse.extract_tags)
  • 传统搜索引擎相关性排序
  • 文本相似度计算
  • 作为机器学习模型(SVM、XGBoost)的特征输入

3. N-gram 模型(词序 + 统计语言模型的开端)

  • 核心思想:基于马尔可夫假设 —— 当前词只依赖前面 N−1 N-1 N−1 个词。
  • 作用:引入局部词序信息,弥补BoW的缺陷。
  • 常见类型
    • Unigram(1-gram):等同BoW
    • Bigram(2-gram)
    • Trigram(3-gram)
  • 现代意义大语言模型(GPT等)的理论鼻祖 —— 本质是超大规模N-gram(通过神经网络实现)。

挑战:维度爆炸 + 数据稀疏 → 推动了神经词向量的发展。


4. 现代深度学习时代的序号化表示(当前主流)

  • 核心变化:不再手工设计复杂特征(TF-IDF、N-gram),而是把“学习语义”交给模型。
  • 流程(非常重要,生产必用):
    1. 分词(或直接字符/子词)
    2. 构建/使用预训练词典(vocab.txt)
    3. 映射为整数ID序列
    4. Padding 对齐长度([PAD] = 0)
    5. 处理未知词([UNK] = 1)
    6. 输入Embedding Layer → 自动学习稠密词向量

示例(面试常考):

  • 句子 → ID序列 → Padding → Tensor → Embedding

优势

  • 维度低(Embedding维度通常256~4096)
  • 端到端学习语义
  • 支持变长序列(Transformer)

总结

技术 适用场景 优缺点关键点 面试/工作出现频率
One-Hot 玩具级演示 维度灾难、无语义 ★★
BoW 简单分类、Baseline 快、丢失词序 ★★★
TF-IDF 关键词提取、搜索、传统ML 区分度高、仍丢失语义 ★★★★★(高频)
N-gram 语言模型、小数据场景 捕捉词序,但稀疏 ★★★★
序号化+Embedding 所有现代NLP/LLM项目 端到端、可迁移 ★★★★★(核心)

三、从主题模型到Word2Vec

1. 分布式表示(Distributed Representation)—— 词向量的理想形态

  • 核心目标:将词映射到低维、稠密、蕴含语义的连续向量空间。
  • 两大关键特性
    • 语义蕴含:语义相近的词向量距离近(基于分布式假设:相似上下文 → 相似向量)。
    • 低维稠密:维度通常 100~300 维(远小于词典大小),每一维都有实际意义。
  • 解决的问题:彻底告别 One-Hot 的维度灾难与语义鸿沟。

就业意义:这是从传统特征工程转向神经网络 NLP 的分水岭,几乎所有现代 NLP 系统(搜索、推荐、情感分析、LLM)都建立在分布式词向量基础上。


2. 主题模型(Topic Model)—— 基于全局统计的早期方案

  • 代表方法:LSA(Latent Semantic Analysis) / SVD 矩阵分解。
  • 核心思想:文档由多个潜在主题混合而成,词语通过主题建立关联。
SVD 矩阵分解公式(核心)

$X_{m \times n} \approx W_{topic}^{m \times k} \times H_{topic}^{k \times n}$

  • X:词-文档矩阵(通常用 TF-IDF 填充)
  • m:词典大小,n n n:文档数量
  • k :主题数量(远小于 m,n,典型 100~300)
  • $ W_{topic} $​:词-主题矩阵每一行就是一个词向量
  • $ H_{topic} $​:文档-主题矩阵

优点

  • 能捕捉同义词(“番茄”与“西红柿”向量接近)
  • 实现简单(sklearn 的 TruncatedSVD 即可)

局限性(面试常问):

  • 计算代价高(大矩阵 SVD)
  • 依赖全局文档共现,忽略局部上下文和词序
  • 静态,无法端到端训练

3. Word2Vec —— 现代词嵌入的真正开端(2013 Google)

  • 提出者:Mikolov et al.
  • 核心思想用局部上下文预测词语(预测任务只是手段,最终目标是学到高质量词向量表)。
  • 本质:浅层神经网络 + 可学习的词向量查找表(Embedding 矩阵)。
3.1 词向量获取机制(面试必考)

输入 One-Hot(或 ID) → 直接查 Embedding 矩阵 Win W_{in} Win​(大小 ∣V∣×D |V| \times D ∣V∣×D) 在 PyTorch 中即 nn.Embedding(vocab_size, embed_dim)

3.2 两种经典架构

(1)CBOW(Continuous Bag-of-Words)

  • 任务:根据上下文预测中心词(速度快,适合大语料)
  • 流程:
    1. 上下文词向量求平均(或求和)得到 h h h
    2. h h h 与输出矩阵 Wout W_{out} Wout​ 相乘得得分
    3. Softmax + 交叉熵

核心损失函数

$J = -\log P(w_c | \text{上下文}) = -u_c^T h + \log \sum_{j=1}^{|V|} \exp(u_j^T h)$

(2)Skip-gram

  • 任务:根据中心词预测上下文(对低频词效果更好)
  • 特点:一个中心词产生多个训练样本(多标签分类)
  • 核心损失函数

$J = -\sum_{j \neq m} u_{c-m+j}^T v_c + 2m \log \sum_{k=1}^{|V|} \exp(u_k^T v_c)$

CBOW vs Skip-gram 对比(就业必知)

维度 CBOW Skip-gram 推荐场景
训练速度 大语料选 CBOW
低频词效果 一般 优秀 小语料/专有名词选 Skip-gram
语义质量 较平滑 更精细 多数情况 Skip-gram 更好
资源消耗 较低 较高 -

3.3 训练技巧(加速关键)
  • Hierarchical Softmax
  • Negative Sampling(最常用,极大提升训练速度)

4. Word2Vec 的局限性(现代模型对比基础)

  • 静态词向量(Static Embedding):一个词永远只有一个固定向量
  • 上下文无关:无法解决一词多义(e.g. “小米”在农业 vs 手机公司)
  • 无法捕捉更长距离依赖

这直接推动了后续 ELMo(上下文相关)、BERT(双向)、GPT 等动态词向量的诞生。

高频问题

  1. One-Hot 与 Word2Vec 的本质区别是什么?One-Hot 是“给每个词一个独一无二的编号”,Word2Vec 是“让含义相似的词住在向量空间的同一个小区”。One-Hot 属于局部表示(Localist Representation),Word2Vec 属于分布式表示,这是 NLP 从传统机器学习走向深度学习的最重要转变之一。
  2. CBOW 和 Skip-gram 的区别及适用场景?
  3. Word2Vec 是如何让语义相近的词向量靠近的?(滑动窗口 + 点积最大化)Word2Vec 通过大量重叠上下文的预测任务,让分布式假设(相似上下文 → 相似含义)变成了向量空间中的几何距离。
  4. SVD 和 Word2Vec 分别捕捉哪种共现信息?SVD 是“看整篇文章里词一起出现的频率”,Word2Vec 是“看同一个句子窗口里词的邻居是谁”。

生产中常用技能

  • Gensim 快速训练 Word2Vec:Word2Vec(sentences, vector_size=300, window=5, sg=1)
  • 加载预训练词向量(腾讯、智谱、百度等中文版)
  • 在下游任务中 冻结或微调 Embedding 层
  • 解决 OOV:用 subword(如 FastText)或 [UNK]

四、基于Gensim的词向量实践

1. Gensim 核心概念与工作流(生产必备)

Gensim 是工业界处理非结构化文本最常用、最高效的 Python 库之一,支持 TF-IDF、LSA、LDA、Word2Vec、FastText 等经典算法。

关键概念(面试常问)

概念 含义 实际用途
语料(Corpus) list[list[str]](分词后的文档列表) 所有模型的原始输入
词典(Dictionary) token → integer ID 的映射表 构建 BoW、过滤 OOV
BoW 稀疏向量 [(token_id, freq), ...] 节省内存,TF-IDF/LDA 输入
模型(Model) 训练好的转换器(如 TfidfModel、LdaModel) 可持久化,用于新文档推理

标准三步工作流(几乎所有 BoW 类模型通用):

  1. 分词 → tokenized = [jieba.lcut(doc) for doc in docs]
  2. 创建词典 → dictionary = corpora.Dictionary(tokenized)
  3. 转为 BoW → corpus_bow = [dictionary.doc2bow(doc) for doc in tokenized]

注意:以上三步适用于 TF-IDF、LSA、LDA、NMF 等基于 BoW 的模型;Word2Vec / FastText / Doc2Vec 不需要 BoW,直接使用 list[list[str]] 即可。

import jieba
from gensim import corpora

# Step 1: 准备分词后的语料 (新闻标题)
raw_headlines = [
    "央行降息,刺激股市反弹",
    "球队赢得总决赛冠军,球员表现出色"
]
tokenized_headlines = [jieba.lcut(doc) for doc in raw_headlines]
print(f"分词后语料: {tokenized_headlines}")

# Step 2: 创建词典
dictionary = corpora.Dictionary(tokenized_headlines)
print(f"词典: {dictionary.token2id}")

# Step 3: 转换为 BoW 向量语料库
corpus_bow = [dictionary.doc2bow(doc) for doc in tokenized_headlines]
print(f"BoW语料库: {corpus_bow}")

输出如下:

分词后语料: [['央行', '降息', ',', '刺激', '股市', '反弹'], ['球队', '赢得', '总决赛', '冠军', ',', '球员', '表现出色']]
词典: {'刺激': 0, '反弹': 1, '央行': 2, '股市': 3, '降息': 4, ',': 5, '冠军': 6, '总决赛': 7, '球员': 8, '球队': 9, '表现出色': 10, '赢得': 11}
BoW语料库: [[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)], [(5, 1), (6, 1), (7, 1), (8, 1), (9, 1), (10, 1), (11, 1)]]

2. TF-IDF 实战(最常用传统特征)

  • 作用:给词赋予重要性权重(文档内高频 × 语料库中稀有)。
  • Gensim 实现
    tfidf_model = models.TfidfModel(corpus_bow)
    corpus_tfidf = tfidf_model[corpus_bow]   # 稀疏 TF-IDF 向量

TF-IDF 是衡量一个词在文档中重要性的经典加权方法。下面将继续使用新闻标题的例子,演示如何计算其 TF-IDF 向量。

import jieba
from gensim import corpora, models

# 1. 准备语料 (新闻标题,包含财经和体育两个明显主题)
headlines = [
    "央行降息,刺激股市反弹",
    "球队赢得总决赛冠军,球员表现出色",
    "国家队公布最新一期足球集训名单",
    "A股市场持续震荡,投资者需谨慎",
    "篮球巨星刷新历史得分记录",
    "理财产品收益率创下新高"
]
tokenized_headlines = [jieba.lcut(title) for title in headlines]

# 2. 创建词典和 BoW 语料库
dictionary = corpora.Dictionary(tokenized_headlines)
corpus_bow = [dictionary.doc2bow(doc) for doc in tokenized_headlines]

# 3. 训练 TF-IDF 模型
tfidf_model = models.TfidfModel(corpus_bow)

# 4. 将BoW语料库转换为 TF-IDF 向量表示
corpus_tfidf = tfidf_model[corpus_bow]

# 辅助函数:把 (token_id, weight) 转成 (token, weight),并按权重降序展示
def tfidf_with_words(tfidf_vec, id2word):
    pairs = [(id2word[token_id], weight) for token_id, weight in tfidf_vec]
    return sorted(pairs, key=lambda x: x[1], reverse=True)

# 打印第一篇标题的 TF-IDF 向量
first_tfidf = list(corpus_tfidf)[0]
print("第一篇标题的 TF-IDF 向量:")
print(first_tfidf)
print("第一篇标题的 TF-IDF 向量(带词语):")
print(tfidf_with_words(first_tfidf, dictionary))

# 5. 对新标题应用模型
new_headline = "股市大涨,牛市来了"
new_headline_bow = dictionary.doc2bow(jieba.lcut(new_headline))
new_headline_tfidf = tfidf_model[new_headline_bow]
print("\n新标题的 TF-IDF 向量:")
print(new_headline_tfidf)

输出如下:

第一篇标题的 TF-IDF 向量:
[(0, 0.44066740566370055), (1, 0.44066740566370055), (2, 0.44066740566370055), (3, 0.44066740566370055), (4, 0.44066740566370055), (5, 0.1704734229377651)]
第一篇标题的 TF-IDF 向量(带词语):
[("刺激", 0.44066740566370055), ("反弹", 0.44066740566370055), ("央行", 0.44066740566370055), ("股市", 0.44066740566370055), ("降息", 0.44066740566370055), (",", 0.1704734229377651)]

新标题的 TF-IDF 向量:
[(3, 0.9326446771245245), (5, 0.360796211497975)]

应用

  • 关键词提取
  • 文档相似度计算(余弦相似度)
  • 传统机器学习(XGBoost、SVM)的文本特征
  • 搜索召回 Baseline

新文档处理:必须先转 BoW,再传入模型(OOV 词会被自动忽略)。


3. LDA 主题模型(无监督主题挖掘)

  • 核心思想:每篇文档是多个主题的混合,每个主题是词的概率分布。
  • Gensim 实现
    lda_model = models.LdaModel(
        corpus=corpus_bow, 
        id2word=dictionary, 
        num_topics=10,      # 关键超参
        random_state=42
    )

实用价值

  • 自动文档聚类
  • 内容分析、用户画像、推荐系统冷启动
  • 可视化主题分布

输出

  • lda_model.print_topics() → 每个主题的 Top 词
  • lda_model[new_doc_bow] → 文档的主题概率分布(稀疏)

4. Word2Vec 实战(分布式词向量核心)

这是本节最重要内容。

4.1 训练代码(背诵版)
from gensim.models import Word2Vec

model = Word2Vec(
    sentences=tokenized_corpus,   # list[list[str]]
    vector_size=100,      # 词向量维度(50-300 常用)
    window=5,             # 上下文窗口大小
    min_count=2,          # 忽略低频词(非常重要)
    sg=1,                 # 1=Skip-gram(推荐),0=CBOW
    hs=0,                 # 0=Negative Sampling(推荐)
    negative=5,           # 负采样数量
    epochs=10,            # 训练轮数
    workers=4             # 多线程
)
4.2 核心参数
参数 含义 推荐值 / 建议
vector_size 词向量维度 100~300
window 上下文窗口 5(新闻),8~10(长文本)
min_count 最小词频 2~5(过滤噪声)
sg 算法选择 1(Skip-gram) 更常用
negative 负采样数 5~20
epochs 迭代次数 5~30(视语料大小)
4.3 使用方式
# 最相似词
model.wv.most_similar('股市', topn=10)

# 相似度
model.wv.similarity('球队', '球员')

# 获取向量
vec = model.wv['市场']          # shape: (vector_size,)

# 保存(推荐只存 wv)
model.wv.save("word2vec.kv")
loaded = KeyedVectors.load("word2vec.kv")

5. 要点总结

生产中常用组合

  • Baseline:TF-IDF + XGBoost / Logistic
  • 语义增强:Word2Vec 平均池化句子向量 → 全连接分类
  • 主题分析:LDA → 内容标签 / 舆情分析
  • 推荐系统:Word2Vec 做 Item Embedding(物品相似召回)

优势与局限

  • Gensim 训练快、内存低,适合中小规模自有语料训练领域词向量。
  • 缺点:Word2Vec 是静态向量,无法解决一词多义(后续 BERT 解决)。
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐