13-词嵌入(Word Embedding)——AI的思考

发布于 25 天前  51 次阅读


“我思故我在向量空间”

1. 认识语言

自然语言——人类最伟大的发明

作为思维载体和沟通桥梁,语言不仅塑造认知范式,更催生情感共鸣与社会协作、记录经验、传递知识……使人类能在科学、艺术、文化、工业等几乎所有领域不断积累和发展。毫不过分地说,语言是传承人类文明、造就现代人类文明世界的基石。

语言学不是这篇文章的重点,所以我们简单概括了解。

自然语言的基本要素

  • 语义——语言背后语言的含义
  • 语法——语言的组织方式

自然语言的载体

  • 文字——语言的视觉载体
  • 发音——语言的听觉载体

1.4 计算机认识的自然语言

对计算机而言,语言的文字和发音更多作为词语标签的形式存在,正真用于理解人类自然语言的,更多是通过学习语义语法


2. 词向量(Word Vector)

2.1 词向量用于解释语义

词向量是包含了解释语义的向量。其不同维度的分量代表了不同维度是抽象特征,由模型根据实际词汇表自动训练而成,可理解为该词在不同维度的意义。

以我们对“国王”一词,可在从多个维度进行解读:

  • 生物维度:“国王”是“人”,与“猫”、“狗”等不同生物在同一维度有所不同;
  • 政治身份维度:“国王”是“王”,与“诸侯”、“平民”等不同政治身份的人在同一维度有所区别;
  • 性别维度:“国王”通常是“男”,与“女”、“无性别”(如无性繁殖生物的性别)有所区别;

词向量也会在不同的维度解读“国王”一词。

需注意的是,词向量对语义各维度的解读,通常不会跟人类的解读一致。

我们对于词语的解读基于庞大的现实世界,而词向量对语义的解读,仅来源于有限的数据集。

简单来说,对于自然语言的词汇,尽管人类和计算机都会用不同维度去解读,但人类有适合人类的解读方式,计算机有适合计算机的解读方式。

GoogleNews的Word2Vec预训练模型为例:

from gensim.models import KeyedVectors

# 下载预训练模型(需提前下载 .bin 文件)
model = KeyedVectors.load_word2vec_format("GoogleNews-vectors-negative300.bin", binary=True)

result = model.most_similar(positive=['woman', 'king'], negative=['man'], topn=1)
print(f"woman + king - man ≈ {result[0][0]}")

## 输出
# woman + king - man ≈ queen
# #

尝试思考上述输出,若能理解,便基本上了解词向量背后的含义了。

2.2 余弦相似度衡量语义的相似

不同词向量之间常用余弦相似度表示语义的相近程度,范围在 [-1, 1](1表示完全相同方向,0表示无关,-1表示完全相反)。有时也可用欧氏距离(空间距离),但在 NLP 中,通常更关注方向而非绝对距离,因此余弦相似度是首选

from gensim.models import KeyedVectors
import numpy as np

# 下载预训练模型(需提前下载 .bin 文件)
model = KeyedVectors.load_word2vec_format("GoogleNews-vectors-negative300.bin", binary=True)

woman = model['woman']
man = model['man']
cat = model['cat']

print(f"'woman' 的前5个向量值: {woman[:5]}")
print(f"'man' 的前5个向量值: {man[:5]}")
print(f"'cat' 的前5个向量值: {cat[:5]}")


def check_similarity(word1, word2):
    # 检查词是否存在
    if word1 not in model.key_to_index or word2 not in model.key_to_index:
        print(f"'{word1}' 或 '{word2}' 不在词汇表中。")
        return
    
    # 计算余弦相似度
    cosine_sim = model.similarity(word1, word2)
    # 计算欧氏距离
    euclidean_dist = np.linalg.norm(model[word1] - model[word2])
    
    print(f"词对: '{word1}' vs '{word2}'")
    print(f"余弦相似度: {cosine_sim:.4f}")
    print(f"欧氏距离: {euclidean_dist:.4f}\n")

# 比较两组词对
check_similarity("woman", "man")
check_similarity("man", "cat")
check_similarity("cat", "woman")

## 输出
# 'woman' 的前5个向量值: [ 0.24316406 -0.07714844 -0.10302734 -0.10742188  0.11816406]
# 'man' 的前5个向量值: [ 0.32617188  0.13085938  0.03466797 -0.08300781  0.08984375]
# 'cat' 的前5个向量值: [ 0.0123291   0.20410156 -0.28515625  0.21679688  0.11816406]
# 词对: 'woman' vs 'man'
# 余弦相似度: 0.7664
# 欧氏距离: 1.7280

# 词对: 'man' vs 'cat'
# 余弦相似度: 0.2991
# 欧氏距离: 3.2199

