机器学习模型输出训练标签而非测试预测结果,求问题排查
问题排查:MultinomialNB模型未正确处理测试数据
问题背景
尝试构建基于message、fingers、tail特征预测species的MultinomialNB模型,数据样例如下:
| message | fingers | tail | species |
|---|---|---|---|
| pluvia arbor aquos | 4 | no | Aquari |
| cosmix xeno nebuz odbitaz | 5 | yes | Zorblax |
| solarix glixx novum galaxum quasar | 5 | yes | Zorblax |
| arbor insectus pesros ekos dootix nimbus | 2 | yes | Florian |
运行代码后,模型未对299条测试数据进行预测,反而输出训练数据(500条)的species标签(仅少量差异,共输出493条结果),无法完成测试任务。
原代码:
import warnings warnings.simplefilter("ignore") import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import LabelEncoder from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB df = pd.read_csv("data.csv") X = np.asarray(df[["message", "fingers", "tail"]]) X = [str (item) for item in X] y = df["species"] le = LabelEncoder() y = le.fit_transform(y) cv = CountVectorizer() X = cv.fit_transform(X).toarray() model = MultinomialNB() model.fit(X, y) test_data = pd.read_csv('test.csv') test_data_array = np.asarray(df[["message", "fingers", "tail"]]) test_data_array = [str (item) for item in test_data_array] test_data_array = cv.fit_transform(test_data_array).toarray() y_prediction = model.predict(test_data_array) y_prediction = le.inverse_transform(y_prediction) print(y_prediction)
错误原因分析
- 测试数据来源错误:处理测试数据时,错误调用了训练集
df而非测试集test_data,导致输入模型的仍是训练数据,自然输出训练数据的预测结果。 - 特征向量化逻辑错误:对测试数据使用
cv.fit_transform()会重新训练CountVectorizer,覆盖训练阶段生成的词汇表,导致特征空间不匹配,这也是结果出现少量差异的原因。正确做法是使用cv.transform(),复用训练好的词汇表映射规则。
修正后的代码
import warnings warnings.simplefilter("ignore") import pandas as pd import numpy as np from sklearn.preprocessing import LabelEncoder from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB # 加载并处理训练数据 df = pd.read_csv("data.csv") # 将多列特征合并为空格分隔的字符串,适配CountVectorizer处理逻辑 X_train = df[["message", "fingers", "tail"]].apply(lambda row: ' '.join(row.astype(str)), axis=1) y_train = df["species"] # 标签编码 le = LabelEncoder() y_train_encoded = le.fit_transform(y_train) # 特征向量化:仅在训练数据上执行fit cv = CountVectorizer() X_train_vec = cv.fit_transform(X_train).toarray() # 训练模型 model = MultinomialNB() model.fit(X_train_vec, y_train_encoded) # 加载并处理测试数据 test_data = pd.read_csv('test.csv') # 用相同规则合并测试数据特征 X_test = test_data[["message", "fingers", "tail"]].apply(lambda row: ' '.join(row.astype(str)), axis=1) # 复用训练好的CountVectorizer,仅执行transform X_test_vec = cv.transform(X_test).toarray() # 预测并解码标签 y_prediction = model.predict(X_test_vec) y_prediction = le.inverse_transform(y_prediction) print(y_prediction)
额外优化说明
- 原代码中将数组转为字符串的方式会生成格式不规范的特征文本(如
['pluvia arbor aquos' '4' 'no']),改用apply逐行合并为空格分隔的字符串,特征表示更合理。 - 移除了未使用的
matplotlib.pyplot导入,精简代码结构。
内容的提问来源于stack exchange,提问作者harry
相关产品推荐
相关产品推荐

