我正在编写一个朴素贝叶斯分类器,因为我有一大组文本文档需要分类。然而,当我尝试测试我的预测时,我得到了以下错误
sklearn.utils.validation.NotFittedError: TfidfVectorizer – Vocabulary wasn’t fitted.
我在提问前做了什么
我了解朴素贝叶斯分类的理论是如何工作的。
P(B|A)*P(A) P(A|B) = ____________________ P(B|A)*P(A) + P(B|C)*P(C) +...+P(B|n)*P(n)
其中A到n是你想要分类的不同类别,P(B|A)是给定A发生的情况下B发生的概率,P(A)是A发生的概率。需要注意的是,我特别使用的是多项式朴素贝叶斯。
我还找到了这个问题:
SciPy和scikit-learn – ValueError: Dimension mismatch
以及这个问题
然而,当我尝试进行预测或测试我的预测时,我仍然遇到问题。
我编写了以下函数,用于创建训练和测试集
def split_data_set(original_data_set, percentage): test_set = [] train_set = [] forbidden = set() split_sets = {} if is_float(percentage): stop_len = int(percentage * len(original_data_set)) while len(train_set) < stop_len: random_selection = randrange(0, len(original_data_set)) if random_selection not in forbidden: forbidden.add(random_selection) train_set.append(original_data_set[random_selection]) for j in range(0, len(original_data_set)-1): if j not in forbidden: test_set.append(original_data_set[j]) split_sets.update({'testing set': test_set}) split_sets.update({'training set': train_set}) split_sets.update({'forbidden': forbidden}) return split_sets
创建并训练模型
def create_and_fit_baes_model(data_set): train = [] expect = [] for data in data_set['training set']: train.append(data[1]) expect.append(data[0]) vectorizer = TfidfVectorizer(min_df=1) # 我认为这是我做错的地方之一 vectorized_training_data = vectorizer.fit_transform(train) model = MultinomialNB() model.fit(vectorized_training_data, expect) return model
以及测试我的模型
def test_nb_model(data_set, model): test = [] expect = [] for data in data_set['testing set']: test.append(data[1]) expect.append(data[0]) # 这是我认为另一个做错的地方 vectorizer = TfidfVectorizer(min_df=1) vectorized_testing_data = vectorizer.transform(test) fitted_vectorized_testing_data = vectorizer.fit(vectorized_testing_data) predicted = model.predict(fitted_vectorized_testing_data) print(metrics.confusion_matrix(expect,predicted)) print(metrics.classification_report(expect, predicted))
我认为我在变换/拟合阶段遇到了问题。
我知道tfidf向量化是如何工作的
这将是一个由包含不同术语计数的文档组成的常规矩阵。
_term1____term2____term3____termn____________doc1| 5 | 0 | 13 | 1doc2| 0 | 8 | 2 | 0doc3| 1 | 5 | 5 | 10. | . | . | . | .. | . | . | . | .. | . | . | . | .docn| 10 | 0 | 0 | 0
从这里你可以应用一个加权方案来确定特定词语对你的语料库的重要性。
我知道所有这些理论上的工作原理,我可以在纸上计算出数学,但当我尝试阅读sklearn的文档时,我仍然有点困惑,不知道应该如何编写所有代码。
我已经为此挣扎了两天。如果有人能提供一些关于我做错什么以及如何完全训练和运行我的模型的见解,我将不胜感激。
回答:
我认为最干净的选择是使用Pipeline
将你的向量化器和分类器打包在一起;然后如果你调用model.fit
,这将拟合你的向量化器的词汇和术语频率,并使它们在后续函数中可用。这样你仍然可以只从你的训练函数中返回一个“模型”,并且你也可以将此模型pickle化,如果你需要保存你的模型的话。
from sklearn.pipeline import Pipelinedef create_and_fit_model(data): # ... 获取你的训练和期望数据 vectorizer = TfidfVectorizer(min_df=1) nb = MultinomialNB() model = Pipeline([('vectorizer', vectorizer), ('nb', nb)]) model.fit(train, expect) return model
顺便说一下,你不需要自己编写训练/测试分割的代码,你可以使用sklearn.cross_validation.train_test_split
。此外,你应该考虑使用pandas来存储你的数据,而不是使用普通列表;这将更容易提取列数据。