DLAI-生成式人工智能评估和调试笔记-全-
DLAI 生成式人工智能评估和调试笔记(全)
001:课程介绍 🎯
在本节课中,我们将一起了解《评估和调试生成式人工智能》这门短期课程的核心内容与目标。课程将重点介绍如何系统化地追踪、评估和优化生成式AI模型,并介绍一套实用的工具集。
欢迎来到《评估和调试生成式人工智能》课程。我是吴恩达,与我一同授课的还有来自Weights & Biases的创始产品经理兼本课程讲师——Carrie Fels。
你好,吴恩达,很高兴来到这里。
当你构建一个机器学习系统时,跟踪所有的数据、模型和超参数选项可能会变得非常复杂。我参与过许多项目,过程通常是:训练模型,调整架构,重新训练模型,然后决定改变训练技术,如此循环。在模型上迭代几次后,你最终会问自己:我上周训练的那个效果不错的模型,现在该如何复现当时的结果?我是否不仅保存了超参数值,还保存了当时使用的确切数据集?
更普遍地说,当运行大量模型时,你如何系统地跟踪所有尝试过的方案,并利用看到的结果来有效地推动改进?即使对于一个小团队,管理和跟踪机器学习模型的训练与评估也变得复杂,而团队规模越大,这种复杂性会急剧增加。
我观察到,如果机器学习开发的这个步骤能更严谨地进行,许多团队的效率可以大幅提升。
因此,这门短期课程涵盖了在开发过程中系统化追踪和调试生成式AI模型的工具与最佳实践。我们将使用来自Weights & Biases的工具,它提供了一套易用且灵活的工具集,已成为机器学习实验追踪领域的事实标准。
课程将涵盖用于文本生成的大语言模型和用于图像生成的扩散模型这两类生成式AI模型。但是,与监督学习相比,生成式AI模型增加了一层复杂性,因为它们的输出很复杂,因此评估起来可能更困难。
那么Carrie,你对这些挑战非常了解。你能向学员们分享一下他们将在本课程中学到什么吗?
当然可以。谢谢,吴恩达。大家好,很高兴与你们一起学习这门课程。

在本课程中,我们将专注于评估和调试生成式人工智能。首先,我们将向你展示如何追踪和可视化你的实验。接着,我们将教你如何监控扩散模型。然后,我们会讨论如何评估和微调大语言模型。
在整个课程中,你将学习一系列调试和评估工具,包括:
- 实验:用于追踪你的机器学习实验。
- 工件:用于版本控制和存储数据集及模型。
- 表格:用于可视化和检查模型做出的预测。
- 报告:用于协作和分享实验结果。
- 模型注册表:用于管理模型的生命周期。
- 提示:用于评估大语言模型的生成结果。
这些工具可以与广泛的框架和计算平台协同工作,包括Python、TensorFlow或PyTorch。
课程内容非常丰富,并且有许多人为本课程的开发做出了贡献。我们感谢Weights & Biases的Derek Qiuke和Thomas Capelle,以及DeepLearning.AI的Jeff Ludwig和Tommy Nelson的辛勤工作。
在本课程结束时,你将理解最佳实践,并掌握一套用于系统化评估和调试生成式AI项目的工具。希望你享受这门课程。


本节课中,我们一起学习了《评估和调试生成式人工智能》课程的整体框架和目标。我们了解到,系统化地追踪实验、评估复杂输出是开发生成式AI模型的关键挑战,而本课程将提供一套强大的工具和最佳实践来应对这些挑战。接下来,我们将深入第一课,开始学习如何具体地追踪和可视化你的实验。
002:01_Weights & Biases 简介 🚀

在本节课中,我们将学习如何在机器学习训练代码中集成 Weights & Biases(W&B)工具。我们将了解如何通过几行代码来监控、调试和评估训练过程。

概述
在第一课中,我将展示如何在你的机器学习训练代码中集成 Weights & Biases。在训练机器学习模型时,许多环节可能出错。W&B 将帮助我们监控、调试和评估整个流程。

现在,让我们开始深入了解。
集成 W&B 到训练流程
只需几行代码,你就能实时监控指标、CPU 和 GPU 使用情况。你可以对代码进行版本控制,复现模型检查点,并在一个集中的交互式仪表板中可视化预测结果。我们的用户使用 W&B 来评估模型、讨论问题,并通过可配置的报告展示进展。
在本课程结束时,你也能做到这些。让我们从学习如何将 Weights & Biases 集成到你的训练过程中开始。
安装与初始化


首先,你需要使用命令 pip install wandb 安装 Python 库。

安装完成后,我们只需要几行代码。第一步是导入 W&B。理想情况下,你已经将超参数组织在一个对象中,例如 Python 字典。否则,请将它们放在一个配置对象中。
接着,你需要初始化一个 W&B 运行。在 Weights & Biases 中,一个“运行”代表一个计算单元。通常,一个运行对应一个机器学习实验。你可以通过调用 wandb.init 并传入项目名称和配置对象来开始一个运行。
然后,你继续执行模型训练代码。当你到达想要跟踪和可视化某些指标的点时,使用 wandb.log 记录它们。如果你在使用笔记本,建议在最后调用 wandb.finish。
实战演示:训练一个精灵分类模型
现在,让我们在一个笔记本中查看这个过程。在这个训练脚本中,我们将训练一个精灵分类模型。精灵是一个 16x16 像素的小图像,我们的目标是将精灵分类为五个类别之一:英雄、非英雄、食物、法术和侧向(未在图中显示)。
让我们从所有导入开始,并确保 W&B 在其中。
我们定义一个具有两个线性层的简单分类器模型。我们将想要跟踪的参数存储在一个简单的命名空间中,这类似于 Python 字典。
这是我们的训练函数,让我们修改它以添加 W&B 日志记录。

