优化超参数子集以实现方针。

Intuition

优化是在试验中微调超参数以优化特定方针的进程。它可能是一个涉及核算的进程,详细取决于参数的数量、查找空间和模型架构。超参数不仅包含模型的参数,还包含来自预处理、切割等的参数(挑选)。当检查一切可以调整的不同参数时,它很快就变成了一个非常大的查找空间。然而,只是由于某些东西是超参数并不意味着需求调整它。

  • lower=True修正一些超参数(例如在预处理期间)并将它们从调整子集中删去是绝对可以的。请必须留意您正在修正哪些参数以及您这样做的理由。
  • 您开始可以只调整一小部分但有影响力的超参数子集,您认为这些子聚会产生最佳成果。

期望优化超参数,以便能够了解它们中的每一个如何影响方针。经过在合理的查找空间中进行多次试验,可以确定不同参数的接近理想值。这也是确定较小参数是否产生与较大参数(效率)相似的功能的好机会。

超参数调整有很多选项(Optuna、Ray tune、Hyperopt等)。将运用 Optuna 是由于它的简单性、流行性和效率,虽然它们都相同如此。这实际上归结为了解程度以及库是否具有易于测验和可用的特定实现。

应用

履行超参数优化时需求考虑许多要素,幸运的是 Optuna 答应轻松实现它们。将进行一项小型研讨,其中将调整一组参数(当将代码移动到 Python 脚本时,将对参数空间进行更完全的研讨)。以下是研讨的进程:

  1. 定义方针(指标)并确定优化方向。
  2. [OPTIONAL]挑选一个采样器来确定后续试验的参数。(默认是根据树的采样器)。
  3. [OPTIONAL]挑选一个修枝剪提早完毕没有期望的试验。
  4. 定义要在每个试验中调整的参数以及要采样的值的分布。
pip install optuna==2.10.0 numpyencoder==0.3.0 -q

将运用与以前相同的训练函数,由于现已添加了在trial参数不是时修剪特定运转的功能None

# Pruning (inside train() function)
trial.report(val_loss, epoch)
if trial.should_prune():
    raise optuna.TrialPruned()

客观的

需求定义一个方针函数,该函数将运用试验和一组参数并生成要优化的指标(f1在比如中)。

def objective(args, trial):
    """Objective function for optimization trials."""
    # Parameters to tune
    args.analyzer = trial.suggest_categorical("analyzer", ["word", "char", "char_wb"])
    args.ngram_max_range = trial.suggest_int("ngram_max_range", 3, 10)
    args.learning_rate = trial.suggest_loguniform("learning_rate", 1e-2, 1e0)
    args.power_t = trial.suggest_uniform("power_t", 0.1, 0.5)
    # Train & evaluate
    artifacts = train(args=args, df=df, trial=trial)
    # Set additional attributes
    performance = artifacts["performance"]
    print(json.dumps(performance, indent=2))
    trial.set_user_attr("precision", performance["precision"])
    trial.set_user_attr("recall", performance["recall"])
    trial.set_user_attr("f1", performance["f1"])
    return performance["f1"]

学习

已准备好运用MLFlowCallback开始研讨,这样就可以跟踪一切不同的试验。

from numpyencoder import NumpyEncoder
from optuna.integration.mlflow import MLflowCallback
NUM_TRIALS = 20  # small sample for now
# Optimize
pruner = optuna.pruners.MedianPruner(n_startup_trials=5, n_warmup_steps=5)
study = optuna.create_study(study_name="optimization", direction="maximize", pruner=pruner)
mlflow_callback = MLflowCallback(
    tracking_uri=mlflow.get_tracking_uri(), metric_name="f1")
study.optimize(lambda trial: objective(args, trial),
            n_trials=NUM_TRIALS,
            callbacks=[mlflow_callback])

A new study created in memory with name: optimization Epoch: 00 | train_loss: 1.34116, val_loss: 1.35091 … Epoch: 90 | train_loss: 0.32167, val_loss: 0.57661 Stopping early! Trial 0 finished with value: 0.7703281822265505 and parameters: {‘analyzer’: ‘char’, ‘ngram_max_range’: 10, ‘learning_rate’: 0.025679294001785473, ‘power_t’: 0.15046698128066294}. Best is trial 0 with value: 0.7703281822265505. … Trial 10 pruned. … Epoch: 80 | train_loss: 0.16680, val_loss: 0.43964 Epoch: 90 | train_loss: 0.16134, val_loss: 0.43686 Trial 19 finished with value: 0.8470890576153735 and parameters: {‘analyzer’: ‘char_wb’, ‘ngram_max_range’: 4, ‘learning_rate’: 0.08452049154544644, ‘power_t’: 0.39657115651885855}. Best is trial 3 with value: 0.8470890576153735.

# Run MLFlow server and localtunnel
get_ipython().system_raw("mlflow server -h 0.0.0.0 -p 8000 --backend-store-uri $PWD/experiments/ &")
!npx localtunnel --port 8000
# Run MLFlow server and localtunnel
get_ipython().system_raw("mlflow server -h 0.0.0.0 -p 8000 --backend-store-uri $PWD/experiments/ &")
!npx localtunnel --port 8000

1. 点击 Experiments 下左边的“优化”试验。2. 经过单击每个运转左边的切换框或单击标题中的切换框来挑选该试验中的一切运转来挑选要比较的运转。3. 单击比较按钮。

优化超参数

  1. 在对比页面中,可以经过各种镜头(概括、平行坐标等)检查成果

优化超参数

优化超参数

# All trials
trials_df = study.trials_dataframe()
trials_df = trials_df.sort_values(["user_attrs_f1"], ascending=False)  # sort by metric
trials_df.head()
# Best trial
print (f"Best value (f1): {study.best_trial.value}")
print (f"Best hyperparameters: {json.dumps(study.best_trial.params, indent=2)}")

Best value (f1): 0.8535985582060417 Best hyperparameters: { “analyzer”: “char_wb”, “ngram_max_range”: 4, “learning_rate”: 0.08981103667371809, “power_t”: 0.2583427488720579 }

# Save best parameter values
args = {**args.__dict__, **study.best_trial.params}
print (json.dumps(args, indent=2, cls=NumpyEncoder))

{ “lower”: true, “stem”: false, “analyzer”: “char_wb”, “ngram_max_range”: 4, “alpha”: 0.0001, “learning_rate”: 0.08833689034118489, “power_t”: 0.1181958972675695 }

…现在终于准备好从运用 Jupyter note本转向 Python 脚本了。将从头审视迄今为止所做的一切,但这次运用恰当的软件工程原则,例如面向对象编程 (OOP)、款式、测验等。


本文主体源自以下链接:

@article{madewithml,
    author       = {Goku Mohandas},
    title        = { Made With ML },
    howpublished = {\url{https://madewithml.com/}},
    year         = {2022}
}

本文由mdnice多渠道发布