实验跟踪

news2025/7/14 5:32:37

管理和跟踪机器学习实验。

Intuition

到目前为止,一直在训练和评估不同的基线,但还没有真正跟踪这些实验。将解决这个问题,但定义一个适当的实验跟踪过程,将用于所有未来的实验(包括超参数优化)。实验跟踪是管理所有不同实验及其组件(例如参数、指标、模型和其他工件)的过程,它使能够:

  • 组织特定实验的所有必要组件。重要的是把所有东西都放在一个地方并且知道它在哪里,这样你以后可以使用它们。
  • 使用保存的实验(轻松) 重现过去的结果。
  • 记录跨时间、数据、想法、团队等的迭代改进。

实验跟踪有很多选项,但将使用MLFlow(100% 免费和开源),因为它具有需要的所有功能(以及不断增长的集成支持)。可以在自己的服务器和数据库上运行 MLFlow,因此没有存储成本/限制,使其成为最受欢迎的选项之一,并被 Microsoft、Facebook、Databricks 和其他公司使用。您还可以设置自己的跟踪服务器,以在多个团队成员之间同步运行同一任务。

还有几个流行的选项,例如Comet ML(被 Google AI、HuggingFace 等使用)、Neptune(被 Roche、NewYorker 等使用)、Weights and Biases (被 Open AI、Toyota Research 等使用) . 这些都是很棒的工具,提供仪表板、无缝集成、超参数搜索、报告甚至调试等功能!

许多平台正在利用其作为实验数据源的地位来提供扩展到 ML 开发管道其他部分的功能,例如版本控制、调试、监控等。

应用

将从初始化实验所需的所有参数开始。

pip install mlflow==1.23.1 -q
from argparse import Namespace
import mlflow
from pathlib import Path

输入参数args包含所有需要的参数,很高兴将它们全部组织在一个变量下,这样就可以轻松地记录它并为不同的实验调整它(会在进行超参数优化时看到这一点)。

# Specify arguments
args = Namespace(
    lower=True,
    stem=False,
    analyzer="char",
    ngram_max_range=7,
    alpha=1e-4,
    learning_rate=1e-1,
    power_t=0.1,
    num_epochs=100
)

接下来,将设置模型注册表,其中将存储所有实验及其各自的运行。还将使用特定的运行 ID 从此注册表中加载经过训练的模型。

# Set tracking URI
MODEL_REGISTRY = Path("experiments")
Path(MODEL_REGISTRY).mkdir(exist_ok=True) # create experiments dir
mlflow.set_tracking_uri("file://" + str(MODEL_REGISTRY.absolute()))

Tip

在 Windows 上,设置跟踪 URI 的最后一行应该有三个正斜杠:

mlflow.set_tracking_uri("file:///" + str(MODEL_REGISTRY.absolute()))

当与其他团队成员合作时,这个模型注册表将存在于云端。团队的成员可以连接到它(通过身份验证)以保存和加载经过训练的模型。如果您不想设置和维护模型注册表,这就是Comet ML、Weights and Biases和其他平台等平台卸载大量技术设置的地方。

训练

为了简单起见,将所有用于训练的组件封装到一个函数中,该函数返回希望能够从实验中跟踪的所有工件。

现在忽略该trial参数(默认为None),因为它将在超参数优化课程中用于修剪没有希望的试验。

