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

使用scikit-learn的HalvingGridSearchCV时min_resources不符合预期

HalvingGridSearchCV(factor=2)迭代行为不符合预期的问题分析

问题场景概述

使用scikit-learn 1.4.0的HalvingGridSearchCV进行超参数调优时,设置factor=2、min_resources="exhaust"(期望最后一轮用全量训练集),针对8组超参数组合,出现以下异常,且仅factor=2时触发,factor=3/4结果正常:

  • 1000样本生成数据:预期3轮迭代n_candidates_=[8,4,2]、n_resources_=[250,500,1000],实际得到4轮n_candidates_=[8,4,2,1]、n_resources_=[125,250,500,1000],首轮资源减半且多一轮迭代
  • 100样本生成数据:迭代轮数符合预期,但最后一轮n_resources_=80未用全量100样本
  • 数据依赖性差异:200样本Fashion-MNIST子集得到2轮n_candidates_=[8,4]、n_resources_=[100,200];200样本生成数据得到4轮n_candidates_=[8,4,2,1]、n_resources_=[25,50,100,200],均不符合预期

核心原因分析

1. 迭代逻辑的边界处理问题

HalvingGridSearchCV的迭代停止与资源量计算受多重约束:

  • 每轮候选数需≥1,且下一轮资源量不能超过总样本
  • 当cv=5时,每轮资源量需满足每个CV折至少有1个样本,源码会自动调整资源量,factor=2时这种调整可能打破预期的资源增长节奏
  • 生成数据的均匀随机性可能导致模型性能差异极小,候选数筛选逻辑触发额外轮次;而结构化数据集(如Fashion-MNIST)性能差异更显著,候选数更早被筛选至<factor,提前停止迭代

2. 对min_resources="exhaust"的理解偏差

该参数仅保证最后一轮使用全量资源,但迭代轮数由资源增长到全量所需的次数、候选数halving次数共同决定,并非严格按照总候选数 / factor^轮数的理想逻辑执行。

调试与验证建议

  1. 查看内部计算逻辑:打印grid._n_required_iterations()和grid._compute_resources()的结果,确认轮数与资源量的计算过程
  2. 调整CV折数:尝试设置cv=3或cv=1(不交叉验证),验证CV拆分是否为影响因素
  3. 升级版本:更新scikit-learn至1.5.x等最新稳定版,确认该问题是否已被官方修复
  4. 强制初始化资源:手动指定initial_resources为预期首轮资源量(如1000样本时设为250),控制迭代起始节奏

临时解决方案

若需严格控制迭代行为:

  • 当factor=2时,手动计算并指定initial_resources和max_resources,确保最后一轮使用全量样本
  • 临时切换至factor=3或factor=4,规避该异常场景

复现代码

import numpy as np
import pandas as pd
from sklearn.datasets import fetch_openml, make_classification
from sklearn.experimental import enable_halving_search_cv 
from sklearn.model_selection import train_test_split, HalvingGridSearchCV
from sklearn.tree import DecisionTreeClassifier

rng = np.random.RandomState(0)
num_samples = 1000  # 可修改为100/200测试不同场景

# 切换数据集:注释下面一行,取消注释Fashion-MNIST代码块
X_train, y_train = make_classification(n_samples=num_samples, n_features=20, random_state=rng)

# # Fashion-MNIST数据集测试
# data_fash = fetch_openml(name="Fashion-MNIST")
# X_train, _, y_train, _ = train_test_split(
#                              data_fash.data, data_fash.target, train_size=num_samples, random_state=rng
#                              )

print("Train samples: ", len(X_train))

param_grid = {"criterion": ["gini", "entropy"],
              "min_samples_split": [2, 3, 4, 5]}

cls = DecisionTreeClassifier()

grid = HalvingGridSearchCV(
           cls, param_grid, factor=2, min_resources="exhaust", scoring="accuracy", cv=5
           )

grid.fit(X_train, y_train)

print("n_candidates_:", grid.n_candidates_)
print("n_resources_:", grid.n_resources_)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:24:55