我正在尝试通过sklearn学习如何处理文本数据,但遇到一个我无法解决的问题。
我正在遵循的教程是:http://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html
输入是一个包含两列的pandas数据框。一列是文本,另一列是二元类别。
代码:
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformerfrom sklearn.naive_bayes import MultinomialNBfrom sklearn.pipeline import Pipelinetraindf, testdf = train_test_split(nlp_df, stratify=nlp_df['class'])x_train = traindf['text']x_test = traindf['text']y_train = traindf['class']y_test = testdf['class']# CVcount_vect = CountVectorizer(stop_words='english')x_train_modified = count_vect.fit_transform(x_train)x_test_modified = count_vect.transform(x_test)# TF-IDFidf = TfidfTransformer()fit = idf.fit(x_train_modified)x_train_mod2 = fit.transform(x_train_modified)# MNBmnb = MultinomialNB()x_train_data = mnb.fit(x_train_mod2, y_train)text_clf = Pipeline([('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', MultinomialNB()), ])predicted = text_clf.predict(x_test_modified)
当我尝试运行最后一行时:
---------------------------------------------------------------------------NotFittedError Traceback (most recent call last)<ipython-input-64-8815003b4713> in <module>()----> 1 predicted = text_clf.predict(x_test_modified)~/anaconda3/lib/python3.6/site-packages/sklearn/utils/metaestimators.py in <lambda>(*args, **kwargs) 113 114 # lambda, but not partial, allows help() to work with update_wrapper--> 115 out = lambda *args, **kwargs: self.fn(obj, *args, **kwargs) 116 # update the docstring of the returned function 117 update_wrapper(out, self.fn)~/anaconda3/lib/python3.6/site-packages/sklearn/pipeline.py in predict(self, X) 304 for name, transform in self.steps[:-1]: 305 if transform is not None:--> 306 Xt = transform.transform(Xt) 307 return self.steps[-1][-1].predict(Xt) 308 ~/anaconda3/lib/python3.6/site-packages/sklearn/feature_extraction/text.py in transform(self, raw_documents) 918 self._validate_vocabulary() 919 --> 920 self._check_vocabulary() 921 922 # use the same matrix-building strategy as fit_transform~/anaconda3/lib/python3.6/site-packages/sklearn/feature_extraction/text.py in _check_vocabulary(self) 301 """Check if vocabulary is empty or missing (not fit-ed)""" 302 msg = "%(name)s - Vocabulary wasn't fitted."--> 303 check_is_fitted(self, 'vocabulary_', msg=msg), 304 305 if len(self.vocabulary_) == 0:~/anaconda3/lib/python3.6/site-packages/sklearn/utils/validation.py in check_is_fitted(estimator, attributes, msg, all_or_any) 766 767 if not all_or_any([hasattr(estimator, attr) for attr in attributes]):--> 768 raise NotFittedError(msg % {'name': type(estimator).__name__}) 769 770 NotFittedError: CountVectorizer - Vocabulary wasn't fitted.
关于如何修复此错误,您有什么建议吗?我已经正确地在测试数据上转换了CV模型。我甚至检查了词汇列表是否为空,它不是(count_vect.vocabulary_)
谢谢!
回答:
你的问题中有几个问题。
首先,你实际上没有对管道进行拟合,因此出现了错误。仔细查看链接的教程,你会看到有一个步骤text_clf.fit
(其中text_clf
确实是管道)。
其次,你没有正确使用管道的概念,管道的目的是端到端地拟合整个流程;相反,你一个接一个地拟合其各个组件…如果你再次查看教程,你会看到管道拟合
的代码:
text_clf.fit(twenty_train.data, twenty_train.target)
使用的是数据的初始形式,不是它们的中间转换,如你所做的那样;教程的目的是展示如何将各个转换包装在(并替换为)一个管道中,不是在这些转换之上使用管道…
第三,你应该避免将变量命名为fit
– 这是保留关键字;同样,我们不使用CV来缩写Count Vectorizer(在机器学习术语中,CV代表交叉验证)。
话虽如此,这是使用你的管道正确的方式:
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformerfrom sklearn.naive_bayes import MultinomialNBfrom sklearn.pipeline import Pipelinetraindf, testdf = train_test_split(nlp_df, stratify=nlp_df['class'])x_train = traindf['text']x_test = traindf['text']y_train = traindf['class']y_test = testdf['class']text_clf = Pipeline([('vect', CountVectorizer(stop_words='english')), ('tfidf', TfidfTransformer()), ('clf', MultinomialNB()), ])text_clf.fit(x_train, y_train) predicted = text_clf.predict(x_test)
如你所见,管道的目的是使事情变得更简单(与依次使用各个组件相比),而不是使事情变得更加复杂…