如何正确地对文本分类器进行tfidf变换和“拟合”值?

我正在编写一个朴素贝叶斯分类器,因为我有一大组文本文档需要分类。然而,当我尝试测试我的预测时,我得到了以下错误

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来存储你的数据,而不是使用普通列表;这将更容易提取列数据。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注