如何在R的Keras/Torch中为layer_dense输入dgCMatrix稀疏矩阵
解决方法
一、Keras(TensorFlow后端)方案
Keras的layer_dense支持直接处理TensorFlow稀疏张量,无需将dgCMatrix转为稠密格式。核心思路是把dgCMatrix转换成TensorFlow的SparseTensor,再传入模型训练。
修改后完整代码
library(Matrix) library(keras) library(reticulate) library(magrittr) inputs <- rsparsematrix(10000, 1000, 0.1) targets <- keras::to_categorical(sample(0:9, 1000, replace = T), num_classes = 10) # 将dgCMatrix转为TensorFlow SparseTensor(转置为样本×特征维度) sparse_input <- inputs %>% t() %>% { tf$sparse$SparseTensor( indices = matrix(c(.@i, .@j), ncol = 2), # 0-based索引匹配TensorFlow规则 values = .@x, dense_shape = as.integer(dim(.)) ) } %>% tf$sparse$reorder() # 必须确保索引按行优先排序,避免训练报错 # 构建支持稀疏输入的模型 model <- keras_model_sequential() %>% layer_input(shape = nrow(inputs), sparse = TRUE) %>% layer_dense(units = 100, activation = "relu") %>% layer_dense(units = 50, activation = "relu") %>% layer_dense(units = ncol(targets), activation = "softmax") compile(model, loss = "categorical_crossentropy", optimizer = optimizer_adam(), metrics = c("accuracy")) # 直接用稀疏张量训练,无需转稠密 fit(model, sparse_input, targets, epochs = 10, batch_size = 32)
二、Torch方案
R的torch包原生支持稀疏张量,线性层(nn_linear())可直接处理稀疏输入,效率更适配大数据量场景。
完整代码示例
library(Matrix) library(torch) # 生成数据 inputs <- rsparsematrix(10000, 1000, 0.1) targets <- sample(0:9, 1000, replace = TRUE) %>% torch_tensor(dtype = torch_long()) # 分类任务需用long类型标签 # 将dgCMatrix转为Torch稀疏张量(转置为样本×特征维度) sparse_input <- inputs %>% t() %>% { indices <- torch_tensor(rbind(.@i, .@j), dtype = torch_long()) values <- torch_tensor(.@x) size <- torch_tensor(dim(.)) torch_sparse_coo_tensor(indices, values, size) } # 定义模型结构 model <- nn_module( initialize = function(input_dim, hidden_dim1, hidden_dim2, output_dim) { self$fc1 <- nn_linear(input_dim, hidden_dim1) self$fc2 <- nn_linear(hidden_dim1, hidden_dim2) self$fc3 <- nn_linear(hidden_dim2, output_dim) }, forward = function(x) { x %>% self$fc1() %>% nnf_relu() %>% self$fc2() %>% nnf_relu() %>% self$fc3() %>% nnf_log_softmax(dim = 2) } ) net <- model(input_dim = nrow(inputs), hidden_dim1 = 100, hidden_dim2 = 50, output_dim = 10) # 设置优化器与损失函数 optimizer <- optim_adam(net$parameters, lr = 0.001) loss_fn <- nn_nll_loss() # 训练循环 epochs <- 10 batch_size <- 32 num_samples <- ncol(inputs) for (epoch in 1:epochs) { net$train() perm <- sample(num_samples) total_loss <- 0 for (i in seq(1, num_samples, batch_size)) { batch_idx <- perm[i:min(i+batch_size-1, num_samples)] # 提取小批量稀疏张量,避免稠密转换 batch_mask <- inputs@j %in% (batch_idx - 1) batch_indices <- rbind(inputs@i[batch_mask], inputs@j[batch_mask]) batch_values <- inputs@x[batch_mask] batch_sparse <- torch_sparse_coo_tensor( indices = torch_tensor(batch_indices, dtype = torch_long()), values = torch_tensor(batch_values), size = torch_tensor(c(nrow(inputs), length(batch_idx))) ) %>% t() # 转置为样本×特征 optimizer$zero_grad() output <- net(batch_sparse) loss <- loss_fn(output, targets[batch_idx]) loss$backward() optimizer$step() total_loss <- total_loss + loss$item() } cat(sprintf("Epoch %d, Loss: %.4f\n", epoch, total_loss / ceiling(num_samples / batch_size))) }
内容的提问来源于stack exchange,提问作者zdebruine
相关产品推荐
相关产品推荐