首先,我们需要调用 wandb.init 并传入我们的项目名称和配置对象。
一旦我们有了指标,我们将使用 wandb.log 将它们记录到 Weights & Biases。

我们还会在每个周期结束时记录验证指标。为了清晰起见,我们可以通过调用 wandb.finish 来显式结束我们的 Weights & Biases 运行。

我们不需要在验证函数中做任何更改。所以,我将直接运行这个单元格。
在本课程中,我们将使用 W&B 云平台,这意味着我们需要登录。也有安装本地 W&B 的选项,但这更复杂,因此本课程不涵盖。W&B 对个人和学术用途是免费的,我们鼓励你注册。这样,你可以保存实验跟踪的结果。但你也可以在匿名模式下运行此代码。
现在,我已经运行了登录,使用我的个人账户并粘贴了我的 API 密钥。你可以在 wandb.ai/authorize 获取它。我按回车键,这意味着我已在此笔记本中登录。
最后,让我们训练模型。运行我们的训练代码并查看进度。
现在,数据正被记录到 W&B 服务器,在那里保存你的结果。当你执行运行时,你可以看到这里打印出的几个不同链接。首先,“正在同步此运行”指的是你刚刚跟踪的单个实验。你也可以打开项目页面,这将比较你正在跟踪的不同运行。
让我们点击那个链接并检查我们的工作空间。
现在,我来到了项目页面工作空间。这是我可以从刚刚在笔记本中运行的训练运行中看到的数据。这些图表很小,我可以展开它们使其变大。这看起来不错。训练损失随时间下降,我也在检查我的验证指标。
查看验证准确率,看起来大约是 51%,这并不理想。所以,如果我想继续改进这个模型,看起来我可以训练更长时间或提高学习率。让我们回到笔记本并进行这些更新。
比较与分析实验结果
现在结果已记录到 W&B,我可以回到同一个项目页面,查看最新结果与先前基线的比较。很好,这是我们工作空间中刚刚出现的新运行。你可以看到这个红色的运行实际上比之前的运行表现更好。这是一个好迹象。这正是我们想看到的。

现在,我将回到笔记本并尝试更多操作。我也鼓励你尝试不同的配置。那么,你如何调整超参数以使模型获得更好的性能呢?花一分钟尝试一下,等我完成更多实验后我们再回来。

回到项目页面,我正在比较我们在那些运行中设置的不同超参数的结果。所以你可以看到每个运行都有不同的训练曲线。当我将鼠标悬停在其上时,它会在侧边栏中高亮显示。我可以看到这个紫色的运行似乎表现最好。它有最低的训练损失,并且看起来也获得了 99% 的最佳验证准确率。
另一种比较实验的方法是使用运行表。这以表格格式显示相同的运行,因此我可以并排查看指标和超参数。在这里,我可以看到我在不同运行中更改了 dropout、周期数和学习率。
一个特别感兴趣的指标可能是准确率。要找到它,我可以转到列部分并搜索“准确率”。当你记录大量指标时,这尤其有帮助。在这里,我可以点击“固定”按钮。当我关闭这个窗口时,该指标将出现在侧边栏这里。
现在,当我收起这个视图时,我可以在侧边栏中看到验证准确率以及其他指标。
在这个例子中,我有一个运行,其验证准确率相当差。我可以使用筛选按钮隐藏低于特定阈值的任何运行。在这里,我添加一个筛选器,输入“准确率”,然后选择“大于或等于”,并输入 0.9。
现在筛选器已应用,你可以看到我只剩下三个符合该条件的运行。这帮助我专注于我最好的运行。由于更高的验证准确率更好,我将按降序排序,将最成功的运行放在顶部。在这里,我选择排序,输入“准确率”,并选择它。现在它是降序排列。所以我的最佳运行在最顶部。当你拥有成百上千个运行时,这尤其有用。
现在,我将选择那个最佳运行并查看其概览。
在我的最佳运行的详细视图中,我可以看到关于它如何创建的一些上下文。W&B 会自动获取 Git 仓库,因此我可以轻松回到用于训练此模型的代码。它还会获取最新 Git 提交的哈希值,因此我知道创建此运行时仓库的确切状态。
但现实情况是,我经常在笔记本中进行一些小调整,并不总是记得提交更改。那么,如果你有未提交的更改该怎么办?幸运的是,W&B 会捕获差异补丁。打开文件选项卡,我可以看到差异补丁已与任何未提交的更改一起保存。
所以现在,如果我回到那个概览,我知道通过拉取这个 Git 提交并应用补丁,我可以轻松回到代码的确切状态。这使得这个运行更具可复现性。如果我把它发送给某人,我也可以轻松地与他们沟通我为这个模型选择的设置。在配置中,我捕获了批次大小、dropout、周期数、学习率等我们在笔记本中拥有的所有设置。这是一个易于总结的格式。
当事情进展顺利时,这些信息很有帮助;但当出现问题时,它也非常有价值。我们可以使用这个上下文进行调试,理解实验中使用了什么代码、环境是什么、数据集等等。
总结
在本节课中,我们一起学习了如何将 Weights & Biases 集成到机器学习训练流程中。我们了解了如何通过简单的代码初始化运行、记录关键指标,并利用 W&B 的仪表板来实时监控训练过程、比较不同实验以及分析最佳模型。我们还看到了 W&B 如何帮助进行版本控制和实验复现,这对于调试和协作至关重要。

