词嵌入矩阵
词嵌入矩阵是自然语言处理中的核心组件,其核心作用是将离散的符号(如单词、字符)转换为连续的、稠密的向量表示,从而捕捉语义和语法信息。
核心作用
1. 语义表示
- 将单词映射为向量:每个单词对应矩阵中的一行(一个向量)。
- 相似词向量接近:语义相近的词(如“king”和“queen”)在向量空间中距离较近。
- 解决“词汇鸿沟”:传统NLP中,单词被视作独立符号(如one-hot编码),无法表示词间关系。
2. 降维与稠密表示
- one-hot编码缺点:维度高(词汇表大小)、稀疏、无语义信息。
- 词嵌入:将高维稀疏向量压缩为低维稠密向量(如50-300维),携带丰富信息。
3. 关系捕捉
- 向量运算可揭示关系。
- 学习类比、类别等语言学模式。
4. 作为模型输入
- 为下游任务(如文本分类、机器翻译)提供特征输入。
- 通常是神经网络的第一层(嵌入层),可随机初始化并随任务训练,也可用预训练嵌入初始化。
技术实现方式
1. 静态预训练嵌入
- Word2Vec:通过上下文预测词(Skip-Gram)或词预测上下文(CBOW)。
- GloVe:基于全局词共现矩阵的统计信息。
- FastText考虑子词(n-gram)信息,能处理未登录词。
2. 动态上下文嵌入
- ELMo、BERT等:根据上下文生成不同向量(如“苹果”在“吃苹果”和“苹果手机”中向量不同)。
3. 可训练的嵌入层
- 在任务中随机初始化,随模型一起训练。
Word2Vec
Word2Vec是Google在2013年推出的词向量学习工具,核心思想:具有相似上下文的单词具有相似语义。
核心创新
- 从大规模无标注文本中自动学习词向量
- 得到的向量具有线性语义关系(类比关系)
- 计算高效,适合大规模语料
两种主要模型架构
1. Skip-gram(跳字模型):中心思想:通过中心词预测上下文词
输入:中心词 w(t)
输出:周围窗口内的上下文词 {w(t-2), w(t-1), w(t+1), w(t+2)}
例如:句子"The quick brown fox jumps"
中心词="brown" → 预测{"The", "quick", "fox", "jumps"}
特点:
- 更适合小型数据集
- 对罕见词效果更好
- 训练时间相对较长
窗口大小设置
(1)常用经验范围
- 典型值:3、5、7、10
- 最小:2(仅相邻词)
- 最大:20+(段落级上下文)
(2) 不同窗口大小的效果
| 窗口大小 | 捕获信息 | 适合场景 |
|---|---|---|
| 小窗口 (2-5) | 语法模式句法关系、词性搭配 | 语法敏感任务句法分析、词性标注 |
| 中等窗口 (5-10) | 混合信息平衡语法与局部语义 | 通用任务文本分类、情感分析 |
| 大窗口 (10-20) | 主题/语义关联文档主题、远程关联 | 主题建模文档相似度 |
Skip-gram:窗口=10效果较好。CBOW:窗口=5左右
2. CBOW(连续词袋模型):中心思想:通过上下文词预测中心词
输入:上下文词 {w(t-2), w(t-1), w(t+1), w(t+2)}
输出:中心词 w(t)
例如:上下文{"The", "quick", "fox", "jumps"} → 预测"brown"
特点:
- 更适合大型数据集
- 训练速度更快
- 对高频词效果更好
3.Skip-Gram与CBOW的差异
| 模型 | 输入 (Input) | 输出 (Output) | 训练目标 |
|---|---|---|---|
| CBOW | 窗口内的所有上下文词 | 一个中心词 | 最大化给定上下文时中心词的概率 |
| Skip-Gram | 一个中心词 | 窗口内的所有上下文词 | 最大化给定中心词时每个上下文词的概率 |
关键技术优化
1. 负采样(Negative Sampling)
问题:原始softmax计算开销大(需计算词汇表中所有词的概率),避免计算整个词汇表的softmax
解决方案:
- 对每个正样本(中心词-上下文词对),采样K个负样本
- 仅更新正样本和负样本对应的权重
- 显著提升训练速度
负采样的实现过程:
- 统计词汇表中每个词的出现频率 $\text{freq}(w)$
- 计算每个词的采样权重:$\text{weight}(w) = \text{freq}(w)^{0.75}$。
- 将所有权重归一化为概率分布 $P(w) = \frac{\text{weight}(w)}{ \sum(\text{weight})}$
- 构建一个巨大的数组(即采样表),其长度通常为1000万或1亿。每个词根据其概率 $P(w)$ 占据表中相应比例的位置。
例如,如果词A的概率是0.01,而表长为1千万,那么词A的ID就会在这个表中出现大约 10^7 * 0.01 = 10万 次。
这样,后续采样就简化为了 O(1) 操作:每次需要负样本时,只需在1到表长之间生成一个随机整数,然后查表得到对应的词ID即可。
word2vec在训练时,不是直接使用整个词汇表进行随机采样,而是通过预先构建一个巨大的、根据词频权重分布填充的查找表(负采样表),将复杂的、基于非均匀概率分布的采样问题,转化成了一个极其简单的、均匀的“查表”问题。这是一种经典的“以空间换时间” 的工程优化,对于需要执行数十亿次采样操作的大型模型训练至关重要。
2. 高频词下采样
- 对"the", "a"等高频词以概率丢弃
- 平衡罕见词与高频词的训练机会
- 提升向量质量
3. 高频词下采样(Subsampling)方法
公式 1:保留概率 (keep probability)
$$ \text{keep prob} = \left( \sqrt{\frac{\text{threshold}}{\text{freq}}} + 1 \right) \times \frac{\text{freq}}{\text{threshold}} $$
其中 feq是词频,threshold控制着下采样的强度:
- 较小的 threshold → 更激进的下采样(更多词被丢弃)
- 较大的 threshold → 更保守的下采样(更少词被丢弃)
公式 2:丢弃概率 (discard probability)
$$ \text{discard prob} = 1 - \sqrt{\frac{\text{threshold }}{\text{freq}}}$$
原始公式(公式 1)更复杂,来自 word2vec 源码。变体公式(公式 2):更简单,数学上更优雅
判断是否丢弃
import random
# 判断是否丢弃当前词
if random.random() < discard_prob:
discard_word() # 丢弃
else:
keep_word() # 保留
这里的关键是:random.random() 生成一个在 [0, 1) 范围内的均匀分布随机数。假设discard_prob = 0.3 表示丢弃概率是 30%,random.random() 均匀分布在 [0, 1),条件 random.random() < 0.3 成立的概率正好是 30%,以下是关于负采样和下采样的比较:
| 特性 | 负采样 (Negative Sampling) | 下采样 (Subsampling) |
|---|---|---|
| 作用阶段 | 训练时的损失函数计算阶段 | 训练前的数据预处理阶段 |
| 解决的问题 | 避免计算整个词汇表的softmax | 减少高频词的训练次数 |
| 操作对象 | 神经网络输出的计算 | 输入文本数据本身 |
| 主要目的 | 降低计算复杂度 | 平衡词频,提升质量 |
| 影响 | 训练速度提升10-100倍 | 训练速度提升2-5倍,向量质量提升 |
如何衡量词嵌入矩阵好坏
1. 词相似度任务(Word Similarity)
余弦线相似度:余弦相似度是衡量两个向量方向相似程度的指标。余弦相似度的定义:
$$ \cos(\theta) = (A\cdot B) / (\begin{Vmatrix}A \end{Vmatrix} * \begin{Vmatrix}B \end{Vmatrix}) $$
取值范围: [-1, 1], “1”: 完全相同方向, “0”: 正交(无关), “-1”: 完全相反方向。优点: 只考虑方向,不考虑向量长度
计算步骤:
- 计算点积(对应元素相乘后求和)
- 计算每个向量的范数(平方和开根号)
- 点积除以范数乘积
例如:
$$ \text{A} = [1,2,3],\text{B}=[4,5,6] $$
$$ A \cdot B = 1\times 4 + 2\times 5 + 3\times 6 = 32 $$
$$ \begin{Vmatrix}A \end{Vmatrix} = \sqrt{1^2+2^2+3^2} = \sqrt{14},\begin{Vmatrix}B \end{Vmatrix} = \sqrt{4^2+5^2+6^2} = \sqrt{77}$$
$$ \text{cosine\_similarity} = \frac{32}{\sqrt{14\times 75}} \approx 0.9746 $$
相似度解释:
| 分数 | 相似度解释 |
|---|---|
| cos_sim > 0.9 | 几乎相同方向(高度相似) |
| cos_sim > 0.7 | 方向很接近(强相似) |
| cos_sim > 0.5 | 方向比较接近(中等相似) |
| cos_sim > 0.3 | 有一定相似性 |
| cos_sim > 0 | 轻微相似 |
| cos_sim == 0 | 正交(无关) |
| cos_sim > -0.3 | 轻微相反 |
| cos_sim > -0.7 | 比较相反 |
| 其它 | 几乎完全相反 |
上面计算的是两个词$A,B$的余弦相似度,如果需要计算两个文本(包含多个词)的余弦相似度呢?下面介绍文本向量化和余弦相似度计算方法
词嵌入平均法(Word Embedding Average)
def text_to_vector_word_embedding(text, embeddings, pooling='mean'):
"""
使用词嵌入将文本转换为向量
Args:
text: 输入文本
embeddings: 词嵌入字典 {word: vector}
pooling: 池化方法 'mean', 'sum', 'max'
"""
# 分词
words = text.lower().split()
# 获取每个词的向量
word_vectors = []
for word in words:
if word in embeddings:
word_vectors.append(embeddings[word])
if not word_vectors:
# 如果没有词在嵌入中,返回零向量
return np.zeros_like(next(iter(embeddings.values())))
word_vectors = np.array(word_vectors) # [n_words, embed_dim]
# 池化操作
if pooling == 'mean':
text_vector = np.mean(word_vectors, axis=0)
elif pooling == 'sum':
text_vector = np.sum(word_vectors, axis=0)
elif pooling == 'max':
text_vector = np.max(word_vectors, axis=0)
else:
raise ValueError(f"未知的池化方法: {pooling}")
return text_vector
def compare_pooling_methods(text1, text2, embeddings):
"""比较不同的池化方法"""
methods = ['mean', 'sum', 'max']
print(f"文本1: '{text1}'")
print(f"文本2: '{text2}'")
print(f"词嵌入维度: {len(next(iter(embeddings.values())))}")
results = {}
for method in methods:
vec1 = text_to_vector_word_embedding(text1, embeddings, method)
vec2 = text_to_vector_word_embedding(text2, embeddings, method)
similarity = cosine_similarity_manual(vec1, vec2)
results[method] = similarity
print(f"\n{method.upper()}池化:")
print(f" 文本1向量范数: {np.linalg.norm(vec1):.4f}")
print(f" 文本2向量范数: {np.linalg.norm(vec2):.4f}")
print(f" 余弦相似度: {similarity:.4f}")
return results
其过程是:
- 将文本分词
- 获取每个词的词向量
- 对所有词向量取平均得到文本向量
词相似度任务的Spearman相关系数:是用来衡量两个变量单调关系强度的统计指标。记作$\rho$或$r_s$(> 0.6为良好):
- 非参数的:不假设数据分布
- 衡量单调关系:不一定是线性,只要是一个变量增加时另一个也增加(或减少)
- 基于排序:使用数据的秩(排名)而非原始值
- 基于排序:使用数据的秩(排名)而非原始值
- 范围:-1 到 +1
- +1:完全正相关(一个排名增加,另一个也增加)
- -1:完全负相关(一个排名增加,另一个减少)
- 0:无单调关系
解释Spearman相关系数$\rho$
| $\rho$ | 模型 |
|---|---|
| $\rho \ge 0.9 $ | 极强相关 |
| $\rho \ge 0.7 $ | 强相关 |
| $\rho \ge 0.5 $ | 中等相关 |
| $\rho \ge 0.3 $ | 弱相关 |
| $\rho < 0.3 $ | 极弱或无相关 |
2. 词类比任务(Word Analogy)
QkCalc中的Word2Vec
在QkCalc中可以使用“机器学习”中的“词嵌入向量”创建和训练Word2Vec模型,具体的训练是通过QkAIService服务来完成。通过QkCalc可对该服务进行管理并对训练的结果进行评估。