TowardsDataScience 2023 博客中文翻译(四十六)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

数据科学 AWS 基础:计算

原文:towardsdatascience.com/aws-essentials-for-data-science-compute-9b4c6e3b46bf

理解和部署 EC2 和 Lambda 服务

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Matt Sosna

·发表于 Towards Data Science ·阅读时间 18 分钟·2023 年 1 月 3 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Nick Owuor (astro.nic.visuals) 提供,来源于 Unsplash

所以你创建了一个很酷的应用程序,并想向全世界展示它。也许它是一个可以生成涂鸦猫咪图片的 AI、一个病毒式 LinkedIn 帖子生成器或一个英语到 RegEx 的翻译器。你希望用户只需点击一个链接,就能立即开始使用你的应用程序,而不是需要下载并在他们的电脑上运行它。

这种“即时交互”需要一个服务器,它接收用户请求(例如,猫咪涂鸦)并提供响应(例如,AI 生成的猫咪图片)。你可以使用个人笔记本电脑,但当它进入睡眠模式或关闭时,它将停止处理请求,而且一个熟练的黑客可能会窃取你的私人数据。更糟糕的是,如果你的计算机尝试同时处理过多的请求,你的硬盘可能会过热!

除非你喜欢被黑客攻击或硬盘过热的笔记本电脑,否则你可能会想要租用云服务器。虽然你失去了一些对物理机器的控制,但你会避免很多你可能不愿意处理的配置和维护。而且如果你愿意多花点钱,你可以轻松租用一台——甚至几台——远比你的笔记本电脑强大的机器。那么我们怎么开始呢?

我们之前覆盖了云计算的高层概述以及存储数据的教程。但云计算的引擎是什么?在这篇最后的文章中,我们将讨论两个计算密集型的亚马逊网络服务。我们将从基础的云构建模块EC2开始,然后转到无服务器计算的Lambda

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Taylor VickUnsplash拍摄

背景

假期季节对于零售商来说是一个反复出现的混乱时刻。例如,第四季度占**惊人的 33–39%**的Macy’sKohl’s年度收入,甚至在夏季的 Prime Day 之后,亚马逊的第四季度仍然约为 31%。这股假日冲动大多在线上发生,转化为更多的用户在商店网站上花费更多的时间

将自己置身于 2005 年 10 月的亚马逊基础设施工程师的角色中,那时互联网泡沫已过去几年,但云计算行业尚未真正起步。你知道你必须做某些事情来应对即将到来的流量洪峰:你最不希望的就是网站崩溃,数百万美元的销售机会溜走,因为沮丧的顾客转向了其他网站。[1]

处理额外负载的一种方法是购买更多计算机。 (确实有早期亚马逊工程师的故事,他们在假期前购买了他们能找到的最强大的服务器,并祈祷一切顺利!) 这些额外的服务器确实应该处理流量激增。但当假期热潮结束时,这些额外的计算资源将会闲置,直到下一个假期季节。[2]

替代方案是以某种方式租用计算资源。理想情况下,资源会弹性地自动地根据你的即时需求增加和减少,而不需要提前猜测。你将抽象化物理硬件,而只需进入一个“资源池”。

亚马逊网络服务(AWS)正是为了应对这些初创互联网的需求而诞生的:动态地访问你所需的计算资源。我们已经介绍过其基础的存储服务:亚马逊简单存储服务(S3),这是一个类似于 Dropbox 的综合数据存储服务。但现在让我们转向亚马逊的基础计算服务:弹性计算云

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

EC2: 弹性计算云

我们可以使用亚马逊 EC2来访问云的基本构建块:虚拟服务器。数据中心充满了服务器,这些服务器被逻辑分区成虚拟服务器,允许多人同时独立使用硬件。

一台服务器可以同时运行天气预报模拟,从多个数据库中获取数据,发送十几个网页的 HTML 等等。重要的是,这台物理服务器对用户来说是抽象的,超出了他们虚拟服务器的配置范围,让他们能够专注于自己的应用。

在 AWS 中,虚拟服务器被称为EC2 实例。EC2 于 2006 年发布,是亚马逊的首批云服务之一,并已成长为Netflix、Pinterest、Lyft 等众多公司技术栈的核心组件。EC2 实例具有模块化和可配置性,允许用户根据需求优化计算、内存、GPU、存储或它们的组合。例如,GPU 优化实例可以用于训练机器学习模型,而存储优化实例则可以托管数据库。

现在我们来创建一个 EC2 实例进行更详细的了解。我们登录到我们的 AWS 账户,然后从服务菜单中导航到 EC2。我们应该会看到类似下面的图像。点击Launch instance按钮并开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

设置

AMI: 亚马逊机器镜像

启动 EC2 实例时,我们首先需要选择亚马逊机器镜像。AMI 指定了我们实例的基本软件配置:操作系统,应用服务器和运行服务器所需的应用程序。AMI 就像Docker 镜像可重用模板,让我们每次都能创建出我们想要的精确环境。

默认的 AMI 配备了优化用于 EC2 的 Linux 内核,系统和服务管理器 systemdGCC 编译器以及其他非常底层的软件。如果我们对如何优化以适应我们的用例有强烈的意见,我们可以创建自己的 AMI。但这是一个入门教程,所以我们就选择默认的 Amazon Linux 2 AMI。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

实例类型

接下来是实例类型,在这里我们选择服务器的硬件。我们不希望偏离t2.micro选项,该选项被免费套餐覆盖。在生产环境中,我们可以决定优化CPU(用于同时运行各种系统操作)、GPU(用于机器学习或图形处理)、存储(用于慢速读写持久数据)、内存(用于快速读写易失性数据)或某种组合。

一旦启动了实例,我们无法更改实例类型,因此请确保你不要意外点击每小时收费 31.21 美元的实例! 仔细检查我们是否选择了t2.micro,然后可以继续下一步。

密钥对

现在我们将创建一对密钥。AWS 使用公钥加密来保护 EC2 实例的登录信息。我们将使用密钥对而不是密码,通过SSH远程登录到我们的实例。

