Функция потерь PyTorch, ссылающаяся на параметры модели - PullRequest
0 голосов
/ 30 сентября 2019

Для задания мне нужно создать систему рекомендации фильмов, которая использует поставляемую функцию потерь:

sum(?i=1,M) ?sum(j=1,M) indicator[i̸=j](viT vj − Xi,j )**2

Что это значит, произведение точек между двумя вложениями фильмов, Vi и Vj, должно быть симпатичнымчертовски близко к Си, Дж. Где Xi, j - сумма пользователей, которым понравился фильм i и фильм j. Записи, в которых i == j опущены функцией индикатора (установлено на 0.)

Результат назначения - это матрица весов из скрытого слоя. Его размеры должны быть 9724x300, где есть 9724 уникальных идентификатора фильма и 300 нейронов. 300 - произвольный выбор, под влиянием использования 300 нейронов в word2vec от Google.

Что у меня есть:

  • source_data: строки - это пользователи, столбцы - это фильмы. «1» в данной ячейке означает, что соответствующему пользователю понравился соответствующий фильм (dislike = 0.)
  • preprocessed_data: матричное умножение source_data, транспонированного на себя. (т. е. каждая ячейка - это сумма пользователей, которым понравились оба фильма i и j. Диагональные записи мне не нужны, поскольку они представляют собой просто сумму пользователей, которым понравился один фильм.)

Где я застрял:

  • Не уверен, как определить мою собственную функцию потерь в терминах i и j, которая может сравнивать сумму пользователей, которым нравятся фильмы i и j в preprocessed_data, со строками,i и j, в тензорном весе скрытого слоя.
  • Не уверен, как организовать мои данные по тензорам X и y, чтобы данные соответствовали функции потерь.

1 Ответ

1 голос
/ 30 сентября 2019

Прежде чем читать дальше, обратите внимание, что просьба и получение прямой помощи по вашему заданию от StackOverflow может противоречить правилам вашей школы и привести к последствиям для вас как ученика!

При этом,Я бы смоделировал эту проблему следующим образом:

import torch

U = 300 # number of users
M = 30  # number of movies
D = 4   # dimension of embedding vectors

source = torch.randint(0, 2, (U, M)) # users' ratings
X = source.transpose(0, 1) @ source  # your `preprocessed_data`

# initial values for your embedding. This is what your algorithm needs to learn
v = torch.randn(M, D, requires_grad=True)
X = X.to(torch.float32) # necessary to be in line with `v`

# this is the `(viT vj − Xi,j )**2` part
loss_elementwise = (v @ v.transpose(0, 1) - X).pow(2)

# now we need to get rid of the diagonal. Notice that we can equally
# well get rid of the diagonal and the whole upper triangular part,
# as well, since both V @ V.T and source.T @ source are symmetric, so
# the upper triangular part contains just
# a mirror reflection of the lower triangular part.
# This means that we actually implement a bit different summation:
# sum(i=1,M) sum(j=1,i-1) stuff(i, j)
# instead of
# sum(i=1,M) sum(j=1,M) indicator[i̸=j] stuff(i, j)
# and get exactly half the original value
masked = torch.tril(loss_elementwise, -1)

# finally we sum it up, multiplying by 2 to make up
# for the "lost" upper triangular part
loss = 2 * masked.sum()

Теперь вам остается реализовать цикл оптимизации, который будет использовать градиент loss для оптимизации значений v.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...