Lightfm: обработка холодного запуска пользователя и предмета

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

Однако я до сих пор не понимаю, как использовать lightfm для решения проблемы холодного запуска. Я обучил свою модель на user-item interaction data. как я понимаю, я могу делать прогнозы только по profile_id, которые существуют в моем наборе данных.

def predict(self, user_ids, item_ids, item_features=None,
            user_features=None, num_threads=1):
    """
    Compute the recommendation score for user-item pairs.

    Arguments
    ---------

    user_ids: integer or np.int32 array of shape [n_pairs,]
         single user id or an array containing the user ids for the
         user-item pairs for which a prediction is to be computed
    item_ids: np.int32 array of shape [n_pairs,]
         an array containing the item ids for the user-item pairs for which
         a prediction is to be computed.
    user_features: np.float32 csr_matrix of shape [n_users, n_user_features], optional
         Each row contains that user's weights over features.
    item_features: np.float32 csr_matrix of shape [n_items, n_item_features], optional
         Each row contains that item's weights over features.
    num_threads: int, optional
         Number of parallel computation threads to use. Should
         not be higher than the number of physical cores.

    Returns
    -------

    np.float32 array of shape [n_pairs,]
        Numpy array containing the recommendation scores for pairs defined
        by the inputs.
    """

    self._check_initialized()

    if not isinstance(user_ids, np.ndarray):
        user_ids = np.repeat(np.int32(user_ids), len(item_ids))

    assert len(user_ids) == len(item_ids)

    if user_ids.dtype != np.int32:
        user_ids = user_ids.astype(np.int32)
    if item_ids.dtype != np.int32:
        item_ids = item_ids.astype(np.int32)

    n_users = user_ids.max() + 1
    n_items = item_ids.max() + 1

    (user_features,
     item_features) = self._construct_feature_matrices(n_users,
                                                       n_items,
                                                       user_features,
                                                       item_features)

    lightfm_data = self._get_lightfm_data()

    predictions = np.empty(len(user_ids), dtype=np.float64)

    predict_lightfm(CSRMatrix(item_features),
                    CSRMatrix(user_features),
                    user_ids,
                    item_ids,
                    predictions,
                    lightfm_data,
                    num_threads)

    return predictions

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


person bohr    schedule 25.10.2017    source источник
comment
Вероятно, вы можете попробовать случайную инициализацию, и на основе все новых и новых реальных данных модель должна предсказать это правильно. Если все первоначальные функции заменены, начните привлекать пользователя / идентификатор к (онлайн) обучению.   -  person meister    schedule 07.08.2018


Ответы (2)


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

Вероятно, лучше всего это объяснить на примере. Предположим, у вас есть пользователи с идентификаторами от 0 до 10 в обучающей выборке, и вы хотите сделать прогнозы для нового пользователя с идентификатором 11. Если бы у вас был только идентификатор нового пользователя, алгоритм не смог бы делать прогнозы. : ведь ему ничего не известно о предпочтениях пользователя 11. Предположим, однако, что у вас есть некоторые функции для описания пользователей: возможно, в процессе регистрации каждый пользователь выбирает ряд интересов, которые у него есть (например, фильмы ужасов или романтические комедии). Если эти функции присутствуют во время обучения, алгоритм может узнать, какие предпочтения в среднем связаны с этими характеристиками, и сможет дать рекомендации для любых новых пользователей, которых можно описать с помощью тех же характеристик. В этом примере вы сможете делать прогнозы для пользователя 11, если сможете указать предпочтения, которые он выбрал в процессе регистрации.

В реализации LightFM все эти функции будут закодированы в матрицах функций, вероятно, в форме горячего кодирования. Делая рекомендации для пользователя 11, вы должны построить новую матрицу признаков для этого пользователя: пока эта матрица признаков содержит только признаки, присутствующие во время обучения, вы сможете делать прогнозы.

Обратите внимание, что обычно полезно иметь функцию, которая соответствует только одному пользователю — например, функция «Является пользователем 0», функция «Является пользователем 1» и так далее. В случае новых пользователей такая функция бесполезна, так как в обучении нет информации, которую модель могла бы использовать, чтобы узнать об этой функции.

