Найти процент токенов, разделяемых двумя документами с пространством
Для nltk это было бы что-то вроде:
def symm_similarity(textA,textB):
textA = set(word_tokenize(textA))
textB = set(word_tokenize(textB))
intersection = len(textA.intersection(textB))
difference = len(textA.symmetric_difference(textB))
return intersection/float(intersection+difference)
Поскольку spacy быстрее, я пытаюсь сделать это в просторном виде, но объекты-токены, похоже, не предлагают быстрого решения этой проблемы. Есть идеи?
Спасибо всем.
1 ответ
Ваша функция получает процент общих типов слов, а не токенов. Вы берете набор слов без учета их количества.
Если вы хотите подсчитать количество токенов, я ожидаю, что следующее будет очень быстрым, если у вас загружен словарный файл (который будет по умолчанию, если у вас установлены данные):
from spacy.attrs import ORTH
def symm_similarity_types(nlp, textA,textB):
docA = nlp.make_doc(textA)
docB = nlp.make_doc(textB)
countsA = Counter(docA.count_by(ORTH))
countsB = Counter(docB.count_by(ORTH)
diff = sum(abs(val) for val in (countsA - countsB).values())
return diff / (len(docA) + len(docB))
Если вы хотите вычислить в точности то же самое, что и код выше, вот эквивалент spaCy. Doc
объект позволяет перебирать Token
объекты. Затем вы должны основывать свои счета на token.orth
атрибут, который является целочисленным идентификатором строки. Я ожидаю, что работа с целыми числами будет немного быстрее, чем наборы строк:
def symm_similarity_types(nlp, textA,textB):
docA = set(w.orth for w in nlp(textA)
docB = set(w.orth for w in nlp(textB)
intersection = len(textA.intersection(textB))
difference = len(textA.symmetric_difference(textB))
return intersection/float(intersection+difference)
Это должно быть немного более эффективно, чем версия NLTK, потому что вы работаете с наборами целых чисел, а не со строками.
Если вы действительно заинтересованы в эффективности, часто удобнее работать на Cython, а не пытаться угадать, что делает Python. Вот основной цикл:
# cython: infer_types=True
for token in doc.c[:doc.length]
orth = token.lex.orth
doc.c
это TokenC*
вы перебираете непрерывную память и разыменовываете один указатель (token.lex
это const LexemeC*
)