Lightfm:处理用户和项目冷启动

时间:2017-10-25 04:40:48

标签: python recommendation-engine matrix-factorization cold-start

我记得lightfm的一个优点是该模型没有冷启动问题,用户和物品冷启动:lightfm original paper

但是,我仍然不了解如何使用lightfm解决冷启动问题。我在user-item interaction data上训练了我的模型。据我所知,我只能对我的数据集上存在的profile_ids进行预测。

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

任何有助于我理解的建议或指示都会受到赞赏。谢谢

2 个答案:

答案 0 :(得分:5)

LightFM与任何其他推荐算法一样,如果未获得有关这些用户的其他信息,则无法对全新用户进行预测。尝试为新用户提供建议时的诀窍是根据算法在培训期间看到的功能来描述它们。

最好用一个例子来解释。假设您的训练集中的ID为0到10之间的用户,并且您希望为新用户ID 11做出预测。如果您拥有的是新用户的ID,则该算法将无法进行预测毕竟,它对用户11的偏好一无所知。然而,假设您有一些功能来描述用户:也许在注册过程中,每个用户都会选择他们拥有的一些兴趣(例如恐怖电影或浪漫喜剧)。如果在训练期间存在这些特征,则算法可以平均地了解与这些特征相关联的偏好,并且能够为可以使用相同特征描述的任何新用户产生推荐。在此示例中,如果您可以提供他们在注册过程中选择的首选项,您将能够为用户11进行预测。

在LightFM实现中,所有这些功能都将在特征矩阵中进行编码,可能采用单热编码的形式。在为用户11提出建议时,您将为该用户构建一个新的特征矩阵:只要该特征矩阵仅包含训练期间存在的特征,您就可以进行预测。

请注意,拥有一个仅对应于单个用户的功能通常很有用 - 所以'是用户0'功能,'用户1'功能等等。对于新用户,这样的功能是无用的,因为模型可以使用培训中的信息来了解该功能。

答案 1 :(得分:1)

这对我有用:

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()