Sklearn网格搜索F1_SCORE与F1_SCORE函数不匹配



我一直在尝试Sklearn Grid搜索和管道功能,并注意到返回的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 ,所有模型参数相同。我的理解是,网格搜索在内部采用了跨数字方法,但我的猜测是,与使用Test_train_split相比,它使用的任何方法都来自原始代码中的test_train_split。但是,从0.83-> 0.73下降对我来说很大,我想对自己的结果充满信心。

任何见解都将不胜感激。

在您提供的代码中,您没有设置LinearSVC模型的random_state参数,因此即使使用相同的超参数,您也不太可能从您的最佳估计器重现最佳估计器GridSearchCV。但是,这比实际发生的要小。

在您的情况下,正在使用数据的3倍进行交叉验证。您看到的Bestrongcore是在测试数据上评分时平均在所有折叠中表现最佳的模型的分数,并且可能不是估计器在火车/测试拆分上得分最佳。如果您提供了GridSearch的分裂,则可能会得分更高,但是如果您要产生少数不同的分配并在每个测试集中评分估算器,则平均best_estimator将在最高。这个想法是,通过交叉验证,您将选择一个更具弹性的估算器,该估计值对数据的变化更具弹性,而不一定在单个火车/测试拆分中表示。因此,您采取的分裂越多,模型就会在新的看不见的数据上执行越好。在这种情况下,更好的可能并不意味着它每次都会产生更准确的结果,但是鉴于现有数据中存在的变化,模型将在涵盖这些变化的情况下做得更好,并且在长期以来平均产生了更准确的结果只要新的看不见的数据就属于培训数据中所看到的。

如果您想查看有关估计器在拆分内执行的更多信息,请查看grid_search.cv_results_,以更好地了解该过程的逐步了解。

最新更新