def train(args, df, trial=None):
    """Train model on data."""

    # Setup
    set_seeds()
    df = pd.read_csv("labeled_projects.csv")
    df = df.sample(frac=1).reset_index(drop=True)
    df = preprocess(df, lower=True, stem=False, min_freq=min_freq)
    label_encoder = LabelEncoder().fit(df.tag)
    X_train, X_val, X_test, y_train, y_val, y_test = \
        get_data_splits(X=df.text.to_numpy(), y=label_encoder.encode(df.tag))

    # Tf-idf
    vectorizer = TfidfVectorizer(analyzer=args.analyzer, ngram_range=(2,args.ngram_max_range))  # char n-grams
    X_train = vectorizer.fit_transform(X_train)
    X_val = vectorizer.transform(X_val)
    X_test = vectorizer.transform(X_test)

    # Oversample
    oversample = RandomOverSampler(sampling_strategy="all")
    X_over, y_over = oversample.fit_resample(X_train, y_train)

    # Model
    model = SGDClassifier(
        loss="log", penalty="l2", alpha=args.alpha, max_iter=1,
        learning_rate="constant", eta0=args.learning_rate, power_t=args.power_t,
        warm_start=True)

    # Training
    for epoch in range(args.num_epochs):
        model.fit(X_over, y_over)
        train_loss = log_loss(y_train, model.predict_proba(X_train))
        val_loss = log_loss(y_val, model.predict_proba(X_val))
        if not epoch%10:
            print(
                f"Epoch: {epoch:02d} | "
                f"train_loss: {train_loss:.5f}, "
                f"val_loss: {val_loss:.5f}"
            )

        # Log
        if not trial:
            mlflow.log_metrics({"train_loss": train_loss, "val_loss": val_loss}, step=epoch)

        # Pruning (for optimization in next section)
        if trial:
            trial.report(val_loss, epoch)
            if trial.should_prune():
                raise optuna.TrialPruned()

    # Threshold
    y_pred = model.predict(X_val)
    y_prob = model.predict_proba(X_val)
    args.threshold = np.quantile(
        [y_prob[i][j] for i, j in enumerate(y_pred)], q=0.25)  # Q1

    # Evaluation
    other_index = label_encoder.class_to_index["other"]
    y_prob = model.predict_proba(X_test)
    y_pred = custom_predict(y_prob=y_prob, threshold=args.threshold, index=other_index)
    metrics = precision_recall_fscore_support(y_test, y_pred, average="weighted")
    performance = {"precision": metrics[0], "recall": metrics[1], "f1": metrics[2]}
    print (json.dumps(performance, indent=2))

    return {
        "args": args,
        "label_encoder": label_encoder,
        "vectorizer": vectorizer,
        "model": model,
        "performance": performance
    }

追踪

使用 MLFlow 需要首先初始化一个实验,然后你可以在该实验下运行。

import joblib
import tempfile
# Set experiment
mlflow.set_experiment(experiment_name="baselines")

INFO: 'baselines' does not exist. Creating a new experiment

def save_dict(d, filepath):
    """Save dict to a json file."""
    with open(filepath, "w") as fp:
        json.dump(d, indent=2, sort_keys=False, fp=fp)
# Tracking
with mlflow.start_run(run_name="sgd"):

    # Train & evaluate
    artifacts = train(args=args, df=df)

    # Log key metrics
    mlflow.log_metrics({"precision": artifacts["performance"]["precision"]})
    mlflow.log_metrics({"recall": artifacts["performance"]["recall"]})
    mlflow.log_metrics({"f1": artifacts["performance"]["f1"]})

    # Log artifacts
    with tempfile.TemporaryDirectory() as dp:
        artifacts["label_encoder"].save(Path(dp, "label_encoder.json"))
        joblib.dump(artifacts["vectorizer"], Path(dp, "vectorizer.pkl"))
        joblib.dump(artifacts["model"], Path(dp, "model.pkl"))
        save_dict(artifacts["performance"], Path(dp, "performance.json"))
        mlflow.log_artifacts(dp)

    # Log parameters
    mlflow.log_params(vars(artifacts["args"]))

Epoch: 00 | train_loss: 1.16930, val_loss: 1.21451 Epoch: 10 | train_loss: 0.46116, val_loss: 0.65903 Epoch: 20 | train_loss: 0.31565, val_loss: 0.56018 Epoch: 30 | train_loss: 0.25207, val_loss: 0.51967 Epoch: 40 | train_loss: 0.21740, val_loss: 0.49822 Epoch: 50 | train_loss: 0.19615, val_loss: 0.48529 Epoch: 60 | train_loss: 0.18249, val_loss: 0.47708 Epoch: 70 | train_loss: 0.17330, val_loss: 0.47158 Epoch: 80 | train_loss: 0.16671, val_loss: 0.46765 Epoch: 90 | train_loss: 0.16197, val_loss: 0.46488 { "precision": 0.8929962902778195, "recall": 0.8333333333333334, "f1": 0.8485049088497365 }

查看

让看看从实验中追踪到的内容。MLFlow 为提供了一个仪表板,供在本地主机端口上查看和探索实验。如果您在本地计算机上运行它,您可以简单地运行 MLFlow 服务器:

mlflow server -h 0.0.0.0 -p 8000 --backend-store-uri $PWD/experiments/

并打开http://localhost:8000/以查看仪表板。但是,如果您使用的是 Google colab,将使用 localtunnel在该note本和公共 URL 之间创建连接。

如果未安装 localtunnel,您可能需要先!npm install -g localtunnel在单元格中运行。

# 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

MLFlow 创建一个包含所有实验及其各自运行的主仪表板。可以通过单击列标题对运行进行排序。

mlflow仪表板
mlflow仪表板

