使用Multinomial Naive Bayes做文本分类时训练集维度适配内存报错求助
解决IMDB情感分析中MultinomialNB的MemoryError及代码问题
看起来你在处理IMDB电影评论情感分析时遇到了两个核心问题:内存溢出错误,以及后续代码中的逻辑问题。我来一步步帮你解决:
1. 根源问题:MemoryError的解决
你遇到的MemoryError是因为这行代码:
X = (vectorizer.fit_transform(tokens).toarray())
CountVectorizer生成的是稀疏矩阵(scipy.sparse类型),这种矩阵只存储非零值,非常节省内存。但你用toarray()把它转换成了密集的numpy数组——IMDB数据集的词汇量非常大(通常上万甚至更多),每个评论都对应一个长度为词汇量的数组,这会瞬间占用大量内存,直接导致内存溢出。
解决方案:完全不需要转成密集数组!MultinomialNB原生支持稀疏矩阵输入,直接用稀疏矩阵训练即可,把这行代码改成:
X = vectorizer.fit_transform(tokens)
2. 修正后续代码的逻辑错误
你的代码里还有几个会导致报错的问题,一起修正:
(1)多余的reshape和transpose
你写了:
X = X.reshape() # 没有参数会直接报错 X = X.transpose()
CountVectorizer输出的稀疏矩阵形状是(样本数, 特征数),这正好是模型需要的输入格式(每个样本对应一行特征)。转置后会变成(特征数, 样本数),完全不符合模型要求,这两行代码直接删掉就行。
(2)模型训练与预测的语法错误
你把fit和predict连在一起赋值,这会导致mnb变成预测结果数组,而不是模型实例,后续调用score会报错。正确的写法是分开执行:
# 初始化模型,训练,然后预测 mnb = MultinomialNB() mnb.fit(X_train, y_train) y_pred = mnb.predict(X_test)
(3)print语句的格式化错误
你的print语句用了%格式化,但没有对应占位符,比如print("MNB " %mnb)会报错。改成正确的格式化方式,比如用f-string:
print(f"MNB预测结果示例: {y_pred[:10]}") # 打印前10个预测结果 print(f"准确率: {accuracy:.2f}")
(4)score方法的调用
score是模型实例的方法,你之前把mnb赋值成了预测结果,所以会报错。修正后用训练好的模型实例调用即可。
修正后的完整代码片段
import sklearn.datasets from sklearn.feature_extraction.text import CountVectorizer from sklearn.model_selection import train_test_split from sklearn.naive_bayes import MultinomialNB import numpy as np categories = ['pos','neg'] doc_to_train = sklearn.datasets.load_files( "/home/satyam/aclImdb_v1/aclImdb/train", categories=categories, encoding='utf-8', shuffle=True, random_state=42 ) vectorizer = CountVectorizer() # 直接用稀疏矩阵,不转成array X = vectorizer.fit_transform(tokens) y = np.array(doc_to_train.target) # 划分训练测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) # 模型训练与预测 mnb = MultinomialNB() mnb.fit(X_train, y_train) y_pred = mnb.predict(X_test) # 输出结果与准确率 print(f"部分预测结果: {y_pred[:5]}") print(f"真实标签对应: {y_test[:5]}") accuracy = mnb.score(X_test, y_test) print(f"MultinomialNB准确率: {accuracy:.4f}")
额外提示
- 确保你的
tokens是正确的输入格式:CountVectorizer.fit_transform接受的是字符串列表(每个元素是一个完整的文档),或者是分词后的列表的列表(每个子列表是一个文档的分词结果)。如果你的预处理是把每个文档分成了tokens列表,那这个输入是没问题的。 - 如果内存还是紧张,可以考虑用
TfidfVectorizer替代CountVectorizer,或者增加max_features参数限制词汇量(比如CountVectorizer(max_features=5000)),只保留最常见的5000个词,进一步节省内存。
内容的提问来源于stack exchange,提问作者Satyam Kumar
相关产品推荐
相关产品推荐

