Skip to main content

用Weights & Biases来进行数据科学实验管理

当我们看到这份关于 BroutonLab 团队如何使用 W&B 的报告时,我们非常激动,因此我们来与您分享!
Created on June 24|Last edited on June 24

前言

可能每个数据科学家都遇到过这种情况——你创建了许多不同的模型来试验不同的参数甚至整个架构。您还想尝试优化器的选择、学习率、时期数等。因此,实际上,您将进行许多不同的实验,并且将越来越难以整理结果。在本文中,我们将向您展示如何正确方便地管理和记录您的 ML 和 DL 实验。
今天有许多工具可以让您方便地管理您的实验,例如:Weights & BiasesMlFlowNeptuneComet.ml 等。
MlFlow 是一个用于管理机器学习生命周期的开源平台。该平台非常适合单人使用,但不太适合在大型团队中使用,也不适合有大量实验的情况。
Neptune 是一种轻量级运行管理工具,可帮助您跟踪机器学习运行情况。它提供 3 种类型的订阅,其中 2 种是付费订阅。如果您打算单人使用此服务,那么您将获得免费访问权限。
Comet 是一个机器学习平台,用于跟踪、比较、解释和优化实验和模型。 它还提供不同的订阅,但团队成员的最大数量限制为 5。
我们将向您展示如何使用一个平台有效地记录实验—— Weights & Biases.

Weights & Biases概述

W&B 是一个平台,可帮助数据科学家跟踪他们的模型、数据集、系统信息等。 只需几行代码,您就可以开始跟踪有关这些功能的所有内容。 它是免费供个人使用的。 团队使用通常是付费的,但用于学术目的的团队是免费的。 您可以将 W&B 与您喜欢的框架一起使用,例如 TensorFlow、Keras、PyTorch、SKlearn、fastai 等。
所有跟踪信息都发送到 W&B UI 上的专用项目页面,您可以在其中打开高质量的可视化、汇总信息并比较模型或参数。远程存储实验信息的优势之一是可以轻松地在同一项目上进行协作并与您的团队成员共享结果。
W&B 提供了 4 个有用的工具:
  1. Dashboard: 实验跟踪
  2. Artifacts: 数据集版本控制、模型版本控制
  3. Sweeps: 超参数优化
  4. Reports: 保存和共享可重现的结果
在本教程的后面,我们将介绍所有这些实用功能。
图 1. W&B 功能。资料来源:Weights & Biases文档。

教程

Google Colaboratory 上试用
首先,我们应该在 W&B 网站上创建一个免费帐户。 然后让我们创建一个带有简单 Keras 分类器模型的Jupyter-notebook。
!pop install wandb -q
import wandb
!wandb login
现在让我们在 W&B 中创建一个新项目,并为第一个实验设置一个带有超参数的配置。
project_name = 'first_steps'
group_name = 'cnn'
experiment_name = '2_conv'
wandb.init(
project=project_name,
group=group_name,
name=experiment_name,
config={
"conv_1": 32,
"activation_1": "relu",
"kernel_size": (3, 3),
"pool_size": (2, 2),
"dropout": 0.3,
"conv_2": 64,
"activation_out": "softmax",
"optimizer": "adam",
"loss": "sparse_categorical_crossentropy",
"metric": "accuracy",
"epoch": 6,
"batch_size": 32
})
config = wandb.config
如您所见,config 是一个带有超参数的字典。 您还可以加载 .yaml 格式的配置文件。 wandb.init 在 W&B 中创建一个新的运行并启动一个后台进程来同步数据。
下一���是加载数据并定义一个简单的 CNN 模型。
from wandb.keras import WandbCallback
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

our_model = cnn_mnist()
class_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
our_model.fit(x_train, y_train, epochs=config.epoch, batch_size=config.batch_size,
validation_data=(x_test, y_test),
callbacks=[WandbCallback(data_type="image",
labels=class_names)])

wandb.finish()
我们使用 Keras 回调函数自动保存在 our_model.fit 中跟踪的所有指标和loss值。 WandCallback() 类支持许多选项,如数据类型、标签等。

Dashboards仪表盘

现在我们可以看看结果。我们执行的运行现在显示在我们项目的左侧,其中包含我们列出的组和实验名称。我们可以访问W&B 自动记录的大量信息。

