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

解决为GaussianProcessRegressor调参多优化器时的getattr类型错误

问题:GPR自定义优化器结合RandomizedSearchCV时触发TypeError

我基于GaussianProcessRegressor实现了自定义优化器,用于时间序列目标预测,同时用RandomizedSearchCV进行超参数寻优,运行时出现TypeError: getattr(): attribute name must be string错误,相关代码及报错信息如下:

关键代码片段(HelperFunctions.py)

模型与搜索参数定义

def intermediate_models(kernel):
    dtr_dic = dict(
        ccp_alpha=uniform(loc=0.0, scale=10.0),
        max_features=randint(low=1, high=100),
        max_depth=randint(low=1, high=100),
        criterion=["squared_error", "friedman_mse", "absolute_error", "poisson"],
    )
    optimizer_names = [
        "minimize_wrapper",
        "least_squares_wrapper",
        "differential_evolution_wrapper",
        "basinhopping_wrapper",
        "dual_annealing_wrapper",
    ]
    model_dist_pairs = []
    for optimizer_name in optimizer_names:
        gpr = GPRWithCustomOptimizer(kernel=kernel, optimizer=optimizer_name)

        gpr_dic = dict(
            optimizer=optimizer_names,  # 错误根源
            n_restarts_optimizer=np.arange(0, 20 + 1),
            normalize_y=[False, True],
            copy_X_train=[True, False],
            random_state=np.arange(0, 10 + 1),
        )
        model_dist_pairs.append((gpr, gpr_dic))
    return [(DecisionTreeRegressor(), dtr_dic)] + model_dist_pairs

自定义GPR类

class GPRWithCustomOptimizer(GaussianProcessRegressor):
    def __init__(
        self,
        optimizer="minimize",
        initial_theta=None,
        bounds=None,
        random_state=None,
        normalize_y=True,
        n_restarts_optimizer=0,
        copy_X_train=True,
        **kwargs,
    ):
        self.initial_theta = initial_theta
        self.bounds = bounds
        self.custom_optimizers = CustomOptimizers(self, self.initial_theta, self.bounds)
        self.optimizer_func = getattr(self.custom_optimizers, optimizer)  # 触发错误的位置
        super().__init__(
            optimizer=self.optimizer_func,
            random_state=random_state,
            normalize_y=normalize_y,
            n_restarts_optimizer=n_restarts_optimizer,
            copy_X_train=copy_X_train,
            **kwargs,
        )

核心错误信息

TypeError: getattr(): attribute name must be string

错误原因分析
  1. 参数类型不匹配:在intermediate_models函数中,gpr_dic的optimizer字段被赋值为整个列表optimizer_names,而非单个字符串。当RandomizedSearchCV克隆GPR实例时,会将这个列表传入GPRWithCustomOptimizer的构造函数,而getattr要求第二个参数必须是字符串,因此抛出TypeError。
  2. 逻辑冗余:循环遍历每个优化器名称创建GPR实例,却给每个实例的搜索参数设置为遍历所有优化器,导致重复搜索,完全没必要。
  3. 默认值不匹配:GPRWithCustomOptimizer的默认optimizer值是"minimize",但自定义优化器类中对应的方法名是minimize_wrapper,默认初始化也会报错。

修复方案

1. 修正搜索参数的optimizer字段

将gpr_dic中的optimizer=optimizer_names改为optimizer=[optimizer_name],确保每个GPR实例仅搜索当前指定的优化器,同时符合RandomizedSearchCV的参数格式要求。

修改后的intermediate_models函数(二选一即可):

方案一:每个优化器单独搜索

def intermediate_models(kernel):
    dtr_dic = dict(
        ccp_alpha=uniform(loc=0.0, scale=10.0),
        max_features=randint(low=1, high=100),
        max_depth=randint(low=1, high=100),
        criterion=["squared_error", "friedman_mse", "absolute_error", "poisson"],
    )
    optimizer_names = [
        "minimize_wrapper",
        "least_squares_wrapper",
        "differential_evolution_wrapper",
        "basinhopping_wrapper",
        "dual_annealing_wrapper",
    ]
    model_dist_pairs = []
    for optimizer_name in optimizer_names:
        gpr = GPRWithCustomOptimizer(kernel=kernel, optimizer=optimizer_name)

        gpr_dic = dict(
            optimizer=[optimizer_name],  # 改为当前优化器名称的单元素列表
            n_restarts_optimizer=np.arange(0, 20 + 1),
            normalize_y=[False, True],
            copy_X_train=[True, False],
            random_state=np.arange(0, 10 + 1),
        )
        model_dist_pairs.append((gpr, gpr_dic))
    return [(DecisionTreeRegressor(), dtr_dic)] + model_dist_pairs

方案二:单实例搜索所有优化器(更高效)

def intermediate_models(kernel):
    dtr_dic = dict(
        ccp_alpha=uniform(loc=0.0, scale=10.0),
        max_features=randint(low=1, high=100),
        max_depth=randint(low=1, high=100),
        criterion=["squared_error", "friedman_mse", "absolute_error", "poisson"],
    )
    optimizer_names = [
        "minimize_wrapper",
        "least_squares_wrapper",
        "differential_evolution_wrapper",
        "basinhopping_wrapper",
        "dual_annealing_wrapper",
    ]
    model_dist_pairs = []
    # 仅创建一个GPR实例,一次性搜索所有优化器
    gpr = GPRWithCustomOptimizer(kernel=kernel)
    gpr_dic = dict(
        optimizer=optimizer_names,
        n_restarts_optimizer=np.arange(0, 20 + 1),
        normalize_y=[False, True],
        copy_X_train=[True, False],
        random_state=np.arange(0, 10 + 1),
    )
    model_dist_pairs.append((gpr, gpr_dic))
    return [(DecisionTreeRegressor(), dtr_dic)] + model_dist_pairs

2. 修复自定义GPR类的默认值与鲁棒性

class GPRWithCustomOptimizer(GaussianProcessRegressor):
    def __init__(
        self,
        optimizer="minimize_wrapper",  # 修正默认值为存在的方法名
        initial_theta=None,
        bounds=None,
        random_state=None,
        normalize_y=True,
        n_restarts_optimizer=0,
        copy_X_train=True,
        **kwargs,
    ):
        self.initial_theta = initial_theta
        self.bounds = bounds
        # 添加参数校验,避免非字符串参数传入
        if not isinstance(optimizer, str):
            raise ValueError(f"optimizer必须是字符串类型,当前传入类型为{type(optimizer)}")
        self.custom_optimizers = CustomOptimizers(self, self.initial_theta, self.bounds)
        self.optimizer_func = getattr(self.custom_optimizers, optimizer)
        super().__init__(
            optimizer=self.optimizer_func,
            random_state=random_state,
            normalize_y=normalize_y,
            n_restarts_optimizer=n_restarts_optimizer,
            copy_X_train=copy_X_train,
            **kwargs,
        )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:54:56