sklearn网格搜索f1_score与f1_score函数

时间:2017-04-27 15:55:22

标签: python scikit-learn cross-validation

我一直在尝试使用sklearn网格搜索和管道功能,并注意到返回的f1_score与使用硬编码参数生成的f1_score不匹配。寻求帮助理解为什么会这样。

数据背景:两列.csv文件

客户评论(字符串),类别标记(字符串)

使用开箱即用的单词方法,无需预处理文本,只需使用countVectorizer。

硬编码模型......

get .csv data into dataFrame
data_file = 'comment_data_basic.csv'
data = pd.read_csv(data_file,header=0,quoting=3)

#remove data without 'web issue' or 'product related' tag
data = data.drop(data[(data.tag != 'WEB ISSUES') & (data.tag != 'PRODUCT RELATED')].index)

#split dataFrame into two series
comment_data = data['comment']
tag_data = data['tag']

#split data into test and train samples
comment_train, comment_test, tag_train, tag_test = train_test_split(
    comment_data, tag_data, test_size=0.33)

#build count vectorizer
vectorizer = CountVectorizer(min_df=.002,analyzer='word',stop_words='english',strip_accents='unicode')
vectorizer.fit(comment_data)

#vectorize features and convert to array
comment_train_features = vectorizer.transform(comment_train).toarray()
comment_test_features = vectorizer.transform(comment_test).toarray()

#train LinearSVM Model
lin_svm = LinearSVC()
lin_svm = lin_svm.fit(comment_train_features,tag_train)

#make predictions
lin_svm_predicted_tags = lin_svm.predict(comment_test_features)

#score models
lin_svm_score = round(f1_score(tag_test,lin_svm_predicted_tags,average='macro'),3)
lin_svm_accur = round(accuracy_score(tag_test,lin_svm_predicted_tags),3)
lin_svm_prec = round(precision_score(tag_test,lin_svm_predicted_tags,average='macro'),3)
lin_svm_recall = round(recall_score(tag_test,lin_svm_predicted_tags,average='macro'),3)

#write out scores
print('Model    f1Score   Accuracy   Precision   Recall')
print('------   -------   --------   ---------   ------')
print('LinSVM   {f1:.3f}     {ac:.3f}      {pr:.3f}       {re:.3f}  '.format(f1=lin_svm_score,ac=lin_svm_accur,pr=lin_svm_prec,re=lin_svm_recall))

f1_score输出通常约为0.86 (取决于随机种子值)

现在,如果我基本上用网格搜索和管道重建相同的输出......

#get .csv data into dataFrame
data_file = 'comment_data_basic.csv'
data = pd.read_csv(data_file,header=0,quoting=3)

#remove data without 'web issue' or 'product related' tag
data = data.drop(data[(data.tag != 'WEB ISSUES') & (data.tag != 'PRODUCT RELATED')].index)

#build processing pipeline
pipeline = Pipeline([
    ('vect', CountVectorizer()),
    ('clf', LinearSVC()),])

#define parameters to be used in gridsearch
parameters = {
    #'vect__min_df': (.001,.002,.003,.004,.005),
    'vect__analyzer': ('word',),
    'vect__stop_words': ('english', None),
    'vect__strip_accents': ('unicode',),
    #'clf__C': (1,10,100,1000),
}

if __name__ == '__main__':

    grid_search = GridSearchCV(pipeline,parameters,scoring='f1_macro',n_jobs=1)

    grid_search.fit(data['comment'],data['tag'])

    print("Best score: %0.3f" % grid_search.best_score_)
    print("Best parameters set:")
    best_params = grid_search.best_estimator_.get_params()
    for param_name in sorted(parameters.keys()):
        print("\t%s: %r" % (param_name, best_params[param_name]))

返回的 f1_score更接近0.73 ,所有模型参数都相同。我的理解是网格搜索在内部应用了一种交叉val方法,但我的猜测是,与使用原始代码中的test_train_split相比,它所使用的方法不同。然而从0.83下降 - > 0.73对我来说很大,我希望对自己的成绩充满信心。

非常感谢任何见解。

1 个答案:

答案 0 :(得分:0)

在您提供的代码中,您没有设置random_state模型的LinearSVC参数,因此即使使用相同的超参数,您也不可能重现您的最佳估算值的完全重复GridSearchCV。然而,这比实际情况更为微不足道。

GridSearch正在使用3倍数据进行交叉验证。您看到的best_score是模型得分,在您的测试数据得分时,您在所有折叠中的平均得分最高,而且可能不是您的火车/测试分数得分最高的估算员。有可能给出GridSearch提供的分割,不同的估算器得分会更高,但是如果要生成少量不同的分割并在每个测试集上对估算器进行评分,那么best_estimator平均会来在顶部。我们的想法是,通过交叉验证,您将选择一个估算器,该估算器对数据中的更改更具弹性,这些更改不一定表示在单个列车/测试拆分中。因此,您采用的分割越多,模型对新的未见数据执行的效果就越好。在这种情况下,更好并不意味着它每次都会产生更准确的结果,但考虑到现有数据中存在的变化,模型将更好地包含这些变化,并且从长远来看平均产生更准确的结果。只要新的看不见的数据落在培训数据中。

如果您想了解有关估算工具如何在拆分中执行的更多信息,请查看grid_search.cv_results_,以便更好地了解整个流程中发生的情况。