如何在R的recommenderlab中使用自定义相似度矩阵构建推荐模型
用自定义相似度矩阵/函数构建recommenderlab推荐模型
我之前刚好折腾过recommenderlab的自定义相似度扩展问题,给你两个实用的解决方案,看哪种更贴合你的需求:
方案1:直接用预计算的自定义相似度矩阵实现推荐
如果已经有了现成的自定义相似度矩阵(比如用户间或物品间的相似度),可以跳过Recommender函数的限制,手动实现协同过滤的核心逻辑,步骤很清晰:
步骤示例(基于用户的协同过滤)
- 先从你的评估方案里提取训练集:
train_data <- getData(e, "train")
- 把训练集转换为普通矩阵方便计算,同时确保你的自定义相似度矩阵(比如
user_sim_matrix)的行/列名和训练集的用户ID完全匹配:
train_mat <- as(train_data, "matrix")
- 编写自定义推荐函数,用你的相似度矩阵计算topN推荐:
custom_user_based_recommend <- function(user_id, sim_matrix, train_matrix, top_n = 10, k = 50) { # 获取目标用户已有的评分 user_ratings <- train_matrix[user_id, ] # 获取该用户与其他用户的相似度,排除自己 sim_scores <- sim_matrix[user_id, ] sim_scores[user_id] <- 0 # 取相似度最高的前k个用户 top_similar_users <- names(sort(sim_scores, decreasing = TRUE)[1:k]) # 计算未评分物品的加权平均得分 item_scores <- colSums(train_matrix[top_similar_users, ] * sim_scores[top_similar_users]) / sum(sim_scores[top_similar_users]) # 过滤掉用户已经评分过的物品 item_scores[!is.na(user_ratings)] <- NA # 取得分最高的top_n个物品作为推荐 top_items <- names(sort(item_scores, decreasing = TRUE)[1:top_n]) return(top_items) }
- 测试推荐:
# 给训练集第一个用户生成10个推荐 first_user <- rownames(train_mat)[1] recommendations <- custom_user_based_recommend(first_user, user_sim_matrix, train_mat)
*注意:*如果是基于物品的协同过滤,只需要把代码里的用户维度换成物品维度,相似度矩阵换成物品间的即可。
方案2:扩展recommenderlab的自定义推荐方法(更优雅)
如果需要重复使用自定义逻辑,或者要和recommenderlab的原生评估流程兼容,可以注册一个自定义的推荐方法,这样就能像用默认的"Cosine"方法一样调用Recommender函数了:
步骤示例
- 定义自定义推荐模型的构造函数:
RecommenderUserBasedCustom <- function(data, parameter = NULL) { # 设置默认参数:可以传预计算的相似度矩阵,或者自定义相似度函数 if (is.null(parameter)) { parameter <- list(sim_matrix = NULL, sim_fun = NULL, k = 50) } # 如果没有预计算矩阵,就用自定义函数计算相似度 if (is.null(parameter$sim_matrix)) { if (is.null(parameter$sim_fun)) { stop("必须提供自定义相似度函数或预计算的相似度矩阵!") } # 转换为矩阵计算相似度 mat <- as(data, "matrix") parameter$sim_matrix <- parameter$sim_fun(mat) } # 返回模型对象 structure( list(data = data, parameter = parameter), class = "RecommenderUserBasedCustom" ) }
- 定义对应的预测函数:
predict.RecommenderUserBasedCustom <- function(object, newdata, n = 10, ...) { # 处理输入数据格式 if (inherits(newdata, "realRatingMatrix")) { newdata <- as(newdata, "matrix") } # 批量生成推荐 recommendations <- lapply(rownames(newdata), function(user_id) { user_ratings <- newdata[user_id, ] sim_scores <- object$parameter$sim_matrix[user_id, ] sim_scores[user_id] <- 0 # 取top k相似用户 top_similar_users <- names(sort(sim_scores, decreasing = TRUE)[1:object$parameter$k]) # 计算物品得分 item_scores <- colSums(as(object$data, "matrix")[top_similar_users, ] * sim_scores[top_similar_users]) / sum(sim_scores[top_similar_users]) # 过滤已评分物品 item_scores[!is.na(user_ratings)] <- NA # 取top n推荐 names(sort(item_scores, decreasing = TRUE)[1:n]) }) # 转换为recommenderlab原生的topNList格式 names(recommendations) <- rownames(newdata) as(recommendations, "topNList") }
- 注册自定义方法到recommenderlab:
registerRecommender("USER_BASED_CUSTOM", RecommenderUserBasedCustom)
- 现在就可以像用默认方法一样使用了:
# 示例1:用预计算的相似度矩阵构建模型 model_custom <- Recommender(train_data, method = "USER_BASED_CUSTOM", parameter = list(sim_matrix = user_sim_matrix, k = 50)) # 示例2:用自定义相似度函数构建模型(比如自己修改的余弦相似度) my_custom_sim <- function(mat) { # 自定义相似度逻辑:比如带权重的余弦相似度 sim <- cor(t(mat), use = "pairwise.complete.obs") sim <- sim * 0.9 + 0.1 * mean(sim) # 自定义调整 return(sim) } model_custom_fun <- Recommender(train_data, method = "USER_BASED_CUSTOM", parameter = list(sim_fun = my_custom_sim, k = 50)) # 生成预测推荐 pred <- predict(model_custom, getData(e, "known"), n = 10)
- 甚至可以用原生的评估流程测试模型:
eval_results <- evaluate(e, method = "USER_BASED_CUSTOM", n = c(5, 10, 15))
*注意:*注册方法后,确保自定义模型的类名和predict函数的后缀一致(比如这里的RecommenderUserBasedCustom对应predict.RecommenderUserBasedCustom),否则predict函数不会被正确调用。
内容的提问来源于stack exchange,提问作者kumaran ragunathan
相关产品推荐
相关产品推荐

