Is there a way to know how much a sentence is related to a word/topic?

For instance the following dataframe and the topics/attributes Romantique, Feminine, ...:

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

As a start I thought about doing a jaccard_similarity distance ...

>>>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})

But is there a better way to see how much a sentence relate to a targeted word?


My main goal is to compare the proportion of people who used some topics in their comments of a product with the presence or absence of these topics in the description of the product. I used a model which use the synonyms:

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?
      # 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)

It produces the following graph:

enter image description here

It's weird because it shows that for most products the difference between the presence/absence of any topic compared to its presence/absence in the description is the same for most topics, but different from 0! Everything that is above zero means that at least the description has it and none of the comments, but everything below zero means that the comments have it but not the description. What strikes me is these straight lines below zero. It means that the presence/absence of a given attribute in absciss is the same for every comment...

  • $\begingroup$ Where do the topics come from? if it's from a topic model, you could re-apply the model on the sentences. $\endgroup$ – Erwan Dec 10 '20 at 17:46
  • $\begingroup$ @Erwan thanks for tour comment. The topics come from a list my of topics in a csv $\endgroup$ – Revolucion for Monica Dec 11 '20 at 8:50

If you have a list of words for every topic you can indeed try to directly measure the similarity of this list against a sentence, but it's likely that a sentence doesn't always contain one of the topic words so it might not work very well.

A more advanced method would be to obtain a semantic representation for every topic (or topic word) from an external corpus. Any large corpus can be used for that, it doesn't have to be related to your input data. The traditional way to do that is to extract a context vector for every target word by counting the co-occurrences of the target in the corpus: for every occurrence of the target word, take for instance a window of 5 words to its left and 5 words to its right. Then count how many times every context word appears in the window of the target across the whole corpus. This way the final context vector contains the distribution of the context words, i.e. a representation of the meaning of the target word. Comparing this context vector against a sentence is likely to produce a more accurate semantic similarity score.

There are many variants about the exact definition of the context vector: usually stop words are removed but one could also use TF-IDF and/or other kinds of normalization. The more modern version of this method is probably to use word embeddings, but I'm not knowledgeable enough about this.

  • $\begingroup$ That sounds like a very interesting idea. I am going to try it and let you know. I have updated my question with my main goal and my attempt so far. $\endgroup$ – Revolucion for Monica Dec 12 '20 at 9:08

If you have a large corpus of text mapped with their respective topics, you can train a Siamese neural network where you have two inputs (one sentence and one topic) and output a similarity score based on whether they are related or not. This would require a good dataset with a good variety of similar and not similar pairs of (sentence, topic) to be effective.

Furthermore, if you incorporate semantic information in your inputs (such as word embeddings or more advanced representations such as encoder outputs) the network will generalize better and be able to work with text outside of your training corpus, since the semantic information will be similar for new unseen but related data.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.