我们有几个分区,例如:
  • Charts ——包含有关损失、准确性等的信息。此外,它还包含我们数据中的一些示例。
  • System ——包含系统负载信息:内存使用情况、CPU 使用情况、GPU 温度等。这是非常有用的信息,因为您可以控制 GPU 的使用情况并选择最佳批量大小。
  • Model ——包含有关我们的模型结构(图形)的信息。
  • Logs ——包括Keras 默认日志记录。
  • Files ——包含在实验过程中创建的所有文件,例如:配置、最佳模型、输出日志、需求等。需求文件非常重要,因为为了重新创建特定的实验,您需要安装特定的版本的图书馆。
重新创建实验需要所有这些日志和文件,您现在可以自动创建此类日志和文件以节省时间。您可以在此处查看此项目的仪表板。

Sweeps

Sweeps 是一种用于超参数和模型优化的工具,它为您提供强大的辅助,只需几行代码,即可根据您的需要准确配置您的Sweeps。如果您想了解有关超参数优化技术的更多信息,可以查看我们的文章使用 Optuna 框架进行高效的超参数优化。它更详细地介绍了优化机制。
首先,您应该定义一个包含要优化的超参数的配置。此外,您应该选择一个超参数优化策略——随机搜索或网格搜索——然后选择一个你要优化的指标。
sweep_config = {
'method': 'random', #grid, random
'metric': {
'name': 'accuracy',
'goal': 'maximize'
},
'parameters': {
'epoch': {
'values': [5, 10]
},
'dropout': {
'values': [0.3, 0.4, 0.5]
},
'conv_1': {
'values': [16, 32, 64]
},
'conv_2': {
'values': [16, 32, 64]
},
'optimizer': {
'values': ['adam', 'nadam', 'sgd', 'rmsprop']
},
'activation_1': {
'values': ['relu', 'elu', 'selu','sigmoid']
},
'kernel_size': {
'values': [(3, 3), (5, 5), (7, 7)]
}
}
}
然后让我们创建一个sweep并定义一个train函数。sweep使用每组超参数调用此函数。
sweep_id = wandb.sweep(sweep_config, entity=user_name, project="first_steps")
def train():
# Default values for hyperparameters we're going to sweep over
config_defaults = {
"conv_1": 32,a
"activation_1": "relu",
"kernel_size": (3, 3),
"pool_size": (2, 2),
"dropout": 0.1,
"conv_2": 64,
"activation_out": "softmax",
"optimizer": "adam",
"loss": "sparse_categorical_crossentropy",
"metric": "accuracy",
"epoch": 6,
"batch_size": 32
}

# Initialize a new wandb run
wandb.init(config=config_defaults, group='first_sweeps')
# config is a variable that holds and saves hyperparameters and inputs
config = wandb.config
model = cnn_mnist(config=config)
model.fit(x_train, y_train, epochs=config.epoch, batch_size=config.batch_size,
validation_data=(x_test, y_test),
callbacks=[wandb.keras.WandbCallback()])

wandb.agent(sweep_id,train)
我们得到以下输出:



Run set
24

让我们看看每次sweep的结果,并为我们的模型选择最合适的超参数。您可以看到精度如何根据我们感兴趣的参数集而变化。除了这些图表之外,您还可以构建对您最重要的图表。例如,您还可以记录模型的预测,从而找到模型最常出错的示例。

Artifacts

除了 Sweeps 和 Dashboard,W&B 还提供了一个名为 Artifacts 的实用工具,允许您记录数据和模型。在这种情况下,Artifacts是产出对象——过程的输出——数据集和模型。我们将使用上一个示例中的数据集日志记录向您展示如何使用 Artifacts。
让我们首先加载一个原始数据集,然后创建一个新的 Artifact。
def load_and_log():
with wandb.init(project=project_name, job_type="load-data") as run:
datasets = load_data()
names = ["training", "validation", "test"]

# Artifact
raw_data = wandb.Artifact(
"mnist-raw", type="dataset",
description="Raw MNIST dataset, splitted",
metadata={"source": "keras.datasets.mnist",
"train_data": len(datasets[0].x),
"valid_data": len(datasets[1].x),
"test_daata": len(datasets[2].x)})

for name, data in zip(names, datasets):
# Save our datasets
with raw_data.new_file(name + ".npz", mode="wb") as file:
np.savez(file, x=data.x, y=data.y)
#save Artifact
run.log_artifact(raw_data)

