我如何 tfidf 正确转换和 "fit" 文本分类器的值?
How do I tfidf transform and "fit" the values for my text classifier correctly?
我正在编写朴素贝叶斯分类器,因为我有大量文本文档需要分类。但是,当我尝试测试我的预测时,出现以下错误
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 and scikit-learn - ValueError: Dimension mismatch
还有这个问题
cannot cast array data when a saved classifier is called
但是,当我尝试做出预测或测试我的预测时,我仍然遇到问题。
我编写了以下用于创建训练集和测试集的函数
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)
# I think this is one of the places where I'm doing something
# incorrectly
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])
#This is the other section where I think that
# I'm doing something incorrectly
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))
我认为我在 transformation/fitting 阶段遇到了问题。
我知道 tfidf 向量化的工作原理如下
这将是一个规则矩阵,由具有不同术语计数的文档组成。
_term1____term2____term3____termn____________
doc1| 5 | 0 | 13 | 1
doc2| 0 | 8 | 2 | 0
doc3| 1 | 5 | 5 | 10
. | . | . | . | .
. | . | . | . | .
. | . | . | . | .
docn| 10 | 0 | 0 | 0
从这里您可以应用加权方案来确定特定单词对您的语料库的重要性。
我知道所有这些在理论上是如何工作的,我可以在纸上计算出数学,但是当我尝试阅读 the documentation for sklearn 时,我仍然对我应该如何理解有点困惑编写所有代码。
过去两天我一直在为此苦苦挣扎。如果有人可以提供一些关于我做错了什么以及我如何全面训练和 运行 我的模型的见解,我将不胜感激。
我认为最干净的选择是使用 Pipeline
将矢量化器与分类器打包在一起;那么如果你调用 model.fit
,这将适合你的向量化器的词汇和术语频率,并使它们可用于以后的函数。这样你仍然可以从你的训练函数中 return 一个 "model",如果你需要保存你的模型,你也可以 pickle 这个。
from sklearn.pipeline import Pipeline
def create_and_fit_model(data):
# ... get your train and expect data
vectorizer = TfidfVectorizer(min_df=1)
nb = MultinomialNB()
model = Pipeline([('vectorizer', vectorizer), ('nb', nb)])
model.fit(train, expect)
return model
顺便说一下,您不需要为 train/test split 编写自己的代码,您可以使用 sklearn.cross_validation.train_test_split
。您还应该考虑使用 pandas 来存储数据而不是普通列表;它将更容易提取列。
我正在编写朴素贝叶斯分类器,因为我有大量文本文档需要分类。但是,当我尝试测试我的预测时,出现以下错误
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 and scikit-learn - ValueError: Dimension mismatch
还有这个问题
cannot cast array data when a saved classifier is called
但是,当我尝试做出预测或测试我的预测时,我仍然遇到问题。
我编写了以下用于创建训练集和测试集的函数
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)
# I think this is one of the places where I'm doing something
# incorrectly
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])
#This is the other section where I think that
# I'm doing something incorrectly
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))
我认为我在 transformation/fitting 阶段遇到了问题。
我知道 tfidf 向量化的工作原理如下
这将是一个规则矩阵,由具有不同术语计数的文档组成。
_term1____term2____term3____termn____________
doc1| 5 | 0 | 13 | 1
doc2| 0 | 8 | 2 | 0
doc3| 1 | 5 | 5 | 10
. | . | . | . | .
. | . | . | . | .
. | . | . | . | .
docn| 10 | 0 | 0 | 0
从这里您可以应用加权方案来确定特定单词对您的语料库的重要性。
我知道所有这些在理论上是如何工作的,我可以在纸上计算出数学,但是当我尝试阅读 the documentation for sklearn 时,我仍然对我应该如何理解有点困惑编写所有代码。
过去两天我一直在为此苦苦挣扎。如果有人可以提供一些关于我做错了什么以及我如何全面训练和 运行 我的模型的见解,我将不胜感激。
我认为最干净的选择是使用 Pipeline
将矢量化器与分类器打包在一起;那么如果你调用 model.fit
,这将适合你的向量化器的词汇和术语频率,并使它们可用于以后的函数。这样你仍然可以从你的训练函数中 return 一个 "model",如果你需要保存你的模型,你也可以 pickle 这个。
from sklearn.pipeline import Pipeline
def create_and_fit_model(data):
# ... get your train and expect data
vectorizer = TfidfVectorizer(min_df=1)
nb = MultinomialNB()
model = Pipeline([('vectorizer', vectorizer), ('nb', nb)])
model.fit(train, expect)
return model
顺便说一下,您不需要为 train/test split 编写自己的代码,您可以使用 sklearn.cross_validation.train_test_split
。您还应该考虑使用 pandas 来存储数据而不是普通列表;它将更容易提取列。