可以在主仪表板上单击任何实验以进一步探索它(单击每次运行的时间戳链接)。然后单击左侧的指标以在图中查看它们:

实验指标
实验指标

加载中

需要能够加载保存的实验工件以进行推理、再训练等。

def load_dict(filepath):
    """Load a dict from a json file."""
    with open(filepath, "r") as fp:
        d = json.load(fp)
    return d

# Load all runs from experiment
experiment_id = mlflow.get_experiment_by_name("baselines").experiment_id
all_runs = mlflow.search_runs(experiment_ids=experiment_id, order_by=["metrics.val_loss ASC"])
print (all_runs)

# Best run
best_run_id = all_runs.iloc[0].run_id
best_run = mlflow.get_run(run_id=best_run_id)
client = mlflow.tracking.MlflowClient()
with tempfile.TemporaryDirectory() as dp:
    client.download_artifacts(run_id=best_run_id, path="", dst_path=dp)
    vectorizer = joblib.load(Path(dp, "vectorizer.pkl"))
    label_encoder = LabelEncoder.load(fp=Path(dp, "label_encoder.json"))
    model = joblib.load(Path(dp, "model.pkl"))
    performance = load_dict(filepath=Path(dp, "performance.json"))

print (json.dumps(performance, indent=2))

{ "precision": 0.8929962902778195, "recall": 0.8333333333333334, "f1": 0.8485049088497365 }

# Inference
text = "Transfer learning with transformers for text classification."
predict_tag(texts=[text])

['natural-language-processing']

Tip

还可以通过使用它的运行 ID 直接从模型注册表加载特定运行的模型工件,而无需将它们保存到临时目录。

artifact_uri = mlflow.get_run(run_id=run_id).info.artifact_uri.split("file://")[-1]
params = Namespace(**utils.load_dict(filepath=Path(artifact_uri, "args.json")))
label_encoder = data.MultiLabelLabelEncoder.load(fp=Path(artifact_uri, "label_encoder.json"))
tokenizer = data.Tokenizer.load(fp=Path(artifact_uri, "tokenizer.json"))
model_state = torch.load(Path(artifact_uri, "model.pt"), map_location=device)
performance = utils.load_dict(filepath=Path(artifact_uri, "performance.json"))

本文主体源自以下链接:

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

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/38254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaWeb】CookieSession

文章目录一.Cookie❤️1.Cookie的概念2.创建Cookie3.获取Cookie4.修改Cookie的值5.Cookie的生命周期控制6.Cookie有效路径Path的设置7.免输入用户名登录二.Session❤️1.session的概念2.Session的创建和获取3.Session域数据的存取4.Session的生命周期控制5.浏览器和Session之间…

pytorch深度学习实战lesson28

第二十八课 resnet的梯度计算(如何缓解梯度问题) 沐神说:“假设你在卷积神经网络里面,只要了解一个神经网络的话,你就了解 rest net 就行了。 rest net 是一个很简单的也是很好用的一个网络。这也是大家会经常在实际中…

OpenCV-Python小应用(六):车道线检测

OpenCV-Python小应用(六):车道线检测前言前提条件实验环境基于霍夫变换的车道线检测参考文献前言 本文是个人使用OpenCV-Python的应用案例,由于水平有限,难免出现错漏,敬请批评改正。更多精彩内容&#xff…

【成为红帽工程师】第五天 NFS服务器

