主题模型Gensim入门系列之四:文本相似度查询

2024-08-24 01:48

本文主要是介绍主题模型Gensim入门系列之四:文本相似度查询,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系列目录:

(1)主题模型Gensim入门系列之一:核心概念

(2)主题模型Gensim入门系列之二:语料和向量空间

(3)主题模型Gensim入门系列之三:主题和变换

(4)主题模型Gensim入门系列之四:文本相似度查询

————————————————————————————

 

本文主要介绍如何从一个语料库中,查询一个指定文本的相似文本。

 

1、创建语料

创建语料和之前的三节相似,代码如下:

from collections import defaultdict
from gensim import corporadocuments = ["Human machine interface for lab abc computer applications","A survey of user opinion of computer system response time","The EPS user interface management system","System and human system engineering testing of EPS","Relation of user perceived response time to error measurement","The generation of random binary unordered trees","The intersection graph of paths in trees","Graph minors IV Widths of trees and well quasi ordering","Graph minors A survey",
]# remove common words and tokenize
stoplist = set('for a of the and to in'.split())
texts = [[word for word in document.lower().split() if word not in stoplist]for document in documents
]# remove words that appear only once
frequency = defaultdict(int)
for text in texts:for token in text:frequency[token] += 1texts = [[token for token in text if frequency[token] > 1]for text in texts
]dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]

 

2、相似度接口

在02-Gensim系列之二:语料和向量空间和03-Gensim系列之三:主题和变换 中,介绍如何创建向量空间的语料,以及如何在不同的向量空间的转换。这是查询文档之间相似性的基础。

接下来通过上述的语料来说明如何实现相似度查询,以LSI模型为例:

from gensim import models
lsi = models.LsiModel(corpus, id2word=dictionary, num_topics=2)

在本示例中,不对LSI模型作详细解释,只对两点加以说明:(1)LSI为一个向量变换模型,它将文本从一个向量空间转换到另外一个向量空间。(2)LSI可以识别文本的模式和文本中单词之间的关系和主题。下面的LSI是一个2维向量空间,即包含2个主题,但是主题的数量是可以任意设置的。更多关于LSI模型的介绍可以参考:Latent Semantic Indexing:

现在,假设有一个用户输入一个查询 "Human computer interaction",则根据和查询的相似度,对原始语料中的9个文本进行排序。不像现在的搜索引擎,这里的相似度搜索仅仅为文本在概率上的相似性——没有语义上的、没有超链接等。

doc = "Human computer interaction"
vec_bow = dictionary.doc2bow(doc.lower().split())
vec_lsi = lsi[vec_bow]  # 将查询文本转换到LSI模型的向量空间
print(vec_lsi)# 输出
"""
[(0, 0.4618210045327158), (1, 0.07002766527900064)]
"""

另外,我们将考虑使用余弦距离来计算两个向量之间的相似度。余弦相似度是计算向量举例的一种常用方法,但是在向量表示概率分布的时候,使用 different similarity measures可能是更好的选择。

 

3、初始化查询结构

为了准备后续的查询,我们需要对用于查询的语料进行处理。在本样例中,9个文本均用于LSI模型的训练,此处将它们都转换到2-D的LSA向量空间。当然我们也可以用训练好的模型,将非训练集的样本进行转换。

from gensim import similarities
index = similarities.MatrixSimilarity(lsi[corpus])  # 将语料转换到LSI空间并建立索引

值得注意的是,similarities.MatrixSimilarity 类将把所有的向量导入内存,举例来说,一个100万规模的语料如果转换为256维的向量可能需要2GB的内存。如果不想消耗这么大的内存,可以使用 similarities.Similarity 类,这种方法只占用固定的内存(较小的内存),通过将语料文件切分成多个部分。这个类的内部使用 similarities.MatrixSimilarity 和 similarities.SparseMatrixSimilarity,所以这个方法仍然很快,但是稍微复杂一点。

建立的索引可以通过 save() 和 load() 两个方法进行保存和加载。

index.save("lsi_index.index")
index=similarities.MatrixSimilarity。load("lsi_index.index")

上述的保存和加载方法对所有的索引类都有效(包括similarities.Similarity,similarities.MatrixSimilarity和   similarities.SparseMatrixSimilarity)。如果出现异常,可以尝试使用 similarities.Similarity,它的兼容性最好,且支持增量索引。

 

4、进行查询

在将查询转换到LSI空间,且将原始语料转换到LSI空间并建立索引之后,就可以获取查询文本和语料中文本的相似度了,代码如下:

sims = index[vec_lsi]  # 获取查询文本和语料中文本的相似度
print(list(enumerate(sims)))  # 打印 (文本序号, 文本相似度) 2元元组#输出
"""
[(0, 0.998093), (1, 0.93748635), (2, 0.9984453), (3, 0.9865886), (4, 0.90755945), (5, -0.12416792), (6, -0.10639259), (7, -0.09879464), (8, 0.050041765)]"""

由于余弦举例在(-1,1)之间,因此查询文本和语料中的第一个文本的相似度得分为 0.99809301,对语料中的文本根据相似度进行排序:

sims = sorted(enumerate(sims), key=lambda item: -item[1])
for i, s in enumerate(sims):print(s, documents[i])# 输出
"""
(2, 0.9984453) Human machine interface for lab abc computer applications
(0, 0.998093) A survey of user opinion of computer system response time
(3, 0.9865886) The EPS user interface management system
(1, 0.93748635) System and human system engineering testing of EPS
(4, 0.90755945) Relation of user perceived response time to error measurement
(8, 0.050041765) The generation of random binary unordered trees
(7, -0.09879464) The intersection graph of paths in trees
(6, -0.10639259) Graph minors IV Widths of trees and well quasi ordering
(5, -0.12416792) Graph minors A survey
"""

值得注意的是,假如采用标准的全文搜索的话,第3个文档 "The EPS user interface management system" 和第4个文档”Relation of user perceived response time to error measurement“ 将不会返回,因为他们和查询文本"Human computer interaction"没有 任何相同的关键词,但是在使用了LSI之后,这两个文本和查询文本的相似度都非常高,这也比较符合我们的直觉。事实上,这也是我们为什么要采用主题模型并进行变换的原因。

 

翻译和编辑自:Similarity Queries

这篇关于主题模型Gensim入门系列之四:文本相似度查询的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101104

相关文章

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

XML重复查询一条Sql语句的解决方法

《XML重复查询一条Sql语句的解决方法》文章分析了XML重复查询与日志失效问题,指出因DTO缺少@Data注解导致日志无法格式化、空指针风险及参数穿透,进而引发性能灾难,解决方案为在Controll... 目录一、核心问题:从SQL重复执行到日志失效二、根因剖析:DTO断裂引发的级联故障三、解决方案:修复

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

mysql查询使用_rowid虚拟列的示例

《mysql查询使用_rowid虚拟列的示例》MySQL中,_rowid是InnoDB虚拟列,用于无主键表的行ID查询,若存在主键或唯一列,则指向其,否则使用隐藏ID(不稳定),推荐使用ROW_NUM... 目录1. 基本查询(适用于没有主键的表)2. 检查表是否支持 _rowid3. 注意事项4. 最佳实