Удалить петли для сравнения предложений в НЛП - PullRequest
1 голос
/ 18 июня 2019

Я использую BERT для сравнения сходства текста со следующим кодом:

from bert_embedding import BertEmbedding
import numpy as np
from scipy.spatial.distance  import cosine as cosine_similarity

bert_embedding = BertEmbedding()
TEXT1 = "As expected from MIT-level of course: it's interesting, challenging, engaging, and for me personally quite enlightening. This course is second part of 5 courses in  micromasters program. I was interested in learning about supply chain (purely personal interest, my work touch this topic but not directly) and stumbled upon this course, took it, and man-oh-man...I just couldn't stop learning. Now I'm planning to take the rest of the courses. Average time/effort per week should be around 8-10 hours, but I tried to squeeze everything into just 5 hours since I have very limited free time. You will need 2-3 hours per week for the lecture videos, 2 hours for practice problems, and another 2 hours for the weekly homework. This course offers several topics around demand forecasting and inventory. Basic knowledge of probability and statistics is needed. It will help if you take the prerequisite course: supply chain analytics. But if you've already familiar with basic concept of statistics, you can pick yourself along the way. The lectures are very interesting and engaging, it gives you a lot of knowledge but also throw in some business perspective, so it's very relatable and applicable! The practice problems can help strengthen the understanding of the given knowledge and the homework are very challenging compared to other online-courses I have taken. This course is the best quality I have taken so far, and I have taken several (3-4 MOOCs) from other provider."
TEXT1 = TEXT1.split('.')

sentence2 = ["CHALLENGING COURSE "]

оттуда я хочу найти лучшее совпадение предложения 2 в одном из предложений TEXT1, используя косинусное расстояние

best_match = {'sentence':'','score':''}
best = 0
for sentence in TEXT1: 
  #sentence = sentence.replace('SUPPLY CHAIN','')
  if len(sentence) < 5:
    continue
  avg_vec1 = calculate_avg_vec([sentence])
  avg_vec2 = calculate_avg_vec(sentence2)

  score = cosine_similarity(avg_vec1,avg_vec2)
  if score > best:
    best_match['sentence'] =  sentence
    best_match['score'] =  score
    best = score

best_match

Код работает, но так как я хочу сравнить предложение2 не только с ТЕКСТОМ1, но и с N текстами, мне нужно улучшить скорость.Можно ли векторизовать этот цикл?или любой способ ускорить это?

1 Ответ

3 голосов
/ 24 июня 2019

cosine_similarity определяется как скалярное произведение двух нормализованных векторов.

Это по сути матричное умножение, за которым следует argmax для получения наилучшего индекса.

I 'Я буду использовать numpy, хотя - как уже упоминалось в комментариях - вы, вероятно, можете подключить его к модели BERT с pytorch или tensorflow.

Сначала мы определим нормализованный средний вектор:

def calculate_avg_norm_vec(sentence):
    vs = sentence2vectors(sentence) # TODO: use Bert embedding
    vm = vs.mean(axis=0)
    return vm/np.linalg.norm(vm)

Затем мы строим матрицу всех предложений и их векторов

X = np.apply_along_axis(calculate_avg_norm_vec, 1, all_sentences)
target = calculate_avg_norm_vec(target_sentence)

Наконец, нам нужно умножить targetвектор с матрицей X и возьмите argmax

index_of_sentence = np.dot(X,target.T).argmax(axis=1)

Возможно, вы захотите убедиться, что axis и индексирование соответствуют вашим данным, но это общая схема

...