我们将点击创建新密钥对。然后给它起个名字,并保持 RSA 和 .pem 的默认设置。(如果你使用 Windows,请选择 PuTTY。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

一旦我们点击创建密钥对,Amazon 将保存密钥的公钥部分,我们的计算机将下载私钥。确保不要丢失这个 .pem(或 .ppk)文件,因为我们将用它来在远程访问 EC2 实例时进行身份验证。

网络设置

现在我们设置通过互联网访问 EC2 实例的规则。对于这个演示,只需点击选择现有的安全组,然后选择我们的默认 VPC(虚拟私有云)。如果你按照之前的AWS 存储帖子进行了操作,你将已经调整了这个 VPC 的入站和出站访问规则。

配置存储

我们将存储配置保持在默认值,这些值在免费层限制范围内。我们写入实例的任何数据将在演示结束后被删除;如果我们关心数据的持久性,可以点击 Add new volume 来预留一个Amazon Elastic Block Storage (EBS) 卷,并将数据保存在那里。但现在我们还是使用根卷吧。

高级细节

我们将在演示中跳过这一部分。但这里是我们可以指定配置的地方,例如使用按需Spot 实例、关闭和休眠行为、是否需要详细的Amazon CloudWatch 日志等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

charlesdeluvioUnsplash 上的照片

连接到我们的实例

我们的实例将在我们点击 Create 后的几分钟内可用。在 EC2 首页,我们可以点击 Instances 并查看类似下图的内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

现在让我们连接到实例。我们将使用SSH,这是一种在不安全网络(如互联网)上进行安全通信的网络协议。一旦我们通过 SSH 连接到实例,我们将能够像在笔记本电脑的终端上控制机器一样控制它。

首先要做的是 修改实例的安全组以允许入站流量。在我们的实例页面上,我们点击底部的 Security 选项卡,然后点击实例安全组的链接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

在安全组页面,点击 Edit inbound rules,然后点击 Add rule。选择 SSH 作为 Type,然后选择 My IP 作为 Source。最后,点击 Save rules

现在让我们尝试连接到我们的实例。命令是 ssh,后跟公共IPv4 DNS,该信息可以在实例页面找到。你也可以通过 Connect > SSH client 来获取地址。

我们遇到了权限被拒绝的错误,因为我们没有传入私钥。让我们切换到包含私钥的目录,然后再试一次。

到目前为止一切顺利,但随后我们遇到了另一个错误:

错误是我们的私钥具有权限代码 644,这意味着任何人都可以读取该文件。这是新文件的默认访问级别,但 AWS 认为这不够安全:任何拥有你的密钥的人都可能冒充你。

所以我们需要修改文件的隐私设置以增强安全性。为此,我们使用 chmod 来更改文件的读写权限。具体来说,我们将文件更改为 仅允许所有者(我们)读取。即使有人将我们的私钥复制到另一台计算机上,或网络上的其他用户以某种方式找到了密钥,文件也无法打开,因为那个人不是所有者。作为额外的预防措施,我们还移除了写权限。

这个权限级别的 chmod 代码是 400: 所有者只能读取(4),安全组无法读取/写入/执行(0),其他人无法读取/写入/执行(0)。因此,让我们在终端中运行这个命令:

现在当我们尝试连接时,我们成功了:

我们进来了!在光标左侧,我们应该看到类似 [ec2-user@ip-xx-xx-xx-xxx ~]$ 的内容,而之前我们只看到 $。现在让我们运行一些快速命令来探索实例。

Python 已经安装了,这很方便!让我们从 GitHub 下载一个 示例 Python 文件,并在我们的 EC2 实例上运行一些基本计算。我们将使用 curl 从 URL 下载文件,然后传递一些参数给 calculate_mean.py 以获取其平均值。

现在让我们在生成的数据上训练一个随机森林分类器。我们将下载 numpypandasscikit-learn,打开 Python,生成数据,然后创建模型。

我们将首先下载必要的库。

我们现在可以运行 Python,生成数据,训练模型,并做出一些预测。我们将使用 np.random.normal 生成特征,用 np.random.choice 生成标签。

呵呵!你(从技术上讲)在云端训练了一个机器学习模型。既然我们已经达到了 EC2 用例的巅峰(😜),让我们断开 SSH 连接并终止我们的实例。

现在在我们的 EC2 实例页面上,我们可以点击 Instance state > Terminate instance。注意,我们将丢失我们的 Python 库和 calculate_mean.py 文件,因为实例的数据将被清除,以便其他人使用。如果我们想多保留一会儿实例,可以点击 Stop instance

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Ivan DiazUnsplash 提供。

基础之外

所以我们刚刚创建了一个 EC2 实例,从互联网上下载了文件,并运行了一些 Python 代码。虽然这很棒,但我们还没有体验到任何无法在自己的笔记本电脑上运行的东西,而 t2.micro 服务器可能不如我们的笔记本电脑强大。 那我们从 EC2 获得了什么真正的价值?

首先需要注意的是,除了免费套餐之外,EC2 选项有很多种。 如果我们想为研究论文运行模拟,我们可以简单地选择一个比我们笔记本电脑拥有更多 CPU 或 GPU 的 EC2 实例。这将更快完成任务,特别是如果我们没有一台不错的计算机或不能将其所有资源都用于模拟的话。(这也可以防止损坏你自己的笔记本电脑,这一点我在大学里用一个非常低效的 R 脚本时不小心做到了!)

更重要的是,我们需要记住,EC2 实例只是构建块 对于我们的研究模拟,租用两个或三个实例并进行并行计算可能更高效。如果我们使用 EC2 实例来托管我们网站的 Flask API,当流量增长时,我们可以简单地复制实例并添加负载均衡器来分配流量。更好的是,我们可以自动调整 实例的数量以满足需求,让我们可以更多地专注于实际应用。尽管 Q4 对零售商来说仍是一个紧张时期,但借助云计算,它已经变得更加可管理。

所有这些抽象化相较于 2000 年代初期的互联网是一个巨大的进步。然而,有时即使是虚拟服务器也可能不够灵活或可扩展以满足我们的用例。在这种情况下,我们可能需要像Amazon Lambda这样的“无服务器”选项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

Lambda

什么时候 EC2 不是正确的选择?

使用 EC2,我们会得到一个完整的虚拟服务器。AWS 在定义这个服务器的外观方面给了我们惊人的灵活性,让我们可以调整每一个硬件和软件细节。比如,本帖的 EC2 设置部分的简单演示就有几十行!

这种灵活性意味着我们可以找到一些 EC2 实例的组合,以满足我们可以想象的任何任务。但这就将责任落在我们身上,以确保我们正确配置实例。 如果我们只执行一个任务,比如训练一个机器学习模型,这种配置可能很简单。但当我们同时处理多个实例时,优化资源使用就变得更加具有挑战性,尤其是当我们有多种实例类型时。如果我们的应用程序运行不畅,我们是应该增加更多实例来托管数据库、从数据库中获取数据,还是在前端展示数据?随着我们应用程序的流量变化,这种情况会如何变化?

另一个问题是,我们的实例只有在运行时才能访问。 就像我们的笔记本电脑在睡眠或关闭时不会响应输入一样,除非 EC2 实例正在运行 — 而且会对其使用收费。 如果我们不断向实例发送请求,这没问题。但如果我们预计会偶尔使用实例,那么在我们不使用它时保持实例运行可能会很昂贵且效率低下。

什么是 Lambda?

在 2014 年,亚马逊发布了Lambda,将云计算的抽象推向了一个新水平,提供了无服务器计算服务。与 EC2 相比,我们对运行代码的机器没有任何信息。我们的唯一可调参数是代码允许使用的内存量。

Lambda 响应事件执行代码,并自动管理底层计算资源。如果我们的代码没有在机器上主动运行,我们不会支付任何费用。这非常适合像将用户操作写入数据库从 ML 模型生成预测这样的单次操作,但我们甚至可以构建一个基于微服务的 Web 应用实时流数据处理器

我们在 Lambda 中的工作流程将涉及设置函数,然后从其他服务中触发这些函数。不需要担心配置硬件、确保其安全补丁是最新的,并有效利用资源。

唯一的主要缺点是因为我们没有专用的虚拟服务器来等待请求,所以在第一次触发函数时会有短暂的延迟,因为 Lambda 需要找到并预留所需的资源。将我们的应用程序分散到多个 Lambda 函数中,而不是一个巨大的 EC2 实例,也可能显著增加应用程序的复杂性。但这些通常是为了完全抽象化硬件所需支付的小代价。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Michael Dziedzic拍摄,来源于Unsplash

创建一个函数

让我们通过设置一个返回一组数字平均值的函数来探索 Lambda。在 AWS 控制台中,我们首先导航到 Lambda 首页。然后点击大橙色的 Create function 按钮。我们将选择“从头开始创建”选项,然后给我们的函数起个名字(calculate_mean)并选择 Python 3.9 运行时。接着我们向下滚动并点击 Create function

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截屏

我们随后被带到了 Lambda 函数页面。向下滚动到 Code 标签,我们可以看到为我们的函数提供的基本模板:

Test 标签中,我们可以看到一个简单的 JSON 输入,供我们测试函数使用。

我们需要为我们的 calculate_mean 函数更改这两个内容。首先更改测试输入为下面的数字数组。给你的测试命名(例如 my_array),然后点击 保存。你应该会看到顶部的绿色横幅,上面写着 “测试事件 my_array 已成功保存。”

现在让我们回到 Lambda 函数,并将其更改为下面的代码。具体而言,我们去掉 json 导入,从 event 中提取 nums 字段,并将返回的 body 字段更改为计算均值。在生产环境中,我们需要添加对空数组、非数字数组等的错误处理,但现在这样就足够了。[3]

保存你的函数(⌘ + s,或 文件 > 保存),然后点击 部署。你应该会看到一条绿色横幅,上面写着 “成功更新了函数 calculate_mean*。”* 现在点击 测试,应该会生成一些日志,如下所示。重要的是响应的 body 字段应该是你测试文件中数字数组的均值(例如我们的是 3,均值为 1 到 5)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

现在让我们从 AWS CLI 尝试一下。(如果你还没有下载 CLI,可以参考 这些步骤。)打开一个终端窗口,创建一个输入 JSON 文件,并将文件发送到你的 Lambda 函数。Lambda 会将响应返回为一个文件,这里是 output.json,然后我们可以查看。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Sergei Wing 提供,来源于 Unsplash

通过 API Gateway 触发

恭喜,我们有了一个 Lambda 函数!但我们只能在 Lambda 控制台和个人计算机上真正与这个函数交互。我们真正想要的是 能够从任何地方触发这个函数。所以回到浏览器,让我们滚动到 calculate_mean 函数页面的顶部,在那里可以看到我们函数的触发器(和目标)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

当我们点击 添加触发器 时,我们会看到一个下拉菜单,其中包含大量服务,从 AlexaAWS IoTDynamoDB,到非 AWS 服务如 Auth0DatadogShopify。例如,我们可以让 Auth0 触发一个 Lambda 函数,在用户登录时写入数据库,或者 Amazon SNS 在每次新文件上传到我们的 S3 桶时发送通知。

让我们选择 API Gateway 为我们的函数创建一个 HTTP 端点。这将允许我们从任何可以发送 HTTP 请求的代码中调用我们的 Lambda 函数。我们将选择 创建一个新的 API,选择 HTTP API 作为 API 类型,然后选择 开放 作为安全性设置。然后点击 添加

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

我们现在应该看到 API Gateway 作为我们 calculate_mean 函数的触发器。端点应该类似于 [xx.execute-api.us-east-1.amazonaws.com/default/calculate_mean](https://xx.execute-api.us-east-1.amazonaws.com/default/calculate_mean.).

如果我们点击链接,我们会看到一个只显示“内部服务器错误”的页面。这是因为我们的 Lambda 函数配置为期望一个包含 nums 字段的 JSON,但我们浏览器的 HTTP 请求没有这个字段。传递此字段的一种简单方法是作为 查询字符串参数,其中 URL 本身 包含 nums 和数值数组。因此,应该是 /default/calculate_mean?nums=1,2,3,而不是 /default/calculate_mean

所以让我们修改我们的 Lambda 函数以接受 URL 参数。我们将添加一个 try-except 块,其中我们首先尝试从查询字符串 (event['queryStringParameters']) 中提取 nums 参数。我们将字符串转换为字符串列表,然后将每个数字转换为浮点数。如果用户传递 JSON(如我们之前所做),我们只需从 event 对象中提取 nums 数组。

不要忘记保存函数并部署它。等待几秒钟,然后将你的 API 端点复制到浏览器新标签页的 URL 地址栏中。将 ?nums=1,2,3 添加到 URL 末尾,然后按回车键。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

太棒了!让我们再尝试最后一件事。在本地机器(或你的 EC2,如果你想要炫耀的话)上打开一个 Python 窗口,并运行以下代码:

我们看到我们甚至可以通过 URL 字符串传递浮点数到我们的函数,并且我们能够从任何地方访问它。恭喜!🎉

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sarah BrownUnsplash 提供的照片

清理

我们的演示结束了,因此让我们确保删除我们创建的所有内容,以避免产生费用。我们应该从我们的 API 端点开始,该端点目前对互联网用户开放——如果有人猜到我们的 URL,他们可能会开始每秒发送数百或数千个请求,而这些请求我们将需要为 AWS 支付费用。

所以让我们在 AWS 控制台中导航到 API Gateway 并删除我们的 API 端点。你点击 calculate_mean-API 旁边的按钮,然后选择 操作 > 删除

接下来是 Lambda 函数。导航到Lambda在 AWS 控制台中,并删除该函数。

最后,如果你还没做,请终止你的 EC2 实例。导航到EC2在控制台中,如果你还没有停止实例,请先停止,然后终止它。你还可以进入你的安全组,将你的 IP 地址从入站流量规则中移除。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由伊恩·斯托弗提供,来自Unsplash

结论

在这篇文章中,我们探讨了两种计算的亚马逊网络服务:EC2Lambda。我们看到Amazon EC2 让我们可以预留一个具有我们所需精确配置的虚拟服务器,根据我们的使用案例调整资源。我们创建了一个服务器,并在修改了私钥的读取权限后通过 SSH 连接到服务器。然后,我们从互联网下载了文件,运行了一个 Python 脚本,并在一些生成的数据上训练了一个分类器。

我们随后将 EC2 与AWS Lambda,亚马逊的“无服务器”计算方法进行了对比。我们创建了一个用于计算数字数组平均值的函数,并从控制台和 AWS CLI 中调用了该函数。我们还添加了 AWS API Gateway 触发器,修改了函数以接受查询字符串参数,并从浏览器和本地 Python 环境中调用了该函数。

在我们的介绍、存储和计算文章中,我们使用了七项基本服务:IAM、S3、RDS、DynamoDB、EC2、Lambda 和 API Gateway。虽然亚马逊提供了超过 200 项服务,许多服务建立在这些核心服务之上。通过我们在这一系列中获得的知识,我们已经做好了充分准备,可以开始利用云服务满足我们的需求。

感谢阅读!

祝好,

马特

脚注

1. 背景

在研究这篇文章时,我发现了很多关于流行网站在不可响应或不可用时的高成本的有趣统计数据。以下是一些更有趣的统计数据:

  • 淘宝,一个中国在线购物平台,在 2021 年双十一期间经历了 20 分钟的崩溃,这可能导致了数十亿美元的销售损失。

  • 加载时间在两秒内的网页具有平均跳出率为 9%。当网页加载时间达到五秒时,这个数字跃升到 38%

2. 背景

对于处于超高速增长期的早期亚马逊来说,节假日期间购买的额外计算资源最终只是满足公司成长后的正常业务需求。但对大多数公司来说,这些额外的计算资源在大部分时间里将成为一种负担。

顺便提一下,有一个常见的说法是 AWS 从亚马逊试图利用这些“额外的计算资源”中分拆出来的。他们有这么多未使用的服务器,那么为什么不让客户使用呢?我对这个说法的最喜欢的反驳是,当下一年的 Q4 到来时,亚马逊显然不能仅仅终止所有这些客户以收回他们的服务器!亚马逊将不得不再次购买大量服务器。

3. 创建函数

我们可以讨论错误处理是否应该在 Lambda 函数内部还是在调用函数的地方。两者各有利弊:将错误处理添加到函数中意味着检查集中在一个地方,减少了与函数交互的开发者的心理负担。但检查会让函数变得更重——它们需要在函数每次被调用时都运行。

我们可以通过让调用者保证有效输入来保持函数的轻量化。但强制执行这一责任是具有挑战性的,特别是当代码库很大而开发者不一定拥有系统的完整上下文时。这也意味着没有标准化的检查内容以及如何将错误反馈给用户。

一个中间选项可能是由一个 Lambda 函数来执行检查,然后将有效输入传递给实际函数。这会增加整体系统的复杂性,但它可以减少调用者的心理负担,并保持函数的轻量化。最终,合适的方法取决于你的使用场景。

《Azure 机器学习工作室简介》

原文:towardsdatascience.com/azure-machine-learning-studio-a21abfc3b1aa?source=collection_archive---------13-----------------------#2023-01-16

模型创建、部署和评分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Jonathan Bogerd

·

关注 发表在 Towards Data Science ·8 分钟阅读·2023 年 1 月 16 日

在本文中,我们将涵盖在 Azure 机器学习工作室中创建、部署和使用模型所需的所有步骤。在之前的系列中,我已经介绍过这个主题。然而,在过去一年中,Azure 机器学习工作室(AML Studio)进行了许多更新,包括 Python SDK 的新版本。因此,需要对这个系列进行更新。本文的结构如下:首先,我们将介绍 AML Studio 的概况,然后创建计算资源和环境。第三,我们将创建一个数据存储并上传数据。接下来,在本文的剩余部分,我们将创建模型、部署模型并进行测试。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Ricardo Resende拍摄的照片,来源于Unsplash

概述介绍

Azure Machine Learning Studio 是微软 Azure 平台上的机器学习套件。它可以用于创建、部署和使用模型,包括数据和模型的版本控制,并且可以与低代码和 SDK 选项一起使用。在本文中,我们将讨论 Python SDK(V2),但也请务必查看 AML Studio 的低代码和 AutoML 功能。

AML Studio 包含用于创建脚本的笔记本,其中可以使用 SDK 来创建计算、环境和模型。要运行笔记本,我们首先需要一个计算,你可以通过计算选项卡创建。我们还将展示如何使用 SDK 创建新的计算,但你首先需要一个计算来运行所需的命令。笔记本可以直接在 AML Studio 中创建和更改,或者你可以连接到 Visual Studio Code 工作区(如果你愿意)。有关如何做到这一点的详细信息,请参见此处

在本文中,我们将在 AML Studio 中创建笔记本。在开始之前,有一个非常方便的快捷键可以运行笔记本中的所有单元格:Alt+R。在我们可以在工作区中创建任何内容之前,我们首先需要进行身份验证以获取工作区句柄。这可以通过运行以下脚本来完成:

这是我们在本文中创建的所有其他笔记本所必需的,因此请始终先运行此命令。现在,让我们开始创建一个计算。

创建计算

可以使用 UI 创建计算,确保创建具有所需规格的计算实例。然后可以使用该计算运行例如笔记本。以下代码片段可以用来使用 Python SDK 创建新的计算实例:

如果你需要多个节点,你还可以创建一个计算集群。实现这一点的代码略有不同,下面有示例代码:

创建环境

为了训练和部署模型,我们还需要一个指定所需安装包的环境。你还可以提供包的版本,以确保代码按预期运行,并且只有在你首先测试了这些包后才会更新它们。AML Studio 中的环境与例如 Conda 环境非常相似。要创建它们,我们将首先创建一个名为‘dependencies’的子目录。然后我们将创建一个用于训练和部署模型的.yml 文件。完成后,我们需要触发实际环境的创建。AML Studio 中的环境可以基于微软维护的预定义镜像。详细说明请参见此处

以下代码在 AML Studio 中创建并注册一个环境:

添加数据

在这篇文章中,我们将使用来自 Kaggle 的数据来训练模型。我们使用的数据集可以在Ahsan Raza 提供的这里找到,并且在 Creative Commons 4.0 许可证下提供。

任务是预测客户是否会取消预订。为了使用这个数据集,我们首先需要将其上传到连接到 AML 工作区的 blob 存储中的容器。一旦完成,我们可以通过在 AML Studio 中选择 Data 选项卡来创建一个数据存储区(如果尚未创建)。在那里,通过 UI 注册数据存储区。现在,我们可以通过使用新的 AzureMachineLearningFileSystem 类来访问文件。为此,需要数据集的完整 URI,可以通过选择数据存储区,选择文件并复制 URI 来获得。

默认情况下,azureml-fsspec 包未安装,因此在使用之前,我们需要通过魔法命令 %pip 安装它。用于打开文件的代码如下:

创建模型

为了创建模型,我们需要创建一个包含训练模型逻辑的 Main.py 文件。为此,我们首先创建一个目录来存储该文件。接下来,我们将编写主文件,类似于我们为 Environment 编写 .yml 文件的方式。然而,请确保在提交为作业之前先测试所有组件。这将节省你很多时间,因为创建作业的时间相当长,大约 10 分钟。

首先,我们需要一种方法来向训练脚本添加参数。我们将使用 argparse 模块来实现这一点。为了日志记录,我们将使用 mlflow 模块。autolog 方法使得不需要编写评分脚本,因为这会自动完成。处理好这些后,让我们构建实际的模型吧!

我们将使用一个非常基础的 sklearn 设置来创建模型。如果你还没有安装 sklearn,请确保安装。首先,我们将数据集分为训练集和测试集。由于这仅仅是一个展示 AML Studio 的示例,我们不会使用验证集或复杂模型。数据集包含数值特征和分类特征。因此,我们将使用 sklearn 的 OneHotEncoder 和 StandardScaler。我们将这些保存到一个包含逻辑回归模型的管道中。这样创建管道可以确保我们对训练数据和测试数据应用完全相同的转换,这些数据稍后会发送到模型中。在拟合模型和变换器之后,我们保存并注册模型。这将产生如下代码:

现在我们有了一个 Main.py 文件,我们需要运行一个命令来执行该文件并注册模型。一个命令包含多个元素,并结合了我们迄今为止采取的所有步骤。首先,我们在字典中提供 Main.py 文件中所有变量的输入。接下来,我们指定代码的位置和实际命令。我们需要一个可以运行此代码的环境,因此我们指定了之前创建的环境。计算也是如此。命令的最后两个部分是实验和显示名称,用于 AML Studio。在触发此作业后,将提供一个包含详细页面的链接,在该页面中你可以跟踪模型的进展。最重要的是,你还可以查看详细的日志,以调试你遇到的任何错误。

模型部署

现在我们已经创建了一个模型,我们需要将模型部署到一个端点才能使用它。为此,我们需要执行两个步骤。首先,我们创建一个端点,其次,我们将模型部署到该端点。在本文中,我们将创建一个在线端点。如果你需要处理大量数据,创建一个批量端点可能更合适。执行这个过程非常相似,关于批量端点的更多细节可以在这里找到。

创建在线端点非常简单。你需要指定一个名称,并可以选择认证到端点的方法。提供的两个选项是密钥和 aml_token。主要区别在于密钥不会过期,而令牌会。在此示例中,我们将使用密钥。可以向端点添加标签,以提供额外的信息,例如所使用的数据和模型类型。标签需要以字典形式提供。下面是创建在线端点的代码。

在创建端点之后(这需要几分钟时间),我们需要将模型部署到该端点。首先,我们通过名称检索模型的最新版本。然后,我们需要指定部署配置。请注意,instance_type 设置了运行端点所用的计算类型,并且必须从可用的实例列表中选择。指定配置后,我们需要运行部署。这同样需要几分钟才能完成。

评分

在创建和部署模型后,是时候测试它了!我们可以将请求文件发送到端点,并接收预测。可以在 Endpoint 选项卡中找到从 AML Studio 外部执行此操作的代码和密钥。那里提供了 C#、Python 和 R 的模型消费代码。然而,让我们首先直接从 AML Studio 笔记本测试模型。为此,我们创建一个包含 input_data 的 JSON 文件。它需要三个值。首先,我们在列表中指定列。使用与模型训练期间完全相同的列名非常重要。接下来,我们指定一个索引列表,计算所需的预测数量。最后,我们创建一个列表,每个数据输入一个列表。数据输入的顺序必须与列列表中的顺序一致。下面您可以找到我们创建的模型的示例和将此文件发送到端点所需的代码。如果您不再需要端点,请务必删除它并终止计算实例。执行此操作的代码在同一示例中提供,并在最后一行注释掉。

结论

在本文中,我们使用 Azure 机器学习 Studio 创建了计算、环境和模型。然后,我们部署了模型,并使用示例数据进行了测试。再次提醒,如果您不再需要端点,请不要忘记删除它并终止计算实例。现在就到这里,祝您使用 AML Studio 进行数据科学项目愉快!

来源

[## 训练机器学习模型 - Azure 机器学习

适用于:Azure CLI ml 扩展 v2(当前) Python SDK azure-ai-ml v2(当前)要使用 SDK 信息,请安装…

learn.microsoft.com](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-train-model?tabs=python&source=post_page-----a21abfc3b1aa--------------------------------) [## 在互动开发期间从 Azure 云存储访问数据 - Azure 机器学习

适用于:Python SDK azure-ai-ml v2(当前)通常,机器学习项目的开始涉及…

learn.microsoft.com](https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-data-interactive?tabs=adls&source=post_page-----a21abfc3b1aa--------------------------------) [## 训练 scikit-learn 机器学习模型(v2) - Azure 机器学习

适用于:Python SDK azure-ai-ml v2(当前)在本文中,了解如何运行您的 scikit-learn 训练脚本…

learn.microsoft.com

基础回顾,第二部分:梯度下降

原文:towardsdatascience.com/back-to-basics-part-dos-linear-regression-cost-function-and-gradient-descent-e3d7d05c56fd

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Shreya Rao

·发布于 Towards Data Science ·阅读时间 11 分钟·2023 年 2 月 4 日

欢迎来到我们的基础回顾系列的第二部分。在 第一部分中,我们讲解了如何使用线性回归和成本函数来为我们的房价数据找到最佳拟合线。然而,我们也看到测试多个截距值可能既繁琐又低效。在第二部分中,我们将深入探讨梯度下降,这是一种强大的技术,可以帮助我们找到完美的截距并优化我们的模型。我们将探讨其背后的数学原理,并看看它如何应用于我们的线性回归问题。

梯度下降是一种强大的优化算法,它旨在快速高效地找到曲线的最小点。最好的可视化方式是想象你站在山顶,山谷里有一个装满金币的宝箱等着你。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,山谷的确切位置是未知的,因为外面非常黑暗,你什么也看不见。此外,你希望在其他人之前到达山谷(因为你想独占所有的宝藏)。梯度下降帮助你导航地形,并高效而迅速地到达这个最佳点。在每个点,它会告诉你该走多少步以及需要朝哪个方向前进。

同样,通过使用算法制定的步骤,梯度下降可以应用到我们的线性回归问题中。为了可视化找到最小值的过程,让我们绘制MSE曲线。我们已经知道曲线的方程是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

曲线方程是用于计算均方误差(MSE)的方程

从上一篇文章中,我们知道我们问题中的MSE方程是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们放大一点,就会看到一个MSE曲线(类似于我们的谷底)可以通过将一堆截距值代入上述方程来找到。所以让我们代入 10,000 个截距值,得到如下曲线:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实际上,我们并不知道 MSE 曲线的样子

目标是达到这个MSE曲线的底部,我们可以通过以下步骤实现:

步骤 1:从一个随机的截距值初始猜测开始

在这种情况下,假设我们对截距值的初始猜测是 0。

步骤 2:计算此点 MSE 曲线的梯度

曲线在某一点的梯度由该点的切线表示(这是说该直线仅在该点接触曲线的一种方式)。例如,在点 A,当截距等于 0 时,MSE曲线的梯度可以由红色切线表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当截距 = 0 时,MSE 曲线的梯度

为了确定梯度的值,我们运用微积分知识。具体来说,梯度等于曲线对截距的导数,这在给定点上表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:如果你不熟悉导数,我建议观看这个Khan Academy 视频。否则,你可以略过下一部分,仍然能够跟随文章的其余内容。

我们计算MSE 曲线的导数如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在为了找到点 A 处的梯度,我们将点 A 处的截距值代入上述方程中。由于截距 = 0,点 A 处的导数为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以当截距 = 0 时,梯度 = -190

注意: 当我们接近最优值时,梯度值接近零。在最优值处,梯度等于零。相反,当我们离最优值越远,梯度就越大。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从中我们可以推断步长应与梯度相关,因为它告诉我们是采取小步还是大步。这意味着,当曲线的梯度接近 0 时,我们应采取小步,因为我们接近最优值。如果梯度较大,则我们应采取较大的步伐,以更快地达到最优值。

注意: 如果我们迈出一个超大的步伐,可能会跳过最佳点。所以我们需要小心。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 3:使用梯度和学习率计算步长,并更新截距值

由于我们看到 步长梯度 彼此成正比,步长梯度 乘以一个预定的常数值来确定,这个常数值称为 学习率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

学习率 控制 步长 的大小,并确保步伐既不太大也不太小。

实际上,学习率通常是一个小的正数,≤ 0.001。但对于我们的问题,我们将其设置为 0.1。

所以当截距为 0 时:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基于我们上面计算的 步长,我们使用以下等效公式更新 截距(即改变我们当前位置):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了找到这一步中的新 截距,我们代入相关值……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…并发现新的 截距 = 19。

现在将这个值代入 MSE 方程中,我们发现当 截距 为 19 时,MSE = 8064.095。在一次大的步骤中,我们更接近了我们的最佳值,并降低了 MSE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

即使我们查看图表,我们也能看到新截距为 19 的直线比旧截距为 0 的直线更好地拟合了数据:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 4:重复步骤 2-3

我们使用更新后的 截距 值重复步骤 2 和 3。

例如,由于此迭代中的新 截距 值为 19,按照 步骤 2,我们将计算该新点的梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们发现 MSE 曲线在截距值 19 处的 梯度 为 -152(如下图中红色切线所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,按照 步骤 3,我们来计算 步长

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随后,更新 截距 值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们可以将之前截距为 19 的直线与新的截距为 34.2 的直线进行比较……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…并且我们可以看到新的直线更好地拟合了数据。

总体而言,MSE 正在变小……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…而我们的步长正在变得越来越小:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们反复进行这个过程,直到我们收敛到最佳解决方案:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们向曲线的最小点推进时,我们观察到步长变得越来越小。在 13 步之后,梯度下降算法估计截距值为 95。如果我们有一个水晶球,这将被确认作为MSE曲线的最小点。很明显,这种方法比我们在上一篇文章中看到的蛮力方法更有效。

现在我们已经有了截距的最佳值,线性回归模型是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线性回归线如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最佳拟合线的截距为 95,斜率为 0.069

最后,回到我们朋友马克的问题——他应该以多少价格出售他那 2400 平方英尺的房子?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将 2400 平方英尺的房屋大小代入上述方程……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…瞧。我们可以告诉我们不必要担心的朋友马克,根据他所在社区的 3 栋房子,他应该将他的房子出售价格定在约$260,600。

现在我们对这些概念有了扎实的理解,让我们进行一个简短的问答环节,解答任何悬而未决的问题。

为什么找出梯度实际上有效?

为了说明这一点,考虑一个场景,我们尝试达到曲线 C 的最小点,记作x**。我们当前在点 A,位于x*的左侧:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们在点 A 对曲线关于x求导,记作dC(x)/dx,我们会得到一个负值(这意味着梯度向下倾斜)。我们还观察到,需要向右移动才能到达x**。因此,我们需要增加x以到达最小x*。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

红线,或称梯度,向下倾斜 => 负梯度

由于dC(x)/dx是负值,x-𝛂dC(x)/dx将大于x*,因此朝着*x**移动。

类似地,如果我们在点 A,位于最小点x的右侧,则我们得到一个正的梯度梯度向上倾斜),dC(x)/dx

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

红线,或称梯度,向上倾斜 => 正梯度

因此x-𝛂dC(x)/dx将小于x*,从而朝着*x**移动。

梯度下降法如何知道何时停止?

步长非常接近 0 时,梯度下降会停止。如前所述,在最小点处,梯度为 0,并且随着我们接近最小点,梯度也会接近 0。因此,当某一点的梯度接近 0 或在最小点附近时,步长也会接近 0,这表明算法已经达到了最优解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们接近最小点时,梯度接近 0,随后,步长接近 0。

实际上,最小步长 = 0.001 或更小。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

话虽如此,梯度下降还包括一个在放弃之前所进行的最大步数限制,称为最大步数

实际上,最大步数 = 1000 或更大。

即使步长大于最小步长,如果已经进行了超过最大步数的迭代,梯度下降也会停止。

如果最小点更难以识别怎么办?

直到现在,我们一直在处理容易识别最小点的曲线(这些曲线被称为凸性曲线)。但如果我们遇到一条不那么美观的曲线(技术上称为非凸性曲线),并且它看起来像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里,我们可以看到点 B 是全局最小值(实际最小值),而点 A 和 C 是局部最小值(可能被误认为是全局最小值的点)。因此,如果一个函数有多个局部最小值和一个全局最小值,并不保证梯度下降能够找到全局最小值。此外,它找到哪个局部最小值将取决于初始猜测的位置(如步骤 1 中所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以上述非凸性曲线为例,如果初始猜测位于 A 区块或 C 区块,梯度下降会声明最小点位于局部最小值 A 或 C,实际上它位于 B。只有当初始猜测在 B 区块时,算法才会找到全局最小值 B。

现在的问题是——我们如何做出一个好的初始猜测?

简单的答案: 试错法。有点。

不那么简单的答案: 从上图来看,如果我们的* x* 最小猜测值为 0,因为它位于 A 区块,这会导致局部最小值 A。因此,如你所见,0 在大多数情况下可能不是一个好的初始猜测。一个常见的做法是在所有可能的 x 值范围内应用均匀分布的随机函数。此外,如果可行,运行算法并比较不同初始猜测的结果可以提供关于猜测是否存在显著差异的见解。这有助于更有效地识别全局最小值。

好了,我们快到了。最后一个问题。

如果我们尝试找到多个最佳值怎么办?

直到现在,我们只关注找到最佳的截距值,因为我们神奇地知道线性回归的slope值是 0.069。但是,如果没有水晶球,不知道最佳的slope值怎么办?那么我们需要同时优化斜率和截距值,分别表示为x₀x₁

为了做到这一点,我们必须使用偏导数,而不仅仅是导数。

注意:偏导数的计算方式与普通导数相同,但由于我们有多个变量需要优化,因此表示方式有所不同。要了解更多信息,请阅读这篇文章或观看这个视频

不过,这个过程与优化单一值的过程相对类似。成本函数(如均方误差(MSE))仍然需要定义,并且梯度下降算法必须应用,但需要额外的步骤来求解 x₀和 x₁的偏导数。

步骤 1:对 x₀和 x₁进行初始猜测

步骤 2:在这些点上找到关于 x₀和 x₁的偏导数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 3:根据偏导数和学习率同时更新 x₀和 x₁

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 4:重复步骤 2–3,直到达到最大步数或步长小于最小步长

我们可以将这些步骤推广到 3、4,甚至 100 个值进行优化。

总之,梯度下降是一种强大的优化算法,可以高效地帮助我们达到最优值。它可以应用于许多其他优化问题,是数据科学家必备的基本工具。

更新: 第三部分:逻辑回归 也已经上线了!

一如既往,欢迎通过LinkedIn与我联系,或通过shreya.statistics@gmail.com发送电子邮件,提出问题或建议任何其他您希望说明的算法!

回到基础,第三部分:逻辑回归

原文:towardsdatascience.com/back-to-basics-part-tres-logistic-regression-e309de76bd66

一本关于逻辑回归的图示指南,包括代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Shreya Rao

·发表于 Towards Data Science ·阅读时间 8 分钟·2023 年 3 月 2 日

欢迎回到我们回到基础系列的最终篇,在这一篇中,我们将深入探讨另一种基础机器学习算法:逻辑回归。在之前的两篇文章中,我们帮助我们的朋友 Mark 使用 线性回归 和 梯度下降 确定了他 2400 平方英尺房子的理想售价。

今天,Mark 再次向我们求助。他住在一个高档社区,他认为某些尺寸以下的房子不会售出,他担心自己的房子也可能售不出去。他请我们帮助他确定他的房子是否可能售出。

这是逻辑回归发挥作用的地方。

逻辑回归是一种预测二元结果概率的算法,例如预测房子是否会售出。与线性回归不同,逻辑回归使用 0%到 100%的范围来预测概率。请注意线性回归模型和逻辑回归模型之间预测的区别:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们更深入地探讨逻辑回归如何通过确定不同大小的房子的销售概率来工作。

我们再次通过收集关于 Mark 所在社区的房屋大小的数据,并查看这些房屋是否售出,来开始我们的过程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在让我们绘制这些点:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

与其将图表的结果表示为二元输出,不如使用概率来表示,因为这是我们试图预测的量。

我们将 100%的概率表示为 1,将 0%的概率表示为 0

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在我们上一篇文章中,我们学习了线性回归及其将直线拟合到数据的能力。但它能否用于我们的这个问题,其中期望的输出是一个概率?让我们通过尝试使用线性回归拟合一条直线来找出答案。

我们知道最佳拟合直线的公式是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过按照线性回归中概述的步骤,我们可以获得β₀和β₁的最佳值,从而得到最佳拟合的直线。假设我们已经完成了这些步骤,让我们看看我们获得的直线:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

根据这条直线,我们可以看到一栋面积稍低于 2700 平方英尺的房子被预测有 100%的概率出售:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

……而一栋 2200 平方英尺的房子被预测有 0%的出售概率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

……而一栋 2300 平方英尺的房子被预测有大约 20%的出售概率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好了,到目前为止一切顺利。但如果我们有一栋面积为 2800 平方英尺的房子呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

嗯……概率超过 100%是什么意思?这样的房子会被预测以 150%的概率出售吗?

奇怪。那一栋 2100 平方英尺的房子呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好吧,很明显我们遇到了一个问题,因为一个 2100 平方英尺房子的预测概率似乎是负值。这显然是没有意义的,这表明使用标准线性回归直线存在问题。

我们知道,概率的范围是从 0 到 1,我们不能超出这个范围。所以我们需要找到一种方法来将预测输出限制在这个范围内。

为了解决这个问题,我们可以通过一个非常酷的机器——sigmoid 函数,来处理我们的线性回归方程。这个机器将我们的预测值转换到 0 和 1 之间。我们将我们的 z 值(其中 z = β₀ + β₁size)输入到机器中……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

……然后出现了一个看起来很高级的新方程,它将符合我们的概率约束。

注意:输出中的e是一个常数值,大约等于 2.718。

一种更数学化的方式来表示sigmoid 函数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们绘制这个公式,我们会看到 sigmoid 函数将直线挤压成一个 S 形曲线,限制在 0 和 1 之间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于所有数学爱好者的可选说明:你可能在想我们为什么以及如何使用 sigmoid 函数来获得期望的输出。让我们来详细解释一下。

我们开始时错误地假设使用线性回归公式会给我们所需的概率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个假设的问题在于(β₀ + β₁size)的范围是(-∞,+∞),而 p 的范围是[0,1]。所以我们需要找到一个范围与(β₀ + β₁size)相匹配的值。

为了解决这个问题,我们可以将直线等同于“对数几率”(观看这个视频以更好地理解对数几率),因为我们知道对数几率的范围是(-∞,+∞)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

既然我们完成了这个步骤,只需重新排列这个方程,以找到p值应该等于多少。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们知道如何修改线性回归线以适应我们的输出约束,我们可以回到最初的问题。

我们需要为我们的数据集确定最佳曲线。为此,我们需要确定β₀和β₁的最佳值(因为这些是预测概率方程中会改变曲线形状的唯一值)。

类似于线性回归,我们将利用一个成本函数和梯度下降算法来获取这些系数的合适值。然而,关键区别在于我们不会使用均方误差成本函数,而是使用一个称为对数损失的不同成本函数,我们将在稍后深入探讨。

假设我们使用梯度下降和对数损失成本(使用这些步骤)发现我们的最佳值为β₀ = -120.6 和β₁ = 0.051,那么我们预测的概率方程将是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对应的最佳曲线是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有了这个新曲线,我们现在可以解决马克的问题。通过观察,我们可以看到一个大小为 2400 平方英尺的房子……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…的预测概率大约为 78%。因此,我们可以告诉马克不必担心,因为他的房子很可能会卖出去。

我们可以通过开发一个分类算法来进一步提升我们的方法。分类算法通常用于机器学习中,将数据分类到不同类别。在我们的情况下,我们有两个类别:会卖出的房子和不会卖出的房子。

要开发分类算法,我们需要定义一个阈值概率。这个阈值概率将预测的概率分为两个类别,“是的,房屋会出售”和“不是,房屋不会出售”。通常,50%(或 0.5)被用作阈值。

如果对房屋面积的预测概率超过 50%,它将被分类为“会出售”,如果低于 50%,则被分类为“不会出售”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就是这样。这就是我们如何使用逻辑回归来解决问题。现在让我们理解我们用来找到逻辑回归最优值的成本函数。

成本函数

在线性回归中,成本是基于直线与数据点之间的偏差。而在逻辑回归中,成本函数取决于我们的预测与实际数据之间的偏差,考虑到我们处理的是概率

如果我们在逻辑回归中使用了MSE成本函数(就像我们在线性回归中所做的那样),我们将得到一个非凸(一种不那么漂亮的曲线,不能有效用于梯度下降难以优化的成本函数曲线。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如你可能从我们的梯度下降讨论中记得的那样,优化一个(即具有明显最小点的曲线)曲线比优化一个非凸曲线要容易得多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了实现一个凸的成本函数曲线,我们使用一个称为Log Loss的成本函数。

要详细解析Log Loss成本函数,我们需要为房屋实际出售(y=1)和未出售(y=0)分别定义成本。

如果y = 1且我们预测为 1(即,100%概率出售),则没有惩罚。然而,如果我们预测为 0(即,0%概率未出售),则会受到严重惩罚。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样地,如果y = 0且我们预测房屋出售的概率很高,我们应受到严重惩罚;如果我们预测房屋出售的概率很低,则应受到较低的惩罚。偏差越大,成本越高。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要计算我们数据集中所有房屋的成本,我们可以像这样对所有单个预测的成本进行平均:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过巧妙地重写这两个方程,我们可以将它们合并成一个方程,以得到我们的Log Loss成本函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是有效的,因为这两个值中总有一个为零,因此只使用另一个值。

结合的成本图看起来是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

既然我们已经很好地理解了逻辑回归背后的数学和直觉,我们来看看如何在 Python 中实现 Mark 的房屋面积问题。

完成了!现在你拥有了解决逻辑回归问题所需的一切。

以及一如既往,如果有任何问题,请随时通过LinkedIn联系我,或者发邮件到 shreya.statistics@gmail.com

回归基础,第一部分:线性回归和成本函数

原文:towardsdatascience.com/back-to-basics-part-uno-linear-regression-cost-function-and-gradient-descent-590dcb3eee46

一份关于基本机器学习概念的图解指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Shreya Rao

·发布于数据科学前沿 ·阅读时间 7 分钟·2023 年 2 月 3 日

今天,我们将深入探讨机器学习中的三个关键概念:线性回归、成本函数和梯度下降。这些概念构成了许多机器学习算法的基础。最初,我决定不写关于这些主题的文章,因为它们已经被广泛讨论。然而,我改变了主意,因为理解这些概念对于理解像神经网络这样的高级主题(我计划在不久的将来讨论)是至关重要的。此外,为了更好地理解,本系列将分为两部分进行。

所以,舒适一下,拿杯咖啡,准备好开始这场神奇的机器学习之旅吧。

与任何机器学习问题一样,我们从一个具体的问题开始。在这个案例中,我们的朋友马克正在考虑出售他 2400 平方英尺的房子,并寻求帮助来确定最合适的挂牌价格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

直观地,我们从寻找我们朋友所在邻里中可比的房子开始。经过一些挖掘,我们找到了一份附近三栋房子的销售记录。自然,一个典型的数据集会有成千上万的数据点,但我们将简单化,先从这三栋房子开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们绘制这些数据:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过检查数据,我们发现房屋的价格似乎与其面积在一个线性关系中相关。为了建模这种关系,我们可以使用一种称为线性回归的机器学习技术。这涉及在散点图上绘制一条最佳拟合数据点模式的直线。我们的模型可能如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在使用这条直线,我们可以说一个 2400 平方英尺的房子应该卖…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…~$260,000。然后就可以得到答案了。

现在最大的问提是:我们如何确定最适合我们数据的直线?

我本可以画一条稍微偏离的直线,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

或者,甚至更糟,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以清楚地看到,它们并没有像我们的第一条直线那样很好地拟合数据。

要找出最佳直线,首先需要数学上表示出一条糟糕的直线是什么样的。所以我们取这条“糟糕”的直线,并根据它,2000 平方英尺的房子应该卖 ~$140,000,而我们知道它实际卖了 $300,000:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

它也与所有其他值显著不同:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

平均而言,这条直线的偏差为 ~$94,000($50,000 + $160,000 + $72,000 / 3)。

这里是一条更好的直线:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这条直线的平均偏差为 ~$44,000,这要好得多。这$44,000 被称为使用此直线的成本成本是直线与实际数据的偏差。最好的直线是与实际数据偏差最小或成本最低的直线。为了找出哪条直线是最好的,我们需要使用成本函数

成本函数

上面,我们利用均绝对误差(MAE)成本函数来确定实际房价与预测价格之间的偏差。这基本上计算了实际房价(表示为 y,因为它表示 y 轴上的值)与预测房价(表示为 ŷ)之间的偏差的平均值。我们将MAE数学上表示为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注:在计算 MAE 时使用绝对值,因为它们确保预测值与实际值之间的差异始终为正,无论预测值是高还是低。这允许在不同预测之间公平比较误差,因为如果不取绝对值,正负差异会相互抵消。

根据机器学习算法和当前问题的不同,可以使用各种类型的成本函数。对于我们的问题,我们将使用一种常用的方法,即均方误差(MSE),它计算预测房价与实际房价之间差异的平方的平均值

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最终,任何成本函数的目的都是将其值最小化并尽可能降低成本

直线方程

在深入研究线性回归之前,让我们退一步回顾基础知识。这里有一个直线的例子:y = 1 + 2x

第一个数字,称为截距,告诉我们直线在开始时应该有多高。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第二个数字告诉我们直线的角度(或者,用技术术语说,就是斜率):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

既然我们了解了方程的工作原理,我们只需要确定这两个值的最佳值——斜率截距,以获得我们线性回归问题的最佳拟合直线。为了更简单些,假设我们已经神奇地拥有了斜率的值,0.069。

所以我们的线性回归直线的方程是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要获取某一特定大小房屋的预测价格,我们只需要插入截距和期望的房屋大小。例如,对于一个大小为 1000 平方英尺,截距为 0 的房子……

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

…我们得到一个预测的房价为 69,000 美元。所以现在我们需要做的就是找到截距的最佳值,以便得到我们的线性回归模型。

一种选择(我们很快会发现这种方法相当繁琐且不太有趣)是使用蛮力法,其中我们反复猜测截距的值,绘制一个线性回归线,并计算MSE。为了实验的目的,我们暂时尝试这种方法。

从一个随机的截距值开始猜测(我们从 0 开始),并绘制线性回归线:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后我们计算这条线的MSE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了获得直观的理解,我们在图上绘制截距值和相应的MSE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,我们将测试另一个截距值(假设为 25),绘制相应的直线,并计算MSE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以继续使用不同的截距值(= 0, 25, 50, 75, 100, 125, 150, 175)进行这个过程,直到我们得到一个如下所示的图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从图上绘制的点可以看出,当截距设置为 100 时,MSE是最低的。然而,也有可能在 75 和 100 之间存在另一个截距值会产生更低的MSE。找到最小MSE的一种缓慢而痛苦的方法是像下面这样插入更多的截距值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

尽管我们付出了努力,但我们无法确定是否找到了最低可能的均方误差值。测试多个截距值的过程既繁琐又低效。幸运的是,梯度下降可以通过更高效和有效的方式找到最优解。而这正是我们将在本系列的第二部分中探讨的内容!

## 回到基础,第两部分:梯度下降

关于基本机器学习概念的易于理解的视角

towardsdatascience.com

你可以通过LinkedIn与我联系,或通过shreya.statistics@gmail.com发邮件给我,提出问题和建议,尤其是对于你希望我讲解的其他算法!

回到基础知识:Probit 回归

原文:towardsdatascience.com/back-to-the-basics-probit-regression-ac05f4694d49?source=collection_archive---------5-----------------------#2023-11-09

二元结果分析中的关键方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Akif Mustafa

·

关注 发布于 Towards Data Science ·7 min read·Nov 9, 2023

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Issac Smith 提供,来自 Unsplash

每当我们面对与分析二元结果相关的任务时,我们往往会将 logistic 回归视为首选方法。这就是为什么大多数关于二元结果回归的文章都专注于 logistic 回归。然而,logistic 回归并不是唯一的选择。还有其他方法,例如线性概率模型(LPM)、Probit 回归和互补对数对数(Cloglog)回归。不幸的是,互联网上缺乏这些主题的文章。

线性概率模型很少被使用,因为它在捕捉二元结果与自变量之间的曲线关系方面效果不佳。我在之前的一篇文章中讨论过 Cloglog 回归。虽然互联网上有一些关于 Probit 回归的文章,但它们往往技术性较强,非技术读者难以理解。在这篇文章中,我们将解释 Probit 回归的基本原理及其应用,并与逻辑斯蒂回归进行比较。

背景

这就是二元结果变量与自变量之间关系的典型表现:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

你看到的曲线被称为 S 形曲线或逻辑斯蒂曲线。如果我们仔细观察这个图,我们会发现它类似于一个随机变量的累积分布函数(CDF)。因此,使用 CDF 来建模二元结果变量与自变量之间的关系是有意义的。最常用的 CDF 是逻辑斯蒂分布和正态分布。逻辑斯蒂回归使用逻辑斯蒂 CDF,其方程如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

在 Probit 回归中,我们利用正态分布的累积分布函数(CDF)。合理地,我们可以用正态分布 CDF 替换逻辑斯蒂 CDF,以得到 Probit 回归的方程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

其中Φ()表示标准正态分布的累积分布函数。

我们可以记住这个方程式,但它并不能澄清我们对 Probit 回归的概念。因此,我们将采用一种不同的方法来更好地理解 Probit 回归的工作原理。

Probit 回归的基本概念

假设我们有一组关于 1000 名个体的体重和抑郁状态的数据。我们的目标是使用 Probit 回归来研究体重与抑郁之间的关系。(从这个链接下载数据。)

为了提供一些直观的理解,让我们假设一个个体(“第 i 个”个体)是否会经历抑郁取决于一个不可观察的潜在变量,记作 Ai。这个潜在变量受到一个或多个自变量的影响。在我们的场景中,个体的体重决定了潜在变量的值。经历抑郁的概率随着潜在变量的增加而增加。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

问题是,由于 Ai是一个未观察到的潜在变量,我们如何估计上述方程的参数?好吧,如果我们假设它呈正态分布且具有相同的均值和方差,我们将能够获得关于潜在变量的一些信息,并估计模型参数。我稍后会更详细地解释这些方程,但首先,让我们进行一些实际计算。

回到我们的数据:在我们的数据中,让我们计算每个年龄的抑郁症概率并将其制表。例如,有 7 个人体重为 40 公斤,其中 1 人有抑郁症,因此体重 40 的抑郁症概率为 1/7 = 0.14286。如果我们对所有体重进行此操作,我们将得到以下表格:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

那么,我们如何获得潜在变量的值呢?我们知道正态分布给出了给定 X 值的 Y 的概率。然而,正态分布的逆累积分布函数(CDF)使我们能够获得给定概率值的 X 值。在这种情况下,我们已经有了概率值,这意味着我们可以通过使用正态分布的逆 CDF 来确定潜在变量的相应值。 [注意:逆正态 CDF 函数几乎在所有统计软件中都可以找到,包括 Excel。]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

这个未观察到的潜在变量 Ai被称为正态等效偏差(n.e.d.),或简单地称为normit。仔细观察,这只是与未观察到的潜在变量相关的 Z 分数。一旦我们有了估计的 Ai,估计β1 和β2 相对简单。我们可以在 Ai和我们的自变量之间进行简单的线性回归。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

权重为 0.0256 的系数给出了与权重的单位变化相关的结果变量(抑郁症)的 z 分数的变化。具体而言,权重的单位增加与抑郁症高概率的 z 分数单位增加约 0.0256 相关。我们可以使用标准正态分布计算任何年龄的抑郁症概率。例如,对于体重 70,

Ai = -1.61279 + (0.02565)*70

Ai = 0.1828

与 z 分数 0.1828(P(x<Z))相关的概率是 0.57;即体重 70 的抑郁症预测概率是 0.57。

可以说,上述解释对一个适度复杂的方法进行了过度简化是相当合理的。同时也需要注意,这只是使用累积正态分布在 Probit 回归中的基本原理的一个说明。现在,让我们看看数学方程。

数学结构

我们之前讨论过存在一个潜在变量 Ai,它由预测变量决定。考虑到潜在变量存在一个临界或阈值(Ai_c)是很合逻辑的,即如果 Ai超过 Ai_c,则个体将会有抑郁症;否则,他/她将不会有抑郁症。假设正态分布的前提下,可以从标准化正态累积分布函数中计算 Ai小于或等于 Ai_c 的概率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

其中 Zi是标准正态变量,即 Z ∼ N(0, σ 2),F 是标准正态累积分布函数。

与潜在变量及β1 和β2 相关的信息可以通过对上述方程取逆得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

当我们想要获得给定概率值的 Z 值时,会使用标准正态分布的逆累积分布函数。

现在,β1、β2 和 Ai的估计过程取决于我们是否拥有分组数据或个体级别的未分组数据。

当我们有分组数据时,计算概率是很容易的。在我们的抑郁症例子中,初始数据是未分组的,即每个个体的权重及其抑郁状态(1 和 0)。最初,总样本量为 1000,但我们按权重将数据分组,结果形成 71 个组,并计算了每个权重组中的抑郁概率。

然而,当数据未分组时,使用最大似然估计(MLE)方法来估计模型参数。下图显示了我们未分组数据(n = 1000)上的 Probit 回归:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

可以观察到,权重系数非常接近我们使用分组数据估计的结果。

Probit 与 Logit

现在我们已经掌握了 Probit 回归的概念,并且对逻辑回归(希望)也比较熟悉,问题来了:哪个模型更优?在不同条件下哪个模型表现更好?事实上,这两个模型在应用上非常相似,并且在预测概率方面的结果也相当接近。唯一的细微区别在于它们对极端值的敏感性。让我们更详细地了解这两个模型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

从图中我们可以观察到,Probit 和 Logit 模型非常相似。然而,Probit 对极端值的敏感性较低。这意味着在极端值下,预测变量单位变化对结果概率的影响在 Logit 模型中高于 Probit 模型。因此,如果你希望模型对极端值敏感,你可能会更倾向于使用逻辑回归。然而,这种选择不会显著影响估计结果,因为两种模型在预测概率方面产生的结果相似。需要注意的是,来自两种模型的系数表示的是不同的量,不能直接比较。Logit 回归提供了结果与预测变量变化的对数赔率的变化,而 Probit 回归提供了结果的 z-score 的变化。然而,如果我们使用两种模型计算预测概率,结果将非常相似。

在实践中,逻辑回归因其数学简洁性和系数解释的方便性而优于 Probit 回归。

回填精通:提升数据工程专业技能

原文:towardsdatascience.com/backfilling-mastery-elevating-data-engineering-expertise-a6873fb7ed2e

数据工程

数据工程师应对回填难题的实用指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 纳赛尔·塔米米

·发布于 Towards Data Science ·阅读时长 7 分钟·2023 年 11 月 17 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Towfiqu barbhuiya 提供,来源于 Unsplash

什么是回填?

想象一下,你刚开始一个新的数据管道,从一个你之前没有解析过的来源获取数据(例如,从 API 或现有的 Hive 表中提取信息)。现在,你的任务是让它看起来像你很久以前就收集了这些数据。这就是我们在数据工程中所说的数据回填的一个例子。

但这不仅仅是启动一个新的数据管道或表。你可能有一个已经收集数据一段时间的表,而突然你需要更改数据(例如由于新的指标定义),或者从新的数据源中添加更多数据。或者你的数据中可能有一个尴尬的空白,你只是想修补它。所有这些情况都是数据回填的例子。共同的特点是“回到”过去,并用一些历史数据“填补”你的表格。

下图(图 1)展示了一个简单的回填场景。在这个实例中,一个每日任务从两个上游来源(一个是平台 A,另一个是平台 B)检索数据。数据集的结构是第一个分区为‘ds’,第二个分区(或子分区)代表平台。不幸的是,由于某些问题,从 2023 年 10 月 3 日到 2023 年 10 月 5 日的数据缺失。为了弥补这一空缺,启动了回填操作(回填任务于 2023 年 10 月 8 日开始)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1)一个简单的回填场景

回填与重述

在继续之前简要说明一下:在数据工程领域,我们通常会遇到两种情况:“回填”一个表格或“重述”一个表格。这些过程虽然有些相似,但也存在一些微妙的差异。回填是指在数据集中填充缺失或不完整的数据。它通常用于更新历史数据或修正数据缺口。相反,重述表格涉及对表格的内容或结构进行重大修改。这种转换通常是为了纠正错误、更新数据模型或对数据集进行重大更改。为了简化起见,考虑到这些术语的微妙差异,在本文中我们将这两种过程统称为“回填”。

值得一提的是,不同的工程师可能对这些过程的称谓有所不同。

让我们谈谈设计

让我们深入探讨一下。你正在设计新的表格模式并规划 ETL 过程。一定要认真考虑回填。因此,花点时间问问自己:我的设计是否适用于常规(主要是每日)任务以及处理未来回填任务?当需要填补缺失数据时,我是否能够轻松完成,还是每次修复时都要经历繁琐的手动步骤?

有时你需要在设计中找到一个平衡点。你希望系统运行顺畅,不仅仅是处理日常数据流,也要在修复数据集中的任何缺口时同样顺畅。因此,现在对设计多加关注,可以为将来节省不少麻烦!

例如,你可能会认为,如果你对这个表格进行回填,你需要覆盖之前的数据而不是追加数据。在这种情况下,如果你使用的是 Hive 表格,也许 Hive 分区可以帮助你更轻松地实现这个目标。在这种情况下,你可以根据日期(通常称为“ds”)定义一个分区,并将你的 ETL 更改为覆盖该分区而不是追加到其中。采用这种模式设计,每次你在表格上写入数据时,之前的分区(在这种情况下是之前的“ds”日期)将被移除,并用新数据替换。然而,你可能会预见到每次回填可能只需要影响“ds”的一部分。例如,查看图 1 和 ds=2023–10–05。在这种情况下,部分数据成功加载,而部分数据加载失败。在这种情况下,你可以定义一个辅助分区(如果需要,也可以定义三级分区)来支持对未来某一特定日期的部分回填。同时,你也希望尽可能保持分区数量较低,以避免小分区(这可能导致数据处理效率低下)。

另一种有效的策略是将新回填的数据写入一个不同的分区位置,而不是覆盖磁盘上的现有分区位置。这可以通过例如在分区位置路径中引入一个独特的 runtime_id 目录来实现。随后,将 Hive 元数据存储中的分区位置从旧路径更新到新路径。这种方法允许保留以前的数据(作为预防措施),同时仍然能够更新整个分区。以下文件夹结构是我们如何使用 runtime_id 在同一表位置下保持不同版本的回填的示例。请记住,这种技术要求你的 ETL 更新 Hive 元数据存储数据库中的分区位置。

table_location_path
       └── runtime_id_1651023692 (*new backfill)
          ├── ds=2021-01-01      (*active/newest partition)
             ├── data_file
          ├── ds=2021-01-02      (*active/newest partition)
             └── data_file
          └── ds=2021-01-03      (*active/newest partition)
             └── data_file
       └── runtime_id_1609562892 (*daily job run)
          └── ds=2021-01-01      (*inactive/archived partition)
             └── data_file

此外,除了你常规的(例如每日的)工作流外,你可能还需要开发一个准备就绪的回填工作流,以应对需要回填数据的情况。例如,如果你使用 Apache Airflow,你可以有一个每日的 DAG 处理你的常规调度数据加载任务,并为回填数据设置一个单独的 DAG。在这种情况下,如果发生需要快速回填数据的情况,你将有一个现成的 DAG 可以使用。

开始回填

你精心设计了表模式和 ETL 管道,预见到未来需要进行数据回填。现在,经过几天、几周,甚至几个月,期待已久的数据回填时刻终于到来了。但你应该采取什么步骤?这是否仅仅是运行你的回填工作流/DAG 来处理指定日期范围,还是在点击回填按钮之前需要更仔细的考虑?

不幸的是,设计并不是唯一需要克服的挑战。回填过程本身可能相当复杂。首先,你必须确保回填是可行的。例如,某些 API 可能不支持超出特定回溯期的历史数据,而一些源表由于隐私限制可能不会保留较长时间的数据。确认你的特定时间范围内回填是否可行是至关重要的。

现在,假设幸运站在你这边,数据可用性没有问题。下一步要考虑的是你的表格用户。添加或修改数据,特别是历史数据,可能会影响下游用户。负责任的数据工程师会考虑这些行为对产品用户的影响,并尊重他们的体验。在某些情况下,提前通知下游用户回填操作可能是必要的,以便他们获取最新的数据。此外,你还需要评估列的变化如何影响其他表格。在开放的编码生态系统中,工程师可以合作检查其他项目和数据管道以进行验证。如果下游用户依赖于即将修改的列,评估影响并探索替代方案(如扩展表格而不是改变列逻辑)是至关重要的。你能协助他们更新 ETL 逻辑,还是应该将他们引导到替代数据源?

从本质上讲,对你和你的团队所负责的内容展示责任感,是区分优秀工程师与效果较差工程师的关键。

验证

现在你的回填工作已经完成,下一步至关重要的是验证。使用一些基本技术可以加快验证过程。

首先,验证回填过程的完成是至关重要的。有时,即使看起来回填作业已经成功执行,错误的参数可能导致没有实际更新或数据写入表格。因此,在验证回填数据之前,必须确认回填过程成功执行。在表格中引入一个捕获处理时间戳的特定列可以帮助验证数据是否已最近更新。或者,检查与新分区位置关联的runtime_id也是一种方法。正如设计部分所述,在分区路径中包含可选的runtime_id允许直接检查表路径。这可以简便地识别回填操作后是否创建了新的runtime_id文件夹。

如果你的回填工作使用了源表来填补空白,最直接的方法是从源表中聚合指标,并与目标表进行比较。编写一个复制 ETL 逻辑的查询可以进行全面的比较,尽管这可能需要一些时间和精力。然而,这个查询有双重作用,不仅有助于即时验证,还作为未来检查的有价值工具。建议在你的 ETL 文档中记录并存储这些查询,以便持续使用。

在补填仅集中在某些列而未向表中引入新行的情况下,额外的验证方法包括检查未更改列与其之前状态的比较。例如,评估这些列在补填前后的总和可以确保未对未受影响的区域进行任何非预期的更改。

摘要

总结一下,这篇文章介绍了一些数据工程中的最佳补填实践。我们分解了补填和重新声明表之间的区别。同时,强调了智能设计在处理常规任务和补填工作中的重要作用。我们解决了补填过程中的难题,例如数据可用性以及保持下游伙伴的信息通畅。最后,我们提到数据工程师需要关注其更改对下游用户的影响,并在需要补填时负责任地行动。

反向传播:逐步推导

原文:towardsdatascience.com/backpropagation-step-by-step-derivation-99ac8fbdcc28

完整的神经网络训练算法指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Roi Yehoshua 博士

·发表于 Towards Data Science ·阅读时间 11 分钟·2023 年 4 月 10 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:DeepMindUnsplash

上一篇文章 中,我们讨论了多层感知机(MLPs)作为第一个可以解决非线性和复杂问题的神经网络模型。

很长一段时间内,如何在给定数据集上训练这些网络并不明确。虽然单层感知机具有保证收敛的简单学习规则,但这一规则无法扩展到多层网络。人工智能社区在这个问题上挣扎了 30 多年(在一个被称为“人工智能寒冬”的时期),直到 1986 年 Rumelhart 等人首次在其开创性论文中提出了反向传播算法

在本文中,我们将详细讨论反向传播算法,并逐步推导其数学公式。由于这是用于训练各种神经网络(包括我们今天拥有的深度网络)的主要算法,我相信了解该算法的详细信息对任何从事神经网络工作的人都是有益的。

尽管你可以在许多教科书和在线资源中找到关于该算法的描述,但在撰写本文时,我尽力牢记以下原则:

  • 使用清晰且一致的符号表示。

  • 解释数学推导的每一个步骤。

  • 推导最一般情况的算法,即适用于任意层数的网络及任何激活函数或损失函数。

在推导了反向传播方程后,提供了完整的算法伪代码,并通过数值示例进行了说明。

在阅读本文之前,我建议你刷新一下微积分知识,特别是在导数领域(包括偏导数导数链式法则)。

现在拿杯咖啡,让我们深入探讨 😃

算法的三个阶段

反向传播算法包括三个阶段:

  1. 向前传播。在这个阶段,我们通过网络输入数据,做出预测并根据真实标签测量其误差。

  2. 反向传播。我们将与每个权重相关的错误梯度从输出层向输入层反向传播。

  3. 梯度下降步骤。我们通过在错误梯度的反方向上迈出一步来轻微调整网络中的连接权重。

我们现在将详细讨论这些阶段。

向前传播

在向前传播中,我们逐层前向传播输入,直到生成输出。层 l 中神经元 i 的激活通过以下方程计算:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

向前传播方程

其中 f 是激活函数,zᵢˡ 是层 l 中神经元 i 的净输入,wᵢⱼˡ 是层 l — 1 中神经元 j 和层 l 中神经元 i 之间的连接权重,bᵢˡ 是层 l 中神经元 i 的偏差。有关符号和该方程推导的更多细节,请参见我的上一篇文章

为了简化学习算法的推导,我们将偏差视为具有常数值 1 的输入神经元 x₀ 的权重 w₀。这使我们能够将上述方程写成如下形式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

反向传播

在反向传播中,我们将错误的梯度从输出层反向传播到输入层。

错误和损失函数的定义

我们首先定义网络在训练集上的错误,关于其权重。假设 w 是包含网络所有权重的向量。

假设我们有 n 个训练样本 {(xᵢ, yᵢ)},i = 1,…,n,且网络在样本 i 上的输出为 oᵢ。那么网络相对于 w 的错误是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

错误函数

其中 J(y, o) 是损失函数。我们使用的具体损失函数取决于网络要完成的任务:

  1. 对于回归问题,我们使用平方损失函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 对于二分类问题,我们使用对数损失(也称为二分类交叉熵损失):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3. 对于多分类问题,我们使用交叉熵损失函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 k 是类别的数量。

我们使用这些特定损失函数的原因在这篇文章中有详细解释。

我们的目标是找到权重w,以使 E(w) 最小化。不幸的是,由于隐藏神经元的非线性激活,这个函数是非凸的。这意味着它可能有多个局部最小值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有多种技术可以用来防止梯度下降陷入局部最小值,例如动量。这些技术将在未来的文章中讨论。

寻找误差的梯度

为了使用梯度下降,我们需要计算 E(w) 对网络中每个权重的偏导数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

误差对给定权重的偏导数

为了简化数学推导,我们将假设只有一个训练示例,并找到该示例对误差的偏导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 y 是该示例的标签,o 是网络对该示例的输出。对 n 个训练样本的扩展是直接的,因为函数和的导数只是它们导数的和。

计算隐藏层权重的偏导数并不是简单的,因为这些权重并不直接影响输出(因此也不直接影响误差)。为了解决这个问题,我们将使用链式法则来建立给定层误差梯度与后续层梯度之间的关系。

Delta 项

我们首先注意到 E 仅通过第 l 层神经元 i 的净输入 zᵢˡ 依赖于权重 wᵢⱼˡ。因此,我们可以将链式法则应用于 E 对该权重的梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方程右侧的二阶导数是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,我们可以写:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

变量 δᵢ 被称为神经元 idelta 项,简称 delta

Delta 规则

delta 规则建立了第 l 层的 delta 项与第 l + 1 层的 delta 项之间的关系。

为了推导 delta 规则,我们再次使用链式法则。损失函数仅通过其在第 l + 1 层连接的所有神经元的净输入来依赖于神经元 i 的净输入。因此,我们可以写:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中求和中的索引 j 遍历第 l + 1 层中与第 l 层神经元 i 连接的所有神经元。

再次使用链式法则分解括号内的第二个偏导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

括号内的第一个偏导数就是层l + 1 中神经元j的 delta,因此我们可以写:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第二个偏导数很容易计算:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

aᵢˡ = f(zᵢˡ),其中f是激活函数。因此,和外的偏导数只是激活函数f’(x)在x = zᵢˡ处的导数。

因此我们可以写:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

delta 规则

这个方程,被称为delta 规则,显示了层l中的 delta 与层l + 1 中的 delta 之间的关系。更具体地说,层l中的每个 delta 都是层l + 1 中 delta 的线性组合,其中组合的系数是这些层之间的连接权重。delta 规则允许我们递归地计算所有 delta 项(从而所有误差的梯度),从输出层中的 delta 开始,一层一层地向回计算,直到达到输入层。

下图说明了误差信息的流动:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过从层l+1 中与神经元i连接的神经元向后传播的 delta 来计算层l中神经元i的 delta。黑色箭头表示前向传播的方向,红色箭头表示误差的反向传播。

对于特定的激活函数,我们可以推导出 delta 规则的更明确的方程。例如,如果我们使用 sigmoid 函数,则:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

sigmoid 函数的导数具有简单的形式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么 sigmoid 函数的 delta 规则变为以下形式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于 sigmoid 函数的 delta 规则

输出层中的 Deltas

拼图的最终部分是输出层中的 delta 项,这些是我们需要计算的第一个项。

输出层中的 deltas 依赖于输出神经元中使用的损失函数和激活函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中f是用于计算输出的激活函数。

现在我们推导每种学习任务的更具体的 delta 项:

  1. 在回归问题中,我们在输出中使用的激活函数是恒等函数f(x) = x,其导数为 1,损失函数是平方损失。因此,delta 为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 在二分类问题中,我们使用的激活函数是 sigmoid,损失函数是对数损失,因此我们得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

换句话说,delta 只是网络输出和标签之间的差值。

3. 在多分类问题中,我们有 k 个输出神经元(其中 k 是类别的数量),我们使用 softmax 激活函数和交叉熵对数损失。与前面的情况类似,第 i 个输出神经元的 delta 项非常简单:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 oᵢ 是网络预测的第 i 个组件,yᵢ 是标签的第 i 个组件。证明过程略长,你可以在 这篇文章 中找到它。

梯度下降

一旦我们完成了所有 delta 项的计算,我们可以使用梯度下降来更新权重。在梯度下降中,我们沿梯度的相反方向(即沿着最陡下降的方向)采取小步骤,以接近最小误差:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

梯度下降

记住,误差函数关于每个权重的偏导数是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,我们可以将梯度下降的更新规则写成如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

梯度下降更新规则

其中 α 是控制步长的学习率(0 < α < 1)。换句话说,我们从第 l 层的神经元 j 到第 l 层的神经元 i 的权重中减去神经元 i 的 delta 乘以神经元 j 的激活(按学习率缩放)。

梯度下降可以应用于以下模式之一:

  1. 批量梯度下降 — 在计算完整个训练集上的误差后更新权重。

  2. 随机梯度下降(SGD) — 在每个训练样本之后执行一次梯度下降步骤。通常比批量梯度下降收敛速度更快,但稳定性较差。

  3. 小批量梯度下降 — 在批量梯度下降和 SGD 之间的一种折中方法。我们使用小批量的随机训练样本(通常在 10 到 1,000 个示例之间)来进行梯度更新。这减少了 SGD 中的噪声,但仍然比全批次更新更高效,并且是训练神经网络的最常见形式。

反向传播:完整算法

我们现在准备以完整的形式展示整个算法:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作为练习,尝试在 Python(或你喜欢的编程语言)中实现这个算法。

反向传播示例

想象一下,我们有一个二分类问题,具有两个二进制输入和一个二进制输出。我们的神经网络有两个隐藏层,权重如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

隐藏层和输出单元的激活函数是 sigmoid 函数,学习率是 α = 0.5*。

网络呈现一个训练示例,输入是 x₁ = 1 和 x₂ = 0,目标标签是 y = 1。让我们执行一次反向传播算法的迭代以更新权重。

我们从输入的前向传播开始:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前向传播

网络的输出是 0.6718,而真实标签是 1,因此我们需要更新权重,以提高网络的输出,使其更接近标签。

我们首先计算输出节点的 delta。由于这是一个二分类问题,我们使用对数损失函数,输出的 delta 是 oy

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输出神经元的 delta

我们现在使用 delta 规则将 deltas 从输出神经元传播回输入层:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

反向传播

注意,当我们向后回溯到各层时,deltas 变得越来越小,导致网络中的早期层训练非常缓慢。这种现象被称为 梯度消失,是反向传播在训练深层网络时未能成功的主要原因之一,也是深度学习兴起的主要动因。

最后,我们执行一次梯度下降步骤:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

梯度下降步骤

让我们再做一次前向传播,看看网络的输出是否更接近目标:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

另一个前向传播

确实,输出已从 0.6718 增加到 0.6981!

最终说明

除非另有说明,所有图像均由作者提供。

感谢阅读!

参考文献

[1] Rumelhart, David E.,Geoffrey E. Hinton 和 Ronald J. Williams. “通过反向传播误差学习表示。” 自然 323.6088 (1986): 533–536。

不良的机器学习模型仍然可以被良好校准

原文:towardsdatascience.com/bad-machine-learning-models-can-still-be-well-calibrated-7a856346fdf2

机器学习

你不需要一个完美的神谕来正确地确定你的概率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Michał Oleszak

·发表在 Towards Data Science ·11 min read·2023 年 2 月 13 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习模型通常根据其性能进行评估,这种性能是通过某些指标接近零或一(具体取决于指标)来衡量的,但这并不是决定其有用性的唯一因素。在某些情况下,一个整体准确度不高的模型仍然可以很好地进行校准,并找到有用的应用场景。在本文中,我们将探讨良好校准与良好性能之间的区别,以及何时一种可能优于另一种。让我们深入了解吧!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

概率校准

概率校准的强定义是分类模型预测的概率与数据集中目标类的真实频率之间的匹配程度。一个良好校准的模型会生成在总体上与实际结果紧密对齐的预测。

实际上,这意味着如果我们使用一个完美校准的二分类模型进行大量预测,然后只考虑那些模型预测为 70%概率为正类的情况,那么模型应该在 70%的时间里是正确的。同样,如果我们只考虑模型预测为 10%概率为正类的例子,实际情况将在十分之一的案例中确实为正类。

一个良好校准的模型会生成在总体上与实际结果紧密对齐的预测。

一个强校准的模型保证其预测满足频率主义的概率定义(而非贝叶斯的定义),即事件的概率是其在多次试验中的相对频率的极限

考虑掷骰子时掷出六的概率。这个概率为 1/6,因为在多次掷骰子中,你平均每六次掷一次就会得到一个六。次数越多,六的频率就越接近 1/6。在这个背景下,当二元分类模型输出 90%的事件概率时,这意味着如果它多次这样做,大约在 10 次中的 9 次情况下事件确实会发生。

大多数机器学习模型的校准不佳,其原因取决于学习算法。基于树的集成方法,如随机森林,通过对单棵树的预测进行平均来生成预测,这使得获得接近零和一的概率不太可能,因为树的预测总是存在一定的方差。因此,我们看到接近零的概率被高估,接近一的概率被低估。许多其他模型优化并通过二元指标进行评分。准确率只关注我们是否正确,而忽略了确定性。决策树用于决定分裂的基尼不纯度优化的是尽可能快地达到尽可能准确的结果。

其结果是,尽管大多数机器学习模型生成的分数保持了顺序(数字越高,正类的可能性越大),但这些分数不能被解释为频率主义的概率。

有一些简单的方法可以校准它们,良好的校准无疑是模型应具备的一个理想特征,但正如我们很快会看到的,它不是模型有用的必要条件,有时我们甚至可能希望模型没有经过校准!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你真的需要校准吗?

在训练分类模型时,你需要问自己一个关键问题:你是否需要模型良好的校准?答案将取决于模型的使用方式。让我们看一些例子。

校准是关键:信用额度分配

在某些情况下,良好的校准是不可或缺的。考虑一下银行如何决定给客户授予多少信用额度。假设我们只考虑那些已经被筛选和评估为低风险且符合贷款条件的申请者(我们将在稍后讨论这一筛选过程)。决定将贷款授予他们。问题是我们可以借给每个人多少钱?

要回答这个问题,银行需要知道每个客户在不同贷款金额下的确切违约概率。了解不同情景的可能性,银行将能够预测所有贷款(无论是已偿还还是违约)的货币影响,并做出最佳决策。为了实现这一目标,他们需要一个经过精确校准的模型。

注意,我们并不真正关心模型的准确性本身。准确性关乎于预测阈值的正确侧面;从它的角度来看,预测 51%和 99%没有区别,只要贷款违约;在这两种情况下,预测都是正确的。但对银行以及贷款申请者而言,这之间有着巨大的差异。这里重要的是获取正确的概率。

校准至关重要:模型性能估计

有时候,良好的模型校准是某些应用的先决条件。想象一下在不知道真实目标的情况下估计模型在生产中的性能。解决这个分类模型的挑战性任务的一种方法是 NannyML 的 基于置信度的性能估计(CBPE)算法。简而言之,这种方法的核心思想是根据期望的错误率来估计混淆矩阵的元素,前提是我们知道模型经过良好的校准。

因此,如果我们想监控模型在生产中的表现而没有立即获得真实目标,我们需要对模型进行校准。然而,模型的准确性并不需要很高,只要它的预测经过良好的校准,就可以使用。

我们不需要校准:排序问题

然而,有些情况下,模型的校准并不那么重要。例如,所有类型的排序问题。

想想那些根据质量或与用户搜索查询的相关性对新闻文章标题进行排名的模型。如果目标是选择一个或多个文章展示给用户,我们并不关心每篇文章是否具有高质量和相关性的确切概率;相反,我们关心的是模型产生的分数的排序。也就是说,我们希望确保展示给用户的内容优于未展示的内容,并且最好的新闻排在结果列表的顶部。在这种情况下,校准模型并没有太大意义。

我们不需要校准:授予贷款

另一个校准不那么重要的场景是我们之前提到的贷款授予筛选。

这里的目标是预测哪些申请者会偿还贷款。在这个二分类问题中,银行主要关注模型分类的准确性,而不是它产生的概率。

根据模型的使用方式,良好的校准可能是必不可少的,也可能是相对不必要的。

现在,让我们看看一些在性能方面较差的模型,但它们的良好校准使其在预期的用途上非常有用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个校准良好的差模型的故事

让我们考虑两个不同的模型。首先,我们将查看一个在性能上难以获得良好表现的模型,但良好的校准确保了模型提供了价值。其次,我们将考虑一个理论上无法获得良好表现的模型,但它经过良好校准,因此仍然有用。

当很难获得良好表现时

一段时间之前,我一直在训练模型来预测足球(也就是足球比赛)的结果,目标是通过在博彩公司下注快速且轻松地致富。准确预测比赛结果是一项不可能完成的任务——涉及到的隐藏因素太多,例如运气和球员当天的状态。但你猜怎么着,准确的预测并不是我们需要的!就像在信用额度分配和绩效评估的例子中一样,这里也是,游戏的关键在于获得正确的概率。

考虑这个二元随机森林分类器,它被训练来预测主队是否会赢得比赛。它是在几个赛季的英超联赛比赛上训练的,特征集包括了两个队伍的ELO 评分以及许多不同的统计数据,汇总了每个球队在近期比赛中的进攻和防守表现。

模型的测试准确率为 63%。这肯定比一个总是预测主队获胜的虚拟模型要好;这样的模型会得到 46%的准确率,因为主队几乎赢得了半数的比赛。也就是说,63%似乎不是一个很好的结果。

让我们看看模型的校准图。水平轴显示了模型为测试集产生的概率,分为 10 个等宽的区间。对于每一个区间,主队获胜的实际频率显示在垂直轴上。一个完全校准的模型将产生一条完美的对角线。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

足球预测器的校准曲线。图片由作者提供。

原始模型,显示为蓝色,在更极端的概率下校准效果很差:90%的预测仅有 30%的正确率!因此,我决定使用最流行的技术之一来进行校准:在模型输出上拟合逻辑回归器。

结果模型,显示为绿色,似乎校准效果好得多。你也会注意到,它不再产生极端概率。至于准确率,它下降了一个百分点,降至 62%。因此,我们成功地提高了模型的校准水平,但准确率有所下降。这有什么用呢?

考虑以下策略:我们只对模型最确定主队会赢的比赛进行投注,即模型预测主队胜率为 70%的比赛。得益于合理的校准,我们知道模型在这种情况下的正确率为 70%。为了简化起见,假设我们对每场比赛分别投注$100。

在 100 场比赛中,我们将错过 30 场,造成$3000 的损失。但我们将赢得剩下的 70 场比赛,现金奖励为70 * 100 * (赔率 — 1)(我们减去 1 是为了考虑到我们最初需要花费$7000 购买彩票)。我们可以解这个方程,找到一个博彩公司赔率,使得我们收支平衡:

3000 = 7000 * odds - 7000
10000 = 7000 * odds
odds = 10000 / 7000 = 1.42

就这样!我们可以对模型预测为 70%的所有比赛进行投注,并且在这些比赛中,博彩公司提供的赔率需高于 1.42(不考虑税)。当然,我们也可以以类似的方式计算其他预测概率的赔率。假设模型的校准在未来保持良好(这是一项强假设!),这种策略应该在长期内相当有利。尽管准确率只有 62%,但这仍然有效!

当无法获得良好的性能时

现在考虑预测掷骰子的尝试。我们的模型应该给出骰子掷出六的概率。我们假设骰子是普通的六面公平骰子。

掷骰子是一个完全随机的过程,每一面朝上的机会是相同的:⅙。换句话说,数据类别是完全不可分的:建立一个准确的模型是不切实际的。那么,我们可以拥有什么模型呢?

考虑这两种竞争方法。模型 A 是一个虚拟的二元分类器,它总是全信心地预测掷出的数字不是六;也就是说,它 0%的时间预测六,100%的时间预测不是六。模型 B 也从不预测六,但它输出的概率不同:它总是以⅙的概率预测六,以⅚的概率预测不是六。

从长远来看,这两个模型的准确率相同:它们的正确率为 5/6。这是任何模型能达到的最好水平。然而,一个重要的事实区分了这两个模型:模型 B 的校准非常完美,而模型 A 根本没有校准。

就校准而言,这两个模型截然不同。那么,这两个模型的有用性如何?模型 A 实际上没有提供任何价值。另一方面,模型 B 允许我们在长期内准确预测目标频率。它还允许我们进行模拟,以回答更复杂的问题,例如:在 11 次掷骰中,掷出四次不是六和七次六的概率是多少?尽管预测性能不佳,但良好的校准使模型依然有用!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要点

  • 校准良好的模型产生的预测与实际结果的频率高度一致。大多数模型由于学习方式的不同而校准不佳,但有一些简单的方法可以解决这个问题。

  • 对于一些应用场景,如分配信用额度或 CBPE 估计,良好的校准至关重要(事实上,比性能指标本身更重要)。对于其他情况,比如贷款发放或排序问题,这一点则不那么重要;在这些场景中,正确的排序和性能才是关键。

  • 不准确的模型在经过良好校准后可能会非常有用;有时,确保概率的正确性就是我们能做到的全部。

这篇文章也发表在 NannyML 博客上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

感谢阅读!

如果你喜欢这篇文章,为什么不订阅电子邮件更新以获取我最新的文章呢?通过成为 Medium 会员,你可以支持我的写作并无限制地访问其他作者及我自己的所有故事。

想要时刻掌握机器学习和 AI 快速发展的领域的动态吗?查看我的新通讯,AI Pulse。需要咨询?你可以在这里问我任何问题或预约一对一服务。

你也可以尝试一下我的其他文章。无法选择?挑一个看看吧:

## 校准分类器

你确定你的模型返回的是概率吗? 🎲

towardsdatascience.com [## 无需真实数据估计模型性能

只要保持你的概率校准,这是可能的。

pub.towardsai.net](https://pub.towardsai.net/estimating-model-performance-without-ground-truth-453b850dad9a?source=post_page-----7a856346fdf2--------------------------------) ## 特征选择方法及如何选择它们

特征选择的原因、方法和时机,以及一些实用的技巧和建议

towardsdatascience.com

平衡行动:解决推荐系统中的受欢迎度偏见

原文:towardsdatascience.com/balancing-act-addressing-popularity-bias-in-recommendation-systems-db5448c6a2a4?source=collection_archive---------3-----------------------#2023-08-18

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Pratik Aher

·

关注 发布于 Towards Data Science · 7 分钟阅读 · 2023 年 8 月 18 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Melanie Pongratz 提供,来源于 Unsplash

一天早上,你决定犒劳自己,买一双新鞋。你打开了最喜欢的运动鞋网站,浏览了系统推荐的商品。特别有一双鞋引起了你的注意——你喜欢它的风格和设计。你毫不犹豫地购买了它们,迫不及待地想穿上你的新鞋。

当鞋子到达时,你迫不及待地想展示它们。你决定在即将到来的音乐会上穿着它们。不过,当你到达场地时,你注意到至少有 10 个人穿着完全一样的鞋子!这概率有多大?

突然间你感到失望。尽管你最初很喜欢这些鞋子,但看到这么多人穿着同样的鞋子让你觉得你的购买并不那么特别了。你本以为会让你与众不同的鞋子,最终却让你融入了人群。

那一刻,你发誓再也不从那个运动鞋网站购买东西了。尽管他们的推荐算法建议了你喜欢的物品,但最终没有带给你你所期望的满足感和独特性。所以尽管你最初欣赏那个推荐的物品,但整体体验让你感到不满。

这突显了推荐系统的局限性——推荐一个“好”的产品并不保证它会带来积极和满足的客户体验。那么,最终这真的是一个好的推荐吗?

为什么衡量推荐系统中的受欢迎度偏见至关重要?

受欢迎度偏见发生在推荐系统建议大量全球受欢迎的物品而非个性化推荐时。这是因为算法通常被训练来最大化用户的参与度,通过推荐许多用户喜欢的内容来实现。

虽然受欢迎的物品仍然可能相关,但过度依赖受欢迎程度会导致缺乏个性化。推荐变得泛泛而谈,无法考虑个人兴趣。许多推荐算法通过优化总体受欢迎度的指标来进行调整。这种对已有受欢迎度的系统性偏向,随着时间的推移可能会成为问题。它导致了对热门或病毒式传播物品的过度推广,而不是独特的建议。在商业方面,受欢迎度偏见还可能导致公司拥有大量小众、鲜为人知的库存,这些库存未被用户发现,导致难以销售。

考虑特定用户偏好的个性化推荐可以带来巨大的价值,特别是对于与主流不同的小众兴趣。它们帮助用户发现专门为他们量身定制的新奇物品。

理想情况下,推荐系统应在受欢迎程度和个性化之间取得平衡。目标应该是展示与每个用户产生共鸣的隐藏宝石,同时偶尔加入一些具有普遍吸引力的内容。

如何衡量受欢迎度偏见?

平均推荐受欢迎度

平均推荐受欢迎度(ARP)是一个用来评估推荐列表中物品受欢迎程度的指标。它根据物品在训练集中收到的评分数量来计算物品的平均受欢迎度。从数学上讲,ARP 的计算方法如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中:

  • |U_t| 是用户的数量

  • |L_u| 是用户 u 的推荐列表 L_u 中的项目数量。

  • ϕ(i) 是在训练集中“项目 i”被评分的次数。

简单来说,ARP 通过将推荐列表中所有项目的受欢迎程度(评分数量)加总,然后在测试集中的所有用户之间取平均值来衡量项目的平均受欢迎程度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

示例:假设我们有一个包含 100 个用户的测试集 |U_t| = 100。对于每个用户,我们提供一个 10 个项目的推荐列表 |L_u| = 10。如果项目 A 在训练集中被评分 500 次(ϕ(A) = 500),而项目 B 被评分 300 次(ϕ(B) = 300),这些推荐的 ARP 可以计算为:

在这个例子中,ARP 值为 8,表示推荐项目在所有用户中的平均受欢迎程度为 8,基于它们在训练集中获得的评分数量。

长尾项目的平均百分比(APLT)

长尾项目的平均百分比(APLT)指标,计算推荐列表中长尾项目的平均比例。它的表达式为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里:

  • |Ut| 代表用户的总数。

  • u ∈ Ut 表示每个用户。

  • Lu 代表用户 u 的推荐列表。

  • Γ 代表长尾项目集合。

简单来说,APLT 量化了推荐中较少受欢迎或利基项目的平均百分比。较高的 APLT 表示推荐中包含了更多的此类长尾项目。

示例:假设有 100 个用户(|Ut| = 100)。对于每个用户的推荐列表,平均来说,50 个项目中的 20 个(|Lu| = 50)属于长尾集合 (Γ)。使用公式,APLT 为:

APLT = Σ (20 / 50) / 100 = 0.4

因此,在这种情况下,APLT 为 0.4 或 40%,这意味着,平均而言,推荐列表中的 40% 项目来自长尾集合。

长尾项目的平均覆盖率(ACLT)

长尾项目的平均覆盖率(ACLT)指标评估了在整体推荐中包含的长尾项目的比例。与 APLT 不同,ACLT 考虑了所有用户中长尾项目的覆盖情况,并评估这些项目在推荐中的有效表示。它的定义为:

ACLT = Σ Σ 1(i ∈ Γ) / |Ut| / |Lu|

这里:

  • |Ut| 代表用户的总数。

  • u ∈ Ut 表示每个用户。

  • Lu 代表用户 u 的推荐列表。

  • Γ 代表长尾项目集合。

  • 1(i ∈ Γ) 是一个指示函数,如果项目 i 在长尾集合 Γ 中,则等于 1,否则为 0。

简单来说,ACLT 计算了每个用户推荐中长尾项目的平均比例。

示例:假设有 100 个用户(|Ut| = 100)和 500 个长尾项目(|Γ| = 500)。在所有用户的推荐列表中,有 150 个长尾项目被推荐(Σ Σ 1(i ∈ Γ) = 150)。所有推荐列表中的项目总数为 3000(Σ |Lu| = 3000)。使用公式,ACLT 为:

ACLT = 150 / 100 / 3000 = 0.0005

因此,在这种情况下,ACLT 为 0.0005 或 0.05%,这表明平均而言,0.05%的长尾项目被包含在总体推荐中。这个指标有助于评估推荐系统中小众项目的覆盖率。

如何减少推荐系统中的流行度偏差

流行度感知学习

这个想法受到位置感知学习(PAL)的启发,该方法是要求你的机器学习模型同时优化排序相关性和位置影响。我们可以用相同的方法结合流行度得分,这个得分可以是上面提到的任何得分,比如平均推荐流行度。

  • 在训练时,你使用项目流行度作为输入特征之一

  • 在预测阶段,你将其替换为一个常量值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

xQUAD 框架

解决流行度偏差的一个有趣方法是使用称为 xQUAD 框架的东西。它结合当前模型的推荐列表(R)和概率/可能性得分,构建一个新列表(S),这个新列表要多样化得多,其中|S| < |R|。这个新列表的多样性由超参数λ控制。

我尝试总结框架的逻辑:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

我们计算集合 R 中所有文档的得分。我们取得分最高的文档,将其添加到集合 S 中,同时将其从集合 R 中移除。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

要选择下一个添加到‘S’的项目,我们计算 R\S(R 去掉 S)中每个项目的得分。对于每个选择添加到“S”的项目,P(v/u)会上升,因此一个不受欢迎项目再次被选中的机会也会增加。

如果你喜欢这个内容,可以在linkedin找到我 😃.

参考文献

arxiv.org/pdf/1901.07555.pdf

www.ra.ethz.ch/cdstore/www2010/www/p881.pdf

[## 如何克服推荐和搜索中的位置偏差?

在这篇文章中,我们将讨论如何通过逆倾向加权(Inverse Propensity Weighting)克服位置偏差及其缺点……

www.analyticsvidhya.com

平衡创新与可持续性:揭示生成 AI 的环境影响

原文:towardsdatascience.com/balancing-innovation-and-sustainability-unpacking-the-environmental-impact-of-generative-ai-5493b7d4e586?source=collection_archive---------7-----------------------#2023-10-04

语言模型碳足迹的深入探讨及可持续解决方案。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Jeremie Charlet

·

跟进 发表在Towards Data Science ·7 分钟阅读·2023 年 10 月 4 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

PixabayKohji Asakawa贡献。

法国协会Data for Good发布了一份白皮书,探讨了生成型人工智能的社会和环境问题。我特别关注语言模型的环境影响,因为这一点比伦理方面的讨论少一些。以下是我的主要收获:

TL;DR

  • 背景全球领导者承诺到 2050 年将我们的排放减少 至远低于 2°C。这意味着我们需要在 2020 年至 2030 年间减少 43%的排放(为了限制升温至 1.5°C,请参见 IPCC 报告的 C.1.1 节)。然而,在数字领域,排放量并未减少,反而从2增加至7%每年。

  • GPT-3 的训练产生了多达 2200 吨的二氧化碳当量——相当于 1600 次从巴黎到纽约的往返航班。

  • 拥有 1300 万用户的 ChatGPT 每月使用量相当于 10000 吨的二氧化碳。如果每个人今天都使用它,它将占法国/英国个人年度碳足迹的 0.1%,到 2050 年则占目标碳足迹的 0.5%。

  • ChatGPT+的影响,依赖于 GPT-4,可能是其 10 到 100 倍,这将使我们的年度碳足迹增加 10%……或者达到目标碳足迹的 50%。

  • 有许多方法可以减少使用这些模型的影响:合理使用它们,并选择具有 proven 环境绩效的云服务。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

英国公民的年度碳足迹

背景

要评估任何事物的环境影响,我们可以估算其碳足迹:它衡量个人、组织或产品直接和间接造成的温室气体排放总量,表示为二氧化碳(CO2e)当量。

从总体上来看,英国的平均年度碳足迹约为每人 8-13 吨,法国为 21 吨,美国为 21 吨,全球为 6 吨](https://www.nature.com/articles/s41893-022-00955-z)。我将考虑 10 吨作为我们当前的碳足迹。

一些例子(附来源):

为了将全球温度升高控制在 2 度以下,我们 应该 目标 到 2050 年将我们的全球碳足迹减少到每人 2 吨。

减少 80% 或 90% 的排放还有很多工作要做,对数字服务的持续需求增长 超过了效率提升,这无济于事。生成性 AI 如何适应这个方程式,我们能做些什么来将我们的数字进步与环境目标对齐?

训练影响:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

归功于 Victor Freitas 的 Unsplash

训练 阶段,我们向语言模型提供一些精选数据,以便它们从中学习并能够回答我们的请求。

研究分析了两个大型语言模型:

1. 开源 Bloom

2. OpenAI 的专有 GPT-3

主要发现:

  • Bloom 的碳足迹:最初估计为 30 吨,经过综合分析后修订为 120 吨。

  • GPT-3 的碳足迹:推算为 2200 吨,相当于 1600 次巴黎——纽约的往返航班。

一个常见的观点是,这些模型的高训练成本是可以接受的,因为它们被许多用户广泛使用。

推理影响

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

归功于 Fitsum AdmasuUnsplash

机器学习中的推理是指我们使用训练好的模型对实时数据进行预测。我们现在正在观察运行 ChatGPT 的影响。

基于 ChatGPT 有 1300 万活跃用户平均每人发起 15 个请求的假设,每月碳足迹为 1 万吨 CO2。

对我而言,关键的经验教训是,这比训练的影响要大得多。

对于一个用户来说,年度碳足迹的增加量是 12 个月 * 10000 吨 / 1300 万用户 = 每年每用户 9 公斤 CO2eq,相当于当前平均年度碳足迹的 0.1%或我们目标足迹的 0.5%。

但如果那个人使用带有 GPT-4 的 ChatGPT+呢?GPT-4 的足迹是 GPT-3 的 10 到 100 倍。这种足迹相当于 100 公斤到 1 吨额外的 CO2e,占法国公民碳足迹的高达 10%——如果你尽力减少它,甚至会是两倍。如果我们考虑到 2050 年的目标足迹,这就代表了 50%!

这太糟糕了。

如果有一天,你生活中的每一个应用互动都向语言模型发起请求,会怎么样?这是个令人恐惧的想法。

好消息是,广泛使用 gpt4 API 的成本非常高,我们无法让用户每天发起 15 个请求,除非他们愿意支付每月 100 美元以上的订阅费用,而我正在开发的产品(一个冥想个人助手)的目标市场并不愿意支付这个费用。这不仅仅是小型企业无法承担的:谷歌和微软也无法承受用 GPT-4 这种规模的模型来替代他们的搜索引擎,这将使他们的查询成本增加 100 倍。

推荐

推荐如下:

  • 保持清醒:用 ChatGPT-4 替代整个 IT 项目可能很诱人,但我们可以质疑项目的实际效用、使用语言模型的真实需求,并将其使用限制在真正需要的具体场景中。例如,尽可能使用比 GPT-4 小得多的模型。在使用(它)ChatGPT+之前要三思。

  • 优化训练和使用:在这一点上,技术众多,持续发展,数据科学家应当已经在使用它们……以降低成本。这些技术主要包括减少基础设施的使用,从而减少电力消耗,进而减少碳排放。本质上,我们只有在必要时才训练模型;如果确实需要训练,我们会规划以避免资源浪费。并且我们使用符合需求的最小模型。

  • 根据能源的碳足迹选择最佳国家来托管你的服务器。这里有法国的骄傲:我们主要依赖核能的碳足迹是美国的 7 倍低。然而,如果你们都开始在这里托管你们的语言模型,我们可能会从亲爱的邻国进口煤炭能源🔥。

  • 根据环境表现选择顶级云服务(这些数据有时是公开的;否则有工具来测量/估算,比如mlco2.github.io/impact/)——偏好那些使用服务器时间较长的云服务(然而超级大规模提供商通常不会将硬件使用超过 4 年),以及共享程度高的数据中心。

你是否有兴趣减少你的影响?

无论你是个人还是公司,资源和专家都可以帮助你走上可持续发展的道路。

在个人层面

  • 如果你想要评估你的碳足迹,网上有许多工具。个人而言,测量我的碳足迹让我大开眼界,促使我探索如何做出积极的影响。如果你在英国,请查看footprint.wwf.org.uk/

  • 快速了解气候变化背后的基础科学,可以参加 3 小时的课程:climatefresk.org/

  • 调查你可以采取的行动并估算它能减少多少足迹,可以参加另一个 3 小时的研讨会:en.2tonnes.org/

在企业层面

许多公司正在探索这些问题,以下是他们可以做的事情:

  • 教育员工(如上面建议的研讨会),

  • 执行审计 并测量他们的碳足迹

  • 制定策略以改善其 ESG(环境、社会和公司治理)评分

我得知这项出色的研究是通过一些我最近认识的优秀 人士了解到的,他们来自ToovaluWavestone。请查看他们的工作!

如果你发现我的估算有错误或想要添加你的观点,请评论并分享你是否觉得这篇文章有趣。

🙌 感谢你抽出时间阅读这篇文章,希望对你有所启发!非常感谢 Thibaut、Léo、Benoit 和 Diane 对这篇文章的宝贵反馈和补充 🙏。

如果你想了解生成式 AI 和负责任的机器学习的最新动态,请关注我在Linkedin 👋。

在大语言模型(LLM)时代平衡创新与安全性和隐私

原文:towardsdatascience.com/balancing-innovation-with-safety-privacy-in-the-era-of-large-language-models-llm-a63570e4a24a?source=collection_archive---------2-----------------------#2023-09-20

关于为你的生成式 AI 应用实施安全性和隐私机制的指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Anjan Biswas

·

关注 发表在Towards Data Science ·12 分钟阅读·2023 年 9 月 20 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由Jason Dent提供,拍摄于Unsplash

AI 时代已将大语言模型(LLMs)推向技术前沿,这在 2023 年引起了广泛关注,并可能在未来许多年内继续受到关注。LLMs 是像ChatGPT这样的 AI 模型背后的强大引擎。这些 AI 模型通过大量的数据和计算能力,实现了从生成类人文本到协助自然语言理解(NLU)任务的卓越能力。它们迅速成为了无数应用程序和软件服务的基础,或至少被用来增强这些服务。

然而,正如任何突破性创新一样,LLMs 的兴起带来了一个关键问题——“我们如何在追求技术进步的同时平衡安全和隐私的迫切需要?” 这不仅仅是一个哲学性问题,而是一个需要积极且深思熟虑的行动的挑战。

安全和隐私

为了在我们基于 LLM 的应用程序中优先考虑安全和隐私,我们将重点关注关键领域,包括控制个人数据(个人身份信息,即 PII)和有害或有毒内容的传播。无论是用自己的数据集对 LLM 进行微调,还是仅仅用于文本生成任务,这一点都是至关重要的。为什么这很重要? 有几个原因说明了它的重要性。

  • 遵守政府法规,保护用户个人信息(如GDPRCCPAHIPAA 隐私规则等)

  • 遵守 LLM 提供商的最终用户许可协议(EULA)或可接受使用政策(AUP)

  • 遵守组织内设定的 InfoSec 政策

  • 减少模型中可能存在的偏差和偏颇;进行后期微调

  • 确保道德使用大语言模型(LLMs)并维护品牌声誉

  • 为任何可能出现的AI 法规做好准备

微调的考虑因素

在准备对 LLM 进行微调时,第一步是数据准备。在研究、教育或个人项目之外,您很可能会遇到训练数据中包含 PII(个人身份信息)信息的情况。第一步是识别数据中是否存在这些 PII 实体,第二步是清理数据以确保这些 PII 实体被妥善匿名化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LLM 微调

文本生成的考虑因素

对于使用 LLMs 进行文本生成,需要注意几点。首先,我们确保任何包含有毒内容的提示不会传播到 LLM 中,其次我们确保提示中不包含任何 PII 实体。接下来,在某些情况下,可能适合对由 LLM 生成的文本进行这些验证,或者对“机器生成的文本”进行验证。这提供了双重保护,以确保我们的安全和隐私原则。第三个方面是确定提示本身的意图,这在一定程度上可以遏制诸如提示注入攻击等攻击。然而,我将主要关注 PII 和毒性问题,并在另一个讨论中讨论意图分类及其对 LLMs 的影响。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 LLM 进行文本生成

实现

我们将采取两步法来实现这一解决方案。首先,我们使用命名实体识别(NER)模型,该模型能够识别文本中的 PII 实体,并允许我们对这些实体进行匿名化。PII 实体通常包括个人姓名、地点或地址、电话号码、信用卡号码、社会安全号码等。其次,我们使用文本分类模型来分类文本是toxic(有毒)还是neutral(中立)。有毒文本的例子通常包括包含辱骂、粗言秽语、骚扰、欺凌等内容的文本。

对于 PII NER 模型,一个最常见的选择是BERT Base 模型,它可以进行微调以检测特定的 PII 实体。你也可以对预训练的transformer模型进行微调,例如Robust DeID(去标识化)预训练模型,它是一个RoBERTa模型,针对医疗笔记的去标识化进行了微调,主要关注个人健康信息(即 PHI)。一个更简单的选项是使用spaCy ER(EntityRecognizer)开始实验。

import spacy

nlp = spacy.load("en_core_web_lg")
text = "Applicant's name is John Doe and he lives in Silver St. \
        and his phone number is 555-123-1290"
doc = nlp(text)

displacy.render(doc, style="ent", jupyter=True)

这给我们提供了

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

spaCy 检测到的 PII 实体的标注

spaCy 的EntityRecognizer能够识别三个实体——PERSON(人名,包括虚构人物)、FAC(地点或地址)和CARDINAL(不属于其他类型的数字)。spaCy 还提供了检测到的实体的开始和结束偏移量(文本中的字符位置),我们可以利用这些信息进行匿名化。

ent_positions = [(ent.start_char, ent.end_char) for ent in doc.ents]

for start, end in reversed(ent_positions):
    text = text[:start] + '#' * (end - start) + text[end:]

print(text)

这给我们提供了

Applicant's name is ######## and his he lives in ###################and his phone number is ###-123-1290

但这里有一些明显的问题。spaCy ER 的默认实体列表并不涵盖所有类型的 PII 实体。例如,在我们的案例中,我们希望将 555-123-1290 识别为 PHONE_NUMBER,而不是将其视为文本的一部分,作为 CARDINAL 导致实体检测不完整。当然,就像基于转换器的 NER 模型一样,spaCy 也可以用您自己的自定义名称实体数据集进行训练,以提高其鲁棒性。然而,我们将使用 开源 Presidio SDK,它是一个更专门的工具包,旨在实现 数据保护去标识化

使用 Presidio 进行 PII 检测和匿名化

Presidio SDK 提供了一整套 PII 检测功能,并支持一长串的 支持的 PII 实体。Presidio 主要使用模式匹配,同时结合 spaCy 和 Stanza 的 ML 功能。然而,Presidio 是可定制的,可以插入使用基于转换器的 PII 实体识别模型,或者使用诸如 Azure 文本分析 PII 检测Amazon Comprehend PII 检测 的云基础 PII 功能。它还配备了一个内置的可自定义匿名化工具,可以帮助清理和编辑文本中的 PII 实体。

from presidio_analyzer import AnalyzerEngine

text="""
Applicant's name is John Doe and his he lives in Silver St.
and his phone number is 555-123-1290.
"""

analyzer = AnalyzerEngine()
results = analyzer.analyze(text=text,
                           language='en')
for result in results:
  print(f"PII Type={result.entity_type},",
        f"Start offset={result.start},",
        f"End offset={result.end},",
        f"Score={result.score}")

这给我们

PII Type=PERSON, Start=21, End=29, Score=0.85
PII Type=LOCATION, Start=50, End=60, Score=0.85
PII Type=PHONE_NUMBER, Start=85, End=97, Score=0.75

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Presidio 检测到的 PII 实体的注释

正如我们之前所见,由于我们拥有文本中每个实体的开始和结束偏移量,因此匿名化文本是一个相对简单的任务。然而,我们将利用 Presidio 的内置 AnonymizerEngine 来帮助我们完成这项任务。

from presidio_anonymizer import AnonymizerEngine

anonymizer = AnonymizerEngine()
anonymized_text = anonymizer.anonymize(text=text,analyzer_results=results)
print(anonymized_text.text)

这给我们

Applicant's name is <PERSON> and his he lives in <LOCATION>
and his phone number is <PHONE_NUMBER>.

到目前为止,这很好,但如果我们希望匿名化只是简单的掩码呢?在这种情况下,我们可以将自定义配置传递给 AnonymizerEngine,它可以对 PII 实体执行简单的掩码。例如,我们只用星号(*)字符来掩盖实体。

from presidio_anonymizer import AnonymizerEngine
from presidio_anonymizer.entities import OperatorConfig

operators = dict()

# assuming `results` is the output of PII entity detection by `AnalyzerEngine`
for result in results:
  operators[result.entity_type] = OperatorConfig("mask", 
                                 {"chars_to_mask": result.end - result.start, 
                                  "masking_char": "*", 
                                  "from_end": False})

anonymizer = AnonymizerEngine()
anonymized_results = anonymizer.anonymize(
    text=text, analyzer_results=results, operators=operators
)

print(anonymized_results.text)

给我们

Applicant's name is ******** and he lives in ********** and his phone number is ************.

匿名化的考虑事项

当您决定在文本中匿名化 PII 实体时,需要注意一些事项。

  • Presidio 的默认 AnonymizerEngine 使用模式 <ENTITY_LABEL> 来掩盖 PII 实体(如 <PHONE_NUMBER>)。这可能会引发问题,尤其是在 LLM 微调时。用实体类型标签替换 PII 可能会引入具有语义意义的词汇,从而潜在地影响语言模型的行为。

  • 伪匿名化是一个有用的数据保护工具,但在对你的训练数据进行伪匿名化时应谨慎。例如,将所有NAME实体替换为伪名John Doe,或将所有DATE实体替换为01-JAN-2000,可能会导致你微调后的模型出现极端偏差。

  • 注意你的 LLM 对提示中的某些字符或模式的反应。有些 LLM 可能需要非常特定的提示模板方式才能充分发挥模型的作用,例如,Anthropic 建议使用提示标签. 了解这一点将有助于决定你可能想如何进行匿名化。

匿名化数据对模型微调可能会产生其他一般副作用,例如上下文丧失语义漂移模型 幻觉等等。重要的是要进行迭代和实验,以确定适合你需求的匿名化程度,同时尽量减少对模型性能的负面影响。

通过文本分类进行毒性检测

为了识别文本是否包含毒性内容,我们将使用二分类方法——如果文本是中性的则为0,如果文本是有毒的则为1。我决定训练一个DistilBERT 基础模型(无大小写),这是一个BERT 基础模型的精简版本。训练数据使用了Jigsaw 数据集

我不会详细介绍模型的训练过程和模型指标等,但你可以参考这篇关于训练 DistilBERT 基础模型的文章进行文本分类任务。你可以在这里查看我编写的模型训练脚本。该模型可以在 HuggingFace Hub 中找到,地址是[tensor-trek/distilbert-toxicity-classifier](https://huggingface.co/tensor-trek/distilbert-toxicity-classifier)。让我们通过推断运行一些示例文本,看看模型会告诉我们什么。

from transformers import pipeline

text = ["This was a masterpiece. Not completely faithful to the books, but enthralling from beginning to end. Might be my favorite of the three.", 
        "I wish i could kill that bird, I hate it."]

classifier = pipeline("text-classification", model="tensor-trek/distilbert-toxicity-classifier")
classifier(text)

这给我们提供了—

[
  {'label': 'NEUTRAL', 'score': 0.9995143413543701},
  {'label': 'TOXIC', 'score': 0.9622979164123535}
]

该模型以相当高的置信度正确地将文本分类为NEUTRALTOXIC。这个文本分类模型,与我们之前讨论的 PII 实体分类结合起来,现在可以用于创建一个机制,以在我们的 LLM 驱动的应用程序或服务中执行隐私和安全。

综合考虑

我们通过 PII 实体识别机制解决了 隐私 问题,通过文本有毒内容分类器解决了 安全 部分。你可以考虑其他可能与贵组织的安全和隐私定义相关的机制。例如,医疗组织可能更关心 PHI 而不是 PII,等等。最终,无论你想引入什么控制措施,整体实施方法保持不变。

考虑到这一点,现在是将一切付诸实践的时候了。我们希望能够将隐私和安全机制与 LLM 结合使用,以便在我们希望引入生成式 AI 功能的应用中使用。我将使用流行的 LangChain 框架的 Python 版本(也可以在 JavaScript/TS 中使用)来构建一个包含这两种机制的生成式 AI 应用。这就是我们的总体架构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LangChain 的隐私和安全流程

在上述架构中,我首先检查文本是否包含有毒内容,模型准确率至少需达到 80% 以上。如果是,整个 LangChain 应用的执行会在此时停止,并向用户显示适当的消息。如果文本被大致分类为 中性,则我会将其传递到下一步以识别 PII 实体。如果这些实体的检测置信度得分超过 50%,我将对文本中的这些实体进行匿名化。一旦文本完全匿名化,它将作为提示传递给 LLM 进行模型的进一步文本生成。请注意,准确率阈值(80% 和 50%)是任意的,你需要在你的数据上测试两个检测器(PII 和有毒内容)的准确性,并决定一个适合你用例的阈值。阈值越低,系统变得越严格;阈值越高,检查的执行力度越弱

另一种更保守的方法是如果检测到任何 PII 实体,则停止执行。这对那些完全未获得处理 PII 数据认证的应用可能很有用,你希望确保无论如何,包含 PII 的文本不会作为输入被喂入应用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LangChain 的隐私和安全流程——备用流程

LangChain 实现

为了使其与 LangChain 配合使用,我创建了一个 自定义 叫做 PrivacyAndSafetyChain。这个链可以与任何 LangChain 支持的 LLMs 连接,以实现隐私和安全机制。这就是它的样子——

from langchain import HuggingFaceHub
from langchain import PromptTemplate, LLMChain
from PrivacyAndSafety import PrivacyAndSafetyChain

safety_privacy = PrivacyAndSafetyChain(verbose=True,
                                       pii_labels = ["PHONE_NUMBER", "US_SSN"])

template = """{question}"""

prompt = PromptTemplate(template=template, input_variables=["question"])
llm = HuggingFaceHub(
    repo_id=repo_id, model_kwargs={"temperature": 0.5, "max_length": 256}
)

chain = (
    prompt 
    | safety_privacy 
    | {"input": (lambda x: x['output'] ) | llm}
    | safety_privacy 
)

try:
    response = chain.invoke({"question": """What is John Doe's address, phone number and SSN from the following text?

John Doe, a resident of 1234 Elm Street in Springfield, recently celebrated his birthday on January 1st. Turning 43 this year, John reflected on the years gone by. He often shares memories of his younger days with his close friends through calls on his phone, (555) 123-4567\. Meanwhile, during a casual evening, he received an email at johndoe@example.com reminding him of an old acquaintance's reunion. As he navigated through some old documents, he stumbled upon a paper that listed his SSN as 338-12-6789, reminding him to store it in a safer place.
"""})
except Exception as e:
    print(str(e))
else:
    print(response['output'])

默认情况下,PrivacyAndSafetyChain 首先执行毒性检测。如果检测到任何有毒内容,它将会报错,从而如前所述,停止链条。如果没有检测到,它将把输入的文本传递给 PII 实体识别器,并根据使用的掩码字符,链条将对检测到的 PII 实体进行文本匿名化。前面的代码输出如下所示。由于没有有毒内容,链条没有停止,它检测到了 PHONE_NUMBERSSN 并正确地进行了匿名化。

> Entering new PrivacyAndSafetyChain chain...
Running PrivacyAndSafetyChain...
Checking for Toxic content...
Checking for PII...

> Finished chain.

> Entering new PrivacyAndSafetyChain chain...
Running PrivacyAndSafetyChain...
Checking for Toxic content...
Checking for PII...

> Finished chain.
1234 Elm Street, **************, ***********

结论

本文的最大收获是,随着我们继续在大型语言模型方面进行创新,平衡创新与安全和隐私变得至关重要。围绕 LLM 的热情以及我们对将其与各种可能用例整合的不断增长的渴望是不可否认的。然而,潜在的陷阱——如数据隐私泄露、无意的偏见或滥用——同样真实,值得我们立即关注。我介绍了如何建立一个检测 PII 和有毒内容的机制,并讨论了与 LangChain 的实现。

仍然有很多研究和开发工作待完成——或许需要更好的架构、更可靠和无缝的数据隐私和安全保障方式。本文中的代码经过简化以便于说明,但我鼓励你查看我的 GitHub 仓库,在这里我整理了每个步骤的详细笔记本以及我们讨论的自定义 LangChain 的完整源代码。使用它、分叉它、改进它,前进并创新!

参考文献

[1] Jacob Devlin, Ming-Wei Chang 等人 BERT: 语言理解的深度双向变换器预训练

[2] Victor Sanh, Lysandre Debut 等人 DistilBERT, BERT 的蒸馏版本:更小、更快、更便宜、更轻量

[3] 数据集 — Jigsaw 多语言毒性评论分类 2020

除非另有说明,所有图片均由作者提供

作为分析团队在紧急性与可持续性之间取得平衡

原文:towardsdatascience.com/balancing-urgency-vs-sustainability-as-an-analytics-team-69b98a1775aa

关于如何有效应对即时报告请求以确保未来工作的指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Matthew Gazzano

·发表于 Towards Data Science ·阅读时间 7 分钟·2023 年 10 月 22 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Carlos Muza 提供,来源于 Unsplash

在数据分析的动态世界中,及时响应数据查询是一个常见的挑战。无论是经理的临时请求、即将召开的董事会会议,还是执行团队突然提出的、之前被忽视的问题,分析师和一线从业者常常发现自己被卷入紧急报告需求的交火中。虽然这对那些实际需要提供分析的人来说可能是令人沮丧的,但我们不能总是指责高层或中层管理没有提前通知业务问题。

那么,你如何为这些情况做好准备并将其影响降到最低呢?是否有适当的时机来推迟这些请求?

好吧,就像数据科学中的每个响应一样——这要看情况。这些情况常常对团队领导的领导能力提出了真正的考验,突显了与利益相关者保持良好关系以及深入了解商业模型以促进迅速行动的重要性。但是,通过遵循成熟的开发和组织框架,你可以使你的团队对这些情况做好充分准备。

这是我在职业生涯中学到的如何最好地应对这些情况的方法。

停下来反思。这个指标是否已经在其他地方存在?

利益相关者可能不知道你团队生成的所有报告。当一个紧急请求进入他们的收件箱时,他们的第一反应可能是分析需要从头开始构建。这是可以理解的,因为领导者不需要了解你的 BI 环境的细节。

退一步,评估领导层的需求,并识别可以利用的现有业务逻辑。通常,领导者会提出相同的业务问题,只是以不同的变体、筛选标准或针对不同的群体。这可能是进一步解释现有仪表板、指标或模型背后的业务背景的过程。

2 次规则

假设所需的指标在其他地方不存在,并且组织必须立即回答这个临时问题。那么你和你的团队继续执行请求,提取所需数据以回答问题。然而在接下来的一周,你的利益相关者回来询问同一报告请求的更新,并要求刷新底层数据。在这种情况下,可能是推迟立即回答并花时间构建更可扩展解决方案的合适时机。

简而言之,“2 次规则”认为第一次请求应当是完全临时的,分析团队可以以“快速而粗略”的方式提供答案。但任何后续请求意味着这是业务的常规需求,应当视为一个可扩展的项目。在这种情况下,不将这个问题构建成一个可扩展的仪表板或模型将对所有相关方产生不利影响。以下是原因:

  • 商业问题的回答和更新保持一致,并且是每日进行的。

  • 领导者可以在可靠的时间表上获得他们所需的即时答案。

  • 分析团队可以利用他们的技能集中于更有影响力的工作。

作为任何分析团队的经理或主要贡献者,按需划定工作范围非常重要。利益相关者可能不知道什么是他们问题的最佳实际解决方案(即 Excel 工作簿、仪表板、保存为 pdf 的 Jupyter Notebook),也没有责任去了解。对于处理较小报告请求的部门领导来说,Excel 通常是主要工具——通常是在数据静态的环境中,需要从底层源系统导出并手动操作以总结数据透视表。由于以领域为重点的利益相关者通常不使用高级工具,分析师/团队负责人也需要确定适当的工具来回答业务问题。

利用这一经验为未来的报告做准备。

一旦情况明朗,找到时间在报告交付后与利益相关者会面,讨论引发即时需求的原因。通过这种方式,你应该了解你和你的团队如何在未来构建报告,以更好地应对这些情况。

思考可能需要回答的相关问题

比如说,你被要求了解自新销售举措开始以来获得了多少新客户。你最初的报告请求可能是将每个客户按地区分类,或展示一个累积每日客户增长的时间序列图表。但每当你提供有效的分析时,它都会引发领导层的进一步讨论(这也是你可以验证自己输出质量工作的方式)。这也意味着你应该准备好深入挖掘你初步分析的“为什么”和更大影响。

换句话说,基于你刚刚提供的结果,你认为还有什么与其对组织的影响相关的信息?我不仅指的是添加额外的维度字段来重新分类相同的指标。而是说,还有哪些其他视角对提供关于你正在回答的业务问题的完整背景也很重要?

从这个例子中,另一个值得考虑的想法可能是将新的销售举措与客户流失进行比较。你可能会显示新举措带来了新客户,但这如何影响你客户基础的净增长呢?你也可能需要考虑转化率。在这种情况下,不同客户细分的平均转化率是多少?最后,对于未能转化的客户,他们表示不感兴趣的原因是什么?

当然,你不能让仪表盘/报告充斥着无尽的关键绩效指标,因为你将无法有效传达信息。然而,你需要挑选和选择如何框定业务问题的完整背景,以便与利益相关者相关联。

站在利益相关者的角度考虑问题

你对利益相关者的关注点、角色和观点理解得越透彻,你就越能为他们未来的仪表盘或模型做好准备。所有分析师与利益相关者团队紧密合作,理解他们领域中的具体细微差别/挑战,对大家都有好处。例如,你的运营团队是如何记录订单的?在准确计算不同 SKU 编号的履行时间方面存在哪些挑战?

当你能更好地理解利益相关者在组织中的角色时,你更有可能像他们一样提问业务方面的问题。我曾与许多优秀的分析经理合作,他们在利益相关者提出要求之前就能很好的确定仪表板中哪些内容对他们最有用。在一个场景中,我的团队正在准备一个产品收入报告以备董事会会议使用,我们被管理层给出了非常具体的指示,要求我们构建什么样的视觉效果。我问我的一位经理:

“你如何构思/真正预测董事会会希望在我们的产品更新分析中看到什么?”

以及他们的回应(简述):

“将自己置于他们的角度,想象一下如果是你的钱投资到我们公司。我们的董事会花费了 XXX 美元来资助这一新产品计划,因此他们希望了解相关的成功指标,以确保能够看到回报。”

这种回应可能显得过于简化,但我可以向你保证,这种视角很容易被个体贡献者忽视。作为分析师,可能更容易集中在解决方案背后的代码上,逐一回答提供的问题。我们在这种视角中时,最好退后一步,从整体上理解为什么我们要回答某个特定的业务问题。

关注“公司新闻”

分析经理还应关注公司的新计划和不断变化的竞争挑战。这有助于团队发现提供有效报告解决方案的简便机会,这些方案可能与“当前热门”相关。

让我们参考一个真实的例子—— 你可能还记得苹果 IOS 14.5 版本发布的影响,这一版本发布于 2021 年 4 月 26 日。在此次更新中,他们在 iPhone 上实现了一项新的隐私功能,其中弹出消息提示用户是否同意跟踪其个人数据。实际上,当 iPhone 用户选择不提供个人信息时,这对像 Meta(当时为 Facebook)这样的科技巨头广告收入构成了重大威胁,因为这意味着他们无法像以前那样有效地为每个用户进行广告变现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者拍摄的照片 — IOS 14.5 安全信息截图

现在,假设在 Meta 的数据科学团队工作时,这个消息刚从苹果公司宣布出来。你可以想象,扎克伯格会想要一些立即的答案,关于这将如何影响 Facebook 的广告收入。

假设现在有一个现有的仪表板显示不同细分市场的每用户平均广告收入。在听到这个消息后,将一个切换开关/基准添加到该仪表板中,显示该 iOS 功能如何影响这些现有指标将会很有益。这样,你可以在它成为管理层紧急请求之前,规划如何正确构建这个仪表板。

结论

掌握平衡紧迫性和可持续性在分析中的艺术不仅仅是响应即时报告请求,还包括构建一个强大且具有前瞻性的数据显示策略。通过理解你的利益相关者,在适当的时候向管理层设定边界,并积极准备未来的报告需求,你可以使你的团队能够推动有影响力的分析。拥抱组织的动态性质,并保持领先于行业趋势,也将确保你总是为可能出现的挑战做好准备,使你的团队成为数据驱动决策的不可或缺的资源。

Bash 处理速度很重要

原文:towardsdatascience.com/bash-processing-speed-matters-d83e4c5adf32

我将 bash 命令行的执行速度提高了 500 倍以上,使其变得非常方便使用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Mattia Di Gangi

·发表于Towards Data Science ·阅读时间 5 分钟·2023 年 3 月 30 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chris Liverani拍摄,发布在Unsplash

当你需要处理文本或表格形式的数据时,长期以来的一个受欢迎选择肯定是GNU Bash,这是具有“内置功能”的 Linux 旗舰 shell。如果你从未使用过它,你错过了很多,绝对应该尝试一下。

Bash 附带的工具遵循 Unix 哲学“只做一件事,并做好它”,并且对许多不同的任务进行了超级优化。Findgrepsedawk只是一些能够通过 Bash 的管道和过滤器架构进行互操作的强大工具,用于文本文件处理。

最近,我需要执行简单的文本处理,bash 非常适合这个任务。我有一个输入文件,每行包含一个绝对文件路径,我需要生成一个输出文件,每行是输入文件中对应路径的基本名称,并有不同的扩展名。实际上,这两个文件作为输入传递给另一个程序,该程序将把输入文件中提到的文件(wav 格式)转换为输出文件中列出的文件(mp4 格式,通过添加一些视频)。

我本可以用 Python 完成这项任务,但对于这个任务来说,bash 看起来更实用。不过,在这个故事的最后,我会展示一个 Python 实现以供比较。然后,我急忙走到键盘前,完成了以下内容:

$ cat input.txt | while read line; do echo $(echo $(basename $line) | sed "
s/.wav/.mp4/") >> output.txt; done

代码是正确的,但极其慢。我的文件有 300 万行,这个命令需要 1 小时才能完成。为了了解每秒处理的行数,让我在一个包含 10000 行的文件上运行它并测量其运行时间。

$ time cat input.txt | while read line; do echo $(echo $(basename $line) | sed "
s/.wav/.mp4/") >> output.txt; done

real    0m13.297s
user    0m19.688s
sys     0m1.881s

一些明显的低效之处包括使用 cat 启动命令,以及 echo 的双重使用(带有嵌套的命令调用)。它们都是 I/O 密集型操作,因此非常慢。它们可以被轻松替换,而且由于我们知道输入文件中的所有路径都具有相同的扩展名,我们还可以去掉 sed,直接使用 basename 进行扩展名的移除。然后,我们用相同的 10000 行的文件运行新命令:

$ time while read line; do name=$(basename $line .txt); echo ${name}.mp4 >> output.txt; done < input.txt

real    0m6.626s
user    0m5.723s
sys     0m1.131s

在这里我们有了显著的改进。仅去掉 cat,我们得到了不到 13 秒的实际时间(相对改进 ~2%),其余的通过用 basename 替换 sed 和第二个 echo 完成。不幸的是,它仍然相当慢。以大约 1500 行/秒的速度完成 3,000,000 行需要 2000 秒,即大约 30 分钟。幸运的是,我们可以通过替换 read 获得显著的提升。Read 从标准输入读取一行并将其内容分配给一个或多个变量(它可以很容易地与表格数据一起使用),但在我们的情况下并不需要,因为逐行处理是任何 bash 命令都在做的事情。

不幸的是,我们不得不放弃方便的 basename 以仅提取文件名,但我们可以用 cut 替代它,cut 可以根据分隔符删除文本片段,以及 rev ,它只是反转字符序列——这是用 cut 提取最后一个字段的常用技巧,默认情况下这是不可行的。

执行的操作数看起来比之前更多,但我们最终获得了巨大的加速,如我们在示例玩具文件中看到的:

$ time rev input.txt | cut -d/ -f1 | rev | sed "s/.wav/.mp4/" >> output.txt

real    0m0.011s
user    0m0.010s
sys     0m0.013s

以 ~910 Klines/秒的新速度,我们可以在 3.3 秒内处理 3,000,000 行,相当于 606 倍的加速。

最重要的是,虽然实际的数字取决于执行命令的硬件,但不同硬件之间的相对改进将保持一致。

Python 实现

这里我们可以看到一个等效的 Python 实现以供比较:

# convert.py
import os
import sys

def convert(tgt_ext: str):
    for line in sys.stdin:
        base, _ = os.path.splitext(os.path.basename(line))
        print(base + tgt_ext)

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} TARGET_EXT")
        sys.exit(1)

    convert(sys.argv[1])
    exit(0)

现在我们可以测量它的时间:

$ time python3 convert.py .mp4 < input.txt > output.txt

real    0m0.022s
user    0m0.021s
sys     0m0.000s

而且这个实现的时间大约是我们用 bash 得到的最佳时间的两倍。它需要编写更多的代码,但这些代码非常快速,而且可能更容易为许多人进行修改。

结论

Bash 在处理文本文件的许多数据处理任务时非常方便。它配备了许多经过高度优化的工具,但仍有些工具在实现相同结果时比其他工具更快。当处理短文件时,这种差异可能不重要,但在这篇文章中,我展示了当文件有成千上万行或数百万行时,这种差异开始变得重要。

了解我们喜欢的程序的性能影响可以节省我们等待工作的时间,并显著提高生产力。此外,我们看到尽管 Python 以慢著称,但在我们的用例中,Python 实现也非常快速。它确实需要更多的编码,但也更灵活。我肯定会选择 Python 来处理那些用 bash 解决起来过于复杂的情况。

感谢你阅读到这里,祝你编程愉快!

更多我的内容

## 不再拖延:自动化开发环境和构建

通过环境和构建自动化使你的软件易于使用,给你的同事带来快乐。与…

## 数据处理自动化与 inotifywait

如何在拥有一个生产就绪的 MLOps 平台之前进行自动化

## 动态添加参数到 Argparse | Python Patterns ## 语音增强介绍:第二部分 — 信号表示

如何使用 argparse.ArgumentParser 根据用户输入指定不同的参数。

## 数据处理自动化与 inotifywait ## 语音增强介绍:第二部分 — 信号表示

让我们深入探讨信号表示、傅里叶变换、频谱和谐波。

## 语音增强介绍:第二部分 — 信号表示

Medium 会员

你喜欢我的写作,并考虑订阅 Medium 会员以获得无限访问文章的权限吗?

如果你通过这个链接订阅,你将以不增加额外费用的方式支持我 medium.com/@mattiadigangi/membership

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值