Optuna调参时如何将实例化模型转为可调用对象?
问题解决:TypeError: 'CatBoostClassifier' object is not callable
问题根源
变量名冲突导致逻辑错误:你用同一个model变量既存储模型类(如CatBoostClassifier),又存储实例化后的模型对象。当执行model = model(**trial.params)时,model已经被覆盖为实例对象,而实例不可调用,因此触发报错。
修复方案
重命名类变量,避免和实例变量混淆,同时优化字典遍历方式,修正study_name的取值:
修改后完整代码
from optuna.samplers import TPESampler # 导入你的分类器类 from catboost import CatBoostClassifier from sklearn.tree import DecisionTreeClassifier # 模型字典 models = { "CatBoostClassifier": CatBoostClassifier, "DecisionTreeClassifier": DecisionTreeClassifier, # 补充剩余3个分类器 } # 遍历模型字典,用不同变量区分类和实例 for model_name, model_cls in models.items(): # 初始化Optuna研究 sampler = TPESampler(seed=1) # study_name传入模型名称字符串,而非类对象 study = optuna.create_study(study_name=model_name, direction="maximize", sampler=sampler) # 通过lambda向objective传递当前模型类 study.optimize(lambda trial: objective(trial, model_cls, X_train, y_train, X_val, y_val), n_trials=100) # 获取最优参数并实例化模型 best_trial = study.best_trial model = model_cls(**best_trial.params, verbose=False) model.fit(X_train, y_train) # 可选:模型评估 # y_pred = model.predict(X_val) # print(f"{model_name} 验证集准确率: {accuracy_score(y_val, y_pred)}")
对应的objective函数示例
from sklearn.metrics import accuracy_score def objective(trial, model_cls, X_train, y_train, X_val, y_val): # 根据模型类定义对应的参数搜索空间 if model_cls == CatBoostClassifier: params = { "learning_rate": trial.suggest_float("learning_rate", 0.01, 0.3), "depth": trial.suggest_int("depth", 3, 10), # 其他CatBoost参数... } elif model_cls == DecisionTreeClassifier: params = { "max_depth": trial.suggest_int("max_depth", 2, 15), "min_samples_split": trial.suggest_int("min_samples_split", 2, 20), # 其他决策树参数... } # 补充其他模型的参数空间 # 实例化模型并训练 model = model_cls(**params) model.fit(X_train, y_train) # 返回评估指标(最大化方向) return accuracy_score(y_val, model.predict(X_val))
关键修改点
- 用
model_cls存储模型类,model存储实例化后的对象,变量职责清晰,避免冲突。 - 改用
models.items()遍历字典,直接获取模型名称和对应类,比下标遍历更简洁易读。 study_name传入字符串类型的模型名称,符合Optuna的参数要求(之前传入类对象会导致内部处理错误)。- 通过lambda向
objective函数传递当前模型类,确保调参逻辑针对对应模型生效。
内容的提问来源于stack exchange,提问作者ludo
相关产品推荐
相关产品推荐

