Так что прямо сейчас у меня действительно простая программа, которая примет предложение и найдет предложение в данной книге, которое наиболее семантически похожее и выведет это предложение вместе со следующими несколькими предложениями.
import spacy
nlp = spacy.load('en_core_web_lg')
#load alice in wonderland
from gutenberg.acquire import load_etext
from gutenberg.cleanup import strip_headers
text = strip_headers(load_etext(11)).strip()
alice = nlp(text)
sentences = list(alice.sents)
mysent = nlp(unicode("example sentence, could be whatever"))
best_match = None
best_similarity_value = 0
for sent in sentences:
similarity = sent.similarity(mysent)
if similarity > best_similarity_value:
best_similarity_value = similarity
best_match = sent
print sentences[sentences.index(best_match):sentences.index(best_match)+10]
Я хочу получить лучшие результаты, сообщив SpaCy игнорировать стоп-слова при выполнении этого процесса, но я не знаю, как лучше всего это сделать. Как я мог создать новый пустой список и добавить каждое слово, которое не является стоп-словом в списке
for sentence in sentences:
for word in sentence:
if word.is_stop == 'False':
newlist.append(word)
но мне пришлось бы сделать это более сложным, чем код выше, потому что мне пришлось бы сохранить целостность исходного списка предложений (потому что индексы должны быть одинаковыми, если я захочу позже распечатать полные предложения). Плюс, если бы я сделал это таким образом, мне пришлось бы запустить этот новый список списков обратно через SpaCy, чтобы использовать метод.similarity.
Я чувствую, что в этом должен быть лучший способ, и я бы очень признателен за любое руководство. Даже если нет лучшего способа добавления каждого нон-стоп-слова в новый список, я был бы признателен за любую помощь в создании списка списков, чтобы индексы были идентичны исходной переменной "предложения".
Спасибо!
Что вам нужно сделать, так это переписать способ, которым spaCy вычисляет сходство.
Для вычисления подобия, spaCy сначала вычисляет вектор для каждого документа, усредняя векторы каждого токена (атрибут token.vector), а затем выполняет косинус-сходство, делая:
return np.dot(vector1, vector2) / (np.linalg.norm(vector1) * np.linalg.norm(vector2))
Вы должны немного подкорректировать это и не учитывать векторы стоп-слов.
Следующий код должен работать для вас:
import spacy
from spacy.lang.en import STOP_WORDS
import numpy as np
nlp = spacy.load('en_core_web_lg')
doc1 = nlp("This is a sentence")
doc2 = nlp("This is a baby")
def compute_similarity(doc1, doc2):
vector1 = np.zeros(300)
vector2 = np.zeros(300)
for token in doc1:
if (token.text not in STOP_WORDS):
vector1 = vector1 + token.vector
vector1 = np.divide(vector1, len(doc1))
for token in doc2:
if (token.text not in STOP_WORDS):
vector2 = vector2 + token.vector
vector2 = np.divide(vector2, len(doc2))
return np.dot(vector1, vector2) / (np.linalg.norm(vector1) * np.linalg.norm(vector2))
print(compute_similarity(doc1, doc2)))
Надеюсь, поможет!
token.text not in STOP_WORDS
противnot token.is_stop
, или это нужно быть сделано по-другому, как это? 2) Был ли выбор 300 для np.zeros произвольным выбором? Кодvector1 = vector1 + token.vector
перезаписывает один из 0 или просто добавляет число в список после 300 нулей?