目录 一、NFS服务器简介 二、NFS的使用 三、客户端使用autofs自动挂载 四、相关实验 一、NFS服务器简介 NFS(网络文件系统),是FreeBSD支持的文件系统中的一种,它允许网络中的计算机(不同的计算机、不同的操作系统&…

Go学习之路:流程控制语句:for、if、else、switch 和 defer(DAY 1)

文章目录前引流程控制语句:for、if、else、switch 和 defer1.1、for循环语句/语法格式(一)1.2、for循环语句/省略前置后置语句(二)1.3、for循环语句/while(三)1.4、for循环语句/无限循环&#x…

美新科技过会:收入依赖美国、产能利用率低,林东亮等均为香港籍

11月25日,深圳证券交易所创业板披露的信息显示,美新科技股份有限公司(下称“美新科技”)获得上市委会议通过。据贝多财经了解,美新科技于2022年3月31日在创业板递交上市申请。 本次冲刺创业板上市,美新科技…

SpringCloudGateway--谓词(断言)

目录 一、定义 二、谓词使用 1、After 2、Before 3、Between 4、Cookie 5、Header 6、Host 7、Method 8、Path 9、Query 10、RemoteAddr 11、Weight 一、定义 SpringCloudGateway中三个重要词汇: 路由(Route):配置网…

傻白入门芯片设计,芯片键合(Die Bonding)(四)

目录 一、键合( Bonding) 1. 什么是键合(Bonding)? 2. 芯片键合步骤 3.芯片拾取与放置(Pick & Place) 4. 芯片顶出(Ejection)工艺 5. 使用环氧树脂(Epoxy)实现粘合的芯片键合工艺 6. 使用晶片黏结薄膜(DAF)的芯片键合工…

Redis实战篇(三)秒杀

一、全局唯一ID (1)定义 全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一半满足下列特性: 唯一性高可用高性能递增性安全性 为了增加ID的安全性,我们不直接使用Redis自增的数值&#xf…

OpenCV-Python快速入门(十五):霍夫变换

OpenCV-Python快速入门(十五):霍夫变换前言前提条件实验环境霍夫变换基本原理霍夫直线变换(cv2.HoughLines())概率霍夫变换(cv2.HoughLinesP())霍夫圆变换(cv2.HoughCircles()&#…

移动端测试理论

App测试基础 App功能测试及专项测试 前言: 对于APP项目的测试,一般是进行系统测试。 测试主要从业务功能和非业务功能两个方面考虑。业务功能测试 根据软件说明,设计文档或用户需求验证App的各个功能的实现。 专项测试 兼容性测试 兼容性测试的关注点…

阿里Java研发面经(已拿offer)

一、自我总结: 1)首先最重要的一点。对自己的要求高点。不要以简单的实习生来要求自己。你要想 你会的别人都会 你的核心竞争力是什么呢。所以楼主建议以Java高级工程师来要求自己。不会的就学嘛。人面对未知的事物 本能反应是恐惧与退缩。可当你尝试去…

Xxl-Job 初次体验

Xxl-Job 初次体验一、定时任务-前置知识二、演变机制三、xxl-Job 设计思想四、xxl-job 实战1. 调度中心部署2. 编写执行器简单使用一下2.1. 让执行器run起来!2.2. 在调度中心配置任务,调度一下!3. XxlJob 任务的生命周期4. 路由策略5. 父子任…

汇川PLC编程软件AutoShop的使用

文章目录一、数据类型二、系统参数.1、内存容量设置2、“掉电保持范围”设置3、系统设置三、符号表1、编辑符号表2、符号表的打印四、元件监控表1、新建元件监控表2、编辑元件监控表3、复制元件监控表4、快速监控表五、元件使用信息表六、交叉引用表七、软元件内存表1、新建和复…

windows的小米11真机appium微信爬虫

1、下载appium 仓库地址 2、下载python的包 pip install Appium-Python-Client -i https://pypi.tuna.tsinghua.edu.cn/simple 3、下载android-sdk 先下SDK Tools 国内一个镜像网站 参考这个教程 安装好后,运行这个SDK Manager.exe 然后install,同意协…

Alphalens使用方法细节判断

首先alphalens的数据格式: factor: MultiIndex(用stack()方法来转换) prices: DataFrame #转换成MultiIndex factor alpha_mom.stack() print (factor.tail()) datetime 2017-11-20 15:00:00 601857.XSHG 1…

小学生python游戏编程arcade----烟花粒子

小学生python游戏编程arcade----烟花粒子前言烟花粒子1、Vector向量类1.1 arcade中的向量类1.2 应用2、绘制粒子所有纹理图片2.1 给定直径和颜色的圆的纹理2.2 arcade.make_circle_texture函数原码2.3 make_soft_circle_texture 函数原码2.4 公共纹理代码3 效果图4 代码源码获取…

【读点论文】Densely Connected Convolutional Networks用残差连接大力出奇迹,进一步叠加特征图,以牺牲显存为代价

Densely Connected Convolutional Networks Abstract 如果卷积网络在靠近输入的层和靠近输出的层之间包含较短的连接,则卷积网络可以训练得更深入、更准确和有效。在本文中,接受了这种观察,并介绍了密集卷积网络(DenseNet),它以…

Linux - Linux下Java安装路径查找;配置Java环境变量

一、查看Java的安装路径 1、已经安装好了JDK,也配置了环境变量 1、执行 java -version java -version 出现了版本号,表示安装过了JDK,配置了环境变量 2、在配置过jdk的情况下,执行java -verbose指令,在打印出的文本…

java stream中的peek()用法

文章目录前言最终操作(terminal operation)peek() vs forEach()peek() 的典型用法:协助调试总结前言 最近看到一段代码: aeFormList.stream().peek(object -> saveInfomation(object, params)).collect(Collectors.toList())…