TowardsDataScience 博客中文翻译 2020(七百七十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

电子显微镜图像的尺寸分析,

原文:https://towardsdatascience.com/saemi-size-analysis-of-electron-microscopy-images-7ab55bd979ac?source=collection_archive---------62-----------------------

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

来源: CNR-IOM ( 抄送)

第 2 部分,如何从 EM 图像获得尺寸分布

本文是我的系列文章的第 2 部分,详细介绍了 SAEMI 的使用和开发,这是我创建的一个 web 应用程序,用于执行电子显微镜图像的高通量定量分析。在这里查看第 1 部分(在这里我回顾了应用背后的动机)和第 3 部分这里(在这里我回顾了我如何训练我的图像分割模型)。你也可以在这里查看 app ,在这里查看它的 Github 。在这篇文章中,我给出了一个如何使用该应用程序并获得最佳结果的演练。

所以你有一个电子显微镜图像

从这篇文章开始,我假设你以前看过/拍过电子显微镜(EM)图像,或者至少熟悉电子显微镜。如果没有,请查看我的系列文章第 1 部分中的,在那里我详细描述了开发这个应用程序背后的动机。不过,让我们假设你是一名研究人员,已经进行了一些电磁测量,现在想对你的图像进行一些定量分析。更具体地说,您想要确定图像中颗粒的平均尺寸以及该分布的标准偏差。例如,假设您有一个 EM 图像,如图 1 所示。

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

1 是一个电磁图像的例子。来源:CNR-IOM(CC-BY)

这里首先要注意的是图像底部显示的横幅,其中包含测量信息,如比例尺、电子高压(EHT)和放大倍数。许多电子显微镜及其配套软件会将这类信息(至少会有一个比例尺)添加到图像中。不幸的是,由于这是图像本身的一部分,因此保留它可能会影响深度学习模型的最终分割。

为了减少出错的可能性,应该尽可能从图像中删除附加的“元信息”。但是,请注意在其他地方保留比例尺的记录,因为在最终步骤中,需要将最终计算结果从像素转换为物理尺寸。目前,“元信息”可以通过许多不同的方法去除。

最简单的方法,也是我个人推荐的方法,就是把它从图像中剔除。它引入更多伪像的可能性最小,并且需要图像处理中最少的技术能力来执行。唯一的缺点是裁剪图像可能会丢失重要的数据。

为了展示其他选项,您还可以使用一些更复杂的图像处理技术,使用 Python 中的 open-cv 或 scikit-image 库来移除横幅。这些方法包括使用反射填充、最近邻填充和常数填充。这三种方法的示例如图 2 所示。在所有三个示例中,横幅原来所在的区域都用红色突出显示。

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

图 2 a)使用反射填充去除标语的示例 b)使用最近邻填充去除标语的示例 c)通过用常数填充替换标语来去除标语。来源: CNR-IOM ( 抄送)

可以看出,这些方法中的每一种都可能导致图像出现非预期的伪像,这取决于您决定如何处理“元信息”。

使用应用程序

现在,假设您决定通过裁剪来移除横幅。然后你可以使用这个链接进入应用程序,然后使用顶部的“上传图片”按钮上传图片。或者,你可以按照我的 github 页面上的说明这里在你的电脑上本地使用这个应用程序。无论哪种方式,一旦打开应用程序,你会看到如图 3 所示的主页。“上传图像”按钮以红色突出显示。如果您手头没有 EM 图像,您也可以使用旁边的“尝试演示”按钮。这将上传一个已经准备好的演示 EM 图像,作为应用程序如何工作的例子。

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

图 3 赛米主页。截图来自 SAEMI

一旦图像上传到服务器,它将通过我的深度学习模型进行馈送,并使用连通分量标记来计算粒子的大小分布。整个过程大约需要 20-30 秒。我会继续尽我所能加快这个过程。然而,即使有这么长的运行时间,它仍然比手动标记 EM 图像快得多,因为这些图像中一次可以有数百个粒子。计算完大小分布后,您将看到一个类似于图 4 所示的网页。

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

图 4 图片上传后的 SAEMI。截图来自萨米

让我们更详细地看一下每一部分。

粒度分布

你会注意到的第一个也可能是最重要的部分是尺寸分布直方图。这在图 5 中更详细地示出。

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

图 5 粒度分布直方图。截图来自萨米

顶部是原始 EM 图像,图像文件的名称显示在它的上方。应用程序计算的大小分布显示在直方图下方,x 轴为大小(以像素为单位), y 轴为计数。因此,有 3 个粒子占据图像中大约 1300 个像素,1 个粒子占据大约 500 个像素。在应用程序中,你可以将鼠标悬停在数据点上来查看它们的确切值。

平均值、中值和标准偏差也已计算出来,并显示在直方图的左上角。在直方图的正上方,你还可以看到一个输入框,上面写着“输入箱子尺寸”。这可用于改变用于定义直方图的仓尺寸。默认的媒体夹大小是 25 像素。例如,图 6 显示了一个 75 像素的直方图。

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

图 6 箱尺寸为 75 的尺寸分布。截图自萨米

最后,点击底部的“下载数据”将下载尺寸分布作为一个单独的列。csv 文件。然后,您可以执行其他计算,例如确定其他统计模式,或者按照您希望的方式对尺寸分布数据进行建模。

不过,需要注意的重要一点是,所有这些尺寸都是以像素为单位计算的。一个粒子在 EM 图像中占据多少像素。为了获得物理相关的测量值,您必须自己将尺寸转换回物理单位。例如,在图 1 的原始图像中,比例尺显示 2 微米占据大约 110 个像素。因此,500 像素大小的颗粒实际上具有大约 0.9 平方微米的面积。

用片段覆盖原件

您应该查看的下一部分是图 7 中右下方的部分。

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

图 7 覆盖了分段预测的原始 EM 图像。截图自萨米

这一部分是为了让你仔细检查预测,并确保应用程序能够正确地分割你的 EM 图像。正如你所看到的,这个应用程序在预测图像中每个粒子的位置方面做得非常好。为了更加清晰,您还可以使用图像底部的滑块来更改叠层的不透明度。如果您希望原始图像更清晰,可以将滑块滑动到较低的值。这如图 8 所示。

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

图 8 显示了原始图像。截图来自萨米

或者,您可以将滑块滑动到更高的值,以便更清楚地显示预测。这如图 9 所示。

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

图 9 示出了预测的分割。截图来自萨米

从覆盖图来看,似乎这个模型在分割原始 EM 图像的粒子方面做得相当不错。然而,请注意在分段预测的左下方,有两个非常小的预测粒子,它们在原始 EM 图像中不存在。这在图 10 中更详细地示出。

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

图 10 原始 EM 图像和预测不匹配的区域。截图自萨米

不幸的是,由于它们的尺寸非常小,它们可能会使计算出的平均值偏向较低的值。在这种情况下,中值可能是 EM 图像中平均颗粒尺寸的更好量度。

处理结果图像

为了确保直方图显示尽可能准确,您可以使用“处理图像”部分编辑掉一些不准确的预测。这在图 11 中有更详细的显示。

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

图 11 后处理图像画布。截图来自 SAEMI

在图 11 中,您可以看到图像下方显示了几个不同的项目,这将帮助您编辑预测。前两个是撤销和重做按钮(分别用左右箭头表示),应该非常简单。在它们旁边的右边是保存按钮,它将保存你对图像所做的更改,然后根据你的更改重新计算尺寸分布。

它们的正下方是“黑白”和“颜色”两个选项按钮。如果选择“黑白”,上面显示的图像将只是二进制掩码。如果你选择“颜色”,图像实际上会显示应用程序看到的单个粒子。换句话说,对于阵列中每个连接的组件,显示的图像将具有唯一的标签。两个选项的比较如图 12 所示。

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

图 12 a)黑白选项 B)颜色选项。截图自萨米

当你不确定应用程序将两个非常接近的粒子视为一个粒子还是两个粒子时,显示“颜色”选项会很有用。请记住,这两个选项都不会编辑图像本身。它只是为您提供对原始预测的不同看法。

在底部,有一个下拉菜单,允许您选择如何编辑图像。有三个选项可供选择:绘制、移除和擦除。选择这些选项将改变画笔的颜色分别为白色,红色和黑色。

使用“绘制”笔刷编辑图像会将您绘制的任何内容添加到预测中。例如,如果在左上角有一个应用程序不知何故漏掉的粒子,你可以用白色画笔在左下角的画布上绘制来填充它。图 14 显示了一个例子。

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

图 14 a)原始分割 b)使用 Draw 函数在左上角添加粒子。截图来自萨米

然而,对于我们的图像,有些斑点被误认为是粒子,最好使用移除(红色)或擦除(黑色)选项。通过使用红色画笔,您可以移除任何被红色笔画标记的粒子。图 15 显示了一个例子。

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

图 15 a)示出了在按下保存并应用移除选项之后,在原始分段 b)上的移除(红色)画笔。截图来自萨米

使用黑色画笔将简单地从预测中擦除该区域。虽然乍一看,红色和白色的画笔是一样的,但它们确实有两种不同的功能。红色画笔移除整个粒子,而白色画笔仅移除已标记的部分。图 16 显示了两种画笔的不同用法。

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

图 16 a)在粒子上使用红色笔刷的结果 b)在粒子上使用黑色笔刷的结果。截图自萨米

最后,在两个显示选项下面有一个滑块,可以改变“笔刷”的宽度。图 13 显示了不同画笔宽度的示例。

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

图 13 a)在宽度尺寸为 5 的画布上绘图 b)在宽度尺寸为 30 的画布上绘图。截图来自萨米

恭喜你!你有一个尺寸分布

在执行了令您满意的后处理步骤后,您最终会得到一个准确反映原始图像的尺寸分布。最终的直方图如图 18 所示。

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

图 18 最终的直方图。截图来自萨米

与我们在图 5 中获得的原始直方图相比,差异并不大,因为该模型已经在预测图像中的粒子方面做得非常好。此外,图像中有许多粒子,所以即使是它犯的小错误也被它识别的阳性粒子淹没了。

但是,如果仔细观察,您会发现平均值从 1.17E3 变为 1.23E3,分布的标准偏差从 5.73E2 变为 5.23E2。同样,您可以将此分布下载为. csv 文件,以便稍后执行其他计算。的。csv 文件包含由我的深度学习模型确定的所有单个粒子的计算尺寸(以像素为单位)。

下载后要执行的计算示例。csv 文件,您可以计算您的大小分布的模式和偏斜,如果您想要更多的统计信息。您也可以从同一样本的多个图像中汇总数据,以获得更大的样本量。此外,您可以绘制多个直方图,反映样品大小分布如何随时间、温度、pH 值等变化。

如果你想在你自己的 EM 图像上尝试 SAEMI,你可以现在就去那里并遵循本文中概述的步骤。祝你好运,请查看本系列的最后部分,在那里我会更深入地了解我是如何训练深度学习模型的,以及它的架构实际上是什么。谢谢!

安全的城市自行车运动第 1 部分:使用历史骑行数据创建随机的城市自行车路线并制作动画

原文:https://towardsdatascience.com/safe-city-biking-part-1-creating-randomized-citibike-routes-using-historical-ride-data-136224bbd955?source=collection_archive---------76-----------------------

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

马克斯·本德在 Unsplash 上的照片

端到端项目

在本文中,我将勾勒出我的项目路线图,从 Arduino 到数据科学/分析再到增强现实,并从第一步开始。

我一直是一个狂热的自行车爱好者:从每天骑自行车在数英里的山上往返于高中,到现在每天骑着 Citibike 在布鲁克林和时代广场之间跑 12 英里去上班。以下是我成为会员两年来的 Citibike 统计数据截图(在此之前,我会在城市里玩滑板):

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

这是横穿美国大约一倍半的距离

如果你熟悉在纽约骑自行车,你就会知道骑自行车并不总是安全或平稳的。这些年来我看到了进步,但也有相当多的事故,比如被打开的车门撞上,或者撞到一个很大的坑洞,我被从自行车上摔了下来。除了伤害/事故统计数据之外,很难找到这个城市实际骑自行车情况的数据,所以我决定收集自己的数据。

以下是项目的主要步骤:

  1. 使用 2019 年夏季的 Citibike 历史骑行数据规划骑行路线。
  2. 创建具有 GPS/LTE、陀螺仪和加速度计功能的 Arduino 传感器。
  3. 路线上超过 100 次骑行,从安装在自行车头盔上的传感器收集数据。使用 HTTP post 请求发送数据,并将这些数据存储在数据库中。
  4. 在 Python 中分析这些数据后,构建一个模型,该模型可以预测从 A 点到 B 点的最稳定乘坐,同时还可以提供路线间平均速度和稳定性的热图。
  5. 使用 Mapbox 将所有这些整合到 Unity 中,并创建 AR 世界范围的应用程序和 VR 可探索的数据体验。

首先,我从 Citibike 的月度骑行数据库下载了 2019 年 6 月和 7 月。我想找出其他骑手最常走的路线,并围绕这些路线规划我的路线。为此,我创建了一个名为pathfinder的函数,它将创建一条从离我最近的自行车站开始的路线,并不断选择每英里最受欢迎的自行车站,直到它到达五英里。第一步是使用哈弗森公式,过滤数据帧,只保留距离起点站 1 英里半径内的终点站。这个公式考虑了地球的曲率,这比只采用欧几里得距离更准确。

我使用斯科尔斯街&曼哈顿大道和 S 4 街&威斯大道,函数返回 1.14 英里,而谷歌地图给我 1.3 英里。我添加了一个 1.15 倍的乘数,以说明从鸟瞰图到实际路线长度的转换,从而得到 1.31 英里。

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

我们将使用 OSMNX 在未来的计算中使用最短的路线

然后,我使用 rand 从该点选择三个最受欢迎的终端站之一。一旦我离开我的第一个出发站 5 英里,我将结束探路者循环,使用osmnx包走所有的路线。

我们的 Pathfinder 函数通过 while 循环输出以下路径:

station number 0: Scholes St & Manhattan Ave
station number 1: Bayard St & Leonard St
station number 2: 49 Ave & 21 St
station number 3: 1 Ave & E 18 St
station number 4: 1 Ave & E 44 St

我们可以用它来绘图:

fig, ax = ox.plot_graph_routes(G, route, route_color='b', node_size=0)

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

经过一些 Geopandas 数据帧处理后,我用 plotly.express scatter_mapbox制作了路线动画。

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

我将在每次外出时为自己生成一条随机路径,尽管随着时间的推移,我将不得不考虑覆盖范围以及与先前路线的重叠。

如果我们有车站自行车数量/可用性数据,我们可以使用它来运行蒙特卡罗马尔可夫链(MCMC)模型(如果在每个时间点从车站租赁自行车,则根据会员/骑手总数有额外的车站激活概率),以计算每天结束时自行车在城市中的分布。我可能会在另一篇文章中做这个练习,因为在运行模型之前,它需要更多的数据收集和更多的预处理步骤。

下一次,我将介绍如何设置 Arduino 设备,并将其连接到数据库以使用 Python 进行查询。如果你对这个项目感兴趣,请随时联系我,就你希望我收集的任何数据或你可能有的想法提出建议。

你可以在这个 GitHub 库里找到所有的代码。

Power BI 中的安全点击技巧

原文:https://towardsdatascience.com/safe-click-trick-in-power-bi-d3e2296ade04?source=collection_archive---------45-----------------------

想要避免恼人的书签“点击”行为?检查这个简单的“安全点击”技巧!

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

JESHOOTS.com 在 Pexels 上拍摄的照片

书签是 Power BI 中最常用的功能之一。就我个人而言,这是我的最爱之一,因为它们让您有可能创建“类似应用程序”的功率 BI 报告,并使它们看起来更具交互性。

我已经写过关于使用书签将静态视觉效果转换成动态视觉效果的文章。你也可以使用书签构建一个你的用户会喜欢的专业切片器面板。老实说,确实有许多可以应用书签的用例。

基本上,书签所做的是,它捕捉报告页面上视觉效果的当前状态,因此您可以通过按钮、图像、形状等在您的操作中使用它作为参考。

讨厌的书签

然而,书签有一个非常令人讨厌的行为,当您处理形状时会出现这种行为。让我们转到 Power BI 中的一个示例,我将解释问题是什么以及如何轻松解决它。

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

