pandas1.1.5下如何将大体积词袋稀疏矩阵转为数组避免内存错误
报错根因
你当前触发内存不足的核心原因是:17799行 × 275656列的int64类型稠密数组,总占用内存恰好为36.6GiB,远超常规机器的可用内存上限。直接通过for循环逐元素转换并不能解决问题——最终整个数组还是要全部加载到内存中,内存占用和直接调用toarray()完全一致。
最优解决方案(按优先级排序)
方案1:直接使用稀疏矩阵,不转稠密数组
绝大多数数据处理、机器学习库均原生支持scipy稀疏矩阵格式作为输入,包括scikit-learn的分类、聚类、回归全系列算法,pandas也可通过SparseArray对接稀疏矩阵,完全不需要转换为稠密数组。你只需删除原有代码里的.toarray()即可,修改后代码如下:
这是成本最低、效率最高的方案,无额外内存开销。vector1 = CountVectorizer(ngram_range=(1,2)) sparse_mat = vector1.fit_transform(text)方案2:压缩数据类型降低内存占用
词袋模型的计数结果最大值通常不会超过单篇文档的总词数,完全不需要用到int64的取值范围,你可以将数据类型转换为int8(取值范围-128127)或uint8(取值范围0255),内存占用直接降低为原来的1/8,36.6GiB可压缩至4.6GiB左右,常规机器均可承载。代码示例:import numpy as np vector1 = CountVectorizer(ngram_range=(1,2)) dense_mat = vector1.fit_transform(text).astype(np.int8).toarray()方案3:过滤低价值特征减少维度
27万+的特征中大量为低频、无统计意义的n-gram特征,你可以在初始化CountVectorizer时添加过滤参数,直接降低特征维度:- 添加
min_df=3:仅保留在至少3篇文档中出现过的特征 - 添加
max_features=20000:仅保留词频最高的前2万个特征
维度降低后,自然可以顺利转换为稠密数组。
- 添加
方案4:分块存储到磁盘(必须使用完整稠密数组时选择)
如果你的下游场景必须使用完整的稠密数组,可以使用numpy的memmap映射机制,将数组直接存到磁盘,不需要全部加载到内存,使用方式和普通numpy数组基本一致。代码示例:import numpy as np vector1 = CountVectorizer(ngram_range=(1,2)) sparse_mat = vector1.fit_transform(text) # 创建磁盘映射数组,不占用运行内存 mmap_mat = np.memmap("full_count_mat.npy", dtype="int8", mode="w+", shape=sparse_mat.shape) # 按1000行的批次分批转换写入 batch_size = 1000 for idx in range(0, sparse_mat.shape[0], batch_size): mmap_mat[idx:idx+batch_size] = sparse_mat[idx:idx+batch_size].astype(np.int8).toarray() # 落盘保存 mmap_mat.flush()
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