在下一课中,我们将探讨如何训练一个生成式 AI 模型,并了解这些工具在那里如何发挥作用。
003:02_训练笔记本的插装
在本节课中,我们将训练一个扩散模型,并学习在此过程中使用的新工具。我们将从回顾扩散模型的关键概念开始,然后逐步完成一个训练笔记本的配置和运行,最后将训练好的模型注册到中央仓库。

概述:扩散模型与训练监控
上一节我们介绍了如何为模型插装。本节中,我们将实际训练一个扩散模型,并学习如何有效地监控和记录训练过程。
扩散模型是一种去噪模型。其核心思想不是直接训练模型生成图像,而是训练它从图像中移除噪声。
训练过程可以概括为:我们按照一个调度器向图像中添加噪声,然后让模型预测图像上存在的噪声。
采样(生成)过程则是:从纯噪声开始,迭代地去除噪声,直到最终图像显现。
在训练生成模型时,正确设置遥测数据至关重要。我们当然需要跟踪损失曲线等关键指标。然而,如下图所示,损失可能在早期就趋于平缓,但生成的样本质量仍然不佳。

因此,在训练期间定期从模型采样至关重要,即使损失下降幅度很小。图像质量会逐步提升。我们将把这些样本上传到Weights & Biases平台,同时保存模型检查点以保持一切井井有条。
进入训练笔记本
现在让我们进入具体的训练笔记本。我们将使用DeepLearning.AI课程《扩散模型工作原理》中的训练笔记本,该笔记本在Sprites数据集上训练一个扩散模型。我们不会深入探讨扩散模型的细节,如果你想了解更多,我们鼓励你学习那门课程。
以下是训练流程的主要步骤:
首先,我们导入相关库和W&B。
import wandb
# ... 其他导入
接下来,我们建议你创建一个W&B账户,但你也可以匿名记录结果。这里我登录到我的个人账户,以便在我的共享仪表板中查看指标。
然后,我们将定义一些环境变量,例如保存模型和检查点的路径。如果你的设备支持CUDA GPU,我们也会利用它。
我们更新了这个笔记本,使用一个简单的命名空间来设置可能在多个实验间变化的超参数。
接下来,我们将导入相关的DDPM噪声调度器和采样器。这些元素对扩散模型训练至关重要,因为噪声是在不同时间步通过调度器移除的。
随后,我们创建要训练的神经网络,使用之前课程中的示例数据集,创建数据加载器,并设置优化器。
设置训练循环
接下来,让我们设置训练循环。为了保持组织性和一致性,我们只生成一次噪声,用于重复生成样本。
现在,我们进入脚本的训练阶段,开始实际训练模型。我们首先初始化一个W&B运行来跟踪这次训练。
run = wandb.init(project="DLAI-Sprite-diffusion", job_type="training")
这个运行将被存储在“DLAI Sprite diffusion”项目中,并分类为“training”。指定任务类型有助于我们日后轻松识别此任务。配置也会被存储,以便跟踪此次训练使用的参数供将来参考。我们还传回W&B配置,以便未来需要时,可以让Weights & Biases来编排和更改这些值。
标准的训练循环会运行多个周期,处理数据加载器并计算前向和后向传播。
这些指标被记录到Weights & Biases。在本例中,跟踪损失、学习率和当前周期数。
接下来,我们希望保存训练结果。我们将每四个周期保存一次模型检查点。
if epoch % 4 == 0:
checkpoint_path = f"model_epoch_{epoch}.pth"
torch.save(model.state_dict(), checkpoint_path)
artifact = wandb.Artifact(name="model-checkpoints", type="model")
artifact.add_file(checkpoint_path)
wandb.log_artifact(artifact)
为了保存检查点文件,我将添加一个Weights & Biases工件来保存它。这是我们版本化并在运行中存储文件的方式。这里我们使用工件来保存模型检查点,但我们也可以用它来保存数据集、预测结果甚至代码。
同时,我们希望采样一些图像以便在工作区查看,因此我将在这里使用wandb.log和wandb.Image添加图像记录。
sampled_images = sample_from_model(model, ...)
wandb.log({"samples": [wandb.Image(img) for img in sampled_images]})
这使我能够实际可视化地看到结果并查看样本预测。
最后,我们通过调用wandb.finish()来结束这次运行。
查看训练结果
在CPU上运行此脚本需要一些时间,因此我将切换到一个我们已经为你运行好的示例。
在这个示例工作区中,你会看到你的损失曲线随时间下降。这是一个好迹象,意味着你的模型随着持续训练而变得更好。
让我们也看看你的模型生成的一些样本。如果我滚动回最开始,可以看到这些图像看起来颗粒感很强,噪声很大,很难分辨每张图像应该是什么。
但随着你滚动查看每个步骤,你可以看到随着时间的推移和模型的训练,它开始改进。现在你的模型实际上正在生成一些看起来非常不错的图像。这张看起来有点像尤达大师。
注册模型

