Previsione della somiglianza delle frasi


15

Sto cercando di risolvere il seguente problema: ho un set di frasi come set di dati e voglio essere in grado di digitare una nuova frase e trovare la frase che la nuova è la più simile a quella nel set di dati. Un esempio potrebbe apparire come:

Nuova frase: " I opened a new mailbox"

Previsione basata sul set di dati:

Sentence                       | Similarity
A dog ate poop                   0%
A mailbox is good                50%
A mailbox was opened by me       80%

Ho letto che la somiglianza del coseno può essere utilizzata per risolvere questo tipo di problemi associati a tf-idf (e gli RNN non dovrebbero apportare miglioramenti significativi ai metodi di base), oppure anche word2vec viene utilizzato per problemi simili. Anche quelli sono effettivamente utilizzabili in questo caso specifico? Ci sono altre tecniche / algoritmi per risolverlo (preferibilmente con Python e SKLearn, ma sono aperto anche a conoscere TensorFlow)?


Sicuramente controlla Bert . Ecco una bella implementazione . Fa esattamente quello che stai cercando con risultati abbastanza buoni
GioGio il

Risposte:


26

Il tuo problema può essere risolto con Word2vec e Doc2vec. Doc2vec darebbe risultati migliori perché tiene conto delle frasi durante l'addestramento del modello.

Soluzione Doc2vec
Puoi addestrare il tuo modello doc2vec seguendo questo link . Potresti voler eseguire alcuni passaggi di pre-elaborazione come la rimozione di tutte le parole di arresto (parole come "the", "an", ecc. Che non aggiungono molto significato alla frase). Una volta addestrato il tuo modello, puoi trovare frasi simili usando il seguente codice.

import gensim  

model = gensim.models.Doc2Vec.load('saved_doc2vec_model')  

new_sentence = "I opened a new mailbox".split(" ")  
model.docvecs.most_similar(positive=[model.infer_vector(new_sentence)],topn=5)

risultati:

[('TRAIN_29670', 0.6352514028549194),
 ('TRAIN_678', 0.6344441771507263),
 ('TRAIN_12792', 0.6202734708786011),
 ('TRAIN_12062', 0.6163255572319031),
 ('TRAIN_9710', 0.6056315898895264)]

I risultati sopra riportati sono un elenco di tuple per (label,cosine_similarity_score). Puoi mappare gli output in frasi facendo train[29670].

Si noti che l'approccio sopra riportato darà buoni risultati solo se il modello doc2vec contiene incorporamenti per le parole trovate nella nuova frase. Se si tenta di ottenere la somiglianza per alcune frasi incomprensibili come sdsf sdf f sdf sdfsdffg, si otterranno pochi risultati, ma quelle potrebbero non essere le stesse frasi simili poiché il modello addestrato potrebbe non aver visto queste parole incomprensibili durante l'allenamento del modello. Quindi prova a formare il tuo modello su quante più frasi possibile per incorporare quante più parole per risultati migliori.

Soluzione Word2vec
Se si utilizza word2vec, è necessario calcolare il vettore medio per tutte le parole in ogni frase e utilizzare la somiglianza del coseno tra i vettori.

def avg_sentence_vector(words, model, num_features, index2word_set):
    #function to average all words vectors in a given paragraph
    featureVec = np.zeros((num_features,), dtype="float32")
    nwords = 0

    for word in words:
        if word in index2word_set:
            nwords = nwords+1
            featureVec = np.add(featureVec, model[word])

    if nwords>0:
        featureVec = np.divide(featureVec, nwords)
    return featureVec

Calcola somiglianza

from sklearn.metrics.pairwise import cosine_similarity

#get average vector for sentence 1
sentence_1 = "this is sentence number one"
sentence_1_avg_vector = avg_sentence_vector(sentence_1.split(), model=word2vec_model, num_features=100)

#get average vector for sentence 2
sentence_2 = "this is sentence number two"
sentence_2_avg_vector = avg_sentence_vector(sentence_2.split(), model=word2vec_model, num_features=100)

sen1_sen2_similarity =  cosine_similarity(sentence_1_avg_vector,sentence_2_avg_vector)

Grazie! Funzionerà su questo nel fine settimana, ma la soluzione sembra perfetta a prima vista. Complimenti!
lte__

dobbiamo tokenizzare le frasi per l'addestramento
pyd

si @pyd dobbiamo! sentence_1.split()fa lo stesso.
Harman,

4

Word Mover's Distance (WMD) è un algoritmo per trovare la distanza tra le frasi. WMD si basa su incorporamenti di parole (ad esempio, word2vec) che codificano il significato semantico delle parole in vettori densi.

