句子与单词相似度

数据挖掘 nlp 语义相似性
2022-02-25 03:31:28

有没有办法知道一个句子与一个单词/主题有多大关系?

例如以下数据框和主题/属性Romantique,,Feminine...:

    comments
0   Très contente de mon achat. Je cherchais ce parfum depuis un temps en magasin et je suis heureuse qu’il soit disponible en ligne il sent tellement bon !! En plus en promo, génial ! \r\nLivraison très rapide !
1   J’adore les parfums de cette marque car je trouve qu’ils sont captivant et surtout ils tiennent toute la journée ! Ils ont des odeurs originales et que l’on ne retrouve pas partout ! Je conseil fortement
2   Le parfum ideal pour porter pendant toutes les saisons du matin à nuit !!!
3   Très bon parfum floral, envoûtant au note de Jasmin qui reste toute la journée\r\nCorresponds aux personnes qui aiment les parfums florales assez imposante
...

作为开始,我想过做一个 jaccard_similarity 距离......

>>>from collections import Counter
>>>Counter(df['comments'].apply(lambda x: x.split(' ')).apply(lambda x: jaccard_similarity(x,['féminin'])))
Counter({0.0: 1344, 0.025: 21, 0.05: 21, 0.0625: 21})

但是有没有更好的方法来查看一个句子与目标词的相关程度?

更新

我的主要目标是比较在产品评论中使用某些主题的人的比例与产品描述中是否存在这些主题。我使用了一个使用同义词的模型:

d = {}
for product in collection.find():
  d_product = {}
  name = product['q0']['Results'][0]['Name']
  description = product['q0']['Results'][0]['Description'] 
  comments = short_comments_df(product['q2'])['comments']
  #for every attributes
  for attribut in attributs:
    consumers_approved = 0
    # Is the attribut, or its synonyms, in the comments?
    try: 
      # if the attribute or it synonyms are in the description then the product has the attribut
      product_approved = presence(synonymes[unidecode.unidecode(attribut)], description)
      # we test every comment to see if they talked about the attribute
      for comment in comments:
        # We only take the nouns and the verbs
        lemmatized_comment = lemmatize_pos_filtering(comment)
        # if the attributes are in the comments then we increment the consumer approved counter
        consumers_approved += presence(synonymes[unidecode.unidecode(attribut)],lemmatized_comment)
      # we take the proportion of people who used the attribute, but shouldn't we normalize it? 
      proportion_approved = consumers_approved/len(record['q2']['Results'])
    except IndexError:
      print("IndexError: ",attribut)
    # we use the difference between if we found it in the description and the % of people who found it as well 
    d_product[attribut] = product_approved - proportion_approved
  d[name] = d_product

df = pd.DataFrame(d)

它产生以下图表:

在此处输入图像描述

这很奇怪,因为它表明对于大多数产品,任何主题的存在/不存在与描述中的存在/不存在之间的差异对于大多数主题来说都是相同的,但不同于 0!高于零的所有内容都意味着至少描述有它并且没有评论,但低于零的所有内容都意味着评论有它但没有描述。令我印象深刻的是这些低于零的直线。这意味着对于每条评论,横坐标中给定属性的存在/不存在都是相同的......

2个回答

如果您有每个主题的单词列表,您确实可以尝试直接测量该列表与句子的相似度,但句子可能并不总是包含主题词之一,因此它可能效果不佳。

一种更高级的方法是从外部语料库中获取每个主题(或主题词)的语义表示。任何大型语料库都可以用于此目的,它不必与您的输入数据相关。这样做的传统方法是通过计算语料库中目标的共现次数来为每个目标词提取上下文向量:对于目标词的每次出现,例如在其左侧有 5 个词和 5 个词的窗口词在它的权利。然后计算每个上下文词在整个语料库中出现在目标窗口中的次数。这样,最终的上下文向量就包含了上下文词的分布,即目标词含义的表示。将此上下文向量与句子进行比较可能会产生更准确的语义相似度分数。

关于上下文向量的确切定义有许多变体:通常会删除停用词,但也可以使用 TF-IDF 和/或其他类型的规范化。这种方法的更现代版本可能是使用词嵌入,但我对此知之甚少。

如果您有大量的文本语料库映射到各自的主题,您可以训练一个有两个输入(一个句子和一个主题)的连体神经网络,并根据它们是否相关输出相似度分数。这将需要一个具有多种相似和不相似对(句子、主题)的良好数据集才能有效。

此外,如果您在输入中加入语义信息(例如词嵌入或更高级的表示,例如编码器输出),网络将更好地泛化并能够处理训练语料库之外的文本,因为语义信息对于新的看不见但相关的数据。