person Maciej Kula    schedule 28.10.2017
comment
привет @Maciej Kula спасибо за объяснение, теперь я понимаю, что проблема холодного запуска для пользователя или предмета может быть решена путем включения функций в модель. Однако мне все еще неясно, как мне это сделать. Итак, учитывая нового пользователя, я бы построил новую матрицу функций для этого пользователя, а затем 1) должен ли я создать функцию для поиска похожего пользователя в соответствии с этой матрицей функций? или 2) могу ли я напрямую использовать модель, которую я обучил, чтобы генерировать рекомендации для этого нового пользователя? еще раз спасибо - person bohr; 29.10.2017
comment
Вы должны построить матрицу признаков (на самом деле строку) для нового пользователя и использовать ее непосредственно в методах model.predict. Частью ответственности модели является автоматическое моделирование этого сходства для вас. - person Maciej Kula; 29.10.2017
comment
ах понял, а для параметра ids что поставить? - person bohr; 29.10.2017
comment
В этом случае вы можете просто установить все столбцы, связанные с идентификатором, равными нулю. - person Maciej Kula; 30.10.2017
comment
@Bohr ... не могли бы вы поделиться своим полным кодом для вышеуказанной проблемы? Также вы использовали какой-либо другой подход для решения проблемы холодного запуска, кроме этого подхода? - person user2906657; 05.06.2018
comment
Привет @bohr, не могли бы вы поделиться своим кодом о том, как вы решили проблему добавления нового пользователя? Я пытаюсь решить эту проблему сам, но я немного борюсь ... спасибо! - person saraherceg; 26.11.2019

Это сработало для меня:

if user_index is not None:
    predictions = model.predict([user_index, ], np.array(target_item_indices))
else:
    predictions = model.predict(0, np.array(target_item_indices), user_features=user_features)

Здесь user_features — это разреженный массив, тщательно собранный из набора функций, который использовался при обучении модели.

Например. если я получаю нового пользователя, а функции пользователя что-то вроде user_feature_list = ["id-2837", "Cape Town", "Woodstock", 7700], то я создаю массив функций следующим образом:

from scipy import sparse

user_feature_map = store_model.user_feature_map  # the feature map was persisted during the previous round of offline training
num_features = len(user_feature_list)
normalised_val = 1.0 / num_features
target_indices = []
for feature in user_feature_list:
    try:
        target_indices.append(user_feature_map[feature])
    except KeyError:
        print("new user feature encountered '{}'".format(feature))
        pass
print("target indices: {}".format(target_indices))
user_features = np.zeros(len(user_feature_map.keys()))
for i in target_indices:
    user_features[i] = normalised_val
user_features = sparse.csr_matrix(user_features)

user_feature_map был сгенерирован ранее путем вызова метода LightFM mapping() для исходного набора входных данных после подгонки:

dataset.fit(
    unique_user_ids,
    unique_item_ids,
    item_features=item_feature_list,
    user_features=user_feature_list
)

user_id_map, user_feature_map, item_id_map, item_feature_map = dataset.mapping()
person petrus-jvrensburg    schedule 13.08.2018
comment
во втором фрагменте кода вы написали store_model.user_feature_map, что такое объект store_model. Кроме того, когда вы получаете user_id_map, user_feature_map, item_id_map, item_feature_map = dataset.mapping(), suer_feature_map просто дает мне то же самое, что и user_id_map , то есть сопоставление кодировки пользователя и пользователя. наконец, означает ли это, что для проблемы с холодным запуском у вас должны быть user_features, созданные из dataset.build_user_features метода набора данных. - person emudria; 07.07.2020
comment
@petrus-jvrensburg Есть ли какая-то особая причина, по которой вы использовали index 0 ``` model.predict(0, np.array(target_item_indices), user_features=user_features) ``` Кроме того, у вас есть пример для холодного запуска элемента? - person Max; 22.09.2020