python: Как рассчитать косинусное сходство двух списков слов?

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

A = [u'home (private)', u'bank', u'bank', u'building(condo/apartment)','factory']

B = [u'home (private)', u'school', u'bank', u'shopping mall']

Я знаю, что косинусное сходство A и B должно быть

3/(sqrt(7)*sqrt(4)).

Я пытаюсь преобразовать списки в такие формы, как «строительная фабрика банка домашнего банка», которая выглядит как предложение, однако некоторые элементы (например, home (private)) имеют пустое пространство внутри себя, а некоторые элементы имеют скобки, поэтому я нахожу трудно вычислить вхождение слова.

Знаете ли вы, как рассчитать вхождение слова в этот сложный список, чтобы в списке B вхождение слова можно было представить в виде

{'home (private):1, 'school':1, 'bank': 1, 'shopping mall':1}? 

Или вы знаете, как рассчитать косинусное сходство этих двух списков?

Большое спасибо

4 голоса | спросил gladys0313 2 MarpmMon, 02 Mar 2015 23:55:34 +03002015-03-02T23:55:34+03:0011 2015, 23:55:34

2 ответа


0
from collections import Counter

# word-lists to compare
a = [u'home (private)', u'bank', u'bank', u'building(condo/apartment)','factory']
b = [u'home (private)', u'school', u'bank', u'shopping mall']

# count word occurrences
a_vals = Counter(a)
b_vals = Counter(b)

# convert to word-vectors
words  = list(a_vals.keys() | b_vals.keys())
a_vect = [a_vals.get(word, 0) for word in words]        # [0, 0, 1, 1, 2, 1]
b_vect = [b_vals.get(word, 0) for word in words]        # [1, 1, 1, 0, 1, 0]

# find cosine
len_a  = sum(av*av for av in a_vect) ** 0.5             # sqrt(7)
len_b  = sum(bv*bv for bv in b_vect) ** 0.5             # sqrt(4)
dot    = sum(av*bv for av,bv in zip(a_vect, b_vect))    # 3
cosine = dot / (len_a * len_b)                          # 0.5669467
ответил Hugh Bothwell 3 MaramTue, 03 Mar 2015 00:22:12 +03002015-03-03T00:22:12+03:0012 2015, 00:22:12
0

Сначала создайте словарь (это технический термин для списка всех отдельных слов в наборе или корпусе).

vocab = {}
i = 0

# loop through each list, find distinct words and map them to a
# unique number starting at zero

for word in A:
    if word not in vocab:
        vocab[word] = i
        i += 1


for word in B:
    if word not in vocab:
        vocab[word] = i
        i += 1

Словарь vocab теперь отображает каждое слово в уникальное число, начинающееся с нуля. Мы будем использовать эти числа как индексы в массиве (или векторе).

На следующем шаге мы создадим нечто, называемое вектором терминов частоты для каждого входного списка. Мы собираемся использовать здесь библиотеку с именем numpy. Это очень популярный способ научного расчета. Если вас интересует косинусное сходство (или другие методы машинного обучения), оно того стоит.

import numpy as np

# create a numpy array (vector) for each input, filled with zeros
a = np.zeros(len(vocab))
b = np.zeros(len(vocab))

# loop through each input and create a corresponding vector for it
# this vector counts occurrences of each word in the dictionary

for word in A:
    index = vocab[word] # get index from dictionary
    a[index] += 1 # increment count for that index

for word in B:
    index = vocab[word]
    b[index] += 1

Последний шаг - фактическое вычисление косинуса подобия.

# use numpy's dot product to calculate the cosine similarity
sim = np.dot(a, b) / np.sqrt(np.dot(a, a) * np.dot(b, b))

Переменная sim теперь содержит ваш ответ. Вы можете извлечь каждое из этих подвыражений и убедиться, что они соответствуют вашей исходной формуле.

При небольшом рефакторинге эта техника довольно масштабируема (относительно большое количество входных списков, с относительно большим количеством отдельных слов). Для действительно больших корпораций (таких как википедия) вы должны проверить библиотеки Natural Language Processing, созданные для такого рода вещей. Вот несколько хороших.

  1. nltk
  2. gensim
  3. spaCy
ответил Waylon Flinn 3 22015vEurope/Moscow11bEurope/MoscowTue, 03 Nov 2015 19:29:51 +0300 2015, 19:29:51

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132