如何合并列不同的binaryRatingMatrix?recommenderlab内存问题求助
解决recommenderlab中binaryRatingMatrix合并与内存优化问题
问题描述
使用recommenderlab处理大规模数据时遇到内存瓶颈,尝试将数据分块生成两个binaryRatingMatrix后无法合并,例如使用rbind.fill.matrix(S1@data,S2@data)时出现错误:Error in as.vector(data) : no method for coercing this S4 class to a vector。
生成两个矩阵的原始代码:
S1 <- S1 %>% select(SessionID, material_number) %>% mutate(value = 1) %>% spread(material_number,value, fill = 0) %>% select(-SessionID) %>% as.matrix() %>% as("binaryRatingMatrix")
S2 <- S2 %>% select(SessionID, material_number) %>% mutate(value = 1) %>% spread(material_number,value) %>% select(-SessionID) %>% as.matrix() %>% as("binaryRatingMatrix")
一、binaryRatingMatrix合并方法
binaryRatingMatrix是S4类,内部存储为稀疏矩阵(dgCMatrix类型),不能直接用普通矩阵合并方法操作。以下是两种可行的合并方案:
方案1:基于稀疏矩阵的高效合并
直接操作矩阵内部的稀疏结构,保证列(物品)一致后合并:
library(Matrix) # 提取两个矩阵的物品列名 items1 <- colnames(S1@data) items2 <- colnames(S2@data) all_items <- union(items1, items2) # 扩展S1到包含所有物品 S1_dgc <- S1@data missing_cols_S1 <- setdiff(all_items, items1) if (length(missing_cols_S1) > 0) { # 补全缺失列的0值稀疏矩阵 add_cols <- Matrix(0, nrow = nrow(S1_dgc), ncol = length(missing_cols_S1), sparse = TRUE) colnames(add_cols) <- missing_cols_S1 S1_dgc <- cbind(S1_dgc, add_cols) } # 统一列顺序 S1_dgc <- S1_dgc[, all_items] # 同理扩展S2 S2_dgc <- S2@data missing_cols_S2 <- setdiff(all_items, items2) if (length(missing_cols_S2) > 0) { add_cols <- Matrix(0, nrow = nrow(S2_dgc), ncol = length(missing_cols_S2), sparse = TRUE) colnames(add_cols) <- missing_cols_S2 S2_dgc <- cbind(S2_dgc, add_cols) } S2_dgc <- S2_dgc[, all_items] # 合并稀疏矩阵并转回binaryRatingMatrix combined_dgc <- rbind(S1_dgc, S2_dgc) combined_matrix <- as(combined_dgc, "binaryRatingMatrix")
方案2:通过DataFrame中转合并
如果数据量不是极端大,可以先转换为长格式DataFrame合并,再转回binaryRatingMatrix:
# 转换为长格式DataFrame df1 <- as(S1, "data.frame") df2 <- as(S2, "data.frame") # 合并DataFrame combined_df <- rbind(df1, df2) # 转回binaryRatingMatrix combined_matrix <- as(combined_df, "binaryRatingMatrix")
二、核心内存优化方案
你的原始代码中spread+as.matrix()是内存爆炸的关键——spread生成的密集宽表会占用大量内存,as.matrix()进一步将稀疏数据转为密集矩阵,完全没必要。以下是优化建议:
1. 直接从长格式数据构造稀疏矩阵
跳过spread步骤,直接用长数据创建稀疏矩阵,再转换为binaryRatingMatrix,这能大幅降低内存占用:
library(Matrix) library(dplyr) # 处理S1的优化代码 S1_long <- S1 %>% select(SessionID, material_number) %>% mutate(value = 1) # 生成用户和物品的唯一列表 users_S1 <- unique(S1_long$SessionID) items_S1 <- unique(S1_long$material_number) # 构造稀疏矩阵 i_S1 <- match(S1_long$SessionID, users_S1) j_S1 <- match(S1_long$material_number, items_S1) sparse_S1 <- sparseMatrix( i = i_S1, j = j_S1, x = 1, dims = c(length(users_S1), length(items_S1)), dimnames = list(users_S1, items_S1) ) # 转换为binaryRatingMatrix S1 <- as(sparse_S1, "binaryRatingMatrix") # S2用同样逻辑处理
2. 避免不必要的类型转换
全程使用稀疏矩阵操作,不要将binaryRatingMatrix转为密集矩阵(如as.matrix()),所有推荐算法都支持直接基于稀疏矩阵运算。
3. 分块增量处理
如果数据量超大无法一次性合并,可考虑:
- 分块训练推荐模型(部分算法支持增量更新,如基于用户/物品的邻域模型)
- 结合大数据工具(如
sparklyr),利用分布式稀疏矩阵处理能力
内容的提问来源于stack exchange,提问作者BoutMouse
相关产品推荐
相关产品推荐