既然我们有了一个在生成精灵方面表现不错的模型,现在让我们实际获取该模型并使其对团队的其他成员可用。



你将打开“Artifacts”选项卡,然后拉取最新的模型,即最近的版本。



并将其链接到模型注册表。现在,我们有了“Sprite generation model”。链接模型后,你可以在模型注册表中看到结果。


模型注册表为你的团队提供了一个中心位置来查看所有最佳模型版本。你还可以查看模型的来源谱系,并轻松返回到那个训练运行,查看指标、样本图像以及生成此模型的精确Git提交。
总结
本节课中,我们一起学习了如何训练一个扩散模型并监控其过程。我们回顾了扩散模型的核心概念,即通过去噪进行训练和采样。我们逐步完成了训练笔记本的设置,包括初始化W&B运行、记录损失和图像、保存模型检查点作为工件。最后,我们将训练好的模型注册到中央模型注册表,以便团队协作和版本管理。

我们已经讨论了跟踪训练和查看最佳模型版本,接下来我们将讨论如何对扩散模型进行采样。
004:在W&B中监控和调试训练运行
概述
在本节课中,我们将学习如何比较扩散模型的输出。我们将使用上一节课训练好的模型,通过Weights & Biases平台,对比不同采样算法(如DDPM和DDIM)生成图像的质量和速度。你将学会如何从模型注册表中获取模型,生成样本,并使用W&B的表格功能进行可视化比较和分享。



模型注册表:中央管理系统
上一节我们介绍了扩散模型的训练,本节中我们来看看如何管理已训练好的模型。
模型注册表是一个组织内所有机器学习模型的中央系统。它作为所有生产就绪模型的记录系统,可用于管理模型从测试到生产的整个生命周期。
模型注册表不仅是一个存储系统,还能通过促进不同团队间的协作来提升团队合作效率。它会详细记录模型在训练、评估和生产阶段的谱系,帮助我们控制和理解模型的整个生命周期。
此外,注册表还能自动化多个下游任务,从而提高效率。为了直接从注册表中比较和评估模型,我们将使用“表格”功能。
使用W&B表格进行可视化比较
表格可以被视为一个强大的、类似数据框的对象,你可以用它来记录、查询和分析数据,包括视频、图像、分子等富媒体内容。
以下是使用表格的基本流程:
- 创建一个表格。
- 为表格命名列。
- 逐行更新表格数据。
- 完成后,使用
wandb.log记录表格并为其命名。
现在,让我们深入代码部分。
从训练好的扩散模型中采样
为生成模型计算指标非常困难,并且在质量和速度之间存在权衡。因此,我们通过比较不同的采样算法来评估模型。在本节结束时,你将学会如何直观地比较不同采样器的效果。
首先,运行必要的导入并登录W&B。
# 设置参数并将配置存储在简单的命名空间中
import wandb
# ... 其他导入和设置代码
在之前的笔记中,我们保存了一个训练好的模型,将其放入一个“工件”中,并注册到了模型注册表。现在,我们使用以下代码片段将工件拉取回来。
我们首先使用W&B API从注册表中拉取模型,这样就将模型下载到了本地计算机。同时,我们还获取了生成该模型的训练运行的相关信息。
# 从注册表拉取模型
api = wandb.Api()
run = api.run("项目路径/运行ID")
model_artifact = run.use_artifact('模型工件名称')
model_path = model_artifact.download()
现在,我们可以从模型工件中加载权重,并使用与原始训练相同的参数来重建模型。
# 加载模型权重并重建模型
model = create_model_with_original_params()
model.load_state_dict(torch.load(f'{model_path}/pytorch_model.bin'))
model.eval()
model.to(device)
不要忘记将模型设置为评估模式并转移到相应的计算设备上。
比较DDPM与DDIM采样器
现在,让我们设置训练时使用的扩散采样器,在本例中是DDPM。接下来,我们将定义一些固定的噪声和上下文向量,就像在训练时一样。
为了让实验更有趣,我们还将导入另一个名为DDIM的采样器(同样来自扩散课程材料)。这个采样器运行速度更快,但会牺牲一些输出质量。我们的目标是比较两个采样器的输出。
为了实现这个目标,我们生成两组样本。首先,使用DDPM采样器生成样本。
# 使用DDPM采样器生成样本
samples_ddpm = ddpm_sampler(model, noise, context, timesteps=500)
这个过程需要一些时间。接下来,让我们与DDIM采样器进行比较。
# 使用DDIM采样器生成样本
samples_ddim = ddim_sampler(model, noise, context, timesteps=25)
当我运行DDIM采样器时,它只迭代了25个时间步,因此比DDPM(500个时间步)要快得多。
在W&B表格中记录并比较结果
现在,让我们在一个可视化表格中比较我们的结果。这个表格的行为类似于一个数据框,可以在你的W&B项目工作区中渲染。
接下来,我们将遍历样本,逐行将它们添加到表格中。我们还将类别名称和输入噪声添加到表格中。
# 创建表格并逐行添加数据
table = wandb.Table(columns=["输入噪声", "DDPM结果", "DDIM结果", "类别"])
for i in range(num_samples):
table.add_data(wandb.Image(noise[i]), wandb.Image(samples_ddpm[i]), wandb.Image(samples_ddim[i]), class_names[i])
在这里,我们逐行构建表格,同时展示图像、类别名称和输入噪声。
创建好表格后,我们可以将其记录到项目中。为此,调用 wandb.init,使用与之前相同的项目,但这次将作业类型设置为“Samplers Battle”,这将使我们更容易找到这个新的运行记录。
# 初始化一个新的W&B运行并记录表格
wandb.init(project="你的项目名", job_type="Samplers Battle")
wandb.log({"samplers_table": table})
wandb.finish()
接下来,设置表格的名称为“samplers_table”,并将其直接记录到运行中。运行这个单元格,结果就会显示在UI中。
表格上传完成后,我可以点击该运行记录,在新标签页中打开并查看生成的图像。
在这里,我们找到了“samplers_table”,可以看到输入噪声、DDPM结果、DDIM结果以及类别。例如,这里有一行是“英雄”类别的图像。
为了比较两个采样器,你可以看到相同的输入噪声实际上从两个采样器生成了两种不同的结果。有趣的是,这些结果在某种程度上依赖于输入噪声。
我将展开表格并调大行高,以便在大屏幕上查看这些图像。例如,在这一行中,这两个角色看起来非常相似,但DDPM生成的图像似乎质量更好。

