【问题标题】:Finding most similar sentences among all in python在python中找到最相似的句子
【发布时间】:2020-12-22 09:24:19
【问题描述】:

建议/参考链接/代码表示赞赏。

我有一个超过 1500 行的数据。每一行都有一个句子。我正在尝试找出在所有句子中找到最相似句子的最佳方法。

我的尝试

  1. 我尝试过 K-mean 算法,它将相似的句子分组到一个集群中。但是我发现了一个缺点,我必须通过 K 来创建集群。很难猜出K。我尝试了 elbo 方法来猜测集群,但将所有集群组合在一起是不够的。在这种方法中,我将所有数据分组。我正在寻找与 0.90% 以上相似的数据,应返回 ID。

  2. 我尝试了余弦相似度,其中我使用TfidfVectorizer 创建矩阵,然后传入余弦相似度。即使这种方法也不能正常工作。

我在寻找什么

我想要一种方法,我可以通过 阈值 示例 0.90 的所有行中彼此相似的 0.90% 以上的数据应作为结果返回。

Data Sample
ID    |   DESCRIPTION
-----------------------------
10    | Cancel ASN WMS Cancel ASN   
11    | MAXPREDO Validation is corect
12    | Move to QC  
13    | Cancel ASN WMS Cancel ASN   
14    | MAXPREDO Validation is right
15    | Verify files are sent every hours for this interface from Optima
16    | MAXPREDO Validation are correct
17    | Move to QC  
18    | Verify files are not sent

预期结果

应使用 ID

获得相似度高达 0.90% 的数据
ID    |   DESCRIPTION
-----------------------------
10    | Cancel ASN WMS Cancel ASN
13    | Cancel ASN WMS Cancel ASN
11    | MAXPREDO Validation is corect  # even spelling is not correct
14    | MAXPREDO Validation is right
16    | MAXPREDO Validation are correct
12    | Move to QC  
17    | Move to QC  

