使用CountVectorizer生成二元/三元组时遇内存不足问题求助
内存高效的N-gram提取方案
核心问题根源
你遇到的内存错误完全是因为ngrams.toarray()把稀疏矩阵(csr_matrix)强制转成了稠密数组——稀疏矩阵只存非零值,而稠密数组要存所有84891×12780210个元素,这显然超出了内存极限。下面是几个直接可行的优化方案:
1. 直接在稀疏矩阵上计算词频(最有效)
不用把稀疏矩阵转成稠密数组,直接调用稀疏矩阵的sum方法,再转成一维数组即可:
from sklearn.feature_extraction.text import CountVectorizer import pandas as pd lemmatized = dat_clean['lemmatized'] c_vec = CountVectorizer(ngram_range=(2,3), lowercase=False) ngrams = c_vec.fit_transform(lemmatized) # 直接在稀疏矩阵上按列求和,A1转成一维数组 count_values = ngrams.sum(axis=0).A1 vocab = c_vec.vocabulary_ # 按词频排序构建DataFrame df_ngram = pd.DataFrame( sorted([(count_values[i], k) for k, i in vocab.items()], reverse=True), columns=['frequency', 'bigram/trigram'] )
这个操作全程基于稀疏矩阵,内存占用只和非零元素数相关,不会出现几十TiB的内存需求。
2. 提前过滤低频率N-gram(减少特征数)
如果特征数还是太大,可以通过CountVectorizer的参数提前过滤掉出现次数极少的N-gram,大幅压缩特征空间:
# 示例:只保留至少出现2次、最多在80%文档中出现的N-gram c_vec = CountVectorizer( ngram_range=(2,3), lowercase=False, min_df=2, # 至少在2个文档中出现 max_df=0.8, # 不在超过80%的文档中出现 max_features=100000 # 可选:限制最多保留10万个特征 )
min_df是最有效的过滤参数,大部分低频N-gram都是噪声,过滤后特征数会骤降。
3. 分块处理大规模语料(极端情况)
如果语料规模极大,连稀疏矩阵都存不下,可以分块加载语料,逐步累加N-gram计数:
from collections import defaultdict import pandas as pd # 初始化CountVectorizer的分析器 c_vec = CountVectorizer(ngram_range=(2,3), lowercase=False) analyzer = c_vec.build_analyzer() # 遍历语料,逐个统计N-gram出现次数 ngram_counter = defaultdict(int) for text in lemmatized: ngrams = analyzer(text) for ngram in ngrams: ngram_counter[ngram] += 1 # 转成DataFrame并排序 df_ngram = pd.DataFrame( sorted(ngram_counter.items(), key=lambda x: x[1], reverse=True), columns=['bigram/trigram', 'frequency'] )
这种方法不需要一次性构建整个文档-词矩阵,内存占用只和所有唯一N-gram的数量相关。
内容的提问来源于stack exchange,提问作者Kaitlin
相关产品推荐
相关产品推荐

