首页 > 解决方案 > 如何使用python获得关键字和段落之间的相似度(PMI)分数?

问题描述

我正在从事一个从客户评论中提取关键字的项目。我以某种方式设法使用主题建模技术提取了关键字。

现在我正在寻找一种 Python 技术或算法来根据关键字之间的相似性对评论进行排名。

例如:对于关键字“美味的食物”,我想获得如下评论的相似度分数。

审查 分数
这个地方很贵,但他们的食物很美味 0.7
我不会推荐这个地方进行聚会。 0.0
这是一个非常干净和友好的地方,也许食物不是那么好! 0.2

如何获得关键字和句子之间的语义相似度得分?

标签: pythonnlpsimilaritytopic-modeling

解决方案


我有一种方法可以做到这一点,但它很复杂,所以我将展示它并在之后复习它。这里是:

sentences = ["this is place is costly but their food is delicious", "This is place is very clean and friendly, perhaps, food is not so great!", "I would not recommend this place for hangout."]
search = "food delicious"

count = 0
lst = []

for sentence in sentences:
    if search in sentence:
        lst.append([sentence, 1])
    else:
        for word in search.split():
            if word in sentence:
                count += 1
        lst.append([sentence, max(round(count / len(search.split()) - 0.3, 1), 0)])
        count = 0

for i in lst:
    print(*i)

这将提供您想要的输出。

基本上,第一行将评论放入一个数组中。第二行创建一个名为 search 的变量,其中包含关键字。

现在,之后我们需要创建 2 个变量,分别称为 count 和 count 和 lst。Lst 将是我们用来存储信息的列表,而 count 是我们稍后需要的计数器。

在第 7 行,我们启动了一个 for 循环,它将逐个循环遍历句子。

在第 8 行,我们检查句子中是否有确切的关键短语,所以如果"food delicious" 出现在句子中的某处。如果是,那么我们将句子及其 PMI 分数 1 添加到我们之前创建的列表中。

注意:(表中并没有说明需要这个,如果不需要,那么你可以删除它!)

因此,接下来,我们使用else:来证明,如果直接关键短语不在句子中,那么我们需要做一些其他事情来获得 PMI 分数。如果我们没有这个else:,那么以后可能会导致重复。

在第 11 行,它开始了另一个 for 循环,但这一次,它将遍历search.split(). search.split()只生成一个搜索词列表,用空格分隔它们。例如,在这里,search.split()将是["food", "delicious"]。所以现在,我们正在遍历该列表。

现在,在第 12 行,我们检查我们正在循环的当前单词是否在我们正在循环的当前句子中,如果这有意义的话。如果这个词是,那么我们之前创建的变量 callcount将增加这个词在句子中出现的次数,或者count那个词的。count每个单词都会增加。

注意:这意味着如果一个词(例如 food)出现了 20 次,计算机仍会像只出现一次一样运行。为避免这种情况,您可以更改count += 1count += sentence.count(word),这将计算该词在这句话。

现在,在search.split()for 循环结束后,我们需要将计数添加到列表中。这里有一些数学的东西。首先,我们将计数除以, 以获得句子中出现变量的search.split()单词数量的小数百分比(小于 1) 。search然而,这带来了一个问题。如果出现 2 个单词,并且search变量中有 2 个单词,那么我们将做 2/2,即 1。我们不想要 1,我们想要 0.7。因此,我们还需要从我们的数字中减去 0.3。我对这个值进行了四舍五入,因为它最终会在除法中变得非常混乱。

现在,我们还有最后一个问题lst.append()。如果句子中有 0 个单词,但search变量中有 2 个单词,那么我们将做 0/2,即 0。这就是我们想要的,但是,我们减去 0.3。这给了我们- 0.3/ 为了避免这种情况,我们可以将 设置max()为 0。

最后,紧接着,我们将 重置count为 0,以便下一句可以从新计数开始,以避免任何统计错误。

就这样!要打印它,我只是在最后使用了一个小的 for 循环,但你不需要它。

这些是我的结果:

this is place is costly but their food is delicious 0.7
This is place is very clean and friendly, perhaps, food is not so great! 0.2
I would not recommend this place for hangout. 0

PS:(最后一行*iprint()的只是从打印值中删除括号和逗号。它不会以任何方式更改列表本身。)

我知道这很长,但是阅读所有内容以理解每一行的要点很重要。


推荐阅读