• 【MLOps】优化超参数


    直觉

    优化是在我们的实验中微调超参数以优化特定目标的过程。它可能是一个涉及计算的过程,具体取决于参数的数量、搜索空间和模型架构。超参数不仅包括模型的参数,还包括来自预处理、分割等的参数(选择)。当我们查看所有可以调整的不同参数时,它很快就变成了一个非常大的搜索空间。然而,仅仅因为某些东西是超参数并不意味着我们需要调整它。

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

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

    工具

    超参数调整有很多选项(OptunaRay tuneHyperopt等)。我们将使用 Optuna 是因为它的简单性、流行性和效率,尽管它们都同样如此。这实际上归结为熟悉程度以及库是否具有易于测试和可用的特定实现。

    应用

    执行超参数优化时需要考虑许多因素,幸运的是 Optuna 允许我们轻松实现它们。我们将进行一项小型研究,其中我们将调整一组参数(当我们将代码移动到 Python 脚本时,我们将对参数空间进行更彻底的研究)。以下是研究的过程:

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

    我们将使用与以前相同的训练函数,因为我们已经添加了在trial参数不是时修剪特定运行的功能None

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

    客观的

    我们需要定义一个目标函数,该函数将使用试验和一组参数并生成要优化的指标(f1在我们的例子中)。

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

    学习

    我们已准备好使用MLFlowCallback开始我们的研究,这样我们就可以跟踪所有不同的试验。

    1. from numpyencoder import NumpyEncoder
    2. from optuna.integration.mlflow import MLflowCallback
    NUM_TRIALS = 20  # small sample for now
    
    1. # Optimize
    2. pruner = optuna.pruners.MedianPruner(n_startup_trials=5, n_warmup_steps=5)
    3. study = optuna.create_study(study_name="optimization", direction="maximize", pruner=pruner)
    4. mlflow_callback = MLflowCallback(
    5. tracking_uri=mlflow.get_tracking_uri(), metric_name="f1")
    6. study.optimize(lambda trial: objective(args, trial),
    7. n_trials=NUM_TRIALS,
    8. callbacks=[mlflow_callback])
    1. A new study created in memory with name: optimization
    2. Epoch: 00 | train_loss: 1.34116, val_loss: 1.35091
    3. ...
    4. Epoch: 90 | train_loss: 0.32167, val_loss: 0.57661
    5. Stopping early!
    6. 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.
    7. ...
    8. Trial 10 pruned.
    9. ...
    10. Epoch: 80 | train_loss: 0.16680, val_loss: 0.43964
    11. Epoch: 90 | train_loss: 0.16134, val_loss: 0.43686
    12. 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.
    1. # Run MLFlow server and localtunnel
    2. get_ipython().system_raw("mlflow server -h 0.0.0.0 -p 8000 --backend-store-uri $PWD/experiments/ &")
    3. !npx localtunnel --port 8000

    1. 点击 Experiments 下左侧的“优化”实验。2. 通过单击每个运行左侧的切换框或单击标题中的切换框来选择该实验中的所有运行来选择要比较的运行。3. 单击比较按钮。

    1. 在对比页面中,我们可以通过各种镜头(轮廓、平行坐标等)查看结果

    1. # All trials
    2. trials_df = study.trials_dataframe()
    3. trials_df = trials_df.sort_values(["user_attrs_f1"], ascending=False) # sort by metric
    4. trials_df.head()
    数字价值日期时间开始日期时间完成期间params_analyzerparams_learning_rateparams_ngram_max_rangeparams_power_tuser_attrs_f1user_attrs_precisionuser_attrs_recall状态
    330.8470892022-05-18 18:16:58.1081052022-05-18 18:17:03.5699480 天 00:00:05.461843char_wb0.08833740.1181960.8470890.8875540.833333完全的
    19190.8470892022-05-18 18:17:58.2194622022-05-18 18:18:00.6425710 天 00:00:02.423109char_wb0.08452040.3965710.8470890.8875540.833333完全的
    12120.8404912022-05-18 18:17:41.8451792022-05-18 18:17:45.7920680 天 00:00:03.946889char_wb0.13957870.1072730.8404910.8774310.826389完全的
    13130.8404912022-05-18 18:17:45.8627052022-05-18 18:17:49.6570140 天 00:00:03.794309char_wb0.15439670.4336690.8404910.8774310.826389完全的
    15150.8362552022-05-18 18:17:50.4649482022-05-18 18:17:54.4464810 天 00:00:03.981533char_wb0.08325370.1069820.8362550.8811500.819444完全的
    1. # Best trial
    2. print (f"Best value (f1): {study.best_trial.value}")
    3. print (f"Best hyperparameters: {json.dumps(study.best_trial.params, indent=2)}")
    1. Best value (f1): 0.8535985582060417
    2. Best hyperparameters: {
    3. "analyzer": "char_wb",
    4. "ngram_max_range": 4,
    5. "learning_rate": 0.08981103667371809,
    6. "power_t": 0.2583427488720579
    7. }
    1. # Save best parameter values
    2. args = {**args.__dict__, **study.best_trial.params}
    3. print (json.dumps(args, indent=2, cls=NumpyEncoder))
    1. {
    2. "lower": true,
    3. "stem": false,
    4. "analyzer": "char_wb",
    5. "ngram_max_range": 4,
    6. "alpha": 0.0001,
    7. "learning_rate": 0.08833689034118489,
    8. "power_t": 0.1181958972675695
    9. }
  • 相关阅读:
    【位置推iMessage苹果推】软件安装在GNU通用公共许可证或GNU Lesser GPL /库
    siRNA-S-S-PEG-LMWP|M-MSN-siRNA介孔二氧化硅修饰RNA(齐岳RNA功能化修饰)
    嵌入式软件工程师面试题——2025校招专题(三)
    在非金融应用中在哪里使用区块链?
    你和工博会观展达人也许只差一篇攻略
    【Linux】进程信号----(一篇带你熟知进程信号)
    如何10分钟搭建效果领先的语义搜索系统?
    JavaScript学习--Day05
    使用android studio将h5项目打包成安卓app
    layui table表格使用table.resize()方法 重置表格尺寸
  • 原文地址:https://blog.csdn.net/sikh_0529/article/details/126902375