我有一个大的切片器面板,作为多个切片器的占位符。然而,如果我点击矩形区域的某个地方,在切片器本身之外,这个窗格将覆盖所有切片器!对于我的用户来说,这不是一个好的体验,因为他们中的大多数人不知道他们可以点击形状以外的任何地方,一切都会恢复正常。而我想改变这种行为…

安全点击技巧!

我们需要做的第一件事是打开 Power BI desktop 中视图选项卡下的书签窗格:

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

展开切片器窗格后,我将创建一个新的书签,取消选中所有内容,因此它变成灰色:

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

现在,让我们为我们的形状定义一个动作,以便它指向我们新创建的书签:

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

由于我们已经禁用了一切,这个形状变得不可点击,这意味着它不会出现在我们的切片器,如果用户点击它!

让我们看看这是否可行:

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

厉害!正如你所注意到的,当我点击形状内的区域时,在切片器之外,什么也没有发生——正如我们所预期的!

结论

小细节可以对用户体验产生很大影响。在设计 Power BI 报告时请记住这一点,您的用户会喜欢您的:)

订阅这里获取更多有见地的数据文章!

安全!击球手对到达一垒的影响

原文:https://towardsdatascience.com/safe-the-effect-of-batting-hand-on-making-it-to-first-base-b89ac3a1888?source=collection_archive---------43-----------------------

实践教程

左撇子或右撇子击球手更容易吗?

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

照片由 Tim GouwUnsplash 上拍摄

几周前,我和家人一起看了 2020 年世界职业棒球大赛的第一场比赛。我不确定为什么会出现这个问题,但有人问客厅对左撇子或右撇子击球手在接到球后是否更容易上一垒的看法。这是一个有趣的问题,没有人有充分的答案。我的父亲是闪耀着智慧光芒的灯塔,他说我应该用科学的方法来解决这个问题,建议我召集大约 30 个朋友和同事在当地的 diamond 进行一个下午的跑步训练。这不是一个坏主意,但让 30 个人一起在全球疫情中可能是一个糟糕的决定。代替直接的科学观察,通过已经收集的数据可能会有用。记住这一点,为了纪念刚刚结束的 2020 年世界职业棒球大赛(祝贺道奇队的球迷!),我决定围绕这个主题来撰写我的首次数据项目文章博客。

假设:距离还是加速度?

在起居室的辩论中,出现了两种假设,各持一方。EASY-L 假说的支持者认为,左手击球手(lhb)更容易,因为从他们的本垒板到一垒的距离比那些右击球手小。EASY-R 的支持者说,因为右撇子面对一垒时转弯较少,所以他们加速更有效率,也更容易到达 1B。图 1 给出了这些假设背后的逻辑的图形表示。两个都是好主意,但只有一个能成为冠军。让我们看看数据是怎么说的。

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

图一。击球几何图;(左)左手面糊几何。θ’ L ‘是击球手的法线矢量和朝向一垒的矢量之间的角度。-X 表示左手击球手在 X 轴上比本垒板的原点更靠近 1B;(右)右手面糊几何。θ’ R ';是击球手的法线向量和朝向一垒的向量之间的角度。+X 表示右手击球手在 X 轴上比本垒板的原点离 1B 更远。作者图片

首先,在这个项目中,我使用了从 MLB 的一个统计网站 BaseballSavant [1]下载的 2020 年统计数据。它有一个伟大的用户界面,这意味着没有必要刮什么…?事情简单时真好。我使用的数据集(以及大多数棒球数据集)的唯一问题是,它没有将击球手作为每个球员条目的一个特征。考虑到击球手是整个分析的阶级区分基础,没有这些数据是一个小问题。幸运的是,在做了一些挖掘后,我能够在 BaseballSavant 上找到另一个数据集,它确实包括击球手作为一个特征(所以肯定没有刮擦!)【2】。

在添加击球手分类变量后,我将主数据集分成三个子集:(1)右手击球手,(2)左手击球手,以及(3)交换击球手统计数据。我将交换击球手从两个单边击球手组中分离出来,因为没有任何容易获得的统计数据来描述交换击球手在本垒板两侧的表现。无论如何,一旦这种分离完成,就该进入数据了。

一个很好的初始统计数据是球员平均击球率(BA 或 AVG ),我们的数据显示 RHBs(2020 年)比 LHBs 表现好约 2%(图 2。).这是一个有趣的结果:常识告诉我们,当击球手面对投掷臂与击球臂相反的投手时,他们会表现得更好。考虑到目前大多数投手都是用右手投球,一般来说,左投手应该比右投手表现更好,但是我跑题了。

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

图二。每类击球手的平均击球率分布;作者图片

RhB 相对于其左对手 BA 的 2%的优势可能是 EASY-R 假说的一个要点,但它绝对是一个次要的要点。BA 是总安打数与每场击球数的比率;在计算这个指标时,单打、双打、三垒打和全垒打都被认为是命中。这使我们的分析变得混乱,我们的分析集中在去 1B 的容易程度上。击球手成为一个好的跑垒员可能是达到高击球率的一个组成部分,但在这方面,成为一个好的击球手是一个更重要的属性。

用于这种特定分析的更好的修正击球率度量将省略非单次击球。我们可以计算一个新的平均打击率,一个“单次平均”,这将是一名球员的总记录单打与该球员的非三振出局数(高飞球、滚地球、边线球和弹出球)的比率。然而,这个标准在描述击球手到达一垒的能力方面仍然有问题。一个球员的单打平均包括所有记录的单打,这意味着线驱动器和飞球被计算在内。同样,总输出数包括弹出型输出和直线驱动输出。包含这些类型的安打/出局的问题是击球手一开始没有机会被出局。如果击球手不能被扔出,那么这个标准就不能准确描述击球手到达 1B 的效率。一个更好的衡量标准是一名球员的地面击球与地面事件的比率(击球+出局)或 H/(H+O)G。

如果你看过一两场棒球比赛,你可能在 1B 看到过击球手击出快速滚地球后的千钧一发。在这些情况下,在跑垒上处于劣势的球员应该比他们的优势对手更经常被淘汰出局;优势跑步者应该获得更高的 H/(H+O)G 数。因此,我计算了每个玩家的 H/(H+O)G,并将结果绘制在图 3 中。同样,右手击球手的表现似乎比左手击球手略好,相差约 5%。EASY-R 机组的另一点。

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

图 3。各类别地面事件总数中地面命中率的分布;右手击球手的表现似乎比左手击球手好 5%。作者图片

到目前为止,显示的数据表明,RhB 平均比 lhb 更容易上垒。然而,右撇子击球手是否有跑动优势或者只是更好的击球手还不清楚。我查看了击球手的跑步指标,找出了真相。

我使用的具体指标是跑步者速度(RS)和跑步者从本垒到 1B (HP-1B)的平均时间。由于速度/速率和位移/距离之间的关系,您会期望这些度量具有某种线性关系。这正是图 4 中观察到的情况,因为来自所有三个类别的数据显示了跑步者的速度和到达 1B 的时间之间的反比关系。这是有道理的——你走得越快,就能越快到达目的地。虽然这个结果是意料之中的,但仍然有很多信息需要从这些数据中解开。

首先,让我们看看对每个类别的数据运行线性回归的结果。右手击球员线和左手击球员线的 R = 0.85,显示出时间和运动员速度之间相对较强的关系。左手线的 R = 0.77,关系明显较弱。左手边的线具有较低的 R 值有一个很好的解释,但我们很快会回到这个问题上。所有三条线都具有相对相似的斜率(L = -0.1345,R = -0.1341,S = -0.140),并且具有 L=8.04,R=8.14 和 S=8.2 的 y 截距。为了解释这些数字,我们必须理解描述数据的线性函数的含义。

我们来谈谈 y 轴截距。我们知道我们的 y 变量是以秒为单位测量的,这意味着我们的 y 截距也是如此。在这种情况下,y 轴截距是一个物体在无摩擦真空中以给定速度从本垒板行进 90 英尺左右所需的理想时间与跑步者到达那里所需的实际观察时间之差;我们称之为“时间成本”让我们假设,从空气动力学的角度来说,玩家相对相似(一个令人震惊的提议)。如果我们的假设是正确的,lhb 和 RhB 之间的时间成本差异可能源于它们必须运行的实际距离的微小差异(图 1。) .

坡呢?同样,我们知道 y 变量以秒为单位,x 变量以英尺/秒为单位。如果我们想把后者转换成前者,我们需要把 x 变量乘以单位秒/英尺。这个斜率单位是我们用来测量加速度的单位(英尺/秒)的倒数,这意味着计算出的斜率代表“加速度倒数”在这种情况下,斜率越负意味着所代表的组加速越慢。这里的解释表明,平均而言,lhb 和 RhB 的加速速率相同。切换击球手的加速速度比 L 和 R 的稍低。

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

图 4。HP 到 1B 时间对跑步者速度;作者图片

数据显示加速度/斜率相对相同,左撇子和右撇子有 0.1 秒左右的时间成本差异。这实际上意味着,一般来说,一个 LHB 人会比一个右撇子以同样的速度提前十分之一秒到达 1B。然而,这只是一般情况。数据还显示,一些左撇子可以在相同的速度下比右撇子多花将近半秒的时间!在 90 英尺的冲刺中,这是一个很大的优势。称之为 EASY-L 的大满贯!

这怎么可能呢?回想一下,回归的左撇子曲线的 R 值明显比右撇子或转换击球手曲线的 R 值差。从视觉上看,这是有意义的,因为对于给定的 x 轴值,y 轴值有更大的分布。这种蔓延的原因是什么?投机时间!我把对回归线的偏离解释为击球手转身效率的一种衡量。回想一下,lhb 必须转过一个大角度来面对 1B。我的猜测是,一些击球手能够比其他人更好地转过这个更大的角度,并因此获得甜蜜的时间奖励。我假设转身的能力,以及延伸的时间奖励,可能与玩家的体能有关系,并绘制了每个玩家的时间差与身体质量指数,以测试这一点(图。5).用于计算身体质量指数的体重和身高数据取自查德威克棒球局数据库[3]。

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

图 5。时差对身体质量指数;时间差,通过计算球员观察到的 HP-1B 时间与该球员的击球组对应的最佳拟合线值之间的差异来计算。作者图片

不幸的是,对我来说,没有这样的关系。事后看来,这并不十分令人惊讶,因为学术界对身体质量指数作为健康指标的有效性存在明显的分歧。这就是说,有趣的是,根据疾病预防控制中心[4],MLB 的大多数球员都超重(身体质量指数> 25 岁)。这里还有更多的分析要做,但是为了我们两个,让我们结束吧。这是 tl。博士带回家的消息。

酱外带

  1. 平均来说,左撇子击球手在到达 1B 时比右撇子多 0.1 秒的优势。轻松赢了。
  2. 根据玩家的转身效率,这个优势可能会增加到大约 0.5 秒。
  3. 2020 年,惯用右手的击球手比惯用左手的击球手获得更好的奖励。
  4. 额外收获:根据疾病预防控制中心的说法,大多数被抽样的球员都超重,理由是身体质量指数高[5]。

如果你做到了这一步,我希望你喜欢我的第一篇博客/文章。我用于数据分析和图形生成的所有代码和数据都可以在我的 github [6]中找到。感谢阅读!

-乔丹

参考文献:

[1]https://baseballsavant.mlb.com/leaderboard/

https://baseballsavant.mlb.com/visuals/batter-positioning

[3]https://raw . githubusercontent . com/chadwickbureau/baseball databank/master/core/people . CSV

[4]https://www . medical news today . com/articles/265215 #腰围与糖尿病风险相关,不考虑身体质量指数

[5]https://www . CDC . gov/healthy weight/assessing/BMI/adult _ BMI/index . html # interpreted adults

[6]https://github.com/Jordan-M-Young?tab=repositories

将 ML 模型安全地推广到生产中

原文:https://towardsdatascience.com/safely-rolling-out-ml-models-to-production-13e0b8211a2f?source=collection_archive---------16-----------------------

理解大数据

轻松部署机器学习模型和版本的最佳 CI/CD 实践

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

指挥不同的(非 ML)乐器。资料来源:联合国人类住区规划署

对于任何数据科学家来说,将模型的新版本投入生产的那一天都是百感交集的一天。一方面,你们正在发布一个新的版本,这个版本旨在产生更好的结果和更大的影响;另一方面,这是一个相当可怕和紧张的时刻。你新的闪亮版本可能包含一些缺陷,只有在它们产生负面影响后,你才能发现这些缺陷。

ML 就像指挥不同的乐器一样复杂

将一个新版本替换或发布到生产环境会触及到业务流程的核心决策逻辑。随着人工智能采用率的上升,自动发布和更新模型的必要性正在成为一项常见和频繁的任务,这使得它成为数据科学团队的首要关注问题。

在这篇文章中,我将回顾是什么使新版本的推出如此敏感,需要什么预防措施,以及如何利用监控来优化您的持续集成(CI)管道,以及您的持续部署(CD)管道,以安全地实现您的目标。

ML 系统由软件的多个移动且独立的部分组成,这些部分需要相互协调工作:

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

“ML 管弦乐队”。作者图片

培训管道:包括利用您的历史数据集生成工作模型的所有处理步骤:数据预处理,如嵌入、缩放、特征工程、特征选择或降维、超参数调整,以及使用交叉验证或保留集的性能评估。

  • 模型注册中心:一个部署的模型可以采取多种形式:特定的对象序列化,比如 pickle,或者跨技术序列化格式,比如 PMML。通常,这些文件保存在基于注册表的共享文件存储中(S3、GCS 等),保存在标准版本存储库(git)或专用服务中,如 MLFlow 模型注册表
  • 服务层:这是实际的预测服务。这些层可以与依赖于模型预测的应用程序的业务逻辑嵌入在一起,也可以分离出来充当与其支持的业务流程分离的预测服务。在这两种情况下,核心功能都是使用模型注册中心的模型,根据新的输入请求检索相关的预测。这种服务可以以批处理或流的方式工作。
  • 标签收集:为监督学习案例收集基础事实的过程。可以手动、自动或使用主动学习等混合方法来完成。
  • 监控:一个集中的服务,监控整个过程和你的活体模型的健康状况,从进入服务的输入的质量,到检测漂移、偏差或完整性问题的收集标签。

鉴于这种相对高级和复杂的编排,许多事情可能会失去同步,并导致我们部署一个性能不佳的模型。一些最常见的罪魁祸首是:

1.缺乏自动化

大多数组织仍然手动更新他们的模型。无论是培训管道还是它的一部分,例如特征选择,或者服务层对新创建的模型的交付和推广;手动这样做可能会导致错误和不必要的开销。

2.多个利益相关方

由于涉及到多个利益相关者和专家,会有更多的移交,因此会有更多的误解和整合问题的空间。当数据科学家设计流程时,ML 工程师通常进行编码-并且没有完全一致(例如,使用不同的缩放方法),这可能导致无意的行为。

3.真实生活数据的超动态性

实证研究是在离线实验室环境中进行的,使用历史数据集,并通过模拟举行测试。不用说,这些环境与生产环境非常不同,对于生产环境,实际上只有部分数据可用。这可能会导致数据泄漏或错误的假设,从而在模型投入生产并需要为实时数据流提供服务时,导致糟糕的性能、偏差或有问题的代码行为。例如,新部署的版本无法处理分类特征中的新值,同时在推理阶段将其预处理为嵌入向量。

4.ML 模型的无声故障与传统 IT 监控

监控 ML 比监控传统软件更复杂——整个系统在工作的事实并不意味着它实际上做了它应该做的事情。如果没有适当的专用 ml 监控服务,此类故障可能会“悄无声息地”消失,直到业务损失已经造成。你可以阅读更多关于如何监控 ml 模型是否应该自己建造

生产中 ML 的 CIֿֿֿ/CD

CI 实践是关于频繁地测试每个软件单元的代码基础,以及通过使用单元/集成/系统测试一起工作的不同软件工件的完整性。

新的模型版本应被视为软件工件

新模型的创建需要一组单元和集成测试,以确保新的“候选”模型在提交到模型注册中心之前是有效的。但是在 ML 领域,CI 不仅仅是关于测试和验证代码和组件,还包括测试和验证数据、数据模式和模型质量。虽然 CI 的焦点是维护有效的代码库和模块的工件,但是在为每个模块构建新的工件之前,CD 过程处理将工件(在我们的例子中,是新的模型版本)实际部署到生产中的阶段。