【问题讨论】:

    标签: python tensorflow scikit-learn sentence-similarity


    【解决方案1】:

    可以使用这个 Python 3 库来计算句子相似度:https://github.com/UKPLab/sentence-transformers

    来自https://www.sbert.net/docs/usage/semantic_textual_similarity.html的代码示例:

    from sentence_transformers import SentenceTransformer, util
    model = SentenceTransformer('paraphrase-MiniLM-L12-v2')
    
    # Two lists of sentences
    sentences1 = ['The cat sits outside',
                 'A man is playing guitar',
                 'The new movie is awesome']
    
    sentences2 = ['The dog plays in the garden',
                  'A woman watches TV',
                  'The new movie is so great']
    
    #Compute embedding for both lists
    embeddings1 = model.encode(sentences1, convert_to_tensor=True)
    embeddings2 = model.encode(sentences2, convert_to_tensor=True)
    
    #Compute cosine-similarits
    cosine_scores = util.pytorch_cos_sim(embeddings1, embeddings2)
    
    #Output the pairs with their score
    for i in range(len(sentences1)):
        print("{} \t\t {} \t\t Score: {:.4f}".format(sentences1[i], sentences2[i], cosine_scores[i][i]))
    

    该库包含最先进的句子嵌入模型。

    查看https://stackoverflow.com/a/68728666/395857进行句子聚类。

    【讨论】:

      【解决方案2】:

      一种可能的方法是使用词嵌入来创建句子的向量表示。就像您使用预训练的词嵌入并让一个 rnn 层创建一个句子向量表示,其中每个句子的词嵌入被组合在一起。然后你有一个向量,你可以在其中计算距离。但是你需要决定,你想设置哪个阈值,所以一个句子被认为是相似的,因为词嵌入的尺度不是固定的。

      更新

      我做了一些实验。我认为,对于此类任务,这是一种可行的方法,但是,您可能想自己了解一下它在您的情况下的效果如何。我在我的 git repository 中创建了一个示例。

      word-mover-distance 算法也可用于此任务。您可以在此媒体article 中找到有关此主题的更多信息。

      【讨论】:

      • 你可以分享任何sn-p以供参考吗?
      • 是的,我看看能不能设置点什么
      • 好吧,我已经完成了这个例子,看起来你正在使用 RNN,代码令人印象深刻,我很困惑如何进一步将它与我的工作联系起来。如果您能将其与我的问题进一步联系起来,那就太好了
      【解决方案3】:

      为什么余弦相似度和 TFIDF-vectorizer 对您不起作用?

      我试过了,它适用于这段代码:

      import pandas as pd
      import numpy as np
      
      from sklearn.feature_extraction.text import TfidfVectorizer
      from sklearn.metrics.pairwise import cosine_similarity
      
      df = pd.DataFrame(columns=["ID","DESCRIPTION"], data=np.matrix([[10,"Cancel ASN WMS Cancel ASN"],
                                                                      [11,"MAXPREDO Validation is corect"],
                                                                      [12,"Move to QC"],
                                                                      [13,"Cancel ASN WMS Cancel ASN"],
                                                                      [14,"MAXPREDO Validation is right"],
                                                                      [15,"Verify files are sent every hours for this interface from Optima"],
                                                                      [16,"MAXPREDO Validation are correct"],
                                                                      [17,"Move to QC"],
                                                                      [18,"Verify files are not sent"]
                                                                      ]))
      
      corpus = list(df["DESCRIPTION"].values)
      
      vectorizer = TfidfVectorizer()
      X = vectorizer.fit_transform(corpus)
      
      threshold = 0.4
      
      for x in range(0,X.shape[0]):
        for y in range(x,X.shape[0]):
          if(x!=y):
            if(cosine_similarity(X[x],X[y])>threshold):
              print(df["ID"][x],":",corpus[x])
              print(df["ID"][y],":",corpus[y])
              print("Cosine similarity:",cosine_similarity(X[x],X[y]))
              print()
      

      阈值也可以调整,但阈值为 0.9 时不会产生您想要的结果。

      阈值为 0.4 的输出是:

      10 : Cancel ASN WMS Cancel ASN
      13 : Cancel ASN WMS Cancel ASN
      Cosine similarity: [[1.]]
      
      11 : MAXPREDO Validation is corect
      14 : MAXPREDO Validation is right
      Cosine similarity: [[0.64183024]]
      
      12 : Move to QC
      17 : Move to QC
      Cosine similarity: [[1.]]
      
      15 : Verify files are sent every hours for this interface from Optima
      18 : Verify files are not sent
      Cosine similarity: [[0.44897995]]
      

      在阈值为 0.39 的情况下,所有预期句子都是输出中的特征,但也可以找到带有索引 [15,18] 的附加对:

      10 : Cancel ASN WMS Cancel ASN
      13 : Cancel ASN WMS Cancel ASN
      Cosine similarity: [[1.]]
      
      11 : MAXPREDO Validation is corect
      14 : MAXPREDO Validation is right
      Cosine similarity: [[0.64183024]]
      
      11 : MAXPREDO Validation is corect
      16 : MAXPREDO Validation are correct
      Cosine similarity: [[0.39895808]]
      
      12 : Move to QC
      17 : Move to QC
      Cosine similarity: [[1.]]
      
      14 : MAXPREDO Validation is right
      16 : MAXPREDO Validation are correct
      Cosine similarity: [[0.39895808]]
      
      15 : Verify files are sent every hours for this interface from Optima
      18 : Verify files are not sent
      Cosine similarity: [[0.44897995]]
      

      【讨论】:

      • 嗯,这令人印象深刻,而且工作起来很迷人。我发现了一些挑战,例如.. 1) 重复超过 2 次的句子第一个句子继续重复示例:索引 [11] 重复 [11, 14] 和 [11, 16] 2) 行数超过 1500 时我将这段代码运行了 500 行,完成它的任务大约需要 1 分钟。一个ID在发现重复句子时会重复
      • 很高兴能帮上忙。如果我的回答对您有帮助,请用绿色复选标记将其标记为“已接受答案”。
      • 当然我会将此标记为答案。但是在你能建议我发现重复时如何提高速度和重复行之前?
      • 1500 行需要 20 分钟以上
      • 我不知道如何提高速度。我建议您以速度为重点提出一个新问题,并包含有关您在那里尝试过的信息,以便其他人可以帮助您。
      猜你喜欢
      • 2021-11-15
      • 2010-11-22
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 2012-02-19
      • 1970-01-01
      • 2020-03-27
      • 2018-02-02
      相关资源
      最近更新 更多