load_and_log()
以下是Artifact管理的一些良好实践:
  • job_type 应该是描述性的并且对应于您的pipeline的单个步骤(我们将加载数据与预处理数据分开)Name of the Artifact should be descriptive
  • Artifact的名称应具有描述性
  • Artifact的类型应该是描述性的和简单的(“数据集”或“模型”)
  • 尝试写下关于您的 Artifact 的足够多的元数据信息
所有这些实践都将帮助您和您的队友正确组织您的pipeline结构。
如果我们转到运行页面和 Artifacts 选项卡,我们将看到以下内容:

“mnist-raw”是一个输出Artifact,包含:
  • 元数据—— 当前Artifact的描述。在我们的例子中,它是我们数据集的描述(来源,分割大小)
  • 文件——数据集
  • 图形视图——Artifacts图表(输入、输出、过程)
现在让我们添加一个新的 Artifact,它将描述数据预处理:
def preprocess_and_log(preprocess_steps):

with wandb.init(project=project_name, job_type="data_preprocessing", name="preprocess_simple") as run:

processed_data = wandb.Artifact(
"mnist-preprocessed", type="dataset",
description="Preprocessed MNIST dataset",
metadata=preprocess_steps)
# which Artifact we will use
raw_data_artifact = run.use_artifact('mnist-raw:latest')

# download Artifact
raw_dataset = raw_data_artifact.download()
for split in ["training", "validation", "test"]:
datafile = split + ".npz"
data = np.load(os.path.join(raw_dataset, datafile))
raw_split = Dataset(x=data["x"], y=data["y"])
processed_dataset = preprocess_dataset(raw_split, **preprocess_steps)

with processed_data.new_file(split + ".npz", mode="wb") as file:
np.savez(file, x=processed_dataset.x, y=processed_dataset.y)

run.log_artifact(processed_data)
首先,我们创建一个新的 Artifact 并为其命名。然后我们选择我们将使用的 Artifact,mnist-raw:latest。之后,preprocess_dataset 应用于每个数据拆分。最后将结果保存在新的 Artifact 中。现在让我们运行它。
steps = {"normalize": True,
"expand_dims": True,
"to_categorical" : True}
preprocess_and_log(steps)

如您所见,我们现在有 2 个Artifacts:“mnist-raw”和“mnist-preprocessed”。图形视图为您的pipeline步骤提供了一个用户友好的界面:矩形是输入/输出Artifacts,圆形是Artifacts之间的过程。在图表视图的帮助下,您可以轻松跟踪您的pipeline在工作过程中发生的变化。

报告

您可以使用报告轻松组织可视化、描述您的发现并与您的团队共享更新。在报告中,您可以指出您认为必要的任何内容、各种图形、相关性、未来计划。您可以使用 Latex 或 Markdown 编辑您的报告。
创建新报告非常简单:转到 wandb.ai 中的工作区,然后单击“创建报告”。您可以为一个项目或一组创建报告,也可以创建跨项目报告来比较两个项目的运行。 W&B 提供了一些模板,您也可以创建自定义空白报告。您正在阅读的这篇文章是一个报告示例。
图 3. 报告模板。资料来源:Weights & Biases文档。
  • Snapshot 将当前日期/时间添加到标题并向运行集添加过滤器,这意味着只有在当前时间之前创建的运行才包含在快照中。
  • Dashboard 将报告命名为“Project Dashboard”并添加过滤器以与当前选定的运行集完全匹配。
  • Update 将报告命名为“<today’s date> Project Update”,并过滤到在工作区中选择的确切运行集。
  • Blank 为您提供了添加新面板网格和可视化效果的空间,或者只是给自己写一些笔记。
以下是此项目的快照报告示例。
图 4. 报告示例。
现在我们可以与我们的团队分享结果。报告的使用帮助我们总结了收到的有关今天实验的信息。以后我们就不需要单独搜索每个实验的结果了,打开对应的Report就够了。

结论

在本教程中,我们展示了如何使用Weights & Biases有效管理和记录实验。 我们已经回顾了这个平台的主要工具。 对于高级研究,您可以参考官方文档。 我们希望本指南对您未来的工作有用。
本文由BroutonLab独立制作。