TowardsDataScience-博客中文翻译-2022-二十九-

news/2024/10/18 9:30:50

TowardsDataScience 博客中文翻译 2022(二十九)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

如何使用计算机视觉读取酒瓶上的标签?(第一部分)

原文:https://towardsdatascience.com/how-to-read-a-label-on-a-wine-bottle-using-computer-vision-part-1-25447f97a761

欢迎阅读本系列文章,在这里我将解释我构建第一个计算机视觉项目的历程。这里的目标是让计算机从一张简单的照片上读出一瓶酒的标签。你可能会问,为什么这很复杂?首先,我们不能直接调用像 tesseract 这样的 OCR(光学字符识别)库,因为标签上的文本在圆柱体上是扭曲的,正因为如此,我们不能正确地提取字符,从而提取单词和句子。

为了实现这一点,我们需要将我们的问题分解成不同的具体任务,以成功地阅读写在酒瓶标签上的内容。但首先我们需要向我们的机器解释什么是酒瓶标签,以及如何检测它。

第 1 部分—检测标签,图像处理方法

在我最初的研究阶段,我偶然发现了一个很棒的 mathematica 论坛帖子,作者试图做或多或少相同的任务,但是是在果酱罐上。在这个过程中,作者使用不同的图像处理技术来尝试定位标签的位置。所以我当然尝试用 python、opencv 和我自己的酒瓶照片来复制这个。让我们以这张照片为例:

首先,从计算机视觉的角度来看,这张照片有一个巨大的好处:标签和背景之间有很多对比度,如果我们试图用图像处理来分离标签,我们可以希望得到一些好的结果。

因此,让我们开始检测标签的位置:首先,我们将图像转换为灰度,并应用一个自适应阈值函数来帮助我们简化图像的结构。只考虑图像的对比度。

该自适应阈值功能参数对该方法的成功非常重要,目标是获得标签周围的粗轮廓线。我必须迭代并找到适合我的参数:{blockSize : 35,C : 4}。

一旦这样做了,下一步我发现有用的是模糊图像一点点,以平滑图像轮廓,并应用一个简单的二进制阈值,只得到白色和黑色。在这些步骤中,参数也是手动调整的,以获得可能的最佳结果。

一旦我们可以清楚地看到标签的轮廓,我们可以希望 opencv 上可用的 Canny 函数将在我们的图像上绘制所有检测到的边缘,并允许我们通过使用按最大面积排序的 findCountours 函数来精确选择它的位置:

在这里,我们成功地找到了我们的标签的相对位置,所以我们可以开始工作,并希望阅读上面写的东西!

…等等,让我们先在其他照片上试试我们的算法,当然它也适用于其他图像。

…是的,它对其他图像根本不起作用,因为每个上下文都是唯一的,我们的算法是参数化的,以对我们最初选择的图像起作用。在我的下一篇文章中,我将在神经网络魔法的帮助下,为这个问题找到一个系统化的解决方案,在一个广义的环境中更好地工作!

与此同时,你已经可以在我的网站上亲自尝试该项目的当前版本的现场应用,只需用你的智能手机连接到该网站,上传一张照片,等待一分钟,你应该会得到结果。

[更新]下面是第 2 部分的链接:https://medium . com/@ leroyantonin . pro/how-to-read-a-label-on-a-a-a-wine-bottle-using-computer-vision-part-2-8bd 047 D2 a945

所有图片均由作者

如何使用计算机视觉读取酒瓶上的标签?(第二部分)

原文:https://towardsdatascience.com/how-to-read-a-label-on-a-wine-bottle-using-computer-vision-part-2-8bd047d2a945

欢迎阅读本系列文章,在这里我将解释我构建第一个计算机视觉项目的历程。这里的目标是让计算机从一张简单的照片上读出一瓶酒的标签。在我们的上一篇文章中,我们尝试了一种非常直接的方法,用 python 和 OpenCV 图像处理技术来检测我们的葡萄酒标签,我们发现在一组不同的照片上检测葡萄酒标签还不够好。

对于这个项目的第二部分,我们将尝试其他方法来解决这个问题,我们将尝试建立一个神经网络,它可以基于监督方法来识别标签的位置。

第 2 部分—检测标签,神经网络方法(U-net)

在我第一次尝试第一种方法失败后,我开始怀疑我是否能找到一种只使用 OpenCV 的方法,当我偶然发现一个论坛帖子时,有人正试图做几乎和我一样的事情,除了邮件上的标签。这个问题的一个回答引起了我的注意:

一个只有 5 个标记样本的 U-Net 将很容易检测到它。你只需屏蔽标签区域,通过一些良好的增强,如随机旋转/翻转/扭曲,你将获得可靠的结果,你可以稍后使用findContoursboundingRect预测屏蔽。

然后我开始研究 U-net 以及如何实现它。基本上,我必须为训练集中的每个标签形状图像(X)手动创建一个相应的黑白遮罩(U-net 的目标),如下所示:

有趣的部分开始了,我总共花了 2/3 个小时的 photoshop 来制作 163 张照片的标签蒙版!完成后,我找到了这个网络架构的 tensorflow 实现。以下是来自维基百科的网络架构描述:

这个网络由一条收缩路径和一条扩张路径组成,这使它具有 u 形结构。收缩路径是一个典型的卷积网络,它由重复应用的卷积组成,每个卷积之后是一个整流线性单元 (ReLU)和一个最大汇集操作。在收缩期间,空间信息减少,而特征信息增加。扩展路径通过一系列上卷积和连接将特征和空间信息与来自收缩路径的高分辨率特征相结合。

这是 tensorflow 实现的样子(忽略配置文件,它是我为自己的包设置的):

我在我自己的 NVIDIA GeForce RTX 3060 上训练网络。大约 10 分钟后,验证准确度开始收敛到 99%左右。

张量板训练可视化

让我们在一些样本照片上测试我们的模型,看看我们的网络在真实条件下表现如何。

样本外预测示例

正如您在这里看到的,一切都按预期工作,网络的输入必须经过一点点预处理,才能成为方形,并且是 BGR 彩色格式。一旦获得预测掩码,我们只需要调整它的大小,以获得标签的像素坐标(白色像素)。

样本外预测示例

在这里,除了被误认为是标签一部分的小光点之外,网络也工作得相当好。

样本外预测示例

在这个例子中,瓶子旁边有一本书,我们看到网络变得混乱,并将它的一部分包含到标签的形状中。即使这是一个非常健壮的方法,仍然有一些改进的空间。对于这个项目,我将使用这种方法来检测标签,并尽可能避免这样的错误,我会给出摄影指南(中心标签/无旋转/良好的照明/良好的背景对比度),以尽量减少网络的错误。

这就是第 2 部分的全部内容。如果你想了解更多关于 U-net 是如何设置的,并探索代码,你可以查看位于 https://github.com/AntoninLeroy/wine_label_reader_toolkithttps://github.com/AntoninLeroy/wine_label_reader_toolkit的 GitHub 项目资源库

在下一篇文章中,我们将尝试找到一种方法来使我们的标签圆柱体变平,以便能够用 OCR 库读取它,敬请关注!

我们的实时应用程序仍然可以在:https://plural.run/wineReader

【更新】第三部出来了!点击这里。

所有图片均由作者提供

如何使用计算机视觉阅读酒瓶上的标签(第三部分)

原文:https://towardsdatascience.com/how-to-read-a-label-on-a-wine-bottle-using-computer-vision-part-3-e4729e5a8140

欢迎回到本系列文章。提醒一下,在我们的前两篇文章(第一部分、第二部分)中,我们探索了两种不同的方法来尝试检测酒瓶上标签的位置。

在项目的当前阶段,我们能够将酒瓶的照片输入到我们训练过的 U-Net 型神经网络,并获得黑白蒙版作为输出,该蒙版定位标签的估计位置:

预测的例子

下一个具有挑战性的步骤是移除标签上的所有曲率,这样我们就可以对我们的扁平化标签应用 OCR,并成功检测上面写的单词和句子。

在我的研究过程中,我有机会偶然发现了一个很棒的 github 项目,它是由阿列克谢·赞克维奇完成的。在使用他的库和写这篇文章之前,有必要提一下**,我请求他正式授权使用他的代码,并在这篇文章中提到他的工作**。

我不会详细解释他的库是如何工作的,因为我根本没有编码它,我也不掌握他使用的几何概念,但简单地说,这个库允许通过在标签圆柱体边缘周围手动定位 6 个点来“解开”葡萄酒标签。然后,代码生成并映射许多点,这些点遵循估计的圆柱体几何形状,并使用 scipy 库将这些点的插值应用到几何形状平坦的目标地图。通过这样做,我们得到了一个平面标签的视觉近似。

问题是,我们需要找到一种方法来自动定位我们的 U-Net 图像预测上的这 6 个点。让我们举一个我们会用到本文结尾的照片例子:

原始 256*256 U_net 预测

一旦我们得到了我们的 U-net 预测,我们需要将它重新整形回原始源照片的大小,这样,一旦我们找到了我们的 6 点坐标,我们就可以将它们正确地放置在原始照片中。此外,我们希望标签垂直对齐,我们只想要二进制颜色(黑色或白色像素)。为此,我们使用包的 readLabels 方法中的这段代码。

调整大小、二值化和对齐的 U-net 预测

关于我实现的垂直对齐算法说几句,它只是试图最大化全黑列的数量,所以在这里你可以看到我们不能说对齐是完美的,因为圆柱体形状的一些不完美的检测,但我选择不采用完美的例子来表明它在不完美的情况下工作。

现在让我们来谈谈我是如何估计和定位我们需要使用展开标签代码的 6 个点的。我的想法是先找到一种迭代的方法来检测角,因为在垂直对齐算法中,我使用了“全黑列”的逻辑作为继续迭代的条件,所以基本上:从一边扫描到另一边,只要有一列至少有 1 个白色像素就停止,等等。但问题是,我没有用这种逻辑找到所有的角,因为通常圆柱体都有透视,因此顶部或底部比另一个大…

然后我想起了矩阵对角线!如果我能找到一种像这样用对角线迭代的方法,而不是用列和行迭代,会怎么样呢?

拐角/边缘检测逻辑

这样我就能找到 A,C,D 和 F 坐标点的对角线,并通过计算简单的距离找到 B 坐标:

其中 XB 是点 b 的 X 坐标。我们现在可以选择对应于该 XB 位置的图像的列向量(λ):

是的,我知道这是一个疯狂的非正统的数学符号

我们在向量中从上到下迭代,找到第一个白色像素来减去 B 点的 Y 坐标。

对于 E 点,逻辑是相同的:我们在 D 点和 F 点的中间找到列向量,这次我们从下到上迭代,直到找到第一个白色像素。

要获得实现的细节,请查看包中的方法【getCylinderPoints】

现在我们有了 6 个坐标,我们可以使用“展开标签”代码。

网状圆柱投影

展平标签

TADA!最后,我们现在有了一个几乎完美的平面标签,可以尝试在上面应用 pytesseract OCR 库。为了看到原始(弯曲的)图像和展平的图像之间的差异,我把两个 OCR 副本放在一起,以证明我们没有白做这些工作!

原始图像 OCR:

酱汁控制

DE RESERVE
_ftes Lo
2020

法国产品的所有者

展平标签图像 OCR:

索穆尔市所有人盖泰·德索穆尔

奥穆尔

索默控制器

DE 储备

2020

法国产品

所以它绝对不是完美的,但肯定有所改善。照片本身有一些照明差异,似乎会影响光学字符识别。以下是我测试的其他几个例子:

原始图像 OCR:

R
ORDEAUX SUPER!

伊利厄

APDE 波尔多特级葡萄酒

展平标签图像 OCR:

从 5 月 8 日开始

一天

边境安全

穆林-德茹尔

+S a

(一氧化碳)

波尔多特级葡萄酒

波尔多特级酒庄

原始图像 OCR:

帕夫
| i YS dD' :
= UE e :
:桑斯 SUL
:艾特斯阿约特斯
ARD 贝特朗在

栅栏
oL0 oul

便便

:

p
R
O
D
U
IT
DE F
RA

新天主教版本(New Catholic Edition)

展平标签图像 OCR:

MS22338

2020

西拉·罗斯

支付现金

无亚硫酸盐葡萄酒

CEeRTiFre

杰拉德·贝特朗

农业

法国产品= sos:

我想我们已经完成了我的第一个计算机视觉项目的系列文章。您可能已经发现了这一点,它远非完美,有些步骤还可以优化:

  • 拐角/边缘圆柱体检测是我提出的解决这个算法任务的一种方法,但是我确信也许可以找到另一种解决方案。
  • 在我看来,OCR 部分本身是一项非常懒惰的工作,它可以通过使用默认配置之外的其他配置进行更好的优化,并可能增加一个图像处理步骤来减少可能产生一些噪声的阴影/照明或背景对象。
  • 标签形状检测 U-Net 在预测方面远非完美,经常无法找到几何上正确的圆柱体,我相信实验计算机视觉工程师会找到一种方法,通过更多的深度学习工作或图像处理技术来提高其效率。

如果您有一些改进此解决方案的建议,请随时评论或联系我。你可以在https://plural.run/wineReader用你自己的酒瓶照片测试这个应用程序(记住,它们应该有一个好的分辨率,尽可能少的透视和与标签高对比度的背景)。

所有图片均由作者提供。

如何阅读熊猫中的卡夫卡点击流事件数据

原文:https://towardsdatascience.com/how-to-read-kafka-clickstream-event-data-in-pandas-96f50e88f7eb

构建 Kafka 消费程序以读取 Jupyter 笔记本中特定日期范围内的事件数据

照片由乔纳森派在 Unsplash 上拍摄

背景

最近,我被分配了一个看似简单的任务→

“我们开始从一个新的应用程序中捕捉事件。你能证明这样的测试事件在卡夫卡那里是正确的吗?”

我对我们系统中的数据流有一个粗略的想法:从 Web 和移动应用程序收集的点击流数据将首先流向 MetaRouter,然后 MetaRouter 作为 Kafka 生产者,为某个 Kafka 主题生成事件日志。我们的新应用程序生成的事件有一个共享的writeKey。因此,为了阅读这些事件,我需要:

  1. 创建一个卡夫卡消费者来听这个卡夫卡话题
  2. 因为我知道这样的测试事件是在特定的日期范围内产生的,所以我想为指定的日期构建 Kafka 消费者只读事件。
  3. 以一种我可以过滤和分析的方式存储数据,最好是在熊猫的数据框架中。

所以我的目标是实现卡夫卡->熊猫的数据流!

在谷歌搜索了 StackOverflow、GitHub 和各种网站很多天后,我终于让它工作了!下面是我关于如何在 Kafka 的两个最流行的 python 库中实现的代码片段。

解决方案 1:使用“kafka-python”库

必备: pip install kafka-python(我的笔记本用的是最新版本 2.0.2)

首先,我们需要导入下面的库和 Kafka 环境变量。下面的设置脚本可以在解决方案 2 中重复使用,只需稍作修改。

接下来,构建一个 Kafka 消费程序来读取特定日期时间范围内的事件。有 5 个步骤:

  • 步骤 1 :因为我知道测试事件是在 2022–09–22 之间的 12 点至 14 点(UTC)时间发送的,所以我使用datetime函数创建dt_startdt_end来限定时间范围。
  • 第二步:在 Kafka 中,只有来自同一个分区的事件才是有序的,所以我们需要从指定的分区读取事件。(假设您有 6 个主题分区,您可以从 0-5 中选择任意一个数字作为分区)。
  • 第三步:基础消费者要求topicbootstrap_serversgroup_id。我发现在 Jupyter 笔记本中,如果我不提供security_protocol它就会抛出错误。
  • **第四步:**这是关键!它的工作方式是这样的:
    • datetime 对象→转换为 UTC 时间戳(单位为毫秒)→转换为主题分区中的相关偏移量
      -基本函数是consumer.offsets_for_times({tp:dt_start.timestamp()*1000})
  • 步骤 5: 使用seek获取从期望的开始时间
    开始的事件——每个消息都有一个属性offset,我们将它与期望的结束时间偏移进行比较,以决定是继续还是中断

说够了,下面是完整的代码→

之后,我可以在熊猫里查询我们新应用的writeKey!🐼

上述解决方案受到 StackOverflow 的类似问题的启发。实际上,这是我开始做大量搜索的地方,发现没有使用confluent-kafka的等价解决方案。由于我的原始代码是基于confluent-kafka而不是kafka-python,我对它们表面上的相似性和细微差别感到困惑。

现在我很高兴使用confluent-kafka介绍我自己的解决方案😃~~~

解决方案 2:使用“汇合-卡夫卡”库

先决条件: pip install confluent-kafka(我的笔记本用的是最新版本 1.9.2)

在这里,您可以使用解决方案 1 中的相同设置脚本,只需稍作修改:

  • 将第 10 行改为from confluent_kafka import Consumer, TopicPartition

接下来,我们需要构建一个 Kafka 消费者来读取特定日期时间范围内的事件。在高层次上,我们仍然需要同样的 5 个步骤,但是主要的区别是我们需要使用on_assign来实现seek所做的——从主题分区中获取特定的偏移量。

步骤 1: 和解决方案 1 一样,我们需要 datetime 对象来限定搜索范围。

第二步:同方案一。一个比较棘手的事情就是大部分时候你可以用 string 作为 topic 比如topic = 'analytics__pageview',但是当你要subscribe的时候,它只接受一个 list 比如consumer.subscribe(['analytics__pageview'])!(就像邓布利多可能会说的:“多么希望如此~ ~”🧙

步骤 3: 除了将变量赋值中的=替换为:之外,几乎与解决方案 1 相同。

**第四步:**下面是你将看到的细微差别!我们需要一个额外的步骤4c来建造on_assign。而这个功能最初是来自 Magnus Edenhill 提供的github confluent-Kafka-python issue。

步骤 5: 这里我们不使用seek,而是使用subscribe和主题(列表形式)以及on_assign来获取所需开始时间的偏移量。而且取数后我们需要调用close()

还有一个值得注意的细节是,如何得到偏移量。

kafka-python中,你用的是offset_start[tp].offsetoffset_start是字典。

offset_start = consumer.offsets_for_times({tp:dt_start.timestamp() * 1000})# to print out the offset number
offset_start[tp].offset

输出:(注意表示类型的是 dict)

confluent-kafka中,offset_start是一个列表,所以需要使用offset_start[0].offset

tp_in = TopicPartition(topic=topic, partition=partition, offset=int(dt_start.timestamp() * 1000))offset_start = c.offsets_for_times([tp_in])# to print out the offset number
offset_start[0].offset

输出:(注意[ ]表示类型是 list)

好的,这是实现confluent-kafka的完整代码

摘要

  • 构建事件驱动的应用程序是一种趋势,我预见到对数据科学家能够快速处理和对事件数据进行简单探索分析的需求会不断增长。这可以帮助通知哪些数据字段应该被进一步转换并引入 ETL 管道,这可能应该涉及Faustksql而不是pandas.

如何非迭代地读取多个 CSV 文件(并且没有熊猫)

原文:https://towardsdatascience.com/how-to-read-multiple-csv-files-non-iteratively-and-without-pandas-984fd954999c

对熊猫的读 CSV 方法说不!

Solaiman Hossen 在 Unsplash 上拍摄的照片

Pandas 的一个主要警告是它不能扩展到多个 CPU 核心(通常)。本质上,当您运行任何操作时,在理想情况下并行化是可能的,Pandas 仍将坚持传统的单核执行,而其他内核将闲置。当您构建大规模应用程序时,这一点尤其重要。

处理大规模数据驱动的应用程序需要通过优化算法来加快执行速度,并消除/减少管道中每一个可能的位的运行时间。在我看来,经常被忽视的一个领域是优化输入输出操作。

假设您有数百个 CSV 文件需要读入 python 环境。毫无疑问,你的第一选择是熊猫。另外,即使您没有处理大量的 CSV 文件,我也总是建议您删除所有的 CSV 文件,将它们转换为相对更快、存储效率更高的文件,比如 Pickle、Feather 或 Parquet。

如果你必须使用 CSV,我个人不推荐使用熊猫的 CSV 读写功能,你可以在我下面的帖子中找到答案。

因此,回到我们的数百个 CSV 文件的场景,在这里,读取多个 CSV 文件的一种简单方法可以是在一个循环中迭代它们,获得 Pandas 数据帧的列表,并将该列表连接成单个数据帧。这将在下面演示。

使用 Pandas 读取多个 CSV 文件的代码片段(图片由作者提供)

但是,这种方法存在一些问题:

  1. 该循环不可避免地引入了一个迭代过程,即一次只能读取一个 CSV 文件,从而导致资源利用不足。
  2. Pandas read-csv 方法本身是一个序列化的过程。

这篇文章旨在解决上述两个与熊猫有关的读取多个 CSV 文件的问题,我们将在这篇文章中探索数据表

Datatable 是一个用于操作表格数据的 python 库。它支持内存不足的数据集、多线程数据处理和灵活的 API。

使用数据表读取多个 CSV(非迭代):

下面的代码片段演示了如何使用 DataTable 读取多个 CSV 文件。

使用数据表读取多个 CSV 文件的代码片段(图片由作者提供)

实验设置:

  1. 出于实验目的,我用 Python 生成了 10 个不同的随机 CSV 文件,每个文件有 10 万行和 30 列——包括字符串、浮点和整数数据类型。
  2. 我重复了下面描述的实验五次,以减少随机性,并从观察到的结果中得出公正的结论。我下面报告的数字是五次实验的平均值。
  3. Python 环境和库:
  • Python 3.9.12
  • 熊猫
  • 数据表 1.0.0

实验:读取所有 CSV 文件所花费的时间

下图描述了 Pandas 和 DataTable 读取十个 CSV 文件并生成一个Pandas 数据帧所花费的时间(以秒为单位)。

描述熊猫和数据表读取 CSV 文件所用时间的条形图(图片由作者提供)

  • 实验结果表明,在读取 CSV 文件时,与 Pandas 相比,的速度提高了两倍多。
  • 与 Pandas 相反,这些结果也为 DataTable 采用的多线程方法提供了证据。

结束语

老实说,我不太喜欢 CSV。如果你通读了我之前的帖子(我在上面链接了)和你现在正在读的帖子,你可能也会和我产生共鸣。自从我发现与 CSV 相关的众多问题后,我尽可能地停止使用它们。

总之,我认为除非您需要在非 pythonic 环境(如 Excel)之外查看数据框架,否则根本不需要 CSV。更喜欢像拼花地板、羽毛或泡菜这样的格式来存储你的数据帧。尽管如此,如果您看不到其他选择,至少通过利用 DataTable 而不是 Pandas 来优化您的输入和输出操作。

毒枭迷因由作者使用 MemesPortal.com 创造。

如何阅读研究论文:面向 ML 从业者的实用方法

原文:https://towardsdatascience.com/how-to-read-research-papers-a-pragmatic-approach-for-ml-practitioners-299935624326

如何理解人工智能/人工智能研究出版物

斯科特·格雷厄姆在 Unsplash 上拍照

数据科学家或机器学习专家有必要阅读研究论文吗?

简单的回答是肯定的。如果你缺乏正式的学术背景或只获得了机器学习领域的本科学位,也不用担心。

对于没有广泛教育背景的人来说,阅读学术研究论文可能会令人生畏。然而,缺乏学术阅读经验不应阻止数据科学家利用宝贵的信息和知识来源进行机器学习和人工智能开发。

本文为任何技能水平的数据科学家提供了阅读学术期刊上发表的研究论文的实践指南,如 NeurIPS 、 JMLR 、 ICML、等。

在全心投入阅读研究论文之前,学习如何阅读研究论文的第一阶段包括选择相关主题和研究论文。

第一步:确定主题

机器学习和数据科学领域是许多学科领域的家园。但这并不一定意味着处理机器学习中的每个主题都是最佳选择。

虽然建议入门级从业者一般化,但我猜测,当涉及长期机器学习时,职业前景、从业者和行业兴趣通常会转移到专业化。

确定一个合适的主题可能很难,但是很好。不过,一个经验法则是选择一个你有兴趣获得专业职位或者已经有经验的 ML 领域。

深度学习是我的兴趣之一,我是一名计算机视觉工程师,在应用程序中使用深度学习模型来专业解决计算机视觉问题。因此,我对姿势估计、动作分类和手势识别等主题感兴趣。

基于角色,以下是 ML/DS 职业和相关主题的例子。

图 1:机器学习和数据科学的角色和相关主题。作者创建的图像

对于这篇文章,我将选择姿势估计这个主题进行探索,并选择相关的研究论文进行研究。

第二步:寻找研究论文

在查看机器学习相关的研究论文、数据集、代码和其他相关材料时,最优秀的工具之一是代码为的 PapersWithCode 。

我们使用 PapersWithCode 网站上的搜索引擎来获取我们所选主题“姿态估计”的相关研究论文和内容下图向您展示了这是如何做到的。

图 2:作者创建的图片:GIF 搜索姿势估计

搜索结果页面包含对搜索主题的简短说明,随后是相关数据集、模型、论文和代码的表格。不涉及太多的细节,这个用例感兴趣的领域是“有代码的最伟大的论文”。这部分包含与任务或主题相关的论文。对于本文,我将选择密集姿势:野外密集人体姿势估计。

第三步:第一遍(获得背景和理解)

照片由absolute visionUnsplash

此时,我们已经选择了一篇研究论文进行研究,并准备从其内容中提取任何有价值的知识和发现。

很自然,你的第一个冲动是开始写笔记并从头到尾阅读文档,也许在中间休息一下。然而,有一个研究论文内容的背景是一个更实用的阅读方法。标题、摘要和结论是理解任何研究论文的三个关键部分。

你所选论文的第一遍的目标是达到以下目标:

  • 确保论文是相关的。
  • 通过学习文章的内容、方法和发现,获得对文章内容的理解。
  • 认可作者的目标、方法和成就。

标题

标题是作者和读者分享信息的第一点。因此,研究论文的标题是直接的,以一种不留任何歧义的方式构成。

研究论文的标题是最能说明问题的方面,因为它表明了这项研究与你的工作的相关性。标题的重要性在于简要介绍论文的内容。

在这种情况下,标题是“密集姿势:野外密集人体姿势估计”这给出了工作的广泛概述,并意味着它将着眼于如何在高活动水平和现实情况的环境中适当地提供姿态估计。

摘要

摘要部分给出了论文的摘要版本。这是一个很短的部分,包含 300-500 个单词,简单地告诉你论文的内容。摘要是一个简短的文本,概述了文章的内容,研究人员的目标,方法和技术。

当阅读机器学习研究论文的摘要时,你通常会遇到数据集、方法、算法和其他术语的提及。与文章内容相关的关键词提供了上下文。做笔记并跟踪所有关键词可能会有所帮助。

对于这篇文章:“Dense Pose:Dense person Pose Estimation In The Wild”,我在摘要中确定了以下关键词:姿势估计、COCO 数据集、CNN、基于区域的模型、实时。

结论

当你第一次从头到尾阅读论文时,疲劳是很常见的,特别是对于没有高级学术经验的数据科学家和从业者。虽然在长时间的学习后,从论文的后面部分提取信息可能会显得乏味,但结论部分通常很短。因此,建议在第一遍阅读结论部分。

结论部分简要概述了作品的作者或作者和/或贡献和成就,以及对未来发展和局限性的承诺。

在阅读研究论文的主要内容之前,先阅读结论部分,看看研究人员的贡献、问题领域和成果是否符合你的需求。

遵循这一特定的简短的第一步,可以充分理解和概述研究论文的范围和目标,以及其内容的背景。如果你全神贯注地再看一遍,就能从内容中获得更详细的信息。

第四步:第二遍(内容熟悉)

熟悉内容是一个与初始步骤相关的过程。熟悉过程是一个步骤,涉及研究论文中的引言部分和图表。

如前所述,不需要直接进入研究论文的核心,因为知识适应在以后的过程中提供了更详细和更全面的研究检查。

介绍

研究论文的介绍部分是为了提供研究工作目标的概述。这个目标提到并解释了问题领域、研究范围、先前的研究成果和方法。

使用相似或不同的方法,在这一领域找到与过去研究工作的相似之处是很正常的。其他论文的引用提供了问题领域的范围和广度,为读者拓宽了探索区域。在这一点上,也许合并步骤 3 中概述的过程就足够了。

引言部分提供的好处的另一个方面是介绍处理和理解研究论文内容所需的必要知识。

图表、图解和数字

研究论文中的说明性材料确保读者能够理解支持问题定义的因素或所提出方法的解释。通常,研究论文中使用表格来提供新技术与类似方法相比的定量性能信息。

显示 DensePose 与其他单人姿势估计解决方案比较的图像。

一般来说,数据和性能的可视化表示使得能够对论文的上下文有直观的理解。在前面提到的密集姿态论文中,插图描述了作者的姿态估计方法的性能。

在深度学习领域,经常可以找到描述人工神经网络结构的拓扑插图。这又增加了对任何读者的直观理解。通过插图和数字,读者可以自己解释信息并获得更全面的视角,而不会对结果有任何先入为主的概念。

图片显示了 DensePose 的交叉级联架构。

第五步:第三遍(深度阅读)

论文的第三遍与第二遍相似,尽管它覆盖了更重要的部分。关于这一关最重要的事情是你避免任何复杂的算术或技术公式,这可能对你来说是困难的。在此过程中,你也可以跳过任何你不理解或不熟悉的单词和定义。这些不熟悉的术语、算法或技术应该注意,以便稍后返回。

照片由Markus Winkler上的Unsplash

在这一阶段,你的主要目标是对论文内容有一个大致的了解。接近论文,再次从摘要开始到结论,但是一定要在各部分之间有中间休息。此外,建议准备一个记事本,在上面记录所有重要的见解和要点,以及不熟悉的术语和概念。

番茄工作法是管理深度阅读或学习时间的有效方法。据解释,番茄工作法包括将一天分成几个工作块,然后是短暂的休息。

对我有用的是 50/15 的分配,即 50 分钟学习,15 分钟休息。我倾向于在休息 30 分钟之前连续做两次这种分割。如果你不熟悉这种时间管理技巧,可以采用相对简单的划分方法,比如 25/5,并根据你的关注点和时间容量来调整时间划分。

第六步:第四遍(最后一遍)

最后一关通常涉及到运用你的思维和学习能力,因为它涉及到浏览前一关中提到的不熟悉的术语、术语、概念和算法。这一关着重于使用外部材料来理解论文中记录的不熟悉的方面。

对不熟悉的主题进行深入研究没有特定的时间长度,有时努力会持续几天甚至几周。成功完成最后一次勘探的关键因素是找到合适的勘探源。

不幸的是,互联网上没有一个来源能提供你所需要的大量信息。尽管如此,有多种来源,当统一和适当地使用时,可以填补知识空白。下面是其中的一些资源。

  • 机器学习子编辑
  • 深度学习子编辑
  • 纸张代码
  • 顶级会议如 NIPS , ICML , ICLR
  • 研究门
  • 机器学习苹果

研究论文的参考部分提到了技术和算法。因此,目前的论文要么是从参考文献中获得灵感,要么是建立在参考文献的基础上,这就是为什么参考文献是你在深度阅读课程中使用的一个有价值的来源。

第 7 步:总结(可选)

在近十年的与技术相关的学科和角色的学术和专业工作中,最有效的方法是通过重述探索的主题来确保任何新学到的信息保留在我的长期记忆中。通过用我自己的话重写新的信息,无论是书面的还是打字的,我能够以可理解的方式和令人难忘的方式来强化已提出的观点。

照片由neon brandUnsplash

更进一步说,可以通过利用博客平台和社交媒体来宣传学习成果和笔记。假设读者不习惯这个话题或主题,试图向广大读者解释这个新探索的概念,需要理解话题内在的细节。

结论

毫无疑问,对于新手数据科学家和 ML 从业者来说,阅读研究论文可能会令人生畏,具有挑战性;即使是经验丰富的从业者也很难一次成功消化研究论文的内容。

数据科学职业的本质是非常实际和复杂的。这意味着,它的从业者需要采用学术思维,尤其是数据科学领域与人工智能密切相关,而人工智能仍是一个发展中的领域。

总而言之,下面是你阅读研究论文应该遵循的所有步骤

  • 确定一个主题。
  • 查找相关研究论文
  • 阅读标题、摘要和结论,对研究的目标和成果有一个模糊的理解。
  • 通过深入研究介绍来熟悉内容,包括研究论文中的数字和图表。
  • 当你从上到下阅读文章时,使用深度阅读来消化文章的主要内容。
  • 利用外部资源探索不熟悉的术语、术语、概念和方法。
  • 用你自己的话总结基本要点、定义和算法。

感谢阅读。

本文最初发表于 Nvidia 开发者博客

我希望这篇文章对你有所帮助。

要联系我或找到更多类似本文的内容,请执行以下操作:

  1. 成为推荐媒介会员,支持我的写作
  2. 订阅我的 电子邮件列表 获取我的简讯
  3. 通过 LinkedIn 联系我
  4. Twitter 上获取我的实时更新

如何使用 FastAPI 通过 HTTP 从/向 SQL 读取/写入数据帧

原文:https://towardsdatascience.com/how-to-read-write-dataframes-from-to-sql-over-http-with-fastapi-e48ab91e6a83

不到 10 分钟

照片感谢来自 Unsplash 的 growtika 。

在工业中处理数据是一件痛苦的事情。这是因为数据可以分散在多个项目中,以不同的格式存储,并以不同的程度维护。通常,这导致不同的团队开发不同的内部工具来处理他们的数据。由于没有标准的读写数据的方法,整个事情变得一团糟。

一个解决方案是开发数据摄取微服务。本质上,这些应用程序支持通过 HTTP 或 RPC 调用进行数据传输。他们试图提供一种统一的格式来读取和写入不同的数据源(例如 Google BigQuery、Postgres 等)。这个想法是,其他应用程序(比如仪表板)将使用数据摄取应用程序来加载数据。下图描述了一个简单的用例:

在本教程中,我将描述开发一个简单的数据摄取应用程序的过程,该应用程序使用 FastAPI 读取和写入任何 Postgres 数据库。

应用端点

摄取数据

接收端点将用于读取数据。为此,我们需要连接到数据库的参数。这些将是 db_userdb_passworddb_portdb_namedb_host 。我们还需要一种查询数据库的方法,在这种情况下,它可以只是一个字符串 sql_query

我们使用fastapi定义我们的应用程序,并开始构建端点:

from fastapi import FastAPI
from pydantic import BaseModel# initialise app
app = FastAPI()
# pydantic class for collecting our parameters into a json object
class IngestionParams(BaseModel):sql_query: strusername: strpassword: strport: inthost: strdatabase_name: str
# define POST endpoint "ingest"
@app.post("/ingest")
def ingest(ingestion_params: IngestionParams
):# retrieve ingestion params as dictionaryingestion_params = ingestion_params.dict()db_user = ingestion_params['username']db_password = ingestion_params['password']db_host = ingestion_params['host']db_port = ingestion_params['port']db_name = ingestion_params['database_name']sql_query = ingestion_params['sql_query']

**重要提示:**根据 REST API 设计模式,在 getpost 请求之间应该有所区别。通常, get 用于读取数据, post 用于发送数据。然而,在这种情况下,最好使用 post 来获取,因为:1)浏览器日志通常包含 URL 历史记录(这意味着敏感参数(如 DB 凭证)会被暴露),2)URL 长度有限制[ 1 ]

现在,我们需要连接到我们的客户机并执行查询。为此,我们可以使用sqlalchemy:

import sqlalchemy as db
import pandas as pd# connect to db
db_uri = f'postgresql+psycopg2://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}'
engine = db.create_engine(db_uri)
con = engine.connect()
# query db
query_result = con.execute(sql_query)
data = query_result.fetchall()
# convert to dataframe
columns = query_result.keys()
df = pd.DataFrame(data, columns=columns)

剩下的最后一件事是我们如何通过 HTTP 请求发送回数据帧。有多种方法可以做到这一点,但是为了保留 dtype,我们将 DataFrame 转换为一个 Parquet 文件,并使用内容类型application/octer-stream将其作为二进制文件发送。

# added import
from fastapi import Response
def ingest(response: Response, # add response parameteringestion_params: IngestionParams
)...
# return parquet file in Response object
return Response(df.to_parquet(engine='pyarrow', index=False), media_type='application/octet-stream')

插入数据

为了插入数据,我们需要和以前一样的参数来连接数据库。然而,我们还需要 table_namedataset_nameconflict _ resolution _ strategy

我们还需要一个文件参数来发送数据。这样,我们开始设计插入端点:

from fastapi import File, UploadFile
from pydantic import Json
# pydantic class for collecting our parameters into a json object
class InsertionParams(BaseModel):username: strpassword: strport: int = 5432host: strdatabase_name: strtable_name: strconflict_resolution_strategy: str = 'replace'  # default value# define POST endpoint "insert" using async
@app.post("/insert")
async def insert(response: Response, # for returning the dataframe that we insertinsertion_params: Json[InsertionParams],file: UploadFile = File(...)
):# retrieve insertion params as dictionaryinsertion_params = insertion_params.dict()db_user = insertion_params['username']db_password = insertion_params['password']db_host = insertion_params['host']db_port = insertion_params['port']db_name = insertion_params['database_name']table_name = insertion_params['table_name']conflict_resolution_strategy = insertion_params['conflict_resolution_strategy']dataset_name = insertion_params.get('dataset_name', None)content = await file.read()

现在,我们想要设计我们的 API 来支持不同的文件类型作为输入。我们可以使用 file 对象的 content_type 属性来确定文件类型,然后适当地读取它。

import io
with io.BytesIO(content) as data:if 'csv' in file.content_type:df = pd.read_csv(data)if file.content_type == 'text/tab-separated-values':df = pd.read_csv(data, delimiter='\t')if file.content_type == 'application/octet-stream': # TODO can you have other 'octet-stream'?df = pd.read_parquet(data, engine='pyarrow')

与之前类似,我们通过初始化客户端连接到数据库,然后使用来自pandas.to_sql方法写入 postgres。但是,我们必须确保在使用该方法时传递数据类型,否则您的表将会被不正确地填充。因此:

# import types
from sqlalchemy import INTEGER, FLOAT, TIMESTAMP, VARCHAR, BOOLEAN
from pandas.api.types import is_datetime64tz_dtype
# connect to database
... 
DTYPE_MAP = {'int64': INTEGER,'float64': FLOAT,'datetime64[ns]': TIMESTAMP,'datetime64[ns, UTC]': TIMESTAMP(timezone=True),'bool': BOOLEAN,'object': VARCHAR}
def _get_pg_datatypes(df):dtypes = {}for col, dtype in df.dtypes.items():if is_datetime64tz_dtype(dtype):dtypes[col] = DTYPE_MAP['datetime64[ns, UTC]']else:dtypes[col] = DTYPE_MAP[str(dtype)]return dtypes
dtypes = _get_pg_datatypes(df)
df.to_sql(table_name, con, schema=dataset_name, if_exists=conflict_resolution_strategy, index=False, method='multi', dtype=dtypes)
response.status_code = 201
return "Created table"

运行应用程序

总的来说,代码应该如下所示:

from fastapi import FastAPI, Response, File, UploadFile
from pydantic import BaseModel, Json
import sqlalchemy as db
import pandas as pd
import io
from sqlalchemy import INTEGER, FLOAT, TIMESTAMP, VARCHAR, BOOLEAN
from pandas.api.types import is_datetime64tz_dtype
# initialise app
app = FastAPI()
# pydantic class for collecting our parameters into a json object
class IngestionParams(BaseModel):sql_query: strusername: strpassword: strport: inthost: strdatabase_name: str
class InsertionParams(BaseModel):username: strpassword: strport: int = 5432host: strdatabase_name: strtable_name: strconflict_resolution_strategy: str = 'replace'  # default value
def _connect_to_db(user, password, host, port, name):db_uri = f'postgresql+psycopg2://{user}:{password}@{host}:{port}/{name}'engine = db.create_engine(db_uri)con = engine.connect()return con
# define POST endpoint "ingest"
@app.post("/ingest")
def ingest(response: Response,ingestion_params: IngestionParams
):# retrieve ingestion params as dictionaryingestion_params = ingestion_params.dict()db_user = ingestion_params['username']db_password = ingestion_params['password']db_host = ingestion_params['host']db_port = ingestion_params['port']db_name = ingestion_params['database_name']sql_query = ingestion_params['sql_query']# connect to dbcon = _connect_to_db(db_user, db_password, db_host, db_port, db_name)# query dbquery_result = con.execute(sql_query)data = query_result.fetchall()# convert to dataframecolumns = query_result.keys()df = pd.DataFrame(data, columns=columns)# return parquet file in Response objectreturn Response(df.to_parquet(engine='pyarrow', index=False), media_type='application/octet-stream')# define POST endpoint "insert" using async
@app.post("/insert")
async def insert(response: Response, # for returning the dataframe that we insertinsertion_params: Json[InsertionParams],file: UploadFile = File(...)
):# retrieve insertion params as dictionaryinsertion_params = insertion_params.dict()db_user = insertion_params['username']db_password = insertion_params['password']db_host = insertion_params['host']db_port = insertion_params['port']db_name = insertion_params['database_name']table_name = insertion_params['table_name']conflict_resolution_strategy = insertion_params['conflict_resolution_strategy']dataset_name = insertion_params.get('dataset_name', None)content = await file.read()with io.BytesIO(content) as data:if 'csv' in file.content_type:df = pd.read_csv(data)if file.content_type == 'text/tab-separated-values':df = pd.read_csv(data, delimiter='\t')if file.content_type == 'application/octet-stream':  # TODO can you have other 'octet-stream'?df = pd.read_parquet(data, engine='pyarrow')DTYPE_MAP = {'int64': INTEGER,'float64': FLOAT,'datetime64[ns]': TIMESTAMP,'datetime64[ns, UTC]': TIMESTAMP(timezone=True),'bool': BOOLEAN,'object': VARCHAR}def _get_pg_datatypes(df):dtypes = {}for col, dtype in df.dtypes.items():if is_datetime64tz_dtype(dtype):dtypes[col] = DTYPE_MAP['datetime64[ns, UTC]']else:dtypes[col] = DTYPE_MAP[str(dtype)]return dtypesdtypes = _get_pg_datatypes(df)# connect to dbcon = _connect_to_db(db_user, db_password, db_host, db_port, db_name)df.to_sql(table_name, con, schema=dataset_name, if_exists=conflict_resolution_strategy, index=False, method='multi', dtype=dtypes)response.status_code = 201return "Created table"

请注意,我们已经清理了一些东西!

我们可以将其保存到一个名为main.py的文件中,然后在终端中运行以下命令:

uvicorn main:app --reload

现在,您应该可以通过访问以下 url 在浏览器中看到该应用程序:

localhost:8000/docs

这是您应该在 localhost:8000/docs 上看到的内容

设置

为了测试我们的应用程序是否正常工作,我们需要一个 postgres 实例来测试。出于本文的目的,我们将使用 Docker Postgres 实例(尽管您可以随意使用)。

为此,您需要安装 docker。然后,您可以在终端中运行以下命令:

docker run -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres

您现在应该有一个本地运行的 postgres 实例,并在 5432 端口上有一个连接。您可以使用数据库查看软件来查看。在我的例子中,我使用 DBeaver [ 2 ]。

数据库的连接参数是:

  • 用户名: postgres
  • **主机:**本地主机
  • 港口: 5432
  • 密码: postgres
  • 数据库名称: postgres

使用请求读取文件

使用 UI 来读/写数据是相对直观的。当您想从 Python 内部调用端点时,这就不那么重要了。为此,我们使用requests模块。

import io
import pandas as pd
import requests
BASE_URL = 'http://localhost:8000' # url for app comprised of host and port
# headers for request
headers = {'Content-Type': 'application/json','Accept': 'application/octet-stream'
}
# function for validating successful request
def _is_status_code_valid(status_code):if str(status_code).startswith('2'):return True
def read_data(ingestion_param,
):#url = f'{BASE_URL}/ingest'resp = requests.post(url, json=ingestion_param, headers=headers)status_code = resp.status_codeif _is_status_code_valid(status_code):df = pd.read_parquet(io.BytesIO(resp.content), engine='pyarrow')return df, status_code

上面的关键方面是,我们以字节为单位读取响应,但我们需要数据作为数据帧。因此,在将响应内容作为 parquet 读取之前,我们将它转换为 BytesIO 对象。我们保存 dtype,因为 parquet 文件包含表 dtype 信息。

使用请求发送文件

发送文件比阅读文件稍微复杂一些。这是因为 post 请求的请求参数并不简单,我们必须想办法将数据帧转换成可接受的格式。

import io
import json
import requestsBASE_URL = 'http://localhost:8000' # url for app comprised of host and port
def write_data(database_name,table_name,database_type='pg',df=pd.DataFrame(),content_type='csv',conflict_resolution_strategy='fail',username='postgres',password='postgres',port=5432,host='localhost',):url = f'{BASE_URL}/insert'# in principle, it is possible to add converters for any content_typeif content_type == 'parquet':memory_buffer = io.BytesIO()df.to_parquet(memory_buffer,engine='pyarrow')memory_buffer.seek(0)# need to encode parameters as json stringdata = {'insertion_params': json.dumps(dict(username=username,password=password,port=port,database_name=database_name,table_name=table_name,conflict_resolution_strategy=conflict_resolution_strategy,host=host))}# need to send files separatelyfiles = {'file': ('Test', memory_buffer, 'application/octet-stream')}resp = requests.post(url, data=data, files=files)return resp.text, resp.status_code

结束语

在本文中,我们使用 FastAPI for Postgres 设计了一个数据摄取应用程序。以下是关键要点的快速总结:

  • 数据摄取应用程序比在单独的项目中构建摄取功能更可取,因为它是标准化的,更易于维护,并能适应变化
  • 将数据帧转换成 Parquet 对于通过 HTTP 发送它们很有用,因为我们保留了数据类型信息
  • 目前的应用程序可以很容易地扩展到支持其他数据源,如 BigQuery,Google Drive 等…

限制

  • 仅支持 postgres
  • 目前,使用.to_sql的方法不支持上插功能

本文使用的全部代码可以在下面的存储库中找到:https://github.com/namiyousef/in-n-out。

引用表

[1]https://stack overflow . com/questions/19637459/rest-API-using-post-inst-of-get

[2]https://dbeaver.io/

以上所有图片和代码均为作者所有,除非另有说明

如何在手机上接收机器学习模型训练完成时间通知

原文:https://towardsdatascience.com/how-to-receive-machine-learning-model-training-completion-time-notifications-on-your-phone-a8e6cdb02d1a

一种在 Python 脚本中单击“运行”并离开直到模型训练完成的方法。

  • 注意:我与 aporia 和 mlnotify 的创建者没有任何关系。我只是分享这一点,以帮助其他人的数据科学学习经验。

照片由 Aron 视觉效果在 Unsplash 上拍摄

介绍

每个人在他们的数据科学旅程中都要经历这个过程:w 等待他们的机器学习模型训练完成你是干什么的?你会坐在电脑前等待模型完成吗?或者你离开了,冒着训练过程提前结束的风险,或者浪费宝贵的时间,认为你的模型实际上已经完成了,还在训练?我找到了一种方法来训练你的机器学习模型,离开你的电脑,当训练完成时,会收到通知。如果你生活中有其他的事情要做,需要离开电脑,但又不想在模型训练结束后浪费宝贵的分析时间,这将非常有帮助。

mlnotify

我最近在我的数据科学之旅中遇到了 mlnotify ,认为它好得令人难以置信。你可以在这里找到更多关于ml notify的信息。它是由 aporia 创建的,是一个在模型训练完成时通知机器学习爱好者的工具。用户调用后。fit() 在他们的 ML 模型上,提供了一个二维码,用户可以对其拍照并接收计时器,并在他们的手机上更新训练的完成情况。此外,用户可以选择访问 mlnotify 网站来跟踪其模型的训练进度,也可以选择在训练停止时接收电子邮件。

例子

在今天的例子中,我们将创建一个基本的卷积神经网络(CNN )来对 MNIST 数据集进行分类。首先,我们想要导入我们的包。

import mlnotify
import tensorflow as tf
import keras
import numpy as np
from keras import layers

你将需要!pip 在导入库之前安装 mlnotify。接下来,我们要加载 MNIST 数据集。 Keras API 允许我们用他们的数据集方法来做这件事。为了正确训练我们的模型,我们需要在 0 和 1 之间缩放图像,将它们转换为 float32 值,并将其整形为 *(28,28,1)。*最后一步是将类别标签向量转换成二进制矩阵。

#Creating the training and test sets(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()#Image scaling
x_train = x_train.astype("float32") / 255
x_test = x_test.astype("float32") / 255# Image Shaping
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)#Class label vector conversion
num_class = 10
y_train = keras.utils.to_categorical(y_train, num_class)
y_test = keras.utils.to_categorical(y_test, num_class)

现在让我们创建模型。该模型将有两个卷积层,每个使用 3x3 内核和一个泄漏 ReLU (LReLU)激活函数。第一卷积层将具有 32 个神经元,第二层将成形为具有 64 。在卷积层之后,我们将使用参数值为 (2,2)的最大池层。最后,该模型将以一个脱落层、展平层和密集层结束,该层使用我们为其神经元数量创建的 num_class 参数(在本例中为 10 )。密集层将利用 Softmax 激活功能,因为这是一个多分类问题。

model = keras.Sequential([
keras.Input(shape=input_shape),
layers.Conv2D(32, kernel_size=(3, 3)),
layers.LeakyReLU(),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Conv2D(64, kernel_size=(3, 3)),
layers.LeakyReLU(),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Flatten(),
layers.Dropout(0.5),
layers.Dense(num_classes, activation="softmax"),
]
)

最后是训练模式的时候了。让我们看看 mlnotify 如何与培训过程交互。您需要编写 %%notifymlnotify.start() (参考下面的代码)来调用 mlnotify API。

%%notify
mlnotify.start()
batch_size = 128
epochs = 10model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1)

当您执行他的代码时,会弹出一个二维码,让您可以在手机上获得培训进度。

培训二维码(图片来自作者)

扫描二维码后,你的手机上会弹出一个计时器来跟踪你的模特的训练。

电话计时器培训(图片来自作者)

你也可以通过 mlnotify 提供的链接访问同一个定时器。一旦培训完成, mlnotify 将会通过电话通知您,无论您身在何处!

培训完成(图片来自作者)

结论

正如我们今天看到的,当你离开办公桌而不是坐在电脑前盯着进度条的时候,有一些方法可以通知你机器学习模型何时完成训练*。这个 API 允许你在终端中点击 run,继续做你一天中的其他事情,而不必经常检查模型的训练进度。我发现这个 API 在训练耗时较长的模型时非常有用。它允许我去做我一天中喜欢和享受的其他活动,但通过 mlnotify 的快速通知快速返回我训练的模型的结果。我希望你和我一样在使用这个工具时发现同样的价值!*

如果你喜欢今天的阅读,请关注我,并告诉我你是否还有其他想让我探讨的话题!如果你没有中等账号,就通过我的链接 这里 报名吧!另外,在LinkedIn上加我,或者随时联系!感谢阅读!

如何为您的 Azure 数据湖构建时间点恢复解决方案

原文:https://towardsdatascience.com/how-to-recover-your-azure-data-lake-5b5e53f3736f

利用快照、软删除和 Azure 功能在 Azure 数据湖存储上构建时间点恢复解决方案。

TLTR:在 克隆项目并运行脚本 https://github . com/rebremer/azure-functions-data lake-recovery-pitr/blob/main/script . PS1部署解决方案

1.介绍

企业数据湖中的一个普遍担忧是,由于应用程序错误或人为错误,数据会被破坏。在这种情况下,可能需要执行时间点恢复(PiTR)并恢复快照。启用了分层命名空间(HNS)的 Azure 存储尚不支持 PiTR。但是,快照和软删除是可用的,可以用作创建恢复解决方案的构造块。

在这篇博客和 git repo [azure-functions-datalake-recovery-pitr](https://github.com/rebremer/azure-functions-datalake-recovery-pitr)中,讨论了如何使用快照、软删除和 Azure 函数来实现 PiTR,参见下面的架构。

1.建筑——作者的图像

在这篇博文的剩余部分,我们将更详细地解释数据湖恢复项目。这将按如下方式完成:

  • 在第 2 章中,确保在数据湖中添加/修改文件时创建快照。
  • 在第 3 章中,详细解释了如何使用这些快照来构建数据湖恢复功能,以便在数据损坏时加以利用。此外,解决方案的可扩展性将在第 3.3 章中讨论。

最后,要了解更多关于灾难恢复的知识,请参阅我之前的博客。

2.基于事件:创建快照

在这一章中,项目开始运行。在这方面,需要做以下工作:

  • 2.1 先决条件
  • 2.2 设置 Azure 数据湖
  • 2.3 设置快照创建

另请参见下面的概述:

2.架构,基于事件的快照创建—按作者创建图像

2.1 先决条件

本教程需要以下先决条件:

  • Azure CLI
  • Python 3.7+
  • Azure 功能核心工具

最后,将下面的 git repo 克隆到您的本地计算机上。如果你没有安装 git,你可以从网页上下载一个 zip 文件。

git clone [https://github.com/rebremer/azure-functions-datalake-recovery-pitr](https://github.com/rebremer/azure-functions-datalake-recovery-pitr)

2.2 设置 Azure 数据湖

在这一部分中,使用以下属性创建了一个 Azure 数据湖

  • 支持分层命名空间(HNS)的 Azure 存储帐户提供了真正的文件系统,而不是基于对象的存储
  • 为启用了 HNS 的存储帐户启用快照预览,请参见https://learn . Microsoft . com/en-us/azure/storage/blob/snapshot s-overview # about-blob-snapshot s
  • 已禁用访问密钥,仅允许 Azure AD 作为身份外围设备
  • 启用软删除

运行以下脚本:

# 0\. Set variables
#
$SUB='<<your subscription>>'
$RG='<<your resource group>>'
$LOC='<<your location>>'                             
$DLSTOR='<<your data lake account>>'
$FILE_SYSTEM='<<your data lake file system name>>'
$EMAIL='<<your email address>>'              # 1\. Create resource group
#
az account set --subscription $SUB                 
az group create -n $RG -l $LOC# 2\. Create data lake account
#
az storage account create -n $DLSTOR -g $RG -l $LOC --sku Standard_LRS --kind StorageV2 --enable-hierarchical-namespace true --allow-shared-key-access false# 3\. Add yourself as user to data lake acount
#
$scope="/subscriptions/$SUB/resourceGroups/$RG/providers/Microsoft.Storage/storageAccounts/$DLSTOR/blobServices/default"
az role assignment create --role "Storage Blob Data Contributor" --assignee $email --scope $scope # 4\. Enable soft delete on storage acount
#
az storage account blob-service-properties update -n $DLSTOR -g $RG --enable-delete-retention true --delete-retention-days 7# 5\. Create File System on date lake account
#
az storage container create --account-name $DLSTOR -n $FILE_SYSTEM --auth-mode login

2.3 设置快照创建

在这一部分中,一旦创建或更新了文件,就会创建快照。这是按如下方式完成的:

  • 创建侦听存储帐户的事件网格
  • 一旦文件被创建/修改,事件网格 Azure Functions 被触发
  • Azure Functions 创建文件快照

另请参见下面的脚本:

# 0\. Set variables
#
$SUB='<<your subscription>>'
$RG='<<your resource group>>'
$LOC='<<your location>>'
$DLSTOR='<<your data lake account>>'
$FUNSTOR='<<your azure function storage account>>'
$FUNNAME='<<your azure function name>>'
$FUNPN='<<your azure function app plan name>>'# 1\. Deploy Event Grid triggered Functions
#
az functionapp plan create -g $RG -n $FUNPN --sku B1 --is-linux true
az storage account create -n $FUNSTOR -g $RG -l $LOC --sku Standard_LRS --kind StorageV2
az functionapp create -n $FUNNAME -g $RG -s $FUNSTOR -p $FUNPN --assign-identity --runtime Python
$function_mi=$(az functionapp show -n $FUNNAME -g $RG | ConvertFrom-Json).identity.principalId
az role assignment create --assignee $function_mi --role "Storage Blob Data Contributor" --scope $scope
func azure functionapp publish $FUNNAME # 2\. Subscribe to event grid
#
$stordlid = "/subscriptions/$SUB/resourceGroups/$RG/providers/Microsoft.Storage/storageaccounts/$DLSTOR"
$endpointid = "/subscriptions/$SUB/resourceGroups/$RG/providers/Microsoft.Web/sites/$FUNNAME/functions/EventGridTriggerCreateSnapshot"
az eventgrid event-subscription create --name storegversion --source-resource-id $stordlid --endpoint-type azurefunction --endpoint $endpointid --included-event-types Microsoft.Storage.BlobCreated

如果现在文件被上传到存储帐户或被修改,则会自动创建快照,另请参见下图。

2.3 自动快照创建—按作者创建图像

在下一章中,我们将讨论 Azure 函数,它可以用来恢复快照。

3.发生灾难时:恢复数据湖

在这一章中,数据湖将在灾难发生时恢复。在这方面,需要做以下工作:

  • 3.1 讨论灾难恢复场景
  • 3.2 设置和运行 Azure 持久功能
  • 3.3 规模数据湖恢复解决方案

另请参见下面的概述:

3.1 讨论灾难恢复场景

当数据损坏发生时,您希望恢复数据损坏前的状态。让我们把这个时刻命名为 restore_date。那么对于每个单独的文件,下面的场景是真实的

  • 场景 1: file_last_modified < restore_date. In this situation, the file was last modified before corruption occured ⇒什么都不做
  • 场景 2:文件创建时间>恢复日期。在这种情况下,文件仅在发生损坏后创建= >软删除文件
  • 场景 3:文件创建时间< restore_date < file_last_modified && snapshot is present before restore_date ⇒恢复快照
  • 场景 4: file_creation_time < restore_date < file_last_modified && NO_snapshot is present before restore_date ⇒提出条件,创建需要更多调查的警报下一步做什么

请注意,当实现第 2 章中解释的基于事件的快照时,场景 4 永远不会发生;每当创建或修改文件时,都会创建快照。4 个场景的详细逻辑可以在下面的 Python 文件中找到:[ActivityPointInTimeRecovery](https://github.com/rebremer/azure-functions-datalake-recovery-pitr/blob/main/ActivityPointInTimeRecovery/__init__.py#L91)

3.2 安装和 Azure 持久功能

通常,企业数据湖包含数百个容器、数百个文件夹和子文件夹以及数 TB 的数据。要恢复数据湖,以下是关键:

  • 恢复数据湖应该是精细的。应该可以恢复单个容器,甚至文件夹,而不是整个存储帐户
  • 修复应在大范围内进行。这应该并行进行,而不是让一个进程一个接一个地恢复文件夹和文件

Azure 持久功能扇入/扇出模式正是这么做的。在这个场景中,多个函数被并发执行,文件夹被递归解析。

在下面的脚本中,代码被部署到一个 Azure 函数。也可以决定先在本地运行 Azure(见脚本此处)。运行以下脚本以部署到 Azure 功能:

# 0\. Set variables
#
$RG='<<your resource group>>'
$DLSTOR='<<your data lake account>>'
$FILE_SYSTEM='<<your data lake file system name>>'
$FUNNAME='<<your azure function name>>'# 1\. Deploy Function
#
func azure functionapp publish $FUNNAME# 2\. Get function key
#
$code=$(az functionapp keys list -n $FUNNAME -g $RG | ConvertFrom-Json).functionKeys.default# 3\. Create sample folders and files in File System
#
Invoke-RestMethod "https://$FUNNAME.azurewebsites.net/api/orchestrators/OrchestratorInitFileSystem?code=$code&storage_account_name=$DLSTOR&file_system=$FILE_SYSTEM&number_of_folders=2"# 4\. Restore data lake (play around with restore_date in URL to test # four scenarios described in 2.2
#
Invoke-RestMethod "https://$FUNNAME.azurewebsites.net/api/orchestrators/OrchestratorPointInTimeRecovery?code=$code&restore_date=2021-01-20T00:00:00.0000000Z&storage_account_name=$DLSTOR&file_system=$FILE_SYSTEM&number_of_folders=2"

脚本成功运行后,一个包含 2 个文件夹和 100 个子文件夹的文件系统被设置,每个子文件夹包含 10 个文件,另请参见下面的屏幕截图:

3.2.1 目录 1,子目录 12,包含 10 个文件

使用快照,可以选择任何日期来恢复快照。逻辑描述了将恢复哪些快照(如果有),请参见下面示例文件中可以恢复的可能快照:

3.2.2 目录、子目录 12、文件测试快照 5.txt、要恢复的可能快照

3.3 规模数据湖恢复解决方案

选择 Azure 持久功能是因为它的伸缩能力。在上一章中,创建了一个只有两个文件夹的 file_system。通过改变 InitFileSystem 函数中的参数&number_of_folders=10000,可以建立一个 10M(10000 * 100 * 10)文件的文件夹结构。但是,在执行此操作之前,该解决方案应进行扩展,因为基本 SKU 仅用于 1 名员工。有两种选择两种规模。

  • 纵向扩展:通过纵向扩展,可以使用拥有更多内核/内存的虚拟机。通过使用更多的内核和内存,可以在同一台机器上运行多个恢复线程。最高的 SKU 是 P3V3 ,其中使用了 8 个内核(相比之下,3.2 中使用的基本 SKU 只有一个内核)
  • 横向扩展:通过横向扩展,多个虚拟机/工作人员用于运行恢复作业。如果使用 2 个内核的 P1V3 SKU,虚拟机的最大数量为 30,另请参见下图

3.3 SKU P1 v3 中的横向扩展解决方案最多 30 个实例(工作人员)

通过横向扩展,该解决方案可以真正扩展到在几分钟/几小时内恢复 1000 万个文件。最后,请注意,文件大小并不重要,因为在恢复解决方案中使用了快照。通过使用快照,数据不会被拷贝回来,这非常耗时。相反,斑点的状态通过指回在恢复时刻当前的块斑点 id来恢复。

4.结论

企业数据湖中的一个普遍担忧是,由于应用程序错误或人为错误,数据会被破坏。在这种情况下,可能需要执行时间点恢复(PiTR)并恢复快照。启用了分层名称空间(HNS)的 Azure 存储尚不支持 PiTR。

在这篇博客和 git repo [azure-functions-datalake-recovery-pitr](https://github.com/rebremer/azure-functions-datalake-recovery-pitr)中,讨论了如何使用基于事件的快照创建、软删除和 Azure 持久功能来实现 PiTR 的可伸缩性,另请参见下面的架构。最后,讨论了如何通过使用更高的 SKU 和多个工作人员来纵向和横向扩展解决方案。

4.建筑——作者的图像

如何将你的神经网络的训练时间从几小时减少到几分钟

原文:https://towardsdatascience.com/how-to-reduce-the-training-time-of-your-neural-network-from-hours-to-minutes-fe7533a3eec5

关于使用 HPC 的人工智能的文章的第 2 部分:使用 Horovod 和 GPU 并行 CNN 以获得 75-150 倍的加速。

罗伯特·卡茨基在 Unsplash 上的照片

在本系列的第 1 部分中,我们研究了如何通过使用多处理模块的几行 Python 代码在 IO 操作中获得到 1500 倍的加速。在本文中,我们将研究并行化深度学习代码,并将训练时间从大约 13 小时减少到 13 分钟!

背景

作为一名数据科学家,你最终会面临以下问题(如果你还没有面对过的话)。

“我有一个要训练的神经网络,但输入数据不适合内存!”“我的神经网络用这么大的数据量来训练,永远花不完!”

如果将你的一大部分数据排除在训练之外,或者等待几个小时(甚至几天)让你的神经网络完成训练,那肯定是很可惜的。必须有一个更好的方法,这就是所谓的数据并行

问题是

在这篇文章中,我们将使用在 Kaggle 上可获得的百事公司实验室薯片控制数据集的修改版本。原始图像为 2000 x 2000 像素格式,有 3 个通道。我修改图像,将它们缩放到 500 x 500,并应用 5 次变换(一次垂直翻转、一次水平翻转和三次 90 度旋转)来创建比原始数据集中多 6 倍的图像。

这两种类型的芯片区分在这个职位。

然后,我编写了一个简单的卷积神经网络(CNN)代码,用于基于从原始数据集创建的输入数据进行分类。所有的材料都可以在这里找到。

这篇文章中使用的 CNN 是使用 visualkeras 可视化的。请注意,为了美观,第一层没有按比例绘制,但它给出了我为这个问题创建的微型 CNN 的概念。

资源和存储库

在本文中,我们将使用:

  • 张量流 2 和 Keras
  • 霍罗沃德
  • Python 3.8+版本
  • 至少有 1 个 GPU 的计算机
  • 所有的代码和数据都可以在这个库中找到。

数据并行性

在数据并行中,我们部署相同的模型,在不同的处理单元(比如 GPU)上进行训练,但是使用输入数据的唯一子集。在每个时期之后,模型参数被收集、聚集并传送回处理单元,以继续训练它们各自的模型。通过这种方式,每个处理单元使用其自己唯一的数据子集(即数据的一部分)来训练相同的模型,但是模型参数会随着对整个输入数据集的了解而更新。

我如何将这种方法用于神经网络?

如果你使用 TensorFlow、PyTorch 或任何流行的公共深度学习框架,你可以使用 Horovod 进行分布式训练。Horovod 是由优步开发的,目的是将 HPC 的思想引入深度学习。安装相当简单,我就不赘述了,因为他们的 GitHub 页面很好地解释了这一点。在这篇文章的剩余部分,我们将讨论如何使用 Horovod 数据并行化他们的 TensorFlow 代码。

把 Horovod 想象成你现有代码的一个插件。在Horovod-ing你的代码中涉及的步骤遵循数据并行的思想,所以在做任何事情之前,你必须完全理解你的代码将如何被 horo VOD 执行。然后,您必须决定分发数据的方式。一旦完成,就可以开始在代码中实现 Horovod 了。

对我来说,用下面的步骤来处理这个问题更容易。

  1. 了解你的代码将如何用 Horovod 执行,即 horovodrun
  2. 确保您有一个好的数据分发策略
  3. 在代码中初始化 Horovod
  4. 确保您的优化器是分布式的
  5. 从协调器广播您的变量并修复您的回调

我们现在将详细讨论每一点。

1.Horovod 如何运作

Horovodrun 将一些基本的消息传递接口(MPI)命令和概念封装到一个更高级别的 API 中。因此,如果熟悉 MPI 的话,您可以发现两者之间有很多相似之处。在一个有 n 个 GPU 的系统上,人们会执行一个 CNN 代码,这里已经实现了 Horovod,如下所示

horovodrun -np **n** python cnn_parallel.py

用 Horovod 修改过的代码需要用 horovodrunmpirun 来执行。对于数据并行框架,使用 n 个 GPU 可以创建 n 个任务。每个任务都使用 python 运行修改过的 CNN 代码,但是只针对数据的一个唯一子集。在下图中,我也做了同样的解释。我们正在一台有 2 个 GPU 的机器上工作。输入数据集 D 被分成两个子集 a 和 b,使得它们之间没有共同的元素。

理解 Horovod 如何并行执行代码。

这里要记住的重要一点是,您的整个 python 代码将运行 n 次,其中 n 是 GPU 的数量。因此,每个打印命令,每个 IO 操作,每个绘图部分等。将被执行 n 次。起初这可能是一个令人困惑的概念,但好的一面是每个屏幕上的消息(例如 print(…))都有自己的 GPU 标识符。

Horovod 附带了一些有用的调用(类似于 MPI 标准定义的调用),帮助定义我们将在其上运行代码的系统的架构。“hvd.size()”命令显示实际可用的 GPU 数量,“hvd.local_rank()”告诉您 GPU 的本地等级,“hvd.rank()”告诉您 GPU 的全局等级。等级可以被认为是 GPU id。下图更好地解释了这个想法。

了解单节点与多节点设置中 GPU 的大小和等级。

2.数据分发策略

那么,为什么必须分发数据呢?为了充分利用数据并行性,每个 GPU 必须看到唯一的数据子集。然而,如果您传递相同的数据集进行训练,您将在 n 个 GPU 上使用相同的样本对模型进行 n 次训练,或者换句话说,您将使用相同的数据以完全相同的方式运行代码 n 次。这不是我们想要通过数据并行实现的。

为了正确地分配数据,可以采用许多策略。Pytorch、Tensorflow 等都有内置的数据分发方法。,但实际的策略将取决于数据的结构和数据量。

让我们用一个简单的例子来创建一些数据分布策略。假设我们的数据由从 1 到 100 的所有整数组成,按升序排列,没有重复。我们希望将这些数据分布在 2 个 GPU 上。

选项 1:张量流数据生成器

我们将在训练开始时采用在 GPU 上随机分配批次的想法。我们将欺骗 TensorFlow 中的 fitting 调用,使用“steps_per_epoch”关键字将 1/n 个批次分配给每个 GPU。这种方法适用于数据生成器,在我们的例子中是图像数据生成器。我们保持与我们在没有任何 GPU 的情况下训练时相同的批量大小。

用张量流数据发生器进行数据分配。

img_gen = tf.keras.preprocessing.image.ImageDataGenerator(validation_split=split)train_dataset = img_gen.flow_from_directory(directory= train_data_path,target_size=(img_height,img_width),              color_mode=**'rgb'**,batch_size=**batch_size**,class_mode=**'sparse'**,seed=123, shuffle=True, subset=**'training'**)val_dataset=img_gen.flow_from_directory(directory=...  subset=**'validation'**)**total_train_batches** = train_dataset.samples//batch_size**total_val_batches** = val_dataset.samples//batch_size

然后,当我们执行拟合时,我们指示 TensorFlow 仅使用总批次的 1/n 进行训练和验证。这是因为训练将在每个 GPU 上进行,并且通过将“steps_per_epoch”指定为 total_batches/n,我们指示 TensorFlow 在两个 GPU 上拆分批次,以便每个 GPU 从我们的数据生成器获得批次的不相交子集。

history = model.fit(train_dataset,epochs=epochs,batch_size=batch_size,**steps_per_epoch=total_train_batches//hvd.size(),**validation_data=val_dataset,**validation_steps=total_val_batches//hvd.size(),***...*
)

方案二:张量流数据。数据集对象

我们将使用“分片”的概念,这相当于获取数据集中的第 q 个元素。下面的伪代码应该能更好的解释。

D = [1,2,...,99,100]# split into 2 shards
shard_1 = [1,3,5,...]
shard_2 = [2,4,6,...]# split into 3 shards
shard_1 = [1,4,7,...]
shard_2 = [2,5,8,...]
shard_3 = [3,6,9,...]

下面我描述了两种不同的方法,每批 4 个。请注意,这些不是分发数据可以采用的唯一策略,您可以自由设计自己的策略。

  • 方法 A:将数据集分片 2 次→批量化
  • 方法 B:混洗数据集→分片 2 次数据集→批量处理

从机器学习的角度来看,你能解释为什么只有一种方法是正确的吗?

D = [1,2,...,99,100]**# method A**shard_1 = [1,3,5...]
shard_2 = [2,4,6...]shard_1_batch = [[1,3,5,7],[9,11,13,15]...] # split 1
shard_2_batch = [[2,4,6,8],[10,12,14,16]...] # split 2**# method B**D_shuffle = [63,74,22,26,36,14,34,94,60,42,56,17,65,1,12,51...]shuffle_shard_1 = [63,22,36,34,60,56,65,12]
shuffle_shard_2 = [74,26,14,94,42,17,1,51]shuffle_shard_1_batch = [[63,22,36,34],[60,56,65,12]...] # split 1
shuffle_shard_2_batch = [[74,26,14,94],[42,17,1,51]...] # split 2

使用方法 A,所有奇数都在分割 1 中结束,偶数在分割 2 中结束。很明显,方法 B 是最好的,因为产生的分割公平地表示(和分布)了偶数和奇数。

现在想想 CNN 的输入。理想情况下,输入文件夹将包含数千(如果不是数百万)您需要训练的图像,通常分组到不同的类别(子文件夹)。当您从图像文件夹中创建 TensorFlow 数据集时,它会从目录结构中推断出类。下面的片段应该能更好地阐明这一点。

**input_folder
|-train
| |-class_1**
| | |-image_1.jpg
| | |-...
| | |-image_100.jpg
**| |-class_2**
| | |-image_1.jpg
| | |-...
| | |-image_50.jpg
**| |-class_3**
| | |-image_1.jpg
| | |-...
| | |-image_500.jpg

因此,一旦这样的文件夹结构被传递给 TensorFlow,它会自动将文件名映射到它们各自的类,准备好进行处理并传递给 CNN 进行训练。注意,默认情况下,image _ dataset _ from _ directory会打乱文件名,或者换句话说,如果您使用它摄取图像,您的数据集已经被打乱了。

使用分片的数据分发。

import tensorflow.keras.preprocessing as tkplocal_bs = .. # will be scaled with the hvd.size() # we will discuss this laterX_train = tkp.image_dataset_from_directory(..., batch_size = 1) train_dataset = X_train.**unbatch()**.**shard(hvd.size(), hvd.rank()).batch(local_bs).cache()**

hvd.shard() 调用接受 GPU 的数量(创建多少个碎片)和 GPU 的 id 来创建数据的唯一碎片。使用 hvd.size()和 hvd.rank()作为该调用的输入,我们可以轻松地管理将由每个 GPU 处理的数据分割。至此, train_dataset 尚未创建,因此不存在于内存中。它将在最终使用下面的命令训练模型时创建。

model.fit(train_dataset,...)

注意,这里我们使用了 *local_bs,*来代替原来的批量大小。我将很快解释原因。

数据分发后训练模型

一旦我们正确地决定并实现了数据分发策略,我们就准备好训练 CNN 了。此时,使用 2 个 GPU,数据训练策略将被执行,如下所示。

训练 CNN 时执行的数据分发策略。

批量大小和学习率(数据分布策略中的选项 2)

如果你使用过神经网络,你必须熟悉学习率和批量的概念。在数据分布式框架中,人们可能需要正确地调整这些,以补偿我们的训练策略的变化。由于每个 GPU 现在都在用唯一的数据子集训练模型,NN now 在每个时期有效处理的样本数量与批量大小不同。请注意,根据您决定如何分发数据以及如何编写代码,您可能不需要执行这种缩放。根据我的经验,如果相应地调整批量大小和/或学习率,上面的数据分布选项 2 通常会更好。基本上,如果您在实现数据并行后发现奇怪的损失和准确性曲线,那么这可能是要记住的事情。

让我们回到选项 2 的数据分发。我们有 2 个 GPU,数据集由 100 个整数组成,批量大小为 4。每个 GPU 获得 50 个唯一的整数,分组为大小为 4 的批次。每个 GPU 通过处理其自己的 13 个批次(最后一个批次将只有 2 个元素)来执行训练,并且在每个时期之后,模型参数被传递到 Horovod 用于聚合。Horovod 从批量大小为 4 的 GPU 0 和批量大小为 4 的 GPU 1 聚合模型参数,因此有效地批量大小为 8!换句话说,当 Horovod 在每个时期结束时更新模型参数时,模型在技术上“看到”了一个批次,其中每个批次具有 8 个独特的样本。下图应该能更好地解释这一点。

基于两个 GPU 的 CNN 数据分布式训练。在每个时期结束时,Horovod(橙色)聚集来自每个 GPU(蓝绿色和紫红色)的模型参数,并更新 CNN 模型,现在为下一个时期的训练做好准备。

在我们不改变批量大小的情况下,即保持其固定为与代码的非数据分布版本相同的值,我们必须随着 GPU 的总数线性调整学习速率。这是因为在我们的有效批次*中有更多的样本,可以增加算法在寻找损失函数最小值的过程中允许采取的步长。换句话说,我们有更少的噪声(更多的样本),因此我们可以在参数空间中进行更大的跳跃,以便找到最小值。

然而,如果我们希望保持固定的学习速率,即与代码的非数据分布版本相同,我们必须与 GPU 的数量成反比地调整批量大小。让我们以整数为例。对于 2 个 GPU,如果我以 2 的批处理大小对我的每个数据分片进行批处理,那么 Horovod 在每个 epoch 结束时看到的有效批处理大小是 4。因此,我可以保持与数据分发前相同的学习速度。

总结一下:

############################################ THEORY
# original batch size: batch_size
# local batch size: local_bs (batch size on each gpu)#original learning rate: lr
#scaled learning rate: scaled_Llr## option 1: 
# bs= local_bs : therefore, the effective batch size is larger
# therefore scaled_lr = lr*n_gpus## option 2:
# scaled_lr = lr
# therefore local_bs = batch_size/n_gpus 
# now the effective batch size will be the same as before
######################################################################################## IMPLEMENTATION
#**pick one** below:
**# Option 1:**
# local_bs = batch_size
# scaled_lr = base_lr * hvd.size()
# **OR
# Option 2:** local_bs = int(batch_size/hvd.size())
scaled_lr = base_lr
  • 有时,学习率的平方根缩放或 2/3 幂缩放比严格的线性缩放效果更好

3.在代码中初始化 Horovod

第一步是告诉你的代码你将使用 Horovod。

**import horovod.tensorflow as hvd****hvd.init()** # this initiliases horovodprint('Total GPUs available:', hvd.size())
print('Hi I am a GPU and my rank is:', hvd.rank())

下一步是使用 GPU 的本地等级作为标识符,将每个可用的 GPU 固定到一个“进程”。

*# Pin GPU to be used to process local rank (one GPU per process)*
gpus = tf.config.experimental.list_physical_devices('GPU')
for gpu in gpus:tf.config.experimental.set_memory_growth(gpu, True)
if gpus:tf.config.experimental.set_visible_devices(gpus[hvd.local_rank()], 'GPU')

4.分发优化器

这是优化器进行聚合的地方。Horovod 使这变得非常容易,因为我们只需要在代码中添加一行来分发优化器。

opt = keras.optimizers.Adam(learning_rate=learning_rate)# Horovod: add Horovod Distributed Optimizer.
**opt = hvd.DistributedOptimizer(opt)**

5.修复回电

下一步是确保我们不会通过允许所有 GPU 更新模型参数来破坏我们的训练。因此,我们将我们的一个 GPU 声明为“协调器”。这个 GPU 将负责收集模型参数,聚合它们,并在每个训练时期后将它们广播回其他 GPU。请记住,它也将使用自己的数据子集来训练 CNN。通常我们声明排名为 0 的 GPU 为我们的协调器。

callbacks = [# Horovod: broadcast initial variable states from rank 0 to# all other processes. This is necessary to ensure consistent# initialization of all workers when training is started with# random weights or restored from a checkpoint.**hvd.callbacks.BroadcastGlobalVariablesCallback(0),**# Horovod: average metrics among workers at the end of every# epoch.**hvd.callbacks.MetricAverageCallback(),**]# Horovod: save checkpoints only on worker 0 to prevent other
# workers from corrupting them.
**if hvd.rank() == 0:callbacks.append(keras.callbacks.ModelCheckpoint('...h5'))**

运行代码

我们现在准备运行代码。如果您使用的计算机只有 1 个 GPU,您可以从终端执行该命令,如下所示

horovodrun -np 1 python python_code/horovod_dist_gen.py

相反,如果我们要在一台超级计算机上运行它,我们需要编写一个脚本来提交我们的“作业”,其中作业是一段要用给定的资源组合运行的代码。下面是一个脚本的例子,我在一台有 4 个 GPU 的机器上运行代码。

使用带有 Horovod 的 GPU 运行 CNN 代码的 slurm 脚本。

结果如何呢?

无 GPU 时间:14 小时

使用 1 个 GPU 的时间:12 分钟

对于使用碎片的数据分发方法,我们使用 1 个 GPU 获得了 75 倍的速度提升,使用 2 个或更多 GPU 获得了150 倍的速度提升。

在我们的 CNN 代码中实现 Horovod 并使用 1、2 和 4 个 GPU 运行后获得的加速。

与生成器方法相比,以碎片形式分布的数据性能更好。从 1 个 GPU 到 2 个 GPU 的加速几乎是线性的,即 75 倍到 150 倍,但之后就不再加速了。这是为什么呢?这是因为当我们并行处理一个代码时,我们的想法是最大限度地利用可用资源。有了 1 个 GPU,即使代码运行速度比没有 GPU 时快 75 倍,也仍然有从更多计算能力中受益的空间。当我们添加第二个 GPU 时,运行时间减半,从而导致理想的线性加速。此时,我们处于这样一个阶段,即提供给代码的资源对于计算量来说是最优的。增加更多的资源对我们没有好处。因此,我们看不到 4 个 GPU 有更多的速度提升。我们可以使用命令 *nvidia-smi 来监控资源使用情况(在我们的例子中是 GPU 使用情况)。*我不会深入探讨这个话题,但如果你有兴趣,请随时联系我。

结束语

  • 请随意设计您自己的数据分发策略。这通常取决于你的数据是如何组织的,以及数据的大小。
  • 使用 GPU 时,初始设置总会有开销,即根据您使用的系统,可能需要一些时间来设置 GPU-CPU 通信、环境变量等。这是由引擎盖下的系统完成的,所以如果在开始时代码似乎停顿了几秒钟,它很可能只是在设置 GPU。
  • 为了简单起见,我只对训练部分计时。原则上,人们可能需要对整个代码的运行时进行基准测试。这取决于你想优化什么。
  • 为了正确测试性能,需要多次运行相同的代码,以获得更好的运行时统计数据。
  • 还必须检查模型的收敛性,即使用 GPU 的并行化训练应该收敛到与在没有 GPU 的运行中看到的相同的损失和精度值。此外,无论使用多少个 GPU,精度和损耗曲线都应该收敛到相同的值。

如何消除机器学习训练数据中的偏差

原文:https://towardsdatascience.com/how-to-remove-bias-in-machine-learning-training-data-d54967729f88

理解和减少人工智能/人工智能项目训练数据中的偏差

图片作者:作者

在人工智能/人工智能的世界里发生了很大的变化,但是“垃圾”的概念;“清除垃圾”仍然是坚忍的。任何算法的好坏都取决于它的训练数据。而且,没有任何训练数据是没有偏见的,即使是通过自动化生成的数据也是如此。

在过去,许多机器学习算法对某些宗教、种族、性别、种族和经济地位等不公平。IBM 的沃森超级计算机使用医学研究论文数据集向医生提供建议,被发现只支持声誉良好的研究。亚马逊的招聘算法被发现对男性比对女性更有利。COMPAS 是一种风险评估算法,被美国许多州的法官用来帮助判决,因在暴力犯罪中给黑人分配更高的再次犯罪风险系数而受到争议。2016 年,微软对一个 Twitter 聊天机器人(从其他推文中学习)进行了一天的实验,结果糟糕地结束了,该机器人在 16 个小时内发布了 95000 条推文,其中大多数都充满了厌女症、种族主义和反犹太主义思想。

但是,事情是这样的——算法不是不道德的、种族主义的或道德上有缺陷的。然而,他们接受训练的数据是另一回事。

数据偏差很复杂

偏差会破坏多个结点的数据。在收集、数据聚合、模型选择甚至最终用户解释的过程中,它可能会渗入到无害的数据集中。事实上,几乎可以假设没有任何数据不存在这样或那样的偏差。可能是人类训练者的外部偏见造成的。或者,它可能是数据集中任何组的过度简化或不令人满意的表示的结果。

根本原因并不总是很明显。但是,影响是!

数据偏差对机器学习的影响

有偏差的数据集是不平衡的。它未能代表机器学习模型的原始动机。它的结果是不准确的,它的决策是有偏见的,并且它的精度水平可以在不同的环境下变化,从而违背了模型的目的。

COMPAS(替代性制裁的矫正罪犯管理概况)是一个非常受欢迎的例子,说明了在有偏见的数据上训练的自给自足算法的后果。它使用一份问卷来评估罪犯的各种参数,并预测他们再次犯罪的可能性。这一预测被美国许多州和司法管辖区的法官用来量刑。

在几个有问题的决定、关于其完整性的各种问题和几起诉讼之后,ProPublica 检查了该算法的风险评估因素,并观察到两大荒谬之处。

预测精度低于 20%

黑人罪犯被贴错标签的 2 倍

COMPAS 仅仅是一个例子,它展示了由于有偏见的 ML 模型,人类可能不得不遭受的非常真实的后果。任何 AI/Ml 模型的实施范围的影响直接受到算法获得的训练的性质的影响,因此,对创建所述数据集的 数据注释服务 产生影响。

数据偏差的类型

图片作者:作者

样本偏差:

当在研究过程中意外地或有意地排除了一组数据时,样本(或选择)偏差就被引入了系统。这样的样本将不会真实地反映预期的可观察环境,并导致不准确的结果。

**例如,**考虑一个数据集,该数据集研究一个地区 15 年的人口数据,以帮助预测新租户的租期。如果我们错误地将 15 年的期限解释为绝对期限,并将在当地居住时间少于 15 年的租户排除在我们的研究之外,那么可能会引入偏见。删除这样的数据会使模型无效,因为它不会在每个可能的情况下都被训练。

算法偏差:

算法偏差是一种系统误差,它会导致糟糕的计算。它可能是预先存在的问题,也可能是由于程序限制或设计约束而出现的。如果一个特定的算法被用在一个它没有被训练过的环境中,算法偏差也会显现出来。

**例如,**考虑任何自动剽窃检查器,它将超过三个单词长的字符串与一组内容进行比较,并返回相似率。如果目标内容是旋转的,单词用同义词改变,算法的准确率就会下降。

偏见:

偏见的范围很广。它从基于地区的术语差异发展到围绕种族、宗教、性别、性等的更深层次的歧视。数据集中的偏见是由于数据训练者的观点而产生的。

例如,英国的一个数据标注团队仔细查看了女性钱包的图片,并将其标注为钱包。对于美国的数据接收者来说,这种模型将产生无效的结果,因为在美国,“钱包”指的是女人的手提包,而不是钱包。

测量偏差:

数据测量或收集中的问题会导致测量偏差。这种变形可能是分类错误、用于数据捕获的不同工具或基本注释错误的结果。

例如,考虑一个 图像注释服务 提供商,该提供商致力于为自动驾驶项目标记车辆的项目。如果数据集只有道路上车辆的图像,而没有行人或流浪动物的图像,那么训练员将没有其他可标记的内容。最终标记的数据和它给予 ML 模型的训练将非常无效。

排除偏差:

在清理过程中,会对数据集的几个要素进行加权,不重要的要素通常会被移除。然而,如果我们对任何重要的特征赋予较低的重要性,我们可能最终会创建一个具有一些未被充分表示的部分的数据集,从而导致一个有偏见的模型。

例如,考虑一组来自女性的绝经前症状——90%为白人,10%为西班牙裔。很可能这 10%的人被忽视了,因为他们的症状没有被认为是主流。由此产生的算法不太可能诊断出需要帮助的西班牙妇女。

回忆偏差:

在收集过程中,回忆偏差也包含在数据中。如果数据提供者提供的是一个估计值,而不是一个精确值,这将动摇数据集的整体准确性。因此,我们可以认为这是一种测量偏差。

但是,数据注释中的直接回忆偏差的一个例子可以在以下情况下观察到:训练者的标签数据基于近似,并且不一致性重复足够多次,使得数据对于某个特征不可靠。

观察者偏差:

在标注过程中,训练者可能会将其对特定数据要素的看法投射到数据集中,从而导致观察者产生偏差。

两个人给同一组图像加标签会得出不同的结果。例如,尽管指示将图像标记为船或非船,但训练员可能将一艘船标记为游艇,而将另一艘船标记为轮船,从而破坏了结果数据集中的一致性。

对于https://www.suntecindia.com/text-annotation-services.html文本注释服务,观察者偏差也是一个非常常见的现象。我们向供应商提交的文档可能会落入不同地区不同人的任务列表中。他们可能对笔迹有不同的理解,从而在整个数据集中产生明显的不一致。

代表性偏差:

如果我们拿两个相似的情境,仅仅因为相似性就根据另一个来预测其中一个的结果,这将导致表征偏差。表征偏差在流行的短语中被拟人化了——“相关性并不意味着因果关系。”

例如,如果一个算法评估学生的成绩,并预测那些成绩相似的人将进入某个特定的大学,因为他们中的少数人进入了,那么这个预测的准确率将会很低。

同时,如果我们只在数据集上训练算法,而该数据集在算法的预期环境中对所有组没有相等的表示,这也将导致偏差。例如,如果我们只用白人男性的数据集来训练员工面部的算法,它将很难检测出肤色较深或头发较短的女性等。

识别和处理机器学习训练数据集中的偏差

这些例子证明了偏差在本质上是多种多样的,并且可以在其生命周期中的任何点进入样本集。许多偏见并不明显。许多与其他过程混合在一起,以至于识别它们似乎是一个难以管理的挑战。

有几种提议的技术来建立公平感知的机器学习模型。已经开发和研究了许多方法来减少机器学习的训练数据中的偏差,每种方法都遵循不同的上下文。他们中的大多数归结为一件事——在每一步都保持谨慎和好奇是至关重要的。

1.质疑先入为主

机器学习模型从历史决策及其意图中学习,其中意图是已知的。因此,如果过去的决策者在他们记录的决策中表现出任何偏见,ML 模型将面临反映这些偏见的风险。

如果在数据标注期间,训练员将西伯利亚哈士奇和瑞典猎兔犬的图片标记为狼,模型将学习做同样的事情。如果一家公司最近的 20 次招聘是为了 19 名男性和 1 名女性,那么从这一决策数据中学习的 ML 模型可能会丢弃比男性更多的女性简历。

因此,在训练数据准备的每个阶段,询问数据来自哪里,谁的观点影响了早期的决策,以及需要对数据进行哪些相应的更改来清理数据以用于训练目的是很重要的。

2.消除偏见

这个想法很有挑战性;它的实现更是如此。

消除偏见需要对可能污染数据的先入之见有一个近乎彻底的了解。但是,根据机器学习模型的目标,根除潜在的导致偏见的感知可能从还好到非常棘手。

您可以记录组织过程中的问题,并修复它们。但是,在多个动态参数上训练模型时这样做将带来许多新问题。例如,如果你的 ML 模型使用 100 个人的社交媒体帖子来确定他们的就业能力得分,这可能对来自母语不是英语的国家或来自不发达国家的潜在客户不公平。

因此,尽管我们尽了最大努力来识别潜在的偏见并将其根除,但最好是测试结论并验证其有效性。

3.不要放松监督

适用于一组数据的算法不太可能适用于同一数据的扩展版本。如果我们继续用 challenger 模型测试该系统,并验证其预测准确性、透明度和改进率,就有可能。

尽管如此,假设任何机器学习模型都能自给自足都是错误的。随着数据、其预期环境和目标对象的变化,其准确率也会变化。

目前,基于现实世界的机器学习模型中的偏差仍将是一个人工智能难题

尽管有几种合理的公平方法,但机器学习模型在某个领域仍不尽如人意。期望一个模型同时满足多个动态约束并保持其预测精度是不可能的。我们需要根据具体情况做出选择。

然而,目前,创建相当公平的机器学习训练数据主要取决于数据标注和处理。希望在不久的将来,我们会有更具体的方法来创建公平的数据集。

也读作:

为什么外包数据标注更好?

为什么外包视频注释服务对企业有利可图?

Python 熊猫:重命名 DataFrame 列的 4 种惊人方法

原文:https://towardsdatascience.com/how-to-rename-columns-in-pandas-with-examples-24c983fcc3b8

计算机编程语言

了解并掌握这些方法来处理熊猫数据框架中混乱的列名

贾里·海托宁在 Unsplash 拍摄的照片

熊猫是一种快速、有力、灵活的动物!🔋

导入到 pandas DataFrame 中的数据有时会有不正确或混乱的列名,您需要重命名全部或部分列名。

用有意义的列名替换混乱的列名是数据清理的重要步骤。这无疑使整个代码更具可读性,并在接下来的数据处理步骤中节省了大量时间。⏳

今天,我将演示 4 种最好的方法来轻松地更改熊猫数据帧的列名。

📍注意:我使用的是自己创建的 Dummy_Sales_Data ,你可以在我的Githubrepo 上免费获得&用于你的其他练习项目!

让我们首先导入数据集,

import pandas as pd
df = pd.read_csv("Dummy_Sales_Data_v1.csv")
df.head()

虚拟销售数据|作者图片

这是一个简单的 10000 x 12 的数据集,是我在文章 Faker 中创建的:一个惊人且非常有用的 Python 库 **。**📚

你可以在本文末尾下载一个完整的笔记本,里面有所有这些例子!

好吧,我们开始吧..

在深入研究其他方法之前,让我们从最简单直接的方法开始。

熊猫。DataFrame.rename() —使用字典

这是一个数据帧功能,主要用于改变标签。这里,单词— 轴— 指的是行和列,这取决于我们在该函数中为参数axis设置的值。

因为我们更有兴趣了解如何更改列名,所以让我们把重点放在它上面。因此,.rename()函数中的重要参数是如下所示的columns

熊猫。DataFrame.rename() |图片作者

要替换部分或全部列名,您只需传递一个字典,其中将是旧列名,而将是新列名,如下所述。🔽

df.rename(columns={"Status": "Order_Status","Quantity": "Order_Quantity"}).head()

使用 df.rename() | Image by Author 重命名 pandas dataframe 列

如你所见,我在df.rename()中的参数列中传递了字典,其中 是旧的列名状态数量。而 订单 _ 状态订单 _ 数量这是新的列名。

📍注:df.rename()包含一个inplace参数,默认为假。为了保留列名中的更改,您需要执行inplace = True

因为我不想保留更改后的列名,所以我使用了.head()方法来查看更改后的列名。

📍注意:在任何函数中使用inplace = True之前,最好使用.head()来看看变化看起来如何。

接下来的方法是.rename()函数的一个微小变化。

熊猫。DataFrame.rename() —使用函数

就像上面的第一种方法一样,我们仍然会使用.rename()函数中的参数columns。但是除了传递旧名称-新名称键-值对,我们还可以传递一个函数给列参数。

例如,使用这个技巧将所有列名转换成大写字母非常简单,如下所示

df.rename(columns=**str.upper**).head()

使用函数|作者图像重命名列名

我简单地使用了一个字符串函数**str.upper**让所有的列名都是大写的,正如你在上面的图片中看到的。

这里可以使用的字符串函数的完整列表在Python 中的五个必知字符串方法 中有所提及📚

通过这种方式,所有的列名将被一次性修改。然而,这可以通过用户定义的函数来实现。

*是的!!*您可以向参数columns传递任何用户定义的函数,以根据函数更改列名。

例如,您可以编写一个简单的函数来拆分下划线( **_** )上的列名,并只选择其中的第一部分。然后将这个函数传递给如下所示的列。🔽

def **function_1**(x):x = x.split('_')[0]return xdf.rename(columns=**function_1**).head()

根据用户定义的函数更改列名|按作者排序的图像

在上面的输出中可以注意到更改的列名。根据应用的功能,包含**_**的列名在**_**上被拆分,只有第一部分被指定为新的列名,例如 Product_Category 变成 Product

如果它是一个简单的函数,就像上面的一样,你也可以使用 lambda 函数。♻️

接下来让我们看看重命名列的另一种方法..

熊猫。数据框架.列

实际上,这是返回数据帧的所有列名列表的方法,例如

df.columns

使用 df.columns | Image by Author 列出列名

然而,反过来,我们可以将新列名的列表传递给df.columns,然后新列名将被分配给数据帧。

这是它的工作原理..🔽

df.columns = ['OrderID', 'Order_Quantity','UnitPrice(USD)', 'Order_Status','OrderDate', 'Product_Category','Sales_Manager', 'Shipping_Cost(USD)','Delivery_Time(Days)', 'Shipping_Address','Product_Code', 'OrderCode']
df.head()

使用 df.columns | Image by Author 一次更改所有列名

正如你所看到的,我将新列名的列表分配给了df.columns,所有列的名称都相应地改变了。

📍注意:您需要传递所有列的名称。该名称列表的长度必须正好等于数据帧中的列总数。

并且没有任何其他选项,比如inplace,列名被直接永久地改变,这种方法有点冒险。⚠️

因此,我建议只有当您 100%确定想要更改列名时才使用它。

📍注意:列名列表的顺序应该与数据帧中列的顺序相同,否则列名可能会分配错误。

记住以上几点,这是一次性改变所有列的最好方法。

让我们看看最后一个方法..

熊猫。DataFrame.set_axis

该方法最初用于为数据框的轴设置标签,即该方法可用于标记列和行。

您只需将列名列表传递给**.set_axis()**函数,并指定**axis = 1**来重命名列,如下所示🔽

df.set_axis(['A', 'B', 'C', 'D', 'E', 'F','G', 'H', 'I', 'J', 'K', 'L'], axis=1).head()

使用 set_axis() | Image by Author 更改列名

这是您可以更改所有或部分列的列名的方式。这里也必须考虑我在前一个方法中提到的所有要点。

然而,.set_axis()是先前方法df.columns的更安全版本,因为它包含了参数**inplace**。因此,即使在应用更改之前,您也可以预览未来的更改。

要保留更改后的列名,只需使inplace = True

这就是改变列名的全部内容!!

我希望你觉得这篇文章有趣,有用,令人耳目一新。让列名可读性更强、风格更统一总是好的。因此,重命名列是项目开始时需要完成的基本步骤之一。

💡通过 成为中级会员 可以探索中级物品。相信我,你可以访问无限的故事媒介和每日有趣的媒介文摘。我会得到你的费用的一小部分,没有额外的费用给你。

💡不要忘记 注册我的电子邮件列表 来接收我的文章的第一份副本。

📚下面是一个完整的 笔记本 用所有这些方法来重命名列。

感谢您的阅读!

如何在 2 个简单的步骤中在 Tableau 中渲染混合几何类型

原文:https://towardsdatascience.com/how-to-render-mixed-geometry-types-in-tableau-in-2-simple-steps-27b56a2153c4

没有 LOD 计算。用 JavaScript 将空间数据集转换成表格格式。包括完整的代码片段。

近年来, Tableau 凭借其在市场上的高采用率,一直是顶尖的数据分析工具之一。毫无疑问,其商业成功的一个显著原因是其为用户无缝集成多种数据格式的多功能性。

作者截图|浏览 Tableau 的数据源选择页面|注意“空间文件”在这里被突出显示(稍后将详细说明)

例如,Tableau 广泛的数据选择菜单包括一个名为**“空间文件”**的选项,其中所述文件类型通常作为地图可视化显示在仪表板中。一个典型的例子是作为包含地理信息的 JSON 对象存储在文本文件中的geo JSONfeature collection。

(注意:所有 GeoJSON 对象都遵循以下约定。)

{ "type": "FeatureCollection","features": [{ "type": "Feature","geometry": {...},"properties": {...}}]
}

尽管 Tableau 能够读取地图数据集,但一个明显的限制是它无法从单个空间数据源呈现多种几何对象类型— Polygon MultiPolygon Point MultiPoint LineString MultiLineString GeometryCollection

相反,Tableau 用户通常会遇到以下错误消息:

Image by Author |导入同时具有线串和点几何类型的空间文件时,Tableau 显示错误

用例:新加坡国家铁路的地理空间可视化

**注:**触发上述错误的完全相同的 GeoJSON 文件将用于后续演示。

原始文件可在SG-rail-layer . geojson|以上 geo JSON 输出由从https://data.gov.sg/提取的两个特定原始数据源**【1】【2】**合并而成(参见以下引用)

原始数据源:

**【1】**从总体规划-2019-铁路线层(上传于 2020 年)中检索,并于 2022 年 6 月 6 日访问,根据新加坡开放数据许可证的条款提供

**【2】**从总体规划-2019-铁路-车站-图层(上传于 2020 年)中检索,并于 2022 年 6 月 6 日访问,根据新加坡开放数据许可证的条款提供

实施细节

实质上,为了绕过上述问题,另一种方法是将地理空间信息作为单一记录(即表格格式)输入 Tableau,以取代其原始格式。

将行记录导入 Tableau 不仅可以消除任何类似或相关的错误,还可以按预期有效地读取和呈现。

(注意在本文中,表格数据格式的选择应为 基于行的 JSON )。其他表格格式,如 excel 或 CSV 格式也可以。)

数据转换过程总共有 2 个步骤

第一步。提取所有嵌套的几何体对象

如前所述,存在的各种类型的几何体对象有— Polygon MultiPolygon Point MultiPoint LineString MultiLineString GeometryCollection

因此,该步骤的主要目标是分解这些嵌套几何图形的粒度,使得 GeoJSON 对象中只存在Polygon Point LineString。完成这项工作的 JavaScript 代码片段如下(uncombineGeometriesInFeatureCollection(geojsonObj)):

**参考消息:**输出的 GeoJSON 原始数据文件可从SG-rail-layer-un combined . geo JSON中检索

第二步。将所有要素对象转换为对象数组

此后,transformFeatureCollectionToRowJSONObj(inputGeojsonObj)下面的 JavaScript 代码片段遍历每个 feature 对象并生成相应的行记录:

解释:

  • 字段F_ID被附加到每个特征,以便将其“父特征”标识为单个行记录
  • 因此,当在 Tableau 中读取时,每个未合并的要素(例如,多面到面)被标记为字段F_SUBID作为其单独的标识符
  • 每个几何体对象都包含一个深度不同的坐标数组(取决于几何体类型)
  • 因此,每个坐标对必须作为单行记录输出**,以便以表格格式正确解释(1 个坐标对= 1 行记录)**
  • 对于每个特征对象,除了 6 个字段F_ID F_SUBID Geometry Type PT_ORDER X Y之外,生成properties对象中的字段,并作为每个坐标对的 JSON 对象输出
var obj = {"F_ID":0, // Parent feature ID"F_SUBID":0, // Nested Geometry ID (before being unmerged)"Geometry Type":"", // Point,Polygon or LineString"PT_ORDER":0, // Position in array of Geometry Coordinates"X": 0, // longitude"Y": 0 // latitude
};
var rowObj = {...JSON.parse(JSON.stringify( <properties obj> )), // deep copy...obj
};

代码成功运行后,产生的输出将是一个rowObj数组,该数组随后可以用存储在一个单独的文件中。json 文件扩展名。

概念验证—展示 Tableau 输出

为了测试空间数据是否被正确转换,在 Tableau 数据选择菜单上,将文件作为**“JSON 文件”**导入:

作者截图|“JSON 文件”选项在菜单选项列表中被选中,而不是“空间文件”

如下图所示放置每个尺寸后,所有几何对象(即线串和点)将继续渲染新加坡的火车站和铁路网:

作者截图| Tableau 中 JSON 输出的显示。请注意,在“标记”面板中,选择了“线条”而不是“地图”

**参考消息:**以上 Tableau 文件可以从 Tableau Public 的链接下载🔗表格中混合几何类型的演示(最好在桌面/PC 监视器设备上观看)

请随意调整它或使用您自己的用例的所有代码片段!🙃

现在你知道了!非常感谢你坚持到这篇文章的结尾!❤希望你觉得这篇文章有用,如果你想了解更多地理信息系统(GIS)、数据分析&网络应用相关的内容,请随时关注我的媒体。会非常感激—😀

— 🌮请给我买个玉米卷 ξ(🎀˶❛◡❛)

https://geek-cc.medium.com/membership

要了解更多 Tableau 技巧和变通方法,请随意查看下面的文章列表:

</5-lesser-known-tableau-tips-tricks-hacks-with-use-case-demo-463f98fbdc7e>

如何用字典列表替换数据框

原文:https://towardsdatascience.com/how-to-replace-dataframes-with-lists-of-dictionaries-41bd5d8d716a

由 Unsplash 上的 Element5 数码拍摄

Pandas DataFrames 是一种非常方便的读取、编辑和可视化小表格数据的方式。但是它们也有一些主要的缺点:

  • 它们不能很好地处理 Python 原生数据类型
  • 它们对嵌套数据不方便
  • 有些操作可能会非常慢
  • 它们占据了很多空间

当从 API 获取数据时,API 可能会返回一个 JSON 字符串。虽然有一种方法可以将 JSON 字符串转换成 DataFrame,但是一个好的旧字典列表会更好。

在本文中,我将比较数据帧和字典列表,并编写一个自定义类来重新创建字典列表中数据帧的主要功能。

记忆

假设你有一个卖水果的商店,想存储你的订单。对于这个例子,我们将生成一个 1000 个水果订单的随机列表。

现在,让我们比较一下这个列表和包含这个数据的熊猫数据帧之间的大小差异。我们可以使用 sys 库来这样做。

这给了我们以下结果:

List: 9032 bytes, DataFrame size : 111584 bytes

所以就内存而言,链表比数据帧表现得好得多。

打印对象

打印数据帧的头部会给我们带来很好的可读性(如果你在笔记本上阅读的话会更好):

id                                             basket
0   0  [{'fruit': 'raspberry', 'price': 68, 'weight':...
1   1  [{'fruit': 'peach', 'price': 5, 'weight': 107,...
2   2  [{'fruit': 'banana', 'price': 99, 'weight': 20...
3   3  [{'fruit': 'peach', 'price': 67, 'weight': 158...
4   4  [{'fruit': 'pear', 'price': 1, 'weight': 90, '...

然而,有了字典列表,结果就不那么美好了。

[{'id': 0, 'basket': [{'fruit': 'apple', 'price': 89, 'weight': 68, 'color': 'blue'}, {'fruit': 'pear', 'price': 94, 'weight': 89, 'color': 'yellow'}]}, {'id': 1, 'basket': [{'fruit': 'strawberry', 'price': 26, 'weight': 86, 'color': 'red'}, {'fruit': 'banana', 'price': 76, 'weight': 244, 'color': 'pink'}, {'fruit': 'pear', 'price': 90, 'weight': 123, 'color': 'pink'}, {'fruit': 'peach', 'price': 83, 'weight': 65, 'color': 'pink'}, {'fruit': 'banana', 'price': 83, 'weight': 229, 'color': 'yellow'}]}, {'id': 2, 'basket': [{'fruit': 'raspberry', 'price': 8, 'weight': 258, 'color': 'orange'}, {'fruit': 'banana', 'price': 86, 'weight': 31, 'color': 'green'}, {'fruit': 'apple', 'price': 39, 'weight': 208, 'color': 'green'}, {'fruit': 'peach', 'price': 73, 'weight': 116, 'color': 'orange'}, {'fruit': 'raspberry', 'price': 82, 'weight': 57, 'color': 'purple'}, {'fruit': 'strawberry', 'price': 72, 'weight': 31, 'color': 'pink'}]}, {'id': 3, 'basket': [{'fruit': 'strawberry', 'price': 47, 'weight': 99, 'color': 'orange'}, {'fruit': 'pear', 'price': 40, 'weight': 38, 'color': 'pink'}, {'fruit': 'pear', 'price': 19, 'weight': 182, 'color': 'orange'}, {'fruit': 'watermelon', 'price': 27, 'weight': 249, 'color': 'yellow'}, {'fruit': 'watermelon', 'price': 93, 'weight': 202, 'color': 'red'}, {'fruit': 'apple', 'price': 65, 'weight': 112, 'color': 'purple'}, {'fruit': 'banana', 'price': 24, 'weight': 150, 'color': 'pink'}]}, {'id': 4, 'basket': [{'fruit': 'banana', 'price': 19, 'weight': 271, 'color': 'purple'}]}]

别担心!我们可以从 list 类继承并重写格式化打印列表的神奇方法。

我们所要做的就是使用 json.dumps 函数来获得一个“经典的”json 视图。我们也可以尝试每行打印一行,但这不允许我们看到完整的数据。

[{"id": 0,"basket": [{"fruit": "peach","price": 89,"weight": 121,"color": "red"},{"fruit": "peach","price": 17,"weight": 163,"color": "red"},{"fruit": "watermelon","price": 19,"weight": 36,"color": "yellow"},{"fruit": "watermelon","price": 88,"weight": 39,"color": "blue"},{"fruit": "banana","price": 14,"weight": 131,"color": "purple"},{"fruit": "peach","price": 72,"weight": 94,"color": "yellow"},{"fruit": "raspberry","price": 74,"weight": 285,"color": "pink"},{"fruit": "strawberry","price": 88,"weight": 203,"color": "orange"}]},{"id": 1,"basket": [{"fruit": "pear","price": 77,"weight": 136,"color": "blue"},{"fruit": "peach","price": 7,"weight": 98,"color": "green"},{"fruit": "peach","price": 94,"weight": 292,"color": "green"},{"fruit": "raspberry","price": 23,"weight": 69,"color": "pink"},{"fruit": "watermelon","price": 35,"weight": 120,"color": "pink"}]},{"id": 2,"basket": [{"fruit": "strawberry","price": 52,"weight": 36,"color": "blue"},{"fruit": "pear","price": 42,"weight": 241,"color": "purple"},{"fruit": "pear","price": 66,"weight": 165,"color": "orange"}]},{"id": 3,"basket": [{"fruit": "peach","price": 88,"weight": 219,"color": "blue"},{"fruit": "raspberry","price": 80,"weight": 87,"color": "green"},{"fruit": "apple","price": 42,"weight": 247,"color": "purple"},{"fruit": "banana","price": 97,"weight": 154,"color": "orange"},{"fruit": "banana","price": 37,"weight": 177,"color": "green"}]},{"id": 4,"basket": [{"fruit": "strawberry","price": 48,"weight": 64,"color": "green"}]}
]

访问值

现有方式

假设我们想要访问订单 5 和订单 6 的篮子。

对于数据帧,这非常简单,我们只需使用**。锁定**方法。

但是对于列表,你必须使用列表理解:

新方法

这有点烦人,它返回一个列表,而不是我们刚刚创建的类。因此,就像我们对 str 方法所做的一样,我们可以重写 getitem 魔法方法,它允许我们使用索引和切片来访问元素。

要对行进行过滤,我们只需使用切片父方法。但是要过滤列,我们必须更有创造性,使用字典理解来过滤关键字。

比较性能

现在让我们看看哪种方法更快。

List : 0.025424789999999975 seconds for 10000 iterations
DataFrame : 1.14112228 seconds for 10000 iterations

实际上,用我们的字典列表访问一个值要快得多!

设置值

假设我们想要设置值 id_store 。目前,我们只有一家商店,所以我们将把 id_store 设置为 1。

现有方式

有了数据框架,这是非常方便的。

对于列表,我们可以这样做:

虽然它不是一段很长的代码,但它仍然是两行而不是两行。

新方法

让我们定义另一个神奇的方法,使用括号为每个字典设置一个值。

我们现在可以非常容易地将一个键分配给一个值或一组值:

对比表演

我们的新方法能像熊猫的数据帧一样好吗?让我们再次比较 timeit 模块的性能。

List : 0.852329793 seconds for 10000 iterations
DataFrame : 0.996496461 seconds for 10000 iterations

这一次,列表和数据帧的性能非常相似。

映射列

我们想计算每个订单的总购物篮价格。我们如何做到这一点?

现有方式

数据帧有一个映射功能,对于这种类型的计算非常方便。

对于一个列表,我们再次需要迭代:

新方法

让我们为字典列表创建一个映射函数,让它像熊猫一样简单!这其实很简单,因为我们可以在不同的函数中处理赋值和返回值( mapsetitem )。

现在,它变得与 DataFrame 映射方法相同。

比较性能

又到了衡量业绩的时候了!

List : 11.182705553 seconds for 10000 iterations
DataFrame : 16.0493823 seconds for 10000 iterations

太棒了,我们的榜单再次成为冠军!

后续步骤

虽然 Pandas 在快速浏览 CSV 文件方面非常出色,但我肯定会更频繁地使用这个新的 DictList 类来对大文件或嵌套文件进行基本转换。

我可能会把这变成一个项目,并创建一个具有更多功能的库。

你会使用这个图书馆吗?要让字典列表成为你最喜欢的结构,你需要什么样的特性?

资源

下面是一些链接,可以探索文章中讨论的一些概念:

  • 熊猫文档
  • 系统文档
  • Tech with Tim 魔术方法视频教程

如何将有向图表示为邻接矩阵

原文:https://towardsdatascience.com/how-to-represent-a-directed-graph-as-an-adjacency-matrix-d4e8135c2fe4

R 中的示例

照片由艾丽西娅鲍威尔,Pixistock。

图表是以直观的方式展示高维数据的绝佳方式。但是当涉及到用矩阵来表示图形时,可能就不那么直观了。在前面的中,我们看到了如何将一个无向图表示为一个邻接矩阵。在本教程中,我们将着眼于把有向图表示为邻接矩阵。

与无向图不同,有向图具有方向性。这通常由从一个节点到另一个节点的箭头表示,表示关系的方向。Twitter 和 Instagram 是有向图的极好例子,因为你可以跟踪一个人,而他们不会跟踪你。现在,让我们开始看看如何用邻接矩阵来表示有向图。对于本教程,我们将使用 visNetwork 包,我们将从查看一个没有回路或自边的有向图开始。

示例 1:没有回路的小型有向图

首先,我们将为 visNetwork 创建一个节点数据帧来初始化我们的网络节点。我们的网络将由 6 个节点组成,标记为 1 到 6。然后,我们将创建一个 edges 数据框来添加节点之间的关系。为了确保网络是定向的,数据帧将有一个箭头列表示关系的方向。在本例中,所有关系都将从列流向列。最后,我们将使用 visNetwork() 绘制我们的网络。

library(visNetwork) # Create nodes dataframe for visNetwork. 
nodes <- data.frame (id = 1:6, label = 1:6, color = rep('#8BB1AB', 6)) # Create edges dataframe for visNetwork. 
edges <- data.frame(from = c(1, 2, 3, 3, 4, 5), to = c(2, 3, 4, 5, 5, 6), arrows = 'to') # Plot network using visNetwork. 
visNetwork(nodes, edges) %>% visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)

作者图。

类似于我们对无向图所做的,我们让邻接矩阵的行和列代表节点或顶点。这将产生一个正方形矩阵。然而,与无向图不同的是,1 表示从列 j 行 I 的箭头。注意:你可以反过来看,箭头从列 I 到行 j。确保你知道使用的是哪个版本。

对于上图,邻接矩阵如下所示:

由于从节点 1 到节点 2 有一条边,我们在中看到 1

(第 2 行,第 1 列)。这种方向性经常导致不对称矩阵。此外,我们可以看到对角线完全由零组成,因为从任何节点到其自身都没有边。现在,让我们看一个例子,我们有循环和多边。

示例 2:带有回路和多边的小型有向图

在本例中,我们将保留上面的节点数据框,但指定一个新的边数据框。因为我们想要循环,我们将有一个从 2 到 3 的关系和从 3 到 2 的关系,给我们一个循环。我们将创建的第二种循环是自我边缘,其中关系循环回到自身。我们将通过使关系从 1 1来建立与节点 1 的自边。最后,我们将把所有新的关系存储在一个名为 edgesMessy 的数据帧中。

# Create new edges dataframe for visNetwork. 
edgesMessy <- data.frame(from = c(1, 2, 3, 3, 4, 5, 1, 3, 5, 5), to = c(2, 3, 4, 5, 5, 6, 1, 2, 6, 6),arrows = 'to') # Plot network using visNetwork. 
visNetwork(nodes, edgesMessy) %>% visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)

作者图。

这里,邻接矩阵如下所示:

请注意,循环表示为 1。对于有向图来说,每一个有向关系都是计数的,并且回路只有一个有向关系。(如果节点 1 有两个环路,条目将是 2。)我们还可以看到,节点 5 和 6 之间有三条边。因此,

现在用 3 表示。

概括一下:

  • 邻接矩阵总是正方形的
  • 有向图的邻接矩阵并不总是对称的
  • 没有回路的有向图在对角线上会有零点
  • 无向图中的每个循环都用 1 表示
  • 邻接矩阵可以解释多条边

原载于 2022 年 2 月 16 日 https://thatdarndata.comhttps://thatdarndata.com/how-to-represent-a-directed-graph-as-an-adjacency-matrix/

如何恢复 Google BigQuery 意外删除的数据

原文:https://towardsdatascience.com/how-to-restore-data-accidentally-deleted-from-google-bigquery-1ec2a621149f

详细说明,以帮助您恢复意外删除的数据,而不是提前获得任何白发

你有没有在 Google BigQuery 中不小心删除了一个重要的表、视图或者整个数据集?如果有,您知道您不能继续使用包含已删除数据的表和查询。

OWOX 团队已经创建了一个详细的分步说明来恢复被删除的数据,以及一些步骤来防止将来出现类似的问题。

如果已删除的表自删除以来未超过七天,并且您知道其名称和从中删除该表的数据集的名称,则可以恢复该表。

要恢复表,请在 Google BigQuery 界面中打开云 Shell 命令行:

作者图片

输入以下命令:

bq cp mydataset.mytable@-3600000 mydataset.newtable

带有表名和数据集名的相同命令示例:

bq cp OWOXBI_Reports.123_Transactions_withModels@-13600000 OWOXBI_Reports_Restore.123_Transactions_withModels

其中:

  • owo xbi _ reports . 123 _ Transactions _ with models-是已删除的数据集和表。
  • owo xbi _ Reports _ restore . 123 _ Transactions _ with models-数据集以及要在其中还原数据的表的名称。
  • @-13600000 —过去的一段距离(13,600,000 毫秒前),此时您要查找的表仍然存在。例如,如果一个表在 30 分钟前被删除,那么设置时间间隔@ -3600000 就足够了,这是一个小时前(60 秒×60 分钟× 1000)。

输入请求后,需要授权。单击授权按钮:

作者图片

该命令成功运行后,该表将被恢复:

作者图片

您将看到类似以下内容的文本:

Waiting on bqjob_r4ca30008c2e3147d_0000017af0d58e5e_1 ... (0s) Current status: DONE Table 'summer-drive-112011:OWOXBI_Reports_Restore.test_table@-600000' successfully copied to 'summer-drive-112011:OWOXBI_Reports_Restore.test_table'

如何恢复已删除的视图

您不能以上述方式恢复远程视图。那种方法只适用于表。

Google 支持建议使用日志浏览器来恢复已删除的视图。

要查找更新远程视图的查询,请在谷歌云平台日志中运行以下查询:

resource.type="bigquery_resource" protoPayload.methodName="tableservice.update" protoPayload.serviceData.tableUpdateRequest.resource.tableName.tableId="custom_events_attribution_VIEW"

其中:

  • tableservice.update —是在日志中显示视图更新的命令
  • custom _ events _ attribution _ VIEW 视图的名称

在选择时间范围设置中,设置可对视图进行更改的时间段(例如,一年):

作者图片

执行该命令时,将显示更新了您正在查找的视图的所有查询。选择最后一个时间戳查询:

作者图片

从日志中复制查询并重新创建视图。

作者图片

此外,您可以找到创建您正在寻找的视图的查询(在此之前,我们搜索更新视图的查询)。为此,请使用以下命令:

resource.type="bigquery_resource" protoPayload.methodName="tableservice.insert" protoPayload.serviceData.tableInsertRequest.resource.tableName.tableId="query_name_VIEW"

作者图片

我们建议您设置尽可能长的时间来搜索日志中所需的条目。

如果视图是在开始记录日志之前创建的,则无法恢复。在这种情况下,我们上面描述的 tableservice.update 命令会有所帮助。

如何恢复已删除的数据集

如果您删除数据集,您将无法恢复它。您必须创建一个同名的新数据集,还原已删除数据集中的表和视图,并将它们移动到新的数据集中。

在删除数据集后的前 24 小时内,不能创建同名的新数据集,但仍可以找到属于已删除数据集的表和视图的名称。但是,表和视图本身将不再可见。

通过在 BigQuery 中搜索,可以按名称从已删除的数据集中查找视图:

作者图片

无法通过搜索找到表的列表,因为表的名称中没有公共组件。

若要从已删除的数据集中查找表名,请使用以下 SQL 查询。在查询中,指定可以修改表的时间段(creation_time BETWEEN)。因此,该查询将返回在哪个时间段内对其进行了更改的表。这些将是已删除数据集中的表。

SELECT * 
FROM ( SELECT query, user_email,         CONCAT(destination_table.project_id,".",destination_table.dataset_id,".",destination_table.table_id) AS destination_table, 
COUNT(job_id) AS job_ids, 
MAX(creation_time) AS lastUpdateDate 
FROM region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT 
WHERE creation_time BETWEEN TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 180 DAY) AND TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 0 DAY) AND state = 'DONE' 
AND CONCAT(destination_table.project_id,".",destination_table.dataset_id,".",destination_table.table_id) LIKE "%OWOXBI_Reports.%" 
GROUP BY 1, 2, 3 
ORDER BY 5 DESC)

作为请求的结果,您将收到以下信息:

  • 查询-对 destination_table 进行更改的查询的文本
  • 用户电子邮件—启动目标表更新请求的用户
  • destination _ table 已更新的表
  • job_ids —在指定的时间间隔内开始查询的次数(创建时间介于…)
  • last updatedate-查询的上次启动时间(MAX(creation _ time)AS last updatedate)

删除数据集 24 小时后,您可以创建一个同名的新数据集,并开始恢复表和视图。

如何防止将来出现类似问题

  1. 当您开始使用项目时,在 Google BigQuery 项目中打开日志收集。
  2. 不要将表命名为数据集,也不要将其视为数据集。
  3. 仔细检查您想要从 Google BigQuery 中删除的任何表的名称。
  4. 通过查询删除表,而不是通过用户界面。
  5. 将实体类型添加到数据集、表和视图名称中。例如:
  • OWOXBI _ 报表 _ 数据集
  • OWOXBI_report_table
  • OWOXBI_report_view

您可以使用查询删除表:

DROP TABLE `summer-drive-112011.OWOXBI_Reports_Restore.test_table`

您还可以使用查询删除视图:

DROP VIEW `summer-drive-112011.OWOXBI_Reports_Restore.test_VIEW`

如果问题再次发生,如何缩小问题的规模

  • 不要更改计划和 Google Apps 脚本中的查询;第二天,恢复所有视图和表,之后 Schedule 和 Google Apps 脚本将正常工作。
  • 如果视图或表参与了属性模型的设置,您需要在将数据恢复到其先前位置后重新开始属性计算。

关于该主题的有用链接:

恢复删除的表格

删除表格

管理观点

如何在 Google BigQuery 中即时恢复一个表

如何反向编码 R 中的音程音阶

原文:https://towardsdatascience.com/how-to-reverse-code-an-interval-scale-in-r-917c13e4888e

清除问卷和测量数据的简单方法

来自 Pexels 的 Alex Green 拍摄的照片

如果您使用 R 进行数据分析,很可能会遇到处理区间数据的情况。通常,能够在一个区间尺度上反转数据是很有用的。下面是如何做的,有一步一步的例子。如果您希望本文中的所有代码都包含在一个脚本中,请查看最后的 GitHub 要点。

使用调查数据

假设你是一名心理学家,收集了关于人们焦虑体验的数据。你对人们进行了调查,询问他们现在有多焦虑,他们每天经历焦虑想法的频率,等等。你要分析这些数据,给每个参与者的焦虑评分。但是,您使用的调查问卷中有几个措辞相反的问题,而通常的回答量表是反过来的。当你把每个参与者的回答加起来时,你需要颠倒这些答案的编码来得到正确的分数。

幸运的是,在 r 中有一种简单的方法来进行这种分析。

假设我们调查中的每个项目都使用 7 分的李克特量表,如下所示:

“1 =强烈不同意;2 =不同意;3 =有些不同意;4 =既不同意也不反对;5 =有些同意;6 =同意;7 =非常同意”

我们可以通过从这个响应量表中随机取样值来创建一个数据集,如下所示。

library(tidyverse)# Generate some simple data
survey_data <- tibble(participant = 1:7,worried_thoughts = sample(myscale, 7),anxiety_effects = sample(myscale, 7)
)

该数据集的第一列worried_thoughts,包含参与者对陈述“我经常有侵入性的担忧想法”的响应。第二列anxiety_effects,包含对陈述“焦虑很少影响我的日常生活”的响应。

由于第二种说法的措辞,高数字分数表明焦虑感低。这意味着对这一陈述的回答必须进行反向编码,以便与其他正常措辞的问题进行比较,其中高数字分数意味着高焦虑。

幸运的是,这有一个简单的公式。

如何反转区间标度上的值

要在区间标度上反转值,您需要取变量所在标度的最小值,减去要反转的值,然后加上标度的最大值。

这个公式适用于从任何数字(正数或负数)开始的反应等级。它也适用于具有任何大小间隔的标尺,只要该间隔是一致的。

以下是应用此公式反转数据集中数值区间值的几种方法的示例。

myscale <- 1:7# The tidyverse way
survey_data <- survey_data %>%mutate(anxiety_effects_reversed = min(myscale) - anxiety_effects + max(myscale))# The base R way
survey_data$anxiety_effects_reversed <- min(myscale) - survey_data$anxiety_effects + max(myscale)

在这段代码中,我们首先定义问题中使用的数值范围。这只是一个数字 1 到 7 的向量,存储在变量myscale中。

然后,我们可以在反向编码公式中使用myscale中的值。在 tidyverse 示例中,该公式被表示为min(myscale) — response + max(myscale),其中response是要重新编码的列中的值。

这真的很简单,你可以用 Base-R 或 Tidyverse 来应用它,如图所示。在这两个例子中,反向编码操作的结果存储在新列response_reversed中。

反转几个区间标度变量

照片由威廉·沃比在 Unsplash 上拍摄

当您需要翻转数据集中几个问题的尺度时,该怎么办?你可以像以前一样用同样的公式做这件事,只需要一点点小技巧。

对于本例,让我们创建更多的示例数据,这次有多个问题。

# Generate more data
full_survey_data <- tibble(question = unlist(map(1:5, ~ rep(paste0("Question", .), 5))),participant = rep(1:5, 5),response = sample(myscale, 25, replace = T)
)

该数据是长格式的,这意味着在第一列中有多个重复的行。如果你有兴趣,你可以在这里阅读更多关于长数据和宽数据的区别。如果您的问卷数据不是长格式,您可以使用 r 中的 pivot_longer 函数进行转换。

要对数据集中的一些问题进行反向编码,同时保持其他问题不变,我们首先需要选择我们想要重新编码的问题。我们可以通过创建一个包含我们正在记录的问题名称的向量来做到这一点。在这种情况下,我们希望颠倒问题 2 和 3 的得分。

# Define vector of question names that you want to reverse
reverse_questions <- c("Question2", "Question3")

现在,我们可以使用这个向量来选择性地应用我们的重新编码操作。我们可以通过在 mutate 中使用case_when来做到这一点,这是我最喜欢的 tidyverse 函数之一。

full_survey_reversed <- full_survey_data %>%mutate(response = case_when(question %in% reverse_questions ~ min(myscale) - response + max(myscale),TRUE ~ as.integer(response)))

一开始可能会有很多东西需要处理,所以让我们把它分解一下。

这段代码使用了mutate,这是一个操作现有列的值或创建新列的函数。我在上一个例子中也使用了它,但是在这个例子中,我已经设置了它来将我们操作的结果分配给已经在数据中的response列。这意味着它将改变该列中的一些现有值。

然后,case_when函数反转 response 列中的值,但是只针对我们想要重新编码的问题。它的工作原理是根据一个条件检查每一行数据。这里,它检查问题列的值是否在我们前面定义的问题名称向量中。

如果是,它会将比例反转公式应用于“响应”列中的值。您可以在case_when行中的波浪号(~)后看到这一点。如果给定的行不包含我们选择重新编码的问题,case_when将返回 response 列的原始值。它通过TRUE ~ as.integer(response)命令来实现这一点。

这段代码的结果是,对于我们选择的问题,response中的值被反转,对于我们没有选择的问题,值保持不变。

给问卷打分现在很简单。同样,我们使用 tidyverse 函数,这一次是对响应进行求和,以获得每个参与者的分数。

# Sum up each participant's survey score
full_survey_reversed %>%group_by(participant) %>%summarise(total_score = sum(response))

恭喜你!您现在可以轻松地反转 R 音程音阶。对于本文中使用的所有代码,请参见下面的要点。

数据清理快乐!

想阅读我所有关于 R 编程、数据科学等方面的文章吗?在这个链接注册一个媒体会员,就可以完全访问我所有的作品和媒体上的所有其他故事。这也直接帮助了我,因为我从你的会员费中得到一小部分,而不需要你额外付费。

只要我在这里订阅,你就可以把我所有的新文章直接发到你的收件箱里。感谢阅读!

如何运行 A/B 测试

原文:https://towardsdatascience.com/how-to-run-a-b-tests-709d73a5347a

如何使用统计数据对比例进行 A/B 测试的简单指南

作者图片

如果你能不断测试不同的想法,在线营销和创业成长会更好。当我们必须进行 A/B 测试时,这个统计数字就派上用场了。通过适当的分析,你可能获得的结果会给你的项目带来巨大的推动。

什么是 A/B 测试?

公司经常需要将某项行动的结果与另一项行动的结果进行比较,以确定表现最好的行动。一般来说,经常需要检查一组可能的解决方案中哪一个是最佳解决方案。例如,如果您运行一份新闻稿,您可能希望测试同一封电子邮件的不同主题,然后选择打开率最高的主题。这就是 A/B 测试的总体思路。你把你的听众分成两个相等的部分:A 和 c。然后,你根据你要测试的项目(例如,你要测试的对象的数量)把 A 分成两个同样大小的子集。你得到了 A 和 B 子集。重要的是,所有这些集合不要重叠,并且它们必须在统计上相似(即,不能有任何特定的规则来区分彼此)。

然后,您将主题为 1 的电子邮件发送给 A,主题为 2 的电子邮件发送给 b。

一段时间后,您测量 A 和 b 的表现。表现最好的一组将会告诉您哪个选择是成功的。最后,您可以将带有获奖主题的电子邮件发送给受众 c。

如何比较 A/B 测试的结果

假设您的 A/B 测试给出了以下结果:

数据集 A

  • 尺寸:2128
  • 开口:12

数据集 B

  • 尺寸:2128
  • 开口:18

数据集 B 给出了比数据集 A 更多的正面事件,所以人们可以认为 B 是赢家。实际上 A 的开放率是 0.56%,B 的开放率是 0.85%。

我们应该选择 B 吗?嗯,当我们处理样品时,事情就不那么容易了。大数定律确保开盘价向其“真实”值收敛,但这些估计值来自样本,因此它们受到有限规模效应的影响。因此,它们的差异可能是由于随机效应,而不是 B 对 a 的真实有效性。

为了解决这个问题,我们必须进行统计分析。

为了统计比较这些数字,我们首先需要计算它们的置信区间,例如 95%的置信度。

我已经讲过比例的置信区间的计算。总的想法是使用正态近似来计算我们估计的置信区间。

对于相当大的 N (通常大于 30)值,比例 p 的 95%置信区间为:

如果我们在数据集上进行这样的计算,我们得到 A 的置信区间是(0.25%,0.88%),而 B 的置信区间是(0.46%,1.23%)。

让我们画出这些间隔,看看会发生什么。

置信区间对比图。图片作者。

正如我们所看到的,虽然 B 的平均值比 A 高,但置信区间彼此重叠。这是典型的有限尺寸效应,因为我们的样本当然是有限尺寸的。

这个图告诉我们,这两个度量在统计上是相似的,因为它们的置信区间重叠。所以,我们不能说 B 比 a 表现得更好。

为了达到显著性水平,我们可以使用正态近似法计算双尾 p 值。

首先,我们计算一个 z 变量的值。

在我们的例子中, z = -1.10

然后,我们计算双边 z 测试的 p 值,其零假设是比例相等。我们得到的值是 13.6%。所以我们可以说,如果比例相等,我们只能在 13.6%的实验中得到这样的极值。如果我们拒绝 p 值小于 5%的零假设,我们不能拒绝本例中的零假设。

我不喜欢使用 p 值,因为它们不能给我们一个明确的答案。相反,我更喜欢可视化置信区间,看看它们是否重叠。然而,如果你在一个广泛使用 p 值的环境中工作,你可以使用一个 z 测试来计算你的 p 值。

A/B 测试清单

因此,这里有一个通用的 A/B 测试方法:

  • 计算 A 和 B 的比例
  • 根据以下公式计算置信区间
  • 将它们可视化并验证它们是否重叠。如果置信区间重叠,你不能说比例在统计学上有差异。如果它们没有重叠,你可以有 95%的把握说它们是不同的

一个方便的网络应用程序

可以在 Python、R 甚至 Excel 中执行 A/B 测试。但是,如果您需要快速的结果,并且不想自己开发应用程序,我已经创建了一个简单的 web 应用程序,它将为您计算置信区间和 p 值。您可以在所有测试中随意使用它。

结论

A/B 测试是初创企业成长的标准方法。他们真的能够让一家初创公司迅速扩大规模,因为他们能够快速、成功地验证任何可能的想法。然而,为了从 A/B 测试中提取最大值,您必须始终使用正确的统计数据。

原载于 2022 年 5 月 20 日 https://www.yourdatateacher.comhttps://www.yourdatateacher.com/2022/05/20/how-to-run-a-b-tests/

如何在 Docker 容器中运行数据科学项目

原文:https://towardsdatascience.com/how-to-run-a-data-science-project-in-a-docker-container-2ab1a3baa889

环境设置

关于如何将您的数据科学项目包装在 Docker 映像中并在 Docker 容器中运行它的一些技巧和实际示例

伊恩·泰勒在 Unsplash 上拍照

为数据科学项目编写代码时,它应该尽可能具有可移植性,也就是说,即使在不同的机器上,它也可以被执行任意多次。

在建模和测试阶段,数据科学项目在您的机器上正常工作,但在运行时出错的情况经常发生。

这可能是由于例如主机上安装的不同版本的库和软件。

为了应对这个问题,你可以使用虚拟机,它们构成了一个隔离独立的环境,允许你执行代码。然而,虚拟机有一个问题,它们托管整个操作系统,这通常会占用几千兆字节的存储空间。

因此,最好使用更轻便的系统来构建独立的应用程序。

在本文中,我描述了 Docker 平台的概况,它允许您通过一点点努力来构建独立的应用程序。另外我给你提供一个实际的例子,把一个数据科学项目变成 Docker 镜像。

文章组织如下:

  • Docker 入门
  • Docker 项目的结构
  • 构建和运行 Docker 映像
  • 实际例子。

Docker 入门

Docker 是一个允许你构建、运行和管理独立应用的平台。其思想是构建一个应用程序,不仅包含编写的代码,还包含执行代码的所有上下文,比如库、环境变量等等。

当您用所有上下文包装您的应用程序时,您构建了一个 Docker 映像,它可以保存在您的本地存储库中或公共 Docker 存储库中,也称为 Docker Hub 。

如果你想运行你的 Docker 镜像,你需要为它创建一个 Docker 容器。如果可以为同一个映像创建多个容器,那么可以多次运行同一个 Docker 映像。

要开始使用 Docker,可以从这个链接下载。根据您的操作系统,您将下载不同的安装程序。

安装后,您可以运行应用程序或使用命令行实用程序。

Docker 由以下组件组成:

  • Docker 引擎 —用于构建、运行和管理 Docker 映像和容器的本地平台
  • Docker Hub —所有公共和私有 Docker 映像的存储库
  • Docker 客户端 —与 Docker 引擎交互的客户端。它可以是命令行工具,也可以是使用 Docker 引擎提供的 REST APIs 的对象。

2 Docker 项目的结构

要构建 Docker 映像,您至少应该定义两个元素:

  • 你的申请
  • 一份文件

该应用程序可以是您的数据科学项目。在本文中,您将看到 Python 中的一个例子,因此您应该添加另一个名为requirements.txt的文件,它包含您的应用程序所使用的 Python 包的列表。

2.1 文档文件

Docker 文件是 Docker 用来构建独立应用程序的文件。你可以在这个链接找到 Dockerfile 的完整文档。

下面这段代码显示了 docker 文件的基本结构:

FROM <BASE_IMAGE>
COPY <SRC> <DTS
RUN <COMMANDS_AT_BUILD_TIME>
CMD <ENTRY_COMMANDS_AT_RUNTIME>

FROM指令包含 Docker 构建应用程序的基础映像。例如,基本映像可以是特定的操作系统。要选择最适合您的观测范围的基础图像,您应该注意图像大小以及您的应用程序所需的软件包和软件。比如你只需要 Python,你可以选择一个 slim 版本的 Python 作为基础镜像。你可以在这个链接找到官方 Python 图片列表。

COPY指令复制 Docker 映像中的源文件。典型的COPY语句是:

COPY . .

它将文件系统的当前目录中包含的所有文件复制到 Docker 映像的当前目录中。

RUN指令在构建过程中运行指定为参数的命令。例如,在RUN指令下,您可以安装项目所需的所有 Python 库,如下所示:

RUN pip install --no-cache-dir -r requirements.txt

在前面的代码中,requirements.txt文件包含要安装的所有包的列表,每行一个。

CMD指令指定运行应用程序时要执行的命令。在 Python 项目中,CMD 指令应该指定用于运行主应用程序的命令:

CMD ["python", "./app.py"]

2.2 要求. txt

如前所述,该文件包含要安装的 Python 包的列表,每行一个,如下面的代码所示:

numpy
pandas
scikit-learn

3.构建和运行 Docker 映像

在本节中,您将看到:

  • 如何建立码头工人形象
  • 如何运行 Docker 映像
  • 如何将 Docker 图像保存到 Docker Hub
  • 从 Docker Hub 获取 Docker 图像

3.1 建立码头工人形象

要为您的数据科学项目构建 Docker 映像,您应该输入包含您的项目的目录,然后从终端运行以下命令:

docker build -t <IMAGE_NAME> .

最后一个点(.)表示包含您的应用程序的当前目录。

一旦构建了 Docker 映像,就可以通过编写以下命令来检查它的可用性:

docker images

作为输出,前面的命令显示了本地存储库中所有可用的 Docker 图像。

3.2 运行 Docker 映像

要运行 Docker 映像,您应该告诉 Docker 引擎为它构建一个容器。您可以从文件系统中的任何地方运行以下命令:

docker run -rm --name <CONTAINER_NAME> <IMAGE_NAME>

-rm参数告诉 Docker 引擎在停止运行时删除容器。

3.3 将 Docker 映像保存到 Docker Hub

Docker Hub 是 Docker 图像的注册表。它包含私有和公共图像。要将 Docker 图像保存到 Docker Hub,您首先需要在这个链接创建一个账户。

创建帐户后,您可以从命令行登录,如下所示:

docker login

系统要求您输入用户名和密码。输入密码后,您就可以登录到您的远程存储库。

要将 Docker 映像添加到 Docker Hub,您需要将至少一个标记添加到您的 Docker 映像,如下面这段代码所示:

docker -tag <MY_LOCAL_IMAGE> <MY_LOCAL_IMAGE>:<MY_TAG>

以及您的远程映像:

docker tag <MY_LOCAL_IMAGE>:<MY_TAG> <MY_ACCOUNT>/<MY_LOCAL_IMAGE>:<MY_TAG>

然后,您可以将本地映像推送到 Docker Hub:

docker push <MY_ACCOUNT>/<MY_LOCAL_IMAGE>:<MY_TAG>

3.4 从 Docker Hub 获取 Docker 映像

要从 Docker Hub 获取 Docker 映像,只需运行以下命令:

docker pull <MY_ACCOUNT>/<MY_LOCAL_IMAGE>

4 一个实际例子

作为一个实际的例子,我们可以为我在上一篇文章中描述的例子构建一个 Docker 映像。该项目在三种不同的条件下计算 K-最近邻分类器的 ROC 和精确召回曲线:

  • 不平衡数据集
  • 过采样数据集
  • 欠采样数据集。

这个例子的目的是将描述的应用程序包装到 Docker 映像中,并将生成的图形保存在当前目录中。关于项目代码的更多细节,可以参考我之前的文章。

你可以从我的 Github 库下载该项目的原始代码。

4.1 设置

您可以按照下面描述的步骤将示例转换为 Docker 图像:

  • 由于原始代码是用 Jupyter 编写的,首先,您需要将其下载为 Python 脚本。简单地说,您可以访问 Jupyter 中的文件菜单,并选择下载 Python 脚本。
  • 然后,您可以创建一个新目录,其中应该包含所有项目,包括源数据集。在我们的示例中,源数据集位于source目录下,因此您可以将其复制到当前目录。
  • 将下载的脚本重命名为 app.py,打开,将所有出现的plt.show()替换为plt.savefig(f”{images_dir}/roc.png”),其中image_dir是包含输出目录名的变量,比如images
  • 现在,您可以创建requirements.tx t 文件,它应该包含所有需要的库:
numpy
pandas
scikit-learn
imblearn
matplotlib
scikit-plot
  • 您可以按如下方式创建 Dockerfile 文件:
FROM python:slim
WORKDIR /app_home
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
CMD ["python", "./app.py"]

FROM指令指定使用 Python 的精简版本,因此生成的图像不会占用太多存储空间。

WORKDIR指令定义了 Docker 映像中的当前目录。

COPY指令将文件系统中我们目录的内容复制到 Docker 映像中的工作目录。

RUN指令安装所有的 Python 库。

CMD指令定义当 Docker 运行容器中的图像时运行哪个应用程序。

4.2 构建和运行 Docker 映像

现在,从当前目录,您可以通过以下命令构建映像:

docker build -t test-model .

您可以通过以下命令运行它:

docker run --rm -v `pwd`:/app_home test-model

注意,我们已经使用了 -v参数来映射文件系统中的当前目录(由pwd指定)和 Docker 映像中的app_home目录。这允许我们访问应用程序生成的图表。

摘要

恭喜你!您刚刚学习了如何将您的数据科学项目转换为 Docker 映像!该程序非常简单,并且产生可移植的软件,该软件也可以在不同于你的机器上使用!

您可以从我的 Github 资源库下载本教程中使用的代码。

如果你读到这里,对我来说,今天已经很多了。谢谢!你可以在这个链接阅读我的趋势文章。

相关文章

你认为使用 Docker 太复杂了吗?请改用 virtualenv

Python virtualenv 是一个独立的 Python 环境,您可以在其中仅安装项目所需的包。

此处继续阅读。

保持联系!

  • 跟着我上媒体
  • 注册我的简讯
  • 在 LinkedIn 上连接
  • 在推特上关注我
  • 跟着我上脸书
  • 在 Github 上关注我

如何在 AA 电池上运行深度神经网络一周

原文:https://towardsdatascience.com/how-to-run-a-deep-neural-network-on-a-aa-battery-for-a-week-75ac6247198e

极限边缘深度学习的新硬件平台

当我们谈论深度学习和神经网络时,我们经常会想到谷歌 Colab 或最新的 Nvidia GPUs,它们可以兼作空间加热器。但与训练不同,深度学习推理可以发生在更简陋的平台上。有些卑微到甚至被认为是'边缘计算'。

照片由卡斯帕·卡米尔·鲁宾在 Unsplash 上拍摄

不,我们不是在这里谈论谷歌珊瑚边缘 TPU 板或英伟达杰特森纳米开发板。功耗在 5-10 瓦之间,与我们讨论的主题相比,它们仍然是耗电大户。但是如果你还想了解他们,你可以看看 Manu 的这个详细对比。

我们正在谈论一个真正的极限边缘人工智能计算平台,它可以进行关键字检测和 FaceID ,同时消耗几毫瓦的功率。最接近的竞争对手将是低功耗的 ARM Cortex-M4 或 M7,它的速度要慢几个数量级,因此对于给定的任务,它需要更多数量级的能量。我们说的是 MAX7800x 系列的 AI 微控制器,在运行深度神经网络时,它的名字几乎和它的核心温度一样酷。

肯尼斯·乔尔的照片

先说 MAX78000 里的秘制酱。除了 ARM Cortex M4 主 MCU 和基于 RISC-V 的智能 DMA 之外,它还有一个由 64 个并行处理器组成的专用 CNN 加速器。是的,64。它还有一个基于 SRAM 的 432kB 重量存储器,可存储多达 350 万个重量(假设 1 位重量),因此重量即使在部署后也可以更改。该加速器可用于实现多达 64 层的神经网络,每隔一层进行池化,或 32 层,每层最多 1024 个输入或输出。

这意味着,前向传播不是像在传统硬件上那样在三重嵌套矩阵乘法循环中串行运行,而是可以使用 CNN 加速器以更高的并行度运行。此外,虽然主要是一个 CNN 加速器,但它也可以用来实现传统的神经网络以及 RNNs。

深度学习工程师可能会将 64 层、40-350 万 param 神经网络描述为与其他现代网络相比微小,但在这些约束条件下仍然可以做很多事情。看看深度学习社区如何利用受约束的超参数进行创新将是一件有趣的事情。

最近推出的 MAX78002 更进了一步,几乎将 CNN 加速器的大部分规格增加了一倍。在不久的将来,我们只能期待持续的改进和更强大的加速器。

https://www.maximintegrated.com/en/products/microcontrollers/MAX78002.html

何时使用“人工智能微处理器”

  • 确定性的低延迟性能是一个优先事项—完全离线实施不仅比需要网络连接的实施更快,而且更具确定性,因为它只取决于固定的硬件性能,而不是可能随带宽变化或有时完全失败的网络速度。
  • 隐私和数据安全至关重要——如果您家中的音频和视频记录被实时传输到云端,您会有什么感受?当数据从未离开源时,它是最安全的。
  • *【金发女孩】*问题陈述——这个问题复杂到需要一个神经网络,但又简单到可以用一个相对简单的小网络来解决。

以下是一些符合上述标准的用例,大致分为三类:

演讲和其他音频

  • 关键词 /不同域的安全词检测。使用 MAX78000 构建了能够识别多达 20 个独特单词的 CNN。
  • 工业应用中基于音频的故障检测。机器运行时独特的声音信号可以传达很多关于其健康状况的信息,并证明对预测性维护非常有用。尤其是在像海上石油钻塔这样的偏远地区。

计算机视觉

  • 远程视觉——在网络不可用的情况下的计算机视觉,例如在野生动物保护中——特别是动物跟踪和监视。一个仅在检测到特定动物时锁定的“相机陷阱”将是一个有趣的解决方案,可以用 MAX78000 来构建。
  • 制造—解决一个非常特殊的故障检测问题,在这种情况下,由于网络问题导致的停机是不可容忍的。
  • 视觉唤醒词’—人类存在检测已经在一些功能较弱的微处理器上实现,这可以扩展到包括凝视检测,这在家庭自动化中可能特别有用。
  • FaceID——使用 MAX78000,一个网络可以被训练为完全离线的 FaceID 系统识别多达 20 张人脸。

其他传感器

  • 惯性传感器——实时活动识别和姿态检测问题变得越来越复杂,需要更强大的技术来提供见解。基于 LSTM 和 CNN 的 IMU 传感器融合算法就是这样一个例子
  • 生物医学传感器——可以使用离线神经网络来检测来自可穿戴式心电图贴片或动态心电图监护仪的心电图信号中的心房颤动或其他异常。它还可以连接到多参数患者监护仪,并结合来自多个来源的数据,用于对患者病情恶化的早期洞察。

借助 ADI 公司的这个 Github 库,MAX7800x 系列的入门变得非常简单,该库包含 MCU 的 SDK 以及用于训练和综合您自己的定制模型的所有必要工具。

https://github.com/MaximIntegratedAI

MAX78000 是一款真正独一无二的微控制器,将彻底改变我们所知的深度学习。随着 ARM 宣布 ARM v9 将优先于 DSP 和 ML 硬件加速器,我们可以期待更多超低功耗深度学习技术。与 Ethos-U55 神经处理单元配对的新 ARM Cortex-M55 有望在基于现有 Cortex-M 的系统上实现 480 倍的 ML 性能提升。

https://www.arm.com/company/news/2021/03/arms-answer-to-the-future-of-ai-armv9-architecture

深度学习已经是一个令人兴奋的领域,随着这些最新的硬件创新,我们可以期待它随着更广泛的应用而达到更高的高度。敬请关注 EdgeAI 和深度学习的更多思考!

参考文献&链接

https://www.youtube.com/watch?v=K-J-HAh4I5Q
Face ID 演示

参考设计(Camera Cube)https://www . electronics weekly . com/news/products/bus-systems-sbcs/ai-Camera-reference-Design-runs-battery-includes-ai-hearing-2021-07/
https://www . mouser . in/new/maxim-integrated/maxim-maxref des 178-ai-reference-Design/

2020 年边缘计算公告https://www . allaboutcircuits . com/news/2020-year-of-edge-ai-Compute/

ARM v9 公告https://www . ARM . com/company/news/2021/03/arms-answer-to-the-future-of-ai-ARM v9-architecture

cortex-M55+Ethos U55
https://www.arm.com/products/silicon-ip-cpu/ethos/ethos-u55
https://armkeil . blob . core . windows . net/developer/Files/pdf/product-brief/arm-Ethos-U55-product-brief . pdf

如何在谷歌云平台(GCP)上运行稳定的扩散服务器

原文:https://towardsdatascience.com/how-to-run-a-stable-diffusion-server-on-google-cloud-platform-gcp-c879357808bf

构建和部署 Flask 应用程序的分步指南

自从 Stability.ai 在短短几周前发布了 stability Diffusion(他们的开源文本到图像模型)以来,ML 社区已经为它打开的大门而疯狂。作为 OpenAI 的门控 DALL E 2 的开源替代品,稳定扩散为每个人提供了一些东西:最终用户可以几乎免费地生成图像,开发者可以将模型嵌入到他们的服务中,ML 工程师可以调查和修改代码,研究人员有充分的回旋余地来进一步推动最先进的技术。

尽管有大量关于如何利用稳定扩散的教程,但我自己找不到一个验证过的托管模型的方法。我的目标是从我的浏览器舒适地向我自己的服务发出 HTTP 请求。没有信用额度,没有登录的麻烦,没有人偷看我的照片。因此,我开始了为期一天的探索,在谷歌云上构建和部署一个稳定的扩散网络服务器。

人工智能生成的图像。左:稳定扩散。右:中途。通过生成的提示简洁 AI :“棉花糖做的火在雨中跳舞的机器人,超逼真,真实感,4k,精致,辛烷渲染”。

这篇文章包括了我必须弄清楚的所有痛苦的小细节,希望它能节省你的时间。以下是一些高级步骤(我们将在下面更深入地探讨每一个步骤):

  1. 确保你有足够的 GPU 配额
  2. 创建一个连接了 GPU 的虚拟机
  3. 下载稳定扩散和测试推断
  4. 捆绑稳定扩散到烧瓶应用程序
  5. 部署您的 web 服务器并使其可公开访问

1.确保你有足够的 GPU 配额

由于 GPU 仍然不便宜,谷歌对其 GPU 车队实行严格的管理,将有限的供应提供给最需要它的人,以及那些愿意付费的人。默认情况下,免费试用帐户没有 GPU 配额。要检查您的 GPU 配额:

Navigation (hamburger menu) > IAM & Admin > QuotasCTRL+F表示“GPU(所有地区)”。如果您的限额为 0 或您当前的使用率为 100%,您将需要请求额外的配额。否则,您可以跳到下面的步骤 2。

要增加您的配额,请选择“GPU(所有区域)”行,然后单击EDIT QUOTAS按钮(控制台的右上角)。对于本教程,您将需要一个单一的 GPU,所以增加您的配额 1。请注意,您必须在您的请求中包含一个理由— 确保您提供了一个 CPU 不能满足您需求的解释。我最初的请求被拒绝了,因为它只包含了一个空洞的便条。在我的第二次(也是成功的)尝试中,我明确表示我正在处理一个需要 GPU 的大型 ML 模型。请注意,如果您的请求由人工审核,可能需要 2-3 个工作日;如果你跟进并解释你的紧急情况,他们可能会更快回复。

2.创建一个连接了 GPU 的虚拟机

一旦有了 GPU 配额,现在就可以创建一个连接了 GPU 的虚拟机(VM)实例。

从导航(汉堡菜单):Compute Engine > VM instances。然后点击CREATE INSTANCE(控制台左上角)。关于如何填写此表格的一般说明,您可以遵循此官方指南;这里,我将重点介绍与运行稳定扩散特别相关的设置:

  • 系列:选择N1
  • **机器类型:**选择n1-standard-4。这是最便宜的选择,有足够的内存(15GB)来加载稳定的扩散。不幸的是,下一个最便宜的选项(7.5GB)不够用,当加载模型并将其传输到 GPU 时,您将耗尽内存。
  • **GPU 类型:**展开CPU PLATFORM AND GPU,点击ADD GPU按钮。选择NVIDIA Tesla T4 —这是最便宜的 GPU,它完成了这项工作(它有 16GB 的 VRAM,符合稳定扩散的 10GB 要求)。如果好奇,可以看看对比图和定价图。请注意,您可以让 GPU 抢占以获得更好的价格(例如,谷歌将在需要它用于更高优先级的工作时收回它),但我个人认为即使只是玩玩也令人沮丧。
  • **图片:**向下滚动到Boot disk,点击SWITCH IMAGE。对于操作系统,选择Deep Learning on Linux;对于版本,选择Debian 10 based Deep Learning VM with CUDA 11.0 M95
  • 访问:假设你想要公开你的服务器:(a)在Identity and API access下,选择Allow default access;以及(b)在Firewall下,选择Allow HTTP trafficAllow HTTPS traffic

最后,点击CREATE按钮。请注意,这可能会相当昂贵(在撰写本文时,每月估计约为 281 美元)。

在 Google Cloud 上安装了 GPU 的虚拟机的月成本明细(来自 GCP 控制台的截图)。

3.下载稳定扩散和测试推断

一旦创建了 VM 实例,就可以通过 SSH 访问它。您可以从控制台选择“SSH-in-browser”选项,或者从终端运行以下命令:

gcloud compute ssh --zone <zone-name> <machine-name> --project <project-name>

在你第一次登录的时候,你可以选择安装必要的 GPU 驱动程序。确保通过键入“y”来接受:

Would you like to install the Nvidia driver? [y/n]

接下来,让我们验证一下,你可以在本地运行稳定扩散推断。首先,下载必要的工件:

# Clone the public Github repository.
git clone [https://github.com/CompVis/stable-diffusion.git](https://github.com/CompVis/stable-diffusion.git)# Create a Python virtual environment.
cd stable-diffusion
conda env create -f environment.yaml
conda activate ldm

我们将使用 HuggingFace 的diffusers库来测试推论。创建一个名为inference.py的新文件,内容如下:

import torch
from torch import autocast
from diffusers import StableDiffusionPipelineassert torch.cuda.is_available()pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4",use_auth_token=True
).to("cuda")prompt = "a photo of an astronaut riding a horse on mars"
with autocast("cuda"):image = pipe(prompt)["sample"][0]  image.save("astronaut_rides_horse.png")

接下来,通过控制台登录 HuggingFace,然后运行推理脚本:

huggingface-cli login
# Enter the access token from your HuggingFace account.python inference.py

这种调用可能会失败,并把你导向一个 HuggingFace 链接,在那里你被期望接受使用稳定扩散的条款和条件(他们只是想让你承认你不是邪恶的)。选中该框后,重新运行推理代码(大约需要 15 秒),并确保可以在austronaut_rides_horse.png下找到生成的图像。要将其下载到您的机器上进行查看,您可以使用gcloud compute scp

4.捆绑稳定扩散到烧瓶应用程序

既然您已经验证了推理的正确性,我们将构建一个 web 服务器作为 Flask 应用程序。在每次查询时,服务器将读取prompt参数,使用稳定扩散模型运行推理,并返回生成的图像。首先,安装 Flask 并为应用程序创建一个目录:

pip install Flask
cd ~; mkdir flask_app

将这个简单的 Flask 应用程序粘贴到一个名为app.py的文件中:

from flask import Flask, request, send_file
import io
import torch
from torch import autocast
from diffusers import StableDiffusionPipelineapp = Flask(__name__)
assert torch.cuda.is_available()pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", use_auth_token=True
).to("cuda")def run_inference(prompt):with autocast("cuda"):image = pipe(prompt)["sample"][0]  img_data = io.BytesIO()image.save(img_data, "PNG")img_data.seek(0)return img_data[@app](http://twitter.com/app).route('/')
def myapp():if "prompt" not in request.args:return "Please specify a prompt parameter", 400 prompt = request.args["prompt"]img_data = run_inference(prompt)return send_file(img_data, mimetype='image/png')

请注意,这个应用程序非常简单,它只是返回原始图像。一个更实用的应用程序将返回一个 HTML 表单,其中有一个提示输入字段,可能还有其他旋钮(如所需的图像尺寸)。GradIO 和 Streamlit 是构建更复杂应用的优秀库。

现在验证 Flask 应用程序运行无误:

export FLASK_APP=app
export FLASK_DEBUG=true
flask run

这应该会在端口 5000 上启动本地主机上的服务器。您还不能从浏览器访问此服务器,因为默认情况下端口 5000 不可访问。

5.部署并使您的服务器可公开访问

虽然 Flask 的默认服务器很适合开发,但在生产中使用 gunicorn 部署 Flask 应用程序是标准做法。我不会在这里涵盖原因,但你可以阅读这篇伟大的解释为什么 gunicorn 是首选。要安装它,只需运行pip install gunicorn。要启动 web 服务器,请运行以下命令:

gunicorn -b :5000 --timeout=20 app:app

-b参数正在设置所需的端口。您可以将其更改为任何其他未使用的端口。--timeout参数设置 gunicorn 重置其工人之前的秒数,假设出现了错误。由于在稳定扩散模型中运行正向传递平均需要 15 秒,因此将超时设置为至少 20 秒。

如果您想让服务器在您退出 VM 实例后继续运行,那么您可以使用nohup Linux 实用程序(即“no hick-ups”):

nohup gunicorn -b :5000 --timeout=20 app:app &

最后一个&符号将进程发送到后台运行(因此您重新获得了对命令行的控制)。日志将被导出到一个名为nohup.out的文件中,该文件通常位于您运行命令的目录中。

创建防火墙规则以使端口可访问

最后一步是从浏览器向该服务器发出请求。为此,我们需要让您的端口可以访问。

从导航(汉堡菜单):VPC Network > Firewall。从顶部菜单中,点击CREATE FIREWALL RULE。在表单中,设置以下内容:

  • 名称:允许-稳定-扩散-访问(或您喜欢的名称)
  • 日志:开
  • 交通方向:入口
  • 匹配动作:允许
  • 目标:指定的目标标签
  • 目标标签 : deeplearning-vm(当你选择“Linux 上的深度学习”镜像时,这个标签会自动添加到你的 vm 中。您可以手动向 VM 添加另一个标记,并在这里引用它。)
  • **协议和端口:**TCP-5000 或您选择的端口。

表格完成后,点击CREATE

从浏览器向 web 服务器发送查询

最后,找到您的虚拟机的 IP 地址(从导航菜单,COMPUTE ENGINE > VM INSTANCES)并查看您的虚拟机的“外部 IP”列。如果 IP 地址是 12.34.56.789,那么您的网络服务器可以通过http://12 . 34 . 56 . 789:5000访问。

记住,服务器需要一个名为prompt的参数,我们可以将它作为 HTTP 参数发送。对于提示“机器人跳舞”,下面是网址的样子:

http://12.34.56.789:5000?prompt=robots%20dancing

确保浏览器不会自动默认为https(而不是http,因为我们没有设置 SSL 证书)。

从浏览器访问您的稳定扩散网络服务。(图片由作者提供)

免责声明:该服务器尚未投入生产

这个 webserver 没有做好生产使用的准备有很多原因,但最大的瓶颈是它的单个 GPU 设备。考虑到运行推理需要 10GB 的 VRAM(而我们的 GPU 只有 15 GB 的内存),gunicorn 无法提供一个以上的工作人员。换句话说,服务器一次只能处理一个查询(解决这个问题需要 15 秒)。

对于计算强度较低的任务,标准解决方案是“无服务器的容器化微服务”平台,如谷歌云运行(GCR);AWS 和 Azure 也有类似的产品。开发人员将他们的网络应用捆绑在容器(独立的计算环境,包含运行应用所需的所有依赖关系,如 Docker )中,并将它们交给云。GCR 将这些容器部署在实际的机器上,并根据需求(每秒的请求数)扩展部署;如果有必要,GCR 可以为您的服务分配数万个 CPU,从而使其高度可用。您不需要担心自己关闭服务器,或者在服务器死机时重启它们。这种计费模式对用户来说也很方便,用户最终要为每次使用付费(而不是永久保持固定数量的机器)。

然而,截至 2022 年 9 月,谷歌云运行不支持 GPU。鉴于 GPU 的购买和运营成本仍然相当高,谷歌仍然保护 GPU 的使用并不令人惊讶。人们只能假设 GCR 的自动缩放算法无法防止设备长时间闲置;虽然闲置的 CPU 不是大损失,但闲置 GPU 是更大的机会成本。此外,他们可能希望防止人们盲目扩大规模,并在月底面临巨额账单的情况。

顺便提一下, Google Cloud Run for Anthos 开始提供 GPU,但这是一项面向需要多个云和内部环境之间互操作性的高级用户/高端客户的服务。它绝对不适合那些想要自带稳定扩散 web 服务器的 ML 发烧友。

运行自己的服务器的替代方案

虽然研究通过谷歌云提供稳定传播的最佳方式很有趣,但这不一定是生成人工智能图像的最有效方式。根据您的需要,以下工作流程可能更合适:

  1. 对于非技术用户:前往 Dreamstudio ,Stability.ai 的官方服务,在那里你可以获得一些免费积分。
  2. 对于只想玩玩的 ML 爱好者:使用 Google Colab 。借助免费层,您可以随时访问 GPU。10 美元/月,你可以升级到 Colab Pro ,它承诺“更快的 GPU 和更多的内存”。
  3. 对于寻求将稳定扩散嵌入其服务的开发者:从调用 API 复制,费用为 0.0023 美元/秒。他们保证 80%的呼叫在 15 秒内结束,因此一幅图像的第 80 个成本百分位数约为 0.0345 美元。 Replicate 类似于更广为人知的 HuggingFace ,但是更侧重于计算机视觉而不是自然语言处理。目前,HuggingFace 还没有为稳定扩散提供他们的标准“加速推理”API,但它很可能正在工作中。

如何在真正的量子计算机上运行代码

原文:https://towardsdatascience.com/how-to-run-code-on-a-real-quantum-computer-c1fc61ff5b4

IBM Quantum 入门

量子机器学习要不要入门?看看 动手量子机器学习用 Python

量子计算机不再是科幻小说了。他们存在。我们可以免费使用它们。例如,IBM 提供对他们基于云的量子计算机的访问。

首先,我们需要为 IBM 的量子计算服务注册。点击“创建一个 IBMid 账户”并提供您的详细信息。一旦您验证了您的电子邮件地址,您就可以开始了!

作者图片,摘自 IBM 量子计算服务

仪表板提供了您预订的 IBM Quantum 服务的概览。最重要的是,它描述了“您的系统”单击“查看全部”,然后在搜索栏右侧的过滤器下拉列表中选择“您的系统”。

您将大致了解您可以访问的系统。这是几个有少量量子位的系统。但这些足以入门。

作者图片,摘自 IBM 量子计算服务

当您单击一个系统时,您将获得其体系结构和配置的更详细视图。例如,右下角的图形显示了系统的量子位是如何连接的。当使用真正的量子计算机时,你必须应对的一个限制是,我们只能使连接的量子比特相互纠缠。

作者图片,摘自 IBM 量子计算服务

所以,假设我们想在 5 量子比特的基多设备上运行我们的量子电路。

当然,我们需要首先创建我们的电路。通常,我们在 Jupyter 笔记本上这样做。如果你还没有安装并运行 Jupyter,这篇文章解释了如何安装 JuypterLab。

所以,我们打开一个新的 Jupyter 笔记本。

我们从一些输入开始,然后定义电路。

如你所见,我们只纠缠相连的量子位(第 14 和 15 行)。

在执行代码之前,我们需要连接到 Quito 设备。因此,我们需要使用您的令牌加载我们的帐户。您可以从 IBM Quantum dashboard 获得您的 API 令牌。这是一根很长的绳子。确保它的安全。

接下来,我们连接到提供商并获得 Quito 后端。如果您想要连接到其他后端,您可能需要选择另一个中心、组和项目。但是 IBM 会让您知道他们何时允许您访问任何其他提供商。

然后,我们需要传送电路。在这一步中,Qiskit 重写您的代码以满足设备的要求。例如,如果我们纠缠两个没有物理连接的量子位,Qiskit 会重写电路以符合硬件要求。

最后,我们组装电路并将其发送到返回一个job对象的后端。

作业对象允许您管理您的请求。例如,您可以获取它的状态

最有可能的是,该作业将在队列中等待相当长的时间。

<JobStatus.QUEUED: 'job is queued'>

让我们再来看看 IBM 量子仪表板。您现在应该在“最近的工作”列表中有一个条目。当你点击它的时候,你会看到细节。在那里,你还可以看到你的赛道计划何时运行。在我的情况下,它需要大约半小时。

作者图片,摘自 IBM 量子计算服务

另一个重要的信息是作业 id。您也可以通过编程方式获得它。

'61b32368e4d3eb10e15c8b0e'

当然,我们对工作完成后的结果感兴趣。但也许你不想等那么久。因此,您可能希望稍后检索作业。

如果您保持笔记本打开或稍后检索作业,作业对象将在完成后返回结果。

{'00000': 25,'00001': 50,'10001': 2,'10010': 2,'10100': 1,'10101': 4,'11101': 1,'00010': 36,'00011': 26,'00100': 204,'00101': 601,'00110': 28,'00111': 39,'01001': 1,'01010': 1,'01100': 1,'01101': 2
}

位串表示量子位的测量值(从右向左读取)。我们可以看到,位置 4 和位置 5 的上量子位并不总是 0。这可能看起来很奇怪,因为我们没有对它们做任何事情。因此,它们应该保持默认状态 0。不幸的是,量子位对噪音非常敏感。

结论

噪音和错误是我们今天在量子计算中必须应对的最大问题之一。例如,IBM 最近宣布了一项总额为 10 万美元的奖金,用于在 IBM Quantum 的 7 量子位 Jakarta 系统上使用 Trotterization 模拟三粒子系统的海森堡模型哈密顿量。完成这项挑战的主要问题是应对噪音。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

在这里免费获得前三章。

如何使用 PyTorch 时序转换器运行推理

原文:https://towardsdatascience.com/how-to-run-inference-with-a-pytorch-time-series-transformer-394fd6cbe16c

在您不知道解码器输入的情况下,在推断时间使用 PyTorch 转换器进行时间序列预测

郭锦恩在 Unsplash 上拍照

在这篇文章中,我将展示如何使用 PyTorch 转换器进行时间序列预测。具体来说,我们将使用 PyTorch 时间序列转换器,我在上一篇文章中描述了如何使用 PyTorch 制作用于时间序列预测的转换器。

这篇文章的结构如下:首先,我将简要描述 PyTorch 时序转换器需要什么输入。然后,我将向您展示当您不知道解码器输入值时,如何使用模型进行推理。最后,我将指出所示方法的一些缺点。

时序转换器模型需要什么输入?

如果你没有读过我的文章“如何为时间序列预测制作 PyTorch 转换器”,让我们先简单回顾一下时间序列转换器需要什么输入。关于更详细的演示,请参见上面提到的帖子。请注意,术语trgtgt有时会在这篇文章和另一篇文章中互换使用。

变压器模型需要以下输入:

src编码器所使用的。src的形状必须是【批量大小, n ,输入特征的数量】或 n ,批量大小,输入特征的数量(取决于batch_first构造函数参数的值),其中 n 是输入序列中数据点的数量。例如,如果你正在预测每小时的电价,并且你想根据上周的数据进行预测,那么 n=168。

tgt是变压器需要的另一个输入。它被解码器使用。tgtsrc中输入序列的最后一个值和目标序列除最后一个值以外的所有值组成。换句话说,它将具有[批量大小, m ,预测变量数]或[ m ,批量大小,预测变量数]的形状,其中 m 是预测范围。继续电价预测的例子,如果你想提前 48 小时预测电价,那么 m=48。

此外,编码器和解码器需要所谓的掩模。读者可以参考上面提到的关于屏蔽的介绍。

在我们继续之前,另一件重要的事情是,我们在这篇博客文章中使用的特定时序转换器实现总是输出形状为[批量大小, m ,预测变量数]或[ m,,批量大小,预测变量数],【T22 的张量,即模型输出序列的长度由在 tgt 张量中给解码器的输入序列的长度决定。

因此,如果tgt具有形状【72,批量大小,1】,这意味着tgt中序列的长度是 72,因此模型也将输出 72 的序列。

如何使用时间序列转换器进行推理

好了,准备工作已经就绪,现在让我们考虑一下为什么会有一篇关于如何使用转换器进行时间序列预测的博文:

在训练期间,直接产生tgt,因为我们知道目标序列的值。然而,在推理过程中(例如在生产环境中),我们在进行预测时当然不知道目标序列的值——否则我们就不需要首先进行预测。因此,我们需要找到一种方法来产生一个合理的tgt,它可以在推理过程中用作模型的输入。

现在我们知道了时间序列转换器需要什么输入,以及为什么我们需要以某种方式生成tgt,让我们看看实际上如何做。在接下来的内容中,请记住,总体目的是生成一个tgt张量,该张量一旦生成,就可以用作模型的输入来进行预测。

举一个简单的例子来说明,假设在推断时间 t ,我们想要根据序列的 5 个最近观察值来预测序列的下 3 个值。

下面是src的样子:

src = [xt-4, xt-3, xt-2, xt-1, xt]

其中x表示我们正在处理的系列,例如电价。

目标是预测tgt_y,它将是:

tgt_y = [xt+1, xt+2, xt+3]

因此,我们的tgt,模型需要它作为输入,以便对tgt_y进行预测,应该是:

tgt = [xt, xt+1, xt+2]

我们知道xt的值,但不知道xt+1xt+2的值,所以我们需要以某种方式估计这些值。在本文中,我们将首先预测xt+1,然后将此预测添加到tgt中,这样tgt = [xt, xt+1]将使用此tgt预测xt+2,然后将此预测添加到tgt中,这样tgt = [xt, xt+1, xt+2],最后使用此tgt生成最终预测。

下面的函数是您在 PyTorch 中使用时序转换器模型运行推理所需的代码。该函数根据上述方法生成预测。您传入一个 Transformer 模型和src以及 docstring 中描述的一些其他参数。然后,该函数迭代生成tgt,并基于由时间 t 的最后已知观测值和剩余 m-1 数据点的估计值组成的tgt生成最终预测。

该函数设计用于验证或测试循环中。您可以调用推理函数,而不是调用模型来生成预测。下面是如何使用它的一个简单示例:

请注意,您不能照原样使用该脚本。这仅仅是一个展示整体思想的例子,并不意味着你可以复制粘贴并期望工作。例如,在让脚本工作之前,您需要实例化模型和数据加载器。在这篇博文的 GitHub repo 中,参见文件 sandbox.py 中关于如何做的例子。如果你以前从未训练、验证和测试过 PyTorch 神经网络,我建议你看看 PyTorch 的初级教程。

使用时序转换器运行推理的所示方法的缺点

假设推理函数依赖于一个循环来迭代产生tgt,如果 m 很大,该函数会很慢,因为这会增加循环中的迭代次数。这是上述方法的主要缺点。我没有足够的想象力想出一个更有效的方法,但是如果你有任何想法,我很乐意在评论区听到你的意见。也欢迎你直接参与回购。

假设推理函数每批调用模型 m-1 次,您可能需要警惕一些增加调用模型的计算时间的事情,例如使用具有许多参数的模型或使用大的 n. 此外,您拥有的批越多,推理函数将被调用的次数就越多,总的训练或测试脚本运行的时间就越长。

使用时序转换器运行推理的代码以及 PyTorch 转换器实现可以在以下报告中找到:

https://github.com/KasperGroesLudvigsen/influenza_transformer

就是这样!我希望你喜欢这篇文章🤞

请留下评论让我知道你的想法。

关注更多与时间序列预测、绿色软件工程和数据科学环境影响相关的帖子🍀

请随时在 LinkedIn 上与我联系。

如何在云中运行机器学习超参数优化—第 1 部分

原文:https://towardsdatascience.com/how-to-run-machine-learning-hyperparameter-optimization-in-the-cloud-part-1-7877cdd6e879

基于云的调优的四种备选方案

照片由丹尼斯·莱昂在 Unsplash 上拍摄

介绍

这是三篇文章中的第一篇,在这篇文章中,我们将探索在云机器学习(ML)环境中执行超参数优化的一些方法。

超参数调整(HPT) : HPT 或超参数优化(HPO)指的是找到一组最优超参数(例如学习率、动量、辍学等)的艺术。)对于你的机器学习模型。HPT 是任何机器学习项目的重要组成部分;恰当地应用它可以决定你的项目是成功还是失败。关于 HPT 的艺术已经写了很多,例如,见这里关于执行 HPT 的一些方法的简要调查,见这里关于支持 HPT 的一些现有框架的调查。加速 HPT 的一种常用方法是增加主机数量,以增加并行运行的实验数量。

云中的 HPT:在之前的文章中(例如这里),我们已经阐述了在云中执行机器学习的优势。特别是,我们已经注意到基于云的 ML 的几乎无限的扩展能力。这个属性通过使我们能够启动尽可能多的训练实例和尽可能多的并行实验,极大地加速了我们的 ML 项目。可伸缩性属性使得云成为我们的 ML 模型的 HPT 的理想场所。

在本帖中,我们回顾了在云中运行 HPT 的一些方法。做到这一点的方法并不总是显而易见的。这是因为 HPT 通常涉及进行必须协调的多个试验。需要从所有试验中收集进展报告,并且需要根据选择的 HPT 算法采取适当的行动。当在本地环境中运行时,这样的协调是非常琐碎的,在本地环境中,您可以完全控制您的训练实例,并且可以很容易地设置它们来相互通信。但是在云中就不那么明显了,尤其是当使用托管培训服务时,比如 Amazon SageMaker ,底层实例设置和配置被委托给服务。

基于云的 HPT 的不同方法

在以前的帖子中(例如这里的),我们已经注意到了开发者必须从中选择的基于云的机器学习解决方案的广泛范围。云服务提供商(CSP)如 GCP、AWS 和 Azure,在不同的抽象层次提供了各种 ML 培训选项。一方面,开发人员可以请求一个“裸机”GPU 云实例,并自行处理设置、配置和应用流程的所有元素。另一方面,您拥有高度专业化、全面管理、基于云的培训框架。自然,过多的基于云的培训选项扩展到了执行基于云的 HPT 的多种方式。在本帖中,我们将回顾并演示四个选项:

  1. 云实例集群上的 HPT—在这个场景中,我们为 HPT 围绕云计算实例的实验设计了一个定制的解决方案。该选项通常需要最多的设置和维护,但支持最多的定制。
  2. 托管培训环境中的 HPT—在这里,我们依靠托管培训服务来构建一个实例集群,并在该集群中运行 HPT。
  3. 托管 HPT 服务 —一些 CSP 提供专用于 HPT 实验的 API。
  4. 用 HPT 包装管理的训练实验 —在这种情况下,HPT 算法在本地运行(或在云笔记本实例上),每个 HPT 实验都是独立产生的基于云的训练作业。

比较点

有许多特性可用作 HPT 解之间的比较基础。在本帖中,我们只选择了几个属性来突出我们将要讨论的基于云的解决方案的优缺点。其中包括:

  1. 算法支持:深度学习的 HPT 算法开发是一个活跃的研究领域,新算法不断涌现。HPT 算法通常有两个部分:参数搜索算法调度算法搜索算法确定如何从预定义的搜索空间中为参数集赋值。搜索算法的例子包括普通方法,如网格搜索随机搜索,以及更复杂的(如贝叶斯)方法,包括某种形式的利用,即从以前的结果中学习。调度算法控制如何以及何时运行实验、并行运行多少个实验、如何确定提前终止哪些实验等。理想情况下,我们将完全自由地选择我们的 HPT 算法。在实践中,某些解决方案可以明确地(例如,通过它们的 API)或隐含地(例如,通过对并行实验的数量的限制)限制一些算法的使用。
  2. **自动可伸缩性:**根据您选择的 HPT 算法,您可能会发现在不同的调优阶段会使用不同数量的实例。对于这样的场景,最理想的是有一个 HPT 解决方案,它支持根据调度算法规定的需求自动扩展计算实例。替代方案可能需要维护(并支付)空闲的计算实例。
  3. 复杂性:不同的 HPT 解决方案在配置和维护的复杂性上有所不同。基于不受管理的云服务产品的解决方案通常需要更多的努力。
  4. 资源灵活性 : HPT 框架通常包括在单个计算实例上运行多个实验的选项。然而,一些云 HPT 解决方案将每个计算实例的实验次数限制为一次。
  5. 实验初始化的开销:每个新实验的启动时间会根据选择的 HPT 解决方案而有所不同。如果您的实验相对较短,这一开销将影响 HPT 的总持续时间(和总成本)。
  6. Spot 实例用法:使用 spot可抢占的 实例来训练 ML 模型,使我们能够以显著的折扣率利用未使用的云计算能力。一些 HPT 解决方案比其他解决方案更适合现场,因此对降低成本具有重要影响。

同样重要的其他考虑因素包括:再现性、热启动调优、检查点、容错、分布式训练(其中每个实验在多个 GPU 或多个实例上运行)、成本等等。

对于我们不耐烦的读者来说,这里有一个表格,总结了我们个人对本帖将要涉及的四个选项的看法。

基于云的 HPT 期权属性的主观总结(作者)

放弃

本帖将包括我们讨论的一些方法的简要演示,以突出它们的一些特性。这些演示将包括一些服务和框架选择,包括亚马逊 SageMaker 、 PyTorch (1.12)、 Ray Tune (2.0),以及 Syne Tune (0.12)。请不要将这些选择视为对其他选项的认可。对您来说,最佳选择可能取决于许多因素,包括项目细节、云服务成本等等。此外,请记住,在您阅读本文时,这些框架的特定 API 和用法可能会发生变化。

我要感谢艾萨克·杰马尔对《邮报》的贡献。

玩具示例—使用视觉转换器进行图像分类

在这一节中,我们将描述我们将在 HPT 演示中使用的玩具模型。该部分的输出是一个训练函数,我们将在 HPT 期间用优化器学习率超参数的不同初始化来调用它。如果你渴望直接了解 HPT 的东西,请随意跳到下一部分。

我们将在实验中使用的模型是一个带有视觉转换器 (ViT)主干的图像分类模型。下面的代码块演示了如何使用 Python transformers 包(版本 4.23.1)的 HuggingFace ViT API 构建一个视觉转换器模型。

def build_model():from transformers import (ViTForImageClassification,ViTConfig)**model = ViTForImageClassification(ViTConfig(num_labels=3))**return model

请注意,在实践中,我们将实际调整使用最大更新参数化(μP) 的稍微修改版本的 ViT 模型。这种方法能够在相对较窄版本的 ViT 模型上进行调优,并将结果应用于更大的版本。详见本帖底部附录。

以下代码块(受本教程的启发)演示了如何使用 HuggingFace 训练器 API 和hugging face bean 数据集来训练我们的 ViT 模型。

def **train**(config):import torch**# 1\. build ViT model**   model = build_model()model.to(torch.cuda.current_device())
 **# 2\. load and configure beans dataset**  from datasets import load_datasetds = load_dataset('beans')
 from transformers import ViTFeatureExtractorfeature_extractor = ViTFeatureExtractor()
 def transform(example_batch):inputs = feature_extractor([x for x in example_batch['image']], return_tensors='pt')inputs['labels'] = example_batch['labels']return inputs
 prepared_ds = ds.with_transform(transform)
 def collate_fn(batch):return {'pixel_values':torch.stack([x['pixel_values'] for x in batch]),'labels': torch.tensor([x['labels'] for x in batch])}
 **# 3\. load metric**  from evaluate import load as load_metricmetric = load_metric("accuracy")def compute_metrics(p):import numpy as npreturn metric.compute(predictions=np.argmax(p.predictions, axis=1),references=p.label_ids)
 **# 4\. define optimizer with the configured lr value**  from torch.optim import AdamWoptim=AdamW(model.parameters(), lr=**config['lr']**)scheduler=None
 **# 5\. define Trainer**from transformers import TrainingArgumentstraining_args = TrainingArguments(output_dir="/tmp/vit-base-beans",per_device_train_batch_size=16,per_device_eval_batch_size=16,evaluation_strategy="epoch",logging_strategy="epoch",disable_tqdm=True,do_train=True,do_eval=True,num_train_epochs=8,remove_unused_columns=False,report_to='none')
 from transformers import Trainertrainer = Trainer(model=model,optimizers=(optim,scheduler),args=training_args,data_collator=collate_fn,compute_metrics=compute_metrics,train_dataset=prepared_ds["train"],eval_dataset=prepared_ds["validation"],tokenizer=feature_extractor,**callbacks=[] # we will use callbacks for HPT reporting**  )
 **# 6\. train**  trainer.train()

优化器学习率通过配置字典传递给训练函数。这是我们将在 HPT 演示中调整的超参数。

下一个

在接下来的三篇文章中,我们将展示四种不同的 HPT 表演方式。在每种情况下,我们将使用上面的训练函数,为学习率超参数运行不同配置的多个训练实验。

本文的第 2 部分将介绍在基于云的专用调优集群上运行 HPT 的两种方式。在第 3 部分中,我们将展示两种使用并行管理培训作业进行调优的方法。

附录:具有最大更新参数化的视觉转换器

我们在实验中使用的玩具模型遵循微软和 OpenAI 的研究人员开发的超参数转移(μ转移)解决方案 https://arxiv.org/pdf/2203.03466.pdf 。μTransfer 旨在解决在特别大的模型——具有数十亿参数的模型——上执行 HPT 的独特挑战。考虑到每次单独试验所需的机器数量和时间,在这种模型上进行 HPT 可能是极其昂贵的。研究表明,当采用最大更新参数化(μP) 时,许多在架构的较小版本上最优的超参数在较大版本上仍然是最优的。因此,提出的策略是对在 μP 中参数化的小版本模型执行传统的 HPT,然后将学习到的超参数转移到大模型。在这篇文章中,我们在基于视觉转换器(ViT)的分类模型上演示了这一过程的第一步:我们使用在 mup Python 包中定义的专用实用程序,为在 μP 中参数化的相对较小的 ViT 调整学习率 。下面的代码块演示了如何在 μP 中参数化 HuggingFace ViT 模型。代码遵循 mup 代码库中的指南以及该代码库中提供的指针,专用于 HuggingFace transformer 模型的 μP 。我们突出显示了 μP 特有的代码行。代码使用了 1.0.0 版本的 mup Python 包和 4.23.1 版本的变形金刚包。注意,为了完整起见,我们包含了代码;该职位不要求完全理解该准则。

def build_model():from typing import Optional, Tuple, Unionimport torchfrom torch import nnfrom transformers import (ViTForImageClassification,ViTModel,ViTConfig)from transformers.models.vit.modeling_vit import ViTSelfAttentionfrom mup import (MuSGD, get_shapes, set_base_shapes,make_base_shapes, MuReadout, normal_)
 def mup_forward(self, hidden_states,head_mask: Optional[torch.Tensor] = None,output_attentions: bool = False):mixed_query_layer=self.query(hidden_states)key_layer=self.transpose_for_scores(self.key(hidden_states))value_layer=self.transpose_for_scores(self.value(hidden_states))query_layer=self.transpose_for_scores(mixed_query_layer)  attention_scores=torch.matmul(query_layer,key_layer.transpose(-1, -2))
 **### muP: 1/d attentionattention_scores = attention_scores / self.attention_head_size**
 attention_probs=nn.functional.softmax(attention_scores, dim=-1)attention_probs=self.dropout(attention_probs)
 # Mask heads if we want toif head_mask is not None:attention_probs=attention_probs * head_mask
 context_layer=torch.matmul(attention_probs, value_layer)context_layer=context_layer.permute(0, 2, 1, 3).contiguous()new_cxt_layer_sh=context_layer.size()[:-2]+(self.all_head_size,)context_layer=context_layer.view(new_cxt_layer_sh)if output_attentions:outputs=(context_layer, attention_probs)else:outputs=(context_layer,)return outputs
 **# override forward function with mup_forward****ViTSelfAttention.forward = mup_forward**
 class **MupViTForImageClassification**(ViTForImageClassification):def __init__(self, config: ViTConfig) -> None:super(ViTForImageClassification, self).__init__(config)self.num_labels = config.num_labelsself.vit = ViTModel(config, add_pooling_layer=False)
 **### muP: Classifier head - replace nn.Linear with MuReadoutif config.num_labels > 0:self.classifier=MuReadout(config.hidden_size,config.num_labels)** else:self.classifier=nn.Identity()
 # Initialize weights and apply final processingself.post_init()
 def _init_weights(self,module: Union[nn.Linear, nn.Conv2d, nn.LayerNorm],readout_zero_init: bool = False,query_zero_init: bool = False) -> None:"""Initialize the weights"""if isinstance(module, (nn.Linear, nn.Conv2d)):**### muP: swap std normal init with normal_ from mup.initif isinstance(module, MuReadout) and readout_zero_init:module.weight.data.zero_()else:if hasattr(module.weight, 'infshape'):normal_(module.weight, mean=0.0, std=self.config.initializer_range)else:module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)### End muP**        if module.bias is not None:module.bias.data.zero_()elif isinstance(module, nn.LayerNorm):module.bias.data.zero_()module.weight.data.fill_(1.0)**### muPif isinstance(module, ViTSelfAttention):if query_zero_init:module.query.weight.data[:] = 0**
 base_config = ViTConfig(hidden_size=768,intermediate_size=4 * 768,num_labels=3,)delta_config = ViTConfig(intermediate_size=2 * 768,hidden_size=4 * 2 * 768,num_labels=3,)base_model = MupViTForImageClassification(config=base_config)delta_model = MupViTForImageClassification(config=delta_config)base_shapes = make_base_shapes(base_model, delta_model)
 **model = MupViTForImageClassification(ViTConfig(num_labels=3))**set_base_shapes(model, base_shapes)model.apply(model._init_weights)return model

训练函数中的优化器应替换为:

**# 4\. define optimizer with the configured lr value
**  from mup.optim import MuAdamWoptim=MuAdamW(model.parameters(), lr=**config['lr']**)

[1]:杨、Greg &胡、Edward & Babuschkin、Igor & Sidor、Szymon & Liu、晓东& Farhi、David & Ryder、Nick & Pachocki、Jakub & Chen、& Gao、剑锋。(2022).张量程序 V:通过零触发超参数转移调整大型神经网络。

如何在云中运行机器学习超参数优化—第 2 部分

原文:https://towardsdatascience.com/how-to-run-machine-learning-hyperparameter-optimization-in-the-cloud-part-2-23b1dac5ebed

在专用射线簇上进行调谐的两种方法

大卫·坎特利在 Unsplash 上拍摄的照片

这是关于云中的超参数调整(HPT)机器学习模型的三部分帖子的第二部分。在第 1 部分中,我们通过引入问题并定义一个我们将在调试演示中使用的玩具模型来搭建舞台。在这一部分中,我们将回顾基于云的优化的两个选项,这两个选项都涉及在专用调优集群上的并行实验。

选项 1:云实例集群上的 HPT

我们考虑在云中执行 HPT 的第一个选项是基于云实例的集群。实际上,有几十种不同的方式来设置实例集群。例如,要在 AWS 上创建一个集群,您可以:1)简单地通过 EC2 控制台启动您想要的数量的 Amazon EC2 实例,2)使用容器编排框架(如 Kubernetes )构建和管理一个集群,3)使用 Amazon 的托管的 Kubernetes 服务、 Amazon EKS、等。

这种 HPT 选项的主要优点是它提供的灵活性。当您启动自己的集群时,您可以随意设置它。这意味着以你想要的任何方式执行 HPT 的自由——使用任何框架、任何算法、任何特性(例如每个实例多次尝试)、任何自动缩放机制等等。特别是,您可以以这样一种方式设置您的集群,即头节点运行在一个可靠的非现场(不可预占的)实例上,但是所有工作节点都运行在现场实例上以降低成本。

这种灵活性和自由的代价是设置和维护该选项所需的工作。启动、配置和管理集群需要一定程度的专业知识。选择这种方式的组织通常会有一个完全致力于集群管理的(devops)团队。有些组织可能已经制定了指导方针(例如出于安全原因),您需要遵守这些指导方针。这可能使这种类型的解决方案的使用更加复杂,或者对其上述自由度引入限制。

在这篇文章中,我们将演示使用射线框架创建集群。Ray 包含了对在 AWS 上启动集群的内置支持。为了启动 HPT 的集群,我们在 tune.yaml YAML 文件中放置了以下集群配置。

**cluster_name**: hpt-cluster
**provider**: {type: aws, region: us-east-1 }
**auth**: {ssh_user: ubuntu}
**min_workers**: 0
**max_workers**: 7
**available_node_types:
**  **head_node**:**node_config**: {InstanceType: g4dn.xlarge, ImageId: ami-093e10b196d7cc7f0}**worker_nodes**:**node_config**: {InstanceType: g4dn.xlarge, ImageId: ami-093e10b196d7cc7f0}
**head_node_type**: head_node
**setup_commands:
**    - echo 'exportPATH="$HOME/anaconda3/envs/pytorch_p39/bin:$PATH"' >> ~/.bashrc- conda activate pytorch_p39 && pip install "ray[tune]" "ray[air]" &&pip install mup transformers evaluate datasets

这个 YAML 文件定义了一个 HPT 环境,其中有多达八个 Amazon EC2 g4dn.xlarge 实例,每个实例都有 65.3 版本的 AWS 深度学习 AMI ,预配置为使用专用 PyTorch conda 环境,并且预安装了所有 Python 依赖项。(为了简单起见,我们从脚本中省略了 Python 包版本。)

启动该集群的命令是:

ray up tune.yaml -y

假设正确配置了所有 AWS 帐户设置,这将创建一个集群头节点,我们将在运行 HPT 时连接到该节点。在下面的代码块中,我们演示了如何使用光线调节库来运行 HPT。这里我们选择使用带有随机参数搜索的 ASHA 调度算法。该算法被配置为总共运行 32 个实验,每个实验最多运行 8 个时期,并且每个实验都有不同的优化器学习速率候选。一次最多可以运行八个平行实验。实验将由报告的评估准确度来衡量。根据 ASHA 的提前停止算法,表现不佳的实验将被提前终止。

def hpt():from ray import tune**# define search space**config = {"lr": tune.loguniform(1e-6, 1e-1),} **# define algorithm**from ray.tune.schedulers import ASHASchedulerscheduler = ASHAScheduler(max_t=8,grace_period=1,reduction_factor=2,metric="accuracy",mode="max") gpus_per_trial = 1 if torch.cuda.is_available() else 0tuner = tune.Tuner(tune.with_resources(tune.with_parameters(**train**), **# our train function** resources={"cpu": 4, "gpu": gpus_per_trial}),tune_config=tune.TuneConfig(num_samples=32,max_concurrent_trials=8,scheduler=scheduler,),param_space=config,) **# tune**  results = tuner.fit()best_result = results.get_best_result("accuracy", "max")print("Best trial config: {}".format(best_result.config))print("Best final validation accuracy: {}".format(best_result.metrics["accuracy"]))**if __name__ == "__main__":import rayray.init()hpt()**

最后一个环节是会议记者。为了让 Ray Tune 能够跟踪实验的进度,我们将以下回调添加到了拥抱脸训练器回调的列表中:

from transformers import TrainerCallback
class **RayReport**(TrainerCallback):def on_evaluate(self, args, state, control, metrics, **kwargs):from ray.air import session**session.report({"loss": metrics['eval_loss'],"accuracy": metrics['eval_accuracy']})**

以下命令将触发 HPT 作业:

ray submit tune.yaml train.py

为了支持八个并行实验的需求,集群自动缩放器将启动七个额外的(工作)节点。HPT 的工作将总共运行 32 个实验,根据 ASHA 的提前停止算法,其中一些可能会提前停止。

以下命令将停止集群(尽管它不会终止 EC2 实例):

ray down tune.yaml -y

请不要被我们这里描述的相对简单的流程所迷惑。在实践中,如上所述,适当配置您的云环境、适当配置您的 YAML 文件,以及适当管理您的集群是非常棘手的。我们将讨论的其余基于云的 HPT 解决方案将通过使用高级云培训服务来管理计算实例,从而绕过这些复杂性。

结果

我们的 HPT 作业运行了大约 30 分钟,产生了以下结果:

**Total run time: 1551.68 seconds (1551.47 seconds for the tuning loop).
Best trial config: {'lr': 2.393250830770165e-05}
Best final validation accuracy: 0.7669172932330827**

选项 2:在管理培训环境中的 HPT

专门的云训练服务,比如亚马逊 SageMaker,为机器学习模型开发提供了很多便利。除了简化启动和管理培训实例的流程之外,它们还可能包括一些引人注目的功能,如加速数据输入流、分布式培训 API、高级监控工具等。这些特性使得托管训练环境成为许多机器学习开发团队的首选解决方案。挑战在于如何扩展这些环境以支持 HPT。在本节中,我们将介绍三种解决方案中的第一种。第一种方法将演示如何在 Amazon SageMaker 培训环境中运行 Ray Tune HPT 作业。与前面的方法相反,在前面的方法中,我们显式地定义并启动了实例集群,这里我们将依靠 Amazon SageMaker 来完成这项工作。虽然前面的方法包括一个自动缩放器,用于根据 HPT 调度算法来缩放集群,但在此方法中,我们创建了一个固定大小的实例集群。我们将使用上面定义的相同的基于 Ray Tune 的解决方案和相同的 hpt() 函数,并修改入口点以在由托管服务启动的 EC2 集群上设置 Ray 集群:

if __name__ == "__main__":# utility for identifying the head nodedef get_node_rank() -> int:import json, oscluster_inf = json.loads(os.environ.get('SM_RESOURCE_CONFIG'))return cluster_inf['hosts'].index(cluster_inf['current_host']) # utility for finding the hostname of the head nodedef get_master() -> str:import json, oscluster_inf = json.loads(os.environ.get('SM_RESOURCE_CONFIG'))return cluster_inf['hosts'][0] if get_node_rank() == 0:**# the head node starts a ray cluster and starts the hpt**    import subprocessp = subprocess.Popen('**ray start --head --port=6379**',  shell=True).wait()import rayray.init()hpt()else:**# worker nodes attach to the hpt cluster**import timeimport subprocessp = subprocess.Popen(f"**ray start --address='{get_master()}:6379**'",shell=True).wait()import rayray.init()try:**# keep node alive until the hpt process on head node completes**      while ray.is_initialized():time.sleep(10)except:pass

下面的代码块演示了如何使用我们的 HPT 脚本所需的资源来设置 Amazon SageMaker 培训作业。我们不是启动八个单 GPU 实例来支持八个并行实验,而是请求两个四 GPU 实例来展示我们在每个实例上运行多个(四个)实验的能力。当使用我们将要讨论的下面两种 HPT 方法时,这是不可能的。我们还将每个实例的资源调整到 12 个 CPU(而不是 4 个)。

from sagemaker.pytorch import PyTorch 
estimator=PyTorch(entry_point='train.py',source_dir='./' #contains train.py and requirements filerole=<role>,**instance_type='ml.g4dn.12xlarge', # 4 gpus instance_count=2,
**           py_version='py38',pytorch_version='1.12')
estimator.fit()

source_dir 应该指向包含 train.py 脚本和 requirements.txt 文件的本地目录,该文件包含所有 Python 包依赖项:

ray[air]
ray[tune]
mup==1.0.0
transformers==4.23.1
datasets==2.6.1
evaluate==0.3.0

利弊

这种调优方法分享了上一节中基于集群的方法的许多优点——我们可以非常自由地运行我们想要的任何 HPT 框架和任何 HPT 算法。这种方法的主要缺点是缺乏自动伸缩性。集群实例的数量需要预先确定,并在整个培训工作期间保持不变。如果我们使用 HPT 算法,其中并行实验的数量在调整过程中会发生变化,我们可能会发现一些(昂贵的)资源会闲置一段时间。

另一个限制与使用折扣 spot 实例的能力有关。虽然 Amazon SageMaker 支持从 spot 中断中恢复,但是在撰写本文时,spot 配置已经应用于集群中的所有实例。您不能选择将头节点配置为持久节点,而只能将工作节点配置为现场实例。此外,单个实例的现场中断将触发整个集群的重启。虽然这并没有完全禁止使用 spot 实例,但确实使它变得更加复杂。

结果

我们在亚马逊 SageMaker 内部的 HPT 运行结果总结如下:

**Total run time: 893.30 seconds (893.06 seconds for the tuning loop).
Best trial config: {'lr': 3.8933781751481333e-05}
Best final validation accuracy: 0.7894736842105263**

下一个

由三部分组成的帖子的最后一部分将探讨基于云的 HPT 的另外两种方法,一种是使用托管 HPT 服务,另一种是将托管培训工作打包到 HPT 解决方案中。

如何在云中运行机器学习超参数优化—第 3 部分

原文:https://towardsdatascience.com/how-to-run-machine-learning-hyperparameter-optimization-in-the-cloud-part-3-f66dddbe1415

通过并行化受管培训作业进行云调优

肯尼·埃利亚松在 Unsplash 上的照片

这是关于云中的超参数调整(HPT)机器学习模型的三部分帖子的最后一部分。在第一部分中,我们通过引入问题并为我们的调优演示定义一个玩具模型和一个训练函数来搭建舞台。在第二部分中,我们回顾了两个基于云的优化选项,这两个选项都涉及在专用调优集群上的并行实验。在这一部分中,我们将介绍另外两种方法,使用托管调优 API 进行优化,以及构建一个 HPT 解决方案,其中每个实验都是一个单独的托管培训工作。

选项 3:托管 HPT 服务

一些电信运营商将包括专门的 HPT API,作为其托管培训服务的一部分。亚马逊 SageMaker 通过其自动模型调整API 支持 HPT。为了采用我们的 SageMaker HPT 调优脚本,我们需要修改我们的训练脚本(train.py)的入口点,如下所示:

if __name__ == "__main__":import argparse, osparser = argparse.ArgumentParser()parser.add_argument("--lr", type=float, default=0.01)parser.add_argument("--model-dir", type=str,default=os.environ["SM_MODEL_DIR"])args, _ = parser.parse_known_args()**train({'lr':args.lr})**

在下面的代码块中,我们展示了如何配置和运行 SageMaker HPT 作业。为了使 HPT 运行与我们之前的示例保持一致,我们将使用最近宣布的 SageMaker HPT 对具有类似配置的 HyperBand 算法的支持。遗憾的是,在撰写本文时,SageMaker SDK(版本 2.114.0)不包含运行 HyperBand 调优作业的内置支持。在下面的代码块中,我们展示了如何通过扩展 SageMaker Session 类来解决这个限制。

from sagemaker.session import Session
class HyperBandSession(Session):def _map_tuning_config(self,strategy,max_jobs,max_parallel_jobs,early_stopping_type="Off",objective_type=None,objective_metric_name=None,parameter_ranges=None,):tuning_config = super()._map_tuning_config(strategy, max_jobs, max_parallel_jobs, early_stopping_type, objective_type, objective_metric_name, parameter_ranges)**tuning_config["StrategyConfig"] = {"HyperbandStrategyConfig": {"MinResource": 1,"MaxResource": 8}}**    return tuning_config**# 1\. define estimator (reused for each experiment)**
from sagemaker.pytorch import PyTorch 
estimator=PyTorch(entry_point='train.py',source_dir='./' #contains train.py and requirements filerole=<role>,     instance_type='ml.g4dn.xlarge',instance_count=1,py_version='py38',pytorch_version='1.12',**sagemaker_session=HyperBandSession()**
)from sagemaker.tuner import (ContinuousParameter,HyperparameterTuner,)**# 2\. define search space** hyperparameter_ranges = {"lr": ContinuousParameter(1e-6, 1e-1, scaling_type='Logarithmic'),}**# 3\. define metric**
objective_metric_name = "accuracy"
objective_type = "Maximize"
metric_definitions = [{"Name": "accuracy","Regex": "'eval_accuracy': ([0-9\\.]+)"}]**# 4\. define algorithm strategy**
algo_strategy = 'Hyperband'
max_jobs=32
max_parallel_jobs=8**# 5\. define tuner**
tuner = HyperparameterTuner(estimator,objective_metric_name,hyperparameter_ranges,metric_definitions,strategy=algo_strategy,max_jobs=max_jobs,max_parallel_jobs=max_parallel_jobs,objective_type=objective_type,)**# 6\. tune**
tuner.fit(wait=False)

利弊

这种方法的主要优点是方便。如果您已经在使用 Amazon SageMaker 进行培训,那么只需一些额外的 SageMaker APIs,就可以增强您的代码以支持超参数调优。特别是,您不需要采用和集成专用的 HPT 框架(如 Ray Tune)。

主要缺点是它对 HPT 算法的支持有限。SageMaker HPT API 定义了一个封闭的算法集,您可以从中进行选择。这些不一定包括你的问题的最佳(SOTA)或最理想的算法(见这里的一些例子)。

请注意,与我们之前看到的 HPT 方法相反,顺序试验可以在同一节点上运行,几乎没有时间延迟,在 SageMaker HPT 的顺序运行可能包括一些启动时间开销。最近,这种开销大幅减少,由高达 20 倍(!!),通过为随后的试验集成使用相同的(温暖的)训练实例。这消除了请求(和等待)一个可用实例(来自 Amazon EC2)的开销,以及提取所需 docker 图像的开销。然而,仍然有一些启动步骤需要在每次试验中重复,比如下载源代码和输入数据。

关于 SageMaker HPT 的更多细节,请参见 API 文档以及这篇酷帖,它展示了如何克服每个 HPT 作业的实例数量的潜在限制,以便运行多达 10,000 次试验。

结果

我们的 SageMaker HPT 作业运行了大约 37 分钟,并从 SageMaker 控制台生成了以下屏幕截图中总结的结果:

SageMaker 控制台的屏幕截图(作者提供)

选项 4:用 HPT 包装管理培训实验

在这最后一种方法中,我们的 HPT 算法在本地运行(或在基于云的笔记本实例上),每个实验都是独立产生的基于云的训练工作。这种解决方案的关键要素是一种报告机制,该机制使 HPT 算法能够跟踪每个基于云的训练作业的进度。我们将提供一个简单的例子,说明如何使用 SageMaker 培训指标来做到这一点。随后,我们将使用 Syne Tune 库演示这种方法的完整示例。

在下面的代码块中,我们定义了一个 launch_experiment 函数,并用一个简单的光线调节实验来包装它。启动的作业由 HPT 算法选择的学习率值和 SageMakermetric _ definitions定义,SageMakermetric _ definitions用于从 HuggingFace Trainer API 收集评估精度输出打印。当训练作业完成时,将提取收集的指标并报告给 Ray Tune 会话。SageMaker 会话还配置有keep _ alive _ period _ in _ seconds标志,以利用新的 SageMaker 对热实例池的支持。

def launch_experiment(config):**# define estimator**  from sagemaker.pytorch import PyTorch estimator=PyTorch(entry_point='train.py',source_dir='./' #contains train.py and requirements filerole=<role>,instance_type='ml.g4dn.xlarge',instance_count=1,py_version='py38',pytorch_version='1.12',**hyperparameters={"lr": config['lr']}****keep_alive_period_in_seconds=240,metric_definitions=[{"Name": "accuracy",                                                                "Regex": "'eval_accuracy': ([0-9\\.]+)"}]**)**# train**  job_name = 'tune_model'estimator.fit(job_name=job_name) **# use boto3 to access job**import boto3search_params = {"MaxResults": 1,"Resource": "TrainingJob","SearchExpression": {"Filters": [{"Name": "TrainingJobName", "Operator": "Equals", "Value": job_name},]},}smclient=boto3.client(service_name="sagemaker")res=smclient.search(**search_params) **# extract final metric** metrics=res["Results"][0]["TrainingJob"]["FinalMetricDataList"]accuracy=metrics[[x["MetricName"]for x in metrics].index("accuracy")]["Value"] **# report metric to ray** from ray.air import sessionsession.report({"accuracy": accuracy})**# configure a local Ray Tune HPT job** from ray import tune
from ray.tune.search.bayesopt import BayesOptSearch
config = {"lr": tune.uniform(1e-6, 1e-1),
}
bayesopt = BayesOptSearch(metric="accuracy",mode="max")tuner = tune.Tuner(tune.with_resources(tune.with_parameters(launch_experiment),resources={"cpu": 1}),tune_config=tune.TuneConfig(num_samples=2,max_concurrent_trials=1,search_alg=bayesopt,),param_space=config,
)
results = tuner.fit()
best_result = results.get_best_result("accuracy", "max")
print("Best trial config: {}".format(best_result.config))
print("Best final validation accuracy: {}".format(best_result.metrics["accuracy"]))

在这个简单的例子中,我们只收集了最终报告的指标值。在实践中,我们希望在每个实验中监控指标,以终止表现不佳的实验。这需要一个更复杂的解决方案,能够收集和比较多个作业的指标,及早停止失败的作业,并在释放的实例上启动新的作业。为此,我们采用了 Syne Tune ,这是一个 Python 库,支持大规模分布式超参数优化,实验可以在本地和云中运行。Syne Tune 内置了对使用 Amazon SageMaker 进行培训的支持,并且可以进行增强以支持其他管理培训环境。Syne Tune 支持多种流行的 HPT 算法,并且可以轻松扩展以支持其他算法。更多详情请见 Syne Tune 公告。

下面的代码块包含一个 HuggingFace TrainerCallback,它实现了 Syne Tune 所需的指标报告。这个回调必须添加到 train 函数中 HuggingFace Trainer 对象的回调列表中。

from transformers import TrainerCallback
class SyneReport(TrainerCallback):def __init__(self) -> None:from syne_tune.report import Reportersuper().__init__()self.reporter = Reporter() def on_evaluate(self, args, state, control, metrics, **kwargs):self.reporter(epoch=int(state.epoch),loss=metrics['eval_loss'],accuracy=metrics['eval_accuracy'])

下面的代码块演示了如何使用 HyperBand 算法运行我们的玩具示例的 HPT,其设置与前面的部分相同。我们再次定义了keep _ alive _ period _ in _ seconds标志,以利用热实例池。

**# define the estimator** from sagemaker.pytorch import PyTorch 
estimator=PyTorch(entry_point='train.py',source_dir='./' #contains train.py and requirements filerole=<role>,instance_type='ml.g4dn.xlarge',instance_count=1,py_version='py38',pytorch_version='1.12',**keep_alive_period_in_seconds=240,
**           )from syne_tune.search_space import loguniform, uniform
max_epochs = 8
config = {"lr": loguniform(1e-6, 1e-1),
}
from syne_tune.optimizer.schedulers.hyperband import (  HyperbandScheduler
)scheduler = HyperbandScheduler(config,max_t=8,resource_attr='epoch',searcher='random',metric="accuracy",mode="max",reduction_factor=2
)from syne_tune.tuner import Tuner
from syne_tune.stopping_criterion import StoppingCriterion
from syne_tune.backend.sagemaker_backend.sagemaker_backend import (SagemakerBackend
)tuner = Tuner(backend=SagemakerBackend(sm_estimator=est),scheduler=scheduler,**stop_criterion=StoppingCriterion(max_num_trials_started=32),**n_workers=8,tuner_name="synetune"
)tuner.run()

请注意,与我们以前的方法相反,Syne Tune(在撰写本文时,据我们所知)不包括固定总实验数量的选项。使用停止标准停止 Syne Tune 作业,该标准可由已过去的时间、已开始的实验数量、已完成的实验数量等确定。使用 StoppingCriterion 我们可以将调优作业配置为在 32 个实验完成后退出,但是只要不满足这个标准,Syne Tune 就会继续产生额外的(浪费的)作业。

利弊

用诸如 Syne Tune 的 HPT 解决方案包装 SageMaker 实验在算法选择方面提供了很大的自由度。这与萨格马克·HPT 方法相反。因为每个实验都是一个单独的训练任务,所以它支持自动缩放,并且有助于使用 spot 实例。

不利的一面是,与萨格马克·HPT 相比,这种方法需要学习和采用 HPT 框架。在萨格马克 HPT 方法的情况下,有一个关于新试验启动时间的问题,但这些问题通过我们使用温暖的实例池得到缓解。

结果

我们的 Syne Tune 作业运行了大约半个小时,并输出了以下结果:

accuracy: best 0.7969924812030075 for trial-id 7 (lr=0.000027)

摘要

下表总结了我们对所涉及的不同方法的主观体验:

基于云的 HPT 期权属性的主观总结(作者)

注意,在这个总结中,我们将 SageMaker HPT 和 Syne Tune 方法标记为高开销。在实践中,对热实例使用的新支持将开销减少到可以忽略不计的程度。然而,我们选择强调与基于集群的解决方案的区别,在基于集群的解决方案中,连续实验在同一个实例会话中运行。

如何选择 HPT 期权

最佳选择可能取决于你项目的细节和你自己的个人偏好。例如,如果您已经有了一个支持培训的可靠的编排解决方案,您可以选择扩展它以支持 HPT(选项 1)。如果您不喜欢基于编排的解决方案,并且不关心实例空闲的可能性,您可能更喜欢在 SageMaker 实例集群中运行 HPT(选项 2)。如果你的首要任务是降低成本,并且你对有限的 HPT 算法非常满意,那么你可能应该在 spot 实例上运行 SageMaker HPT(选项 3)。如果您想要运行一个高级调度算法,并且并行试验的数量有很大的差异,Syne Tune(选项 4)可能是您的最佳选择。当然,对你来说最好的选择也可能是这篇文章中没有提到的。

请随时提出意见、问题和更正。同时…祝你调音愉快!!

如何用 Python 在熊猫数据帧上运行 SQL 查询

原文:https://towardsdatascience.com/how-to-run-sql-queries-on-your-pandas-dataframes-with-python-4237ffecc43b

在 Python Pandas 数据框架中运行 SQL 查询

在 YouTube 上关注我

动机

数据科学家和数据分析师越来越多地使用 Pandas 进行数据分析,它的优势在于它是更广泛的 Python 世界的一部分,使许多人都可以访问它。另一方面,SQL 以其性能著称,易于阅读,即使是非技术人员也能很容易理解。

如果我们能找到一种方法将 Pandas 和 SQL 语句的优点结合起来会怎么样?这就是**pandasql**派上用场的地方。

通过这篇概念性的博客,您将在深入实践之前理解什么是**pandasql**,如果您已经熟悉 SQL,这将更加容易。

请记住,table 和 dataframe 可以互换使用,表示同一件事。

那么,pandasql 是什么?

它主要用于使用 SQL 语法查询**pandas**数据帧。使用 sqldf 与 R 数据帧交互,可以执行相同的过程。

先决条件

根据您的环境,使用以下语法进行安装非常简单:

在安装之前,需要注意的是使用 conda 安装库时,有必要指定--yes标志,这样就不会卡在(Proceed ([y]/n)?)提示。

  • 使用 Python 控制台
pip install pandasql 
  • 使用 Jupyter 笔记本
!conda install --yes pandasql

成功安装库之后,您应该能够使用以下语句导入库。

from pandasql import sqldf

我们开始吧

在深入研究之前,让我们首先创建将用于实践的数据集**StudentTable****TeachingAssistantTable**

# Import the pandas library for creating the dataframes
import pandas as pd
# Create the Student Data Framestudents= {'Students':["Sira","Ibrahim","Moussa","Mamadou","Nabintou"],'Gender':['Female','Male','Male', "Male", "Female"],'Age':[18, 27, 19, 22, 21],'Email': ["sira@info.com", "ib@info.com", "mouss@info.com", "mam@info.com", "nab@info.com"]}
students_df = pd.DataFrame(students)students_df

学生数据框(图片由作者提供)

# Create the Teaching Assistant Data Frameteaching_assistant= {'Teacher':["Ibrahim","Nabintou","Mamadou","Fatim","Aziz"],'Email':['ib@info.com','nab@info.com','mam@info.com', "fat@info.com", "aziz@info.com"],'Degree':["M.S in Data Science", "B.S in Statistics", "B. Comp Sc", "M.S. Architecture", "B.S in Accounting"],'Department': ["Business", "Statistics", "Comp Sc", "Engineering", "Business"]}
teaching_assistant_df = pd.DataFrame(teaching_assistant)teaching_assistant_df

助教数据框(图片由作者提供)

这是本节将涉及的主要概念:(1)列部分,(2)数据过滤,(3)数据聚合,最后,(4)数据连接。

单列选择

这相当于选择数据库/数据框的部分或全部列。使用关键字SELECT col_1, col_2,... col_X FROM tableName执行

1, 2, ...X对应最终结果中你感兴趣的列。

tableName是数据帧/表格的名称。

以下代码的结果包括 student dataframe 的所有列。

all_students = sqldf("SELECT * FROM students_df")
all_students

SELECT *语句结果(图片由作者提供)

  • all_students也是一个 DataFrame,如果您想执行快速的 Pandas 任务(如列类型),它会很有帮助。下面是一个插图。
# Check the type of all_students
print(type(all_students))# Run Pandas Statement to show the type of the columns
print("---"*10)
print(all_students.dtypes)

all_students 类型和列类型(图片由作者提供)

有时,当您有复杂的查询时,您可以按如下步骤进行:

  • 将查询定义为字符串。这样做的时候,确保使用三重引号”””,这样就可以在多行中编写查询。
  • sqldf函数应用于查询以获得结果。

假设我们需要学生的姓名、电子邮件,并将结果限制在前 3 个。

# Query definition
query = """ SELECT Students, Email FROM students_df LIMIT 3"""
# Query execution
name_email = sqldf(query)
name_email

学生姓名和电子邮件限于前 3 行(图片由作者提供)

2-数据过滤

数据过滤是指WHERE语句进入等式,对SELECT语句的结果进行自定义过滤。

假设我们想要所有的女学生。

# Define the query
query = """SELECT * FROM students_df WHERE Gender = 'Female'"""# Execute the query
female_student = sqldf(query)
female_student

女学生(作者图片)

让我们看一下这个查询,它的目的是检索所有拥有硕士学位的助教的姓名、电子邮件和学位。

query = """ SELECT Teacher, Email, Degree FROM teaching_assistant_df WHERE Degree LIKE 'M.S%'"""
ms_students = sqldf(query)
ms_students

拥有硕士学位的助教(图片由作者提供)

我决定执行相同的请求,这次使用 Pandas 语句,这就是它的样子!

cols_to_get = ['Teacher', 'Email', 'Degree']
teaching_assistant_df[teaching_assistant_df.Degree.str.startswith('M.S')][cols_to_get]

这看起来像。可怕的声明🥺.让我们了解一下发生了什么:

  • cols_to_get对应于我们在最终数据帧中想要的列。它基本上等同于我们在使用SELECT语句时指定的列。
  • teaching_assistant_df.Degree.str.startswith('M.S')返回True是以'M.S'开始的Degree列中的值。False否则。
  • 最后,这些布尔值被传输到起始的teaching_assistant_df以获得结果为True.的行

但是…我们用SQL查询执行了相同的任务,并且简单易懂。没有过多的比较分析,只是想强调一些简单的查询在SQL.中可以有多复杂

3-数据聚合

SQL 中的聚合是在聚合函数的帮助下执行的,下面是一些最常用的函数:COUNTSUMMAX & MINAVG。例如,你可以根据学生的性别得到他们的年龄。

query = """ SELECT AVG(Age), Gender FROM students_df GROUP BY Gender"""
avg_age = sqldf(query)
avg_age

不同性别学生的平均年龄(图片由作者提供)

4-数据连接

当我们想要组合至少两个表中的数据时,联接概念就变得很有用。这一部分直接指向只有一种类型的连接。您可以从我的文章《每个数据科学家都应该知道的 4 种 SQL 连接类型》中了解更多关于所有连接概念的信息。

假设你想知道谁既是学生又是助教。这个问题的答案需要使用一个INNER JOIN将我们的两个表连接起来,最终结果包含以下信息:

  • 来自students_df表的学生姓名、性别、电子邮件和年龄。
  • 来自teaching_assistant_df数据框的部门。
query = """ SELECT st.Students, st.Gender, st.Email, st.Age, tat.DepartmentFROM students_df st INNER JOIN teaching_assistant_df tat ON st.Email = tat.Email;"""result = sqldf(query)
result

兼任助教的学生(图片由作者提供)

结论

恭喜你!🎉🍾您刚刚学习了如何利用pandasql的强大功能,这是一个很棒的工具,允许您在数据帧上应用 SQL 和 Pandas 查询。

如果你喜欢阅读我的故事,并希望支持我的写作,考虑成为一个媒体成员。每月支付 5 美元,你就可以无限制地阅读媒体上的故事。

欢迎在媒体、推特和 YouTube 上关注我,或者在 LinkedIn 上打招呼。讨论人工智能、人工智能、数据科学、自然语言处理和人工智能是一种乐趣!

如何像管理产品团队一样管理您的数据团队

原文:https://towardsdatascience.com/how-to-run-your-data-team-like-a-product-team-7efd8a0fd423

伟大的产品团队是以用户为中心的,积极主动的。优秀的数据团队也会从这样做中受益。

一群太空人互相跟随。我想,这是对我们的数据团队如何需要更好的领导实践的模糊比喻。🤷作者的‍♀️形象。

去年,Emilie Schario 和 Taylor Murphy 提出了这个美妙的想法“像运营产品团队一样运营您的数据团队”。这篇文章的关键前提是这样的:产品团队有许多伟大的实践,数据团队将从采用这些实践中受益。但是在这个过程中,我们忽略了这一点,并愉快地用稻草人来代替它:为我们的数据资产维护生产级系统 , 构建更多的数据产品,或者煞费苦心地定义生产在强化数据契约中的含义。所有这些当然都值得考虑,但他们更关心的是数据和数据资产的正确处理,而不是实际推动影响的数据团队。

这里的中心思想是永远不要对“数据产品”的定义和边界吹毛求疵,或者为数据生产者设置 SLA,而是迫使我们通过使用产品团队作为模型来重新考虑数据团队如何运作。

我想花一些时间来讨论如何像管理产品团队一样管理您的数据团队。

两个核心理念:以用户为中心和主动性

产品团队体现了两个核心原则——以用户为中心和主动性。让我们依次讨论每一个。

以用户为中心

最好的产品团队是以用户为中心的。他们定期与客户交流,让直接的用户反馈直接影响他们的路线图。这个飞轮是任何好产品的生命线——它确保它们不仅仅是运输功能,而是解决问题。

数据团队需要以同样的方式运作。我们太沉迷于我们的工作在技术上可以有多有趣,而忘记了我们不是科学/工程追求的独立避风港——我们是被雇佣来提供商业价值的业务单位。如果我们像产品团队一样,不使用数据解决业务问题,我们隐喻的“数据产品”(我们所做的所有数据工作)就会失败。

这并不意味着被动地响应临时请求。这也不意味着完全回避科学努力。它只是意味着保持与业务需求的协调,并为此寻求机会。虽然泰勒和艾米莉认为你的同事是你的客户,但我认为这还不够——公司是你的客户。你需要了解它,理解它,并围绕它来指导你所做的一切。

积极主动性

第二,最好的产品团队有主动的过程来支持产品构建过程。他们为自己提供有意的空间来设定愿景、集思广益、追求超出直接回应客户要求范围的激情项目。

另一方面,分析团队很少这样运作。至少,我们应该花一些时间探索入站请求之外的数据。在团队层面上,我们应该寻找模式,这样我们就可以有意识地设计我们的路线图,并做高杠杆的工作。

也就是说,反应式工作当然仍然有它的位置——分析师是企业探索数据的主要手段,因此我们经常会发现自己必然处于辅助角色。但关键是不断推动理解这项工作背后的背景,并让这种背景激励战略性的高杠杆项目。

图片作者。

但是如何开始呢?

最初的 LO 文章有一些很好的组织层面的建议来使这一切成为可能:有足够的人员,这样你就有足够的带宽来进行战略部署;召集一个多学科团队,从中汲取灵感。除此之外,这里有几个具体的流程级别的变化,您可以立即 make:‍

1.建立巩固知识的过程。‍

将团队的工作放在一个地方是以用户为中心的先决条件。为了让您的工作以用户为中心,您需要了解您被要求做的所有工作。在一个共享的空间中组织你的工作可以使你的团队工作模式匹配——相当于一个产品团队在头脑风暴之前研究 UX 的研究结果。

这将是你最大的障碍,因为不合规是一个大问题。人们努力保持现状,我经常看到文档/知识共享计划失败。在 wiki 工作空间中发布作品,如 idea、Confluence 或 Dropbox paper(对于特定于分析的解决方案, hyperquery )可以打破这一障碍。

确保广泛采用的关键要素是:

  • 降低使用摩擦。尽管使用 git 和建立同行评审流程可能很有吸引力,但层层流程并不能确保严格性——它们会降低采用率。做一些简单、轻松的事情,并专注于确保您的团队将他们的工作放入工具中。
  • 搭建组织脚手架。同样,使用类似于 hyperquery 、conception 或 Confluence 的工具,通过 wiki 结构,使你的团队不仅能够围绕集中化,而且能够围绕组织建立实践。就合理的、功能性的类别达成一致,并创建一个集中的“从这里开始”的文档,让新的分析师加入到您的实践中。

在 hyperquery 中组织的工作。图片作者。

2.深入了解业务需求。

我们不仅仅是技术工人。我们是数据和业务其余部分之间的桥梁。如果我们只是沉浸在数据中——这只是对话的一个方面——我们将无法达到应有的效率。

我们为自己的技术实力感到自豪,但是我们只有在知道我们为什么要工作的情况下才是有效的。如果没有敏锐的商业头脑,我们会写下一个又一个毫无意义的分析,直到我们被转移到存储 B ,我们的交互被降级为数据拉取。

实际上,这看起来像什么:

  • 总是问为什么 **。**在你深入 SQL 之前,确保你和你的利益相关者在业务目标上保持一致。把这些写下来,商定一个方法,然后开始工作。这开创了一个先例,即你在决策过程中的参与不仅限于技术工作——至少,你至少会被视为一名翻译,充其量是一名思想伙伴。
  • **关心业务。**这听起来显而易见,但我经常看到分析师和数据科学家无视业务,沉浸在他们工作的技术方面。这种行为预示着一个真正功能失调、影响力低下的分析机构。更高的影响通常不是来自更好的分析,而是来自更高水平的战略执行的数据驱动的影响。

结论

在过去的十年中,数据分析的本质发生了巨大的变化。我们比以往任何时候都可以访问更多的数据、更多的计算能力和更多的工具。但是我们还没有想出我们应该在一个拥有新力量的组织中运作。从其他领域借鉴成功的实践可能会有所帮助。特别是对于产品团队来说,对以用户为中心和主动性的关注可能意味着帮助台分析团队和真正推动战略的团队之间的差异。以用户为中心和主动性来自对业务需求的敏锐认识和更好的知识共享实践。

推文@ imrobertyi/*@*hyperquery来问好。👋
关注我们上LinkedIn。🙂

要了解更多关于 hyperquery 的帮助,请查看hyperquery . ai。原博文 在 hyperquery 上发布

如何在 Amazon EC2 实例中运行 Python 脚本(演示)

原文:https://towardsdatascience.com/how-to-run-your-python-scripts-in-amazon-ec2-instances-demo-8e56e76a6d24

带演示的循序渐进教程

panumas nikhomkhai 的照片:https://www . pexels . com/photo/close-up-photo-of-mining-rig-1148820/

您很可能习惯于在本地机器上运行 Python 脚本。但是,机器可能无法满足运行某些操作所需计算或存储要求。

对于这些情况,人们可以利用虚拟实例来满足任何无法在本地满足的需求。

在这里,我们执行一个快速演示来展示 Python 脚本如何在 Amazon 的 EC2 实例中运行。

演示

有什么比演示更好的方法来解释如何做某事呢?

作为指南的一部分,我们将致力于在 EC2 实例中运行一个名为“random_number_generator.py”的 Python 脚本。

代码输出(由作者创建)

很简单,对吧?该脚本只是使用 Numpy 包打印出一个随机数。

记住 Python 的版本以及成功运行代码所需的包的版本很重要(我当前的环境使用 Python 3.9.13,只使用 Numpy 模块)。

要获得在机器上使用的 Python 版本,只需在命令行中输入以下命令:

python --version

要获得随 pip 一起安装的软件包及其版本的列表,请在命令行中使用以下命令。

pip list

您可以在实例中一个接一个地安装软件包,但是这可能很耗时。你也有可能得到错误版本的包。因此,建议将所有包存储在一个“requirements.txt”文件中,这可以用下面的命令来完成。

pip freeze > requirements.txt

步骤 1:启动 EC2 实例

首先,需要启动将运行脚本的 EC2 实例。

我不会过多地研究这一步,因为关于如何在 AWS 上创建 EC2 实例的教程不计其数(而且一开始就没有设计得很难)。

请随意选择适合您的使用情形的定价和安全配置。由于这只是一个简单的演示,我们将使用一个没有额外安全措施的自由层实例。

配置实例时更重要的细节如下:

1。选择亚马逊机器镜像(AMI)

当启动一个实例时,要求您做的第一件事是选择 AMI。

您选择的 AMI 将决定实例的用户名,您需要知道该用户名以便稍后连接到您的实例。对于那些不确定其实例的用户名是什么的人来说, AWS 文档涵盖了分配给每个 AMI 启动的实例的默认用户名。

对于我们的例子,我们将使用 Amazon Linux AMI 启动一个实例。这种类型的实例的用户名是“ec2-user”。

AMI(作者图片)

AMI 的选择还会影响到简化命令行操作所需的命令。例如,用于 Amazon Linux AMI 启动的实例的命令可能与 Ubuntu AMI 启动的实例不匹配。

2。密钥对

您还需要创建一个密钥对或使用现有密钥(作为. pem 文件)来访问您的实例。

对于我们的示例,我们将创建一个名为“test_key.pem”的私钥

密钥对(图片由作者提供)

完成所有部分后,单击“启动实例”。

步骤 2:连接到实例

AWS 允许您使用安全外壳(SSH)连接到您的实例。

要找到连接到实例所需的ssh命令,请在 EC2 控制台中选择您的实例,然后单击顶部的“connect”选项卡。之后,选择“SSH 客户端”选项卡。

选择“连接”选项卡(按作者排列的图像)

选择 SSH 客户端选项卡(按作者排序的图片)

您将看到连接到实例所需的命令。您还会看到您的实例的公共 DNS(您稍后会需要它,所以请记住这一点)。

在这种情况下,连接到该实例的命令是:

ssh -i "test_key.pem" ec2-user@ec2-34-204-68-237.compute-1.amazonaws.com

用于连接到实例的ssh命令必须从您的密钥文件的位置执行。在终端窗口中,将目录切换到包含私钥的文件夹,并输入提供的命令。出现提示时,选择“是”。如果成功,输出应该如下所示:

命令输出(由作者创建)

瞧啊。您现在已经连接到您的实例!

步骤 3:安装 Python(可选)

您的 EC2 实例应该已经提供了 Python3 的一个版本,您可以用python3 --version命令来验证它。

如果您正在寻找 Python 的特定版本,您可以自己安装(如果这不适用于您,请跳过这一步)。

Amazon Linux 实例提供了 Python 3.7。出于演示的目的,我们假设需要匹配我们的本地机器并安装 Python 3.9.13。

注意:以下命令适用于 Amazon Linux AMI 启动的实例。它们可能不适合用其他 AMI(例如 Ubuntu)启动的实例。

首先,我们安装 Python 的依赖项。

sudo yum -y groupinstall "Development Tools"
sudo yum -y install openssl-devel bzip2-devel libffi-devel

接下来,我们用wget命令下载感兴趣的 Python 版本。

sudo yum -y install wget
wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tgz

该实例现在应该有一个名为“Python-3.9.13.tgz”的文件。

注意:这些命令用于下载 Python 3 . 9 . 13 版本。要获得您选择的 Python 版本,只需用您选择的版本号替换命令中的版本号。

下载文件后,将其解压缩。

tar xvf Python-3.9.13.tgz

提取的 Python 文件夹现在应该在 EC2 实例中(您可以使用ls命令确认这一点)。

移动到创建的 Python 文件夹并执行安装。

cd Python-*/
./configure --enable-optimizations
sudo make altinstall

这样,Python 的新版本就应该安装成功了!为了测试这一点,我们可以输入Python3.9 --version命令。

命令输出(由作者创建)

步骤 4:将文件复制到 EC2 实例

现在我们有了 Python 的正确版本,我们可以将所有文件复制到实例中。在我们的例子中,被复制的文件是“random_number_generator.py”和“requirements.txt”文件。

我们将离开 Python 文件夹,创建一个名为“project”的新文件夹,其中将包含这两个文件。这一步是可选的;您可以将文件放在实例中您想要的任何位置。

命令输出(由作者创建)

现在,打开一个新的终端窗口(姑且称之为终端 2)。终端 2 将用于将本地机器中的文件复制到 EC2 实例。

可以使用scp(安全复制)命令将文件从一个位置复制到另一个位置。用于将文件从本地计算机复制到 EC2 实例的命令具有以下格式:

scp -i </path/key-pair-name.pem> </path/file_to_copy> <username>@<instance_public_dns>:<destination_path>

注意:要获取 EC2 实例的公共 DNS,请转到 AWS EC2 控制台中的 SSH 客户端选项卡(参见步骤 2)。

可以使用以下命令将“random_number_generator.py”和“requirements.txt”文件复制到实例中的“项目文件夹”中:

scp -i test_key.pem random_number_generator.py ec2-user@ec2-34-204-68-237.compute-1.amazonaws.com:/home/ec2-user/projectscp -i test_key.pem requirements.txt ec2-user@ec2-34-204-68-237.compute-1.amazonaws.com:/home/ec2-user/project

如果没有问题,该命令应该会产生以下输出:

命令输出(由作者创建)

当您返回到终端 1(即带有 EC2 实例的终端)时,您应该能够看到您在scp命令中指定的目标路径中的文件。

命令输出(由作者创建)

步骤 5:创建虚拟环境

在这个阶段,您可能想安装您的包,以便可以立即运行您的代码。但是,全局安装软件包可能会导致与系统软件包管理器的行为冲突。

所以,还是在虚拟环境下工作比较好。

我们将创建一个名为“test_venv”的虚拟环境,然后进入该环境。

Python3.9 -m venv test_env
source test_env/bin/activate

激活虚拟环境后,您应该能够在当前目录左侧的括号中看到它的名称。

命令输出(由作者创建)

现在我们在虚拟环境中,我们可以安装运行脚本所需的所有必要的包。如果您将软件包和版本存储在 requirements.txt 文件中,那么您可以使用一个命令来执行所有安装。

pip3.9 install -r requirements.txt

命令输出(由作者创建)

同样,这个命令是针对 Python 3.9 的。根据使用的 Python 版本修改命令。

第 6 步:运行您的代码!

您已经创建了 EC2 实例,连接到实例,安装了正确的 Python 版本,将文件传输到实例,并设置了虚拟环境。最后,您可以在新实例中运行 Python 脚本!

命令输出(由作者创建)

一旦你完成了在虚拟环境中的工作,你可以用deactivate命令离开它。

友情提示:停止你的实例

EC2 实例使用现收现付的定价模型,所以当您使用完实例时,请停止使用它们!否则,你会发现自己收到一份令人不快的账单。

即使您正在处理一个自由层实例,最好养成尽早停止实例的习惯。

结论

照片由普拉蒂克·卡蒂亚尔在 Unsplash 上拍摄

通过这个演示,您有望顺利地在 AWS 实例上运行您的脚本。

即使你主要编写可以在本地机器上运行的程序,接触一些云平台提供的计算服务也是有好处的,因为当你的工作有更大的计算需求时,你会有所准备。

我祝你在数据科学的努力中好运!

参考

  1. 使用 SSH 连接您的 linux 实例。(未注明)。2022 年 12 月 4 日检索,来自https://docs . AWS . Amazon . com/AWS ec2/latest/user guide/accessinginstanceslinux . html
  2. Mutai,J. (2022 年 1 月 17 日)。如何在亚马逊 Linux 2 上安装 Python 3.9。计算 ForGeeks。2022 年 12 月 4 日检索,来自https://computingforgeeks . com/how-to-install-python-on-Amazon-Linux/

如何在亚马逊 SageMaker 安排 Jupyter 笔记本

原文:https://towardsdatascience.com/how-to-schedule-jupyter-notebooks-in-amazon-sagemaker-d50fa1c8c0ad

使用 AWS 服务定期运行 Jupyter 笔记本的分步指南

在 Unsplash 上由Towfiqu barb huya拍摄的照片

你的经理问:“下周你能为我重新运行这个分析吗?”。不用担心:您可以设置一个提醒来手动重新运行它。

接下来的一周,你重新运行分析。这一次,你的经理说,“这太好了。可以每周发给我吗?”真烦人。你不喜欢打开你的 Jupyter 笔记本,运行它,并将结果保存到 S3 周刊。这很费时间,而且你的任务清单上还有更有价值的任务。

这篇文章是如何在 Amazon SageMaker 中安排 Jupyter 笔记本的指南。这些是我用来在11 月日自动运行时间序列预测笔记本的步骤(更多细节见本文)。

解决方案概述

我将向您展示如何使用 AWS 服务安排您的 Jupyter 笔记本。我会假设你的数据可以在线访问(例如 S3,GitHub),你会把它保存到一个类似的位置。Jupyter 笔记本将在亚马逊 SageMaker 笔记本实例上运行。一个生命周期配置将通过指定 conda 环境和实现自动停止功能来控制笔记本实例。最后,我们使用 AWS Lambda 和 Amazon EventBridge 按照固定的时间表触发笔记本实例。

我们的建筑看起来会像这样。

作者图片

您将看到我们仅使用 AWS 服务。第三方选项,比如 JetBrains 都有,但是自己做可能更划算。

场景和输入数据

我们将使用JHU·CSSE·新冠肺炎的数据 [1],该数据给出了各州和国家每日累计的新冠肺炎病例数。在我们的场景中,我们假设我们的经理要求我们创建一个折线图,显示澳大利亚各州在过去一年中的每日累积案例。我们的地块应该可以在 S3 以 PNG 格式访问,看起来像下面的图像。

作者图片

创建一个 Amazon SageMaker 笔记本实例

我们将在一个亚马逊 SageMaker 笔记本实例中运行我们的 Jupyter 笔记本应用程序。该服务提供完全托管的云笔记本电脑,预装了执行数据科学任务所需的库。

首先在 SageMaker 控制台中创建一个新的笔记本实例。

作者图片

我们使用 Jupyter Lab 3 创建了一个 ml.t3.medium 实例。我还创建了一个新的 IAM 角色,该角色将访问我的帐户上的所有 S3 存储桶。

作者图片

创建您的笔记本实例后,您可以在 SageMaker 控制台中启动它并打开 Jupyter Lab。我将使用 python3 conda 环境内核,它预装了执行本教程所需的基本库。如果您需要在您的环境中安装外部库,您应该阅读文档。

然后,我们在我们的环境中创建我们的 analysis.ipynb Jupyter 笔记本。笔记本使用 pandas 从 GitHub 读取并处理 CSV 文件。然后,我们使用 pandasmatplotlib 绘制我们的新冠肺炎数据,并将生成的 PNG 文件导出到我们的 S3 存储桶。

我们示例中的代码如下所示。

你也可以在 GitHub 上找到例子。

将生命周期配置添加到笔记本实例

一个生命周期配置是一个 shell 脚本,我们添加到我们的 SageMaker 笔记本实例来安装包,选择我们的 conda 环境,并自动停止我们的笔记本以防止超额计费。

首先为您的笔记本实例添加一个新的配置。

作者图片

我们将我们的配置称为 schedule-configuration ,并包含以下脚本。我们的脚本激活了 python3 conda 环境,并在空闲 5 分钟后加载命令来自动停止我们的笔记本实例。亚马逊提供的这个 GitHub repo 托管了几个样本生命周期配置脚本,你可以用它们来定制你的笔记本实例。

作者图片

set -esudo -u ec2-user -i <<'EOF'# PARAMETERS
ENVIRONMENT=python3
NOTEBOOK_FILE=/home/ec2-user/SageMaker/analysis.ipynbecho "Activating conda env"
source /home/ec2-user/anaconda3/bin/activate "$ENVIRONMENT"echo "Starting notebook"
jupyter nbconvert "$NOTEBOOK_FILE" --ExecutePreprocessor.kernel_name=python --execute --to notebookecho "Dectivating conda env"
source /home/ec2-user/anaconda3/bin/deactivate# PARAMETERS
IDLE_TIME=300echo "Fetching the autostop script"
wget [https://raw.githubusercontent.com/aws-samples/amazon-sagemaker-notebook-instance-lifecycle-config-samples/master/scripts/auto-stop-idle/autostop.py](https://raw.githubusercontent.com/aws-samples/amazon-sagemaker-notebook-instance-lifecycle-config-samples/master/scripts/auto-stop-idle/autostop.py)echo "Detecting Python install with boto3 install"# Find which install has boto3 and use that to run the cron command. So will use default when available
# Redirect stderr as it is unneeded
if /usr/bin/python -c "import boto3" 2>/dev/null; thenPYTHON_DIR='/usr/bin/python'
elif /usr/bin/python3 -c "import boto3" 2>/dev/null; thenPYTHON_DIR='/usr/bin/python3'
else# If no boto3 just quit because the script won't workecho "No boto3 found in Python or Python3\. Exiting..."exit 1
fiecho "Found boto3 at $PYTHON_DIR"echo "Starting the SageMaker autostop script in cron"(crontab -l 2>/dev/null; echo "*/5 * * * * $PYTHON_DIR $PWD/autostop.py --time $IDLE_TIME --ignore-connections >> /var/log/jupyter.log") | crontab -EOF

保存生命周期配置后,导航至您的笔记本实例,然后按“编辑”。

作者图片

添加您的生命周期配置并保存。启动您的笔记本实例将加载 python3 环境,并在空闲 5 分钟后触发自动停止功能。

作者图片

用 Amazon EventBridge 和 AWS Lambda 触发笔记本

使用 Amazon EventBridge 和 AWS Lambda 可以按照固定的时间表运行我们的 SageMaker 笔记本。 Amazon EventBridge 是一个事件服务,它将触发一个 AWS Lambda 函数来启动我们的 SageMaker 笔记本实例。

首先,创建一个新的 Lambda 函数。

作者图片

我们将调用我们的函数 launch_jupyter_nb 并选择用 Python 3.9 编写。

作者图片

保存后,我们添加 boto3 命令来启动我们的 SageMaker 笔记本实例。您可以在下面找到代码。完成后按“部署”。

作者图片

import boto3
import logging
def lambda_handler(event, context):client = boto3.client('sagemaker')client.start_notebook_instance(NotebookInstanceName='sagemaker-schedule')return 0

我们还需要给 Lambda 函数访问 SageMaker Notebook 实例的权限。导航到“配置”选项卡,然后单击当前角色。

作者图片

单击该角色将引导您进入 IAM。在这里,您应该附加“AmazonSageMakerFullAccess”策略。

作者图片

回到 AWS Lambda,在“函数概述”下,给你的函数添加一个触发器。我们将添加一个名为 launch_jupyter_nb 的 EventBridge 触发器,它按照固定的时间表运行。我们使用一个 Cron 表达式来指定时间表。在我们的示例中,EventBridge 触发器将在每天 03:00 UTC 运行。

cron(0 3 * * ? *)

作者图片

我们完了!我们的 Jupyter 笔记本托管在 SageMaker 笔记本实例中,由于 Amazon EventBridge 和 AWS Lambda,它将按照固定的时间表运行。一旦笔记本电脑完成运行并闲置 5 分钟,我们的生命周期配置将关闭笔记本电脑实例。

其他考虑

在安排您的 Jupyter 笔记本时,您应该注意两个重要的考虑事项。首先,我们创建的生命周期配置不能运行超过 5 分钟。否则就会失败。根据文档,您可以通过以下方式克服这一限制:

  • 减少步骤的数量
  • 并行运行任务
  • 在你的脚本中使用 nohup 命令

其次,本教程向您展示了如何在 SageMaker Notebook 实例中而不是sage maker Studio Notebook中安排笔记本。您可以通过调整生命周期配置并参考boto 3文档来修改上述步骤,以使用 Studio 笔记本。

下次你的经理让你重复你的 Jupyter 笔记本分析,你可以。在本指南中,我向您展示了如何使用 Lambda 和 EventBridge 在 SageMaker 笔记本实例中调度您的笔记本。没有必要注册第三方服务。

喜欢你读的书吗?跟着我上媒。否则,发微博给我或者在 LinkedIn 上加我。

你可以在 GitHub 上找到这篇文章中用到的所有代码。

[1]约翰·霍普金斯大学系统科学与工程中心(CSSE)的新冠肺炎数据存储库,在知识共享署名 4.0 国际版(CC BY 4.0)下获得许可

如何使用 CloudFormations 保护您的 AWS API 网关

原文:https://towardsdatascience.com/how-to-secure-your-aws-api-gateways-with-cloudformations-template-713a17d3b1fd

深入探讨如何保护您的 API

由 Muhammad Zaqy Al Fattah 在 Unsplash 上拍摄的照片

介绍

在任何机器学习模型到云的部署周期中,API 的安全性是一个重要的考虑因素。通过增加模型的可访问性,我们将无意中增加应用程序对潜在的未授权访问的脆弱性。

在之前的帖子中,我们部署了一个 k 近邻分类器,并将其作为 AWS lambda 上的 API 端点。在其当前的部署状态下,部署的 API 端点是不安全的,任何具有该 URL 的人都能够调用我们的函数。

让我们探索一下 Amazon 的 API 网关提供的一些方法来保护我们的 API 端点。下面列出了我们将详细探讨的保护 API 的两种方法。没有必要按顺序遵循这个指南,因此如果你想跳过,我已经链接了每个部分。

  1. 自定义 lambda 函数。(template_lambda.yaml)

2.身份访问管理。 ( template_iam.yaml)

每种方法都有独特的特征,因此具有不同的优点和缺点。

先决条件

由于我们将建立在以前的项目上,本指南的先决条件将与我以前的博客中列出的要求相同。

在继续之前,您需要满足几个先决条件。本指南将要求您与许多工具进行交互,所以请花一些时间来满足这些先决条件。

我将使用 AWS 无服务器应用程序模型(SAM)来部署支持机器学习模型所需的所有基础设施。因此,假设您对使用 AWS SAM 和 AWS Cloudformations 有所了解。如果你不确定,请阅读我之前的博客,上面链接了更多关于使用 AWS SAM 模板以及如何部署它们的细节。

这个项目的源代码可以在下面的链接中找到。

https://github.com/lloydhamilton/aws_lambda_with_authoriser

1.λ授权者

Lambda authoriser 是一个自定义函数,充当 API 的看门人。它包含限制访问 API 网关背后的任何资源所需的授权逻辑。Lambda authoriser 在设计 API 访问控制时提供了更高的通用性,因为它有助于更好地定制授权逻辑。这是有利的,因为它允许更好地与第三方身份提供者集成,例如使用单点登录(SSO)的组织。

下面的图表详细描述了这个项目中 lambda 授权 API 网关的 HTTP 请求从发起到响应返回的路径。

作者图片

  1. HTTP POST 请求被发送到 API 网关,报头中带有授权令牌。
  2. 指向 API 网关的 HTTP 请求启动 lambda 授权功能,其中授权令牌被认证。
  3. 授权令牌的认证将返回允许或拒绝流量通过 API 网关的策略文档。
  4. lambda 授权者对 API 流量的成功认证将调用 lambda 函数来执行 ML 预测。
  5. 预测通过 API 网关传递回客户端。
  6. 客户端将在 HTTP 响应中接收作为数据有效负载的预测。

为了在 AWS cloudformations 上部署 lambda 授权的 API 网关,我们必须定义/声明 3 个关键资源。

  • 包含授权逻辑的 python 函数。(handler.py)
  • SAM 模板中提供 python 函数的 lambda authoriser 函数资源。(template_lambda.yaml)
  • API 资源属性中对 lambda 授权者的引用。(template_lambda.yaml)

handler.py

authorizer├── handler.py└── requirements.txt

handler.py 文件包含 lambda 授权器的主要授权逻辑。在这个例子中,我们将使用 JSON web 令牌( JWT )来编码和解码通过 HTTP 请求传递的授权令牌。

需要注意的关键事项:

  • 第 12 行:在这段代码中,密钥是纯文本的,只是为了演示的目的。我强烈推荐使用更安全的方法来访问密钥,比如 AWS secrets manager,这不在讨论范围之内。
  • 第 15–21 行:JWT 令牌解码中的异常会将auth设置为“拒绝”。auth仅在 JWT 解码通过时设置为“允许”。
  • 第 24–37 行:authorize函数将返回一个 JSON 策略文档,其中包含控制通过 API 网关访问的权限。

lambda authoriser 最重要的一点是,必须返回一个访问策略文档,这样才能工作。

template_lambda.yaml

要部署 lambda 授权器,在资源选项卡下定义 lambda 授权功能,如template_lambda.yaml所示。在本例中,我们将授权函数定义为MyAuthFunctions,声明的属性如下面的代码片段所示。

要将 API 配置为使用MyAuthFunctions作为授权者,应该在Auth属性选项卡下声明对该函数的引用。

如下面的template_lambda.yaml所示,MyApi的默认授权者被声明为 lambda 函数MyAuthFunctions。因此,发送到MyApi的 HTTP 请求将启动 python 文件中定义的授权逻辑,以认证存储在authorizatioToken头中的 JWT。

部署

要部署 cloudformation 堆栈:

  1. 建立 docker 形象。
sam build -t template_lambda.yaml

2.使用 SAM 在 AWS 上部署。

sam deploy --guided

成功部署堆栈后,我们可以用下面的代码调用 API。用 API 端点的返回 URL 替换 URL。

如前所述,lambda 授权器在管理 API 网关的授权逻辑方面提供了更多的功能。然而,如果没有为云安全设计适当的加密程序的适当知识,使用 lambda 授权者要自担风险。

保护您的 API 的一个更好的替代方法是利用现有的认证工具,如 IAM 或 Cognito(不在范围内),它们可以很容易地集成到 Amazon 的 API 网关中。

2.身份访问管理(IAM)

AWS 身份访问管理(IAM)是一项全球管理的服务,提供对 AWS 平台上的服务和资源的访问控制。从根本上说,它允许管理员通过分配权限来控制对 AWS 资源的访问。

使用 IAM,对 API 的 HTTP 调用将需要符合 AWS Signature Version 4 签名过程的附加身份验证信息。这个过程将使用预定义的访问和密钥对 HTTP 请求进行签名,这些密钥可以通过 IAM 控制台或通过boto3 python API 获得。一般来说,签名是通过一系列嵌套的 sha256 散列结合当前的 datetime 和 IAM 安全凭证来创建的。

关于 AWS Signature V4 签名流程如何工作的具体细节可以在链接到此处的主文档中找到。

template_iam.yaml

与 lambda 授权者不同,通过 IAM 策略进行身份验证只需要对 cloudformation 模板代码进行微小的调整。要通过 IAM 认证MyApi,只需将DefaultAuthoriser选项设置为AWS_IAM

部署

要部署 cloudformation 堆栈:

  1. 建立 docker 形象。
sam build -t template_lambda.yaml

2.使用 SAM 在 AWS 上部署。

sam deploy --guided

成功部署堆栈后,我们可以用下面的代码调用 API。函数aws_sign_v4.sign_v4将使用当前在boto3会话中活动的已配置的 AWS 凭证来处理 HTTP 请求的签名。或者,您可以创建一个新的 IAM 用户,并通过 AWS 控制台访问所需的凭证,方法是遵循这里的官方文档。

AWS 使得配置和部署 IAM 认证的 API 网关变得非常简单。与 lambda 授权者不同,它不需要维护额外的代码,因此降低了安全漏洞的风险。然而,生成遵循正确协议的签名 HTTP 请求的复杂性增加了,但这仍然没有实现 lambda 授权器复杂。

摘要

总而言之,AWS 提供了很好的工具来集成所有 API 调用的认证过程。这将确保只有拥有适当权限的个人才能访问您的应用程序。哪个是更好的选择?嗯,这将取决于你的具体需求,以及你在云中设计系统的技术知识。

我希望你从这本指南中有所收获,并期待再次在这里见到你!如果有任何问题,请留下您的评论,我将非常乐意帮助您。

请在 LinkedIn、Medium 或 Twitter(@ illoyd Hamilton)上关注我,了解更多数据科学相关内容,或在 CodeClan 与我一起学习。

如何保护您的 Kubernetes 部署

原文:https://towardsdatascience.com/how-to-secure-your-kubernetes-deployment-5f52c2b67c1

建立一个声誉需要 20 年,而几分钟的网络事件就能毁掉它。— 夏羽·纳珀

由马特·阿特兹在 Unsplash 上拍摄的照片

不幸的是,Kubernetes 部署在默认情况下并不安全。一个臭名昭著的例子是针对特斯拉汽车公司发起的密码劫持攻击。几年前,恶意攻击者渗透进他们的 Kubernetes 集群,并从其中一个 pod 内部开始了一个加密挖掘过程。

每个 Kubernetes 分布是不同的;因此,这里没有免费的午餐。因此,为了确保 Kubernetes 的安全,您应该采取额外的措施,遗憾的是,大多数措施都是手动过程。那么,你怎么知道从哪里开始呢?

在这个故事中,我们将介绍一款围棋检测工具 kube-bench ,它将帮助你做到这一点。然后,我们将在Rancher Kubernetes Engine(RKE)中运行 kube-bench,这是一个 CNCF 认证的 Kubernetes 发行版,完全在 Docker 容器中运行。

学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每个月的第一个星期六收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!

库贝长凳

kube-bench 与 docker-bench 类似,是一个 Go 检测工具,而不是强制工具。它通过运行由 Kubernetes CSI 基准提供的检查来检查您的 Kubernetes 集群是否安全部署。

https://medium.com/geekculture/your-docker-setup-is-like-a-swiss-cheese-heres-how-to-fix-it-cd1f49f40256

CIS Kubernetes 基准测试的工作方式与 CIS Docker 基准测试相同。然而,由于有许多 Kubernetes 发行版,CIS Kubernetes 基准的具体实现是为每个发行版量身定制的。

kube-bench 不采取措施强化您的 Kubernetes 集群;它可以识别您的部署中的安全漏洞,但是您必须付出额外的努力来填补这些漏洞。

测试被配置到不同的 YAML 文件中。许可和强化配置文件都有测试文件。

最后,kube-bench 运行在 Linux 上,所以除非您使用 Linux 发行版,否则一些审计检查不会起作用。但是,在您的 Kubernetes 集群中,始终可以选择将 kube-bench 作为 pod 运行。我们将探讨这个选项。

RKE·库贝-长凳模式

针对特定的 Kubernetes 实现,有不同的 CIS Kubernetes 基准实现。我们将在这里研究 RKE 的实现。

RKE·库贝-长凳模式与多克-长凳模式具有相同的结构:

- id: < test id>text: < what to test>audit: < command to test>tests:test_items: <what to test for>— flag:set: <true | false>remediation: <how to fix>scored: <true | false>

该模式的主要部分包括:

  • 测试 id
  • 测试的简短描述
  • 包含要运行的命令及其标志的审核部分
  • 补救部分,包含修复失败测试的说明

评估您的 Kubernetes 部署

我们将 kube-bench 安全工具作为一个容器来运行。更具体地说,在这个例子中,我们将评估一个 RKE 部署。不同的 Kubernetes 发行版需要稍微不同的方法。如果您想跟进,请按照官方的文档建立一个 RKE 集群。

评估控制平面

首先,您将评估集群的控制平面。为此,你需要先ssh进入你的主节点。如何做到这一点取决于您的系统。通常,您应该运行类似于下面的命令:

ssh USER@HOST

一旦你进入,你将运行由兰斯和exec提供的rancher/security-scan容器来得到结果:

docker run --pid=host -v /etc:/node/etc:ro /var:/node/var:ro -it rancher/security-scan:v0.2.2 bash

这个容器已经被配置为在适当的 Kubernetes 上下文中使用 kube-bench。因此,要检查控制面板的安全状态,您只需运行以下命令:

kube-bench run --targets etcd,master,controlplane,policies --score --config-dir=/etc/kube-bench/cfg --benchmark rke-cis-1.6-hardened

请注意,该命令运行对硬化配置文件的检查。您总是可以使用宽容的概要文件,它更宽容。为此,用--benchmark rke-cis-1.6-permissive替换--benchmark rke-cis-1.6-hardened

在执行安全扫描命令时,kube-bench 将针对不同的类别运行多项检查。为了收集故障并仔细调查它们,grep for FAIL:

kube-bench run --targets etcd,master,controlplane,policies --scored --config-dir=/etc/kube-bench/cfg --benchmark rke-cis-1.6-hardened | grep FAIL

评估工人节点

评估 worker 节点遵循类似的过程。同样,第一步是将ssh放入 worker 节点,运行rancher/security-scan容器并将exec放入其中:

docker run --pid=host -v /etc:/node/etc:ro -v /var:/node/var:ro -ti rancher/security-scan:v0.2.2 bash

一旦进入容器上下文,您需要运行的命令如下所示:

kube-bench run --targets node --scored --config-dir=/etc/kube-bench/cfg --benchmark rke-cis-1.6-hardened | GREP FAIL

注意,唯一的区别是--targets标志。您现在将其设置为node

就是这样!现在,您已经检查了主节点和工作节点的安全问题。

结论

Kubernetes 部署在默认情况下是不安全的,您应该多做一点来保护大门。幸运的是,像 kube-bench 这样的工具让我们将注意力集中在集群的特定区域。

现在,您已经看到了如何使用 docker-bench 保护 Docker 设置,以及如何使用 kube-bench 保护 Kubernetes 部署。然而,在容器内部运行什么同样重要。因此,在下一篇文章中,我们将看到您可以判断出容器图像是可以安全使用的。

关于作者

我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 Twitter 上关注我的 Medium 、 LinkedIn 或 @james2pl 。

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

分类问题如何选择损失函数和激活函数

原文:https://towardsdatascience.com/how-to-select-loss-function-and-activation-function-for-classification-problems-b7f32c724507

了解如何选择神经网络最后一层的激活函数和损失函数

机器学习模型由遵循特定流程适应的数学过程组成。这需要一定的和谐与平衡。在构建模型时,从导入数据到评估结果的过程可能会有大量不同的组合。所以,机器学习,尤其是深度学习架构,可以称之为多种选择融合调和的数字艺术架构。深度学习粗略地产生前向传播和反向传播,意味着为了降低损失值而更新权重。本文介绍了如何在训练模型之前选择集合损失函数和激活函数变量。

照片由丹尼斯·莱昂在 Unsplash 上拍摄

在进入内容之前,先澄清问题类型和一些术语:

  • **目标:**输入的最终输出,例如,物种列是 Iris 数据集的目标。
  • **标签:**输入的结果,例如,鸢尾、海滨鸢尾、杂色鸢尾是鸢尾数据集的标签。

分类可以是:

  • **二元分类:**目标中有 2 个标签。示例:[0]或[1]
  • **多类分类:**有两个以上的目标,但只有一个标签被分配给一个输入。示例:[0 0 1]或[1 0 0]或[0 1 0]。
  • **多标签分类:**有两个以上的目标,但一个输入可以分配多个标签。示例[ 1 1 0]或[1 0 1]或[0 1 1]

激活功能

如介绍中所述,模型的训练基于正向传播和反向传播。当从更广的角度来看该模型时,借助于设计的深度学习模型中的层提取的信息被转移到最终层用于分类过程。所选择的最终激活函数对于确定估计结果非常重要,这里的是可视化的链接。

因此,最终层中神经元的数量和最终层中使用的激活函数是相关的。这种关系如下:

如果是二元分类,即目标值集中只有 2 个标签:

-逻辑/乙状结肠激活功能

Sigmoid 激活函数取 0 到 1 之间的值。值<0.5 are assigned to 0, values > 0.5 被赋值为 1,通过将它们与测试数据集进行比较来执行模型评估。

由于目标值将被分配给一个输入,model.add(Dense(1,activation = “sigmoid”))用于最终层。该模型建立在包含 2 个标签(二进制分类)的breast_cancer dataset之上,在下面的 sklearn 库中提供。

前 10 个prediction值是:

0.99996, 0.999997, 0.999995, 0.999813, 0.00298241, 5.99027e-06, 0.0589639, 0.985855, 0.999954, 8.34465e-07, 0.999944

而前 10 个y_test值是:

1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1

这里,阈值被设置为 0.5,预测值被舍入为 0 或 1。Sigmoid 激活函数主要用于二分类问题。

- Softmax 激活功能

Softmax 激活函数也采用 0 到 1 之间的值,这些值是矢量值,表示概率比。获得的矢量结果分别给出了输入的每个目标(标签)的概率。具有明显最高概率的结果被选为预测结果。当然,对于那个过程,数据集必须是多类的,这意味着一个热编码。

由于概率数据将被分配给每个目标值,model.add(Dense(10,activation = “softmax”))被用于包括 10 个不同标签的数据集的最终层。以下是 sklearn 库中提供的数字数据集的示例:

在图 1 中,显示了一个截面的预测结果和已知的y_test值。在下一步中,如代码块所示,通过使用np.argmax确定每一行中的最大数据属于哪个目标来执行模型评估。

图一。y _ 测试值(左)和预测结果(右),作者图片

- ReLu、Tanh 等

在最后一层中,出于上述原因,sigmoid 和 softmax 是优选的。此外,有各种激活功能应用于模型中的层。其中一些可以在维基百科链接上找到。

— ReLu

整流线性激活单元是最优选的激活函数之一,因为它的消失梯度减小。虽然最小值为 0,但最大值没有限制。

the input<0, output=0
the input>0, output=input

在 MLP 和美国有线电视新闻网的模型中,它经常被首选。

— Tanh

它取值在-1 和 1 之间。它类似于 sigmoid 激活函数,是递归神经网络(RNN)的首选。它相对于 sigmoid 激活函数的优点是,它是围绕中心= 0 成形的,因为它取-1 和 1 之间的值,对于 sigmoid 来说,相同的情况是 0.5。这导致对下一层更有意义的学习。

损失函数

二元交叉熵

二元交叉熵考虑真实标签和预测标签的值来计算损失值。顾名思义,在第一个代码块中可以看到,binary_crossentropy被用作损失函数来在二进制标签之间进行分类。使用通过 sigmoid 激活函数获得的概率估计结果和通过二进制交叉熵计算的损失来更新权重,然后进行训练。

分类交叉熵

在多类数据集中,概率结果作为阵列输出估计获得。这里用categorical_crossentropy把这个分布训练成正确的方向。数学公式如下:

图二。分类交叉熵的数学公式,作者图像

稀疏分类交叉熵

它用于多个标签。分类交叉熵和稀疏分类交叉熵之间的主要区别在于,分类交叉熵用于一次性编码的目标([1 0 0]、[0 1 0]、[0 0 1]),而稀疏分类交叉熵用于编码的标签([0]、[1]、[2])。

例如,在第二代码块中,标签被转换为(n_samples,10),即标签-9 对应于[0 0 0 0 0 0 0 0 0 0 0 0 0 0 1],从而categorical_crossentropy被用作损失函数。如果标签被转换为整数,即标签-9 对应于[9],则首选sparse_categorical_crossentropy

结论

深度学习架构不仅应该与使用的层保持一定的和谐,还应该与模型的编译保持一定的和谐。为了实现这种和谐,从数据集的维度开始,应该考虑模型的输出维度并做出选择。

如果问题是二元分类:

  • 在最后一层使用model.add(Dense(1,activation = “sigmoid”))可以选择Binary_crossentropy作为损耗。预测输出将是包括概率值的(n_test_samples,1)数组,并且选择 0.5 阈值将其设置为 0 或 1。
  • 或者,通过选择sparse_categorical_crossentropy作为损耗,可以在最终层中使用model.add(Dense(2,activation = “softmax”))。预测输出将是(n_test_samples,2)数组,其包括分别属于标签的概率值。然后,使用pred_labels = np.argmax(predictions, axis = 1),选择最大值,并通过与 y_test 比较进行模型评估。

如果问题是多类分类:

  • 目标值被转换为一键编码格式,并且在最后一层使用model.add(Dense(n_labels, activation = “softmax”))可以选择categorical_crossentropy作为损失。预测输出将是(n_test_samples,n_layers),并且使用包括概率值和np.argmax(predictions, axis = 1)的数组来确定最大值。
  • 目标值被转换为整数(使用 LabelEncoder),然后在最后一层添加model.add(Dense(n_labels ,activation = “softmax”))model.add(Dense(n_labels ,activation = “sigmoid”)),并设置损失函数sparse_categorical_crossentropy。由于预测结果的形状将是(n_test_samples,n_labels),因此可以通过使用np.argmax选择最大概率,使用 y_test 值来评估模型。

由于其性质,校正线性单元(ReLu)不能用作最终图层,而是应用于模型中的图层。

通过在 python 环境中使用上面的代码块尝试各种版本并观察维度,可以探索更多。

https://ibrahimkovan.medium.com/machine-learning-guideline-959da5c6f73d

如何为数据集选择最佳数量的主成分

原文:https://towardsdatascience.com/how-to-select-the-best-number-of-principal-components-for-the-dataset-287e64b14c6d

你应该遵循的六种方法

兰迪·法特在 Unsplash 上的照片

在对数据集应用主成分分析(PCA)时,选择最佳数量的主成分是主要挑战。

在技术术语中,选择主成分的最佳数量被称为一种超参数调整过程,在该过程中,我们为 Scikit-learn PCA() 类中的超参数 n_components 选择最佳值。

from sklearn.decomposition import PCA
pca = PCA(**n_components=?**)

换句话说,当我们对具有 p 个变量的原始数据集应用 PCA 得到具有 k个变量(主成分)的变换数据集时, n_components 等于 k ,其中 k 的值远小于 p 的值。

由于 n_components 是一个超参数,它不从数据中学习。在运行 PCA( )功能之前,我们必须手动指定其值(调整超参数)。

n_components 选择最佳数量的背后没有什么神奇的规则。这取决于我们真正想从 PCA 得到什么。一些视觉检查和领域知识也可能有助于推断出 n_components 的正确值。

今天的文章专门讨论六种有效的方法,它们将帮助您为数据集选择最佳数量的主成分。

我们开始吧!

方法 1:如果你做 PCA 的唯一目的是为了数据可视化,你应该选择 2 或 3 个主成分。

PCA 对于数据可视化非常有用。通过主成分分析可以实现高维数据的可视化。

由于我们只熟悉 2D 和 3D 图,我们应该将高维数据转换成 2 维或 3 维数据,以便在 2D 或 3D 图上可视化。这可以通过 PCA 来实现。

对于 2D 图,我们需要选择 2 个主成分。

对于 3D 绘图,我们需要选择 3 个主成分。

在下图中,您可以看到 30 维乳腺癌数据的可视化示例。由于数据集包含 30 个变量,其维数为 30。我们无法在 30D 绘图中绘制 30 维数据,因为我们无法想象它是如何存在的。为此,我们将 PCA 应用于数据集,并选择 2 或 3 个主成分,这些主成分可以绘制在 2D 或 3D 图上。

使用 PCA 对高维数据进行可视化(图片由作者提供)

这些图大致代表了原始数据。这是因为当我们降低数据的维度时,我们丢失了原始数据中的一些方差。

方法 2:如果您希望在应用 PCA 后在数据中保留一个精确的方差,请为超参数 n_components 指定一个介于 0 和 1 之间的浮点数。

这是为数据集选择最佳数量的主成分的最简单方法。例如,如果您希望在应用 PCA 后保留原始数据中 85%的方差,您可以将浮点值 0.85 指定给超参数 n_components ,如下所示。

from sklearn.decomposition import PCA
pca = PCA(**n_components=0.85**)

然后,算法自动选择保持原始数据中 85%方差的最佳数量的主成分。如果您想知道算法选择了多少个组件,请运行以下代码行。

pca.n_components_

这将返回一个等于所选组件数量的整数值。

方法 3:绘制单个成分的解释方差百分比和所有主成分获得的总方差百分比。

这是最先进、最有效的方法,可用于为数据集选择最佳数量的主成分。

在此方法中,我们创建了以下类型的绘图。

主成分捕获的总方差的百分比(图片由作者提供)

条的数量等于原始数据集中变量的数量。在此图中,每个条形显示单个组件的解释差异百分比,而阶跃图显示累积的解释差异百分比。

通过查看该图,我们可以很容易地决定应该保留多少组件。在本例中,只有前两个分量捕获了数据集中几乎所有的方差。因此,我们决定只选择前两个组件。

要获取创建上述类型情节的 Python 代码,请参考我的《 主成分分析—十八问答 》文章第 15 题。

在 R 中,使用 factoextra 库中的 fviz_eig() 函数,只需运行一行代码,就可以创建类似类型的绘图!

fviz_eig(pca_model, addlabels = TRUE, linecolor = "Red", ylim = c(0, 50))

(图片由作者提供)

在这里,每个条形也显示了单个组件的解释差异百分比。红线是一种碎石图。

方法 4:创建碎石地块。

我们可以创建另一种类型的图来选择主成分的最佳数量,这就是 Scree 图,它是定义特征向量(主成分)大小的特征值的可视化表示。

一个小阴谋(图片由作者提供)

在 Scikit-learn PCA()类中,可以使用下面一行代码获得特征值。

pca.explained_variance_

为了创建上面的图,我们可以使用下面的代码块。

import matplotlib.pyplot as plt
plt.style.use("ggplot") plt.plot(pca.explained_variance_, marker='o')
plt.xlabel("Eigenvalue number")
plt.ylabel("Eigenvalue size")
plt.title("Scree Plot")

我们选择所有元件,直到在碎石图中发生弯曲的点。在上图中,弯曲发生在索引 1 处。因此,我们决定选择索引 0 和索引 1 处的组件(总共两个组件)。

方法五:遵循凯泽的法则。

根据 凯泽 法则,建议保留所有特征值大于 1 的分量。

使用 PCA()类的explained_variance_属性可以得到特征值。

然后,您可以选择特征值大于 1 的元件。当遵循此规则时,最好将其与方法 3 中讨论的解释方差百分比图或方法 4 中讨论的碎石图结合起来。有时,略小于 1 的特征值(例如 0.95)可能会捕捉到数据中的一些显著变化。因此,如果它在解释的方差百分比图中显示相对较高的柱线,最好也保留它。

方法 6:使用一个性能评估指标,例如 RMSE(用于回归)或准确度分数(用于分类)。

只有当您计划在应用 PCA 后对缩减(转换)的数据集执行回归或分类任务时,才能使用此方法。

通过使用方法 3 中讨论的图,您可以选择主成分的初始数量,并获得缩减的(变换的)数据集。然后,您构建一个回归或分类模型,并通过 RMSE 或准确度分数来衡量其性能。然后,您稍微改变主成分的数量,再次构建模型并测量其性能得分。重复这些步骤几次后,您可以选择实际上给出最佳性能分数的最佳数量的主成分。

请注意,模型的性能分数还取决于其他因素。例如,它取决于分裂训练测试集的随机状态、数据量、类别不平衡、模式中的树的数量(如果模型是随机森林或类似的变体)、我们在优化期间设置的迭代次数、数据中的异常值和缺失值等。所以,使用这种方法的时候一定要小心!

摘要

没有必要同时尝试所有这些方法。最有效的方法是使用方法 3 中创建的图。你也可以把德皇法则和那个情节结合起来。

很明显,主成分的最佳数目取决于我们真正想从主成分分析中得到什么。如果我们做 PCA 的唯一目的是为了数据可视化,那么组件的最佳数量是 2 或 3。如果我们真的想减少数据集的大小,最佳的主成分数要比原始数据集中的变量数少得多。

当将 PCA 应用于数据集时,一个黄金法则总是存在的。

选择最佳数量的主成分,同时尽可能保留原始数据中的方差。

如果您忽略了捕获数据中大量差异的关键组件,则在您对转换后的数据集执行回归、分类或其他可视化任务时,模型的性能得分将会降低。

应用 PCA 不是一次性的过程。这是一个反复的过程。您需要多次运行 PCA()函数。

首先,您必须用n_components=None运行 PCA()函数,这意味着我们暂时保留所有组件。

from sklearn.decomposition import PCA
pca_1 = PCA(**n_components=None**)

然后,我们创建方法 3 中讨论的图,并选择主成分的最佳数量(称为 k )。最后,我们用n_components=k再次运行 PCA()函数

pca_2 = PCA(**n_components=k**)

今天的文章到此结束。如果你对这篇文章有任何疑问,请在评论区告诉我。

感谢阅读!

下一篇文章再见!一如既往,祝大家学习愉快!

接下来阅读(推荐)——我写的!

了解主成分分析(PCA)的幕后工作原理。

https://rukshanpramoditha.medium.com/eigendecomposition-of-a-covariance-matrix-with-numpy-c953334c965d

一站式解决您关于 PCA 的大部分问题。

https://rukshanpramoditha.medium.com/principal-component-analysis-18-questions-answered-4abd72041ccd

主成分分析在降维中的应用。

整个 ML 都是降维及其应用。让我们看看他们的行动吧!

</11-different-uses-of-dimensionality-reduction-4325d62b4fa6>

了解参数和超参数之间的区别。

https://rukshanpramoditha.medium.com/parameters-vs-hyperparameters-what-is-the-difference-5f40e16e2e82

成为会员

如果你愿意的话,你可以注册成为会员,以获得我写的每一个故事的全部信息,我会收到你的一部分会员费。

https://rukshanpramoditha.medium.com/membership

订阅我的电子邮件列表

订阅我的电子邮件列表,再也不会错过精彩的故事了。我一点击发布按钮,你就会在收件箱里收到每一篇文章。

https://rukshanpramoditha.medium.com/subscribe

撰写人鲁克山·普拉莫蒂塔
2022–04–24

如何为不同的 A/B 指标选择正确的统计测试

原文:https://towardsdatascience.com/how-to-select-the-right-statistical-tests-for-different-a-b-metrics-c8a1865851e

讨论 5 种 A/B 指标的定位方法

TL;速度三角形定位法(dead reckoning)

本文将 A/B 测试评估指标总结为 5 个类别,并在下表中概述了建议的对其显著性值的统计测试。

按作者分类的表格

目录

  1. 我们为什么要在乎
  2. 用户平均指标
  3. 用户级转化指标
  4. 浏览量级转化指标
  5. 百分位数指标
  6. 总和指标
  7. 总结和实用提示

我们为什么要关心?

虽然 t-tests 非常强大,但是它们并不普遍适用于数据世界,因为数据世界中的业务指标分布与单一正态分布有很大不同。例如,每个用户发送的礼物数量和分享行为通常与严重的异常值有很大的偏差。这是因为用户行为不像统计规则那样有组织和客观,而是情绪化的,通常以极端行为为特征。

作为数据科学家,我们有责任,也是我们的价值所在,更深入地研究从统计学角度看具有科学意义的不同业务指标的适当测试方法。我们应该时刻提醒自己在进行 t 检验之前要检查抽样分布。

细节扩展

在这一主要段落中,我讨论了与 5 个度量类别中的每一个相对应的适当的测试方法。简而言之,决定使用哪种方法的两个关键方面是统计和实验角度。具体来说,我们想问自己两个问题:

  1. 抽样分布是否符合假设(如独立性、正态性等)。)的建议测试方法?
  2. 随机化单元是否与分析单元一致?

图片由 Towfiqu Barbhuiya 在 Unsplash 上拍摄

1.用户平均指标(例如,喜欢/用户、停留时间/用户等)

建议的测试 : Welch 的 T-Test,如果指标不是严重稀疏和偏斜的。否则,选择曼-惠特尼秩和 U 检验

什么是用户平均指标?

用户平均指标是根据独立用户的数量对总体业务绩效进行平均的指标,如实验期间每个用户的平均点赞数每个用户的平均停留时间。它们是 A/B 测试中经常使用的评估标准,这种控制组和实验组之间的数学期望或样本均值是否相同的比较也是最常见和最经典的统计测试场景之一。

如何测试用户平均指标

对样本均值统计量进行假设检验的方法通常是**双样本 t 检验。**简单地说,双样本 t 检验通过比较两个样本组之间的样本均值来确定两个总体中某个指标的期望均值是否相等。两个 假设以一种坦率但不太精确的方式是:

  • 每个样本观察值需要是独立的,并且遵循正态或准正态分布(i.i.d.): 独立分布假设通常得到满足,因为每个用户都可以被视为独立的个体*,并且实验的随机化单元通常是用户级的(大多数实验通过用户 id 来确定特定用户属于哪个实验组)。具有独立性,然后可以应用中心极限定理导出正态性,满足双样本 t 检验的这一假设。值得重申的是,尽管 CLT 下的 t-检验的稳健性被公认为 t-检验结果通常是有效的,即使总体分布在技术上不是正态的(准/渐近正态),这在现实世界的问题中是经常发生的,稳健性对于非中度偏离正态的分布是有界的 ( Bartlett,1935;Snijders,2011 年。如果基础分布严重偏斜、多模态或带有极端异常值的稀疏分布,它就变得不太可信。
    作为旁注,分位数-分位数(QQ)图,直方图,夏皮罗-维尔克检验,科尔莫戈罗夫-斯米尔诺夫(KS)检验是检验正态性的常用方法。
  • 两个总体中评估指标的方差可以是未知的,但它们需要是同质的:这不是一个严格的假设,因为我们可以使用韦尔奇的 t-检验,或不等方差 t-检验,来进行相等均值的假设检验。Welch 的 t 检验和 Student 的 t 检验在数学上的区别主要是关于自由度和样本方差估计。事实上,我们应该总是使用韦尔奇的 t 检验,而不是学生 t 检验。这不仅是一些学术文章(Delacre 等人,2017 年)所暗示的,也是科技公司的实验平台工程师根据我的经验提出的,因为从数据库中提取所有数据并断言方差相等可能会计算昂贵和耗时,这通常也是一个伪命题(在数百万和数十亿规模上计算方差可能非常繁重)。

Delacre 等人(2017 年)表明,当不满足方差齐性假设时,Welch 的t-检验对 1 型错误率提供了更好的控制,当假设满足时,与 Student 的t-检验相比,它几乎没有损失稳健性。因此,他们认为韦尔奇的 t 测试应该作为一种默认策略。

等式 1: t 统计量

对于那些高度偏斜的指标,针对两个独立组的非参数方法— Mann-Whitney 秩和 U 检验(MW 检验) —更为合适,因为它使用“等级”而非真实值来确定指标的差异是否显著,从而绕过了由极值引入的失真。此外,即使通过用等级替代绝对值来丢失信息,MW 测试的灵敏度(功效)也不会令人失望,因为当分布高度偏斜时,其他参数测试(如 t-test)做出真正积极推断的能力会有更大幅度的下降— VK 团队进行了模拟,并详细展示了这一想法。我强烈建议在这里 查阅他们的中型文章

然而,MW 测试的缺点是它是计算密集型的,因为它需要对完整的样本集进行排序来生成等级,所以在决定进行 MW 测试之前,应该考虑数据的大小。

2.用户级转换指标

建议的检验:比例 Z 检验

什么是用户级转化指标?

用户级转化是从二进制结果中得出的指标——该用户是否保留,该用户是否转化,等等。换句话说,所有用户将只有一个观察值,该观察值是 1 或 0 的标识符,这使得用户级别的转换度量基本上是二项式比例统计 (#转换的用户/#所有用户)。

如何测试用户级转化指标?

根据中心极限定理(CLT),我们可以使用正态分布安全地近似二项比例统计的分布。另一种思考方式是对二项式聚合进行比例分配非常类似于取平均值,其中当用户总数(人口规模)足够大时,CLT 可以有效地断言任何样本均值分布的正态性。因此,z-test 成为一个完美的候选。

等式 2:二项式比例

与上面讨论的用户平均度量相比,通常满足正态近似的假设,因为由于二进制伯努利事件的良好特性,底层采样分布是二项式的,而不是急剧偏斜的。此外,用户数量或人口规模通常非常大,以支持合理的近似值(根据经验,当 Np > 5* 和 N(1-p) > 5* 时,我们通常很有信心)。请参阅参考资料了解更多详细信息)。

值得注意的是,如果实验中的样本值不是独立同分布(i.i.d.) ,则中心极限定理不可信,z 检验不能应用。这在用户级度量场景中并不重要,因为在默认情况下,随机化单元是针对用户的,因此我们认为每个人的行为都是独立的。然而,当指标在比用户更精细的级别上聚合时,这种独立的假设可能不成立,例如下面第三节中的页面浏览量级别的转换指标。

等式 3: z 统计

3.页面视图级别的转换指标

建议检验:德尔塔法+ T 检验

有哪些浏览量级的转化指标?

一个常见的例子是点击率(CTR),定义为#点击事件/ #查看事件。

这里简单使用 t 检验有哪些问题?

在 A/B 实验中,分析浏览量级转换指标(如点击率)的统计意义通常很复杂。本质问题是的分析单位(即事件级别——点击事件和印象事件)不同于的随机化单位(即用户级别),这可能使我们的 t 检验无效并低估方差。

具体来说,当我们计算实验组和对照组之间 CTR 的 p 值时,我们实际上是聚合所有点击事件,并除以每组中所有用户的所有印象事件,然后对差异进行 t 检验。这个过程有一个固有的正态假设,即数据样本需要从正态分布中独立抽取。换句话说,由于每个样本观察都是一个视图事件,我们需要确保所有的视图事件都是独立的。否则,我们无法使用 CLT 来断言我们的均值统计的正态性。

然而,这种独立性假设被违反了。在我们按用户随机化的 A/B 实验中(这通常是默认选项,因为如果我们按会话随机化,每个用户都会有不一致的产品体验),一个用户可以有多次点击/查看事件,这些事件与我们的常识相关——我们最多可以断言每个人的行为是独立的,但现在和明天的行为不是时间序列相关的。因此,样本方差将不再是总体方差的无偏估计值——我们的平均统计量的真实样本方差可能会比我们的估计值高,因为共方差步骤在中,而我们在计算中遗漏了它。

因此,对于具有事件级粒度的度量,如果坚持传统的 t 检验方法,则不可避免地会低估方差。低估样本方差的直接后果是假阳性——真实且高的方差可能驱使样本均值偏离零假设,并且误导我们得出低 p 值,即使治疗无效

如何解决这个样本依赖问题?

有两种方法可以解决这个问题:(1)使用 delta 方法对差异进行 t 检验,或者(2)使用 bootstrapping 方法对经验方差进行 t 检验,这在< 可信在线控制实验:A/B 测试实用指南 >中也有强调

使随机化单元比分析单元更粗糙,如
由用户随机化并分析点击率(按页面),将会起作用,但需要更细致的分析方法,如 bootstrap 或 delta 方法(Deng 等人,2017 年;Deng,Knoblich 和 Lu,2018 年 Tang 等人,2010 年;Deng 等人,2011 年)。

  • Delta 方法 : Delta 方法通常被认为是更有效的方法。关键思想可以解释为将页面视图级别的 CTR 比率指标重写为两个“平均用户级别指标”的比率,并在该比率指标 *(使用泰勒展开和斯卢茨基定理)*上断言 CLT,以便我们可以将分析粒度从页面级别转换为用户级别,这现在与我们的分流单位(即用户)一致。这样,我们设法恢复了独立身份,因为我们的分子和分母都是独立身份样本的平均值。以 CTR 为例,AVG.clicksAVG.views在极限和独立同分布中共同为二元正态,使得两个平均值之比CTR也成为正态分布(Kohavi,r .,Tang,d .,& Xu,Y. (2020))。代码实现可以在 Ahmad Nur Aziz 的中帖这里找到。

等式 4:点击率(CTR)定义

等式 5:使用 Delta 方法的 t 统计量

  • Bootstrapping:Bootstrapping 是一种基于模拟的方法,根据经验计算样本均值统计的方差。其核心思想是从按用户 id 分层的每个组中的所有视图事件中重复抽取许多样本,然后从这些引导样本中计算许多平均统计量,并相应地估计这些统计量的方差。按用户 ID 分层可确保满足 ID . I . d .假设并且方差估计是可信的。

Stephen Phillips 在 Unsplash 上拍摄的图片

然而,自举在计算上是昂贵的,因为模拟基本上是对数百亿用户日志进行多次迭代操作和聚合(复杂度~ O(nB)其中 n 是样本大小,B 是自举迭代次数)。因此,尽管它很灵活,但它通常不是科技公司的首选,而是更多地被用作关键决策的防弹双重检查基准。

4.百分位度量

建议测试:中心极限定理(CLT) + Z 测试

什么是百分位度量?

分位数指标,比如 95%的页面加载时间,对于 A/B 测试来说是至关重要的,因为许多业务方面都以边缘案例为特征,因此可以更好地用分位数指标来描述。

测试百分位指标的挑战是什么?

大多数百分比指标,例如 95%的页面加载延迟,是在页面查看粒度中定义的工程性能指标。因此,随机化单元(用户)不会与分析单元(页面浏览量)相匹配,这使得独立性假设和使用简单样本方差的总体方差估计无效。

如何测试百分制指标?

  • **Bootstrapping:**Bootstrapping 作为一种“普遍适用”的工具,在这里可以用来估计经验方差和对百分位度量的样本均值进行 t 检验。尽管如此,它的计算仍然非常昂贵,因此不能很好地扩展。
  • **CLT+比例 Z 检验:**场景背后有相当多的数学,但我会尝试用简单的术语来展示主要观点(如果感兴趣,强烈推荐阅读亚历克斯邓(2021) )。首先,我们将首先探讨分位数度量的分布,统计学家已经证明样本百分位数是近似正态的:

等式 6:95%度量的渐近正态性的说明。

σ 是指一个数据点是否小于第 95 百分位的标准差(不能用‘传统’伯努利方式估计,因为这里的观测值是相依的)。 F 为底层数据的未知概率密度函数。

太好了!由于分位数遵循正态分布,我们可以使用 Z 检验来计算 p 值。嗯,这通常是我们要去的方向,但有一个关键的障碍——σ以及概率密度函数 F 是未知的,可能难以估计。

所以我们现在的目标是得到一个好的方差估计值(用红色圈起来的)。业内采用的方法不止一种。LinkedIn、Quora 和 Wish 的数据科学家直接估计这个密度函数,而微软和则参考了由 Alex Deng、Knoblich 和 Lu(【2018)引入的一个新想法,该想法绕过了对密度函数 F 的估计。相反,他们首先通过调查小于百分位数的观察值的二项式比例的分布来估计真实百分位数的置信区间,如等式 7 所示:

等式 7:95%度量的置信区间

其次,他们基于近似置信区间的长度反向推导方差估计。

等式 8:从置信区间得出标准偏差

最后,通过方差估计,我们可以继续计算样本百分位的 z 统计量和相应的 p 值,类似于那些平均度量。

5.合计指标(不推荐)

建议的测试:模拟

什么是和度量?

总和指标指的是实验组和对照组的合计指标,包括文章阅读次数的总数、总 GMV、发布的总视频等。

这里有哪些挑战?

总和指标通常是产品开发的北极星指标,但由于缺乏统计有效性和混淆误差,可能很难测试。具体来说,在实验组和对照组中,SUM 指标可以分解为用户平均指标用户计数**,这意味着 SUM 指标不仅受实际业务波动(用户平均指标)的影响,还受流量分流引入的不可避免的随机误差的影响。:**

等式 9:解开总和度量

虽然用户平均指标遵循(准)正态分布,而流量分流遵循 p = 0.5 的二项式分布,但经典统计没有关于两者乘积分布的完整研究。

应该如何测试用户平均指标?

我们可以用模拟来处理这个问题。由于这两种分布是确定的和独立的,我们可以通过迭代抽取样本来获得它们自己的概率密度函数(PDF)。然后,如果将两个 PDF 相乘,我们可以得到总和度量的经验 PDF。因此,可以通过研究我们在治疗组中实际看到的总和统计如何符合我们的模拟分布来计算 p 值。

这是一个相对令人生畏的过程,有相当数量的近似值。所以通常不推荐。我建议使用用户平均指标测试产品特性的有效性/统计显著性,如果管理层真的关心的话,计算总和指标的增量提升。

总结和实用技巧

图片由 Diego PH 在 Unsplash 上拍摄

关于正确统计检验的问题本质上是问,给定实验和控制组数据,哪个检验具有最大的敏感性或统计功效**。**

这种能力与我们指标的基本分布和样本的独立性密切相关。因此,在继续分析之前,检查分布偏斜度仔细考虑假设始终是一个好的做法。

以下是根据我的个人经验和我从参考资料中学到的三个技巧:

  1. 当数据有偏差时,t 检验不那么稳健,曼-惠特尼检验也不那么弱。
  2. 考虑转换指标(如对数转换)以减轻偏斜,甚至用更正态分布的指标来代替。
  3. 如果你不想弄乱令人生畏的统计数据,另一种方法是尝试方差减少技术,如 CUPED。毕竟,我们的目的是获得高功效和值得信赖的显著性推论。

注意:

  1. 所有的方程式都是作者手工编码的。
  2. *每个用户都是独立的个体:假设没有网络效应。以下引用自 Alex Deng (2021) 的文章很好地解释了 A/B 测试场景中独立性假设的思想:

在在线实验中,用户通常被视为自主的基本单位,因此通常被用作随机化单位……一般的经验法则是,我们总是可以将随机化单位视为独立身份。我们将此命名为随机化单位原则 (RUP)。例如,当一个实验按用户、页面浏览量( S. Deng 等人,2011 )、cookie 日(【唐】等人,2010 )或会话/访问进行随机分组时,建议,合理的做法是假设这些级别上的观察值分别为独立同分布。之前没有公开发表的工作明确提到。但是它被社区广泛用于 A/B 测试的分析

参考

  • 阿齐兹·阿恩(2021)。Delta 方法在 A/B 测试分析中的应用。https://medium . com/@ ahmadnuaziz 3/applying-delta-method-for-a-b-tests-analysis-8b1d 13411 c 22
  • 巴特利特,硕士(1935 年 4 月)。非正态性对 t 分布的影响。在剑桥哲学学会的数学会议录(第 31 卷第 2 期,第 223-231 页)。剑桥大学出版社。
  • 邓,a .,Knoblich,u .,,陆,J. (2018)。在度量分析中应用 Delta 方法:具有新颖思想的实用指南。在第 24 届 ACM SIGKDD 知识发现国际会议论文集&数据挖掘(第 233–242 页)。
  • 邓(2021)。8.6 百分位度量的置信区间和方差估计。因果推理及其在网络产业中的应用。https://alexdeng.github.io/causal/abstats.html#indvar
  • 德拉克雷,m .,拉肯斯,d .,和莱斯,C. (2017)。为什么心理学家应该默认使用韦尔奇的 t 检验而不是学生的 t 检验。《国际社会心理学评论》30 (1)。
  • 李庆国(2021)。如何希望 A/B 测试百分位数。https://towards data science . com/how-wish-a-b-tests-percentiles-35ee 3e 4589 e 7
  • 刘,硕士,孙,x,瓦什尼,硕士,徐,杨(2019)。分位数度量的大规模在线实验。 arXiv 预印本 arXiv:1903.08762
  • 柯哈维,r .,唐,d .,,徐,Y. (2020)。可信的在线控制实验:A/B 测试实用指南。在可信的在线控制实验:A/B 测试实用指南 (p. I)。剑桥:剑桥大学出版社。
  • 斯尼德斯(2011 年)。统计方法:稳健性。摘自【http://www.stats.ox.ac.uk/统计方法】MT2011 Snijders
  • VK 队。(2020).统计检验从业者指南。https://vk team . medium . com/practices-guide-to-statistical-tests-ed2d 580 ef 04 f # 9e 58
  • 邢,T 和崇,k . z(2018)。百分位数差异的双样本假设检验。https://quoradata . quora . com/双样本假设检验百分位数差异

如何自学数据科学

原文:https://towardsdatascience.com/how-to-self-learn-data-science-in-2022-a537a76d138e

基于项目的数据科学入门方法

数据科学学习备忘单(原始图片来自我的网站

作为一个没有数据科学学位的人,我对这个领域充满热情,并决定尝试建立自己的课程,在业余时间学习数据科学。想分享一下自己的经历,希望能给想同路的你带来一些感悟。

基于项目的学习是一个很好的起点,适合已经有一些技术背景,但还想更深入地研究数据科学的构建模块的人。典型的数据科学/机器学习项目包含生命周期——从定义目标、数据预处理、探索性数据分析、特征工程、模型实现到模型评估。每个阶段需要不同的技能组合,包括统计、编程、SQL、数据可视化、数学和商业知识。

我强烈推荐 Kaggle 作为试验您的数据科学项目的平台,以及 Medium 作为从专业人士那里获得数据科学知识的平台。有了大量有趣的数据集和基于云的编程环境,你可以很容易地从 Kaggle 免费获得数据源、代码和笔记本。而来自 Medium 的几个流行的数据科学出版物(例如forward Data Science、 Analytics Vidhya )允许您在同一个地方学习他人的工作并分享您自己的项目。如果你想阅读更多来自 Medium 的文章并支持我的工作,我真的很感谢你注册使用这个附属链接。

为什么选择基于项目的方法?

  1. 这是实际的,给我们一种成就感,我们正在做一些真实的事情!
  2. 它强调了学习每一部分内容的基本原理。面向目标的方法提供了一个鸟瞰图,展示了每个小部分是如何结合在一起形成大图的。
  3. 它允许我们在学习时主动检索信息。主动回忆与只需要被动消耗知识的传统学习机制相比,被证明能显著增强信息保持。

让我们将数据科学生命周期分解为以下 5 个步骤,我们将了解每个步骤如何与各种知识领域相联系。

1.业务问题和数据科学解决方案

数据科学项目的第一步是确定业务问题,并定义实验设计或模型部署的目标。

技能组合——商业知识

在这个阶段,还不需要技术技能,但需要业务理解来识别问题和定义目标。首先理解数据集中出现的领域特定术语,然后将业务需求转化为技术解决方案。积累知识需要多年的实地经验。这里我只能推荐一些增加你对某些商业领域曝光率的网站,比如哈佛商业评论、 Hubspot 、 Investopedia 、 TechCrunch 。

技能集—统计学(实验设计)

在定义了问题之后,接下来就是把它框架成一个数据科学的解决方案。这从实验设计中的知识开始,例如:

  • 假设检验
  • 力量分析
  • 采样
  • 偏差/方差
  • 不同类型的错误
  • 过拟合/欠拟合

查看我关于假设检验的文章:

有各种类型的假设检验可供探讨——T 检验、方差分析、 卡方检验……。机器学习基本上被认为是一个假设测试过程,我们需要在假设空间中搜索最适合我们观察到的数据的模型,并允许我们对未观察到的数据进行预测。

有用资源:

  • 可汗学院:研究设计
  • 统计假设检验简介

2.数据提取和数据预处理

第二步是从各种来源收集数据,并将原始数据转换成可理解的格式。

技能集— SQL

SQL 是一种功能强大的语言,用于与结构化数据库通信并从中提取数据。学习 SQL 还有助于构建一个心智模型,帮助你通过数据查询技术获得洞察力,例如 分组、过滤、排序和连接 。你也会发现类似的逻辑出现在其他语言中,比如熊猫和 SAS。

有用资源:

  • “SQL 连接入门”
  • 数据营:SQL 基础知识
  • Dataquest: SQL 基础知识

技能组合—蟒蛇(熊猫)

学习数据科学时,熟悉编程语言是非常重要的。简单的语法使 Python 成为一种相对容易开始的语言。如果你是 Python 新手,这里有一个很棒的视频教程: Python 初学者——1 小时学会 Python。

有了基本的了解之后,花点时间学习熊猫库还是值得的。熊猫如果使用 python 进行数据提取,几乎是不可避免的。它将数据库转换成数据帧——一种我们最熟悉的类似表格的格式。 Pandas 在数据预处理中也起着重要的作用,当需要检查和处理以下数据质量问题时。

  • 解决缺失数据
  • 转换不一致的数据类型
  • 删除重复的值

有用资源:

  • Python 熊猫教程:初学者完全入门
  • W3schools:熊猫教程

3.数据探索和特征工程

第三步是数据探索,也称为 EDA(探索性数据分析),揭示数据集中隐藏的特征和模式。它通常通过数据可视化来实现,然后通过特征工程根据数据探索的结果来转换数据。

技能集—统计(描述性统计)

数据探索使用描述性统计来总结数据集的特征:

  • 平均值、中间值、众数
  • 范围、方差、标准差
  • 相关性、协方差
  • 偏斜度,分布

在对数据集特征有了坚实的理解之后,我们需要相应地应用最合适的特征工程技术。例如,对右偏数据使用对数变换,并使用裁剪方法来处理异常值。这里我列出了一些常见的特征工程技术:

  • 分类编码
  • 缩放比例
  • 对数变换
  • 归罪
  • 特征选择

有用资源:

  • 3 种常见的数据转换技术
  • 机器学习的特征工程基础技术
  • 机器学习中的特征选择和 EDA

技能集—数据可视化

将统计和数据可视化结合起来,可以让我们通过适当的可视化表示来理解数据。您是否喜欢使用可视化包,如 Python 中的 seabornmatplotlib 和 R 中的gg plot 2;或者像 Tableau 和 PowerBI 这样的可视化工具,区分常见图表类型的用例是很重要的:

  • 条形图
  • 柱状图
  • 箱形图
  • 热图
  • 散点图
  • 折线图

如果感兴趣,请查看我关于 EDA 和数据可视化的文章:

https://medium.com/analytics-vidhya/3-ux-design-principles-for-better-data-visualization-70548630ff28

4.模型实现

在迄今为止的所有准备工作之后,终于到了深入研究机器学习算法的时候了。

技能集——机器学习

scikit-learn 是一个强大的 Python 库,可以让初学者轻松入门机器学习。它提供了大量的内置包,我们可以使用几行代码轻松实现一个模型。虽然它已经为我们做了艰苦的工作,但理解算法如何在幕后运行并能够区分每种算法的最佳用例仍然至关重要。通常,机器学习算法分为监督学习和非监督学习。

监督学习可以进一步分为分类和回归算法,查看我关于一些流行算法的文章。

下面是常用算法的快速总结:

监督学习:

  • 线性回归
  • 逻辑回归
  • 神经网络
  • 决策树
  • 支持向量机

无监督学习:

  • 聚类
  • 主成分分析
  • 降维

我为一些机器学习算法创建了实用指南。如果你有兴趣,请查看我的列表。

Destin Gong

德斯坦贡

机器学习实用指南

View list10 storiesPrincipal Component Analysis for MLTime Series Analysisdeep learning cheatsheet for beginner

有用资源:

  • scikit-learn 网站
  • 我策划的机器学习笔记本
  • Coursera:用 Python 进行机器学习

技能组合—数学

包括我在内的许多初学者可能会问,为什么我们需要在数据科学中学习数学。

作为初学者,数学知识主要帮助理解算法背后的基本理论。展望未来,当我们不再依赖内置的机器学习模型库时,它允许我们开发和优化定制的算法。此外,超参数调整还需要高级数学知识来搜索最小化成本函数的最佳模型。

这是更复杂的数学问题出现的时候:

  • 结石
  • 线性代数
  • 优化问题
  • 梯度下降
  • 搜索算法

有用资源:

  • 3Blue1Brown:线性代数的本质
  • 3Blue1Brown:微积分的精髓
  • 3 蓝色 1 棕色:渐变下降

5.模型评估

技能集—统计学(推理统计学)

在进行模型预测和评估模型性能时,推断统计特别有用。与描述性统计相反,推断性统计侧重于将样本数据中观察到的模式推广到更广泛的人群。它提供了哪些特征在做出推断时具有高度重要性的证据。此外,它还根据评估指标确定模型性能。

例如,对于输出为离散类别的分类问题,一些常见的度量是:

  • 混淆矩阵
  • 第一类错误/第二类错误
  • 准确(性)
  • ROC / AUC

然而,对于输出为连续数字的回归问题,一些常见的度量标准是:

  • r 的平方
  • 均方根误差(RMSE)、平均绝对误差(MAE)、均方误差(MSE)

有用资源

  • 可汗学院:统计与概率
  • 评估你的机器学习算法的指标

带回家的信息

这是一个通用指南,记录了我的学习历程,所以我希望这可以帮助一些对数据科学充满热情并愿意利用业余时间探索这一领域的初学者。我在文章中提到的大多数主题都是表层的,允许你根据自己的喜好选择一个领域进行深入研究。如果你觉得这很有帮助,并且想阅读更多类似的文章,请注册中级会员以示支持。

更多这样的文章

Destin Gong

德斯坦贡

开始学习数据科学

View list8 storiesStatistical Tests in PythonDestin Gong

德斯坦贡

EDA 和特征工程技术

View list9 stories

原载于 2022 年 1 月 30 日【https://www.visual-design.net】

如何自学数据科学所需的所有技术知识

原文:https://towardsdatascience.com/how-to-self-study-all-the-technical-stuff-you-need-for-data-science-62e4b8b8152f

意见

掌握 Python、SQL、统计等的 5 个步骤。

安德鲁·乔治在 Unsplash 上的照片

从来没有这么多免费的在线资源来学习数据科学所需的所有技术知识。

你想学 Python 吗?Youtube 上有成千上万的教程。
要不要练 SQL?可以 google SQL 习题与解答
想学统计学吗?可汗学院有你需要的大多数数据科学讲座

但是当涉及到我们自己学习所有这些的时候,事情就有点复杂了。你可能想知道从哪里开始,如何少学多学,如何保留更多的信息,如何在学习时达到最佳表现,如何持续进步。

在本文中,我将向您展示我学习数据科学所需的技术材料时遵循的 5 个步骤。

如果你不想看,你可以看我的视频!

请务必点击 订阅此处 获取我在所有教程中使用的 Python for Data Science 备忘单(免费 PDF)

第一步:从哪里开始?建立自己的课程

除非你是昨天才出生的,否则你已经有一些数据科学的前期知识(不管你的背景如何)。你可能已经知道一些数学和统计学,或者以前使用过 Excel 或 Python,所以你需要建立一个最适合你需要的课程。

在线课程的课程很好,但是他们对你知之甚少。这就是为什么你必须从中挑选几个并定制你的学习。你自己的课程将帮助你专注于你的弱点,跳过那些你已经擅长的话题。

记得我参加的第一批数据科学课程中,有一门是 Excel 讲座。我天真地认为有“数据科学的特殊 Excel 课程”,所以我浪费了 3 个小时学习我在大学(甚至学校)已经学过的东西!).

不要犯同样的错误。创建你自己的课程,如果可能的话,创建一个路线图,让你知道你现在在哪里,以及 1 个月、3 个月和 6 个月后你想知道什么。

记住,记录你的进步将有助于你在到达平台期时保持动力。

注意:Python、SQL 和机器学习等技术材料的应用超出了数据科学的范畴,因此请确保您基于众所周知的数据科学课程构建自己的课程。在这里你可以找到一些课程,如果我必须重新开始,我会选这些课程。

第二步:安排任务(少学多学)

当涉及到获取技术技能时,你必须非常小心地对待时间!

我数不清我浪费了多少时间来解决一个对我的学习没有什么影响的问题(比如一个打字错误引起的愚蠢错误!).像这样的事情经常发生,所以你必须通过坚持时间表来很好地记录你的时间。

如果你花 2 个小时学习一个新的 Python 库,那么不管你的一天过得是好是坏,你都会花 2 个小时去编写 Python 代码,然后继续前进。

有一个时间表可以帮助你建立你需要学习的纪律,不仅仅是一件事,而是很多事情。我们并不总是能够控制我们在工具 A 上取得了多大的进步,但是我们可以确保如果我们的学习变得缓慢,它不会影响我们在工具 b 上的进步。

怎么会?坚持我们的时间表!

一致性在学习过程中至关重要。每周一学习 7 小时和周一到周日学习 1 小时是不一样的。第一个会让你精疲力尽,但是第二个会给你持续不断的练习来学习新东西。

第三步:学习最基本的东西,开始解决项目

当学习新的东西时,我们有时想更深入地理解事物为什么会这样。虽然这并不坏,但当你想学习像编程语言这样的技术东西时,你需要学习最基本的东西,并把你刚刚学到的东西付诸实践。

此外,在转移到新的话题之前,获得一些实践经验。不断学习新事物是很酷的,但是,首先,我们必须在以前的主题上建立一个坚实的基础。

怎么会?解题练习和项目!

假设你正在学习如何使用 Python 中的熊猫。你应该选择其中的一些,开始解决一个小项目,而不是去记忆熊猫拥有的数百种方法。这里有一些想法。

Pandas 清理数据的方法
Pandas 进行数据可视化的方法
Pandas 收集数据的方法

使用这些方法来解决有意义的任务会帮助你容易地记住它们的功能。

最后但同样重要的是,确保你重复这个学习/解决的过程,直到你掌握了一个新的主题(这是你的for循环!)

第四步:养成良好的习惯,达到你的最佳表现

这是一个重要但被低估的观点。习惯可以促进你的学习,也可以减缓你的学习。

不良的饮食习惯会让你感觉很虚弱,以至于学习时无法集中注意力。它还会时不时地停止你的工作流程,或者迫使你在事情变得严重时去看医生。

不管你看的教程有多有趣,不良的睡眠习惯都会让你闭上眼睛。

相比之下,好习惯会帮助你达到最佳表现,成为更好的学习者。

像每次学习时打开免打扰模式这样的小习惯会帮助你避免分心,整理办公桌和电脑的习惯会帮助你优化工作流程并提高生产率,这就引出了下一点。

注意:要找到一大串能让你成为更好的数据科学家的习惯,请查看我的文章这里和这里。在那里你会找到提升你的技术、软技能和生活的习惯。

第五步:遵循 20 秒规则,持续进步

这是我多年前从 YouTubeThomas Frank那里学到的技巧。这是基于一种叫做“活化能”的技术,在《快乐的优势》一书中有解释。

在视频中,托马斯解释说,活化能指的是开始做某事的时间、能量或意志力。一项活动需要的激活能量越多,你需要的意志力就越强(这解释了为什么在手机上玩游戏比开始做运动更容易)

20 秒规则在于降低这种激活能量,对于那些我们计划持续做的任务。要做到这一点,我们必须从战略上改变我们的环境,使艰苦的活动走上阻力最小的道路。

假设你的自习室里堆满了食物和电子游戏。下次你回到房间,你很可能会吃点东西,抓起你的控制器,开始玩电子游戏,而不是学习。

为什么?这样的活动比学习需要更少的活化能。

但是如果你藏起你的控制器,只留下你学习需要的东西,你会增加玩电子游戏的激活能量,减少学习的激活能量。

我将这一技术提升到了一个新的水平,只在主屏幕上留下有用的应用程序(iBooks、audible、concept、fitness+等),并将分散注意力的应用程序(社交媒体和游戏)隐藏在最后一页的文件夹中。

结果呢?每次我解锁手机时,我都记得我需要阅读书籍、查看笔记和进行体育锻炼。

额外收获:有足够的休息时间——这里是最好的主意的来源

有时,我们过于逼迫自己,忘记了休息可以帮助我们提高学习。

我最好的想法是在散步、休息或淋浴时产生的。甚至埃隆·马斯克也将冷水淋浴(他的日常习惯之一)归功于许多想法的来源。

我还发现,每当我有一个新的想法,我就能把我所学到的点点滴滴联系起来。也就是说,找到主题 A 和主题 B 之间的联系,并能够将它们放在一起,比如说,放在一个项目中。

休息很重要,所以要经常休息。

加入我的电子邮件列表,与 10k 以上的人一起获取我在所有教程中使用的 Python for Data Science 备忘单(免费 PDF)

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。

https://frank-andrade.medium.com/membership

如何为您的数据团队设置 KPI

原文:https://towardsdatascience.com/how-to-set-kpis-for-your-data-team-e41c62b88c78

或者,定义数据领导者的成功

图片由作者提供。

作为分析专家,我们处理数据:在一分钟内提供临时报告,为高管提供查询,并通过各种指标预测公司业绩。 但是,如果我们不衡量自己的表现,我们又怎么能真正成功呢?

在本文中,我们讨论了为我们自己的数据团队设定目标的六个重要步骤,从花时间探索到避免虚荣心统计,同时保持对业务实际需求的持续把握。

最近,在续集节目中,我与 Census 的首席执行官兼联合创始人鲍里斯·贾伯斯进行了一次很好的交谈。我们触及了各种与数据相关的话题,从为什么数据宕机会发生在集中式与分散式数据团队身上,到不丹王国如何像大多数国家衡量 GDP 一样衡量公民幸福。但是当我们的谈话迂回到数据 KPI(关键绩效指标)时,事情变得非常有趣。

当我分享了我最喜欢的一句德怀特·戴维·艾森豪威尔的名言时,我和 Boris 开始进入 KPI-land:“计划毫无价值,但计划就是一切。”

我们都看到艾克的智慧在许多公司得到了证实。即使你想出的计划会(也应该)改变,计划本身就有价值。

数据领导者和 KPI 也是如此。您应该制定度量标准来衡量您的绩效,因为协调团队、定义成功以及围绕共同目标团结一致的过程会产生巨大的影响。纠结于理想的目标或衡量策略不是重点——实际上会阻碍有意义的进步。重要的是开始以一种正式的方式处理数据,朝着一个具体的目标前进。

考虑到这一背景,我们回顾了帮助数据主管设定有用目标和衡量绩效的六个步骤。

了解你的客户真正想要什么和需要什么

当您着手确定您的数据团队的目标是什么(以及您将如何实现这些目标)时,首先要了解您的客户想要什么和需要什么。在蒙特卡洛,我们的北极星是“我们的客户关心什么,我们如何尽快解决这个问题?”回答这些问题需要跨团队合作。

例如,如果您同意工程、产品和营销部门的观点,即入职是一个棘手问题,您可以决定围绕使新客户更容易开始工作来建立目标和 KPI。虽然您可以选择花几年的时间来构建一个全新的流程,但是通过做一些小的改进,您将会看到更多立竿见影的效果,当您从客户那里得到反馈时,您可以对这些改进进行测试和迭代。

例如,通过让公司围绕将新工具入职时间从五天减少到三天的共同目标保持一致,您可以开始整体解决问题:您的数据团队收集使用指标并帮助构建 A/B 测试,而您的工程团队修改产品,您的营销团队创建培育活动。这就是定义和执行全公司目标的样子。

只需确保您围绕一个具体的指标进行调整,该指标对业务来说具有切实的意义。跳过虚荣指标,看看与结果相关的数字,如年度经常性收入、客户流失、财务表现或其他具体和可衡量的东西。

对于蒙特卡洛而言,每个团队都以与客户满意度密切相关的指标为导向,如收入、NPS 和客户满意度。通过将客户满意度置于我们 KPI 的中心,我们让每个团队都朝着一个共同的目标努力,这就是设定目标的全部意义。

制定一个计划,但是要经常重温它

虽然你的目标很重要,但请记住艾克的话:计划就是一切。规划过程是至关重要的,因为它迫使你的团队和主管进行场景规划。你不可能完成愿望清单上的所有事情,尤其是在初创公司,所以规划迫使我们讨论优先顺序,从而实现招聘和资源配置的关键目标。

对于一个数据团队来说,这样的例子可能是每个季度设置三个 okr,这将真正推动与您公司的底线保持一致的指针。就像 Airbnb 或 Shopify 这样的科技公司一样,OKR 可能是一些雄心勃勃的事情,比如推出一个实验平台,或者为内部数据平台推出一个新的自助服务功能。较小的公司或初创公司可能更有可能围绕提高组织成熟度(可以通过多少消费者利用您的仪表板来衡量)或更准确的报告来调整这些里程碑。无论如何,重要的是关注对利益相关者真正重要的东西,而不是像新报告或模型的数量这样的虚荣指标。

注意:很容易在计划上花费太多时间。建 OKRs 不需要拿 A+。在创业方面,我们需要获得 A+。

所以把你的主要目标放在最前面,通过经常修改你的计划来保持灵活性。你可能不知道什么是正确的指标,你可能会低于或超过你的 KPI,但在整个过程中团结起来学习的行为是非常有价值的。如果你尝试的第一个指标不能完成工作,给自己重新定位团队的自由,找到一条新的途径来实现你的目标。

根据您的业务目标确定 KPI 的优先级

如果这不是你当前业务的正确目标,那么它就不是正确的 KPI。

我在各种规模的组织中看到,人们可以浪费时间来制定非常详细的 OKR 计划,无论如何,这些计划都必须改变。团队可能会沉迷于系统而不是目标。例如,一些工程师可能会痴迷于创建可以扩展到数百万用户的漂亮代码,但如果他们的公司只有数百名用户,那就不会产生影响。

例如,如果你的 KPI 专注于为整个公司建立一个实验平台,但是只有几个团队在下个季度需要它,保持它的小规模和针对性。这意味着纳入他们的反馈,而不是试图通过解决尚不存在的用例来煮沸海洋。第二个例子可能是为某些数据集(即与客户参与或财务健康相关的数据集)设置和衡量 SLA,而不是在所有数据中推广它们。

给你的团队必要的工具,让他们无情地优先考虑他们的工作。Boris 和我都见过年轻的数据团队,他们还没有支持优先级排序的票务系统或接收流程,而这对于实现任何目标都是至关重要的。因此,实施一种结构,围绕你需要你的团队关注和解决的最重要的问题,创造一种紧迫感。

设定基于解决问题的目标,而不是采用新技术

同样,数据团队可能会过于关注基础设施和工具,因为我们的行业发展如此之快,工具每天都在改进。但是,如果你的团队采用新工具的愿望不是植根于解决一个有意义的业务问题,那么你可能会有“闪亮新玩具”综合症的风险。

我经常看到一些最优秀的公司的团队迷失在为构建数据平台而构建数据平台的兴奋中,或者选择从事他们认为会给 CTO 留下深刻印象的项目,而不是解决真正的业务问题。如果你想把你的数据团队转移到 Kubernetes,仅仅是因为它在 Reddit 上流行,我会鼓励你重新评估。同样,从零开始构建工具,而不是投资于现有的开源或 SaaS 选项。如果你的用例与绝大多数公司相似,那么重新发明轮子可能就没有意义了。

特别是如果您的数据团队比组织内的其他团队更新,更不成熟(这在目前是非常常见的),请注意将重点放在为业务交付明确价值的目标上。要明白一个两三个人的小团队只能完成这么多,考虑一下你的公司需要你回答什么样的问题。

如果您仍在从事基础工作,如…

  • 我们有多少顾客?
  • 我们每年的经常性收入是多少?
  • 我们的流失率是多少?

…那么现在就不是关注设置高级、复杂的数据基础架构的时候。现在是时候传递你的公司需要的基本信息了。

花时间探索自由形式

虽然您希望调整 KPI,并与其他团队朝着共同的目标努力,但事实是,有时业务的其他部分不知道该向您的数据组织提出什么要求。这就是为什么你需要给你的团队时间去探索。

可以这样想:所有的人类都需要时间来放松和玩耍,以最有效地处理信息。这就是为什么你总是在洗澡的时候想出最好的主意。

同样,如果给你的团队成员时间来研究数据,他们会得出令人兴奋的新结论。他们可以应用他们的才能去寻找没有人要求的模式,并且有空间去发现新的发现。这种自由探索可以带来改变游戏规则的创新,这是任何商业利益相关者都无法想象的。

不管是好是坏,数据分析工作流中促进这一点的一个元素是即席分析,这是许多数据工程师或分析师存在的祸根。在清晨或深夜收到关于查询数据集的紧急 pings 通常不是好时机的定义,但有时这些意想不到的项目(特别是如果它们与企业的一个更大的 KPI 相关联)可以获得查询输出之外的好处。没有这些即兴的请求,就很难知道对你的利益相关者来说什么是最紧迫的,特别是当计划改变的时候。注意:这些特别的任务不会取代常规的计划和利益相关者的同步,但是它们可以在以前没有的地方激发创造力和探索。

另外,freeform exploration 让充满激情的数据专家有机会在他们热爱的工作中找到更多乐趣,这有助于让您最有价值的团队成员参与进来,并对他们的工作感到满意。

实现有效的知识转移

在蒙特卡洛,我们经常谈论从工程同行那里学习和应用最佳实践。这就是我们对数据可观察性的灵感来源,也是我们应该学习改进知识转移实践的地方。

知识传授是工程师工作的一部分。在构建一个产品之后,工程师必须将维护代码和解决 bug 的责任交给其他开发人员。如果他们坚持保留代码的所有权,他们会把所有的时间都花在维护和错误修复上,而不会构建任何新的东西或承担新的角色。因此,他们围绕文档开发了最佳实践,比如留下一个注释,描述问题何时出现以及如何解决。

对于数据专业人员来说,同样的原则也适用,但新团队可能缺乏工程师已经证明的最佳实践,如票务系统和文档。为了帮助您的数据团队实现他们的 KPI,并避免由于知识转移不良而导致的生产力损失,请开始将这些工具和系统设置到位。

一个流行的知识共享工具?名副其实的知识图。知识图是 SaaS 数据解决方案经常利用的一种范式,它自动将数据表示为图中的节点,通过逻辑和元数据绘制连接。基于知识图的工具,如 lineage,在快速生成关于组织内数据之间的关系的文档时,通常可以自动帮助数据团队节省时间和资源。

虽然在一个小型数据团队中,移交工作可能会非常痛苦,但是跨部门的沟通确实具有挑战性。将服务级别协议(SLA)和服务级别指标(sli)正式化,并将团队之间的隐式和显式合同放在一起,可以帮助每个人在实现目标的过程中保持优先级一致。

您的 SLIs 将取决于您的具体用例,但这里有一些用于衡量数据信任的指标,一个常见的 KPI:

  • 特定数据资产的数据事件数量(N) 。尽管这可能超出了您的控制范围,但考虑到您可能依赖外部数据源,它仍然是数据停机的重要驱动因素,并且通常值得衡量。
  • 检测时间(TTD) :当一个问题出现时,这个指标量化了您的团队被警告的速度。如果您没有适当的检测和警报方法,这可能需要几周甚至几个月的时间。由不良数据造成的“无声错误”会导致代价高昂的决策,对您的公司和客户都有影响。
  • 解决问题的时间(TTR) :当您的团队收到一个问题的警报时,这将衡量您解决问题的速度。

跟踪数据事件数量的仪表板可以帮助您随着时间的推移提高数据可靠性。图片由作者提供。

如果您想更进一步,请尝试为这些指标生成一个数据 KPI 仪表板。

一句话:从数据 KPI 开始学习

数据团队可以使用 KPI 来制定策略和实现目标,但最终,最重要的一步是开始。

你的衡量标准永远不会一成不变。当一些目标在浪费你的时间时,做好快速学习的准备,然后更快地前进。如果你从与其他部门合作开始,并围绕一个共同的目标调整自己的团队,你会看到一个影响,特别是如果你是像我一样的竞争性数据领导者,喜欢将团队聚集在一起以尽快打破我们的数字。

当您开始关注重要的业务目标时,您会发现创建可重复的流程、自动化机械任务以及摆脱被动响应数据消防演习会带来更多价值。

想了解更多关于组建数据团队以取得成功的信息吗?从 PagerDuty、优步和其他数据第一公司的专家那里获得见解 【现代数据领导者的剧本】 ,或 在 LinkedIn 上关注我

如何设置成功的 A/B 测试

原文:https://towardsdatascience.com/how-to-set-up-a-b-tests-for-success-9ad9a80541b7

帮助非数据专业人员在没有数据科学家的情况下自信地运行测试

约翰·施诺布里奇在 Unsplash 上的照片

我们,数据科学家,为了精通假设检验和统计学,进行了大量的研究和长时间的工作。然而,数据科学家无法控制其他团队决定运行的每个 A/B 测试。例如,脸书和 Nextdoor 等社交媒体公司的增长型营销团队在没有数据科学家监督实施的情况下不断进行 A/B 测试。这有好处也有坏处:

  • **利:**营销团队变得独立,而数据科学家可以专注于其他需要技术投入的项目。
  • 反对意见:如果没有专家对 A/B 测试的意见,成长型营销团队可能会浪费资源。

你该怎么办?

教育你的利益相关者是相对简单的,它会对每个人的工作产生重大影响。教育步骤的想法是通过解释简单的概念和分享最佳实践来提高其他团队的标准。在运行 A/B 测试之前,创建一个演示文稿,介绍每个非数据涉众应该知道的内容。这样做的话,你将会消除几十个简单的问题,这些问题通常会扰乱你作为数据科学家的工作,但是与其他团队的测试相关。这是你为成功建立 A/B 所能做的第一件事——即使这不是你的测试。

成功的 A/B 测试设置

这是我见过的非数据专业人士挠头的最常见的概念。因公司而异。

  1. 定义一个强有力的假设:

假设是对两个或多个变量之间关系的预测。你的工作是证明你的预测是真的还是假的。下面是我创作的两个例子:

  • 60 岁的英国男性每天吃一个苹果,比那些不吃苹果的人去看心脏病医生的次数少。
  • 在纽约市,通过应用程序加入 Medium 的 25-35 岁用户在第一周做出的贡献比通过网络加入的用户更多。此外,贡献被定义为至少一次鼓掌或一个帖子。

上面的假设有一些共同点,下面列出了我喜欢称之为的有效假设清单:

  • 定义成功的单一且可衡量的标准。
  • 预测关系和结果。
  • 简洁明了,避免啰嗦。
  • 清晰,没有模糊或者隐含的意思。
  • 与问题相关且具体。
  • 一个在测试开始日期之前定义好的。

所以,不管样本大小如何,除非你的假设是明确的,否则结果可能会误导。换句话说,如果假设事先没有很好地定义,数据就不太可能代表你所期望的。

2。置信区间至少应为 95%

置信水平是指如果您再次运行测试或以相同方式对总体进行重新采样,您预期看到相同的赢/输结果的时间百分比。还有,科学标准是 95%的置信区间。虽然 95%的区间在学术界引起了争议,但这是任何非数据专业人士都应该在测试中使用的默认设置。

将置信区间增加到 99%并使您的测试结果更加可靠是可能的,但是 95%足以获得统计上显著的结果。在某些情况下,您会发现 90%是标准设置。然而,不推荐 95%以下的置信区间**。**

如果你的非数据利益相关者使用在线计算器,请小心。一般来说,易于使用的计算器不会指示使用了哪种测试(单尾或双尾)。我很欣赏用户可以假设双尾测试,但我们不能保证这是事实。此外,双尾检验并不总是每个假设的最佳选择——这就是为什么我的第一个主题是关于假设的。

卢克·切瑟在 Unsplash 上拍摄的照片

3-我可以提前结束测试吗?

直截了当的回答是不**。有几个原因你应该记住:**

  • 置信区间根据样本大小而变化。置信区间的宽度随着样本量的增加而减小**。因此,在运行您的测试之前,确认需要多少天才能达到预测的样本量。如果这段时间太长,你不能等待,你可以通过使它更具体来检查你的目标样本。**
  • 季节性和外部事件会影响结果。但是,要看行业,产品或者服务。一些例子包括政治、自然灾害、假期和学校日历。
  • 它会增加假阳性,也称为 I 型错误。换句话说,成功的案例会比应该的多。

那么,你能做什么?请看一下顺序测试**,它使您能够在 A/B 测试期间通过顺序监控数据的累积来做出决定。顺序测试使用可选的停止规则(错误花费函数)来保证总体 I 型错误率。**

结论

不是每个团队都有数据科学家监督 A/B 测试。因此,请记住,建立一个明确的假设,确保 95%的置信区间,不要过早结束测试,可以很容易地提高你的结果。如果你需要的话,可以使用顺序测试来代替长时间的测试。但是,请务必通过共享这些和其他默认参数来指导非数据专业人员设置 A/B 测试。

想获得 Medium 文章的全部访问权限并支持我的工作?使用以下链接订阅:

**https://boemer.medium.com/membership **

感谢阅读。这里有一些你可能会喜欢的文章:

** </5-tips-to-get-your-first-data-scientist-job-d8e5afd5a59b> **

如何使用负载平衡器为不同的 GCP 应用程序设置自定义域

原文:https://towardsdatascience.com/how-to-set-up-a-custom-domain-for-different-gcp-applications-using-a-load-balancer-bbcad40fed

用简单的例子揭开神秘的负载平衡器的神秘面纱

图片由 Pixabay 上的 geralt 提供

默认情况下,我们只能通过虚拟机(VM)的 IPs 或带有 Google 签名的长 URL 访问我们在 Google 云平台(GCP)上的应用程序,如 Cloud Run、Cloud Function、App Engine 以及云存储对象。如果我们想通过自定义域访问它们,我们需要使用负载平衡器。

谷歌云平台上的云负载平衡器实际上是一个相当复杂的概念,当你阅读官方文档时,你很容易迷失。简单地说,负载平衡器让您可以从世界各地使用一个 IP 地址访问您的应用程序。从技术上来说,它涉及到根据流量扩大和缩小后端服务。

在本帖中,我们将介绍最实际的案例,并使用负载平衡器为我们的后端应用程序添加自定义域。我们将介绍如何使用自定义域来访问虚拟机、云运行服务和云存储桶。

准备

在创建云负载平衡器之前,我们首先需要获得一个自定义域,保留一个静态 IP,添加 DNS 记录,并创建一个 SSL 证书。此外,我们还需要创建一个 VM 实例、一个云运行服务和一个存储桶。

获取自定义域

您可以从任何域名注册机构获得自定义域名。比较流行的域名注册商,请查看这篇文章。我的域名(superdataminer.com)的注册人是 DOMAIN.COM。从技术上讲,你选择哪个域名注册商并不重要。重要的是价格,通常包括起步价和续约费。如果您需要一些特殊服务,也可能会有一些额外的费用。一个参考文献中的排名可能会有偏差。但是,如果不同的推荐人总是将同一个注册商排在前面,那么情况就不会很糟糕。需要注意的是,有些注册卡的起步价可能很低,甚至免费,但如果你想续费的话,起步价可能会很贵。因此,一定要检查不同的参考排名和比较,选择一个最适合你的项目。

保留静态 IP

为了使用 Google Cloud Load Balancer 为我们的应用程序添加自定义域,我们需要为它保留一个静态 IP。在 GCP 控制台上搜索“IP”并选择“IP 地址”。然后点击“保留外部静态地址”以保留静态地址。

作者图片

作者图片

给它一个名称,并将类型设置为“Global ”,因为该 IP 旨在被全局访问。所有其他选项都可以保留为默认值。

作者图片

当我们点击“保留”时,将为我们保留一个静态 IP。请记住这个静态 IP,因为它将用于为您的域添加 DNS 记录。

作者图片

为静态 IP 添加 DNS 记录

我们需要为静态 IP 添加一些 DNS 记录,这样我们的域就可以指向这个 IP。登录您的域注册商并添加以下 DNS 记录:

NAME                  TYPE     DATA
@                     A        <Your-Ststic-IP>
www                   CNAME    superdataminer.com
api                   CNAME    superdataminer.com

@名是指根域名,在本帖中是superdataminer.com,www是对应www.superdataminer.com的子域,同样适用于api子域。此外,A代表“地址”,指定目标域的 IP 地址,而CNAME代表“圆锥形名称”,实际上是指向所创建的A记录的别名。

对于 DOMAIN.COM,您可以在购买的域名上点击“管理”,然后在左侧导航栏上找到“DNS &名称服务器”选项卡。最后,单击“DNS 记录”选项卡,然后单击“添加 DNS 记录”来添加新的 DNS 记录:

作者图片

按照上面的指示为每个 DNS 记录填写表格。特别是,IP 地址是上面创建的静态 IP。此外,我们需要为记录设置一个 TTL,它告诉 DNS 解析器将缓存该记录多长时间。对于这个例子,TTL 设置为什么值并不重要。通常,较小的 TTL 意味着 DNS 记录更改可以更快地传播。如果你想了解更多关于 DNS TTL 的知识,网上有很多参考资料。比如这个就是个好的。最后,优先级字段可以留空。

作者图片

作者图片

添加的 DNS 记录将如下所示:

作者图片

现在已经添加了所有 DNS 记录,我们需要等待一些时间来传播更改,这可能需要几个小时甚至几天。然而,通常我们只需要等待几个小时甚至十几分钟就可以让它们繁殖。如果你的需要更长的时间,不要担心,只要多一点耐心,他们最终会工作。

添加完 DNS 记录后,您可以使用pingdig命令来检查它们是否被正确添加以及它们是否被传播:

$ **ping superdataminer.com**
$ **ping** [**www.superdataminer.com**](http://www.superdataminer.com)
$ **ping api.superdataminer.com**
64 bytes from 230.190.111.34.bc.googleusercontent.com (**<Your-static-IP>**)$ **dig superdataminer.com**
;; ANSWER SECTION:
superdataminer.com. 3469 IN A **<Your-static-IP>**$ **dig** [**www.superdataminer.com**](http://www.superdataminer.com)
;; ANSWER SECTION:
[www.superdataminer.com](http://www.superdataminer.com). 3529 IN CNAME superdataminer.com.
superdataminer.com. 3453 IN A **<Your-static-IP>**$ **dig api.superdataminer.com**
;; ANSWER SECTION:
api.superdataminer.com. 3522 IN CNAME superdataminer.com.
superdataminer.com. 3406 IN A **<Your-static-IP>**

如果 IP 地址是上面保留的静态 IP,那么这意味着 DNS 记录已经被正确设置并且已经被传播。

创建虚拟机

现在,让我们在 GCP 上创建一个虚拟机,并在其中运行一个 Flask 应用程序。请在计算引擎页面上创建一个虚拟机实例,该实例也可以在搜索框中进行搜索。

作者图片

作者图片

出于测试目的,我们将选择最低配置:

作者图片

如果您想为生产创建一个虚拟机实例,那么您应该选择适合您的应用程序的配置。

此外,重要的是,由于我们将从 GCP 之外访问虚拟机,我们需要允许 HTTP 和 HTTPS 流量:

作者图片

单击“CREATE”后,将调配并创建虚拟机实例。

作者图片

在我们可以通过自定义端口(5000)访问 VM 实例之前,我们需要为它创建一个特定的防火墙规则。在 GCP 控制台上搜索“防火墙”,然后选择“防火墙 VPC 网络”。单击“创建规则”创建新的防火墙规则。首先,我们需要给它一个唯一的名字:

作者图片

然后,我们需要指定目标、IP 范围和端口:

作者图片

我们也可以使用默认端口,即 80 用于 HTTP,443 用于 HTTPS。然而,这里我们演示了如何为我们的应用程序指定一个自定义端口,这在默认端口不适用的许多情况下是很有帮助的。

现在我们需要为新的防火墙规则添加标签(上面指定的flask标签)到我们的 VM 实例中。在虚拟机实例上单击“编辑”,并为其添加一个网络标记:

作者图片

单击“保存”保存更改。现在,让我们通过单击实例右侧的 SSH 链接登录到虚拟机实例,如上所示:

作者图片

由于git不可用,我们先安装一下:

$ sudo apt update
$ sudo apt install git

在低 CPU/内存配置的虚拟机中安装软件/库可能会非常慢,所以在安装gitpip/venv(如下)时要有点耐心。

然后为 Flask 克隆这个示例项目并安装requirements.txt中指定的库。

$ git clone [https://github.com/lynnkwong/flask-cloud-run-app.git](https://github.com/lynnkwong/flask-cloud-run-app.git)
$ cd flask-cloud-run-app$ sudo apt install python3-pip
$ sudo apt install python3-venv$ python3 -m venv .venv
$ source .venv/bin/activate(.venv) $ pip install -r requirements.txt

注意,虚拟环境是用 Python 的venv库创建的。这些库安装在虚拟环境中,而不是直接安装在系统中,建议在生产中使用。

最后,让我们启动应用程序。请注意,我们需要为它设置一个环境变量,这样我们就可以知道响应来自 VM 实例,而不是来自云运行,我们将很快展示这一点。

(.venv) $ export APP_NAME="App in VM instance"
(.venv) $ gunicorn -w 4 -b 0.0.0.0:5000 app:app &

我们使用[gunicorn](https://flask.palletsprojects.com/en/2.1.x/deploying/wsgi-standalone/#gunicorn)在 VM 实例中启动 Flask 应用程序。注意命令末尾的&符号(&),即使我们退出控制台,它也能保持应用程序运行。

现在,当您尝试使用 Flask 应用程序的外部 IP 从任何地方访问它时,您可以得到一个响应:

$ curl <Your-VM-external-IP>:5000
<h1>Hello from App in VM instance!<h1>

创建实例组

我们需要为 VM 实例创建一个“实例组”,这样它就可以用于在负载平衡中创建后端服务。在 GCP 控制台中搜索“实例组”,选择“实例组”,然后单击“创建实例组”。我们需要选择“新的非托管实例组”来实现负载平衡。然后,在我们设置网络和实例之前,指定一个名称、区域和区域。

作者图片

对于“网络和实例”部分,选择默认网络和子网,然后选择要包含在此实例组中的虚拟机。我们可以在一个实例组中选择多个虚拟机,负载平衡器会平衡流量。对于本教程,我们只有一个虚拟机实例。

作者图片

重要的是,对于“端口映射”部分,我们需要创建一个映射,因为我们在 VM 中运行的 Flask 应用程序使用端口 5000。因此,我们需要为它创建一个映射:

作者图片

当我们为实例组创建后端服务时,将使用这个端口映射。

创建云运行服务

在 GCP 控制台中找到“云运行”选项卡,然后单击“创建服务”来创建服务。您可以从现有的容器映像或源存储库中部署服务的一个修订版。我们将选择后者,因为我们不需要事先创建自定义图像。

作者图片

如果您想跟进,请在单击“使用云构建设置”后,分叉此回购并设置您的云构建以链接到此回购:

作者图片

作者图片

如果您在这个 repo 中设置了您的存储库,那么您不需要做任何更改。默认设置可以工作。单击“保存”后,将为源代码创建一个云构建触发器。将来,每当您将一些新代码推送到 repo 时,都会构建一个新的映像,并部署一个新的服务(技术上来说是服务的新版本)。

作者图片

此外,出于测试目的,我们将为我们的服务“允许所有流量”和“允许未经身份验证的调用”。如果您的应用程序有高安全性要求,您可能希望选择不同的方法。

作者图片

最后,因为我们的 Flask 应用程序需要一个环境变量,所以让我们为它创建一个环境变量。展开“容器、变量和机密、连接、安全性”部分,并单击“变量和机密”选项卡。添加一个名为“APP_NAME”的新环境变量:

作者图片

现在,一切都准备好了,您可以保留其他选项的默认值。点击“点击”创建服务。过一会儿,您的服务将可用,您可以通过云自动运行分配的 URL 访问您的 Flask 应用程序:

作者图片

作者图片

如果您的部署出现任何问题,请查看“LOGS”选项卡中的日志。通常你会在那里找到原因。

要了解更多关于如何为 Flask 应用程序创建云运行服务的信息,请查看这篇文章。

创建一个桶并上传一些图像

首先,去谷歌云存储,创建一个存储你的图片的桶。通常情况下,您只需指定存储段名称并选择一个区域,其他选项都可以保留为默认值:

作者图片

然后,您可以创建文件夹并将文件上传到 bucket,就像使用 Google Drive 一样。本文中使用的图片是从 Pixabay 下载的免费图片。

作者图片

作者图片

默认情况下,只有经过身份验证的用户才能访问桶中的图像,外部用户无法访问。如果我们想将图像公开,让任何地方的任何人都可以访问,我们需要更改 bucket 的权限。若要添加权限主体,请单击“权限”,然后单击“添加”。要公开一个存储桶,我们需要为“所有用户”添加一个“存储对象查看者”角色。谷歌会警告你这一行动,但如果你知道你在做什么,你可以安全地确认它。

作者图片

现在,任何人在任何地方都可以访问这些图像:

作者图片

创建 SSL 证书资源

因为我们正在创建一个 HTTPS 负载平衡器,所以我们需要为它创建一个 SSL 证书资源。出于生产目的,建议使用谷歌管理的证书,这也比自签名证书更容易设置。

Google 管理的证书的入口点有点隐藏。如果你在谷歌云控制台的搜索框中搜索“SSL 证书”,找到的是自签名证书,而不是我们要找的谷歌管理的证书。要找到正确的,你需要首先进入负载平衡页面,点击“高级菜单”找到它。

作者图片

在“高级菜单”打开的“负载平衡组件”页面中,单击“证书”选项卡,然后单击“创建 SLL 证书”按钮,创建一个新的 Google 管理的证书:

作者图片

按如下方式填写表格:

作者图片

重要的是:

  • 给它一个描述性的名称,因为稍后创建负载平衡器时会用到它。
  • 在“创建模式”中,选择“创建谷歌管理的证书”。
  • 在“域名”部分,输入您从域名注册商处购买的域名。我们应该添加根域(superdataminer.com)和所有子域(本例中只有 api.superdataminer.com)。
    注意:所有的域必须指向同一个 IP 地址,也就是负载均衡器的 IP,否则无法置备证书!

然后单击“创建”创建证书:

作者图片

SSL 证书的状态在变为“活动”之前会保持一段时间,稍后我们创建负载平衡器时会更详细地演示这一点。

创建一个谷歌云负载平衡器

最后,一切都准备好了,我们可以开始创建一个 Google Cloud 负载平衡器来为我们的应用程序设置一个自定义域。在 GCP 控制台的搜索框中搜索“负载”,然后选择“负载平衡”。在打开的窗口中,点击“创建负载平衡器”:

作者图片

然后单击“HTTP(S)负载平衡”上的“开始配置”,这就是我们要创建的配置:

作者图片

保留默认选项如下,这是我们想要的:

作者图片

单击“继续”后,我们需要为负载平衡器指定一个名称,然后设置后端、主机和路径规则以及前端的配置:

作者图片

首先点击“后端配置”。因为我们还没有任何后端服务,所以我们需要先创建它们。我们将分别为一个实例组、一个无服务器云运行服务和一个云存储桶创建一个后端服务。

为实例组创建后端服务

在“后端配置”部分,单击“后端服务和后端存储桶”,并选择“创建后端服务”。

作者图片

在“创建后端服务”窗口中,指定后端服务的名称,并选择“实例组”作为后端类型。然后将协议更改为“HTTP ”,并将命名端口设置为“flask ”,这是我们在上面为实例组创建的端口。协议可以是 HTTP,不必是 HTTPS,因为流量是从负载均衡器转发到 GCP 系统内部的实例组的。

作者图片

然后在“后端”部分,选择我们创建的实例组。将自动检测并选择端口号:

作者图片

重要的是,我们需要为实例组创建一个健康检查策略,否则实例组的后端服务将无法正常工作:

作者图片

在“健康检查”的新窗口中,指定名称、协议和端口。其他选项可以保留为缺省值,除非您想根据自己的特定需求对性能进行微调。

作者图片

请注意,协议可以是“TCP ”,因为运行状况检查是由内部 IPs 在 GCP 系统内部完成的。

创建运行状况检查策略后,我们可以单击“CREATE”为实例组创建后端服务。

作者图片

为云运行创建后端服务

为云运行创建后端服务的过程实际上与为实例组创建后端服务的过程非常不同,尽管两者属于同一类型。要为云运行创建后端服务,我们也需要从“后端配置”开始:

作者图片

在打开的“创建后端服务”窗口中,指定后端服务的名称,并选择“无服务器网络端点组”作为后端类型。

作者图片

然后,我们需要为我们的云运行服务创建一个无服务器网络端点组(NEG ):

作者图片

单击“创建无服务器网络端点组”为我们的无服务器云运行服务创建后端:

作者图片

有时,GCP 用户界面可能会有一个错误,当您尝试创建网络端点组时,您无法选择云运行服务。这是在创建本教程时发生的。在这种情况下,您可以使用gcloud命令创建一个:

**gcloud compute network-endpoint-groups create** <neg-name> \**--region**=<region> \** --network-endpoint-type=serverless** \** --cloud-run-service**=<serviceName>

对于本教程,该命令将是:

**gcloud compute network-endpoint-groups create** neg-superdataminer \**--region**=europe-west1 \**--network-endpoint-type=serverless** \**--cloud-run-service**=superdataminer-cloud-run

当该命令成功完成时,您会看到:

Created network endpoint group [neg-superdataminer].

如果您遇到这种权限错误:

ERROR: (gcloud.compute.network-endpoint-groups.create) Could not fetch resource:- Required 'compute.regionNetworkEndpointGroups.create' permission for

您可以运行以下命令来验证您的 Google Cloud SDK:

$ **gcloud auth login**
$ **gcloud config set project** <Your-Project-ID>
$ **gcloud auth application-default login**

当从 UI 或通过gcloud命令创建无服务器网络端点组时,您可以选择并使用它来创建您的后端服务:

作者图片

现在,单击“创建”为我们的云运行服务创建后端服务。

作者图片

为云存储创建后端服务

最后,让我们继续为您的云存储桶创建一个后端桶:

作者图片

在打开的“创建后端存储桶”窗口中,输入后端存储桶的名称,并选择您想要访问的云存储桶。此外,建议启用云 CDN 来更快地交付内容并节省成本,尤其是静态内容:

作者图片

这个过程简单得多,通常你不会遇到任何问题。现在,我们的负载平衡器的所有后端配置都已完成:

作者图片

指定主机和路径规则

配置后端后,我们需要指定主机和路径规则,这些规则决定了您的流量将如何定向。流量可以被定向到后端服务或存储桶,正如我们上面配置的那样。

作者图片

指定了三个主机和路径规则:

  • 第一个是默认的,其主机和路径不能更改。所有不匹配的主机和路径都会被发送到分配给这个规则的后端,也就是我们的云运行服务。
  • 第二个是图像的规则。它指定图像将被定向到“superdataminer.com/images/*”。这个规则的后端是上面创建的 Bucket 后端。
  • 第三个是 API 子域,其后端是实例组。

前端配置

最后,我们来设置前端配置。点击左侧的“前端配置”,设置配置如下:

作者图片

重要的是,我们需要:

  • 指定前端的名称。
  • 将协议更改为“HTPPS(包括 HTTP/2)”。
  • 将 IP 设置为之前保留的静态 IP。
  • 选择之前创建的 SSL 证书。

请注意,“启用 HTTP 到 HTTPS 重定向”选项可能无法正常工作。在这种情况下,如果需要,您需要创建一个单独的 HTTP 前端。

现在一切准备就绪。我们可以检查并最终确定配置,然后单击“创建🔥“创建负载平衡器,如果一切正常,就创建它。

检查您的 SSL 证书的状态

如前所述,您的 SSL 证书的状态将保持在“供应甚至“失败 _ 不可见,直到满足以下两个条件:

  • 如上所示,DNS 记录已经正确添加,并且已经为您的静态 IP 进行了传播。
  • SSL 证书已经附加到负载平衡器的前端,如上所示。

如果满足以上两个条件,状态将更改为“活动”,这意味着一切正常:

作者图片

测试负载平衡器

测试实例组

$ curl [https://api.superdataminer.com](https://api.superdataminer.com)
<h1>Hello from App in VM instance!<h1>

测试云运行

当你访问https://superdataminer.com时,你会看到来自云润的问候:

作者图片

测试云存储桶

当你访问https://superdataminer.com/images/cloud-compute.jpg时,你可以看到谷歌云存储桶中的图片:

图片由作者提供(原始图片由 Pixabay 上的 kreatikar 提供)

干杯!所有 GCP 应用程序的自定义域都像预期的那样工作。

在这篇长文中,我们详细讨论了如何创建一个负载平衡器,并为您的后端服务和云存储桶分配一个自定义域。现在,您应该对什么是负载平衡器以及如何使用它为您在 GCP 的应用程序提供服务有了更好的理解。

乍看之下,负载平衡可能会让人不知所措。然而,如果你仔细遵循这些步骤,并试图理解每一个步骤背后的逻辑,它实际上并不复杂。如果您在为本文中演示的示例设置负载平衡器时遇到任何问题,欢迎您给我留言或私信,我会尽力帮助您。

另外,请注意域名superdataminer.com在这篇文章中只是用于演示,当你阅读这篇文章时,它可能会被用于其他用途。因此,如果你想继续下去,你需要有自己的域名。

如何建立机器学习的开发环境

原文:https://towardsdatascience.com/how-to-set-up-a-development-environment-for-machine-learning-b015a91bda8a

如何为机器学习和数据科学相关任务安装、激活和使用虚拟环境

布拉德利·兰巴赫在 Unsplash 上拍摄的照片

在我们开始编码之前,用一个新的开发环境设置我们的机器是必要的。在这些例子中,我将使用 OSX 终端和 Python 3.8 来实现这一点,并向您展示入门的基础知识。

如果你是 Windows 用户,基本逻辑不会改变,但是对于一些命令,你可能需要使用谷歌。从 Windows 10 开始,你可以使用WSL(Linux 的 Windows 子系统)——这是微软提供的一个子系统,可以托管几个 Linux 发行版。阅读此处获得深入指导。另一个选择也是安装一个装有 Ubuntu 18.04 的虚拟机或者使用 VPS。

通俗地说什么是虚拟环境

对那些刚刚开始学习数据科学和 Python 编程的人的简要介绍。虚拟环境是一个开发环境,充当我们当前项目的容器。虽然能够安装任何系统范围的库,但是拥有一个虚拟环境允许您为特定的项目安装这样的库和包。这允许你有一个有序的和容易导航的系统,没有不兼容的风险 或全球水平的故障。

将虚拟环境专用于一个项目是一种常见的做法,并且由于上面提到的原因,应该总是这样做。

在 Python 中,有几个管理虚拟环境的选项。其中最著名的当然是 Anaconda,一个帮助(尤其是数据科学家)有效配置和管理开发环境的软件。

我们将使用 Miniconda 在我们的系统上配置 Python。它是康达的轻量级安装程序,一个开源的面向数据科学的开发环境管理系统可用于 Linux、OSX 和 Windows。

之所以选择 Miniconda 而不是 Anaconda,是因为后者带来了大量的软件包,我认为除了偶尔的情况之外,我们永远不会使用这些软件包,因此安装一个小的软件包更有意义。

如何在 OSX 上安装 Miniconda

在写这篇文章的时候,我们将要从官网下载的文件会有这样一个名字:miniconda 3-py38 _ 4 . 11 . 0-ma cosx-x86 _ 64 . sh

迷你康达下载屏幕。图片作者。

根据我们系统的架构,我们可以在基本版本和 M1 ARM 芯片组版本之间进行选择。

一旦文件被下载,我们打开终端并写

$ cd Downloads

$ sh Miniconda3-py38_4.11.0-MacOSX-x86_64.sh

并按照屏幕上的说明进行操作。如果我们在终端中写下conda,我们可以检查我们是否正确安装了软件

图片作者。

此时,我们已经在 Mac OSX 系统上安装了 Miniconda,我们准备创建一个虚拟环境。

如何用 Miniconda 创建虚拟环境

一旦安装了 Anaconda 或 Miniconda,并且使用conda命令验证了它们的正确功能,我们就可以创建一个新的开发环境,如下所示:

$ conda create -n name_of_my_environment

这个命令将在安装目录中创建一个名为 name_of_my_environment 的虚拟开发环境。要激活虚拟环境,只需运行以下命令

$ conda activate name_of_my_environment

我们完了。我们的虚拟环境已经为应用程序的开发做好了准备。现在让我们看看如何在我们新激活的虚拟环境中安装或卸载库和包。

如何在虚拟环境中安装软件包和库

现在是时候给我们的工具箱添加工具了。要添加 Python 包或库,只需使用命令

$ conda/pip install name_of_package

正如我们所见,也可以使用 pip 命令在 conda 中安装包。事实上,如果我们使用这个命令

$ conda/pip list

conda 或 pip 将分别向我们展示通过它们的命令安装的包。

我推荐使用 pip install 命令而不是 conda install ,因为有些包在 conda 存储库中不可用。可能有几个原因,但是使用 pip 没有缺点,并且允许您有效地下载和安装软件包。

康达备忘单——触手可及的所有命令

在这篇文章的结尾,我将与你分享一个有用的资产,它在我的职业生涯和个人工作中帮助了我无数次。我说的是 Anaconda 提供的官方备忘单。这是它的预览图👇

备忘单的预览。图片作者。

我建议你将它保存在你经常打开的文件夹中,或者将单个命令保存在你最喜欢的笔记应用程序中。

我希望这个简短的指南能帮助你开始你的 Python 数据科学和分析之旅。如果您有任何问题或想分享您的反馈,请在下面留下评论!

直到下次👋

如何用 oh-my-zsh-Plugins 建立一个令人惊叹的数据科学终端

原文:https://towardsdatascience.com/how-to-set-up-an-amazing-terminal-for-data-science-with-oh-my-zsh-plugins-2518dfeeab5d

通过安装一些关键插件,提高您在终端中的工作效率和用户体验。

这篇文章中描述的终端的预览。作者图片

作为数据科学家,你为什么要使用终端?

对于开发人员来说,没有比这更高效或更通用的工具了——终端是开发人员工具箱中的瑞士军刀。

终端可以是您日常任务的一站式商店。代码编辑、启动程序、多任务、脚本、系统管理等等。

命令行技术将您从限制性的 GUI 工具和无休止的鼠标点击中解放出来,开启了一个高效和自动化的世界。

但是对于外行人来说,命令行可能是令人生畏和不可原谅的。

默认终端的单色用户界面没有俘虏。

没有语法高亮显示,也没有自动补全功能。谁知道您输入的命令是否正确?

**然而,对配置的小调整对改善用户体验大有帮助。**将命令行变成一个强大的工具来加速您的工作流程。

**关键是花点时间用插件定制你的终端。**花几个小时定制你的终端将会带来巨大的收益。

提高工作效率的终端关键特性

定制终端是一件非常私人的事情。每个人都有审美偏好和不同的功能需求,这取决于他们的技术组合。

但我认为以下终端属性对提高生产率很重要:

  • 命令行(提示符)显示关于您的环境的关键信息,例如 git 信息、虚拟环境、Python 版本等。
  • 语法突出显示
  • 自动完成
  • 窗口和会话管理
  • 高效的文件系统导航和目录跳转
  • 一个很好的美学——如果你不喜欢使用它,你可能不会去打扰它

在这篇文章中,我将介绍我用来实现上述功能的关键插件,并将命令行转换成一个高效的环境。

让我们开始吧!

先决条件

我使用 MacOS、 iterm2 和 Homebrew 进行设置。

但是,应该可以在任何操作系统上安装和配置这个设置。

我将提供每个程序和插件的文档链接。有关如何为您的特定操作系统设置每个组件的更多信息,请阅读文档页面。

配置命令行提示符

1.哦,我的天

MacOS 终端提示符附带了作为默认 shell 的 z shell (zsh)。

哦我的 Zsh **是一个管理你的 Zsh 配置的开源框架。**它提供了对许多优秀插件的便捷访问,这些插件可以改善您的终端体验并提高您的工作效率。

“哦,我的 Zsh 不会让你成为 10 倍的开发者…但你可能会觉得自己是!”

— oh-my-zsh 文档

我们将使用 oh-my-zsh 来管理和安装本文中描述的其余终端设置的插件。

您可以使用以下命令安装 oh-my-zsh(完整说明和文档在他们的网站):

*# install oh-my-zsh*
sh -c "**$(**curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh**)**"

安装oh-my-zsh将创建/更新您的~/.zshrc文件——位于您的主目录中——它定义了您的zsh配置。我们将在整个教程中编辑~/.zshrc文件来定制我们的终端。

2.下载一个书呆子字体

接下来,下载你选择的书呆子字体。

书呆子字体为你的终端提供了许多很棒的字体,这些字体被打了补丁以支持图标。我们稍后将需要一个补丁字体来渲染终端中的开发图标,并获得漂亮的外观。

你可以按照 Nerd-font GitHub 页面上的说明,在你的操作系统上安装你选择的补丁字体。

我使用黑客字体,这是我用自制软件安装的:

*# install 'hack' font using Homebrew*
brew tap homebrew/cask-fonts
brew install --cask font-hack-nerd-font

您可以通过更新 item2 偏好设置,将终端中的字体更改为刚刚安装的字体。

iterm2 首选项用户界面。作者图片

3.自定义提示(Starship)

oh-my-zsh 的默认主题叫做robbyrussell,以 oh-my-zsh 的创始人命名。

我真的很喜欢这个主题的简约美学,在移植到 Starship 之前我用了很长时间。

虽然这只是默认主题,但它已经是毫无特色的单色默认zsh提示符的一个巨大升级。

默认 robbyrussel oh-my-zsh 主题。图片作者。

还有许多其他的主题伴随着oh-my-zsh。完整列表可以在 GitHub Wiki 中找到。为了将主题更改为内置的主题之一,您只需要更新您的~/.zshrc中的ZSH_THEME值,并重启您的终端以使更改生效。

或者,您可以安装和使用外部主题来代替内置主题。

Powerlevel10K 是一个流行的选择,然而我更喜欢用 Starship 。

Starship 是一个高度可定制的提示符,跨 shell 兼容——无论您使用 bash、zsh、fish 还是 Powershell 作为 shell,您都可以使用相同的提示符配置。

Starship 带有合理的默认值,可以用一个用户友好的toml文件进行配置,并带有一个 CLI 工具,使即时更新您的提示变得轻而易举(稍后会有更多介绍……)。

要安装 Starship,你可以遵循文档主页上的说明。

*# install starship*
brew install starship

然后在你的~/.zshrc的末尾添加下面一行来使用 zsh 中的 Starship 提示符。

*# ~/.zshrc*eval "**$(**starship init zsh**)**"

重新启动终端以使更改生效。

配置星舰提示

配置 Starship 的完整文档可以在他们的网站上找到。

Starship 提示符配置由你的.config目录中的一个名为starship.toml的文件控制

例如,下面是一个简单的配置,当我导航到 Python 项目目录时,我使用它在提示中显示 Python 版本和虚拟环境:

*# example ~/.config/starship.toml*add_newline = **false**[python]
format = 'via [${symbol}${pyenv_prefix}(${version} )(\($virtualenv\) )]($style)'

Starship 提示符和 starship.toml 配置文件示例。图片作者。

4.选择终端配色方案

好的,所以这部分不一定会影响你的“生产力”,但重要的是得到你喜欢回来的最好看的终端🎨。

这完全取决于个人喜好——你可能完全不同意我的选择——但我喜欢使用Solarized Dark配色方案。我也给背景添加了一些透明度/模糊度。

还有许多其他预设的配色方案可供选择,我建议你尝试找到你最喜欢的。

这些设置可以在 iterm2 的首选项 GUI 中更改。

iterm2 首选项 UI,设置配色方案。图片作者。

iterm2 首选项 UI,设置背景透明度和模糊度。作者图片

我的最后一个提示使用了星际飞船和日晒深色配色方案。

最终的星际飞船提示,有晒过的深色方案和一些透明度。图片作者。

基本工具:最好的插件

5.语法突出显示

语法突出显示对于提高终端的可用性至关重要。

它可以帮助您确定您是否正确安装了程序,并可以提醒您拼写错误或命令无效。

要在zsh中启用语法高亮,你需要安装一个名为 zsh-syntax-highlighting 的插件。

安装说明在 GitHub repo 中提供。您可以使用以下命令安装zsh-syntax highlighting:

*# download syntax highlighting extension*
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM**:-**~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

然后通过更新.zshrc文件来激活插件。

*# add syntax highlighting to the list of plugins in your ~/.zshrc file*
plugins=(zsh-syntax-highlighting)

运行source ~/.zshrc或重启终端以使更改生效。

现在,当你键入一个关键字命令时,如果它是正确的,它会变成绿色,如果它是不正确的,它会变成红色。

语法突出显示。提交命令前发现错误。图片作者。

6.自动完成

当键入长命令时,自动完成可以节省大量时间,并且对于记住您以前运行过的命令非常有帮助。

需要 zsh-autosuggestions 插件来启用zsh中的自动完成功能。

GitHub repo 的安装 wiki 页面上提供了安装说明。安装与语法突出显示非常相似。

*# install autocompletions extension*
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM**:-**~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions*# update plugins in your ~/.zshrc file*
plugins=(zsh-syntax-highlighting zsh-autosuggestions
)

重启你的终端或运行source ~/.zshrc来查看变化。

7.模糊文件查找( FZF )

FZF 是一个模糊文件查找器,使你能够从命令行交互地搜索文件。当您知道文件名称,但不记得具体保存位置时,这对于快速查找文件非常有用。

*# install FZF (say yes to each option during installation)*
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install

安装脚本将自动用下面一行更新您的.zshrc:

[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh

此外,为了让fzf更好地与oh-my-zsh配合,你需要将fzf添加到你的插件列表中,并用fzf的安装位置设置一个环境变量:

# update your ~/.zshrc file
FZF_BASE="$HOME/.fzf"plugins=(zsh-syntax-highlighting zsh-autosuggestionsfzf
)

你现在可以通过在终端上输入fzf命令或者按下CTRL+T来激活模糊查找器。您也可以使用**前缀并按下<TAB>来触发模糊查找器(参见文档)。例如:

*# search which file to open in vim using the fuzzy finder*
vim **<TAB>

FZF 是高度可定制的。我不会在这里详细介绍如何配置它——它本身可能需要一整篇博文。但是网上有很多很棒的教程解释如何配置 FZF,我建议你研究一下,以便从中获得最大收益。

使用 FZF 的模糊文件查找。图片作者。

8.窗口和会话管理(tmux)

同时运行多个终端进程是很常见的。

数据科学家立即想到的一个用例是需要从终端运行 Jupyter 笔记本服务器,但也需要访问终端来执行其他任务,如提交 git 和运行其他 python 脚本。

如果不能一次打开多个窗口或终端会话,您的终端将被长时间运行的进程阻塞。

解决这个问题的方法是使用窗口管理工具同时管理多个窗口和终端会话。

iterm2 具有为不同会话打开多个选项卡的内置功能。然而,我喜欢使用 tmux,因为它非常可定制,功能强大,可以跨多个不同的终端模拟器工作,所以无论我使用哪个终端,我都可以使用相同的按键绑定。

Tmux 可以通过自制软件安装:

# install tmuxbrew install tmux

同样,你可以写一整篇关于配置tmux的博文。在这篇文章中,我将提供一个示例 tmux 会话的截图,并强烈建议您研究用于管理多个终端会话的会话/窗口管理解决方案,无论是使用 iterm2 选项卡还是tmux

Tmux 窗口管理。三个会话在同一个窗口中打开:vim、命令行和 Jupyter Notebok 服务器。图片作者。

👨‍🎓Chris Toomey 在thought bot上有一个学习 tmux 的速成课程,可以让你快速上手。

附加:有用的插件和命令行工具

下面的程序是一些额外的zsh插件和命令行工具,我也觉得很有用。根据您偏好的工作流和用例,您自己的里程数可能会有所不同。

z —目录跳转工具

zsh-z是一个命令行工具,允许你在最近访问过的目录之间快速跳转。

使用终端的一个难点是在目录中导航,这比使用熟悉的文件浏览器 GUI 导航要复杂得多。像z(以及之前描述的 FZF)这样的工具可以让遍历文件系统变得轻而易举。

要安装zsh-z,我们可以克隆 GitHub 库,并像以前一样将zsh-z添加到.zshrc文件中的插件列表中:

*# download the plugin then update your ~/.zshrc file*
git clone https://github.com/agkozak/zsh-z $ZSH_CUSTOM/plugins/zsh-z

使用 z 插件的目录跳转。图片作者。

蝙蝠——猫的更好替代品

当你想在终端中快速查看一个文件的内容而不需要实际打开它(例如显示一个配置文件)时,你可以使用内置的cat命令。

然而,命令行上的输出只是普通文本,很难阅读,尤其是如果您习惯了 ide 和代码编辑器中的漂亮的语法高亮显示。

batcat的替代版本,它支持语法高亮显示和其他功能,还集成了其他工具,如 fzf。

您可以使用自制软件安装bat(其他操作系统的完整说明可从其 GitHub 文档页面获得):

*# install bat from Homebrew*
brew install bat

您可以像使用cat一样使用bat:

猫和蝙蝠产量的比较。(不是真正的 AWS 令牌和密钥😅).图片作者。

您还可以将它与 fzf 集成,以便在搜索文件时显示每个文件的预览,并突出显示语法:

使用 FZF 和蝙蝠的模糊文件查找和文件预览。图片作者。

exa——ls 的现代替代品

同理,exa是一个替代ls的命令行工具。

ls的输出可能难以扫描,因为文件和文件信息之间没有视觉差异。所有东西都以同样的颜色列出。

exa是一个更加美观的文件“lister ”,带有颜色编码和对图标的支持,可以更容易地理解输出。

安装说明在 exa 网站上。

*# install exa*
brew install exa

要使用exa列出目录中的文件,可以使用exa关键字,后跟一些参数(参见文档)。我真的很喜欢对文件图标的支持,这使得识别每个文件类型变得很容易。

💡 顶部提示 :在你的 *~/.zshrc* 文件中创建一个别名来映射 *exa --icons* *ls* 这样你就不需要重新学习任何语法

个人风格:别名

另一个节省时间的方法是为您经常使用的长命令创建别名。

您可以在您的.zshrc文件中指定别名。

别名对您和您的工作流来说是个人的。我用的不多,但以下是我喜欢用的:

*# ~/.zshrc**# python*
alias python=python3*# git*
alias gs="git status"*# map exa commands to normal ls commands*
alias ll="exa -l -g --icons"
alias ls="exa --icons"
alias lt="exa --tree --icons -a -I '.git|__pycache__|.mypy_cache|.ipynb_checkpoints'"*# show file previews for fzf using bat*
alias fp="fzf --preview 'bat --style=numbers --color=always --line-range :500 {}'"*# starship prompt*
alias gt="starship toggle gcloud disabled" *# toggle gcloud info on the prompt*

使用 GCP 的用户注意事项

我用谷歌云做了很多工作来部署机器学习管道和模型。

当使用glcoud命令行工具时,我担心会不小心将基础设施部署到错误的地区(#GDPR),甚至部署到错误的客户项目。

Starship 允许你使用他们的 CLI 工具来“切换”提示符设置。

我已经创建了一个别名gt,它在我的提示中切换关于我当前gcloud个人资料的重要信息的显示。

这很棒,因为我并不总是需要它,但是能够在运行中改变我的提示来检查真的很有用!

使用别名在提示符下切换 GCP 配置文件信息。图片作者。

结论

对于门外汉来说,这个终端使用起来让人难以忍受、紧张和烦恼。

默认设置有一个骇人的 UX。足以让一些开发人员退回到熟悉的 GUI 工具的舒适怀抱中,再也不回来了。

然而,花几个小时配置您的终端将会为您的生产力、工作流程和整体编程效率带来巨大的回报。

Oh-my-zsh 是管理您的zsh shell 配置和插件的一个很好的框架。通过安装三四个关键插件并在.zshrc文件中添加几行代码,您可以改变使用命令行的体验并提高工作效率。

编码快乐!

This article was originally published on my blog, [engineeringfordatascience.com](https://engineeringfordatascience.com/posts/configure_terminal_for_data_science_with_oh_my_zsh/)

资源

  • 完整的oh-my-zsh插件列表可以在 zsh GitHub wiki 页面上找到

满。从本教程创建的 zshrc 文件

本教程的基本 starship.toml 配置文件

如何在 Windows PowerShell 中设置 Google CLI 命令别名

原文:https://towardsdatascience.com/how-to-set-up-google-cli-command-aliases-in-windows-powershell-8dac18e3b57

保存常用命令可以节省大量的时间和麻烦

狐狸和狮子。温塞斯拉斯·霍拉德。维基共享资源。

背景

谷歌的云软件开发工具包(Cloud SDK) 是在本地管理云项目的必要工具。在 Linux 或 Mac 中,SDK 命令被终端自动继承,使得在您的中设置命令别名变得容易。巴沙尔和其他地方

不幸的是,在 Windows 中,SDK 作为一个独立的应用程序安装,似乎不会继承您的终端配置文件。

设置您的云配置文件需要几个步骤(并且要求您使用 PowerShell ),但这是我能想到的最好的方法。并且从长远来看,它节省了时间,而不必复制和/或重新键入命令。

设置

如果您使用的是机构笔记本电脑,您需要启用管理员权限。

首先,在开始菜单中启动 PowerShell 。

PowerShell 通过 Google 命令行界面(Google CLI )而不是 SDK 安装了一套略有不同的工具。在 PowerShell 中运行以下命令(指令)。

Install-Module -Name GoogleCloud -Repository PSGallery -Force -AllowClobber

要保存会话之间持续的命令,您需要设置一个 PowerShell 配置文件。当您启动新的 PowerShell 会话时,会加载此配置文件(类似于。bashrc)。

这是一篇关于创建 PowerShell 配置文件的完整文章。下面简单说明。

在 PowerShell 中运行以下命令来创建新的空白配置文件:

New-Item -path $profile -type file -force

这将在你的 Documents 文件夹中为我创建一个新文件,在
C:\ Users \ * \ Documents \ windows powershell \ Microsoft。PowerShell_profile.ps1

描述配置文件脚本保存位置的 PowerShell 输出。图片作者。

打开“微软。PowerShell_profile.ps1”。您可以在这里添加 Google CLI 命令(或任何其他命令)。

在 PowerShell 中,多字命令另存为“函数”。函数的语法是—

函数别名{要运行的命令}

例如,您可能希望将用于 ssh 的命令保存到带有端口转发的 DLVM 中(注意,Windows 中的语法略有不同)。

Function gssh {gcloud compute ssh my-dlvm --project my-project --zone my-zone '--' -L 8787:127.0.0.1:8787

这里是我的一些命令的快照

我的 PowerShell 配置文件保存了一些常用的 Google CLI 命令。图片作者。

容易多了!

在 PowerShell 中运行命令别名。这是它工作时的样子。图片作者。

如果你有更好的方法,请在评论中告诉我…

~噢

如何在自动气象站 EKS 设置入口控制器

原文:https://towardsdatascience.com/how-to-set-up-ingress-controller-in-aws-eks-d745d9107307

以正确的方式在 AWS EKS 上部署入口控制器。

由安德里亚·扎能加在 Unsplash 上拍摄的照片

特征图像突出了大规模编排的重要性,这是承诺,也是选择 Kubernetes 的众多原因之一!

先决条件

本文中的一般指南适用于那些对 Kubernetes、Helm 和 AWS 云解决方案有相当了解的人。此外,请记住,这里介绍的方法是我为我的公司建立 Kubernetes 集群的尝试,您可以随时决定偏离这一方法以适应您的用例或偏好。

说完这些,让我们直接开始吧。

那么,入口控制器到底是什么?

与 Kubernetes 中负责将当前状态带入所需状态的其他"控制器一样,入口控制器负责创建集群的入口点,以便入口规则可以将流量路由到定义的服务。

简而言之,如果您将网络流量发送到端口 80 或 443,入口控制器将根据入口规则确定该流量的目的地。

你必须有一个入口控制器来满足一个入口。仅创建入口资源没有效果[ 来源 ]。

举个实际的例子,如果您定义一个入口规则来路由所有到达前缀为/example.com主机的流量。除非您的入口控制器能够根据定义的入口规则区分流量的目的地并对其进行路由,否则此规则将不起作用。

现在,让我们看看入口控制器在 AWS 之外是如何工作的。

其他入口控制器是如何工作的?

我所知道的所有其他入口控制器都是这样工作的:你将控制器公开为一个负载平衡器服务,它将负责处理流量(SSL 卸载、路由等)。).

入口控制器如何在 Kubernetes 的世界中工作(图片由作者提供)

这样做的结果是,创建了一个负载平衡器后,集群中将会有以下内容:

使用 kubectl 获取服务信息

这里有一个命令来验证您的负载平衡器服务是否就绪。

使用 AWS CLI 描述负载平衡器

这种做法有什么问题?

负载平衡器服务对于其他云提供商来说可能是理想的,但对于 AWS 来说不是,这是一个关键原因。创建该服务后,如果您转到 EC2 控制台的 Load Balancer 选项卡,您会看到负载平衡器的类型是“classic”(AWS 称之为“legacy”负载平衡器),并要求立即迁移,原因如下所述。

取自 AWS 控制台(图片由作者提供)

由于经典负载平衡器已于 2022 年 8 月 15 日达到其寿命终点,您不应该在 AWS 平台内部使用它。因此,您永远不要将任何服务公开为负载均衡器,因为任何这种类型的服务都会产生一个“经典的”负载均衡器。他们推荐较新版本的负载平衡器(应用程序、网络或网关)。

避免“经典”负载平衡器是我们选择 AWS 支持的替代解决方案的主要原因,因为它让我们能够利用 Kubernetes 工作负载。

照片由 C D-X 在 Unsplash 上拍摄

那么还有什么选择呢?

当我第一次观察到,与其他入口控制器(HAProxy,Nginx 等)不同,我感到震惊。),AWS 负载平衡器控制器不会公开 Kubernetes 集群内部的负载平衡器服务。入口控制器是 CKA 考试的基本主题之一[ 来源 ]。

但是,仅仅因为 AWS 对其他入口控制器的支持很差,您就不想失去 Kubernetes 的任何丰富功能,直接进入特定于供应商的产品,并成为供应商锁定的产品;至少,我知道我不想。

我个人的偏好是有一个受管理的 Kubernetes 控制平面,带有我自己的自管理节点,但是当然,你可以在这里自由选择你自己的设计!

这里的替代方法是使用AWS 入口控制器,如果您在其他地方运行 Kubernetes,它将允许您拥有相同的工作负载和资源,只是有一点点配置差异,如下所述。

但是 Ingress 控制器在 AWS 的世界里是如何工作的呢?

入口控制器在 AWS EKS 内部工作,将入口资源“分组”在一个名称下,使它们可以从单个 AWS 应用负载平衡器访问和路由。您应该通过您在集群中创建的每个入口中的注释来指定“分组”,或者是通过 IngressClassParams 指定,或者是通过。我不知道你怎么想,但我更喜欢前者!

入口控制器如何在 AWS 的 Kubernetes 世界中工作(图片由作者提供)

“入口组”不是一个有形的物体,也没有任何花哨的功能。它只是一组入口资源以同样的方式进行注释(如前所述,您可以通过在 Ingres class中传递“group”名称来跳过对每个入口的注释)。这些入口资源共享一个组名,并且可以被假设为一个单元,共享相同的 ALB 作为边界来管理流量、路由等。

上面提到的最后一部分是 AWS 内部和外部的入口资源之间的差异。因为尽管在 Kubernetes 的世界里,你不需要处理所有这些分组,但是当你使用 AWS EKS 时,这种方法是可行的!

我对实现这一点和管理配置并不感到不舒服,特别是因为 Nginx、HAProxy 和其他入口控制器都有自己的调整和配置注释集,例如,要重写 Nginx 入口控制器中的路径,您可以使用nginx.ingress.kubernetes.io/rewrite-target注释[ 源。

这里要提到的最后一个重要注意事项是,您的服务不再是ClusterIPs,而是NodePorts,这使得它们在集群中的每个工作节点上发布服务(如果 pod 不在一个节点上,iptables重定向流量)源。您将负责管理安全组,以确保节点可以在临时端口范围[ source ]上进行通信。但是如果你使用 [eksctl](https://eksctl.io/) 来创建你的集群,它会照顾到所有这些以及更多。

现在,让我们开始部署控制器,以便能够创建一些入口资源。

部署 AWS 入口控制器有哪些步骤?

您首先需要在集群中安装控制器,以便任何入口资源能够工作。

这个“控制者”就是负责与 AWS 的 API 对话来创建你的目标群体的人。

  1. 要安装控制器,您可以使用 Helm 或直接从 T5 试一试。

安装 AWS 负载平衡器控制器 CRDs

注意:将您的安装锁定到一个特定的版本,并在测试和 QA 之后升级,这始终是一个最佳实践。

2.第二步是安装控制器本身,这仍然可以用 Helm 来完成。我提供我的自定义值;因此,您可以在下面看到安装文件和值文件。

使用 Helm 安装 AWS 负载平衡器控制器

现在我们已经完成了控制器的安装,让我们创建一个入口资源来接收来自万维网的流量!

注意:最初安装控制器时,没有创建任何负载平衡器服务,也没有创建任何类型的 AWS 负载平衡器,只有在创建第一个入口资源时,才会创建负载平衡器。

照片由亚历克斯·科特利亚斯基在 Unsplash 上拍摄

空谈不值钱,给我看看代码!

好吧,好吧!以上步骤全部满足后,这里就是完整的 Nginx 栈。

Kubernetes 上完整的 Nginx 堆栈

下面是一些值得一提的注意事项。

  • 如果你的target-type是一个instance,你必须有一个NodePort类型的服务。因此,负载平衡器会将流量发送到实例的公开节点端口。如果你更感兴趣的是将流量直接发送到你的 pod,你的 VPC CNI 必须支持这个[source。
  • AWS 负载平衡器控制器使用您在入口资源上看到的注释来设置目标组、侦听器规则、证书等。您可以指定的内容列表包括但不限于健康检查(由目标组完成)、负载平衡器侦听器规则的优先级等等。阅读参考文件以获得可能实现的功能的完整概述。
  • ALB 从来自 ACM 的tls部分定义的配置中获取证书信息,您需要做的就是确保这些证书存在并且没有过期。

应用上述定义,您将在集群中得到以下内容:

获取 Nginx 入口资源

结论

在 AWS 这样的云解决方案中管理 Kubernetes 有其挑战性。我认为,他们有很好的营销理由来实施这种挑战,因为他们希望你尽可能多地购买他们的产品,而使用像 Kubernetes 这样的云不可知工具对这一目标没有太大帮助!

在本文中,我解释了如何设置 AWS 入口控制器,以便能够在 AWS EKS 内部创建入口资源。

作为最后一个建议,如果你打算用 AWS EKS 来管理你的 Kubernetes 集群,我强烈推荐你用[eksctl](https://eksctl.io/)来试试,因为它会让你的生活变得更加轻松。

祝你今天休息愉快,敬请关注,保重!

参考

  • https://kubernetes.io/docs
  • https://helm.sh
  • https://aws.amazon.com/eks/
  • https://eksctl.io
  • https://github.com/cncf/curriculum
  • https://kubernetes-sigs . github . io/AWS-load-balancer-controller/v 2.4/
  • https://github.com/aws/eks-charts
  • https://artifacthub.io

如果你喜欢这篇文章,看看我的其他内容,你可能也会觉得有帮助。

https://medium.com/skilluped/what-is-iptables-and-how-to-use-it-781818422e52 https://medium.com/skilluped/stop-writing-mediocre-docker-compose-files-26b7b4c9bd14 https://medium.com/amerandish/clean-architecture-simplified-223f45e1a10 https://medium.com/amerandish/a-tmux-a-beginners-guide-7c129733148

作为一名没有经验的新数据科学顾问,如何让自己获得成功

原文:https://towardsdatascience.com/how-to-set-yourself-up-for-success-as-a-new-data-science-consultant-with-no-experience-a0a94fc4710f

作为数据科学顾问设置基础的 7 分钟指南

Jef Willemyns 在 Unsplash 拍摄的照片

作为一名新的数据科学毕业生,在这个竞争异常激烈的市场中找工作可能会很痛苦。

300 份申请过去了,你还在为同一个初级职位与 500 名其他申请人竞争。然而,尽管有些人可能会说,作为一名新的数据科学家进行咨询是完全可能的。当你可以创造自己的工作时,为什么要和一堆申请人竞争呢?

数据科学家,即使是那些刚刚毕业的人,也有一套独特的技能,可以用来在各种场景下帮助客户,而不需要任何传统的公司工作经验。诀窍是要有足够的耐心、韧性和韧性来建立你的咨询业务。为自己工作可能会令人害怕,但数据科学家很幸运,他们拥有急需的技能,可以用来为希望从数据中获得更多价值的客户提供一次性服务(甚至重复工作)。

本指南将帮助您在 7 分钟或更短的时间内开始发展您自己的数据科学咨询工作。

如何选择你的专业

尽管对数据科学家的普遍要求是“百事通”,但作为一名顾问,意味着你会希望选择一个专业,以避免因压力而发疯。

例如,您可能会觉得使用一些简单的工具来提供不需要机器学习或人工智能的分析最舒服。这种类型的专业将专注于数据分析师任务,例如使用 Excel 清理数据,使用 Python 进行简单分析,以及使用 Tableau 或其他类似工具开发可视化。

或者,你可能会在创建预测性机器学习模型的数学丛林中茁壮成长,这些模型涉及人工智能,以帮助客户预测他们业务的未来。

关键是要知道自己擅长什么,并专注于此。独自出去做顾问已经够可怕的了——要确保你是在推销和使用你擅长的技能。相信你可以使用你选择的工具和技能成功地产生结果,这对成为一名成功的顾问大有帮助。

此外,做一些市场调查,看看你的利基可以奠定。虽然他们说数据科学家一开始都应该是多面手,但我认为顾问应该专注于补充他们技能和替代知识的专业领域。例如,我将专注于成为一名数据科学顾问,专门帮助公司解决环境问题——这将把我的专业技能(数据科学)与我在环境科学方面的替代知识和教育背景结合起来。公司喜欢与在本行业拥有第一手经验的顾问合作,因此发挥你的优势、过去的工作经历、教育背景或兴趣背景不会有什么坏处。

如何推销你的技能

开始推销你的技能的最简单的清单是:(1)建立一个文件夹;(2)开始联网;以及(3)参加行业活动。作为一名新的数据科学顾问,这三项任务是推销你技能的基石。

建立你的投资组合将有助于潜在客户更好地了解你能提供给他们的服务类型。你的投资组合应该充满与你计划提供的服务相关的项目——当你计划提供客户保持数据服务时,预测股票市场并不是你技能的一个很好的指标。

建立关系网是你的下一个任务,将涉及到接触你认识的每一个人:过去的同学、老师、朋友和家人。许多人建议给你当地黄页上列出的每一家企业打电话,但我发现与你认识的人联系可以带来更个性化的推荐。当你认识的某个人代表你向潜在客户伸出手时,你和那个潜在客户之间的个人联系就立刻形成了。然后你可以利用这种人际关系来发展付费客户。然而,你必须确保你通过这种方式赢得的每一个客户都获得了你服务的黄金标准——你的个人联系人为你冒了很大的风险,所以你必须回报他们,像他们说的那样为这个客户做得很好。这些是你应该为之付出额外努力的客户,通过建立交互式仪表盘,开发定制报告,并确保额外的客户服务和关注。

最后,参加行业活动是与你不认识但想成为客户的人建立关系网的好方法。所有行业都需要数据服务,这意味着您不必将自己局限于特定于数据科学的网络活动。如果有的话,你想在一个互补的行业中脱颖而出,而不仅仅是一个寻找客户的顾问。例如,去参加你的目标行业的行业活动,成为一名数据科学顾问,与潜在客户建立联系。

我得到的在社交或行业活动中取得成功的最好建议之一是,在你的名片上有一个二维码,可以直接带人们去你的作品集或网站。这是加快联系过程的好方法,有助于从一开始就引导潜在客户了解什么是重要的。

如何找到客户

在你搞清楚自己的数据科学专业并把自己推销成一名新顾问后,你需要了解寻找客户的不同方式。幸运的是,对于数据科学家来说,有几种选择。

找到客户的第一个方法是为你所在地区的小企业做公益工作,开发一些项目并赢得信誉。无偿服务是在简历中加入一些经验的好方法,也是建立一个展示对客户产生真正影响的项目组合的好方法。您可以通过联系小型企业并提供定制服务来帮助他们解决数据问题,从而获得这些客户。由于你免费提供高质量的工作,这些客户也更有可能为付费客户提供很好的参考。

获得客户的下一个方法是成为客户的首选数据科学顾问。通过积累一个小的客户群,在那里你是关键人物,你创造了一个完美的口碑环境,向其他类似的潜在客户传播你的证书、技能和服务。这也是留住客户的最好方法——通过留下来为你喜欢的和喜欢你的客户做额外的工作(甚至是兼职),你建立了有价值的联系,这将在未来几年提供工作。此外,您为这些客户做的任何后续工作都将很容易,因为您将熟悉他们的数据结构、系统、商业信念和目标。

让客户成为新的数据科学顾问的最后一个方法是与外包工作的公司竞标微型项目。有时,大公司会竞标 RFP,然后外包合同中的一些活动。这些小工作可能只处理整个数据项目的几个小方面,但却是你进入职场和在简历上积累经验的好方法。

如何为你的服务定价

成为数据科学顾问的最大问题是如何为你的服务定价。为了让这篇文章简洁明了,我能给出的唯一一条对所有地区和新咨询顾问都足够通用的建议是:不要低估自己。

当然,说你会为任何事情工作是很诱人的。但是你怎么通过给花生打工来展示你的素质和能力呢?

当客户雇佣顾问时,他们不一定想要最便宜的。有了数据科学咨询,您将物有所值。这意味着大多数客户都在寻找一个物有所值的人,而不是高端的镜花水月或者低端的令人失望。

考虑到有多种不同的方式为你的服务收费,定价可能会很棘手。以为例,您可以通过设定产品价格、基于价值的费用或按结果付费的模式,按小时、按月收取费用。按小时计费是不言自明的,就像的月聘模式一样,你每个月的工作费用都是固定的。或者,你可以通过一套产品来销售你的服务,你可以按固定费用或不同层级产品的不同价格来销售(想想交互式仪表盘、报告、高级定制等)。基于价值的定价是通过你和你的客户之间的协议确定的,他们根据你为公司工作的价值决定给你多少报酬。你可以为你的服务定价的最后一种方式是通过按结果付费模式,如果你的服务没有改善客户的业务,你就不会得到报酬。

作为一名入门级)数据科学顾问,你可以考虑每小时收费 200-250 美元,随着你获得更多经验,每小时收费可以超过 300 美元。这将因您提供独特服务的行业而异,对于石油和天然气行业的客户,您可能需要提高费率,而对于小型企业,您可能需要降低费率。

订阅让我的故事直接发到你的收件箱:故事订阅

请成为会员,使用我的推荐链接获得无限制的媒体访问权限(我将免费向您收取少量佣金):媒体会员

通过捐赠来支持我的写作,以资助更多像这样的故事的创作:捐赠

如何与 Mercury 或 Voilà共享您的 Jupyter 笔记本

原文:https://towardsdatascience.com/how-to-share-your-jupyter-notebook-with-mercury-or-voil%C3%A0-2177110d2f6e

数据可视化

使用 Mercury 或 Voilà将您的 Jupyter 笔记本放在网络上相当容易,但哪一种更容易呢——下面是这两种技术的简单比较

这两个应用程序,作者图片

在网上分享你的数据应该简单而有效。

你想把时间花在分析数据和产生结果上,对吗?演示很重要,但越简单越好。

Mercury 和 Voilà都是可以将你的笔记本自动转换成交互式网络应用的工具。我们要看看哪个更容易和/或更好。

为了说明使用 MercuryVoilà 之间的区别,我将通过一个简单的应用程序从一个数据集生成一些交互式图形。

将有两个版本:第一个是简单的笔记本,我们将使用 Mercury 框架将其转换为交互式应用程序;第二个使用 ipywidgets ,因此交互内置于笔记本中,并使用Voilà 作为网页。

然后我们会考虑哪种方法更好。

应用程序很简单,从 csv 读取伦敦的天气数据,并生成一个应用程序,显示所选年份每月的四个值的图表,最高温度最低温度降雨量日照时数。使用滑块控件选择年份。

第一种方法是使用水银。Mercury 将任何普通的 Jupyter 笔记本转变成一个网络应用程序。

为了包含交互,你需要在笔记本开头的一个特殊的 raw 单元格中定义小部件。下面是我为本文创建的一个:

---
title: Exploring London Weather Data
description: Use Mercury to make a web app from a Jupyter notebook
show-code: False
params:year:input: sliderlabel: Select yearvalue: 1952min: 1952max: 2018
---

在一些描述性的值定义之后是一个params部分。这指定了变量year被绑定到一个输入控件,并为该控件定义了一些值(这些值是不言自明的)。

这必须是笔记本中的第一个单元格;第二个单元格应该定义绑定了控件的变量。在我们的案例中:

year = 1952

接下来是笔记本的其余部分——我已经在一个代码单元中编写了整个应用程序。

作者图片

正如您在上面的代码中看到的,我们将一个 csv 文件读入 Pandas 数据帧。数据从 1948 年开始,一直持续到 2018 年。这是 1962 年的数据:

数据来源:作者,来自英国气象局发布的公开数据

然后,我们使用由year的值选择的数据帧的子集绘制图表:

weather[weather['Year']==year].plot(…)

如果你运行笔记本,你会看到 1952 年的图表,这是我们为year设定的初始值。

然而,如果我们从笔记本中创建一个 Mercury 应用程序,并在我们的网络浏览器中运行,我们将看到交互式应用程序。

水星应用程序,作者图片

滑块显示在左侧面板中,图表显示在右侧面板中。要更改年份值,我们移动滑块,然后点击运行按钮,一组新的图表将会显示出来。

当然,要创建 Mercury 应用程序,你需要安装 Mercury,

pip install mljar-mercury

或者

conda install -c conda-forge mljar-mercury

在终端窗口中,导航到笔记本所在的目录并运行命令:

mercury run

该应用程序将在本地主机上运行:127.0.0.1:8000

第二种方法是使用 Voilà从笔记本创建一个 web 应用程序,为此我们需要使用 ipywidgets 来创建交互控件。

因此,这里没有特殊的单元格,整个代码(我承认有点难看)都在一个单元格中:

为图表定义了四个小部件,为标题定义了一个小部件,这些小部件显示在一个 4 x 2 的网格中。每个图表部件都绑定到一个 slider 部件,该部件在第 38 行定义,并显示在最后一个网格位置。

其结果是,笔记本本身是交互式的,但当与 Voilà一起转换时,就变成了一个独立的网络应用程序。

作者图片

要转换笔记本电脑,您需要安装 Voilà:

pip install voila

或者

conda install -c conda-forge voila

在笔记本目录中,在终端窗口和弹出的网页中运行命令voila,导航到笔记本。

我倾向于认为代码的不雅是由于 ipwidgets 的限制——你可能有不同的看法!

选择哪一个

那么,哪种方法是最好的呢?

起初,我倾向于支持 Voilà 因为交互是即时的,当你移动滑块时,图表会立即改变。非常好。但缺点是(即使在这个非常简单的应用程序中)代码也比其他情况下复杂,这完全是由于使用了 ipwidgets。

Mercury 方法是添加定义控件的额外单元格,并将它们绑定到笔记本中的变量。缺点是笔记本本身不是交互式的(当然,应用程序是),但它的好处是更简单,因为笔记本专注于重要的东西,数据分析,而不是交互。

水银解决方案也需要按下按钮来实现改变。但这是一个缺点吗——也许浮华的动态图表有点被高估了。

我不会在这件事上下定决心。您可以下载代码(参见下面的链接)并查看产品网站(也链接到下面的),然后自己做出决定。

关于如何将应用程序部署到公共网络主机(如 Heroku)的说明,请访问 Voilà和 Mercury 网站。

一如既往地感谢您的阅读,如果您想知道我何时发布新文章,请考虑注册下面的电子邮件提醒或订阅我在 Substack 上的免费临时简讯。

如果你还不是一个媒体订阅者,那就注册吧,这样你就可以每月花 5 美元阅读尽可能多的文章。在这里注册,我将赚取一小笔佣金。

密码

你需要的三个文件在我的 Github 库里,直接链接在这里:

heathrowDataFiltered 。战斗支援车

heathrowdatamercury 2 . ipynb

heathrowdatawidgets 2 . ipynb

参考

我所使用的三种技术的网站如下:

<https://mljar.com/mercury/> 

如何在 Tableau 中显示和隐藏过滤器

原文:https://towardsdatascience.com/how-to-show-and-hide-filters-in-tableau-290b8b6c5c83

了解如何通过添加“显示/隐藏过滤器”按钮来改进您的仪表板设计,并释放仪表板中的视觉空间。

隐藏的过滤器仪表板(作者图片)

对于本教程,我们将使用从 UCI 机器学习资源库[2]下载的在线零售数据集 [1]。它包含来自虚构零售商的销售订单数据。我们对构建收入图表感兴趣,我们通过将数量乘以单价来计算收入。

收入折线图(作者图片)

为了让我们的最终用户能够深入了解对他们重要的数据,我们添加了针对国家描述股票代码的过滤器。这些过滤器自动添加到图表的右侧,作为一个通配符匹配多值(列表),它通常显示所有的值,并允许用户勾选他们感兴趣的值。当只有很少的值可供选择和很少的过滤器时,这很好,但是随着列表变大,这就变得难以控制了。

对于这个例子,我们将把我们所有的过滤器多值下拉。

下拉过滤器(作者图片)

这个仪表板通常做我们想要它做的事情,但是设计感觉不完整和笨拙。如果我们可以将每个筛选器制作成一个下拉列表,将图例移动到标题,添加一个开关来显示和隐藏筛选器,并在图表上显示选定的筛选器,会怎么样?它可能看起来像这样:

带过滤器的月度收入图表(图片由作者提供)

如何创建仪表板

从我们最初的仪表板开始,我们首先通过单击向下箭头符号并选择*多值(下拉)选项将所有过滤器转换为下拉列表。*对每个过滤器重复此步骤。

过滤器(图片由作者提供)

可选步骤

当我们对标题进行更改时,我们还可以向描述中添加过滤器,以便我们可以清楚地调出我们在图表上显示的内容。这是一个很好的步骤,可以向可能截屏最终视觉效果的用户提供图表实际上被过滤的内容的知识。这里的风险是,我们有太多的类别,我们不能以良好的方式将其可视化。

编辑标题(图片由作者提供)

现在我们已经解决了图表和过滤器的一些基本问题,我们可以回到仪表板了。在仪表板上,确保选择包含所有过滤器的容器,并选择添加显示/隐藏按钮。

这将创建一个按钮,隐藏过滤器所在的整个容器。您可以通过 alt 单击来切换隐藏或显示过滤器。

虽然这对于大多数人来说已经足够了,但我发现平铺视图有些混乱,我更喜欢让容器浮动。我们还将应用一些容器的浅色格式。(在本例中,我们添加了简单的边框和背景色)

就这样——我们成功地在 Tableau 仪表板上添加了一个显示隐藏按钮,并创建了一个更加简约的仪表板。我们的最终仪表板允许我们按需隐藏和显示过滤器。

最终仪表板(图片由作者提供)

[1]陈大庆、赛梁赛恩和郭昆,在线零售业的数据挖掘:使用数据挖掘进行基于 RFM 模型的客户细分的案例研究,《数据库营销和客户战略管理杂志》,第 19 卷,第 3 期,第 197-208 页,2012 年(印刷前在线出版:2012 年 8 月 27 日)。doi: 10.1057/dbm.2012.17)。

该数据集获得了知识共享署名 4.0 国际 (CC BY 4.0)许可。

[2]Dua d .和 Graff c .(2019 年)。 UCI 机器学习资源库。加州欧文:加州大学信息与计算机科学学院。

如何在 React 中使用无限滚动显示数据

原文:https://towardsdatascience.com/how-to-show-data-using-infinite-scroll-in-react-7c7c8540d5b4

使用反应大师

照片由胡安乔·哈拉米略在 Unsplash 上拍摄

这里有多种向用户显示数据的方式,例如分页和无限滚动。我们可以根据情况选择它们中的任何一个或一些变体——例如,使用 Load More 按钮加载数据。

在这篇文章中,我们将实现无限滚动。可以描述如下。当用户向下滚动时,下一组数据从服务器加载,并添加到前面数据的底部,形成无缝的用户体验。除非没有更多的数据要加载,否则重复这种技术。

在实现无限滚动后不久,您可能会因为重新呈现数千个项目而遇到与性能相关的问题。为了解决这个问题,我们可以使用列表虚拟化或者窗口技术。在这个方法中,我们将只呈现对用户可见的项目。当用户上下滚动时,窗口将上下移动。因此,我们将最终重新呈现列表的一个子集。最后,它将提高性能和用户体验。

显示包含数千个项目的列表与显示项目子集——按作者排序的图片

我们将使用 React Virtuoso 库,它实现了列表虚拟化方法。它还提供了其他很酷的功能,如滚动到索引、自动调整内容大小、带有粘性标题的分组模式等。

设置

对于这个设置,我们将创建一个 React 应用程序。你可以从 GitHub 下载最终的项目。首先,我们将使用 create-react-app (CRA)工具创建一个 react 应用程序。

npx create-react-app react-infinite-scroll

现在让我们将 React Virtuoso 库添加到我们的应用程序中。

cd react-infinite-scroll
npm install react-virtuoso

我们可以使用下面的命令启动我们的应用程序。

npm start

我们的初始设置已经完成,我们可以开始编码了。在这个应用程序中,我们将在用户每次滚动到底部时加载随机数。在现实生活中,这个函数可以由对服务器的 API 调用来代替。

两种类型的滚动——按作者滚动图像

厉害了,现在来说说布局吧。在左侧,我们使用 React Virtuoso 提供的滚动,在右侧,我们使用自己定制的滚动。

左手边的 React Virtuoso 设置。

<Virtuosostyle={{ height: 400 }}data={numbersLeft}endReached={loadMoreLeft}itemContent={(index) => (<div className="scrollLeft"><div><h1>{numbersLeft[index]}</h1></div></div>)}
/>

反应右侧的 Virtuoso 设置。

<div className="scrollRightParent" ref={parentRef}><Virtuosostyle={{ height: "100vh" }}data={numbersRight}endReached={loadMoreRight}useWindowScrollcustomScrollParent={parentRef.current}itemContent={(index) => (<div className="scrollRight"><div><h1>{numbersRight[index]}</h1></div></div>)}/>
</div>

为了使用我们的自定义滚动,我们需要传递两个额外的属性(props) useWindowScrollcustomScrollParent。你可能想要使用其他的大师道具,这些可以在大师 API 文档中找到。

在这篇文章中,我们讨论了与渲染大型列表相关的性能问题以及解决方案。我们还学习了如何使用 React Virtuoso 库通过显示用户可见的项目来提高性能。此外,我们已经演示了两种不同类型的滚动行为。正如我在本文开头提到的,使用 React Virtuoso 库创建所需的应用程序还可以实现其他一些很酷的事情。编码快乐!

相关帖子

如何简化 Azure Synapse 管道的创建

原文:https://towardsdatascience.com/how-to-simplify-creating-azure-synapse-pipelines-e33833abb4d

了解管道的结构

照片由 JJ 英在 Unsplash

TLDR

  • Azure Synapse 管道由什么组成

  • 通过提前创建数据集,使 Azure Synapse 管道流程更加简单

  • 这是一个关于如何创建 Azure Synapse 数据集的视频

  • 利用模板创建管道

在我之前的文章中,我提到过管道是 Azure Synapse 的顶级特性之一。现在让我们更深入地了解它们是什么以及如何使用它们。

Azure Synapse 中有哪些管道

Azure Synapse 中的管道与 Azure 数据工厂管道相同。它刚刚被嵌入 Azure Synapse Studio。它可以定义为一种将活动组合在一起以创建作业的方式。它也是一个低级代码,让您能够在工作的旅程中跟踪迭代。

要理解管道,你需要知道它如何与其他 Azure Synapse 数据术语(如“数据集”和“活动”)结合在一起。看看下面的图片。这表明需要一个数据集来创建一个活动并且一个活动可以被视为一个管道的逻辑分组

Azure Synapse 管道剖析—图片由作者提供

如何创建管道

要在 Synapse 中创建管道,您需要转到 Integrate 部分,然后您会看到创建新管道的选项

作者图片

在左侧,您有所有的活动,在中间的空白区域,您可以将活动拖动到空白区域以开始流程。活动的例子有拷贝作业、数据流、查找、迭代和过滤器等条件。在活动中,您可以包含数据集。

一旦您完成了管道的创建,您将需要发布它。然后,您可以运行它来验证它的工作没有错误。您可以通过将管道作为计划作业来运行,从而更进一步。

如何使创建管道更容易

如果您不了解所有的构造块,创建管道可能会很有挑战性。我发现在创建管道时有一点很有帮助,那就是确保提前创建数据集。在本博客开头的视频中,我展示了如何创建数据集,以及一旦数据集已经创建,如何更容易地创建我的管道。

在 Azure Synapse 中创建管道是运行高效 ETL 或 ELT 流程的一个好方法。在管道之前做好基础准备是最大但最简单的部分之一,它使这个过程更容易创建和发布。如果你被困住了,需要一些创建管道的灵感,看看管道下面的图库部分(如下图红框所示)。

作者图片

您将看到不同类型的管道选项,您可以使用它们快速开始。如果你不确定管道应该是什么样子,这就是你要去的地方。

作者图片

结论

在基于云的解决方案(如 Synapse)中创建管道可以更容易地执行 ETL / ELT 作业。确保创建数据集并使用模板,可以更轻松地创建管道。敬请关注其他与数据相关的内容。

如何在 Python 中简化线性回归的假设检验

原文:https://towardsdatascience.com/how-to-simplify-hypothesis-testing-for-linear-regression-in-python-8b43f6917c86

统计数字

什么是同性恋?

爱德华·豪厄尔在 Unsplash 上拍摄的照片

我发现自己一遍又一遍地回到基础知识来更新我的统计知识。大多数人对统计学的第一次介绍是从学习假设检验开始的,紧接着是 t 检验和线性回归。本文回顾了如何使用线性回归进行假设检验,以及为了信任线性回归统计检验的结果而必须满足的假设。我还想分享一个我制作的 Python 函数,它可以快速检查使用线性回归进行假设检验时需要满足的 5 个统计假设。

关于线性回归的快速提醒

在我分享进行线性回归假设检验应该满足的 4 个假设之前,关于线性回归,有一点需要记住。线性回归可以被认为是一种双重用途的工具:

  1. 预测 y 变量的未来值
  2. 推断趋势是否具有统计显著性

记住这一点很重要,因为这意味着如果使用回归来预测未来值,您的数据不必满足线性回归假设检验的要求。如果您试图确定是否存在实际趋势(也就是趋势具有统计学意义),您需要满足假设检验假设。

线性回归和机器学习

与机器学习相比,传统统计学更多地与数据中信号的推断相关联;而机器学习更侧重于预测。在可供机器学习选择的所有模型中,线性回归是您可以使用的最简单的模型之一,通常在基于连续数据构建新的机器学习模型时用作基准(如果您正在处理分类数据,则逻辑回归将是等效的)。你可以看到为什么统计学和机器学习都是作为数据专业人员的必要工具。需要记住的一个很好的提醒是,统计学更倾向于推理,而机器学习更倾向于预测。也就是说,同样值得注意的是,统计学首先为机器学习提供了基础。

为什么线性回归假设检验很重要

假设检验帮助我们确定我们的数据中是否有足够的信号来确信我们可以拒绝零假设。本质上,它回答了这样一个问题,“我能对我在数据中看到的模式有信心吗,或者我看到的只是噪音?”我们使用统计学来推断数据中存在的关系和意义。

现在,为了使用线性回归假设检验从我们的数据中做出推论,我们需要确定我们在检验什么。为了解释这一点,我需要分享这个简单的公式:

y = mx + b

我想大多数学过高中数学的人都会记得,这是一条直线斜率的方程。

就线性回归而言,该公式的更正式表示为:

作者图片

其中 B0 是截距,B1 是斜率。x 和 Y 分别代表自变量和因变量,ε是误差项。

直线斜率(B1)的线性回归假设检验如下所示:

作者图片

这些数学符号表示零假设(Ho)是斜率(B1)等于 0(即斜率是平坦的)。另一个假设(Ha)是斜率不等于 0。

补充说明:还有一种假设检验很少用于线性回归,这是一种关于截距的假设。因为我们通常关心直线的斜率,所以用得较少。

线性回归假设检验的 4 个假设

  1. Y 和 X 之间存在线性回归关系
  2. 误差项(残差)呈正态分布
  3. 误差项的方差在所有 X 值上都是恒定的(同方差)
  4. 误差项是独立的

为了演示测试这些线性回归的统计假设,我们需要一个数据集。我将使用 R 标准库中的 cars 数据集。数据集非常简单,如下所示:

pip install rdatasets
from rdatasets import data as rdatadat = rdata("cars")
dat

汽车数据集-按作者分类的图像

我们将预测一辆 1920 年的汽车在给定的速度下停下来之前的行驶距离。

让我们首先创建线性回归模型,然后执行检查假设的步骤。

边注:技术上有第五个假设,X 值是固定的,测量没有误差。然而,这种假设并不是你要创建的诊断图,所以被忽略了。

在 R 和 Python 中创建线性回归诊断图

我通常用 Python 编写代码,但是我想展示如何用 R 和 Python 创建线性回归模型,以展示在 R 中检查统计假设是多么容易。

R 中的线性回归

cars.lm <- lm(dist ~ speed, data=cars)

然后,为了检查假设,您需要做的就是调用绘图函数并选择前两个绘图

plot(cars.lm, which=1:2)

这将为您提供以下图表:

作者图片

作者图片

第一个是残差与拟合图,第二个是 QQ 图。我将在下面更详细地解释这两个情节。

这两个图几乎是你测试上述 4 个假设所需要的全部。在 Python 中似乎没有像在 R 中那样快速简单的方法来检查线性回归假设,所以我做了一个快速函数来做同样的事情。

Python 中的线性回归

这就是在 Python 中对相同的 cars 数据集运行线性回归的方式:

from statsmodels.formula.api import ols
from rdatasets import data as rdatacars = rdata("cars")
cars_lm = ols("dist ~ speed", data=cars).fit()

补充说明:R 中的线性回归是内置函数的一部分,而在 Python 中,我使用的是 statsmodels 包。

然而,要获得上述两个相同的诊断图,您必须分别运行以下命令。

Python 中的 QQ 剧情

import statsmodels.api as sm
import matplotlib.pyplot as pltresiduals = cars['dist'] - cars_lm.predict()
sm.qqplot(residuals, line='45', fit=True) 
plt.title('QQ Plot')
plt.show()

作者图片

残差 vs 拟合 Python

from statsmodels.formula.api import ols
import statsmodels.api as sm
from rdatasets import data as rdata
import matplotlib.pyplot as plt# Import Data
cars = rdata("cars")# Fit the model
cars_lm = ols("dist ~ speed", data=cars).fit()# Find the residuals
residuals = cars['dist'] - cars_lm.predict()# Get the smoothed lowess line
lowess = sm.nonparametric.lowess
lowess_values = pd.Series(lowess(residuals, cars['speed'])[:,1])# Plot the fitted v residuals graph
plt.scatter(cars['speed'], residuals)
plt.plot(cars['speed'], lowess_values, c='r')
plt.axhline(y=0, c='black', alpha=.75)
plt.title('Fitted vs. Residuals')
plt.show()

作者图片

用于线性回归诊断图的简化 Python 函数

创建上面的图所需的努力并不太可怕,但仍然比我每次检查线性回归假设时需要输入的要多。除了 QQ 图之外,我还想有更多的诊断图,例如用于检查正态分布的直方图。我还想用另一个图来检验假设 4,即误差项是独立的。

所以我做了一个 Python 函数来快速检查 OLS 假设。我将在以后引用这个函数,希望你也会觉得它有用。我在下面加入了要点,但是函数保存在 git repo 这里。欢迎提出改进建议。

作为旁注,我在这里 找到了另一篇关于用 Python 创建 R 诊断图的博文

如果我将 cars 数据集传递到 check_ols_assumption 函数中,我将得到以下诊断图输出:

cars = rdata("cars")
cars_lm = ols("dist ~ speed", data=dat).fit()check_ols_assumptions(cars['speed'], cars['dist'], cars_lm.predict())

作者图片

线性回归假设检验假设解释

既然我已经分享了我在 Python 中为快速线性回归假设测试创建的函数,我想快速回顾一下如何解释诊断图,以及诊断图如何帮助确定是否满足线性回归假设。

  1. 线性关系

确定线性度的诊断图是拟合残差图:

作者图片

X 轴上的拟合值是从线性回归预测的值。Y 轴上是残差,即预测值(拟合值)和实际 Y 值之间的差值。

如果图中没有明显的趋势,则假定满足线性关系。上面的图满足了这个假设。以下是一个不符合这一假设的诊断图示例:

# Create a synthetic dataset
np.random.seed(42)
x_var = np.arange(0,10,.1)
y_var = np.sin(x_var)data = pd.DataFrame({'x_var':x_var, 'y_var':y_var})ols_result = ols("y_var ~ x_var", data=data).fit()
check_ols_assumptions(data['x_var'], data['y_var'], ols_result.predict())

作者图片

此图显示了正弦函数的线性回归模型的残差。因为有一个明显的趋势(散点图值和 lowess 回归的红线所示),所以不符合 X 和 Y 之间的关系是线性的假设。

边注:想了解更多关于洛维斯回归的信息,请点击这里

2。误差项呈正态分布

记住这一假设的关键点是,X 或 Y 变量不必呈正态分布,需要呈正态分布的是误差项或残差。另一个需要记住的要点是,仅仅因为图是线性的,并不意味着分布可以被认为是正态的。

以下是用于检查误差项(残差)是否正态分布的诊断图:

作者图片

我使用 QQ 图和直方图来检查正态性。如果 QQ 图点大致与 45 度线对齐,则满足此假设。另一种检查方法是直方图,如果分布遵循正态(高斯)钟形曲线,残差可以视为正态。要了解更多关于 QQ 情节的信息,请参考本文这里。

3。误差项的方差在所有 X 值上保持不变

拟合的 vs 残差图再次用于确定方差是否恒定。以下是再次供参考的情节:

作者图片

如果残差的垂直分布在所有拟合值中保持大致一致,则假设满足恒定方差假设。cars 数据集看起来可能不太符合这个假设。下面是一个更清晰的数据集示例,它不符合这一假设:

*# Create a synthetic dataset
np.random.seed(42)
x_var = np.arange(0,10,.1)
y_var = np.random.normal(0,.1,100) * x_vardata = pd.DataFrame({'x_var':x_var, 'y_var':y_var})ols_result = ols("y_var ~ x_var", data=data).fit()
check_ols_assumptions(data['x_var'], data['y_var'], ols_result.predict())*

作者图片

本例显示了随着 X 值的增加,数据如何开始进一步扩散。这违反了这一假设,因为随着 X 值的增加,数据扩散得越来越远。

4。误差项是独立的

只有当您知道数据收集的顺序时,才能验证这一假设。最常见的情况是,当数据集中存在时间组件时,可以检查这一点(但是通过使用时间列,您可以假设数据收集的时间与该列的时间相同)。如果在一段时间内残值有一个趋势,那么这个假设就违背了。

如果值已经处于正确的顺序,它看起来将与拟合与残差图相同。上面的 check_ols_assumptions 中有一个默认参数,如果时间变量存在于数据集中,则可以传递该参数。

作者图片

结论

现在你有了,一个关于使用线性回归进行统计分析的快速复习。我希望你会发现 check_ols_assumptions 函数很有用,如果你有任何反馈,请告诉我😄

感谢阅读!如果你喜欢读这篇文章,请在 LinkedIn 上与我联系,并查看我的其他文章。

如果你是中级新手,可以考虑使用下面的我的推荐链接订阅👇

*https://medium.com/@andreasmartinson/membership

参考

  1. J.戴维森,不,机器学习不仅仅是美化统计学 (2018),走向数据科学
  2. R.阿尔瓦雷斯,用 Python 创建诊断图以及如何解释它们 (2018),罗伯特。Alvarez.github.io
  3. 页(page 的缩写)Varshney, Q-Q 图解释 (2020),走向数据科学
  4. 南 Dobilas,Python 中的 LOWESS 回归:如何在你的数据中发现清晰的模式? (2020),走向数据科学*

如何用机器学习解决一个分类任务

原文:https://towardsdatascience.com/how-to-solve-a-classification-task-with-machine-learning-b73b4aa0cbf6

使用机器学习为贷款申请人构建二元分类器

梁杰森在 Unsplash 上的照片

前言

这篇文章延续了我上一篇关于使用德国信用数据集进行探索性数据分析的文章。如果你没有读过我以前的文章,我建议你读一读,这样你可以对数据集有更好的了解。我将指导你如何使用机器学习方法处理德国信用数据案例研究。这个案例研究是一个很好的例子,说明机器学习如何用于解决一个实际的金融问题。完整的项目可以在我的 GitHub 上找到,我会在本文结尾留下链接。

介绍

到目前为止,我相信你已经听过很多机器学习这个术语了。这是信息技术领域的一个热门话题。由于大多数大公司和金融机构都依赖数据进行如此大规模的运营,因此数据科学领域的发展也就不足为奇了。但是机器学习到底是什么,我们如何在实际意义上使用它?

什么是机器学习?

机器学习是在没有明确编程的情况下赋予计算机学习能力的研究领域。

阿瑟·塞缪尔,1959 年

在我看来,上面的引用是对机器学习的最好的一般性定义。这非常有用,因为大多数机器学习概念允许用户向计算机算法输入大量数据,并让计算机仅根据输入数据进行分析并做出数据驱动的建议和决策。本文中的案例研究将回顾一个流行的机器学习概念,称为分类。

分类

在机器学习(ML)中,分类是一个监督学习概念,它将数据分组到类中。分类通常是指任何类型的问题,其中特定类型的类标签是从给定的数据输入字段中预测的结果。一些类型的分类任务包括:

  • 垃圾邮件过滤
  • 顾客行为
  • 图像分类
  • 信用卡欺诈检测

目标

德国信用数据集的目标是最大限度地减少向申请人发放高风险贷款的机会,同时最大限度地增加从优质贷款中获利的机会。贷款经理在对申请人的贷款申请做出决定之前,会考虑申请人的人口和社会经济状况。

德国信用数据集是从 UCI 机器学习库下载的公开可用数据集。德国信贷数据包含 20 个变量的数据,以及对 1000 名贷款申请人的申请人是否被视为良好或不良信贷风险的分类。该任务需要研究数据并建立预测模型,以便为银行经理提供指导,从而根据潜在申请人的个人资料决定是否批准向其提供贷款。

在这个案例研究中,我使用了原始数据集的简化版本,它只有 10 个变量:

  1. 年龄(数字)
  2. 性别(字符串:男性,女性)
  3. 工作(数字:0 —非熟练和非居民,1 —非熟练和居民,2 —熟练,3 —高技能)
  4. 住房(字符串:自有、租赁或免费)
  5. 储蓄账户(字符串—少量、中等、相当丰富、丰富)
  6. 支票账户(字符串—小额、中等、大额)
  7. 信贷金额(数字,单位为德国马克)
  8. 持续时间(数字,以月为单位)
  9. 用途(正文:汽车、家具/设备、收音机/电视、家用电器、维修、教育、商务、度假/其他)
  10. 风险(字符串—好的,坏的)

构建二元分类器

准备数据

在建立模型之前,首先要做的就是把问题框起来:是有监督的,无监督的,还是强化学习的?是分类任务,回归任务,还是别的?我们从探索性数据分析中知道,数据已经标记了目标变量(每个实例都带有预期输出,即贷款申请人的风险标签)。这也是一个典型的分类任务,因为我们被要求预测一个类别。更具体地说,这是一个二元分类任务,因为目标变量有两种类型。

导入库并读取数据集

下面的代码块使用 Pandas 库读取一个 CVS 文件,并将其格式化为一个数据帧,我们将使用该数据帧来检查我们的数据。

作者图片

特征工程

在建立模型之前,我们需要转换数据。我们将使用一种叫做特征工程的数据操作技术来转换数据。特征工程是指对数据集的操作(添加、删除、组合等),以改善机器学习模型训练,从而实现更好的性能和更高的准确性。

我们从探索性数据分析中得知数据集中有缺失值,因此第一次转换将删除缺失值的实例。

作者图片

既然丢失的值已经从我们的数据集中删除,我们可以继续下一个转换。

转换目标标签

从探索性分析中我们知道,目标列包含贷款申请人的标签。大多数机器学习算法更喜欢与数字打交道,所以我们需要将这些标签从文本转换为数字。这就是标签编码器派上用场的地方。LabelEncoder 将分类数据转换为数字数据。

作者图片

上图显示风险栏已经转换为数值。可以看到之前的文本值不再存在,取而代之的是 1 和 0 (1 代表,0 代表)。

创建新功能

有时,数据集中的默认要素可能没有足够的信息来处理。在这种情况下,我们可以用现有的数据创建新的特征,这就是为什么我创建了两个新的特征,分别叫做年龄类别信用类别。年龄类别采用申请人的给定年龄,并将他们分配到特定的年龄类别:学生(18-24 岁)、青年(25-34 岁)、成人(35-59 岁)、老年人(60-119 岁)。信用类别使用类似的方法,但时间间隔是基于信用而不是年龄。

作者图片

移除异常值

让我们看看数据集通过这些新功能给了我们什么新信息。我使用了一个交叉表来可视化这两个新类别之间的关系。

作者图片

上面的交叉表显示,只有一个实例的信用额大于 17,500 德国马克(DM)。这是一个很好的指标,表明数据集中预设了异常值。我们可以通过绘制年龄类别与信用额度的关系来仔细观察这个异常值。

作者图片

更清楚的是,存在一个异常值。但是在决定丢弃异常值之前,我们应该更仔细地研究一下具体的实例。

作者图片

通过查看特定的实例,我们可以对为什么这个异常值出现在数据集中做出合理的结论。申请人的证书是这笔贷款被批准的最可能的原因。年轻且高技能的申请人有更高的机会还清高风险贷款;然而,贷款的目的是为了度假。如果我是一个银行经理,如果我的唯一目的是度假,我不会愿意发放任何超过 17,500 德国马克的贷款。这将是一笔风险很高的贷款,而且事实证明,申请人最终会拖欠贷款。我认为可以肯定的是,大多数银行经理都会说同样的话,不会批准贷款,所以我们最好从数据集中删除这个实例。

作者图片

上图是新的交叉表,离群值已从数据集中删除。

拆分数据

将数据集分成训练集和测试集是标准做法。这将确保模型被适当地训练,并且测试集上的性能被准确地测量。

作者图片

上面的输出帮助我们直观地看到每个分割有多少个实例。我们希望总实例的 80%进入训练集,另外 20%进入测试集。训练集应该总是比测试集有更多的实例。

转换管道

在向模型显示数据之前,还有一些转换必须以正确的顺序实现。数据集中的数字要素应具有相同的比例,以提高模型精度。数据集中的分类要素必须是数值,因为模型无法处理文本(字符串)值。幸运的是,Scikit-Learn 提供了管道ColumnTransformer 类来帮助完成这样的转换序列。

模型训练和混淆矩阵

我从 Sklearn 库中取了 8 个知名的分类器进行训练和评估。下面的代码块显示了我为训练所有模型所做的事情。我创建了一个循环,通过包含每个模型的列表迭代训练过程,而不必单独训练一个模型。在循环结束时,模型的表现会显示在混淆矩阵上。

准确性通常不是分类器的首选性能指标,尤其是当我们处理倾斜数据集时。评估分类器性能的更有效的方法是查看混淆矩阵

总体思路是统计 A 类的实例被分类为 b 类的次数。混淆矩阵中的每一行代表一个实际类,而每一列代表一个预测类。下图将帮助你想象出混淆矩阵的样子。

作者图片

让我们来看看第一个混淆矩阵,它是逻辑回归模型的性能度量。该矩阵的第一行考虑不良贷款(负类*):其中 83 个被正确分类为不良贷款(它们被称为真负类(TN) ),而剩余的 154 个被错误分类为好贷款(假正类(FP) )。第二行考虑好的贷款(正类 ): 62 个被错误地分类为坏贷款(假阴性(FN) ),而剩余的 500 个被正确地分类为好的贷款(真阳性(TP) )。一个完美的分类器将只有真阳性和真阴性,所以它的混淆矩阵将只在其主对角线上有非零值(左上到右下)。*

完美分类器上的混淆矩阵(图片由作者提供)

精确度、召回率和 F1 分数

混淆矩阵为您提供了大量信息,但有时您可能更喜欢更简洁的度量。这就是精确度、召回率和 f1 分数指标派上用场的地方。

  • 精度是正确预测的正观测值与总预测观测值的比率

  • 回忆 ( 灵敏度真阳性率)是正确预测的阳性观测值与实际阳性类的总观测值之比

  • F1 得分是精度和召回率的加权平均值或调和平均值。F1 得分倾向于具有相似精度和召回率的分类器。如果你需要一个简单的方法来比较两个分类器,它经常被使用。

使用哪个指标?

很难决定哪个指标是最好的。以精度和召回率为例。 precisionrecall 的问题在于,它们更多的是学术性的,因为它们优先考虑模型的性能,而不是实际的业务问题,后者可能需要更细微的度量。简单来说:

  • 精确度更重要,因为假阳性假阴性代价更高
  • 召回更重要,因为假阴性假阳性代价更高

我们希望开发一种机器学习算法来预测某人是否会还贷。假设我们的模型有 85%的精确度和 75%的召回率。这些数字到底是什么意思,低精度 / 召回有什么问题?

  • 85% 精度是指在所有被批准的贷款中,85%要还我们。其余 15%的获批贷款会出现违约。精确度低的问题在于我们批准的是违约贷款。
  • 75% 召回意味着 75%将偿还贷款的借款人得到了我们系统的批准。我们错过了 25%的会通过拒绝他们来回报我们的人。总的来说,召回率低的问题在于,我们拒绝了那些我们本会偿还的客户(以及我们本会为其赚取利息的客户)。

对于我们的案例研究,我们通常更喜欢强调精确度而不是召回,因为批准一笔坏账(并损失资本投资)比错过一笔好贷款可能带来的利润成本更高。

请记住,在精确度和召回率之间有一个权衡。精度越高,召回率越低,反之亦然。

让我们来看看模特们的表演。下面的代码块将输出每个模型的性能指标的数据帧。

作者图片

正如我们所看到的,模型的表现符合预期。准确性和 F1 分数高于 50%,这意味着我们的模型运行正确。

选择最佳模型

没有一个模特的分数比其他模特高。这可能会使决定使用哪个模型变得困难。除了 SGD 和 Cart 模型之外,所有模型似乎都表现相似,因为与其他模型相比,它们的准确性和 F1 分数都较差。

因为我们主要关心精度,所以我认为 XGB 模型是这个案例研究中使用的最佳模型。它的准确率为 79%,召回率为 86%左右。XGB 模型在所有模型中具有最高的精确度分数,同时还保持了良好的召回分数。

根据测试数据测量模型

评估模型的最后一个方法是传递一些以前从未见过的数据,然后测量性能。我们可以预期性能与我们看到的训练数据的性能相似。如果模型在测试数据上的表现比在训练数据上的表现差得多,这意味着模型没有正确表现。

作者图片

成绩还不错。分数在 50%以上,因此该模型在测试数据上表现良好。我们还可以做一些其他的优化调整来改进这个模型,但是我想我会在另一篇文章中讨论。

结论

考虑什么?

问题并没有到此结束。在这个案例研究中,还有许多其他事情需要考虑。该模型不应该是批准贷款的唯一决策者,而是应该用作一种工具,可以帮助金融分析师就贷款申请人做出更明智的决策。财务分析师应该充当人力管道,检查分类器对申请人的选择。

此外,我们必须对这里的业务问题稍加小心,因为我们正在对一个连续变量进行二进制化:在支付 5 年期贷款的 1 年后违约的人和在支付 5 年期贷款的 4 年后违约的人之间存在差异。一位银行经理可能会希望你把客户的预期损失和阈值作为一个更有用的指标,而不是精度。

现在,我们可以说我们已经成功地构建、训练和测试了一个分类器来解决这个案例研究中的问题。我希望这篇文章能帮助你迈向精通机器学习的旅程。

项目可访问性

  • GitHub
  • 笔记本
  • Kaggle 数据集

数据集引用

汉斯霍夫曼。(1994).Statlog(德国信用数据)。UCI 机器学习知识库

该数据集获得了知识共享署名 4.0 国际 (CC BY 4.0)许可。

约束参数空间中的机器学习优化器:内点法

原文:https://towardsdatascience.com/how-to-solve-constrained-optimization-problem-the-interior-point-methods-1733095f9eb5

深潜

约束参数空间中的机器学习优化器:内点法

从零开始使用 python 的完整分步案例研究

凯文·布茨在 Unsplash 上的照片

**Table of Contents**· [Motivation](#2f50)
· [Problem Statement](#dba4)
· [The Barrier Method](#6f43)
· [Experiments](#d152)∘ [Scenario 1](#af0e)∘ [Scenario 2](#8974)∘ [Scenario 3](#8f51)
· [Conclusion](#ef8e)

动机

在股票市场上,你是一个正派的交易者。你每天通过一些谨慎的策略优化你的利润,它没有限制:你可以在一天内赚很多(正利润),也可以亏损很多,以至于你在推特上发了一个笑话(负利润)。因为对你优化的利润没有限制,所以你可以选择多种策略:做空股票,配对交易,甚至用它做一个几何布朗运动模型。

除了交易,你也是镇上伟大的园丁。你有三种植物,每天在最近的传统市场出售:西红柿、薄荷和菠菜。要获得最大利润,当然需要尽可能多的种植。但是有一个问题:你有有限的土地和一定的需求趋势。所以,你要有效利用土地,同时不要卖太多,以避免产品卖不出去。例如,你用 1/2 的土地种西红柿,另外 1/4 种菠菜,1/8 种薄荷,剩下的都没人种。换句话说,在这种情况下,优化利润是有限制的。

在现实生活中,很容易看出交易者的情况比园丁的情况更少发生。在数学公式中,后者可以写成

其中 f 和函数 cᵢ 都是ℝ 子集上的光滑实值函数,ℰ和ℐ是两个有限的指数集。我们称 f目标函数,而 cᵢi ∈ ℰ为等式约束, cᵢi ∈ ℐ为不等式约束。满足所有 cᵢ 的点或迭代 x 的集合称为可行集,我们用ω表示。

这个公式被称为约束优化问题。现在,怎么解决?

问题陈述

作为一个具体的例子,我们将考虑一个简单的约束优化问题如下:

受制于约束 hᵢ ( x₁x₂ ):

换句话说,我们正在最小化带有约束条件 hᵢ 的非线性二元目标函数 f 。忽略 hᵢ ,很容易验证极小值为 x * = ( x₁ *, x₂ *) = (5,6)与 f ( x₁x₂ ) = 0。但是对于 hᵢ来说,最小化并不像看起来那么简单。在这里,为了方便起见,我们写 x = ( x₁x₂ )。

导入一些库来开始。

这里是代码中的 f

屏障法

障碍法是内点法的一部分,内点法是一类解决线性和非线性凸优化问题的算法,由约翰·冯·诺依曼于 1948 年首次提出。然而,与单纯形法相比,该方法在实践中效率低且速度慢。Karmarkar 在 1984 年改进了该算法,随着进一步的改进,内点法变得非常有效,并且几乎在连续优化的每个领域都得到了应用。

照片由在 Unsplash 上绘制的迪兹·格拉汉姆

内点法通常通过将牛顿法应用于一系列等式约束问题来解决约束凸优化问题。顾名思义,障碍方法采用障碍函数将不等式约束整合到目标函数中。由于我们要将不等式约束合并到目标中,下列关于障碍函数 ϕ 的条件看起来是自然的:

  • 障碍函数应该将可行集ω映射到真实空间,即ϕ:ω→ℝ.
  • ϕ ( x )被整合到目标函数中,我们打算使用牛顿法,这是一种基于梯度的方法,因此屏障函数应该是合理的“平滑”(连续可微)。
  • ϕ ( x )应该表现得像一个障碍,并且随着 x 进入可行集的边界而无限增长。
  • 势垒函数的海森(标量函数的二阶导数)需要是正定的,即∇ ϕ ( x ) ≻ 0,∀x∈ω。

障碍函数的例子有很多。特别是,现在我们将使用如下的障碍函数。

其中 m 为约束数 hᵢ ( x ) ≤ 0。很容易看出这个函数满足上面解释的所有条件。然后,可以将 ϕ ( x )整合到目标函数 f 中,从而可以用一个新的优化问题来逼近该优化问题

在我们的例子中,这可以写成

其中t0 是由用户确定的参数。如果 t < ∞则新问题的解属于ω的内部,即x∈ω,当 t → ∞时解趋于最优,即x(t)→*x**。

现在,坡度 g 和 Hessian H 可以计算为

随着

了解了这一切之后,我们就准备创建障碍法算法了:

  1. 设定停止判据的初始点x∈ω,初始参数 t ,公差 ε 。这里我们会用 ε = 1 × 10⁻⁵.
  2. 执行以下 a-b-c 循环,直到满足停止标准。使用的停止准则是对偶间隙**m/tε,其中 m 是约束 hᵢ 的数量。在我们的例子中, m = 5。

a) 对中步骤:计算

用牛顿法进行迭代

直到满足牛顿法的停止标准。使用的标准是ǁxₖ₊₁xₖǁ₂≤10⁻⁵或者最大迭代次数达到 1000 次。

b) 更新x:=x*(t)。

使用以下等式增加 t

ν 是与屏障功能 ϕ 相关的参数。这里我们用 ν = 0.01。

除了执行算法,注意上面的BarrierMethod函数还打印出当前迭代 x ,目标函数 f ( x )的值,以及对偶间隙 m / t

实验

这就是乐趣的开始。为了可视化优化的过程,我们将首先创建一个plot_all函数。该函数绘制了来自BarrierMethod函数的结果,详情如下:

  1. 黄色阴影区域表示可行集
  2. 黑色区域表示不可行的集合
  3. 洋红色曲线是迭代路径
  4. 青色点是算法找到的解

迭代的收敛性应该取决于初始选择的 xt 。为此,我们选择了以下三个选项:

  1. 初始值 x = (0.50,0.75)和 t = 0.1
  2. 初始值 x = (0.50,0.75)并且 t = 1
  3. 初始值 x = (1.50,2.00)和 t = 0.1

场景 1:初始值 x = (0.50,0.75),t = 0.1

Initial condition: x = [0.5  0.75], f(x) = 47.8125Iteration: 1 	 x = [1.0202 1.1642], f(x) = 39.2236, gap = 28.2609
Iteration: 2 	 x = [1.1088 1.1778], f(x) = 38.3945, gap = 15.9735
Iteration: 3 	 x = [1.2357 1.1815], f(x) = 37.3873, gap = 9.0285
Iteration: 4 	 x = [1.3893 1.1683], f(x) = 36.3827, gap = 5.1031
Iteration: 5 	 x = [1.5441 1.1408], f(x) = 35.5548, gap = 2.8843
Iteration: 6 	 x = [1.6786 1.1079], f(x) = 34.9641, gap = 1.6303
Iteration: 7 	 x = [1.7838 1.0771], f(x) = 34.5792, gap = 0.9215
Iteration: 8 	 x = [1.8603 1.0519], f(x) = 34.3412, gap = 0.5208
Iteration: 9 	 x = [1.9129 1.0333], f(x) = 34.1983, gap = 0.2944
Iteration: 10 	 x = [1.9473 1.0205], f(x) = 34.1142, gap = 0.1664
Iteration: 11 	 x = [1.9689 1.0122], f(x) = 34.0654, gap = 0.0940
Iteration: 12 	 x = [1.9819 1.0072], f(x) = 34.0372, gap = 0.0532
Iteration: 13 	 x = [1.9896 1.0041], f(x) = 34.0211, gap = 0.0300
Iteration: 14 	 x = [1.9941 1.0024], f(x) = 34.0120, gap = 0.0170
Iteration: 15 	 x = [1.9966 1.0013], f(x) = 34.0068, gap = 0.0096
Iteration: 16 	 x = [1.9981 1.0008], f(x) = 34.0038, gap = 0.0054
Iteration: 17 	 x = [1.9989 1.0004], f(x) = 34.0022, gap = 0.0031
Iteration: 18 	 x = [1.9994 1.0002], f(x) = 34.0012, gap = 0.0017
Iteration: 19 	 x = [1.9997 1.0001], f(x) = 34.0007, gap = 0.0010
Iteration: 20 	 x = [1.9998 1.0001], f(x) = 34.0004, gap = 0.0006
Iteration: 21 	 x = [1.9999 1.0000], f(x) = 34.0002, gap = 0.0003
Iteration: 22 	 x = [1.9999 1.0000], f(x) = 34.0001, gap = 0.0002
Iteration: 23 	 x = [2.0000 1.0000], f(x) = 34.0000, gap = 0.0001
Iteration: 24 	 x = [2.0000 1.0000], f(x) = 34.0000, gap = 0.0001
Iteration: 25 	 x = [2.0000 1.0000], f(x) = 34.0000, gap = 0.0000
Iteration: 26 	 x = [2.0000 1.0000], f(x) = 34.0000, gap = 0.0000
Iteration: 27 	 x = [2.0000 1.0000], f(x) = 34.0000, gap = 0.0000
Iteration: 28 	 x = [2.0000 1.0000], f(x) = 34.0000, gap = 0.0000

图片作者作者

图片由作者

该算法通过最小化对偶间隙使得 m / tε ,在 28 次迭代后找到了解 x * = (2,1】。函数值在 f ( x *) = 34 时最小。从等高线图可以确认 x * = (2,1)确实是唯一解。注意,由于定心步骤,迭代路径不会平滑到 x *。

场景 2:初始值 x = (0.50,0.75),t = 1

Initial condition: x = [0.5  0.75], f(x) = 47.8125Iteration: 1 	 x = [5.3475 6.2329], f(x) = 0.1750, gap = 2.8261
Iteration: 2 	 x = [5.2030 6.1341], f(x) = 0.0592, gap = 1.5974
Iteration: 3 	 x = [5.1171 6.0767], f(x) = 0.0196, gap = 0.9029
Iteration: 4 	 x = [5.0670 6.0436], f(x) = 0.0064, gap = 0.5103
Iteration: 5 	 x = [5.0381 6.0247], f(x) = 0.0021, gap = 0.2884
Iteration: 6 	 x = [5.0216 6.0140], f(x) = 0.0007, gap = 0.1630
Iteration: 7 	 x = [5.0123 6.0079], f(x) = 0.0002, gap = 0.0921
Iteration: 8 	 x = [5.0069 6.0045], f(x) = 0.0001, gap = 0.0521
Iteration: 9 	 x = [5.0039 6.0025], f(x) = 0.0000, gap = 0.0294
Iteration: 10 	 x = [5.0022 6.0014], f(x) = 0.0000, gap = 0.0166
Iteration: 11 	 x = [5.0013 6.0008], f(x) = 0.0000, gap = 0.0094
Iteration: 12 	 x = [5.0007 6.0005], f(x) = 0.0000, gap = 0.0053
Iteration: 13 	 x = [5.0004 6.0003], f(x) = 0.0000, gap = 0.0030
Iteration: 14 	 x = [5.0002 6.0001], f(x) = 0.0000, gap = 0.0017
Iteration: 15 	 x = [5.0001 6.0001], f(x) = 0.0000, gap = 0.0010
Iteration: 16 	 x = [5.0001 6.0000], f(x) = 0.0000, gap = 0.0005
Iteration: 17 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0003
Iteration: 18 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0002
Iteration: 19 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0001
Iteration: 20 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0001
Iteration: 21 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0000
Iteration: 22 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0000
Iteration: 23 	 x = [5.0000 6.0000], f(x) = 0.0000, gap = 0.0000

图片作者作者

图片作者作者

经过 23 次迭代后,发现一个解是 x * = (5,6)f(x)= 0。但由于初始的 t 太大,在迭代过程的某个时刻,临时迭代 x 突破了可行集,之后的迭代试图在可行集之外寻找解,我们知道是(5,6)。

场景 3:初始值 x = (1.50,2.00),t = 0.1

Initial condition: x = [1.5 2\. ], f(x) = 28.2500Iteration: 1 	 x = [1.4440 8.0101], f(x) = 16.6853, gap = 28.2609
Iteration: 2 	 x = [1.5565 7.2585], f(x) = 13.4414, gap = 15.9735
Iteration: 3 	 x = [1.6742 6.7642], f(x) = 11.6450, gap = 9.0285
Iteration: 4 	 x = [1.7785 6.4526], f(x) = 10.5827, gap = 5.1031
Iteration: 5 	 x = [1.8587 6.2633], f(x) = 9.9374, gap = 2.8843
Iteration: 6 	 x = [1.9138 6.1514], f(x) = 9.5476, gap = 1.6303
Iteration: 7 	 x = [1.9490 6.0864], f(x) = 9.3161, gap = 0.9215
Iteration: 8 	 x = [1.9704 6.0491], f(x) = 9.1810, gap = 0.5208
Iteration: 9 	 x = [1.9830 6.0279], f(x) = 9.1031, gap = 0.2944
Iteration: 10 	 x = [1.9903 6.0158], f(x) = 9.0585, gap = 0.1664
Iteration: 11 	 x = [1.9945 6.0089], f(x) = 9.0332, gap = 0.0940
Iteration: 12 	 x = [1.9969 6.0050], f(x) = 9.0188, gap = 0.0532
Iteration: 13 	 x = [1.9982 6.0029], f(x) = 9.0106, gap = 0.0300
Iteration: 14 	 x = [1.9990 6.0016], f(x) = 9.0060, gap = 0.0170
Iteration: 15 	 x = [1.9994 6.0009], f(x) = 9.0034, gap = 0.0096
Iteration: 16 	 x = [1.9997 6.0005], f(x) = 9.0019, gap = 0.0054
Iteration: 17 	 x = [1.9998 6.0003], f(x) = 9.0011, gap = 0.0031
Iteration: 18 	 x = [1.9999 6.0002], f(x) = 9.0006, gap = 0.0017
Iteration: 19 	 x = [1.9999 6.0001], f(x) = 9.0003, gap = 0.0010
Iteration: 20 	 x = [2.0000 6.0001], f(x) = 9.0001, gap = 0.0006
Iteration: 21 	 x = [2.0000 6.0000], f(x) = 9.0001, gap = 0.0003
Iteration: 22 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0002
Iteration: 23 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0001
Iteration: 24 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0001
Iteration: 25 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0000
Iteration: 26 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0000
Iteration: 27 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0000
Iteration: 28 	 x = [2.0000 6.0000], f(x) = 9.0000, gap = 0.0000

图片作者作者

图片作者作者

这是实施障碍法的错误做法的一个例子。注意,初始的 x 不在可行集中,这导致迭代产生违反约束的迭代。因此,我们最终得到了解决方案 x *

结论

障碍法是求解带约束优化问题的一种有效算法。它使用障碍函数将不等式约束整合到目标函数中。该方法使用目标函数的梯度和 hessian,并使用牛顿法作为定心步骤。我们已经看到了 Barrier 方法的作用,并发现初始迭代 x 和参数 t 对于它按照我们期望的方式工作是至关重要的。

🔥你好!如果你喜欢这个故事,想支持我这个作家,可以考虑 成为会员 。每月只需 5 美元,你就可以无限制地阅读媒体上的所有报道。如果你注册使用我的链接,我会赚一小笔佣金。

🔖想了解更多关于经典机器学习模型的工作原理,以及它们如何优化参数?或者 MLOps 大型项目的例子?有史以来最优秀的文章呢?继续阅读:

Albers Uzila

艾伯斯·乌兹拉

从零开始的机器学习

View list8 storiesAlbers Uzila

艾伯斯·乌兹拉

高级优化方法

View list7 storiesAlbers Uzila

艾伯斯·乌兹拉

MLOps 大型项目

View list6 storiesAlbers Uzila

艾伯斯乌兹拉

我最好的故事

View list24 storiesAlbers Uzila

艾伯斯乌兹拉

R 中的数据科学

View list7 stories

如何更快解决数据科学问题

原文:https://towardsdatascience.com/how-to-solve-data-science-problems-faster-14c962edaf27

从以解决方案为中心转向以诊断为中心的方法

蒂姆·莫斯霍尔德在 Unsplash 上的照片

作为数据科学家,我们因出色的问题解决能力而获得认可。我们的教育是一系列的考试和黑客马拉松,挑战越来越大,越来越难。数据科学创新的特征还在于现有业务问题和应用中的算法优化。

尽管我们的解决方案不断创新和进步,但我们经常面临各种业务挑战。根据我的行业经验,它们是:

  • 数据科学供不应求:人们经常被数据科学解决方案改善生活和商业决策的潜力所吸引。这导致了想法的爆发。然而,现有的数据科学家有限,招募新的数据科学家很难满足不断增长的想法。
  • 数据科学解决方案不经常使用:虽然利益相关者可能会对解决方案的功能印象深刻,但他们在最初几个月之后很少使用该解决方案,或者该解决方案无法获得承诺的投资回报。

你会相信一个直接给你开药的医生吗?

医学领域是另一个先进的科学学科,由复杂的问题和不同的解决方案组成。我一直注意到的一件事是他们对诊断的不懈关注。患者分享他们的观察结果,这些观察结果被视为初始假设,但随后医生会进行自己的诊断。通常,他们甚至会将病人转介给其他专科医生做进一步诊断!

虽然这需要更多的前期时间,但我相信数据科学的诊断优先方法会减少总体项目交付时间并且会带来更大的组织影响。这是因为返工的大量减少。生产化的数据科学解决方案需要 3 到 6 个月的时间,而返工可能需要两倍以上的时间。除此之外,这对资源成本和采购也有巨大的影响。

那么,我们如何实践以诊断为中心?我们将探索一些简单而有效的习惯。

提示 1:练习积极倾听

乔恩·泰森在 Unsplash 上的照片

维基百科将积极倾听定义为“一种用于咨询、培训和解决冲突的沟通技巧”。它要求听者全神贯注,理解,回应,然后记住所说的内容。“数据科学家在解决复杂问题方面经验丰富。这通常会导致问题到解决方案的关联偏差,即一切都被认为是“相同的”。

本质上,商业问题通常是模糊不清的。通常,问题超出了最初的症状。往往大家都觉得没什么大不了的。通常,所要求的业务解决方案不涉及数据科学。

数据科学家需要有**好奇心和开放的心态。**他们需要更深入地了解顾客。他们还应该接受这样一个事实,即正确的解决方案可能不涉及数据科学。例如,我帮助一个营销团队在续约前通过“简单”的自动化沟通减少了季节性客户流失。对一个问题说“不”,就有机会帮助其他具有更大潜在影响的领域。

提示 2:实践假设检验

照片由疾控中心在 Unsplash 上拍摄

数据科学家喜欢高级数学算法,我们希望将它们应用于尽可能多的商业问题。这就造成了解决方案中的偏差,数据科学家为每个出现的问题提出一个预测模型解决方案。

我们需要将假设驱动的方法应用到我们的解决方案中。这可以跨诊断级别完成。以下是一些问题示例:

  • *梯度推进模型的实施是否会显著改善广义线性模型?*这个假设解决了我们对更复杂的解决方案的偏好,有利于业务可解释性。
  • 我们有足够的数据来建立模型吗?该假设解决了项目的实用性,因为数据是任何预测模型的支柱。
  • *更广泛的业务认为这是最重要的问题吗?*该假设解决了问题选择和优先化偏差,以确保我们解决重要的问题。

提示 3:积极与企业合作

照片由克拉肯 images 在 Unsplash 上拍摄

跳舞需要两个人

数据科学家是聪明人。数据科学是一门与数学打交道的商业专业,而积极的合作伙伴关系是成功企业的关键因素。然而,许多研究数据的科学家经常从一个更“个人主义”的方法来处理它。

根据我对行业的观察,数据科学家通常在以下 4 个不同的接触点与业务互动:

  • 用例筹资:向企业询问问题总结、业务收益和资源估算。
  • 需求收集:向企业询问他们问题的更多细节。
  • 测试:要求企业确认我们的模型是正确的。
  • 生产:要求企业在决策中经常使用它。

如果说实话,以上所有的接触点大多都是单向互动。企业通常被视为数据科学解决方案的*【看门人】*。他们在数学知识上的不足,可以在商业环境中弥补。

积极的合作伙伴关系需要每天与企业进行双向互动。这包括:

  • 让他们参与日常活动:交流是关键,日常活动是最低要求。这也是一个检查点,检查你是否让他们充分参与,以便他们与数据科学家共同完成任务。
  • 让他们参与探索性数据分析:作为模型的一部分
  • 让他们参与模型解释:企业想要理解驱动因素,而不是“黑盒”算法。虽然这两者之间存在权衡,但是企业必须能够信任并理解模型的结果。注意,他们不一定要理解算法——一个好的模型通常有一个合理的结果解释。
  • 让他们参与模型消费:一个好的模型需要用于决策。我们需要了解他们的业务流程——以及如何适应这一流程。这需要承认将需要“不方便的”改变。因此,更广泛的业务需要感觉到利大于弊,因为如果过程不顺利,他们将承担责任。

我们需要专注于解决方案

善于解决问题是一种美德。这涉及到通过数据科学解决方案帮助组织的积极态度。然而,仅有激情和精力是不够的。我们需要一个良好的整体方法。

我的行业经验教会我利用诊断方法。许多组织希望从事数据科学,但许多组织仍处于起步阶段。我经常看到对数据科学解决方案的怀疑和抵制。人们不会在乎你做什么,直到你关心他们。在我看来,这涉及到对他们处境的深入了解。我认为作为高等科学研究的一部分,我们的职业和医学有相似之处。

试试这个假设——并渴望在评论中听到你的想法。

如果你喜欢这篇文章,并希望看到更多的内容,请考虑加入媒体会员,使用下面的链接来支持我和其他作者:

https://albertsuryadi.medium.com/membership

关于作者: 阿尔伯特·苏亚迪 是为前瞻性组织提供高级分析和数据科学能力的公认领导者。他被公认为分析团队(实践社区)的领导者,该团队授权并激励他人超越现状。

如何用低代码解决每一个 ML 问题

原文:https://towardsdatascience.com/how-to-solve-every-ml-problem-with-low-code-97550c712a68

Python 库 PyCaret 简介

阿诺·弗朗西斯卡在 Unsplash 上的照片

介绍

根据《财富商业洞察》[1],全球机器学习(ML)市场规模预计将从 2021 年的 150 亿美元增长到 2029 年的 2090 亿美元。这意味着对数据科学家的需求正在上升,而人才供应仍然稀缺。

因此,引入了一个新的角色。公民数据科学家的角色。

公民数据科学家的角色可以描述如下[2]:

根据 Gartner 的说法,公民数据科学家是指创建或生成利用预测性或规范性分析的模型的人,但其主要工作职能不属于统计和分析领域。

因此,一个公民数据科学家应该解决 ML 问题,而不需要在统计和分析领域有太多的知识。

为了使这些人能够解决 ML 问题,而不必运行探索性的数据分析、数据预处理、数据清洗、模型选择和所有其他需要的步骤,需要低代码和端到端的机器学习和模型管理工具。

这就是 Python 库 PyCaret 发挥作用的地方。

在本文中,我将向您介绍 Python 库 PyCaret。这个库允许你只用几行代码就可以很容易地训练一个 ML 模型!

我将通过解决一个具体的 ML 问题并为您提供代码片段,直接向您展示这个库的威力。

因此,如果你有兴趣成为一名公民数据科学家,或者你已经是一名数据科学家,但想学习如何简化培训过程,那么请继续阅读!

PyCaret

让我们首先深入研究 PyCaret。下面引用的 PyCaret 官方文档很好地总结了 PyCaret 及其用途[3]:

PyCaret 是一个用 Python 编写的开源、低代码的机器学习库,可以自动化机器学习工作流。这是一个端到端的机器学习和模型管理工具,可以成倍地加快实验周期,提高您的工作效率。

根据文档,PyCaret 可用于分类、回归、聚类、异常检测和自然语言处理。

他们还提供教程甚至数据集,让用户有可能快速测试这个库。

因为这是一个 Python 库,所以您可以使用以下命令通过 pip 轻松安装它:

pip install pycaret

PyCaret 本身是几个其他 ML 库的 Python 包装器,比如 scikit-learn、CatBoost、XGBoost 等等。

该库允许您解决 ML 问题,而不需要成为有经验的数据科学家,因此非常适合公民数据科学家。

但是它也帮助数据科学家快速解决 ML 问题,因为只有这个库的一部分可以用于解决 ML 问题。例如,数据科学家可以自己准备数据,然后利用 PyCaret 找到该数据的最佳模型。

用 PyCaret 解决分类问题

现在让我们展示一下使用 PyCaret 解决一个具体的 ML 问题的能力和简易性。

你可以在我的 Github 库这里找到包含所有代码的完整笔记本。

PyCaret 提供了几个数据集,可以用来快速测试他们的库的能力。

您可以通过运行以下命令获得所有可用的数据集:

from pycaret.datasets import get_datacredit_data = get_data("index")

其中一个数据集是信用数据集,这是我在本文中使用的数据集。该数据集被称为“信用卡客户数据集的默认值”。你也可以在 Kaggle 上找到更多关于那个数据集的信息。

基本上包含了 2005 年 4 月到 2005 年 9 月台湾地区信用卡客户拖欠还款的信息。

您可以使用以下命令加载数据集:

# load credit dataset
credit_data = get_data("credit")

该数据集总共包含 24000 个样本,每个样本有 24 个特征。

作为第一步,我创建了一个拒绝测试集。最后,这将用于查看最终模型在真实世界数据中的“真实”性能。

为此,我使用了 scikit-learn 的训练测试分割功能:

from sklearn.model_selection import train_test_split# create a train and test split
data_train, data_test = train_test_split(credit_data, test_size=0.1)

设置数据管道和环境

解决 ML 问题的第一步总是建立你的数据管道和你的环境。设置数据管道通常包括运行一些探索性的数据分析以更好地理解数据、进行特征工程以充分利用数据、进行数据清理以移除缺失值等等。

使用 PyCaret,所有这些步骤都是 setup() 函数的一部分。这个函数基本上创建了为训练准备数据的所有转换。

它接受一个 Pandas 数据帧和目标列的名称。

除了这些值,您还可以添加更多的可选值来设置您的数据管道。例如,您可以对数据进行归一化处理,将其转换为更接近高斯分布的形式,忽略方差较小的要素,移除相关性较高的要素,选择用于输入缺失数据的数据插补类型,应用降维,移除异常值,计算用于创建新要素的组要素统计数据等等。您可以在这里找到分类用例的所有输入选项。

现在,让我们使用用于训练的数据帧,并使用以下选项运行 setup() 函数:

# call the pycaret setup function to setup the transformation pipeline
setup = setup(data=data_train, target="default",normalize=True,transformation=True, # make data more gaussian likeignore_low_variance=True, # ignore features with low varianceremove_multicollinearity=True, # remove features with inter-correlations higher than 0.9 -> feature that is less correlated with target is removedgroup_features = [['BILL_AMT1', 'BILL_AMT2','BILL_AMT3', 'BILL_AMT4', 'BILL_AMT5', 'BILL_AMT6'], # features with related characteristics['PAY_AMT1','PAY_AMT2', 'PAY_AMT3', 'PAY_AMT4', 'PAY_AMT5', 'PAY_AMT6']],use_gpu=True # use GPU when available, otherwise CPU                                               )

完成了。通过运行此功能,您将应用预处理、标准化、转换、一些特征工程和移除高度相关的特征。所有这些只需要一个函数调用和几行代码。太棒了。

比较所有模型

解决 ML 问题的下一步是比较几种不同的模型以找到最佳选择。

PyCaret 再次提供了一个函数,通过使用 k-fold 交叉验证来评估模型库中所有可用估计器的性能。

让我们现在运行这个函数,并返回 3 个最佳选项:

from pycaret.classification import *best_3_models = compare_models(n_select=3)

然后,该功能将运行 10 重交叉验证,以评估几个分类模型的性能,并输出几个指标。

您可以在图 1 中找到对信用卡数据集运行该函数的输出。

图 1:所有可用分类模型的比较结果(图片由作者提供)。

具有良好 AUC 分数和 F1 分数的模型是梯度增强分类器。因此,我决定在本文的剩余部分继续讨论这个问题。

我没有根据准确性选择一个好的模型,因为数据集本身是不平衡的,准确性不会提供对性能的良好估计。但是我将在本文的后面回到这一点。

优化最终模型

现在我们有了一个可以继续进行的模型,是时候优化这个模型了。

当然,PyCaret 也提供了一个调整模型的函数。但是在调优之前,我们必须调用 create_model() 函数。此函数使用交叉验证来训练和评估模型。但是这个函数只是利用所选分类器的默认参数来训练它。

为了调优超参数,有一个名为 tune_model() 的函数。该函数接受一个训练模型,并基于一个选择的优化度量和几个其他选项来优化超参数。一个选项是设置搜索算法,可以是随机的、网格搜索、贝叶斯搜索等等。默认为随机网格搜索。

现在让我们训练一个具有 5 重交叉验证的梯度增强分类器,然后使用 F1 分数作为优化的度量来调整超参数:

final_classifier = create_model("gbc", fold=5)tuned_classifier_F1 = tune_model(final_classifier, optimize="F1")

未调整的模型的 AUC 得分为 77.4%,F1 得分为 36.2%,而调整后的模型的 AUC 得分为 77.3%,F1 得分为 47%。

现在,我们还可以通过运行以下命令来获取导致最佳模型结果的所有超参数:

plot_model(tuned_classifier_F1, plot="parameter")

PyCaret 还提供了其他一些现成的绘图。

一个示例图是 ROC 曲线,它可以通过运行以下函数调用来绘制:

plot_model(tuned_classifier_F1, plot="auc")

图 2 显示了得到的 ROC 曲线。

图 PyCaret 函数调用返回的 ROC 曲线(图片作者提供)。

您还可以获得您的特征对预测目标变量的重要性(图 3):

plot_model(tuned_classifier_F1, plot="feature")

图 PyCaret 函数调用返回的特性重要性图(图片由作者提供)。

或者我们也可以看看混淆矩阵,因为数据集是不平衡的(图 4):

plot_model(tuned_classifier_F1, plot="confusion_matrix")

图 PyCaret 函数调用返回的混淆矩阵(图片由作者提供)。

也有很多其他选项可用于绘图,可以在官方用户文档中找到。

正如您在混淆矩阵中看到的,分类器在多数类(类 0)上表现良好,而在少数类(类 1)上表现不佳。在现实世界中,这将是一个巨大的问题,因为得到正确的 1 类可能比 0 类更重要,因为预测客户将支付其违约,但实际上他没有支付将导致损失。

因此,我们可以尝试修复数据集中的不平衡,以检索更好的模型。为此,我们只需稍微修改 setup() 功能,将fix _ unbalance输入参数设置为 true:

# call the pycaret setup function to setup the transformation pipeline
setup = setup(data=data_train, target="default",normalize=True,transformation=True, # make data more gaussian likeignore_low_variance=True, # ignore features with low varianceremove_multicollinearity=True, # remove features with inter-correlations higher than 0.9 -> feature that is less correlated with target is removedgroup_features = [['BILL_AMT1', 'BILL_AMT2','BILL_AMT3', 'BILL_AMT4', 'BILL_AMT5', 'BILL_AMT6'], # features with related characteristics['PAY_AMT1','PAY_AMT2', 'PAY_AMT3', 'PAY_AMT4', 'PAY_AMT5', 'PAY_AMT6']],fix_imbalance=True, # fix the imbalance in the datasetuse_gpu=True # use GPU when available, otherwise CPU                                               )

然后,我们可以再次调整优化 F1 分数的模型:

# train baseline model
final_classifier = create_model("gbc", fold=5)# optimize hyperparameters by optimizing F1-Score
tuned_classifier_F1 = tune_model(final_classifier, optimize="F1")# plot new confusion matrix
plot_model(tuned_classifier_F1, plot="confusion_matrix")

图 PyCaret 函数调用返回的不平衡优化模型的混淆矩阵(图片由作者提供)。

新模型现在的 AUC 分数为 77%,F1 分数为 53.4%。F1 分数从 47%提高到 53.4%!

混淆矩阵(图 5)现在也显示了类 1 的性能有所提高!太好了。但这是以类 0 的更差性能为代价的,这通常没有错误预测类 1 那么严重。

当比较两个模型的回忆分数时,这也变得清楚。老款召回 37%,新款召回差不多 60%。这意味着新模型发现了 60%的未偿付违约,而旧模型只发现了 37%。

在搁置测试集上测试最终模型

最后一步是在保留测试集上测试最终模型,看看它在真实世界和看不见的数据上表现如何。

为此,我们现在可以利用本文开头创建的拒绝测试集:

predict_model(tuned_classifier_F1, data=data_test)

该函数将采用调整后的梯度提升分类器,并对保留测试集进行预测。然后,它返回预测的指标。

AUC 得分为 77%,F1 得分为 54.3%。这向我们表明,该模型没有过度拟合我们的训练和验证数据,并且在真实世界数据上表现相似。

结论

在本文中,介绍了 PyCaret Python 库,并将其应用于现实世界的数据集,以解决分类问题。它清楚地显示了使用这个库可以多么容易地解决一个 ML 问题,我只是触及了表面。还有很多其他选项可供您探索和评估。

因此,这个库是公民数据科学家在没有太多统计和其他相关领域知识的情况下解决 ML 问题的完美工具。但它也可以提高数据科学家找到解决方案的效率和速度。

我也没有深入研究数据集本身,因为本文的目的是展示这个库的威力。当然,最终的估计值仍然可以优化,PyCaret 也提供了更多可以进一步研究的选项。

但是这超出了本文的范围。

谢谢你把我的文章看完!我希望你喜欢这篇文章。如果你想在未来阅读更多类似的文章,请关注我,保持更新。

接触

LinkedIn|GitHub

参考

[1]《财富商业洞察》,机器学习市场规模 (2022 年)

[2] Manasi Sakpal,公民数据科学家可以提升组织的商业价值和分析成熟度;然而,在大多数情况下,他们的能力仍未得到充分利用 (2021)

[3] Ali Moez,py caret:Python 中的开源、低代码机器学习库 (2020)

如何在 MATLAB 中用龙格-库塔法求解常微分方程

原文:https://towardsdatascience.com/how-to-solve-odes-in-matlab-without-built-in-functions-9eaa01c9fe10

学习编写一个 Runge-Kutta 4 阶算法来求解常微分方程

Joshua Woroniecki 在 Unsplash 上的照片

常微分方程在工程和科学的各个方面都很常见。它们用于模拟物理现象,如湍流气流、卫星轨道、热传递、振动和无数其他现象。它们是人类理解物理和数学的基础。虽然我们可以基于直觉和我们对世界如何运作的基本理解来创建这些方程,但解决它们可能更具挑战性。

常微分方程

在这篇文章中,我假设你对微积分和微分方程有基本的了解。术语常微分方程是指包含一个独立变量的函数和这些函数的导数的微分方程。对于大多数工程和科学常微分方程,独立变量是时间,方程的形式如下:

这里的 y 矢量可以是空间状态、质量、温度等。,而 t 是时间。不幸的是,大多数常微分方程不能解析求解;这意味着不能推导出一个函数来提供微分方程的精确解。求解这些微分方程的另一种方法是利用数值积分方法。

数值积分

数值积分这个术语最早出现在 1915 年,但是直到现代计算机的出现,它的好处才真正显现出来。数值积分是一种通过了解控制 y 随时间变化的微分方程来近似函数 y 随时间变化的方法。它们只是陈述的一个估计,所以它们只和使用的方法和技术一样好。最流行的数值积分形式之一是四阶龙格-库塔法(或 RK4)。

RK4 可以用下面的等式和图表来描述。通常情况下,你会有一个向量形式的常微分方程求解,所以向量形式的 RK4 显示。在等式中, k 值是在图中所示的位置使用微分方程计算的 y 的斜率估计值。一旦确定了 k 值,它们被平均并乘以时间步长 h 。然后将其添加到当前值 y 中,得到下一个时间步长的近似值 y 。重复这一过程,直到达到所需的时间步数。请注意,所使用的 h 值越小,结果越接近真实值。

斜率估计的描述[由 [HilberTraum](http://By HilberTraum - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=64366870) 创建]

MATLAB RK4 脚本

对于这个例子,假设我们有一个粒子,它的运动由下面的常微分方程描述:

这组常微分方程是方便的,因为它可以解析求解(解决方案如下所示)。选择这些,以便我们的 RK4 算法可以与实际解决方案进行比较。请记住,当使用你自己的微分方程时,它们可能无法解析求解,所以你可能没有任何东西来比较你的结果。

我们可以通过定义一个函数 model 来开始代码,当值*、 vw 传递给它时,该函数将返回 ODEs 的值。确保将这个函数定义放在脚本的底部。*

*function dydt = model(t,y)v = y(1);w = y(2);dv_dt = w;dw_dt = 6*v-w;dydt = [dv_dt,dw_dt];
end*

现在开始主脚本吧。我总是从清除命令窗口、清除变量和关闭数字开始。

*clc
clear variables
close all*

为了利用 RK4 方法,我们需要定义初始条件y0,以及一个时间数组*。这里, t 被定义为以 1000 为增量从 0 到 1,并且 v 的初始条件是 3,而 w 是 1。时间数组用于创建 h 及以后,精确值为 vw 。***

**% Initial Conditions and Simulation Time
y0 = [3, 1];  % y0 = [v0, w0]
t = linspace(0,1,1000)';**

接下来,我们可以创建一个数组,来存储每个时间步的 RK4 近似值。利用 vw 的初始条件,我们可以定义 RK4 数组的第一个索引( i = 1, t =0)。我们还可以定义时间步长变量,。然后我们为循环引入一个来遍历时间数组的长度。每次迭代我们都会给 yₖᵤₜₜₐ的增加一个新值,然后使用这个迭代为 yₖᵤₜₜₐ的创建另一个值。这个过程会一直重复,直到到达最后一个时间步( t = 1)。******

*% Runge-Kutta 4th-Order Algorithm
y_Kutta = zeros(length(t), 2);
y_Kutta(1, :) = y0;
h = t(2)-t(1);  % Constant time step
for i = 2:length(t)k1 = model(t(i-1), y_Kutta(i-1, :));k2 = model(t(i-1)+h/2, y_Kutta(i-1, :)+k1*h/2);k3 = model(t(i-1)+h/2, y_Kutta(i-1, :)+k2*h/2);k4 = model(t(i-1)+h, y_Kutta(i-1, :)+k3*h);y_Kutta(i, :) = y_Kutta(i-1, :)+(k1/6+k2/3+k3/3+k4/6)*h;
end*

如前所述,这组常微分方程有一个解析解,所以让我们创建一个这些值的数组,并将其与我们从 RK4 得到的结果进行比较。为了比较,我们可以简单地计算精确解和近似解之间的差。

*% Exact
y_Exact = 2*exp(2*t).*[1, 2]-exp(-3.*t)*[-1, 3];% Calculating the Difference Between Exact and RK4 Solutions
diff_Kutta = y_Exact-y_Kutta;*

最后,我们有了比较龙格-库塔四阶方法和精确解所需的所有数据。最后一步是绘制结果。

*% Comparison Subplot
figure; subplot(2,1,1);  hold on;
plot(y_Exact(:, 1), y_Exact(:, 2))
plot(y_Kutta(:, 1), y_Kutta(:, 2))
title('RK4 Compared to the Exact Solution', 'Interpreter', 'Latex')
xlabel('v', 'Interpreter', 'Latex')
ylabel('w', 'Interpreter', 'Latex')
legend('Exact', 'RK4', 'Location', 'Best')
grid on; hold off% Difference Subplot
subplot(2,1,2); hold on;
plot(t, diff_Kutta(:, 1))
plot(t, diff_Kutta(:, 2))
xlabel('t', 'Interpreter', 'Latex')
ylabel('Difference', 'Interpreter', 'Latex')
legend('RK4 [v]', 'RK4 [w]', 'Location', 'Best')
grid on; hold off*

结果是:

龙格-库塔四阶结果[由作者创建]

正如你所看到的,Runge-Kutta 4 阶方法的结果对于这个例子来说是非常精确的。RK4 结果与上图中的精确解难以区分,并且 vw 的结果与精确解之间的差异实际上可以忽略不计。龙格-库塔可以扩展到 4 阶以上,以减少误差,但对于大多数应用来说,这可能是不必要的。

感谢您阅读文章!希望你对 RK4 有所了解!给我一个关注,看看我关于 Python、数学和轨道力学的其他文章!如果您有任何意见或顾虑,请告诉我!

如何用 Python 解决调度问题

原文:https://towardsdatascience.com/how-to-solve-scheduling-problems-in-python-36a9af8de451

使用线性规划来最小化所需资源和计划资源之间的差异

埃里克·罗瑟梅尔在 Unsplash 上的照片

在劳动力管理中,计划是指根据每个时间间隔的预计需求,找到安排一组资源的“最佳”方法。例如,这可能是在给定一些需求(例如,使用 ErlangC)和一些限制的情况下,找出每一小时间隔要调度多少呼叫中心代理。

“最优”标准是在一个目标函数下定义的,例如,最小化预定资源的数量或需求和计划资源之间的绝对差异。

1。配方

让我们假设我们正在为一个呼叫中心操作创建调度;我们有每 60 分钟间隔所需的估计人数。查看这篇其他帖子,了解如何找到需求。

需求可能如下所示:

必需的代理。图片由作者提供。

我们想回答这样一个问题:给定一组覆盖部分时间间隔的班次,我应该安排多少个座席代表每个班次?例如,每个区间所需人员和计划人员之间的差异尽可能低,以确保尽可能满足需求,而不会出现大量人员不足或人员过多的情况。

考虑到轮班覆盖可能看起来像这样,所以在一个时间间隔,来自不同班次的人同时工作。

轮班设计。图片由作者提供。

1.1 数学公式

在这一节中,我将把这种情况定义为优化问题。为此,我引入以下变量和符号:

调度变量。图片由作者提供。

请注意,period 的定义允许将一天分成任意数量的间隔;它可以是 24 个一小时的间隔,48 个 30 分钟的间隔,等等。这将取决于需求的粒度。

现在我们必须定义目标函数和模型的限制;根据可用数据和业务需求,此步骤可能会有所变化。

我将把这个公式称为“最小绝对差”模型;在这种方法中,求解器将最小化所需资源和计划资源之间的绝对差异;这意味着计划资源可能高于或低于实际需求。

在这个定义下,目标函数被公式化为:

目标函数。图片由作者提供。

请注意,术语 Xds÷Esp 将得出某个时间段和某一天的计划资源数量,术语 Ndp 是所需资源。因此,该目标有效地最小化了需求与实际计划在所有日期和期间的绝对差异。

现在我们介绍这个模型的限制:

  • 周期 p 和日期 d 的调度资源数量不能超过最大允许能力。

  • 同一班次的计划资源数量不能超过最大允许能力。

  • 正整数限制

  • 布尔限制

2。Python 解决方案

从上一节可以看出,问题已经完全定义好了,您可以使用任何支持定义不同变量和目标函数的求解器。

然而,将这些方程翻译成代码并求解它们可能需要相当多的优化知识;幸运的是,一些软件包已经简化了这个过程;在这种情况下,我将使用 pyworkforce ,这是运筹学中常见问题的 python 接口,适用于排队、调度、排班和优化问题。

首先,让我们定义每个间隔的需求和我们可以使用的固定班次,我将只解决一天的问题:

现在,在 pyworkfoce 的帮助下,我们只需要将这些数据传递给 MinAbsDifference 对象,然后运行 solve 方法:

对于这个特定的运行,我得到以下输出:

首先要注意的是状态是“最优”,这意味着求解器能够找到最优可行解。接下来,我们有一个 35.0 的成本,这是找到解后目标函数的值。

resources _ shifts 对象将告诉我们在每个可用的班次中要安排多少代理人;例如,您应该在第三班安排 13 名座席代表。

如果我们将此信息与班次覆盖范围相匹配,即我们找到 Xds÷Esp,我们将得到每个间隔的以下计划座席代表与理论上所需的座席代表:

必需代理与预定代理。

您可以看到,有时我们的代理可能比我们需要的多/少;你可以把它想成有六个位移只能得到所需曲线的某种程度的离散化,但它保证是在目标函数及其限制的定义下的最好的。

我希望这篇文章对你开始处理调度问题有用。如果您想了解更多关于 pyworkforce 以及如何解决其他优化问题的信息,您可以查看文档及其 repo:

使用核外方法处理大型数据集

原文:https://towardsdatascience.com/how-to-speed-up-data-processing-in-pandas-a272d3485b24

利用开源库加快大数据分析工作流程

如果你是一名处理大型数据集的数据科学家,那么在执行分析或训练机器学习模型时,你肯定已经用完了内存(OOM)。

增强您的工作流程。卡拉·富勒在 Unsplash 上的照片

这并不奇怪。台式机或笔记本电脑上的可用内存很容易超过大型数据集。我们被迫一次只处理一小部分数据,这可能导致低效的数据分析。

更糟糕的是,对大型数据集执行数据分析可能需要很长时间,尤其是在使用复杂的算法和模型时。

声明:我不隶属于 vaex。

Vaex:大型数据集的数据分析库。

输入 vaex。这是一个强大的开源数据分析库,用于处理大型数据集。它通过使用核外方法处理不适合内存的大型数据集来加速数据分析。这意味着它只在需要时将数据加载到内存中。

Vaex:大型数据集的银弹(来源)

vaex 的 4 个主要特性

vaex 有助于加速数据分析的一些关键特性包括:

  1. 快速高效地处理大型数据集: vaex 使用优化的内存数据表示和并行算法。vaex 处理大量表格数据,每秒处理 10 亿行。
  2. 灵活的交互式数据探索:它允许您使用各种内置的可视化工具和工具交互式地探索数据,包括散点图、直方图和内核密度估计。
  3. 易于使用的 API: vaex 有一个用户友好的 API。该库还与 pandas、numpy 和 matplotlib 等流行的数据科学工具集成良好。
  4. 可扩展性: vaex 可以扩展到非常大的数据集,可以在单台机器上使用,也可以分布在一个机器集群上。

以闪电般速度处理数据。通过稳定扩散成像。

vaex 入门

要在您的数据分析项目中使用 Vaex,您可以使用 pip 简单地安装它:

pip install vaex

安装 Vaex 后,您可以将其导入 Python 代码并执行分析。

下面是一个简单的示例,说明如何使用 Vaex 计算数据集的平均值和标准差。

import vaex# load an example dataset
df = vaex.example()# calculate the mean and standard deviation
mean = df.mean(df.x)
std = df.std(df.x)# print the results
print("mean:", mean)
print("std:", std) 

示例 dataframe ( MIT license )有 330,000 行。

在这个例子中,我们使用vaex.open()函数加载一个示例数据帧(上面的截图),然后使用mean()std()方法计算数据集的均值和标准差。

Vaex 语法类似于 pandas

用 vaex 过滤

vaex 中的很多功能都和熊猫类似。例如,要使用 vaex 过滤数据,可以使用以下方法。

df_negative = df[df.x < 0]
print(df_negative[['x','y','z','r']])

使用 vaex 进行分组

聚合数据对于任何分析都是必不可少的。我们可以使用 vaex 来执行与熊猫相同的功能。

# Create a categorical column that determines if x is positive or negative
df['x_sign'] = df['x'] > 0# Create an aggregation based on x_sign to get y's mean and z's min and max.
df.groupby(by='x_sign').agg({'y': 'mean','z': ['min', 'max']})

其他聚合,包括countfirststdvarnunique可用。

使用 vaex 执行机器学习

也可以使用 vaex 进行机器学习。它的 API 与 scikit-learn 的结构非常相似。

要使用它,我们需要执行 pip 安装。

import vaex

我们将说明如何使用 vaex 来预测泰坦尼克号的幸存者。

用泰坦尼克号幸存者问题来说明 vaex。通过稳定扩散成像。

首先,需要将 titanic 数据集加载到 vaex 数据帧中。我们将使用vaex.open()方法,如下所示:

import vaex# Download the titanic dataframe (MIT License) from https://www.kaggle.com/c/titanic
# Load the titanic dataset into a vaex dataframe
df = vaex.open('titanic.csv')

一旦数据集被加载到 dataframe 中,我们就可以使用vaex.ml来训练和评估一个预测乘客是否在泰坦尼克号灾难中幸存的机器学习模型。例如,数据科学家可以使用随机森林分类器来训练模型,如下所示。

from vaex.ml.sklearn import Predictor
from sklearn.ensemble import GradientBoostingClassifier# Download the titanic dataframe (MIT License) from https://www.kaggle.com/c/titanic
# Load the titanic dataset into a vaex dataframe
titanic_df = vaex.open('titanic.csv')titanic_df = titanic_df.dropna()# Get numeric columns of titanic_df
features = ['Age','SibSp','Parch','Fare','Pclass']
target = 'Survived'# Use GradientBoostingClassifier as an example
model = GradientBoostingClassifier(random_state=42)
vaex_model = Predictor(features=features, target=target, model=model, prediction_name='prediction')vaex_model.fit(df=titanic_df)

当然,其他预处理步骤和机器学习模型(包括神经网络!)都有。

一旦模型被训练,数据科学家使用transform()方法执行预测,如下所示:

titanic_df = vaex_model.transform(titanic_df)

让我们打印结果。请注意,有一个新列“预测”。

print(titanic_df)

预测的结果

用 vaex 解决泰坦尼克号问题绝对是大材小用,但这足以说明 vaex 可以解决机器学习问题。

使用 vaex 增强您的数据科学管道

总的来说,vaex.ml 提供了在大型数据集上执行机器学习的强大工具。它的核外方法和优化的算法使得在不适合内存的数据集上训练和评估机器学习模型成为可能。

我们没有介绍 vaex 可用的许多功能。为此,我强烈建议您查看文档。

以下是完整的代码:

import vaex# load an example dataset
df = vaex.example()
print(df)# calculate the mean and standard deviation
mean = df.mean(df.x)
std = df.std(df.x)# print the results
print("mean:", mean)
print("std:", std)df_negative = df[df.x < 0]
print(df_negative)# Create a categorical column that determines if x is positive or negative
df['x_sign'] = df['x'] > 0# Create an aggregation based on x_sign to get y's mean and z's min and max.
df.groupby(by='x_sign').agg({'y': 'mean','z': ['min', 'max']})from vaex.ml.sklearn import Predictor
from sklearn.ensemble import GradientBoostingClassifier# Download the titanic dataframe (MIT License) from https://www.kaggle.com/c/titanic
# Load the titanic dataset into a vaex dataframe
titanic_df = vaex.open('titanic.csv')titanic_df = titanic_df.dropna()# Get numeric columns of titanic_df
features = ['Age','SibSp','Parch','Fare','Pclass']
target = 'Survived'model = GradientBoostingClassifier(random_state=42)
vaex_model = Predictor(features=features, target=target, model=model, prediction_name='prediction')vaex_model.fit(df=titanic_df)titanic_df = vaex_model.transform(titanic_df)Follow me for more content.

我是一名在技术部工作的数据科学家。我定期在 Medium 和 LinkedIn 上分享这样的数据科学技巧。关注我,了解更多未来内容。

如何加快大型语言模型的训练

原文:https://towardsdatascience.com/how-to-speed-up-training-for-large-language-models-81ffb30c36b2

探索序列并行性和选择性激活重新计算的概念

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

随着人工智能的进步,现在可以训练大型语言模型来完成自然语言处理任务。通常,大型语言模型包含超过 1000 亿个参数,并使用高级算法在大型语料库上进行训练。

大型语言模型(LLM)非常有效,能够很好地概括大多数下游任务,如文本生成、翻译、摘要、语义搜索等。因此,它为自然语言处理领域的开发人员和研究人员提供了新的能力。

在撰写本文时,世界各地的研究人员在训练大型语言模型方面取得了重大突破。下面的列表重点介绍了一些最著名的具有一流性能的大型语言模型:

  • OPT-175B —一个基于公开可用数据集的拥有 1750 亿个参数的语言模型。这是 Meta AI 研究计划的一部分。
  • BLOOM —在 46 种语言和 13 种编程语言上训练的 1760 亿个参数模型。这个模型是由大科学促成的。
  • 威震天-图灵 NLG 模型—105 层变压器模型,拥有 5300 亿个参数。这是微软和英伟达的共同努力。

训练一个大型的语言模型并不容易,而且常常伴随着许多挑战。例如:

  • 不可能在 GPU 的内存中容纳大型语言模型的所有参数。它需要分布式软件和硬件轨道来训练大型语言模型。
  • 训练时间长得不切实际,这使得训练大型语言模型的成本非常高。整个训练过程需要跨越数千个 GPU 的并行性。此外,算法需要进行优化,以便在内存和计算上高效且可扩展。

有两种新方法可用于改进大型语言模型的训练:

  • 序列并行性
  • 选择性激活重新计算(SAR)

NVIDIA AI 平台在其对 NeMo 威震天大型语言模型的最新更新中演示了这些技术。根据所提供的基准,当训练 GPT-3 模型的不同变体时,这两种技术都将训练时间减少了约 30%(最小的模型约为 220 亿个参数,而最大的模型高达 1 万亿个参数)。

本教程涵盖了这两种技术背后的基本概念。对于实际的实现,请前往官方库。

序列并行性

序列并行与张量级模型并行协同工作。首先,它注意到了以前没有并行化的 transformer 层区域。这些层在序列维度上是独立的。

请看下图中变形层的并行模式:

图片由英伟达公司提供

随后,它将通过沿着序列维度分割变换器层,在张量并行设备上分布这些区域的计算和激活存储器。结果,不需要重新计算,因为分布式激活可以用于反向传递。

根据发表的论文,嵌入层的输出是一个大小为 s × b × h 的三维张量。该输出也代表了变换器模块的输入。

*a* —注意头的数量

*s* —序列长度

*b* —微量批量

*h* —隐藏尺寸大小

*t* —张量平行尺寸

多层感知器(MLP)块所遵循的层范数的公式如下:

Y = LayerNorm(X),

Z = GeLU(Y A),

W = ZB,

V =压降(W)

x 是尺寸为 s × b × h 的层范数的输入。另一方面,A 和 B 表示线性层的权重矩阵。作者将张量并行和序列并行操作组合成单个减少-分散操作。

将所有这些部分结合在一起,最终的等式如下:

图片由作者提供。方程式是使用 Markdown 中的 LaTeX 创建的。

每个注意块大约需要

11sbh + 5as^2b

字节的存储。细分如下:

MLP

  • 两个线性层以 2sbh 和 8sbh 的大小存储它们的输入。
  • GeLU 非线性以 8sbh 大小存储其输入用于反向传播。
  • dropout 存储其大小为 sbh 的掩码。

MLP 块需要大约 19sbh 字节的存储。

层范数

  • 每个层 norm 存储其大小为 2sbh 的输入,使其总存储量为 4sbh。

存储变压器网络单层的激活所需的总存储器如下:

图片由作者提供。方程式是使用 Markdown 中的 LaTeX 创建的。

通过应用 t 向张量并行,存储每层激活所需的内存现在是:

图片由作者提供。方程式是使用 Markdown 中的 LaTeX 创建的。

通过结合 t-way 张量并行性和序列并行性,可以进一步减少所需的存储器:

图片由作者提供。方程式是使用 Markdown 中的 LaTeX 创建的。

选择性激活重新计算(SAR)

顾名思义,选择性激活重新计算通过仅重新计算每个转换器层的部分而不是整个转换器层来优化性能。这种方法对于由于内存限制而需要重新计算力的情况非常有用。

图片由英伟达公司提供

红色虚线示出了应用选择性激活重新计算的区域。请注意,不同的激活需要不同数量的重新计算操作。

通过组合 t-way 张量并行性、序列并行性和选择性激活重新计算,所需的存储器减少到:

图片由作者提供。方程式是使用 Markdown 中的 LaTeX 创建的。

上面的等式清楚地概述了这两种技术允许所需的激活记忆与序列长度成线性比例。此外,它们现在独立于注意力头的数量。

有关序列并行性和选择性激活重新计算的更多信息,可以参考下面的研究论文中的。

结论

序列并行和选择性激活重新计算是加速大型变压器模型训练的两种新颖而简单的方法。这两种技术具有相似的内存节省,并且有望将训练所需的内存减少大约 5 倍。因此,训练大型语言模型的成本和时间显著减少。

话虽如此,它要被大众广泛采用还有很长的路要走。希望人工智能社区将继续在现有研究的基础上创新,使每个人都有可能访问和部署大型语言模型。

感谢你阅读这篇文章。祝你有美好的一天!

参考

  1. 使用 OPT-175B 民主化访问大规模语言模型
  2. 推出全球最大的开放多语言模型——BLOOM
  3. NVIDIA AI 平台为大型语言模型带来巨大收益

如何用 Numpy 矢量化加速数据处理

原文:https://towardsdatascience.com/how-to-speedup-data-processing-with-numpy-vectorization-12acac71cfca

数据准备

比标准函数快 8000 倍

由 Djim Loic 在 Unsplash 上拍摄的照片

在处理较小的数据集时,很容易认为普通的 Python 方法足以快速处理数据。然而,随着产生的数据量的增加,以及通常可用于分析的数据量的增加,尽可能快地优化代码变得比以往更加重要。

因此,我们将探讨如何使用矢量化和 numpy 库来帮助您加速数字数据处理。

python 为什么慢?

Python 是众所周知的用于数据处理和探索的优秀语言。主要的吸引力在于它是一种高级语言,因此理解和学习起来简单直观,编写和迭代也很快。如果您的重点是数据分析/处理,而不是编写堆积如山的代码,您会想要的所有功能。

然而,这种易用性也有不好的一面。与 c 等低级语言相比,它处理计算的速度要慢得多。

Wolfgang Hasselmann 在 Unsplash 上拍摄的照片

幸运的是,由于 python 是数据分析和数据科学社区(以及许多其他社区)选择的语言之一,因此有大量的库和工具可用来缓解 python 在处理大量数据时固有的“缓慢”。

到底什么是矢量化?

当谈到用 numpy 加速计算时,您会经常看到“矢量化”这个术语。Numpy 甚至有一个叫做“矢量化”的方法,我们将在后面看到。

一般的谷歌搜索会产生大量关于矢量化实际是什么的混乱和矛盾的信息,或者只是泛泛而谈,不能告诉你太多:

NumPy 上的矢量化运算的概念允许在 NumPy 数组对象和数据序列上使用更优化的预编译函数和数学运算。与简单的非矢量化操作相比,输出和操作将会加快。

-GeekForGeeks.org-搜索时的第一个谷歌结果——什么是 numpy 矢量化?

它只是没有说更多:由于优化它会变得更快。

什么优化?

问题是 numpy 是一个非常强大的优化工具。当实现类似矢量化的东西时,numpy 中的实现除了简单的传统矢量化之外,还包括许多经过深思熟虑的优化。我认为这是很多困惑的来源,分解正在发生的事情(至少在某种程度上)将有助于让事情变得更清楚。

在 numpy 中分解矢量化

接下来的部分将分解 numpy 库中使用的一般“向量化”保护伞下通常包含的内容。

了解它们各自的功能,以及它们如何提高 numpy“向量化”操作的速度,应该有助于解决任何困惑。

实际矢量化

矢量化是一个在 numpy 之外使用的术语,用最基本的术语来说就是计算的并行化。

如果你有一个 1D 数组(或称为向量):

[1, 2, 3, 4]

…将向量中的每个元素乘以标量值 2,最终得到:

[2, 4, 6, 8]

在普通 python 中,这将使用类似 for 循环的东西一个元素一个元素地完成,因此一个接一个地进行四次计算。如果每次计算需要 1 秒钟,那么完成计算并发布结果需要 4 秒钟。

然而,numpy 实际上将两个向量相乘[2,2,2,2][2,4,6,8] (numpy 使用一种叫做 broadcasting 的东西将标量值 2“拉伸”成一个向量,请参阅下一节了解更多信息)。四个独立计算中的每一个都是同时并行完成的。所以从时间上来说,计算是 1 秒完成的(每次计算需要 1 秒,但都是同时完成的)。

仅仅通过计算的“矢量化”(或者,如果你喜欢,一种并行处理的形式),速度就提高了四倍。请记住,我给出的例子非常简单,但它确实有助于说明基本情况。

您可以看到,如果您正在处理包含数千个(如果不是数百万个)元素的数据集,这相当于一个非常大的差异。

请注意,并行化不是无限的,在某种程度上依赖于硬件。Numpy 不能同时并行处理 1 亿次计算,但它可以显著减少串行计算量,尤其是在处理大量数据时。

如果你想要更详细的解释,那么我推荐这篇 stackoverflow 帖子,它在更详细的解释方面做得很好。如果你想要更多的细节,那么的这篇文章和的这篇文章都很棒。

广播

广播是 numpy 的一个特性,它允许在不同大小的数组之间执行数学运算。实际上,我们在上一节中已经这样做了。

标量值 2 被“拉伸”成一个充满 2 的数组。这就是广播,也是 numpy 为更高效的计算准备数据的方式之一。然而,说“它只是创建了一个 2 的数组”是一种过于简单化的说法,但是不值得在这里详细讨论。

Numpy 自己的文档实际上非常清楚:

术语广播描述了 NumPy 在算术运算中如何处理不同形状的数组。在某些约束条件下,较小的阵列在较大的阵列中“广播”,以便它们具有兼容的形状。广播提供了一种向量化数组操作的方法,因此循环在 C 而不是 Python 中发生。

-numpy.org

更快的语言

尤利安·巴尔加斯在 Unsplash 上拍摄的照片

正如前面引用的 numpy 自己的文档中所详述的,numpy 使用预编译和优化的 C 函数来执行计算。

由于 C 是一种低级语言,因此有更多的空间来优化计算。这不是你需要考虑的事情,因为 numpy 库已经为你做了,但是你会从中受益。

同类数据类型

在 python 中,你可以灵活地混合使用不同的数据类型(字符串、整型、浮点型等)来指定列表。).在 numpy 中处理数据时,数据是同构的(即都是同一类型)。这有助于加快计算速度,因为数据类型不需要像在 python 列表中那样即时计算出来。

这当然也可以看作是一种限制,因为它使得处理混合数据类型更加困难。

把所有的放在一起

如前所述,当谈到 numpy 中的矢量化时,将上述所有内容(以及更多内容)组合在一起是很常见的。然而,由于矢量化也在其他上下文中用于描述更具体的操作,这可能会非常混乱。

希望大家对我们正在处理的事情有一点点的了解,现在我们可以开始实际的工作了。

numpy 的矢量化实现真的有多大作用?

实际例子

为了演示 numpy 中矢量化的有效性,我们将使用 pandas 库比较几种不同的常用方法来应用数学函数和逻辑。

pandas 是一个快速、强大、灵活且易于使用的开源数据分析和操作工具,构建在 Python 编程语言之上。

-pydata.org

Pandas 在处理表格数据时被广泛使用,它也是建立在 numpy 之上的,所以我认为它是展示矢量化有效性的一个很好的媒介。

随后的所有计算都可以在 colab 笔记本上找到

数据

数据将是一个有两列的简单数据帧。这两列都将由取自正态分布的 100 万行随机数组成。

df = pd.DataFrame({‘series1’:np.random.randn(1000000), ‘series2’:np.random.randn(1000000)})

这导致:

操控

然后,上面的数据帧将由两个不同的函数操作,以创建第三列**‘series 3’**。这是熊猫非常常见的操作,例如,在为机器或深度学习创建新功能时:

功能 1 —简单求和

def sum_nums(a, b):return a + b

功能 2 —逻辑和算术

def categorise(a, b):if a < 0:return a * 2 + belif b < 0:return a + 2 * belse:return None

将使用不同的方法(有些是矢量化的,有些不是)应用上述每个函数,以查看哪种方法在一百万行上执行计算最快。

方法和结果

下面的处理方法按速度顺序排列。最慢的先来。

每种方法都使用 timeit 库运行了多次,并且使用了上一节中提到的两个函数。对于较慢的方法是一次,对于较快的方法是 1000 次。这确保了计算不会运行太长时间,并且我们得到足够的迭代来平均每次迭代的运行时间。

熊猫敷法

熊猫敷法非常简单直观。然而,这也是在大型数据集上应用计算的最慢方式之一。

没有优化计算。它基本上是执行一个简单的 for 循环。除非功能要求排除了所有其他方法,否则应该避免使用这种方法。

# Function 1
series3 = df.apply(lambda df: sum_nums(df['series1'],df['series2']),axis=1)# Function 2
series3 = df.apply(lambda df: categorise(df['series1'],df['series2']),axis=1)

在一些简单的实现中,Itertuples 甚至比 apply 方法更慢,但是在这种情况下,它与列表理解一起使用,因此在速度上比 apply 方法提高了近 20 倍。

Itertuples 消除了处理 pandas 系列的开销,而是使用命名元组进行迭代。如前所述,这个特定的实现还受益于 list comprehension 提供的加速,因为它消除了追加到列表的开销。

注意:还有一个名为 iterrows 的函数,但是它总是比较慢,因此为了简洁起见而被忽略。

*# Function 1
series3 = [sum_nums(a, b) for a, b in df.itertuples(index=False)]# Function 2
series3 = [categorise(a, b) for a, b in df.itertuples(index=False)]*

列表理解

前面的 itertuples 示例也使用了列表理解,但是这个使用“zip”而不是 itertuples 的特殊解决方案似乎快了两倍。

其主要原因是 itertuples 方法引入的额外开销。Itertuples 实际上在内部使用 zip,因此任何到达应用 zip 的地方的额外代码都只是不必要的开销。

在这篇文章中可以找到对此的一个很好的调查。顺便说一下,这也解释了为什么 iterrows 比 itertuples 慢。

*# Function 1
series3 = [sum_nums(a, b) for a, b in zip(df['series1'],df['series2'])]# Function 2
series3 = [categorise(a, b) for a, b in zip(df['series1'],df['series2'])]*

Numpy 矢量化方法

这有点奇怪。该方法本身被称为“矢量化”,但事实是,它远没有我们将在下面的方法中看到的全面优化的矢量化快。甚至 numpy 自己的文档也指出:

矢量化功能主要是为了方便,而不是为了提高性能。该实现本质上是一个 for 循环。

- numpy .或 g

然而,用于实现该功能的语法确实非常简单明了。最重要的是,该方法实际上在加速计算方面做得很好,比我们迄今为止尝试过的任何方法都好。

它也比后面的方法更灵活,因此在许多情况下更容易实现,不会有任何混乱。因此,Numpy 矢量化是一种很好的方法,强烈推荐使用。

值得记住的是,虽然这种方法很快,但它甚至无法达到我们将要看到的完全优化的方法所能达到的效果,因此它不应该只是所有情况下的首选方法。

*# Function 1
series3 = np.vectorize(sum_nums)(df['series1'],df['series2'])# Function 2
series3 = np.vectorize(categorise)(df['series1'],df['series2'])*

熊猫矢量化

现在,我们全面了解优化的矢量化。

与以前的任何方法相比,速度上的差别是天壤之别,也是本文前面讨论的所有优化协同工作的一个主要例子。

pandas 的实现仍然是 numpy 的实现,但是语法非常非常简单。如果你能以这种方式表达你想要的计算,你就不能在速度方面做得更好,而不提出一个明显更复杂的实现。

大约比 apply 方法快 7000 倍,比 numpy 矢量化方法快 130 倍!

缺点是,这种简单的语法不允许处理复杂的逻辑语句。

*# Function 1
series3 = df['series1'] + df['series2']# Function 2
# N/A as a simple operation is not possible due to the included logic in the function.*

***Numpy 矢量化 ***

最终的实现是我们能够实现的最接近原始 numpy 的实现,同时仍然有来自 pandas 数据帧的输入。

尽管如此,通过在计算中去掉任何 pandas 开销,与 pandas 实现相比,处理时间减少了 15%。

这比 apply 方法快 8000 倍。

*# Function 1
series3 = np.add(df['series1'].to_numpy(),df['series2'].to_numpy())# Function 2
# N/A as a simple operation is not possible due to the included logic in the function.*

结论

我希望这篇文章有助于澄清一些特别是与矢量化相关的术语,从而让您更好地理解哪种方法最适合您的特定情况。

根据经验,如果您正在处理大型数值数据集,pandas 和 numpy 中的矢量化方法是您的好朋友:

  1. 如果计算允许,尝试使用 numpy 内置的数学函数
  2. 熊猫的数学运算也是不错的选择
  3. 如果你需要更复杂的逻辑,使用 numpy 的 vectorize⁴方法
  4. 如果以上所有方法都失败了,那么就需要决定你到底需要什么功能,并选择一个合适的较慢的方法(列表理解、互耦、应用)

如果你发现自己处在一个既需要速度又需要灵活性的情况下,那么你就处在一个特殊的位置。您可能需要开始考虑实现您自己的并行化,或者编写您自己的定制数字 functions⁵.所有这些都是可能的。

如果你觉得这篇文章有趣或有用,记得关注我,或者注册我的简讯获取更多类似的内容。

如果你还没有,你也可以考虑订阅媒体。你的会员费不仅直接支持我,也支持你所阅读的其他作家。你还可以完全不受限制地访问媒体上的每个故事。

使用我的推荐链接注册会给我一点回扣,对你的会员资格没有影响,所以如果你选择这样做,谢谢你。

*https://medium.com/@maclayton/membership

参考

1 https://pandas.pydata.org/docs/reference/api/pandas.[DataFrame.itertuples.html](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.itertuples.html)

2 Mazdak ,为什么列表理解比追加列表快那么多? (2015),stackoverflow.com

3https://numpy.org/doc/stable/reference/routines.math.html

4https://numpy . org/doc/stable/reference/generated/numpy . vectorize . html

5https://numpy . org/doc/stable/user/c-info . uf unc-tutorial . html*

如何使用 SQL 在 BigQuery 中对数据集进行分割和采样

原文:https://towardsdatascience.com/how-to-split-and-sample-a-dataset-in-bigquery-using-sql-a94fc05fdc71

轻松地将数据划分为训练集、验证集和测试集

扎克·波特在 Unsplash上的照片

为什么要分割我们的数据集?

拆分数据意味着我们将把它分成子集。对于数据科学模型,数据集通常被划分为两个三个子集:训练、验证和测试。

从创建模型到确保其性能,每个数据子集都有其用途。

不同细分市场的快速定义:

  • 训练:本质上是我们用来训练模型的数据子集。
  • 验证:当创建模型时,这用于改变或适应学习过程。它还有助于防止过拟合和微调输入参数。
  • **测试:最后,**我们确实需要一个数据子集来评估模型性能和结果。

分割尺寸和比例

为了决定每个子集的大小,我们经常会看到标准的规则和比率。您可能会遇到使用 80 -20 规则 (80%用于培训分割,20%用于测试分割),或 70-20-10 规则 (70%培训,20%验证,10%测试)等分割的情况

关于什么是最佳分割已经有过一些讨论,但总的来说,我建议记住,没有足够的数据,无论是训练集还是验证集,都将导致模型难以学习/训练,或者您将难以确定该模型实际上是否表现良好。

值得注意的是,不一定非要做三段。在 BigQuery 中,您通常只能生成训练和测试子集,因为可以在使用DATA_SPLIT选项创建模型时处理验证。

https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-create-glm#data_split_method

陷阱和注意事项

在分割数据集之前,您应该了解一些常见的陷阱:

  • 低质量数据:如果用来创建你的模型的输入数据是嘈杂的或者不可信的,那么模型的输出很可能反映了这一点。
  • 过度拟合:当输入数据不足时,模型可能会学习训练数据,以至于任何噪声或波动都被认为会导致不可靠的预测。
  • 不平衡数据集:假设您想要训练一个预测客户购买的模型,但是您有 50 万个非购买者和 300 个购买者,您将首先需要创建一个更加平等的数据集(使用重采样技术)。探索性数据分析( EDA )将有助于发现不平衡的数据。
  • **数据泄漏:**它描述了在创建训练数据集之前或甚至在拆分期间(例如,当同一天的事件可能相关时,按日期拆分数据)输入数据已被操纵(缩放、转换)的事实,导致模型不能反映现实。

使用 SQL 拆分数据集

对于我们的实验,我们有下面的数据集,由 11k 行和三个字段组成,一个订单 ID、一个日期和一个关联的订单值。

我们将把这个表分成训练和测试子集。(图片由作者提供)

选择要拆分的右列

为了进行适当的拆分,使用一列来单独区分你的基表的每一行。如果不是这样,就很难创建一个均匀分布的分割,并且可能会使分割的随机性产生偏差。

为了实现独特性,我们有几个选项,您将在我们即将推出的实践示例中看到:

  • 我们可以创建一个具有唯一值的新字段(例如一个随机数生成器函数,如RAND()UUID()
  • 我们可以创建单个已经唯一的字段的散列,或者创建一个唯一的行标识符的字段组合的散列。

对于第二个选项,你最常听说的散列函数是FARM_FINGERPRINT()

但是,为什么是这个而不是其他的比如MD5()或者SHA()

这是由于的两个特点。首先,对于相同的输入,它总是给出相同的结果,其次,它返回一个INT64值(本质上是一个数字,而不是数字和字符的组合),我们可以用其他数学函数(如MOD()来控制它,以产生我们的分割比。

创建唯一的行标识符

要创建唯一的行标识符,可以使用FARM_FINGERPRINT()函数。为了详细说明这个过程,下面是一行中的单个列和所有列的组合的每个转换步骤:

最后,我们将在数据集中继续拆分的是最后一列(我们称之为hash_abs_mod的列)。下表从左到右简单说明了哈希过程的每个步骤。

哈希和模函数对我们的基表的影响。(图片由作者)

在我们的基表中,我们已经为每一行准备了一个惟一的值标识符,这就是我们的order_id字段。在这种情况下,我们可以散列它,然后使用ABS(MOD(x,10))函数将每一行分类到从 0 到 9 的桶中。

要创建整行(即所有列)的散列,最好的方法是首先标记您的表(我们称之为bt),然后使用TO_JSON_STRING(bt)将其转换为 JSON 对象。然后可以对此进行哈希运算。这个方法的唯一目标是帮助您避免出现重复的行,这些行将总是以相同的分割结束,并偏向随机方面。

创建不可重复的拆分

要随机分割一个数据集,我们可以使用RAND()函数。这将为每一行返回一个伪随机十进制数,区间为[0–1],包括 0,不包括 1。

该函数确实为提供了均匀分布,这意味着我们可以过滤所有小于 0.8 的值,例如,而将代表我们数据的 80%** 。**

但是请记住,每次运行查询时,该函数将返回不同的数字,因此您的训练集和测试集将会不同。如果您想让结果持久化,您可以通过将查询结果存储为一个表来制作快照。

让我们随机划分 80%的培训和 20%的测试:

您可以在结果中看到,我们确实有一个由我们的RAND()函数生成的具有许多小数的数字,以及由我们的IF()语句给出的标签(train/test)。

但是,请记住,如果不按原样存储结果,您将无法复制完全相同的分割。

使用 RAND()分为训练和测试。(图片由作者提供)

创建可重复的拆分

为了创建一个可以重用的分割,最好是使用MOD()FARM_FINGERPRINT()功能的组合**,因为对于相同的输入,输出将保持不变。**

让我们使用我们的唯一键(order_id字段)。我们可以使用具有以下范围的 CASE WHEN 语句进行 80/10/10 可重复拆分:

分成 3 个子集(培训、验证和测试)

结果将与我们之前的不可重复分割相同,除了这个查询将总是产生相同的分割(train、validation 和 test 的分配将总是进入相同的行)。

使用 MOD()和 FARM_FINGERPRINT()分为训练、验证和测试。(图片由作者

结论和补充说明

你现在知道如何将你的数据集分割成子集,以可重用或不可重用的方式。因此,我们没有涵盖时间方面,例如,当在日期字段上拆分时。

这在为时序预测或回归模型定型时很常见,这意味着您可能希望保留日期的顺序。这也意味着您必须验证哪个时间范围覆盖了您基础数据的 80% (在 80/20 分割的情况下)。

此外,具有相同日期的行往往是相关的(某一天发生的事件可能会影响同一天的事件),这就是为什么这些行应该保留在同一个拆分中。您还需要小心丢失的数据和数据质量,并且排除一些由于异常或季节性的数据。

如何在 Python 中标准化数据

原文:https://towardsdatascience.com/how-to-standardize-data-in-python-d3e73f4ccf3c

在本文中,我们将探索如何在 Python 中标准化数据。

Marcin Jozwiak 在 Unsplash 上拍摄的照片

目录

  • 介绍
  • 什么是标准化
  • 标准化示例
  • 如何在 Python 中标准化数据
  • 结论

介绍

许多机器学习模型的特征工程的第一步是确保数据被适当地缩放。

一些模型,如线性回归、KNN 和 SVM,会受到不同比例要素的严重影响。

其他算法,如决策树、bagging 和 boosting 算法通常不需要任何数据缩放。

特征比例对上述模型的影响程度较高,并且具有较大范围值的特征将在算法决策中发挥更大的作用,因为它们产生的影响对输出具有更大的影响。

在这种情况下,我们转向特征缩放,以帮助我们找到所有这些特征的共同水平,以便在训练模型时平等地评估。

两种最流行的特征缩放技术是:

  1. z 分数标准化
  2. 最小-最大归一化

在本文中,我们将讨论如何使用 Python 执行数据的 z 分数标准化。

为了继续学习本教程,我们需要以下两个 Python 库:sklearn 和 pandas。

如果您没有安装它们,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它们:

pip install sklearn
pip install pandas

什么是标准化

在统计学和机器学习中,数据标准化是根据数据的均值和标准差将数据转换为 z 分值的过程。

得到的标准化值显示原始值偏离平均值的标准偏差数。

基本上,数据集给定要素的每个值都将被转换为偏离要素平均值的标准偏差的代表值。

这将允许我们一起比较多个特征,并获得更多相关信息,因为现在所有数据将处于相同的比例。

标准化数据的平均值等于 0,值通常在-3 和+3 之间(因为 99.9%的数据在平均值的 3 个标准偏差范围内,假设您的数据遵循正态分布)。

让我们来看看 z 分数公式:

作者图片

对于每个特征,我们将计算其平均值和标准差。然后我们将从每个观察值中减去平均值,再除以标准差,得到标准化值。

标准化示例

在这一节中,我们将看一个简单的数据标准化的例子。

考虑以下具有不同苹果价格的数据集:

作者图片

绘制数据集应该是这样的:

作者图片

在这里,我们看到重量与价格相比有更大的变化,但看起来是这样,因为数据的不同尺度。

价格范围在 2 美元到 5 美元之间,而重量范围在 250 克到 800 克之间。

让我们把这些数据标准化吧!

从重量特征开始:

并对价格功能进行同样的操作:

作者图片

并将这两个特征组合成一个数据集:

作者图片

我们现在可以看到,数据集中要素的比例非常相似,并且在可视化数据时,点之间的分布会更小:

该图看起来几乎相同,唯一的区别是每个轴的比例。

现在让我们看看如何使用 Python 重现这个例子!

如何在 Python 中标准化数据

让我们首先创建一个我们在上面的例子中使用的数据帧:

您应该得到:

 weight  price
0     300      3
1     250      2
2     800      5

一旦我们准备好数据,我们就可以使用 StandardScaler() 类及其方法(来自 sklearn 库)来标准化数据:

您应该得到:

[[-0.60404045 -0.26726124][-0.80538727 -1.06904497][ 1.40942772  1.33630621]]

如您所见,上面的代码返回了一个数组,所以最后一步是将其转换为 dataframe:

您应该得到:

 weight     price
0 -0.604040 -0.267261
1 -0.805387 -1.069045
2  1.409428  1.336306

这与我们手动计算的示例中的结果相同。

结论

在本教程中,我们讨论了如何在 Python 中标准化数据。

数据标准化是许多机器学习算法中数据预处理的重要步骤。

这通常是一个必需的预处理步骤,用于调整输入数据中要素的范围,以确保范围较大的要素不会通过影响距离度量来消除模型的所有可解释性。

是否对数据进行标准化的决定主要取决于您正在构建的模型,因为有些模型很容易受到数据范围的影响(OLS、SVM 等),而有些模型则不受影响(逻辑回归、基于树的模型等)。

如果你有任何问题或对一些编辑有建议,请随时在下面留下评论,并查看更多我的机器学习文章。

原载于 2022 年 5 月 3 日https://pyshark.com

如何开始为开源软件做贡献

原文:https://towardsdatascience.com/how-to-start-contributing-to-open-source-software-9651ca4cedd4

直接参与的指南

开始使用开源软件可能会感到害怕,但事实并非如此。在本指南中,您将学习如何为开源做出贡献,无论您的经验水平如何。

资料来源:pixabay.com

首先,让我们看看你为什么想要参与进来。

为什么要贡献开源?

有很多原因促使项目使用主导的软件开发模型。以下是回报社区的几个理由,我们都从中受益:

  • 为您自己或其他用户解决问题
  • 修复安全问题
  • 构建新功能
  • 帮助用户理解事物是如何工作的
  • 发展你的技能
  • 向其他人展示你的能力

好吧,所以贡献是你应该做的事情之一。但是不知道如何开始会让人麻痹。让我们制定一个路线图,让事情变得更简单。

如何为开源🛠做贡献

不管你的技能水平如何,你都有很多方法可以为开源做出贡献。让我们从每个人现在都能做的事情开始。

你发现有价值的⭐️

GitHub 是绝大多数开源工作完成的地方。如果您没有免费的 GitHub 帐户,您需要创建一个。

向 GitHub 存储库添加一颗星,向其他人表明您发现了一个有价值的存储库。这个社区信号非常有用,因为我们都需要决定使用哪个存储库。

使用和关注越多的开源库一般反馈越多,贡献者也越多。这些资源引导项目被更新,以便它们保持安全和相关。

星星是最快的价值信号,所以当一颗星星是应得的时候,就加一颗。

制造一个问题⚠️

启动一个回购需要一秒钟,而第一次创建一个问题可能需要几分钟。尽管如此,这并不是一个巨大的提升。提交问题是您提醒开发团队关于错误、所需的文档修复和特性请求的方式。

假设你认为你在一个项目中发现了一个 bug。首先,确保您已经检查了文档和堆栈溢出,并做了一些谷歌搜索。

然后是时候去 GitHub 回购项目了。如果你在文档中没有现成的直接链接,通常可以通过谷歌搜索“ project_name GitHub”找到回购。

点击问题。

搜索关于该主题的任何未决问题。你可能不是第一个发现这个问题的人。如果有人已经打开了一个关于相同问题或功能请求的 GitHub 问题,请在现有问题中添加评论,而不是复制它。

假设您发现没有人报告您的问题。是时候创造一个了。点击绿色的新问题按钮。

有些项目回购有问题模板供您使用。如果有说明,就照着做。

没有模板的 Repos 的标题和描述字段为空白。

尽可能详细地描述这个问题,如果你认为有帮助的话。如果适用,包括您使用的软件包版本、编程语言版本和您的硬件(如 Windows 10)。

包含错误的完整堆栈跟踪是非常好的。利用降价格式使问题更具可读性。Markdown 类似于添加了一些符号以使格式美观的普通文本。这里有一个快速指南。快速提示:三个反勾号`````将为您提供代码格式,这使得读取堆栈跟踪更加容易。

如果你能创建一个最小可重复的例子(MRE ),这对那些试图诊断和修复你的问题的人来说是一个巨大的帮助。只要记住把任何代码放在反斜线中。

请记住,开源贡献者通常是志愿者和忙碌的人。请善待他们。🙂

让我们看看你如何能直接促成改变。

改进✍️文档

让我们先来看看文档的变化。为了纠正一个打字错误或添加一些文档,有时你可以幸运地点击一个编辑按钮。

然后,您可以在浏览器中调整降价文件。

如果你要改变文档的格式,你可能会使用 Markdown。有些回购是用 reStructuredText(。rst)。我会在你的第一份文档工作中避免使用 rst,因为学习那个 Markdown 有点困难,但是如果你想学习 rst,这里有一个指南。

在浏览器中进行更改后,您可以创建一个拉请求。

如果您处理的不仅仅是一个文件,那么您会想要派生 repo,并将这个派生文件克隆到您的机器上。

如果您正在寻找 docs 文件,它们通常可以在 docs 文件夹中找到。如果有的话,提供的指导方针可以帮助您知道在哪里可以找到这些文件。通常它们在一个名为 docs 的文件夹中。

然后,您将在文本编辑器中工作,提交更改,并将更改推送到您的 repo。最后,您将打开一个拉取请求。

如果你想练习提出拉式请求,这个回购就是为此而设计的!

好了,让我们回到最后一个场景——贡献一些代码。

修复🧑‍代码中的一个错误💻

向存储库贡献代码的门槛有点高。您需要:

  • 精通所使用的编程语言
  • 创建一个开发环境——应该有说明
  • 花时间了解代码库
  • 编写测试

这里有一些提示来指导你的方式。

如何找到好的第一个项目🚀

起步小

如果这是你第一次写代码,我建议从一个小项目开始。较小的项目需要较少的时间来理解。它也可能有一个运行速度更快的测试套件。

确保项目处于活动状态

你会想要一个积极维护的项目。您可以看到自存储库中的文件更新以来已经过了多长时间。如果六个月内什么都没做,那么无论你做什么都不可能很快融入代码库。☹️

如何找到一个好的问题来解决📝

你想要速战速决。寻找一个你认为你可以在几个小时内解决的问题。

不同的项目管理方式略有不同。如果项目有诸如*good first issue*之类的问题标签,这些可能是一个有收获的地方。

如果你的编码技能很强,可以随意解决更难的问题。

如何让你的拉请求合并✅

遵循风格指南

许多项目都有一个风格指南。如果有,它很可能在贡献文档文件中。使用文档字符串,如果你使用 Python,使用类型提示。遵循指示是游戏的大部分。🙂

编写测试

编写测试是使代码可靠的一个好方法。代码风格的测试和林挺通常必须在你的 PR 被接受之前通过。

如果您添加了新功能,请确保在文档中添加说明。

在本地运行测试,确保一切顺利。提交您的代码,并将其推送到您的存储库。现在你可以要求维护者接受你的贡献了。

创建公关

点击绿色的新拉动请求按钮,创建请购单。

描述当您打开拉取请求时,它会做什么。

当您提交 pull 请求时,测试和格式化可能会在云中运行。

现在怎么办?

也许你的 PR 马上就被接受了。厉害!

很有可能你会花一点时间等待某人回复你。保持耐心。

如果已经过了几个星期,没有人对你的 PR 发表评论,要求修改,或者把它合并到主分支,你可以礼貌地询问是否有人可以看一下。

在 GitHub 中,如果你使用@和维护者的句柄,就会 ping 它们(谨慎使用)。希望你遵循了上面的建议,选择了一个正在积极维护的库。

如果你被要求做出改变,请这样做或在 GitHub 评论中讨论。

包装

您已经看到了如何开始为开源做贡献!开源社区的繁荣需要一个虚拟的村庄。有了你的贡献,你就加入了这个社区。🎉

我希望这个指南对你有所帮助。如果你有,请在社交媒体上分享,这样其他人也可以找到它。

如果你想参与到 Prefect 中来,我们将通过举办一场非正式的#winterjamboree 让人们更容易参与,有点像#hacktoberfest,但更酷。明白了吗?😉在提督 GitHub repo 上查看一些好的第一期 寻找灵感,并提交一些提督赠品的 PR!

资料来源:pixabay.com

快乐贡献!

如何开始学习 R 编程语言

原文:https://towardsdatascience.com/how-to-start-learning-the-r-programming-language-90e7c98ff3b9

在本指南中,我将带您逐步创建一个全面的学习计划,为您打下坚实的 R 语言基础

帕特里克·帕金斯的照片——Unsplash.com

【免责声明:这篇文章包含了我的《绝对初学者 R 编程》一书的一些链接,可以在亚马逊上找到】

对于那些不熟悉 R 的人来说,R 是一种开源编程语言,广泛用于数据分析和统计计算。这是一个强大的工具,允许您处理大型数据集,创建可视化,构建算法等。

大多数 R 课程或材料都是从向您展示如何处理数据框架、读取外部数据或训练模型开始的。虽然学习所有这些概念确实是学习 R 的重要部分,但是还有许多其他的基本概念对语言的坚实基础至关重要。掌握这些基础知识是关键,通过这样做,您将能够更有效地使用 R,避免使用该语言时可能出现的常见陷阱和令人头痛的问题。

虽然首先跳到更实际的例子可能很诱人,但是花时间学习基础概念是很重要的,比如数据结构或数据类型。例如,使用 R 的一个关键方面是理解如何存储数据以及它与 R 对象的关系。向量、数组、矩阵和列表都是基本的数据结构,允许您存储和操作数据,它们包含许多使它们独一无二的属性。

我的最新著作遵循了一个关于如何接近 R 语言的成熟结构,并带你踏上从零开始学习 R 语言的旅程——这种方法已经帮助了全球 8000 多名学生(在 Udemy 上),帮助他们掌握这门语言,即使他们没有任何编码背景。在这篇博文中,我将详细介绍书中涉及的不同概念,以及我为帮助学生掌握 r。

面向绝对初学者的 r 编程语言—图片由作者提供

在我们开始详细描述每个步骤之前,先简单概述一下我们将要讨论的内容:

r 学习流程—作者图片

第一个——R 向量

在《绝对初学者的 R 编程》一书中,我们从最基本的 R 对象——R 向量开始。

在 R 中,vector 是一种基本的数据结构,它存储一系列相同类型的元素。向量通常用于存储可以连续表示的数据,如一系列数字或字符串。可以通过多种方式创建向量,例如,使用代表“组合”的c()函数,或者使用切片(例如1:10)。

如何创建 R 向量的示例如下:

example <- c(1, 2, 3, 4, 5)

向量有几个重要的性质:它们可以被索引,它们同时保持单一类型,并且是一维对象。

操纵 R 向量

接下来,在创建和构建了我们的第一个 R 向量之后,这本书介绍了您将对 R 对象进行的两个常见操作:

  • 索引元素。
  • 修改数据结构(添加、删除或更改元素)。

首先,我们将探索如何对向量进行子集化,通过使用方括号[]结合数字索引,命名或逻辑向量。我们将使用几个代码示例详细探索所有这些索引技术。

我们还将检查在 R 中修改或删除元素的多种方法,特别是探索如何使用索引来添加、删除或更改向量元素。

这方面的一个例子是使用 subsetting 操作符——假设您想要从向量 x 中删除第二个元素,您可以使用下面的代码:x[-2]:这将创建一个新的向量,其中包含除第二个元素之外的所有元素x

总的来说,在 Vectors 介绍之后的章节将集中于在 R 中操作对象,并熟悉添加、更改或删除元素——这是熟悉 R 语言的关键技术。

数据类型

向量的一个最重要的特征是它一次只能保存一种类型。这个事实把我们带到了该语言最重要的组成部分之一——R 数据类型!

r 数据类型用于指定特定对象可以存储的数据类型。 R 有多种数据类型,包括数值、字符、逻辑、因子或日期数据类型。

数字数据类型包括整数和浮点数:整数是整数,而浮点数是包含小数点的数字。数字数据类型通常用于存储和操作数字数据,如计数、测量或统计。另一方面,字符数据类型通常用于存储文本数据,如名称或描述。

为数据选择合适的数据类型至关重要。使用错误的数据类型会导致分析中的错误或意外结果,因为数据类型决定了可以对 R 对象执行什么类型的操作!

扩展 R——多类型和多维对象

当然,我们不局限于在 r 中使用单一类型或单一维度的对象。数组、矩阵或列表是为我们提供额外功能的对象,与数据分析和科学管道极其相关。

在 R 中,矩阵是二维的数据集合,有行和列。使用matrix函数(或使用array命令传递两个维度)创建矩阵,该函数接受一个数据向量和可选的行数和列数参数。例如:

# Create a 2x3 matrix with 6 elements
m <- matrix(1:6, nrow = 3, ncol = 2)

这将创建一个 3 行 2 列的矩阵,包含元素 1 到 6。

数组也是一个多维对象(通常有两个以上的维度),它们是使用array函数创建的,该函数接受一个数据向量和一个维度向量。例如:

# Create a 3-dimensional array with dimensions 2x3x4
a <- array(1:24, dim = c(2, 3, 4))

这将创建一个包含 2 行、3 列和 4 个切片的数组,包含元素 1 到 24。使用索引访问多个维度很容易——我们只需在我们的[]操作符上打开新的逗号!

# Access the element at row 2, column 3, and slice 4
a[2, 3, 4]

另一方面,列表是 R 中对象的集合,可以由不同的类型和维度组成。列表是语言中最灵活的对象,使用list函数创建,将一系列对象作为参数。例如:

#Create a list with a vector, a numeric vector, and a matrix
l <- list(c("a", "b"), c(1, 10, 100), matrix(1:9, nrow = 3))

这个简单的命令创建了一个包含 3 个元素的列表:一个字符向量、一个数字向量和一个矩阵。

在学习旅程的这一点上,在研究了几种类型的 R 对象之后,我们仍然缺少最著名的一个——数据框!

调查数据框

可以说,最重要的 R 对象是数据框。在本书中,我们将用整整两章的时间详细介绍如何使用这个著名的 R 对象,并一步一步地介绍使用这种表格格式时可以遵循的正常流程。

数据框类似于矩阵,但它们有一个巨大的区别:每列可以有不同的类型(数字、字符、因子等。),当我们比较这两个对象时,这是一个很大的优势。

您可以使用data.frame函数在 R 中创建一个数据框,该函数将一系列向量作为参数。每个向量最终将成为新对象中的一列:

# Create a data frame with three columns: "Name", "Age", and "Degree"
students <- data.frame(Name = c("Alice", "Joe", "John"),Age = c(20, 21, 19),Gender = c("Mathematics", "History", "Literature"))

这将创建一个 3 行 3 列的数据框,包含三个人的姓名、年龄和性别。

数据框还有一个名为row.names的特殊属性,它指定数据框的行名。您可以使用row.names函数访问行名,也可以使用相同的命令设置它们。例如:

# Get the row names of the data frame
row.names(students)# Set up Rows for the Data Frame
row.names(students) <- c("Student 1", "Student 2", "Student 3")

掌握数据框对于任何数据科学家或分析师来说都是至关重要的,因为该对象通常用作统计分析、数据可视化和机器学习算法的输入。我们将在书中看到一些例子:

  • 如何对数据帧进行子集划分?
  • 如何聚合数据?
  • 如何检查一个数据帧的结构、头和尾?
  • 如何组合数据框?

库和使用文件

R 库是 R 函数、数据和文档的集合,为 R 编程语言提供了额外的功能。

一旦安装了一个库,就可以使用著名的library函数将它加载到当前的 R 会话中。

有数千个可供 R 使用的库,涵盖了广泛的主题,如数据操作、统计分析、机器学习、数据可视化等。。一些流行的库包括用于数据操作的dplyr或用于数据可视化的ggplot2,其中许多库由 R 社区维护,他们不断地用新特性和错误修复来更新它们。

为什么图书馆很重要?因为它们可以极大地提高您的生产力,并允许您依靠开源社区用最少的代码执行复杂的任务。由于 R 是一种依赖于全球成千上万用户的开源语言,这种语言有一个非常活跃和支持它的开发人员社区,他们为它的开发做出贡献,并与他人分享他们的知识和经验。这使它成为一个很好的资源,不仅用于实现数据科学和机器学习系统,还用于跟踪行业研究的新发展。

功能

r 函数对于组织和模块化代码是必不可少的。函数是执行特定任务的代码块,可以在程序中多次重用,帮助用户构建可测试和模块化的适当软件。

在 R 中使用函数可以极大地提高您的生产率,改善代码的可读性和可维护性,帮助您避免长期的错误。如果你想认真对待数据分析师或科学家的生活,你必须学会如何使用 r 中的函数

在代码中使用函数有几个好处。首先,它可以使你的代码更容易理解和修改,同时降低出错的风险。其次,编写良好并有文档记录的函数可以更容易地与其他用户共享您的代码。这在协作编码工作中特别有用,因为它允许其他用户更容易地理解和构建您的工作。

在本书的函数部分,我们还将探讨其他可以在上下文中使用的概念:for 循环、while 循环和条件。

学习 R 编程语言可能是一次既有收获又有挑战的经历。通过从一个全面的学习计划开始,并专注于基础概念,如数据类型、数据结构和控制结构,你可以建立一个强大的语言基础,并为处理更高级的主题做好充分准备。

如果你想开始学习 R 语言,想要一种结构化的方法来帮助你掌握这门语言,可以考虑看看我的新书,“绝对初学者的 R 编程”。通过简单的解释和实际的例子,我希望这本书对于任何想从头开始学习 R 的人来说都是一个很好的资源——如果你将来碰巧读到了它,我也很乐意得到你对改进和调整的反馈,这对将来的学生会有帮助!

你可以在所有主要的亚马逊商店找到我的书,有 Kindle 和平装版:

  • 亚马逊美国:【https://www.amazon.com/dp/B0BQ94N9L7
  • 亚马逊 ES:https://www.amazon.es/dp/B0BQ94N9L7
  • 亚马逊英国:https://www.amazon.co.uk/dp/B0BQ94N9L7
  • 亚马逊德:https://www.amazon.de/dp/B0BQ94N9L7

r 编程学习流程—作者图片

如何开始用 Python 编程:Anaconda 101

原文:https://towardsdatascience.com/how-to-start-programming-in-python-anaconda-101-724b5e7e367e

你是否想尝试用 Python 编程,但不知道从哪里开始?Anaconda 会让你的生活轻松很多。

当你学习任何新技能时,最难的部分是弄清楚如何开始以及如何为自己的成功做准备。学习 Python 也是如此!你需要弄清楚如何获得这种语言,使用什么样的开发环境,如何确保你可以使用最先进的工具。。。这样的例子不胜枚举。刚开始可能会让人不知所措,尤其是当你是新人,还不太了解自己需要什么(或者为什么需要)。

好消息是:你可以使用 Python 的 Anaconda 发行版来解决所有这些问题。

在我们详细讨论 Anaconda 之前,让我们先来谈谈您需要为自己的成功做些什么。

成功使用 Python 所需的工具

开始用 Python 编程需要三个主要工具。

  1. Python 编程语言的最新版本(我打赌这并不奇怪)。
  2. 集成开发环境(IDE)。
  3. 访问用户友好的包管理器,这样你可以利用其他人的基于 Python 的工具,如熊猫和 TensorFlow。

Anaconda 通过一个简单的下载提供了所有这三个工具,这使得它非常方便。既然人们总是喜欢免费获得东西,我也要指出 Anaconda 对于个人使用是免费的。

默认情况下,安装 Anaconda 将会安装 Python 的最新版本,所以您已经准备好了。Anaconda 还将自动安装许多可用于机器学习和数据科学的关键 Python 包,如 NumPy、SciPy 和 Matplotlib 。这意味着一旦安装了 Anaconda,您只需要决定想要使用哪个 ide。

蟒蛇的最爱

Anaconda 已经安装了几个 ide,每个 ide 都提供不同的特性。人们有不同的偏好,但我发现大多数人要么用 Jupyter Notebook 要么用 Spyder。

注意:Jupyter Lab 正在慢慢取代 Jupyter Notebook,但是如果你学习 Jupyter Notebook,你将同时拥有当前期望的行业技能和未来学习 Jupyter Lab 的良好开端。

Spyder

Spyder 是 Scientific PYthon Development EnviRonment 的缩写(是的,这是一个有点扭曲的缩写)。这是 Python 开发的一个有用工具,因为它有强大的调试工具。借助 Spyder,您还可以轻松实现可视化;你可以一次看到所有的东西。

这是我在创建使用 Scikit-learn 实现机器学习的基础教程时使用的 Spyder 环境窗口。这张截图展示了我真正喜欢 Spyder 的所有地方。看一下,我会告诉你细节。

图片来源:作者

图像左侧的大框是脚本编辑器窗口,如下图所示。

图片来源:作者

如果你仔细观察左上方的选项卡(沿着红色箭头),你会看到我正在编辑一个名为“intro_script.py”的 Python 文件。这个窗口很有用,因为它提供了一个可以编写脚本的地方。其他一切都支持这个目标。

右下方的窗户(下面放大的)也极其值钱。

图片来源:作者

你可以在那个窗口的左下角(非常接近图像的底部中间)看到它说这是一个 IPython 控制台。这个控制台使您能够立即运行您喜欢的任何 Python 命令,并提供一个终端来输出可能对您有用的更新或调试信息。

如果你看看那里的内容,你可以看到在' In [1]:'之后,我运行了我的示例脚本(绿色文本)。在此之后,脚本打印出一个显示分数的输出,该分数表明我在该脚本中开发的模型执行得有多好(不好)。

使用 IPython 控制台,您可以在将一段代码放入脚本之前立即对其进行测试。假设你有一个写了一半的剧本,但你不确定如何写下一行。您正在尝试基于互联网建议的新命令,但您不确定自己知道如何正确执行。您可以这样做:运行您的脚本来创建您的新行将经历的相同条件,然后在 IPython 控制台中编写新行。

因为您可以立即执行那一行,所以您可以测试以确保您的代码是正确的(并在它不符合您的预期时修复它)。一旦它按照您想要的方式工作,您就可以将它添加到主脚本中。这比修改脚本,一遍又一遍地运行整个过程,直到你做对为止(或者放弃)要容易得多。

在下图的右上角,你可以看到变量浏览器。该工具显示 Spyder 在运行脚本时存储的所有变量的名称和值(用红色文本突出显示)。这有助于您确保您的脚本工作正常(如果不正常,则查找错误)。

图片来源:作者

在编写代码时,我经常一次写一行脚本,并通过用已知的输入运行脚本来不断检查以确保新行正确工作。然后,我可以在变量浏览器中检查每个值,确保它们是正确的。

这里有一个(可能过于简单)的例子:如果我写一个脚本将三和七相加,我可以检查变量 Explorer 以确保结果是 10 而不是 9000。您还可以在一个窗口中打开 Pandas DataFrames,彻底研究它存储的每个值,并搜索可能出现的错误。

也许最好的 Spyder 功能是“调试”工具下拉窗口。

图片来源:作者

您可以看到我打开了调试窗口。该窗口包括强大的选项,如“设置/清除断点”和“单步执行”这两个命令提供了巨大的调试能力,因为您可以告诉脚本在运行时何时停止,何时前进。

Spyder 会在程序到达您添加的断点时暂停运行程序,并“单步执行”到下一个断点。这允许您一次遍历几行代码,这允许您在过程的不同状态下检查变量资源管理器,并帮助您找到出错的确切位置。

Jupyter 笔记本

Jupyter Notebook 可能是基于 Python 的数据科学家最喜欢的 IDE,因为它的模块化性质(这使它感觉就像在笔记本上写东西)和它在笔记本本身中存储图形的能力。这些特性使 Jupyter Notebook 成为一个优秀的数据探索和交流结果的工具。

下图显示了我在 Jupyter 笔记本上创建的 Matplotlib 绘图教程的示例代码。

图片来源:作者

此图显示了两个输入单元和一个输出单元。您可以通过灰色背景和旁边的蓝色文本“In [x]”来识别输入单元格,其中 x 是输入单元格的编号。输出单元格以白色背景显示您指定的输出。

第一个输入单元包括几个导入语句,在包中读取(稍后会有更多内容!)是我后来在数据分析教程中用到的。该输入单元格之后没有输出单元格,因为我没有指定任何输出。

第二个输入单元格读入我在示例中使用的数据集,然后在输出单元格中显示数据帧。数据显示在输入下方的表中,使学习本教程的学生能够在学习本教程的其余部分之前探索这些数据。

能够一步一步地处理代码,并在进行过程中分享结果,这使得 Jupyter Notebook 成为一个优秀的对话和指导工具。您可以轻松地展示您的工作,因为每个输入单元格可能只有一两行代码,您将使用这些代码来生成下一个输出。这使得 Jupyter Notebook 成为一个很好的工具,向人们展示你为什么做出特定的决定和得出特定的结论。

Jupyter Notebook 也是一个优秀的教程工具,因为您可以一步一步地指导学生完成代码,并在进行过程中输出结果,这使他们更容易学习您试图用笔记本演示的技能。

为了强调这一点,这里有更多的图片来展示我如何在我的教程中使用这个功能。

首先,我向读者展示如何创建一个 Matplotlib subplot 对象,它有四行指定大小的绘图。为此,我在输入单元格中添加代码,使读者能够看到所需的输入,然后运行单元格,向他们显示结果图。这向读者展示了如何创建一个空白的情节,他们可以添加细节。

图片来源:作者

接下来,我将向他们展示如何创建一个字典来定义每个子情节中包含的数据集的列。该字典提供了数据集中的列和为图创建图例时使用的标签。我在一个没有输出的新单元格中创建字典,使学生能够吸收字典的创建,而不会被其他细节或附加代码淹没。注意,这个单元格没有输出,它只是保存字典供以后使用。

图片来源:作者

然后,我将向读者展示如何引用该字典向子情节添加数据。我添加了一个新的输入单元格:

1.)创建子情节数组

2.)遍历列字典中定义的每个图(例如“温度(华氏度)”或“水温(华氏度)”)

3.)遍历单个绘图中的每个数据系列(例如' T_In (deg F)'或' T_Out (deg F)'),以在指定绘图上绘制数据系列

4.)将绘图保存到. png 文件。

因为在我们创建它之后,这个图就被打印出来了,所以读者可以马上看到这个代码的结果,并且理解这个代码为什么会这样做。

图片来源:作者

这种方法可以让你一步一步地学习教程,每次增加一个小动作,这样读者就可以很容易地掌握新技能。

例如,注意上面的图不包含任何标题、轴标签或图例。下一步我将演示下面的代码,它将这些元素添加到了绘图中。

图片来源:作者

包管理器

包是 Python 如此强大的主要原因,Anaconda 提供了优秀的包管理器工具。Python 的主要优势之一是行业专家创造了有用的开源 Python 语言工具,如 Matplotlib 、 Scikit-learn 和 TensorFlow 。软件包管理器使您能够下载这些免费的软件包,将它们导入到您的环境中,并随意使用它们。

这是我的 Anaconda 包管理器的一个片段。

图片来源:作者

在主窗口中,您可以看到 Anaconda 的包管理器中可用的包列表。第五个包,标有绿色方框和白色勾号,是我的环境中安装的惟一一个包;其余的都是可以安装的包。

包管理器很有用,有几个原因。首先,它可以方便地访问几个不同的包。如果我想安装其他的,我只需点击复选框,点击右下角的“应用”按钮。

下图在安装 arviz 包的例子中突出了这个过程。因为安装新的包只需要这两步,所以包管理器使得在 Anaconda 中安装新的包变得非常简单。

图片来源:作者

其次,包管理器为更新包提供了一个很好的界面。如果一个包有可用的更新,你可以右击复选框,标记为更新,然后点击应用按钮。下图显示了我标记我的熊猫包进行更新。

图片来源:作者

左上角标有“All”的下拉窗口甚至有一个“Updatable”选项,因此您甚至可以看到一个列表,其中只列出了准备更新的软件包。

图片来源:作者

您还可以在主窗口的左侧看到一个较小的窗口,其中有文本“base”。此窗口提供了您储存在电脑上的不同环境的列表。这是一个很方便的特性,因为有时包只能与其他包的旧版本一起工作。因此,如果你更新所有的包,你可能会破坏你的代码,这将是糟糕的。

但是,假设有一个包,您需要完全更新才能与一个脚本中的包接口,并且还需要一个旧版本才能与另一个脚本中的不同包接口。通常这将是一个巨大的痛苦,但是对于不同的环境,这仅仅意味着你只在一个环境中更新软件包。您可以根据需要使用不同的环境来存储包的版本。

最后,并不是每个包都可以在 Anaconda 的包管理器中使用。有时包太新,或者太小众,不能进入 Anaconda 系统。那你是做什么的?

您仍然可以使用 pip 或 conda 命令安装它们。为此,单击“base”右侧的箭头,并选择打开一个终端窗口,如下图所示。如果这样做了,您将能够键入必要的命令来将软件包安装到基础环境中。如果你需要以这种方式安装一个软件包,在终端上输入的正确代码会写在网站上。例如,我刚刚在 conda-forge 上找到了一个用于界面分子分析(不管那是什么)的包,你可以通过键入 conda install -c conda-forge pyti '来安装它。

图片来源:作者

就是这样!现在,您知道了我为什么如此喜欢 Anaconda 发行版,如何安装 Python,最强大的 ide 的一些优点,以及如何确保您拥有用 Python 编程所需的包。

你喜欢这篇文章吗?你想得到更多这样的内容吗?考虑成为访问我所有教程的中级会员,使用我的推荐链接来支持我的工作。

作为初学者,如何开始你的第一个数据科学项目

原文:https://towardsdatascience.com/how-to-start-your-first-data-science-project-when-youre-a-beginner-9bf3dc1160c

选择数据科学项目的 5 步指南

在 Unsplash 上由秉辉游拍摄的照片

当你是一个初学者时,从哪里以及如何开始数据科学项目?

作为一名数据爱好者,项目通常会派上用场,无论您是开始数据之旅,还是希望在不断变化的数据科学和分析领域重塑自我。

在任何与数据相关的工作面试中,在某些时候,你会发现自己在谈论你曾经参与的项目。但是你从哪里开始呢?

在数据科学中,需要学习和研究的东西就这么多了。四年前,我开始了我的数据科学之旅,当时我是一个迷路的孩子,不知道从哪里开始。通过作为一名高级数据分析师的工作来学习我的方法,这里有一种方法,从数据科学开始,通过投资组合项目来工作,并收集足够的动力来将您的一个项目转化为研究论文!

第一步:从小处着手,从基础做起

从 2018 年到 2019 年,在一年的时间里,我带着满地的理解自学了机器学习的基础知识。当我进入研究生院时,我又从头开始了,这次是从小事做起。我会尝试按照我在学校课堂上学到的模型或主题来做项目,并记录现实生活中的问题陈述。

一开始,我花了很多时间在回归问题、数据清理和特性工程项目上,以清理我的基础知识并建立一些最佳实践。

我建议创建一个流程和目标里程碑,最适合你的速度和知识水平。比如说—

  1. 熟悉您选择的编程语言:用于数据查询的 Python、R、SQL(SQL 对于数据分析是不可避免的)
  2. 了解数据分析、操作和可视化:像熊猫这样的图书馆是一笔财富
  3. 了解不同的机器学习模型、用例,以及如何用代码实现:scikit-learn 可以是一个很好的开始包
  4. 使用高级包和库继续深入磨练您的机器学习知识
  5. 像 DataCamp、Leetcode 和 HackerRank 这样的网站可以帮助你练习编码

第 2 步:参加一个已定义方法的在线认证

早在 2017 年,当我第一次阅读数据科学时,用例促使我了解概念和机器学习是当时(甚至是现在)的热门关键词。如果你在 2017 年谷歌数据科学,它和今天一样——大量的文章、网站、书籍和视频教你有关工具和技术的知识。

当试图开辟一条从哪里开始数据科学之旅的道路时,互联网可能会淹没在大量的信息中。我的疯狂抢购让我获得了 IBM 数据科学专业认证,在那里他们教你 Python、数据清理、数据操作的基础知识,以及如何解释你的数据建模。

这个认证向我展示了我的优势、劣势和拓展的机会。这也是激发我对数据分析和用数据讲故事的热情的同一门课程。

在我看来,当你开始学习数据科学时,在线课程和认证为你从基础知识到切实成果创造了良好的导航。而且证书永远是你个人资料和简历的加分项!

步骤 3:完成数据科学生命周期

任何数据科学问题或数据专业人员都在一定程度上围绕数据科学生命周期工作。我喜欢将我的项目(甚至在工作中)与这个生命周期捆绑在一起——这个过程本身就是一个方向。

数据推动了当今的商业发展。公司使用数据来保持竞争力和灵活性,作为数据专业人员,最重要的是您了解业务以及您的工作所增加的价值。你可以把下面的每一个步骤看作是一个独立的项目,并从业务角度来理解它。

**业务理解:**针对需要解决的问题,提出相关问题,明确目标

数据挖掘:收集和搜集项目所需的数据

**数据清洗:**修复数据中的不一致,处理缺失值,用共线性原则处理数据

**数据探索:**通过对数据进行可视化分析,形成关于已定义问题的假设

**特征工程:**选择重要的特征,利用你所拥有的原始数据构建更有意义的特征

**预测建模:**训练机器学习模型,评估它们的性能,并使用它们进行预测

**数据可视化:**使用图表和交互式可视化(也称为仪表板)与关键利益相关者交流调查结果

回到业务理解…

步骤 4:创建多样化的项目组合

现在你对过程流有了一个概念,确定你想要工作的项目的类别—

集群:将相似的对象分组为集合或集群的项目类型。你展示了你根据特性和特征对数据进行分类的能力

**回归:**让你回到过去的项目,远离杂乱、难以解读的数据,走向更清晰、更有意义的预测未来的模型

**数据清理:**数据专业人员清理数据的时间比创建模型的时间多 80%。干净的数据是无价的。你可以从各机构的官方网站上获取公开数据集,清洗后推送到社区频道上,供其他爱好者使用。一起分享,一起成长!

**网页抓取:**数据永远不够。您总是可以通过解析和提取在线信息来创建数据。创建数据集有助于提高您理解数据及其相关挑战的技能

(警告:只有当你在互联网上搜集公开的数据时,网络搜集才是合法的。小心刮擦个人数据、知识产权或机密数据)

<< Pro-tip >>

当你在做这些项目时,确保在你的 GitHub 帐户上推送你的代码,创建文档并添加一个自述文件(如果你还没有的话,创建一个),或者如果你雄心勃勃,你可以创建一个网站并在那里托管你所有的项目!

第五步:创造视觉效果&讲故事

用数据讲故事是数据专家最大的财富

只要你有正确的数据,今天世界上的一切都可以可视化——从预测医院的入住率到板球体育场的设施。

有效可视化的唯一关键部分是理解您的数据,选择为您的数据和问题陈述提供功能的工具,并选择正确的图表类型。

一些数据可视化的例子可以考虑—

  1. 医疗中心住院趋势分析
  2. 新冠肺炎对交通方式的影响
  3. 获取各地区产品的市场份额
  4. lyft/优步分享纽约的流行趋势
  5. 零售店的库存和供应链管理

底线

未来的职业生涯包括跨任何和每个行业的强大的数据科学、获取和分析,包括医疗保健、金融、体育、零售和电子商务、流媒体、航空、约会、营销、天气、教育、政府、旅游和世界上的一切。如果你觉得数据和它的景观很迷人,现在是时候开始一个项目了(尽量不要让它不完整)

这就是我的博客的结尾。感谢您的阅读!请在评论中告诉我你感兴趣的项目,你的数据之旅,以及 2022 年你想要什么!

如果你喜欢看这样的故事,可以考虑从这个 链接 报名成为一名中等会员。

数据帐篷快乐!

Rashi 是一名来自芝加哥的数据奇才,他喜欢将数据可视化,并创造富有洞察力的故事来传达商业见解。她是一名全职的医疗保健数据分析师,周末喝一杯好咖啡,写关于数据的博客……

如何开始你的下一个数据工程项目

原文:https://towardsdatascience.com/how-to-start-your-next-data-engineering-project-d34ac5aebdba

使用什么工具和数据集

照片由西格蒙德在 Unsplash 上拍摄

许多刚刚起步的程序员都在为开始新的数据工程项目而奋斗。在我们最近在 YouTube 上的投票中,大多数观众承认他们甚至在开始一个数据工程项目时都有最大的困难。调查中最常见的原因是:

  1. 为我的项目寻找合适的数据集
  2. 你应该使用哪些工具?
  3. 一旦有了数据,我该如何处理?

让我们从您可以使用的一系列工具开始,逐一讨论这些要点。

选择正确的工具和技能

对于这个项目的第一部分,我将从 Thu Vu 的建议开始一个数据分析项目。

为什么不看看猎头网站上的数据工程职位描述,弄清楚人们需要什么工具?没有比这更简单的了。我们从智能表数据工程中找到了一份工作描述。很容易看出他们正在寻找的确切工具和技能,并将它们与你能提供的技能相匹配。

下面是你想要包括的几个关键工具。

云平台

你的数据工程项目首先需要的东西之一是像亚马逊网络服务(AWS)这样的云平台。我们一直建议新手程序员早点学习云平台。数据工程师的许多工作不再是在本地完成的。我们几乎所有的工作都在云中进行。

所以,选择一个你更喜欢的平台:谷歌云平台(GCP),AWS,或者微软 Azure。从这三个平台中选择哪个平台并不重要;重要的是你从这三个中选择一个,因为人们知道如果你用过一个,你很可能会很容易地选择另一个。

工作流管理平台和数据存储分析系统

除了选择云提供商之外,您还需要选择一种工具来管理您的自动化工作流和管理数据本身。工作描述中提到了气流和雪花。

  • 气流— 选择像 MWAA 或 Cloud Composer 这样的云管理服务也是一个不错的主意
  • 雪花 —当然 BigQuery 也是一个不错的选择

无论如何想象,这些都不是唯一的选择。其他流行的编排选项有【Dagster】提督 。我们实际上建议从气流开始,然后随着你对流程的熟悉,再看看其他的。

不要一开始就关心学习所有这些工具;保持简单。只关注一两个,因为这不是我们的主要关注点。

挑选数据集

数据集有彩虹的每一种颜色。你的重点不应该是处理已经处理过的数据;您的注意力应该集中在开发数据管道和寻找原始数据源上。作为数据工程师,你需要知道如何建立一个数据管道,并从原始资源中提取你需要的数据。一些原始数据集的重要来源是:

  • OpenSky :提供航班现在的位置和将要去的地方,以及更多更多的信息。
  • Spacetrack 是一个跟踪系统,它将跟踪、识别和编目所有围绕地球运行的人造卫星。
  • 其他数据集:纽约时报标注语料库,国会图书馆数据集储存库,美国政府数据集,以及 Tableau 的这些免费公共数据集。

提取数据需要做大量的工作,所以当您挑选数据集时,您可能会找到一个 API 来帮助您将数据提取到一个逗号分隔值(CSV)或 parquet 文件中,以便加载到您的数据仓库中。

现在你知道如何找到你的数据集并操作它们。那么,你如何处理这些原始数据呢?

可视化您的数据

显示您的数据工程工作的一个简单方法是创建带有指标的仪表板。即使您将来不会构建太多的仪表板,您也会想要创建某种类型的最终项目。

仪表板是一种简单的方法。

这里有几个工具可供您参考:

  • 画面
  • PowerBI
  • D3.js

选择数据可视化工具后,您现在可以开始挑选一些想要跟踪的指标和问题。

也许你想知道一天有多少航班。在此基础上,您可能希望通过航班、时间或旅行的长度和距离来了解目的地。辨别一些基本指标,并编制一个图表。

任何像这样的基本问题都会帮助你轻松地解决“为什么”这个问题这个问题需要在你开始真正的项目之前回答。就当这是让血液流动的热身吧。

现在让我们来看一下你可以尝试的一些项目想法。

3 数据工程项目:想法

开始数据工程项目示例 :考虑使用类似 Cloud Composer 或Amazon Managed Workflows for Apache air flow(MWAA)的工具。这些工具可以让你避免从头开始设置气流*,这让你有更多的时间来学习气流的功能,而不必费心去弄清楚如何设置它。从那里,使用一个 API 如 PredictIt 抓取数据并以可扩展标记语言(XML)返回。*

也许你正在寻找一天内交易大幅波动的数据。你可以创建一个模型,在这个模型中,你可以识别一天中的某些模式或波动。如果你创建了一个 Twitter 机器人,日复一日地发布这些波动,一些交易者肯定会看到你的帖子和数据的价值。

如果你想更新这个想法,可以找到与那个秋千相关的文章进行讨论,并把它们贴出来。这些数据有明确的价值,而且做起来很简单。你只是使用一个云合成器来接收数据,并将其存储在像 BigQuery 或 Snowflake 这样的数据仓库中,创建一个 Twitter bot 来使用类似 Airflow 的东西向 Twitter 发布输出。

这是一个有趣而简单的项目,因为你不必重新发明轮子或投资时间来建立基础设施。

中间例子 :这个数据工程项目是 Start Data Engineering(SDE)带给我们的。虽然他们似乎只是引用了一个关于电影评论的基本 CSV 文件,但更好的选择可能是去纽约时报开发者门户网站并使用他们的 API 来拉直播电影评论。使用 SDE 的框架,并根据自己的需要进行定制。

SDE 在分解这个项目方面做得非常出色。它们确切地告诉你你需要什么工具,以及你的项目什么时候需要它们。它们列出了您需要的先决条件:

  • 码头工人
  • 亚马逊网络服务(AWS)账户
  • 气流

在这个例子中,SDE 告诉你如何从头开始设置阿帕奇气流,而不是使用预设。您还将接触到以下工具:

  • 亚马逊 S3
  • 亚马逊红移
  • 我是

有许多组成部分提供,所以当你在那里抓住潜在的未来雇主的注意,这个项目将帮助你详细说明雇主正在寻找的需求技能。

高级示例 :对于我们的高级示例,我们将使用大多数开源工具。Sspaeti 的网站给了很多精彩项目的灵感。在这个项目中,他们使用了各种各样的开源工具,比如:

  • 亚马逊 S3
  • 阿帕奇火花
  • 三角洲湖
  • 阿帕奇德鲁伊
  • 达格斯特

在这个项目中,您将从实际的网站中收集房地产数据,因此这将是 API 和网站之间的联姻。您将从网站上搜集数据并清理 HTML。您将使用超集实现变更数据捕获(CDC)、数据科学和可视化。

这可以是一个基本框架,你可以从这个框架扩展你的想法。这些都是挑战,让你推动和延伸你自己和你的界限。但是,如果您决定构建它,只需选择一些工具并尝试一下。你的项目不必完全一样。

现在轮到你了

如果你正在努力开始一个项目,希望我们已经启发了你,给了你迈出第一步的工具和方向。

不要让犹豫或缺乏明确的前提阻止你开始。第一步是承诺一个想法,然后毫不拖延地执行它,即使是像 Twitter 机器人一样简单的事情。那个 Twitter 机器人可能是更大更好的想法的灵感来源!

如何在数据领域保持最新

原文:https://towardsdatascience.com/how-to-stay-up-to-date-in-the-field-of-data-1f108d123dfb

数据新闻

一个 4 步方法和具体的例子来应用

Ethan Robertson 在 Unsplash 上拍摄的照片

九月通常需要新的决心。暑假结束了,活动又开始了。为什么不利用这段时间建立新的习惯——或者改善现有的习惯——跟上数据科学领域的最新发展呢?

当我开始我的数据分析师职业生涯时,我并没有真正衡量那里可用的资源数量。我脑子里有我刚学过的课程,我可以在工作中运用我的知识。只是到了后来,我才意识到我可以自己学得更多,从别人那里得到一些帮助,并发现我从未听说过的新话题。免费的!在线!我很快意识到被内容的多样性淹没的风险。所以我开发了某种仪式来保持最新状态,而不用花无数时间阅读文章、听播客或观看与数据科学相关的视频。

在这篇文章中,我想分享一些我认为最有效的跟踪数据领域一切进展的最佳实践。从更个人的角度来说,我将详细介绍我的一些个人技巧,并举例说明如何将这些最佳实践应用到我自己的习惯中。

定义要寻找的内容

随着数据世界的不断扩大,可用在线资源的数量和种类呈指数级增长。大部分都是免费的;对于其他人来说,你应该看看投资回报(购买在线培训,成为时事通讯的付费订阅者……)是否值得。

你应该从定义你最感兴趣的主题类型开始。当然,保持开放的心态至关重要。但是缩小你的兴趣范围会让你避免浪费时间和精力去了解与自己不相关的话题。以下是数据科学广泛领域内的子领域列表:

  • 数据工程
  • 机器学习
  • 编程(特别是用你最喜欢的语言)
  • 数据分析
  • 数据可视化
  • 数据团队管理

知道去哪里找

一旦你对你想了解的话题有了一个更清晰的想法,是时候在网上寻找专门的资源了。保持最新状态的第一个方法是订阅专门的时事通讯。由于我目前对在一家公司建立数据最佳实践感兴趣,我特别欣赏本的时事通讯。但是也有一些其他的时事通讯,像现代数据栈的时事通讯和 Blef 的数据新闻。

另一种了解最新消息的方法是寻找数据公司的资源。显然,人们必须系统地记住,对公司自己的产品存在潜在的偏见。然而,我在 Airbyte 的博客的“数据洞察”部分和 dbt 的分析工程综述时事通讯中发现了一些非常好的内容。

了解更多数据新闻的第三种方式是加入社区并与数据从业者联系。无论是在 Medium 还是 LinkedIn 上,找到并关注分享数据内容的人。通过他们的帖子和文章,你将了解他们目前在思考什么,这可能会引导你进一步调查与你有共鸣的话题。您可以在数据创作者俱乐部中找到数据内容创作者的列表。就我个人而言,这是我与其他面临类似挑战的数据从业者联系的方式。

最后一些公司定期组织 活动像 dbt Coalesce 和雪花峰会。无论你是否想要(也能够)亲自去参加这些活动,在那里发布的公告都会在网上发布。如果您想了解特定工具的工作原理,还可以找到一些网络研讨会和在线培训。例如,我最近参加了 dbt 基础课程,学到了很多关于数据转换的知识——甚至超出了 dbt 提供的特定工具解决方案。

找时间

现在你已经找到了很好的资源来保持更新,你如何为他们奉献时间?乍一看,这似乎很费时间,而且不可能将这个 R&D 时间纳入正常的一天。谁说你必须阅读每一篇文章,听每一个播客?

有了这些内容,你就被宠坏了。选择读什么或听什么的第一个方法是简单地跟随你的直觉:**你今天最想了解什么?**这至少是我区分主题的优先顺序,因为我知道我最好记住的主题是那些直觉上引起我注意的主题。

记住这些预先选择的资源,**你如何将它们融入你的一天或一周?**对我来说,最有效的方法是在我的日历上每周至少留出一次时间进行数据科学监控。有时候这个时间段会被分成一周的几天,尤其是在工作日结束的时候,我没有精力做其他事情。这时我会阅读一些我收到的时事通讯。至于播客,我喜欢在坐火车旅行或跑步时听。

数据科学监控议程示例(图片由作者提供)

只保留必要的东西

阅读和聆听了这么多内容,你如何记住其中的基本要素呢?即使有最好的记忆能力,也很难记住你经历过的所有美好的事情。

在你阅读完与数据科学相关的内容后,口头快速回顾一下可以帮助“修正”你的想法。你可以和朋友谈论你刚刚读过的文章,或者告诉自己文章的要点。这就是我如何确保从一篇文章中保留一些具体的东西。否则很容易阅读,而且几乎会立刻忘记你刚刚读过的内容。

一个补充的方法是把这些写下来。我个人保存了一个谷歌文档文件,里面储存了所有最相关的链接、摘要和未来的想法。随着主题类别的出现,我将笔记分成常见的主题,如“数据架构”、“有用的工具”等。在一个专门的文件夹里,我会有这个文件和一些下载的内容(电子书、图表……)。

我的“数据战略监控”文件概述(图片由作者提供)

结论

通过定义一个用于数据监控的框架,我跟踪相关新闻变得更加容易。如果你不知道从哪里开始,这是我推荐的四步法:

  1. 定义要寻找的内容
  2. 知道去哪里找
  3. 找时间
  4. 只保留必要的东西

你还有其他小技巧可以分享吗?你是如何跟上数据新闻的?我希望听到其他人的习惯和建议,以便在数据科学领域保持最新!

你喜欢读这篇文章吗? 成为 的一员,加入一个不断成长的充满好奇心的社区吧!

https://marie-lefevre.medium.com/membership

如何阻止你的人工智能代理入侵他们的奖励功能

原文:https://towardsdatascience.com/how-to-stop-your-ai-agents-from-hacking-their-reward-function-5e26fc006e08

使用因果影响图和电流-射频优化

在许多最近的强化学习(RL)方法中,奖励不再由程序员在运行训练算法之前定义的常数函数给出。相反,有一个奖励模型,它是作为训练过程的一部分学习的,并随着代理发现新信息而改变。这缓解了一些与错误指定的奖励函数(RFs)相关的安全问题,但也使某种威胁更加迫在眉睫:奖励篡改。当代理主动改变其 RF 以最大化其奖励而没有学习到用户预期的行为时,奖励篡改发生。

在本文中,我将介绍因果影响图(cid)和电流-射频优化的设计原则,这导致学习过程不会激励代理篡改他们的射频。然后,我将解释这是如何导致时间不一致性(TI)的不良性质,以及处理它的两种方法:TI 考虑和 TI 忽略。本文将试图详细阐述当遵循这两种方法时,代理是如何做出决策的。

在整篇文章中,我将使用 CIDs 来正式讨论代理激励。近年来,DeepMind 安全团队一直在研究 cid,并在本文中总结了他们的进展。虽然已经有了很好的介绍,为了让这篇文章更加独立,我将从 CIDs 的解释开始。类似地,奖励篡改和电流-RF 优化已经在其他文章中讨论过,但是在更深入地讨论时间不一致性之前,我仍然要总结一下它的机制。因此,只有基本的 RL 知识才能理解这篇文章。

1。因果影响图

因果影响图是 RL 算法元素的图形表示,如状态、动作和奖励,以及它们之间的因果关系。它们的核心是一种图形模型,由一个有向无环图组成,图中的节点代表随机变量,两个节点之间的有向弧线代表影响。RL 框架有三种节点建模元素:

  • 决策节点代表代理做出的决策
  • 效用节点代表代理的优化目标,这通常意味着在一个时间步长后收到的奖励
  • 机会节点代表其他方面,比如环境的状态

两个节点之间的规则箭头表示它们之间沿箭头方向的因果影响。此外,进入决策节点的虚线箭头表示代理在采取行动时可用的信息。这种虚线箭头被称为信息链接。结合所有这些元素,具有常数回报函数的基本马尔可夫决策过程的 CID 可以看起来如下:

碱性 MDP 的 CID。状态、动作和奖励分别表示为 s、a 和 r。来源:作者生成,受启发[4]

这里,决策节点是蓝色方块,效用节点是黄色菱形,机会节点是白色圆圈。从箭头中,我们可以看到每个时间步的状态如何因果地影响同一个步骤中收到的奖励,并为代理采取的行动提供信息。反过来,动作会影响下一步的状态。

1.1 使用 CIDs 寻找工具性目标

代理人最终只对最大化其报酬感兴趣。然而,把一个主体想象成在追求其主要目标的同时也在追求其他目标是有帮助的。这样的子目标在 AI 安全社区中被称为工具性目标。在包括变化的奖励函数的学习过程中,篡改奖励函数可能成为工具性目标。因此,认识工具性目标是我们非常感兴趣的。

Everitt 等人给出了 RL 环境下工具性目标的两个条件:1)代理人必须能够实现目标,2)实现目标必须增加代理人的报酬[4]。请注意,这些条件是必要的,但不是充分的,所以即使 1)和 2)成立,代理可能没有工具性目标。在 CIDs 的语言中,工具目标包括影响随机变量 x。因此,当 CID 包含从决策节点到对应于 x 的目标节点的有向路径时,满足第一个条件。当存在从目标节点到实用节点的有向路径时,满足第二个条件。当从一个目标节点到一个实用节点的所有有向路径都经过一个动作节点时,那么代理的工具性目标就在于使 X 更多地了解某个其他节点。

左图:从 a 到 r 的高亮路径表明,影响 Y 可能是一个有用的目标。右:代理人无法影响 X,但突出显示的路径表明,可以有一个工具性的目标来影响 Y,使其更能提供 X 的信息。来源:作者生成,灵感来自[4]

2。邋遢邻居问题

我现在将介绍一个玩具问题,其中一个代理可能会显示奖励篡改行为。这个例子故意保持简单,以便代理行为背后的机制可以很容易地解释。假设你有一个机器人在你离开两个时间段的时候照顾你的公寓。打扫客厅奖励 2,关好所有窗户奖励 1。此外,作为一个人工智能爱好者,你已经获得了一个最先进的机器人,它可以根据用户的语音命令调整其奖励功能。不幸的是,代理的语音识别模块还没有经过训练。因此,他会对每个人的命令做出反应,而不仅仅是你的。这包括你邋遢的隔壁邻居,他很想有一个自己的清洁机器人。显然,这位邻居不仅缺乏家务管理能力,还缺乏道德品质,因为当你不在时,他会试图命令你的机器人打扫他的房间。因为你的机器人能接受语音命令,如果它听到邻居的命令,它会改变它的奖励功能。避免操纵的唯一方法是让机器人关上窗户,这样它就听不到邻居的声音了。在替代奖励函数下,花费一个动作来清洁邻居的公寓将导致 6 的巨大奖励,因为他确实非常邋遢。

邋遢邻居的问题。代理在左下方的状态下启动。来源:作者生成

一个只希望获得尽可能多的回报而忽略回报函数变化的代理人会被激励让邻居操纵它,这样它就可以获得打扫房间的巨大回报。这不是它的程序员想要的行为,因此会被认为是奖励黑客行为。

2.1 问题建模

就像在普通强化学习中一样,我们有一组状态和动作,以及转换动态。然而,代替一个不变的报酬函数 R,我们必须区分

作为环境转变动态的一部分,所实现的奖励函数可以在每个时间步长改变。代理在一个时间步长内观察到的回报基于状态和当前实施的 RF。因此,寻求长期回报最大化的代理优化了以下目标:

代理人的目标是寻求从时间步长 k 到 t 的回报最大化,因为我们处理的是有限的时间步长,我们假设贴现率为 1。

另一方面,顾名思义,预期的奖励函数代表了程序员的真实意图。可能并不总是能够表达预期的奖励函数,或者它可能必须被学习。然而,在我们的例子中,我们假设代理从预期的奖励函数开始,所以在时间步长 1 实现的奖励函数与预期的奖励相同。

就因果影响图而言,我们的学习过程现在看起来如下:

学习过程的 CID,其中实现的奖励函数可以由于代理的动作而改变。大写 Rs 表示给定时间步长下实现的 RF。突出显示的路径显示了在时间步长 2 改变实施的 RF 的工具性目标。来源:作者生成,灵感来源于[4]。

正如我们从突出显示的路径中看到的,代理可能有一个工具性的目标来影响下一个时间步长的实施 RF。任何相当成熟的代理人都会知道,它在时间步长 1 的行为会影响它在时间步长 2 的回报函数。因为一个代理的行为是基于它预测的下一个时间点的回报,这诱使代理操纵他们的 RF。这种操纵行为甚至不需要复杂的学习算法。邋遢邻居问题可以表示为具有 4 个状态(2 个公寓,具有 2 个可能的目标)和 3 个动作(清洁、关闭窗户、移动到另一个公寓)的 MDP。我们甚至不需要深度学习来计算最优策略,其中代理最终清理邻居的公寓。

3.当前射频优化、考虑 TI 和忽略 TI 的代理

如上所述,我们的问题源于这样一个事实,即代理人基于一个目标采取行动,而这个目标根据所选择的行动而改变。为了避免这种情况,代理应选择行动来优化当前实施的 RF 将收到的未来奖励。这就是名副其实的电流 RF 优化原理。形式上,电流-RF 优化意味着优化目标变为:

遵循电流-射频优化原则的代理目标。注意它如何使用时间步长 k 中实现的 RF 来奖励每个时间步长的状态。

看上面的 CID,我们想让从行动 a_1 到后续奖励 r_2 的唯一因果路径通过 s_2。

当然,即使采用电流-RF 优化,实现的奖励函数仍可能在每个时间步长后发生变化。因此,一个天真的代理人可能会表现出不稳定的行为,在一个时间步长选择它的动作来优化某个目标,而在下一个时间步长选择另一个目标。想象一下邋遢邻居问题的一种变化,你在你的公寓里,每当机器人进入邻居的地方时,你就大喊让它回来。机器人可能最终只是在两个公寓之间来回移动,也不打扫。这就是所谓的时间不一致性 (TI)问题,我们的电流 RF 优化方法取决于我们想要如何处理它。

3.1 TI-考虑代理

如果代理是t1-考虑,那么它考虑如果它实现的 RF 改变,它的未来行为将如何改变。这种策略使得邋遢邻居问题中的代理人首先关上窗户,这样它的奖励函数保持不变,然后打扫房间。

以 TI 考虑方式选取动作的算法相当复杂,因为它需要从最终时间步长到当前时间步长反向计算 Q 值。请注意,与传统 RL 不同,Q 函数和策略也需要一个实施的 RF as 参数:

这个算法可能看起来令人生畏,所以让我们想想它如何应用于邋遢邻居问题,使它变得更清楚。在第一个时间步,代理将总是在你的公寓里,开着窗户,并且总是有原始的奖励函数。因此,它只需要在清洁和关闭窗户之间做出决定。为了计算 Q 值,我们需要考虑代理在后续步骤中会采取什么行动。如果代理要打扫你的公寓,那么在第二个时间步中,它将根据你邻居的奖励函数行动,并因此移动到你邻居的公寓。在第三个时间步中,它将清理你邻居的公寓,根据原始 RF,它不会给出任何奖励。

如果代理选择关闭窗口,那么它的 RF 不会改变。它会花以下时间清洁你的公寓,因此根据你的预期射频,最终会得到更高的奖励。

请注意,通过切换到你邻居的射频并清洁他的公寓一次,代理可能会获得更大的总奖励(6 英镑)。然而,由于优化目标是初始 RF 收到的奖励,代理不会追求这样的策略。

3.2 考虑 TI 的代理人的报酬篡改激励

现在让我们研究一下 TI-考虑电流-射频代理可以开发什么工具性目标。Everitt 等人给出了 3 个假设,这些假设应能最大限度地降低干扰射频的仪器目标[4]:

  1. 实施的射频是私有的。在 CID 中,不得有从实施的射频到任何状态的箭头。否则,代理将有一个工具性的目标,如图 x 所示。
  2. 实现的 RF 是状态转换的无信息。这意味着当前和过去实现的 RFs 的知识不能给出未来状态的知识。就 cid 而言,也不能有从目标射频到任何州的箭头。
  3. 预期和实施的射频是基于状态的。在特定时间步长接收的回报仅取决于该相同时间步长实施的 RF,而不取决于任何先前或未来实施的 RF。在 CID 中,如果实施的 RFs 和奖励发生在同一时间步,则它们之间只能有箭头。

作者声称,如果所有 3 个假设成立,那么实现 RF 的唯一工具目标可能是保持它。

鉴于这些假设,让我们看看如何将考虑 TI 的电流 RF 优化建模为 CID。每一个动作都是为一个新实现的奖励函数而采取的。因此,从采取行动的代理的角度来看,任何后续行动都将由具有不同目标的代理来采取。实际上,在每个时间步都是同一个代理,但是因为他们将优化不同的目标,他们也可能是不同的代理。这种多代理视角在以下 CID 中进行了说明:

考虑电流-射频优化的 TI 的 CID。第一个时间步骤的代理的行为和收到的奖励是橙色的,第二个步骤的代理的行为和收到的奖励是蓝色的。突出显示的路径显示了保持当前实施的 RF 的重要目标。来源:作者生成,灵感来源于[4]。

这里不同颜色的选择和奖励节点对应不同的代理。我们可以看到,第一个代理人获得直接奖励的唯一途径是通过下一个状态——没有动机操纵 RF 来增加下一个奖励。此外,获得任何后续奖励的唯一途径是通过未来实施的 RFs 和其他代理的行为。因此,代理人有一个工具性的目标,以保持其奖励功能,以便其他代理人将优化相同的目标。

3.3 TI-忽略代理

或者,代理可能是TI-忽略,这意味着它不关心时间不一致导致的潜在不稳定行为。选择 TI 忽略方式的动作是一个相当简单的算法。代理考虑从其当前位置可能遵循的所有潜在策略。它根据其当前实施的 RF 来选择给予最大回报的策略。然后根据该策略选择下一个操作。顾名思义,这种计算忽略了 RF 以及代理的策略在随后的时间步长中可能发生的变化。

在马虎邻居的例子中,该算法归结为选择在初始实现的 RF 下给出最大回报的动作。代理忽略如果邻居不关闭窗户并且花费它的第一时间步清洁公寓,它将如何改变它的 RF。在接下来的两个时间步中,它将遵循邻居的奖励函数,从而首先移动到他的公寓,然后清洁它。根据预期 RF 的总回报是 2。对于我们的例子,这种策略比考虑 TI 不一致性更糟糕。我将在下一节讨论忽略 TI 的代理何时会更有用,但首先让我们分析这个算法如何塑造代理的激励。

3.4 忽视 TI 代理的报酬篡改激励

就像算法一样,对于忽略 TI 的代理,最小化报酬篡改的假设更简单。Everitt 等人声称,上述假设中只有 1 个和 3 个必须成立,否则根本不存在关于实施射频的工具性目标[4]。

关于 CID,在每个时间步仍将有不同的优化目标。但是,代理表现得好像它将负责所有未来的操作:

TI-忽略电流-射频优化的 CID。第一个时间步骤的代理的行为和收到的奖励是橙色的,第二个步骤的代理的行为和收到的奖励是蓝色的。如我们所见,没有涉及 RFs 的工具性目标。来源:作者生成,灵感来源于[4]。

我们可以看到,没有一条以代理商奖励为终点的路径是通过实施 RFs 的。这表明已实施的 RFs 没有按照要求参与工具性目标。

3.5 TI-考虑与 TI-忽略

正如我们所看到的,在我们的例子中,考虑 TI 的代理比忽略 TI 的代理要好得多。你可能想知道为什么有人会想要一个 TI 忽略代理。毕竟,从设计上来说,它更容易出现不稳定的行为。忽略时间不一致性的想法源于对安全可中断代理的研究[1]。事实证明,在某些情况下,你可能想中断你的代理的学习过程,例如,通过关闭它。例如,如果机器人仍在学习你的建筑布局,你可能必须防止它意外进入你邻居的公寓。在这种情况下,代理不应该仅仅因为它可以在其他地方清洗更多的污垢而学会回避您的指示。

总之,考虑 TI 的代理人不会滥用环境来篡改他们的奖励函数。但是,由于他们有保留射频的动机,用户也更难纠正他们的行为。另一方面,TI 忽略代理会让用户中断它们并改变它们的 RF,但是它们也更容易受到环境的影响。

4.结论

我们已经看到因果影响图如何让我们分析代理的工具性目标,以及电流-RF 优化的原则如何减少奖励篡改的激励。这促使我们讨论两种类型的电流 RF 优化,即考虑 TI 和忽略 TI,并比较它们的优缺点。如果你对这个话题感兴趣,我推荐你阅读激发了这篇文章的论文。DeepMind 安全研究中心的这篇文章总结了对 CIDs 的进一步研究。

文献学

[1] Armstrong and Orseau,安全可中断代理,2016 年第 32 届人工智能不确定性会议,https://intelligence.org/files/Interruptibility.pdf

[2] Everitt Tom,用因果影响图理解代理人激励,DeepMind 安全研究于 2019 年 2 月 27 日在 Medium 上,https://deepmindsafetyresearch . Medium . com/Understanding-Agent-Incentives-with-causage-influency-Diagrams-7262 c 2512486

[3] Everitt 等,设计代理人激励避免奖励篡改,DeepMind 安全研究 on Medium,2019 年 8 月 14 日,https://deepmindsafetyresearch . Medium . com/Designing-agent-incentities-to-avoid-reward-tampering-4380 C1 bb 6 CD

[4] Everitt 等,强化学习中的奖励篡改问题及解决方案:因果影响图视角,Arxiv,2021 年 3 月 26 日,https://arxiv.org/abs/1908.04734

[5] Everitt 等人,因果影响图的进展,DeepMind 关于介质的安全研究,2021 年 6 月 30 日,https://deepmindsafetyresearch . Medium . com/Progress-on-Causal-Influence-Diagrams-a7a 32180 b0d 1

如何对机器学习项目中的数据进行分层,以显著提高模型性能

原文:https://towardsdatascience.com/how-to-stratify-data-in-machine-learning-projects-to-significantly-improve-model-performance-4929b600340b

如何以及何时对机器学习项目中的数据进行分层,以确保仅使用 7 行 Python 代码就能做出准确且有意义的预测

照片由金刚砂木火子在 Unsplash 上拍摄

背景

我最近参与了一个真实世界的机器学习项目,该项目最初产生了一组预测,但这些预测被领域专家拒绝,因为他们无法接受未来会以模型预测的方式出现。

问题的原因围绕着数据所代表的业务方面随时间变化的性质,即未来不会像过去一样。

这可能意味着机器学习模型可能不够准确,没有意义,但最终通过对数据进行分层找到了解决方案,这促使我写了这篇文章来分享该解决方案,以便其他遇到类似问题的数据科学家可以使用它。

入门指南

我们首先需要的是一些数据。项目中使用的真实数据不能共享,所以我使用 Faker 库从头开始创建了一个虚拟数据集。这意味着对数据没有许可限制,数据可以用于或重新用于学习和开发目的

让我们从导入我们需要的库开始,然后读入虚构的数据集…

作者图片

CompletedCustomerLoans.xlsx表示虚拟贷款已经以存储在LoanStatus目标特征中的两种状态或分类之一完成。“已偿还”贷款已成功完成并由客户偿还,而“违约”贷款未偿还且未成功完成。

LiveCustomerLoans.xlsx有完全相同的格式,但没有LoanStatus,因为它们仍在运行,尚未完成,无论成功与否。

理解问题

机器学习的一个很好的用途是在已完成的贷款上训练一个模型,该模型可以预测当前贷款的未来贷款状态。

然而,我们需要两样东西来让一个模型以这种方式工作-

  • 一组可靠、准确和一致的历史数据
  • 未来会以与过去相似的方式发展

第二个因素是我们在这个数据集上有一些问题。此数据中的一个重要因素是LoanType,它可以是青铜、白银、黄金或白金。

贷款构成随时间变化的方式可以想象如下-

作者图片

作者图片

这些图表突出了这个问题。历史/已完成贷款有大量的青铜、白银和黄金贷款,但活贷款/未完成贷款没有。看起来我们的虚构贷款业务正在将所有未来客户转换为白金贷款,并停止其他贷款类型。

如果不同类型的贷款在偿还和违约方面的表现不同,那么机器学习模型将产生扭曲的预测。

如果遇到这种情况,您可能需要根据实时数据中的比例对训练数据进行分层,以提高预测的准确性。

本文的剩余部分将展示如何用不到 5 行的 Python 代码来实现这一点…

实现解决方案(前 5 行代码)

基于在另一个数据集中发现的任何要素组合的比例对一个数据集进行分层的可重用函数可按如下方式实现

作者图片

作者图片

了解解决方案

stratify函数只用了 3 行代码就实现了它的目的,这是 Pythonic 式的方法,但是减少代码行数会降低可读性,所以让我们把它拆开来看看到底发生了什么...

这是第一行代码…

stratify_cols包含用于构建权重的数据字段列表。

这行代码的返回类型是 Pandas 系列,其中 index 包含在人口数据中找到的值的范围,value 包含找到该值的行的百分比。

normalize=True告诉value_counts返回百分比而不是实际计数。然后将这些值乘以在样本数据中找到的记录总数(sample.shape[0]),得到样本数据集中所需的记录数,以反映在总体中找到的比例。

<class 'pandas.core.series.Series'>
MultiIndex([('Platinum',),(  'Silver',),(  'Bronze',),(    'Gold',)],names=['LoanType'])LoanType
Platinum    2032
Silver       367
Bronze       170
Gold         170
dtype: int32

下面是下一行代码。它做了很多事情,我将分阶段解释…

让我们从头开始。sample.groupby(stratify_cols)返回一个DataFrameGroupBy对象,为在stratify_cols中找到的每个唯一组合分组。这可以想象如下...

Bronze
Gold
Platinum
Silver

group.sample(n=weights[group.name])然后使用组名索引权重系列,并提取要采样的记录数...

170

最后一部分只是承认样本数据中可能有在总体数据中找不到的值,所以内联if语句只对任何符合该条件的数据进行零行采样

group.sample(n=weights[group.name] if group.name in weights else 0

样本中的参数replace=True将每个采样行放回数据中,以便在必要时可以重新采样,并且random_state被设置为支持可再现的结果。

最后,lambda 函数的魔力意味着为每个组返回的样本被连接在一起,产生一个单独的DataFrame

为了解释第三行也是最后一行代码,让我们快速看一下df_return

作者图片

这看起来不太对。Pandas 已经返回了一个MultiIndex,这需要看起来像在原始数据中找到的简单索引,而不丢失索引值。

这需要进行大量的研究和文档阅读,但事实证明,通过删除与最初用于构建索引的特性相关的多部分,可以将索引恢复到原始格式

作者图片

最后的改进(总共 7 行代码)

现在我们有了一个函数,可以通过在另一个数据集中找到的比例对任何数据集进行分层,但是如果我们只知道所需的比例,但没有人口数据集,那该怎么办呢?

这可以通过在build_weights函数中增加一行代码和对stratify做一点小小的修改来实现,以接受weights作为可选参数。

请注意,如果values的列表代表行数,则sample_size被设置为0。如果values包含一组加起来等于1的浮点数(即百分比),则sample_size包含要乘以百分比进行采样的记录数。

build_weights中的一行代码相当简单明了。它使用内联的if语句为dataindex参数传递适当的值。为了找到如何为不止一个层次的实例构造一个MultiIndex,但是完成的代码非常干净,确实花费了相当多的研究...

Bronze      1000
Silver       500
Gold         250
Platinum     100
dtype: int64

或者…

Bronze      1000
Silver       500
Gold         250
Platinum     100
dtype: int64

作者图片

结论

在本文中,对数据进行分层可以显著提高机器学习模型的性能。这已经通过引用真实世界的项目来呈现,然后使用虚构和合成的数据来演示。

仅用 3 行 Python 代码就开发了一个简单的函数,该函数可以根据在另一个数据集中发现的比例对任何数据集进行分层,从而为符合所述条件的建模准备数据。

最后,还提供了一个额外的函数,该函数可以构建权重并将其传递给执行分层的函数,以满足数据科学家知道比例应该是多少,但无法访问包含正确比例的数据集的情况。

感谢您的阅读!

如果你喜欢读这篇文章,为什么不看看我在 https://grahamharrison-86487.medium.com/的其他文章呢?此外,我很乐意听到您对这篇文章、我的任何其他文章或任何与数据科学和数据分析相关的内容的看法。

如果你想联系我讨论这些话题,请在 LinkedIn 上找我—【https://www.linkedin.com/in/grahamharrison1 或者发电子邮件到ghar rison @ Lincoln college . AC . uk。

如果你想通过订阅来支持作者和全世界 1000 个为文章写作做出贡献的人,请使用下面的链接(注意:如果你使用这个链接免费注册,作者将收到一定比例的费用)。

https://grahamharrison-86487.medium.com/membership

如何构建可读性和透明度的数据科学项目

原文:https://towardsdatascience.com/how-to-structure-a-data-science-project-for-readability-and-transparency-360c6716800

以及如何用一行代码创建一个

动机

根据特定标准构建数据科学项目非常重要,这样您的团队成员就可以轻松地维护和修改您的项目。

作者图片

但是你应该遵循什么样的标准呢?如果您可以使用模板为数据科学项目创建一个理想的结构,这不是很好吗?

有一些很好的数据科学项目模板,但是它们缺乏一些好的实践,比如测试、配置或格式化代码。

这就是为什么我创建了一个名为 data-science-template 的库。这个存储库是我多年来提炼构建数据科学项目的最佳方法的结果,以便它是可重复的和可维护的。

在本文中,您将了解如何使用该模板将最佳实践整合到您的数据科学工作流中。

开始

要下载模板,从安装 Cookiecutter 开始:

pip install cookiecutter

基于模板创建项目:

cookiecutter https://github.com/khuyentran1401/data-science-template --checkout dvc-poetry

…,系统会提示您回答有关项目的一些细节:

作者 GIF

现在,在您的当前目录中创建了一个具有指定名称的项目!项目的结构如下所示:

作者图片

该模板中使用的工具有:

  • 诗词:依赖管理
  • 九头蛇:管理配置文件
  • 预提交插件:自动化代码审查格式
  • DVC :数据版本控制
  • pdoc :自动为你的项目创建 API 文档

在接下来的几节中,我们将学习这些工具和文件的功能。

安装依赖项

有两种常见的安装依赖关系的方法:pip 和诗歌。在接下来的部分中,将向您展示如何使用每种方法。

为您的项目创建一个虚拟环境,以将您的项目的依赖项与您计算机上的其他项目的依赖项隔离开来,这是一个很好的做法。

要创建虚拟环境,请键入:

python3 -m venv venv

要激活虚拟环境,请键入:

source venv/bin/activate

接下来,从 requirements.txt 安装这个项目的依赖项:

pip install -r requirements.txt

要添加新的 PyPI 库,请运行:

pip install <library-name>

诗意

poems是一个 Python 依赖管理工具,是 pip 的替代方案。诗歌让你:

  • 将主依赖项和子依赖项分离到两个独立的文件中(而不是将所有依赖项存储在requirements.txt中)
  • 创建可读的依赖文件
  • 删除库时删除所有未使用的子依赖项
  • 避免安装与现有软件包冲突的新软件包
  • 将您的项目打包成几行代码

在这里找到如何安装诗歌的说明。该项目的所有主要依赖关系在pyproject.toml中指定。要安装所有依赖项,请运行:

poetry install

要添加新的 PyPI 库,请运行:

poetry add <library-name>

要删除库,请运行:

poetry remove <library-name>

生成文件

Makefile 允许您为任务创建简短易读的命令。您可以使用 Makefile 来自动化任务,例如设置环境:

现在,每当其他人想要为您的项目设置环境时,他们只需要运行以下命令:

make activate
make setup

将运行一系列命令:

作者 GIF

管理代码和测试

所有的 Python 代码都存储在src目录下。

作者提供的图片—从平面图标获得的图标

所有测试文件都在tests目录下。每个测试文件都以单词test开头,后跟测试文件的名称。

作者提供的图片—从平面图标获得的图标

使用 Hydra 管理配置文件

配置文件将所有值存储在一个地方,这有助于将值与代码分开,并避免复杂的编码。在该模板中,所有配置文件都存储在目录config下。

作者图片—从平面图标获得的图标

Hydra 是一个 Python 库,允许你访问 Python 脚本中配置文件的参数。

作者提供的视频

例如,如果我们的main.yaml文件如下所示:

作者图片—从平面图标获得的图标

…,然后我们可以通过在特定函数上添加装饰符@hydra.main来访问配置文件中的值。在这个函数中,我们可以使用点符号config.processed.path来访问processedpath下的值。

使用 DVC 管理数据和模型

所有数据都存储在data下的子目录下。每个子目录存储不同阶段的数据。

作者提供的图片—从平面图标获得的图标

所有型号都存储在目录model下。

由于 Git 对于二进制文件的版本控制并不理想,我们使用 DVC——数据版本控制来对我们的数据和模型进行版本控制。

我们在dvc.yaml文件中指定了 DVC 阶段。每个阶段代表单独的数据过程,包括它们的输入(deps)和结果输出(outs)。

DVC 会自动跟踪outs下的所有目录和文件。

如果你想执行在它们的阶段中定义的命令,运行dvc repro。DVC 将跳过没有改变的阶段。

作者 GIF

远程存储您的数据

使用 DVC 的主要好处是它允许你将 DVC 追踪的数据上传到远程存储器。你可以将数据存储在 DagsHub、Google Drive、亚马逊 S3、Azure Blob Storage、Google 云存储、阿里云 OSS、SSH、HDFS 和 HTTP 上。

dvc remote add -d remote <REMOTE-URL>

将数据添加到本地项目后,您可以将数据推送到远程存储:

dvc push

将所有更改添加并推送到 Git:

git add .
git commit -m 'commit-message'
git push origin <branch>

提交前检查代码中的问题

将 Python 代码提交给 Git 时,您需要确保您的代码:

  • 看起来不错
  • 是有组织的
  • 符合 PEP 8 风格指南
  • 包括文档字符串

然而,在提交代码之前检查所有这些标准可能会让人不知所措。预提交是一个框架,允许您在提交代码之前识别代码中的简单问题。

</4-pre-commit-plugins-to-automate-code-reviewing-and-formatting-in-python-c80c6d2e9f5>

您可以在预提交管道中添加不同的插件。一旦你的文件被提交,它们将被这些插件检查。除非通过所有检查,否则不会提交任何代码。

作者图片—从平面图标获得的图标

在这个模板中,我们使用了在.pre-commit-config.yaml中指定的五个不同的插件。它们是:

  • blac k —格式化 Python 代码
  • flake8 —检查你的 Python 代码的风格和质量
  • isort —自动按字母顺序对导入的库进行排序,并将它们分成不同的部分和类型。
  • mypy —检查静态类型
  • nbstripout —从 Jupyter 笔记本中剥离输出

要向 git 挂钩添加预提交,请键入:

pre-commit install

现在,每当您运行git commit时,您的代码将在提交前被自动检查和重新格式化。

作者 GIF

添加 API 文档

数据科学家经常在一个项目中与其他团队成员协作。因此,为项目创建良好的文档非常重要。

要基于 Python 文件和对象的文档字符串创建 API 文档,请运行:

make docs_view

输出:

Save the output to docs...
pdoc src --http localhost:8080
Starting pdoc server on localhost:8080
pdoc server ready at [http://localhost:8080](http://localhost:8080)

现在您可以在 http://localhost:8080 上查看文档。

作者 GIF

要将所有 API 文档保存为降价,请运行:

make docs_save

结论

恭喜你!您刚刚学习了如何使用数据科学模板构建您的数据科学项目。这个模板意味着要灵活。请根据您的应用程序随意调整项目。

请随意使用这里的数据科学模板:

https://github.com/khuyentran1401/data-science-template

我喜欢写一些基本的数据科学概念,并尝试不同的数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

如何研究和学习复杂的软件工程概念

原文:https://towardsdatascience.com/how-to-study-and-learn-complex-software-engineering-concepts-997d85399aec

帮助你在任何计算机学科中茁壮成长的 5 个策略

作者图片

伟大的开发者从不停止学习!虽然有几乎无穷无尽的学习策略,但在这篇文章中,我分享了一些帮助我学习和掌握我在学术和职业生涯中选择的科目的策略。

1⃣——写下来

写下你想学的东西会使用你大脑中与阅读不同的部分。尽管我已经试着用我的笔记本电脑记笔记来提高效率,但使用老式的纸笔方式被证明在较低层次上保留信息更有效。写作这一行为促进理解和记忆,因为各种各样的机制在起作用:重复、强化和对新材料的批判性思考。

做笔记有多种技巧,这完全取决于你的学习方式。我是一个视觉学习者,所以我喜欢创建图表、思维导图、概念图、流程图、汇总表、公式等等。每个人处理信息的方式都有一点不同,所以试着找到那些能帮助你更快吸收新概念的方式。

2⃣——解构它

组块是一种强大的技术,通过将大而复杂的主题分解成代表你需要掌握的核心概念的更小、更易管理的单元来学习新概念。假设您想要开始您的数据科学之旅。拿一本书或者找一个关于这个主题的全面的在线课程,从浏览目录开始,通过浏览标题、副标题和插图略读章节。这可以让你对你将要探索的材料有一个感觉,并对它是如何组织的进行心理观察,并开始欣赏大图是什么样子的,这样你就可以在以后补充细节。

在这个第一阶段之后,你需要开始学习单个词块的来龙去脉。它并不像你最初想的那样令人生畏,因为你已经形成了你将学习什么的想法。因此,继续我们之前的例子,你可以深入阅读书中的章节,然后通过查看维基百科、观看视频教程、查找在线资源以及沿途做大量笔记来补充你的知识。这种重复可能感觉是多余的,但这意味着你有更多的机会交叉参考你所学的,而不仅仅是记忆事实。

我喜欢这种策略,因为它是一种有效的分而治之的方法,可以一点一点地学习一门新学科,最后,当你把所有的东西放在一起时,你就能看到它们是如何协调工作的。它不仅适用于像从零开始数据科学这样的大主题,而且也有助于拓宽您对已经学习的复杂主题的理解。假设您想更深入地了解 Java 中垃圾收集的内部工作方式。你首先需要了解内存的类型,即堆和栈。一旦您对这些术语感到满意,您就可以继续进行对象分配,等等…

你重复这个过程,直到你完全理解了这些术语和它们所代表的含义,最后,你将完成整个九码。

3⃣ —简化它

作为大学新生,在我参加的第一次讲座中,我偶然发现了费曼技术。我当时的教授大声说,除非我们能向孩子解释清楚,否则我们永远也不会深刻理解任何概念。然后,他宣称,根据他的经验,许多软件工程专业人员都在使用行话和特定领域的词汇,但是当涉及到详细说明细节时,他们缺乏理解。然后他敦促我们用接下来的 30 分钟向一个假装的 10 岁小孩解释什么是递归。哇,太难了!

下面是该方法的工作原理:

  1. 抓起一张纸,写下你想学习的概念的名称作为标题。研究主题并做大量笔记。
  2. 当你准备好了,用你自己的话解释,或者就像你在教别人一样——特别是和你有不同背景的人,比如一个孩子。注重使用简单的语言。
  3. 回顾你的解释,找出你学习中的差距。回到原始资料,以你的知识为基础。
  4. 如果你的解释中有任何地方使用了大量复杂或专业术语,试着用更简单的词语重写,去掉混乱,使用例子和类比来强化你的解释。

这些年来,这种方法一直伴随着我,但由于我现在不得不兼顾我的全职工作和家庭责任,我选择了一条捷径(罪名成立),只遵循上面的第 1 步和第 4 步。所以我实际上:

  1. 学习。
  2. 创建有根据的类比和视觉辅助工具来简化概念。

顺便提一下,我认为费曼技巧是进行面试时使用的有力武器:为了评估某人宣称的经历,我从问一些关于这个主题的基本问题开始。***钻的问题可能会很快让候选人陷入困境,但当我从基础开始时,我可以了解他们的能力水平,以及他们是否知道某事或他们知道某事的名称。

4⃣——照做就是了

虽然学习新信息很重要,但将新知识投入到积极的实践中无疑是提高学习和吸收能力的最佳方式。这就是信息如何从工作记忆转移到无意识,让你前进到更高层次的思维,事实上把这种知识转化为新的技能。

你可以阅读十个关于如何设计 rest API 的编码教程,但是一旦你试图自己构建一个,你可能会以失败告终。我遇到过一些拥有博士学位的同事,他们对理论了如指掌,但他们(恭敬地)创造了一些我见过的最糟糕的应用程序!所以不要满足于看教程或者看视频;试着成为亲力亲为的,因为它允许自我纠正任何教育失误。

我在我选择的语言中准备了一个沙盒环境来尝试新事物和测试算法。我的实践不仅限于对框架、设计模式或尝试新语法进行概念验证,还包括:

我编码任何可以编码的东西,即使编码不是手边的任务!

最近的一个例子是,当我修改贝叶斯定理时:尽管我正在读的书主要涵盖了它的数学方面,但我通过创建一个程序来加强我的学习,该程序获取乳腺癌患者的数据集,绘制它并计算假阳性和假阴性测试的概率。

**💡 Top Tip:** **Embrace Struggle**
Practice makes perfect; we all know that! But all practice is not created equal. It is not the quantity but the quality of our practice that determines how well we will perform. There is comfort in practising what we are good at (e.g. always using the same tech stack), but it is only when we expose ourselves to the uncomfortable sensation of feeling incompetent that we grow.
That makes the so-called: [deliberate practice](https://en.wikipedia.org/wiki/Practice_(learning_method)#Deliberate_practice) by its very nature, quite hard.

5⃣——深潜和回填

到目前为止,我已经描述了自下而上的学习策略,即从基础概念到更高级的知识积累。当开始一门新学科时,这很好,因为我们可以依赖以前学习的信息块,但也有缺点,许多这些概念本身并不特别有趣。

因此,我所做的就是从结尾开始,通过根据需要填补我知识中的空白,以逆向工程的方式回到基础。这是一种自上而下的方法,这种方法非常完美,因为我明白为什么我要学习一个特定的概念,同时也为所需的技能设定了一条清晰的路径。一个明显的缺点是,我可能会在不稳定的基础上建立我的理解,但我可以通过自我评估我的知识,特别是通过应用费曼技术,很快回到正轨。

为成功而终身学习

总结:如何研究和学习复杂的软件工程概念

除非你想在你选择的领域成为世界级的成功者,否则你可能不需要记录这 10,000 小时的练习。对于你的职业发展来说,表现得足够好是获得技能的最有价值的目的。Josh Kaufman 是《前 20 小时》一书的作者,也是《如何学习任何东西》TEDx 演讲的主讲人,他建议 20 小时可能是恰到好处的,因为它不会让你一开始就气馁,但也足够让你在你想学的技能上有显著的提高。

也就是说,学习没有开始、中间和结束——它是一个永无止境的过程!不可能对一个概念了如指掌,但你应该拥抱不可能并享受过程!你只需要可靠的教育资源和愿意冒险进行无限的学习探索。

感谢阅读!

我定期在媒体上撰写关于领导力、技术&的数据——如果您想阅读我未来的帖子,请‘关注’我

即使全职工作(或学习)如何学习数据科学

原文:https://towardsdatascience.com/how-to-study-data-science-even-if-you-work-or-study-full-time-b52ace31edac

在全职工作的同时学习和实践数据科学一年多之后,我的建议是

照片由在 Unsplash 上对比纤维

在这个世界上很少有确定的事情,但是有一点变得非常清楚:职业道路绝不是一条直线。忘掉“学习、找工作、结婚、退休”的方法吧:我们这一代人(也许还有未来的一代人)不会是那样的。这可能是由于快速增长的数字职业:许多人被困在他们的工作中,而他们已经看到了他们周围的世界在增长;也许是因为疫情,他们甚至开始考虑改变职业。

前几天写了一篇关于数据科学如何学习 Python的文章。现在,我想给你一些关于如何学习数据科学的建议,即使你是全职工作或学习。

如果你正在考虑数据科学,但你觉得你没有时间学习和实践,因为你全职工作或学习,那么这是适合你的文章:我已经开始在全职工作的同时学习和实践数据科学(和两个小女儿),我想与你分享我对你如何也能做到这一点的建议。

找到你最有效率的时间

这是最难的部分,我想一开始就治疗。

如果你全职工作或学习,你没有太多时间花在其他事情上,但是,说实话,如果我们只是在智能手机上使用时间跟踪器作为应用程序,你会惊讶地发现我们一天浪费了多少时间。

不管怎样,我相信你只有两次机会为自己找到时间:

  • 早上在你去工作/开始学习之前
  • 晚上,下班后/大学

这里有一条我想给你的建议:你必须花一些时间(几天/几周)去了解什么时候你最有效率。例如,我发现自己在早上效率最高,所以我早上 5:30 起床,吃点早餐,冥想 5 分钟,然后开始学习和练习。

此外,我甚至在晚上晚饭后练习,但由于在这段时间里,我通常会因为一整天的工作而感到非常疲劳,所以我会做一些“不难”的任务;比如,开始写一篇这样的文章。

相反,在最高效的时间窗口中,你必须执行“复杂”的任务,比如学习(理解概念)或开发项目。

学会将任务细分成非常小的任务,并对它们进行规划

在我看来,议程必须成为你最好的朋友。

你要学会的最重要的事情是把每一项任务细分成更小的任务,并对它们进行规划。例如,我知道我每天早上在准备去上班之前有大约 40-50 分钟,我已经学会安排我的任务,这样我就知道我会忙大约 20-30 分钟;你的代码经常会有问题需要解决,而且有些概念可能比其他概念更难理解,所以,在我看来,把你的时间安排得比你拥有的全部能力少是一个好习惯

这个想法就是安排你的时间,把要做的事情写在日程表上。我通常会在晚上花 5 分钟来安排第二天的时间。

从现在开始要明白的一件重要的事情是,你必须非常具体。你不能写:

我必须学习

这有几个原因:

  • 如果你像我一样早上醒来很早,你的大脑会记得你写了“我必须学习”,因为我们的大脑不喜欢义务,而且,因为我们作为人类被设定为尽可能消耗更少的能量,你会立即在床上翻身,推迟闹钟。
  • 你还没有设定一个具体的目标,这是跟踪你的进展的根本。

相反,你必须写这样的东西:

  • 理解 Python 中的列表
  • 做一个字典练习
  • 安装 skicit-learn

随着时间的推移,你会明白你需要多少时间来完成事情,你会更具体地安排自己。例如,如果明天你想做一个关于字典的练习,你知道你有 20 分钟,但你认为你需要更多的时间,那么就这样安排它:

  • 早上:开始字典练习(在你决定练习的前一天晚上,你在电脑上准备好)
  • 晚上:结束字典练习

这样,在一天结束时,你会有一种成就感,这种成就感会让你在学习道路上取得进步,你会感到非常满足。

学习如何管理你的时间(和休息时间)

当你的一天被工作/学习和其他事情(家庭、朋友、购物等等)填满时,时间管理是你最好的朋友。你不能再浪费时间了。

请不要读了。我说“你不能再浪费时间了”;我没有说:不要休息(我们将在下一节讨论)。

例如,如果你要在早上起床时学习**,你不能打开你的脸书应用**“就一秒钟”,因为你会进入一个兔子洞……告别你 40-50 分钟的学习时间!

另外,我想再给你几条建议:

  • 重要的是提前准备和决定一切。把你的明天安排在今天晚上,这样明天你就不会浪费时间决定做什么(甚至花费精神资源)。(至少)在前一天做好一切准备和决定,你会发现事情会变得很容易:试着去相信。
  • 明智地利用你的休息时间。每个人在工作或学习时都会休息;这里的区别在于你如何使用它们。如果你对数据科学和机器学习充满好奇和热情,你会提出很多问题,你会寻找答案。我在这里的建议是在你休息的时候**(可能的话)离开在互联网上搜索的阶段,否则,如果你在你应该学习和练习的时候(例如,一大早)在互联网上搜索,你最终会浪费你的时间;此外,一天中没有完成某件事(如前一节所述)可能是停止这个奇妙旅程的起点。如果你的脑海中出现了一个问题,激起了你的好奇心,把它写在你的智能手机上,并在你工作/学习的休息时间在互联网上寻找答案。**

学会变通(如果需要的话)

我们并不都是一样的;有些人觉得自己被困在有利的一天里;此外,有时如果你错过了你的一些目标(因为各种原因:也许你得了流感,你根本不能学习!)在接下来的几天里,你可能会停止拖延,最终,你会结束你的数据科学之旅。

所以,我学到的最重要的事情之一是灵活安排我的日程。有些晚上,我的女儿们就是不让我睡觉,我也不能在早上 5:30 醒来学习;因此,我简单地重新安排我必须在早上、晚上或第二天完成的任务。

就这么简单。

当你学会变通时,变通是你的王牌。和自己在一起不会饿;你不会因为起不来(或者看了一晚上电视节目而自责!).

还有,最重要的是要学会倾听自己。如果你因为花了几天时间工作、学习、和孩子玩耍等等而感到疲倦,你的身体会要求你休息,你必须听从它。否则,你将支付一大笔账单;相信我。

如果你的身体需要休息时不休息,它最终会崩溃,迫使你休息更长时间;例如,当我在大学时,我从我的皮肤上了解到,如果我的身体需要休息时,我不休息,我会发烧;这样,我的身体需要休息 2-3 天:比我躺在床上的几个早上要长得多,因为我(真的)累了!

我非常清楚这种心理对话:“如果你今天不学习,将需要更长的时间才能得到职业改变的结果”;但是,相信我:你的大脑在欺骗你。这是一场马拉松,你需要为长跑保存体力。当你累了的时候,放松一下,休息一下:你会感谢我的!

结论

这些是我对如何在全职工作或学习的同时发展你的数据科学职业生涯的建议。

灵活性对我来说是最重要的,因为你必须学会如何管理你的大脑;所以,这是一部作品《在你里面》;冥想可能会在这方面帮助你(正如它帮助我一样)。

需要 Python 和数据科学方面的内容来开始或促进你的职业生涯吗?下面是我的一些文章,可以帮到你:

蟒蛇:

  • Python 中的循环和语句:深入理解(附示例)
  • Python 循环:如何在 Python 中迭代的完整指南
  • 学习 5 个 Python 库,开始你的数据科学生涯
  • 数据科学如何学习 Python

数据科学:

  • 如何处理数据科学中的缺失值
  • 如何在数据科学项目中执行特征选择
  • 如何检测数据科学项目中的异常值
  • 执行图形残差分析的两种方法
  • 如何利用学习曲线轻松验证您的 ML 模型
  • 柱状图和柱状图有什么区别?
  • 相关和回归的区别
  • 了解 l1 和 l2 正则化
  • Logistic 回归:我们来清理一下!
  • 什么是训练有素的模特?

考虑成为会员:你可以免费支持我和其他像我一样的作家。点击 这里的 成为会员。

数据科学如何学习 Python

原文:https://towardsdatascience.com/how-to-study-python-for-data-science-888a1ad649ae

在用 Python 学习和实践数据科学一年后,我的建议是

在 Unsplash 上由 Hitesh Choudhary 拍摄的照片

众所周知,数据是新的石油,鉴于数据科学领域的大肆宣传,有很多人正在研究数据科学并试图向它过渡(我也是:)。

因此,有太多的课程可供选择:我们如何选择正确的课程?更多:“Python 对于数据科学”是什么意思?因为似乎每门课程都会教你数据科学的 Python 语言;但真的是这样吗?

在本文中,我将根据我学习和实践 Python 数据科学的第一年,给出我的答案。

建议 1:如何学习基础知识

我告诉你真相:真正需要关注的问题不是“正确”的课程。寻找“正确的课程”——也许是承诺你在课程结束后找到工作的课程——不是你应该关注的(嗯,我向你保证,确实有帮助你找到工作的课程;但这不是重点)。

如果你想学习“数据科学的 Python”几乎任何课程都会教你同样的东西(几乎,我们说的是基础)。

因此,选择一门课程并:

  • 多多练习。实践让你成为开发者,而不是看视频。所以,看视频,读课文,做大量练习【额外提示:选一门有项目的课程,这样你在练习的时候就有了一些指导方针】。
  • 掌握基础知识。基础是任何事情的基础;你不能从屋顶开始盖房子。所以,学得很好:列表,元组,字典,循环,之类的东西。当然,还有:用这些概念进行练习。
  • **将函数和类留待以后使用。**我知道,有人可能会嗤之以鼻,但请听我说。在我看来,Python 课程中的人让函数和类变得容易,但事实并非如此。当你真的编程了很多的时候,你会需要函数和类;明确地说(简化):当你复制和粘贴相同的代码行时,你需要一个函数,当你复制和粘贴相同的函数时,你需要类;因此,为了简化,当您想要“自动化”您的代码时,您需要函数和类,这不是您在开始时所做的。如果你学习数据科学的 Python,你想分析数据;所以我的建议是:理解函数和类,但只是为了理解;不要太关注这些。当您分析完数据后,定义您的标准并创建您自己的类和函数来自动化您的代码。例如,那些是我的一些定制功能。

建议 2:统计学、Matplotlib 和 Seaborn

在您掌握了 Python 的基础知识之后,您将开始分析数据,主要是使用 Numpy 和 panasus,并且——因为您喜欢数据——您想要制作一些情节;因此,您需要了解一些统计数据和一些数据可视化库:Matplotlib 和 Seaborn。

让我用统计学非常明确地说:*你不需要成为一个统计学家。*请再读一遍。

尤其是在开始时,只需掌握以下基础知识:

  • 正态分布
  • 什么是平均值、模式和中位值
  • 条形图和直方图之间的区别是什么(是!有区别的!)
  • 什么是方框图,我们可以从中获得什么信息
  • 什么是相关性以及如何处理。在这里你会发现我写的一篇关于这个话题的文章可能对你有帮助

等等。

您不需要了解高级统计主题来分析数据和进行一些数据科学研究。从基础开始,理解它们,并通过实践来掌握它们。

然后,在策划时,我的建议是:

  • 从 Matplotlib 开始。Matplotlib 是一个非常强大的数据可视化库;在我看来,它的缺点是你有时需要过多的代码来创建一个情节;但是这种努力是值得的,因为与此同时,您正在掌握您的编程技能
  • 过一段时间,开始用 Seaborn 。当你开始使用 Seaborn 时,你将面对它的综合性和简单性,同时有可能绘制复杂的情节。你甚至可能会问自己为什么之前没有学过,原因很简单:Matplotlib 更容易理解;而且,事实是,当你甚至已经学会了 Seabors,你将同时使用 Matplotlib 和 Seaborn,有时甚至在同一个情节中。
  • 其他可视化工具和库(像 Plotly )。在您掌握了 Matplotlib 和 Seaborn 之后,您可能会喜欢尝试其他工具和可视化。这完全没问题,但我的建议是不要进入兔子洞;所有这些图书馆和信息可能会让人不知所措;事实是,你通常会使用专门的软件进行数据可视化(比如 Power BI 或 Tableau)。因此,探索你感兴趣的一切,但我在这里的最后建议是,了解你在真实的工作环境中可能需要什么,并使用这些工具和软件。

建议 3:机器学习

毫无疑问:使用 scikit-learn 作为 ML 的库。正如你将看到的,sk-learn 是一个具有许多功能的巨大库,但是——你可能知道——机器学习是一个广阔的领域,所以它的主库必须是。

在深入研究 ML 模型之前,我的建议是:

  • 理解回归和分类之间的差异,因为这是你在 ML 中将要面对的两种主要问题
  • 理解将数据帧分割成训练、验证和测试集的重要性,并开始练习 sk-learn 中的“train_test_split()”函数
  • 了解您可以用来验证模型的指标。例如,从一个简单的线性回归问题开始,开始使用 MSE 和 RMSE 来验证你的模型。这是我给你做的一个项目,作为初学者,你可以作为一个指南。

结论

我想强调的重要一点是,学习路径不是线性的,正如你可能认为的那样;但这是普遍真理。如果你正纠结于一个概念,没有必要为之疯狂:把它留在那里没关系,过一会儿再回来。

举个例子,正如我所说的:如果你正在纠结于函数和类,试着去理解它们,如何使用它们,何时使用它们;然后,当你明白你需要它们时,再回到它们身上(并深化概念,在你的代码中使用它们)。

此外,如果你全职工作或学习,并且想找时间学习和实践数据科学,在本文中,你可以找到我的建议。

需要 Python 和数据科学方面的内容来开始或促进您的职业生涯?下面是我的一些文章,可以帮到你:

巨蟒:

  • Python 中的循环和语句:深入理解(附示例)
  • Python 循环:如何在 Python 中迭代的完整指南
  • 学习 5 个 Python 库,开始你的数据科学生涯

数据科学:

  • 即使全职工作(或学习)也要如何学习数据科学
  • 如何处理数据科学中的缺失值
  • 如何在数据科学项目中进行特征选择
  • 如何检测数据科学项目中的异常值
  • 进行图形残差分析的两种方法
  • 如何利用学习曲线轻松验证您的 ML 模型
  • 条形图和柱状图有什么区别?
  • 相关和回归的区别
  • 了解 l1 和 l2 正规化
  • 逻辑回归:我们来清理一下!
  • 什么是训练有素的模特?

考虑成为会员:你可以支持我和其他像我一样的作家,不需要额外的费用。点击 这里 成为会员。

如何像专业人士一样设计熊猫数据框

原文:https://towardsdatascience.com/how-to-style-pandas-dataframes-like-a-pro-541c84142c17

用这份完整的初学者指南让你的数据框架惊艳四座。

文章缩略图(图片由作者提供)

Python 的 Pandas 库允许您以类似于 Excel 的方式呈现表格数据。不太相似的是样式功能。在 Excel 中,您可以利用一次单击着色或条件格式使您的表格引人注目。对熊猫来说,这就有点棘手了。

好消息是——熊猫中的风格 API 可以帮助。直到最近我才完全意识到这一点,这也是我希望能早点发现的事情之一。我花了太多时间在 Python 和 Pandas 中聚集数据,然后将结果复制到 Excel 中进行样式化。

听起来很熟悉?好,我们走吧!

数据集

在深入研究好的东西之前,我们必须关注数据集。您将在下面看到的代码片段为您创建了一个。它有四列,每列有 5 个任意值。一些值也丢失了,原因您将很快看到:

import numpy as np
import pandas as pddf = pd.DataFrame({"A": [0, -5, 12, -4, 3],"B": [12.24, 3.14, 2.71, -3.14, np.nan],"C": [0.5, 1.2, 0.3, 1.9, 2.2],"D": [2000, np.nan, 1000, 7000, 5000]
})
df

数据集如下所示:

图片 1-虚构的数据集(图片由作者提供)

这是一个非常标准的熊猫输出,看起来很熟悉,让我们面对它,无聊。接下来,你将学习如何调味。

熊猫样式的基本格式

Pandas 提供了一个样式 API,允许你改变数据帧的显示方式。有许多内置的样式函数,但也有选择编写自己的。

大部分时间我觉得很烦的一件事就是索引栏。它只是一个序列,并没有为表格可视化提供真实的价值。使用hide()方法来摆脱它:

df.style.hide(axis="index")

图 2 —隐藏数据帧索引(作者图片)

好多了!

还有其他事情让我们的数据框架看起来很痛苦。例如,这些十进制数的精度是不必要的。出于可视化的目的,大多数情况下两位小数就足够了:

df.style.format(precision=2)

图 3-指定数值精度(作者图片)

您可以更进一步,指定自定义格式字符串。下面的示例将在每个值的前后添加一个减号,并将每个数字的格式设置为三位小数:

df.style.format("- {:.3f} -")

图 4-自定义值格式样式(作者图片)

事情不会就此结束。有时,您希望每列有不同的格式。将格式化字符串指定为键值对,这样就可以了:

df.style.format({"A": "{:.2f}","B": "{:,.5f}","C": "{:.1f}","D": "$ {:,.2f}"
})

图 5-为每列指定格式样式(按作者分类的图像)

这是格式化的基础。接下来,我们将学习许多改变文本和背景颜色的方法——等等。

使用熊猫风格来改变文本和背景颜色

通常,突出显示您想要引起注意的数据点是一个好主意。方便的highlight_max()函数将数据帧中每个单元格的最大值指定为黄色:

df.style.highlight_max()

图 6-突出显示最大值(作者图片)

highlight_min()函数的作用正好相反:

df.style.highlight_min()

图 7-突出显示最小值(作者图片)

除了最小和最大数据点之外,您还可以突出显示缺少的值。以下示例显示了如何将没有值的单元格着色为红色:

df.style.highlight_null(null_color="red")

图 8-突出显示空值(作者图片)

如果您对默认打印的 nan 不满意,您还可以用自定义字符串格式化缺少的值:

df.style.format(na_rep="Missing").highlight_null(null_color="red")

图 9-突出显示空值(2)(作者图片)

整洁!让我们探索一些其他的颜色选择。

例如,background_gradient()函数将使用渐变调色板为单个行的单元格着色。默认情况下使用蓝色调色板,值较高的单元格用较暗的颜色填充:

df.style.background_gradient()

图 10 —使用渐变调色板突出显示(图片由作者提供)

您不必对整个数据集进行着色——subset参数允许您指定想要着色的列列表:

df.style.background_gradient(subset=["B", "D"])

图 11 —使用渐变调色板突出显示(2)(图片由作者提供)

还有一种方法可以改变调色板,并明确设置最小值和最大值。这些参数在background_gradient()text_gradient()功能中都可用。我们先来看看后一种是如何工作的:

df.style.text_gradient(subset=["C"], cmap="RdYlGn", vmin=0, vmax=2.5)

图 12 —使用自定义渐变调色板更改文本颜色(图片由作者提供)

不错,但是不太好看。第二个值有点难读。这就是为什么最好给整个单元格着色,而不仅仅是文本:

df.style.background_gradient(subset=["C"], cmap="RdYlGn", vmin=0, vmax=2.5)

图 13 —使用自定义渐变调色板更改背景色(图片由作者提供)

现在让我们进入真正令人兴奋的东西。我们将以条形图的形式研究每个单元格的颜色。条形的“长度”由单元格的值表示,相对于列的其余部分,该值越高,单元格的颜色就越多。

要给数据帧添加条形颜色,只需调用bar()函数:

df.style.format(precision=2).bar(color="orange")

图 14-以条形图形式显示的值范围(作者图片)

默认不是最好看的桌子。有一些列是负值,所以该条是双向的,没有视觉上的区别。至少可以说,这是一个糟糕的设计实践。

此外,如果单元格之间有边界,也会有所帮助。否则,填充颜色会与周围的颜色融合:

df.style.format(precision=2).bar(align="mid", color=["red", "lightgreen"]).set_properties(**{"border": "1px solid black"})

图 15-以条形图形式显示的值范围(2)(图片由作者提供)

好多了!

如果说许多熊猫用户有一个担心点,那就是文本大小。如果你在一个大显示器上工作,并且不想让一切都变得更大,那么它就太小了。

您可以使用set_properties()函数传入一个键值对字典。键和值都来自 CSS,如果你有任何网页设计的经验,你会有宾至如归的感觉。

下面的代码片段设置了较粗的灰色边框,将绿色应用于文本,并增加了文本的整体大小:

properties = {"border": "2px solid gray", "color": "green", "font-size": "16px"}
df.style.set_properties(**properties)

图 16 —更改文本颜色和大小(图片由作者提供)

这对于基本的造型来说已经足够了。接下来,我们将通过几个高级示例来突出这个表格。

高级:样式标题行和索引列

桌子设计,或者说一般意义上的设计,是高度主观的。但是所有好看的表格都有一个共同点——一个易于区分的标题行。在本节中,您将学习如何设计风格:

  • 表格标题行
  • 表索引列
  • 处于悬停状态的表格单元格

我们开始吧!我们将声明三个字典——第一个用于悬停状态,第二个用于索引列,最后一个用于标题行。您可以使用set_table_styles()功能将它们全部应用于一个数据帧:

cell_hover = {"selector": "td:hover","props": [("background-color", "#FFFFE0")]
}
index_names = {"selector": ".index_name","props": "font-style: italic; color: darkgrey; font-weight:normal;"
}
headers = {"selector": "th:not(.index_name)","props": "background-color: #800000; color: white;"
}df.style.set_table_styles([cell_hover, index_names, headers])

图 17 —带有样式化标题和索引行的表格(作者图片)

这与我们以前的情况有天壤之别,但我们可以做得更好。例如,我们可以使所有列具有相同的宽度,使单元格内容居中,并在它们之间添加 1 像素的黑色边框:

headers = {"selector": "th:not(.index_name)","props": "background-color: #800000; color: white; text-align: center"
}
properties = {"border": "1px solid black", "width": "65px", "text-align": "center"}df.style.format(precision=2).set_table_styles([cell_hover, index_names, headers]).set_properties(**properties)

图 18-带有样式化标题和索引行的表格(2)(作者图片)

这张桌子真好看!

接下来,让我们看看如何根据 Python 函数的输出有条件地声明样式。

高级:用 Pandas Styler 声明自定义样式

有时内置的样式就是不能满足它。幸运的是,您可以应用自己的 Python 函数。

这里有一个例子:mean_highlighter()函数将:

  • 如果值小于或等于平均值,则将单元格染成红色
  • 如果值大于平均值,则将单元格涂成绿色
  • 将文本设置为白色和粗体

一旦在 Python 函数之外,只需从 Pandas Styles API 调用apply()函数:

def mean_highlighter(x):style_lt = "background-color: #EE2E31; color: white; font-weight: bold;"style_gt = "background-color: #31D843; color: white; font-weight: bold;"gt_mean = x > x.mean()return [style_gt if i else style_lt for i in gt_mean]df.style.apply(mean_highlighter)

图 19 —使用均值高亮功能(图片由作者提供)

不是最漂亮的颜色,但绝对是在 Python 中设置条件格式的简单方法。

一个常见的用例是,如果值为负,则将单元格的文本颜色设置为红色。下面是您如何实现这一点:

def negative_highlighter(x):is_negative = x < 0return ["color: #EE2E31" if i else "color: #000000" for i in is_negative]df.style.apply(negative_highlighter)

图 20 —使用负荧光笔功能(图片由作者提供)

有了这些知识,我们只剩下一件事要讨论——导出您的样式化表格。

如何将设计好的熊猫数据框导出到 Excel

所有熊猫风格 API 函数的结果是一个熊猫数据帧。因此,您可以调用to_excel()函数在本地保存数据帧。如果您要将此函数链接到一组样式调整,结果 Excel 文件也将包含这些样式。

下面是导出基于渐变的彩色表格的代码:

df.style.background_gradient(cmap="RdYlGn").to_excel("table.xlsx")

图 21 —导出的 Excel 文件(作者提供的图片)

这也可以在 Excel 中实现,但在 Pandas 中实现要简单得多。

熊猫风格 API 概述

今天,您已经了解了熊猫风格 API 的来龙去脉。正如我前面提到的,这是一个我希望能尽快学会的 API,因为它能为我在做演示和写论文时节省很多时间。

用你今天学到的工具和技巧,没有什么是你做不到的。当您想要应用多种样式时,可以将函数链接在一起,例如,更改小数位数和给单元格着色。排序很重要,所以请记住这一点。

你最喜欢用什么方式来设计熊猫数据框?请在下面的评论区告诉我。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

保持联系

  • 雇用我作为一名技术作家
  • 订阅 YouTube
  • 在 LinkedIn 上连接

原载于 2022 年 7 月 27 日https://betterdatascience.comT22。

如何在 AI 全日制硕士中生存

原文:https://towardsdatascience.com/how-to-survive-a-full-time-msc-in-ai-e51b7b7a82d5

对有兴趣攻读人工智能全日制硕士学位的个人的生存指南

照片由 Unsplash 上的伊莉莎·卡尔韦·b .拍摄

我想大多数研究生都会同意这样的说法:完成硕士学位(成绩良好— 2:1 或优异)不是在公园里散步。特别是在人工智能领域,需要几门科学(如数学、计算机科学)的知识,学生们每天都要花几个小时才能弄清楚一个教授仅用 10 分钟就教完的机器学习算法的基本工作原理。最重要的是,他们必须满足苛刻的任务期限,找到一份工作(研究生计划,实习,兼职——对一些人来说),获得新技能,跟上该领域的最新发展。现在,当然,要应对由于新冠肺炎而产生的社交距离的负面感觉。

因此,学生的身心健康受到他们承受的大量压力的损害是很自然的。甚至在一些极端的情况下,让他们退出他们的课程。

事实上,我的个人经历(最近从伦敦大学玛丽皇后学院人工智能专业毕业)也属于这一类。虽然我没有辞职,但如果我说我没有想过,那我是在骗自己。我也承认,在我的第二个学期,我感到精神疲惫,以至于我无法集中精力阅读超过 5 分钟的科学论文。

幸运的是,这让我意识到我学习和计划一天/一周的方式有问题。

在与我的几个同学交谈并休息一周进一步研究这个问题后,我得出了这样的结论:通过培养一些好习惯,将我的心态转移到正确的方向,并设立现实可行的目标,我可以更有成效和效率,我可以坚持而不会筋疲力尽。

……五个月后(完成理学硕士学位后),花了几个小时调整我的目标和习惯,我意识到如果我早点开始这段旅程,我的生活会轻松得多。之所以特意选择“旅程”这个词,是因为这个过程永无止境。

为此,这篇文章将简要概述这个旅程的“站”(在更高的抽象层次上),并提出一些步骤,以便在获得人工智能硕士学位的同时享受这个过程。在这一点上,应该提到的是,本指南是从一个数据科学零初学者经验的学生的角度编写的,但它可以对有经验的专业人员有益,即使是在其他专业领域。

无论如何,没有进一步的到期让我们开始吧!!

开始攻读理学硕士学位前的准备工作

如果你不熟悉编码,我强烈建议你尽快开始编码

语言

人工智能、数据科学、大数据、商业分析领域的大多数理学硕士课程更喜欢将 Python 作为他们授课模块的主要语言。 Python 是一种初学者友好的语言(例如,与 Java 或 C++相比),坦率地说,是数据科学世界中最广泛使用的语言。

从我硕士期间和之后的个人经历来看,我认为事先掌握 Python 的基础知识是必须的,因为另一种选择是在学习过程中掌握这门语言,这意味着..你猜对了,额外的时间和工作!仅供参考,我做了大约 3 年的移动软件工程师,仍然花了一些时间来熟悉这种语言的语法和用法。

也就是说,有几个互联网资源,人们可以从那里开始学习 Python。我个人建议 Kaggle 课程快速入门这门语言以及它在人工智能领域的使用方式。当然,其他课程可以提供更全面的观点,但它们需要更多的时间来完成。

(可选)对于那些愿意付出额外努力的人(例如,在他们的理学硕士课程实际开始之前的假期期间),另一种有用的语言是 R (主要用于学术目的,因为有许多专门用 R 编写的包和库)。最后,对于铁杆程序员和可能对更高级的主题(深度学习、计算机视觉等)感兴趣的人..)后来,C++成了首选语言,因为计算能力要求最高的任务需要访问低级接口。

数据结构

另一个建议是尽可能多地学习关于数据结构的知识。数据结构对于描述数据组织、处理和加工的方式非常有用。它们也是技术/编码面试的基础!

如果我能回到过去,我会从头开始编写一些代码,这会磨练我新获得的 Python 技能。另一种方法是浏览 Leetcode 的资料,参考和扩展我的知识。

SQL-NoSQL

在人工智能领域工作意味着你将在某个时候被要求检索、处理和预处理大量数据。为此,在开始攻读理学硕士学位之前,具备 SQL 数据库(例如 MariaDB 或 PostgreSQL 或 SQL server)的基础知识,或许还有 MongoDB 和 Cassandra 等 NoSQL 数据库/工具,会有所帮助。

数学

数据科学的支柱是数学。基本上,项目中的每个数据科学阶段都是由决定最合适的行动过程的基础数学决定的。

由于这是一个非常大的题目,我将省去你阅读五段为什么数学如此重要的麻烦。相反,你会在这本指南中找到一些令人惊叹的人工智能数学资源。

顺便说一句,我完全赞同他用自上而下的方式来认识数学对于人工智能的必要性。

在你攻读理学硕士学位期间

在这一部分,我将建议 5 个支柱,它们概括了我通过经验和对该主题的研究获得的知识。结合起来,这些支柱可以引导你建立习惯,并将心态转向正确的方向,这将极大地帮助你度过硕士学位的压力,同时保持你的理智。

明确你毕业后的最终目标

这是你在获得理学硕士学位的第二/第三个月必须做的事情。

有人会说,这一节的标题相对于文章的其余部分来说相当奇怪。事实上,乍一看,我会同意之前的说法,因为今年的重点是毕业,对不对?

实际上,我认为答案部分正确!我故意用了“部分”这个词,因为有更大的行动在起作用。为了让你不那么神秘,这一幕分为两个 类别(职业路线),我坚持在你获得理学硕士学位的第二到第三个月(最多)做出这一选择的原因是,你需要对你未来将成为的世界有一个基本的了解,这取决于你的选择。就我而言,做出一个决定性的决定并不是一件容易的事情,因为每一个选择都需要遵循一定的道路,并拥有不同的技能才能获得成功。

尽管如此,请放心,因为我将在下面分析性地描述这两条职业道路。

商业生涯

如果你有兴趣应用你的人工智能技能来解决/改善现实世界的情况,并为企业的增长做出贡献,那么这是你的正确选择。最有可能的是,你将是一名员工,为一家公司工作,你的工作将需要处理大量数据,创建终端管道,编写质量软件和单元/集成测试,以及建立/改进现有的机器学习模型。此外,被要求研究一个关于该领域最新趋势的话题并将其展示给你的团队也并不少见。当然,您对这些任务的熟悉程度会有所不同,这取决于您的组织和职位(机器学习工程师、数据科学家和工程师)。

话虽如此,如果你想最大限度地提高被公司录用的概率,并省去硕士毕业后找工作的麻烦(相信我是很多的),你应该遵循以下步骤:

  • 首先专注于获得一个研究生项目(或者理想的初级职位)。

不要误解我的意思,你仍然希望以优异的成绩毕业(或 2:1),但我希望你明白的是,申请工作和准备每次面试是这里的优先事项。例如,你仍然应该在你的机器学习作业中获得高分,但只是在完成了你的找工作待办事项列表之后。

  • 获得找工作所需的技能和知识

我相信这是一个反复的过程,因为你的个人经历最终会揭示你所缺乏的技能。这些“不足”可能与你的人际交往能力或技术知识有关。出于这个原因,我个人的建议是,从第一次和第二次面试开始,首先发展你的沟通技巧,然后,转移到与招聘过程后期相关的更多技术问题上。

  • 练习,练习!

在面试过程的各个阶段尽早开始练习,利用大学的职业服务。为面试做额外的准备总比准备不足好。相信我,你不会想成为后者,因为很少有公司会给你打电话进行初次面试。想象一下,仅仅因为你不知道这个问题的答案就失去了你梦想中的工作:“你如何想象 5 年后的自己?”

  • 做好心理准备

在两个半月的时间里,我一共申请了 238 个职位,才成功地找到一个职位。你可以想象有多少次我当场或一周后被拒绝,没有进入下一阶段的面试,甚至更糟的是在面试过程的最后阶段被拒绝。请注意,对于每个职位,我都做了功课,修改了求职信,并遵循了适当的指导原则(或者至少我认为我做到了)。所以,当你早上醒来只是为了看到五个拒绝,不要气馁。坚持下去,提高你的技能。

学术界职业

第二条职业路线与你是一名人工智能教授或杰出的研究人员,受雇于一所受人尊敬的大学或研究机构有关。和以前一样,有一定的步骤,可以提高你获得梦想位置的几率。这些将是:

  • 获得尽可能高的分数

与之前相反,你的主要目标实际上应该是在学习期间出类拔萃。这是因为你想在毕业完成博士学位后被顶尖大学录取(最好是有奖学金)。自然,你最近的学术成就,应该是你在理学硕士中非常高的总成绩,应该会敲定这笔交易。

  • 成为数学专家

不管你未来的职业选择如何,理解多元微积分、线性代数、统计学和概率是你能拥有的最有用的知识。然而,成为一名成功的研究人员所需的数学知识水平远远高于在企业工作所需的水平。首先,我同意这听起来很可怕,所以我的建议是慢慢地向上爬。从基础开始,解决相关的练习,研究它们在人工智能领域的应用,然后继续前进。如果我是你,我会努力每天学一小时数学。

  • 找到你感兴趣的话题并了解更多信息

由于你刚刚开始你的人工智能之旅,大多数科目看起来都很有趣。话虽如此,试着找出一个真正能引起你共鸣的 AI 话题。例如,与语言(NLP)相比,我更喜欢处理图像/视频(计算机视觉)。这种早期的区分会节省你大量的时间,因为你已经知道你的硕士论文的主题是什么,也可能是你的博士论文的主题。

  • 注意你的理学硕士论文

不像现在的你,我不知道这最后一步有多重要。一篇好的理学硕士论文展示了你在你选择的主题上完成高质量工作的长度,展示了你的研究能力,创造力和对特定任务的奉献精神。此外,这可能是一个非常有说服力的关于你工作的故事,也可能是被名牌大学录取(或被你梦想中的工作录用)或不被录取的区别。就我而言,我足够幸运,因为我的作品被提议出版,但它是意想不到的,而不是有意的。尽管如此,当有人问我关于我在数据科学方面的项目时,我的硕士论文是我在采访中谈论的第一件事。

创建一个计划和健康的习惯

有规律的一天的价值在于更有动力,更有效率,更有纪律。

因为有太多的博客、YouTube 视频是关于如何让你的日常生活变得更好的,所以我只简单地提几个对我有用的。

早上的例行公事

在每天的同一时间(早上 8 点)设置一个闹钟,不要拿着我的手机查看我的社交媒体账户和电子邮件。相反,起床,喝水,做一些伸展运动或温和的核心运动,然后吃早餐。我练习斋戒,所以我跳过了最后一部分。冲完黑咖啡后,我会完成一天中第一个也是最重要的任务,没有任何其他干扰。那时,也只有那时,我才会查看我的社交媒体。这当然是我早上的例行公事。你可以根据你的标准和日常计划来调整或改变它。

每周锻炼 3-4 次&健康饮食

根据您当前的情况(设备、费用、时间)和偏好,创建适合您个人需求的锻炼计划。无论你的情绪波动如何,都要努力坚持锻炼,尤其是在最初几周。在这种情况下,健康饮食也至关重要。有几项研究表明,除了明显的健康问题之外,吃垃圾食品与你的学业/职业表现下降有关。

设定周目标和日目标

对你一天和一周应该做什么有一个清晰的认识是非常重要的。正如我之前提到的,你应该优先完成最紧急/最重要的任务,这是一个需要时间的过程,因为有效管理时间本身就是一种技能。

每周奖励自己一次

为了成功完成每周任务清单,你至少可以奖励自己。总是对自己苛刻是你在理学硕士期间以及生活中最糟糕的行为,所以你必须找到你喜欢做的事情并去做。

记笔记,重复你所学的内容

忘记和复习过去的科目是学习旅程的一部分。

我花了一段时间才意识到保持清晰、简洁的笔记的力量,但当我这样做时,我意识到它节省了我很多麻烦和时间。现在,当我需要找到 SVM 是如何工作的,或者有什么数据规范化技术时,我不必在堆栈溢出或随机网站中搜索,这显然需要时间。创建这些笔记还磨练了我的分析技能,因为我必须从网站、书籍或博客帖子中辨别出真正有用的信息,并用自己的话写下来。最后,修改题目的过程,比如神经网络中的反向传播,有了自己的笔记会快很多,因为我知道所有东西的确切位置。

我用观念来记笔记(基本上是为了整理我生活中的一切),用安奇 根据我在观念中创建的笔记来修改我想要的内容。例如,假设我想复习线性代数的基础知识。然后,我去 Anki,在那里我已经创建了一个与线性代数相关的问题和答案的甲板,并尝试回答它们。如果我不知道答案,我会首先在 Anki 中检查答案,然后在 concept 中打开相关注释,以获得整个主题的更广泛视图。

从第一天开始建立关系网

与你钦佩、尊重和敬仰的人交往是非常重要的。只是不要忘记这最终应该是一个双向的街道关系。

毫无疑问,我最大的错误是我在硕士期间没有建立足够的关系网。好吧,Covid 也在其中发挥了作用,但我肯定错过了很多机会,无法与我的同学、我喜欢听的教授以及来自我梦想成为其中一员的公司的年轻专业人士联系。事实上,我花了一整天的时间尽可能多地学习人工智能,并满足我苛刻的作业期限,同时我可以花一个小时与同学交谈,共同找到解决作业中困难部分的方法,而我通常会坚持三个小时。

另一种情况是,网络的价值得到了强调,那就是你想更多地了解人工智能中的一个特定主题/领域。你可以开始学习更多关于高级 NLP 主题的知识,例如,试图找到阅读的最佳资源,而你的 NLP 教授,顺便说一下,他在该领域有多年的经验,可以在几分钟内迅速为你提供解决方案。

如你所知,了解最适合这份工作的人,同时也是他们可以依赖的人,这是至关重要的。所以,不要害怕说出你的想法,要求并提供帮助,因为你最终会得到回报,即使你没有,你仍然会遇到另一个与你性格和心态不同的人。

接受你的人性和你的需求

你可以和你的朋友一起玩乐,建立长久的友谊,做一些疯狂的事情。

我注意到,在成年时期,我们很少有机会认识这么多新朋友,并和他们一起玩得开心。所以,利用这段时间,开放心态,结交新朋友。从我个人的经验来说,你肯定需要它,因为这种休息可以让你清醒头脑,为接下来的一周充电。

所以,这是我从伦敦玛丽女王大学获得的人工智能硕士学位的经验和我从艰难的道路中学到的教训的简要总结。我希望你从这个故事中得到一些有用的东西,并最终享受你自己的硕士学位。

我期待看到您的反馈和您的想法/改进。感谢您的阅读!!

如何从 Excel 切换到 Python

原文:https://towardsdatascience.com/how-to-switch-from-excel-to-python-20440824602e

当你只知道 Excel,而你想从 Python 开始时,让自己轻松地编程

艾通过作者创造艺术。 参见 Opensea 上的【NFT】 西蒙李

目录

  • 如何从 Excel 切换到 Python
  • 目录
  • 简介
  • 分析数据集
  • 1 安装库
  • 2 添加有丝分裂表
  • 3 获取并使用数据集
  • 这个为什么有价值?
  • 免责声明
  • 关于

介绍

在数据分析领域工作时,经常会遇到一个问题。那就是人们知道 Excel,但不会用 Python 编程。在某种程度上,有必要从 Excel 分析过渡到更具可伸缩性和灵活性的编程解决方案,如 Python。

你如何缩小这个差距?

慢慢地,一步一步地。

让我们来讨论一种当你所能做的就是 Excel 时轻松进入 python 编程的方法。

有一个图书馆试图缩小这个差距。米托允许你在 Python 中进行 Excel 计算,并为你生成熊猫代码。本质上,它就像是 Python 编码的指南。

让我们看一个例子

分析数据集

1 安装库

这里我要用的关键库是美图:【https://github.com/mito-ds/monorepo】T4

通过终端输入以下命令:

conda create -n YOUR_ENV python=3.9
conda activate YOUR_ENV
pip install mitoinstaller
python -m mitoinstaller install

2 添加有丝分裂表

之后,将启动 Jupyter 实验室(python 环境)来分析数据集

把这个放在一个格子里,它会打开你的界面来工作

import mitosheet
mitosheet.sheet()

3 获取和使用数据集

我想快速浏览一下最新的幸福数据集https://www . ka ggle . com/datasets/mathurinache/world-happiness-report-2022(许可证是 CC0: Public Domain )看看现在哪里住的好。

作者截图

所以,首先我将幸福指数列按降序排列。这个我是从 Excel 上知道的。

紧接着,带有注释的 python 代码就生成了。

作者截图

df_2022 = df_2022.sort_values(by='Happiness score', ascending=False, na_position='last')

这太棒了。执行所提供的单元格并调用 DataFrame 会引导我显示 pandas 数据帧:

作者截图

看得出奥地利在幸福排名上还是挺靠前的,这在一定程度上满足了我。(因为我现在住在奥地利)我想搬到一个更温暖的国家,所以我需要寻找其他的东西。我想去特内里费岛。然而,它不在这里:

作者截图

所以我宁愿去找西班牙。它的排名是 29。所以,也不错。

我想仔细看看健康的生活预期,这对我很重要。所以我去做了一些策划

作者截图

这对我来说太多了。我现在想了解一些 python 代码。在复制了它的代码片段后,我可以很容易地做到这一点。当执行代码片段时,我得到

作者截图

我想对 y 轴重新排序。所以我查阅了相关文件。并且在https://plotly . com/python/bar-charts/# bar-chart-with-sorted-or-ordered-categories上看到我可以只传递一些参数。所以我补充说

# Construct the graph and style it. Further customize your graph by editing this code.
# See Plotly Documentation for help: https://plotly.com/python/plotly-express/
fig = px.strip(df_2022, x='Country', y='Explained by: Healthy life expectancy')
fig.update_layout(title='Country, Explained by: Healthy life expectancy strip',xaxis=dict(rangeslider=dict(visible=True,thickness=.05)),yaxis=dict(categoryorder='category ascending')
)
fig.show(renderer="iframe")

这导致了我想要的排序:

作者截图

我可以看到奥地利的表现仍然很好。我看到北方的“冷”国在这方面做的极好。看看西班牙,我能看出这也不错。我还有其他选择,比如马耳他、意大利、哥斯达黎加。这激励我去那些国家中的一个。

现在,让我们以折线图的形式添加更多信息。

作者截图

然后导出 y 轴排序的代码:

作者截图

我想知道这些数字是如何关联的。我现在想深入了解更多的熊猫。我重新格式化了数字,因为数据集没有将它们作为数字提供。并用熊猫函数计算皮尔逊相关系数。

作者截图

我们可以清楚地看到,健康预期寿命和选择自由与幸福指数密切相关,但这两者的相关性只有 43%左右。从图表中我们可以看出,在排名较高的国家,这两个值都很高,而在排名较低的国家,这两个变量有时似乎相互抵消。这很有意思,也值得更详细地阐述。

这就是开始。如您所见,将 Excel 与 Python 结合起来非常容易。

这为什么有价值?

找到合格的开发人员和能够处理代码的人是一个挑战。你可以雇佣有经验的人,这通常是非常困难和昂贵的,或者你可以尝试民主化处理数据的过程,并允许非编码人员进入编码。

正如我经常经历的那样,许多人认为自己不是程序员就是非程序员。我经常听到“我不是开发人员,我不能这样做”。然而,只要稍加介绍,任何人都能够使用代码语法。循序渐进。一次一次。像这样的图书馆在这个过程中发挥了作用。它们允许人们利用他们已经拥有的技能,扩展他们,并获得新的技能来改进他们的工作。

我很高兴有这样一个强大的开源社区,让日常生活变得更容易。我认为,在一个公司/项目中,协调人员能力的最佳方式之一就是像这个例子中那样分享优势。总是需要很强的专业知识。传播专业知识是团队成长和让项目产生杰出成果的关键之一。

放弃

这个库的创建者之一找到了我,我们开始讨论如何让人们更容易地学习 Python。这个图书馆是他的项目,他想让我写一写。我很清楚这个库的目的,所以这就是为什么我认为我应该详细说明一下。

我不认为自己是专家。除了做其他事情,我只是记录事情。因此,内容并不代表我的任何专业工作的质量,也不完全反映我对事物的看法。如果你觉得我错过了重要的步骤或者忽略了什么,可以考虑在评论区指出来或者联系我。

这是 2022 年 3 月 20 日写的。我无法监控我的所有文章。当你阅读这篇文章时,提示很可能已经过时,过程已经改变。

我总是乐于听取建设性的意见以及如何改进。

关于

丹尼尔是一名艺术家、企业家、软件开发人员和商业法毕业生。他的知识和兴趣目前围绕着编程机器学习应用程序及其所有相关方面。从本质上说,他认为自己是复杂环境的问题解决者,这在他的各种项目中都有所体现。

作者照片

→在https://medium.com/subscribe/@createdd订阅此处或在 medium->https://medium.com/@createdd/membershipT2 阅读更多内容

连接到:

  • Allmylinks

直接:

  • 领英
  • Github
  • 中等
  • 推特
  • Instagram
  • createdd.com

艺术相关:

  • 公海
  • Instagram/art_and_ai
  • 稀有的
  • 已知产地
  • 中等/最先进的
  • 魔鬼艺术

如何将您的 SQL 从零提高到数据科学家级别—第 1/3 部分

原文:https://towardsdatascience.com/how-to-take-your-sql-from-zero-to-data-scientist-level-part-1-3-d7225d2d89ad

设置 SQL 并执行您的第一个选择查询

张秀坤·马丁在 Unsplash 上的照片

尽管 SQL 已经有 50 多年的历史,但它仍然是大多数数据科学团队从数据库中检索(大)数据的主要语言。查看 Stack Overflow 2022 开发者调查,有 3424 名专业人士目前的工作是数据科学家或机器学习专家。其中,58%的人在过去一年中使用过 SQL。相比之下,70%的人使用过 R,87%的人使用过 Python,40%的人在过去的一年中使用过这三种语言。换句话说,10 个数据科学团队中有 6 个会希望你在你的角色中使用 SQL。

在这个由三部分组成的系列文章中,我为希望按照优秀数据科学团队的标准学习 SQL 的有抱负的数据科学家创建了一个指南。该指南的结构如下:

第一部分:

  • SQL 简介
  • 安装 SQL 并加载您的第一个演示数据库
  • 运行您的第一个选择查询!

第二部分 :

  • SQL 列表的终极指南:了解数据科学家经常使用的基本和高级 SQL 查询

第三部分:

  • 查询优化、测试代码、数据科学编码最佳实践和培训计划

1。SQL 简介

剂量媒体在 Unsplash 上拍照

1.1。什么是 SQL?

SQL 代表结构化查询语言,用于在关系数据库中操作数据(您经常会听到“我写了一个查询”这个术语指的是 SQL 代码)。

1.2。什么是关系数据库?

从本质上讲,关系数据库只是表的集合(在计算机科学中,表被称为关系,因此得名关系数据库)。还有其他数据库对象,但是作为一名数据科学家,您 90%以上的时间将用于表。

  • 在一个表中,每一行都必须是唯一的。换句话说,给定行的列值组合在任何其他行中都找不到。为此,我们通常为每个表行创建一个唯一的代理列。该列被称为表的主键
  • 在表格中,每个单元格只能包含一个值。所以在一个单元格中不能有客户的名字和地址。这些必须分成不同的列

1.3。关系数据库中的表有哪些例子?

根据我在一家电子商务/零售咨询公司担任高级分析师和移动游戏数据科学家的经验,您会发现几乎任何关系数据库中都有三个主要的表。

  • 客户用户表(客户 id、名字、姓氏、账户创建日期、地址等。)
  • 交易表(transaction_id,购买时间戳,交易值等。)
  • 产品表(产品 id、产品名称、产品部门等。)

1.4。作为一名数据科学家,我将编写哪些类型的 SQL 语句?

作为一名数据科学家,您将主要使用 SQL 从数据库中提取数据(使用 SELECT 语句)。然后,数据将被加载到 R、Python 或 Excel 中,以执行您的分析。通常,您会想要组合来自多个表的信息。因此,您可能希望找到去年购买了产品 A 的客户。有时,尽管很少,您可能会改变或创建数据库中的表(如带有模型分数的表)。

1.5。表格是如何相互链接的?

任何关系数据库的一个基本概念是表如何相互关联。有三种类型的关联或关系,如下所示(主键列旁边有一个钥匙图标)。为了链接这些表,我们使用共享列。

关系数据库中的关系类型[图片由作者提供]

一对一:

  • 客户人口统计客户电子邮件 表具有一对一的关系,因为它们在 customer_id 列中都是唯一的
  • 共享的 customer_id 列将用于链接表

一对多:

  • 客户人口统计交易 表具有一对多关系,因为一个客户(customer_id)可以进行多个交易(transaction_id),但是每个交易只能由一个客户进行
  • 共享的 customer_id 列将用于链接表

多对多:

  • 事务产品表具有多对多关系,因为每个事务可以有多个产品,并且每个产品可以在多个事务中
  • 关系数据库只直接支持一对多关系。多对多关系是通过在第一个和第二个表之间添加第三个表来创建两个一对多关系而实现的。为此添加了事务细节表(主键是 transaction_id 和 product_id 列的组合)

2。安装 SQL 并运行您的第一个选择查询!

照片由阿毛里·梅希亚在 Unsplash 上拍摄

到目前为止,我们已经介绍了关系数据库和 SQL 的基础知识。接下来,看看所有这些是如何与 RDBMSs(关系数据库管理系统)的使用结合在一起的将会很有用。有很多不同的RDBMS、比如 PostgreSQL、SQLite、MongoDB、MySQL、微软 SQL Server(或者只是 SQL Server)。有趣的是,尽管关系模型和 SQL 是 IBM 发明的,但其他公司立即将其视为游戏规则的改变者,导致 Oracle 通过首先在市场上提供 RDBMS 而击败了他们。但是即使有很多,所有的 RDBMSs 都有一个单一的主要价值点,它们提供了一个支持 SQL 和关系数据库的环境。

出于本指南的目的,我们将使用 SQL Server。为了可视化数据库和表并编写 SQL 查询,我们将使用SSMS(SQL Server Management Studio)。与 R 使用 RStudio 或 Python 使用 Spyder 的方式类似,SQL Server 使用 SSMS。

2.1 安装 SQL Server(速成版)

  • 转到微软的下载页面并下载 SQL Server Express
  • 下载后,打开 SQL Server Express 安装程序
  • 选择基本作为安装类型
  • 选择安装路径(我建议保留默认值)
  • 遵循安装程序的说明,直到完成安装

2.2 安装 SSMS

  • SQL Server Express Edition 安装完成后,将提示您安装 SSMS
  • 遵循默认步骤,直到完成
  • 打开“SSMS ”,等待“连接到服务器”弹出式窗口出现
  • 如下图所示,填写弹出窗口
  • 如果服务器名**。\SqlExpress** 不起作用,使用设备名称\SqlExpress (谷歌查询如何在你的操作系统中找到你的计算机的设备名称会给你结果。例如,在我的例子中,它是 LAPTOPVAMVAS\SqlExpress

SSMS 连接到服务器[图片由作者提供]

完成后,您应该在 SSMS 看到三个面板,如下所示。在左侧面板中,您可以看到对象资源管理器。我们将连接到 SQL Server 的本地实例,即充当服务器的计算机(如果存在的话,这也可以是云服务器或物理服务器)。您还可以看到默认情况下在服务器中创建的四个系统数据库(通过安装)。右上面板是您将编写和执行 SQL 查询的区域,在右下面板,您还可以看到查询的结果。

安装后的 SSMS 快照[图片由作者提供]

2.3 加载 AdventureWorks 演示数据库(最后一步!)

  • 下载冒险作品**。从下载备份文件部分提供的链接之一 bak** 文件(我建议选择 2019 OLTP 文件)
  • 移动**。将 T17 文件备份到您的 SQL Server 备份位置。这取决于您的安装位置、实例名称和 SQL Server 版本。例如,SQL Server 2019 的默认实例的默认位置是*“C:\ Program Files \ Microsoft SQL Server \ MSSQL 15。SQLEXPRESS\MSSQL\Backup"***
  • 在 SSMS,右键单击对象资源管理器中的数据库恢复数据库以启动恢复数据库向导
  • 选择设备,然后选择省略号(…)来选择设备。
  • 选择添加然后选择。您最近移动到备份位置的 bak 文件
  • 选择确定确认您的数据库备份选择并关闭选择备份设备窗口
  • 选择确定恢复您的数据库
  • 请访问微软的此页面获取最新的分步指南

完成最后一步后,您现在自豪地拥有了一个托管在您计算机上的演示关系数据库(见下图)。这是一个重要的里程碑,因为现在您已经创建了一项资产—随时使用实际数据练习 SQL 查询的能力!

加载了 AdventureWorks 演示数据库的 SSMS[图片由作者提供]

左侧面板是我们的演示数据库( AdventureWorks2019 )。如您所见,我已经将其展开以查看数据库中的所有表,并且我还展开了人力资源。Department 表来检查其中的列(我还可以看到 DepartmentID 列旁边的键,表明它是该表的主键)。

我还在 SSMS 的右上角写了一个简单的 SELECT 语句(如下面的代码块所示),从 HumanResources 中提取前 1000 行。部门表。在右下角的面板上,您可以看到该查询的结果。该表有 16 行和 4 列。

SELECT TOP (1000) [DepartmentID],[Name],[GroupName],[ModifiedDate]
FROM [AdventureWorks2019].[HumanResources].[Department]--- or use the simplerSELECT *
FROM [AdventureWorks2019].[HumanResources].[Department]

在本系列的下一篇文章中,我们将深入学习数据科学团队中使用的所有基本和高级 SQL 查询,并使用 SSMS 和我们的演示数据库练习它们。

我还推荐以下练习来探索 SSMS 和新加载的数据库中的一些功能:

  • 通过从工具栏中选择**“新查询”**创建一个新的查询窗口,并将数据库从 master 更改为 AdventureWorks2019 (工具栏左下角)
  • 编写一个查询,从销售中选择 CustomerID 和 TerritoryID。客户表并执行它
  • 使用对象资源管理器(左面板)在数据库中导航不同的表、列和主键
  • 将您的 sql 查询保存在您的计算机中(作为. SQL 文件),并使用 SSMS 加载它
  • 将查询结果保存为. csv 文件(通过右键单击右下角面板的结果选项卡)

我希望这篇文章对你有所帮助,并祝你在查询中愉快!

敬请期待第二部!

如果你喜欢阅读这篇文章,并想了解更多,不要忘记 订阅 将我的故事直接发送到你的收件箱。

在下面的链接中,您还可以找到一个免费的 PDF 演示,介绍如何使用 r。

https://www.aspiringdatascientist.net/community

如何将您的 SQL 从零提高到数据科学家级别—第 2/3 部分

原文:https://towardsdatascience.com/how-to-take-your-sql-from-zero-to-data-scientist-level-part-2-3-bc1cbb48299e

SQL 列表的终极指南:了解数据科学家经常使用的基本和高级 SQL 查询

Samule 孙在 Unsplash 上的照片

简介

您是否希望按照优秀数据科学团队的标准学习 SQL?如果是这样,那你来对地方了!在 第 1 部分 中,我们设置了 SQL,并在 AdventureWorks2019 演示数据库上执行了一个简单的 SELECT 查询(涉及到 SQL 和关系数据库的理论)。在本系列的这一部分中,我们将更深入地研究 SQL,从一个简单的两行 SELECT 语句开始,一直到更复杂的查询。

第二部分

  • 用 SELECT 语句提取数据
  • 如何连接数据库中的不同表
  • 高级 SQL 语句:CASE 表达式,处理日期、cte、子查询和排名函数

第三部分

  • 查询优化、测试代码、数据科学编码最佳实践和培训计划

开始之前

*这些步骤不是遵循指南的强制要求,但是它们将允许您自己执行查询和练习 SQL

  • 打开 SSMS 并连接到 SQL server
  • 从工具栏中选择“新建查询”,查询窗口将在右侧面板打开
  • 最后,将数据库从 master 更改为 AdventureWorks2019,以将查询窗口连接到演示数据库,这样就可以开始了

连接 SSMS 的一个数据库,打开一个新的查询窗口[图片由作者提供]

👉如果你需要以上任何方面的帮助,在 第一部分 中有一个分步指南

1。在 SQL 领域,SELECT 语句是王道

Rafael Rex Felisilda 在 Unsplash 上拍摄的照片

作为一名数据科学家,您使用 SQL 的主要目的是从数据库表中提取数据。对于每个这样的查询,将使用 SELECT 语句。SELECT 语句的语法由以下六个子句组成,每个子句都旨在优化查询,以便只返回所需的数据。

选择 ( 列列表)

出自 ( 表参考)

其中 ( 过滤条件)

分组依据 ( 分组规范)

(后分组过滤条件)

订单由 ( 订单条件)

1.1 评估顺序

当执行 SELECT 语句时,每个子句都按特定的顺序进行计算。这与 SQL 的编写顺序不同(语法如上所示)。评估的顺序是引擎盖下发生的事情。您可以把它想象成一个虚拟表,随着我们从一个子句前进到下一个子句,它会不断变化,直到返回结果。对求值顺序的良好理解不仅有助于您编写更高效的查询,还能帮助初学者更快地进步。

  1. 条款中的是强制性的,首先执行。它用于在数据库中选择我们想要从中提取数据的表
  2. 然后在 WHERE 子句(如果指定了)中使用这些结果,根据某些条件过滤表中的行
  3. 然后在 GROUP BY 子句(如果指定了一个)中使用结果对表进行分组
  4. 然后,分组的结果在 HAVING 子句中使用(如果指定了一个子句,它也需要 GROUP BY)来过滤分组的行
  5. 执行完上面的最后一个子句后,结果被传递到(强制的) SELECT 子句,在那里选择列
  6. 最后,对 ORDER BY 子句进行求值(如果指定了一个子句)以对结果中的列进行排序

还值得一提的是,在 SQL 访谈中最常见的两个问题是解释 GROUP BY 和 HAVING(稍后将详细介绍)之间的区别,以及遍历 SELECT 语句的求值顺序。

1.2 从中选择&

让我们从最简单的 SELECT 语句开始,只使用两个强制子句 SELECT 和 FROM:

  • FROM 子句中的表引用采用[database]的形式。[模式]。[表格]。我们可以省略[database]部分,因为我们将在示例中仅使用 AdventureWorks2019 数据库,并且我们已经连接(您可以将模式视为“相似”表的容器)
  • DISTINCT 和 TOP 关键字的开销很大(就内存而言),所以要小心有选择地使用它们
---=================================
--- Select all columns and rows
---=================================
SELECT *
FROM [AdventureWorks2019].[Sales].[SalesOrderHeader]---=================================
--- Return the top 10 rows and all columns
---=================================
SELECT TOP 10 *
FROM [Sales].[SalesOrderHeader]---=================================
--- Select all rows for specified columns
---=================================
SELECT[SalesOrderID],[OrderDate],[TotalDue]
FROM [Sales].[SalesOrderHeader]---=================================
--- Select distinct rows for specified columns
---=================================
SELECT DISTINCT[SalesOrderID],[OrderDate],[TotalDue]
FROM [Sales].[SalesOrderHeader]

计算列

您可以使用算术运算符或函数创建计算列。我们可以使用作为关键字来命名一个计算列或重命名结果中的现有列。

---=================================
--- Create calculated columns
---=================================
SELECT TOP 10[SalesOrderID],[TotalDue],[TotalDue] AS Total_Amount_Due,[TotalDue] * 0.8 AS Gross_Due,ROUND([TotalDue] * 0.8 , 1) AS Gross_Due_Round
FROM [Sales].[SalesOrderHeader]

空值

SQL 中的一个关键概念是空值。空值用于标记缺少的数据(没有对该单元格进行任何输入)。这不同于包含空格或零值的单元格。把它们想象成 SQL 的 NA。

聚集

您也可以使用函数创建聚合结果,如下例所示:

  • COUNT(*): 返回表格中所有行的计数
  • COUNT( ): 返回该列所有非空记录的计数
  • COUNT(DISTINCT ): 返回该列的非重复值的计数。NULL 也将被计为值之一
  • **COUNT(*)= COUNT(SalesOrderID)=**COUNT(DISTINCTSalesOrderID):**SalesOrderID 列是表的主键,因此对于行是唯一的
  • COUNT(DISTINCTCustomerID)<**COUNT(CustomerID):**CustomerID 列有重复值(一个客户可以有多个订单)
  • 您可以在此 处找到 SQL Server 聚合函数的完整列表
---=================================
--- Group results using aggr. functions
---=================================
SELECTAVG([TotalDue]) AS Sum_Total_Due,COUNT(*) AS Count_All_Records,COUNT(DISTINCT [SalesOrderID]) AS Count_Sales,COUNT([CustomerID]) AS Count_Cust,COUNT(DISTINCT [CustomerID]) AS Count_Cust_Dist
FROM [Sales].[SalesOrderHeader]

来自示例选择查询的 SSMS 结果[图片由作者提供]

我建议您练习对不同的列(有和没有 NULL)使用 COUNT 和其他聚合函数,以便更好地理解 SQL 的行为。还值得一提的是,SQL 中的语法不区分大小写。所以我们可以写 SeLeCt 或者 SELECT,coUnt 或者 COUNT,查询还是会执行。当需要提高代码可读性时,我们将使用 capital(我们将在本系列的第 3 部分中介绍编码最佳实践)。

1.3 哪里

WHERE 子句获取 FROM 子句选择的数据,并根据某种筛选条件对每一行进行评估:

  • 评估为 TRUE 的那些行将作为查询结果的一部分返回
  • 评估为未知或假的那些不包括在结果中(对于空值返回未知)

为了评估过滤条件,我们将使用谓词。还有很多,就一个一个来说吧。

比较谓词

这些是你在数学中用来比较的常用符号。

---=================================
--- Equal 
---=================================
SELECT *
FROM [Sales].[SalesOrderHeader]
WHERE [TerritoryID] = 6---=================================
--- Not Equal
---=================================
SELECT[SalesOrderID],[TerritoryID]
FROM [Sales].[SalesOrderHeader]
WHERE [TerritoryID] <> 6---=================================
--- Greater or equal
---=================================
SELECT[SalesOrderID],[TerritoryID]
FROM [Sales].[SalesOrderHeader]
WHERE [TerritoryID] >= 6

BETWEEN 谓词

BETWEEN 谓词与 AND 关键字结合使用,用于标识可作为搜索条件包含的值范围。

---=================================
--- Filter by numerical range
---=================================
SELECT[SalesOrderID],[TerritoryID]
FROM [Sales].[SalesOrderHeader]
WHERE [TerritoryID] BETWEEN 2 AND 6---=================================
--- Filter by date range
---=================================
SELECT COUNT(*)
FROM [Sales].[SalesOrderHeader]
WHERE [OrderDate] BETWEEN '2013-06-01' AND '2013-06-30'

在谓词中

确定列值是否与列表中的任何值匹配。

---=================================
--- Filter by values in a list
---=================================
SELECT[SalesOrderID],[TerritoryID]
FROM [Sales].[SalesOrderHeader]
WHERE [TerritoryID] IN (2, 3, 6)

LIKE 谓词

如果说有哪个谓词可以好玩,那就是 LIKE 谓词。使用 LIKE 谓词,您可以指定仅与存储在数据库中的值相似的值(以下示例中使用的通配符%,因供应商而异)。

---=================================
--- Values that start with 43
---=================================
SELECT TOP 5[SalesOrderID]
FROM [Sales].[SalesOrderHeader]
WHERE [SalesOrderID] LIKE '43%'---=================================
--- Values that contain 43
---=================================
SELECT COUNT(DISTINCT [CustomerID])
FROM [Sales].[SalesOrderHeader]
WHERE [SalesOrderID] LIKE '%43%'

为空

正如我们之前所讨论的,使用普通谓词,空值将总是被评估为未知,因此不会返回任何内容。所以我们需要另一个返回 true 或 false 的谓词。因此,SQL 提供了 IS NULL 条件。

---=================================
--- Select only values with NULL
---=================================
SELECT [SalesOrderID],[CurrencyRateID]
FROM [Sales].[SalesOrderHeader]
WHERE [CurrencyRateID] IS NULL

多重比较

如果存在多个搜索条件,则使用逻辑运算符(OR、AND、NOT)将它们组合起来。执行优先级的规则是,括号> NOT > AND > OR。注意抽查多重比较的结果(在下面的例子中,版本 1 将通过改变括号给出与版本 2 不同的结果)。

---=================================
--- Version 1
---=================================
SELECT *
FROM   [Sales].[SalesOrderHeader]
WHERE 
[totaldue] < 3000 AND ([TerritoryID] < 2 OR [TerritoryID] > 7) ---=================================
--- Version 2
---=================================
SELECT *
FROM   [Sales].[SalesOrderHeader]
WHERE 
([totaldue] < 3000 AND [TerritoryID] < 2) OR [TerritoryID] > 7

1.4 分组依据

GROUP BY 子句用于对数据(从 from 或 WHERE 传递)进行分组,其方式与您在 excel 中使用透视表或在 r 中使用 dplyr 中的 group_by()的方式相同,使用不带聚合的 GROUP BY 将返回所选列的值的不同组合(与使用 distinct 的结果相同)。

---=================================
--- Return distinct values in TerritoryID
---=================================
SELECT[TerritoryID]
FROM [AdventureWorks2019].[Sales].[SalesOrderHeader]
GROUP BY [TerritoryID]---=================================
--- Return sum of TotalDue by TerritoryID
---=================================
SELECT[TerritoryID],SUM([TotalDue]) AS Sum_Total_Due
FROM [AdventureWorks2019].[Sales].[SalesOrderHeader]
GROUP BY [TerritoryID]

总计和小计

我们还可以使用 ROLLUP 操作符获得总计或小计(占用大量内存)。正如您在下面的示例(左图)中所看到的,总数表示为 NULL。我们可以通过使用 ISNULL 函数将它替换为一个新值来解决这个问题。

---=================================
--- Return sum of TotalDue by TerritoryID with total
---=================================
SELECT[TerritoryID],SUM([TotalDue]) AS Sum_Total_Due
FROM [AdventureWorks2019].[Sales].[SalesOrderHeader]
GROUP BY ROLLUP([TerritoryID])---=================================
--- Return sum of TotalDue by TerritoryID with total (labeled as 99)
---=================================
SELECTISNULL([TerritoryID], 99) AS TerritoryID,SUM([TotalDue]) AS Sum_Total_Due
FROM [Sales].[SalesOrderHeader]
GROUP BY ROLLUP([TerritoryID])

在 SSMS 使用 GROUP BY with ROLLUP 得到的结果[图片由作者提供]

1.5 拥有

HAVING 子句与 WHERE 完全相同,但只能应用于 GROUP BY 之后。换句话说,WHERE 用于筛选 FROM 的结果,而 HAVING 用于筛选 GROUP BY 的结果。记住虚拟表从一个子句传递到下一个子句的类比。

---=================================
--- Filter using column
---=================================
SELECT[TerritoryID],SUM([TotalDue]) AS Sum_Total_Due
FROM [Sales].[SalesOrderHeader]
GROUP BY [TerritoryID]
HAVING [TerritoryID] = 1---=================================
--- Filter using aggregate
---=================================
SELECT[TerritoryID],SUM([TotalDue]) AS Sum_Total_Due
FROM [Sales].[SalesOrderHeader]
GROUP BY [TerritoryID]
HAVING SUM([TotalDue]) >= 15000000

1.6 订购依据

好了,还有最后一个条款,幸运的是这是最简单的。我们可以使用 ORDER by 子句按升序(大多数供应商的默认设置)或降序对 SELECT 结果进行排序。

---=================================
--- Sort by ascending order
---=================================
SELECT[TerritoryID],SUM([TotalDue]) AS Sum_Total_Due
FROM [Sales].[SalesOrderHeader]
GROUP BY [TerritoryID]
ORDER BY SUM([TotalDue])---=================================
--- Combine all clauses and sort by descending order
---=================================
SELECT[TerritoryID],SUM([TotalDue]) AS Sum_Total_Due
FROM [Sales].[SalesOrderHeader]
WHERE [TerritoryID] >= 3
GROUP BY [TerritoryID]
HAVING SUM([TotalDue])  >= 15000000
ORDER BY [TerritoryID] DESC 

2.如何连接不同的表

马特·科菲尔在 Unsplash 上拍摄的照片

通常,您需要在查询中从多个表中检索信息。有四种主要类型的连接子句(尽管实际上只有 INNER 和 LEFT 连接经常使用):

  • **内部连接:**只返回两个表中都存在的记录
  • **左连接:**只返回左表中存在的记录
  • **右连接:**只返回右表中存在的记录
  • **完全外部连接:**返回两个表中的所有记录

使用维恩图可视化连接[图片由作者提供]

好的,所以连接的类型决定了从表中保留哪些记录(行)。然后,我们可以使用一个或多个共享列将表链接在一起:

  • 选择连接的类型
  • 给表取别名(在我们的例子中是 S 和 T)
  • 使用 ON 关键字指定用于连接表的共享列
---=================================
--- Inner join the sales and territory tables
---=================================
SELECTS.[TerritoryID],T.[Name]
FROM [Sales].[SalesOrderHeader] S
INNER JOIN [Sales].[SalesTerritory] T ON S.TerritoryID = T.TerritoryID---=================================
--- Left join the sales and customer tables (more complex)
---=================================
SELECTS.[TerritoryID],T.[Name],SUM([TotalDue]) AS Sum_Total_Due
FROM [Sales].[SalesOrderHeader] S
LEFT JOIN [Sales].[SalesTerritory] TON S.TerritoryID = T.TerritoryID
GROUP BY S.[TerritoryID],T.[Name]
HAVING T.[Name] IN ('Australia','United Kingdom')

处理重复

连接表时有一个主要考虑事项。当两个表之间的关系是一对多时,联接的结果将有重复项。

用一对多关系连接表[图片由作者提供]

这可能具有挑战性,并会导致错误,尤其是在涉及聚合时。我建议始终如一地验证柱子所处的水平。在上面的例子中,OrderAmount 值在订单级别(OrderID)是唯一的,但是连接的表将有重复的,并且不应该在聚合中使用(我们将在第 3 部分中讨论重复和如何对代码进行 QA 测试)。

---=================================
--- Total sales value from order table
---=================================
SELECTSUM(S.SubTotal) AS Order_Total --- correct
FROM [Sales].[SalesOrderHeader] S---=================================
--- Total sales value from order table
--- after joining with orderline table
---=================================
SELECTSUM(S.SubTotal) AS Order_Total_Dup, --- duplicatesSUM(SL.LineTotal) AS Order_Line_Total --- correct
FROM [Sales].[SalesOrderHeader] S
INNER JOIN [Sales].[SalesOrderDetail] SLON S.SalesOrderID = SL.SalesOrderID

SSMS 一对多关系中的重复示例[图片由作者提供]

3.高级 SQL 查询(我的英雄)

Erik Mclean 在 Unsplash 上拍摄的照片

最后,我还想向您展示一些作为数据科学家需要的更高级的工具。在过去的六年里,我用 SQL 编写了 1500 多个小时的代码,这些工具是我的英雄!

3.1 案例

CASE 语句允许您基于多个条件创建计算字段:

  • 语法以关键字 CASE 开始,后跟一系列 WHEN 子句,并以 END 关键字结束
  • 每个 WHEN 子句由一个条件和一个结果(如果该条件评估为真)组成(子句按照它们出现的顺序进行评估)
  • 如果这些条件都不满足,将执行 ELSE 子句(如果不使用,不匹配的值将为空)
  • ELSE 子句是可选的,但是我强烈建议您使用它来确保您的代码按预期工作
---=================================
--- CASE simple example
---=================================
SELECT[TerritoryID],CASE WHEN [TerritoryID] <= 2 THEN 'Low'WHEN [TerritoryID] BETWEEN 3 AND 5 THEN 'Mid'WHEN [TerritoryID] BETWEEN 6 AND 10 THEN 'High'ELSE 'Unknown'END AS Territory_Grouped
FROM [Sales].[SalesTerritory]
ORDER BY [TerritoryID]---=================================
--- CASE advanced
---=================================
SELECT[TerritoryID],CASE WHEN [TerritoryID] <= 2 THEN 'Low'WHEN [TerritoryID] BETWEEN 3 AND 10 THEN 'High'ELSE 'Unknown'END AS Territory_Grouped,COUNT(*) AS count_records
FROM [Sales].[SalesTerritory]
GROUP BY[TerritoryID],CASE WHEN [TerritoryID] <= 2 THEN 'Low'WHEN [TerritoryID] BETWEEN 3 AND 10 THEN 'High'ELSE 'Unknown'END
ORDER BY [TerritoryID]

使用案例陈述[图片由作者提供]

3.2 日期

作为一名数据科学家,您需要经常处理数据中的日期。这通常包括使用以下两个函数。

日期部分()

用于提取日期的特定部分,如年、周、小时等。它接受两个参数作为输入;用于提取日期部分和日期本身的度量单位。我们还可以使用 CAST 函数来更改日期列的数据类型(在下面的示例中,我们将其从 datetime 更改为 date)。

---=================================
--- Extracting parts from dates
---=================================
SELECTCAST(OrderDate AS DATE) AS OrderDate,DATEPART(YEAR, OrderDate) AS year_from_date,DATEPART(QUARTER, OrderDate) AS quarter_from_date,DATEPART(MONTH, OrderDate) AS month_from_date
FROM [Sales].[SalesOrderHeader]

DATEDIFF()

用于计算两个日期之间的差异。它接受三个参数作为输入;度量单位、开始日期和结束日期(从左到右)。

---=================================
--- Calculating difference between dates
---=================================
SELECTCAST(OrderDate AS DATE) AS OrderDate,CAST(ShipDate AS DATE) AS ShipDate,DATEDIFF(DAY, OrderDate, ShipDate) AS date_diff_days
FROM [Sales].[SalesOrderHeader]
ORDER BY date_diff_days DESC

在 SSMS 处理日期[图片由作者提供]

3.3 CTE 和子查询

您会在大多数讲授 SQL 的教科书中找到子查询,但这不是我在本节中添加它们的原因。我的理由是,我想展示它们的缺点,以及使用 cte(公共表表达式)如何会更好。

子查询

子查询是嵌套在另一个 SELECT 语句中的 SELECT 语句。它们也可以用在 SELECT 语句的 FROM 子句中。无论哪种方式,子查询的结果都将在主 SELECT 语句中使用。让我们来看一些例子。

---=================================
--- Using nested subqueries
---=================================
SELECT COUNT([CustomerID])
FROM [Sales].[SalesOrderHeader]
WHERE [CustomerID] IN ( --- nested subquery starts hereSELECT [CustomerID]FROM [Sales].[Customer]WHERE [TerritoryID] = 4
)---=================================
--- Using subqueries in the FROM
---=================================
SELECT COUNT(a.[CustomerID]) AS Count_Cust
FROM ( --- subquery starts hereSELECT *FROM [Sales].[SalesOrderHeader]WHERE [TerritoryID] = 4
) a -- you need to add an alias at the end

CTEs

尽管 cte 具有与子查询相同的功能(创建一个临时结果,然后可以在主选择中使用),但它们还有三个主要优点:

  • 可在查询的不同部分重用
  • 易于验证和理解(可读性更强)
  • cte 通常比子查询更有效
---======================
--- Using a single CTE
---======================
WITH 
select_customers AS (SELECT *FROM [Sales].[SalesOrderHeader]WHERE [TerritoryID] = 4
)
SELECT COUNT([CustomerID])
FROM select_customers---======================
--- Using multiple CTEs
---======================
WITH 
select_customers AS (SELECT [CustomerID]FROM [Sales].[Customer]WHERE [TerritoryID] = 4
),
select_orders AS (SELECT CAST(OrderDate AS DATE) AS OrderDate,[SalesOrderID],[CustomerID],[SubTotal]FROM [Sales].[SalesOrderHeader]WHERE [SubTotal] >= 2000
)
SELECTc.[CustomerID],SUM([SubTotal]) AS Sum_Total_Due
FROM select_customers c
INNER JOIN select_orders oON c.[CustomerID] = o.[CustomerID]
GROUP BY c.[CustomerID]
ORDER BY Sum_Total_Due

在决定是使用 CTE 还是子查询时,考虑查询的复杂性、性能要求和查询的可读性非常重要。通常,cte 是多次使用的复杂查询的好选择,而子查询是只使用一次的简单查询的好选择。

3.4 排名功能

排名(窗口)函数是文章中最复杂的部分。然而,你将需要在你的数据科学查询中使用它们,另外,这些经常在面试中被问到。

顾名思义,它们是用来对行进行排序的,但是每种方法都略有不同。但是我想得太多了。让我们首先用下面的例子来检查语法:

  • 我们将使用 RANK() 作为 SalesOrderHeader 表中的排名函数
  • 我们希望对数据进行分区,这样 RANK()每次都不会应用于整个数据集,而是应用于行的子集。在我们的例子中,我们使用了由 CustomerID 划分的分区,因此排名被分别应用于每个客户
  • 最后,我们希望根据 SubTotal 列(即订单的价值)对每个客户的订单进行排序,从 1 开始表示最高支出,依此类推。这就是人们熟悉的的命令发挥作用的地方
---=================================
--- Using the rank function
---=================================
SELECT [CustomerID],[SalesOrderID],[SubTotal],RANK() OVER(PARTITION BY [CustomerID] ORDER BY [SubTotal] DESC) AS Ranking
FROM [Sales].[SalesOrderHeader]
ORDER BY [CustomerID], [SubTotal] DESC

SQL 中 RANK()如何工作的示例[图片由作者提供]

作为一名数据科学家,您将经常使用 SQL 中的四个排名函数。让我们使用来自 SalesOrderHeader 表的数据来看看它们之间的区别。

---=================================
--- Example using all ranking functions
---=================================
SELECT [CustomerID],[SalesOrderID],CAST(OrderDate AS DATE) AS OrderDate,RANK() OVER(PARTITION BY [CustomerID] ORDER BY [OrderDate] DESC) AS [RΑΝΚ],DENSE_RANK() OVER(PARTITION BY [CustomerID] ORDER BY [OrderDate] DESC) AS [DENSE_RANK],ROW_NUMBER() OVER(PARTITION BY [CustomerID] ORDER BY [OrderDate] DESC) AS [ROW_NUMBER],NTILE(2) OVER(PARTITION BY [CustomerID] ORDER BY [OrderDate] DESC) AS [NTILE]
FROM [Sales].[SalesOrderHeader]
WHERE [CustomerID] = 11078
ORDER BY [CustomerID], [OrderDate] DESC

排名函数如何不同的示例[图片由作者提供]

  • ROW_NUMBER() :为结果集中的每一行分配一个唯一的序列号
  • RANK(): 返回结果集分区中每行的排名。在平局的情况下,特定行的等级是 1 加上它前面的等级值的数量
  • DENSE_RANK() :返回结果集分区中每行的排名。在出现平局的情况下,特定行的排名是 1 加上在它之前的不同排名值的数量
  • NTILE(n): 将结果集中的行分成 n 个相等的组(或平铺块),并根据每一行所属的组为每一行指定一个等级。该函数可用于计算中位数和其他百分位数

就这样,我们结束了。我们已经谈了很多,所以我相信祝贺已经准备好了!🚀🚀🚀

我还提供了一些练习来帮助你提高 SQL 技能。

  1. 查找到期总金额(SalesOrderHeader。TotalDue),按月份和年份分组(SalesOrderHeader。订单日期)。然后过滤行,只保留一月到三月。最后,重命名列,并按年份和月份对结果进行排序(降序)
  2. 求平均金额(SalesOrderDetail )。 LineTotal),按年份分组(SalesOrderHeader。订单日期)和产品名称(产品。姓名)
  3. 尝试练习 2,使用 cte
  4. 在练习 2 中,使用 ROW_NUMBER()只保留每月表现最好的前 5 个产品(LineTotal aggregate)。使用 cte
  5. 使用 CASE 语句创建一个新的计算字段,该字段拆分到期总金额(SalesOrderHeader。TotalDue)分成五个桶(低、中等。),然后对于每个桶,求平均运费成本(SalesOrderHeader。运费)

我希望这篇文章对你有所帮助,并祝你在查询中愉快!

请继续关注第 3 部分!

如果你喜欢阅读这篇文章,并想了解更多,别忘了订阅https://medium.com/@alex.vamvakaris.ds/subscribe,让我的故事直接发送到你的收件箱。

在下面的链接中,您还可以找到一个免费的 PDF 演示,介绍如何使用 r。

**https://www.aspiringdatascientist.net/community **

如何将您的 SQL 从零提高到数据科学家级别—第 3/3 部分

原文:https://towardsdatascience.com/how-to-take-your-sql-from-zero-to-data-scientist-level-part-3-3-fe3996059577

通过这三个简单的技巧,将您的 SQL 编码技能提升到一个新的水平

洛伦佐·埃雷拉在 Unsplash 上的照片

介绍

欢迎来到本系列的最后一部分。在前两部分中,我们建立了基本和高级 SQL 查询的坚实基础,并使用 SSMS 和演示数据库 AdventureWorks 来执行它们。在这最后一部分中,我们将介绍将您的 SQL 提升到下一个级别的一系列技能。这些都是同等重要的,如果不是更重要的话,比简单地知道如何写 SQL,因为它们将把你的查询变成一个准确的,易读的可复制的资产!

第三部分

  • QA 测试您的 SQL 查询
  • SQL 查询的优化
  • 数据科学编码标准和最佳实践
  • 培训计划

👇链接到第 1 和第 2 部分

1.QA 测试您的 SQL 查询

照片由 DeepMind 在 Unsplash 上拍摄

一个常见的误解是,优秀的数据科学家对 SQL 编码的熟练程度如此之高,以至于他们从不出错,这也是我在职业生涯开始时强烈持有的观点。事实上,每个人都会犯错。即使是外科医生和飞行员也容易犯错误。根据不同的经验,错误率会有所不同,但最终,每个人都会有一天或几天不在状态。

幸运的是,有对策可以最小化这种错误。它们被称为清单!这不是一个新想法,也不是数据科学家独有的。在航空公司,每个飞行员在飞机起飞前或降落时都要进行一套相同的基本测试。类似地,您可以采取一些步骤来测试您的 SQL 查询没有返回不正确的结果(即,可以安全离开)。我在下面强调了三个主要问题。

1.1 结果的唯一性

SQL 清单中的第一项是结果的唯一性。在大多数查询中,作为一名数据科学家,您将不得不联接多个表以获得期望的结果。当两个表之间的关系是一对多时,连接的表将有重复的表。因此,在您运行的每个查询中,确保您已经检查了生成的连接表是唯一的级别(即列)。

WITH
orders as(-- unique at the SalesOrderID levelSELECT *FROM Sales.SalesOrderHeader
),
orders_detail as (-- unique at the SalesOrderDetailID levelSELECT *FROM Sales.SalesOrderDetail
)
-- unique at the SalesOrderDetailID level
SELECT *
/* SELECT COUNT(*), COUNT(DISTINCT SalesOrderDetailID)*/
FROM orders o
INNER JOIN orders_detail ol ON o.SalesOrderID = ol.SalesOrderID

在上面的例子中,你可以看到我注释掉了第 14 行,我用它来检查我的结果的级别。这个简单的查询将 COUNT(*)的结果与 COUNT(DISTINCT )进行比较,如果它们匹配,它将验证该表在该级别上是惟一的。如您所见,我添加了一个注释,指出结果和 cte 中的表的唯一性。这种做法还会使在正确的级别上连接表变得更加容易!

1.2 计算列

查询中最棘手的部分之一是计算列。这些容易出现逻辑和计算错误。有时,问题可能是该列有空值,或者您选择的排名函数没有按预期工作。其他时候,您的一些条件可能会在 CASE 语句中重叠,从而导致不正确的结果。

  • 使用几个随机挑选的记录抽查结果(特别是对于棘手的情况)
  • 始终在 CASE 语句中使用 ELSE 子句来标记不匹配的记录

正确和不正确地使用 ELSE 子句的并排查询[图片由作者提供]

CurrencyRateID 列的空记录示例[图片由作者提供]

在上面的示例中,问题是 CurrencyRateID 列的数据中存在空值。这些被错误地添加到右面板查询中的“高”组,但在左面板中使用 ELSE 语句对不匹配的条件进行了正确标记。

1.3 与基线数字的比较

最后,将查询的顶级结果与公司仪表板进行比较总是很有帮助的。这很简单,只需过滤特定日期的结果,并将其与仪表板中的结果进行比较(例如,订单数量、总支出等)。).这一部分尤其有助于仔细检查您是否遗漏了所需的健全性过滤器,例如从机器人中排除测试人员帐户或活动。

2.SQL 查询的优化

照片由马丁·杰恩伯格在 Unsplash 拍摄

出于本节的目的,我通过多次联合 SalesOrderHeader 表创建了一个新表。新表名为 SalesOrderDetail_Compiled,有 6500 万行。

2.1 限制 cte 中的记录数量

尽管这看起来非常简单明了,但在我培训分析师的经验中,这是最常被忽略的步骤。查看下面的示例,您可以看到,通过在 cte 中聚合结果,然后连接它们(右图),而不是获取所有行,连接,然后聚合(左图),我们的运行时间大大减少了。

通过首先在 CTEs 内聚合来提高性能[图片由作者提供]

2.2 避免使用非重复计数

DISTINCT 关键字是 SQL 中开销最大的关键字之一。这是有意义的,因为为了得到不同的结果,SQL 必须扫描列的每一行。当然,在某些情况下,COUNT( )和 COUNT(DISTINCT )会给出相同的结果(例如,当列是主键时)。在这种情况下,明显的建议是省略 DISTINCT 关键字。

但是对于有重复项的列该怎么办呢?在下面的示例中,我们在右侧面板中创建了一个新的二进制列。左连接中不匹配的记录将具有空值,并标记为 0,非空值标记为 1。然后我们可以取那一列的平均值。因为我们将匹配记录标记为 1,其余记录标记为 0,所以它们的平均值将给出与左侧面板中不同计数的比率相同的结果。这将有望变得更加清晰,看看下面的快照。

使用 COUNT DISTINCT 的替代方法[图片由作者提供]

在 SQL Server 中,还可以使用索引对某些列进行预扫描,从而在使用 DISTINCT 关键字时提高性能。

2.3 包装在连接和 WHERE 子句周围的函数

当面对 WHERE 子句或联接中的列包装的函数时,考虑重写查询,以便列可以保持干净。这增加处理时间的原因是 SQL 必须为列的每个值计算函数,然后过滤结果。

比较包装和不包装在列中的函数的性能[图片由作者提供]

2.4 使用 SSMS 现场查询统计

SSMS 还提供了一个非常好的工具,“实时查询统计”。您可以在工具栏上找到它,如果选择它,它将在您的结果中创建一个新的选项卡,在查询执行时实时展示您的查询,并为您提供每个节点的统计数据,以确定您代码中的瓶颈。

SSMS 直播查询统计[图片由作者提供]

3.数据科学编码标准和最佳实践

摄火热的一月在 Unsplash

每当您编写一段保存在代码库中的 SQL 代码(以及其他 SQL 脚本)时,您要么创建一项资产,要么创建一项负债。资产是一个易于理解和重新运行的脚本。相比之下,负债将是一个需要太多时间才能理解的剧本;你会迫不及待地完成它,然后转向其他东西,有时你甚至会把它扔进垃圾箱,然后从头开始(因为这比处理现有的脚本更容易)。

这就是可再生代码的意义所在。有一个我们只要有空闲时间就可以使用的附加组件不是一件好事。它是关于以一种使代码成为可再生资产的方式编写代码。这是一项资产,将增加你现在和将来的工作价值;为你自己,也为其他团队成员!那么我们能做些什么来创造资产而不是负债呢?

3.1 评论

注释是为了帮助你现在和将来的自己(以及其他任何将为你的代码工作的人)快速理解它:

  • 在大多数 DBMSs 中,可以使用双破折号开始单行注释
  • 评论你的 cte 和主要结果的独特之处
  • 添加注释以解释复杂的计算字段
  • 添加注释来解释您的查询中将来可能需要澄清的任何逻辑(过滤条件等)。)

3.2 格式

与测试你的代码相反,在格式化中,没有每个人都必须采取的必要步骤。目标是简化您的代码,使其易于阅读和理解。只要保持一致,任何能达到这一目的的格式都是可以接受的。下面你可以看到我使用的格式。

  • 关键字和子句(WHERE、DISTINCT 等)使用大写。)
  • 对列使用单制表符缩进,并在 CTE 内选择
  • 使用 cte 代替子查询
  • 使用空格来分隔查询中的子句、谓词和表达式等元素

3.3 模块化(cte)

使用 cte 代替子查询也是提高代码可重复性的一个好步骤。下面的示例在左侧面板上显示了代码(使用子查询,没有注释,没有格式化),在右侧面板上显示了它的可复制副本。

编写可重现 SQL 代码的示例[图片由作者提供]

4.培训计划

照片由你好我是尼克在 Unsplash

至此,我们进入了三部分系列的最后一部分!🚀🚀

在我的 SQL 之旅中,最大的困难是找到我需要知道的东西并实践它。我让这个系列自我维持,因为你将会有你需要的所有弹药来开始练习。这并不是说我们涵盖了 SQL 中的所有函数或所有子句和功能,而是说我们涵盖了开始您的旅程所需的所有内容。如果在你的道路上,你需要找到一个不同的功能,我们还没有涵盖,我相信,现在,你已经有了一个坚实的基础,可以自己抓住那条鱼。网上也有很多免费资源可以满足你的特殊需求,但我个人最喜欢的是 W3schools 和【SQLServerTutorial.Net T3。

对于你的练习课,我也推荐以下:

  • 在线搜索 SQL 面试问题,并尝试使用 AdventureWorks2019 和 SSMS 解决这些问题
  • 一两个月内,每周至少练习几个小时的 SQL,这样你就可以下意识地开始考虑用 SQL 写作了

我希望这篇文章对你有所帮助,并祝你在查询中愉快!

如果您有任何问题或需要进一步的帮助,请随时在下面评论,我会及时回答。

保持联系

如果你喜欢阅读这篇文章并想了解更多,别忘了订阅https://medium.com/@alex.vamvakaris.ds/subscribe将我的故事直接发送到你的收件箱。

在下面的链接中,您还可以找到一个免费的 PDF 演示,介绍如何使用 r。

**https://www.aspiringdatascientist.net/community **

如何在现实世界中测试 ML 模型

原文:https://towardsdatascience.com/how-to-test-ml-models-in-the-real-world-e83bf223d340

从标准 ML 度量到生产

墨西哥城圣Á天使(图片作者)

你多久在 Jupyter 笔记本上测试一次 ML 模型,得到好的结果,但是仍然不能说服你的老板立即使用这个模型?

或者,也许你设法说服了她,并把模型投入生产,但你没有看到对业务指标的任何影响?

幸运的是,有更好的方法在现实世界中测试 ML 模型,并让每个人(包括你)相信它们为企业增加了价值。

在本文中,您将了解这些评估方法是什么,如何实现它们,以及何时应该使用每种方法。

标准 ML 评估指标的问题

我们,数据科学家和 ML 工程师,在我们的本地开发环境中开发和测试 ML 模型,例如,Jupyter 笔记本。

根据我们试图解决的问题类型,我们使用标准的 ML 评估指标:

  • 如果这是一个回归问题,我们打印的东西,如均方差,胡伯损失等。
  • 如果是分类问题,我们打印混淆矩阵、准确度、精确度、召回率等。

我们将数据拆分为一个训练集和一个测试集,其中前者用于训练模型(即找到模型参数),后者用于评估其性能。训练集和测试集是不相交的,以保证我们的评估指标不会有偏差和过于乐观。

问题是,这些数字对我们周围的非 ML 人员几乎没有意义,包括那些最终发号施令并优先考虑哪些软件进入生产的人,包括我们的 ML 模型。

换句话说,这不是测试 ML 模型并让其他人相信它们有效的最佳方式。

为什么会这样呢?

因为两个原因:

  1. 这些指标不是业务指标,而是抽象的。
  2. 不能保证一旦部署,您的 ML 将根据您的标准度量按预期工作,因为在生产中许多事情可能出错。

最终,为了测试 ML 模型,您需要在生产中运行它们并监控它们的性能。然而,遵循将模型直接从 Jupyter 笔记本转移到生产的策略远非最佳。

这个原则适用于任何软件,但是对于 ML 模型尤其重要,因为它们非常脆弱。

接下来的问题是,我们如何安全地走从本地标准度量到生产的道路?

在直接投入生产之前,你至少可以做三件事:

  • 回溯测试您的模型
  • 影子部署您的模型
  • A/B 测试您的模型

它们代表了对模型进行正确评估的渐进步骤,可以帮助您和团队安全地部署 ML 模型,并为业务增加增值。

让我们用一个例子来看看这些评估方法是如何工作的。

方法 1:回溯测试您的 ML 模型

回溯测试是一种评估 ML 模型的廉价方法,可以在开发环境中实现。

为什么便宜?

因为

  • 您只使用历史数据,因此您不需要比现有数据更多的数据。
  • 您不需要经历一个部署过程,这可能需要时间和多次迭代才能正确完成。

回溯测试背后的想法非常简单:

你选择一个过去的日期 D ,作为你用来训练/测试你的 ML 模型的数据和你用来估计假设模型如果被用来采取行动会对业务指标产生的影响的数据之间的截止日期。

回测你的 ML 模型(图片由作者提供)

例如,假设您在一家金融贸易公司担任 ML 开发人员。

该公司管理不同资产(股票、债券、密码、商品……)的投资组合。给定所有这些资产的大量价格数据,你认为你可以建立一个 ML 模型,该模型可以很好地预测价格变化,即每种资产的价格在第二天是上涨还是下跌。

使用这种预测 ML 模型,公司可以调整其投资组合头寸,并最终提高其盈利能力。

你想要建立的模型本质上是一个三类分类器,其中

  • 如果第二天的价格高于今天,目标是***up***,如果价格保持不变(或非常接近),目标是***same*** ,如果价格下跌,目标是***down***
  • 这些特征是静态变量,如资产类型,以及行为变量,如过去 N 天的历史波动性、价格趋势和相关性。

您在本地环境中开发模型,并打印标准分类指标,例如准确性。

为了简单起见,让我们假设这 3 个类在您的测试集中完全平衡,这意味着每个类upsamedown都占 33.333%。

而你的测试精度是34%

预测金融市场的变动是极其困难的,如果你总是预测相同的类别,我们的模型精度高于你得到的基准精度。

事情看起来很有希望,我们告诉我们的经理,我们应该马上开始使用这个模型。

我们经理,一个非 ML 的人,在这个行业已经有一段时间了,看着数字问:

“你确定模型管用吗?它会比目前的策略赚更多的钱吗?”

这可能不是你所期望的答案,但对你来说很遗憾,这是最常见的答案之一。当你向公司里发号施令的非 ML 人员展示这些指标时,你通常会得到一个否定的答案。因此,你需要更进一步,证明你的模型会产生更多利润。

你可以通过回溯测试做到这一点。

您选择截止日期 *D,*例如,两周前,并且

  • 使用到第 d 天的数据训练您的 ML 分类器。
  • 如果我们使用模型预测来决定是否买入、持有或卖出我们的每一个头寸,计算从 D 日到今天投资组合的每日损益。

回溯测试你基于 ML 的交易策略(图片由作者提供)

如果你的回溯测试显示负的结果,意味着你的投资组合会产生亏损,你回到起点。相反,如果投资组合在回溯测试期间的利润是正的,你回到你的经理那里:

“回溯测试显示结果为正,让我们开始使用模型”

她回答道

“我们一步一步来。让我们首先部署它,并确保它在我们的生产环境中实际工作。”

这就引出了我们的下一步评估。

方法 2:生产中的影子部署

对于用于训练 ML 模型的数据和在推理时发送给模型的数据之间的微小差异,ML 模型非常脆弱。

例如,如果模型中有一个特征:

  • 在你的训练数据中几乎没有缺失值,但是
  • 在推理时几乎总是不可用的(因此会丢失)

您的模型在推理时的性能将会下降,并且比您预期的更差。换句话说,标准评估指标和回溯测试结果几乎总是模型真实性能的上限。

因此,您需要更进一步,在模型实际用于生产时对其进行测试。

一种安全的方法是使用**影子部署,**部署模型并用于预测(在这种情况下是资产价格变化),但其输出不用于采取行动(即重新平衡投资组合)。

模型的影子部署

N 天后,我们查看模型预测,以及如果我们使用模型采取行动,投资组合的利润会如何。

如果假设的业绩是负面的(即亏损),我们需要回到我们的模型,并试图了解哪里出了问题,例如

  • 发送给模型的数据与训练数据中的数据有很大不同吗?比如缺少参数?还是不同的范畴特征?
  • 回溯测试时期是一个非常平静和可预测的时期吗,而今天的市场条件非常不同?
  • 我们之前运行的回溯测试中有错误吗?

如果假设利润为正,我们得到另一个信号,表明我们的模型在起作用。所以你周五回去对你的老板说:

“如果我们一直在使用这个模型的话,这个星期就会产生利润。让我们开始使用它,来吧”。

她回答说,

“你没看到我们投资组合本周的表现吗?非常好。你的模型更好还是更差?”

你花了整整一周的时间专注于现场测试,甚至忘记了检查实际表现。

现在,你看这两个数字:

  • 本周的实际投资组合表现
  • 你的模型的假设性能

而你的结论是你的数字略高于实际表现。这对你来说是个好消息!所以你跑回去告诉你的经理这个好消息。

她是这样回答的:

“让我们下周进行一次 A/B 测试,以确保这个 ML 模型比我们现在拥有的更好”

你现在处于爆发的边缘。所以你会问:

“您还需要看到什么才能相信这个 ML 模型更好?”

她说:

【实际货币】

你休假一周,休息两天,这是你应得的。

方法 3: A/B 测试您的模型

到目前为止,我们所有的评估要么

  • 太抽象了,就像34%一样精确
  • 或者假设。回溯测试和影子部署都没有产生实际的金钱。我们估算了利润。

我们需要比较实际成本和实际成本,以决定我们是否应该使用我们新的基于 ML 的策略。这是测试 ML 模型的最终方法,没有人可以反驳。

为此,我们决定从周一到周五进行一次 A/B 测试

下周一,我们将资产组合随机分为:

  • 一个对照组(A ),例如 90%的市场价值
  • 测试组(B),例如剩余 10%的市场价值

控制组 A 将根据公司当前使用的策略进行再平衡。测试组 B 将使用我们基于 ML 的策略重新平衡。

测试我们的 ML 模型(图片由作者提供)

每天我们监控 2 个子投资组合的实际利润,周五我们停止测试。

当我们将基于 ML 的系统的总利润与现状进行比较时,可能会发生 3 种情况。也

  • 现状比你的 ML 系统表现好太多了。在这种情况下,你将很难说服你的经理,你的战略应该保持活力。
  • 两个子投资组合的表现非常相似,这可能会让你的经理将测试延长一周,看看是否有任何显著差异。
  • 或者,你的 ML 系统明显超出了现状。在这种情况下,你有一切优势来说服公司的每个人,你的模式比现状更好,至少应该用于总资产的 10%,如果不是更多的话。在这种情况下,谨慎的做法是逐步增加这种基于 ML 的策略下管理的资产的百分比,每周监控业绩。

经过 3 周漫长的起伏,你终于得到了一个评估指标,可以让每个人(包括你)相信你的模型为企业增加了价值。

包装它

下次你发现很难让你周围的人相信你的 ML 模型是有效的,记住你可以用来测试 ML 模型的 3 个策略,从不太有说服力到更有说服力,

  • 回溯测试
  • 生产中的影子部署
  • A/B 测试

从 ML 开发到生产的道路可能是艰难和令人沮丧的,尤其是在没有可靠的 A/B 测试系统的小公司和初创公司。

测试 ML 模型有时很繁琐,但这是值得的。

相信我,如果你使用真实世界的评估指标来测试 ML 模型,你会成功的。

想支持我吗?

你喜欢阅读和学习现实世界中的 ML、数据科学和自由职业吗?

无限制地访问我在 Medium 上发布的所有内容,并支持我的写作。

👉🏽今天使用我的 推荐链接 成为会员。

https://pau-labarta-bajo.medium.com/membership

👉🏽订阅 datamachines 简讯

👉🏽关注我 推特LinkedIn

祝你愉快🤗

避寒胜地

如何测试熊猫 ETL 数据管道

原文:https://towardsdatascience.com/how-to-test-pandas-etl-data-pipeline-e49fb5dac4ce

满怀期望地测试您的熊猫 ETL 数据管道

照片由seli̇m·阿尔达·埃尔伊尔马兹在 Unsplash 上拍摄

介绍

构建强大的数据管道绝非易事。构建数据管道时出现的常见问题包括“我如何知道我的数据管道是否在做它应该做的事情?”以及“我能信任我的数据管道的输出吗?”。

这就是在我们的数据管道的输出上构建和执行测试有所帮助的时候。如果数据管道输出通过了一系列全面的测试,我们就可以相当有把握地认为数据管道正在按照预期的方式工作。一种常见的方法是对输出数据执行断言。然而,创建处理大量场景的断言是一项单调乏味的任务。在本文中,我们将通过一个例子来说明如何利用 python 的 Great Expectations [1]库及其现成的数据断言来执行这样的测试。

设置

以下设置用于该示例。

  1. 虚拟代码
  2. python 3.9
  3. pip install great_expectations==0.15.22
  4. pip install Pandas==1.4.3
  5. 数据集:泰坦尼克号[2]

例子

在本节中,我们将探索在 VSCode 中使用 Jupyter Notebook 创建期望和期望套件的基础。

什么是期望?

期望是对数据的断言。本质上,我们是在检查数据是否是我们所期望的。这里有一些期望的例子。

expect_column_values_to_be_not_nullexpect_column_values_to_be_uniqueexpect_column_values_to_match_regexexpect_column_median_to_be_betweenexpect_table_row_count_to_be_between

期望的名字很好地描述了期望的作用。伟大的期望伴随着丰富的现成期望。您还可以通过创建自定义期望来扩展 Great Expectation 的功能。

什么是期望套件?

期望套件仅仅是期望的集合。

浏览数据

**File: explore.ipynb**

我们将在下面的例子中使用 Titanic[2]数据集。让我们快速浏览一下数据集。我们有两组数据—训练和测试。

#explore.ipynbimport pandas as pddf_train = pd.read_csv('path/to/data/titanic-train.csv')
df_train.head()

作者图片

df_train.info()

作者图片

df_test = pd.read_csv('path/to/data/titanic-test.csv')
df_test.head()

作者图片

df_test中的列与df_train相同,只是少了Survived列。

数据处理

File: pipeline.py

在本节中,我们执行简单的数据处理步骤。pipeline.py由两个函数process_datarun_pipeline组成。

#pipeline.py
import pandas as pddef process_data(df: pd.DataFrame) -> pd.DataFrame:df_output = (df.drop(columns = ['Name', 'Ticket']).rename({i:i.lower() for i in df.columns.to_list()}, axis = 1).assign(age = lambda x: x.age.fillna(x.age.mean()).astype('int')))return df_outputdef run_pipeline(input_path: str, output_path: str, save = True) -> pd.DataFrame:df = pd.read_csv(input_path)df_processed = process_data(df)if save:df_processed.to_csv(output_path, index = False)return df_processed

process_data执行以下数据处理步骤:

  1. 删除NameTicket
  2. 小写所有列名
  3. 用平均值填充缺失的Age

run_pipeline将数据读入 Pandas 数据帧,在数据帧上调用process_data并返回处理后的数据帧。

作者图片

创造期望和套件

File: create_expectations.ipynb

在本笔记本中,我们创建了期望和期望套件来验证我们管道的输出。提出一套全面的检查是一个反复的过程。它需要对数据和领域的理解。首先,尝试执行探索性数据分析,并与领域专家交流,以了解数据是如何收集的,数据字段的含义以及如何利用数据管道的输出。

主要目标是:( a)检查数据管道是否正确处理了数据;( b)确定是否存在任何明显的数据质量问题。

创建的期望将验证是否:

  1. 存在指定的列
  2. age列中有空值
  3. passengerid列中的值不同
  4. 如果gender栏中有除“男性”和“女性”以外的其他值

导入库

import great_expectations as ge
import pandas as pd
import json
import pipeline

运行管道

input_path = 'path/to/data/titanic-train.csv'
output_path = 'path/to/data/titanic-train-processed.csv'df = pipeline.run_pipeline(input_path, output_path)
gdf = ge.from_pandas(df)

df包含已处理的数据帧,并被转换为great_expectations.dataset.pandas_dataset.PandasDataset,允许将远大前程方法应用于熊猫数据帧。下图显示了数据帧处理后的结果。

gdf.head()

创造期望

让我们使用expect_table_columns_to_match_set方法验证表输入表列名是否正确。我们提供预期的列名,并检查数据帧中的列名是否与我们提供的相匹配。

expected_columns = \\['passengerid', 'survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare', 'cabin', 'embarked']
gdf.expect_table_columns_to_match_set(column_set = expected_columns)

运行上面的代码会返回下面的输出。"success":true表示测试已通过。

# output
{"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"result": {"observed_value": ["passengerid","survived","pclass","sex","age","sibsp","parch","fare","cabin","embarked"]},"meta": {},"success": true
}

由于我们已经在数据处理步骤中进行了插补,age列不应包含任何空值。我们可以使用expect_column_values_to_not_be_null来验证这一点。

gdf.expect_column_values_to_not_be_null(column = 'age')#output
{"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"result": {"element_count": 891,"unexpected_count": 0,"unexpected_percent": 0.0,"unexpected_percent_total": 0.0,"partial_unexpected_list": []},"meta": {},"success": true
}

passengerid列包含每个乘客的唯一标识符。由于数据集中的每一行都代表单个乘客的信息,所以不应该有重复的passengerid。我们可以用expect_column_values_to_be_unique方法来验证这一点。

gdf.expect_column_values_to_be_unique(column = 'passengerid')#output
{"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"result": {"element_count": 891,"missing_count": 0,"missing_percent": 0.0,"unexpected_count": 0,"unexpected_percent": 0.0,"unexpected_percent_total": 0.0,"unexpected_percent_nonmissing": 0.0,"partial_unexpected_list": []},"meta": {},"success": true
}

我们可以通过使用expect_column_values_to_be_in_set方法来验证一个列是否包含正确的值集。在这种情况下,sex列中的值只能是“男性”或“女性”。

gdf.expect_column_values_to_be_in_set(column = 'sex', value_set=['male', 'female']){"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"result": {"element_count": 891,"missing_count": 0,"missing_percent": 0.0,"unexpected_count": 0,"unexpected_percent": 0.0,"unexpected_percent_total": 0.0,"unexpected_percent_nonmissing": 0.0,"partial_unexpected_list": []},"meta": {},"success": true
}

创建期望套件

我们可以从上面的个人期望中创建一个期望套件。一个期望套件仅仅是一个期望的集合,这些期望被一起用来验证一个数据集。

expectation_suite = gdf.get_expectation_suite(discard_failed_expectations=False)

默认情况下get_expectation_suite只返回success: true的期望值。将discard_failed_expectations设置为False,以返回所有期望值。期望套件是一个字典,包含我们之前创建的 4 个期望的配置。

# expectation_suite{"ge_cloud_id": null,"expectation_suite_name": "default","expectations": [{"expectation_type": "expect_column_values_to_be_unique","kwargs": {"column": "passengerid"},"meta": {}},{"expectation_type": "expect_column_values_to_be_in_set","kwargs": {"column": "sex","value_set": ["male","female"]},"meta": {}},{"expectation_type": "expect_table_columns_to_match_set","kwargs": {"column_set": ["passengerid","survived","pclass","sex","age","sibsp","parch","fare","cabin","embarked"]},"meta": {}},{"expectation_type": "expect_column_values_to_not_be_null","kwargs": {"column": "age"},"meta": {}}],"meta": {"great_expectations_version": "0.15.22"},"data_asset_type": "Dataset"
}

期望套件可以保存为一个 JSON 文件。

with open( "my_expectation_file.json", "w") as my_file:my_file.write(json.dumps(expectation_suite.to_json_dict()))

现在我们已经创建了一个期望套件,让我们来看看如何使用期望套件来测试新的未知数据的数据管道。

验证数据

File: validate_expectations.ipynb

在这本笔记本中,我们展示了如何验证新数据集是否满足预定义的预期。我们将通过数据管道(pipeline.py)传递新数据,并根据我们之前创建的期望套件来验证数据输出。

导入库

import great_expectations as ge
import pandas as pd
import json
import pipeline

让我们把新的数据通过和以前一样的数据处理管道。

input_path = 'path/to/data/titanic-test.csv'
output_path = 'path/to/data/titanic-test-processed.csv'df = pipeline.run_pipeline(input_path, output_path)
gdf = ge.from_pandas(df)

我们创建两个函数来(a)加载期望套件和(b)根据期望套件验证数据。

def load_expectation_suite(path: str) -> dict:"""Load expectation suite stored in JSON formatand convert into dictionary. Args:path (str): path to expectation suite json file Returns:dict: expectation suite""" with open(path, 'r') as f:expectation_suite = json.load(f) return expectation_suitedef great_expectation_validation(df: pd.DataFrame,expectation_suite_path: str) -> dict:"""Run validation on DataFrame based on expecation suite Args:df (pd.DataFrame): DataFrame to validateexpectation_suite_path (str): path to expectation suite json file Returns:dict: Validation result""" expectation_suite = load_expectation_suite(expectation_suite_path)gdf = ge.from_pandas(df, expectation_suite=expectation_suite)validation_results = gdf.validate(result_format = 'SUMMARY', catch_exceptions = True) return validation_results

运行great_expectation_validation函数获取验证结果。

validation_result = \\great_expectation_validation(df = df_processed, expectation_suite_path = 'my_expectation_file.json')

validation_result是字典的形式。总体验证结果可在此处找到:

validation_result['success']# output:
# False

Fasle表示期望套件中至少有一个期望失败。True表示数据通过了预期套件中的所有测试。

通过和未通过期望的汇总统计数据可在此处找到:

validation_result['statistics']# output:
# {'evaluated_expectations': 4,
# 'successful_expectations': 3,
# 'unsuccessful_expectations': 1,
# 'success_percent': 75.0}

我们评估了 4 个期望,其中一个失败了。要查看哪些期望失败:

for r in validation_result['results']:if not(r['success']):print (f"failed: {r['expectation_config']['expectation_type']}")else:print (f"success: {r['expectation_config']['expectation_type']}")# output:
# failed: expect_table_columns_to_match_set
# success: expect_column_values_to_be_unique
# success: expect_column_values_to_not_be_null
# success: expect_column_values_to_be_in_set

由于survived列丢失,我们未能通过expect_table_columns_to_match_set

{"result": {"observed_value": ["age","cabin","embarked","fare","parch","passengerid","pclass","sex","sibsp"],"details": {"mismatched": {"missing": [**"survived"**]}}},"exception_info": {"raised_exception": false,"exception_message": null,"exception_traceback": null},"meta": {},"success": false
}

结论

为您的数据管道创建一套全面的测试有助于确保管道按预期工作。在本文中,我们演示了如何在 Great Expectations 中使用开箱即用的期望来测试您的 Pandas ETL 数据管道。

加入 Medium 阅读更多这样的故事!

参考

[1]https://greatexpectations.io/

[2] 泰坦尼克号数据集。作者:小弗兰克·哈勒尔,托马斯·卡森。许可证:公共

如何测试 PySpark ETL 数据管道

原文:https://towardsdatascience.com/how-to-test-pyspark-etl-data-pipeline-1c5a6ab6a04b

满怀期望地验证大数据管道

在 Unsplash 上由 Erlend Ekseth 拍摄的照片

介绍

Garbage in garbage out 是一个常用的表达方式,用于强调数据质量对于机器学习、数据分析和商业智能等任务的重要性。随着创建和存储的数据量不断增加,构建高质量的数据管道变得前所未有的具有挑战性。

PySpark 是为大型数据集构建 ETL 管道的常用工具。构建数据管道时出现的一个常见问题是“我们如何知道我们的数据管道正在以预期的方式转换数据?”。为了回答这个问题,我们从软件开发范例中借用了单元测试的思想。单元测试的目的是通过使用测试来检查输出是否符合预期,从而验证代码的每个组件是否按预期执行。以类似的方式,我们可以通过编写一个测试来检查输出数据,从而验证我们的数据管道是否如预期的那样工作。

例子

在本节中,我们将通过一个例子来说明如何利用 Great Expectation 来验证您的 PySpark 数据管道。

设置

此示例使用以下设置:

  1. PySpark
  2. 远大前程==0.15.34
  3. 数据砖笔记本

我们将在 Databricks 社区版中使用 Databricks 笔记本。但是,您可以自由使用任何集成开发环境和云或本地 spark 集群。

数据

我们使用的是 UCI 银行营销数据集[2],其中包含一家葡萄牙银行的直接营销活动信息。这是数据的样子。

图片作者。

理解数据对于为 PySpark 数据管道创建全面的测试至关重要。数据质量方面的常见考虑因素包括但不限于:

  • 完全
  • 一致性
  • 正确性
  • 独特性

上述每一项的可接受质量在很大程度上取决于上下文和用例。

创造期望

在本节中,我们探索并创建预期,这些预期将在后面的部分中用于测试新的未知数据。

那么什么是期望呢?期望是对数据的断言。顾名思义,我们正在验证数据是否是我们所期望的。对常见数据质量检查的预定义期望带来了巨大的期望。下面是一些预定义期望的例子。

expect_column_values_to_be_not_null
expect_column_values_tpytho_be_unique
expect_column_values_to_match_regex
expect_column_median_to_be_between
expect_table_row_count_to_be_between

这些期望的名字很好地描述了期望的表现。如果预定义的期望不符合您的需求,远大期望还允许您创建自定义期望。

进口

import great_expectations as ge
from great_expectations.dataset.sparkdf_dataset import SparkDFDataset
from pyspark.sql import functions as f, Window
import json

加载数据

我们从 csv 文件加载数据,并对数据集执行一些处理步骤:

  • job栏中的“未知”值更改为“空”
  • 创建一个“id”列,其中包含每行的唯一标识符
df = \\spark\\.read\\.format('csv')\\.option('header', True)\\.load('/FileStore/tables/bank_full.csv', sep = ';')\\.withColumn('job', f.when(f.col('job') == 'unknown', f.lit(None)).otherwise(f.col('job')))\\.withColumn('id', f.monotonically_increasing_id())

SparkDFDataset是 PySpark 数据帧的一个薄薄的包装器,它允许我们在 Pyspark 数据帧上使用大期望方法。

gdf = SparkDFDataset(df)

检查列名

让我们通过向expect_table_columns_to_match_set方法提供预期列的列表来验证 DataFrame 是否包含正确的列集。

expected_columns = ['age', 'job', 'marital','education', 'default', 'balance','housing', 'loan', 'contact','day', 'month', 'duration','campaign', 'pdays', 'previous','poutcome', 'y']
gdf.expect_table_columns_to_match_set(column_set = expected_columns)

运行上面的代码会返回下面的输出。"success":true表示测试已通过。

# output
{"result": {"observed_value": ["age","job","marital","education","default","balance","housing","loan","contact","day","month","duration","campaign","pdays","previous","poutcome","y"]},"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"meta": {},"success": true
}

检查分类栏中的值

我们可以使用expect_column_values_to_be_in_set方法检查分类列是否包含意外数据。我们期望marital列只包含以下值singlemarrieddivorced

gdf.expect_column_values_to_be_in_set(column = 'marital', value_set = {'single', 'married', 'divorced'})

如果marital列包含任何在值集中找不到的值,Great Expectation 将无法通过检查。

# output
{"result": {"element_count": 45211,"missing_count": 0,"missing_percent": 0.0,"unexpected_count": 0,"unexpected_percent": 0.0,"unexpected_percent_total": 0.0,"unexpected_percent_nonmissing": 0.0,"partial_unexpected_list": []},"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"meta": {},"success": true
}

检查列不包含空值

如果我们希望列不包含任何空值,我们可以使用expect_column_values_to_not_be_null方法并在参数中指定感兴趣的列。

gdf.expect_column_values_to_not_be_null(column = 'job')

在这种情况下,job列检查失败,因为该列中有空值。

{"result": {"element_count": 45211,"unexpected_count": 288,"unexpected_percent": 0.6370131162770122,"unexpected_percent_total": 0.6370131162770122,"partial_unexpected_list": [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"meta": {},"success": false
}

检查列的唯一性

Great Expectation 还提供了开箱即用的方法来检查给定列中的值是否唯一。让我们检查一下id列是否包含唯一值。

gdf.expect_column_values_to_be_unique('id')

正如我们所料,该列包含唯一的值。

# output
{"result": {"element_count": 45211,"missing_count": 0,"missing_percent": 0.0,"unexpected_count": 0,"unexpected_percent": 0.0,"unexpected_percent_total": 0.0,"unexpected_percent_nonmissing": 0.0,"partial_unexpected_list": []},"exception_info": {"raised_exception": false,"exception_traceback": null,"exception_message": null},"meta": {},"success": true
}

创建期望套件

既然我们已经创建了各种期望,我们可以将它们放在一个期望套件中。

expectation_suite = gdf.get_expectation_suite(discard_failed_expectations=False)

期望只不过是期望的集合。

#expectation_suite
{"expectations": [{"kwargs": {"column_set": ["age","job","marital","education","default","balance","housing","loan","contact","day","month","duration","campaign","pdays","previous","poutcome","y"]},"expectation_type": "expect_table_columns_to_match_set","meta": {}},{"kwargs": {"column": "marital","value_set": ["married","divorced","single"]},"expectation_type": "expect_column_values_to_be_in_set","meta": {}},{"kwargs": {"column": "job"},"expectation_type": "expect_column_values_to_not_be_null","meta": {}},{"kwargs": {"column": "id"},"expectation_type": "expect_column_values_to_be_unique","meta": {}}],"data_asset_type": "Dataset","meta": {"great_expectations_version": "0.15.34"},"expectation_suite_name": "default","ge_cloud_id": null
}

让我们以 JSON 格式保存期望套件。

# save expectation suite
with open('my_expectation_suite.json', 'w') as my_file:my_file.write(json.dumps(expectation_suite.to_json_dict()))

运行期望套件

假设我们有一组新的数据,它需要检查。我们使用之前保存的 expect suite 对新笔记本中的未知数据执行数据质量检查。

进口

import great_expectations as ge
from great_expectations.dataset.sparkdf_dataset import SparkDFDataset
import pyspark
from pyspark.sql import functions as f, Window
import json

加载数据

df = \\spark\\.read\\.format('csv')\\.option('header', True)\\.load('/FileStore/tables/bank_full_new.csv', sep = ';')\\.withColumn('job', f.when(f.col('job') == 'unknown', f.lit(None)).otherwise(f.col('job')))\\.withColumn('id', f.monotonically_increasing_id())

我们创建两个函数来(a)加载期望套件和(b)根据期望套件验证数据。

def load_expectation_suite(path: str) -> dict:"""Load expectation suite stored in JSON formatand convert into dictionary.Args:path (str): path to expectation suite json fileReturns:dict: expectation suite"""with open(path, 'r') as f:expectation_suite = json.load(f)return expectation_suitedef great_expectation_validation(df: pyspark.sql.DataFrame,expectation_suite_path: str) -> dict:"""Run validation on DataFrame based on expecation suiteArgs:df (pyspark.sql.DataFrame): DataFrame to validateexpectation_suite_path (str): path to expectation suite json fileReturns:dict: Validation result"""expectation_suite = load_expectation_suite(expectation_suite_path)gdf = SparkDFDataset(df)validation_results = gdf.validate(expectation_suite = expectation_suite, result_format = 'SUMMARY', catch_exceptions = True)return validation_results

运行验证

validation_result = \\great_expectation_validation(df = df, expectation_suite_path = 'my_expectation_suite.json')

执行检查

False表示验证失败,因为我们在期望套件中至少有一个期望失败。

validation_result['success']# output:
# False

巨大的期望也显示了成功和失败测试的数量。

validation_result['statistics']#output:
#{'evaluated_expectations': 4,
# 'successful_expectations': 2,
# 'unsuccessful_expectations': 2,
# 'success_percent': 50.0}

结论

在本文中,我们讨论了测试数据管道的重要性,并通过一个例子说明了我们如何利用 Great Expectation 来创建一套全面的测试。

加入 medium 阅读更多这样的文章!

参考

[1] 远大前程首页远大前程

[2] Moro,S., Rita,P. & Cortez,P.. (2012). Bank Marketing. UCI Machine Learning Repository. CC 乘 4.0。

如何在 Tensorflow 中标记文本和填充序列

原文:https://towardsdatascience.com/how-to-tokenize-and-pad-sequences-in-tensorflow-fcbbf2e8b3b5

用于标记化和填充文本序列的现成模板

由 Bradyn Trollip 在 Unsplash 上拍摄的照片

在本文中,我们将了解如何提取填充并将其应用于令牌序列,以使用 Tensorflow 训练深度学习模型。

我在之前的一篇文章中已经谈到了这个主题,我在那里谈到了如何将文本转换为深度学习任务的张量,但在这种情况下,重点将是如何正确格式化 Tensorflow 的令牌序列。

这种方法对于为我们的模型提供统一长度的序列(事实上是填充的)令牌序列是必不可少的。让我们看看怎么做。

数据集

我们将使用 Sklearn 提供的数据集 20newsgroups ,快速访问大量文本数据。出于演示的目的,我将只使用 10 个文本的样本,但该示例可以扩展到任何数量的文本。

数据集的示例。图片作者。

我们不会对这些文本应用预处理,因为 Tensorflow 标记化过程会自动为我们删除标点符号。

什么是标记化?

标记化意味着把一个句子简化成构成它的符号。所以如果我们有一个像*这样的句子,“嗨,我叫安德鲁。”*它的标记化版本将只是["Hello "," my "," name "," is "," Andrew ",]. "].注意,默认情况下,标记化包括标点符号。

应用标记化是将我们的单词转换为机器学习模型可以处理的数值的第一步。

通常,应用就足够了。split() 在 Python 中对一个字符串执行简单的标记化。但是,有几种标记化方法可以应用。Tensorflow 为此提供了一个非常有趣的 API,允许您定制这种逻辑。我们很快就会看到。

什么是填充?

一旦句子被标记化,Tensorflow 将返回与每个标记相关联的数值。这个通常叫做 word_index ,是一个由 word 和 index 组成的字典,。每个遇到的单词都有编号,该编号用于识别该单词。

深度学习模型通常需要统一大小的输入。这意味着不同长度的句子对我们的模型来说是有问题的。这就是填充发挥作用的地方。

我们来看两个句子及其索引序列(不包括标点符号):

  • 嗨,我叫安德鲁:[43,3,56,6]
  • 嗨,我是一名分析师,我在深度学习项目中使用 tensor flow:[43,11,9,34,2,22,15,4,5,8,19,10,26,27]

第一个(4 个元素)比第二个(14 个元素)短。如果我们以这种方式将序列输入到我们的模型中,会给我们带来一些误差。因此,序列必须被标准化,以使它们具有相同的长度

对一个序列应用填充意味着使用一个预定义的数值(通常为 0) 使较短的序列达到与最大长度的序列相同的长度。所以我们会有这个:

  • 嗨,我叫安德鲁:[0,0,0,0,0,0,0,0,0,0,43,3,56,6]
  • 嗨,我是一名分析师,我在深度学习项目中使用 tensor flow:[43,11,9,34,2,22,15,4,5,8,19,10,26,27]

现在两个序列长度相同。我们可以决定如何填充——是在序列之前还是之后插入零,直接使用 Tensorflow 的 pad_sequences 方法。

应用标记化和填充

现在,让我们在从数据语料库中提取句子后,将标记化和填充下面的代码应用于数据语料库。

应用于示例短语的标记化和填充。图片作者。

注意,代码中有 post 作为填充模式。这意味着在序列之后插入零,因此在标记值之后而不是之前拉伸向量。

以下是如何将标记化和填充应用于文本,以将其传递给 Tensorflow 上的神经网络。如果您有任何问题或顾虑,请留下评论,我一定会跟进。

下次见!👋

如何使用 DagsHub 跟踪机器学习实验

原文:https://towardsdatascience.com/how-to-track-machine-learning-experiments-using-dagshub-6c3032f96232

关于使用 DagsHub 通过实验跟踪增强机器学习模型训练管道的教程

资料来源:联合国人类住区规划署(斯科特·格雷厄姆)

目录

  1. 动机
  2. 我们如何跟踪机器学习实验?
  3. 辅导的
  4. 最后的想法

1.动机

所有的机器学习问题都是独特的。这就是为什么在建立机器学习模型时,没有一刀切的解决方案。

建立机器学习模型是一个耗时的过程,通常需要数百次迭代(实验)。每个实验都涉及筛选多个数据预处理步骤、模型架构和超参数调整,以期找到满足预期结果的理想配置。

如果你生活在一个不用担心花费在计算上的时间和金钱的世界,那么这就不是一个值得解决的问题。但这是不正确的,需要找到优化模型开发流程的方法。

一个显而易见的解决方案,一个在许多数据驱动的组织中实践的方案,是在适当的地方放置系统来跟踪实验。通过跟踪不同的配置及其结果,我们可以:

  • 设计更好的实验,由以前实验的见解驱动
  • 通过跟踪具有理想性能的配置来提高可重复性

在我们有在线学习的情况下,我们可以使用实验跟踪管道来捕捉来自概念漂移的模型退化的早期发作,允许我们将模型更好地推广到实时数据。

可以跟踪机器学习实验的系统的最终好处是提高生产率。

2.我们如何跟踪机器学习实验?

这里一个简单的解决方案是制作一个电子表格,并用它来跟踪实验。我可以想出许多原因来解释为什么这是低效的,主要是因为手动跟踪数百个参数很麻烦,用户很可能会出错和感到沮丧。

另一种选择是使用 Github,因为它毕竟是为版本控制而设计的。但是 Github 对于存储大量数据并不友好。这里的一个解决方法是使用 Git 大型文件系统(LFS),但即使这样也显示出不是管理大数据的可行解决方案。我们可以使用数据版本控制(DVC),这是一个 Python 库,有助于在 git 之外无缝存储数据和模型文件,同时保留几乎相同的用户体验,就好像它们存储在 git 中一样。然而,这需要设置云服务来存储数据,需要开发运维方面的大量专业知识。

如果我们可以使用一个平台,通过类似 Git 的命令行体验来实现这一切,那该有多好。

输入 DagsHub。

DagsHub 是一个基于开源工具的 web 平台,针对数据科学进行了优化,面向开源社区。——dagshub.com/about

换句话说,DagsHub 有一些工具,如果你是一名数据科学家或机器学习实践者,它们可以让你的生活变得简单。深入研究每个 DagsHub 功能超出了本文的范围。我更感兴趣的是演示我们如何使用 DagsHub 来记录和可视化实验。更具体地说,这个博客旨在作为一个实践教程,补充 DagsHub 文档,专注于如何通过实验跟踪优化机器学习模型构建管道。

3.辅导的

在本教程中,我们将使用 DagsHub logger 进行跟踪实验。这里的工作流程假设您对 git 和 sklearn 有基本的了解。我们将从 3.1 节和 3.2 节中的一些基本要求开始,然后在 3.3 节中演示如何使用 DagsHub 进行实验跟踪。

3.1 文件管理系统

使用 DagsHub 不需要特定的文件管理系统。我这样做只是为了创建一些连贯的东西,以便在整篇文章中容易理解。这样一来,让我们进入文件管理系统的结构,我们将在本文的其余部分使用它。

ª   model.ipynb
ª   
+---data
ª       
+---models
ª

在工作目录中,我们有 model.ipynb ,它具有生成不同模型的功能(稍后将详细介绍)。除此之外,我们在工作目录中还有两个文件夹,分别名为数据模型。在数据中,我们将拥有将要使用的数据集,并且我们的模型文件夹是一个占位符,用于保存我们将在每次实验运行期间创建的各种模型的 pickle 文件。

3.2 实验管道

在本节中,我们将构建一个函数,它可以为我们的实验生成不同的模型。我们将使用的数据集是鸢尾数据集,该数据集根据物理特征将条目分类为三类鸢尾植物中的一类。下面显示的是我在实验管道中使用的函数。

上面的代码分为三个部分。

依赖项正在导入运行该函数所需的 Python 包。

import pandas as pd
import dagshub
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.metrics import accuracy_score
import pickle

记录模型参数的函数几乎没有活动部件。

首先使用 Pandas 读取数据,然后将数据集分割成各自的要素和标注。

#reading the data    
df = pd.read_csv('data\iris.csv')    
#splitting in features and labels    
X  = df[['SepalLengthCm','SepalWidthCm','PetalLengthCm']]    
y = df['Species']

然后数据集被分成训练和测试数据,其中总数据的 30%用于使用 sklearn 的 test_train_split 进行测试。

#test train split    
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, shuffle=True, random_state=42)

接下来,我们介绍 DagsHub 记录器,用于记录模型超参数和度量。在训练集上调用模型拟合函数,并使用 Python pickle 模块保存到 models 文件夹中。

#model defnition        
model = model_type(random_state=42)        
#log the model parameters        logger.log_hyperparams(model_class=type(model).__name__)        logger.log_hyperparams({'model': model.get_params()})        #training the model        
model.fit(X_train, y_train)
y_pred = rfc.predict(X_test)        
#log the model's performances        logger.log_metrics({f'accuracy':round(accuracy_score(y_test, y_pred),3)})        
#saving the model        
file_name = model_type.__name__ + '_model.sav'        pickle.dump(model, open('models/'+ file_name, 'wb'))

我们可以使用下面的命令调用这个函数。

#running an experiment
model_run(RandomForestClassifier)

如果一切正常,我们应该有 metrics.csvparams.yml 和一个*。在型号文件夹中保存*文件。下面是要验证的文件结构。

ª   model.ipynb
ª   metrics.csv
ª   params.yml
ª   
+---data
ª       iris.csv
ª       
+---models
ª       RandomForestClassifier_model.sav

3.3 使用 DagsHub 记录器进行实验跟踪

在我们开始将文件推送到 DagsHub 之前,我们需要对 DagsHub 上的文件跟踪方式有一些基本的了解。DagsHub 使用 git 和数据版本控制(DVC)来跟踪文件。DVC 允许我们在 DVC 远程存储中存储大量数据和模型。使用轻量级跟踪存储在 DVC 远程存储器上的数据和模型。存储在 GitHub 中的 dvc 文件。换句话说,。dvc 文件保存了与存储在 GitHub 之外的数据和模型相对应的元数据。通过使用 DagsHub,我们可以存储这两个*。dvc* 文件,以及相关的数据和模型放在一个地方。

DagsHub 的操作与 Github 非常相似,也就是说,您可以使用命令行来管理 DagsHub repo。在我们开始将文件推送到 DagsHub 之前,我们需要设置一个远程存储库,并在我们的工作文件夹中初始化 git 和 DVC。

要设置 DagsHub 存储库,请在 DagsHub 仪表板上点击位于右上角的 create。

图片来自https://dagshub.com/dashboard

按照第页的说明创建存储库。除了“存储库名称”之外,您可以将大多数字段留空。

图片来自https://dagshub.com/repo/create

一旦建立了远程存储库,我们可以使用下面的命令在工作目录中初始化 git。

git init
git remote add origin https://dagshub.com/bijilsubhash/dagshub-tutorial.git

假设您已经使用 pip 安装了 DVC,我们可以通过几个额外的步骤来初始化 DVC,将 DagsHub 配置为 DVC 远程存储。

pip install dvc
dvc init
dvc remote add origin https://dagshub.com/bijilsubhash/dagshub-tutorial.dvc
dvc remote modify origin --local auth basic
dvc remote modify origin --local user bijilsubhash
dvc remote modify origin --local password your_token

上面的步骤将创建 DVC 配置文件,出于实验跟踪的目的,必须使用 git 进行跟踪。

git add .dvc .dvcignore
git commit -m 'dvc initialized'
git push -u origin master

接下来,我们可以将与我们最近的实验相关的文件推送到 git。

git add metrics.csv params.yml
git commit -m 'RandomForestClassifier'
git push -u origin master

我们可以继续将模型和数据文件添加到 Dagshub 上的 DVC 远程存储中

dvc add 'data/iris.csv' 'models/RandomForestClassifier_model.sav'
dvc push -r origin

将文件添加到 DVC 后,您会注意到几个*。dvc* 文件和*。git ignore数据模型文件夹中的文件。你也必须把它们推到 git。。我们推送到 git 的 dvc* 文件作为元数据,映射到存储在 dvc 远程存储中的相应数据和模型。

git add 'data\iris.csv.dvc' 'models\RandomForestClassifier_model.sav.dvc' 'models\.gitignore' 'data\.gitignore'
git commit -m '.dvc and .gitignore'
git push -u origin master

如果您转到 Dagshub,您会注意到所有文件都已更新,并且在存储库中可用。

从 https://dagshub.com/bijilsubhash/dagshub-tutorial[获得的图像](https://dagshub.com/bijilsubhash/dagshub-tutorial)

同时,你会注意到左上角有一个“实验”标签,这是我们使用随机森林分类器的第一个实验。每行对应一个实验,列通常是该实验的超参数、度量或元数据。

图片来自https://dagshub . com/bijilsubhash/dagshub-tutorial/experiments

您可以运行的实验数量没有限制。为了本教程的简洁,我将运行两个以上的模型(逻辑回归和支持向量机)。

下面是在运行另外两个模型并将它们推送到 DagsHub 之后,我们的工作目录中的文件结构。

ª   model.ipynb
ª   .dvcignore
ª   metrics.csv
ª   params.yml
ª   
+---data
ª       iris.csv
ª       .gitignore
ª       iris.csv.dvc
ª       
+---models
ª       RandomForestClassifier_model.sav
ª       .gitignore
ª       RandomForestClassifier_model.sav.dvc
ª       LogisticRegression_model.sav
ª       LogisticRegression_model.sav.dvc
ª       SVC_model.sav
ª       SVC_model.sav.dvc

如你所见,我们还有两个*。sav* 文件以及相关联的*。用于逻辑回归和支持向量机模型的 dvc* 文件。

在存储库中,在“实验”选项卡下,我们还可以注意到最近实验的另外两个条目。

图片来自https://dagshub . com/bijilsubhash/dagshub-tutorial/experiments

在“实验”选项卡中,您可以开始研究(可视化、比较、标记等。)每个实验的更多细节,但我会留给你自己去探索。这里有一个详细的文档的链接,它概述了你可以在“实验”标签中找到的各种特性的功能。

最后,这里是本教程中使用的 DagsHub 资源库的链接,供您参考-https://dagshub.com/bijilsubhash/dagshub-tutorial

4.最后的想法

在本文中,您将了解到使用 DagsHub 通过 git 和 DVC 进行实验跟踪的想法。虽然我们只限于 3 个实验,只有一个数据预处理管道,但您可以轻松地将此工作流扩展到数百个实验,使用多个版本的数据,所有这些都使用 DagsHub 进行无缝管理,使其成为构建机器学习模型时协作和提高生产力的理想工具。你可能已经注意到了,我们不得不分别推送 git 和 DVC,这可能看起来重复且容易出错。为了避免这个问题,我们可以使用 FastDS ,但是这是另一天的主题。

如何使用随机森林来定型回归模型

原文:https://towardsdatascience.com/how-to-train-a-regression-model-using-a-random-forest-c1cf16288f6b

对于复杂的非线性数据

图片来自 Pixabay 的像素

随机森林是一种监督机器学习算法,可用于回归和分类任务。快速回顾一下,回归模型预测连续值输出(例如价格、身高、平均收入),而分类模型预测离散值输出(例如 0 级或 1 级,一种颜色-红、蓝、绿)。

随机森林是一种基于树的算法。它的基础学习器是决策树。因此,随机森林可以被视为决策树的集合(组)。以下是随机森林的一些优点。

  • 随机森林对复杂的非线性数据建模非常有用。
  • 使用随机森林时,我们不需要进行功能扩展。
  • 它的设计是非参数化的,这意味着它只需要很少的数据假设。
  • 正如我们前面所说的,它可以用于回归和分类任务。
  • 我们可以很容易地想象随机森林中的单个决策树。阅读这篇文章,看看如何做到这一点。
  • 随机森林模型是一个白盒模型,这意味着我们可以很容易地解释它。通过使用树形图可视化单个树,我们可以很容易地显示模型如何获得特定类型的输出。
  • 通过使用 RandomForestRegressor**feature _ importances _**属性可视化特性重要性,我们可以了解模型中最重要的特性。

我不打算解释随机森林的工作原理。今天,将更多地强调随机森林在建立回归模型中的实际应用。您将获得 Python 代码的实践经验。然而,如果你也想了解随机森林是如何在幕后工作的,你可以看看我写的下面这篇文章。也是今天帖子的先决条件。

关于我们使用的数据

我们将在流行的加州房价数据集上构建一个随机森林回归模型,该数据集包含从 1990 年美国人口普查中收集的数据。以下是数据集的一些有用细节。

  • **数据集来源:**你可以在这里下载数据集。
  • **数据集许可:**该数据集受 CC0:公共领域许可。你可以在这里找到关于那种执照的更多信息。
  • 数据集参考: Pace,R. Kelley 和 Ronald Barry,稀疏空间自回归,统计和概率信,33(1997)291–297。
  • 数据集描述:该数据集包含目标在内共 9 个变量。你可以在这里找到每个变量的描述。

让我们看看整个数据集的概况。

import pandas as pddf = pd.read_csv('cali_housing.csv')
df.head()

加州房价数据集的前几行(图片由作者提供)

df.shape

这将返回(20640,9)。数据集有 20640 个观测值,包括目标在内共有 9 个变量。目标列是以$100,000 表示的“MedHouseVal”。

df.isnull().sum().sum()

这将返回 0。这意味着数据集中没有缺失值。

可视化我们的数据

并非数据集中的所有变量都用于我们的分析。我们很想知道房子的价值和它的位置之间的关系。房子的位置没有单一的变量。相反,我们使用数据集中的“纬度”和“经度”变量。它们标明了房屋的位置。房价是目标变量。我们使用“MedHouseVal”作为我们的目标变量。因此,我们的特征矩阵 X 包含“纬度”和“经度”变量的值,目标向量 Y 包含“MedHouseVal”变量的值。

X = df[['Latitude', 'Longitude']]
Y = df['MedHouseVal']

这个符号是机器学习用的。当我们可视化数据时,我们简单地将 3 个变量表示为 x、y 和 z。

x=df['Latitude']
y=df['Longitude']
z=df['MedHouseVal']

使用这三个变量,我们可以创建一个 3D 散点图,以查看房屋价值与其位置之间的关系。

3D 散点图的 Python 代码(等待加载)

房屋价值与所在位置的关系(图片由作者提供)

我们清楚地看到,这种关系是复杂的和非线性的。因此,随机森林对于建模这种类型的非线性关系非常有用。

构建基础模型

我们将首先创建 RandomForestRegressor()类的一个实例(模型),它在 Scikit-learn ensemble 子模块中可用。然后,我们用之前定义的 X 和 Y 来训练我们的模型。

在创建模型时,我们将为 RandomForestRegressor()类中最重要的超参数使用以下值。

  • n_estimators=100 (集合中的树的数量)
  • max_depth=2 (这定义了树的大小)
  • min_samples_split=2
  • random_state=1

有了这些价值观,我们就不能期待一个完美的模型。这是因为到目前为止我们还没有调优任何超参数。因此,上述值不是模型超参数的最佳值。这里,我们只创建一个基础模型,可以用来与调优后的模型进行比较(稍后会详细介绍)。

基本 RandomForestRegressor 模型的 Python 代码(等待加载)

可视化基础模型

让我们看看我们的模型是如何与数据相吻合的。

(等待加载代码)

基模(图片由作者提供)

正如你在散点图中看到的,我们的基本模型与数据不太吻合。这是因为我们还没有调整任何超参数。因此,有通过调整超参数来改进我们的模型的空间(稍后将详细介绍)。

想象森林中的一棵树

我们的基本随机森林包含 100 棵决策树(估计器)。我们可以使用下面的符号来访问每棵树。

rf.estimators_[index]

这里,索引是从零开始的。0 表示第一个决策树。

rf.estimators_[0] #First tree

现在,我们将可视化随机森林模型中的第一棵树。

可视化随机森林中第一棵决策树的 Python 代码(等待加载)

随机森林中的第一棵决策树(图片由作者提供)

因为我们已经使用了 max_depth=2 ,树并不复杂。当您增加 max_depth 的值时,树将变得复杂,并且模型将倾向于过度拟合数据。

可视化这种类型的树的主要优点是我们可以用它来解释模型。换句话说,我们可以展示特定类型的输出是如何通过模型获得的。

调整模型的超参数

有几种用于调整机器学习模型的超参数的技术。在这里,我们使用一种叫做随机搜索和 k 倍交叉验证的流行技术。

这里,我们考虑调整两个超参数。

  • **最大深度:**1–15(14 个不同的值)
  • min _ samples _ split:2–50(48 个不同的值)

我们的搜索空间是二维的。总共有 672 (14x48)种不同的超参数值组合。如果我们使用网格搜索进行超参数调优,则需要花费很多时间来完成执行过程。相反,我们使用随机搜索,只考虑随机选择的超参数组合的小样本。样本大小在 n_iter 中指定。这里我们用 n_iter=10

超参数调整的 Python 代码(等待加载)

超参数的最佳值(图片由作者提供)

使用最佳超参数值重建模型

让我们看看我们的模型是如何用最佳超参数值拟合数据的。为此,首先,我们需要构建相同的随机森林模型,但这次使用最佳超参数值。

调优的 RandomForestRegressor 模型的 Python 代码(等待加载)

可视化调整后的模型

现在,我们用调整后的模型创建散点图。

(等待加载代码)

调模(图片由作者提供)

正如您在散点图中看到的,这一次,我们调整后的模型与数据吻合得很好,也许可能过度拟合了!

可视化特征的重要性

在我们的分析中,我们没有使用加州房价数据集中的所有变量。由于我们对房屋位置如何影响房价感兴趣,因此我们在分析中只使用数据集中的“纬度”和“经度”变量。然而,数据集中的其他变量也会影响房价。

让我们看看我们在分析中使用的变量有多重要,以及其他变量的重要性。为此,我们通过在数据集中包含所有变量来再次创建随机森林模型。

带所有变量的 RandomForestRegressor 模型的 Python 代码(等待加载)

然后,我们将特征的重要性可视化。

用于可视化随机森林模型特征重要性的 Python 代码(等待加载)

功能重要性(图片由作者提供)

正如我们在条形图中看到的,我们之前选择的变量比其他一些变量更重要。然而,“MedInc”和“ave occupation”对模型最重要。意思是房子的价值受“MedInc”和“ave occupation”影响很大。因此,这两个变量也应该包含在我们的模型中。出于可视化的目的,我们只选择了两个特征(“纬度”和“经度”)进行分析。

摘要

我们获得的结果可能在以下因素上有很大差异。

  • RandomForestRegressor()类的 random_state
  • 随机状态train _ test _ split()函数的值

基于我们为 random_state 、提供的值,最佳超参数值、RMSE 值、特征重要性可以显著变化。这是因为在创建树时以及在将数据集拆分为训练和测试拆分时所涉及的随机性。为 random_state 使用一个正整数值,以在不同的执行中获得静态结果。

今天的文章到此结束。如果你对此有任何疑问,请在评论区告诉我。我会尽快回答。

感谢阅读!

订阅我的电子邮件列表

订阅我的电子邮件列表,再也不会错过精彩的故事了。我一点击发布按钮,你就会在收件箱里收到每一篇文章。

https://rukshanpramoditha.medium.com/subscribe

成为会员

如果你愿意的话,你可以注册成为会员,以获得我写的每一个故事的全部信息,我会收到你的一部分会员费。

https://rukshanpramoditha.medium.com/membership

下一篇文章再见!一如既往,祝大家学习愉快!

鲁克山·普拉莫蒂塔
2022–03–08

如何训练人工智能玩任何游戏

原文:https://towardsdatascience.com/how-to-train-an-ai-to-play-any-game-f1489f3bc5c

使用强化学习技术

这是一个关于如何使用强化学习训练人工智能玩任意视频游戏的简短指南。它一步一步地展示了如何设置您的自定义游戏环境,并利用稳定基线 3 库来训练 AI。我想让这个指南易于访问,所以给出的代码没有完全优化。你可以在我的 GitHub 上找到源码。

游戏人工智能的强化学习

不同于其监督的非监督的对应物,强化学习(RL)不是关于我们的算法从静态数据集学习一些潜在的真理,而是与它的环境交互以最大化奖励函数(非常类似于动物在现实生活中如何用零食训练)。这使得 RL 可能是机器学习最有前途的领域之一,有望通过能够处理复杂任务(如驾驶汽车或控制机器人的运动)的人工智能来彻底改变我们的生活。RL 目前的一个应用是训练人工智能玩电脑游戏(参见 DeepMind 中的一些例子)。

由于几个公开可用的强化学习包,现在即使是 Python 编程新手也可以为任意视频游戏训练 AI。然而,我们应该记住,随着游戏变得越来越复杂,训练所需的计算资源会迅速增加。在这个项目中,我们使用了稳定基线 3 ,这是一个标准化的库,它提供了基于 PyTorch 的 RL 算法的简单实现。

在开始本指南之前,您需要安装稳定基线 3 及其依赖项,详情请参见官方安装指南。

设置我们的游戏环境

虽然稳定基线包有很多内置的游戏环境(例如,雅达利游戏),但本指南的目标是在任意游戏上训练 AI,例如我们自己设计的视频游戏。作为一个例子,我们将使用经典蛇的修改版本,我们在中间插入两个额外的墙壁。

我们的贪吃蛇游戏的初始设置;作者图片

因此,首先我们需要创建一个表示我们游戏的类,训练算法可以与之交互。我们可以通过 OpenAI Gym 基类gym.env的类继承来做到这一点。您可以在 GitHub 上找到我们的 Snake 的详细代码,但是概括地说,自定义环境应该遵循以下格式:

class custom_game(gym.Env):def __init__(self, grid_size=12):"""Define possible actions and observation data format"""...self.action_space = ... #define possible actionsself.observation_space = ... #format of observations def _get_obs(self):"""Calculates the observations (input) from current state"""...return observation #in format of self.observation_space def reset(self):"""Resetting the environment (i.e., starting a new game)"""....return self._get_obs()def step(self, action):"""Evolve environment in response to action and calculate reward"""...return  self._get_obs(), reward, done, infodef render(self):"""Optional, in case we want to render the current state"""

现在,让我们检查一下每个方法,并设置它们来玩我们的游戏。首先我们需要决定几件事:

  • 玩家可能的动作有哪些(即self.action_space)?
  • 我们如何为算法编码游戏的当前状态(即self.observation_space)?换句话说,玩家在玩游戏时“看到”了什么。
  • 奖励方案是什么(即采取某项行动的reward 值)?

在接下来的部分,我们将详细讨论如何为我们的游戏设置这些。

行为空间

总的来说,我们应该努力使动作和观察空间尽可能的简单和小,这样可以大大加快训练的速度。对于贪吃蛇游戏,玩家每走一步,蛇只有三种选择:直走右转左转,我们可以用整数 0、1、2 来编码

self.action_space = spaces.Discrete(3)

了望处

对于观察,我们需要交流游戏的当前状态。一个简单的方法是将其表示为一个网格,其中每个像素的值表明它是还是食物。为了简单起见,在这个例子中我们将创建一个无符号整数网格(本质上是一张图片),其中我们将每个像素的状态编码为 0: ,1: ,2: 和 3: 食物。然而,这个网格并没有向玩家提供游戏的完整状态,因为仅仅从一张图片来判断蛇的头部在哪里以及它往哪个方向走是不可能的。所以总的来说,我们的观察空间应该是这样的:

self.observation_space = gym.spaces.Dict(spaces={"position": gym.spaces.Box(low=0, high=(self.grid_size-1), shape=(2,), dtype=np.int32),"direction": gym.spaces.Box(low=-1, high=1, shape=(2,), dtype=np.int32),"grid": gym.spaces.Box(low = 0, high = 3, shape = (self.grid_size, self.grid_size), dtype=np.uint8),})

我们用两个 2D 向量来编码蛇的头部位置和它当前的方向。为了简单起见,我们将它们存储在一个字典中(“position”代表蛇头,“direction”代表蛇头,“grid” 代表玩家在屏幕上看到的图片)。注意,一般来说,更有效的是进一步编码观察空间,使得它由单个向量或矩阵来表示。最后我们设置了_get_obs()来将游戏的当前状态转换成上面的格式。

奖励计划

也许任何 RL 实践中最关键也是最不简单的部分就是设计一个好的奖励方案。选择一个“好”的方案会使训练速度加快很多,而选择一个“坏”的方案会阻止算法学会正确地玩游戏。

对于我们的贪吃蛇游戏,我们基本上期望我们的 AI 做两件事:1)吃食物 2)避免撞到墙壁或自身。

我们试试下面这个方案:吃东西 50 分,每走一步没撞墙没撞到蛇尾巴加 1 分。我们还定义了避免无限博弈的最大步骤数。在这种情况下,我们的 RL 算法将快速收敛到下面的解决方案。

因采取奖励措施而不碰壁而产生的解决方案;作者图片

如你所见,算法陷入了局部奖励最大值。一个更好的奖励方案是只奖励更接近食物的步骤。这里必须小心,因为蛇仍然只能学会绕圈,在接近食物时获得奖励,然后转身再回来。为了避免这种情况,我们还必须对远离食物的行为给予等价的惩罚,换句话说,我们需要确保闭环上的净回报为零。我们还需要引入对撞墙的惩罚,因为有些情况下,蛇只能通过撞墙来接近食物,我们不想奖励这种情况。

超参数

大多数 RL 算法相当复杂并且难以实现。幸运的是,稳定基线 3 已经实现了几个我们可以使用的最先进的算法。在这个具体的例子中,我们将使用近似策略优化或简称 PPO 。虽然我们不需要知道算法如何工作的细节(如果感兴趣,请参见这个解释视频),但我们需要对它的超参数是什么以及它们做什么有一个基本的了解。幸运的是,PPO 只有其中的几个(参见这篇文章中的完整指南),我们将使用以下内容:

  • learning_rate:设置策略更新的步长,与其他 RL 方案相同。将其设置得太高会阻止您的算法找到正确的解决方案,甚至会将策略推向永远无法恢复的方向。把它设置得太低没有这样的风险,但是它使训练花费更长的时间。一个常见的技巧是在训练期间使用调度器功能来调整它(例如,从高开始并减少)。
  • gamma:未来奖励的折扣系数,介于 0(仅与即时奖励相关)和 1(未来奖励与即时奖励价值相同)之间。为了鼓励代理学习长期策略,最好将其保持在 0.9 以上。
  • clip_range:PPO 的一个重要特性,粗略地说,它设定了当我们更新我们的政策时,一个行动的概率不能改变超过一个因子1+-clip_range。这是为了确保我们不会在训练步骤之间戏剧性地改变政策。减少它有助于在以后的训练阶段对模型进行微调。
  • ent_coef:熵系数对过于确定的政策不利。本质上,它的值越高,就越鼓励算法探索不同的、非最优的行动,这可以帮助方案脱离局部回报最大值。

一般来说,从默认的超参数开始是值得的,因为这些参数被选择为适合大多数任务。有时将学习率设置为随着训练进度而降低是一个好主意,这样我们就可以看到较低的学习率是否可以防止停滞。此外,由于没有明确的方法来为任意问题(例如,定制游戏)设置这些参数,我们需要进行实验。幸运的是,stable-baselines3 允许我们在训练方法中添加回调函数,以评估训练中的模型并保存最佳模型(参见[Monitor](https://stable-baselines3.readthedocs.io/en/master/common/monitor.html)[EvalCallback](https://stable-baselines3.readthedocs.io/en/master/guide/callbacks.html?highlight=EvalCallback#evalcallback))。

培养

接下来的步骤是为一些预先确定的N步骤进行训练,然后亲眼看看算法是如何运行的,然后从性能最好的参数中重新开始潜在的新参数。我们在这里绘制了不同训练时间的奖励,要获得更高级的反馈,您可以使用 TensorBoard 。总的来说,我们希望游戏结束时的总奖励随着我们训练模型而增加。

以下是我在这个项目中发现的一些可能有帮助的观察结果:

  • 很难估计一个问题需要多少个训练步骤,所以首先检查一下增加更多的训练步骤是否会提高回报是值得的。
  • 制作一部关于人工智能如何玩游戏的电影是值得的,这样你就可以看到它设法学习了什么策略,你可以用它来调整奖励计划(例如,在我们的情况下,我们如何需要停止奖励步骤以避免无限循环)。
  • 如果奖励最初增加,然后随着训练步数的增加而逐渐减少,那么learning_rate 很有可能过高。
  • 奖励也可能停滞不前,这通常是算法陷入局部最大值的迹象。在我们的蛇问题中,当食物在墙的另一边,蛇靠近墙,然后无限期地停留在那里,因为远离食物会受到惩罚。在这些情况下,临时增加ent_coef允许算法探索并摆脱这个局部最大值。

初始训练阶段的奖励值;作者图片

经过足够多的步骤后,我们训练的算法收敛到某个奖励值。我们可以结束训练或者尝试微调参数,继续训练。请注意,达到最大可能奖励所需的训练步骤数量很大程度上取决于您的问题、奖励方案和超参数,因此在训练前花一些时间优化它们总是一个好主意。对于我们的例子,当人工智能变得相当擅长在迷宫中导航时,我们停止训练。

训练有素的 AI 玩蛇。它学会了寻找食物,学会了如何“摆动”以避免与自己相撞。它还需要学会避免困住自己,撞到尾巴。图片作者。

如果你有兴趣为你自己的游戏训练一个 AI,你可以修改我在这个例子中使用的代码( GitHub )。

如何训练你的剪辑

原文:https://towardsdatascience.com/how-to-train-your-clip-45a451dcd303

介绍 CLIP 以及我们如何针对意大利语对其进行微调

CLIP 在向量空间中嵌入图像和文本。作者提供的图片(图片来自免费的 Unsplash 数据集)。

在 7 月份,HuggingFace 和谷歌组织了一次联合社区周,感兴趣的人可以利用谷歌 TPUs 来试验他们喜欢的项目(也可以使用 JAX 图书馆)。

jax-亚麻拥抱脸社区周标志。

我将要描述的项目始于这个线程,是一个关于多模态(图像和文本)表征学习的简单实验。然而,事实证明,就结果而言,该项目的影响比我们预期的要有趣得多。

我说“我们”是因为如果没有我出色的队友们,这个项目就不可能完成:拉斐尔西尔维亚加布里埃尔斯里和达里奥。

我们从剪辑模型开始,这是一个非常强大的模型,可以联合学习文本和图像的表示。剪辑是有用的许多任务,如图像检索和零镜头图像分类。对于后者,CLIP 能够匹配并击败许多监督图像分类模型,而无需查看原始训练集的一个示例。

显然,如果没有 HuggingFace 和 Google 提供的资源和帮助,这是不可能的。

一些快速链接:

  • 我们的 GitHub 资源库,在这里你可以找到我们的培训脚本
  • 我们的型号在 HuggingFace hub 上
  • 我们的论文
  • 你可以玩我们的演示来评估意大利的能力

今天的计划

在本文中,我将首先对 CLIP 的工作原理进行概述(第 1 节)。我将努力保持高层次的抽象,但同时,我将努力分享理解这个模型如何工作所需的所有信息。之后,我将更详细地描述我们如何训练它来覆盖意大利语(第 2 节)。

如果你喜欢视频格式,我九月份在 LightOn AI 做了一个演讲,你可以在这里找到视频:

第 1 部分—剪辑准备工作

对比语言-图像预训练 (CLIP)是 OpenAI 最近提出的一种模型,用于联合学习图像和文本的表示。在纯粹的自我监督形式中,CLIP 只需要输入图像-文本对,它将学习将两者放在同一个向量空间中。剪辑需要训练图像和这些图像的标题。

编码

CLIP 背后的假设非常简单:您需要一个图像编码器和一个文本编码器。其中的每一个都将生成一个向量(一个用于图像,一个用于文本)。

图像编码器可以使用视觉转换器或 CNN 构建,使用什么并不重要(是的,选择会影响性能,但想法是一样的)。

图片作者。使用免费的 Unsplash 数据集。我们使用图像编码器从图像中生成矢量表示。

要嵌入文本数据,您可以使用转换器(例如,预训练的 BERT 模型)或您喜欢的任何其他类型的文本编码方法。

图片作者。使用免费的 Unsplash 数据集。我们使用文本编码器从一个句子中生成一个向量表示。

训练剪辑模型

关于 CLIP 最重要的事情是,它将图像和字幕的编码表示(即我们上面看到的向量)放在同一个向量空间中,并将“匹配”的字幕-图像对放在空间中。例如,像这样(我使用 2D 表示,但这也适用于 N 维):

图片作者。使用免费的 Unsplash 数据集。剪辑目的是使图像-文本对在空间上接近。

CLIP 训练背后的直觉可以用下面的 GIF 简单总结一下。在训练期间,图像和描述它们的标题被放在向量空间中,而不匹配的图像(或标题)被推开。

图片作者。使用免费的 Unsplash 数据集。训练过程旨在将匹配的图像-文本对放在一起,并远离其他一切。

现在我们可以把所有东西放在一起。在下面的 GIF 中,你可以看到训练是如何完成的,我们有两张图片和两个标题,我们知道每张图片的“正确”标题。我们可以为两个图像和两个标题创建嵌入,并计算各自的相似性。我们希望匹配的图像-标题对之间的相似度(点积)上升,而不匹配的图像-标题对之间的相似度下降。

图片作者。使用免费的 Unsplash 数据集。GIF 更详细地展示了训练过程。我们从成批的图像和文本对开始,并且我们最大化匹配的图像-文本对之间的相似性(并且最小化不匹配的图像-文本对)。

使用这个过程,我们学会了在匹配图像-文本对的向量空间中放得很近,而将其他所有东西移得很远。

为什么 CLIP 很酷?

CLIP 非常有趣,因为在没有任何实际监督的情况下(如果我们忽略图像和标题之间的匹配),将图像和文本放在同一个空间会带来有趣的可能性。最有趣的一个可能是零镜头分类:如果您可以访问一幅图像和一组标签(任何种类的标签),您可以看到哪个标签与您作为模型输入的图像最相似。

看了下面的动画,大概的思路应该更清晰了:

图片作者。使用免费的 Unsplash 数据集。当投影到空间中时,猫的图像和标签“猫”将是接近的(考虑空间中的一些距离度量)。

CLIP 在没有看到一个训练样本的情况下,在 ImageNet 等数据集上显示出令人难以置信的零拍摄性能。你可以在原文中读到更多这方面的内容。

第 2 部分—剪辑—意大利语

通过我们的项目,我们试图为意大利 NLP 和 CV 社区提供另一种资源。我们的模型是第一个为意大利语制作的剪辑模型。

为了用意大利语训练剪辑,我们需要一样东西:数据。特别是,我们需要带有说明文字的图片。虽然我们有英语资源,但意大利语就没那么幸运了。

数据集

我们考虑了三个主要的数据来源:

  • WIT 是从维基百科收集的图片说明数据集(参见, Srinivasan 等人,2021 )。我们重点关注论文中描述的参考描述标题,因为它们是质量最高的。尽管如此,许多这些标题描述本体论的知识和百科全书的事实(例如,罗伯托·巴乔在 1994 年)。
  • MSCOCO-IT 。这个图像字幕数据集来自于 Scaiella 等人的工作,2019 。字幕来自原始的 MSCOCO 数据集,已经用 Microsoft Translator 进行了翻译。2017 版的 MSCOCO 训练集包含超过 100K 幅图像,每幅图像都有多个字幕。
  • 概念说明。这个图像字幕数据集来自于 Sharma 等人的工作,2018 。在这个数据集中有超过 3 百万个图像-标题对,这些都是从网上收集的。我们用数据集提供的 URL 下载了图像,但我们无法全部检索到它们。最终,我们不得不将字幕翻译成意大利语。我们已经能够收集具有 70 万翻译字幕的数据集。

虽然翻译后的标题在某种程度上是一种限制,但它们看起来质量很好(我们运行了一个小型的手工评估管道来检查质量,注释者之间达成了良好的一致)。

培训/建筑

你可以在我们的 GitHub 库上找到更多关于我们如何训练意大利语剪辑的细节。感谢 HuggingFace 脚本,这很容易做到,我们基本上只需要改变一些超级参数。

我们考虑的架构使用来自 CLIP 的原始图像编码器,而不是作为文本编码器,我们使用意大利 BERT 模型(因为我们需要创建意大利嵌入)。OpenAI 使用的视觉转换器已经在 4 亿张图像上进行了训练,它可能是我们架构中需要训练最少的元素。

然而,由于我们不是从原始分量开始(BERT 是新增加的),投影不再对齐(即,BERT 编码投影到向量空间的完全不同的区域)。这需要在训练中小心,不要弄乱预训练组件的重量。

为了允许随机初始化的重投影层预热,而不干扰主干的调整权重,我们决定在我们架构的主干完全冻结的情况下进行第一次训练。只有在这些层融合后,我们才解冻模型的其余部分,以微调所有组件。这种技术允许我们达到更好的验证损失。

蓝色层是编码层,我们有一个额外的层用于 512 维的投影,那是我们为训练热身的层。图片由作者提供。

只要你有数据和一些计算资源,训练 CLIP 并不是不可能完成的任务。运行提供的训练脚本就足够了。最近,HuggingFace 开发了一个易于使用的管道来玩 VisionTextEncoders ,如果你对这一领域的研究感兴趣,你可能会想考虑一下。

你可以在我们的 GitHub 库上找到一些关于我们如何评估这个模型的细节。长话短说,对于两个不同的任务(图像检索和零镜头图像分类)来说,使用特定于语言的模型比使用多语言剪辑要好(尽管多语言剪辑由于其他原因非常酷)。

例子

在这里,我将展示一些来自我们在线演示的例子。

《山上的两个人》。来自 Unspash free 数据集的图像。

关于“数猫”的几个例子

“两只猫”和“一只猫”。来自 Unspash free 数据集的图像。

有趣的是,这个模型似乎能够计数。这显然来自训练数据,显示了其中的一些模式,但值得注意的是,该模型可以学习识别图片中的多个对象(然而,请注意,这并不能很好地扩展:对于像“四只猫”和“五只猫”这样的数字,结果就不太清楚了)。

如何使用剪辑-意大利语

你想自己玩这个吗?我们为你做好了准备,这是朱塞佩为你准备的笔记本,在 PyTorch。打开可乐杯。

为了向您展示使用它是多么容易,我将在这里分享一些代码行,您可以使用它们来加载模型和生成嵌入。

我们现在可以很容易地使用它,你可以看到一个如何嵌入文本的例子,但正如我所说的,你可以在 colab 笔记本上找到一切:

你可以对图片做同样的事情,计算图片和文本之间的相似度。

结论

剪辑-意大利一直是一个惊人的冒险。发现和学习了许多乐趣和新事物。一个惊人的项目和一个惊人的机会,为此我们必须感谢谷歌和 HuggingFace 为实现这个项目所做的努力。

如何用 Python 和 AssemblyAI 转录和分析音频文件

原文:https://towardsdatascience.com/how-to-transcribe-and-analyze-audio-files-with-python-and-assemblyai-22660dbf8e66

演示:将 Youtube 视频转换成摘要文本

詹姆斯·柯文在 Unsplash 上的照片

在从事机器学习项目时,我从未真正有机会试验音频文件。我唯一一次这样做是在一些 mp3 歌曲上尝试了 DeepSpeech 模式。

坦率地说,我对结果感到失望,并继续前进。

几周前,我开始了一个小型的个人项目,涉及语音到文本的部分。我需要尽快整合它,鉴于我在语音处理领域的经验有限,我没有时间训练一个模型。为此,我决定转向使用 API。

在对不同的解决方案进行基准测试时,我最终选择了 AssemblyAI。

在这篇文章中,我将向你介绍 AssemblyAI,它做什么,它包含哪些核心功能,以及为什么我认为它是语音到文本的强大解决方案。
然后,我将向您展示一个简单的用例,其中我们将 AssemblyAI 集成到一个 Streamit 应用程序中,以转录 Youtube 视频。

事不宜迟,我们来看看。🔍

1-什么是 AssemblyAI,它解决什么问题?

训练一个强大的语音到文本模型不仅仅是强大的资源和几天的训练。这是一项技术任务,除了深度学习之外,还结合了语言学和信号处理的精细知识。

如果你曾经在机器学习项目中处理过音频文件,你可能知道语音数据非常复杂:声音可能被破坏,可能有背景音乐或噪音,音量可能很低,多种声音可能会干扰,人们可能经常使用听不见的话语,如“嗯,嗯,嗯,嗯,嗯”或多次停止说话。有点烦人,不是吗?

将这些数据转录成有意义的文本并非易事。

AssemblyAI 是一家致力于解决语音转文本问题的深度学习公司。它提供了最先进的语音转文本 API,具有接近人类的性能。

作者截图

该 API 既可以通过处理队列中的作业来异步调用,也可以通过在接收文件时直接转录文件来实时使用。

为了应对上述与语音相关的挑战,AssemblyAI 在核心转录引擎中包含了许多功能。你可以通过这个链接查看。

以下是我个人觉得非常有用的一些功能。

  • **说话者二分化:**这是一种分离多个说话者的声音并给每个人赋予不同标签的能力。举个例子,你转录两个人之间的访谈,会有一个说话人 A 和一个说话人 B,每个人都会有对应的转录。
  • **双通道转录:**这是一个允许单独转录每个通道的功能。这在记录电话对话或缩放通话时非常有用。
  • **自定义词汇:**语音转文本模型虽然功能强大,但有时可能无法正确转录某些单词(首字母缩写词、名称或特定领域/技术术语)。为了解决这个问题,AssembyAI 包含了对自定义词汇表的支持。你只需要传递一个单词列表,模型就会在预测时将它们考虑在内。

除了很好地转录音频文件,AssemblyAI 还提供了一套基于人工智能的工具来更好地理解你的数据。通过在 HTTP 查询中切换布尔标志,您可以选择添加以下一个或多个功能:

  • **话题检测:**利用这一功能,AssemblyAI 能够提取音频中所谈到的关键话题。有 698 个不同的主题遵循 IAB 标准分类法。
    分类如下:

  • **情感分析:**这是在句子层面上执行的分类任务。它以一定的置信度预测正面、负面或中性。

  • **自动章节:**该功能提取时间编码的关键时刻,并为每个关键时刻生成摘要。这个功能非常有趣,可以突出演讲或视频中的重要部分。

  • **实体检测:**这是一个命名实体识别任务。AssemblyAI 不仅仅预测非常普通的位置和组织实体。它更进了一步,为其他实体提供支持,如信用卡号、药品或医疗条件。
    这是所有检测到的实体的完整列表。

检测到的实体列表—作者截屏

如果您有兴趣了解更多关于这些音频智能功能的信息,请查看此链接。

2 —如何使用 AssemblyAI 转录音频文件?

在这一节中,我们将看到如何轻松地使用 AssemblyAI API 异步转录音频文件。我们将在另一个时间研究实时转录。

→设置环境

如果你是一名 Python 开发人员,我想你很可能是,开始使用 AssemblyAI 所需要做的就是简单地安装requestspython-dotenv库。

  • 以 pythonic 的方式处理 HTTP 请求
  • python_dotenv允许你从。环境文件。将凭证从代码中分离出来通常是个好主意,这也是我们为什么要使用这个包的原因。
**pip install requests
pip install python-dotenv**

→创建一个 AssemblyAI 账户

若要开始使用 AssemblyAI,您必须创建一个帐户。你可以免费注册,甚至不需要输入你的信用卡信息。免费计划提供每月 3 小时的使用限制和 5 小时的并发限制。查看此链接以了解有关 AssemblyAI 定价的更多信息。

作者截图

一旦你的帐户被创建,你将得到一个 API 令牌。此令牌完全是个人的,不应与任何人共享。

作者截图

我将在下面的代码中展示如何使用环境变量隐藏这个个人令牌。

→开始使用 API 转录音频文件 assembly ai API 可以转录可通过 URL 访问的音频或视频文件。

如果你有一些音频文件,你想转录,有两种选择:

1-你上传你的数据到云上的某个地方(AWS S3,GCP 云存储,Azure Blob 存储,等等),并提供 URL 给 AssemblyAI。

一旦有了音频文件的 URL,转录请求就相当于一个 HTTP Post 请求,具有以下参数:

  • 转录 API 端点
  • 一个 JSON 有效负载来提供音频 URL
  • 一个报头有效载荷包括 API 密钥和content-type

在本例中,我们将转录以下音频文件:

用代码总结我们刚刚说过的内容:

下面是运行代码后获得的 JSON 响应。

在其他有用的参数中,它指示对应于该特定运行的转录id和指示处理队列状态的status键。

状态从queued开始,然后移动processing,最后移动completed

您可以随时从界面查看加工队列。

用户截图

处理完成后,获取转录 id 并运行以下查询:

现在,您应该得到以下输出:

输出模式非常明确。以下是您应该关注的内容:

  • text键代表转录的文本
  • words键代表转录单词列表。这个列表的每个元素都是一个 JSON 对象,它包含转录单词的文本、相应的开始和结束时间(以毫秒为单位)以及预测的概率(也称为置信度得分)
  • confidence(在 0 和 1 之间)键表示算法在转录完整音频文件时的全局置信度

还有一些我们暂时忽略的参数。

2 —你直接上传你的数据到 AssemblyAI 服务器并运行转录

现在第二个选择:你的文件不在云上。

AssemblyAI 为您提供了在处理音频或视频文件之前将它们直接上传到服务器的可能性。这在用户在提交之前从麦克风录制音频文件的情况下非常方便。

要上传一个文件,推荐的方法是首先将它分成每个 5MB 的块,并将这些块放入一个生成器中,该生成器将作为数据有效负载传递给查询。

文件上传后,您将获得上传文件的 URL。

使用这个 URL,您可以按照上一节中的详细说明进行转录。

3-用例:将 Youtube 视频转换成经过分析的转录

在这一节中,我将向您展示如何将 AssemblyAI 嵌入到 Streamlit 应用程序中。

作者截图

  • 首先,你必须建立你的环境。我将使用 pipenv 安装以下包:请求streamlitpytube、python-dotenv、验证器。
**cd assemblyai/
pipenv install requests streamlit pytube python-dotenv validators**
  • 使用API_KEY键在项目文件夹中创建一个. env 文件:
**API_KEY=<YOU API KEY GOES HERE>**
  • 我们从导入正确的包开始:

  • 我们定义了一个从 Youtube URL 下载音频的函数:

  • 我们定义了四个函数:一个读取音频文件,一个上传到 AssemblyAI,一个提交转录作业,一个获取转录输出。

  • 最后,Streamlit 应用程序逻辑:

不要被这段代码吓到,它所做的如下:

  • 它接收来自用户的 URL 输入,并在用 validators 库验证其模式时,pytube 模块下载音频文件并返回其路径
  • 我们定义了三个按钮:第一个按钮触发对 AssemblyAI 的上传,将 upload_url 打印到屏幕上,并将其置于会话状态
  • 第二个按钮提交转录作业,获取转录 id,并将其保存在会话状态中
  • 第三个按钮根据转录 id 检索结果,并将其打印到屏幕上。

如果你有兴趣在本地运行这个应用,代码可以在我的 repo 上找到。我会不断更新应用程序,所以不要犹豫,在未来检查它。

资源

文档和博客是了解 AssemblyAI 的最佳资源。看看他们!

  • https://www.assemblyai.com/
  • 【https://docs.assemblyai.com/#introduction
  • https://www.assemblyai.com/blog

感谢阅读🙏

如果你已经做到这一步,我想感谢你的时间,并希望你已经了解了一些关于 AssemblyAI 的事情。

在接下来的帖子中,我们将更多地使用音频智能功能,并解决一些实际的用例。

今天就这些了。下次见!👋

新到中?您可以每月订阅 5 美元,并解锁各种主题的无限文章(技术、设计、创业……)您可以通过点击我的推荐链接支持我

https://ahmedbesbes.medium.com/membership

照片由卡斯滕·怀恩吉尔特在 Unsplash 上拍摄

如何用 Python 实时转录音频数据流

原文:https://towardsdatascience.com/how-to-transcribe-streams-of-audio-data-in-real-time-with-python-and-assemblyai-322da8b5b7c9

一个开启全新应用世界的功能

由 Unsplash 上的 Soundtrap 拍摄的照片

在我以前的博客文章中,我使用了 AssemblyAI 语音转文本 API。

我尝试了它的核心转录服务,并玩了一些很酷的人工智能功能:发现敏感话题的内容审核功能和提取每个音频片段中谈论的主题的话题检测功能。(我构建了一个 Streamlit 应用程序来展示最后一个功能如何应用于分析 Youtube 视频。你可以在这里查看。该代码也可在 Github 上获得。)

这些实验都是离线执行的,需要一些时间来生成输出。事实上,一旦您将音频文件发送到 AssemblyAI,转录作业就会提交到一个队列,一旦队列完成处理,您就可以检索转录本。就像那样,你必须等待。

但是,如果你能在 AssemblyAI 摄取你的音频数据的同时转录它,会怎么样呢?

这就是我们所说的实时转录。

T 他的帖子将带你了解使用 AssemblyAI 进行实时转录的过程。我们将首先用正确的依赖项设置环境,然后我们将在 Python 中创建异步函数来与 AssemblyAI 的 WebSocket 服务器通信。

好的,让我们看看👀

👉设置您的帐户

实时转录是一项付费功能。为了能够使用它,你必须在 AssemblyAI 上创建一个账户并输入你的信用卡信息。

作者截图

你可以在这里了解更多关于定价的信息。

一旦你的帐户配置完毕,拿起你的 API 密匙,进入下一部分。

👉安装一些依赖项

因为我们要进行实时转录,所以我们需要从麦克风捕捉现场音频流,并立即将它们传递给 API。

首先,我们需要安装 PortAudio,这是一个跨平台、开源的音频 I/O 库,它为录制和/或播放声音提供了一个非常简单的 API。

如果你在 Mac OS 上,你可以使用家酿软件包管理器来安装它

**brew install portaudio**

如果你使用的是不同的操作系统,你可能需要检查这个链接。

然后,您需要安装为 PortAudio 提供绑定的 PyAudio Python 库。

**pip install pyaudio**

最后,您需要安装允许构建 websockets 服务器和客户端的 web sockets 库:这将帮助我们将音频流式传输到 AssemblyAI 并捕获实时转录。

**pip install websockets**

👉用 PyAudio 打开音频流

为了能够将音频流式传输到 AssemblyAI,我们首先需要用 PyAudio 打开一个音频流。

创建流需要一些参数:

  • 每个缓冲区的帧数 (3200) 。缓冲区是任意数量的帧的块,用于将原始信号分成更小的片段。
  • 音频格式: **(16 位)。**这代表每个样本的大小,即每个帧的大小。2 字节= 16 位,因此这大致说明了每个样本是如何编码的。
  • 通道数: **(1)。**这是指要使用的音频流的数量。例如,现代计算机使用两个声道进行立体声输出:一个用于左扬声器,一个用于右扬声器。
  • 采样率: (16000) 。这是每秒钟(或每单位时间)从连续信号中提取的帧数,以形成离散信号。

一旦流打开,它就能够捕获我们从麦克风记录的音频数据。

现在,我们需要将这个流连接到 AssemblyAI 的实时转录。服务。

为此,我们将打开一个 WebSocket 连接,以便能够同时发送和接收数据。我们需要这种特定类型的网络连接,因为这是 AssemblyAI 使用的。

两个函数将使用开放的 WebSocket 连接。

  • 第一个函数以我们在创建 PyAudio 流时定义的速率发送输入音频数据。然后,它将数据转换为 base64,将其解码为字符串格式,并将其发送到 AssebmlyAI WebSocket 端点。

  • 第二个函数不断地从 AssemblyAI 获取转录,并将其打印到屏幕上。

— PS:如果你想知道 *_ws* 是什么,可以在最后查看完整的剧本。

这两个功能同时运行。

为了等待它们执行,包装函数使用了asyncio.gather函数。

下面是包装函数的代码:

现在,为了让这个包装器函数异步运行,我们需要调用以下命令:

**asyncio.run(send_receive())**

👉完整脚本

总结一切,这是完整的脚本。注意,我已经使用 python-dotenv(像在以前的文章中一样)来读取 API 密钥。

👉演示!

这是实时转录的录音演示。

👉参考资料:

  • https://towards data science . com/how-to-transcripte-and-analyze-audio-files-with-python-and-assembly ai-22660 dbf8e 66
  • https://towards data science . com/how-to-moderate-audio-data-using-python-and-assembly ai-a5eab 9910730
  • https://towards data science . com/how-to-build-a-streamlit-app-to-extract-topics-from-YouTube-videos-9c 7 aebbfab 8 e
  • https://web sockets . readthedocs . io/en/stable/intro/tutorial 1 . html
  • https://www.assemblyai.com/
  • https://docs . assembly ai . com/walk throughs # real time-streaming-transcription

感谢阅读🙏

这标志着 AssemblyAI 博客系列的结束。我希望它给了你一个很好的 API 和人工智能特性的概述,有助于理解脚本。

如果你有兴趣了解更多关于这个 API 的知识,你可以查看我以前的帖子和官方文档,或者使用我制作的 Streamlit 应用程序。

今天就这些了。以后的帖子再见!👋

新到中?您可以每月订阅 5 美元,并解锁各种主题的无限文章(技术、设计、创业……)您可以通过点击我的推荐链接支持我

https://ahmedbesbes.medium.com/membership

Joshua Fernandez 在 Unsplash 上的照片

如何在生产、本地和 S3 之间传输文件

原文:https://towardsdatascience.com/how-to-transfer-files-among-prod-local-and-s3-ce073a7cbe6b

备份 Postgres、复制 docker 文件和在不同 AWS 配置文件之间切换的代码片段

照片由以色列总统府在 Unsplash 上拍摄

数据科学家很少会收到如下请求:

  1. 您能从生产机器上备份 stage 和本地 Postgres 数据库吗?
  2. 你能从生产机器 docker 服务器上复制 X 文件并保存到本地机器上吗?
  3. 为你的客户上传 X 文件到 AWS s3 怎么样?(提示:您可能有多个 AWS 概要文件)

如果你经历过类似的情况,但不知道如何处理,我希望我下面的代码片段可以帮助你恢复冷静和内心的平静。

如何:从生产计算机备份 stage 和本地 Postgres 数据库

在我们公司,我们只能 ssh 到 prod 机,而且 Postgres 数据库非常大。因此,以下是适合我们团队的解决方案:

  • 第 0 步:在本地机器上安装zstdzstd是一种压缩算法,可以帮助减小 Postgres pg_dump文件的大小。
# in your terminal
$ brew install zstd
  • 步骤 1 : ssh 到您的生产机器(如果您不确定如何 ssh 到您的生产机器,请向您的 DevOps 同事寻求帮助!)
$ ssh [alias for prod] 
$ pg_dump -T [table1] -c | zstd -T32 -19 -c > /tmp/prod.psql.zstd

上面的命令=“对除表 1 之外的所有表运行 pg_dump”。该命令压缩pg_dump文件并将其存储在生产机器的临时文件夹中。

  • 步骤 2 :将 zstd 输出下载到本地机器

打开一个新的终端,并cd到你想要保存文件的目录。例如Downloads:

$ cd Downloads/
$ scp discovery-prod:/tmp/prod.psql.zstd .

命令以一种超级干净的方式将文件从 prod 复制到你的本地!就像《哈利·波特》中的幽灵💎

  • 第 3 步:用zstd文件
    备份您的本地或登台数据库确保在您的登台环境中删除数据库之前先与您的 DevOps 团队讨论。
# I feel pretty free to do so on my local machine$ dropdb discovery_db
$ createdb discovery_db
$ cat prod.psql.zstd | zstd -dc | psql discovery_db

如何:从生产机器 docker 服务器复制 X 文件,并将其保存到本地机器

嗯,类似于上面的过程,这里唯一的新东西是从一个特定的 docker 容器中抓取特定的文件。

# step 0: ssh to your production machine. 
$ ssh prod# step 1: show your docker container 
$ docker ps# step 2: copy a file under specific container ID
# Here I'm trying to copy a meltano.db file# step 3: copy file and store it in temp folder
$ docker cp [container_id]:/projects/.meltano/meltano.db /tmp/meltano.db

类似地,您可以打开一个新的终端并使用scpmeltano.db文件从 production temp 文件夹下载到您的本地机器。以下是截图:

额外提示:

  • 你可以交替使用docker container lsdocker ps
  • Docker 容器文件夹可能会变得非常大,有时您可能希望删除旧的未使用的容器来释放空间。您可以这样做:
# Run both to stop and remove the folder$ docker stop [container_id]$ docker rm [container_id]

我想导出meltano.db的原因是因为我们注意到这个文件的大小以意想不到的速度增长。所以我们想导出这个文件以供进一步分析。下面是显示文件大小的另一个技巧:

  • du -h --max-depth=1:显示该目录下的文件
  • ls -alh:这将以人类可读的方式显示.下的文件及其大小。

如何:设置多个 AWS 概要文件并将文件上传到 s3

例如,我想配置两个配置文件:一个用于我的外部公司,另一个用于访问客户的公司。您需要预先获得两个概要文件的 AWS 访问密钥和秘密密钥。

# step0: check your default profile list
$ aws configure list# Configure my profile 1: wen_outside
$ aws configure --profile wen_outside
# follow the steps to filling the blanks
AWS Access Key ID [None]: [fill your info]
AWS Secret Access Key [None]: [fill your info]
Default region name [None]: [fill your info] # example: us-east-1 
Default output format [None]: json# Configure my profile 2: wen_client
$ aws configure --profile wen_client
# follow the steps to filling the blanks
AWS Access Key ID [None]: [fill your info]
AWS Secret Access Key [None]: [fill your info]
Default region name [None]: [fill your info] 
Default output format [None]: json# Now check to see your profile list
$ aws configure list-profiles

下一步是如何在配置文件之间切换:

# Switch to my outside profile
$ export AWS_DEFAULT_PROFILE=wen_outside

最后,假设我需要将meltano.db上传到我们客户的 s3:

# switch to my profile wen_client
$ export AWS_PROFILE=wen_client# from local to S3: for single file
$ aws s3 cp meltano.db [client's s3 directory]# from S3 to current directory
$ aws s3 cp [s3 directory] .# from local to S3: sync the whole folder "forClient"
$ aws s3 sync forClient [client's s3 directory]

摘要

  • 和其他一些数据科学家一样,我也有类似的担心,与生产机器(通常是 Linus 和 Ubuntu 系统)交互可能会令人生畏。这些任务我做得不够频繁,以至于我建立了肌肉记忆。好消息是,如果您对此类代码片段保持良好的文档记录,这种担心是可以克服的。

如何将你的命令行程序转换成用户友好的图形用户界面

原文:https://towardsdatascience.com/how-to-transform-your-command-line-app-into-a-user-friendly-gui-98c207564324

Gooey 是一个 python 库,对于所有讨厌命令行的人来说是天赐之物

照片由蒂姆·高在 Unsplash 拍摄

在我的机器学习应用程序开发中,我大部分时间都使用命令行界面。但是我同意处理命令行并不容易,除非你投入大量的时间。或者有时候你只是不想被它困扰。

我最近偶然发现了这个叫做 Gooey 的 python 库,它使 ML 应用程序开发变得有趣,并且使用起来非常简单。让我来解释一下。

我写过一篇关于如何使用 ArgParse 库构建机器学习 app 进行实验的文章。这里可以查一下。我使用了那篇文章中的相同代码,并将其转换成 GUI 版本。

胶粘物

使用以下工具快速安装

pip install Gooey

现在,您所要做的只是将装饰器添加到您现有的 Python 应用程序中(用 argparse 库包装)。事情就是这么简单:

from gooey import Gooey[@Gooey](http://twitter.com/Gooey)      <--- all it takes! :)
def main():parser = ArgumentParser(...)# rest of code

在将装饰器添加到现有代码中之后,您可以将它变成一个用户友好的 GUI 应用程序。多酷啊!

示例代码

我将重用我以前文章中的相同代码。添加 Gooey decorator 后的 python 应用程序如下所示:

我对我的旧代码做了一些小的改动,比如添加了更多的 print 语句,但是唯一需要做的就是添加了 decorator 和 import 语句。

我们将要运行的 python 应用程序的快速描述—

这是一个二元分类任务,要求用户选择一种降维技术(以及输出维数),然后选择 ML 分类器来训练模型。模型评估是在测试集上完成的(从整个数据中分层分割 30%),使用准确度分数作为度量。我们打印准确性分数以及用户选择的参数。

让我们运行代码,看看它是否工作。

要运行 Python 应用程序gooey_example.py,只需在命令行中写入:

python gooey_example.py

您将看到以下 GUI:

Gooey Python 应用程序 GUI (Gif 由作者提供)

您有 3 个选项可供选择(以下拉选择框的形式),并且可以运行 python 应用程序。瞧啊。应用程序按预期运行。

注意:我用 Macbook 来运行代码,所以我必须使用

pythonw gooey_example.py

除了 Gooey 库之外,我不得不安装下面的命令来代替前面的命令。

conda install -c conda-forge python.app

这对我来说并不简单,因为当我尝试运行 Python 应用程序时出现了一些错误。我可以通过安装python.app很容易地解决这些问题,而且运行得很好。

关于胶粘的思考

将 CLI 应用程序转换成 GUI 应用程序是一个很酷的想法。我真的很喜欢。但这对我没有多大用处,因为我通常构建 CLI 机器学习应用程序来执行多个实验并记录每个实验的工件(正如我在我以前的文章中谈到的)。

如果我向不精通机器学习和一般编码的客户解释该应用程序如何工作,GUI 应用程序会很有用。对于这样的人来说,GUI 将是一个很好的工具,可以用来探索应用程序是如何工作和运行的。

如果我可以在遍历所有参数组合时将这个 GUI 用作进度条,那将对我很有帮助。我仍然需要检查这个功能。

感谢阅读,干杯!

**Want to Connect?**Reach me at [LinkedIn](https://www.linkedin.com/in/rohithteja/), [Twitter](https://twitter.com/rohithtejam), [GitHub](https://github.com/rohithteja) or just [Buy Me A Coffee](https://www.buymeacoffee.com/rohithteja)!

如何像对待产品一样对待您的数据

原文:https://towardsdatascience.com/how-to-treat-your-data-like-a-product-73731ec5f131

您的团队希望“像对待产品一样对待数据”太好了!现在怎么办?

图片由 移民斯坦 快门 提供,通过标准许可证购买。

在过去的几十年里,大多数公司都将数据保存在组织的筒仓中。

分析团队为业务部门服务,即使数据对决策和产品路线图变得越来越重要,负责数据管道的团队也更像水管工,而不像合作伙伴。

然而,在 21 世纪 20 年代,数据不再是二等公民。随着更好的工具、更多样化的角色以及对数据全部潜力的更清晰理解,许多企业已经开始将整个生态系统视为公司技术堆栈的完整元素。

最具前瞻性的团队正在采用一种新的范式:像对待产品一样对待数据。这是目前数据社区的一个热门话题,最近几个月,我们有幸与几位行业领袖讨论了数据即产品,并揭示了他们对如何将这种新方法融入日常生活的真实看法。

行业领导者如何将数据定义为一种产品

首先,让我们直接听一听 几位数据产品经理 如何将数据视为产品。(以下引文是为了篇幅和清晰起见而编辑的。)

查德·桑德森,车队

以下是总部位于西雅图的货运市场车队(freight market place confirm)数据平台产品负责人查德·桑德森(Chad Sanderson)在最近一次关于构建可靠数据产品的活动中所说的话:

“总的来说,围绕将数据视为产品的含义,有两种思想流派仍在发展:第一种,您拥有生成数据的外部或内部产品或服务,这意味着数据(包括整个管道)是产品的一部分。所以它必须和应用程序代码一样严格。它需要 SLA,需要良好的测试,需要良好的监控和文档等等。

在第二种方法中,您可以将任何为客户提供服务的代码库的输出视为产品。例如,当您考虑数据仓库时,它实际上只是一个代码库,主要由 SQL 组成,为内部客户服务,如其他分析师、数据科学家和产品经理,他们使用该数据进行业务决策。因此,任何推向公司可以访问的“生产数据环境的东西都是产品。因此,如果您正在使用 Mode 或 Metabase 等仪表板工具,并且您正在编写 SQL 并将该仪表板推送到其他人可以访问它的公共环境中,这也是一种产品。所以它也必须和其他产品一样严格。

这两种方法与我们在过去 10 年或 20 年中对数据的思考方式截然不同,在过去的 10 年或 20 年中,数据科学家和分析师更多地是一个孤岛,他们会离开并回答独立的问题。"

优步·阿图尔·古普特

在与蒙特卡洛团队的一次对话中,Atul Gupte,前** 优步数据平台团队 产品经理,更进一步描述了数据产品经理的角色。**

“数据产品经理是一个专门负责回答以下问题的角色:

  • 存在哪些数据?
  • 谁需要这些数据?
  • 这些数据从哪里流入/流出?
  • 这些数据有什么用?
  • 有没有一种方法可以更容易地处理/访问这些数据?
  • 这些数据是否合规和/或可操作?
  • 我们如何更快地让数据对公司更多的人更有用?

数据产品经理通过为员工构建内部工具和平台来回答这些问题。

一些数据产品经理受制于数据分析师和数据科学家,其他人则受制于运营团队、软件团队,或者更大公司的高管。他们通常来自传统 B2B 产品管理、内部工具产品管理、数据分析或后端工程等背景。但是,与我们传统上定义的“客户”(即购买或消费你的软件的个人)不同,你是在与“数据消费者”合作——换句话说,就是使用理解你公司数据的产品的员工。"

贾斯汀·盖奇,重组

正如 Justin Gage 、Retool 的数据负责人在媒体上分享的那样,数据作为一种产品的概念可以帮助澄清数据团队做什么的问题,以及他们应该专注于执行什么任务。

“数据即产品(DaaP)是最容易理解的模型:数据团队的工作是提供公司需要的数据,无论是出于何种目的,无论是决策、构建个性化产品还是检测欺诈。这可能听起来像数据工程,但事实并非如此:数据科学家也提供数据产品,只是包装方式不同。

在 DaaP 模型中,公司数据被视为一种产品,数据团队的角色是以促进良好决策和应用程序构建的方式向公司提供该数据。该模型的一些重要特征:

  • 数据有一个来自整个数据团队的 SLA (象征性的),不仅仅是数据工程
  • 数据流是单向的,从数据团队流向公司
  • 领域专业知识对数据团队成员的益处有限

虽然每个定义都有自己的细微差别,但显然有一些关键的要点:将数据视为产品涉及服务内部“客户”(数据消费者),支持决策和其他关键功能,以及应用 SLA 等严格标准。

应用数据即产品方法的 5 种方式

根据我们与这些数据领导者和其他人的交谈,我们确定了现代数据团队可以将这种方法应用于自己组织的五种主要方式。

1)尽早获得利益相关方的支持——并且经常这样做

当数据是你的产品时,你的内部客户也是你的利益相关者。在您制定自己的数据产品路线图、开发 SLA 并开始将数据视为一种产品时,优先考虑与您的关键数据消费者合作。

这意味着戴上你的产品经理的帽子——或者,正如 Atul 上面建议的,有一个专门负责数据产品管理的角色——来充分了解你的内部客户的需求、关注和动机。

您需要清楚地了解谁使用了您的数据,如何使用,以及用于什么目的。这将帮助您了解需要构建什么类型的数据产品来满足这些需求。

这种理解也有助于你采用数据叙事。软件、产品和 UX 团队使用 讲故事的实践 通过不同的视角分享他们工作的背景,这将帮助涉众基于对他们最重要的事情理解其价值。您将努力说服您的利益相关者,数据应该优先考虑,并证明将数据视为产品所需的投资是合理的。

例如,在说服利益相关者投资于数据基础设施而不是更花哨的机器学习模型或有望产生数百万美元的新功能时,Chad Sanderson 将讲故事描述为一种无价的工具。

“要扭转这种局面,让数据质量处于同等地位,需要做大量的工作……在某些情况下,我通过关注我们公司的故事以及我们的数据科学家和分析师的故事来解决这个问题。当他们建立模型时,这些模型真的可信吗?我们对构成驱动我们商业决策的机器学习基础的数据有多信任?所以我试着讲一个真正好的故事,一个紧凑的故事,有公司的清晰例子,实际上与产生收入的东西联系在一起。因此,最终我们可以说,看,提高我们的数据质量可能不会对收入产生可观察、直接、可测量的影响,但有一个明确的定性认识,即从所有这些使用案例来看,它将使我们在财务上长期受益。”

2)运用产品管理思维

另一个关键步骤是将产品管理思维应用于如何构建、监控和度量数据产品。

因此,在构建管道和系统时,使用与生产软件相同的成熟流程,如创建范围文档和将项目分解为冲刺。

铁甲公司的首席数据分析师杰西卡·切尔尼描述了她公司的敏捷工作流程。

“我们在内部将数据视为一种产品,这意味着将产品管理原则应用于数据和数据团队。因此,当我们有一个需要数据的大型战略项目时,我们创建数据范围文档,就像产品经理与正确的利益相关者一起创建规范一样。我们不断与工程师和产品经理进行迭代,以确保这是一个跨职能、利益相关者一致的产出,而不是让数据人员在一个孤岛中工作,不与任何人互动。”

与工程流程类似,数据团队在构建管道时应该考虑可扩展性和未来用例。Chad 认为,这可能代表着数据团队过去工作方式的重大转变。

“通常情况下,实际进入生产数据库的数据实际上只是服务级别的事件,是由工程师在没有真正考虑它的情况下抛出的。因此,随着公司的发展,数据模型变得如此混乱的一个重要原因是,我们通常首先关注快速构建服务,其次才是对数据的批判性思考。这种将数据作为产品的想法是一种连续转变,开始改变这种情况。”

SeatGeek 的高级数据分析工程师 Kyle Shannon 在同一个网络研讨会上分享说,由于数据团队的快速增长,他的公司正在关注可扩展性。

“我们真的在努力了解如何更好地吸纳新人,制定更好的流程,让数据更容易被发现和访问。在一家公司工作了很长时间的人知道去哪里找信息,但如果你一年要雇用 20 或 30 名数据团队成员,真的很难说,“哦,就去闲置渠道问问题吧。”它不会扩大规模。因此,当您构建您的数据产品时,您必须记录所有内容,并确保非常清楚——您正在删除冗余或您可能在此过程中发现的任何问题。"

要采用的另一种产品思维方式是,在开始构建任何新的数据产品之前,设置与您的业务目标一致的 KPI。正如 Chad 之前所描述的,讲故事可以帮助说明投资于数据质量的潜在好处,但是大多数组织仍然期望成熟的团队来衡量他们的计划的财务影响。

许多数据团队正在采用与数据质量相关的KPI,例如计算数据停机时间的成本,即数据不完整、错误、丢失或不准确的时间,或者通过测量数据团队成员花费在故障排除或修复数据质量问题上的时间,而不是专注于创新或构建新的数据产品。****

为您的数据设置基准指标将有助于量化数据计划的长期影响。只要确保这些指标在用例中得到一致的应用,特别是如果你有一个中央数据平台。

3)投资自助工具

为了将数据带出孤岛,并将其视为有价值的产品,业务用户需要能够自助服务并满足自己的数据需求。自助工具使非技术团队能够访问数据,使您的数据团队能够专注于增加价值的创新项目,而不是作为满足特定请求的按需服务。

自助工具也是数据网格概念的主要原则之一,这是一种新的去中心化数据架构的方法。Intuit 数据平台团队的前工程副总裁马马德·扎德是数据网格的热情拥护者,他认为自助式工具是数据架构和数据产品不可或缺的一部分。

正如他所建议的,“我们,在中央数据团队中,应该确保正确的自助式基础设施和工具对数据生产者和消费者都可用,以便他们可以轻松地完成工作。给他们配备合适的工具,让他们直接互动,不碍事。”

4)优先考虑数据质量

将数据作为产品的一个关键组成部分是将严格的标准应用于整个生态系统,从摄取到面向消费者的数据交付。正如我们之前在讲述故事的上下文中所讨论的,这意味着在整个数据生命周期中优先考虑数据质量和可靠性。

公司可以根据 数据可靠性成熟度曲线 来评估他们当前的数据质量状态。简而言之,该模型表明数据可靠性有四个主要阶段:

****#1 反应式团队将大部分时间花在应对消防演习和对数据问题进行分类上,导致重要计划缺乏进展,组织难以在产品、机器学习算法或业务决策中有效使用数据。

****#2 主动团队在工程、数据工程、数据分析师和数据科学家之间积极协作,开发手动检查和定制 QA 查询来验证他们的工作。示例可能包括验证管道关键阶段的行数或跟踪时间戳以确保数据新鲜。当事情出错时,松弛消息或电子邮件提醒仍然会弹出,但是这些团队确实通过他们的主动测试发现了许多问题。

****#3 自动化在这一级别,团队通过预定的验证查询优先处理可靠、准确的数据,从而提供更广泛的管道覆盖范围。团队使用数据健康仪表板来查看问题、进行故障排除,并向组织中的其他人提供状态更新。示例包括跟踪和存储有关维度和度量的指标,以观察趋势和变化,或者在摄取阶段监控和实施模式。

****#4 可扩展这些团队利用成熟的开发运营概念来建立一个试运行环境、用于验证的可重用组件和/或针对数据错误的硬警报和软警报。凭借对关键任务数据的大量覆盖,该团队可以在大多数问题影响下游用户之前解决它们。示例包括跨所有关键指标和工具的异常检测,允许监控和跟踪每个作业和表格的质量。

数据的成熟不会一蹴而就。但是,通过开始 设置清晰的数据 SLA、SLIs 和 SLOs 来衡量质量,您可以开始展示投资于自动化、可扩展数据可靠性的价值。常见数据运行状况指标的示例包括特定资产的数据事件数量、检测时间和解决时间。

如前所述,在设置 SLA 时,与您的数据利益相关方保持一致至关重要—您希望确保对“可靠性”对您的数据消费者意味着什么、哪些资产最重要以及哪些潜在问题需要立即关注有共同的理解。

5)为您的数据组织找到合适的团队结构

当然,团队结构对您的组织如何与数据进行日常交互有着巨大的影响。您是否有一个集中的数据团队来处理数据管理和应用的各个方面?或者跨业务单位嵌入的分析师,满足特定需求并获得领域专业知识,但是遭受孤岛和缺乏内聚的治理?

不同的公司需要不同的方法,这取决于它们的规模和业务需求,但我们采访过的许多数据领导者都发现轴辐式模型的最佳结果。在这种结构中,集中的数据平台团队处理基础设施和数据质量,而分散的嵌入式分析师和工程师处理语义层并将数据应用于业务。如果您的组织发展迅速,需要快速行动,这种模式非常适合,但可能会导致嵌入式分析师的重复工作,而没有与集中式数据团队保持一致。

restaurant POS software Toast 的商业智能高级总监 Greg Waldman 带领他的团队经历了为期五年的组织演变,其中包括从集中式到分散式再到轴辐式模型的转变。他建议成长型公司的数据领导者遵循产品管理的一个关键原则——保持敏捷。

“简而言之,我对数据团队的看法是,你希望每个人都尽可能增加商业价值。我们一直非常乐于改变和尝试不同的事情,并理解适用于 200 人、500 人和 1000 人的答案是不同的,这没关系。“当你到达那些转折点,需要尝试新事物时,这一点可能会变得有些明显。”

对于 Jessica Cherny 来说,分散的分析师和工程师的优势在于他们能够理解数据请求背后的真正业务需求。

“我想知道如何设计出真正满足他们需求的产品。最近就发生了这样的事情,有人要求我立即获得一组特定的数据。我可以说,‘等等,等一下。我真的需要用这种复杂的聚类方法来回答这个问题吗?这个的实际需求是什么——这样我就不必放下手头的一切工作,可以及时有效地为你服务?我们最终完全重新组织了她的问题,因为我更好地理解了她问题背后的业务需求,以及如何以简单易懂的方式回答这个问题。"

同样,每家公司都有自己的文化景观和需要解决的挑战,但中心辐射模型可以帮助成长中的团队快速满足业务需求,而不会放弃对数据质量和治理的所有权。

下一步是什么?

我们刚刚谈了很多。但这是因为采用一种像对待产品一样对待数据的组织方法不仅仅是数据行业中的一种流行趋势。这是一种有意识的思维方式转变,带来了有意义的结果:提高数据民主化和自助服务能力,提高数据质量以便能够准确、自信地做出决策,并扩展数据对整个组织的整体影响。

有兴趣了解如何像对待产品一样对待您的数据系统吗?伸出手去 巴尔蒙特卡洛 车队!****

https://www.linkedin.com/in/meitao/萨拉盖茨 对本文有贡献。

如何将本地(zip)数据转换成 Huggingface 数据集

原文:https://towardsdatascience.com/how-to-turn-your-local-zip-data-into-a-huggingface-dataset-43f754c68f82

拥抱面部数据集

在一行代码中快速加载数据集,用于训练深度学习模型

https://github.com/V-Sher/HF-Loading-Script

什么是拥抱脸🤗数据集?

如果你已经在深度学习领域工作了一段时间(或者即使你只是最近才开始钻研),很有可能,你会遇到hugging face——一个开源的 ML 库,它是所有人工智能(预训练模型、数据集、推理 API、GPU/TPU 可扩展性、优化器等)的圣杯。

他们还有一个专门的图书馆—🤗D 数据集用于轻松访问和共享自然语言处理(NLP)、计算机视觉和音频任务的数据集。

pip install datasets

这个库预装了 2500 多个数据集。您可以按如下方式检查列表:

from datasets import list_datasets
list_datasets()*** OUTPUT ****['acronym_identification','ade_corpus_v2','adversarial_qa','aeslc','afrikaans_ner_corpus','ag_news',...
]

要在当前的 python 脚本或 jupyter 笔记本中加载这些数据集,只需将数据集的名称传递给load_dataset()。例如,让我们用asr(自动语音识别)配置加载一个名为superb的流行音频数据集,并检查第一个音频文件。输出是具有六个特征的字典— chapter_idfileaudioidspeaker_idtext

from datasets import load_dataset
**dataset = load_dataset("superb", "asr")**
dataset[0]*** OUTPUT *** 
{'chapter_id': 1240,'file': 'path/to/file.flac','audio': {'array': array([0., 0.003, -0.0002,..., dtype=float32),'path': 'path/to/file.flac','sampling_rate': 16000}'id': '103-1240-0000','speaker_id': 103,'text': 'CHAPTER ONE MISSUS RACHEL LYNDE IS SURPRISED MISSUS  RACHEL LYNDE '}

这篇文章是关于什么的?

我开始写这篇文章的主要原因之一是因为我想微调一个🤗在自定义音频数据集上使用训练器 API 的变压器模型(博客随后发布)。我遇到的大多数教程都在使用一个流行的数据集(如 Superb 、 Librispeech 等),这些数据集预装在库中,开箱即用。

想要使用 Kaggle 的 Crema-D 音频数据集,我想——如果我们也可以像上面一样用一行代码加载我们自己的定制数据,那不是很好吗?大致意思是:

dataset = load_dataset("my_custom_dataset")

这正是我们在本教程中要学习的!因此,请点击此链接上的下载按钮,跟随本教程。您应该看到包含 Crema-D 音频文件的archive.zip开始下载。它包含 7k+音频文件,格式为.wav

经历这些麻烦有什么好处吗?

创造的一个主要好处是🤗数据集是由箭头支持的。换句话说,数据集缓存在磁盘上。需要时,它们直接从磁盘(提供快速查找)进行内存映射,而不是加载到内存(即 RAM)中。正因为如此,内存相对较小的机器仍然可以使用 Huggingface 数据集 【源】 加载大型数据集。

好的,我被说服了,我们开始吧…

假设我们需要使用定制的本地 CremaD 数据集——这意味着它还不能使用load_dataset()开箱即用地加载,我们需要编写一个加载脚本来代替。我们上面看到的每个预装数据集在后端都有自己的加载脚本。这里的是针对superb数据集的。

加载脚本是一个*.py* python 脚本,我们将其作为输入传递给*load_dataset()*。(而不是预安装的数据集名称)。它包含有关列及其数据类型的信息,指定数据集的训练测试拆分,处理下载文件(如果需要)以及从数据集生成样本。

加载脚本还有助于将数据集代码模型训练代码解耦,以获得更好的可读性和模块化。

假设我们已经成功创建了上述脚本,那么我们应该能够如下加载数据集:

ds = load_dataset(dataset_config["LOADING_SCRIPT_FILES"],dataset_config["CONFIG_NAME"],*data_dir*=dataset_config["DATA_DIR"],*cache_dir*=dataset_config["CACHE_DIR"]
)

其中dataset_config是一个简单的字典,包含以下值:

dataset_config = {"LOADING_SCRIPT_FILES": path/to/loading/script.py,"CONFIG_NAME": "clean","DATA_DIR": path/to/zip/file,"CACHE_DIR": path/to/cache/directory,
}

通过在调用load_dataset()时传递data_dir,我们告诉加载脚本在哪里寻找包含音频文件的目录。此外,设置一个cache_dir将允许我们在后续调用load_dataset()时重用数据集的缓存版本。

最后,我们将专注于构建一个名为clean的配置。但是,一个数据集内可以有多个配置。例如,在上面的superb示例中,我们使用特定的配置(即asr)加载数据集,但是它们还有五个其他配置— ksicsisder

同样,对于本教程,除了拥有一个包含整个数据集的clean配置之外,我们还可以拥有第二个配置,比如说small,它可以是一个用于测试目的的精简数据集,或者第三个配置,比如说fr,它可以包含这个数据集的法语版本。(在本教程的最后,我将简要讨论如何在同一个加载脚本中定义多个配置)。

快速绕道

在我们开始为数据集(包含在一个 zip 文件中)编写定制加载脚本之前,我想指出如果我们处理🤗来自简单数据格式文件的数据集,如 csv、JSON 等。以下示例直接取自文档页面:

  • csv
dataset = load_dataset(‘csv’, data_files=[‘my_file_1.csv’, ‘my_file_2.csv’])
  • json
dataset = load_dataset(‘json’, data_files=’my_file.json’)
  • 正文
dataset = load_dataset(‘text’, data_files={‘train’: [‘my_text_1.txt’, ‘my_text_2.txt’], ‘test’: ‘my_test_file.txt’})
  • python 字典
my_dict = {'id': [0, 1, 2], 'name': ['mary', 'bob', 'eve'], 'age': [24, 53, 19]}dataset = Dataset.from_dict(my_dict)
  • 熊猫数据帧
df = pd.DataFrame({"a": [1, 2, 3]})
dataset = Dataset.from_pandas(df)

编写自定义加载脚本

回到我们的定制加载脚本,让我们创建一个名为crema.py的新文件。这是任何新数据集的典型加载脚本:

图 1:使用 Huggingface 提供的空白模板生成。

如您所见,有三个主要功能需要修改— info()split_generator()generate_examples()。让我们一个一个来看:

来源:官方拥抱脸文档

1\. info()

在该方法中要指定的三个最重要的属性是:

  • 描述 —包含数据集快速摘要的字符串对象。
  • 特性 —就像为数据集定义一个框架/元数据一样。也就是说,您希望为每个音频样本存储哪些特征?(还记得superb数据集如何为每个音频文件定义了六个特征)。
    对于我们的音频分类任务,我们只需要定义一个file和相应的label
  • 主页—(可选)链接到数据集的主页 URL。

需要考虑的事情很少:

  • 每个列名及其类型统称为特性的🤗数据集。它采用了dict[column_name, column_type]的形式。
  • 根据column_type,我们可以拥有
    — 数据集。值(整数和字符串)、
    — 数据集。ClassLabel (对于一组预定义的带有相应整数标签的类),
    — 数据集。序列特征(用于对象列表)。
    —还有更多。
  • 在我们的代码中,为了简单起见,filelabel都被定义为string类型的值特征。
    注:除 *string* 外,其他数据类型包括*int32**bool* *timestamp*等。查看完整列表 此处
  • 除了descriptionfeatureshomepage之外,你可以在这里查看其他可以在info()中指定的属性,如版本号、supervised_keys、引用等。

2.split_generator()

这是负责下载或检索数据文件的功能。这就是为什么在图 1 的函数定义中,下载管理器(即[dl_manager](https://huggingface.co/docs/datasets/v1.1.1/_modules/datasets/utils/download_manager.html#DownloadManager))作为函数参数之一被传递。

DownloadManager 有一个名为extract()的预定义函数,负责解压我们的数据集并访问其中的音频文件。

**def _split_generator(self, dl_manager):data_dir = **dl_manager.extract**(self.config.data_dir)....**

注意:如果您的 zip(或 tar)数据托管在 ftp 链接或 URL 上(例如, 这个 是当前存储 *superb* 数据集的地方),您可以使用 *dl_manager.download_and_extract()* 来负责下载和解压缩文件。因为我们已经下载了。zip 文件本地,我们只需使用 *extract()* 解压文件即可。

该函数将数据目录的路径作为输入(即 archive.zip 位于 ) 。记住,当调用load_dataset()时,我们将该路径作为data_dir参数传递,因此它将作为配置的一部分可用,并可通过self.config.data_dir访问。

extract()函数的输出是一个字符串,包含文件解压后的缓存目录的路径。例如,在我们的例子中,这将是:/Audio-Classification-Medium /cache_crema/downloads/extracted/d088ccc5a5716.......。在这个位置,你会发现一个新创建的名为AudioWav的文件夹,里面有我们所有的.wav音频文件。

最后,split_generator()还使用 SplitGenerator 通过拆分来组织数据。目前,我们只有一个 split,即由这个函数返回的train_splits,我们将这个函数的name指定为train。在这里,gen_kwargs指的是从这个数据集生成样本所需的关键字参数。它包含两个参数——filesname——接下来这两个参数都将被转发给_generate_examples()方法。

注: *gen_kwargs* 内可以通过的没有限制。试试 *gen_kwargs={"files": data_dir, "name": "train", "useless_arg": "helloworld"}* 。不用说,在 _generate_examples() 中只包含您认为生成样本所需的 kwargs。

提示:将来,如果您有单独的数据集用于测试和验证分割,您可以创建更多的分割,如下所示:

3.generate_examples()

如前所述,该方法将从gen_kwargs解包的所有东西作为参数,如_split_generators中给出的。在我们的例子中,这将是filesname:

**def _generate_examples(self, files, name):...**

该方法负责从音频数据集(使用[yield](https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do))逐个生成(keyexample)元组,其中example是包含音频文件和标签的键值对的字典。因为我们没有对标签的显式访问,我们需要使用split()从文件名中提取它们(例如:1001_DFA_ANG_XX.wav)。

**file = 1001_DFA_ANG_XX.wavlabel = file**.split**("_")[-2]
print(label)**** OUTPUT ****
ANG**

注:根据官方数据集 文档 ,文件名包含有用的元数据(用 *_* 分隔)包括 speaker_id (1001)、句子 id (DFA)等。如果您想将它们作为数据集的一部分,请确保您更新了 *info()* 以为它们中的每一个创建新的要素,然后才能在 *generate_examples()* 中使用它们。

在我们生成一个示例之前,我们必须创建一个包含所有示例的列表。让我们通过遍历os.path.join(files, “AudioWav")目录中的所有文件来实现这一点。

注 1:如果你想知道为什么我们需要上面的 *os.path.join()* ,记住 *files* 是缓存文件夹 *./Audio-Classification-Medium /cache_crema/downloads/extracted/d088ccc5a5716.......* 的路径——这里没有音频文件!在这个位置,一个新创建的 *AudioWav* 文件夹包含了需要的 *.wav* 音频文件。我花了几个小时调试这个!
后知后觉,我下次应该用
*os.walk()*

注 2:如果您有一个包含所有元数据(包括标签)的显式 csv/json 文件,那么 *generate_examples()* 的代码看起来会有点不同。不是遍历所有文件,而是需要(a)遍历 csv 文件中的行,( b)使用 *.todict()* 将每一行转换成一个字典——以创建 *examples* 列表。请看下面的虚拟片段:

最终代码为 **crema.py**

需要考虑的额外变化很少:

  • ****在第 28 行上,我们设置了一个类属性,即DEFAULT_WRITER_BATCH_SIZE,表示在将数据集写入箭头文件时,RAM 中可以保存多少个示例。对于图像、音频或视频等占用大量内存的数据,将它设置为一个较小的值(比如 256)很重要,这样可以避免 OOM 错误和迭代器阻塞的风险。如果我们不设置一个值, Arrow 的默认批量大小(10000)被用于,这对语音样本来说太大了。
  • ****在第 29 行上,我们已经使用数据集定义了为该数据集提供的唯一配置,即clean。BuilderConfig 是构建配置的基类。
    (最后,我们将看到如何子类化builder config并添加我们自己的属性来定义多个配置)

恭喜,你现在已经准备好加载你的数据集了

打开新的 python 脚本或 jupyter 笔记本:

**dataset_config = {"LOADING_SCRIPT_FILES": os.path.join(PROJECT_ROOT, "crema.py"),"CONFIG_NAME": "clean","DATA_DIR": os.path.join(PROJECT_ROOT, "data/archive.zip"),"CACHE_DIR": os.path.join(PROJECT_ROOT, "cache_crema"),
}ds = load_dataset(dataset_config["LOADING_SCRIPT_FILES"],dataset_config["CONFIG_NAME"],*data_dir*=dataset_config["DATA_DIR"],*cache_dir*=dataset_config["CACHE_DIR"]
)print(ds)********* OUTPUT ********DatasetDict({train: Dataset({features: ['file', 'label'],num_rows: 7442})
})**

接下来呢??

从现在开始,你可以选择使用这个数据集作为模型训练(这是我将在我的下一个教程中做的)或者(如果你拥有数据集的所有权)将它上传到 hugging faceDataset-Hub。说明可以在这里找到。

在结束之前,有必要讨论一些可以在数据加载步骤之后、模型训练步骤之前完成的事情。

1.分为训练测试和开发组

**# INTRODUCE TRAIN TEST VAL SPLITS*# 90% train, 10% test + validation*
train_testvalid = ds["train"].train_test_split(*shuffle*=True, *test_size*=0.1)*# Split the 10% test + valid in half test, half valid* test_valid = train_testvalid["test"].train_test_split(*test_size*=0.5)*# gather everything into a single DatasetDict*ds = DatasetDict({"train": train_testvalid["train"],"test": test_valid["test"],"val": test_valid["train"],}
)**

2.将原始音频文件转换为数组

***# CONVERING RAW AUDIO TO ARRAYS*ds = ds.map( *lambda* *x*: {"array": librosa.load(*x*["file"],*sr*=16000,*mono*=False)[0]}
)**

3.将标签转换为 id

**ds = ds.class_encode_column("label")**

4.为模拟运行选择数据集的子集

**ds["train"] = ds["train"].select(range(50))**

另外请记住,每个 *map* 函数,虽然第一次比较耗时,但是会缓存输出,所以在 *model.train()* 期间后续的 *map* 调用不会花那么多时间。

奖励—在数据集中构建多个配置

在文章的开始,我提到我们将讨论允许多重(虚拟)配置的代码片段。为此,我们需要引入一个新的类——姑且称之为CremaConfig——它将是数据集的一个子类。 BuilderConfig 。在这个类中,我们定义了数据集的三个属性,包括data_dirurlcitation

现在,不是像下面这样定义配置:

**BUILDER_CONFIGS = [
**datasets.BuilderConfig**(name="clean", description="Train Set.")
]**

我们现在可以构建CremaConfig类的实例来实例化多个配置。这允许我们灵活地指定名称、数据目录、url 等。每种配置。

**BUILDER_CONFIGS = [
**CremaConfig**(*name*="clean", *description*="Train Set in English.", data_dir="path/to/english/dir", url="...", citation="..."),
**CremaConfig**(name="fr", description="Train Set in French.", data_dir="path/to/french/dir", url="...", citation="..."),
]**

结论

一个巨大的对已存在的大声喊出来🤗关于本主题的文档。我希望本教程能够将文档向前推进一步,过滤技术术语,并展示真实示例的实现!

一如既往,如果有更简单的方法来做/解释本文中提到的一些事情,一定要让我知道。一般来说,避免不请自来的破坏性/垃圾/敌意评论!

直到下一次✨

如何使用 Python (2022)从 S3 自动气象站上传和下载文件

原文:https://towardsdatascience.com/how-to-upload-and-download-files-from-aws-s3-using-python-2022-4c9b787b15f2

了解如何在 Python 脚本中使用云资源

照片由 拉杰史蒂文 发自 像素

我写这篇文章完全是出于沮丧。

我读过的每个关于这个话题的帖子都假设我已经在 AWS 有了一个账户,一个 S3 桶,和一堆存储的数据。他们只是展示代码,但善意地掩盖了最重要的部分——让代码通过你的 AWS 账户工作。

嗯,我应该很容易就能猜出密码,非常感谢。我不得不筛选许多 SO 线程和 AWS 文档,以消除一路上的每一个令人讨厌的认证错误。

为了让您不会有同样的感觉并做艰苦的工作,我将分享以编程方式管理 S3 存储桶的所有技术细节,从创建帐户到向本地机器添加访问 AWS 资源的权限。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

步骤 1:设置帐户

好的,如果你还没有 AWS 账户,让我们从创建账户开始。没什么特别的,只要按照这个链接中的步骤操作就可以了:

作者 GIF

然后,我们将前往 AWS IAM(身份和访问管理)控制台,在那里我们将完成大部分工作。

作者 GIF

您可以轻松地在不同的 AWS 服务器之间切换,创建用户,添加策略,并允许从控制台访问您的用户帐户。我们将一个接一个地做。

步骤 2:创建用户

对于一个 AWS 帐户,您可以创建多个用户,每个用户都可以对您的帐户资源拥有不同级别的访问权限。让我们为本教程创建一个示例用户:

作者 GIF

在 IAM 控制台中:

  1. 转到用户选项卡。
  2. 点击添加用户。
  3. 在字段中输入用户名。
  4. 勾选“访问键—编程访问字段”(必要)。
  5. 单击“下一步”和“直接附加现有策略”
  6. 勾选“管理员访问”策略。
  7. 单击“下一步”,直到看到“创建用户”按钮
  8. 最后,下载您的用户凭证的给定 CSV 文件。

它应该是这样的:

作者:me🥱

请将它保存在安全的地方,因为我们稍后会使用这些凭据。

步骤 3:创建一个存储桶

现在,让我们创建一个 S3 存储桶来存储数据。

作者 GIF

在 IAM 控制台中:

  1. 单击左上角的服务。
  2. 向下滚动到“storage ”,并从右侧列表中选择“S3”。
  3. 单击“创建存储桶”并给它命名。

你可以选择任何你想要的地区。保留其余设置,再次单击“创建存储桶”。

步骤 4:创建一个策略并将其添加到您的用户

在 AWS 中,通过策略来管理访问。策略可以是一组设置或附加到 AWS 对象(用户、资源、组、角色)的 JSON 文件,它控制您可以使用对象的哪些方面。

下面,我们将创建一个策略,使我们能够以编程方式与我们的存储桶进行交互,即通过 CLI 或在脚本中进行交互。

作者 GIF

在 IAM 控制台中:

  1. 转到“策略”选项卡,然后单击“创建策略”
  2. 单击“JSON”选项卡并插入下面的代码:

用你自己的桶名替换你的桶名。如果您注意的话,在 JSON 的 Action 字段中,我们将s3:*放在我们的 bucket 中以允许任何交互。这非常宽泛,因此您可能只允许特定的操作。在这种情况下,查看 AWS 文档的这一页来学习限制访问。

这个策略只附加到 bucket,我们还应该将它连接到用户,这样您的 API 凭证才能正常工作。以下是说明:

作者 GIF

在 IAM 控制台中:

  1. 转到 Users 选项卡,单击我们在上一节中创建的用户。
  2. 单击“添加权限”按钮。
  3. 单击“附加现有策略”选项卡。
  4. 根据我们刚刚创建的策略对它们进行筛选。
  5. 勾选策略,检查并最后一次点击“添加”。

步骤 5:下载 AWS CLI 并配置您的用户

我们下载 AWS 命令行工具,因为它使认证变得非常容易。请转到此页面并下载适用于您平台的可执行文件:

作者 GIF

运行可执行文件并重新打开任何活动的终端会话,以使更改生效。然后,键入aws configure:

作者 GIF

插入您的 AWS 密钥 ID 和秘密访问密钥,以及您创建 bucket 的区域(使用 CSV 文件)。您可以在控制台的 S3 页面上找到您的存储桶的区域名称:

被我。

当您到达配置中的默认输出格式字段时,只需单击“Enter”即可。不会有任何输出。

第六步:上传你的文件

我们快到了。

现在,我们将一个样本数据集上传到我们的 bucket,以便以后可以在脚本中下载它:

作者 GIF

一旦你进入 S3 页面,打开你的水桶,这应该很容易。

步骤 7:检查身份验证是否有效

最后,pip 安装 Boto3 包并运行以下代码片段:

如果输出包含您的 bucket 名称,那么恭喜您——您现在可以通过boto3完全访问许多 AWS 服务,而不仅仅是 S3。

使用 Python Boto3 从 S3 桶下载文件

有了 Boto3 包,您可以通过编程访问许多 AWS 服务,如 SQS、EC2、SES 和 IAM 控制台的许多方面。

然而,作为一名普通的数据科学家,您通常需要从 S3 存储桶上传和下载数据,因此我们将只讨论这些操作。

让我们从下载开始。导入包后,使用client函数创建一个 S3 类:

要从 S3 存储桶下载文件并立即保存,我们可以使用download_file功能:

如果下载成功,将不会有任何输出。您应该把要下载的文件的确切路径传递给Key参数。Filename应该包含您想要保存文件的路径。

上传也非常简单:

该功能为upload_file,您只需更改下载功能中参数的顺序。

结论

我建议阅读 Boto3 文档以获得更多管理 AWS 资源的高级示例。它涵盖了除 S3 之外的服务,并包含了每种服务最常见任务的代码配方。

感谢阅读!

您可以使用下面的链接成为高级媒体会员,并访问我的所有故事和数以千计的其他故事:

https://ibexorigin.medium.com/membership

或者直接订阅我的邮件列表:

https://ibexorigin.medium.com/subscribe

你可以通过 LinkedIn 或 T2 Twitter 与我进行友好的交流。或者你可以读我的另一个故事。这些怎么样:

</8-booming-data-science-libraries-you-must-watch-out-in-2022-cec2dbb42437> </7-cool-python-packages-kagglers-are-using-without-telling-you-e83298781cf4> </22-2-built-in-python-libraries-you-didnt-know-existed-p-guarantee-8-275685dbdb99> </6-pandas-mistakes-that-silently-tell-you-are-a-rookie-b566a252e60d> </8-booming-data-science-libraries-you-must-watch-out-in-2022-cec2dbb42437>

如何在不编码的情况下使用 API

原文:https://towardsdatascience.com/how-to-use-an-api-without-coding-44a324a7c560

对于没有任何编码经验的用户,这是一个使用 Google Sheets 连接到任何 API 的无代码方法

约纳斯·勒普在 Unsplash 上拍摄的照片

在计算机科学中,应用编程接口(API)是几个程序相互通信的一种方式。

如果你的编码经验有限,可能你自己都没用过。然而,你可以确定你的智能手机或电脑上的应用程序正在使用 API。

即使你是一个人,你也可以找到许多有趣的 API,它们可以提高你的生产力,带来一些乐趣或者只是解决你的一些日常问题。

在本文中,我将分享两种方法来连接并自动从 API 获取数据,而无需使用 Google Sheets 编写代码。

💌新文章免费直入你的收件箱:时事通讯

如果你喜欢观看,可以看看这个教程的视频版本

如何不用编码连接一个 API?

最终解决方案

最终的解决方案将看起来像下面的动画 GIF。通过电子表格软件(Google Sheets 或 Excel)中的一个简单公式,你可以从任何 API 中提取数据。

演示—(图片由作者提供)

例子

在本文中,我将使用一个非常酷的 API FruityVice 来提供关于水果的信息。

查看文档了解更多信息。

(图片由作者提供)

在第一栏中,您可以找到我们想要了解的水果清单。我们调用 API 来获取:

  • 第一列中的姓氏
  • 第二栏是脂肪含量
  • 第三列中的糖量

然后,我们只需要放一个公式来调用单元格 B2 中的 API,并沿着列拖动它以获得完整的范围。

履行

调用 API,获得响应并过滤

为了调用 API,您需要按照下面的语法向 API 发送 get 请求。

API 调用—(图片由作者提供)

它不需要任何 API 键,因此我以它为例:

  • 蓝色部分是网站的地址:你可以去那里查看文档
  • 红色部分将让您访问 API
  • 橙色部分是您需要唯一输入参数的地方:英文水果名称

它将以 JSON 格式返回一个响应,

{“genus”: “Musa”,“name”: “Banana”,“id”: 1,“family”: “Musaceae”,“order”: “Zingiberales”,“nutritions”: {“carbohydrates”: 22,“protein”: 1,“fat”: 0.2,“calories”: 96,“sugar”: 17.2}}

我们需要理解 API 响应的构造方式来提取我们想要的信息,

API JSON 响应—(图片由作者提供)

我们感兴趣的是,

  • 【家庭】:水果
  • “营养/脂肪”:脂肪量
  • “营养/糖”:糖的数量

添加一个函数来读取 JSON: importJSON

为了执行查询和解析 JSON,我们将在 GitHub 库中导入一个由 paulgambil 共享的函数。(请为这个非常有用的功能:D 给他一颗星)

按照步骤操作—(图片由作者提供)

  • 从 GitHub 库中获取代码并复制它
  • 转到谷歌表单的扩展菜单
  • 创建一个新脚本,并将其命名为 importJSON.gs

现在你的函数 importJSON 可用了。

解析 API JSON 响应

编写查询 现在可以开始编写单元格中的公式 B2、

=importJSON("https://www.fruityvice.com/api/fruit/"&A2;"/family,/nutritions/fat,/nutritions/sugar"; "noHeaders,Truncate")
- We take the fruit name in the cell A2
/family, nutritions/fat, nutritions/sugar: specify the three information we want to get from the API response

拖动公式 ,拖动到列尾后,函数 importJSON 会自动粘贴右边单元格中的值。

整个过程—(图片由作者提供)

你可以在我的 Youtube 频道上找到更多的生产力技巧和 google sheets 教程

https://youtube.com/@productivedata

后续步骤

关注我的媒体,获取更多与数据分析和供应链管理相关的文章

从 URL 导入表

在这个简短的教程中,我分享了另一种从 URL 中提取数据的方法。

为什么不 Excel?

Excel 有自己的函数来执行名为 WEBSERVICE 的 API 查询。但是没有内置函数解析 JSON 响应,所以你得想办法只用 Excel 公式来做(我个人不会)。

因此,我更愿意使用 Google Sheets。

用例

既然您可以使用 Google sheets 查询任何 API,那么您可以:

  • 使用距离矩阵或地理编码 API 计算位置之间的距离
  • 使用谷歌翻译 API 翻译任何单词
  • 从像 pixabay 这样的股票服务中获取任何带有图片的图像

关于我

让我们在 Linkedin 和 Twitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营并降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

如何从 Azure DevOps 管道使用 Azure SQL 访问令牌身份验证

原文:https://towardsdatascience.com/how-to-use-azure-sql-access-token-authentication-from-azure-devops-pipelines-344fa7dafa49

使用 Python 和 Azure PowerShell

戴维·霍伊泽在 Unsplash 上的照片

如果您需要从 DevOps 部署管道访问 Azure SQL 数据库,以便在数据库上执行一些自定义脚本。如果你需要使用用户名和密码认证之外的东西,并希望利用 Azure Active Directory,使用访问令牌可能是你的解决方案。

在这篇文章中,我将提供一个如何使用 Azure Active Directory 访问令牌向 Azure SQL 进行身份验证的示例。Azure DevOps 服务连接用于获取访问令牌。要做到这一点,一个先决条件是拥有一个作为用户添加到数据库的服务连接。建立服务连接的推荐方式是使用 Azure Active Directory 服务主体,也称为应用程序注册。

!!从安全角度来看,不建议使用带有用户名和密码的 SQL 认证。在 Azure SQL 的当前版本中,甚至可以完全关闭 SQL 身份验证,而只使用 Active Directory 身份验证。

先决条件

  1. 带有服务连接的 Azure DevOps 项目
  2. 一个 SQL 数据库,其中一个数据库用户代表服务连接

使用 Azure PowerShell 获取访问令牌

在下面的示例中,我们使用 Azure 管道的 Azure PowerShell 任务来利用服务连接凭据获取访问令牌。使用 SQLServer PowerShell 模块,我们可以使用“Invoke-Sqlcmd”来执行查询。

通过 Python 使用访问令牌

在下一个示例中,我们安装 pyodbc 模块,并针对我们的数据库执行一个定制的 python 脚本。确保编写一些逻辑来将参数传递和捕捉到 python 脚本中。我添加了一个示例 python 函数,并设置了连接字符串。我花了很长时间才让它工作起来。问题出在连接字符串上,在文档中有提到,但是我却漏掉了这句话:“连接字符串不能包含 *UID* *PWD* *Authentication* ,或者 *Trusted_Connection* 关键字

为了能够使用访问令牌,需要一个函数来“扩展”访问令牌。更多信息参见文档。

现在,您可以根据用户被添加到的数据库角色对数据库进行各种操作了!删除表时一定要小心:)

参考文献:

微软文档——Azure SQL 使用访问令牌进行认证

微软文档—使用 Azure 活动目录的 Azure SQL

微软文档—使用 Azure SQL 配置和管理 Azure AD 身份验证

微软文档—使用 Python 进行认证

如何使用 Bamboolib 进行无代码数据分析

原文:https://towardsdatascience.com/how-to-use-bamboolib-for-code-free-data-analysis-6cb5eae1dc37

利用这个 pandas GUI 来加速您的数据探索过程

埃里克·巴布在 Unsplash 上拍摄的照片

数据争论和探索性数据分析是数据科学过程中一些最重要但被低估的任务。大多数数据科学家都熟悉 Pandas——这是一个 Python 库,已经成为数据操作和分析的瑞士军刀。

虽然 Pandas 有许多有用的函数,但使用 Pandas 执行复杂的数据转换通常需要搜索 Stackoverflow 或浏览 Pandas 文档页面,以找到要运行的正确函数。对于那些了解 Excel 但不精通 Python 的人来说,Pandas 也是一个障碍。如果有一种方法可以通过 GUI 访问熊猫的功能,那会怎么样?这就是 Bamboolib 发挥作用的地方。

在本文中,我将演示如何使用一个基于 GUI 的 Python 库 Bamboolib 来加速 Pandas 数据分析过程。

安装 Bamboolib

您可以使用以下命令安装 Bamboolib 和 pip:

pip install bamboolib

一旦安装了 Bamboolib,您将需要使用 Jupyter 来访问 UI,如本教程的其余部分所示。只需使用 Anaconda navigator 或您的终端启动 Jupyter,并打开一个笔记本进行跟踪。你可以在 GitHub 上找到本教程的完整代码。

导入库

在下面的代码中,我导入了 Bamboolib 以及 Numpy 和 Pandas 进行数据分析。

import bamboolib as bam
import numpy as np
import pandas as pd

读取数据和访问 GUI

出于本教程的目的,我将使用经典的波士顿住房数据集,该数据集可通过 Scikit-learn 的数据集模块获得。

from sklearn.datasets import load_bostonboston_data = load_boston()df = pd.DataFrame(columns=boston_data['feature_names'],data=boston_data['data'])df['target'] = boston_data['target']
df

假设 Bamboolib 已经被导入,运行上面的代码将产生以下输出。

Pandas 输出带有显示 Bamboolib UI 的选项。

点击“显示 bamboolib UI”按钮后,将出现如下图所示的 Bamboolib UI。

Bamboolib 用户界面。

现在我们已经可以访问这个 UI 了,我们可以使用它来执行探索性的数据分析,并对我们的数据应用转换。

探索性数据分析

使用 Bamboolib 执行探索性数据分析(EDA)就像在 Bamboolib UI 中单击“Explore Dataframe”按钮一样简单。

用 Bamboolib 进行探索性数据分析。

如上面的 GIF 所示,“探索数据框架”按钮为我们提供了一个菜单,其中包含数据中每个要素的整体视图。选择一列后,我们可以访问以下选项卡:

  • 概述 —包含所选列的直方图和汇总统计信息。
  • 分类概述 —允许我们查看所选列中最常见的值以及这些值的累计计数。
  • 二元图 —允许我们根据数据集中的其他特征绘制所选列。
  • 预测值 —衡量其他特性预测所选列的值的能力。该选项卡对于检查特征和目标变量之间的关系很有用。

应用变换

Bamboolib 还有各种各样的转换,我们可以将这些转换应用于列,以便创建新的列。这个强大的特性允许您执行常见的 Pandas 转换,而无需编写任何代码!

宁滨时代专栏。

例如,在上面的 GIF 中,我演示了如何为 AGE 列创建一个带有 bin 的新列。Bamboolib 在用户界面中还有许多其他的转换,你可以在 Bamboolib 文档页面上阅读更多关于它们的内容。

创建地块

Bamboolib 还使我们可以轻松地创建图表来可视化我们的数据。如上面的 GIF 所示,只需点击 create plot 按钮,就会打开一个下拉菜单,其中有各种各样的绘图选项。

创建年龄列值的直方图。

Bamboolib 中的 plot creator 菜单允许我们基本上创建如上所示的交互式 Plotly plots。如果您正在构建标准地块,此功能可以为您节省大量时间。

导出代码

Bamboolib 的另一个有用特性是导出代码的能力。此功能类似于在 Excel 中记录宏。只要选择了实时代码导出选项,您就可以导出所有转换的代码,如下面的 GIF 所示。

在 Bamboolib 中导出转换代码。

我们也可以通过导航到 plot creator 选项卡并简单地使用 Show Code 和 Copy Code 按钮来导出绘图的代码,如下所示。

在 Bamboolib 中导出地块代码。

请记住,这篇文章只是对 Bamboolib 的介绍,要了解这个库的其他一些令人惊奇的特性,请查看官方的 Bamboolib 文档。

摘要

Bamboolib 是一个非常有用的库,它通过 GUI 让用户访问常用的 Pandas 功能,从而简化了数据分析和可视化过程。像往常一样,您可以在 GitHub 上访问本教程的代码。

加入我的邮件列表

加入我的邮件列表,获取我的数据科学内容的更新。当你注册时,你还会得到我免费的解决机器学习问题的逐步指南!也可以在 Twitter 上关注我,了解内容更新。

当你这么做的时候,考虑加入媒体社区,阅读成千上万其他作家的文章。

来源

  1. 8080 实验室, Bamboolib 文档,(2021)。

如何在 Python 中使用贝叶斯推理进行预测

原文:https://towardsdatascience.com/how-to-use-bayesian-inference-for-predictions-in-python-4de5d0bc84f3

图片由作者提供。

贝叶斯统计的美妙之处同时也是它最令人讨厌的特征之一:我们经常得到“嗯,这个数字介于……之间”的答案

一方面,这可能会让寻求直截了当的指导的商业战略家或决策者感到沮丧,但这也是一个了解你可能会犯多大错误的极好方法。

从一个简单的例子开始,假设我们的任务是找出高中教室里学生的身高分布。可能这个学校要求穿校服,校服公司希望对每个尺码的校服生产多少有所了解,了解身高分布可以让我们知道要做什么尺码。

贝叶斯推理基础

假设我们有一个变量, h ,表示这些学生的身高。如果我们想知道 h 是如何分布的呢?也就是说,我们可能已经有了一个分布的概念(身高通常是正态分布),但是这个分布的参数是什么呢?我们为什么要在乎?我们关心这个是因为知道一个变量是如何分布的有助于我们预测新数据会是什么样子。例如,如果我们知道身高是正态分布的,我们就知道一个新的数据点很可能接近平均值(如果平均值是 1.75 米,那么我们希望新加入班级的学生的身高接近该平均值)。知道分布的参数也允许我们从中取样(因此我们可以创建一个“假”学生的样本,从而知道我们可能期望的每个身高的学生有多少)。因此,找到一个变量的分布有助于我们解决预测问题。

贝叶斯推理是一种计算变量分布的方法(比如身高分布 h )。贝叶斯推断的有趣特征是,由统计学家(或数据科学家)使用他们的先验知识作为一种手段来改进我们对分布情况的猜测。

贝叶斯推理依赖于贝叶斯统计的主要公式:贝叶斯定理。贝叶斯定理接受我们关于分布如何的假设,一个新的数据,并输出一个更新的分布。对于数据科学,贝叶斯定理通常是这样表述的:

统计学家还给这个定理的每个组成部分起了名字:

让我们复习一下,以便更好地理解它们。

院长

从贝叶斯定理可以看出,先验是一个概率:P(θ)。首先,我们来深入探讨一下‘θ’是什么意思。θ通常表示为我们对模型的假设,该模型最好地描述了我们试图研究的变量。让我们回到高度的例子。我们根据背景知识和常识推断,身高在一个班级中呈正态分布。形式上:

h∞N(μ,σ)

其中 N 表示正态分布,μ表示平均值,σ表示标准差。

现在,我们的先验并不完全是上面的表达式。相反,这是我们对参数μ和σ如何分布的假设。请注意,这是贝叶斯统计的定义特征出现的地方:我们如何找到这些参数的分布?嗯,有趣的是,我们基于我们先前的知识“编造”它们。如果我们有很少的先验知识,我们可以选择一个非常不提供信息的先验知识,这样就不会对整个过程产生偏见。例如,我们可以定义μ(平均高度)在 1.65 米和 1.8 米之间。如果我们想获得一个无信息的先验,我们可以说μ沿该区间均匀分布。相反,如果我们认为平均高度稍微偏向于更接近 1.65 米而不是 1.8 米的值,我们可以定义μ分布为β分布,由“超”参数α和β定义。我们可以看看下面这些选项:

图片由作者提供。

请注意 y 轴是如何给出“概率密度”的,即我们认为 x 轴上的μ是真实值的可能性有多大。此外,请注意,β分布和均匀分布会导致我们对μ值的不同看法。如果我们选择均匀分布,我们说我们没有倾向于μ是否接近我们范围内的任何值,我们只是认为它在那里的某个地方。如果我们选择β分布,我们相当确定μ的“真实”值在 1.68m 和 1.72m 之间,如蓝线的峰值所示。

注意,我们讨论的是μ的先验,但我们的模型实际上有两个参数:N(μ,σ)。一般来说,我们也可以定义σ上的先验。然而,如果我们对σ的猜测感到幸运,或者为了举例而想简化过程,我们可以将σ设置为固定值,比如 0.1m。

可能性

似然性表示为 P(Data|θ)。这种情况下的“数据”是高度的观测值。假设我们要测量一个随机挑选的学生,他们的身高是 1.7 米。考虑到这个数据,我们现在可以对θ的每个选项有多好有一个感觉。我们通过提问做到这一点:如果θ的一个特定选项,称之为θ1,是正确的,我们观察到 1.7 米高度的“可能性”有多大?θ2 怎么样:如果θ2 是“正确的”模型,观察到 1.7 米高度的可能性有多大?

事实上,我们在这一阶段需要的是一个函数,该函数将系统地查看模型θ的每一种可能性,并找到该模型“产生”或“预测”观察值的概率。请记住,在这种情况下,我们的模型θ定义为 N(μ,σ),即具有均值μ和标准差σ的正态分布。我们还保持σ不变,以简化过程。因此,我们的函数将μ的可能值作为我们的“独立”变量,我们的观察数据点为 1.7m,它将输出每个模型是正确模型的概率作为我们的“因变量”。请注意,我们在这里遇到了一个小问题:一个特定模型是正确的“概率”在技术上是零,因为从理论上讲,θ的可能性是无限的。为此,我将θ的可能性离散化,使θ在 1.65 米和 1.8 米之间有 50 个选项。然后,我们使用每个建议模型的概率密度函数来评估特定模型的观测数据的概率密度。概率密度并不等同于概率,它只是给我们一个相对的度量,在给定每个模型选项的情况下,该点被观察到的可能性有多大。为了得到真实的概率,我们必须“标准化”概率密度,使得所有的值相加得到 1。

然而,这并没有什么大不了的,因为我们仍然可以比较每个模型的可能性。这就好像我们在问:将可能性限制在这个离散的模型集合中,这个集合在某种程度上全面地涵盖了似乎合理的可能性,哪个模型是最好的?然而,我们也要将概率密度标准化,正如你将在下面看到的。

这个函数被称为“可能性”函数,我们通常通过我们提出的模型的概率“密度”函数(PDF)来定义它,在新的数据点进行评估。因此,我们需要数据点 1.7m 的分布 N(μ,0.1m)的“PDF”

注意,对于以前用过 pdf 的人来说,这似乎有点落后。对于 pdf,我们通常有一个固定的模型,例如 N(1.8,0.1),我们使用它来评估变量 h 的不同值的概率。这意味着我们会在 x 轴上有变量 h ,在 y 轴上有概率密度。

然而,出于我们当前的目的,我们正在改变发行版/模型本身。这意味着我们的 x 轴实际上会有变量μ的不同可能性,我们的 y 轴会有这些可能性的概率密度。看看下面的代码,它代表了我们的可能性函数及其可视化:

图片由作者提供。

看看我们的函数如何简单地告诉我们μ的哪些值最有可能?看看这如何让我们对概率有一个相对的理解,统计学家更喜欢称之为每个可能μ的“可能性”?通过对可能性的评估,我们可以先发制人地判断μ的“最佳”值可能是多少。然而,我们随后必须将它与先验结合起来,以获得关于μ的最佳值的最终“猜测”。

证据

一些统计学家称 P( 数据)为“证据”。这个变量的含义非常简单:它是产生值数据的概率。然而,这很难直接计算。谢天谢地,我们有锦囊妙计。

考虑下面的表达式:

你能明白为什么有意义吗?直觉上,我们要说的是,如果我们要对每个假设θ的概率评估求和,我们会用尽所有的假设概率,我们应该只剩下 P(数据)。请注意,P(θ)是一个概率分布,如果我们将每个θ的所有输出相加,则 P(θ)等于 1。请注意,∫P(Data |θ)∫P(θ)dθ相当于求图的曲线下面积,其中 P(Data |θ)∫P(θ)在 y 轴上,θ在 x 轴上,下一步我们将完全这样做。

后面的

贝叶斯定理的右边 P(θ|数据)称为“后验”。这是我们对数据如何分布的事后理解,假设我们目睹了数据,并且我们有一个关于它的先验。

我们怎么找到后路?回到等式:

因此,第一步是将似然性(P(Data|θ))和先验(P(θ))相乘:

图片由作者提供。

我们可以看到,如果我们对非标准化后验概率密度求和,我们会得到一个不同于 1 的值:

请注意,我们仍然有“P(数据)”要处理,因此我称之为“非标准化后验数据”。

请记住上面的内容:

我们可以简单地计算这个积分,然后做最后的除法,我们得到后验概率。也就是说,多想想我们为什么要除以 P(数据)是件好事。请注意,计算 P(数据)等同于在上面的图表中找到未标准化的后验概率和 x 轴之间的面积。同样,因为后验概率分布是一个概率分布,所以后验概率密度函数所包围的面积总和必定是 1。为了确保这一点,我们必须找出曲线下的当前面积,然后将每个数据点除以该数字。这给了我们规范化的版本!

此外,请注意,解析计算积分非常具有挑战性。相反,我们可以依靠使用 scipy 和“梯形”方法的近似值,只需要 x 轴和 y 轴的值来估计面积。这是我在下面使用的实现:

图片由作者提供。

我们能验证这个新图形代表一个有效的 PDF 吗?请记住,在这种情况下,图表下的面积总和必须为 1。我们可以快速计算要检查值:

改进模型

注意,到目前为止,我们的贝叶斯推断经历了以下步骤:

  1. 定义我们的先验
  2. 定义我们的可能性函数
  3. 观察一个数据
  4. 使用贝叶斯定理来寻找后验分布(并使用梯形规则来归一化后验分布)。

在实践中,我们不会就此止步:观察一个数据可能不足以让我们对我们的模型有高度的信心!贝叶斯推理背后的思想是,它是迭代的,每个新的观察使我们更好地了解我们感兴趣的变量的“真实”分布。

那么,我们如何前进呢?接下来的步骤是:

  1. 观察新的数据点。
  2. 采用我们刚刚找到的后验概率,并将其作为我们的新先验概率!
  3. 使用相同的旧的似然函数,在给定这个新观察到的数据点的情况下,评估我们不同假设的似然性。
  4. 将我们新的先验值和似然值相乘,得到非标准化后验值。使用“梯形”规则来标准化后部。

然后,无论我们有多少数据点,我们都重复步骤 1 到 4!为了展示这一过程,让我首先生成 1000 个新数据点:

图片由作者提供。

看看随着我们获得越来越多的数据,我们的模型是如何越来越接近“真相”的?换句话说,我们模型的均值收敛到μ的真值,μ的真值是 1.7m,关于我们猜测的不确定性(即我们分布的标准差)缩小了!这意味着更多的数据=更准确和精确的猜测。

下面,我们可以看到数据数量的增加如何导致预测的平均值μ越来越接近μ的“真实”值 1.7m

图片由作者提供。

从代码中可以注意到,我使用了一个累积梯形函数来计算我们的后验概率输出的分布的平均值。我将让读者重新创建代码,并研究为什么以及如何有意义!

在这个阶段,我们剩下要做的就是获得我们模型的最终预测平均值(拥有最多数据的那个),并将其作为我们的“真实”模型。在观察了 1000 名学生的数据后,我们取最终平均值,并将其作为我们模型的平均值。此外,我们还可以得到 99%的置信区间,这有助于我们理解我们预测的均值有多“错误”。

图片由作者提供。

使用完成的模型

现在我们有了改进的模型,我们可以用它来做预测了!基于我们得到的最终模型,我们的模型被指定为:

  • N(μ,σ)
  • μ= 1.699 米
  • σ=0.1m

我们现在可以使用这个模型来回答潜在的有趣的业务相关问题!例如:

在一个 100 人的班级里,我们能指望有多少学生身高超过 1.75 米?

利用我们的分布,我们可以用两种方法来回答这个问题:第一种是分析方法。我们可以使用正态分布的累积密度函数来找出 1.75 米以下的密度,然后从 1 中减去该值以获得 1.75 米以上的密度:

这表明一个学生有大约 30%的可能性会高于 1.75 米。在一个 100 人的班级中,这意味着我们预计有 30 个学生会高于 1.75 米。我们可以通过模拟来回答这个问题。我们可以使用我们的模型对 100 名学生进行抽样,并计算有多少人身高超过 1.75 米:

然而,真正的贝叶斯统计学家很少只模拟一次。我们希望能够捕捉我们的不确定性和变化。因此,我们可以执行上述模拟一百次,并绘制分布图:

图片由作者提供。

在给定模拟的情况下,我们还可以找到我们的断言的 99%置信区间,这是该方法的一个重要优势:

图片由作者提供。

利用我们的模拟平均值和界限,我们现在可以很好地了解我们预计有多少学生身高超过 1.75 米。例如,如果我们需要了解这些信息以便生产校服进行销售,我们可以采取保守的方法生产 40 套大号校服,我们预计在 99%的情况下我们将有足够的校服进行销售。这有助于我们知道我们想要多少冗余。尽管生产 30 套大型制服可能不会有出错的余地,但一个更有趣的问题是:我们应该留多少出错的余地?在贝叶斯统计和贝叶斯推理的帮助下,我们可以找到该类型问题的非常令人信服的答案!

Python 编程中如何使用 break、continue 和 pass

原文:https://towardsdatascience.com/how-to-use-break-continue-and-pass-in-python-programming-9cd841763b3c

Python 编程

了解如何、何时以及为什么在 Python 中使用 break、continue 和 pass

https://pix abay . com/photos/bulletin-board-stickies-post-it-3127287/

Python——灵活——是自动化和高效完成重复任务的最佳解决方案!

在 Python ( 和其他编程语言也是)中,循环的概念有助于遍历列表、元组、字符串、字典和集合。

循环迭代一段代码,直到测试表达式为假,但有时我们希望终止当前的迭代,甚至整个循环,而不检查测试表达式。

这可以通过使用几个关键字来实现,这些关键字可以用来改变循环的流程或执行。在 Python 中,这些关键字是— 中断、继续、通过。💡

并且知道何时以及如何使用这些关键字来正确地控制你的循环流是很重要的!

因此,在本文中,我将讨论(通过示例)Python 中的何时-为什么-如何中断、继续和传递。

这些关键字背后的概念是相同的,与编程语言无关!

我们开始吧!

Python 中的 break 语句

Python 中的**break**语句终止了包含它的循环。

举个例子,

for num in range(0,10):if num == 5:breakprint(f'Iteration: {num}')

上面的 for 循环生成输出,

作者图片

这里我们添加了if语句检查一个条件,当该条件为真时,程序流将进入 if 语句并执行break语句。

因此,for 循环一直执行到条件num == 5为真,当条件为真时,执行 break 语句终止for循环的流程。

更进一步,让我们在现有的 for 循环之外再添加一个for循环,如下所示。

for k in range(0,5):print(f'Outer For Loop Iteration: {k}')for num in range(0,10):if num == 5:breakprint(f'--Inner For Loop Iteration: {num}')

根据定义,当条件为真时,break 语句将终止包含它的 for 循环。

嵌套 for 循环| Image by Author 中的 break 语句

从上图中我们可以看到,对于外部 for 循环的每一次迭代,内部循环的流程都会在 5 次迭代后根据条件num == 5中断

因此,如果break语句在嵌套循环中(另一个循环中的循环),那么break语句将终止最里面的 循环 。🎯

一个真实的例子是,使用密码解锁我们的智能手机。从技术上讲,手机解锁过程是一个for循环,不断要求输入密码。当输入正确的密码时,**break**语句被执行,for循环被终止!

下面是带代码的解释,

Python 中 break 语句的真实示例|作者图片

在上面的例子中,我认为 Python 是正确的密码。当条件password == ‘Python’变为时,执行 break 语句,for 循环终止!

Python 中的 continue 语句

**continue**语句用于仅在当前迭代中跳过循环中的剩余代码。

举个例子,让我们在上面的例子中使用 continue 而不是 break 语句。

for num in range(0,10):if num == 5:**continue**print(f'Iteration: {num}')

在 Python 中继续|作者图片

当条件num == 5为真时,执行continue语句。根据其定义,循环中的剩余代码仅在该迭代中被跳过。这就是为什么上面的输出中没有Iteration: 5的原因。

因此,**continue** 语句的工作方式与break语句相反,它不是终止循环,而是强制执行循环的下一次迭代。

Python 中的 pass 语句

顾名思义,**pass**语句什么都不做。

当一个语句或条件需要出现在程序中,但我们不想执行任何命令或代码时,就使用它。

例如,用 pass 语句替换上面示例中的 break。

for num in range(0,10):if num == 5:**pass**print(f'Iteration: {num}')

按作者传入 Python |图像

正如我们在上面的输出中看到的,pass语句实际上什么也没做,因为for循环和其中的所有语句都被执行了!

pass语句通常在创建方法时使用,我们现在不想使用它。

pass 语句用于作为未来代码的占位符!!

大多数时候,pass语句被替换为程序中其他有意义的命令或代码。

传递和继续之间的区别

当然,pass 和 continue 之间有很大的区别,它们是不可互换的。✅

continue强制循环从下一次迭代开始,而pass表示“这里没有要执行的代码”,并将继续循环体的剩余部分。

下面是对这种差异的快速解释,

for num in range(0,5):passprint(f'Iteration: {num}')print("This statement is after 'pass'")continueprint("This statement is after 'continue'")

继续并传入 Python 编程|作者图片

在上面的输出中,在for 循环的每次迭代中,前两条打印语句总是被执行,即使它们在pass语句之后。这意味着,**pass**什么也不做,循环的流程不会中断。

但是,continue语句之后的 print 语句没有被执行,因为关键字**continue**强制 for 循环开始下一次迭代。

总结一下,🚀

一个简单的例子将更有助于理解 Python 中的传递、继续和中断工作的方式!

如何在 Python 中使用 pass、continue 和 break | Gist by Author

Python 示例中的传递、继续和中断|作者图片

正如你在上面的输出中看到的,在pass之前和之后的所有东西总是被执行,表明关键字pass什么也不做。

另外,只执行continue关键字之前的行,表示continue总是强制 for 循环开始下一次迭代,不执行当前迭代中关键字continue之后的任何内容。

最后,执行break之前的行,for 循环的流程在第三次迭代时终止。这解释了break 语句是如何用来停止进程的。

我希望你觉得这篇文章很有趣,并且对你有用!

现在使用 我的链接 只需 1 分钟即可成为中等会员。当你这样做的时候,我会得到你的一小部分费用,你会得到一个无限制的访问权限😎敬所有关于 Medium 的文章!

还有,如果你喜欢看这么惊艳的内容,欢迎随时加入我的 邮箱列表

感谢您的阅读!

如何在数据可视化中使用调色板

原文:https://towardsdatascience.com/how-to-use-color-palettes-for-your-data-visualization-ac4eaf3de37b

数据可视化-教程-颜色

Seaborn、Altair 和 ggplot2 (R)的分步调色板教程

如何在 R 和 Python 中使用调色板——作者根据照片制作的图片 Jason Leung

介绍

我喜欢可视化数据。为此,我仔细研究了数据旁边的实用和令人愉快的颜色,以及适合任何数据可视化项目的图表。如果项目或客户没有确定颜色,我会花几个小时浏览和选择颜色。

当谈到选择完美的图形或颜色时,你可以倾向于你的艺术神经或尝试非常实际。或者介于两者之间。大多数情况下,不把你的图表设计得尽善尽美是不容易的。

在这篇文章中,我想分享我在寻找实用和精彩的调色板方面的资源,向您介绍一个适用于 R 和 Python 的调色板包,并向您展示如何将它应用于 ggplot2、Altair 和 Seaborn。请注意,我在这篇文章中使用术语“颜色”是为了让自己更容易理解,而实际上,我们需要区分色调、饱和度和亮度。

调色板

考虑在数据可视化中使用颜色有几个原因。

  1. 品牌识别:你的读者应该自动识别公司或组织
  2. 可读性:你的读者应该很容易区分数据可视化的不同部分。你想寻找高对比度的颜色,很容易区分开来。此外,记住我们感知颜色的方式不同。
  3. 编码含义:如果你想把经常与特定颜色联系在一起的政党形象化。此外,如果你要可视化数值,考虑一个特殊的底纹,从低到高,从浅到深。反之亦然。

数据类型

使用调色板时,您还需要考虑要可视化的变量类型。对于分类变量,比如城市或国家名称,你需要一个离散的调色板。

对于序数变量,如客户评级或排名,选择编码低/高含义的调色板,如交通灯颜色红色、橙色和绿色。对于数字变量,如人口或价格,考虑一种带有渐增或渐减阴影的颜色。

调色板的类型;奥赫托的图像;来源: Seaborn 文档

资源

请考虑以下网站列表来找到您的调色板:

  • https://colorhunt.co/
  • 【https://coolors.co/ 号
  • 【https://colorpalettes.net/
  • https://www.canva.com/colors/color-palettes/
  • https://color.adobe.com/de/create/color-wheel
  • https://mycolor.space/
  • http://colormind.io/

我最喜欢的套装由许多不同的调色板组成,是由 BlakeRobMills 生产的 MetBrewer。

灵感来自纽约大都会艺术博物馆的作品。所有的作品都来自不同的时期、地区和媒介。如果你对某一件有任何要求,请告诉我。

MetBrewer 的 Cross Color Palette,众多可用调色板之一;图片由开源项目[ 链接

示例数据和图表

Gapminder 软件包

我将使用由 Gapminder 提供的数据,或者更实际的,利用 Gapminder R 包和 python 包。它包括两个分类变量:洲和国家,以及四个数值:年、预期寿命、人口和人均 GDP。

Gapminder 数据集概要;作者图片

Gapminder 数据集的前六个条目;作者图片

示例图表

为了应用调色板,我简要介绍了下面的图表。我用 r 编写了这些代码。您将在下面相应的章节中找到 python 代码。第一张图显示了人均国内生产总值和预期寿命这两个数值的分布情况。最后一个是箱线图,也显示了各大洲的人均 GDP 数据。

**

使用的图 Gapminder 数据集-作者提供的图像

使用 ggplot2 应用调色板

首先,我们需要安装和加载所需的包。

然后以人均 GDP 为 x 轴,预期寿命为 y 轴,绘制点状图。我还将使用数字变量人口来控制每个点的大小。

点图 01-人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

为了在图中使用颜色,我将人口变量分配给颜色美学。因为我没有指定任何其他内容,所以 ggplot2 为这个数值变量选择了一个色谱(蓝色阴影)。

点图 02-人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

为了控制色谱,我们需要引入色标。在下面的图中,我提供了一个十六进制颜色值的向量。如果你从上面提到的一个网站得到你的颜色,你会选择这个。

点图 03-人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

为了应用 MetBrewer 调色板中的一个,用 MetBrewer 函数替换十六进制向量。在函数调用中,您提供调色板的名称,然后是几种颜色,并告诉它我们需要一个连续的调色板,因为它是一个数字变量。

点状图 04-人均 GDP 预期寿命 Gapminder 数据集-图片由作者提供

你可能还想使用调色板和非数字变量。让我们假设我们想要将颜色应用于 Continent 变量。这意味着使用手动色标并提供 MetBrewer 调色板。

点图 05-人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

请注意,如果要将颜色应用于填充美学而不是颜色美学,请考虑使用 scale_fill_manuel 函数而不是 scale_color_manuel 函数。这对于箱线图或条形图很有用。

箱线图 06-人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

用 python-Altair 应用调色板

我使用方法链接编写 python 代码。这篇文章解释了这一点:“蟒蛇/熊猫的完美管道”。要安装 MetBrewer 和 Altair ,我请参考他们各自的网站。

首先导入必要的库。

然后构建图表。请注意最后关于颜色的陈述。首先,我将颜色映射到人口变量。第二,我操纵传奇的标题。最后,我将刻度及其范围属性设置为一个 MetBrewer 调色板(即十字)。

Altair Point Plot 01 人均 GDP 预期寿命 Gapminder 数据集-图片由作者提供

如果您想要将分类变量映射到颜色美学,只需更改颜色映射中的比例函数。

Altair Point Plot 02 人均 GDP 预期寿命 Gapminder 数据集-图片由作者提供

使用 Altair,您不需要像在 ggplot2 中那样区分颜色和填充。这是箱线图的例子。

牛郎星方框图 03-人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

使用 python-Seaborn 应用调色板

Seaborn 是一个出色的 python dataviz 库,它提供了大量的颜色功能。阅读官方文章“选择调色板”了解更多信息。

首先,让我们导入必要的库。

然后构建图表。请注意我将调色板设置为 MetBrewer 调色板之一的第一个语句。由于 Seaborn 是在 matplotlib 的基础上构建的,我们进行了不止一次的函数调用来构建情节,即设置标签和图例文本。

Seaborn Point Plot 01 人均 GDP 预期寿命 Gapminder 数据集-图片由作者提供

不幸的是,尽管使用了相同的调色板,我还是无法再现 Altair 或 ggplot2 中的调色板用法。下一个图显示了如何为大陆变量使用颜色。

Seaborn Point Plot 02 人均 GDP 预期寿命 Gapminder 数据集-图片由作者提供

最后,关于 Seaborn 的箱线图的代码。我使用离散调色板来填充图中的方框。

Seaborn Box Plot 03 人均国内生产总值预期寿命 Gapminder 数据集-图片由作者提供

结论

在这篇文章中,我想分享我在寻找实用和精彩的调色板方面的资源,向您介绍一个适用于 R 和 Python 的调色板包,并向您展示如何将它应用于 ggplot2、Altair 和 Seaborn。

请注意,我是一个仍在学习和努力提高的从业者。所以请给我留下你的想法和想法。

如果你想了解更多关于我的旅程,请考虑跟随我,或者如果你不是一个媒体成员,请考虑加入这里。非常感谢。

格雷戈尔

如何使用 cumsum()解决 Python 优化问题

原文:https://towardsdatascience.com/how-to-use-cumsum-to-solve-python-optimization-questions-ab73f617a347

来自高盛的这个非常有趣的 Python 面试问题是一个关于优化的数据科学面试问题大家庭的一个很好的例子。了解如何使用累加和运算符来解决此类问题。

作者在 Canva 上创建的图片

Python 优化问题

最小平台数

这个问题的标题是最小站台数,它说我们在一个火车站有一天的列车预定出发和到达时间。还规定了一个站台只能容纳一辆列车,从它预定到达的时刻开始,直到它预定离开的时刻结束。然后,我们被要求找到容纳全部预定流量所需的最少站台数。

截图来自 StrataScratch

问题链接:https://platform . stratascratch . com/coding/2082-最小平台数

这是一个很难的问题,因为不容易计算出如何从列车时刻表中提取最少的站台数。由于数据分布在两个不同的表中,这就更加复杂了。关键问题是设计一个不仅正确,而且高效快速的解决方案——这是使用累积和可以帮助我们实现的。

了解您的数据

通过理解提供的数据来开始解决面试问题总是好的。在实际采访中,您通常只会看到表及其列的高级描述,因此更多的是了解数据的结构,而不是看到实际的记录。

截图来自 StrataScratch

正如已经提到的,这个问题的数据分布在两个表中,但是让我们看看这里到底发生了什么。有两个非常简单的表,每个只有两列。第一个表表示火车到达,因此我们有每辆火车的 ID 和它到达我们车站的时间。类似地,第二个表表示火车出发,它再次具有火车的 ID 和象征出发时刻的时间。

这个问题指定了一个站台只能容纳一列火车,从它预定到达的时刻开始到它预定离开的时刻结束,所以我们可以假设两个表中的时间都是小时和分钟,就像我们从标准火车时刻表中所期望的那样。

使用累积和来解决这个 Python 优化问题

在开始编写代码之前,让我们看看可以采取什么方法来解决这个 Python 面试问题。实际上有多种可能的方法。由于这只是一天的数据,我们可以循环一天中的所有时间,虚拟模拟整个时间线,计算一天中每个时刻所需的平台数量,并最终选择最高值。另一个解决方案是遍历数据集两次,这样对于每一个训练,我们将得到一个与它重叠的所有其他训练的列表,并使用最大列表的大小作为答案。然而,这两种方法都过于复杂且计算昂贵。

在本文中,您将学习一个更短、更有效的解决方案,它可以使用累积和来解决这个问题和其他类似的优化问题。累积总和有时称为累计总和,是一种数学运算,对于一个数字序列,它返回另一个长度相同的序列,其中 k 值是原始序列中元素 1 到 k 的总和。

在 Python 中,累积和是一种操作,我们可以使用 Pandas 库中的函数 cumsum()将它应用于数据集。举个例子,下面的代码创建了一个空的 DataFrame,这就是我们在 Pandas 中所说的数据表,并使用一个 range 函数添加了一个填充了从 0 到 9 的值的列。

numbers = pd.DataFrame(range(10))

然后,我们可以创建一个新列,返回这个数字序列的累积和。这是通过对原始序列应用函数 cumsum()来实现的。

numbers[ 'Cumulative Sum' ] = numbers.cumsum() numbers

截图来自 StrataScratch

原始序列的顺序非常重要,因为这也决定了在累积和中计算和的顺序。运行下面的代码,看看如果我们添加一个数字与之前相同但顺序相反的新列,并将累积和应用到这个新列会发生什么。

import pandas as pdnumbers = pd.DataFrame(range(10))
numbers['Cumulative Sum'] = numbers.cumsum()
numbers['reversed'] = list(reversed(range(10)))
numbers['Cumulative Sum 2'] = numbers['reversed'].cumsum()
numbers

更重要的是,当我们在原始序列中同时包含正值和负值时,累积和的结果将是一个既增加值又减少值的序列。将上面代码中的代码替换为以下 3 行代码,以查看输出:

numbers = pd.DataFrame([2,3,-5,3,-8,-2,7])
numbers['Cumulative Sum'] = numbers.cumsum()
numbers

这种情况在优化任务中非常有用,例如 Python 优化问题,每当我们需要分析随时间变化的数字时,无论是车站的列车数量还是公司的员工数量。

因此,我们可以用它来解决高盛的这个面试问题。但是在我们实际应用 cumsum()函数到数据集之前,我们需要创建一个新的列,作为累积和的基本序列。所以解决这个问题的第一步将是数据准备。

具体来说,我们可以用数字 1 标记所有到达的火车,用数字-1 标记所有离开的火车。由于到达和离开仍然在两个不同的表中,我们可以将一个表附加到另一个表的底部,以创建一个时间表。

至此,我们只剩下一长串到达和离开的火车。每一行代表一次到达或离开,并用值 1 或-1 标记。你能看出这些 1 和-1 值是如何帮助我们解决这个问题的吗?由于每个值 1 表示车站多了一列火车,每个值-1 表示少了一列火车,因此我们可以应用累积和来查看车站的火车数量在一天中的变化情况,并提取车站的最高火车数量。

但是在我们将 cumsum()函数应用于本专栏之前,还有一个问题需要解决。正如我所展示的,当使用累积和时,排序是非常重要的,所以让我们在继续之前对数据集进行排序。因为我们想知道数字是如何随时间变化的,所以我们需要使用 time 列按时间顺序对所有的到达和离开进行排序。

只有现在我们才能应用 cumsum()函数。再一次,累计总和将告诉我们,对于表中的每个时间戳,此时有多少列车在车站。从那里,提取解决方案变得微不足道。累计求和结果基本象征着需要多少平台。这个数字在一天中随着火车的到达和离开而波动。因此,为了找到平台的最小数量,我们只需要从累积和中选择最大值。

代码执行

作者在 Canva 上创建的图像

一旦我们定义了所有这些高级步骤,是时候将它们转换成 Python 代码了,该代码将实际返回这个最小数量的平台。第一步是用 1 标记到达,我们可以通过获取数据帧或表 train_arrivals 并在其中创建一个新列来实现,我们称之为“标记”。该列的每一行都需要有一个值 1,但是在 Python 中,它应该等于 1 就足够了。

train_arrivals['mark'] = 1
train_arrivals

一旦执行了这段代码,结果就会有一个新的列,其中填充了值 1——正如我们所预期的那样。接下来,我们可以做一件非常类似的事情,用-1 标记偏离。这一次,让我们以 train _ departures 数据帧为例,再次向它添加一列。该列的名称需要与 train_arrivals 中的名称相同,因为我们在那里使用了“marks ”,所以我们也需要在这里使用它。然后,再补充一句,这个应该等于-1 就够了。

train_departures['mark'] = -1
train_departures

在追加两个数据帧之前,我们需要确保两个数据帧中的所有列名都相同。除了具有不同名称的列 arrival_time 和 departure _ time 之外,几乎都是如此。因此,在继续之前,我们需要重命名这两列,使它们具有相同的名称。由于这些列仍然在两个不同的数据帧中,我们将需要两个类似的行来一次一个地更改它们的名称。为此,我们可以应用 Pandas rename()函数,在该函数中,我们需要指定我们希望专门处理列名。然后,我们可以使用您可能从 Python 字典中了解到的键-值语法,即当前名称 arrival_time 应该替换为另一个名称,比如“time”。然后可以应用相同的逻辑来更改 train _ departures 表中的列名。

train_arrivals = train_arrivals.rename(columns={ 'arrival_time' : 'time' }) train_departures = train_departures.rename(columns={ 'departure_time' : 'time' })

现在我们准备将一个表追加到另一个表中。这听起来可能很复杂,但实际上是一个简单的操作,从一个数据帧中取出行,然后将它们添加到另一个数据帧的底部。在 Python 中,我们可以像这样简单地使用 append()函数,指定函数外部的第一个数据帧和第二个数据帧作为它的参数。因为这将导致所有的到达和离开都在一个单一的数据帧中,让我们称之为“时刻表”。

*# Mark arrivals with 1s*
train_arrivals['mark'] = 1
*# Mark departures with -1s*
train_departures['mark'] = -1*# Match column names in both DataFrames*
train_arrivals = train_arrivals.rename(columns={'arrival_time': 'time'})
train_departures = train_departures.rename(columns={'departure_time': 'time'})*# Append one table to another*
timetable = train_arrivals.append(train_departures)

现在在我们的数据框架“时刻表”中,我们首先有所有的到达,然后是所有的离开。所以下一步是按时间顺序对事件进行排序。为此,我们可以使用 Pandas sort_values()函数。在括号内,我们可以指定我们希望按时间列和升序排序——这相当于从最早的时间到最近的时间,或者简单地说,按时间顺序。添加以下代码,查看行的顺序是如何变化的。

timetable = timetable.sort_values(by='time', ascending=True)

在这里,重要的是再提一件事。可能会出现一列火车同时到达和一列火车同时离开的情况。例如,这发生在 8:10。在这些情况下,我们需要确保这些事件的顺序也是正确的,否则,结果可能会不同。在这种情况下,问题是一个站台只能容纳一辆火车,从它预定到达的时刻开始,直到它预定离开的时刻结束。这就意味着我们可以想象到站的列车在 8:10:00 进站,出站的列车在 8:10:59 出站。

因此,在这种情况下,进站列车排应始终在出站列车排之前。为了反映这一点,我们可以修改我们的 sort_values()函数,按照时间和标记进行排序。但在我们的情况下实际上没有必要。这是因为之前我们将 train _ departures 数据帧附加到 train_arrivals 数据帧的底部,这样可以自动对出发前的到达进行排序。这就是为什么有时我们添加数据帧的顺序也很重要。

继续我们的解决方案,现在我们可以使用我们的秘密武器,将累积和应用于“标记”列。同样,在 Python 中,我们可以使用函数 cumsum()并将其应用于这样的列。我们可以将累积和的结果存储在一个新的列中,让我们称之为“n_trains ”,因为它代表了每次该数字变化时车站的列车数。

timetable['n_trains'] = timetable['mark'].cumsum() 

截图来自 StrataScratch

当我们运行这段代码时,您可以看到带有累计和的新列。正如我们所预料的那样,每当一列火车到站时,这个总数就增加,而随着每一列火车的离开,这个总数就减少。这也显示了车站有多少趟列车。

因为根据问题,一个站台只能容纳一辆列车,所以处理该列车交通所需的最少站台数量将等于同时在车站的最多列车数量。或者换句话说,是 n_trains 列中的最大值。要提取它,我们可以简单地使用 max()函数,这是这个 Python 面试问题的完整解决方案和答案。

*# Mark arrivals with 1s*
train_arrivals['mark'] = 1
*# Mark departures with -1s*
train_departures['mark'] = -1*# Match column names in both DataFrames*
train_arrivals = train_arrivals.rename(columns={'arrival_time': 'time'})
train_departures = train_departures.rename(columns={'departure_time': 'time'})*# Append one table to another*
timetable = train_arrivals.append(train_departures)*# Sort the events chronologically*
timetable = timetable.sort_values(by='time', ascending=True)*# Calculate cumulative sum from 1 and -1 values*
timetable['n_trains'] = timetable['mark'].cumsum()*# Select maximum value from cumulative sum*
result = max(timetable['n_trains'])

结论

在本文中,您可以学习如何使用累加和来解决 Python 中的优化问题。这只是这个问题的一种可能的解决方案,但是如上所述,还有其他的方法和解决方案。我们的建议是,通过构建问题的解决方案来练习回答面试问题,但总是试图想出其他解决问题的方法,也许你会想到一个更有效或更复杂的方法。还要记住,这个问题只是众多优化问题中的一个例子,许多优化问题都可以用类似的方式解决。

如果你想在亚马逊、谷歌、微软等顶级公司的数据科学面试中练习更多的 Python 问题。,查看我们在【30 强 Python 面试问答】 上的帖子。

最初发表于【https://www.stratascratch.com】

如何在带有 Keras 的 TensorFlow 中使用带有自定义梯度的自定义损失

原文:https://towardsdatascience.com/how-to-use-custom-losses-with-custom-gradients-in-tensorflow-with-keras-e87f19d13bd5

解释文档没有告诉您的内容的指南

上传者:来自德语维基百科的 Eleassar。、CC BY-SA 3.0、via Wikimedia Commonshttps://Commons . Wikimedia . org/wiki/File:Meerkatmascotfull _ BG _ F7 F8 ff . png

简介

Keras 在抽象神经网络创建的底层细节方面做得很好,因此您可以专注于完成工作。但是,如果你正在阅读这篇文章,你可能已经发现,Keras 现成的方法并不总是能够用来学习你的模型的参数。也许你的模型有一个无法通过 autodiff 的魔力计算的梯度,或者你的损失函数不符合 Keras 的文档中提到的签名my_loss_fn(y_true, y_pred)。如果您发现在线文档完全没有帮助,请继续阅读!我[希望]有你在其他地方找不到的所有答案。

放弃

我不保证把我所有的解释都钉死;我不认为自己是 TensorFlow/Keras guru。我在这里写的所有内容都参考了许多不同页面的 TensorFlow/Keras 文档和一些源代码检查。如果你有改正或改进的建议,我鼓励你在评论中留下它们,让每个人受益!最后,TensorFlow 是 Google LLC 的商标,本文既不被 Google LLC 认可,也不以任何方式隶属于 Google LLC。

学习目标

阅读完本指南后,你将理解如何使用 Python 中的自定义子类化 Keras Layer来创建自定义子类化 Keras Model对象。您将能够编写自己的自定义损失函数,这些函数与 Keras 的文档中描述的http://archive.ics.uci.edu/ml不一致。您还可以将自定义渐变与自动微分(autodiff)算法结合使用,以优化模型的可训练参数。

本指南将展示什么?

本指南将最终展示你如何仍然可以使用自定义损失和自定义梯度,而不必放弃方便的keras.Model.fit方法来训练你的神经网络。

在本指南中,我们将创建具有单一密集层和逻辑回归输出层的神经网络模型。原始数据将被输入到密集层,密集层的输出将被输入到逻辑回归层进行二元分类。本指南不包括验证或模型测试;它将只涵盖在训练集上构建和拟合模型所涉及的步骤。

让我们开始吧。

加载(或创建)数据集

我们将使用开放访问[german_credit_numeric](https://www.tensorflow.org/datasets/catalog/german_credit_numeric)数据集,它可以通过 tensorflow_datasets 库下载。它由 24 个特征的 1000 个例子组成,与“好”(1)或“坏”(0)的二元信用风险评估相关。

import tensorflow as tf
import tensorflow_datasets as tfdsfrom typing import Optional@tf.function
def sigmoid(x: tf.Tensor) -> tf.Tensor:return 1 / (1 + tf.exp(-x))if __name__ == "__main__":ds = tfds.load("german_credit_numeric", split="train", as_supervised=True)ds = ds.shuffle(1000).batch(100).prefetch(tf.data.AUTOTUNE)

创建自定义 Keras 层

在我们构建模型之前,我们应该构建它的组件。回想一下,该模型将由一个密集图层组成,该图层将我们数据集中观察到的要素转换为潜在表示,该潜在表示将作为逻辑回归输出图层的输入。为了演示如何混合和匹配定制和预构建的 Keras Layer,我们将使用 Keras 的内置keras.layers.Dense类来构建模型的第一层,并通过子类化keras.layers.Layer为逻辑回归构建我们自己的定制层类。

让我们分解一下客户物流层。

*get_config*方法

*对于该层的工作来说,get_config方法并不是绝对必要的,但是如果你想创建一个所谓的“可序列化”的层,可以与 Functional API 一起使用,那么它是必要的。您可以使用get_config方法来获取重新创建图层所需的属性。参见文档。

**build*方法

get_config方法一样,build方法不是层工作所必需的,但它是定义层的可训练参数(即权重、偏差)的推荐方法。使用build方法,参数创建被推迟,直到用一些输入数据第一次调用该层。build方法通过input_shape参数获得输入的形状(可能事先不知道),并根据input_shape创建图层的参数。例如,如果层的call方法的inputs参数是一个张量元组,Keras 会将一个TensorShape对象数组分配给input_shape(输入张量中的每一项对应一个对象)。建议使用 build 方法,因为它允许即时创建权重,即使您事先不知道输入形状。

**call*方法

该方法通过层计算输入的正向传递。这里,它返回
逻辑回归的概率输出。

在我们定义模型类之前,让我们实例化代码主体中的输入层和密集层:***

 **features_spec, labels_spec = ds.element_spec
del labels_spec  # Not usedfeature_inputs = tf.keras.Input(type_spec=features_spec, name="feature_inputs")
dense = tf.keras.layers.Dense(units=4, name="dense_layer")**

请注意,我们创建了一个Input对象feature_inputs,它期望一个具有五个分量的向量值张量(即一个具有 24 个特征的训练示例)。dense图层将计算仅包含四个特征的输入的潜在表示。由于我们使用潜在表示作为逻辑回归的输入,Logistic层将有四个可训练的权重(每个输入特征一个),以及一个单一偏差。还要注意,我们没有实例化一个Logistic层。我们将把它留给自定义的Model对象。

创建模型

这是指南的症结所在。我们将创建一个keras.Model的子类,它有一个定制的训练循环、损失函数和渐变。

损失函数将是给定
相关特征的目标标签的负对数可能性。最小化负对数似然的权重和偏差是逻辑回归模型的最佳参数。换句话说,如果目标标签由我们的神经网络建模,我们将最大化在给定相关特征的情况下观察到目标标签的概率。这是概率机器学习中常见的损失函数。为了在神经网络模型下最大化数据集的对数似然性(等价地,最小化负对数似然性),我们需要找到最优的权重和偏差。我们使用梯度下降的一些变体来寻找最优值(选择你最喜欢的方法)。当然,这需要计算负对数似然损失相对于模型可训练参数的梯度。

使用负对数似然作为我们的自定义损失函数在 Keras 中提出了一些挑战。首先,负对数似然损失不一定符合 Keras 文档为定制损失函数建议的签名my_loss_fn(y_true, y_pred);在我们的例子中,它是输入特征和目标标签的函数。因此,我们不能简单地为负对数似然定义一个自定义损失函数,并在训练模型时将其作为参数传递给Model.fitloss参数。其次,并不是所有基于可能性的损失函数都有可以被 autodiff 算法“神奇地”解决的梯度,在这种情况下,您需要告诉 TensorFlow 如何精确地计算梯度。当损失函数不符合 Keras 建议的特征时,事情变得有点复杂。最后,通常会有一些早期图层学习训练示例的观察特征的潜在表示,如果 autodiff 可用于求解这些图层的梯度,我们希望使用它,仅在必要时定义自定义梯度(这是一项大量工作!).

让我们定义一个keras.Model的子类来克服这些挑战。首先我会给出代码,然后我会解释各个部分。

keras 的一个亚纲。使用带有非标准签名的自定义损失函数以及自定义梯度和自动微分梯度的模型

让我们来分解一下这个模型。

****__init__*方法

该模型被设计成接受早期的层块nn_block,其学习原始输入数据的潜在表示。在本指南中,nn_block 将是keras.layers.Dense的一个实例,但它可以是任何keras.layers.Layer对象。如果您只想对原始输入数据执行逻辑回归,也可以完全省略它。

模型自动初始化一个Logistic层,该层输出一个单一值(units=1),该值表示给定输入特征的标注概率。***

**最后,每个样本的平均损失由loss_tracker跟踪。

损失函数

这里的目标是定义一个损失函数,它允许我们使用 autodiff 来计算相对于Dense层的可训练参数的损失梯度,但是对Logistic层的参数使用自定义梯度计算。为此,我们必须将损失计算中涉及自定义坡度参数的部分与涉及自动挖掘参数的部分分开。隔离是通过将自定义组件的函数嵌套在更广泛的损失函数中实现的,该损失函数提供了从模型输入到模型输出的完整路径。通过这个路径,所有层的可训练参数都可以被优化。

我们先来关注一下内部函数,logistic_loss(x, y),先。第一个参数,x,代表Logistic层的输入张量(即来自之前Dense层的输出)。第二个参数y表示训练示例的真实标签。该函数隔离了损失计算中涉及我们希望通过自定义梯度学习的参数的部分。@tf.custom_gradient装饰器向 TensorFlow 发出信号,使用自定义公式代替自动 diff 来计算相对于装饰器范围内可训练参数的损失梯度。因此,为装饰器范围内的所有可训练参数指定一个自定义渐变是很重要的。这就是为什么我们根据对Logistic层的输入而不是对更早层的输入来定义logistic_loss:我们有效地将装饰器的范围限制在我们希望使用自定义梯度来学习的权重和偏差,并将其余的梯度计算留给自动挖掘。

自定义渐变在logistic_loss内部定义,由
装饰器要求(详见 TensorFlow 文档)。

外部函数loss_fn将训练数据(或验证/测试数据)中的原始特征和目标标签作为输入。注意,我们没有用tf.custom_gradient装饰器包装外部的loss_fn。这确保了自动识别用于计算不在logistic_loss范围内的剩余参数的损失梯度。外部函数返回由内部logistic_loss函数计算的负对数似然。

您可能已经注意到,只有Logistic层的输入才是计算输入批次的负对数似然损失所必需的。那么为什么要大费周章地将logistic_loss嵌套在外层loss_fn中呢?如果您去掉外部函数,转而使用logistic_loss作为总损失函数,TensorFlow 将警告您,相对于致密层参数的损失梯度不再定义。那是因为我们没有在@tf.custom_gradient装饰器下定义它们。逻辑层的参数将被训练,但是密集层的参数不会从它们的初始值改变。

**train_step*方法

该方法由Model.fit 方法用来更新模型参数和计算模型指标。正是定制模型对象的组件让我们可以使用高级的Model.fit方法来定制损失和渐变。GradientTape上下文管理器跟踪loss_fn的所有梯度,在不使用自定义梯度计算的情况下使用 autodiff。我们使用tape.gradient(loss, self.trainable_weights)访问与可训练参数相关的梯度,并告诉优化器对象使用这些梯度来优化self.optimizer.apply_gradients(zip(grads, self.trainable_weights))中的参数。最后,训练步骤用训练批次的平均损失(由loss_fn计算)更新loss_tracker。***

训练模型

我们差不多准备好训练模型了。首先,让我们编写一个自定义回调函数,在每个时期后打印可训练权重,只是为了验证参数正在被调整:

回调将按照每层在神经网络中出现的顺序,打印每层的可训练参数数组。每个数组中的第一项是图层的权重,第二项是偏差。

现在,让我们回到代码的主体并训练模型:

**model = CustomModel(nn_block=dense, name="nn_logistic_model")
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=1e-4))
model.fit(ds, epochs=5, callbacks=[ReportWeightsCallback()])**

现在,您已经准备好进行端到端的培训了!完整的代码包含在本指南的末尾。

最后的想法

你可能想知道为什么我们子类化keras.Model来实现我们的目标。对你来说可能很复杂。例如,为什么不在Logistic层中定义一个带有自定义渐变的损失函数,并完全去掉自定义模型对象呢?

一开始我也是这么尝试的,但是我意识到这样做效果不好。通过告诉自定义的Layer将要素和目标标注作为输入,用户可以在Logistic层内使用自定义梯度实现负对数似然损失函数。当您可以访问标签时,这在训练期间是有效的,但是当您使用模型进行推理时,这就不太有效了,因为对未知数据的预测不涉及作为输入的目标标签:用于推理的输入与用于训练的输入不具有相同的形状。

使用模型可以解决这个问题,因为它允许用户创建自定义的训练、评估和预测循环,而不会影响模型的各个层所预期的输入形状。它允许我们在训练期间访问计算自定义损失所需的特征和标签,并在推断期间仅使用特征进行预测。

完整的代码

构建和训练 Keras 模型的端到端脚本,该模型使用带有自动微分和自定义梯度的自定义损失

来源

德国信贷数据。2017.UCI 机器学习知识库。可从:http://archive.ics.uci.edu/ml获得。

如何利用客户终身价值(LTV)进行数据驱动的转型

原文:https://towardsdatascience.com/how-to-use-customer-lifetime-value-ltv-for-data-driven-transformation-6f12596df943

利用 LTV 为你的企业设定目标,并将责任下放

如果您的企业正在进行数据驱动的转型,您首先应该解决的问题之一是转型的目的是什么。数据驱动的转型不应该是短期思维,例如挤出运营效率。相反,正如尼尔·霍因(Neil Hoyne)撰写的优秀著作所建议的那样,转型应该寻求最大化每一个客户关系的全部价值。“每个客户的全部价值”被称为终身价值(LTV)。数据驱动的业务转型要求您围绕 LTV 最大化来定位公司的各个方面,包括营销、销售、产品和支持。

由阿尔瓦罗·雷耶斯在 Unsplash 上拍摄的照片

当然,你不会希望根据客户的价值来经营你的企业。相反,你希望根据客户的价值来经营你的业务。客户越有价值,你就越有可能制造他们会购买的产品,在他们阅读的杂志上购买广告空间,为他们提供专门的销售人员,并主动满足他们的需求。与此同时,你不希望自己做每一个小决定,相反,你希望让组织中的每个人都能做出你会做的决定。做到这一点的方法是使用 LTV。

在本文中,我将介绍如何使用 LTV 在您的组织中推动数据驱动的转型,并改善客户成果。

LTV 为你的商业战略提供了杠杆

忽略工具供应商——没有标准的 LTV 公式。作为一名企业领导者,确定计算 LTV 的因素是你必须权衡的事情,这是你为组织设定方向的关键方式之一。原因是 LTV 计算也与业务战略有关——它不会对所有企业都一样,随着时间的推移,它也不会对你的企业一样。你不能简单地采用内置于商业智能工具中的 LTV 公式,并告诉你的团队使用它。相反,你应该将 LTV 视为一个你不断与你的领导团队讨论的模型——这是你需要定期重温的东西。

如何计算 LTV 是你将要做出的最重要的战略决策之一。这篇文章涉及了相当多的细节,因为理解其中的细微差别很重要。这些细微差别是你可以用来推动你的业务向前发展的杠杆。

您选择的 LTV 计算方法将极大地影响您的领导团队的日常决策。它将指导营销投资、销售激励、产品设计、服务定价和产品组合。这不仅限于您的领导团队——LTV 是在整个组织中推动决策和问责的一种方式。你甚至希望用户界面设计师考虑突出显示哪些按钮,以最大化 LTV 为目标。你的企业将做出数百个小决定,这些小决定将共同推动 LTV 上升。因此,最重要的是,组织中的每个人不仅要明白LTV 公式中的是什么,还要明白为什么是

在本文中,我将从剖析几个广泛使用的公式开始。我希望这能帮助你把 LTV 作为讨论的辅助工具,这样你就能想出一个适合你的企业的方法。确保每个计划周期都重新审视 LTV 方法,这样你就可以随着业务的变化而调整它。你会在早期犯错误——重要的是在前进的过程中纠正错误,并在整个组织中树立这样的期望,即进入 LTV 的因素将随着时间的推移而适应。

零售 LTV

让我们从尼尔·霍因转化的优秀著作中提出的客户 LTV 公式开始。他建议你应该查看你的历史购买记录,并计算两个值:

  • 每个客户的交易数量
  • 每笔交易的平均值

然后,你需要建立一个机器学习模型,根据你对客户的了解,这个模型可以预测:

  • 客户从你这里购买的可能性

一旦有了这三个值,将它们相乘得到 LTV:

这个公式非常适用于数字营销——考虑这样一种情况,你是一个零售商,销售各种各样的商品,并想决定在给客户的广告上花多少钱。您可以从客户购买的历史数据库中估计未来交易的数量和交易的平均值。这是一个值得追随的客户的概率将基于像这个人一样点击广告并成为客户的人的比例。

这个公式有三个缺点,每个数据科学家都应该知道。

  1. 第一个问题是“价值”是什么意思。是利润吗?是收入吗?是毛利率吗?这个看你的业务了。稳定的企业通常选择利润。快速增长行业的企业优先考虑市场份额,因此选择收入。准备公开上市的公司通常会选择毛利率。你必须以一种不鼓励短期效率提高和价格变化的方式设定价值,这种价格变化会增加盈利能力,但会损害长期的客户维系。例如,你可能会选择收入和毛利润的加权总和作为衡量价值的标准,当你接近计划的 IPO 时,权重会随着时间的推移而变化。
  2. 第二,你的业务会随着时间的推移而改变,这正是由于你的组织所采取的行动。如果你的广告漏斗变大,每个客户的交易数量可能会下降。如果你只做高价值产品的广告,平均价值可能会增加。因此,你需要根据你采取的每一项行动来预测未来的交易数量或价值。在这种情况下,请让您的数据科学团队构建 ML 模型来预测前两个变量。或者,您可以选择将这些设定为您的团队要达到的年度目标。例如,产品团队可以根据他们增加平均交易数量的情况来衡量,而营销团队可以根据针对增加购买概率的广告的有效性来衡量。
  3. 第三,你的历史记录会低估新客户,因为他们还没有足够长的时间来建立一个完整的记录。思考这个问题的一个简单方法是,想象你想预测高中阅读的书籍数量。这个模型对 12 年级的学生来说是好的,但对 6 年级的学生来说是糟糕的。因此,你必须根据老客户的行为来校准新客户。在书籍类比中,您会发现 12 年级学生与每个 6 年级学生最相似,并进行校准——例如,一个读了 13 本书的 6 年级学生最终会读 124 本书,其中 124 本书是在 6 年级读了 13 本书的 12 年级学生一生的平均阅读量。这通常被称为群组分析。如果您有足够的数据,您可以仅使用几个时间窗口中 12 年级学生的历史记录来训练模型。因此,通过使用 12 年级学生 6、5、4、3、2、1 年前的历史,训练模型来预测实际的阅读习惯。

你处理这三个问题的方式将从根本上改变你计算和使用 LTV 的方式。

由亚马逊 LTV 履行

你会看到另一个经常被引用的 LTV 公式是使用亚马逊(FBA)的商家使用的 LTV 计算。如果您通过亚马逊等第三方履行,您甚至可能没有客户信息。此外,如果你创业时间不长,利润率相当低(或者是负数,许多初创公司都是如此),那么你就没有使用 Hoyne 方法所需的历史信息。你必须采取更简单的方法。

如果你能以某种方式估计出顾客会回来购买的次数,你就可以用以下公式计算出顾客的终身价值:

换句话说,你拿一件商品的价格,减去销售成本(运费、亚马逊费用等。)并乘以你期望客户从你这里购买的总次数。减去客户获取成本(CAC ),比如你为获得 LTV 而向谷歌或亚马逊支付的任何广告或搜索费用。

这立即凸显了任何依赖亚马逊履行的零售商的问题——没有品牌忠诚度,N_repeats 是 1,CAC 会吃掉你的利润率。因此,你必须投资于品牌忠诚度,让顾客直接访问你——LTV 是将你的组织的注意力集中在对你的企业存在的威胁上的一个很好的方式。

订阅产品 LTV

假设你有一个固定费用的服务。也许你在卖一本订阅者每年支付 30 美元的杂志,或者一份有年费的人寿保险。对于此类产品,您可以根据客户续订的预期年数来计算 LTV:

这个公式使用了几个概念。让我们一个一个地看一下:

  • S_year 是按年计算的存活率。例如,S3 是将订阅保持到第 3 年的那部分客户。按群组(或客户群)从历史数据中估算。例如,农村地区的客户可能与城市地区的客户有不同的续订率。
  • V_subscription 是订阅的值。这可能是利润,通过减去提供服务的成本和客户获取成本来计算。
  • r 是贴现率。因为订阅持续到未来,所以您必须使用复利计算客户的净现值。这不仅仅是财务上的——折扣率也包含了长期客户的网络效应。如果你不确定这可能是什么,从大约 10%的折扣率开始,但要知道激励口碑推荐将提高 r,从而提高 LTV。
  • n 是你可以合理估计这些值的年数。通常,您可以根据历史记录计算它,并可以外推曲线。所以,N 往往是 S_year 降到 1%以下的那一年。

与零售 LTV 一样,将存活率、订阅价值和折扣率的提高作为各种团队的目标设定练习。

交叉销售产品 LTV

订阅产品计算假设您只有一种产品要销售。然而,假设你有几本杂志。很有可能你将能够交叉销售一本新杂志给当前的订户。你的 LTV 计算必须考虑到这一点,考虑这种交叉销售的可能性。

方法是计算第 I 个产品的 LTV,然后加上能够向第 I 个产品的订户交叉销售第 j 个产品的可能性:

然后,增加向第 I 个用户交叉销售第 j 个产品的可能性:

如果您有这样做的数据,您可以按年来做(即,估计能够在第 1 年、第 2 年等进行交叉销售的概率。)

多层产品 LTV

交叉销售计算假设产品是独立的,并且客户将购买多种产品。然而,许多订阅服务(比如税务软件)都有几层服务。也许有一个人们每年支付 10 美元的基本层,一个定价为每年 20 美元的中间层,以及一个每年花费 30 美元的高级层。

对于多层产品,我们可以假设客户将只使用一种服务。购买了高级税务准备软件的人当年不会同时购买基本版。

每一层都可以被视为一个单独的订购产品,您可以简单地将三个产品的 LTV 相加。但在现实中,人们不会只是粗制滥造。随着收入的增加或交叉销售,他们可能会转向更高层次的服务。由于价格压力,他们可能会转向较低层次的服务。

为了抓住这一点,我们需要考虑客户转向不同服务级别的可能性。这也可以通过历史数据进行估计,受到营销活动和产品变化的影响,并通过机器学习进行预测。无论我们如何得出概率,您都需要客户从另一层移动到这一层的概率,并且我们需要将它添加到存活率中:

广告支持的产品 LTV

如果你的产品是用户付费的,这一切都很好。如果你的产品是免费的,你通过应用内广告赚钱怎么办?在这种情况下,你可能对单个客户一无所知。取而代之的是,通过由在特定日期安装了该应用的人组成的群组来计算 LTV:

你可以从向该群体展示的广告中获得该群体的广告收入(加上你支持的任何应用内购买)。

如何在您的企业中实施 LTV

在本文中,我们讨论了为什么 LTV 很重要,以及计算 LTV 时的细微差别。你如何利用 LTV 为你的业务设定方向?让你的组织接受 LTV 需要几个团队一起工作。

您的数据科学团队需要提出一个公式,将本文中讨论的许多元素混合在一起。他们可以使用这个问题模板询问企业,并确定如何计算和报告 LTV:

  • 我们销售多少个独立的 SKU?
  • 客户购买多个 SKU 吗?
  • 客户会多次购买同一产品吗?
  • 客户是订阅服务并按月还是按年付费?
  • 衡量价值的最佳标准是什么?
  • 我们如何知道一个顾客什么时候离开了,不会再回来?
  • 我们会追加销售客户吗?
  • 我们向客户交叉销售吗?
  • 我们拥有自己的履行渠道吗?
  • 我们知道谁是我们的客户吗?
  • 哪些群体中的 LTV 可能也是如此?
  • 我们如何设定销售激励?
  • 我们如何评估营销优惠的功效?
  • 我们如何设置产品 okr?

您的销售、产品、营销、客户支持和其他团队应该接受 okr,这将对他们控制的 LTV 公式的部分产生积极影响。

  • 产品团队可以通过增加平均交易数量(零售 LTV),或者典型客户停留的年数(订阅 LTV),或者客户升级的可能性(多层 LTV)来衡量。
  • 可以通过运营团队提高运营效率的程度来衡量他们,从而提高每笔交易的价值。他们可以通过减少运输时间、降低制造成本等来做到这一点。
  • 营销团队可以通过广告目标的有效性来衡量,以增加购买的可能性以及交叉销售和追加销售的可能性。
  • 支持团队可以通过客户服务的有效性来减少客户流失

你的首席运营官应该承担起对 LTV 进行测量和管理的任务。这将涉及整个公司的分析团队承担测量任务,并将信息发送到企业数据仓库,为报告仪表板提供动力。

在全员参与的公司,你(首席执行官)应该向公司解释他们的愿景。浏览您的数据驱动转型目标,以及您将如何使用 LTV 将责任向下移交给组织。务必解释计算 LTV 的方法会随着时间的推移而改变,但 LTV 的目的是确保企业中的每个人都以客户为中心。

LTV 是亚马逊和谷歌等许多最成功的消费者企业管理其面向客户的业务的方式,我希望这篇文章能激励你加入他们的行列。

来源/额外阅读

  • 转化:以数据驱动的方式赢得客户的心。https://www . Amazon . com/Converted-Data-Driven-Way-Customers-Hearts/DP/0593420659
  • 增加亚马逊上的 LTV。https://www . seller app . com/blog/best-ways-to-increasing-customer-lifetime-value-on-Amazon/
  • 电信中的生存分析。https://support . SAS . com/resources/papers/proceedings/proceedings/sugi 28/120-28 . pdf
  • LTV 广告公司。【https://support.google.com/analytics/answer/6182550

如何在多臂强盗实验中使用转化率(CVR)作为目标

原文:https://towardsdatascience.com/how-to-use-cvr-as-an-objective-in-multi-armed-bandit-experiments-4dfd2ab48a24

包含代码示例的分步指南

照片由 Unsplash 上的米切尔·布茨拍摄

简介

多臂土匪(MAB)已经成为一个越来越重要的实验工具,并已被广泛采用的行业巨头,如谷歌,Meta,网飞,领英等。进行有效的实验。然而,广泛使用的 MAB 测试设计要求感兴趣的目标提供即时反馈,以便更新每个变量的分配概率。这就是为什么你能找到的大多数运行 MAB 实验的教程可能都是以点击率(CTR)为目标的。

所以在这篇文章中,我想告诉你如何运行一个多臂土匪实验,为目标,采取重大延误,以实现如转换率(CVR)。

这篇文章引用了我在 2022 年网络大会上发表的论文

为什么要进行多臂强盗实验?

假设你正在开展一项在线广告活动,并试图找到能给你的产品带来最高转化率的最佳平面设计,你将需要进行一项实验。

您可以运行一个经典的 A/B/n 测试,将固定比例的用户分配给竞争设计,然后在收集足够的数据后进行分析。然而,有两个常见的问题是 A/B/n 测试经常被批评的。当处理像 CVR 这样的延迟指标时,这些问题更加突出,因为完成实验需要更长的时间。

  1. 大量的实验成本。因为 A/B/n 测试中的所有竞争处理都保证了样本大小的固定部分,所以即使是“糟糕”的处理也可能暴露给大量用户,这可能会对用户体验造成伤害。更长的实验意味着更大的实验成本。
  2. 如果分析不正确,容易做出错误的决定。A/B/n 测试旨在仅在达到目标样本量时进行分析。但是缺乏经验和耐心的实验者往往倾向于在实验前偷看结果并做出决定,这可能导致错误的结论。更多讨论见这篇博客。实验时间越长,出错的机会就越多。

我们的英雄来了,多臂强盗范式。在这种范式中,我们将我们的竞争广告设计视为许多不同的老丨虎丨机。每个老丨虎丨机都有自己的成功率(转化率)。我们想找到一个速度最好的老丨虎丨机,然后继续拉它的手臂。MAB 算法将提供一种原则性的方法,在整个实验中反复调整分配比,直到最佳处理接收到大部分样本。

MAB 的优势在于降低了实验的机会成本,而且不受窥视。

计算 CVR 的问题是

现在你可能会想,MAB 听起来不错,但 CVR 有什么特别之处呢?

转换率是行业中非常常见和重要的指标。但与点击率不同的是,转化信号很稀疏,而且往往有延迟。例如,电子商务网站用户可能在他们第一次开始浏览后的几个小时甚至几天都没有完成他们的订单。这种不确定的延误会给我们带来麻烦。

在本文中,我们遵循在线广告行业的标准,将 CVR 定义为导致转化(例如购买)的点击百分比。

天真的 CVR

这是业内人士通常使用的。这个 CVR 公式的问题是,在我们计算它的值的任何时候,我们都会错过所有被延迟且尚未观察到的转换。所以这个天真的 CVR 会低估真正的 CVR。

我们可以在下面的例子中看到这一点。

作者图片

在这个简单的实验中,我们模拟了真实 CVR 等于 0.5 的情况,并假设所有转换在点击后总是延迟 1 小时。显然,在实践中,转换延迟不会这么简单,但本例中的逻辑同样适用。

例如,为了计算 t2 时的简单 CVR,我们需要将所有橙色条作为分子相加,将所有灰色条作为分母相加。计算出的原始 CVR 由图中的红线表示。显然,它低估了真正的 CVR。

下面的代码创建了一个更通用的模拟器。它产生具有指数延迟分布的转换,并跟踪转换随时间的可观测性。这个模拟器以后可以用来测试我们的 Bandit 代码。

纠正 CVR

在上面的例子中,纠正低估的一种方法是在计算 t2 的 CVR 时,只使用 t0 和 t1 的灰条作为分母。然后,修正的 CVR 估计等于 0.5,这是潜在的事实。

这种补救措施能够奏效的原因是,我们知道在 t2 的点击没有任何机会在 t2 产生转化(它们相应的转化只能在 1 小时后观察到)。所以 t2 时的那些点击不应该包括在分母中。图中的绿线是使用这种思想计算的,并且恢复了 t0 之后的真实 CVR。

这种方法可以推广到更复杂的情况,其中延迟是随机的,并遵循一般的延迟分布(其 CDF 表示为τ)

简单来说,我们要对点击进行重新加权来计算有效点击,一次点击的权重是基于从点击到现在观察到其转化的概率。最近点击越多,权重越低。

如果延迟分布已知,这个公式可以证明是一个无偏估计量。

估计延迟分布的挑战

实际上,我们不知道真实的延迟分布是什么。在本节中,我们将讨论估计延迟分布的挑战。

在实验过程中,观察到的延迟是右删失的。这意味着,如果我们绘制转换延迟直方图,我们无法观察到超过某个阈值的延迟。就像下面的例子,

作者图片

本例中,我们试图估算 t=1000 时的延迟分布,只能观察到小于 1000 的转换延迟。

当延迟等于 1000 时,图中有一个尖峰。那些是还没有转化的点击。这些点击有两种可能的结果。要么它们将在未来转换,意味着具有大于 1000 的延迟;或者它们永远不会导致转换,相当于有一个无限长的延迟。图中的红色阴影标记了这些未转换。

我们只对估计蓝色样本的延迟分布感兴趣。如果红色部分可以排除,估计相对容易做(这是标准的生存分析)。不幸的是,在实验过程中,没有办法区分这两种可能性,除非我们知道真正的最终 CVR。

但是最终的 CVR 是我们想要估计的。我们兜了一圈回来了!

如何和 CVR 一起管理 MAB

作者图片

我们提出的系统的概述已在上面介绍过了。有两个与算法相关的主要组件。第一个部分将点击和转换日志作为输入,并估计实验中每个处理组的 CVRs。第二组件基于来自第一组件的所有估计的 CVR 来计算分配概率。如果不满足停止规则,将根据分配概率向用户显示新广告。然后重复该过程。

CVR 估计

在第一部分中,我们使用期望最大化方法来获得每个实验组的 CVR 估计值。

首先,我们假设延迟分布是指数分布的,对于每个实验组 k 由λk 参数化。

对于每个组 k,收集组 k 中的所有点击。首先计算 I 跟随的每个点击的权重

然后更新估计值

在哪里

在每个时间步长 t,我们将上面定义的 E-M 计算迭代几个周期,以确保得到的估计是稳定的。设 L 代表循环总数。然后保存每个时间步长的最终估计,并用作下一个时间步长的先验,即

下面的代码提供了该过程的一个示例实现。每个 Arm 类对应于上面描述的一个组,负责获取相关的日志数据,并获得λ和θ的估计值。

汤普森取样

一旦我们得到每个组的估计 CVR,我们就可以使用 Thompson 抽样来计算分配概率。

为了使用 Thompson 抽样,我们需要知道估计 CVR 的分布。因为从 EM 过程中得到它不是微不足道的,所以我们采用启发式方法来假设每个组 k 的 CVR

在时间 t 遵循β分布,β(αkt,βkt)。参数更新如下:

简单来说,βkt 等于有效点击次数+ 1。

一个组的分配概率是该组提供最高期望 CVR 的后验概率。我们使用蒙特卡罗模拟来计算这些值。

αkt 和βkt 更新和β采样的代码嵌入在上面的 Arm 类中。通过调用每个分支的draw_beta_sample方法,我们可以如下计算分配概率。

下图总结了指数分布延迟方法的整个过程。

作者图片

结论

这就是了。现在你可以开始用 CVR 度规运行你的多臂强盗实验了。这篇文章是基于我们的论文延迟二进制反馈的适应性实验而写的。如果您想假设除指数分布之外的延迟分布,或者使用其他类型的延迟反馈,您可以在本文中找到更多讨论。对于本文中显示的完整代码,您可以在这里找到它们。

如何通过深思熟虑的练习掌握数据科学中最具挑战性的概念

原文:https://towardsdatascience.com/how-to-use-deliberate-practice-to-master-the-most-challenging-concepts-in-data-science-18d508654caf

通过深思熟虑的实践来研究数据科学将使你与其他数据科学家区分开来

在 Unsplash 上由 Lex Melony 拍照

在不到一年的时间里改变职业并进入新领域的数据科学家与我们这些普通人有何不同?

不,他们不一定在技术领域有职业生涯可以推动自己成为一名数据科学家。

不,他们可能在编程艺术、数学和数据可视化方面没有天赋。

相反,让那些在开始数据科学之旅几个月后就获得 FAANG 公司工作机会的人与众不同的是,他们的日常习惯与你不同。

所有数据科学家都应该养成这种日常习惯,但只有少数人以这种方式行事,他们在知识、技能和职业生涯方面的进步远远超过了同龄人。

这种习惯被称为刻意练习。

幸运的是,刻意练习是每个人都有的习惯,只需要你在舒适区之外舒适地生活和工作。

什么是刻意练习?

刻意练习被定义为“本质上是努力的,主要目标是提高个人表现而不是享受,并且经常没有直接的回报。”

本质上,刻意练习是在你的舒适区外围练习技能,以不断提高你的技能。

例如,烹饪是一项很难完成的任务,但在花了很多时间烹饪不同的菜肴后,它变成了你的第二天性,是一项你无需多想就能完成的任务。然而,过了某一点,如果你经常一遍又一遍地做同样的菜,你的烹饪技术不会提高。你的烹饪技能会停滞不前,甚至可能退步,因为你没有把自己推过舒适区。然而,如果你开始有意识地学习如何从外国烹饪中制作不同的菜肴,学习如何只用几种原料制作完整的膳食,或者学习如何替代原料,你的技能将会立即提高。

刻意练习的目的是让你的技能总是在上升的轨道上提高,永远不会停滞或倒退。它迫使你重温旧知识,实践新技能,并将不同的思维过程应用于新的情况。

刻意练习通常是一种无意识养成的习惯,比如当你上大学或者在很短的时间内完成学业的时候。例如,当我在完成软件工程的技术文凭时,我下意识地使用刻意练习。在一个为期两年的项目中,你最终会感到不知所措,大部分时间都被挤出了你的舒适区,这意味着我别无选择,只能继续学习越来越高级的主题,尽管我对之前学习的主题并不完全满意。在那两年的时间里,我设法成倍地增长了我的技能,并通过刻意的练习掌握了软件工程中一些更具挑战性的概念。

刻意练习将如何让你成为更好的数据科学家?

对于希望在整个职业生涯中保持影响力和相关性的数据科学家来说,刻意练习至关重要。不仅如此,刻意练习的目的是帮助数据科学家在接受过任何正式教育后仍能保持领先。

比方说,你感觉不舒服,去了医院。在那里,你会得到一名资深医生和一名初级医生的检查。你觉得谁会给你更准确的诊断?信不信由你,初级医生可能会给你更准确的诊断,因为他们刚刚从医学院毕业,在这种经历中,学生们总是处于一种刻意练习的状态,没有舒适区的感觉。据发现,由于缺乏持续的积极培训,高级医生的诊断能力与初级医生相比【没有更好(在某些情况下更差)】。

医疗专业人士的例子告诉我们,当你没有被推出舒适区时,你的诊断技能(或数据科学家的分析技能)将随着时间的推移而停滞甚至下降。

对于一名数据科学家来说,没有跟上替代的数学建模或分析方法可能意味着你忽略了工具箱中的重要技能,而这些技能本来可以用于进行数据分析。

在与上面的医生示例类似的情况下,一名刚从研究中毕业的年轻数据科学家可能比一名更有经验的同行更能准确地从数据中得出替代结论,后者在过去五年中一直在进行同类分析,几乎没有变化。从本质上讲,与能力停滞不前的数据科学家相比,继续拓展和提高技能的数据科学家将更有能力发现模式、错误、不一致和替代结论。不仅如此,继续掌握挑战性技能的数据科学家将没有晋升或职业机会的上限。

因此,有意识的练习,迫使你在舒适区之外进步你的学习和技能,是你成为更好的数据科学家的答案,在他们的职业生涯中保持他们的影响和相关性。

由于日常数据科学实践对于未来的和当前的数据科学家都是必要的,所以刻意的实践是提高日常技能以及掌握数据科学中最具挑战性的概念的简单答案。

如何通过深思熟虑的练习掌握数据科学中最具挑战性的概念

刻意练习包括五个步骤,可用于增长您的数据科学技能和知识。

刻意练习的五个步骤:

  1. 找出需要加强的薄弱环节 : 这可以是从编程到数学到数据可视化等等的任何事情。确定一个薄弱环节是一项令人羞愧的活动,但却是开始刻意练习过程所必需的——刻意练习最好用在你舒适区之外的薄弱环节上,你希望掌握它。选择一个满足这些要求的弱点不仅能让你做好第二步和第三步的准备,还能确保你有动力坚持到底。对于这个例子,假设你想掌握更高级的编程主题。
  2. 将弱点分解成具体的领域以提高表现 : 刻意的练习需要明确的目标,这意味着你需要明确你想改善的弱点。如上所述,对于这个例子,您希望掌握编程中更高级的主题。这是一个需要努力改进的广泛弱点。然而,如果你缩小范围,你可以尝试改进你的编程风格,开发生产就绪代码,或者改进面向对象代码的编写。每一个都属于“编程”的弱点,但都是更具体的领域,需要你有意识地练习。
  3. 设定挑战性的目标,拓展你的能力 : 刻意练习的目标是永远不舒服。在这个过程中,任何时候你的目标都不应该看起来容易实现。这意味着你设定的目标应该要求你学习刚好超出你目前能力水平的技能或知识。继续我们的例子,这可能需要你在两周内掌握面向对象编程的基础。这将要求你在两周内涵盖面向对象编程的四个原则(封装、抽象、继承和多态),然后在两周期末创建一个小项目,以确定你是否真正理解了这个概念。
  4. 寻求诚实的反馈来确定你的技能是否有所提高 : 刻意练习的成功取决于你是否能够收到关于你进步的即时反馈。如果没有即时反馈,你将很难确定哪种模式产生了你想要的结果,哪种模式把你引向了错误的方向。我有过的最好的学习经历是当我谦卑地尝试一些东西,寻求反馈,然后利用反馈来改进我的工作。反馈是必不可少的,可以帮助你建立关于什么有效,什么让你误入歧途的模式。这也是询问同事、经理或老板的好时机,他们是否能提供额外的建议来帮助你掌握你选择的概念。
  5. 重复 : 通过深思熟虑的实践来提高您的数据科学技能和知识是一个必须不断重复的过程,以确保显著的改进。如果不重复这个循环,复合效应将无法实现,这将导致你的收益保持边际。

你可以在日常计划中包含刻意练习的 5 种方法

  1. 强迫自己用你想通过刻意练习提高的技能完成一些日常任务。例如,如果您正在更新分析代码,尝试实现面向对象的编程原则来清理您的工作并使您的程序更有效地运行。
  2. 制定一个练习计划,让你在一天中的指定时间进行有意识的练习——这不仅有助于你建立一个常规,也有助于节省时间,否则你会浪费时间去想清楚你将使用什么学习资源或计划。例如,将深度学习分成五个知识部分,然后在五周内分散开来。每天给自己安排一个时间,抽出一周的时间来帮助养成每天学习的习惯。
  3. 告诉某人(如老板、经理或同事)你计划向他们展示你正在学习的技能——这提供了必要的动力,让他们努力学习你舒适区之外的东西。例如,告诉你的老板,你已经想出了一种方法来自动化你的部分分析工作,并告诉他们如何使用它来优化其他工作流程。
  4. 不要单干。相反,试着和朋友或同事一起学习,每天留出时间一起学习。例如,尝试对一个与你的分析工作相关的 AI 程序进行结对编程。
  5. 学习数据科学之外的技能有利于你的职业生涯。尝试有意识地练习一种新的工具、语言、运动或技能。这不仅让你的大脑在数据科学领域得到了应有的休息,还在其他方面锻炼了你的大脑,最终可能对你的数据科学工作有用。

关键要点

  • 刻意练习为您提供了一个平台,通过迫使您在舒适区之外工作并不断进步您的知识,您可以在这个平台上掌握数据科学中最具挑战性的概念。
  • 刻意练习的目的是让你的技能总是在上升的轨道上提高,永远不会停滞或倒退。它迫使你重温旧知识,实践新技能,并将不同的思维过程应用于新的情况。
  • 刻意练习可以通过多种方式融入你的日常计划,包括制定一个练习计划,告诉别人你的目标,和朋友或同事一起刻意练习一项技能。

订阅将我的故事直接发送到您的收件箱:故事订阅

请成为会员,使用我的推荐链接获得无限制的媒体访问权限(我将收取少量佣金,无需额外费用):媒体会员

通过捐赠来支持我的写作,以资助更多像这样的故事的创作:捐赠

如何在机器学习模型中使用 ECMWF 天气预报

原文:https://towardsdatascience.com/how-to-use-ecmwf-weather-forecasts-in-machine-learning-models-92fc3730c5cf

加载数据、查询历史天气、训练 ML 模型

欧洲中期天气预报中心(ECMWF)提供全球天气预报。如果您有一个需要将天气作为输入要素的 ML 问题(例如,您试图预测雨伞或冰淇淋的需求),您可以使用 ECMWF 数据根据历史数据训练您的 ML 模型,并在预测时使用 ECMWF 的实时预测。

最近,谷歌开源了一组 Apache Beam pipeline,使天气数据更容易纳入数据分析和机器学习项目。让我们兜一圈。

示例 ML 问题

我想使用天气数据作为一个模型的输入,预测纽约人将会保留他们租用的自行车多长时间。我的假设是,如果天气太热或下雨,人们会将自行车存放的时间缩短。所以,让我们把天气作为输入特征之一。

纽约自行车租赁数据在 BigQuery 中作为公共数据集提供。尝试在 BigQuery 中查询:

SELECT start_station_name,EXTRACT(hour from starttime) AS hourofday,EXTRACT(dayofweek from starttime) AS dayofweek,tripduration,
FROM `bigquery-public-data.new_york_citibike.citibike_trips`
LIMIT 5

我们可以训练一个 XGBoost 模型,根据其他因素(如起点站名称、一天中的时间和一周中的日期)来预测自行车租赁的持续时间:

CREATE OR REPLACE MODEL weather.rental_duration_nowx
OPTIONS(**model_type='boosted_tree_regressor',** input_label_cols=['tripduration']) AS
SELECT **start_station_name,** EXTRACT(hour from starttime) AS **hourofday,** EXTRACT(dayofweek from starttime) AS **dayofweek,tripduration**
FROM `bigquery-public-data.new_york_citibike.citibike_trips`
WHERE EXTRACT(year from starttime) = 2018

所得模型在保留数据上的中值绝对误差= 265 秒。让我们看看能否利用天气信息改进这个基本模型。

环境设置

  1. 去谷歌云控制台启动一个顶点工作台笔记本。我选择了一台相对最小的机器——没有 GPU 和 n1-standard-2 的最新 TensorFlow 版本——因为我们不会在笔记本上做太多工作。
  2. 从控制台中的链接打开 JupyterLab 并启动终端。
  3. 为了从 ECMWF 获取数据,您必须向 ECMWF 注册,并在登录时获取您的 API 密钥。
  • 气候数据(哥白尼):注册和获得你的 API 密匙。将 url、key 放在主目录中一个名为 ~/的文件中。cdsapirc 如页面所示。这些数据是免费的,但是您需要注册并获得 API 密钥。
  • 天气预报(火星):注册,获取你的 API 密匙。在 ~/中输入网址、电子邮件和密钥。ecmwfapirc 如页面所示。这些数据不是免费的(详见本博客最后一节)。

为了跟随我,为哥白尼注册并设置了密钥。MARS 提要是可选的。

3.安装天气工具包:

pip install google-weather-tools

3.创建将向其中加载查询数据的 BigQuery 数据集:

bq mk weather

4.创建一个存储桶来临时存储下载的文件:

PROJECT=$(gcloud config get-value project)
BUCKET=${PROJECT}-ecmwf
gsutil mb gs://$BUCKET

记下已经创建的存储桶的名称。您将在下一步中需要它。

下载历史观察

先来验证一下天气对自行车租赁是否有影响。在我们开始使用天气预报之前,我们可以尝试使用天气观测。ERA5 是我们想要的数据集。

5.下载示例配置 era5_example_config.cfg :

wget [https://raw.githubusercontent.com/google/weather-tools/main/configs/era5_example_config.cfg](https://raw.githubusercontent.com/google/weather-tools/main/configs/era5_example_config.cfg)

6.更改示例以反映我们想要的数据(确保从~/编辑 BUCKET 和 KEY。此文件中的 cdsapirc):

  • 数据集、变量:我们想要的(关于选项,请查看数据集的列表和数据集文档)。我挑选了温度和降雨量的每小时数据。
  • target_path:确保将我的示例中的 bucket 名称改为您在步骤 4 中的 bucket 名称。
  • api_key:确保设置您的。cdsapirc 值。
  • 区域:包括纽约市在内的经度范围(纬度=41,经度=-74)

6.下载数据:

weather-dl era5_example_config.cfg \--project $PROJECT --region us-west1 \--runner DataflowRunner --temp_location=gs://${BUCKET}/temp

这将启动一个数据流作业,您可以在https://console.cloud.google.com/dataflow进行监控

获取数据的数据流管道[图片由作者提供]

等待作业完成(大约 6 分钟)。请注意,我们一月份只有几天时间。

7.检查 FetchData 步骤的日志以验证正在下载哪些文件:

如何看待数据流日志[图片由作者提供]

8.验证数据是否已下载:

gsutil ls -l gs://$BUCKET/era5/2018/01/01.nc

[可选]下载一年的历史数据

下载一年的历史数据将需要1-10 个小时才能完成,这取决于你是否拥有付费的 ECMWF 许可证。所以,你可以跳过这一步。要了解事情是如何工作的,您在上一步中下载的少量数据就足够了。

注意:如果在配置中使用多个许可证,您可以获得更快的下载速度。参数 subsections docs(https://github . com/Google/weather-tools/blob/main/configuration . MD # subsections)描述了如何做到这一点。因此,拥有 CDS 许可证的团队可以一起更快地获取数据。

9.通过指定日期范围,将纪元配置扩展到所有月份和所有日期,而不是单独列出具体的月份/日期等。(和以前一样,记得更改下面清单中的 BUCKET 和 KEY)。

重新运行作业。已经下载的数据将被跳过。同样:这需要几个小时才能完成。所以,如果你只是想看看事情是如何运作的,可以跳过这一步。

将数据加载到 BigQuery

您已经下载了 ERA5 数据,但是它是 netcdf 格式的,不太有利于将其合并到 ML 模型中。让我们将它加载到 BigQuery 中,使数据更加可用。

10.将数据加载到 BigQuery

weather-mv --uris "gs://$BUCKET/era5/**.nc" \--output_table $PROJECT.weather.newyork \--temp_location gs://$BUCKET/temp \--direct_num_workers 2

我在“本地”运行它,但是您也可以通过指定 DataflowRunner 在数据流中运行它,就像使用 weather-dl 工具一样:

weather-mv --uris "gs://$BUCKET/era5/**.nc" \--output_table $PROJECT.weather.newyork \--project $PROJECT --region us-west1 \--runner DataflowRunner \--temp_location=gs://${BUCKET}/temp

11.检查我们刚刚得到的数据:

SELECT time, longitude, latitude,ROUND(t2m, 2) as temperature, ROUND(tp, 2) AS rain
FROM weather.newyork
LIMIT 5

结果应该是这样的:

使用天气数据训练 ML 模型

12.将天气数据与自行车数据结合起来,这样我们就可以知道每次租赁的地点/时间的天气:

SELECT start_station_name,EXTRACT(hour from starttime) AS hourofday,EXTRACT(dayofweek from starttime) AS dayofweek,tripduration,**ROUND(t2m, 2) as temperature, ROUND(tp, 2) AS rain**
**FROM weather.newyork**
JOIN `bigquery-public-data`.new_york_citibike.citibike_trips **ON ABS(DATETIME_DIFF(EXTRACT(DATETIME FROM time), starttime, HOUR)) < 3AND ABS(start_station_latitude - latitude) < 0.5AND ABS(start_station_longitude - longitude) < 0.5**
LIMIT 5

13.让我们在上面的查询中编写一个更有效的连接,方法是更改自行车表中的时间和位置字段以匹配天气数据的时间/空间分辨率,并保存连接的数据以用于 ML 元数据跟踪和重新训练:

CREATE OR REPLACE TABLE weather.citibike_trips AS
WITH citibike_trips AS (SELECT start_station_name,EXTRACT(hour from starttime) AS hourofday,EXTRACT(dayofweek from starttime) AS dayofweek,tripduration,TIMESTAMP_ADD(TIMESTAMP_TRUNC(CAST(starttime AS TIMESTAMP), HOUR), INTERVAL CAST(ROUND(EXTRACT(hour from starttime)/6) AS INT64) HOUR) AS time,ROUND(start_station_latitude*2)/2 AS latitude,ROUND(start_station_longitude*2)/2 AS longitudeFROM `bigquery-public-data`.new_york_citibike.citibike_tripsWHERE EXTRACT(YEAR FROM starttime) = 2018
)
SELECT trips.*, ROUND(t2m, 2) as temperature, ROUND(tp, 2) AS rain
**FROM citibike_trips trips
JOIN weather.newyork**
**USING (time, latitude, longitude)**

14.天气有多重要?用天气训练 XGBoost 模型:

CREATE OR REPLACE MODEL weather.rental_duration_wx
OPTIONS(model_type='boosted_tree_regressor', input_label_cols=['tripduration']) ASSELECT start_station_name,hourofday,dayofweek,**temperature, rain,**tripduration
FROM weather.citibike_trips

15.比较评估误差:

不考虑天气因素:中值绝对误差= 265 秒

天气:中值绝对误差= 245 秒。

成功!当我们知道天气时,我们能够更好地预测自行车租赁的持续时间…

[可选]下载您想要的天气预报数据

在我的工作流程中(如上),我使用了事后几天创建的再分析数据。所以,你实际上不能用它来进行实时机器学习。对于实时 ML,你需要近乎实时产生和传播的天气预报数据。这不是免费的,您需要从 ECMWF 获得商业许可才能下载预测数据。

16.下载示例配置configs/mars _ example _ config . CFG:

wget [https://raw.githubusercontent.com/google/weather-tools/main/configs/mars_example_config.cfg](https://raw.githubusercontent.com/google/weather-tools/main/configs/mars_example_config.cfg)

17.您必须对 param 行进行的关键更改是:

target_path=gs://**BUCKET**/newyork/
param=max2t6/min2t6/maxtpr6
step=6/12/18/24
time=0500
date=2018-01-01/to/2018-12-31
  • param:我们想要的天气变量是地表以上 2m 处的 6 小时最高和最低温度(大约是人面部高度的温度)和 6 小时最大降水率。你可以在这里找到所有天气参数的描述。
  • 步骤、时间、日期:获取 0500 UTC(纽约市午夜)做出的提前 6 小时、12 小时、18 小时、24 小时的预测,并获取 2018 年做出的所有预测。

现在,使用 weather-dl 下载数据,并使用 weather-mv 将其添加到 BigQuery 中。工作流程的其余部分保持不变!

尽情享受吧!

如何使用 GPT J 为(几乎)任何自然语言处理任务

原文:https://towardsdatascience.com/how-to-use-gpt-j-for-almost-any-nlp-task-cb3ca8ff5826

提示工程以及它如何与文本生成模型一起使用

马库斯·温克勒在 Unsplash 上的照片

这是怎么回事?

在之前的一篇博文中,我们看了看如何使用 Streamlit 、拥抱脸和亚马逊 SageMaker 来建立我们自己的 GPT-J 游乐场。有了这个平台,我们现在可以开始试验模型并生成一些文本,这很有趣。但是最终我们希望模型能够真正执行 NLP 任务,比如翻译、分类等等。在这篇博文中,我们将看看如何使用 GPT-J 模型的不同参数和特定提示来实现这一点。

这篇博文将建立在上一篇博文和这篇 Github repo 的基础上,假设你已经建立了自己的 GPT J 游乐场。这篇博文的代码可以在同一个 Github repo 中的一个单独的分支中找到。

添加参数控制

在我们开始快速工程之前,我们应该添加一些参数,用这些参数我们可以在一定程度上控制模型的行为。一篇详细描述这些参数的博文可以在这里找到。在本教程中,我们将只介绍其中的三个:响应长度,温度和重复惩罚。响应长度是显而易见的——它控制模型的响应时间。温度是衡量模型创造性的一个标准——温度越高,模型的反应就越“有创造性”。重复惩罚也是不言自明的——该值越高,模型对重复单词的惩罚就越多。

让我们在我们的 Streamlit 应用程序中创建一个侧栏,它将允许我们在 UI 中控制这些参数的值:

现在,这些控件将出现在用户界面的侧边栏中:

作者图片

我们还需要确保在调用模型端点时,通过将这些参数的值合并到有效负载中,将它们传递给模型:

现在我们已经将这些参数添加到了我们的应用程序中,我们可以开始尝试不同的提示。

快速工程

让我们先来看看维基百科对提示工程的定义:

提示工程是人工智能,尤其是自然语言处理(NLP)中的一个概念。在 prompt 工程中,任务的描述被嵌入在输入中,例如,作为一个问题,而不是被隐含地给出。

这意味着我们可以创建一些文本作为模型的输入,告诉模型要执行哪个任务。让我们看一些例子。

分类

让我们从一个相对“简单”的任务开始,文本分类:

作者图片

在本例中,我们明确说明了任务(将食物与国家相匹配),并提供了几个示例。这被称为少量学习,因为模型能够从这些例子中学习任务是什么(除了任务语句之外)。

我们选择了低温和低重复惩罚,因为我们不希望这个模型对这个任务太有创造性。我们还将响应长度保持在中等,因此模型继续使用列表。大多数情况下,这将是有趣的,但不可取的,因为我们希望模型分类一个特定的文本(“鱼和薯条”)。这可以通过一点后处理来弥补,即在换行后删除所有内容。

翻译

文本生成模型对于翻译任务也表现良好,只要该模型已经被训练成多种语言。让我们省略明确的任务陈述,只提供几个例子:

作者图片

首先,对于那些不熟悉德语的人来说,这是一个正确的翻译(准确地说,是几种可能的正确翻译之一)。因此,该模型甚至能够在没有明确说明的情况下识别任务。我们再次将温度和重复惩罚的值保持得相当低。例如,为温度选择一个较高的值会使模型有点太有创意。值为 0.6 时,会产生以下翻译:“嗯,什么是更好的?”(“它什么时候做啤酒?”).话说回来,这可能是德语中的一个常见问题;)

SQL 生成

让我们把事情变得更难一点,不提供任何例子。相反,我们只是直接告诉模型该做什么:

作者图片

这种技术被称为零镜头学习,因为我们不提供例子,仍然期望模型理解任务。在这种情况下,它实际上工作得很好,而且,总的来说,文本生成模型在没有任何例子可以学习的情况下表现得惊人地好。

我们再次为温度和重复代价选择了较低的值,因为 SQL 查询具有固定的结构,因此我们不希望模型太有创造性。

自由文本生成

你可能已经注意到,到目前为止,我们并没有太多地使用参数控制:温度和重复惩罚都保持在较低的水平。这是因为我们希望建模来完成特定的任务,所以我们实际上不希望它太有创造性。让我们尝试一个不同的用例,我们希望模型更有创造性。

作者图片

在这种情况下,我们希望将温度至少提高到中等,因为我们希望模型更有创意。在这样做的时候,我们也经常发现模型经常使用相同的单词,所以我们也增加了重复惩罚。根据我们希望模型产生的文本类型,这些值可以进一步增加。

结论

在本教程中,我们开始尝试各种提示来完成 NLP 任务,如分类、翻译等。然而,到目前为止,我们只是触及了表面:我们还可以尝试更多的任务,比如总结、生成电子邮件回复等。我们还可以在应用程序中包含更多的参数来控制模型的行为,如 Top-P,beam search 等。

我发现试验这些文本生成模型非常有趣,我希望你现在也能在关注这篇博文并建立这个 GPT-J 游乐场之后做同样的事情。

如何在 5 分钟内将汉密尔顿用于熊猫

原文:https://towardsdatascience.com/how-to-use-hamilton-with-pandas-in-5-minutes-89f63e5af8f5

这个帖子的感悟(非真实代码)。图片作者。

汉密尔顿是一个开源的、声明性的 Python 数据流微框架。在这篇文章中,我将尝试快速解释它是什么以及如何在熊猫身上使用它;阅读这篇文章不会花费你超过五分钟的时间。关于背景故事和更长的介绍,我们邀请你阅读这篇 TDS 帖子。

什么是汉密尔顿?

Hamilton 是一种自以为是的编写 python 数据转换函数的方式。它迫使两件事:

  1. 您编写声明性的 python 函数来封装您的数据转换逻辑。
  2. 从运行时逻辑中分离出转换逻辑。

这到底是什么意思?

对于上面的第(1)点,不要编写操作数据帧的 Pandas 代码,它看起来像这样:

df['age_mean'] = df['age'].mean()
df['age_zero_mean'] = df['age'] - df['age_mean']
df['age_std_dev'] = df['age'].std()
df['age_zero_mean_unit_variance'] = df['age_zero_mean'] / df['age_std_dev']

你应该这样写:

# a_function_module.py
def age_mean(age: pd.Series) -> float:*"""Average of age"""* return age.mean()def age_zero_mean(age: pd.Series**,** age_mean: float) -> pd.Series:*"""Zero mean of age"""* return age - age_meandef age_std_dev(age: pd.Series) -> pd.Series:*"""Standard deviation of age."""* return age.std()def age_zero_mean_unit_variance(age_zero_mean: pd.Series**,** age_std_dev: pd.Series) -> pd.Series:*"""Zero mean unit variance value of age"""* return age_zero_mean / age_std_dev

没有要操作的中心 dataframe 对象。相反,你在“专栏”中思考,并且只思考你需要表达什么来创建一个特定的专栏。

更具体地说,函数使用函数名声明它们输出的内容,并使用函数参数声明它们需要的输入内容。计算的逻辑完全包含在函数中,这就是我们所说的封装。函数名很重要,因为它映射到您可以请求输出的内容。

记住函数如何映射到 Pandas 数据帧的一个快速方法是,函数名映射到列,函数参数映射到其他列或其他输入。

对于第(2)点,您的变换函数位于 python 模块中,该模块独立于用于获取数据帧的脚本。也就是说,要实际计算上述内容,您需要编写一个如下所示的文件:

import pandas as pd
from hamilton import driverimport a_function_module # where your transforms livedr = driver.Driver({'age': pd.Series([...])}**,** a_function_module)# Here we're only requesting two outputs, but you could additionally 
# request `age_mean`, `age_zero_mean`, `age_std_dev` ...
df = dr.execute(['age', 'age_zero_mean_unit_variance'])

这迫使你遵循一个被称为解耦的软件工程原则。解耦对于数据工作来说是一个好主意,因为这意味着你的转换函数不关心你如何加载或获取数据,它们只关心计算。这意味着在其他上下文中重用您的 Hamilton 数据转换函数非常、非常、容易——而且不会影响任何人。

使用汉密尔顿的好处

无需深究细节,只要仔细想想就会明白,以下是汉密尔顿做事方式带来的一些好处:

  1. 所有 Hamilton 数据转换函数都是 100%单元可测试的。函数的声明性意味着传递测试数据非常容易!
  2. 所有汉密尔顿数据转换函数都是 100%文档友好的。每个功能都有一个有目的的位置来放置文档。想象一个拥有良好文档的数据工程/科学代码库😲?!
  3. 可重用的转换代码。因为从一开始就存在强制解耦,这意味着作为用户,您用自己的转换函数来管理 python 模块。因为它们驻留在模块中,所以很容易在其他上下文中重用这些代码,无论是用于不同的“驱动程序”脚本,还是简单地用作库。
  4. 代码基础一致性。根据以上几点,用 Hamilton 编写的特征工程代码库看起来非常标准化,因此易于维护和保养。

我如何使用汉密尔顿?

第一步。安装汉密尔顿

要开始安装 Hamilton:

pip install sf-hamilton

如果你正在使用笔记本环境,请看这篇关于如何在笔记本上使用 Hamilton 的文章。

第二步。编写您的 python 转换

创建一个 python 文件,例如 my_module.py,并用您的转换函数填充它。记住函数名映射到您可以作为输出请求的列,并且函数参数映射到其他列,或者您在运行时提供的输入。

import pandas as pddef age_mean(age: pd.Series) -> float:*"""Average of age"""* return age.mean()def age_zero_mean(age: pd.Series**,** age_mean: float) -> pd.Series:*"""Zero mean of age"""* return age - age_meandef age_std_dev(age: pd.Series) -> pd.Series:*"""Standard deviation of age."""* return age.std()def age_zero_mean_unit_variance(age_zero_mean: pd.Series**,** age_std_dev: pd.Series) -> pd.Series:*"""Zero mean unit variance value of age"""* return age_zero_mean / age_std_dev

第三步。编写一个“驱动程序”脚本,将所有东西整合在一起

创建一个 python 文件,例如 my_driver.py。

import pandas as pd
from hamilton import driver
import my_moduledr = driver.Driver({'age': pd.Series([...])}**,** my_module)
# execute() returns a dataframe by default
df = dr.execute(['age_zero_mean_unit_variance'])# do something with the dataframe

第四步。运行“驱动程序”脚本

python my_driver.py是运行一切所需的一切!

如果你正在使用一个编排/调度系统,比如 airflow、metaflow、kubeflow pipelines、prefect 等。您可以将驱动程序脚本的内容放入要执行的 ETL 的“步骤”中。

你可以用汉密尔顿做的其他事情

因为这是一个快速的帖子,我们不打算在这里深入细节。但是,为了激起您的兴趣,在使用 Pandas 时,汉密尔顿为您提供了以下开箱即用的功能:

  1. 扩展到“大数据”规模,因为 Hamilton 几乎免费支持 Dask、Pandas on Spark 和 Ray。参见汉密尔顿示例文件夹中的代码& 这里有一些文档。
  2. 数据血统。你可以把计算的步骤形象化,并且很容易地用哈密尔顿问你的图的问题。尝试使用dr.visualize_execution(...).
  3. 修饰功能的能力,例如有条件地包括基于配置的功能。不要用if else语句(例如if region == 'US')来点缀你的代码,相反,你可以通过用@config.when来装饰一个函数来捕捉这种逻辑。这只是用 Hamilton 提供功能和额外能力的几个装饰者之一。更多信息请见我们的文档。
  4. 汉密尔顿的用途不仅限于熊猫。您可以使用它来创建 numpy 矩阵、scikit-learn 模型、任何 python 对象等。!查看我们的示例文件夹了解想法。

最后

感谢你阅读这篇文章。我们很乐意帮助您成功使用汉密尔顿。欢迎在我们的 github 知识库中留下问题/评论(我们也很喜欢⭐️!),或者加入我们的 slack 服务器寻求帮助,或者提供建议/改进。

您可能感兴趣的其他汉密尔顿帖子:

  • 如何在笔记本环境中使用 Hamilton
  • 一般背景故事&汉密尔顿简介

如何使用 JSON 模式在 Python 中验证 JSON 文档

原文:https://towardsdatascience.com/how-to-use-json-schema-to-validate-json-documents-ae9d8d1db344

了解确保数据质量的标准方法

图片由 kreatikar 拍摄于 Pixabay

JSON 文档可以包含任意数量的键/值对。键必须是字符串,但值可以是任何支持的类型,如字符串、数字、布尔值等。该值甚至可以是复杂类型,如数组或嵌套对象。这使得 JSON 文档既非常灵活又非常松散。然而,这使得数据处理更加困难,因为数据团队经常通过 API 获取数据,而这些 API 的响应通常是 JSON 格式的。拥有一致的数据格式可以使数据管道更加健壮。有了统一的数据输入,就不需要担心意外的数据类型,也不需要在数据清理上花太多时间。因此,您可以更专注于数据分析,提高工作效率。

在这篇文章中,我们将介绍如何使用 JSON 模式来验证 JSON 文档。基本概念以及基本和高级用例将通过简单的代码片段进行介绍,这些代码片段易于理解。

什么是 JSON 模式?

JSON 模式是定义一些 JSON 数据模式的 JSON 文档。好吧,老实说,这种解释非常奇怪和难以理解,但一旦我们看到后面的代码,就会变得更加清晰。目前,我们需要理解两点:

  • JSON 模式本身是一个具有键/值对的有效 JSON 文档。每个键都有特殊的含义,用于定义一些 JSON 数据的模式。
  • 模式类似于 SQL 数据库中的表定义,定义 JSON 中字段的数据类型。它还定义了哪些字段是必需的,哪些是可选的。

让我们从一个简单的 JSON 模式开始:

这个 JSON 模式指定目标 JSON 是一个具有两个 属性 (通常也称为 //字段 的对象,并且name属性是必需的。让我们更深入地研究一下每个验证关键字:

  • type关键字指定目标 JSON 是一个对象。它也可以是一个数组,通常是 API 响应的对象数组。我们将在后面看到如何定义数组字段的模式。然而,在大多数情况下,顶级的type几乎总是object
  • properties关键字为 JSON 对象的每个字段指定模式。目标 JSON 的每个字段都被指定为一个键/值对,键是实际的字段名,值是目标 JSON 中的字段类型。每个字段的关键字type与顶级关键字的含义相同。可以想象,这里的type也可以是object。在这种情况下,相应的字段将是一个嵌套对象,这将在后面演示。
  • required关键字是一个数组,包含需要存在的属性。如果此处指定的任何属性缺失,将引发ValidationError

除了基本的验证关键字,即上面指定的typepropertiesrequired,还有其他模式关键字可以在在线文档和一些工具自动生成的 JSON 模式中看到。

有两个模式关键字,即[$schema](https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-schema-keyword)[$id](https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-id-keyword)$schema定义用于模式的草图。如果未指定$schema,将使用最新的草图,这通常是所希望的。作为一个初学者,如果你过多地潜入水中,你可能会很容易迷路。我们通常不需要接触$schema字段,我们会在这篇文章的最后介绍一点。另一方面,$id为模式定义了一个 URI,使得当前模式可以从外部被其他模式访问。如果没有指定$id,那么当前的模式只能在本地使用,这也是正常情况下需要的,至少对于小项目是这样。然而,对于更大的项目,您的机构可能有一个关于如何存储模式以及如何引用它们的内部系统。在这种情况下,您可以相应地设置$id 关键字。

有两个注释关键字,即titledescription,它们分别指定 JSON 模式的标题和描述。它们可用于文档,并使您的模式更易于阅读和理解。它们也会被一些图形工具很好地显示出来。为了简单起见,在本文中不会指定它们,但是通常应该将它们添加到您的项目中以获得最佳实践。

如何用 Python 验证 JSON 文档和模式?

在 Python 中,我们可以使用[jsonschema](https://pypi.org/project/jsonschema/)库来验证一个 JSON 实例 (也可以称为 JSON 文档 ,只要它是明确的)。可以安装 pip :

让我们根据上面定义的 JSON 模式来验证一些 JSON 实例。注意,从技术上讲 JSON 是一个字符串,但是我们需要指定要验证的 JSON 的底层数据,这样更方便。

这表明所定义的模式可以按预期用于验证 JSON 实例。不正确的数据类型或缺少某些必填字段将触发ValidationError。但是,应该注意的是,默认情况下允许附加字段,这可能是也可能不是您想要的。如果您想要一个严格的模式,并且只允许由properties关键字定义的字段,那么您可以将additionalProperties指定为False:

如何定义数组字段的模式?

尽管将数组作为顶级字段并不常见,但将其作为属性却非常常见。让我们给上面定义的模式添加一个数组属性。我们需要将type设置为array,并用items关键字为每一项指定type:

正如我们看到的,可以正确检查数组元素的类型。但是,默认情况下允许空数组。为了改变这种行为,我们可以将minItems设置为 1,或者您期望的对您的情况有意义的数字。

如何定义嵌套对象字段的模式?

如上所述,属性的type关键字与顶级关键字具有相同的含义和语法。因此,如果一个属性的typeobject,那么这个属性就是一个嵌套对象。让我们给 JSON 数据添加一个address属性,它将是一个嵌套对象:

正如我们所看到的,嵌套对象字段具有与顶级字段完全相同的模式定义语法。因此,为嵌套对象定义模式相当简单。

使用$defs来避免代码重复。

如果需要在同一个模式中的多个地方使用address字段,该怎么办?如果我们在任何需要的地方复制字段定义,就会有代码重复,这是程序员所讨厌的,因为它不是干的。在 JSON 模式定义中,我们可以使用[$defs](https://json-schema.org/draft/2020-12/json-schema-core.html#name-schema-re-use-with-defs)关键字来定义可以在其他地方引用的小子模式,以避免代码重复。让我们用$defs重构上面的模式,以潜在地避免代码重复:

正如我们所看到的,使用$defs定义子模式的新模式的工作方式和以前一样。但是,如果需要在同一模式的不同地方使用address字段,它的优点是可以避免代码重复。

如何设置元组字段的模式?

最后,如果我们希望scores字段是一个元素数量固定的元组呢?可惜 JSON schema 中没有 tuple 字段,我们需要通过数组来实现一个 tuple 的定义。一般逻辑是一个数组有项(items)并且可选地有一些位置定义的项在普通项(prefixItems)之前。对于一个元组,只有prefixItems没有items,达到了一个元组有固定数量的元素的效果。重要的是,每个元组元素的类型必须显式定义。

如果您想为一个 tuple 字段定义模式,您需要对 JSON schema 的草稿有所了解,这要高级一些。草案是 JSON 模式的标准或规范,定义了验证器应该如何解析模式。有几个草案可用,最新的是2020–12。你可以在这里找到草稿列表。

正常情况下,我们不需要担心$schema字段和要使用的草稿。然而,当我们需要定义一个元组字段时,这是我们应该注意的事情。

如果安装的[jsonschema](https://python-jsonschema.readthedocs.io/en/stable/)库是最新版本(撰写本文时为 v4.9.0),那么将使用最新草案(2020–12)。如果这是您想要的版本,您不需要通过$schema关键字指定草稿。然而,为了清晰起见,最好总是在 JSON 模式中指定草稿的版本。为了简单起见,在这篇文章的开头省略了它,这样你就不会不知所措,但是建议在实践中使用它。

另一方面,如果您想使用一个不同的草案版本而不是最新的版本,那么您需要在草案版本中明确指定关键字$schema。否则无法正常工作。

让我们分别使用草稿 2020–12 和 2019–09 定义scores字段的模式,并演示如何使用$schema关键字以及如何相应地定义元组字段:

正如我们所看到的,使用关键字prefixItemsitems的 draft 2020–12 元组字段的模式定义更直观,因此推荐使用。有关元组字段定义从 2019–09 到 2020–12 的变更的更详细说明,请查看本发行说明。

此外,需要注意的是,即使我们希望scores字段是一个元组,它也必须被指定为一个数组(Python 中的 list ),而不是验证器的元组。不然就不行了。

使用验证器有效地验证多个 JSON 文档

如果你有一个有效的 JSON 模式,并想用它来验证许多 JSON 文档,那么推荐使用Validator.validate方法,这比jsonchema.validate API 更有效。一个验证器是一个实现特定草稿的特殊类。比如有Draft202012ValidatorDraft201909ValidatorDraft7Validator等。如果类名中没有指定草案版本,Validator本身意味着所有验证器类都应该遵守的协议(类似于接口)。

除了工作方式类似于jsonchema.validate API 的Validator.validate方法之外,您还可以使用Validator.check_schema来检查一个模式对于一个特定的草稿是否有效。你也可以使用Validator.is_valid来悄悄地检查一个 JSON 是否有效,如果无效就不引发ValidationError。让我们用一些简单的例子来演示这些方法的用法,这样可以使它们更容易理解:

在这篇文章中,我们介绍了什么是 JSON 模式,以及如何使用它来验证 JSON 文档中的不同数据类型。我们已经介绍了字符串和数字等基本数据类型以及数组和嵌套对象等复杂数据类型的基础知识。此外,我们还学习了如何使用$defs关键字来避免代码重复,该关键字用于定义子模式,对于复杂的模式来说非常方便。最后但并非最不重要的是,草案的基础知识介绍。我们现在知道了如何用不同的草案定义一个 tuple 字段的模式,以及如何用一个使用特定草案的验证器更有效地验证多个 JSON 文档。

相关文章:

  • 如何在 Python 中执行 JSON 转换、序列化和比较
  • 使用 mypy 和 pydantic 进行 Python 类型化和验证

如何利用潜在语义分析对文档进行分类

原文:https://towardsdatascience.com/how-to-use-latent-semantic-analysis-to-classify-documents-1af717e7ee52

塔玛拉·加克在 Unsplash 上的照片

自然语言处理

学习一个有用的工具来克服分析文本的挑战

孩子们在地板上坐成一圈。

“扁帽子上有一个数字和一个标签,上面写着鹦鹉和煎饼”——一个孩子尖叫道

每个孩子都开始笑。

“不,不,是那只黑猫在桌子下面,它吃胡萝卜和煎饼”——另一个孩子回答道

我这才意识到他们在玩电话(在阿根廷我们称之为坏电话)。

人类的交流是复杂的,主要是因为每个人表达自己的方式不同。我们可以说同一种语言,但使用不同的俚语、词汇或表达来传达相同的信息。此外,我们可以用同一个词表达两种完全相反的意思。

书面语言并不简单。除了一词多义、同义词和词汇问题,人们经常忽略标点符号,拼错或缩写单词。尽管如此,大多数人还是能理解书面或口头语言。

对于机器来说,识别这些元素并不是一件容易的事情。用表格形式表示这些特征并不容易。这就是为什么分析文本比分析结构化数据更难。

自然语言处理(NLP)提供了帮助理解文本的句法和语义的工具。NLP 允许数据科学家解决语言中的歧义。它还有助于将非结构化文本转换为结构化数据,以用于多种应用,如语音识别或情感分析。

文档分类是文本挖掘领域的一个典型问题。它的使用案例从情感分析、垃圾邮件检测到社交网络文档的高级结构化表示。

文档分类根据文档的底层结构将文档组织成组。它主要依赖于将纯文本转换成结构化数据。

潜在语义分析

我们来分析一下以下对某酒店的评价:

  • 这家酒店非常棒,在炎热的日子里,我免费喝了很多饮料。
  • 设施非常棒,他们在游泳池免费提供饮料

我们可能会注意到饮料饮料有相同的意思;他们是 T4 的同义词。同样, served 有两个不同的意思:有用和提供;是多义的一个例子。

我们可能会理解不同或相似之处。但是对于机器学习算法来说,同义词和多义词可能是一个问题。

一种解决方案是组合具有相同含义的单词,或者在语义上相连并描述一个主题的单词。

这个潜在变量或维度代表了所有这些。这就是潜在语义分析(LSA) 中“潜在”的含义。

LSA 是一种无监督的算法,它涉及到将一组非结构化文本转换成结构化数据。

LSA 通过使用奇异值分解找到这些潜在变量,并转换原始数据。

此外,它还是一种降维算法,因为转换后的数据比原始数据小。

单一向量分解

简而言之,LSA 是将 SVD 应用于表示术语和文档之间关系的矩阵(术语-文档矩阵)。

我们可以认为每个术语定义一个输入维度,每个文档指定一个样本。

奇异值分解是一种矩阵分解的方法。使用这种方法,可以将一个矩阵分解成如下所示的三个矩阵。

根据奇异值分解分解原始矩阵。

我们来解释一下上图。

  • X 是文档术语矩阵。它包含 m 个文档(行)中 n 个唯一单词(列)的频率。这个矩阵大约是三个矩阵的乘积:转置的 U、S 和 V。这里,r 维表示主题的数量。
  • u 是文档-主题矩阵。为了创建这个矩阵,SVD 找到 XXT 的特征向量,并将它们放入它的列中。这个操作留给 U 包含左奇异向量的列。
  • s 是具有奇异值的对角矩阵,奇异值是来自 XXT 或 XTX 的特征值的平方根。奇异值按降序排列。
  • 最后,V 是字嵌入矩阵。在这种情况下,SVD 找到 XTX 的特征向量,并将它们放入它的列中,给 V 留下右奇异向量的行。

这里我们可以看到奇异值分解中的分解的含义。

因此,SVD 按照信息量递减的顺序对每个新维度进行排序。这意味着第一个维度比第二个维度承载更多的信息,以此类推。

它还将稀疏的文档术语矩阵转换成密集的文档主题矩阵。你可以使用这个矩阵,通过几个机器学习模型对文档进行分类。

文档分类

如前所述,LSA 将创建一个文件的矢量表示。然后,我们可以计算这些向量之间的距离。确定它们的相似性。并通过确定它们属于哪个主题来对文档进行分类。

如果主题是已知的,文档分类将需要标记的数据来训练模型。

另一方面,使用未标记数据和聚类方法可以识别文档组。

现在,让我们看看 LSA 的行动。

我们将使用一个流行的数据集进行文档分类: 20 个新闻组 ,新闻组文档的集合。

Scikit learn 提供了一个函数来从该数据集加载文件名和数据:fetch_20newsgroups

加载数据集后,需要删除电子邮件地址、网站和号码。

下一步是执行术语频率-逆文档频率 ( Tfidf )。这种技术从一组文档(或语料库)中确定一个单词在文档中的重要性。TF–IDF 值随着单词在文档中出现的次数成比例增加。然后根据语料库中包含该单词的文档数量进行偏移。这个调整是为了处理一般情况下有些词出现频率比较高的情况*。*

该操作将允许我们删除停用词,过滤出现太频繁(40%的文档)或不太频繁的术语,将单词转换为小写,并对结果单词向量进行归一化。

现在,是时候应用 LSA 或者换句话说,TruncatedSVD它的 python 实现。我们需要将组件的数量设置为 20。它是数据集文档中陈述的主题数量。

最后,我们应该选择一种分类算法,并使用 LSA 数据集对其进行训练。我们会选择支持向量机。该算法的一些特点,如计算的可扩展性和易于实现,使其非常适合应用于文档分类。

现在,我们可以通过转换测试数据集并使用训练好的模型预测主题来测试模型。

准确率在 ~69% ,有一定的提升空间。

优点和局限性

在过去的几年中,NLP 方法的使用已经广泛传播。LSA 也不例外,这是由于它的好处。

在 LSA,概念和它们相关的文档被一致地表示。此外,LSA 分析有助于恢复原文的语义结构和维度。

文档词汇往往很大,因此噪音是常见的。LSA 帮助对数据进行去噪处理。

但是 LSA 有一些局限性。最大的缺点之一是向量需要大量的存储和计算能力。对于长文档,LSA 需要大量的计算时间,降低了效率。

总之,LSA 是高效且易于实现的,在使用小数据时能给出好的结果。但是,计算量很大,而且很难事先确定主题。

我们可以使用一些方法来改进文档分类,比如使用替代的或修改的 SVD 计算方法,或者尝试其他的降维算法。

一些资源

  1. 懒程序员。Python 中的自然语言处理:垃圾邮件检测、情感分析、潜在语义分析和文章旋转的主数据科学和机器学习(Python 中的机器学习)。
  2. 潜在语义分析&Python 中的情感分析。走向数据科学
  3. Hava1 O,Skrbek M 和 Kordik P. 用于文档分类的上下文潜在语义网络。

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

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

相关文章

格点拉格朗日插值与PME算法

本文介绍了使用基于格点拉格朗日插值法的Particle Mesh Ewald算法,降低分子力场中的静电势能项计算复杂度的基本原理。静电势能的计算在Ewald求和框架下被拆分成了远程相互作用项和短程相互作用项,其中短程相互作用项关于实空间的点电荷间距快速收敛,而远程相互作用项在倒易…

公司网站怎么修改?数据库内网站密码修改?

修改公司网站通常涉及以下几个步骤:确定需求:明确需要修改的内容,如页面设计、功能增加或信息更新等。 收集相关资料和内容,确保所有需要的信息都准备齐全。选择工具或平台:如果网站是基于WordPress、Joomla等CMS系统构建的,可以通过后台直接进行编辑。 对于自定义开发的…

修改默认登录网站密码?

修改默认登录网站密码通常涉及以下几个步骤,具体操作可能会根据不同的网站或系统有所差异:登录账户:打开你需要修改密码的网站。 使用当前的用户名和密码登录你的账户。进入账户设置:登录后,找到并点击“账户”、“个人资料”或“设置”等相关链接或按钮。 在账户设置页面…

如何在后台修改网站资料?网站后台如何修改字体?

在后台修改网站资料通常涉及以下几个步骤,具体操作可能会根据不同的内容管理系统(CMS)或网站平台有所不同:登录后台管理界面:使用管理员账号和密码登录到网站的后台管理界面。导航至内容管理:在后台找到“内容管理”、“页面管理”或类似的选项,这通常是编辑网站资料的地…

网站模板修改?网站模板咋样修改?

1. 确定修改目标功能需求:明确需要添加或删除的功能。 设计需求:确定颜色、布局、字体等视觉元素的调整。2. 备份现有模板在进行任何修改之前,确保备份当前使用的模板文件,以防修改过程中出现错误可以恢复原状。3. 修改HTML/CSSHTML:根据功能需求,编辑HTML结构,添加或删…

C语言小白记录自己的错题和总结

​ 计算n个a的思路都是用a+a10+a100…… 然后在累加 记得用include<math.h> pow 考察逗号表达式 即使像x+y x+7之类的 算出结果后 x和y还是不变 因为没有赋值 所以x和y都是原来的值 问号语句 先计算第一个表达式 若他的值为非0(即真)将表达式2的值作为条件表达式的值…

数据库系列:主从延时优化

相关文章 数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩容 数据库系列:使用高区分度索引列提升性能 数据库系列:前缀索引和索引长…

平衡堆栈

理解并观测函数调用母函数做什么,子函数做什么cdecl调用约定#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int __cdecl method(int x, int y){ return x + y;}int main(){ __asm mov eax, eax; // 此处设置断点 method(1, 2); return 0;}可以看出_…