我正在使用Optuna来优化一些目标函数。我想创建“包装”标准Optuna代码的自定义类。
例如,这是我的类(它仍在进行中!):
class Optimizer(object):
def __init__(self, param_dict, model, train_x, valid_x, train_y, valid_y):
self.model = model
self.param_dict = param_dict
self.train_x, self.valid_x, self.train_y, self.valid_y = train_x, valid_x, train_y, valid_y
def optimization_function(self, trial):
self.dtrain = lgb.Dataset(self.train_x, label=self.train_y)
gbm = lgb.train(param, dtrain)
preds = gbm.predict(self.valid_x)
pred_labels = np.rint(preds)
accuracy = sklearn.metrics.accuracy_score(self.valid_y, pred_labels)
return accuracy
def optimize(self, direction, n_trials):
study = optuna.create_study(direction = direction)
study.optimize(self.optimization_function, n_trials = n_trials)
return study.best_trial我试图将optuna优化的所有“逻辑”都包装在这个类中,而不是每次都像下面这样(来自文档)编写一些代码:
import optuna
class Objective(object):
def __init__(self, min_x, max_x):
# Hold this implementation specific arguments as the fields of the class.
self.min_x = min_x
self.max_x = max_x
def __call__(self, trial):
# Calculate an objective value by using the extra arguments.
x = trial.suggest_float("x", self.min_x, self.max_x)
return (x - 2) ** 2
# Execute an optimization by using an `Objective` instance.
study = optuna.create_study()
study.optimize(Objective(-100, 100), n_trials=100)我想让我的代码“模块化”,并将所有东西合并到一个类中。我的最终目标是根据__init__函数中给定的输入模型,设置不同的优化函数“模板”。
因此,回到主要问题,我想从外部传递param字典。基本上,我希望能够从类的外部声明它,并在__init__函数中传递我的字典。
但是,Optuna代码中常用的范围和分布依赖于trial对象,因此我无法执行以下操作:
my_dict = {
'objective': 'binary',
'metric': 'binary_logloss',
'verbosity': -1,
'boosting_type': 'gbdt',
# HERE I HAVE A DEPENDENCY FROM trial.suggest_loguniform, I can't declare the dictionary outside the objective function
'lambda_l1': trial.suggest_loguniform('lambda_l1', 1e-8, 10.0),
'lambda_l2': trial.suggest_loguniform('lambda_l2', 1e-8, 10.0),
'num_leaves': trial.suggest_int('num_leaves', 2, 256),
'feature_fraction': trial.suggest_uniform('feature_fraction', 0.4, 1.0),
'bagging_fraction': trial.suggest_uniform('bagging_fraction', 0.4, 1.0),
'bagging_freq': trial.suggest_int('bagging_freq', 1, 7),
'min_child_samples': trial.suggest_int('min_child_samples', 5, 100),
}
my_optimizer = Optimizer(my_dict, ..., ..., ..., ......)
best_result = my_optimizer.optimize('maximize', 100)有没有什么办法或者解决方案可以通过这个字典呢?
发布于 2021-10-23 10:48:37
这样如何,创建一个要传递给类的详细字典,然后为试用建议类型重新构建它。
代码
class Optimizer(object):
def __init__(self, param_dict):
self.param_dic = param_dict
self.objective = self.param_dic.get('objective', None)
self.metric = self.param_dic.get('metric', None)
def optimization_function(self, trial):
suggested_param = {} # param storage
# int
int_param = self.param_dic['param'].get('int', None)
if int_param is not None:
for k, v in int_param.items():
suggested = trial.suggest_int(k, v['low'], v['high'])
suggested_param.update({k: suggested})
# log
loguniform_param = self.param_dic['param'].get('loguniform', None)
if loguniform_param is not None:
for k, v in loguniform_param.items():
suggested = trial.suggest_loguniform(k, v['low'], v['high'])
suggested_param.update({k: suggested})
a = suggested_param.get('a', None)
b = suggested_param.get('b', None)
c = suggested_param.get('c', None)
return a + b + 1.5*c
def optimize(self, direction, n_trials):
study = optuna.create_study(direction = direction)
study.optimize(self.optimization_function, n_trials = n_trials)
return study.best_trial
my_dict = {
'objective': 'binary',
'metric': 'binary_logloss',
'param': {
'int': {
'a': {
'low': 0,
'high': 20
},
'b': {
'low': 0,
'high': 10
}
},
'loguniform': {
'c': {
'low': 1e-8,
'high': 10.0
}
}
}
}
my_optimizer = Optimizer(my_dict)
best_result = my_optimizer.optimize('maximize', 100)
print(f'best param: {best_result.params}')
print(f'best value: {best_result.values}')https://stackoverflow.com/questions/67504503
复制相似问题