Прогнозування подібності вироку


15

Я хочу вирішити таку проблему: у мене є набір речень як мій набір даних, і я хочу мати можливість ввести нове речення та знайти речення, яке нове є найбільш подібним до цього в наборі даних. Приклад виглядає так:

Нове речення: " I opened a new mailbox"

Прогнозування на основі даних:

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

Я читав, що подібність косинуса може бути використана для вирішення подібних питань, пов'язаних з tf-idf (а RNN не повинні принести значних вдосконалень до основних методів), або також word2vec використовується для подібних проблем. Чи справді такі життєздатні для використання і в цьому конкретному випадку? Чи є якісь інші методи / алгоритми для вирішення цього питання (бажано, з Python та SKLearn, але я також відкритий, щоб дізнатися про TensorFlow)?


Однозначно перевірити Берта . Ось приємна реалізація . Це робить саме те, що ви шукаєте, з досить хорошими результатами
GioGio

Відповіді:


26

Вашу проблему можна вирішити як з Word2vec, так і з Doc2vec. Doc2vec дав би кращі результати, оскільки він враховує пропозиції при навчанні моделі.

Рішення Doc2vec
Ви можете навчити свою модель doc2vec за цим посиланням . Можливо, ви хочете виконати деякі етапи попередньої обробки, як-от видалення всіх стоп-слів (слова типу "the", "an" тощо), які не додають великого значення реченню). Після того, як ви навчили свою модель, ви можете знайти подібні речення, використовуючи наступний код.

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)

Результати:

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

Наведені вище результати - список кортежів для (label,cosine_similarity_score). Ви можете картографувати виходи на речення, виконуючи train[29670].

Зауважте, що вищезазначений підхід дасть хороші результати, лише якщо ваша модель doc2vec містить вбудовування для слів, знайдених у новому реченні. Якщо ви спробуєте отримати схожість на якесь химерне речення на кшталт sdsf sdf f sdf sdfsdffg, це дасть вам мало результатів, але це може бути не справжніми подібними реченнями, оскільки ваша навчена модель, можливо, не бачила цих безглуздих слів під час навчання моделі. Тому спробуйте навчити свою модель на якомога більше речень, щоб включити якомога більше слів для кращих результатів.

Рішення Word2vec
Якщо ви використовуєте word2vec, вам потрібно обчислити середній вектор для всіх слів у кожному реченні та використовувати схожість косинусів між векторами.

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

Обчисліть схожість

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)

Дякую! Працюватиме над цим у вихідні, але рішення на перший погляд здається ідеальним. Кудо!
lte__

чи потрібно нам
токенізувати

так @pyd ми повинні! sentence_1.split()робить те саме.
Харман

4

Word Mover's Distance (WMD) - алгоритм пошуку відстані між реченнями. WMD заснований на вбудованих словах (наприклад, word2vec), які кодують смислове значення слів у щільні вектори.

Відстань WMD вимірює різницю між двома текстовими документами як мінімальну кількість відстані, яку потрібно "пройти" вкладеним словам одного документа, щоб досягти вбудованих слів іншого документа.

Наприклад:

введіть тут опис зображення Джерело: Папір "Від вставки Word до документа відстань"

Пакет gensim має реалізацію WMD .

Для вашої проблеми ви порівняєте введене речення з усіма іншими реченнями і повернете речення, яке має найнижчий рівень WMD.


2

Ви можете спробувати просте рішення, використовуючи sklearn, і це буде добре працювати.

  • Використовуйте tfidfvectorizer, щоб отримати векторне зображення кожного тексту

  • Підійміть векторизатор до своїх даних, видаляючи стоп-слова.

  • Перетворіть новий запис за допомогою попередньо підготовленого векторизатора

  • Обчисліть схожість косинуса між цим поданням та кожним поданням елементів у вашому наборі даних.

Якщо у вас є набір даних Hugh, ви можете кластеризувати його (наприклад, використовуючи KMeans від scikit learn) після отримання представлення та перед прогнозуванням нових даних.

Цей код виконує всі ці дії. Ви можете перевірити це на моєму 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])

Гей, було б дуже приємно, якби ви могли показати приклад використання косинусної подібності?
Тідо

Ей, не варто, щоб частина 2 прийшла першою, помістіть усі дані та використовуйте це для перетворення кожного тексту? Було б дуже приємно, якби ви могли показати приклад використання косинусної схожості?
Тідо

1

Існує деяка нещодавня робота, заснована на змінному автоматичному кодері в моделях RNN. Генерування речень з безперервного простору , з реалізаціями піторха: код github .
їм вдалося стиснути семантичну, синтаксичну глобальну особливість речення в якийсь латентний простір, виражений, можливо, з якимись кінцевими 10 - 30 незалежними випадковими змінними (факторизований розподіл).
романну ідею в цьому творі вони інтерполюють між двома реченнями. і результати були досить дивовижними.


0

Узагальнене рішення складається з наступних етапів -

  1. Особливість чи вкладення слів речення.
  2. Застосування метрики подібності серед речень.

nXnnXdd

Після того, як ви вбудуєте слово у кожне слово, ви можете застосувати будь-яку з метрик подібності, як косинусна схожість тощо, до кожного речення, щоб виміряти схожість з іншими.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.