“我思故我在向量空间”
1. 认识语言
自然语言——人类最伟大的发明
作为思维载体和沟通桥梁,语言不仅塑造认知范式,更催生情感共鸣与社会协作、记录经验、传递知识……使人类能在科学、艺术、文化、工业等几乎所有领域不断积累和发展。毫不过分地说,语言是传承人类文明、造就现代人类文明世界的基石。
语言学不是这篇文章的重点,所以我们简单概括了解。
自然语言的基本要素
- 语义——语言背后语言的含义
- 语法——语言的组织方式
自然语言的载体
- 文字——语言的视觉载体
- 发音——语言的听觉载体
1.4 计算机认识的自然语言
对计算机而言,语言的文字和发音更多作为词语标签的形式存在,正真用于理解人类自然语言的,更多是通过学习语义和语法。
2. 词向量(Word Vector)
2.1 词向量用于解释语义
词向量是包含了解释语义的向量。其不同维度的分量代表了不同维度是抽象特征,由模型根据实际词汇表自动训练而成,可理解为该词在不同维度的意义。
以我们对“国王”一词,可在从多个维度进行解读:
- 生物维度:“国王”是“人”,与“猫”、“狗”等不同生物在同一维度有所不同;
- 政治身份维度:“国王”是“王”,与“诸侯”、“平民”等不同政治身份的人在同一维度有所区别;
- 性别维度:“国王”通常是“男”,与“女”、“无性别”(如无性繁殖生物的性别)有所区别;
- …
词向量也会在不同的维度解读“国王”一词。
需注意的是,词向量对语义各维度的解读,通常不会跟人类的解读一致。
我们对于词语的解读基于庞大的现实世界,而词向量对语义的解读,仅来源于有限的数据集。
简单来说,对于自然语言的词汇,尽管人类和计算机都会用不同维度去解读,但人类有适合人类的解读方式,计算机有适合计算机的解读方式。
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典型处理流程
- 语料库(Raw Corpus)
- 原始文本数据(如书籍、网页、对话记录等)。
- 示例:
["I love cat.", "Attention is all you need."]
- 预处理(Preprocessing)
- 分词(Tokenization):将文本分割为词或子词单元。
- 示例:
["I", "love", "
cat
", ".", "Attention
", "is
", "
, "
"all
you
","
"."]
",need
- 示例:
- 清洗(Cleaning):去除噪声(如HTML标签、特殊符号)、标准化(如小写化)。
- 编码(Indexing):为每个词分配唯一ID(构建词汇表)。
- 示例:
{"I": 0, "love": 1, "
cat
": 2, ...}
- 示例:
- 分词(Tokenization):将文本分割为词或子词单元。
- 数值化表示(Vectorization)
- 词嵌入(Word Embedding):将词ID映射为词向量(如Word2Vec、BERT)。
- 位置编码(Positional Encoding):注入位置信息(如绝对位置、相对位置)。
- 其他编码(可选):段编码(区分句子)、模态编码(多模态任务)。
- 模型输入(Model Input)
- 最终形式:词向量 + 位置向量(+ 其他编码)的拼接或相加。
- 数学表示:Input = WordEmbedding(token_ids) + PositionalEncoding(positions)
3.2 早期词嵌入
早期词嵌入技术最常见的两种主要是词袋模型(BoW)和独热编码(one-hot)。
3.2.1 词袋模型(Bag of Words, BoW)
词袋模型通过统计文本中单词的出现频率(或存在性)来表示文本。比起“编码”,它更偏向于“统计”。
步骤
- 构建词汇表:从所有文本中提取唯一单词,形成词汇表(如:["我", "喜欢", "睡觉", "他", "吃饭"])。
- 生成向量:对每个文本,统计词汇表中每个单词的出现次数(或是否出现),形成一个向量。
示例
- 句子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 词嵌入的进化
- 早期探索(2000年以前)
- 统计语言模型:早期的NLP依赖词袋模型(BoW)和独热编码,仅关注词频统计,缺乏语义关联,且面临维度灾难问题。
- 概率模型与降维:2000年,约书亚·本希奥(Yoshua Bengio)提出神经概率语言模型,首次通过神经网络学习词的分布式表示;同年,Roweis和Saul在《科学》发表的局部线性嵌入(LLE)方法,为高维数据降维提供了新思路。
- 突破阶段(2010年代)
- Word2Vec的诞生:2013年,谷歌团队(Tomas Mikolov等)推出Word2Vec工具,通过浅层神经网络(如CBOW和Skip-gram)高效生成词向量,显著提升了训练速度和语义捕捉能力,成为里程碑式突破。
- GloVe的全局优化:2014年,斯坦福大学的GloVe模型结合全局词共现矩阵和局部上下文,进一步优化低频词的表示效果。
- 动态嵌入时代(2018年后)
- 上下文感知模型:以ELMo、BERT为代表的动态词嵌入模型兴起,通过预训练和注意力机制,使词向量能根据上下文动态调整,解决了一词多义问题。
3.3.2 词嵌入的分类
根据生成后的词向量是否固定(与上下文无关),词嵌入可分为静态嵌入和动态嵌入。
静态词嵌入 | 动态词嵌入 | |
---|---|---|
核心思想 | 每个词被映射到固定的向量,与上下文无关。 | 词向量根据上下文动态生成,同一词在不同语境中向量不同。 |
上下文处理 | ❌ 忽略上下文,所有场景下同一词向量相同。 | ✅ 基于上下文动态调整词向量。 |
词义消歧 | ❌ 无法处理多义词(如“苹果”在“水果”和“手机”中含义不同,但向量相同)。 | ✅ 能区分多义词(如“苹果”在不同句子中生成不同向量)。 |
模型结构 | 基于浅层神经网络或统计方法(如矩阵分解)。 | 基于深层预训练语言模型(如Transformer)。 |
训练数据量 | 通常需要中等规模语料库。 | 需要大规模语料库(如维基百科、书籍、网页文本)。 |
计算资源 | 训练和推理资源需求较低。 | 训练资源需求极高(需GPU/TPU),推理时资源消耗也较高。 |
应用场景 | 资源有限、简单任务(如文本分类、关键词匹配)。 | 复杂任务(如问答系统、机器翻译、语义理解)。 |
灵活性 | 词向量固定,无法适应新任务或领域。 | 可通过微调(Fine-tuning)适应特定任务或领域。 |
典型技术 | Word2Vec、GloVe、FastText | BERT、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)。 |
RoBERTa | BERT的改进版本: - 移除NSP任务,动态调整掩码模式,增大训练数据量和批量大小,提升模型鲁棒性。 | 语义相似度计算、大规模文本分类(如新闻主题分类)。 |
ALBERT | 通过参数共享(跨层参数复用)和嵌入分解(拆分词嵌入维度)压缩模型规模,降低计算成本。 | 资源受限场景(如移动端部署)、多语言任务(参数效率高)。 |
5. 总结
个人认为,所谓的词嵌入,就是计算机通过思考人类提供的知识(语言),从而构建自己的认知框架(词向量空间)的过程。某种意义上,可以说词嵌入让计算机在词汇方面学会了和人类相似的思考。尽管词嵌入在现阶段更多地被当成是NLP领域的步骤之一,但我看到的是它让计算机“通过对知识的思考,构建了认知体系”。其背后的原理值得我们深思,其未来的发展值得我们期待。:)
Comments NOTHING