分组查看与报告分享

现在,我将按类别分组,以便并排查看所有“英雄”类别的图像。点击菜单,选择“按列分组”,系统会自动将所有“英雄”样本图像组织到一行中。
接下来,我将隐藏“输入噪声”列,可以通过点击菜单并选择“移除”来完成。
现在,我可以轻松地翻看“英雄”、“非英雄”或“食物”类别的样本图像了。这个视图很有趣,我想与我的同事分享。
因此,我可以创建一个报告,并将这个样本表格拉取进来。我会展开表格使其更清晰可见,并切换视图模式以查看更多行。
我可以在报告内部添加一些上下文和注释,这样如果我发送给同事,他们就能了解发生了什么以及我的发现是什么。我将给这个报告起一个有用的标题,并描述我的发现。在本例中,DDPM的表现似乎优于DDIM。我会解释发生了什么,这样任何收到报告的同事都有足够的背景信息来查看这个表格并理解结果。
现在,我点击“发布到项目”。这意味着这份报告对所有同事都可用。

如果你想分享一份报告,操作很简单。你可以通过电子邮件或用户名邀请他人,也可以直接分享链接。


总结

本节课中,我们一起学习了如何在Weights & Biases平台中比较扩散模型的输出。我们回顾了模型注册表的作用,使用W&B表格功能对DDPM和DDIM两种采样器生成的图像进行了可视化对比,并学会了如何通过分组查看和创建报告来分析与分享实验结果。这为我们评估生成模型的质量提供了一种直观有效的方法。接下来,我们将学习如何评估大语言模型。
005:04_评估生成式图像模型



在本节课中,我们将学习如何评估大型语言模型。我们将深入细节,查看单个生成的样本。让我们开始使用笔记本。
概述:我们将要学习什么
在本节课中,我们将通过三个循序渐进的例子,学习如何使用工具来评估、分析和调试LLM的输出。我们将从最简单的API调用开始,逐步深入到更复杂的链和代理的跟踪与调试。
第一课:使用表格评估LLM输出 🧮
上一节我们介绍了课程目标,本节中我们来看看第一个也是最简单的例子:直接调用LLM API并记录结果。
我们将遵循一个直接的工作流程。首先,设计系统提示词和用户提示词。之后,使用聊天补全API调用OpenAI端点。API将作出响应,然后我们解析结果并将其记录在W&B表格中。
我们将继续使用虚拟游戏世界的设定,这次的任务是为游戏资产生成名称。
现在,让我们跳转到笔记本。首先运行导入并设置API密钥。
接下来,定义项目名称并指定要使用的模型,本例中使用GPT-3.5 Turbo。
然后登录,以便跟踪我们的结果。现在,初始化一个新的运行来跟踪生成过程。

我们有一些辅助代码。首先定义 completion_with_backoff 函数,这个函数可以避免速率限制。然后定义一个函数,它接收系统提示词、用户提示词和一个W&B表格。我们将使用 completion_with_backoff 函数来收集响应。此外,我们还会跟踪每次响应后的开始时间和经过时间。
对于每个生成的响应,我们都会打印出结果。如果你运行更多实验,在笔记本中打印结果效率不高,这就是为什么我们要将所有输出记录到表格中。


这里我们定义了系统提示词。它要求语言模型扮演一个创意文案的角色,根据类别为游戏资产生成名称。
接下来,创建一个包含我们想要跟踪的所有列的表格。
现在,让用户提示词为“hero”,看看模型生成了什么名字。很好,这些名字听起来确实像英雄。“Harmonic Champion”、“Unity’s Chorus”、“Unity’s Valor”,我喜欢这些名字。


