所有预处理都会降低准确性

时间:2017-07-04 18:45:18

标签: python scikit-learn countvectorizer

我正在使用逻辑回归模型执行网格搜索交叉验证。我首先拥有默认模型,然后是预处理数据的模型。数据是随机文本文档,属于4个类别之一。我的预处理器似乎会恶化我的准确性和f1分数,即使我只是让它返回数据,如下所示。 gridsearch在通过这个不应该做任何事情的预处理后选择的正则化参数C.

Cs = {'C' : [0.0001, 0.001, 0.01, 0.1, 0.5, 1.0, 2.0, 10.0]}
gs_clf_LR = GridSearchCV(LogisticRegression(penalty='l2'), Cs, refit=True)
gs_clf_LR.fit(transformed_train_data, train_labels)
preds = gs_clf_LR.predict(transformed_dev_data)
#print gs_clf_LR.score(transformed_dev_data, dev_labels)
print gs_clf_LR.best_params_
print 'With optimal C, accuracy score is: ', gs_clf_LR.best_score_
print 'f1 score: ', metrics.f1_score(dev_labels, preds, average='weighted')
print metrics.classification_report(dev_labels, preds)
print

def better_preprocessor(string):
    #return re.sub(r'^[A-Z]', '^[a-z]', string)
    #return re.sub(r'(ing)$', '', string)
    #return re.sub(r'(es)$', '', string)
    #return re.sub(r's$', '', string)
    #return re.sub(r'(ed)$', '', string)
    return string


vec = CountVectorizer(preprocessor=better_preprocessor)
transformed_preprocessed_train_data = vec.fit_transform(train_data)
transformed_preprocessed_dev_data = vec.transform(dev_data)

gs_clf_LR.fit(transformed_preprocessed_train_data, train_labels)
preds_pp = gs_clf_LR.predict(transformed_preprocessed_dev_data)
#print gs_clf_LR.score(transformed_preprocessed_dev_data, dev_labels)
print gs_clf_LR.best_params_
print 'With optimal C, accuracy score is: ', gs_clf_LR.best_score_
print 'f1 score: ', metrics.f1_score(dev_labels, preds_pp, average='weighted')
print metrics.classification_report(dev_labels, preds_pp)

通过一些真正的预处理,例如我已经注释掉的正则表达式线,我也看到了我的准确性和f1得分的降低(似乎合理但我已经摆脱了复数并且被告知这应该提高我的分数)。

2 个答案:

答案 0 :(得分:2)

您是否已将随机生成的测试集与交叉验证之外的数据分开,以测试两个模型?通过减少对数据的过度拟合,可以更准确地降低精度。

答案 1 :(得分:0)

问题在于您的预处理基本上什么都不做,因为预处理是在标记化之前在CountVectorizer中发生的事情。这意味着您可以通过您的函数获得整个文本,并且最终不会出现$的正则表达式。

这是使用better_preprocessing

拟合矢量图的结果
In [16]: data = ['How are you guys doing? Fine! We are very satisfied']

In [17]: vec.fit(data)
Out[17]:
CountVectorizer(analyzer='word', binary=False, decode_error='strict',
        dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
        lowercase=True, max_df=1.0, max_features=None, min_df=1,
        ngram_range=(1, 1),
        preprocessor=<function better_preprocessor at 0x000002DB839FF048>,
        stop_words=None, strip_accents=None,
        token_pattern='(?u)\\b\\w\\w+\\b', tokenizer=None, vocabulary=None)

In [18]: vec.get_feature_names()
Out[18]: ['Fine', 'We', 'are', 'doing', 'guys', 'ow', 'satisfied', 'very', 'you']

这意味着您必须使用您的功能覆盖analyzer步骤,而不是preprocessor。比较:

  

分析器:字符串,{'word','char','char_wb'}或可调用是否   功能应该由单词或字符n-gram组成。选项'char_wb'   仅从字边界内的文本创建字符n-gram。如果一个   callable被传递它用于提取特征序列   未经处理的原始输入。

     

预处理程序:可调用或无   (默认)覆盖预处理(字符串转换)阶段   同时保留了令牌化和n-gram生成步骤。

但是,您必须在函数中处理标记化,但是您可以使用默认的'(?u)\\b\\w\\w+\\b',因此并不困难。无论如何,我不认为你的方法是非常可靠的,我建议使用来自NLTK的SnowballStemmer而不是这些正则表达式。