寻找两个语句之间的语义相似度

3

我目前正在使用 Python 开发一个小型应用程序,并且我的应用程序具有搜索功能(目前使用 difflib),但是我想创建基于用户输入文本的语义搜索,它可以根据数据库中的内容给出前5或10个结果。就像谷歌搜索引擎一样工作。我在这里找到了一些解决方案

但问题是,以下来自其中一种解决方案的两个陈述在语义上不正确。但我并不关心这一点,因为它们使事情变得太难了,而我不想要那样的效果。我还找到了一些解决方案,这些解决方案显示使用 gensimGlove 嵌入,并查找单词相似度而不是句子。

我想要什么?

假设我的数据库中有语句 display classes,用户输入 showshoweddisplayeddisplayed classshow types等都是相同的。即使以上两个语句被视为相同,我也不在乎。displayeddisplayed class 已经显示在 difflib 中。

需要注意的要点

  • 从一组固定语句中查找,但用户输入的语句可能会有所不同
  • 必须适用于语句
3个回答

3

我认为这不是gensim嵌入,而是word2vec嵌入。无论如何。

你需要tensorflow_hub

通用句子编码器将文本编码成可以用于文本分类语义相似聚类和其他自然语言任务的高维向量

我认为你需要的是文本分类语义相似,因为你想要找到给定用户语句的最近的前5或10个语句。

它很容易使用。但模型的大小约为1GB。它适用于单词、句子、短语或简短段落。输入为可变长度的英文文本,输出为512维向量。你可以在这里找到更多信息。

代码

import tensorflow_hub as hub
import numpy as np

# Load model. It will download first time.
module_url = "https://tfhub.dev/google/universal-sentence-encoder-large/5" 
model = hub.load(module_url)

# first data[0] is your actual value
data = ["display classes", "show", "showed" ,"displayed class", "show types"]

# find high-dimensional vectors.
vecs = model(data)

# find distance between statements using inner product
dists = np.inner(vecs[0], vecs)

# print dists
print(dists)

输出

array([0.9999999 , 0.5633253 , 0.46475542, 0.85303843, 0.61701006],dtype=float32)

结论

第一个数值 0.999999 是指“显示类(display classes)”和它本身之间的距离。第二个数值 0.5633253 是指“显示类(display classes)”与“显示(show)”之间的距离。最后一个数值 0.61701006 是指“显示类(display classes)”与“显示类型(show types)”之间的距离。

利用这些数值,您可以找到给定输入与数据库中语句之间的距离,并根据这些距离进行排名。


1
你可以使用wordnet查找同义词,然后使用这些同义词来查找类似语句。
import nltk
from nltk.corpus import wordnet as wn

nltk.download('wordnet')

def get_syn_list(gword):
  syn_list = []
  try:
    syn_list.extend(wn.synsets(gword,pos=wn.NOUN))
    syn_list.extend(wn.synsets(gword,pos=wn.VERB))
    syn_list.extend(wn.synsets(gword,pos=wn.ADJ))
    syn_list.extend(wn.synsets(gword,pos=wn.ADV))
  except :
    print("Something Wrong Happened")
  syn_words = []
  for i in syn_list:
    syn_words.append(i.lemmas()[0].name())
  return syn_words

现在使用 split 函数将数据库语句拆分,就像这样:
stat = ["display classes"]

syn_dict = {}
for i in stat:
   tmp = []
   for x in i.split(" "):
       tmp.extend(get_syn_list(x))
   syn_dict[i] = set(tmp)

现在你有同义词,只需将它们与输入的文本进行比较。并且在比较单词之前使用词形还原器,这样 "displayed" 就变成了 "display"。

但是如何将输入的文本与这个字典进行比较呢? - FocusNow

1

嗨,当我安装了spacy并运行上面的代码时,我遇到了错误“找不到模型'en_core_web_lg'。它似乎不是快捷方式链接、Python包或有效的数据目录路径。” - FocusNow
虽然这段代码可能解决了OP的问题,但最好还是解释一下你的代码如何解决OP的问题。这样,未来的访问者可以从您的帖子中学习,并将其应用于自己的代码中。SO不是编码服务,而是知识资源。此外,高质量、完整的答案更有可能被点赞。这些特点以及所有帖子都必须是自包含的要求,是SO作为一个平台的一些优势,使其与论坛区分开来。您可以编辑以添加其他信息和/或使用源文档补充您的解释。 - SherylHohman
请记住,虽然链接是可以接受的,但 SO 上的所有帖子都必须是自包含的,以防页面内容更改或链接不可用。当用户被要求在网上跳来跳去拼凑“答案”时,用户体验会受到影响。只需将链接中的任何相关说明包含在您的帖子中即可。通过这种方式,UX 很棒,而链接则提供了一个欢迎的补充,用于后续跟进、确认或深入探讨。 - SherylHohman
@FocusNow 我更新了解决方案。你的问题已经解决了。 - PP-56

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接