Cholmod 错误 'problem too large' 到底是什么意思?将 dfm 转换为 df 时出现问题

What does the Cholmod error 'problem too large' means exactly? Problem when converting a dfm to a df

这是发布的另一个问题的新版本,现在有一个可重现的例子。

我正在尝试将文档特征矩阵从 29117 条推文转换为 R 中的数据框,但出现错误

"Error in asMethod(object) : Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105"

dfm 的大小约为 21MB,包含 29117 行和 78294 个特征(推文中的单词按列拆分为 1 或 0,具体取决于该单词是否出现在推文中)

##generel info;
memory.size(max=TRUE)
# [1] 11418.75
sessionInfo()
# R version 3.6.1 (2019-07-05)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
# Running under: Windows 10 x64 (build 18362)

##install packages, load librarys
# install.packages(c("quanteda", "devtools"))
# devtools::install_github("quanteda/quanteda.corpora")
library("quanteda")
library(RJSONIO)
library(data.table)
library(jsonlite)
library(dplyr)
library(glmnet)

##load data, convert to a dataframe, convert to a dfm

baseurl <- "https://raw.githubusercontent.com/alexlitel/congresstweets/master/data/"
d0 <- fromJSON(paste0(baseurl, "2019-10-07.json"), flatten = TRUE)
d1 <- fromJSON(paste0(baseurl, "2019-10-06.json"), flatten = TRUE)
d2 <- fromJSON(paste0(baseurl, "2019-10-05.json"), flatten = TRUE)
d3 <- fromJSON(paste0(baseurl, "2019-10-04.json"), flatten = TRUE)
d4 <- fromJSON(paste0(baseurl, "2019-10-03.json"), flatten = TRUE)
d5 <- fromJSON(paste0(baseurl, "2019-10-02.json"), flatten = TRUE)
d6 <- fromJSON(paste0(baseurl, "2019-10-01.json"), flatten = TRUE)
d7 <- fromJSON(paste0(baseurl, "2019-09-30.json"), flatten = TRUE)
d8 <- fromJSON(paste0(baseurl, "2019-09-29.json"), flatten = TRUE)
d9 <- fromJSON(paste0(baseurl, "2019-09-28.json"), flatten = TRUE)
d10 <- fromJSON(paste0(baseurl, "2019-09-27.json"), flatten = TRUE)
d11 <- fromJSON(paste0(baseurl, "2019-09-26.json"), flatten = TRUE)
d12 <- fromJSON(paste0(baseurl, "2019-09-25.json"), flatten = TRUE)

d <- rbind(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12)

rm(d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12)

d$text <- as.character(d$text)

dfm <-dfm((corpus(select(d, id, text))), remove_punct=TRUE, remove=c(  stopwords("english"), "t.co", "https", "rt", "amp", "http", "t.c", "can"))

dfm_df <- convert(dfm, to= 'data.frame')

#Error in asMethod(object) : 
  #Cholmod error 'problem too large' at file ../Core/cholmod_dense.c, line 105

下面的代码适用于具有 2000 行的数据集样本(dfm (2MB) 中的 12577 个特征)。

我需要将 dfm 转换为数据框,因为我想添加变量并在二元逻辑(套索)回归中使用它们,作为源以及推文是否为转推并包含 url


d_t <- d[c(1:2000), (1:7)]

##code control variable

#url

d_t$url<- as.integer(ifelse(grepl("://", d_t$text), "1", "0"))

#source used
d_t$source_grp[grepl("Twitter for Android", d_t$source)] <- "Twitter for Android"
d_t$source_grp[grepl("Twitter Web Client", d_t$source)] <- "Twitter Web Client"
d_t$source_grp[grepl("Twitter for iPhone", d_t$source)] <- "Twitter for iPhone"
d_t$source_grp[grepl("Twitter for Windows", d_t$source)] <- "Twitter for Windows"
d_t$source_grp[grepl("Twitter for Samsung Tablets", d_t$source)] <- "Samsung Tablets"
d_t$source_grp[grepl("Twitter for Android Tablets", d_t$source)] <- "Android Tablets"
d_t$source_grp[grepl("Twitter for Windows Phone", d_t$source)] <- "Windows Phone"
d_t$source_grp[grepl("Twitter for BlackBerry", d_t$source)] <- "BlackBerry"
d_t$source_grp[grepl("Twitter for iPad", d_t$source)] <- "Twitter for iPad"
d_t$source_grp[grepl("Twitter for Mac", d_t$source)] <- "Twitter for Mac"
d_t$source_grp[is.na(d_t$source_grp)] <- "Other"   

#retweet

d_t$retweet <- ifelse(grepl("RT @", d_t$text), "1", "0") #create a variable that takes the value 1 when it is a RT

##create a x and y matrix

x= model.matrix ( retweet~., cbind(select(d_t, retweet, source_grp, url), convert(dfm((corpus(select(d_t, id, text))), remove_punct=TRUE, remove=c(  stopwords("english"), "t.co", "https", "rt", "amp", "http", "t.c", "can")), to="data.frame")) )[,-1]

y=d_t$retweet

lasso <- cv.glmnet(x=x, y=y, alpha=1, nfolds=5, family="binomial")


我读过其他帖子说 'problem too large' 错误是因为 RAM 的数量。这个数据不是很大,我尝试创建一个 30RAM 的虚拟机(在 64 位 windows 上,有 30GB 可用空间 space),但我仍然遇到同样的错误。 因此,我想知道是不是 RAM 的数量有问题,或者 R 中数据帧的列数是否有限制?我可以毫无问题地将相同大小和更大的额外 DFM 添加到内存中。

减少数据集并重新运行代码不是解决方案,因为这已经是示例。我需要从 6 mio 行数据集(如果可能)创建的 dfm 创建一个数据框(或类似的东西)

感谢任何 help/solutions,还有其他将变量添加到 dfm 而无需将其转换为数据帧的方法。

提前致谢!

问题是您正在尝试将稀疏矩阵 (dfm) 转换为密集对象。在您的情况下,它的尺寸为:

> dfm
Document-feature matrix of: 29,117 documents, 78,294 features (100.0% sparse).

> prod(dim(dfm))
[1] 2279686398

或23亿个单元格,这就是错误发生的原因。该对象非常稀疏,这就是为什么它作为 dfm 不是问题,但当您尝试在矩阵中记录如此多的零时会爆炸。大多数对象为空:

> sparsity(dfm)
[1] 0.9996795

表示 99.97% 的单元格为零。即使您可以创建 data.frame,拟合 LASSO 模型也不会起作用,因为特征中极度缺乏信息。

解决方案?Trim一些特征。

这有效,至少在我的机器上是这样:

> dfmtrimmed <- dfm_trim(dfm, min_docfreq = 10, min_termfreq = 20, verbose = TRUE)
Removing features occurring: 
  - fewer than 20 times: 73,573
  - in fewer than 10 documents: 70,697
  Total features removed: 73,573 (94.0%).
> dfmtrimmed
Document-feature matrix of: 29,117 documents, 4,721 features (99.6% sparse).

> nrow(convert(dfmtrimmed, to = "data.frame"))
[1] 29117

但这仍然是 99.6% 的稀疏度,因此更积极地 trim 更有意义。