Scikit-learn垃圾邮件分类预测时出现CountVectorizer未拟合错误
解决CountVectorizer加载时的Vocabulary wasn't fitted错误
这个问题我太熟了,咱们一步步拆解问题、搞定它!
错误原因分析
你在保存和加载环节犯了两个核心错误:
- 保存的对象完全不对:app.py里你用
pickle.dump(bow_transformer, open("vector.pkl", "wb"))保存的是CountVectorizer().fit_transform()的结果——这是一个已经转换好的稀疏特征矩阵,根本不是带有词汇表的CountVectorizer实例。这个矩阵里没有任何词汇表信息,自然没法用来转换新文本。 - 加载和使用逻辑混乱:temp.py里你新建了一个完全未拟合的
cv=CountVectorizer(),还搞反了加载的文件(把模型文件当成vectorizer,把矩阵当成分类器),用没学过词汇表的cv去transform,不出错才怪。
修正后的代码
第一步:修改app.py的保存逻辑
要保存拟合完成的CountVectorizer实例,而不是转换后的矩阵:
import pandas as pd import pickle from sklearn.feature_extraction.text import CountVectorizer from sklearn.model_selection import train_test_split from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import classification_report df = pd.read_csv('spam.csv', encoding="latin-1") # 丢弃无用列 df.drop(['Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4'], axis=1, inplace=True) # 标签映射为0/1格式 df['label'] = df['v1'].map({'ham': 0, 'spam': 1}) df['message'] = df['v2'] df.drop(['v1', 'v2'], axis=1, inplace=True) # 关键:先实例化vectorizer,拟合后保存这个实例(它包含训练好的词汇表) vectorizer = CountVectorizer() bow_transformer = vectorizer.fit_transform(df['message']) # 划分数据集 X_train, X_test, y_train, y_test = train_test_split(bow_transformer, df['label'], test_size=0.33, random_state=42) # 训练朴素贝叶斯模型 clf = MultinomialNB() clf.fit(X_train,y_train) y_pred = clf.predict(X_test) print(classification_report(y_test, y_pred)) # 保存拟合好的vectorizer和训练完成的模型 pickle.dump(vectorizer, open("vectorizer.pkl", "wb")) pickle.dump(clf, open("my_model.pkl", "wb"))
第二步:修改temp.py的预测逻辑
用加载后的vectorizer转换新文本,绝对不能新建未拟合的实例:
import pickle # 正确加载拟合好的vectorizer和分类器 vectorizer = pickle.load(open("vectorizer.pkl", "rb")) clf = pickle.load(open("my_model.pkl", "rb")) test_set = ["hello how are u"] # 用保存好的vectorizer转换测试文本(它会用训练时的词汇表处理新文本) new_test = vectorizer.transform(test_set) # 执行预测 prediction = clf.predict(new_test) # 输出友好结果 print("这是垃圾邮件(Spam)" if prediction[0] == 1 else "这是正常邮件(Ham)")
关键要点总结
- 保存文本特征提取器时,必须保存拟合完成的实例(比如这里的
vectorizer),而不是转换后的特征矩阵。 - 预测新文本时,必须用保存的特征提取器来转换,不能重新创建未拟合的实例——新实例没有学习过训练数据的词汇表,根本没法正确转换文本。
- 一定要注意文件加载的对应关系,别把vectorizer和模型的文件搞混了。
内容的提问来源于stack exchange,提问作者Himanshu
相关产品推荐
相关产品推荐