CI 阶段的最佳实践

以下是 CI 阶段的一些主要最佳实践,它们会影响模型/新版本实现的安全展示:

数据有效性

使用历史数据重新训练/生成模型。为了使模型与生产相关,训练数据集应该充分表示当前出现在生产中的数据分布。这将避免选择偏差或干脆不相关。为此,在开始训练管道之前,应该测试训练集的分布,以确保它适合任务。在这一阶段,可以利用监控解决方案提供关于最后生产案例分布的详细报告,通过使用数据测试工具,如 deequTDDA ,这种类型的数据验证约束可以自动添加到 CI 流程中。

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

使用监控服务从生产中提取数据分布,并将它们与您的训练数据集进行比较(图片来自 superwise.ai 系统)

模型质量验证

在执行培训管道时,在将新模型作为“候选”模型提交到注册表之前,请确保新的培训流程经过了健康适合度验证。

即使培训管道是完全自动化的,它也应该包括一个保留/交叉验证模型评估步骤。

给定所选的验证方法,应该应用测试来验证拟合的模型收敛不指示过度拟合,即:在训练数据集上看到减少的损失,而在验证集上看到增加的损失。性能还应该高于某个最低速率——基于硬编码的阈值、作为基线的原始模型,或者通过利用监控服务并在使用的验证集期间提取生产模型的速率来动态计算。

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

交叉验证评估设置示例。作者图片

测试案例—生产数据假设的稳健性

一旦模型质量验证阶段完成,就应该执行集成测试,以查看服务层如何与新版本集成,以及它是否成功地为特定边缘情况的预测服务。例如:处理可能为空的要素中的空值,处理分类要素中的新分类级别,处理不同长度的文本输入,甚至处理不同的图像大小/分辨率……这里的示例也可以手动合成或取自监控解决方案,其功能包括识别和保存存在数据完整性问题的有效输入。

模型压力测试

更改模型或更改其预处理步骤或包也会影响模型的操作性能。在许多用例中,比如实时竞价,增加模型服务的延迟可能会极大地影响业务。因此,作为模型 CI 流程的最后一步,应该执行压力测试来测量操作方面,如平均响应时间。这种度量可以相对于业务约束或者相对于由监控解决方案计算的当前生产操作模型等待时间来评估。

CD 阶段的最佳实践

CD 阶段是实际部署代码以替换先前版本的过程。在传统的软件工程中,这通常是通过“蓝绿色或“金丝雀”部署来实现的——一种逐步推出版本的方法。首先,变更被部署到案例的一个小的子集,通常逐渐扩展到服务器的一个子集。一旦确定功能运行良好,就可以将更改推广到其余的服务器。

**将 CD 过程应用于 ML 模型,基本上应该是一个渐进的过程,在让它发挥作用并做出真正的自动化决策之前,使用生产系统验证实时数据的模型正确性和质量。**这种评估通常被称为“在线评估”,与 CI 阶段完成的测试相反,CI 阶段完成的测试基于历史数据集,可被视为“离线评估”。

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

完整的 CI/CD 模型生命周期。作者图片

这种模型在线评估可能涉及一些基本策略:

影子评估

影子评估(或通常称为“黑暗发射”)是一种非常直观和安全的策略。在影子模式中,新模型作为“候选模型”添加到注册表中。任何新的预测请求都由模型版本(当前在生产中使用的版本)和影子模式中的新候选版本来推断。

在影子模式下,使用新的生产数据流测试新版本,但只有最新“生产模型”版本的预测被使用并返回给用户/企业。

有了影子模式,在新版本确实被批准并按预期工作之前,没有暴露的风险。影子模式的好处有两个:

  1. 新版本的性能在它“运行”之前被评估,
  2. 您确保新版本在生产管道中运行良好

使用这种方法,监控服务应该在两组预测中持续存在,并持续监控两个模型,直到新模型足够稳定,可以提升为新的“生产版本”。一旦新版本准备好了,监控服务就向服务层发信号通知它需要升级模型版本。从技术上讲,这种“提升”可以通过为新版本更新“最新”标签并使服务层始终与“最新”模型版本标签一起工作来完成(类似于 docker 图像中的“最新”概念)。或者通过使用显式模型版本标签,但是这将要求服务层总是首先检查什么是最新的生产就绪版本标签,然后才重新加载相关版本并使用它来执行预测。

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

监控服务负责决定何时提升影子模型。作者图片

我们应该使用统计假设将新的“影子”版本与当前最新的生产模型进行比较

这种测试应该验证新版本的性能具有所需的效果大小,也称为:在特定的统计功效下,两个版本性能指标之间的差异,也称为:当存在一个效果时,正确识别该效果的概率。例如:如果最新版本在过去一周的精度水平为 91%,则新的候选版本必须具有 0 或更大的效果大小,因此新的精度率将至少为 91%。

整体绩效水平不是唯一的衡量标准

不过,在提升模型之前,监控其他因素可能也很重要:性能稳定性,即确定我们上一个示例中每日精度性能的变化,或者检查特定子群体的性能约束。例如,对于我们的“VIP 客户”,该模型必须至少具有 95%的精确度。当标签收集需要时间或可能完全丢失时,可以使用其他 KPI 来测试新模型,作为其质量的代理,即:在贷款审批用例中,此类反馈循环可能需要 3-6 个月以上的时间。在这些情况下,可以使用两个版本的预测之间的相关水平,因为新版本相对于其前一版本应该具有相对较高的相关水平。另一种选择是测试生产数据相对于其训练数据集的分布偏移水平,以确保新版本是在相对于当前生产分布的相关数据集上训练的。

除了所有的好处之外,影子评估也有局限性,只是部分实用。这就是我们将在下面分析的内容,以及审查替代解决方案。

A/B 评估

在许多 ML 场景中,模型的预测实际上会影响它运行的周围环境。让我们以一个推荐模型为例,该模型负责排列要提供的前 5 个电影建议。在大多数情况下,标签取决于用户是否确实观看了建议的电影之一。在这里,模型的预测影响了用户的行为,从而影响了收集的数据。如果候选阴影模型输出 5 部非常不同的电影,用户没有选择它们的事实并不一定意味着它们是糟糕的推荐——只有模型处于阴影模式并且没有采取任何现实生活中的行动的事实使得用户不可能实际看到这些电影。在这种情况下,性能成功是无法比较的。这时需要进行在线 A/B 测试评估。

在 A /B 设置中,当前最新版本和新的候选版本(可称为模型 A/“控制”组和模型 B /“处理”组)实际上都在生产中活动。根据特定的逻辑,每个新请求被路由到其中一个模型,并且只有所选的模型用于预测。

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

A/B 路由示例。作者图片

这些评估可以进行一段时间,预测,或者直到统计假设——新版本是否至少和以前的版本一样好——被验证。与影子策略类似,要测试的 KPI 可以是性能、稳定性或一些其他代理,……但需要注意的是,监控服务应该负责管理和评估 A/B 测试。

这种方法的成功很大程度上取决于正确仔细地划分 A/B 测试组的能力。

一个好的做法是对一个特定的部分做一个随机的抽样来得到“治疗”,意思是从新的版本中预测。例如,对于电影推荐用例,任何新的请求应该有 X(例如 10%)的机会被新的模型版本服务,直到测试完成。通常,暴露系数相对较低,因为这种策略实际上甚至在定性测试完成之前就“暴露”了新模型。

这种 A/B 配置也可以推广到 A/B/C/…设置中,即同时比较多个模型。请记住,由于测试次数较多,同时测试几个模型会增加假阳性结果的几率。此外,考虑到我们在每组中测试的样本数量较少,因此“小效应大小”的统计功效会降低,因此应谨慎考虑。

多臂土匪

多臂土匪(MAB)实际上是一种更“动态”的 A/B 测试实验,但也是一种更复杂的测量和操作。这是一种经典的强化学习,人们试图“探索”(尝试新的模型版本),同时“利用”和优化已定义的绩效 KPI。这种配置是基于监控服务内部的探索/开发权衡的实现。根据收集的性能 KPI(或前面描述的其他代理),流量在两个(或更多)版本之间动态分配。

在这种情况下,新版本会遇到一定数量的案例。它越是等于或超过之前的版本,基于它的性能 KPI,越来越多的流量会被导向它。

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

基于监控结果的动态多臂 bandit 路由。作者图片

这样的配置看起来很理想,因为我们试图在优化主要指标的同时动态地优化“曝光度”。但是,它需要高级监控和自动化功能来实施多臂 bandit 解决方案,并根据其结果动态调整流量。特别是考虑到与系统要利用的一个明确的 KPI(性能、稳定性,…

监控安全部署的好处

通过查看传统软件中使用的示例,并将其实施到我们自己的 ML 范例,CI/CD 最佳实践中,我们了解到要有一个更好的“推出日”需要采取许多步骤。所有这些策略都依赖于强大的监控组件来使流程更加数据驱动。

安全地推出模型是为了监控 ML 基础设施的所有部分的协调

下面我们可以看到新版本的安全交付(V2,标记为蓝点),在生产中产生改进的 ROC AUC 性能。

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

superwise.ai 监控的模型截图

展望未来,您的模型在生产中的健康还需要一个全面的、数据驱动的再培训策略。虽然 CI/CD 范例解决了新模型推出的“什么”和“如何”问题,但 CT(持续培训)范例涵盖了“何时”问题。这将是我的同事或 Itzahary 下一篇帖子中的重点,敬请关注!

从 CI/CD 到 CT(持续培训)。CT 是一个新的属性,是 ML 系统独有的,它涉及自动重新训练和服务模型

我希望这篇文章对你有所帮助。如果你对本文的内容有任何问题、反馈或者想集思广益,请在这里发表评论或者通过 LinkedIn 联系我

我要感谢我的同事们珀尔·利伯曼或伊扎哈里奥里·科恩他们有见地的评论和想法

柳文欢·拉松 super wise . AI公司的联合创始人兼首席技术官,该公司让数据科学&运营团队能够利用先进的人工智能监控平台了解和控制他们的人工智能活动。柳文欢是一位经验丰富的 ML 从业者,在过去的 15 年里,他为初创公司和企业的大型 ML 活动提供领导和咨询。

我总是在找借口阅读、写作、谈论和分享关于 MLOps 主题的想法。

处理数据的安全注意事项

原文:https://towardsdatascience.com/safety-considerations-for-working-with-data-5442b23ce0af?source=collection_archive---------49-----------------------

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

(图片来源:pexels.com)

介绍

在处理数据项目时,科学家/分析师通常会关注许多不同的元素,因此很容易忘记安全性。然而,当安全方面被遗忘,它可能会适得其反,大时间。安全漏洞会导致许多不良后果,如数据丢失、云资源被劫持、法律问题、黑客攻击、客户离开等等。

这听起来有点戏剧性,但幸运的是,有一些非常简单的步骤可以实施,已经可以防止一系列的问题。由于我收到了很多关于这方面的问题,我决定把一些关键点放在一个帖子里。

一些考虑

始终使用双因素身份验证。

双因素身份认证(或 2FA)是一个简单的原则,其中您的凭证不限于“您知道的东西”(您的密码),而是扩展到“您是什么东西”(生物数据)和/或“您拥有的东西(电话/令牌/……)。

2FA 通常很容易实现,鉴于目前的技术(FaceID、智能手表等),它相当容易实现。实施 2FA 将极大地限制非法访问的风险,因为如果没有第二个因素,即使密码被盗,它也是无用的。如果您还没有为您最重要的客户(电子邮件、云存储等)制定 2FA。)我强烈建议你今天就去买一个。

不要在本地机器上存储数据

我明白了,在本地机器上存储数据既简单又快捷。但是,数据的所有者(客户、业务伙伴……)会不高兴您将数据存储在本地。IT 安全领域有这样一句话:“物理访问=游戏结束。”虽然现实中有更多的细微差别,但被盗或丢失的笔记本电脑/硬盘可能会带来严重的后果。因此,实施了适当安全措施的云存储是首选。

除了像 AWS 和 Azure 这样的主要平台之外,还有很多将数据存储在云上的可能性。

如果除了在本地存储数据之外别无选择,除了锁定计算机之外,您应该始终加密您的驱动器。

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

物理访问应该受到高度限制。(图片来源:pexels.com)

使用密码管理器

我经常惊讶于许多人仍然对密码管理器持怀疑态度,尽管它们通常是更安全的选择。密码管理器允许你存储数以千计的复杂密码,自动填充它们,并随时生成新的密码。

除了数据专业,使用密码管理器也大大提高了我的个人便利性。例如,现在你需要一个几乎任何网店的用户账户,我的个人经理只是简单地为这个网站建议一个困难的和唯一的密码,并会在我每次访问时填写。万一网站被黑了,我的信息被泄露了,这也没什么大不了的,因为密码只分配给那个网站访问。不要忘记添加 2FA 来访问您的密码管理器。

对您的数据库或笔记本电脑应用 IP 限制

这一简单的技巧阻止了数据被盗,黑客们恨他!

玩笑归玩笑,当在服务器上托管像 MySQL 或 Jupyter 笔记本这样的数据库时,你可以很容易地添加 IP 限制。这意味着数据库只能从某些地方访问,如你的家,办公室,客户等。这个非常简单但有效的措施对您的数据安全有很大的积极影响。尽管这不是万无一失的,但它是防止不必要的访问的非常简单和非常有效的方法。

不过要小心,大多数非专业的互联网计划都有一个动态的 IP。对动态 IP 应用 IP 限制可能会导致您自己被锁在外面。

注意动向

“以量为知”。跟踪通常是数据安全中被忽视的一个方面,但它的重要性不容忽视。我所说的跟踪是指:

  • 谁知道密码?
  • 最后一次更改密码是什么时候?
  • 谁有 IP 访问权限?
  • 记录登录(以及尝试)

跟踪不仅可以防止数据丢失(例如,限制不再需要数据的人访问数据),还可以帮助诊断数据丢失时的问题所在。

不要硬编码密码

我重复一遍,不要不要硬编码密码。一次也没有,不是短暂的,不是内部的,从来没有。尽管当您实现前面提到的步骤(即 2FA、IP 限制)时,硬编码的风险是有限的,但您很可能没有这样做,这很可能会适得其反。通常是这样的:

  1. 编码器硬编码数据库密码,因为它更容易。目前,没有风险,因为它只供内部使用,以后会被删除。
  2. 编码器忘记删除它。
  3. 代码最终会出现在一个私有的 Github 或一些 webscript 上
  4. 一只爬虫捡起它
  5. 混乱随之而来…

我很幸运自己没有经历过这些,但我听过很多故事。然而,硬编码密码有一个好处:你只需要做一次。因为一旦爬虫抓取了它并对您的数据库/云实例/web 服务器造成严重破坏,您就不太可能重复您的错误。

了解风险

最后一部分,我会稍微宽松一点。谈到安全,最重要的是了解风险。当然,理想情况下,您会实现所有这些措施以及更多措施,但这可能不值得付出努力。你需要区分一个简单的个人项目和一个有机密数据的大客户的脚本。风险应该与措施相匹配,高估风险比低估风险更好。

最后,你还需要理解数据和洞察力之间的区别。大部分时间(但不总是!)原始数据需要最高程度的保护,而见解可以较少限制地共享。我之所以强调这种差异,是因为非技术客户通常很难遵守您的安全标准。然而,如果这些见解不像数据本身那样具有同样的风险,你可以自己评估是否可以简单地通过电子邮件或其他渠道分享它们。一旦行被聚合,数据通常会失去其机密性。

结论

*“数据是新的石油,”*作为一名数据专业人员,您将经常负责存储和保管大量这种宝贵的石油。虽然承担这一责任听起来令人生畏,但有很多简单的方法可以降低这种风险。实施本帖中描述的部分或全部步骤,将使那些不应该访问你的数据的人很难访问你的数据。但是,请记住:

  • 没有任何措施是 100%有保证的。
  • 你的安全系统有多强就有多弱。

本文列出的考虑事项并不详尽。您可以(或许应该)实施许多其他措施,如加密、注入漏洞、哈希等等。

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