接下来,为游戏中的一个物品生成名字,让用户提示词为“Jewel”。很好,这里有几个选项:“Harmony Gem”、“Laughter’s Gem”、“Gleaming Unity”。看来“Unity”是一个大主题。
现在,将这个表格记录下来,然后去W&B界面查看。接下来,点击这里打印出的运行链接来查看仪表板。

在这里,你可以看到刚刚在笔记本中生成的结果,但它们已被保存下来,以便你以后可以回顾,或者与他人分享。
我将展开这些列,以便更好地查看文本。我可以看到系统提示词、用户提示词和生成的例子。现在我想估算一下成本:我们为生成这些资产名称向OpenAI API支付了多少钱。
因此,我可以创建一个新列来进行计算。在这里,我将鼠标悬停在行标题上,然后点击“插入右侧”。现在我得到了一个只显示“行”的新列,点击它。现在我可以更新单元格表达式,在这里输入方括号和 total_tokens。我们想用令牌数乘以估算成本,本例中因为使用OpenAI,成本是0.0000015。

很好,现在我们有了一个新列,它是总令牌数乘以那个数字,让我们将其重命名为“cost”,以便其他人更容易理解发生了什么。
现在,这个表格可以分享给同事,展示我为生成名称所做的尝试。
第二课:使用追踪器调试LLM链 🔍
上一节我们学习了如何用表格记录和评估简单输出,本节中我们来看看如何调试更复杂的LLM链。
在第二个例子中,你将创建一个简单的链。虽然这看起来像是一个玩具示例,但你可以用它来演示“追踪器”的概念,这对于调试LLM链和工作流非常强大。
你的链将只包含两个动作。第一个动作涉及选择一个虚拟世界,你将其称为“World Picker”。当你使用这个工具时,你将跟踪各个方面,例如输入、输出、开始和结束时间、结果以及动作是否成功。
然后,将输出(即虚拟世界)传递给链中的下一步,即生成描述。这一步带有另一组需要跟踪的输入和输出,以及它们的开始和结束时间以及最终结果。
这两个步骤都将被追踪为“跨度”。它们将成为“My Chain Trace”的一部分,这将帮助你理解和分析这个工作流。
现在让我们在代码中看看。
我们将创建并追踪一个链来为我们的资产生成名称。首先,定义三个示例世界,并从这个列表中随机挑选。
然后定义配置,我们仍然使用GPT-3.5 Turbo,你可以在这里设置温度,目前是0.7,但如果你希望模型更有创意,可以提高这个值。
系统消息要求LLM扮演创意文案的角色。因此,我们不仅向LLM提供游戏资产的类别,还提供一个奇幻世界。目标是在给定的奇幻世界中为资产设计一个名称。
下一个函数将执行我们的创意链,说明追踪的概念以及它是如何构建的。
我们将从顶层跨度“creative_chain”开始。然后定义一个“world_picker”工具,我们将从列表中随机挑选一个世界,跟踪开始和结束时间,并记录这个跨度的输入和输出。我们将这个工具跨度添加到我们的顶层追踪中。
接下来,我们将这个工具的输出传递给LLM链,这需要一个系统提示词和一个用户提示词。我们使用OpenAI聊天补全,并将其作为追踪保存到Weights and Biases。然后将其添加到我们的顶层追踪中。更新元数据,并通过记录根跨度将所有跨度记录到W&B。
最后,打印出我们链的响应。
现在我们可以启动一个Weights and Biases运行。我们将尝试使用“hero”和“jewel”的游戏资产提示词来运行这个链。
既然我们已经执行了这些创意链,我们可以看到结果。然而,我们并不确切知道后台发生了什么。我们是如何为英雄得到“Volcanic Sentinel”,或者为珠宝得到“Gleamstone”这个名字的?
让我们完成这个运行,然后在用户界面中更仔细地查看结果。
在这里,我将点击这个运行的链接,以便看到表格。现在在这个表格中,我可以看到我们刚刚运行的结果,即追踪视图。我将展开它。
顶部是表格,它捕获了我们发送的两个输入(“hero”和“jewel”)以及输出(生成的名称)。但是幕后发生了什么?当你点击第1行时,你可以在下面的追踪时间线中看到幕后发生的事情。
那么对于第一行,让我们看看这两个步骤。首先,“World Picker”工具将“hero”作为输入,并产生一个描述:“A Modern Castle”,这是从三个选项的数组中随机选择的。
这个结果随后被传递到下一步,即OpenAI LLM。你可以看到生成的输出“that modern fantasy castle”现在实际上被拉到了这个下一步中。现在,对于该LLM的输入,我们有系统提示词以及来自World Picker的结果。
这个追踪时间线帮助我们理解这个链的执行以及这些步骤是如何组合在一起的。现在,这个追踪时间线相当简单,只有两个步骤。但当你的链中有很多不同的步骤,链更长、更复杂时,这将非常有用,它将允许你调试并精确定位任何问题,如果结果不符合预期的话。例如,如果World Picker失败了,我们可以在这里看到。
虽然手动定义链可能很繁琐,但有像LangChain这样的库可以加速这个过程。我们将在下一个例子中讨论这一点。
第三课:追踪LangChain代理的决策过程 🤖
上一节我们介绍了如何手动追踪链,本节中我们来看看如何使用LangChain库和追踪功能来理解更复杂的代理行为。
这最后一个例子使用了LangChain代理。与链中每个步骤都是预先确定和固定的不同,代理使用LLM进行推理,并决定采取什么步骤或使用什么工具。在演示中,你将看到代理更加不可预测,更不确定,因此更难调试,使用追踪器将很有帮助。
除了“World Picker”工具,这次我们还将让代理使用一个新工具:“Name Validator”,用于检查名称是否看起来不错。
现在,让我们回到笔记本看看实际操作。首先,运行必要的导入。然后,开始一个新的运行来跟踪我们的结果。
接下来,设置一个环境变量 LANGCHAIN_WANDB_TRACING 为 true。这设置了跟踪功能,以便自动记录这些追踪。
现在让我介绍我们的工具。我们将保持简单,因为这个例子只是为了说明追踪的概念。第一个工具是“World Picker”,它随机从世界列表中返回一个选择。第二个工具是“Name Validator”,它检查查询的名称是否少于20个字符。如果是,它会说“This is a correct name”,否则会说“This name is too long”。
我们将再次使用OpenAI API,温度为0.7。如果你想要更多创意,可以调高这个值。然后,我们将用一个工具列表来初始化代理。
好了。现在我们准备好运行一个查询。我们将要求我们的代理找到一个虚拟游戏世界,并想象那个世界中一个英雄的名字。
代理启动了一个新链,我们甚至不需要等待它,我们可以运行代理几次并查看结果。
我将点击这里打印出的运行链接来打开仪表板。
现在你在你的工作区,可以看到追踪列表。点击你的第一行,并展开它以更好地查看。
在这里,表格的第一行中,输入是“find a virtual game world and imagine the name of a hero”。但输出是“I couldn’t generate a name for the hero”。现在,这是个问题。这个追踪中出了些问题。让我们深入并找出问题所在。
向下滚动到追踪时间线部分,我可以看到代理为得到那个结果所采取的步骤。让我们从第一步开始,我们输入了提示词。我们可以看到代理的推理:“我应该先挑选一个虚拟游戏世界,然后为那个世界中的英雄生成一个名字。”然后它采取了行动“pick_world”。
很好,那么接下来那个世界发生了什么?它被拉入下一步,LLM查看那个虚拟世界并需要为英雄生成一个名字。模型输出:“我已挑选了一个由友好的机器学习工程师居住的虚拟游戏世界,现在我需要为那个世界中的英雄生成一个名字。”
但这就是出错的地方。它接着说:“Action: validate_name”和“Action Input: none”。所以它实际上还没有生成名字,它直接跳到了验证步骤。这就是问题所在。
当我们到达“validate_name”步骤时,它接收输入“none”,因为没有生成名字,并给出输出:“This is a correct name: none”,因为从技术上讲,它少于20个字符,这是该工具的规则。
因此,使用这个追踪时间线视图,我们能够识别代理在哪里出错了,现在我们可以调试这个问题,以便在未来的生成中修复它。
总结:本节课的核心要点
在本节课中,我们一起学习了如何评估和调试生成式AI模型。我们从简单的API调用和表格记录开始,逐步深入到使用追踪器来可视化复杂的LLM链和代理的执行过程。通过分析追踪时间线,我们获得了关于链可能在何处出错的宝贵见解,并可以利用这些信息来改进结果,使我们的代理更加成功。