# 词对: 'cat' vs 'woman'
# 余弦相似度: 0.3241
# 欧氏距离: 3.3242
# #

2.3 注意⚠️

⚠️ 词向量相似度词义相似度。两个词是否是反义词,跟这两个词的词向量相似度是否相反,通常情况下没有必然联系。

check_similarity("yes", "no")
##
# 词对: 'yes' vs 'no'
# 余弦相似度: 0.3921
# 欧氏距离: 2.4503
# #

⚠️ 词向量只在特定环境下才有意义。 在不同的环境下(如不同嵌入模型、维度、语料库等),相同词汇的词向量的数值也通常会截然不同。


3. 词嵌入(Word Embedding)

3.1 将自然语言嵌入到向量空间

词嵌入是指将词语映射到连续向量空间的技术或过程。即创建词向量、将语义量化的关键技术,正是词嵌入。

在进行词嵌入之前,我们通常需要先对原始文本数据(通常称为语料库)进行适当的预处理,以提取出词汇表。

NLP典型处理流程

  1. 语料库(Raw Corpus)
    • 原始文本数据(如书籍、网页、对话记录等)。
    • 示例["I love cat.", "Attention is all you need."]
  2. 预处理(Preprocessing)
    • 分词(Tokenization):将文本分割为词或子词单元。
      • 示例["I", "love", "cat", ".", "Attention", "is", "all", "you", "need", "."]
    • 清洗(Cleaning):去除噪声(如HTML标签、特殊符号)、标准化(如小写化)。
    • 编码(Indexing):为每个词分配唯一ID(构建词汇表)。
      • 示例{"I": 0, "love": 1, "cat": 2, ...}
  3. 数值化表示(Vectorization)
    • 词嵌入(Word Embedding)将词ID映射为词向量(如Word2Vec、BERT)。
    • 位置编码(Positional Encoding):注入位置信息(如绝对位置、相对位置)。
    • 其他编码(可选):段编码(区分句子)、模态编码(多模态任务)。
  4. 模型输入(Model Input)
    • 最终形式:词向量 + 位置向量(+ 其他编码)的拼接或相加。
    • 数学表示:Input = WordEmbedding(token_ids) + PositionalEncoding(positions)

3.2 早期词嵌入

早期词嵌入技术最常见的两种主要是词袋模型(BoW)和独热编码(one-hot)。

3.2.1 词袋模型(Bag of Words, BoW)

词袋模型通过统计文本中单词的出现频率(或存在性)来表示文本。比起“编码”,它更偏向于“统计”。

步骤

  1. 构建词汇表:从所有文本中提取唯一单词,形成词汇表(如:["我", "喜欢", "睡觉", "他", "吃饭"])。
  2. 生成向量:对每个文本,统计词汇表中每个单词的出现次数(或是否出现),形成一个向量。

示例

  • 句子1:“我喜欢睡觉” → 向量为 [1, 1, 1, 0, 0](假设词汇表顺序为["我", "喜欢", "睡觉", "他", "吃饭"])。
  • 句子2:“他喜欢吃饭” → 向量为 [0, 1, 0, 1, 1]

特点

  • 优点:简单易实现,适合基础文本分类(如情感分析、垃圾邮件检测)。
  • 缺点
    • 忽略词序和上下文(例如,“猫喝水”和“水喝猫”会被视为相同)。
    • 维度高且稀疏(词汇表大时,向量中大部分值为0)。
    • 无法捕捉语义相似性(如“快乐”和“开心”被视为完全无关)。

3.2.2 独热编码(One-Hot)

One-Hot 编码将每个单词表示为唯一的稀疏向量,向量长度为词汇表大小,只有对应单词的位置为1,其余为0。

示例

  • 词汇表:["苹果", "香蕉", "橘子"]。
  • One-Hot 编码:
    • “苹果” → [1, 0, 0]
    • “香蕉” → [0, 1, 0]
    • “橘子” → [0, 0, 1]

  • 优点:简单直观,适用于类别型特征的编码。
  • 缺点
    • 维度灾难(词汇表大时,向量维度极高)。
    • 无法表达单词间的关系(所有向量相互正交,相似度为0)。

3.3 现代词嵌入技术

3.3.1 词嵌入的进化

  1. 早期探索(2000年以前)
    • 统计语言模型:早期的NLP依赖词袋模型(BoW)和独热编码,仅关注词频统计,缺乏语义关联,且面临维度灾难问题。
    • 概率模型与降维:2000年,约书亚·本希奥(Yoshua Bengio)提出神经概率语言模型,首次通过神经网络学习词的分布式表示;同年,Roweis和Saul在《科学》发表的局部线性嵌入(LLE)方法,为高维数据降维提供了新思路。
  2. 突破阶段(2010年代)
    • Word2Vec的诞生:2013年,谷歌团队(Tomas Mikolov等)推出Word2Vec工具,通过浅层神经网络(如CBOW和Skip-gram)高效生成词向量,显著提升了训练速度和语义捕捉能力,成为里程碑式突破。
    • GloVe的全局优化:2014年,斯坦福大学的GloVe模型结合全局词共现矩阵和局部上下文,进一步优化低频词的表示效果。
  3. 动态嵌入时代(2018年后)
    • 上下文感知模型:以ELMo、BERT为代表的动态词嵌入模型兴起,通过预训练和注意力机制,使词向量能根据上下文动态调整,解决了一词多义问题。

