3. 多语言词向量与嵌入:静态词向量(Word2Vec、FastText)、上下文嵌入(BERT、XLM-R)、跨语言对齐与映射
好,咱们今天聊聊多语言词向量。说实话,这个领域我踩过不少坑。早期做跨语言情感分析时,我天真地以为把中文词向量和英文词向量直接拼在一起就能用,结果模型训练出来一塌糊涂。后来才明白,不同语言的空间压根不在一个坐标系里。
多语言词向量的核心,说白了就是让不同语言的词语在同一个向量空间里找到自己的位置。这样,中文的「苹果」和英文的「apple」距离很近,而「苹果」和「汽车」距离很远。嗯,这个目标听起来简单,实现起来却各有门道。
3.1 静态词向量:Word2Vec 与 FastText
静态词向量,就是每个词只有一个固定的向量表示。不管这个词出现在什么语境里,它的向量都不变。我刚开始做 NLP 时,用的就是这种方案。
3.1.1 Word2Vec:经典但有限
Word2Vec 有两种训练方式:CBOW 和 Skip-gram。CBOW 用上下文预测当前词,Skip-gram 用当前词预测上下文。我个人习惯用 Skip-gram,尤其在数据量不大的时候,它对低频词的表现更好。
但 Word2Vec 有个硬伤——它不认识没见过的词。你在训练集里没见过「元宇宙」,那模型就傻眼了。而且它无法处理词形变化,比如「run」和「running」在它眼里是完全不同的词。
3.1.2 FastText:子词信息的引入
FastText 是 Word2Vec 的升级版。它把每个词拆成字符级别的 n-gram。比如「apple」拆成「ap」、「pp」、「pl」、「le」这些子词。这样即使遇到新词,只要它的子词在训练中出现过,就能拼出向量。
我在做一个多语言电商评论分析项目时,遇到过大量拼写错误和变体词。比如用户把「delicious」打成「delicous」。Word2Vec 直接报错,FastText 却能通过子词匹配给出合理向量。这就是它的优势。
# FastText 训练示例(伪代码)
from gensim.models import FastText
# 假设我们有中英文混合的语料
sentences = [['我', '喜欢', 'apple'], ['he', 'likes', '苹果']]
# 训练 FastText 模型
model = FastText(sentences, vector_size=100, window=5, min_count=1, workers=4)
# 获取词向量
vec_apple = model.wv['apple'] # 存在
vec_appple = model.wv['appple'] # 不存在,但通过子词也能生成向量
3.2 上下文嵌入:BERT 与 XLM-R
静态词向量有个根本问题——一词多义。比如「bank」可以是银行,也可以是河岸。静态向量只能给一个平均表示,这显然不够用。
上下文嵌入就解决了这个问题。每个词的向量会根据它所在的句子动态变化。你想想看,这多符合人类理解语言的方式。
3.2.1 BERT:双向编码的突破
BERT 用 Transformer 的编码器,通过 Masked Language Model 任务训练。它同时看一个词左右两边的上下文,所以叫「双向」。我记得第一次用 BERT 做中文分词时,效果比传统方法好了将近 10 个点。
但 BERT 有个问题——它是单语言的。你用中文 BERT 处理英文,效果会大打折扣。而且不同语言的 BERT 模型,向量空间是独立的,没法直接比较。
3.2.2 XLM-R:真正的多语言王者
XLM-R 是 Facebook 推出的多语言模型,在 100 种语言上训练。它用了一个技巧——共享词表。所有语言的 token 都映射到同一个词表里,这样模型就能学到跨语言的共性。
我在做一个东南亚多语言客服系统时,用了 XLM-R 做句子编码。泰语、越南语、印尼语混在一起,模型照样能准确理解意图。说实话,当时我被惊艳到了。
# 使用 XLM-R 获取上下文嵌入
from transformers import XLMRobertaTokenizer, XLMRobertaModel
tokenizer = XLMRobertaTokenizer.from_pretrained('xlm-roberta-base')
model = XLMRobertaModel.from_pretrained('xlm-roberta-base')
# 中英文混合句子
text = "I like 苹果 and 香蕉"
inputs = tokenizer(text, return_tensors='pt')
outputs = model(**inputs)
# 获取每个 token 的上下文向量
token_embeddings = outputs.last_hidden_state
3.3 跨语言对齐与映射
好,现在问题来了。我们有中文词向量空间,也有英文词向量空间,怎么让它们对齐?
跨语言对齐,说白了就是找到一个映射矩阵,把一种语言的向量空间映射到另一种语言的空间里。这样,中文的「猫」和英文的「cat」在映射后的空间里距离很近。
3.3.1 基于映射的方法
最经典的方法是使用双语词典做监督学习。比如我们有 5000 对中英文词对,用这些词对训练一个线性映射矩阵 W。训练目标是让映射后的中文词向量和对应的英文词向量尽可能接近。
我曾经试过用这种方法做中英跨语言情感分析。效果还行,但有个坑——映射后的空间会有扭曲。有些词映射得很好,有些词却跑偏了。后来我改用正交约束,效果稳定了不少。
# 跨语言映射示例(伪代码)
import numpy as np
# 假设我们有中英文词向量矩阵
X = chinese_vectors # 形状: (n, d)
Y = english_vectors # 形状: (n, d)
# 求解映射矩阵 W,使得 ||XW - Y|| 最小
# 使用正交约束保证映射保距
U, _, Vt = np.linalg.svd(Y.T @ X)
W = U @ Vt
# 映射中文词向量到英文空间
mapped_vector = chinese_word_vector @ W
3.3.2 无监督对齐方法
没有双语词典怎么办?别急,还有无监督方法。核心思想是利用向量空间的几何结构。不同语言的词向量空间,虽然坐标系不同,但几何结构是相似的。比如「国王-王后」和「king-queen」的向量差应该差不多。
我记得有一篇论文用 GAN 做无监督对齐,效果出奇的好。生成器负责把一种语言的向量映射到另一种语言,判别器负责判断映射后的向量是否和真实向量分布一致。嗯,这个思路很巧妙。
3.3.3 多语言 BERT 的隐式对齐
XLM-R 这类多语言模型,其实已经隐式地做了跨语言对齐。因为它在训练时,不同语言的 token 共享同一个 Transformer 层,模型被迫学习跨语言的共性。
我在实际项目中发现,XLM-R 的最后一层隐藏状态,天然具有跨语言对齐的特性。你拿中文句子和英文句子分别过模型,得到的句子向量可以直接比较相似度。这比单独训练映射矩阵方便多了。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Word2Vec | 训练快,资源消耗小 | OOV 问题,无上下文 | 小规模项目,资源受限 |
| FastText | 处理 OOV,支持子词 | 仍为静态表示 | 拼写错误多,形态丰富语言 |
| BERT | 上下文感知,效果好 | 单语言,模型大 | 需要高质量语义理解 |
| XLM-R | 多语言,隐式对齐 | 模型巨大,推理慢 | 多语言混合场景 |
| 映射对齐 | 可解释性强 | 需要双语词典 | 有双语资源时 |
最后说一句,词向量这个领域发展很快。从静态到动态,从单语言到多语言,每一步都在解决实际问题。我当年做跨语言项目时,光是对齐就折腾了两个月。现在有了 XLM-R,几行代码就能搞定。技术迭代真快啊。