You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SGDClassifier超参数调优后准确率下降、训练时长增加,求问题原因

问题:超参数调优后模型准确率下降且训练时长增加的原因

我的数据集包含训练集、验证集和测试集三类。我先在训练集上运行以下代码训练结合BOW的SGDClassifier模型,随后在验证集上评估:

#model for SVM with BOW
sgd_1 = Pipeline([('vect', CountVectorizer()),
                ('clf', SGDClassifier()),
               ])

#time to train the model
stsgd_1 = time.time()

sgd_1.fit(x_train, y_train)

print("time to train the model", (time.time() - stsgd_1))

ypred_sgd1 = sgd_1.predict(x_val)

print('accuracy %s' % accuracy_score(ypred_sgd1, y_val))
print(classification_report(y_val, ypred_sgd1,target_names=my_tags))

cf_matrix_sgd = confusion_matrix(y_val, ypred_sgd1)
print_confusion_matrix(cf_matrix_sgd, my_tags)

该模型在验证集上达到了90.15%的准确率。之后我使用以下代码进行超参数调优:

#tuning both BOW and sgd resulted in lowering the accuracy
param_sgd1 = {
    "vect__max_df": (0.5, 0.75, 1.0),
    'vect__max_features': (None, 5000, 10000, 50000),
    "vect__ngram_range": ((1, 1), (1, 2)),  # unigrams or bigrams
    "clf__alpha": (0.00001, 0.000001),
    "clf__penalty": ("l2", "elasticnet"),
    'clf__max_iter': (10, 50, 80),
}

gs_sgd1 = GridSearchCV(sgd_1, param_sgd1, n_jobs=-1, verbose=1)

print("performing grid search on SVM")
print("pipeline:", [name for name, _ in sgd_1.steps])
print("parameters:")
pprint(param_sgd1)
#t0 = time()
gs_sgd1.fit(x_val, y_val)
#print("done in %0.3fs" % (time() - t0))
print()

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

调优得到了最优参数后,我构建了以下带有调优后超参数的模型:

#Refit the model for SVM with tuned hyperparameters
sgd_final1 = Pipeline([('vect', CountVectorizer(max_df=1.0, max_features=5000, ngram_range=(1,1))),
                ('clf', SGDClassifier(alpha=1e-05, max_iter=80, penalty="elasticnet")),
               ])

我将该模型在同一验证集上拟合以对比之前的结果,但这次准确率下降,且训练时长有所增加。请问我哪里操作出错了?


核心错误分析

  • 超参数调优的数据集误用
    你调用gs_sgd1.fit(x_val, y_val)时,直接把验证集当作网格搜索的训练数据,这会导致严重的数据泄露:网格搜索会反复用验证集的数据训练和评估模型,最终选出的参数是专门适配验证集的,完全不具备泛化能力。当你用这些参数重新训练模型时,自然无法达到初始模型的泛化表现。
    正确做法是用训练集做网格搜索,通过交叉验证(GridSearchCV默认的cv=5)在训练集内部拆分数据来寻找最优参数,绝对不能动用外部验证集。

  • 最终模型的训练逻辑错误
    你应该把sgd_final1在训练集上拟合(sgd_final1.fit(x_train, y_train)),再用验证集评估,而不是直接在验证集上训练。直接在验证集上训练模型,相当于让模型“记住”了验证集的所有样本,完全失去了验证集用来评估泛化能力的意义,也和初始模型的训练逻辑完全不一致,根本无法做有效对比。

训练时长增加的原因

你最终模型使用了penalty="elasticnet"(弹性网惩罚),它的计算开销比SGDClassifier默认的l2惩罚更大;另外虽然max_iter=80比默认值小,但弹性网需要同时处理L1和L2正则项,整体训练耗时会有所上升。

修正后的操作流程

  1. 超参数调优阶段:将网格搜索的训练数据改为训练集
    gs_sgd1.fit(x_train, y_train)
    
  2. 最终模型训练:用最优参数构建模型后,在训练集上拟合,再用验证集评估
    sgd_final1.fit(x_train, y_train)
    ypred_sgd_final = sgd_final1.predict(x_val)
    print('accuracy %s' % accuracy_score(ypred_sgd_final, y_val))
    

内容的提问来源于stack exchange,提问作者user13178113

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:31:05