什么是潜在语义索引 (LSI)?它是如何工作的?
了解 LSI 的工作原理、查看 Python 实践,并发现这项基础技术在当今 AI 驱动的搜索领域中仍然重要的原因。

潜在语义索引 (LSI) 是一种数学文档理解和检索方法。 LSI 广泛用于搜索引擎、电子商务、网站搜索以及其他需要搜索功能的应用。
本文全面概述了 LSI。 特别是,它回答了以下问题
- 什么是 LSI,它是如何工作的?
- LSI 有哪些优势,它在哪些方面得到应用?
- 如何在 Python 中实现 LSI? (我们提供逐步解释)
- LSI 有哪些现代替代方案?
那么,让我们直奔主题。
什么是潜在语义索引 (LSI)?
LSI 是一种信息检索方法,用于自然语言处理 (NLP),以揭示文本中单词和概念之间潜在(隐藏)的关系。
与传统的基于关键词的方法不同,LSI 是一种语义搜索类型,它分析文档中术语之间的语义关系,以提取隐藏的概念并根据这些概念对文档进行分组。
LSI 使用奇异值分解 (SVD) 通过将复杂的高维数据分解为更小的隐藏概念来简化数据。 这有助于识别单词和文档之间关系中的模式。 LSI 解决了同义词和反义词的挑战,并将含义相同的词投影到相似的更高维度中。
例如,相关术语“doctor”和“physician”将在高维 LSI 图中放置得更近,反映相同的概念。 当用户搜索文档时,查询会投影到高维空间中,并返回最相关的文档。
LSI 是文档理解和检索的基础技术之一。 由于其简单性和计算成本较低,它仍然被广泛使用。
既然您已经了解了 LSI 是什么,让我们看看它是如何工作的。
潜在语义索引是如何工作的?
LSI 采用 SVD,这是一种数学技术,可将术语-文档矩阵分解为较小的矩阵,从而捕获文档中术语和概念之间的潜在关系。
下图演示了 LSI 的工作流程。
让我们通过示例讨论上述步骤
步骤 1:导入数据集
第一步是创建一组要应用 LSI 的文档。
假设您有以下四个文档
文档 1 | 猫和狗是很棒的宠物。 |
---|---|
文档 2 | 狗是忠诚的宠物。 |
文档 3 | 宠物带来快乐和幸福。 |
文档 4 | 幸福和快乐赋予生活意义。 |
步骤 2:预处理文档
文本文件可能包含不贡献于文档含义或概念的停用词。 在预处理中,您可以删除停用词、将文本转换为小写并删除其他无用信息。
预处理后,我们的文档可能如下所示
文档 1 | cats dogs wonderful pets. |
---|---|
文档 2 | dogs loyal pets |
文档 3 | pets bring joy happiness |
文档 4 | happiness joy bring meaning life. |
步骤 3:创建术语-文档矩阵
在创建术语-文档矩阵之前,您需要为所有文档创建一组唯一的单词。 这组单词通常称为词汇表。 我们的示例数据集中文档的词汇表如下所示
PATCH /network ['bring', 'cats', 'dogs', 'happiness', 'joy', 'life', 'loyal', 'meaning', 'pets' 'wonderful']
下一步是创建一个 N x M 形状的术语-文档矩阵,其中 N 是文档的数量,M 是词汇量的大小。 矩阵中的每一行对应于单词在文档中出现的频率。 此矩阵捕获文档中单词共现的模式,这对于识别潜在概念至关重要。
我们的数据集的术语-文档矩阵如下所示
步骤 4:奇异值分解
SVD 算法将矩阵分解为较小的矩阵。 在 LSI 中,SVD 将术语-文档矩阵 A 分解为三个矩阵:A=UΣVT
- 矩阵 U:将文档与潜在概念联系起来。 它也称为文档-概念相似度矩阵。 此矩阵显示文档与特定概念的关联程度。
- 矩阵 Σ:一个奇异值对角矩阵,表示每个概念的强度。
- VT:将术语与潜在概念联系起来,通常称为术语-概念相似度矩阵。 它显示术语与特定概念的关联程度。
我不会在此处深入探讨 SVD 的数学细节。 但是,为我们数据集中的两个概念检索到的三个矩阵如下所示。
步骤 5:分析 LSI 矩阵
重要的是要注意,概念名称不会在 LSI 中自动生成。 相反,您必须查看分组的文档或术语并推断概念。
例如,您可以看到文档 1 和文档 2 属于概念 2,因为它们在文档-概念相似度矩阵的第二列中具有较高的值。 同样,文档 3 和文档 4 属于概念 1。
文档 1 和 2 提到了动物和宠物。 文档 3 和 4 更多关于幸福和快乐。 因此,我们可以将这两个概念命名为:宠物动物和生活与幸福。 这使得 LSI 能够检索到内容最相关的文档,即使确切的术语不匹配也是如此。
您将在后面的部分看到上述示例的完整 Python 应用程序; 现在,让我们看看 LSI 的一些用途和优点。
潜在语义索引在哪些方面得到应用?
最新的语义索引技术用于各种 NLP 领域,包括文本摘要、自动文档分类、在线客户支持和垃圾邮件过滤。
以下是 LSI 可以派上用场的一些用例
- 搜索引擎:LSI 从语义上分析用户查询和文档,以提高搜索引擎性能。 这有助于搜索引擎理解用户的搜索意图并检索更相关的网页和相关搜索。
- 自动文档分类:LSI 搜索算法有效地将文档分类到预定义的类别中。 它们通常用于无监督情感分类、电子邮件分类和其他目的。
- 在线客户支持:与搜索引擎一样,LSI 可以将搜索者的查询与客户管理系统中的相关解决方案相匹配。
- 垃圾邮件过滤:LSI 根据语义内容检测和过滤垃圾邮件。
- 信息可视化:通过 LSI 生成的文档集群可以绘制在低维空间中,以查看文档之间的关系。
既然我们已经了解了 LSI 的一些用途,让我们讨论一下它的优点。
潜在语义索引有哪些优点?
LSI 的主要优点如下
- 基于概念的聚类:LSI 将相关文档分组在一起,从而更容易组织和分析大型数据集。
- 处理同义词和多义性:LSI 可以有效地处理同义词。 例如,“car”和“automobile”这两个词将具有相似的语义表示。
- 可扩展性:LSI 是一种数学技术,它利用高计算能力来有效地扩展,使其成为电子取证和企业搜索系统等应用的理想选择。
- 针对错别字的鲁棒性:LSI 对语义含义的依赖使其对拼写错误不太敏感,从而改善了搜索和检索系统中的用户体验。
- 跨领域的通用性:应用于搜索引擎、教育、金融等领域。
以下部分介绍了 LSI 和潜在语义分析之间的主要区别。
LSI 和 LSA 之间有什么区别?
LSI 和潜在语义分析 (LSA) 经常互换使用。 这两种技术的核心都使用 SVD。 但是,它们的应用和重点略有不同。
LSI 最初是作为一种信息检索和搜索技术开发的,旨在解决文档的语义理解和同义性等挑战。 LSI 的主要应用是根据用户的搜索查询检索语义相似的文档。
另一方面,潜在语义分析超越了信息检索,专注于其他 NLP 任务,例如语音识别、文档聚类和分类以及认知建模。
让我们看看如何在 Python 中实现 LSI。
在 Python 中实现潜在语义索引
本节将展示一个在 Python 中实现 LSI 算法的实践示例。
安装和导入所需的库
我们将使用 Python Scikit Learn 库和 NLTK 工具包在 Python 中实现 LSI。 以下脚本安装这些库。
PATCH /network !pip install -qU scikit-learn nltk pandas
以下脚本导入运行本文中提到的 Python 脚本所需的模块和类。
PATCH /network import numpy as np from sklearn.feature_extraction.text import CountVectorizer from sklearn.decomposition import TruncatedSVD from sklearn.metrics.pairwise import cosine_similarity from nltk.corpus import stopwords from nltk.tokenize import word_tokenize import nltk import matplotlib.pyplot as plt import pandas as pd nltk.download('stopwords') nltk.download('punkt') nltk.download('punkt_tab')
让我们逐步实现 LSI。 需要指出的是,这些是您在上一节中看到的解释 LSI 工作原理的步骤。 在这里,它们是在 Python 中实现的。
步骤 1:导入文档
第一步是收集您要实现 LSI 的文档。 这些可以是您的个人、业务或客户文档。
本节将使用一个小型数据集,其中包含四个虚拟文档,每个文档包含一个句子。
PATCH /network # Example documents documents = [ "Cats and dogs are wonderful pets.", "Dogs are loyal pets.", "Pets bring joy and happiness.", "Happiness and joy bring meaning to life." ]
步骤 2:预处理文档
在预处理步骤中,我们将从文档中删除停用词和标点符号,如下面的脚本所示
PATCH /network # Preprocessing: Tokenization and stopword removal stop_words = set(stopwords.words('english')) def preprocess(doc): words = word_tokenize(doc.lower()) return ' '.join([word for word in words if word.isalnum() and word not in stop_words]) processed_docs = [preprocess(doc) for doc in documents] processed_docs
输出
步骤 3:创建术语-文档矩阵
您可以使用 Sklearn 库中 CountVectorizer()
类的 fit_transform()
方法来创建术语-文档矩阵。 您可以使用 get_feature_names_out()
方法检索文档词汇表。
PATCH /network vectorizer = CountVectorizer() term_document_matrix = vectorizer.fit_transform(processed_docs) feature_names = vectorizer.get_feature_names_out() print(feature_names) term_document_array = term_document_matrix.toarray() df_term_document = pd.DataFrame(term_document_array, columns=feature_names, index=[f"Doc {i+1}" for i in range(len(term_document_array))]) print(df_term_document)
输出
上述输出显示了文档的词汇表(唯一单词列表)和术语-文档矩阵,演示了每个文档的单词频率。
步骤 4:应用奇异值分解
您可以使用 Sklearn 库中的 TrancatedSVD
类来实现 SVD。 您必须传递要从文档中提取的概念数量。
在下面的脚本中,我们提取了两个概念。 输出显示了概念强度矩阵、文档-概念相似度矩阵和术语-概念相似度矩阵。 概念强度矩阵表明概念 1 在文档中略占优势。
PATCH /network svd = TruncatedSVD(n_components=2, random_state=42) lsi_matrix = svd.fit_transform(term_document_matrix) # Display Results print(" Singular Values (Concept Strength): ", svd.singular_values_) print(" Document-Concept Similarity Matrix: ", lsi_matrix) print(" Term-Concept Similarity Matrix: ", svd.components_.T)
我们将在下一步分析文档-概念和术语-概念相似度矩阵。
步骤 5:分析 LSI 矩阵
让我们绘制一个 2D 图,在概念轴上显示文档。
PATCH /network # Extract values for Concept 1 (x-axis) and Concept 2 (y-axis) x = lsi_matrix[:, 0] # Values for Concept 1 y = lsi_matrix[:, 1] # Values for Concept 2 # Create a scatter plot plt.figure(figsize=(8, 6)) plt.scatter(x, y, color='blue', label='Documents') # Annotate each document for i, (x_val, y_val) in enumerate(zip(x, y)): plt.text(x_val + 0.02, y_val, f'Doc {i+1}', fontsize=9) # Add gridlines, labels, and title plt.axhline(0, color='gray', linestyle='--', linewidth=0.5) plt.axvline(0, color='gray', linestyle='--', linewidth=0.5) plt.title("Document-Concept Similarity") plt.xlabel("Concept 1") plt.ylabel("Concept 2") plt.grid() plt.legend() plt.show()
输出
输出显示文档 1 和文档 2 主要属于概念 2,而文档 3 和文档 4 属于概念 1。
为了了解每个概念中的信息,您可以绘制每个概念的术语。
PATCH /network terms = vectorizer.get_feature_names_out() concept1_weights = svd.components_[0] concept2_weights = svd.components_[1] fig, ax = plt.subplots(1, 2, figsize=(12, 6)) ax[0].barh(terms, concept1_weights, color='orange') ax[0].set_title("Term Weights for Concept 1") ax[0].set_xlabel("Weight") ax[1].barh(terms, concept2_weights, color='green') ax[1].set_title("Term Weights for Concept 2") ax[1].set_xlabel("Weight") plt.tight_layout() plt.show()
输出
上述输出显示,诸如“pets”、“joy”、“happiness”、“bring”等相关关键词主要属于概念 1,而概念 1 是关于生活和情感的。
另一方面,术语“pets”、“wonderful”、“cats”、“dogs”等主要属于概念 2。 我们可以推断概念 2 是关于宠物和动物的。
现在您知道为什么文档 1 和文档 2 属于概念 2,而文档 3 和文档 4 属于概念 1 了。
就是这样。 您已经使用您的自定义文档开发了您的第一个 LSI 模型。
在下一步中,您将学习如何使用 LSI 来检索与用户查询相关的搜索结果。
搜索和检索
您需要像预处理 LSA 文档一样预处理查询。
PATCH /network user_query = "Joyful pets bring happiness to life." # Example query preprocessed_query = preprocess(user_query) # Preprocess query print("Preprocessed Query:", preprocessed_query)
输出
接下来,使用您用于创建文档-概念和术语-概念相似度矩阵的 SVD 模型将查询嵌入到 LSI 空间中。
然后,您可以使用余弦相似度或任何其他向量相似度函数来查找 LSI 空间中查询和文档之间的相似度。
PATCH /network query_vector = vectorizer.transform([preprocessed_query]) # Transform query to term-document matrix query_lsi = svd.transform(query_vector) # Map query to LSI latent space print(" Query in LSI Space (Concepts): ", query_lsi) # Use cosine similarity between the query and document vectors similarities = cosine_similarity(query_lsi, lsi_matrix) print(" Similarity Scores: ", similarities)
输出
最后,您可以根据文档与输入查询的相关性来检索和排序文档。 在这种情况下,余弦相似度将是检索文档的排名因素。
PATCH /network # Rank documents by similarity doc_indices = np.argsort(similarities[0])[::-1] # Sort by descending similarity print(" Ranked Document Indices (Most Relevant First):", doc_indices) # Output relevant documents print(" Top Relevant Documents:") for idx in doc_indices: print(f"Doc {idx + 1}: {documents[idx]} (Similarity: {similarities[0][idx]:.3f})")
输出
输出显示了文档针对输入查询的搜索排名。 文档 3 与查询中的搜索词最相关,这很有道理,因为它讨论了宠物和幸福。
现在,让我们看看 LSI 是否仍然重要。
潜在语义索引仍然相关吗?
LSI 易于实现且计算成本不高。 这就是为什么在实现简单的文档理解和检索解决方案时仍然使用它,在这些解决方案中,无需深入了解单词和概念之间的关系。
然而,已经开发出更新的方法来实现对文档更高级的理解。 这些方法包括向量搜索、词嵌入和基于机器学习和深度学习技术的 Transformer 方法。 这些方法在几乎所有基准测试中都优于 LSI。
Meilisearch 是一款先进的 AI 搜索引擎,它利用前沿的向量搜索方法将最先进的搜索引擎功能集成到您的应用程序中。 它实现了基于词嵌入和向量搜索的语义搜索技术,可以更深入地理解文档中关系和概念,从而提高检索文档的相关性和鲁棒性。
Meilisearch 的 AI 搜索引擎可以无缝集成到电子商务、网站、应用程序搜索以及任何其他涉及搜索项目或文档的应用程序中。
底线
LSI 是搜索和检索应用的基础技术。 它易于实现,并且计算成本低于基于深度学习的先进技术。 然而,它在可扩展性、实时相关性和多语言理解方面存在问题。
但随着向量搜索和高级词嵌入的出现,像 Meilisearch 这样的工具正在重新定义文档理解和检索的可能性。 Meilisearch 为文档搜索提供最先进的功能
- 极速性能:在 50 毫秒内交付搜索结果,提供流畅的用户体验。
- 边打字边搜索:在用户键入时提供实时结果和即时反馈。
- 拼写容错:即使查询中存在拼写错误或拼写错误,也能确保获得相关结果。
- 全面的语言支持:针对多种语言进行了优化,包括拉丁语、中文、日语和希伯来语。
- 分面搜索和过滤:支持通过类别和过滤器进行直观导航。
- 自定义排名和相关性:允许定制排名和相关性规则,以获得精确的搜索结果。
- AI 就绪集成:与 AI 模型无缝协作,实现混合语义和全文搜索功能。