pd.DataFrame

问题描述

我有一个带有2列和500万行的DF,所有文字(商家的客户评论)。 df.head()产生:

enter image description here

df.info()显示内存使用量只有120.3+ MB

我正在尝试使用gensim库对df['text']进行主题建模。我尝试先创建一个文档术语矩阵(dtm),然后执行如下的潜在Dirichlet分配(LDA):

from sklearn.feature_extraction.text import CountVectorizer
from nltk.corpus import stopwords
from gensim import matutils,models
import scipy.sparse

cv = CountVectorizer(stop_words='english')
data_cv = cv.fit_transform(df.text)
data_dtm = pd.DataFrame(data_cv.toarray(),columns=cv.get_feature_names()) #LINE THROWING MemoryError

data_dtm.index = df.index

tdm = data_dtm.transpose()

sparse_counts = scipy.sparse.csr_matrix(tdm)
corpus = matutils.Sparse2Corpus(sparse_counts)

id2word = dict((v,k) for k,v in cv.vocabulary_.items())
lda = models.Ldamodel(corpus=corpus,id2word=id2word,num_topics=2,passes=10)
lda.print_topics()

问题:但是第7行(pd.DataFrame())抛出MemoryError,而我仍然有60%的机器可用内存。即使我对df的前100,000行重复该操作,也会得到相同的MemoryError。

由于这是主题建模,所以我宁愿一起分析所有行,或者至少分批分析它们。

问题是什么导致将data_cv转换为数据帧时Python耗尽内存?我该如何克服?

解决方法

通过将有效的稀疏表示转换为完整/密集数组,很有可能data_cv.toarray()对内存扩展最负责。

尝试在单独的前一行上的该步骤中将其放入临时变量中进行检查。

但是,如果您的最终目标是进行Gensim LDA分析,则这些步骤将标记化文本作为输入可以很好地工作,因此其他操作(涉及CountVectorizer并在Pandas数据结构中存储临时结果或巨型术语文档数组)可能是多余的。

例如(忽略任何停用词过滤):

from gensim.corpora.dictionary import Dictionary
from gensim.models import LdaModel

tokenized_texts = [text_string.split() for text_string in df.text]
texts_dictionary = Dictionary(tokenized_texts)
texts_bows = [texts_dictionary.doc2bow(text_tokens) for text_tokens in tokenized_texts]

lda = LdaModel(corpus=texts_bows,id2word=texts_dictionary,num_topics=2)

这仍会在内存中创建df.text列的两个巨型副本,一个tokenized_texts的列表和一个texts_bows的列表,因此它使用更多的内存比最优。 (对于大型语料库,最佳做法是将它们保留在磁盘上,并将它们逐项流式传输到处理步骤中。)

但是,它使用的步骤可能比密集的.toarray()步骤要少,甚至永远不会创建非严格必要的CountVectorizer或临时数组和DataFrame对象。