> _先用世界上所有的文本得到共现矩阵, > 然后确定好参数也就是想做成几维,之后给每个词一个初始 embedding, > 再通过随机梯度下降移动这些 embedding,直到两个 embedding 的点积等于最初共生矩阵里的数的对数 大体上可以这么理解,**GloVe** 确实是基于全局共现信息来训练词向量的。 1. **GloVe 与传统"共现矩阵 + SVD"思路的关系** - GloVe 的核心思想是:词和词在全球范围内(整个语料)的共现频次 (co-occurrence frequency),能提供一个比较稳定的全局统计信息。 - 它会构建一个反映词之间"共现关系" (co-occurrence) 的目标函数,然后进行迭代式的优化训练,得到每个词的向量表示。 - 表面上看,GloVe 也和"共现矩阵 + 降维 (SVD)"的思路接近,但是 **GloVe 并不是简单地先显式构造一个完整 `N×N` 的共现矩阵再去做 SVD**,而是利用了一个针对共现频次的损失函数(以及权重函数)来直接训练出词向量。对比简单的 "共现矩阵 + SVD",GloVe 的训练目标会更灵活,也能避免储存超大矩阵的问题。 2. **预训练好的 GloVe 词向量** - 你在实验中用的 "GloVe 数据库" 或者官方提供的 "GloVe 预训练词向量"(如 `glove.6B`, `glove.42B`, `glove.840B` 等),确实是作者在**大规模语料**(比如维基百科、Common Crawl、Gigaword 等)上,按照 GloVe 的算法训练好后发布的。 - 这就好比他们在非常大的文本上做了全局的"共现统计 + 训练",得到了一套"通用" (general) 的词向量空间。我们可以直接拿过来用,不需要自己在本地再做"从头训练"。 3. **为什么成为"General 的向量空间"** - 因为他们的语料库覆盖面很广,包含新闻、百科等各种领域,学到的词向量能够在较多一般场景下表现得不错。 - 如果你的任务或领域非常特殊,也可以考虑自己在专业语料上重新训练(或者在通用 GloVe 上做微调),但最常见的方式是直接用这些预训练好的向量做初始化或做特征,帮助下游 NLP 任务。 因此,用你的话来说,**"GloVe数据库"可以理解为:他们(GloVe 的作者 / 维护者)在非常大规模的文本上做了'共现统计'以及对应的目标优化,最终得到一个通用的词向量空间**。我们下载后就可以直接使用它来进行相似度计算、类比、下游模型的 embedding 初始化等。 1. 首先构建共现矩阵X: ```Java 假设窗口大小=2,统计得到的共现次数是: cat dog pet cat 2 3 5 dog 3 1 4 pet 5 4 2 ``` 2. 对共现矩阵取对数log(X): ```Java cat dog pet cat 0.69 1.10 1.61 dog 1.10 0 1.39 pet 1.61 1.39 0.69 (注:这里是自然对数ln,保留两位小数) ``` 3. 开始训练GloVe模型: 假设我们想要学习2维的词向量(实际应用中通常是50-300维)。 初始随机化词向量和偏置项: ```Java # 随机初始化的词向量(wi): cat = [0.2, -0.5] dog = [0.1, 0.3] pet = [-0.3, 0.4] # 随机初始化的偏置项(bi): cat_bias = 0.1 dog_bias = -0.2 pet_bias = 0.3 ``` 1. 计算一个具体的预测值: 以cat和dog为例: ```Java # 计算 cat·dog + b_cat + b_dog: cat·dog = (0.2 × 0.1) + (-0.5 × 0.3) = -0.13 预测的值 = 词向量相似度(点积) + 第一个词的偏好 + 第二个词的偏好 预测值 = -0.13 + 0.1 + (-0.2) = -0.23 # 与实际的log值比较: 真实值 = 1.10 误差 = -0.23 - 1.10 = -1.33 ``` 2. 更新向量(使用梯度下降): ```Java learning_rate = 0.1 # 更新cat的向量: new_value = old_value - learning_rate × gradient × error # 原值 = 0.2 # learning_rate = 0.1 # error = -1.33 # gradient = dog[0] = 0.1 cat[0] = 0.2 + 0.1 × (-1.33) × dog[0] = 0.187 cat[1] = -0.5 + 0.1 × (-1.33) × dog[1] = -0.54 # 更新dog的向量: dog[0] = 0.1 + 0.1 × (-1.33) × cat[0] = 0.075 dog[1] = 0.3 + 0.1 × (-1.33) × cat[1] = 0.37 # 更新偏置项: cat_bias = 0.1 + 0.1 × (-1.33) = -0.033 dog_bias = -0.2 + 0.1 × (-1.33) = -0.333 ``` 3. 重复这个过程: - 对所有词对重复这个计算过程 - 多次迭代整个数据集 - 直到词向量收敛 最终得到的词向量会使得: ```Java cat·dog + b_cat + b_dog ≈ log(3) cat·pet + b_cat + b_pet ≈ log(5) dog·pet + b_dog + b_pet ≈ log(4) ``` 这样,通过最小化这些预测值与实际log共现值之间的差异,我们就得到了能够捕捉词语语义关系的词向量。这些词向量的几何关系会反映词语之间的语义关系。 所以GloVe: - ✓ 确实使用了全局的共现统计 - ✗ 但不是简单地分析共现矩阵 - ✓ 而是训练了一个模型来学习词向量 - ✓ 使词向量能够捕捉词之间的语义关系 这就是为什么它叫"Global Vectors": - Global:使用全局统计信息 - Vectors:通过模型学习获得的向量表示 这种方法的优势是: 1. 保留了全局统计信息 2. 同时通过模型学习得到更好的语义表示 3. 词向量具有良好的线性代数性质