我正在使用 scikit 对短语进行文本分类以了解其含义。一些例子是:
"Yes" - label.yes
"Yeah" - label.yes
...
"I don't know" - label.i_don't_know
"I am not sure" - label.i_don't_know
"I have no idea" - label.i_don't_know
使用 TfidfVectorizer 和 MultinomialNB 分类器,一切都运行良好。
当我添加新的文本/标签对时出现问题:
"I" - label.i
预测“I”的类仍然返回 label.i_don't_know,即使文本恰好在这样的训练数据中,这可能是由于一元组“I” 在 label.i_don't_know 中比在 label.i 中更频繁地出现。
是否有分类器可以在此任务上提供可比或更好的性能并保证正确返回训练数据元素的预测?
这段代码进一步说明了问题:
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
#instantiate classifier and vectorizer
clf=MultinomialNB(alpha=.01)
vectorizer =TfidfVectorizer(min_df=1,ngram_range=(1,2))
#Apply vectorizer to training data
traindata=['yes','yeah','i do not know','i am not sure','i have no idea','i'];
X_train=vectorizer.fit_transform(traindata)
#Label Ids
y_train=[0,0,1,1,1,2];
#Train classifier
clf.fit(X_train, y_train)
print clf.predict(vectorizer.transform(['i']))
代码输出标签 1,但正确的分类应该是标签 2。
最佳答案
问题不在于分类器,而在于向量化器。 TfidfVectorizer
有一个参数 token_pattern : string
,它是一个“表示什么构成“ token ”的正则表达式,仅在 tokenize == 'word' 时使用。默认的正则表达式选择2 个或更多字母字符的标记(标点符号被完全忽略并始终被视为标记分隔符)。” (强调)。分词器抛出单词 i
,生成一个空文档。然后,朴素贝叶斯将其分类为 1
类,因为这是训练数据中出现频率最高的类。
根据数据,您可能需要考虑对朴素贝叶斯使用统一先验。
关于为什么事情可能不起作用的进一步提示:
您的管道设置方式可能还有其他一些奇怪之处。我发现检查每个阶段(分词器、向量化器、分类器等)的输入和输出很有用。从长远来看,花一些时间编写单元测试将为您节省大量时间。
一旦您对一切正常工作感到满意,请尝试在测试数据上评估您的分类器。我怀疑您的类之间存在相当大的重叠,尤其是 label.i_don't_know
和 label.i
。如果是这种情况,分类器将表现不佳。
关于python - 用于文本分类任务的最佳 scikit 分类器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17418884/