在下一课中,我们将讨论如何微调LLMs。
006:评估和调试大语言模型
在本节课中,我们将要学习如何训练或微调一个全新的大语言模型,并重点关注在此过程中的评估与调试方法。上一节我们介绍了通过API使用大语言模型,本节中我们来看看如何从零开始训练或对现有模型进行微调。


😊


从头开始训练大语言模型耗时且成本高昂,评估过程同样复杂且消耗资源。因此,密切监控训练过程并使用检查点来应对意外问题至关重要。
以下是训练过程中的关键监控点:
- 从仪表板获取有价值的信息,仪表板会显示训练进度和各项指标。
- 在需要时,仪表板能帮助你获取模型检查点。
微调方法让你能够以更经济的方式优化大语言模型,即使计算资源有限。但在评估过程中仍需谨慎。根据你希望大语言模型达成的目标,可能需要制定特定的评估策略。
接下来,让我们一起看看具体的代码实现。
我们将展示如何使用Hugging Face高效地在CPU上微调一个语言模型。为此,我们将使用一个名为tiny-stories、拥有3300万参数的小型语言模型。我们将在《龙与地下城》游戏世界的角色背景数据集上微调这个轻量模型。
和往常一样,从导入库和登录开始。然后设置要拉取的模型检查点。
我们将从Hugging Face Hub拉取数据集。观察这个示例,可以看到数据集有两列。text列要求模型生成背景故事,而target列则存放着已生成的角色背景故事。




我们将设置数据集分割,以便进行验证。



在训练模型之前,我们将合并并准备指令和故事,确保它们被分词和填充。我们还会创建标签。

标签与我们的输入完全相同。标签需要向右移动一个位置,因为模型应该预测序列中的下一个词元,这一步将由Hugging Face完成。

现在,让我们尝试生成一个样本来确保一切运行正常。当我们解码输出时,会看到指令后面跟着生成的背景故事。如果一切看起来都没问题,我们就可以继续了。