La distanza WMD misura la differenza tra due documenti di testo come la quantità minima di distanza di cui le parole incorporate di un documento devono "viaggiare" per raggiungere le parole incorporate di un altro documento.

Per esempio:

inserisci qui la descrizione dell'immagine Fonte: documento "Dalle parole incastonate alle distanze del documento"

Il pacchetto gensim ha un'implementazione di WMD .

Per il tuo problema, confronteresti la frase immessa con tutte le altre frasi e restituiresti la frase che ha WMD più basso.


2

Puoi provare una soluzione semplice usando sklearn e funzionerà bene.

  • Utilizzare tfidfvectorizer per ottenere una rappresentazione vettoriale di ciascun testo

  • Adatta il vettorizzatore ai tuoi dati, rimuovendo le parole chiave.

  • Trasforma la nuova voce con il vettorizzatore precedentemente addestrato

  • Calcola la somiglianza del coseno tra questa rappresentazione e ciascuna rappresentazione degli elementi nel tuo set di dati.

Se si dispone di un set di dati hugh, è possibile raggrupparlo (ad esempio utilizzando KMeans da scikit learn) dopo aver ottenuto la rappresentazione e prima di prevedere nuovi dati.

Questo codice esegue tutti questi passaggi. Puoi controllarlo sul mio repository github .

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_score
import numpy

texts = ["This first text talks about houses and dogs",
        "This is about airplanes and airlines",
        "This is about dogs and houses too, but also about trees",
        "Trees and dogs are main characters in this story",
        "This story is about batman and superman fighting each other", 
        "Nothing better than another story talking about airplanes, airlines and birds",
        "Superman defeats batman in the last round"]

# vectorization of the texts
vectorizer = TfidfVectorizer(stop_words="english")
X = vectorizer.fit_transform(texts)
# used words (axis in our multi-dimensional space)
words = vectorizer.get_feature_names()
print("words", words)


n_clusters=3
number_of_seeds_to_try=10
max_iter = 300
number_of_process=2 # seads are distributed
model = KMeans(n_clusters=n_clusters, max_iter=max_iter, n_init=number_of_seeds_to_try, n_jobs=number_of_process).fit(X)

labels = model.labels_
# indices of preferible words in each cluster
ordered_words = model.cluster_centers_.argsort()[:, ::-1]

print("centers:", model.cluster_centers_)
print("labels", labels)
print("intertia:", model.inertia_)

texts_per_cluster = numpy.zeros(n_clusters)
for i_cluster in range(n_clusters):
    for label in labels:
        if label==i_cluster:
            texts_per_cluster[i_cluster] +=1 

print("Top words per cluster:")
for i_cluster in range(n_clusters):
    print("Cluster:", i_cluster, "texts:", int(texts_per_cluster[i_cluster])),
    for term in ordered_words[i_cluster, :10]:
        print("\t"+words[term])

print("\n")
print("Prediction")

text_to_predict = "Why batman was defeated  by superman so easy?"
Y = vectorizer.transform([text_to_predict])
predicted_cluster = model.predict(Y)[0]
texts_per_cluster[predicted_cluster]+=1

print(text_to_predict)
print("Cluster:", predicted_cluster, "texts:", int(texts_per_cluster[predicted_cluster])),
for term in ordered_words[predicted_cluster, :10]:
print("\t"+words[term])

Ehi, sarebbe davvero bello se potessi mostrare un esempio di utilizzo della similiairità del coseno?
Tido,

Ehi, non dovresti essere la prima parte a venire prima, adattarti a tutti i dati e usarli per trasformare ogni testo? Sarebbe davvero bello se potessi mostrare un esempio di utilizzo della similiairità del coseno?
Tido,

1

Esistono lavori recenti basati sull'encoder automatico variabile nei modelli RNN. Generare frasi da uno spazio continuo , con implementazioni pytorch: codice github .
sono riusciti a comprimere la caratteristica globale semantica e sintattica di una frase in uno spazio latente espresso forse con alcune variabili casuali indipendenti da 10 a 30 finite (distribuzione fattorizzata).
l'idea del romanzo in questo lavoro, interpolano tra due frasi. e i risultati sono stati piuttosto sorprendenti.


0

La soluzione generalizzata consiste nei seguenti passaggi:

  1. Caratterizzazione o incorporamenti di parole di una frase.
  2. Applicazione di una metrica di somiglianza tra le frasi.

nXnnXdd

Una volta ottenuto l'incorporamento delle parole di ogni parola, puoi applicare una qualsiasi delle metriche di somiglianza come la somiglianza del coseno, ecc. Su ogni frase per misurare la somiglianza con le altre.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.