ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Gensim 软余弦度量(Soft Cosine Measure)实战指南:从 Word2Vec 词相似度到语义文本检索

Gensim 软余弦度量(Soft Cosine Measure)实战指南:从 Word2Vec 词相似度到语义文本检索 Gensim 软余弦度量Soft Cosine Measure实战指南从 Word2Vec 词相似度到语义文本检索【免费下载链接】gensimTopic Modelling for Humans项目地址: https://gitcode.com/gh_mirrors/ge/gensim导读软余弦度量Soft Cosine MeasureSCM让 Gensim 能够衡量“完全没有共同单词”的两篇文档之间的语义相似度其核心思路是用词向量之间的相似度构造非正交基再在非正交基下计算加权的余弦相似度。本文以 Gensim 官方教程docs/src/auto_examples/tutorials/run_scm.rst为主线完整讲解inner_product单次计算与SoftCosineSimilarity语料库检索两大 API 的用法并结合 gensim/similarities/termsim.py 的源码解析其内部机理与参数语义。读完本文你将能够用几行代码在 Gensim 中搭建一套“零词重叠也能排序”的语义检索流程。Soft Cosine Measure 原理与动机Soft Cosine Measure 是一种语义文本相似度方法即使两篇文档没有任何单词重合也能给出有意义的相似度评分。它首先需要一种“词与词之间的相似度”在 Gensim 的实践中这种词相似度通常由 Word2Vec 词向量Mikolov et al., 2013的余弦相似度导出在社区问答Community Question Answering场景下SCM 已被证明在语义文本相似度任务上优于许多当时的 SOTA 方法Charlet Damnati, 2017。SCM 的直观想法是文档仍然使用词袋bag-of-words即单词在文档中的频次向量表示但不再假设基向量两两正交而是假设文档向量表达在一组非正交基上——两个基向量即两个词之间的夹角由这两个词对应的 Word2Vec 向量的夹角决定。于是普通余弦相似度被推广为“软”形式两个文档即使表面词完全不同只要内部词义相近如 “president” 与 “Obama”、“press” 与 “media”就能获得较高的相似度。这一方法最早见于 Grigori Sidorov、Alexander Gelbukh、Helena Gomez-Adorno 与 David Pinto 的论文Soft Measure and Soft Cosine Measure: Measure of Features in Vector Space Model2014。Gensim 中的高效实现细节则参考了 Vít Novotný 的Implementation Notes for the Soft Cosine Measure2018——即 gensim/similarities/termsim.py 中SparseTermSimilarityMatrix.inner_product的 docstring 所引用的两篇文献。引用提示官方教程明确建议如果使用 Gensim 的 SCM 功能请考虑引用论文 [1]Sidorov et al.、[2]SimBow / SemEval-2017 Task 3和 [3]Novotný 的实现笔记详见文末参考文献。Gensim 中的 SCM 功能总览Gensim 的 SCM 功能由两大部分组成教程中分别对应两种使用场景API使用场景实现位置SparseTermSimilarityMatrix.inner_product一次性计算少量文档/查询之间的相似度gensim/similarities/termsim.pySoftCosineSimilarity类基于整个语料库建立索引支持index[query]式批量检索gensim/similarities/docsim.py两者都依赖同一个核心组件——词相似度矩阵term similarity matrix一个以词典Dictionary词汇为行/列的方阵S[i][j]表示词 i 与词 j 的相似度对角线上恒为 1.0。该矩阵由SparseTermSimilarityMatrix构建而其词相似度来源term similarity index则是可插拔的目前仓库提供了三种索引WordEmbeddingSimilarityIndex基于词向量余弦相似度教程所用UniformTermSimilarityIndex假设任意两个不同词之间的相似度是某个常数主要用于测试见 gensim/similarities/termsim.pyLevenshteinSimilarityIndex基于 Levenshtein 编辑距离的拼写相似度见 gensim/similarities/levenshtein.py。下面我们按教程的完整流程逐步实现。准备工作数据与依赖SCM 需要现成的词向量。你可以自己训练 Word2Vec 模型教程指向 run_word2vec 示例本文不再展开也可以像教程一样直接使用 Gensim 下载器加载预训练模型。先初始化日志并准备三句用于演示的句子import logging logging.basicConfig(format%(asctime)s : %(levelname)s : %(message)s, levellogging.INFO) sentence_obama Obama speaks to the media in Illinois sentence_president The president greets the press in Chicago sentence_orange Oranges are my favorite fruit前两句内容高度相关Obama 对媒体讲话 / 总统在芝加哥问候记者SCM 应当给出较高分数第三句与前两句完全无关SCM 应当很低。预处理去除停用词在计算相似度之前先移除 “the”“to” 等停用词因为它们对句子的信息量贡献不大。教程使用 NLTK 的英文停用词表from nltk.corpus import stopwords from nltk import download download(stopwords) # 下载停用词表 stop_words stopwords.words(english) def preprocess(sentence): return [w for w in sentence.lower().split() if w not in stop_words] sentence_obama preprocess(sentence_obama) sentence_president preprocess(sentence_president) sentence_orange preprocess(sentence_orange)首次运行时输出类似[nltk_data] Downloading package stopwords to /home/witiko/nltk_data... [nltk_data] Package stopwords is already up-to-date!构建词袋BoW与 TF-IDF 表示SCM 的文档向量仍是词袋形式因此接下来用Dictionary把分词结果映射为词袋向量再用TfidfModel做加权from gensim.corpora import Dictionary documents [sentence_obama, sentence_president, sentence_orange] dictionary Dictionary(documents) sentence_obama dictionary.doc2bow(sentence_obama) sentence_president dictionary.doc2bow(sentence_president) sentence_orange dictionary.doc2bow(sentence_orange) from gensim.models import TfidfModel documents [sentence_obama, sentence_president, sentence_orange] tfidf TfidfModel(documents) sentence_obama tfidf[sentence_obama] sentence_president tfidf[sentence_president] sentence_orange tfidf[sentence_orange]TF-IDF 在这里有两个作用一方面它是对词袋向量的标准加权另一方面从源码看gensim/similarities/termsim.py_create_source在构建词相似度矩阵时会按 TF-IDF 重要性降序决定矩阵列的填充顺序即越重要的词越优先获得其相似词条目若未提供tfidf参数则按词典 id 顺序处理。这能保证在矩阵规模受限时重要的词仍然保留最丰富的相似关系。加载词向量并构建词相似度矩阵教程使用 Google News 预训练词向量约 300 维import gensim.downloader as api model api.load(word2vec-google-news-300) from gensim.similarities import SparseTermSimilarityMatrix, WordEmbeddingSimilarityIndex termsim_index WordEmbeddingSimilarityIndex(model) termsim_matrix SparseTermSimilarityMatrix(termsim_index, dictionary, tfidf)注意内存警告教程明确标注“这里选择的词向量需要大量内存”。该示例脚本的整体预估内存占用约为7701 MB运行耗时约 57 秒见 run_scm.rst 底部的sphx-glr-timing元数据。在真实项目中请务必评估机器内存或改用更小的预训练模型 / 自训练模型。WordEmbeddingSimilarityIndex 的构造参数WordEmbeddingSimilarityIndexgensim/similarities/termsim.py的核心逻辑是对每个词用KeyedVectors.most_similar找出最相似的词只保留相似度高于threshold的词并对其相似度取exponent次幂。构造参数如下参数默认值含义keyedvectors必填词向量对象KeyedVectors如api.load(...)的返回threshold0.0只有相似度大于该阈值的词对才会被保留exponent2.0对超过阈值的词相似度取幂例如取 2 次幂可压低低相似度项kwargsNone透传给most_similar的关键字参数如{indexer: AnnoyIndexer(...)}加速近邻查找SparseTermSimilarityMatrix 的构造参数SparseTermSimilarityMatrixgensim/similarities/termsim.py把索引展开为真正的稀疏矩阵其__init__签名与参数语义如下参数默认值含义source必填词相似度索引TermSimilarityIndex或一个现成的scipy.sparse稀疏矩阵此时其余参数被忽略dictionaryNone词典决定矩阵的行/列维度与词索引映射传入稀疏矩阵时可为NonetfidfNoneTfidfModel用于决定矩阵列的构建优先级按 TF-IDF 降序symmetricTrue是否强制矩阵对称。对称是正定性的必要条件后续若要用 Cholesky 分解导出基变换矩阵则必须对称设为False可显著降低构建期内存dominantFalse是否强制严格列对角占优。与对称性一起构成正定性的充分条件nonzero_limit100每列对角元之外最多保留的非零元素数None表示不限制dtypenp.float32矩阵数据类型支持float16 / float32 / float64从构建逻辑termsim.py 的_create_source可以看到几个工程细节每列至少写入对角元素 1.0即词与自身的相似度为 1每个词的相似词取自索引的most_similar(t1, topnnum_rows)只保留出现在词典中的词若启用symmetric一个词对的两个方向都会被写入且用assigned_cells集合去重若启用dominant则会检查“添加该相似度后列绝对值之和是否 ≥ 1.0”从而维持严格对角占优构建完成后会打印矩阵密度日志如constructed a sparse term similarity matrix with 0.xx% density。为什么是“稀疏”矩阵词向量空间中任意两个词都可能有一定相似度理论上词相似矩阵是全稠密的对大规模词典而言存储和运算都不可行。nonzero_limit默认 100把每一列限制为最多 100 个非对角非零项使矩阵保持稀疏这是 SCM 能够落地到大规模词典的关键设计。用 inner_product 一次性计算 SCM词相似矩阵就绪后即可调用termsim_matrix.inner_product(vec1, vec2, normalized(True, True))计算两个文档的软余弦相似度similarity termsim_matrix.inner_product( sentence_obama, sentence_president, normalized(True, True) ) print(similarity %.4f % similarity)输出similarity 0.2575再比较一对完全无关的句子similarity termsim_matrix.inner_product( sentence_obama, sentence_orange, normalized(True, True) ) print(similarity %.4f % similarity)输出similarity 0.0000可以看到语义相关但无共同词的句子得到 0.2575无关句子得到 0.0000这正是 SCM 的价值所在——标准余弦相似度对这两对句子都会给出 0。normalized 参数的三态语义inner_product(X, Y, normalized(...))的normalized是一个二元组分别控制查询向量 X 与文档向量 Y 的归一化方式termsim.py#L518-L584。每个元素可取三个值取值数学含义对应方法True在基变换后做 L2 归一化即软余弦度量本身教程使用maintain基变换后保持向量的原始 L2 范数对应带部分成员归属的查询扩展query expansion with partial membershipFalse基变换后不做归一化对应普通查询扩展query expansion实现上termsim.py#L314-L348归一化是通过在基变换矩阵词相似矩阵下计算vector^T · S · vector的平方根完成的因此要求矩阵对任意非零词袋向量 x 满足x^T · S · x 0即半正定。当normalized(True, True)时最终结果还会被裁剪到[-1.0, 1.0]区间。此外inner_product支持“向量 × 向量”“向量 × 语料库”“语料库 × 语料库”三种输入形态返回标量、numpy数组或稀疏矩阵。关于归一化行为的正确性可参考 gensim/test/test_similarities.py 中TestSoftCosineSimilarity第 385 行起以及test_inner_product_vector_vector_true_true等一组测试用例第 1185–1267 行它们覆盖了True / False / maintain的九种组合与空向量边界情况如inner_product([], [])返回 0.0。语料库级相似度检索SoftCosineSimilarity对于“给定查询返回语料库中最相关的 N 篇文档”这类批量场景应当使用SoftCosineSimilarity类gensim/similarities/docsim.py#L883-L1006。它把整个语料库的词袋向量连同词相似矩阵保存在内存中构造参数如下参数默认值含义corpus必填词袋格式list of(id, weight)的文档集合similarity_matrix必填前面构建的SparseTermSimilarityMatrixnum_bestNone每次查询返回的最相似文档数None返回与全部文档的相似度chunksize256每次处理的语料块大小normalizedNone已弃用的别名等价于(normalize_queries, normalize_documents)传入时会触发DeprecationWarning将在 5.0.0 移除normalize_queriesTrue查询向量是否在基变换后 L2 归一化对应软余弦度量normalize_documentsTrue文档向量是否在基变换后 L2 归一化典型用法from gensim.similarities import SoftCosineSimilarity # corpus 为词袋格式的文档列表similarity_matrix 复用上文的 termsim_matrix docsim_index SoftCosineSimilarity(bow_corpus, termsim_matrix, num_best10) query Obama speaks in Illinois.split() sims docsim_index[dictionary.doc2bow(query)] # 返回与每篇文档的相似度其内部实现get_similaritiesdocsim.py#L973-L1003本质上就是把查询/文档整体交给self.similarity_matrix.inner_product(query, self.corpus, normalizedself.normalized)再统一转成numpy数组。同时SoftCosineSimilarity实现了interfaces.SimilarityABC接口因此支持len()、self[query]下标语法等标准的 Gensim 相似度索引约定值得注意的是它将自身的normalize置为False因为软余弦需要基于词相似矩阵的特殊归一化若再按普通向量归一化会造成二次归一化、放大数值误差docsim.py#L962-L965。进阶替换词相似度来源词相似度矩阵的构建是“索引可插拔”的因此 SCM 并不局限于词向量一种来源拼写相似度对 OCR 文本或含拼写变体的语料可用LevenshteinSimilarityIndex计算词间编辑距离相似度从而让“softly”与“soft”这类词相互贡献相似度常数相似度UniformTermSimilarityIndex(dictionary, term_similarity0.5)假设所有不同词对的相似度为同一常数它主要面向单元测试termsim.py#L67-L97但也适合快速验证矩阵构建与检索管线是否正确复用现成矩阵SparseTermSimilarityMatrix的source参数允许直接传入一个scipy.sparse稀疏矩阵此时忽略dictionary、tfidf等其余参数方便把构建好的矩阵序列化保存、加载复用跳过昂贵的重构建过程。工程实践注意事项内存是头号约束预训练word2vec-google-news-300本身约 3.6 GB示例整体预估内存约 7.7 GB。构建大词典的词相似矩阵前建议先用小词典试跑并观察构建日志中的矩阵密度合理设置nonzero_limit默认 100 意味着每列最多 100 个相似词词典很大时可适当调小以控制矩阵规模语义近似度要求高时可调大symmetric与dominant只有当你后续需要基于 Cholesky 分解导出基变换矩阵例如在非正交基下做更严格的数学推导时才必须开启纯检索场景可以关闭symmetric以显著降低构建期内存归一化语义别搞混normalized(True, True)才是严格意义上的软余弦度量maintain与False对应不同的查询扩展变体选择前请确认你要的数学含义空输入是合法的inner_product对空向量返回 0.0见 test_similarities.py 中的零向量测试组生产代码无需额外防御。参考文献Grigori Sidorov et al.Soft Similarity and Soft Cosine Measure: Similarity of Features in Vector Space Model, 2014.Delphine Charlet and Geraldine Damnati,SimBow at SemEval-2017 Task 3: Soft-Cosine Semantic Similarity between Questions for Community Question Answering, 2017.Vít Novotný.Implementation Notes for the Soft Cosine Measure, 2018.Tomáš Mikolov et al.Efficient Estimation of Word Representations in Vector Space, 2013.完整的可运行示例代码见 docs/src/auto_examples/tutorials/run_scm.py 与对应的 Jupyter 笔记本 docs/src/auto_examples/tutorials/run_scm.ipynb核心 API 的源码位于 gensim/similarities/termsim.py 与 gensim/similarities/docsim.py。【免费下载链接】gensimTopic Modelling for Humans项目地址: https://gitcode.com/gh_mirrors/ge/gensim创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表