Prediksi kesamaan kalimat

15

Saya mencari untuk memecahkan masalah berikut: Saya memiliki satu set kalimat sebagai dataset saya, dan saya ingin dapat mengetikkan kalimat baru, dan menemukan kalimat yang paling mirip dengan yang ada di dataset. Contohnya akan terlihat seperti:

Kalimat baru: " I opened a new mailbox"

Prediksi berdasarkan dataset:

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

Saya telah membaca bahwa cosine similarity dapat digunakan untuk menyelesaikan masalah-masalah seperti ini yang dipasangkan dengan tf-idf (dan RNNs seharusnya tidak membawa perbaikan signifikan pada metode dasar), atau juga word2vec digunakan untuk masalah yang serupa. Apakah itu benar-benar layak untuk digunakan dalam kasus khusus ini juga? Apakah ada teknik / algoritma lain untuk menyelesaikan ini (sebaiknya dengan Python dan SKLearn, tapi saya juga terbuka untuk belajar tentang TensorFlow)?

lte__
sumber
Pasti tandai Bert . Ini adalah implementasi yang bagus . Itu tidak persis apa yang Anda cari dengan hasil yang cukup bagus
GioGio

Jawaban:

26

Masalah Anda dapat diselesaikan dengan Word2vec serta Doc2vec. Doc2vec akan memberikan hasil yang lebih baik karena memperhitungkan kalimat saat melatih model.

Solusi Doc2vec
Anda dapat melatih model doc2vec Anda dengan mengikuti tautan ini . Anda mungkin ingin melakukan beberapa langkah pra-pemrosesan seperti menghapus semua kata berhenti (kata-kata seperti "the", "an", dll. Yang tidak menambah banyak arti pada kalimat). Setelah Anda melatih model Anda, Anda dapat menemukan kalimat yang sama menggunakan kode berikut.

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)

Hasil:

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

Hasil di atas adalah daftar tuple untuk (label,cosine_similarity_score). Anda dapat memetakan output ke kalimat dengan melakukan train[29670].

Harap dicatat bahwa pendekatan di atas hanya akan memberikan hasil yang baik jika model doc2vec Anda berisi embeddings untuk kata-kata yang ditemukan dalam kalimat baru. Jika Anda mencoba untuk mendapatkan kesamaan untuk beberapa kalimat omong kosong seperti sdsf sdf f sdf sdfsdffg, itu akan memberi Anda beberapa hasil, tetapi itu mungkin bukan kalimat serupa yang sebenarnya karena model terlatih Anda mungkin belum melihat kata-kata omong kosong ini saat melatih model. Jadi cobalah latih model Anda pada kalimat sebanyak mungkin untuk memasukkan sebanyak mungkin kata untuk hasil yang lebih baik.

Solusi Word2vec
Jika Anda menggunakan word2vec, Anda perlu menghitung vektor rata-rata untuk semua kata dalam setiap kalimat dan menggunakan persamaan cosinus antara vektor.

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

Hitung Kesamaan

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)
Harman
sumber
Terima kasih! Akan bekerja pada akhir pekan ini, tetapi solusinya tampak sempurna pada pandangan pertama. Pujian!
lte__
apakah kita perlu mengurangi hukuman untuk pelatihan
pyd
ya @ pyd kita harus! sentence_1.split()melakukan hal yang sama.
Harman
4

Word Mover's Distance (WMD) adalah algoritma untuk menemukan jarak antar kalimat. WMD didasarkan pada embeddings kata (misalnya, word2vec) yang menyandikan makna semantik kata menjadi vektor padat.

Jarak WMD mengukur ketidaksamaan antara dua dokumen teks sebagai jarak minimum yang dibutuhkan kata-kata yang melekat pada satu dokumen untuk "bepergian" untuk mencapai kata-kata yang disematkan pada dokumen lain.

Sebagai contoh:

masukkan deskripsi gambar di sini Sumber: "Dari Embeddings Kata Ke Jarak Dokumen"

The paket gensim memiliki implementasi WMD .

Untuk masalah Anda, Anda akan membandingkan kalimat yang dimasukkan dengan semua kalimat lain dan mengembalikan kalimat yang memiliki WMD terendah.

Brian Spiering
sumber
2

Anda dapat mencoba solusi mudah menggunakan sklearn dan itu akan berfungsi dengan baik.

  • Gunakan tfidfvectorizer untuk mendapatkan representasi vektor dari setiap teks

  • Fit vectorizer dengan data Anda, menghapus stop-kata.

  • Ubah entri baru dengan vektorizer yang sebelumnya dilatih

  • Hitung persamaan cosinus antara representasi ini dan setiap representasi elemen dalam set data Anda.

Jika Anda memiliki hugh dataset, Anda dapat mengelompokkannya (misalnya menggunakan KMeans dari scikit belajar) setelah mendapatkan representasi, dan sebelum memprediksi data baru.

Kode ini melakukan semua langkah ini. Anda dapat memeriksanya di repo github saya .

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])
Federico Caccia
sumber
Hai, alangkah baiknya jika Anda bisa menunjukkan contoh penggunaan cosinus similiairity?
Tido
Hai, bukankah seharusnya bagian 2 menjadi yang utama, cocokkan dengan data lain dan gunakan ini untuk mengubah setiap teks? Akan sangat menyenangkan jika Anda dapat menunjukkan contoh penggunaan cosinus similiairity?
Tido
1

Ada beberapa karya terbaru berdasarkan Variational Auto-Encoder dalam model RNN. Menghasilkan Kalimat dari Ruang Berkelanjutan , dengan implementasi pytorch: kode github .
mereka berhasil memampatkan fitur global semantik, sintaksis dari sebuah kalimat ke dalam ruang laten yang diekspresikan mungkin dengan beberapa variabel acak independen hingga 10 hingga 30 (distribusi faktor).
ide baru dalam karya ini, mereka interpolasi antara dua kalimat. dan hasilnya sangat menakjubkan.

Fadi Bakoura
sumber
0

Solusi umum terdiri dari langkah-langkah berikut -

  1. Pemeringkatan atau embeddings kata dari sebuah kalimat.
  2. Menerapkan metrik kesamaan di antara kalimat.

Untuk 1. word2vec adalah pilihan terbaik tetapi jika Anda tidak ingin menggunakan word2vec, Anda dapat membuat beberapa perkiraan untuk itu. Salah satu caranya adalah membuat matriks kata-kata yang muncul bersamaan dari kalimat-kalimat terlatih Anda diikuti dengan menerapkan TSVD di atasnya. Matriks coccurance darinXn dimensi ketika dikonversi menjadi nXd dimensi, membuat untuk kata vektor d ukuran.

Setelah Anda menyematkan kata setiap kata, Anda dapat menerapkan salah satu dari metrik kesamaan seperti kesamaan cosinus, dll. Pada setiap kalimat untuk mengukur kesamaan dengan yang lain.

Mr.Sigma.
sumber