代码之家  ›  专栏  ›  技术社区  ›  HarriS

Python:如何从opgbm研究中获取最佳模型?

  •  0
  • HarriS  · 技术社区  · 6 年前

    我想得到最好的模型,以便以后在笔记本中使用,以预测使用不同的测试批次。

    可复制示例(摘自Ophub):

    import lightgbm as lgb
    import numpy as np
    import sklearn.datasets
    import sklearn.metrics
    from sklearn.model_selection import train_test_split
    
    import optuna
    
    
    # FYI: Objective functions can take additional arguments
    # (https://optuna.readthedocs.io/en/stable/faq.html#objective-func-additional-args).
    def objective(trial):
        data, target = sklearn.datasets.load_breast_cancer(return_X_y=True)
        train_x, valid_x, train_y, valid_y = train_test_split(data, target, test_size=0.25)
        dtrain = lgb.Dataset(train_x, label=train_y)
        dvalid = lgb.Dataset(valid_x, label=valid_y)
    
        param = {
            "objective": "binary",
            "metric": "auc",
            "verbosity": -1,
            "boosting_type": "gbdt",
            "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),
        }
    
        # Add a callback for pruning.
        pruning_callback = optuna.integration.LightGBMPruningCallback(trial, "auc")
        gbm = lgb.train(
            param, dtrain, valid_sets=[dvalid], verbose_eval=False, callbacks=[pruning_callback]
        )
    
        preds = gbm.predict(valid_x)
        pred_labels = np.rint(preds)
        accuracy = sklearn.metrics.accuracy_score(valid_y, pred_labels)
        return accuracy
    
    

    我的理解是,下面的研究将调整的准确性。我想以某种方式从研究中检索到最好的模型(不仅仅是参数),而不将其保存为pickle,我只想在笔记本的其他地方使用该模型。

    
    if __name__ == "__main__":
        study = optuna.create_study(
            pruner=optuna.pruners.MedianPruner(n_warmup_steps=10), direction="maximize"
        )
        study.optimize(objective, n_trials=100)
    
        print("Best trial:")
        trial = study.best_trial
    
        print("  Params: ")
        for key, value in trial.params.items():
            print("    {}: {}".format(key, value))
    
    

    期望的输出是

    best_model = ~model from above~
    new_target_pred = best_model.predict(new_data_test)
    metrics.accuracy_score(new_target_test, new__target_pred)
    
    
    0 回复  |  直到 6 年前
        1
  •  2
  •   Toshihiko Yanase    6 年前

    我想你可以用 callback 的论点 Study.optimize 保存最佳模型。在下面的代码示例中,回调将检查给定的试用是否对应于最佳试用,并将模型保存为全局变量 best_booster .

    best_booster = None
    gbm = None
    
    def objective(trial):
        global gbm
        # ...
    
    def callback(study, trial):
        global best_booster
        if study.best_trial == trial:
            best_booster = gbm
    
    if __name__ == "__main__":
        study = optuna.create_study(
            pruner=optuna.pruners.MedianPruner(n_warmup_steps=10), direction="maximize"
        )
        study.optimize(objective, n_trials=100, callbacks=[callback])
    
    

    如果将目标函数定义为类,则可以删除全局变量。我创建了一个笔记本作为代码示例。请看一下: https://colab.research.google.com/drive/1ssjXp74bJ8bCAbvXFOC4EIycBto_ONp_?usp=sharing

    我想以某种方式从研究中检索最佳模型(不仅仅是参数),而不将其保存为pickle

    仅供参考,如果你能对助推器进行pickle处理,我认为你可以通过以下方法简化代码 this FAQ .

        2
  •  2
  •   avinashpancham    6 年前

    简短的补充@Toshihiko Yanase的回答,因为条件 study.best_trial==trial 对我来说从来都不是真的。甚至在两个(冻结的)试验对象具有相同内容的情况下也是这样,因此这很可能是Optuna中的一个bug。将条件更改为 study.best_trial.number==trial.number 帮我解决问题。

    另外,如果您不希望在Python中使用globals,那么可以使用study和trial用户属性

    def objective(trial):
        gmb = ...
        trial.set_user_attr(key="best_booster", value=gbm)
    
    def callback(study, trial):
        if study.best_trial.number == trial.number:
            study.set_user_attr(key="best_booster", value=trial.user_attrs["best_booster"])
    
    
    if __name__ == "__main__":
        study = optuna.create_study(
            pruner=optuna.pruners.MedianPruner(n_warmup_steps=10), direction="maximize"
        )
        study.optimize(objective, n_trials=100, callbacks=[callback])
        best_model=study.user_attrs["best_booster"]
    
    推荐文章