3.3.2 词嵌入的分类

根据生成后的词向量是否固定(与上下文无关),词嵌入可分为静态嵌入动态嵌入

静态词嵌入动态词嵌入
核心思想每个词被映射到固定的向量,与上下文无关。词向量根据上下文动态生成,同一词在不同语境中向量不同。
上下文处理❌ 忽略上下文,所有场景下同一词向量相同✅ 基于上下文动态调整词向量
词义消歧无法处理多义词(如“苹果”在“水果”和“手机”中含义不同,但向量相同)。能区分多义词(如“苹果”在不同句子中生成不同向量)。
模型结构基于浅层神经网络或统计方法(如矩阵分解)。基于深层预训练语言模型(如Transformer)。
训练数据量通常需要中等规模语料库。需要大规模语料库(如维基百科、书籍、网页文本)。
计算资源训练和推理资源需求较低。训练资源需求极高(需GPU/TPU),推理时资源消耗也较高。
应用场景资源有限、简单任务(如文本分类、关键词匹配)。复杂任务(如问答系统、机器翻译、语义理解)。
灵活性词向量固定,无法适应新任务或领域。可通过微调(Fine-tuning)适应特定任务或领域。
典型技术Word2Vec、GloVe、FastTextBERT、ELMo、RoBERTa、GPT系列
未来趋势仍在轻量级场景中发挥作用逐渐成为主流,结合文本与图像/视频的多模态嵌入(如CLIP、SkyReels-V2的视频理解模型),成为新兴方向

4. 常见词嵌入模型

4.1 静态嵌入

词嵌入名称实现原理常见应用
Word2Vec通过浅层神经网络(CBOW/Skip-Gram)学习词向量:
CBOW:用上下文预测中心词,适合高频词学习。
Skip-Gram:用中心词预测上下文,适合低频词建模。优化方法包括负采样和层次Softmax。
文本分类、关键词匹配、语义相似度计算(如词类比任务:king - man + woman ≈ queen)。
GloVe基于全局词共现矩阵的统计信息,通过矩阵分解学习词向量:
使用加权回归损失函数,结合词与上下文的共现频率(如距离衰减加权)生成低维向量。
词相似度计算、文档聚类、信息检索(捕捉全局语义关系)。
FastText引入子词(Subword)信息:将单词拆分为字符级n-gram,通过子词向量求和生成词向量,解决未登录词(OOV)问题。形态丰富的语言处理(如土耳其语)、社交媒体文本分析(处理拼写变体)。

4.2 动态嵌入

词嵌入名称实现原理常见应用
ELMo基于双向LSTM生成上下文相关词向量:
- 前向LSTM捕捉左上下文,后向LSTM捕捉右上下文,多层LSTM输出的加权组合形成动态嵌入。
词义消歧(如区分“bank”的金融/地理含义)、命名实体识别。
BERT基于Transformer编码器的双向预训练模型:
掩码语言模型(MLM):随机掩码15%的词并预测。
下一句预测(NSP):判断句子间的连贯性。
问答系统(如SQuAD)、文本分类、情感分析、机器翻译(微调后)。
GPT系列基于Transformer解码器的自回归模型:
- 通过单向语言模型(预测下一个词)生成上下文相关向量,逐层叠加解码器。
文本生成(如故事续写)、对话系统、代码生成(如GPT-3)。
RoBERTaBERT的改进版本:
- 移除NSP任务,动态调整掩码模式,增大训练数据量和批量大小,提升模型鲁棒性。
语义相似度计算、大规模文本分类(如新闻主题分类)。
ALBERT通过参数共享(跨层参数复用)和嵌入分解(拆分词嵌入维度)压缩模型规模,降低计算成本。资源受限场景(如移动端部署)、多语言任务(参数效率高)。

5. 总结

个人认为,所谓的词嵌入,就是计算机通过思考人类提供的知识(语言),从而构建自己的认知框架(词向量空间)的过程。某种意义上,可以说词嵌入让计算机在词汇方面学会了和人类相似的思考。尽管词嵌入在现阶段更多地被当成是NLP领域的步骤之一,但我看到的是它让计算机“通过对知识的思考,构建了认知体系”。其背后的原理值得我们深思,其未来的发展值得我们期待。:)