Не в состоянии понять функцию питона косинусного сходства - PullRequest
0 голосов
/ 26 апреля 2018

Я работаю с примером в блоге , чтобы понять метод совместного фильтра, используемый в системе рекомендаций. Я столкнулся с косинусным сходством, выраженным как

enter image description here

В python, используя numpy, его записывают как

def similarity(ratings, kind='user', epslion=1e-9):
      if kind == 'user' :
         sim = ratings.dot(ratings.T)
      elif (kind=='item'):
          sim = ratings.T.dot(ratings) + epslion
      norms = np.array([np.sqrt(np.diagonal(sim))])

      return  (sim / norms / norms.T )

Вопросы

  1. что за математика стоит за вычислением нормы в коде
  2. как (sim / norms / norms.T ) равно sim(u,u`) в уравнении

Заранее спасибо за ваше время - если я что-то упустил, переоценил или недооценил конкретный момент, дайте мне знать в комментариях.

1 Ответ

0 голосов
/ 26 апреля 2018

Рейтинги хранятся в единой матрице ratings, где строки соответствуют пользователям (индекс u), а столбцы соответствуют элементам (индекс i). Поскольку вы хотите вычислить sim(u, u'), то есть сходство между пользователями, давайте предположим, что ниже kind = 'user'.

Теперь давайте сначала посмотрим на r_{ui}r_{u'i} без коэффициентов масштабирования с квадратным корнем. Это выражение суммируется по i, что можно интерпретировать как умножение матрицы на r с транспонированием r, т.е.:

\sum_i r_{ui}r_{u'i} = \sum_i r_{ui}(r^T)_{iu'} =: s_{uu'}

Как уже было сделано выше, обозначим полученную матрицу как s (переменная sim в коде). Эта матрица по определению является симметричной, а ее строки / столбцы помечены индексами «пользователя» u/u'.

Теперь масштабный «коэффициент» f_{u} := \sqrt\sum_i r^2_{ui} на самом деле представляет собой вектор, индексированный с помощью u (каждый элемент которого является евклидовой нормой соответствующей строки матрицы r). Однако, построив s_{uu'}, мы можем видеть, что f_{u} - это не что иное, как \sqrt s_{uu}.

Наконец, интересующий фактор сходства равен s_{uu'}/f{u}/f{u'}. Размещенный код вычисляет это для всех индексов u/u' и возвращает результат в виде матрицы. Для этого оно:

  1. вычисляет sim (матрица s выше) как ratings.dot(ratings.T)
  2. получает квадратный корень из его диагонали (вектор f выше) как np.sqrt(np.diagonal(sim))
  3. для эффективного масштабирования строки / столбца s, это затем выражается в виде двумерного массива norms = np.array([np.sqrt(np.diagonal(sim))]) (обратите внимание на отсутствующий [] в вашем посте)
  4. наконец, матрица s_{uu'}/f{u}/f{u'} рассчитывается как sim / norms / norms.T. Здесь, поскольку norms имеет форму (1, num_of_users), первое деление выполняет масштабирование столбца, а деление с norms.T масштабирует строки.
...