(图片来源:【https://xkcd.com/327/】T2)

当您在处理真正非常重要或保密的数据时,我建议您向认证 it 审计员咨询,他们可以指导您完成应该实施的步骤。

关于我:我叫 Bruno,是一名数据科学家,目前专攻电力 BI。可以通过我的网站与我联系:https://www . zhongtron . me

销售和数据科学:使用 Python 分析竞争对手的分步指南

原文:https://towardsdatascience.com/sales-data-science-a-step-by-step-guide-to-competitor-analysis-using-python-7dc03461d284?source=collection_archive---------18-----------------------

是什么让卖家在亚马逊或易贝这样的在线市场上获得成功?数据科学有助于回答这个问题。

像亚马逊或易贝这样的在线市场到处都是卖家,每一步都在互相竞争。当其他人提供的产品与你的非常相似时,增加销售并不容易。

你有没有想过,如果卖家提供的东西都差不多,是什么让买家选择一个卖家而不是另一个?

你可能会认为这都是价格的问题。

我也是,但后来我禁不住诱惑,想看看这里是否有其他因素在起作用。

在本文中,我站在一个在线卖家的角度,来看看使用 Python 编程工具的数据驱动方法如何帮助回答这个问题。

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

来源:我的团队在Sunscrapers提供。

为此,我采取了两个步骤。

**第一步:找到一个有丰富销售历史内容的在线市场。**这篇文章是为教育目的而写的,所以我想对市场名称保密。

第二步:想出一个可以比较不同报价的方法。这里的诀窍是找到一种产品,它有许多相似的变体,并由大量的卖家出售。我为这项研究挑选的在线市场上最常出售的产品之一是我们都在使用的:

一款智能手机屏幕保护器

在这篇文章中,我要问和回答 4 个问题:

Q1。我们产品类型的平均价格是多少?

Q2。定价如何影响销售?

Q3。最受欢迎的屏幕保护器品牌有哪些?

Q4。哪些品牌最赚钱?

贸易工具

python——我们为数据科学选择的编程语言。

Python 工具:

  • scrapy——这个 web 抓取/爬行框架提供了一些便利的特性,比如字段值的编组和预处理。你可以通过在线清理平台运行它,这有助于减轻你的抓取过程。
  • Pandas —我将使用它将数据加载到表中(然后清理、处理和分析它)。
  • Seaborn 和 Matplotlib——这是 Python 中一些方便的数据可视化库。

顺便说一句。我还写了两篇文章来帮助你研究熊猫,看看吧:

如何在熊猫小组中运用分-用-合策略

如何用熊猫和 Dask 在 Python 中处理大型数据集

数据挖掘和准备

1.获取数据

第一步是找到数据源。我需要选择一个能够提供某种销售业绩指标的在线市场——这样我就可以根据其他产品特性对其进行评估。我选的平台提供了最近 100 笔交易的信息。

注意:网络爬虫代码内容相当广泛,并且会因不同的市场网站而异,所以我决定不在本文中包含抓取代码的例子。用于抓取和网页抓取的 Python 框架 Scrapy 提供了大量文档和易于理解的教程,所以如果需要的话可以参考它们。

以下是我如何获得本文数据的简短描述:

首先,我在网上市场手动搜索智能手机屏幕保护器,并从那里开始爬行过程。通常,搜索模式从某种商品列表开始,每个列表指向一个包含更多信息的商品专用页面,甚至可能是过去购买的列表。

请注意,您通常可以在搜索结果列表中获得关于产品展示的有价值信息(如卖家状态、积分、过去购买次数)。毕竟,这是客户第一次接触该优惠,这可能会影响他们的决策过程。

爬行之后,我得到了两张熊猫桌子。主表(df)包含所有的产品信息,每一行对应一个商品。另一个表(sale_history)存储了关于过去购买的信息,每个产品包含许多行单独的销售事件数据。

稍后我将向您展示表格示例。

2.处理数据

在数据提取步骤之后,是时候做一些清理和数据准备了。除了所有通常的步骤(删除空值、将列转换成正确的数据类型等。),这里有几个有趣的步骤我想提一下——同样,不用深入细节。

作为第一步,我倾向于用熊猫unique()的方法浏览各个专栏。这就是我如何能看到价值观是否一致和明智——并捕捉任何潜在的问题。然后,我通过按列对行进行分组来检查数据重复,该列是特定项目的惟一标识符——在本例中,我使用了product_id

我注意到的第一件事是,一些产品页面链接到搜索结果页面中的多个列表(巧合?我不这么认为!).我去掉了重复的,但是决定保留这些信息用于分析。因此,我创建了一个新列,首先列出每件商品的列表数量,然后删除了副本,只留下一个:

df[‘same_offer_count’] = df.groupby(‘product_id’)[‘product_id’]\
    .transform(‘count’)
df = df.drop_duplicates(subset=’product_id’, keep=’first’)

另一个有趣的问题是处理市场上使用的多种货币。我的原始数据表包含裸价格字符串值以及带引号的货币符号(例如,“US $1.09”或“C $2.42”),因此我需要提取数值,并通过将它们转换为 USD 来统一所有价格货币。以下是转换前的几个示例行:

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

下面是我用来转换它的代码:

import refrom currency_converter import CurrencyConvertercc = CurrencyConverter()
currency_shortcuts = {‘C’:’CAD’, ‘US’:’USD’, ‘AU’:’AUD’} # first I checked only these occur…
regx_str=r’(\w+\s*)\$[ ]?(\d+[.|,]?\d+)’ # note the two ‘re’ groups!df[[‘currency’, ‘quoted_price’]] = df[‘current_price’]\
    .str.extract(pat=regx_str)df[‘currency’] = df[‘currency’].str.replace(‘ ‘, ‘’)
df[‘currency’] = df[‘currency’].map(currency_shortcuts)
df[‘price_USD’] = df[‘quoted_price’].copy()for currency in [ c for c in df[‘currency’].unique() 
                  if c not in [‘USD’]]:
    fltr = df[‘currency’].isin([currency]) 
    df.loc[fltr, ‘price_USD’] = df.loc[fltr, ‘quoted_price’]\
        .apply(lambda x: cc.convert(x, currency, ‘USD’))

这导致了:

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

接下来,我处理了销售历史表(sale_history)。我执行了一些基本的类型修复,提取并转换了价格和货币,并填充了空值(代码未显示)。我最终得到了这个表(同样,它只是行的快照):

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

为了让它对我的分析和绘图有用,我按日期(当然还有product_id)汇总了条目,并计算了售出商品的数量和每日销售率。将所有这些打包到一个函数中,可以将它按行应用于数据框:

def calculate_sale_history_stats(df):
    *“””Calculates statistics on sale history, 
    returns new dataframe”””* delta = df[‘purchase_date’].max() — df[‘purchase_date’].min()
    days = int(delta.days)
    values = list(df[‘quantity_sold’])
    earnings = list(df[‘total_price’])
    sold_count = sum(values)

    if len(values) < days:
        values.extend([0]*(len(values) — days))
        earnings.extend([0]*(len(earnings) — days))

    res = pd.Series(
        [ sold_count, np.mean(values), 
          np.std(values), np.mean(earnings), 
          np.std(earnings)
        ], 
        index=[‘Sold_count’, ‘Mean_daily_sold_count’,
               ‘Sold_count_St.Dev’, ‘Daily_earnings’,
               ‘Daily_earnings_St.Dev’]
    )

    return round(res, 2)

并将其应用于sale_history数据帧:

sale_history_stats = sale_history.groupby(‘brand’)\
    .apply(calculate_sale_history_stats)

导致了:

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

最后,我将汇总的销售统计数据(sale_history_stats)合并到主 df 表中:

df = pd.merge(
    how=’left’,
    on=’product_id’,
    left=aggreg_sale_history,
    right=df[[‘product_id’,’shipping_cost’, ‘shipping_from’,
              ‘top_rating_badge’, ‘seller_feedback_score’, 
              ‘seller_feedback_perc’,]]
)

下面是生成的df表(同样,只显示了选择的列):

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

现在我们可以走了。因此,让我们开始我们的竞争对手分析。

Q1:我们这种产品的平均价格是多少?

让我们看看我们能从屏幕保护装置中获得多少利润。这类产品卖家一般收费多少?

我可以分析市场上的价格,看看客户通常会为这样的智能手机屏幕保护器支付多少钱:

import matplotlib.pyplot as plt
import seaborn as snsprices = df[‘price_USD’]sns.distplot(df[‘price_USD’], ax=ax, bins=200)paid_prices = sale_history[‘sell_price’]sns.distplot(paid_prices, ax=ax, bins=100)

下面是两个叠加了附加信息的直方图(代码未显示):

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

如你所见,大多数屏幕保护器的价格约为 1.15 美元(平均约为 3.9 美元)。然而,顾客似乎更喜欢在购买时额外投入一些钱(平均约 5 美元,中位数约 3.8 美元)。“越便宜越好”的规则在这里不适用。

基于这种认识,我们可以假设选择将我们的产品定价在 4 美元左右就可以了。

Q2:定价如何影响销售?

定价可能是客户决策过程中最重要的因素。销售者通常认为高价格会阻止消费者购买他们的产品。在盈利性和可承受性之间取得恰当的平衡可能会成为一项挑战。

让我们看看售出商品的数量和每日收入如何与单价相匹配(作为每日平均值):

*# The daily earnings vs price:*
sns.lmplot(
    x=’sell_price’, 
    y=’Daily_earnings’, 
    data=df[[‘sell_price’, ‘Daily_earnings’]]
)*# Plot the sales frequency vs price:*
sns.lmplot(
    x=’sell_price’, 
    y=’Mean_daily_sold_count’, 
    data=df[[‘sell_price’, ‘Mean_daily_sold_count’]]
)

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

不出所料,更高的价格意味着平均销量的下降。但是当我们看每天的收入时,似乎利润倾向于随着更高的价格而增加。

在这一点上,发现定价是否反映了产品的质量和/或声誉是很有意思的。不幸的是,这超出了本研究的范围。

Q3。最受欢迎的屏幕保护器品牌有哪些?

让我们仔细看看品牌名称。有一系列的价值观指向“没有品牌”

所以,让我们先把这些乱七八糟的东西收拾干净,给它们都贴上“无品牌”的标签:

ubranded_values = [ 
    ‘Does not apply’, 
    ‘Does Not Apply’, 
    ‘Unbranded/Generic’, 
    ‘unbranded’
]df[‘brand’] = df[‘brand’].apply(
    lambda s: ‘Unbranded’ if s in ubranded_values else s
)

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

现在,我可以将数据输入到工作中,并得到一个显示品牌名称的饼图。这表明我们在线市场上提供的大多数产品(约 60%)根本没有品牌(或没有标明品牌)。

消费者可能希望坚持一个可识别的名称,所以让我们暂时忽略未命名的产品,而是专注于市场上每天卖出最多产品的前 20 个品牌。

为此,我将使用包含所有事务数据的sale_history表。

让我们创建一个包含市场上提供的品牌信息的表格:

sold_brands = sale_history\
    .groupby(‘brand’)\
    .apply(calculate_sale_history_stats)

接下来,让我们来看看迄今为止销量最高的 10 个品牌——创建一个表格并绘制成这样:

top_sold_brands = sold_brands.sort_values(
    by=[‘Sold_count’, ‘Daily_earnings’, ‘Mean_daily_sold_count’], 
    ascending=False
).reset_index()sns.barplot(
    data=top_sold_brands.iloc[1:21], 
    x=’brand’, 
    y=’Sold_count’)

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

一眼就足以看出,所有未命名的品牌加起来已经累积了最高的销售数量。然而,Spigen 似乎是这一类别的亚军,并在命名品牌产品中占据市场主导地位。

Q4。哪些品牌最赚钱?

哪些屏幕保护器品牌在最短的时间内给卖家带来了最高的收益?让我们回到无品牌产品的话题上来,因为当谈到收益时,情况可能会略有不同:

most_profitable_brands = sold_brands.sort_values(
    by=[‘Daily_earnings’, ‘Mean_daily_sold_count’, ‘Sold_count’],
    ascending=False
).reset_index()most_profitable_brands = most_profitable_brands[[
    ‘brand’, ‘Daily_earnings’, 
    ‘Daily_earnings_St.Dev’,’Sold_count’,
    ‘Mean_daily_sold_count’, ‘Mean_Sold_count_St.Dev’]]

我得到了这张表:

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

让我们把它形象地画在柱状图上,就像这样:

plt.bar(x, y, width=0.85, yerr=y_err, 
        alpha=0.7, color=’darkgrey’,  
        ecolor=’black’
)

这应该会创建以下图形:

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

很明显,没有品牌的产品利润并不高。请注意,当我们比较收入而不是销售商品总数时,品牌的顺序发生了很大变化。中档价位的品牌现在排在榜首(比如售价约 9.5 美元的 PureGear)。尽管他们的日销售率相对较低(每天 1-2 英镑)。

回答这四个问题向我们展示了“质量重于数量”可能是制定在线市场销售策略的最聪明的方法。

在本文中,我将重点带您完成数据挖掘和准备过程,最终回答我在本次研究中选择的关于在线市场销售趋势的四个关键问题。

以下是我可以从数据中回答的一些其他问题:

  • 运输成本会影响客户决策吗?
  • 有多少卖家对自己的产品打折?
  • 打折会带来更高的销售额吗?
  • 顾客从哪里购买产品会有什么不同吗?
  • 卖家反馈分数如何影响销量?
  • 拥有最高评级的徽章会促进产品销售吗?

幸运的是,我已经做到了。你可以在我的研究中找到所有答案,如何用数据科学增加在线市场的销售额。在这里免费下载

原载于 2020 年 3 月 16 日 https://sunscrapers.com。****

销售预测:从传统时间序列到现代深度学习

原文:https://towardsdatascience.com/sales-forecasting-from-time-series-to-deep-learning-5d115514bfac?source=collection_archive---------1-----------------------

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

图片由我可爱的女朋友 Beatriz Belbut 提供

从传统时间序列模型到现代深度学习,直观地进行销售预测。

介绍

在任何一家公司,都有一种预测未来收入和未来销售的内在愿望。基本配方是:

收集与以前销售相关的历史数据,并使用它来预测预期销售。

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

照片由马库斯·斯皮斯克Unsplash 拍摄

在过去的十年里,深度学习作为所有可想象的机器学习基准背后的驱动力的兴起彻底改变了这个领域:无论是在计算机视觉、语言还是其他许多领域。最近,有人可能会说,深度学习通过允许模型在单个模型中编码多个时间序列以及解释分类变量,重构了销售预测的潜在未来。我今天的目标是:

从时间序列的角度带您了解销售预测的主要概念和模型背后的基本直觉,并讨论最近的深度学习模型可以带来什么样的功能。

阅读建议

如果你觉得你需要温习销售预测和时间序列的基础知识,我推荐这三本书:

销售预测问题

销售预测就是利用历史数据为决策提供信息。

一个简单的预测周期如下所示:

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

作者图片

就其核心而言,这是一个[时间序列](https://en.wikipedia.org/wiki/Time_series#:~:text=A time series is a,sequence of discrete-time data.)问题:给定一些时间上的数据,我们希望预测这些数据在未来的动态。为了做到这一点,我们需要一些可训练的动态模型。

根据亚马逊的时间序列预测原则,预测是一个难题,原因有二:

  • 合并大量历史数据,这可能会导致丢失有关目标数据动态过去的重要信息。
  • 整合相关但独立的数据(假期/事件、位置、营销推广)

除此之外,销售预测的一个重要方面是准确性非常关键:

  • 如果预测过高,可能会导致过度投资,从而亏损。
  • 如果预测过低,可能会导致投资不足,从而失去机会。

纳入天气、时间和空间位置等外部因素可能有利于预测。在柳德米拉·塔拉年科的这篇中型文章中,她提到了一个很好的例子,讨论了优步、Lyft 或滴滴出行等按需乘车服务如何必须考虑天气条件(如湿度和温度)、一天中的时间或一周中的某一天等因素来进行需求预测。因此,好的预测模型应该具有能够解释这些因素的机制。

总而言之,到目前为止我们知道些什么?

  • 我们知道预测是一个难题,准确性非常重要。
  • 我们知道有一些难以解释的外部因素在起作用。

我们还不知道的是:

  • 什么是传统的预测方法,为什么他们可能会屈服于这些挑战。
  • 深度学习方法如何有所帮助,以及取代传统模型的前景如何。

预测模型的类型

根据《哈佛商业评论》的这篇文章,有三种预测技巧:

  • 定性技术:通常涉及专家意见或关于特殊事件的信息。
  • 时间序列分析和预测:涉及历史数据,在数据的动态中寻找结构,如周期模式、趋势和增长率。
  • 因果模型:这些模型涉及相关的因果关系,可能包括库存或市场调查信息等渠道因素。它们可以包含时间序列分析的结果。

我们将重点介绍时间序列分析方法,这是传统预测方法背后的驱动力,它可以给出预测前景的综合布局。

时间序列方法

时间序列是在连续的、等距的时间点获取的数据点序列,可用于预测未来。时间序列分析模型涉及使用历史数据来预测未来。它在数据集中查找趋势、周期性波动、季节性和行为模式等特征。

在处理从时间序列角度解决的销售预测问题时,需要考虑的三个基本要点是:

  • 重复模式
  • 静态模式
  • 趋势

现在,我们将研究这些因素中的每一个,并编写代码让我们直观地理解它们。在那之后,我们将看到现代深度学习模型可以带来什么。

重复模式

当查看时间序列数据时,我们寻找的一个元素是在时间上重复的模式。与这个想法相关的一个关键概念是 [自相关](https://en.wikipedia.org/wiki/Autocorrelation#:~:text=Autocorrelation, also known as serial,the time lag between them.) 。

直观地说,自相关对应于观测值之间的相似性,作为它们之间时滞的函数。

那是什么意思?它指的是通过查看不同时间点的观测值之间的相关性(即“自动”)来发现时间序列中观测值动态的结构。这是寻找重复模式的主要工具之一。

为了澄清这一点,让我们来看看 kaggle 公开发布的天气数据集,并绘制其原始温度数据和自相关图。

这些步骤将是:

  • 加载我们的数据集
  • 清除日期列
  • 绘制原始天气数据
  • 使用statsmodels绘制自相关图
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
from statsmodels.graphics.tsaplots import plot_acf

green = sns.color_palette("deep", 8)[2]
blue = sns.color_palette("deep", 8)[0]

# Loading the dataset
df_weather = pd.read_csv("data/weatherHistory.csv")

#Cleaning the dates column
df_weather['Formatted Date'] = pd.to_datetime(df_weather['Formatted Date'])

#Plotting the raw weather data
fig = plt.figure(figsize=(17,8))
ax1 = fig.add_subplot(121)

plt.scatter(df_weather["Formatted Date"],df_weather["Temperature (C)"], color=green,s=20)
plt.title("Weather Data Time Series",fontsize=15)
plt.xlabel("Date",fontsize=15)
plt.ylabel("Temperature (ºC)",fontsize=15)

# Plotting the autocorrelation plot
ax2 = fig.add_subplot(122)
plot_acf(df_weather["Temperature (C)"], ax=ax2,color=blue)
plt.title("Autocorrelation Plot for Weather Data", fontsize=15)
plt.ylabel("Correlation",fontsize=15)
plt.xlabel("Lag",fontsize=15)
plt.show()

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

我们可以清楚地看到左边有一个重复的图案,似乎是正弦曲线形状。在右边,我们可以看到自相关图:线条的大小表示给定滞后值的相关程度。当我们考虑天气的季节性和重复性时,该图似乎表明了一种相关的循环模式。

然而,我们能从销售数据集的自相关图中得到什么呢?它会呈现出和这个简单的天气数据集一样清晰的重复模式吗?

让我们用这个零售销售数据集绘制与上面相同的信息。

这里的步骤将是:

  • 加载数据集
  • 获得 45 家商店的总销售额
  • 绘制 2010 年至 2013 年间的总销售量
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.dates as mdates
import datetimegreen = sns.color_palette("deep",8)[2]
blue = sns.color_palette("deep",8)[0]

retail_sales = "./sales_dataset.csv' df_sales  = pd.read_csv(retail_sales)fig = plt.figure(figsize=(17,8))
ax1 = fig.add_subplot(121)
df_sales_sum = df_sales.groupby(by=['Date'], as_index=False)['Weekly_Sales'].sum()
df_sales_sum["Date"] = pd.to_datetime(df_sales_sum["Date"])
df_sales_sum.plot(x="Date",y="Weekly_Sales",color="g",ax=ax1, fontsize=15)
plt.xlabel("Date",fontsize=15)
plt.title("Total Sales Volume", fontsize=15)
plt.ylabel("Sales", fontsize=15)
date_form = mdates.DateFormatter("%Y-%m-%d")
year_locator = mdates.YearLocator()
ax1.xaxis.set_major_locator(year_locator)ax2 = fig.add_subplot(122)
plot_acf(df_sales_sum.Weekly_Sales,ax=ax2)
plt.title("Autocorrelation", fontsize=15)
plt.xlabel("Lag",fontsize=15)
plt.ylabel("Correlation", fontsize=15)
plt.show()

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

在这里,我们看到在lag = 5的观察中有一个相对高相关性的点。我们在前面的图表中看到的相同结构的缺乏是销售的偶然性的结果:考虑到预测销售的因素的数量,我们不应该期望数据像在天气数据集中那样具有完全清晰的相关性。然而,有趣的是观察到可能与所涉及产品类型相关的因素相关的相关性峰值。例如,对于一个销售圣诞礼物的商店,我们应该期望看到从圣诞节开始相隔一年的观察结果之间的高相关性,因为人们更有可能在这个特定时期购买更多的礼物。

静态模式

顾名思义,静态模式的概念与不变的事物相关。

在时间序列中,这个概念最著名的代理是,平稳性是指一个时间序列保持静态的统计性质:一个平稳时间序列中的观测值不依赖于时间。

趋势和季节性会影响时间序列在不同时间的值。传统上,我们会随着时间的推移寻找一致性,例如通过使用观察值的平均值或方差。当时间序列是平稳的时,建模会更容易,统计建模方法通常假设或要求时间序列是平稳的。

如果你想更深入地了解平稳性,我推荐 Shay Palachy 的这篇作品

检查数据集是否稳定的标准过程包括使用一种称为 Dickey-Fuller 测试的测试,该测试检查数据是否具有静态统计属性的置信度。要了解更多细节,请查看这篇文章

from statsmodels.tsa.stattools import adfuller

adf_test_sales = adfuller(list(df_sales_sum["Weekly_Sales"]))

adf_test_weather = adfuller(list(df_weather["Temperature (C)"]))

print("Weather Results:")
print("ADF = " + str(adf_test_weather[0]))
print("p-value = " +str(adf_test_weather[1]))

print("Retail sales results:")

print("ADF = " + str(adf_test_sales[0]))

print("p-value = " +str(adf_test_sales[1]))Weather Results:
ADF = -10.140083406906376
p-value = 8.46571984130497e-18
Retail sales results:
ADF = -2.6558148827720887
p-value = 0.08200123056783876

在这里,我们可以看到天气数据集的测试结果指向平稳,这是一个我们应该持保留态度的结果,因为它在很大程度上取决于我们如何对数据进行采样,通常气候数据是循环平稳的。然而,在我们的零售销售数据集上,p 值表明数据将是稳定的,这种置信度并不显著。

趋势

趋势代表在我们的数据中识别的趋势。在股票市场的情况下,这可能是给定股票的趋势,看起来是上涨或下跌。对于销售预测来说,这是关键: 确定一个趋势可以让我们知道我们的时间序列前进的方向,这是预测销售未来的基础。

我们将使用[fbprophet](https://facebook.github.io/prophet/docs/quick_start.html)包来确定我们两个数据集的总体趋势。这些步骤将是:

  • 选择天气数据的范围(在 2007 年和 2009 年之间)
  • 将数据作为具有两列的 dataframe 提供给fbprophet.Prophet对象:“ds”(表示日期)和“y”(表示数据)
  • 运行模型
  • 用上限和下限绘制趋势图
from fbprophet import Prophet
from datetime import datetime

start_date = "2007-01-01"
end_date = "2008-12-31"
df_weather["Formatted Date"] = pd.to_datetime(df_weather["Formatted Date"], utc=True)

date_range = (df_weather["Formatted Date"] > start_date) & (df_weather["Formatted Date"] < end_date)

df_prophet = df_weather.loc[date_range]

m = Prophet()

ds = df_prophet["Formatted Date"].dt.tz_localize(None)
y = df_prophet["Temperature (C)"]
df_for_prophet = pd.DataFrame(dict(ds=ds,y=y))
m.fit(df_for_prophet)

future = m.make_future_dataframe(periods=120)

forecast = m.predict(future)
forecast = forecast[["ds","trend", "trend_lower", "trend_upper"]]
fig = m.plot_components(forecast,plot_cap=False)
trend_ax = fig.axes[0]

trend_ax.plot()
plt.title("Trend for Weather Data", fontsize=15)
plt.xlabel("Date", fontsize=15)
plt.ylabel("Weather Trend", fontsize=15)
plt.show()INFO:fbprophet:Disabling yearly seasonality. Run prophet with yearly_seasonality=True to override this.
C:\Users\lucas\.conda\envs\env_1\lib\site-packages\pystan\misc.py:399: FutureWarning:

Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.

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

我们可以看到,对于天气来说,趋势正如我们所预期的那样遵循常规季节,在夏季上升,在冬季下降。

现在,让我们对零售数据集做同样的事情。这些步骤与上面的图类似,唯一的区别是我们将从零售数据集中选择一家商店。

from fbprophet import Prophet

m = Prophet()
# Selecting one store
df_store_1 = df_sales[df_sales["Store"]==1]

df_store_1["Date"] = pd.to_datetime(df_store_1["Date"])
ds = df_store_1["Date"].dt.tz_localize(None)
y = df_store_1["Weekly_Sales"]
df_for_prophet = pd.DataFrame(dict(ds=ds,y=y))
m.fit(df_for_prophet)
future = m.make_future_dataframe(periods=15)
forecast = m.predict(future)
forecast = forecast[["ds","trend", "trend_lower", "trend_upper"]]
fig = m.plot_components(forecast,plot_cap=False)
trend_ax = fig.axes[0]
trend_ax.plot()
plt.title("Trend for Retail Data", fontsize=15)
plt.xlabel("Date", fontsize=15)
plt.ylabel("Sales Trend", fontsize=15)

plt.show()C:\Users\lucas\.conda\envs\env_1\lib\site-packages\ipykernel_launcher.py:8: SettingWithCopyWarning:

A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

INFO:fbprophet:Disabling daily seasonality. Run prophet with daily_seasonality=True to override this.
C:\Users\lucas\.conda\envs\env_1\lib\site-packages\pystan\misc.py:399: FutureWarning:

Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.

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

从 2010 年到 2013 年,所选商店的销售业绩呈现出近乎完美的线性上升趋势,总销量增幅超过 1%。对这些结果的实际解释需要其他指标,如流失率和潜在的成本增加,因此上升趋势不一定意味着利润增加。然而,一旦考虑了所有因素,趋势是整体性能的良好指标。

传统时间序列模型在销售预测中的应用

到目前为止,我们已经介绍了销售预测问题的基本知识,并从时间序列的角度确定了它的主要组成部分:重复模式、静态模式和趋势的概念。如果你想更深入地了解时间序列,我推荐@Will Koehrsen 的这篇文章。

现在,我们将研究处理销售预测问题的传统时间序列方法:

  • 移动平均数
  • 指数平滑法
  • ARIMA

移动平均数

该模型假设下一个观察值是所有过去观察值的平均值,它可用于识别数据中有趣的趋势。我们可以定义一个窗口来应用移动平均模型平滑时间序列,并突出显示不同的趋势。

让我们用移动平均线模型来预测天气和销售。这些步骤将是:

  • 选择一个范围
  • 定义移动平均窗口的值
  • 计算平均绝对误差
  • 画出滚动平均值的上下界
  • 绘制真实数据
from sklearn.metrics import mean_absolute_error

green = sns.color_palette("deep", 8)[2]
blue = sns.color_palette("deep", 8)[0]

start_date = "2007-01-01"
end_date = "2008-12-31"
df_weather["Formatted Date"] = pd.to_datetime(df_weather["Formatted Date"], utc=True)
date_range = (df_weather["Formatted Date"] > start_date) & (df_weather["Formatted Date"] < end_date)
df_weather_ma = df_weather.loc[date_range]
series = df_weather_ma["Temperature (C)"]

window=90
rolling_mean = series.rolling(window=window).mean()
fig,ax = plt.subplots(figsize=(17,8))

plt.title('Moving Average Model for Weather Dataset',fontsize=15)
plt.plot(rolling_mean, color=green, label='Rolling mean trend')
#Plot confidence intervals for smoothed values
mae = mean_absolute_error(series[window:], rolling_mean[window:])
deviation = np.std(series[window:] - rolling_mean[window:])
lower_bound = rolling_mean - (mae + 2 * deviation)
upper_bound = rolling_mean + (mae + 2 * deviation)
plt.plot(upper_bound, 'r--', label='Upper bound / Lower bound')
plt.plot(lower_bound, 'r--')
plt.plot(series[window:],color=blue, label="Actual Values")

plt.legend(loc='best')
plt.grid(True)
plt.xticks([])

plt.show()

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

这个模型似乎捕捉到了一些天气的动态变化。让我们看看该模型如何处理零售数据集。

series = df_sales_sum.Weekly_Sales
window=15

rolling_mean = series.rolling(window=window).mean()
fig,ax = plt.subplots(figsize=(17,8))

plt.title('Moving Average Model for Retail Sales',fontsize=15)

plt.plot(rolling_mean, color=green, label='Rolling mean trend')

#Plot confidence intervals for smoothed values
mae = mean_absolute_error(series[window:], rolling_mean[window:])
deviation = np.std(series[window:] - rolling_mean[window:])
lower_bound = rolling_mean - (mae + 1.92 * deviation)
upper_bound = rolling_mean + (mae + 1.92 * deviation)

plt.plot(upper_bound, 'r--', label='Upper bound / Lower bound')
plt.plot(lower_bound, 'r--')

plt.plot(series[window:], color=blue,label='Actual values')

plt.legend(loc='best')
plt.grid(True)
plt.xticks([])
plt.show()

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

对于销售数据集,拟合看起来没有那么有希望,但是与天气数据集相比,零售数据集的数据也少得多。此外,设置我们的平均大小的窗口参数对我们的整体性能有很大的影响,我没有做任何额外的超参数调整。在这里,我们应该明白的是,复杂的销售数据集需要比简单的一维时间序列所能提供的更多的信息。

指数平滑法

指数平滑类似于移动平均,但在这种情况下,每个观察值的权重会递减,因此,随着我们远离当前,观察值的重要性会降低。这种假设有好有坏:降低时间序列动态中过时信息的权重可能是有益的,但当过去的信息与数据的动态有某种永久的因果关系时,这种假设可能是有害的。

让我们在上面使用的天气数据集中使用指数平滑,我们将:

  • 符合数据
  • 预报
  • 对照实际值绘制预测图
from statsmodels.tsa.api import ExponentialSmoothing
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns
sns.set()
import pandas as pd

fit1 = ExponentialSmoothing(df_weather["Temperature (C)"][0:200]).fit(smoothing_level=0.1, optimized=False)
fit2 = ExponentialSmoothing(df_weather["Temperature (C)"][0:200]).fit(smoothing_level=0.5, optimized=False)
forecast1 = fit1.forecast(3).rename(r'$\alpha=0.1$')
forecast2 = fit2.forecast(3).rename(r'$\alpha=0.5$')
plt.figure(figsize=(17,8))

forecast1.plot(color='blue', legend=True)
forecast2.plot(color='red', legend=True)
df_weather["Temperature (ºC)"][0:200].plot(marker='',color='green', legend=True)
fit1.fittedvalues.plot(color='blue')
fit2.fittedvalues.plot(color='red')
plt.title("Exponential Smoothing for Weather Data", fontsize=15)
plt.xticks([])

plt.show()

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

现在,对于零售数据集:

# Put the correct dataframe here!

fit1 = ExponentialSmoothing(df_sales_sum["Weekly_Sales"][0:200]).fit(smoothing_level=0.1, optimized=False)

fit2 = ExponentialSmoothing(df_sales_sum["Weekly_Sales"][0:200]).fit(smoothing_level=0.5, optimized=False)

forecast1 = fit1.forecast(3).rename(r'$\alpha=0.1$')
forecast2 = fit2.forecast(3).rename(r'$\alpha=0.5$')
plt.figure(figsize=(17,8))

forecast1.plot(color='blue', legend=True)
forecast2.plot(color='red', legend=True)
df_sales_sum["Weekly_Sales"][0:200].plot(marker='',color='green', legend=True)
plt.ylabel("Sales", fontsize=15)

fit1.fittedvalues.plot(color='blue')
fit2.fittedvalues.plot(color='red')

plt.title("Exponential Smoothing for Retail Data", fontsize=15)
plt.xticks([], minor=True)
plt.show()

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

这里,我们使用平滑因子(最近一段时间的权重)的两个值 alpha = 0.1 和 alpha = 0.5 进行平滑,并用绿色绘制实际温度和零售数据。

正如我们在这里看到的,平滑因子越小,时间序列就越平滑。这具有直观的意义,因为随着平滑因子接近 0,我们接近移动平均模型。第一个似乎很好地捕捉了两个数据集的动态,但它似乎未能捕捉某些峰值活动的幅度。

从概念上讲,在给定数据集的性质的情况下,思考模型的假设如何影响其性能是很有趣的。我认为新信息对销售更重要,因为影响商店销售产品可能性的因素可能会不断变化和更新。因此,与假设动态以某种方式保持不变的模型相比,具有降低过去信息重要性的能力的模型将更准确地捕捉这种变化动态。

有马

ARIMA 或自回归综合移动平均是一种时间序列模型,旨在描述时间序列数据中的自相关性。它适用于短期预测,并且对于为用户指定的时间段提供预测值非常有用,可以显示需求、销售、计划和生产的良好结果。

ARIMA 模型的参数定义如下:

  • p:模型中包含的滞后观测值的数量
  • d:原始观测值被差分的次数
  • 问:移动平均线窗口的大小

现在,我将使用 ARIMA 模型来模拟天气数据和零售销售。这些步骤将是:

  • 将数据分为训练和测试
  • 符合数据
  • 打印均方差(我们的评估指标)
  • 用真实值绘制模型拟合图
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
import pandas as pd

X = df_weather["Temperature (C)"].values

train_size = 600
test_size = 200

train, test = X[0:train_size], X[train_size:train_size+test_size]

history = [x for x in train]
predictions = []
for t in range(len(test)):
	model = ARIMA(history, order=(5,1,0))
	model_fit = model.fit(disp=0)
	output = model_fit.forecast()
	yhat = output[0]
	predictions.append(yhat)
	obs = test[t]
	history.append(obs)

mse = mean_squared_error(test, predictions)
print(f"MSE error: {mse}")
plt.figure(figsize=(17,8))

plt.plot(test)
plt.plot(predictions, color='red')
plt.title("ARIMA fit Weather Data")
plt.xticks([])
plt.show()MSE error: 3.105596078192541

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

在这里,我们看到了 ARIMA 模型与天气数据集的预期良好拟合,因为之前我们看到该数据集具有非常高的自相关性。让我们将此与模型在销售数据集上的表现进行比较:

from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

X = df_sales_sum["Weekly_Sales"].values

split = int(0.66*len(X))
train, test = X[0:split], X[split:]

history = [x for x in train]
predictions = []
for t in range(len(test)):
	model = ARIMA(history, order=(5,1,0))
	model_fit = model.fit(disp=0)
	output = model_fit.forecast()
	yhat = output[0]
	predictions.append(yhat)

	obs = test[t]
	history.append(obs)
mse = mean_squared_error(test, predictions)

print(f"MSE error: {mse}")

plt.figure(figsize=(17,8))
plt.plot(test)
plt.plot(predictions, color='red')
plt.title("ARIMA fit to Sales Data",fontsize=15)
plt.xticks([])
plt.show()MSE error: 47664398980324.34

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

在这里,拟合度远不如在气象数据集中的拟合度好,考虑到 ARIMA 模型通常适用于高度稳定的数据集,这是意料之中的。

让我们记住,这里的结果只是为了展示模型,并不代表准确的估计。数据集是有限的(求和后的零售数据集小于 200 个数据点),我没有执行任何复杂的超参数调整。这里的目标只是演示这些模型是如何工作的,以及如何在 python 中实现它们。我们可以证实,零售数据集似乎提出了传统模型无法克服的挑战。

我们可以看到,对于有明确模式的数据集,传统模型工作得很好。然而,在缺乏这种结构的情况下,这些模型似乎不具备适应的灵活性,因为它们依赖于关于目标时间序列动态的强有力的假设。

现在,我们将讨论当前用于销售预测的深度学习方法,并尝试了解它们可以带来什么,这将有利于在传统模型不足以满足需求的情况下提高预测准确性。

现代销售预测和深度学习

在这里,我想概述一下我认为最适合销售预测的深度学习候选人的主要候选人。

亚马逊的 DeepAR 模型

我们今天在这里讨论的模型对每个单独的时间序列都适用一个模型。然而,在销售中,通常有多个时间序列与您试图建模的动态相关。因此,能够在所有相关时间序列上联合训练模型是非常有益的。

进入亚马逊预测 DeepAR+,这是一种使用递归神经网络预测一维时间序列的监督学习算法。它允许在一个模型上训练多个时间序列特征,并且在标准时间序列基准上优于传统模型。

该模型的主要特点是,它克服了传统模型只能在单一时间序列上训练的局限性。此外,该模型使用概率预测**,其中,该模型预测不同未来情景的可能性分布,展示一组预测区间,而不是传统的对我们在给定日期或期间预期销售多少的点预测。这些预测分位数可以用来表示预测中的不确定性,从而为我们提供每个预测的置信区间。当涉及到点预测用处不大的下游使用决策时,这些类型的预测特别重要。**

销售预测的 NLP

一种乍一看似乎非常规但很有希望的方法是使用自然语言处理模型进行预测。我想提到两种方法:

实体嵌入

在 LotusLabs 的这篇文章中,他们描述了使用分类数据(彼此不相关的数据)并利用该数据的嵌入表示来进行预测的想法。为了建立这种表示,传统的神经网络用于将输入映射到嵌入空间。

通过识别相似的输入并将它们映射到相似的位置,他们能够识别出原本很难看到的模式。使用这种方法的一个优点是,您不必执行任何特性工程。

关于这种方法的一个有趣的细节是,它克服了简单的一热编码表示中的稀疏性等问题。

NLP 对产品描述进行销售预测

这篇论文采取了不同的方法。他们使用了日本电子商务市场 Rakuten 上超过 90,000 个产品描述的数据,并确定了可操作的写作风格和词汇用法,这些风格和用法高度预测了消费者的购买行为。

该模型综合使用了词向量、LSTMs 和注意力机制来预测销售额。他们发现,季节性的、礼貌的、权威的和信息丰富的产品描述会带来最好的结果。

此外,他们表明,即使你考虑到品牌忠诚度和商品身份等其他因素,产品描述的嵌入式叙述中的词语也是销售的非常重要的决定因素。他们使用神经网络的新特征选择方法具有良好的性能,并且该方法本身指出了在使用执行销售预测时必须考虑的数据集环境的异质性。

用于销售预测的 WAVENET】

Corporacion Favorita 杂货销售预测比赛中获得第二名的选手使用了改编版的 Wavenet CNN 模型。Wavenet 是一个生成模型,可以在给定一些条件输入的情况下生成实值数据序列。根据作者的说法,这里的主要思想在于扩张因果卷积的概念。

WaveNet 被构造为完全卷积神经网络,其中卷积层具有各种膨胀因子,允许其感受野指数增长,并使用能够保持特征图大小的上采样滤波器覆盖许多时间点。这种方法可以扩大内核的视野,并捕捉输入的整体全局视图。要了解更多,我推荐 DeepMind 的这篇文章。

生成模型似乎是深度学习中销售预测的一个明显趋势,因为它们已经证明有能力对分布进行建模,因此可以预测不同场景的可能性,在销售预测的偶然背景下,当人们可以访问足够的数据时,这似乎是比传统模型更好的方法。

关于元学习的快速说明

在今年 5 月发表的这篇论文中,邵会·马和罗伯特·菲尔德斯开发了一种销售预测的元学习方法。这个想法是使用元学习者利用潜在的预测方法池,而不是一个模型的方法。

他们的方法使用元学习器来提取数据的相关特征,这些元学习器使用 1-D 卷积的堆叠序列和最后合并的校正线性单元。在集合阶段,他们使用密集层和 softmax 将来自多个预报的预测结合起来。

他们的方法点表明该领域趋向于更混合的自学方法,而不是单一模型解决方案。

结论

传统的方法只能解释它们被训练的一维数据的动态。然而,像这样的方法指出了混合模型的未来,其中多个时间序列可以被考虑,分类变量可以被包括在预测管道中。

通用性和灵活性似乎是渗透成功销售预测模型的关键因素。深度学习能够开发复杂的定制预测模型,这些模型包含非结构化零售数据集,因此只有当数据足够复杂时,使用它们才有意义。

如果你想看看这篇文章的笔记本,你可以在这里找到它。

如果你喜欢这种类型的内容,请查看我的 Youtube 频道:

作者

如果您想更深入地了解 Python 预测,请查看 Udemy 的这些课程:

这些是附属链接,如果你使用它们,我会得到一小笔佣金,干杯!😃

这里有一些程序员必备的附属链接:)

如果你喜欢这篇文章,请在 LinkedInTwitter 上联系我。

谢谢,下次再见!😃

参考

具有价格和促销效果的销售预测

原文:https://towardsdatascience.com/sales-forecasting-with-price-promotion-effects-b5d70207b128?source=collection_archive---------0-----------------------

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

图片来源:Pixabay

促销分析,时间序列预测,干预分析

许多生意都是季节性的,有些生意会在假期赚钱,比如超级碗、劳动节、感恩节和圣诞节。此外,他们在一年中的几个星期里利用促销来增加对产品或服务的需求或知名度。

在本帖中,我们将使用时间序列分析技术来分析历史数据,具有推广效果。

我们将要使用的数据是 9 家商店和 3 种产品的每周销售和价格数据。最后,我们将预测其中一家商店三种产品之一未来 50 周的销售情况。你可以在这里找到数据集

数据

  • 商店:商店代码。我们总共有 9 家店。
  • 产品:产品代码。我们总共有三种产品。
  • Is_Holiday:该周是否包含假日的指标:0 =否,1 =是。
  • 基价:无折扣的基本价格或日常价格。
  • 价格:每周的实际价格。它们要么是促销时的促销价格,要么是日常价格。
  • 周销售量:周销售量。

新功能. py

在上面的数据预处理中,我们添加了新的功能,如以美元、年、月、日、周为单位的周销售额。

电子设计自动化(Electronic Design Automation)

为了获得关于数据中连续变量的第一印象,我们将绘制 ECDF

ECDF.py

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

1

  • 虽然在最好的一周,一家商店销售了 2500 多台,但大约 80%的时间,周销售量都没有超过 500 台。
  • 尽管最高周销售额超过 25K 美元,但超过 90%的数据的周销售额低于 5K 美元。
df.groupby('Store')['weekly_sales'].describe()

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

图 2

df.groupby('Store')['Weekly_Units_Sold'].sum()

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

图 3

  • 很容易看出,在所有 9 家商店中,商店 10 的平均周销售额最高,商店 10 的总周销售量也最高。
  • 而 5 号店的平均周销售额最低。
  • 显然,10 号店是最畅销和最拥挤的一家。
g = sns.FacetGrid(df, col="Is_Holiday", height=4, aspect=.8)
g.map(sns.barplot, "Product", "Price");

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

图 4

g = sns.FacetGrid(df, col="Is_Holiday", height=4, aspect=.8)
g.map(sns.barplot, "Product", "Weekly_Units_Sold");

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

图 5

  • 产品 2 是所有三种产品中最便宜的产品,它卖得最多。
  • 产品 3 是所有三种产品中最贵的产品。
  • 此外,产品价格在节假日期间没有变化。
g = sns.FacetGrid(df, row="Is_Holiday",
                  height=1.7, aspect=4,)
g.map(sns.distplot, "Weekly_Units_Sold", hist=False, rug=True);

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

图 6

sns.factorplot(data= df, 
               x= 'Is_Holiday',
               y= 'Weekly_Units_Sold',
               hue= 'Store');

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

图 7

sns.factorplot(data= df, 
               x= 'Is_Holiday',
               y= 'Weekly_Units_Sold',
               hue= 'Product');

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

图 8

  • 假期似乎不会对业务产生积极影响。对于大多数商店来说,假日期间的周销售量与平时相同,而 10 号商店在假日期间有所下降。
  • 产品 1 的周销售量在假日期间略有增加,而产品 2 和产品 3 在假日期间有所下降。
g = sns.FacetGrid(df, col="Product", row="Is_Holiday", margin_titles=True, height=3)
g.map(plt.scatter, "Price", "Weekly_Units_Sold", color="#338844", edgecolor="white", s=50, lw=1)
g.set(xlim=(0, 30), ylim=(0, 2600));

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

图 9

  • 每个产品都有不止一个价格,在节假日和平时都是如此。我猜一个是正常价格,另一个是促销价格。
  • 产品 3 的价格差距是巨大的,在促销期间它被削减到将近 50%。
  • 产品 3 在非节假日期间销量最大。
g = sns.FacetGrid(df, col="Store", hue="Product", margin_titles=True, col_wrap=3)
g.map(plt.scatter, 'Price', 'Weekly_Units_Sold', alpha=.7)
g.add_legend();

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

图 10

这 9 家商店都销售这 3 种产品。他们似乎都有类似的打折促销活动。但是,在商店 10 的促销活动中,产品 3 的销量最高。

g = sns.FacetGrid(df, col="Store", col_wrap=3, height=3, ylim=(0, 1000))
g.map(sns.pointplot, "month", "Weekly_Units_Sold", color=".3", ci=None, order = [1,2,3,4,5,6,7,8,9,10,11,12]);

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

图 11

每个商店都有一定的季节性,10 号店的季节性最明显。

g = sns.FacetGrid(df, col="Product", col_wrap=3, height=3, ylim=(0, 1000))
g.map(sns.pointplot, "month", "Weekly_Units_Sold", color=".3", ci=None, order = [1,2,3,4,5,6,7,8,9,10,11,12]);

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

图 12

每个产品都有一定的季节性,产品 2 每年有两个旺季,产品 3 有一个旺季。

g = sns.FacetGrid(df, col="Store", col_wrap=3, height=3, ylim=(0, 2000), hue='Product', palette="Set1")
g.map(sns.pointplot, "month", "Weekly_Units_Sold", ci=None, order = [1,2,3,4,5,6,7,8,9,10,11,12], alpha=.7)
g.add_legend();

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

图 13

  • 总的来说,在每家商店,产品 2 每周的销售量都比其他产品多。
  • 在商店 10,产品 3 偶尔会超过产品 2。
g = sns.PairGrid(df, y_vars=["Weekly_Units_Sold"], x_vars=["Price", "Is_Holiday"], height=4)
g.map(sns.regplot, color=".3");

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

图 14

  • 价格越便宜,每周售出的数量就越多。
  • 是不是放假跟单位卖不卖没关系。

这里我们增加了一个新的栏目,叫做“促销”,这个栏目是从“底价”和“价格”派生出来的。

推广. py

sns.factorplot(data= df, 
               x= 'promotion',
               y= 'Weekly_Units_Sold',
               hue= 'Store');

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

图 15

在促销期间,每家商店都卖得更多,没有例外。

sns.factorplot(data= df, 
               x= 'promotion',
               y= 'Weekly_Units_Sold',
               hue= 'Product');

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

图 16

促销期间,每种产品都卖得更多,尤其是产品 2 和产品 3。

g = sns.FacetGrid(df, col="Store", hue="promotion", palette = 'plasma', row='promotion')
g = (g.map(plt.scatter, "Price", "Weekly_Units_Sold")
     .add_legend())

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

图 17

所有的商店都有相似的价格促销模式,出于某种原因,商店 10 在促销期间卖得最多。

g = sns.FacetGrid(df, hue="promotion", col="Product", height=4)
g.map(qqplot, "Price", "Weekly_Units_Sold")
g.add_legend();

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

图 18

每个产品都有正常价格和促销价格。在促销期间,产品 3 的折扣最高,销量也最大。

观察值

  • 销售最多、最拥挤的是 10 号店,最不拥挤的是 5 号店。
  • 就售出的单位数量而言,全年最畅销的产品是产品 2。
  • 商店不一定在假期进行产品促销。节假日似乎不会对商店或产品的表现产生影响。
  • 产品 2 好像是最便宜的产品,产品 3 是最贵的产品。
  • 大多数商店都有一些季节性,他们每年有两个旺季。
  • 产品 1 在 2 月份的销量比其他月份稍高,产品 2 在 4 月和 7 月左右的销量最高,产品 3 在 7 月至 9 月的销量最高。
  • 每种产品都有其正常价格和促销价格。产品 1 和产品 2 的正常价格和促销价格之间没有明显的差距,但是,产品 3 的促销价格可以削减到其原价的 50%。虽然每个商店都对产品 3 进行这种降价,但在降价期间,商店 10 的销售额最高。
  • 促销期间比平时卖得多并不稀奇。商店 10 使产品 3 在 7 月至 9 月期间成为最畅销的产品。

先知的时间序列

我们将为商店 10 中的产品 3 构建一个时间序列分析,并以美元为单位预测每周销售额。

timeseries_viz.py

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

图 19

商店 10 中产品 2 的季节性很明显。在学校放假期间,销售总是在七月和九月之间达到高峰。

下面我们正在实现 prophet 模型,预测未来 50 周的周销售额。

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

图 20

该模型能够捕捉到季节性。

model.plot_components(forecast);

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

图 21

metric_df = forecast.set_index('ds')[['yhat']].join(store_10_pro_3.set_index('ds').y).reset_index()
metric_df.dropna(inplace=True)
error = mean_squared_error(metric_df.y, metric_df.yhat)
print('The RMSE is {}'. format(sqrt(error)))

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

季节性效应

关于 Prophet 的一个伟大的事情是,我们可以添加我们自己的定制季节。这里我们将添加从七月初到九月初的学校假期。

add _ 季节性. py

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

图 22

metric_df = forecast.set_index('ds')[['yhat']].join(store_10_pro_3.set_index('ds').y).reset_index()
metric_df.dropna(inplace=True)
error = mean_squared_error(metric_df.y, metric_df.yhat)
print('The RMSE is {}'. format(sqrt(error)))

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

RMSE 下降了一点。

model.plot_components(forecast);

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

图 23

Jupyter 笔记本可以在 Github 上找到。享受这周剩下的时光吧!

参考资料:

[## 季节性、假日效应和回归因素

如果您有假期或其他想要建模的周期性事件,您必须为它们创建一个数据框架。它有…

facebook.github.io](https://facebook.github.io/prophet/docs/seasonality,_holiday_effects,_and_regressors.html)

https://seaborn.pydata.org/generated/seaborn.FacetGrid.html

Tableau 中的销售与利润(象限)分析

原文:https://towardsdatascience.com/sales-vs-profit-quadrant-analysis-in-tableau-aeafd1b757dc?source=collection_archive---------16-----------------------

使用 Tableau 中的象限分析快速识别任何销售数据集中表现最佳的类别。

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

Tableau 中的销售与利润象限分析(图片由作者提供)

使用 Tableau 中的象限分析快速识别任何销售数据集中表现最佳的类别。

详细信息:象限图只不过是一个由四个相等部分组成的散点图。每个象限支持具有相似特征的数据点。以下是如何使用超市销售数据集在 Tableau 中绘制象限分析图的分步方法,以确定在销售和利润方面表现最佳的品类:

步骤 1: 打开一个新的 Tableau 文件,将“超市”公共数据集导入工作簿。如果你以前没有用过 Tableau,请从以下网址下载“Tableau Public”:https://public.tableau.com/en-us/s/download

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

Tableau 公开下载(图片由作者提供)

**第 2 步:**我们的目标是根据销售和利润指标评估各个子类别的表现。因此,将“订单”表导入到工作区中;将汇总的“销售”和“利润”指标拖放到行&列中。

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

导入订单表(作者图片)

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

总销售额和利润(作者图片)

**第 3 步:**通过将“子类别”字段拖放到“标签”和“分析”窗格中,引入子类别。

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

导入子类别(按作者分类的图片)

步骤 4: 为参考行创建计算字段:

Reference Line for Profit = WINDOW_AVG(SUM([Profit]))Reference Line for Sales = WINDOW_AVG(SUM([Sales]))

将参考线计算拖至“详细信息”和“分析”窗格。编辑两个参考行计算,一个用于销售,另一个用于利润。

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

创建计算字段(作者图片)

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

利润参考线(图片由作者提供)

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

销售参考线(图片由作者提供)

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

统一参考线部件(图片由作者提供)

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

带圆圈的参考线(图片由作者提供)

步骤 5: 为“象限(颜色指示器)”创建计算字段:

Quadrant (Colour Indicator)=IF [Reference Line for Profit]>= WINDOW_AVG(SUM([Profit]))
AND [Reference Line for Sales]>= WINDOW_AVG(SUM([Sales]))
THEN 'UPPER RIGHT'ELSEIF[Reference Line for Profit]< WINDOW_AVG(SUM([Profit]))
AND [Reference Line for Sales]>= WINDOW_AVG(SUM([Sales]))
THEN 'LOWER RIGHT'ELSEIF[Reference Line for Profit]> WINDOW_AVG(SUM([Profit]))
AND [Reference Line for Sales]< WINDOW_AVG(SUM([Sales]))
THEN 'UPPER LEFT'ELSE 'LOWER LEFT'END

拖动“象限(颜色指示器)”来着色和编辑表格计算;选择“子类别”作为特定维度。

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

象限颜色指示器(图片由作者提供)

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

选择子类别(按作者分类的图片)

步骤 6: 此外,为等级创建一个计算字段,并将它拖到工具提示中:

Sales Rank = RANK(SUM([Sales]))Profit Rank = RANK(SUM([Profit]))Count of Sub-Category = WINDOW_COUNT(COUNTD([Sub-Category]))

对于每个计算字段:编辑表格计算&选择“子类别”作为特定维度。

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

销售排名(作者图片)

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

利润排名(作者图片)

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

子类别计数(按作者分类的图片)

**第七步:**给标题,格式化坐标轴,添加参考线。

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

Y 轴格式(图片由作者提供)

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

X 轴格式(图片由作者提供)

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

在两个轴上添加参考线(图片由作者提供)

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

y 轴参考线配置。(图片由作者提供)

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

x 轴参考线(图片由作者提供)

**第 8 步:**固定 BI 小工具的大小,设置工具提示。

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

BI 部件大小(图片由作者提供)

工具提示:

<Sub-Category>Sales:<SUM(Sales)>Sales Rank:<AGG(Sales Rank)>/<AGG(Count of Sub-Category)>Profit:<SUM(Profit)>Profit Rank:<AGG(Profit Rank)>/<AGG(Count of Sub-Category)>

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

工具提示配置。(图片由作者提供)

第九步:产生洞察力:

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

销售与利润象限分析(图片由作者提供)

(1)我们可以从象限图中清楚地看到,通过为超市创造最大的销售额和利润,手机、储物件和活页夹销量最大。因此,让销售团队知道这些产品对我们的年收入有多重要。

(2)另一方面,我们可以看到销售了大量的桌子和机器,但它们的利润似乎出人意料地低于同行。我们在抛售吗?我们应该提高产品的价格吗?

(3)超市出售的电器不多,而它们的利润率似乎真的很高。因此,让销售团队知道,如果他们能想出更多创新措施来推动这些设备的销售,那就太好了。

(4)最后,重新审视我们的销售和营销策略,以确保有足够数量的家具、书架和艺术品以修订后的价格售出。

结论:

因此,在本文中,我们简要地研究了 Tableau 中交互式象限分析的基本原理,并从相似和不相似的数据点中获得见解。从这里,我们可以继续用 R 或 Python 进行探索性数据分析,以识别数据集中真正推动销售的其他重要组件。

GitHub 库

我已经从 Github 的许多人那里学到了(并且还在继续学到)。因此在一个公共的 GitHub 库 中分享我的 Tableau 文件,以防它对任何在线搜索者有益。此外,如果您在理解 Tableau 中数据可视化的基础知识方面需要任何帮助,请随时联系我。乐于分享我所知道的:)希望这有所帮助!

关于作者:

[## Sreejith Sreedharan - Sree

数据爱好者。不多不少!你好!我是 Sreejith Sreedharan,又名 Sree 一个永远好奇的数据驱动的…

srees.org](https://srees.org/about)

使用 Docker 和 Nginx 的负载平衡解决方案示例

原文:https://towardsdatascience.com/sample-load-balancing-solution-with-docker-and-nginx-cf1ffc60e644?source=collection_archive---------0-----------------------

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

当今大多数业务应用程序都使用负载平衡在不同资源之间分配流量,避免单个资源过载。

负载平衡架构的一个明显优势是提高了应用程序的可用性和可靠性,因此,如果一定数量的客户端向后端请求一定数量的资源,负载平衡器会留在它们之间,并将流量路由到满足大多数路由标准(不太忙、最健康、位于给定区域)的后端…等等)。

有很多路由标准,但我们将把本文的重点放在固定的循环标准上——这意味着每个后端接收固定量的流量——我认为这很少被记录下来:)。

为了简化,我们将基于 flask Python 文件创建两个后端“应用程序”。我们将使用 NGINX 作为负载平衡器,将 60%的流量分配给应用 1,40%的流量分配给应用 2。

让我们开始编码,以下是我们项目的完整架构:

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

负载平衡项目树

app1/app1.py

from flask import request, Flask
import jsonapp1 = Flask(__name__)
@app1.route('/')def hello_world():
return 'Salam alikom, this is App1 :) 'if __name__ == '__main__':
app1.run(debug=True, host='0.0.0.0')

app2/app2.py

from flask import request, Flask
import jsonapp1 = Flask(__name__)
@app1.route('/')def hello_world():
return 'Salam alikom, this is App2 :) 'if __name__ == '__main__':
app1.run(debug=True, host='0.0.0.0')

然后,我们必须通过添加 requirements.txt 文件来对两个应用程序进行 dockerize。它将只包含 flask 库,因为我们使用的是 python3 映像。

app 1/requirements . txt
您可以为 app2 创建相同的。

Flask==1.1.1

app1/Dockerfile
你可以为 app2 创建相同的。

FROM python:3
COPY ./requirements.txt /requirements.txt
WORKDIR /
RUN pip install -r requirements.txt
COPY . /
ENTRYPOINT [ "python3" ]
CMD [ "app1.py" ]

我们将使用 NGINX 作为负载平衡器,路由标准将由循环法权重参数保证:

nginx/nginx.conf

upstream loadbalancer {
server 172.17.0.1:5001 weight=6;
server 172.17.0.1:5002 weight=4;
}
server {
location / {
proxy_pass [http://loadbalancer;](http://loadbalancer;)
}} 

然后,我们将通过使用 Nginx 映像创建 Dockerfile 来对我们的负载平衡器进行 dockerize。它会在启动时将上述 conf 文件复制到容器内的相关路径中。

nginx/Dockerfile

FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf

现在我们将创建 docker-compose 文件,该文件将加速我们的完整架构,以便我们可以从浏览器访问它。

docker-compose.yml

version: '3'
services:
app1:
build: ./app1
ports:
- "5001:5000"
app2:
build: ./app2
ports:
- "5002:5000"
nginx:
build: ./nginx
ports:
- "8080:80"
depends_on:
- app1
- app2

关于 docker-compose.yml 的一些要点:

  • 它将基于我们的 docker 文件为 app1、app2、Nginx 构建映像,然后根据这些映像构建容器。
  • app1 和 app2 容器中打开的端口是 5000(flask 使用的默认端口),这些端口将被映射到 5001 和 5002。
    负载平衡器会根据该端口将流量路由到适当的应用程序。
  • 负载平衡器(Nginx)会将其内部 80 端口暴露给 8080,这样我们就可以从 http://localhost:8080 访问应用程序

最后,我们将通过运行下面的命令来加速我们的架构,并在浏览器中享受结果:)

docker-compose up

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

您还可以在下面的 GitLab repo 中找到完整的代码:

[## Abdelilah OUASSINI /负载平衡

GitLab.com

gitlab.com](https://gitlab.com/ouassini/load-balancing)

一如既往,我希望你学到了新的东西。萨拉姆:)

抽样分布——样本均值

原文:https://towardsdatascience.com/sampling-distribution-sample-mean-fcf69484535e?source=collection_archive---------33-----------------------

用 Python 模拟和例子

在推理数据分析中讨论的最重要的概念之一是抽样分布的概念。了解抽样分布有助于我们更好地理解和解释描述性和预测性数据分析调查的结果。在不确定性和假设检验的情况下,抽样分布也经常用于决策。

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

Marcin JozwiakUnsplash 上拍摄的照片

什么是抽样分布?

你可能已经熟悉了概率分布的概念。概率分布让我们了解与随机变量可能假设的值(或值的范围)相关的概率和可能性。随机变量的值(结果)是随机确定的。随机变量的一些例子包括零售商店的月收入、在任何给定的一天到达洗车场的顾客数量、在任何给定的一天在某条高速公路上的事故数量、零售商店的周销售量等。虽然随机变量的结果是随机的,但概率分布允许我们获得和了解结果中出现不同值的可能性和概率。抽样分布是我们附加到样本的样本统计上的概率分布。

样本均值作为样本统计量

样本统计量(也简称为统计量)是从样本中获得的值。这里有一个例子,假设你收集了居住在某个街区的 250 个随机选择的个人填写的调查结果。根据调查结果,您意识到该样本中个人的平均年收入为 82,512 美元。这是一个样本统计,用*x̅= 82,512 美元表示。*样本均值也是一个具有概率分布的随机变量(用 X̅表示)。X̅的概率分布称为样本均值的抽样分布。可以为其他类型的样本统计定义样本分布,包括样本比例、样本回归系数、样本相关系数等。

你可能想知道为什么 X̅是一个随机变量,而样本均值只是一个单一的数字!理解这一点的关键在于样本间可变性的概念。这个想法指的是从同一人群中抽取的样本并不完全相同。这里有一个例子,假设在上面的例子中,我们不是只对居住在某个特定社区的 250 个人进行一次调查,而是在那个社区进行了 35 个同样大小的样本。如果我们为 35 个样本中的每一个计算样本均值 ,你将得到 35 个不同的值。现在假设,假设,我们在那个社区进行了许多相同规模的调查。我们会得到许多许多(不同的)样本均值。由这些样本平均值得到的分布就是我们所说的样本平均值的抽样分布。从这个角度考虑样本均值,我们可以想象 X̅(注意大写字母)是如何代表样本均值的随机变量,而*(注意小写字母)只是该随机变量的一种实现。*

样本均值的抽样分布

假设 X 代表数据(总体),若 X 具有均值μ和标准差σ的分布,且若 X 近似正态分布或样本量 n 较大,

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

上述分布仅在以下情况下有效,

  • x 近似正常样本量 n 大,
  • 数据(总体)标准差σ已知。

如果 x 是正态的,那么 X̅也是正态分布的,与样本大小 n 无关。中心极限定理告诉我们,即使 x 不正态,如果样本量足够大(通常大于 30),那么 X̅’s 分布近似正态(Sharpe,De Veaux,Velleman and Wright,2020,PP . 318–320)。如果 X̅是正态的,我们可以很容易地将其标准化并转换为标准正态分布 Z

如果总体标准差σ是而不是已知的,我们不能假设样本均值 X̅是正态分布的。如果满足某些条件(下面解释),那么我们可以将 X̅变换为另一个随机变量 t ,

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

随机变量 t 据说遵循 t 分布,具有 n-1 个自由度,其中 n 是样本大小。t 分布呈钟形且对称(就像正态分布一样),但与正态分布相比,它的尾部更厚。这意味着与正态分布相比,离平均值越远的值出现的可能性越大。

对随机变量 t 使用 t 分布的条件如下(Sharpe 等人,2020 年,第 415-420 页):

  • 如果 X 是正态分布,即使对于小样本量(n<15),也可以使用 t 分布。
  • 如果样本量在 15 到 40 之间,只要 X 是单峰的并且合理对称,就可以使用 t 分布。
  • 对于大于 40 的样本量,可以使用 t 分布,除非 X 的分布严重偏斜。

用 Python 模拟

让我们从正态分布中抽取一个大小为 n=250 的样本。这里我们假设我们的数据是正态分布的,参数μ = 20,σ = 3。从这个群体中收集一个样本

运行这段代码一次,我就会得到随机变量 X̅.的一个实例(或实现)下面是我运行这段代码 10 次后, 的 10 个值。

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

但是如果我运行这段代码 10,000 次,记录下 的值,并绘制出这些值的频率(或密度),我会得到下面的结果。

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

样本均值的分布(图片由作者提供)。

如您所见,该分布近似对称且呈钟形(就像正态分布一样),平均值约为 20,标准误差约等于 3/sqrt(250) = 0.19。

用不同的样本量从相同的人群中取样将导致不同的结果分布的分布测量。正如我们所预期的,增加样本量将减少标准误差,因此,分布将在其平均值附近变窄。请注意,即使样本量非常小,X̅分布也是正态分布。这是因为 X 是正态分布的。

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

样本大小对样本均值分布标准误差的影响(图片由作者提供)。

人口(数据)不正常怎么办?

别担心!即使您的数据不是正态分布,如果样本量足够大,X̅的分布仍然可以使用正态分布来近似(根据中心极限定理)。下图显示了 x 严重向左倾斜时的 X̅分布。正如你所看到的,对于小样本,X̅’s 分布倾向于模拟 x 的分布。然而,随着样本量的增长,X̅的分布变得更加对称和钟形。如上所述,如果样本量很大(通常大于 30),不管 x 的分布是什么,X̅’s 分布都是近似正态的。

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

对于大样本量,X̅’s 分布是正常的,即使 x 有一个偏斜的分布。

示例和应用

了解 X̅的分布可以帮助我们解决问题,在不确定的情况下,我们需要使用推断数据分析来做出决策。许多商业问题需要能够解决随机事件的随机性和概率性的决策工具。假设测试 是许多不同商业领域经常使用的工具之一,包括零售运营、市场营销、质量保证等。

例如,假设一家零售店开展了一项大型营销活动,并有兴趣调查该活动对该店平均销售额的影响。假设管理层想要调查平均日销售额现在是否大于 8000 美元。以下假设证明了这个研究问题:

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

请注意,我们正在对总体平均销售额进行测试,因此μ。为了解决测试问题,假设我们记录了 40 天的销售量(样本为 n=40 )并计算所需的统计数据。假设日销售量的平均值和标准差分别计算为 x̅=$8,100s=$580,。由于σ的值未知,并且假设上述假设检验正在进行,我们可以将 X̅转换为自由度为 n-1=39 的随机变量 t ,其中,

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

为了解决测试问题,我们需要找到与测试相关的 p 值。该属性计算如下:

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

随机变量 t 的概率密度函数以及测试的 p 值如下所示。

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

测试的 p 值在图片中突出显示(图片由作者提供)。

下面将找到测试的 p 值。

计算得出的 p 值约等于 0.14。根据大多数标准(显著性水平),这是一个大的 p 值,表明我们未能拒绝零假设。换句话说,根据 X̅的分布和收集的样本,我们不能得出零售店的平均日销售量μ大于 8000 美元的结论。这个计算是可能的,只是因为我们知道 X̅的分布。

可以为其他样本统计(例如,样本比例、回归预测系数等)定义采样分布。)也用于其他环境,如置信区间和预测区间或对回归结果的推断分析。

使用 Python 实现的样本分布

原文:https://towardsdatascience.com/sampling-distributions-with-python-implementation-3f4555e1d450?source=collection_archive---------29-----------------------

抽样分布、中心极限定理和用 Python 例子解释的自举

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

Unsplash 上由 Jametlene Reskp 拍摄的照片

抽样分布是统计数据的分布(可以是任何统计数据)。你可能会问为什么抽样分布很重要?嗯,它们是推断统计学的关键,推断统计学的目标是根据从一个群体的个体样本中收集的数据得出关于该群体的结论。

在本文中,感兴趣的群体是 10,000 只澳大利亚牧羊犬幼犬。我一直很好奇澳洲狗有蓝眼睛的比例是多少,淡褐色的比例是多少(假设这是它们唯一能拥有的两种眼睛颜色现实中并不是这样!).所以我们要估计的参数是蓝眼睛小狗在我们人口中所占的比例。假设我能找到 20 只小狗作为我们的样本参与实验。那 30 只小狗中蓝眼睛的比例(比例是 0,1 值的平均值)是我们的统计。下面你可以看到这个例子是模拟的

采样分发服务器有以下两个属性:

  1. 采样分布以原始参数值为中心。
  2. 样本量越大,抽样分布的方差越小。

从上面我们可以看到,原始样本的平均值为 0.75,标准偏差和方差分别为 0.433 和 0.187。让我们在示例中探索上述属性:

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

我们看到样本的比例以原始平均值(0.75)为中心。对于较大的样本量(20,如图中橙色所示),这一点更容易观察到。我们还可以看到,与 5 个样本相比,20 个样本的方差在减小。实际上,每个样本的方差就是原始数据的方差除以样本量。

在处理抽样分布时,经常会讨论两个重要的数学定理:

  1. 大数定律
  2. 中心极限定理

大数定律

大数定律表明,随着样本量的增加,样本均值将越来越接近总体均值。让我们用我们的例子来验证一下。

我们可以看到,在一个规模为 100 的样本中,平均值更接近原始平均值。

中心极限定理

该定理指出,在样本量足够大的情况下,均值的抽样分布将呈正态分布。这个定理并不适用于所有的统计学。它适用于以下情况:

  1. 样本均值
  2. 样本均值之间的差异
  3. 样本比例
  4. 样本比例之间的差异

为了验证这一点,让我们将我们的示例更改为非正态分布的样本。

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

我们看到,对于大小为 3 和 5 的样本,分布向右倾斜,对于大小为 30 的样本,分布更接近正态分布。

拔靴带

依赖数学定理,如中心极限定理,会导致缺口。我们可能不总是能够获得足够大的样本(收集 5 只小狗已经够难了!正如我们在中心极限定理一节中看到的,5 不是一个足够大的样本)或者我们可能在这些定理不适用的地方使用样本统计。

在这些情况下,我们可以使用自举。统计学中的自举意味着替换抽样,它允许我们模拟抽样分布的创建。np.random.choice(sample, size, replace=True可用于自举。事实上,在前面的所有章节中,我们已经从 20 只小狗的样本中进行了引导。通过自举,然后计算我们统计数据的重复值,我们可以了解我们统计数据的抽样分布。

采样是不够的,取而代之的是分析您的 ML 数据

原文:https://towardsdatascience.com/sampling-isnt-enough-profile-your-ml-data-instead-6a28fcfb2bd4?source=collection_archive---------25-----------------------

人工智能和数据管道的生产测井方法

艾萨克·巴克斯和伯尼斯·赫尔曼

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

照片由 Unsplash 上的 Petri R 拍摄

现在是 2020 年,我们大多数人仍然不知道我们的模型在生产中何时、何地、为何或如何出错。虽然我们都知道“什么会出错,什么会出错”,或者“老鼠和[数据科学家]精心制定的计划经常出错”,但复杂的模型和数据管道往往被推向生产,而很少关注诊断不可避免的不可预见的故障。

在传统的软件中,日志记录和工具已经被作为标准的实践来创建透明性和理解复杂系统的健康状况。当涉及到人工智能应用时,日志记录通常是不完整的。在这篇文章中,我们概述了 ML 日志记录的不同方法,并对它们进行了比较和对比。最后,我们提供了一个名为 WhyLogs 的开源库,只需几行代码就可以实现数据记录和分析。

传统软件中的登录是什么?

日志是开发和操作健壮软件系统的重要工具。当您的生产系统进入错误状态时,使用工具来更好地定位和诊断问题的来源是非常重要的。

对于许多软件工程学科来说,堆栈跟踪有助于定位执行路径并确定程序在失败时的状态。但是,堆栈跟踪并不能提供故障发生前状态如何变化的信息。日志记录(及其相关术语,软件跟踪)是将程序执行和事件信息存储到一个或多个文件中的一种实践。日志对于诊断各种软件的问题至关重要;生产系统的必备。

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

图片由monkeyuser.com免费使用

数据记录有何不同?

统计应用程序,如数据科学和机器学习中的应用程序,是需要日志记录的主要候选对象。然而,由于这些应用程序的复杂性,可用的工具仍然有限,它们的采用远不如标准软件日志广泛。

统计应用通常是不确定的,并且需要许多状态变化。由于需要处理广泛分布的状态,必须避免严格的逻辑断言,并且机器学习软件通常永远不会到达错误状态,而是静静地产生差的或不正确的结果。这使得错误分析变得更加困难,因为维护人员在问题发生时不会被提醒。

当检测到错误状态时,诊断问题通常很费力。与显式定义的软件相比,数据集对于内省来说尤其不透明。软件完全由代码指定,开发人员可以轻松地包含精确的日志记录语句来查明问题,而数据集和数据管道则需要大量的分析来进行诊断。

虽然 ML 中有效的日志实践可能难以实现,但在许多情况下,它们甚至比标准软件更有必要。在典型的软件开发中,在部署到生产环境之前,大量的问题可能会被编译器、ide、类型检查、逻辑断言和标准测试所捕获。有了数据,事情就没那么简单了。这激发了在 ML 操作中改进工具和最佳实践的需求,以推进统计记录。

软件开发中对好的测井工具的一般要求同样适用于 ML 操作领域。这些要求可能包括(但当然不限于)以下内容。

记录要求

  1. 易于使用
    良好的日志记录有助于开发,因为它可以尽早地、经常地向开发人员公开内部功能。如果日志是笨重的,没有人会使用它。软件开发中常见的日志模块可以像打印语句一样简单易用。
  2. 轻量级
    日志记录不应该干扰程序执行,因此必须是轻量级的。
  3. 标准化便携
    现代系统庞大复杂,我们必须能够调试。日志需要多语言支持。输出格式应该是标准的,易于从多个来源进行搜索、过滤、消费和分析。
  4. 我们必须能够在不修改代码的情况下修改所有服务的详细程度、输出位置,甚至可能是格式。对于开发人员或数据科学家来说,详细程度和输出要求可能与生产服务非常不同。
  5. 接近代码
    日志记录调用应该存在于它们所引用的代码/服务中,日志记录应该让我们非常快速地查明服务中的问题发生在哪里。日志记录提供了一种生成系统内部逻辑功能跟踪的系统方法。

谈到 ML 日志记录,有哪些方法可用?

标准代码内日志记录

在数据科学中,标准日志模块可以而且应该做很多事情。我们可以记录数据访问、正在执行的步骤(培训、测试等)。还可以记录模型参数和超参数以及更多细节。专注于 ML 用例的服务和库(比如 CometML)可以扩展这种日志的效用。

虽然标准日志记录可以提供很大的可见性,但它很少甚至不提供对数据的内省。

优点

  • 灵活且可配置
  • 可以跟踪中间结果和低复杂度的数据
  • 允许重用现有的非 ML 测井工具

缺点

  • 高存储、I/O 和计算成本
  • 数据科学家可能不熟悉或不适合日志记录格式
  • 日志处理需要计算量很大的搜索,特别是对于复杂的 ML 数据
  • 由于昂贵的存储成本,数据保留率较低;对过去问题的根本原因分析不太有用

抽样

监控 ML 特有的大量数据的一种常见方法是记录数据的随机子集,无论是在训练、测试还是推理过程中。随机选择数据的某个子集并存储它以供以后参考,这可能是相当直接和有用的。基于采样的数据记录不能准确表示异常值和罕见事件。因此,诸如最小值、最大值和唯一值等重要指标无法准确测量。保留异常值和不常见值非常重要,因为它们通常会影响模型行为,导致模型预测出现问题,并且可能表明存在数据质量问题。

优点

  • 易于实施
  • 比其他日志解决方案需要更少的前期设计
  • 日志处理等同于对原始数据的分析
  • 数据科学家熟悉的数据输出格式

缺点

  • 高存储、I/O 和计算成本
  • 信号嘈杂,覆盖范围有限;小样本要求可扩展且轻便
  • 没有统计分析处理步骤是不可读或不可解释的
  • 抽样往往会遗漏罕见事件和异常值
  • 无法精确计算依赖于异常值的指标,如最小值/最大值和唯一值
  • 输出格式依赖于数据,这使得与监控、调试或自省工具集成更加困难

数据剖析

记录数据的一种有前途的方法是数据剖析(也称为数据草图或统计指纹)。这个想法是捕捉给定数据集的人类可解释的统计特征,以提供对数据的洞察。已经存在广泛的有效流算法来生成可扩展的、轻量级的数据集统计特征,并且文献非常活跃并且正在增长。然而,在实践中实现这些算法存在重大的工程挑战,特别是在 ML 日志记录的环境中。一个项目正在努力克服这些挑战。

优点

  • 易用性
  • 可扩展且轻量级
  • 通过基于文本的配置文件灵活配置
  • 准确表示罕见事件和离群值相关指标
  • 无需进一步处理即可直接解释的结果(如直方图、平均值、标准差、数据类型)

缺点

  • 没有现有的普遍解决方案
  • 解决方案背后涉及数学和工程问题

让数据记录变得简单而不妥协!介绍 WhyLogs。

数据分析解决方案 WhyLogs 是我们对 ML 的现代、简化数据记录的贡献。WhyLogs 是一个开源库,其目标是通过提供近似的数据分析和满足上述五个日志记录要求(简单、轻量级、可移植、可配置、接近代码)来弥补 ML 日志记录的不足。

估计的统计配置文件包括每个要素的分布近似值,这些近似值可以提供直方图和分位数、总体统计数据(如最小/最大/标准偏差)、唯一性估计值、空计数、频繁项目等。所有的统计数据都是可合并的,这使得算法变得非常并行,并且允许将多个数据集的数据合并在一起,以便以后进行分析。这对于实现灵活的粒度(因为您可以更改聚合级别,例如,从每小时更改为每天或每周)和登录分布式系统非常关键。

WhyLogs 还支持适用于生产环境的特性,如标记、小内存占用和轻量级输出…标记和分组功能是实现细分级别分析以及将细分映射到核心业务 KPI 的关键。

便携轻巧

目前,有 PythonJava 实现,提供 Python 与 pandas/numpy 的集成,以及与 Spark 的可扩展 Java 集成。生成的日志文件很小,并且跨语言兼容。我们在以下数据集上测试了 WhyLogs Java 的性能,以验证 WhyLogs 的内存占用和输出二进制文件的大小。

我们在每个数据集上运行我们的配置文件,并收集 JMX 指标:

易于使用、可配置且接近代码

WhyLogs 可以很容易地添加到现有的机器学习和数据科学代码中。Python 实现可以“pip”安装,除了具有可访问 API 的库之外,还提供交互式命令行体验。

WhyLogs jupyter 笔记本示例

更多示例

更多使用 WhyLogs 的例子,请查看 WhyLogs 入门笔记本

强大的附加功能

当与实时数据的监控和其他服务相结合时,可以看到 WhyLogs 的全部威力。要探索这些功能如何与 WhyLogs 配合,请查看 WhyLabs 平台的实时沙盒,该沙盒运行在 Lending Club 数据集的修改版本上,每天接收 WhyLogs 数据。

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

WhyLabs 平台截屏捕捉了模型运行状况仪表板和功能运行状况视图。作者图片

让我们让数据记录成为生产 ML 系统的黄金标准!

数据科学、机器学习以及围绕它们的技术正以极快的速度发展,这些操作的规模以及参与其中的人数也是如此。伴随这种快速增长而来的是不可避免的问题激增。最佳实践在 ML 中仍处于萌芽状态,但正如软件和系统工程的情况一样,最佳实践必须继续成长和发展。有效的日志记录肯定在操作健壮的 ML/AI 系统的最佳实践中扮演主要角色。需要 WhyLogs 等项目来应对这些统计系统的独特挑战。

点击这里查看 Python 和 Java 的 WhyLogs,点击这里,或者开始阅读文档。我们喜欢反馈和建议,所以请加入我们的 Slack 频道或发送电子邮件至 support@whylabs.ai

感谢我在 WhyLabs 的队友 Bernease Herman 合作撰写了这篇文章。关注 Bernease 上的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值