在进入模型训练之前,让我们先查看数据集中的一个示例,了解其具体样貌。
这里,它提取了角色名Mr. Gail和种族Half-Orc,然后给出了输出故事:“growing up that only half Ork in a small rural town was rough.” 这看起来不错,似乎是一个很好的模型输入。

现在让我们开始模型训练。我们将使用Hugging Face的transformers.Trainer,并演示其与Weights & Biases的简单集成。

我们创建的模型用于因果语言建模,这是一种类似于GPT的自回归语言模型架构,其核心是预测序列中的下一个词。我们将启动一个新的Weights & Biases运行,并将任务类型设置为training。
接下来,我们将定义一些训练参数,例如训练轮数、学习率、权重衰减。关键的是,我们将设置report_to为wandb。这意味着你所有的结果都将流式传输到同一个中央仪表板。这就是开始流式传输指标所需做的全部工作。让我们开始训练模型。

现在,我不想等到训练完成才开始查看结果,所以我会向上滚动到W&B运行记录。我可以点击这个链接来实时查看结果。
在这里,我可以看到指标随时间推移而流入,其中训练损失最让我感兴趣,这是我随时间监控的指标。在调试模型训练运行时,检查损失是否持续下降很有用,你希望看到这条曲线向右下方走。
一些非常大的语言模型可能需要数天甚至数周来训练,因此拥有这样一个可以远程查看的图表非常有帮助。这有助于我们确保模型持续改进,而不是浪费GPU资源。
很好,训练完成了。这是一个非常小的模型,为了效率只训练了一个轮次,所以结果不会完美。如果你有兴趣,我鼓励你尝试改进它们,也许可以通过延长训练时间或调整超参数。
😊
现在训练已完成,让我们从模型生成一些样本。回到笔记本中,我们定义了几个提示词,并用它们为我们的角色生成背景故事。之后,我们创建了一个新表格,针对每个提示词,我们将调用model.generate。我们可以在这里传递各种参数,如top_p或temperature来引导模型。我们将生成的文本添加到表格中,记录它并完成这次运行。
现在让我们在仪表板中查看结果。这里我正在项目页面查看结果,我可以展开那个表格来查看一些样本。
在表格中,我可以查看提示词和一些生成的输出样本。
这个提示词是针对一个名为Froger的角色。生成的内容是:“Fewborn is a small dragon who lives in the woods. His mother was a dragon, a small dragon, a small dragon, a small dragon, large dragon, a small dragon.” 这看起来可能有点卡在“dragon”这个想法上了。
我们有一个Smarty角色。他发生了什么?“He was born in the city of a wealthy merchant. He was a young boy, but he was not a good man.”
😊
最后,我们还有另一个例子,角色Volcano是一个安卓机器人。对于这个角色,输出仅仅是:“the tribe of the tribe of the tribe of the tribe.” 这作为一个背景故事似乎不太理想。
所以你可以看到这个小模型存在一些问题,这是可以理解的,因为我们优化的是速度而非性能。
从这里你可以看到,在训练生成式AI模型时,进行定性评估是多么重要。因为仅仅查看这些消息、这些输出,你就能判断它是否表现良好。
我们鼓励你根据你的具体用例想出可能相关的指标,然后实现它们,并与生成的文本一起记录下来。例如,你可以测量像唯一词数量这样的指标。在这个输出中,我们可以看到它实际上只用了三个词:“the”、“tribe”、“of”。所以这可能不是一个很好的输出。
因此,下次你训练或微调模型时,我们希望你能使用这些工具来更快地获得更好的结果。
😊


本节课中我们一起学习了如何微调一个大语言模型,包括数据准备、模型训练、使用仪表板监控训练过程(特别是训练损失曲线),以及如何对模型生成的结果进行定性评估。我们看到了即使是一个小型模型,通过监控和评估也能发现其生成内容的问题,这强调了在生成式AI开发中持续评估和调试的重要性。
007:06_结论
在本节课中,我们将对《评估和调试生成型人工智能》课程进行总结,回顾所学到的核心技能与工具。
课程概述
恭喜你完成了本课程。现在,你已经掌握了如何对生成式模型进行迭代、如何追踪实验的结果,以及如何分享研究发现。借助这些工具,你的开发过程将变得更加透明和可复现。我迫不及待想看到你的成果。




核心技能回顾
上一节我们介绍了评估生成式AI的具体方法,本节中我们来总结整个课程的核心收获。以下是你在本课程中学到的关键能力:

- 迭代生成式模型:掌握了通过系统化实验来改进模型性能的方法。
- 追踪实验结果:学会了使用工具记录和管理不同实验的输入、输出与评估指标。
- 分享研究发现:理解了如何清晰地呈现和沟通实验过程与结论,促进团队协作。

工具的价值

拥有了上述技能和相应的工具,你现在能够建立一个更高效的开发流程。这个流程的核心优势在于其透明性和可复现性,这对于任何严肃的AI项目都至关重要。

总结
本节课中我们一起学习了《评估和调试生成型人工智能》课程的最终结论。我们回顾了如何迭代模型、追踪实验与分享发现,并明确了这些实践如何使你的开发工作更加透明和可复现。现在,你已经具备了推动生成式AI项目向前发展的坚实基础。

浙公网安备 33010602011771号