You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用R实现User based CF训练测试拆分及评分预测方法咨询

1 训练集与测试集拆分实现

因为你的数据集是行对应用户、列对应电影的评分矩阵,拆分时需要避免数据泄露,采用按用户分层掩蔽的方案:

  • 对每个用户,随机选取20%~30%的已评分条目设为掩蔽状态,这部分的真实评分作为测试集的标注
  • 剩余已评分条目保留,作为训练集用来计算用户相似度

拆分代码示例:

# 设置随机种子保证可复现
set.seed(123)
train_data <- final_data
test_mask <- matrix(FALSE, nrow = nrow(final_data), ncol = ncol(final_data))
test_rate <- 0.2 # 测试集占已评分数据的20%

for (u in 1:nrow(final_data)) {
  # 找到当前用户所有已评分的列索引
  rated_cols <- which(!is.na(final_data[u, ]))
  # 随机选test_rate比例的列作为测试集
  test_cols <- sample(rated_cols, size = ceiling(length(rated_cols)*test_rate))
  test_mask[u, test_cols] <- TRUE
  # 训练集掩蔽测试集的评分
  train_data[u, test_cols] <- NA
}

运行后train_data是训练用评分矩阵,test_mask标记了测试集位置,注意相似度计算要基于train_data而非全量数据,避免数据泄露。

2 用户相似度矩阵计算优化

你现有代码用嵌套循环计算10000*10000的相似度矩阵效率极低,推荐改用向量化实现,速度提升至少10倍:

# 替换你现有嵌套循环的实现
# 先对每行做标准化,处理缺失值
train_norm <- train_data
train_norm[is.na(train_norm)] <- 0
# 计算每行的L2范数
row_norms <- sqrt(rowSums(train_norm^2))
# 余弦相似度 = 矩阵叉乘 / 范数外积
user_similarities <- tcrossprod(train_norm) / outer(row_norms, row_norms)
diag(user_similarities) <- 0 # 自身相似度设为0
user_similarities[is.na(user_similarities)] <- 0
rownames(user_similarities) <- rownames(train_data)
colnames(user_similarities) <- rownames(train_data)
user_similarities <- round(user_similarities, 3)
3 评分预测实现步骤与代码

3.1 预测核心步骤

  • 对每个目标用户u,筛选出Top K个相似度最高的邻居(K通常取20~100,可调整优化),仅保留相似度为正的邻居避免负权重干扰
  • 对用户u未评分的每部电影i,提取所有给i评过分的邻居用户
  • 对邻居的评分做加权平均,权重为对应邻居和u的相似度,得到u对i的预测评分:

    预测评分公式:( pred(u,i) = \frac{\sum_{v \in N(u,i)} sim(u,v) * r(v,i)}{\sum_{v \in N(u,i)} |sim(u,v)|} )
    其中N(u,i)是给i评过分的u的邻居集合,r(v,i)是用户v对i的真实评分

3.2 预测代码实现

# 可调参数:邻居数量K
K <- 50
# 初始化预测矩阵,和原矩阵维度一致
pred_matrix <- matrix(NA, nrow = nrow(train_data), ncol = ncol(train_data))
rownames(pred_matrix) <- rownames(train_data)
colnames(pred_matrix) <- colnames(train_data)

for (u in 1:nrow(train_data)) {
  # 取当前用户的Top K正相似度邻居
  sim_vec <- user_similarities[u, ]
  top_neighbors <- order(sim_vec, decreasing = TRUE)[1:K]
  top_neighbors <- top_neighbors[sim_vec[top_neighbors] > 0] # 过滤负相似度
  top_sim <- sim_vec[top_neighbors]
  
  # 计算当前用户所有未评分电影的预测分
  unrated_cols <- which(is.na(train_data[u, ]))
  for (i in unrated_cols) {
    # 提取邻居中对i有评分的用户
    neighbor_rated <- which(!is.na(train_data[top_neighbors, i]))
    if (length(neighbor_rated) == 0) {
      # 没有邻居评分时,用当前用户的平均评分填充
      pred_matrix[u, i] <- mean(train_data[u, ], na.rm = TRUE)
      next
    }
    # 加权计算预测分
    sum_sim_rating <- sum(top_sim[neighbor_rated] * train_data[top_neighbors[neighbor_rated], i])
    sum_sim <- sum(abs(top_sim[neighbor_rated]))
    pred_matrix[u, i] <- sum_sim_rating / sum_sim
  }
}
# 输出结果四舍五入到1位小数和示例输出匹配
pred_matrix <- round(pred_matrix, 1)

运行完成后pred_matrix就是你需要的预测结果矩阵,你可以通过pred_matrix[test_mask]提取测试集的预测值,和final_data[test_mask]的真实值计算RMSE等评估指标。


内容的提问来源于stack exchange,提问作者Anilaaryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 02:54:05