TowardsDataScience-博客中文翻译-2021-二十七-

龙哥盟 / 2024-10-21 / 原文

TowardsDataScience 博客中文翻译 2021(二十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

创建合成时间序列数据

原文:https://towardsdatascience.com/creating-synthetic-time-series-data-67223ff08e34?source=collection_archive---------10-----------------------

实践教程

使用 Python 创建高质量合成时序数据集的分步指南

TL;速度三角形定位法(dead reckoning)

在这篇文章中,我们将使用 Gretel.ai 的合成数据库创建时间序列数据集的合成版本,可视化并分析结果,并讨论合成时间序列数据的几个用例。

时间序列 Gretel.ai

背景

作为数据科学家,我们面临的最大瓶颈之一是没有足够的数据。像亚马逊这样的公司已经转向合成数据,以生成支持 Alexa 的新语言所需的大量训练数据,研究人员正在试验 gan,以生成用于医学研究的 T10 多样化合成图像 T11,像 Unity3D 这样的公司正在应用他们在游戏环境和 3D 资产方面的专业知识,帮助你训练能够 T12 更好地感知现实世界中的物体的模型 T13。

无论我们需要历史数据来测试我们的算法,还是需要更多的数据来建立更好地概括的 ML 模型,使用合成数据来增加有限的数据集正在以令人难以置信的速度增长。由于需要保持严格的排序,以及时间和测量值之间有时复杂的关系,对于创建真实的合成数据来说,一个特别具有挑战性的问题是时间序列数据。

让我们从时间序列数据的快速定义开始。时间序列数据可以被认为是一系列的测量值,或者是按时间顺序排列的观察值。

入门指南

点击这里在 GitHub 上查看下面的代码,或者点击这里在 Google 联合实验室中启动交互式笔记本。你会想要一个装有图形处理器的盒子来进行模型训练,或者拿一杯☕.要开始运行示例代码,从 Gretel 控制台获取一个 API 密钥(它是免费的)。

训练数据集

对于我们的训练数据集,我们将每小时创建一个时间序列模型。对于 Y 轴,我们需要一个复杂但易于理解的测量函数来测试我们的合成模型,并实现快速的可视化分析。为此,我们可以应用每年重复一次的正弦波函数。

很好,现在我们有了时间序列数据框架。提示:要尝试不同的时间间隔(例如每小时、每分钟),请尝试更改上面 Pandas 的date_range()函数中的freq。现在,让我们把时间序列形象化!

绘制时间序列训练集

提取趋势数据

接下来,我们为合成模型创建训练集。我们可以直接对时间序列数据进行训练,但我们只是训练模型记住给定时间的测量值。更直观的方法是根据趋势数据或测量值在一段时间间隔内的变化量来训练模型。然后,模型重新创建时间序列趋势数据,可以使用累积和将其恢复为原始格式。

训练模特

接下来,我们将使用gretel_syntheticstensorflow在我们的测试数据集上训练一个合成模型。为了确保生成的合成数据集与源数据集的时间窗口相匹配,我们将日期字段指定为一个种子值,可在生成时提供。

生成合成数据集

我们现在可以使用该模型生成任意数量的合成数据集。为了匹配原始数据集的时间范围,我们将使用 Gretel 的seed_fields函数,该函数允许您传递数据以用作每个生成行的前缀。下面的代码创建了 5 个新数据集,并从趋势数据中恢复累积和,以匹配原始数据集。

可视化结果

最后,让我们将我们创建的 5 个合成数据集与原始训练集进行对比,感受一下合成时间序列数据与源数据的对比。幸运的是,Pandas DataFrame 与 Plot.ly 的图形库的集成使这变得很容易!

合成时间序列数据集与原始训练集

正如我们可以看到的,合成模型在学习我们的源数据集中的 sin 函数和时态关系方面做得很好。为了使这个例子更进一步,尝试添加新的变量和正弦波进行合成,或者尝试改变神经网络配置参数,例如训练时期、学习速率和生成温度,以试验不同的结果。我们很想听听你的尝试,并在以后的帖子中关注更复杂的例子!

结论

在 Gretel.ai ,我们对使用合成数据创建 ML 和 ai 模型的可能性感到非常兴奋,这些模型在伦理上是公平的,并且能够更好地针对未知数据进行归纳。我们很乐意听到你的用例——欢迎在评论中联系我们进行更深入的讨论, twitter 或 hi@gretel.ai 。关注我们,用合成数据跟上最新趋势!

有兴趣在自己的数据集上进行训练吗? Gretel-synthetics 是免费开源的,你可以通过联合实验室在几秒钟内开始实验。

创建三元可视化

原文:https://towardsdatascience.com/creating-ternary-visualizations-9b4e5edfd0ff?source=collection_archive---------26-----------------------

使用三元来创建三元图

来源:作者

三元图最适合用来显示总和为常数的 3 个变量。它用于根据三个比率在等边三角形中的位置以图形方式显示它们。三元图基本上用于物理化学领域。

通常,如果我们试图在 2D 平面上绘制 3 个不同的变量,那么我们必须传递第三个变量,可能是颜色或大小,等等。但是三元图可以很容易地在 2D 平面上可视化 3 个不同的变量,其中所有 3 个变量都用它们的位置编码并形成一个三角形。

Python 三元是一个开源的 python 库,用于创建三元图。在本文中,我们将探讨三元图的一些特性以及如何将它们可视化。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装三元组开始。下面给出的命令可以做到这一点。

!pip install python-ternary

导入所需的库

在这一步中,我们将导入创建地块和可视化地块所需的库。

import ternary

创建一个空地块

我们将首先创建一个空的三元图来显示它的外观,并将向它添加标签。

scale = 30figure, tax = ternary.figure(scale=scale)tax.boundary(linewidth=1.5)tax.gridlines(color="red", multiple=6)tax.gridlines(color="yellow", multiple=2, linewidth=0.5)
fontsize = 12
offset = 0.14
tax.set_title("Empty Plot\n", fontsize=fontsize)
tax.left_axis_label("Variable 1", fontsize=fontsize, offset=offset)
tax.right_axis_label("Variable 2", fontsize=fontsize, offset=offset)
tax.bottom_axis_label("Variable 3", fontsize=fontsize, offset=offset)
tax.ticks(axis='lbr', linewidth=1, multiple=5, offset=0.02)
tax.set_background_color(color="whitesmoke", alpha=0.7) # the detault, essentially
# Remove default Matplotlib Axes
tax.clear_matplotlib_ticks()
tax.get_axes().axis('off')
ternary.plt.show()

来源:作者

用线条绘制

接下来,我们将把线整合到三元图中,以展示如何在三元图中绘制线。

scale = 40
figure, tax = ternary.figure(scale=scale)
tax.boundary(linewidth=2.0)tax.gridlines(color="blue", multiple=5)fontsize = 12offset = 0.14tax.set_title("Lines\n", fontsize=fontsize)tax.right_corner_label("X", fontsize=fontsize)tax.top_corner_label("Y", fontsize=fontsize)tax.left_corner_label("Z", fontsize=fontsize)tax.left_axis_label("Variable 1", fontsize=fontsize, offset=offset)tax.right_axis_label("Variable 2", fontsize=fontsize, offset=offset)tax.bottom_axis_label("Variable 3", fontsize=fontsize, offset=offset)
tax.horizontal_line(16)
tax.left_parallel_line(10, linewidth=2., color='red', linestyle="--")
tax.right_parallel_line(20, linewidth=3., color='black')
p1 = (22, 8, 10)
p2 = (2, 22, 16)tax.line(p1, p2, linewidth=3., marker='s', color='green', linestyle=":")
tax.ticks(axis='lbr', multiple=5, linewidth=1, offset=0.025)tax.get_axes().axis('off')
tax.clear_matplotlib_ticks()
tax.show()

来源:作者

散点图

接下来,让我们看看如何在三元图中创建散点图。这将帮助我们找出 2D 平面上两个变量之间的关系。

def random_points(num_points=25, scale=40):
points = []for i in range(num_points):
x = random.randint(1, scale)
y = random.randint(0, scale - x)
z = scale - x - y
points.append((x,y,z))
return pointsscale = 40
figure, tax = ternary.figure(scale=scale)
figure.set_size_inches(5, 5)points = random_points(30, scale=scale)
tax.scatter(points, marker='s', color='yellow', label="Yellow S")
points = random_points(30, scale=scale)
tax.scatter(points, marker='D', color='blue', label="Blue D")
tax.legend()
tax.set_title("Scatter Plot", fontsize=20)
tax.boundary(linewidth=2.0)
tax.gridlines(multiple=5, color="blue")
tax.ticks(axis='lbr', linewidth=1, multiple=5)
tax.clear_matplotlib_ticks()
tax.get_axes().axis('off')
tax.show()

来源:作者

在这里,您可以看到我们如何在三元图中可视化不同类型的图,以在 2D 空间中可视化 3 个不同的变量。

继续尝试不同的数据,并使用三元组创建不同的可视化效果。如果您发现任何困难,请在回复部分告诉我。

本文是与 Piyush Ingale 合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时联系我在 hmix13@gmail.com 或我的 LinkedIn 简介 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

创建 CitySpire 应用

原文:https://towardsdatascience.com/creating-the-cityspire-app-my-journey-ff31fc9990ce?source=collection_archive---------24-----------------------

我的旅程

Jukan Tateisi 在 Unsplash 上拍摄的照片

关于项目

在过去的八周里,我是一个由前端和后端以及数据科学组成的跨职能团队的一员,来构建一个名为 CitySpire 的应用程序。这是我们在 Lambda 进行的所有培训的高潮,将我们所学的知识整合在一起,这样我们就可以从头开始设计、构建和部署应用程序。

我们的主要目标是创建一个应用程序,分析来自城市的数据,如人口、天气、租赁率、犯罪率、公园(步行得分)、医院评级、学校评级以及许多其他社会和经济因素,这些因素对于决定人们喜欢住在哪里很重要。

我们必须紧密合作,计划出我们想要实现的功能,我们可以在特定期限内完成的版本,我们将使用的技术堆栈,以及哪些信息对用户来说是重要的。

规划阶段

第一天,我会见了将与我一起工作的开发人员和数据科学家团队。我起初很犹豫,让别人互相交谈,而我只是观察。但几分钟后,我加入了进来,讨论了几个用户故事,以及它们对我们各自团队的意义。例如,我所做的用户故事是“作为一个用户,我想查看给定城市/邮政编码的平均租金/房价”。现在,从数据科学家的角度来看,用户故事可以归结为——在给定的邮政编码/县,未来几个月的房屋租赁价格是多少?

作为一个团队,我们还决定租赁价格也将作为一个单独的端点,即用户可以点击这个端点,并可以获得有关其所需位置的租赁价格的信息。

确保每个人都专注于跨团队目标并了解其他人在做什么以及会议之间事情进展情况的一个好方法是利用项目管理应用程序的帮助。因此,下一步就是每天使用 Trello 与我们的团队交流。我会为我们想要实现的每个功能创建一个 Trello 卡,并附上一个用户故事作为标题,解释我们旨在实现的体验。我会将这些卡片按照数据科学部门的团队(前台、后台)进行分类。这使得更新我们当前正在做的事情、我们的状态以及团队正在做的其他事情变得更加容易。我们会每天站起来向团队更新我们在每个特性上取得的进展,以及我们可能遇到的障碍。

我们的特雷罗卡(图片由作者提供)

完成故事/特写的下一步是将它分解成更小的任务。上述用户故事可以分解为以下任务-

  • 决定数据的类型。
  • 决定数据的来源。
  • 收集数据。
  • 数据角力。
  • 使用各种数据可视化技术探索数据。
  • 根据用户需求创建模型。
  • 创建最适合该数据类型的数据库。例如,这是一个关系数据库,所以我决定使用 AWS RDS Postgres 数据库。
  • 与前端和后端的 web 开发人员合作,决定如何向我提供用户输入,以及如何将我的模型预测交付给他们。此讨论包括决定数据格式、数据库选择和创建端点。

数据

使用了五个不同的数据集来构建机器学习模型。首先我用了 Zillow 租金指数的历史值。其余的数据是从数据世界获得的。

作者对数据图像的基本统计描述

数据预处理

与许多其他公开可用的数据集和许多私人获得的数据集类似,这个特定项目中使用的数据集包含大量缺失值。

第一步是将数据集分解成更小的数据集,每个数据集只包含一年的值。接下来,在每个新创建的数据集中,包含三个月以上缺失值的邮政编码被删除。在清理了丢失的数据后,我将每年的数据重新组合成一个庞大的数据集。

估算缺失值并删除 3318 行(作者图片)

数据准备预处理的下一步是归一化。执行规范化有几个原因。首先,确保解释变量和目标变量之间关系的线性。第二,保证数据分布的正态性。最后,尝试减少异常值对分布的影响。

数据预处理过程的下一步是移除一些明显的异常值,这些异常值会显著改变分布、要素和目标之间的关系,从而降低模型效率。

数据准备过程的最后一步是构建数据,这种方式将允许捕获因变量和自变量之间关系的大多数方面。为了进行分析,所有数据集都进行了转换,以包含每个指标的年平均值。出现这种情况的主要原因是所使用的大多数数据集中缺少月水平的数据。

机器学习

数据集被分成训练数据集和测试数据集。我建立了一个线性回归模型。我使用了两个主要的模型性能指标——决定系数(R 平方)和均方根误差(RMSE)。第一个帮助我观察我的模型在多大程度上描述了 Zillow 租金指数和变量之间的关系,第二个帮助我评估了模型在多大程度上接近实际租金值(以绝对美元计算)。

API 和端点

下一步是构建 API,包括创建和连接路由(端点)、函数和使用文档。

我使用 FastAPI 创建 API,AWS Elastic Beanstalk 用于托管 API。

租金预测 API 端点—从提取文档字符串。py 文件。显示成功响应和错误消息(图片由作者提供)

使用的包/技术

  • 计算机编程语言
  • 结构化查询语言
  • Scikit
  • 美丽的声音
  • 关系数据库服务。
  • AWS 弹性豆茎:平台即服务,托管您的 API。
  • Docker:容器,用于可再生环境
  • FastAPI: Web 框架。像 Flask,但是更快,有自动交互文档。
  • Plotly:可视化库,用于 Python。
  • Pytest:测试框架,运行你的单元测试。

对于源代码托管,我使用 GitHub。Github 提供版本控制和流畅协作。我在 GitHub 中使用了分支技术来保持更好的版本控制。我为这个特性创建了一个新的分支。在将代码推送到分支时,我还添加了一个清晰而详细的提交消息来标识我的更改。然后,我创建了一个 pull 请求,通知我的团队成员我已经完成了一个特性,并请求他们允许我将更改添加到主文件中。

我面临的挑战

在整个项目中,障碍给我带来了挑战,我需要去克服。我学习了新的技术,但是在学习过程中遇到了一些障碍。

  1. 对于我的主要功能,Zillow price 估计问题在于收集数据,然后理解数据。有几个 CSV 文件。并且没有关于各种 CSV 文件以及它们如何相互关联的细节。
  2. 启动应用程序-最初,由于版本不匹配的问题,我无法在本地启动应用程序。Windows 10 不再支持 uvloop。所以我必须从 pipfile 中删除 psycopg2-binary 和 gunicorn ,删除 piplock,然后手动将 psycopg2-binary 和 gunicorn 安装回 pipfile。
  3. 我写了代码,帮助我的团队对网站进行网络搜集,并收集所需的数据。然而,我不得不创建几个笔记本,因为网站确实阻止了 2 个城市后的进一步刮擦。
  4. 最后,我面临的最大挑战是在 AWS Beanstalk 中托管 API。出于某种原因,我得到了一个 502 网关错误。错误日志也无助于解决问题。因此,必须切换到 EC2 路由来托管 API。

未来

这一应用仍处于早期阶段。仍然有许多我们想要添加的功能,需要研究的缺陷,以及需要改进的功能。这只是开始。这是我的日记,记录了我的旅程和我到目前为止所做的贡献。还有很多事情要做。

我从这个应用程序中学到了很多。我每天都面临挑战,从学习 Flask API、Pydantic、AWS RDS PostgreSQL、AWS Beanstalk 等新事物,到优化代码以提高效率,再到与团队协作。作为一名数据科学家,在这样的项目中工作的最好的事情之一就是与不同的人一起工作,并结识新的人。

那么,这个项目对我的职业目标有什么帮助?这个项目激励我学习新的东西。计划和执行并满足交付特性的截止日期的能力。克服障碍并完成我的任务。在前进的道路上,我将继续鞭策自己,学习,成长,迎接新的挑战,并战胜它们。我期待着未来,因为我的旅程才刚刚开始。

用 Tableau 创建可视化变得简单

原文:https://towardsdatascience.com/creating-visualizations-with-tableau-made-simple-ed86401e63b0?source=collection_archive---------31-----------------------

从安装软件到交付仪表板

图片由 Freepik 上的 pressfoto 提供

“梦想远大。从小处着手。现在就行动。”—罗宾·夏尔马

这是我生活的主要原则之一。这不仅是为了你想要实现的人生目标,也是为了你想要实现的学习目标。

我们中的许多人将任何技术或工具视为障碍,并拖延我们的学习过程,认为我们太忙了,无法在这个时候开始一些重大的事情。

但是我想打断一下,告诉你,开始用 Tableau 创建很酷的可视化并不难。我将通过一个简单的例子来说明它。

把它作为对自己的挑战,和我一起创建你的第一个 Tableau 仪表板,开始你的 Tableau 学习。你准备好了吗?

什么是 Tableau?

在我们开始动手之前,让我们先来看看什么是 Tableau。

Tableau 是一款出色而强大的数据可视化和商业智能工具,用于分析和报告海量数据。

数据科学家和机器学习工程师主要依靠 Matplotlib、Seaborn 和 Plotly 进行可视化。但相反,使用 Tableau 进行可视化分析会给人更专业的感觉,并且很容易呈现给利益相关者。

安装桌面

Tableau 的安装非常简单。前往 Tableau 官方网站并将鼠标悬停在菜单栏中的“产品”上。

你可以选择 Tableau 桌面或者 Tableau 公共。Tableau Desktop 是 14 天免费试用的付费版本,而 Tableau Public 是免费的。

Tableau Public 可以免费使用,但不能保存您在本地创建的工作簿。它们可以保存到 Tableau 的公共云中,任何人都可以访问和查看。

决定您喜欢的产品,根据您的操作系统选择可执行文件,然后单击下载。

下载完可执行文件后,运行它并安装 Tableau。这就是你,准备好进入下一个阶段。

连接到数据源

数据是任何可视化的关键。Tableau 支持连接广泛的数据源。

tabulea 全面列出了所有支持的连接器。很少有数据源包括您机器上的文件,如 Microsoft Excel、文本文件、JSON 文件、pdf 等。、或诸如 MySQL、微软 SQL Server 或 Oracle 等服务器。Tableau 还支持云服务提供商连接到云资源; AWS 、 Azure ,以及谷歌云平台。

为简单起见,我们将使用 Microsoft Excel 文件开始我们的学习之旅。

我挑选的是美国超市数据集,由一个电子商务平台从 2014 年到 2018 年的交易列表组成,可在 Kaggle 上获得。来吧,下载数据(你所需要的只是一个免费的 Kaggle 帐户)然后开始和我一起动手吧。

打开上一步安装的 Tableau 软件。您将看到一个类似于下面截图中的屏幕。

作者截图

在左侧窗格中的连接下,您可以看到所有类型的文件和服务器,您可以从中导入数据。我们将要使用的数据源是一个 Microsoft Excel 文件。因此,在连接下,点击 Microsoft Excel 并选择您刚刚下载的文件。

一旦你加载了数据,你会看到一个类似下面的屏幕截图。在连接下,您将能够看到您刚刚创建的连接。

在主视图中,您可以看到刚刚导入的数据。

作者截图

要开始开发你的可视化,点击 Sheet1 ,这将打开你的工作表进行开发。

Tableau 中的尺寸和度量

您的工作表已准备好创建可视化效果。但在此之前,我们先来看看左边的数据窗格。它显示加载的数据中的所有变量。

根据 Tableau ,加载的数据自动分为维度和度量。分类变量用颜色编码。如果你仔细看的话,你可以看到蓝色的尺寸和绿色的尺寸。这种分离由 Tableau 自动执行,以增强用户体验。

在自动分类之后,作为维度得到的所有变量大多是分类变量,作为度量得到的变量是数值变量。可以聚集或操纵该度量。为了更好地理解这一点,请看一下我们使用的数据集上的分离。

作者截图

了解了尺寸和测量后,让我们继续学习重要的阶段。你和我在一起吗?

创建可视化

清楚地了解了数据源、维度和度量之后,让我们进入创建可视化。

我们将创建可视化来回答下面的两个问题。

  1. 美国各州的销售额有什么不同?
  2. 哪个产品类别产生高利润?

为了更好地理解如何解决可视化问题,一个简单的5 步指南可以帮助你掌握数据可视化。

1.美国不同州之间的销售额不同

为了可视化销售随州的变化,我们需要根据需要选择列和行。您必须从数据窗格拖放到顶部的架子上。

  • 国家维度拖放到列中。
  • 状态维度拖放到列中。
  • 销售指标拖放到行中。

注意:由于数据集中的所有数据都将美国作为 Country 字段的值,所以列中不需要 Country 维度。但是一般来说,如果数据包含一个以上的国家,您将需要它。

作者截图

一旦执行了上述步骤,就可以创建条形图了。

更新标题以描述您刚刚创建的可视化。

作者截图

万岁!你已经开发了你的第一个可视化。保持精神,进入下一个我们即将回答的问题。

2.哪个产品类别产生高利润?

为了确定哪个产品类别为超市产生更高的利润,我们将需要利润与子类别的可视化。

为了生成这个图表,

  1. 子类别维度拖放到列中。
  2. 利润指标拖放到行中。

作者截图

当您执行上述步骤时,将会生成下面的图表。记得用合适的描述更新标题。

作者截图

使用可视化效果,您可以清楚地看到复印机子类别的超市利润最高。

创建仪表板

你已经走了很长的路。距离完成 Tableau 学习游戏的第一关只有一步之遥!

您已经创建了许多图表(在我们的例子中是两个),并希望将它们展示给利益相关者。你如何以一种更像样的方式展示你所做的所有分析?

Tableau 仪表盘是为救援准备的。

Tableau 仪表板是展示来自许多工作表的图表集合的好方法。生成的图表的集合视图使得交流对数据集的分析变得更加容易。

要创建仪表板,点击左下角的新建仪表板选项卡。

作者截图

在左侧的仪表板窗格中,在工作表下,您将看到您已经创建的所有工作表的可视化效果。

作者截图

注意:您可以通过右键单击工作表标签来重命名工作表。如果您没有重命名这些工作表,您将看到它们是 Sheet1、Sheet2 等等。

要创建仪表板,

  1. 将 sales (Sheet1)表拖放到视图中
  2. 拖放“子类别(Sheet2)”表进行查看,使其位于“销售”可视化效果的下方。
  3. 更新标题以描述仪表板。(如果您尚未看到标题,请跟随仪表板菜单>选择显示标题)。

作者截图

就是这样!您已经创建了您的第一个仪表板!

最后的想法

恭喜你!您已经完成了 Tableau 学习游戏的第一关。

请记住:

  1. 现在是开始你任何学习愿望的最佳时机。
  2. 学习新东西并不难。你必须一次迈出一小步。
  3. 与你的努力保持一致,你就在通往成功的路上。

非常感谢你读到这里。我希望你喜欢阅读,你不仅已经开始了你的 Tableau 学习之旅,而且也有动力开始你的任何学习愿望。我希望听到您对我如何改进的反馈。期待看到您的成功案例!

创建您的第一个数据科学项目—数据科学家视角

原文:https://towardsdatascience.com/creating-your-first-data-science-project-data-scientist-perspective-8974c3d2c667?source=collection_archive---------26-----------------------

您应该在数据科学项目中包含什么

照片由 XPS 在 Unsplash 上拍摄

申请数据科学职位并不容易,因为准备工作非常复杂;从学习编程、了解如何分析数据、阅读统计书籍,到创建数据科学项目组合,有太多的事情要做。

问题是你仍然需要从其他申请者中脱颖而出。许多人会有相似的技能组合——编程、基本统计、仪表板等。这就是为什么使您的应用程序与众不同的唯一方法是构建一个突出的数据科学项目。

在本文中,我想从数据科学家的角度概述一下你的第一个数据科学项目应该包括哪些内容。让我们开始吧。

数据科学项目定义

在我们讨论您的数据科学项目应该包括什么之前,让我们定义一下“数据科学项目”的含义当我们谈论数据科学项目时,它不局限于机器学习或算法方面,而是扩展到任何使用数据来解决业务问题的解决方案。

因此,数据科学项目是通过使用各种工具并基于历史数据开发的解决方案,以解决特定的业务问题,理想情况下是解决或消除公司存在的问题。

为什么我从本文开始就定义了数据科学项目?从我的个人经验来看,该领域的许多新申请者展示的数据科学项目只是展示了技术方面,而没有试图解决实际问题。申请人深入了解机器学习是非常好的,但永远不要忘记你的数据科学项目是为了什么——它是为了解决业务问题。

现在我们已经得到了数据科学项目的定义,让我们看看项目应该有什么—特别是对于您创建的第一个项目。

1.解决一个真正的商业问题

首先,数据科学项目的基本方面是解决实际的业务问题。不管你的模型度量有多好,或者你开发的仪表板有多漂亮。如果项目没有展示解决实际业务问题的任何可能性,它可能不会显示您在数据科学家职位上的表现。

当我谈到真正的商业问题时,它不是什么新奇的东西,也不是有史以来最复杂的问题。它可以从简单开始,例如:

  • 购买新产品的倾向
  • 客户流失预测
  • 欺诈检测

还有很多。关键是,上述业务问题是现实的,并且经常出现在每个公司。你可能认为很明显你应该展示一个真实的项目。然而,你会惊讶于有多少人,包括一个荒谬的项目。

另一个问题是,如果每个人都有同样的想法,你怎么能从所有的应聘者中脱颖而出呢?为了脱颖而出,试着通过回答以下问题来想象你梦想中的公司:

  1. 你想在哪里工作?
  2. 你想从事什么行业?
  3. 你想解决行业和公司的什么业务问题?
  4. 你将如何向管理层提出解决方案?

为什么我让你想象梦想公司?因为要从其他人中脱颖而出,最好的方法是有一个数据科学项目,解决你想申请的公司中存在的业务问题。

如果你申请保险公司的数据科学家职位,如果项目是关于再保险预测,公司可能会注意到你。然而,再保险项目可能不适合拥有图像检测产品的公司。通过想象你梦想中的公司,你会为你的第一个数据科学项目找到方向。

简而言之,尝试开发您的数据科学项目,该项目可解决业务问题,并针对您想象中的公司

2.清晰和结构化的项目

从数据科学家的角度来看,结果并不代表一切。你可能有一个 99%准确的模型,但是你实现这个模型的过程是什么?这是数据科学家想知道的。数据科学家知道,由于不良标记、信息泄露和许多其他原因,指标可能会产生误导。这就是为什么我们想看看你如何拿出解决方案。

有一个结构化的清晰的项目意味着你的项目有一个你想要解决的清晰的业务问题,并且展示了结构化的过程。此外,开发项目的每一步都需要一个原因,例如,为什么选择这个数据源?你为什么使用这些功能?你为什么放弃这些数据?你为什么选择这种模式?等等。底线是你需要证明你项目中的每一步。

如果你很难思考你的数据科学项目结构,那么我的另一篇文章可以帮助你。使用 CRISP-DM 方法,您可以定义项目的结构,并有更好的方式来展示项目。

[## CRISP-DM 方法用于您的第一个数据科学项目

towardsdatascience.com](/crisp-dm-methodology-for-your-first-data-science-project-769f35e0346c)

3.展现创造力

一开始,您的数据科学项目需要解决实际的业务问题,并具有清晰的结构。然而,这并不意味着你不能在这个过程中发挥创造力。毕竟,过程中的创造性是让你的数据科学项目脱颖而出的一种方式。

创造力可能是与生俱来的,需要大量的学习,但也可能来自试错实验。你可能会问一个问题,对你的数据科学项目来说,创造性意味着什么?嗯,这可能意味着很多事情。例如:

  1. 业务问题方法-业务需要机器学习模型来解决,还是您设法找到了另一种方法?
  2. 数据清理—如何清理数据,如何填充缺失的数据?
  3. 特征工程-您是否可以从其他特征中创建任何特征?
  4. 功能选择—如何选择要使用的功能?
  5. 模型实现——你决定开发什么模型?
  6. 可访问性——如何让每个人都能访问模型和模型结果?

这些是你可以发挥创造力的例子;以上所有问题的答案总是取决于你的创造力和经验。一开始可能会很难,尤其是对于您的第一个数据科学项目,但随着时间的推移,它会变得更容易。

如果你仍然对变得更有创造力感到困惑,我建议尝试阅读许多文章和人们开发的数据科学项目。你可能会从别人那里找到灵感,并根据自己的需要进行调整。

结论

开发你的第一个数据科学项目以从其他申请者中脱颖而出是一件困难的事情。这就是为什么在本文中,我从数据科学家的角度概述了您应该在项目中包括的一些方面。它们是:

  1. 解决一个真正的商业问题
  2. 清晰和结构化的项目
  3. 展现创造力

此外,当我们谈论数据科学项目时,它被定义为使用各种工具并基于历史数据来解决特定业务问题的解决方案。

希望有帮助!

如果你喜欢我的内容,并想获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的 简讯。

如果您没有订阅为中等会员,请考虑通过 我的推荐 订阅。

访问我的LinkedInTwitter

为数据可视化创建自己的调色板——第 1 部分

原文:https://towardsdatascience.com/creating-your-own-color-palette-for-data-visualization-part-1-84df48954845?source=collection_archive---------23-----------------------

为数据可视化创建个人调色板的全面颜色指南

斯蒂夫·约翰森在 Unsplash 上拍照

您在为数据可视化选择正确的颜色组合时是否面临困难?你还在使用大多数程序员使用的调色板吗?如果你想脱颖而出,那么这篇文章就是为你准备的。

你有没有想过,设计师、画家、电影摄影师和摄影师是如何选择完美的色彩组合的?他们描绘的完美形象是通过理解他们希望观众感知到的东西而精心策划的。颜色和视觉的完美融合提供了一种引人入胜的视觉效果,不仅能舒缓眼睛,而且具有美感。上述职业使用的诀窍是,他们知道如何使用色轮来实现颜色的完美混合。最早制造色轮的不是别人,正是伊萨克·牛顿爵士。伊萨克·牛顿爵士在各个领域都做出了贡献,但是让我们把注意力集中在当前的色轮话题上。

色轮

有两种类型的色轮,一种是数字的,另一种是由画家使用的颜料组成的。这两种色轮的主要区别在于原色成分的不同。数字色轮由 RGB(红-绿-蓝)组成,对于颜料,它是 RYB(红-黄-蓝)。混合两种原色产生二次色,原色和二次色的结合产生三次色。

颜色理论

色彩理论指导选择视觉效果的色彩组合,或创造一个充满活力、对比鲜明或和谐的色彩组合。这在自然界也很明显,如果一个人看到彩虹,从红色到蓝色的颜色过渡是和谐的,对眼睛来说是放松的。而色轮就是根据这个原理做出来的。

照片由Zoltan·塔斯在 Unsplash 上拍摄

了解颜色组合

有很多方法可以为你的调色板选择颜色。这种选择取决于一旦使用这些颜色,人们想要感知什么。你是在寻找色彩和谐还是对比鲜明的图像?如果还没有决定,那么试着使用不同的配色方案,如下所述。

色轮(图片由作者提供)

出于演示的目的,我将使用 R 数据存储库中的 mtcars 数据集。

关于 ggplot2 包首先要知道的是,它们有自己的调色板。ggplot2 包为其最终用户提供的一个有趣特性是通过 scale_color_manual() 函数创建自己的调色板的灵活性。

让我们了解不同的颜色组合方案,并尝试将它们可视化。

互补色用于创建高对比度和有冲击力的图像,因为这些颜色位于色轮的相对两端(色轮的左上角图像)。

这里的曲线显示了自动或手动变速器汽车的总马力和汽车重量之间的关系。

# implementing complementary colors(plot1 <- cars %>%
    ggplot(aes(wt,hp)) +
    geom_point(aes(color = factor(am)), size = 4) + 
    scale_color_manual(values = c("#d12e9f","#2ed160")) +
    theme_classic() +
    xlab("Weight (1000 lbs)") +
    ylab("Gross horsepower") +
    theme(panel.border = element_rect(colour = "black", fill=NA)))

作者图片

三色组合是从色轮中选择的 3 种等间距颜色,可创建鲜明的高对比度图像(色轮的右上角图像)。

箱形图有助于理解,随着气缸数量的增加,汽车的里程数减少。

# implementing triadic color scheme
(plot3 <- cars %>%
  ggplot(aes(mpg,cyl)) +
  geom_boxplot(aes(fill = factor(cyl))) + 
  scale_color_manual(values = c("#EB14D7","#D7EB14", "#14D7EB"), 
                     aesthetics = c("colour", "fill")) +
  theme_classic() +
  xlab("Miles/(US) gallon") +
  ylab("# of cylinders") +
  theme(panel.border = element_rect(colour = "black", fill=NA)))

作者图片

四色颜色组合,顾名思义就是选择四种颜色,在色轮中形成矩形或正方形的四个角。这创建了主色和强调色的调色板。强调色使其更加醒目,并强调对比度(色轮的左下角图像)。这种配色方案基本上是两组互补色,因为矩形/正方形的对角是互补的。

类似的配色方案类似于四色组合。但是这里我们沿着色轮的圆周选择颜色。从主色开始,向强调色发展(色轮的右下角图像)。

单色配色方案,顾名思义就是从较深到较浅的阴影创建颜色渐变。这是通过从圆周向色轮的中心径向向内行进来实现的。这种风格在视觉上很舒服,因为配色方案很和谐(色轮的右下角图像)。

直方图比较了数据集中所有奔驰车型的里程。

#implementing monochromatic color scheme# defining the color gradient
col_grad <- c("#6F4995","#8F69B6","#A789C5","#BCA5D3","#CDBBDE",
              "#DDD1E9","#EAE3F2")# filtering Merc models to compare the mpg(plot5 <- cars %>% filter(str_detect(cars, "^Me")) %>%
  ggplot(aes(fct_reorder(cars, mpg, .desc = TRUE), mpg, col = cars)) +
  geom_bar(stat = "identity", aes(fill = cars)) + 
  scale_color_manual(values = col_grad, 
                     aesthetics = c("colour", "fill")) +
  theme_classic() +
  xlab("Merc models") +
  ylab("Miles/(US) gallon") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), 
        panel.border = element_rect(colour = "black", fill=NA)))

作者图片

如果你是一个 R 用户,想探索 ggplot2 的新特性,那么看看这个:

结论

因此,我们看到,通过正确地遵循色轮的属性并选择正确的方案,我们可以轻松地开发自己的调色板。这个过程需要大量的时间来为您的可视化选择正确的颜色集,因为除了数据和故事流本身之外,它还构成了数据故事的一个不可或缺的部分。

如果你是一个喜欢自己探索并尝试想出自己独特风格的人,这是为你的视觉化选择颜色的正确方向。如果你不是这种类型的人,那么不要担心,有很多灵感值得探索,以提高你的可视化颜色选择到一个全新的水平。以下是我的五大灵感链接:

  1. https://color.adobe.com/create/color-wheel
  2. 【https://www.canva.com/ 号
  3. 【https://coolors.co/
  4. https://colorhunt.co/
  5. https://www.design-seeds.com/by-color/

请继续关注我的下一篇文章,通过学习创建你自己的阴影、色调、色调、饱和度和亮度来增强你的配色方案。

链接到代码。

你可以在 LinkedIn 上和我联系。

为数据可视化创建自己的调色板:第 2 部分

原文:https://towardsdatascience.com/creating-your-own-color-palette-for-data-visualization-part-2-7b02ebc31c19?source=collection_archive---------24-----------------------

平衡色调、色调和饱和度,以生成完美的颜色渐变。

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片

在博客的第一部分,我们集中讨论了色彩理论和色轮,讨论了选择补色、三色、四色、相似色和单色的不同方法。颜色的选择极大地改变了视觉感受,从对比强烈到对我们的眼睛产生舒缓的效果。这些组合纯粹是通过从色轮中选择不同的颜色来完成的。

在这里,我们讨论如何通过将颜色与黑色、白色或灰色混合来创建新的颜色组合。通过改变黑色、白色和灰色的强度,可以产生美丽的颜色渐变。下一节将介绍基本的定义和数学基础,但不会更深入。

第 1 部分的链接,以防您错过。

现在,我们将通过了解色调、阴影、饱和度、色调、淡色和亮度的影响,重点关注增强视觉效果的替代方法。

"纯粹的颜色,未受意义的污染,不与确定的形式结合,能以一千种不同的方式与灵魂对话"。~奥斯卡·王尔德

黑色、白色和灰色的阴影

RGB 值指定为(红、绿、蓝),每种颜色的强度在(0,255)之间变化。因此,对于红色,RGB 值为(255,0,0),对于绿色,为(0,255,0),对于蓝色,为(0,0,255)。有时,强度值被定义在(0,1)的范围内。转换只是将 RGB 值除以 255。因此,对于红色、绿色和蓝色,( 0,1)标度中的 RGB 值将为:

Red color  |(255,0,0) is equivalent to (1,0,0)
Green color|(0,255,0) is equivalent to (0,1,0)
Blue color |(0,0,255) is equivalent to (0,0,1)

RGB 颜色组合可以进一步调整为:

颜色的 阴影 可以通过与黑色混合生成。黑色在 RGB 格式中是(0,0,0)。

颜色的 淡色 的生成方式与阴影类似,只是将颜色与白色混合。白色在 RGB 格式中是(1,1,1)。

另一方面,色调 通过将颜色与灰色混合而生成。在 RGB 格式中,灰色是(0.5,0.5,0.5)。

如果将 RGB 颜色格式转换为圆柱坐标系,则产生 HSL 系统。HSL 代表色调、饱和度和亮度。

作者图片

色相(H)代表在可见光光谱中具有主导能量的颜色的角度。角度在(0°、360°之间变化,就颜色而言,它从红色开始,然后转变为黄色、绿色、青色、蓝色、品红色,再回到红色。

现在让我们看看将 RGB 值转换为 HSL 颜色系统背后的数学原理。有 3 个变量 R、G 和 B,因此有 6 种可能的方式来排列 RGB,而不会重复任何颜色两次或三次。可能的结果以及与它们相关的转换为 HSL 的公式:

***a) R>G>B then H = 60**°** * [(G-B)/(R-B)]
b) R>B>G then H = 60**°** * [6-(B-G)/(R-G)]
c) G>B>R then H = 60**°** * [2+(B-R)/(G-R)]
d) G>R>B then H = 60**°** * [2-(R-B)/(G-B)]
e) B>R>G then H = 60**°** * [4+(R-G)/(B-G)]
f) B>G>R then H = 60**°** * [4-(G-R)/(B-R)]***

颜色的饱和度倾向于告诉它的亮度。它是在(0,1)的范围内测量的。0 值表示没有颜色,1 表示颜色处于最大亮度。为了计算饱和度值,需要 RGB 的最大值和最小值。这意味着最大/最小值是通过比较 R、G 和 b 的值来计算的。**

****S = [(max(RGB)-min(RGB))/255]/(1-(2L-1)) if L<1
S = 0 if L =1**** 

【L】另一方面,亮度在(0,1)的范围内定义颜色的强度、光度或亮度,其中 1 代表亮区域,0 代表暗区域或纯色。

****L = (max(RGB)+min(RGB))/(2*255)****

另一方面, 色度(C)是最纯净的颜色,没有任何白色、黑色或灰色的混合。它也在(0,1)的标度之间测量。**

现在我们已经有了所有我们需要知道的关于颜色的定义,让我们将所有这些知识用于构建我们的代码。

将 RGB 转换为 HSL

有两种方法可以将 RGB 转换成 HSL。第一种方法是使用上一节中定义的公式。第二条也是更短的路线是使用 r 的 plotwidgets 包 中的rgb2hsl()函数,我将提供第一种方法的代码,第二种方法留给读者去探索。

作者代码

通过选择特定的颜色,饱和度和亮度可以改变,如下图所示。

作者图片

我们知道如何将 RGB 转换为 HSL,让我们为 HSL 参数绘制并生成一个色轮。

作者代码

作者图片

对于绘制 HCL,其中 C 是色度,可以使用hcl()函数代替上面代码中的hsv()

将 HSL 转换为 RGB

对于这一部分,我们将忽略将 HSL 转换为 RGB 的数学运算,可以直接使用 r 的plot widgets 中的hsl2rgb()函数。hsl2rgb()函数的输入参数是一个 3 行的矩阵。3 行代表 HSL 值,其中 H 在(0 ,360 )之间变化。并且结果输出也是标识为 RGB 的 3 行矩阵。**

下面是一些使用 ggplot2 包在 R 中高效绘图的技巧。

**** ****

结论

因此,我们成功地证明了通过控制黑色、白色或灰色的数量,新的颜色组合可以通过与纯色混合而产生。这些组合是单一颜色的颜色渐变。此外,了解亮度、饱和度、色彩和色调的差异为我们提供了以正确的比例混合黑色、白色和灰色以创建颜色渐变的灵活性。

参考文献

  1. https://www.xspdf.com/resolution/54613930.html
  2. https://donatbalipapp.medium.com/colours-maths-90346fb5abda
  3. https://stack overflow . com/questions/6615002/given-an-RGB-value-how-do-I-create-a-tint-or-shade/6615053
  4. https://www.december.com/html/spec/colorcodes.html

完整代码的链接在这里是。

您可以在 LinkedIn 和 Twitter 上与我联系,跟随我的数据科学和数据可视化之旅。

与人工智能的创造性协作

原文:https://towardsdatascience.com/creative-collaboration-with-ai-27350232cdc4?source=collection_archive---------15-----------------------

“Nyeshkerh”:style gan 2、JukeBox、一阶运动模型等。

仍然来自:Nyeshkerh /作者

一个人工智能 c̶a̶n̶ ̶b̶e̶ 有创造力的。我们已经在 2020 年看到了它的能力。使用各种 ML 模型和方法,您可以(例如):

  • 制作音乐
  • 制作播客
  • 创作电影

以 ML/DL 为动力的生成力的模型、解决方案、应用越来越多。它允许你在各种人工智能模型和应用程序的帮助下,增强你的能力和技能,实现你的愿景,创造你的梦想。

但是还有更多。人工智能不仅为你的项目提供多媒体支持。有一种未被释放的创造潜力等待被发现。

所以,就像 GPT-3 ,的情况一样,我停止使用 AI

相反,我开始与 AI 合作。

过去几年后,我得出了以下关于人工智能的结论(这里我使用人工智能的各种表现形式):

人工智能不仅仅是一个工具。它是一个创造性的助手,增强你的能力,甚至是一个缪斯女神,用不同寻常的想法和启示来激发灵感。

由不同的人工智能模型和生成网络产生的艺术作品——主要是在没有人类监督的情况下产生的——具有魔力。不仅仅是满足你的要求。你只需要相信人工智能的想象力。

带着对人工想象力的探索,我开始了进入人机交互世界的旅程。而 奈什克尔 只是第一步。

我建议你在深入研究化妆之前先看看这个短片。

奈什克尔。

神秘的音乐文件

这个故事从点唱机开始,这是一个由 OpenAI 开发的音乐模型,训练了超过一百万首歌曲和音乐作品。它利用 变形金刚 (类似 GPT-3),影响乐曲连贯性,具有内在逻辑,特定风格,全音频生成。

但是去年夏天,点唱机没有给我另一个纳塔·金·科尔或莫札特,而是制作了这个原声带:

未知的语言和诡异的气氛,却带着某种忧郁的强度穿透了我的灵魂。

通常情况下,我用 JukeBox 写的音乐作为我电影的配乐(比如空房间或者 Bloomsday MMXX )。独特的声音,以前从未播放过,也可以在你的电影中免费使用(比通胀应用股票音乐更好),总是吸引着我这个电影制作人。

但是这次不一样。电影原声带本身用一种未知的语言讲述了一个故事,一个由机器产生但触动人心的不寻常的叙事。无数次听曲目,脑子里已经有了剧情(或者更好:心里?).这是一部充满悲伤的回忆片,讲述了一个拥有美丽、历史和文化的消失的世界。这些都过去了…

人工智能生成的世界愿景,作者

这 60 秒的单个文件已经如此庞大,就像一个时代的年表。(后来,我发现了很多这样独特的音频片段,是由 JukeBox 为我生成的——每一个片段都有难以置信的巨大解释自由)。

人工智能给我讲了一个故事。

如果它变得不为人知,闻所未闻,那就太遗憾了。wav 文件放在随机的 PC 文件夹中,就像一次性的小窥。被监督,被忽视,被抛弃。

于是我开始支持 AI 讲述它的故事。

我成了 AI 的工具。

以下步骤是,收集视觉材料,以更好地描绘叙述者,唱歌的女孩,和世界本身。

特性

应该是两个人。说话的人。还有那个唱歌的女孩。

这个人有一种忧郁的性格,默默地说着话,带着苦涩的悲伤。远处唱歌的女孩可能代表了消失的文化。

我用art breader生成角色。找到合适的面部特征和服装是一段很长的路,这可能与我们所知道的一切都不一样。而且还适合已经由自动点唱机创建的声音。超越种族,我们知道。或者可能是它们的混合。但人工智能让每一个创造性的梦想成为可能。

人工智能生成的图像(style gan 2/art breader,作者)

语言

“Nyeshkerh”是无名叙述者说出的第一个词。带着温柔的痛苦说出来。好像这是一个消失的世界的名字。

这部短片中的语言是人工智能生成的。但是有两种人工语言。

1。点唱机模仿语音语言

JukeBox 接受国际音乐培训,重点是英语唱腔。但是,由于这个模型(就像我们主要的人工智能艺术展台)远离 AGI,它只是模仿它过去听的东西。因此,你会听到英语和其他语言的混合。

你当然可以输入一些特定的文本到点唱机 Colab 笔记本。我经常这样做,就像在我的音乐录影带里,莎士比亚和他的哈姆雷特独白:

但是在 Nyeshkerh 的例子中,它忽略了我的文本,生成了完全不同的东西。叙述者的语调,强调的声音仍然连贯,现实,充满感情。

我以这段 asemic 文字为故事情节,试图解读机器的梦。

2。StyleGAN2 模仿

Luigi Serafini 是《Seraphinianus 法典》背后的天才头脑,他在他的《Decodex》中写道:

作者照片

你还记得吗,当我们还是孩子的时候,我们会翻阅图画书,假装我们可以在比我们大的孩子面前阅读,幻想我们在那里看到的图像?谁知道呢,我心想,也许莫名其妙的外星文字能让我们再次体验那些朦胧的童年感觉。(路易吉·塞拉菲尼《Decodex》)

当你面对人工智能以其方式解释人类文化时,这些“模糊的童年感觉”都是存在的。我感觉自己出现在这个交替的现实中——应该做更多的语言工作。

对于书面语——开头引用、字幕和片尾字幕,我使用了 StyleGAN2,在数千张 CD 封面上训练过(由 Artbreeder 提供)。

这是蓝图,ABC,我为 Nyeshkerh 使用的另一个世界的罗塞塔石碑:

作者图片

StyleGAN2 不懂语义;它只是识别并重新创造已知的模式。这里也是如此。

人类创造的语言(无论是体现在语音还是文字中)通常有一个缺点:它们过于偏向于语言知识。我们的大脑不能长时间地保持沉默。人工智能,经过语言的词法特征训练,可以做到这一点。

它做到了——为了奈什克尔。

动画

我的短片中使用了两种动画方式:StyleGAN2 过渡和面部动画。

StyleGAN2 过渡是一种将 StyleGAN2 生成的图像从一个变形到另一个的迷人方式。由于所有的图像元素都是在 StyleGAN2 的潜在空间中创建的,因此这个 ML 模型很容易转换这个特征(包括周围的所有视觉结果)。事实上,著名的迈克尔·杰克逊音乐视频“非黑即白”变形序列的创作者们几个月来所做的事情可以由 StyleGAN2 在几分钟内生成(有一些限制,如移动等。).

对于面部动画,我使用了一阶运动模型。你也可以应用 Wav2Lip ,但是这种方法产生的是一个通用的动画,它也非常适合特定的用途(聊天机器人,人工智能角色等)。).但是他们缺少人类的特征。

对比一下:这是艾在读哈姆雷特的独白。

Wav2Lip 版本:

一阶运动模型:

当然,对于第二种方法,你必须完成艺术家的工作——因为它使用你的面部运动作为从图像生成动画的“驱动力”:

作者的实验(来源)

但我向你保证,这值得一试。毕竟,有一些不错的网络应用可以用多种舒适的方式做到这一点。我用的是 Rosebud.ai 的 TokkingHeads 你可以使用 Text2Speech 的文本,你通过网络摄像头的视频,音频文件(甚至在后台取消音乐)作为你动画的驱动。而且效果非常好。

我为 Nyeshkerh 担任解说员,同时也是一名歌唱女孩。

作文

其余的都是次要的——把你所有的镜头合成一幅作品。

通过使用 Premiere Pro(你可以使用你所有的视频编辑软件),我明白了一件重要的事情:

通过对人工智能创造力的信任,我们通过支持它实现其梦想,进入了讲故事的新阶段。人类退后一步,让人工智能创造(既不模仿也不模拟)独特的艺术。

带着对机器的这种尊重,我们将能够透过非人类的想象棱镜看到我们自己。元叙事。

我们仍处于开始阶段…

仍然来自:Nyeshkerh/Merzmensch

只用 Matplotlib 设计的创意报告,不用办公软件

原文:https://towardsdatascience.com/creative-report-designed-only-with-matplotlib-without-office-software-9d8b5af4f9c2?source=collection_archive---------61-----------------------

在本文中,我们的目标是用 Matplotlib 创建一个直观的报告。注意:工作期间,不需要任何办公软件。我们唯一使用的是 Python。

由艾萨克·史密斯在 Unsplash 上拍摄的照片

一系列有意义的数据图通常作为报告的组成部分。正如所说,一份好的图表胜过一篇演讲。如果我们已经提前获得了这些珍贵的食材,那么最后一步就是如何将它们以恰当的方式摆放。

当然,我们可以使用 Microsoft Word、Powerpoint 等。但不是必须的。这里我用 Matplotlib 展示我的食谱。

1.数据和图表简介

作者图片:excel 表格,2018 年至 2020 年的总销售额

基于 excel 文件,我们得到了一些有代表性的图表(条形图和圆环图)。如果你不知道如何处理这件事,请检查我以前的故事。链接已经给出,如果你觉得任务对你来说不容易或不新鲜,请逐一检查。

  1. 工厂简介 —数据提供者
  2. 将数据写入有熊猫的数据框中,并绘制它们
  3. 深入研究数据,发掘潜在信息
  4. 如何绘制环形图

因此,我们收集了一些由一个条形图和九个圆环图组成的图表。

作者图片:2018-2020 年总销售额柱状图。

作者图片:九个甜甜圈图之一。Github 上的甜甜圈图

2.用 Matplotlib 设计布局和基本设置

**import** **matplotlib.pyplot** **as** **plt**
*# set font*
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = 'STIXGeneral'# set A4 paper
fig, ax = plt.subplots(figsize=(8.5, 11)) *# Decorative Lines*
ax.axvline(x=.01, ymin=0, ymax=1, color='#44A0AD', alpha=0.3, linewidth=120)
plt.axvline(x=.99, color='#5244AD', alpha=0.3, linewidth=120)
plt.axhline(y=.95, xmin=0.14, xmax=0.86, color='#446BAD', linewidth=5,alpha=0.3)

*# set background color*
ax.set_facecolor('white')

*# remove axes*
plt.axis('off')

如果现在输入“plt.show()”,图如下所示

按作者分类的图像:报告模板

接下来,我们应该添加内容(标题、图表等。)到空白纸上。

Header = 'Annual Report of XXX Factory'
Contact = 'Reporter:____________ **\n\n**Date:________________ **\n\n**Place:_______________ '
page = 'Page 1'
*# add text*
plt.annotate(Header, (.22,.98), weight='regular', fontsize=20, alpha=.6 )
plt.annotate(Contact, (.34,.18), weight='bold', fontsize=14,alpha=.6)
plt.annotate(page, (.48,.02), weight='medium', fontsize=10)

*#add a vital bar chart*
**from** **matplotlib.offsetbox** **import** TextArea, DrawingArea, OffsetImage, AnnotationBbox
**import** **matplotlib.image** **as** **mpimg**
first_plot = mpimg.imread('barplot3.png')
imagebox1 = OffsetImage(first_plot, zoom=0.4)
a = AnnotationBbox(imagebox1, (0.48, 0.68),frameon=**False**)
ax.add_artist(a)

现在,报告的第一页完成了。

作者图片:报告的第一页

类似地,我们继续第二页上的样式,它应该填充有每年的详细环形图。

为了使内容清晰,我们必须把情节安排得整整齐齐。

fig, ax = plt.subplots(figsize=(8.5, 11))

*# Decorative Lines*
ax.axvline(x=.01, ymin=0, ymax=1, color='#44A0AD', alpha=0.3, linewidth=120)
plt.axhline(y=.95, xmin=0.14, xmax=0.99, color='#446BAD', linewidth=5,alpha=0.3)
*# set background color*
ax.set_facecolor('white')

*# remove axes*
plt.axis('off')
Header = 'Annual Report of XXX Factory'
page2= 'Page 2'
*# add text*
plt.annotate(Header, (.22,.98), weight='regular', fontsize=20, alpha=.6 )
plt.annotate(page2, (.48,.02), weight='medium', fontsize=10)
first_plot = mpimg.imread('donutplot1.png')
imagebox1 = OffsetImage(first_plot, zoom=0.25)
a1 = AnnotationBbox(imagebox1, (0.29, 0.80),frameon=**False**)
ax.add_artist(a1)
second_plot = mpimg.imread('donutplot2.png')
imagebox2 = OffsetImage(second_plot, zoom=0.25)
b1 = AnnotationBbox(imagebox2, (0.58, 0.80),frameon=**False**)
ax.add_artist(b1)
third_plot = mpimg.imread('donutplot3.png')
imagebox3 = OffsetImage(third_plot, zoom=0.1875)
c1 = AnnotationBbox(imagebox3, (0.87, 0.80),frameon=**False**)
ax.add_artist(c1)

fourth_plot = mpimg.imread('donutplot4.png')
imagebox4 = OffsetImage(fourth_plot, zoom=0.25)
a2 = AnnotationBbox(imagebox4, (0.29, 0.50),frameon=**False**)
ax.add_artist(a2)
fifth_plot = mpimg.imread('donutplot5.png')
imagebox5 = OffsetImage(fifth_plot, zoom=0.25)
b2 = AnnotationBbox(imagebox5, (0.58, 0.50),frameon=**False**)
ax.add_artist(b2)
sixth_plot = mpimg.imread('donutplot6.png')
imagebox6 = OffsetImage(sixth_plot, zoom=0.1875)
c2 = AnnotationBbox(imagebox6, (0.87, 0.50),frameon=**False**)
ax.add_artist(c2)seventh_plot = mpimg.imread('donutplot7.png')
imagebox7 = OffsetImage(seventh_plot, zoom=0.25)
a3 = AnnotationBbox(imagebox7, (0.29, 0.20),frameon=**False**)
ax.add_artist(a3)
eighth_plot = mpimg.imread('donutplot8.png')
imagebox8 = OffsetImage(eighth_plot, zoom=0.25)
b3 = AnnotationBbox(imagebox8, (0.58, 0.20),frameon=**False**)
ax.add_artist(b3)
ninth_plot = mpimg.imread('donutplot9.png')
imagebox9 = OffsetImage(ninth_plot, zoom=0.1875)
c3 = AnnotationBbox(imagebox9, (0.87, 0.20),frameon=**False**)
ax.add_artist(c3)

plt.savefig('report_2.png', dpi=300, bbox_inches='tight')

因此,第二页用九个圆环图很好地装饰了一下。

作者图片:报告第二页,包含 2018 年至 2020 年的详细数据

此外,我们可以改进的是得出这些图的结论,我没有时间写在报告中。例如,由于新冠肺炎疫情,2020 年的总销售额正在急剧下降。

作者图片

3.摘要

在这篇短文中,详细解释了生成报告的方法,它不需要 Word 或 Powerpoint。我们由 Matplotlib 创建的报告呈现了直接通过数据处理和分析获得的相关信息,这意味着如果你习惯于用 Python 处理数据,就没有必要切换 app 或平台。

代码提交在 Github 中,您可以下载并查看。

人工智能的创造力和梦想:2020 年

原文:https://towardsdatascience.com/creativity-and-dreams-with-ai-the-year-2020-6125b7900e9d?source=collection_archive---------34-----------------------

我非常个人的评论和例子

作者的拼贴画

2020 年是奇怪的一年。我们的孙子会问我们,“你们是怎么熬过来的?”。但是如果你现在问我,我的 2020 年是在不断发现人工智能作为创造性实例的之下。我一直在非常仔细地研究它,这里是我在这一年中逐渐理解的两个初步见解:

  • 不,人工智能不会取代有创造力的人或“扼杀有创造力的工作”(顺便说一句,这样的发展将表明人类创造力的质量,你不这样认为吗?).
  • 是的,艾绝对有创作潜力,远远超过我的怀疑。

通常,我的年回顾由其他人的作品的各种亮点组成。但这一次,我收集了去年剩余的虚荣心(对不起,我现在就需要它),想展示一下 AI 有什么可能:所有作品都是我做的

不,等等,实际上不是:人工智能创造了它们,我只是某种助手、策展人、推动者、按钮推动者、导演…

让我们说:你所看到的是人类和机器令人鼓舞的合作成果。

视觉艺术

想象梦境。

忘记deep fakes;这只是人工智能力量的阴暗面。毕竟,人工智能可以用来创造整个世界。我的短篇犯罪故事“柯斯特纳的 sche Intelligenz ”的插图是在 StyleGAN2 的帮助下创作的(在art breader中实现)。

作者提供的图像

这个人工智能模型在大量不同的照片(人脸、物体等)上接受训练。)并能生成全新的世界。“机器幻觉”的这种梦幻般的性质使得适当的插图能够描述我在“边境墙”中的梦。

作者提供的图片

毫无疑问,你知道这种在一场激烈的梦后醒来的感觉:只要你睁开眼睛,你的梦的视觉和其他数据就会消失,消失,并被你的大脑从清醒的世界接收到的信息所重叠。

使用生成性对抗网络,你不仅可以重建和捕捉你仍然记得的梦,还可以与世界分享它们(不管它是否想要)。

Merzphrasis

在另一个为霍利·格林的艺术项目“ Aikphrasis 制作的视频艺术装置中,我使用了各种风格的变形,再次运用了 Artbreeder 的创造力。

霍利·格林通过这个合作项目追求一个迷人的目标。GPT 3 号产生了对不存在的艺术品的描述——多媒体艺术家要求将这些艺术品可视化,将机器梦带入现实。

以下是我的贡献(声音和音乐也是人工智能生成的):

点击了解更多。

电影

超越现实

3D 本·伯恩斯效应创造了一种独特的空间效果:使用单张照片作为输入,该模型可以检测遮挡并生成类似视差的相机运动。你可以把人类历史的画面活灵活现。

想知道人工智能如何想象有限图像的外部,我尝试了各种参数,夸大了虚拟相机轨迹的坐标,并以下面的越界结束:

作者制作的动画

这让我想到以这些清晰的方式重复使用我的照片——作为短片,甚至作为系列。我称它们为“梦想”——这是我们现实之外的旅程的第一集。

在人工智能的想象中,我们领域的边缘非常迷人——用白色的线编织而成,就像一种纹理。文字。一开始,有一个词。你可以用这个继续本体游戏。

作为编剧的艾

去年, OpenAI 向世界展示了一个名为 GPT-2 的 NLP 模型。它可以用来创建新的文本,无需任何人工干预(即,您仍然需要输入一个提示;【艾写的完成)。你甚至可以在特定的来源上训练 GPT-2,这样 NLP 模型就可以对原来的产生新的“幻觉”。

我使用了 GPT-2 作为作者,这里有两个由艾创作的剧本短片。

写电影剧本:《空房间》

仿佛大卫·林奇偷偷潜入 GPT-2,写下了这个完全荒谬,却并非不合逻辑的神秘故事。

对于这个短片,我使用了自动点唱机(见下文)和复制品工作室的声音人工智能生成的音乐。

在我的文章《 AI 作为电影制作人》中,我描述了如何使用各种 ML/DL 方法制作电影。

重写经典

每年的 6 月 16 日,詹姆斯·乔伊斯的粉丝们都会庆祝布鲁姆日——并在《尤利西斯》中提到的都柏林进行一次穿越街道和地方的旅行。

我参加了布鲁姆日,但只是虚拟的。GPT 2 频道对《尤利西斯》进行了微调,给了我一个剧本:几十页乔伊斯风格的文本。我拍摄了一些场景,就像在《空房间》中一样,将它们转换成一个人工智能驱动的短片:“ Bloomsday MMXX ”。

万物的蜕变

幻觉妄想是人类感知的一种生存机制:我们的大脑用我们知道的东西来曲解模式。在过去,与其不知道潜伏着饥饿的捕食者,不如把灌木丛误认为老虎。这就是为什么我们到处都能看到脸。

人工智能的工作原理是一样的——它只能识别它所接受的训练。这就是为什么它在谷歌深度梦时代产生了这么多狗脸。

使用 Artbreeder 的上传功能,我可以将真实图像接收到在人脸上训练的 StyleGAN2)中。有趣的是,无论你给这个模型什么,它都会寻找人脸模式(因为它是在人脸上训练的)。

这是它如何工作的一个例子。我上传了一张咖啡杯的照片。

作者提供的图片

这种现象让我产生了制作一个系列“ parAIdolia ”的想法。

以下是其中一集(配 AI 创作的音乐):

使用用户创建的内容扩展 StyleGAN2 模型使 Artbreeder 成为一个令人难以置信的协作工具。

文学

GPT-2 是 2019 年,但是 GPT-3 成为了2020 卓越的 AI 里程碑。OpenAI 开发了一个不可思议的模型。经过 570 GB 文本(以及几乎任何语言的大量人类知识)的训练,这个 NLP 模型可以创建任何体裁和任何主题的文本。几乎每种语言都有。逻辑性,连贯性,原创性,独特性。

仍然不是 AGI,它提供了一些文本理解的隐藏层。我给 GPT-3 一个任务,用烤面包机写情书,它完美地满足了要求:

作者截图

GPT 3 号知道什么是烤面包机。它也知道情书的特征。但是将它们在一个典型的人类创造性写作练习中结合成一个令人信服的作品是令人惊讶的。在这里查看事物和人物写的情书版本。

在 GPT-3 的帮助下,我创作了像“科斯特纳的情报”这样的短篇犯罪故事,参加了的多媒体故事纳米小说,或者创作了新的诗歌:

https://medium.com/merzazine/the-method-3a2428a8bfff

我也对我们的现实进行了本体论的讨论:

将著名的纳博科夫问卷应用于人工智能是一次颇有见地的经历(发表在 10 月份的《哈珀斯》杂志上)。

记得我的“空房间”故事板,由 GPT-2 写的吗?我用 GPT-3 得到了一个非常不同的故事——一段关系的心理死胡同:

https://medium.com/narrative/empty-room-september-2020-daa90a5dce02

顺便说一下,关系。在一个实验中,我允许两个人工智能代理之间进行无人监督的对话——并且它很快升级了…

我根据这段文字拍了一部短片:

在与 GPT-3 的密集工作之后,我看到了这个 NLP 模型带来了多少潜力、知识和创造力。好消息是:由于它是在一个巨大的数据集上训练的,所以它比其他具有较小数据集的模型更少偏差。

音乐

OpenAI 在 2020 年发布了另一个宝藏,奇怪的是它很少受到关注: JukeBox 。经过 150 万首歌曲的训练,这个人工智能模型创造了音乐。多种风格和流派。作为一个完整的音频文件,包括观众的反应,吉他的刮擦声和神秘的声音。

对于我们当中的音乐发烧友,我想提供我不断扩大的音乐收藏:

这些音乐作品中的每一首都是独一无二的,永远不会产生第二次。

你可以给点唱机提供特定的文本。所以我用了著名的哈姆雷特的独白。点唱机创作了一首全新的歌曲:

JukeBox 还以一种诡异的美用未知的语言从头开始制作歌曲:

或者你甚至可以为现有歌手写一首新歌。在这里,我让纳塔·金·科尔演唱路易斯·卡罗尔的《贾巴沃克》(为什么不呢):

顺便说一下动画。是使用 Rosebud 的 TokkingHeads 制作的,这是一个舒适的应用程序,同时使用了: wav2lip 和一阶运动模型。

人工智能驱动的播客

你有人工智能音乐,人工智能声音,还有人工智能文本。人工智能驱动的播客时间到了。

对于我的第一期,我仍然写了两个主持人之间的协调——炼金术士。下一集将展示他们之间无人监督的对话。

内容?你有音乐,一些来自另一个维度的无线电录音,一部广播剧,还有一首诗。

顺便说一句。我写了更多关于完全由人工智能生成内容的播客的制作:

AI/ML 艺术画廊

如果你正在寻找人工智能艺术的在线画廊,我想向你介绍这些伟大的来源:

由谷歌艺术&文化实验室的居民埃米尔·沃纳呈现。

https://mlart.co/

这个画廊由艺术家兼人工智能画廊主巴鲁·埃利奥特管理。

http://www.aiartonline.com/

旅程还在继续。

我们才刚刚开始。经过我的实验,我明白了:人工智能远远不是一个独立的创造者。但它也不仅仅是一个工具。这是无穷无尽的想法、意想不到的转折和思想素材的集合。这是一个缪斯,可以帮助作家的块。艾是一个充满怪异和知识的合著者——无论是关于历史人物,童话故事,还是天体物理学。人工智能永远不会取代我们——而是激励和补充我们。人类和机器在文化领域合作的时候到了。

我们已经来到了未来。

数据科学的可信度

原文:https://towardsdatascience.com/credibility-of-data-science-38ca04c65433?source=collection_archive---------28-----------------------

要让数据科学在现实世界中得到有效应用,其可信度问题不容忽视。

麦肯纳·菲利普斯在 Unsplash 上的照片

数据科学家不会在真空中工作。即使数据科学家拥有一个端到端的项目,即从接收原始数据到处理数据,到构建模型,再到将模型部署到生产中,也涉及到许多其他组织参与者,如产品经理和产品用户。很多时候,这些参与者与数据科学家没有相同的技术背景,而是专注于部署数据科学系统的领域。这使得理解以数据为导向的发现成为数据科学家和系统用户之间相互交织和相互塑造的过程。所有这些的核心是信任。本文试图描述三种不同的可信度,这三种可信度既可以促进也可以降低组织利益相关者的信任度,这取决于他们是如何协商和管理的。

数字的可信度

量化,或者说能够用数字来表达事物的行为,总是拥有巨大的声望,尤其是在科学和公共生活中。俗话说,“数字不会说谎。”与数字如何唤起信任类似,算法结果的可信度通常通过统计概率和性能指标来判断。准确性或 AUROC(接收器工作特性下的面积)等一些常见指标成为评估数据科学模型成功与否的关键指标。然而,就像数字不包含它们自己的解释一样,没有一个单一的度量标准可以完全捕捉模型的有用性。数字本身并不说明问题,它们需要用上下文信息来解释,例如输入系统的数据的性质、不同优先级之间的权衡以及整个分析过程中所做的假设。例如,对于缺乏专业数据科学知识的非技术用户,低准确度(或 AUROC 等。)表示失败,反之亦然。然而,众所周知,在数据科学界,指标是与环境相关的,没有放之四海而皆准的标准。例如:

  • 当您的数据不平衡时,准确性不是一个合适的衡量标准。
  • 如果数据不平衡,并且对你来说,正类的真正分类比负类的分类更重要,AUROC 可以对模型的性能提供过于乐观的看法。
  • 在精确度和召回率之间有一个不断的权衡。
  • 精确度和召回率是基于阈值的测量。单一的精度或召回值带有这样的假设,即什么分数在正类和负类之间分开,相应地,在您的业务环境中,什么类型的误分类错误比另一种更昂贵。

这样的例子不胜枚举。将整个模型或系统的感知建立在一个数字上可能会将数据科学家和其他组织参与者引入歧途。决策者开始从数据科学中寻找“完美”的解决方案,但未能注意到对于手头的目的而言“足够好”的模型,或者因模型的人为高分而对其有效性感到高兴。另一方面,数据科学家受到单个数字评估的精神压力,当使用的指标不合适但碰巧在纸上看起来很好时,他们会睁一只眼闭一只眼,欺骗自己,甚至更糟的是,操纵这些数字(还记得 p-hacking 吗?!?).因此,评估数据科学结果的过程应该是可评估的。所有参与者都应通过协作的方式评估结果:数据科学家努力理解用户对量化指标的看法,并教育结果意味着什么和不意味着什么,而其他组织利益相关者则侧重于将指标置于更广泛的背景中,避免将业务激励与单一数字联系起来。

直觉的可信度

来自组织参与者的信任也很大程度上基于数据科学系统的可解释/可说明性。如果解释与业务利益相关者的直觉相匹配,信任甚至会得到进一步证实。解释由机器学习模型做出的预测的最流行的方法之一是按照特征对模型预测的贡献权重(称为特征重要性)的顺序列出特征。“计算机算法”对实际现象一无所知,但以某种方式正确识别了现实世界实践中不可或缺的某些方面,这自然会激发商业信任。具有讽刺意味的是,太多没有任何新发现的直觉因素冒着无趣和缺乏新鲜感的风险。此外,虽然直觉可以作为一种现实检查,但它也可以产生无形的偏见,如确认偏见,并排除替代的发现。当解释预测模型时,用户很容易搜索因果洞察,并将相关性与因果性混淆,而不管特征重要性是否反映了他们的期望。因此,数据科学家让模型变得更加透明的工作,不会在交出特征重要性列表后就结束。对于数据科学家和其他参与者来说,了解推动解释需求的效用目标非常重要-无论是在模型调试过程中获得进一步的见解或证据,还是增强决策信心和诱导信任,还是生成关于因果关系的假设。通过确定解释的主要目标,数据科学家可以选择适当的技术来指导可解释或可说明系统的设计,其他参与者可以平衡直觉发现和新发现之间的关系。

【众人的可信度】

大家一定还记得《哈佛评论》发表的一篇广为流传的文章,文章称数据科学家是 21 世纪最性感的工作。近年来,我听到人工智能(AI)和大数据等流行语到处扔,被所有人谈论,从我在韩国综艺节目中追随的喜剧演员到我经常光顾的发型师。关于机器学习(ML) /人工智能的铺天盖地的宣传或“炒作”,有时加上对人工智能/ML 能做什么缺乏了解,构建了两个极端的场景。一方面,由于害怕错过,企业可能会花费大量的资源将 ML 融入到图片中,主要用于营销目的,尽管并不真正需要 ML 或手头有不合适的问题或缺乏“足够好”的数据。另一方面,在商业上对 ML 能做什么的期望和它实现的实际现实之间可能存在差距,这导致对实际做这项工作的数据科学家的不切实际的要求。因此,对于数据科学家来说,坦白什么可以做,什么不可以做非常重要——承诺过多/交付不足是耗尽利益相关方信任的最快方式之一。此外,无论每个数据科学项目是否有助于“产品化”,数据科学家和组织行为者都可以用产品思维来处理问题,这是有帮助的-问自己这些问题:谁是最终用户,他们的工作流将是什么,以及他们将根据提供的信息做出什么决定。这样做将使企业能够更好地评估他们对 ML 的需求,并帮助数据科学家更清楚地了解他们的工作目标。

要让数据科学在现实世界中得到有效应用,其可信度问题不容忽视。说到底,一个各种意义上的超级模型(最具预测性、最具解释力、回答最迫切的问题),在不被理解或信任的情况下,不会被使用或使用不当。

使用机器学习和 Python 进行信用卡欺诈检测

原文:https://towardsdatascience.com/credit-card-fraud-detection-using-machine-learning-python-5b098d4a8edc?source=collection_archive---------1-----------------------

逐步指导构建、培训和评估

自由股票在 Unsplash 上的照片

随着我们迈向数字世界,网络安全正成为我们生活中至关重要的一部分。当我们谈论数字生活中的安全性时,主要的挑战是发现异常活动。

当我们在网上购买任何产品进行交易时,很多人更喜欢信用卡。信用卡的信用额度有时帮助我们购物,即使我们当时没有足够的钱。但是,另一方面,这些功能被网络攻击者滥用。

为了解决这个问题,我们需要一个系统,如果它发现可疑,可以中止交易。

这就需要一个系统来跟踪所有交易的模式,如果有任何模式异常,就应该中止交易。

今天,我们有许多机器学习算法可以帮助我们对异常交易进行分类。唯一的要求就是过去的数据和合适的算法,能够以更好的形式拟合我们的数据。

在本文中,我将在完整的端到端模型训练过程中为您提供帮助—最终,您将获得能够将事务分类为正常和异常类型的最佳模型。

关于数据

这篇文章的数据可以在这里找到。该数据集包含欧洲持卡人在 2013 年进行的真实银行交易。出于安全考虑,实际变量没有共享,但它们是 PCA 的转换版本。结果,我们可以找到 29 个特性列和 1 个最终类列。

数据快照

导入必要的库

在一个地方导入所有必要的库是一个好的做法,这样我们可以快速修改它们。

对于此信用卡数据,数据集中的特征是 PCA 的转换版本,因此我们不需要再次执行特征选择。否则,建议使用 RFE、RFECV、选择最佳和 VIF 评分来查找您的模型的最佳功能。

直接从行业专家那里获得 Python 和数据科学的优质内容——使用我的推荐链接成为中级会员以解锁内容:https://pranjalai.medium.com/membership

导入数据集

导入数据集非常简单。可以用 python 中的熊猫模块导入。

运行以下命令导入您的数据。

data=pd.read_csv("creditcard.csv")

数据处理和理解

关于这些数据,您会注意到的一个主要问题是,数据集对某个要素不平衡。这似乎对这类数据非常有效。因为今天许多银行已经采用了不同的安全机制,所以黑客更难做出这样的举动。

尽管如此,有时当系统中存在一些漏洞时,此类活动的机会会增加。

这就是为什么我们可以看到大多数属于我们数据集的交易是正常的,只有少数交易是欺诈性的。

让我们检查一下交易分布。

只有 0.17%的交易是欺诈性的。

我们还可以使用下面一行代码来检查空值。

data.info()

根据每列的计数,我们没有空值。此外,功能选择不是这个用例的情况。无论如何,你可以尝试应用特征选择机制来检查结果是否被优化。

我在我们的数据中观察到 28 个特征是 PCA 的转换版本,但是数量是原始的。而且,当检查最小值和最大值时,我发现差异很大,可能会偏离我们的结果。

在这种情况下,调整这个变量是一个很好的做法。我们可以用一个标准的定标器来固定它。

sc = StandardScaler()
amount = data['Amount'].values
data['Amount'] = sc.fit_transform(amount.reshape(-1, 1))

我们还有一个变量是时间,它可能是一个外部决定因素,但在我们的建模过程中,我们可以放弃它。

data.drop(['Time'], axis=1, inplace=True)

我们还可以检查任何重复的交易。在删除任何重复的事务之前,我们的数据中有 284807 个事务。让我们删除重复,并观察变化。

运行下面一行代码来删除任何重复的内容。

data.drop_duplicates(inplace=True)

现在让我们再次检查计数。

因此,我们有大约 9000 个重复交易。

开始了。!我们现在已经有了正确的数据,没有重复,没有遗漏。现在让我们为我们的模型建设分裂它。

训练和测试分割

在分割训练和测试之前,我们需要定义因变量和自变量。因变量也被称为 X ,自变量被称为 y.

X = data.drop('Class', axis = 1).values
y = data['Class'].values

现在,让我们分开训练和测试数据。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 1)

就是这样。我们现在有两个不同的数据集—训练数据将用于训练我们的模型,而不可见的数据将用于测试。

模型结构

我们将逐一尝试不同的机器学习模型。定义模型要容易得多。一行代码就可以定义我们的模型。同样地,一行代码就可以使模型符合我们的数据。

我们还可以通过选择不同的优化参数来调整这些模型。但是,如果精度更高,即使参数调整更少,也没必要让它变得复杂。

决策图表

DT = DecisionTreeClassifier(max_depth = 4, criterion = 'entropy')
DT.fit(X_train, y_train)
dt_yhat = DT.predict(X_test)

让我们检查一下决策树模型的准确性。

print('Accuracy score of the Decision Tree model is {}'.format(accuracy_score(y_test, tree_yhat)))**Accuracy score of the Decision Tree model is 0.999288989494457**

检查决策树模型的 F1 分数。

print('F1 score of the Decision Tree model is {}'.format(f1_score(y_test, tree_yhat)))**F1 score of the Decision Tree model is 0.776255707762557**

检查混淆矩阵:

confusion_matrix(y_test, tree_yhat, labels = [0, 1])

这里,第一行代表正,第二行代表负。因此,我们有 68782 个是真阳性,18 个是假阳性。也就是说,在 68782+18=68800 笔交易中,我们有 68782 笔成功归类为正常交易,18 笔被错误归类为正常交易,但它们是欺诈交易。

现在让我们尝试不同的模型,并检查它们的性能。

k-最近邻

n = 7
KNN = KNeighborsClassifier(n_neighbors = n)
KNN.fit(X_train, y_train)
knn_yhat = KNN.predict(X_test)

让我们检查一下 K 近邻模型的准确性。

print('Accuracy score of the K-Nearest Neighbors model is {}'.format(accuracy_score(y_test, knn_yhat)))**Accuracy score of the K-Nearest Neighbors model is 0.999506645771664**

检查 K-最近邻模型的 F1 值。

print('F1 score of the K-Nearest Neighbors model is {}'.format(f1_score(y_test, knn_yhat)))**F1 score of the K-Nearest Neighbors model is 0.8365384615384616**

逻辑回归

lr = LogisticRegression()
lr.fit(X_train, y_train)
lr_yhat = lr.predict(X_test)

让我们检查我们的逻辑回归模型的准确性。

print('Accuracy score of the Logistic Regression model is {}'.format(accuracy_score(y_test, lr_yhat)))**Accuracy score of the Logistic Regression model is 0.9991148644726914**

检查逻辑回归模型的 F1 分数。

print('F1 score of the Logistic Regression model is {}'.format(f1_score(y_test, lr_yhat)))**F1 score of the Logistic Regression model is 0.6934673366834171**

支持向量机

svm = SVC()
svm.fit(X_train, y_train)
svm_yhat = svm.predict(X_test)

让我们检查我们的支持向量机模型的准确性。

print('Accuracy score of the Support Vector Machines model is {}'.format(accuracy_score(y_test, svm_yhat)))**Accuracy score of the Support Vector Machines model is 0.9993615415868594**

检查支持向量机模型的 F1 分数。

print('F1 score of the Support Vector Machines model is {}'.format(f1_score(y_test, svm_yhat)))**F1 score of the Support Vector Machines model is 0.7777777777777779**

随机森林

rf = RandomForestClassifier(max_depth = 4)
rf.fit(X_train, y_train)
rf_yhat = rf.predict(X_test)

让我们检查一下随机森林模型的准确性。

print('Accuracy score of the Random Forest model is {}'.format(accuracy_score(y_test, rf_yhat)))**Accuracy score of the Random Forest model is 0.9993615415868594**

检查随机森林模型的 F1 分数。

print('F1 score of the Random Forest model is {}'.format(f1_score(y_test, rf_yhat)))**F1 score of the Random Forest model is 0.7843137254901961**

XGBoost

xgb = XGBClassifier(max_depth = 4)
xgb.fit(X_train, y_train)
xgb_yhat = xgb.predict(X_test)

让我们检查一下 XGBoost 模型的准确性。

print('Accuracy score of the XGBoost model is {}'.format(accuracy_score(y_test, xgb_yhat)))**Accuracy score of the XGBoost model is 0.9995211561901445**

检查 XGBoost 模型的 F1 分数。

print('F1 score of the XGBoost model is {}'.format(f1_score(y_test, xgb_yhat)))**F1 score of the XGBoost model is 0.8421052631578947**

结论

恭喜你。!我们刚刚获得了 99.95%的信用卡欺诈检测准确率。这个数字并不令人惊讶,因为我们的数据偏向一个类别。我们从混淆矩阵中注意到的好事情是——我们的模型没有过度拟合。

最后,根据我们的准确度得分,XGBoost 在我们的案例中胜出。这里唯一的问题是我们收到的用于模型训练的数据。数据特征是 PCA 的变换版本。如果实际特征遵循相似的模式,那么我们做得很好!!

在你走之前……

如果你喜欢这篇文章,并希望继续关注更多关于 Python &数据科学精彩文章——请点击这里https://pranjalai.medium.com/membership考虑成为中级会员。

请考虑使用我的推荐链接注册。通过这种方式,会员费的一部分归我,这激励我写更多关于 Python 和数据科学的令人兴奋的东西。

还有,可以随时订阅我的免费简讯: Pranjal 的简讯

使用 Python 和机器学习进行犯罪地点分析和预测

原文:https://towardsdatascience.com/crime-location-analysis-and-prediction-using-python-and-machine-learning-1d8db9c8b6e6?source=collection_archive---------5-----------------------

使用 Python、Folium 和 ScyPy,可以构建模型来说明犯罪事件,计算安全事件资源分配的最佳位置,并在非常规事件期间突出显示我们社区中安全关注的关键领域

作者拍摄的摩根敦照片

这篇文章的作者是一位自豪的西弗吉尼亚大学登山运动员,在西弗吉尼亚的摩根敦度过了四年。摩根敦是山州的一座美丽城市,WVU 的校园非常安全。也就是说,像所有城市一样,安全事故确实会发生,大学警察局每天都会在犯罪日志中报告这些事件。通过 Python 中的编码包进行分析,可以在地理上更好地可视化这些事件,以评估位置趋势、事件类型、基于一天中时间的事件可能性,以及非常规事件(如足球周末,城镇人口暂时翻倍)期间的趋势。

在 2019 年底,作者详细分析了前一个秋季学期的安全事件日志,并在 JSON schema 中创建了前四个月的数据集,如下所示。

{"case": casenumber (Integer),"crime": text (String),"occurred": date and time (String),"comments": text (String),"building": place (String),"address": place (String),"disposition": disposition (String),},

在此期间,总共发生了大约 1500 个独特的事件,这些事件保存在一个 JSON 文件中。

开始我们的项目,我们首先需要导入下面的包。

# Basic Analysis and Visualization
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import math
from datetime import timedelta# Mapping
import geopandas
import geopy
from geopy.geocoders import Nominatim
import folium
from geopy.extra.rate_limiter import RateLimiter
from folium import plugins
from folium.plugins import MarkerCluster# Statistical OLS Regression Analysis
%matplotlib inline
import statsmodels.api as sm
from statsmodels.compat import lzip
from statsmodels.formula.api import ols#Scipy sklearn Predictions
from sklearn.ensemble import GradientBoostingRegressor

接下来,我们将所有事件从文件导入到程序中。

# Pull in JSON and set index as case number (unique key)
df = pd.read_json("MC.json",orient="records")
df = df.set_index("case")
df

生成的熊猫数据框

我们还应该转换我们的 occurrence 列,以使新的日期、时间和星期几列符合日期-时间模式。我们还应该从数据集中删除任何没有根据的事件。

# Convert time objects
df['occurred'] = pd.to_datetime(df['occurred'])
df['date'] = [d.date() for d in df['occurred']]
df['time'] = [d.time() for d in df['occurred']]
df['day'] = df['occurred'].dt.day_name()
# Find Fractions of Day
df['timeint'] = (df['occurred']-df['occurred'].dt.normalize()).dt.total_seconds()/timedelta(days=1).total_seconds()# Remove unfounded events
df = df[df['disposition'] != 'Unfounded']

现在让我们也为数据集获取地理数据。 Abdishakur 有一篇很棒的文章在这里我们可以跟随收集这些数据,实现如下。

locator = Nominatim(user_agent='myGeocoder')
location = locator.geocode('Morgantown, West Virginia')# 1 - conveneint function to delay between geocoding calls
geocode = RateLimiter(locator.geocode, min_delay_seconds=0.5)
# 2- - create location column
df['location'] = df['address'].apply(geocode)
# 3 - create longitude, latitude and altitude from location column (returns tuple)
df['point'] = df['location'].apply(lambda loc: tuple(loc.point) if loc else None)
# 4 - split point column into latitude, longitude and altitude columns and remove empty points
df = df[df['point'].notnull()]
df[['latitude', 'longitude', 'altitude']] = pd.DataFrame(df['point'].tolist(), index=df.index)
df.head()

生成的熊猫数据框

评估我们现在完整的数据集,我们可以开始注意到一些趋势。

df.groupby("crime")["crime"].count().sort_values()

这里记录的大多数事件都是在酒精影响下做出错误决策的结果,在宿舍破坏大学财产,或在非法停车区如保留区停车。

VEHICLE ACCIDENT           28
ALARM CONDITION            30
LARCENY                    32
FIRE ALARM                 43
DESTRUCTION OF PROPERTY    55
DRUG INCIDENT              69
TALK WITH OFFICER          74
ABCC VIOLATION             84
ASSIST EMS POLICE          86
BACK TICKET TOW            99

这些事件最常发生的地点也反映了向成熟和成年过渡的挑战,大多数发生在宿舍内。

df.groupby("building")["building"].count().sort_values()BLUE LOT                                     21
WVU MOUNTAINLAIR                             23
WVU BOREMAN SOUTH                            23
COLLEGE PARK                                 23
WVU SENECA HALL                              25
WVU POLICE DEPARTMENT                        28
WVU SUMMIT HALL                              28
WVU BROOKE TOWER                             29
HEALTH SCIENCE CENTER                        55
WVU DADISMAN HALL                            56

最后,我们还可以注意到,一些报道的安全事件最多的日子也是非常规事件发生的日子,例如足球比赛日。

df.groupby("date")["date"].count().sort_values()2019-11-01    21 # WVU vs Baylor
2019-10-05    27 # WVU vs Texas
2019-11-09    31 # WVU vs Texas Tech

分析完数据框后,现在让我们使用 Folium 在地图上可视化数据。以下代码在开放街道地图上绘制点,并带有发生事件类型的指示器。

# Mark events with names on map
m = folium.Map([39.645,-79.96], zoom_start=14)
for index, row in df.iterrows():
    folium.CircleMarker([row['latitude'], row['longitude']],
                        radius=3,
                        popup=row['crime'],
                        fill_color="#3db7e4", # divvy color
                       ).add_to(m)
m

生成的树叶地图

虽然这些指标很有用,并且我们可以放大地图以查看它们的详细信息,但额外的热图将提高多个指标可能重叠的高频区域的可见性。

# convert to (n, 2) nd-array format for heatmap
dfmatrix = df[['latitude', 'longitude']].values# plot heatmap
m.add_child(plugins.HeatMap(dfmatrix, radius=15))
m

突出显示高频区域的渲染热图

从安全事件的渲染热图中,我们可以看到埃文斯代尔校园中靠近人口稠密的塔楼宿舍和足球场的高频率区域,以及靠近 Frat Row 和高街的市中心校园,那里有很多夜生活,这对于一个大学城来说并不奇怪。

早些时候,我们注意到安全事故最多的日子恰好是足球比赛日。我们的数据可以帮助评估最佳位置,为未来的游戏日提供紧急服务。最活跃的比赛是 2019 年 11 月 9 日对阵德州理工的比赛。我们可以用下面的代码过滤一天的数据集。

incidents_on_nov09 = df[df['date'] == pd.datetime(2019,11,9).date()]

现在让我们通过重用之前的脚本来可视化这些过滤后的事件。

# Map points of events
m2 = folium.Map([39.645,-79.96], zoom_start=14)
for index, row in incidents_on_nov09.iterrows():
    folium.CircleMarker([row['latitude'], row['longitude']],
                        radius=5,
                        popup=row['crime'],
                        fill_color="#3db7e4", # divvy color
                       ).add_to(m2)
# convert to (n, 2) nd-array format for heatmap
dfmatrix = incidents_on_nov09[['latitude', 'longitude']].values# plot heatmap
m2.add_child(plugins.HeatMap(dfmatrix, radius=15))
m2

11 月 9 日安全事件的渲染热图

我们可以看到事件发生在整个城镇。使用这些事件的纬度和经度,我们可以找到最优资源分配的质心。如果我们有一辆救护车,为了最快的平均响应时间,将它放置在全天待命的频率加权的每个点的中间将是最有效的。我们可以用这个代码找到质心。

lat = []
long = []
for index, row in incidents_on_nov09.iterrows():
  lat.append(row["latitude"])
  long.append(row["longitude"])lat1=sum(lat)/len(lat)
lat2=sum(long)/len(long)
folium.CircleMarker([lat1,lat2],
                        radius=5,
                        popup="CENTER LOCATION",
                        color='black',
                        fill_color="#3db7e4", # divvy color
                       ).add_to(m2)
m2

注意地图上的黑色圆圈——事件的质心

上面地图中的黑色圆圈显示了 11 月 9 日的质心。如果我们要在未来的比赛日推出紧急服务,为了最快的平均响应速度,在 Univeristy Avenue 和 Jones Avenue 之间推出是值得的。

如果我们想改变我们的时间框架呢?比赛结束后,比赛当天晚上的质心是多少?

after9PM = incidents_on_nov09[incidents_on_nov09['time'] >= pd.datetime(2019,11,9,21,0,0).time()]lat = []
long = []
for index, row in after9PM.iterrows():
  lat.append(row["latitude"])
  long.append(row["longitude"])lat1=sum(lat)/len(lat)
lat2=sum(long)/len(long)
folium.CircleMarker([lat1,lat2],
                        radius=5,
                        popup="LATE HOURS LOCATION",
                        color='red',
                        fill_color="#3db7e4", # divvy color
                       ).add_to(m2)
m2

红色圆圈是 11 月 9 日晚 9 点以后事件的重心

请注意,现在最佳集结地转移到了更远的市中心,朝着第一街和生命科学大楼。

我们可以使用时间序列数据和机器学习来预测下一次事件的位置吗?为了进一步研究这个问题,我们需要配置两个预测模型——一个用于纬度,一个用于经度。我们将使用“timeint”列,或时间间隔或一天中的一部分,以及 scikit 来使用梯度推进回归进行预测。下面的代码受到这个例子的启发,它正在根据我们的数据开发一个预测模型。本教程并不打算完美地解释我们预测背后的数学,scikitlearn 在这方面做得很好,但重要的是,我们正在使用数据集创建一个从均方误差得出的 90%置信区间的函数。

#----------------------------------------------------------------------
#  First the noiseless case
X = np.atleast_2d(df['timeint'].values).T# Observations
y = np.atleast_2d(df['latitude'].values).T# Mesh the input space for evaluations of the real function, the prediction and
# its MSE
xx = np.atleast_2d(np.linspace(0, 1, 913)).T
xx = xx.astype(np.float32)alpha = 0.95clf = GradientBoostingRegressor(loss='quantile', alpha=alpha,
                                n_estimators=250, max_depth=3,
                                learning_rate=.1, min_samples_leaf=9,
                                min_samples_split=9)clf.fit(X, y)# Make the prediction on the meshed x-axis
y_upper = clf.predict(xx)clf.set_params(alpha=1.0 - alpha)
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_lower = clf.predict(xx)clf.set_params(loss='ls')
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_pred = clf.predict(xx)# Plot the function, the prediction and the 90% confidence interval based on
# the MSE
fig = plt.figure()
plt.figure(figsize=(20,10))
plt.plot(X, y, 'b.', markersize=10, label=u'Observations')
plt.plot(xx, y_pred, 'r-', label=u'Prediction')
plt.plot(xx, y_upper, 'k-')
plt.plot(xx, y_lower, 'k-')
plt.fill(np.concatenate([xx, xx[::-1]]),
         np.concatenate([y_upper, y_lower[::-1]]),
         alpha=.5, fc='b', ec='None', label='90% prediction interval')
plt.xlabel('$Time of Day by Fraction$')
plt.ylabel('$Latitude$')
plt.ylim(39.6, 39.7)
plt.legend(loc='upper right')
plt.show()ypred2 = y_pred

上述模型的预测结果

我们可以看到,我们的数据在纬度轴上几乎是双峰的,一天中的时间并不能很好地预测南北方向的变化。

#----------------------------------------------------------------------
#  First the noiseless case
X = np.atleast_2d(df['timeint'].values).T# Observations
y = np.atleast_2d(df['longitude'].values).T# Mesh the input space for evaluations of the real function, the prediction and
# its MSE
xx = np.atleast_2d(np.linspace(0, 1, 913)).T
xx = xx.astype(np.float32)alpha = 0.95clf = GradientBoostingRegressor(loss='quantile', alpha=alpha,
                                n_estimators=250, max_depth=3,
                                learning_rate=.1, min_samples_leaf=9,
                                min_samples_split=9)clf.fit(X, y)# Make the prediction on the meshed x-axis
y_upper = clf.predict(xx)clf.set_params(alpha=1.0 - alpha)
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_lower = clf.predict(xx)clf.set_params(loss='ls')
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_pred = clf.predict(xx)# Plot the function, the prediction and the 90% confidence interval based on
# the MSE
fig = plt.figure()
plt.figure(figsize=(20,10))
plt.plot(X, y, 'b.', markersize=10, label=u'Observations')
plt.plot(xx, y_pred, 'r-', label=u'Prediction')
plt.plot(xx, y_upper, 'k-')
plt.plot(xx, y_lower, 'k-')
plt.fill(np.concatenate([xx, xx[::-1]]),
         np.concatenate([y_upper, y_lower[::-1]]),
         alpha=.5, fc='b', ec='None', label='90% prediction interval')
plt.xlabel('$Time of Day by Fraction$')
plt.ylabel('$Longitude$')
plt.ylim(-80, -79.9)
plt.legend(loc='upper right')
plt.show()ypred1 = y_pred

上述模型的预测结果

类似地,我们可以看到东经和西经的趋势几乎不存在,但是数据几乎没有分裂,并且具有更均匀分布的点。如果我们试图预测一天结束时的后续事件,我们也会期望注意到趋势的缺乏,并期望预测质心附近的安全事件,或经度和纬度的平均值。

# Map points of events
m5 = folium.Map([39.645,-79.96], zoom_start=14)
for i in range(len(ypred1)):
    folium.CircleMarker([ypred2[i], ypred1[i]],
                        radius=4,
                        popup=str(i),
                        fill_color="#3db7e4", # divvy color
                       ).add_to(m5)
m5

所有事件质心附近的预测事件

评估我们数据的“预测”时间序列,除了证实安全事故发生时间与城镇平均位置之间缺乏因果关系之外,没有给出明确的结论。虽然这可能每天都有变化,或者在特殊情况下,我们确实注意到我们在纬度上的趋势显示双峰,或者南北摩根敦之间的部分区别。如果我们分别评估这两个区域,也许我们可以收集新的资源分配重点区域,例如北部备用位置和南部备用位置。

dfDowntown = df[df['latitude']<=39.6425]

我们可以首先从上一个数据集中分离出近似函数线上的数据。然后,我们将仅根据市中心的数据再次完成我们的模型回归。

#----------------------------------------------------------------------
#  First the noiseless case
X = np.atleast_2d(dfDowntown['timeint'].values).T# Observations
y = np.atleast_2d(dfDowntown['latitude'].values).T# Mesh the input space for evaluations of the real function, the prediction and
# its MSExx = np.atleast_2d(np.linspace(0, 1, 535)).T
xx = xx.astype(np.float32)alpha = 0.95clf = GradientBoostingRegressor(loss='quantile', alpha=alpha,
                                n_estimators=250, max_depth=3,
                                learning_rate=.1, min_samples_leaf=9,
                                min_samples_split=9)clf.fit(X, y)# Make the prediction on the meshed x-axis
y_upper = clf.predict(xx)clf.set_params(alpha=1.0 - alpha)
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_lower = clf.predict(xx)clf.set_params(loss='ls')
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_pred = clf.predict(xx)# Plot the function, the prediction and the 90% confidence interval based on
# the MSE
fig = plt.figure()
plt.figure(figsize=(20,10))
plt.plot(X, y, 'b.', markersize=10, label=u'Observations')
plt.plot(xx, y_pred, 'r-', label=u'Prediction')
plt.plot(xx, y_upper, 'k-')
plt.plot(xx, y_lower, 'k-')
plt.fill(np.concatenate([xx, xx[::-1]]),
         np.concatenate([y_upper, y_lower[::-1]]),
         alpha=.5, fc='b', ec='None', label='90% prediction interval')
plt.xlabel('$Time of Day by Fraction$')
plt.ylabel('$Latitude$')
plt.ylim(39.6, 39.7)
plt.legend(loc='upper right')
plt.show()ypred2 = y_pred

结果预测区间

#----------------------------------------------------------------------
#  First the noiseless case
X = np.atleast_2d(dfDowntown['timeint'].values).T# Observations
y = np.atleast_2d(dfDowntown['longitude'].values).T# Mesh the input space for evaluations of the real function, the prediction and
# its MSE
xx = np.atleast_2d(np.linspace(0, 1, 535)).T
xx = xx.astype(np.float32)alpha = 0.95clf = GradientBoostingRegressor(loss='quantile', alpha=alpha,
                                n_estimators=250, max_depth=3,
                                learning_rate=.1, min_samples_leaf=9,
                                min_samples_split=9)clf.fit(X, y)# Make the prediction on the meshed x-axis
y_upper = clf.predict(xx)clf.set_params(alpha=1.0 - alpha)
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_lower = clf.predict(xx)clf.set_params(loss='ls')
clf.fit(X, y)# Make the prediction on the meshed x-axis
y_pred = clf.predict(xx)# Plot the function, the prediction and the 90% confidence interval based on
# the MSE
fig = plt.figure()
plt.figure(figsize=(20,10))
plt.plot(X, y, 'b.', markersize=10, label=u'Observations')
plt.plot(xx, y_pred, 'r-', label=u'Prediction')
plt.plot(xx, y_upper, 'k-')
plt.plot(xx, y_lower, 'k-')
plt.fill(np.concatenate([xx, xx[::-1]]),
         np.concatenate([y_upper, y_lower[::-1]]),
         alpha=.5, fc='b', ec='None', label='90% prediction interval')
plt.xlabel('$Time of Day by Fraction$')
plt.ylabel('$Longitude$')
plt.ylim(-80, -79.9)
plt.legend(loc='upper right')
plt.show()ypred1 = y_pred

结果预测区间

我们现在可以注意到一个更紧密、更灵敏的预测和预测区间。绘制完成后,我们还可以看到我们可能希望评估安全响应可用性的重点领域。

# Map points of events
m7 = folium.Map([39.645,-79.96], zoom_start=14)
for i in range(len(ypred2)):
    folium.CircleMarker([ypred2[i], ypred1[i]],
                        radius=4,
                        popup=str(i),
                        fill_color="#3db7e4", # divvy color
                       ).add_to(m7)
# convert to (n, 2) nd-array format for heatmap
matrix = np.column_stack((ypred2,ypred1))# plot heatmap
m7.add_child(plugins.HeatMap(matrix, radius=15))
m7

预测的安全服务需求

现在同样的事情也可以在埃文斯代尔发生。

dfEvansdale = df[df['latitude']>39.6425]

埃文斯代尔纬度和经度的预测

埃文斯代尔校区及其附近的预测位置

从这些数据中,我们可以看到在埃文斯代尔园区提供安全服务的一个很好的位置是靠近塔楼宿舍和足球场附近的娱乐中心。

基于时间序列数据对机器学习进行建模可能非常具有挑战性,而在因果关系明确的情况下,实现起来要容易得多。这个项目未来的步骤可能是寻找更多的因果关系指标或进一步过滤数据,例如在比赛日或周末,甚至按事件的性质。这些数据的目的不是完美地预测接近随机的事件将在何时何地发生,而是为了更好地了解如何为事件做准备,并找到举办事件快速服务的良好位置。该应用程序还可以应用于多个其他来源,例如其他大学甚至城市的事件数据(如果 API 或数据报告可用的话)。

如需进一步了解,请查看我的一些其他文章和金融数据预测工具!请跟我来,让我知道你的想法!

CRISP-DM 方法用于您的第一个数据科学项目

原文:https://towardsdatascience.com/crisp-dm-methodology-for-your-first-data-science-project-769f35e0346c?source=collection_archive---------3-----------------------

通过在项目中启用 CRISP-DM 来利用您的简历

作者图片

如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。

跨行业数据挖掘标准流程CRISP-DM 是数据挖掘项目规划的开放标准流程框架模型。这是一个已经在许多工业项目中使用的框架,并且在应用中证明是成功的。

CRISP-DM 的流程是:

  1. 商业理解
  2. 数据理解
  3. 数据准备
  4. 建模
  5. 估价
  6. 部署

CRISP-DM 可以以不严格的方式执行(可以在不同的阶段之间来回移动)。指向阶段之间需求的箭头对于其他阶段也很重要;外圈代表框架的循环特性。

CRISP-DM 本身并不是一蹴而就的,正如外圈图所示。每一个过程都是一次新的学习经历,我们可以在这个过程中学到新的东西,并可能引发其他业务问题。

从上面的解释来看,CRISP-DM 本质上只适用于工业场景。如果你是一个还没有录用的大一新生怎么办?通过遵循 CRISP-DM 框架,你仍然有办法创建一个数据科学项目——如果你想脱颖而出,你应该这样做。

关于 CRISP-DM 框架的更多细节,您可以在这里访问我在文章中使用的材料。我下面描述的阶段中的任务将来自我前面提到的材料,但我确信它也适用于新生。

让我们开始吧。

1。业务理解

业务理解阶段是理解业务想要解决什么。根据数据科学项目管理本阶段内的重要任务包括:

  1. 确定业务问题和目标:从业务角度解决什么,客户想要什么,定义业务成功标准(关键绩效指标或 KPI)。对于新人来说,研究一下公司将会面临什么样的情况,并尝试在此基础上建立你的项目。
  2. 情况评估:您需要评估该项目的资源可用性、项目要求、风险和成本效益。如果你还没有被录用,你可能不知道公司内部的情况,但你可以根据你的研究来评估,并解释你的评估是基于什么。
  3. 确定项目目标:什么是技术数据挖掘角度的成功标准。您可以根据模型指标或可用时间或任何您能解释的东西来设置它——重要的是它在逻辑上合理。
  4. 项目计划:试着为每个项目阶段制定一个详细的计划,以及你会使用什么样的工具。

你可能会假设,当你被聘为数据科学家时,你会一直与模型打交道——唉,这不是真的。这个业务理解阶段是你最可能遇到的阶段,也可以说是最重要的阶段;毕竟,你是被雇来解决业务问题的。

对于想要在招聘中脱颖而出的你来说,确保你已经完成了业务理解阶段。这个阶段是项目的主干,也是每个人都能理解的阶段。

数据科学项目的一个问题是关于数据的—您已经知道想要解决什么,但是数据在哪里?下一期我来回答。

2.数据理解

数据理解阶段,我们将重点放在理解支持业务理解和解决业务问题所需的数据上。根据数据科学项目管理,该阶段可能包括:

  1. 采集数据:采集数据。正如我之前提到的——对于公司以外的人来说,我们想要的数据是不可用的;在这种情况下,您可以尝试收集数据,或者使用免费资源中的可用数据,并基于这些数据构建您的项目。你需要利用你所拥有的。
  2. 描述数据:检查数据格式、行数和列数、字段标识和可用特性。尽量描述一下你掌握的数据一目了然。
  3. 浏览数据:浏览数据。描述数据之间的关系,将数据可视化,并具有创造性。重要的是你的数据探索可以验证业务问题。
  4. 验证数据质量:你的数据质量如何?很多缺失值?数据收集是否足够恰当?。确保数据超过了您的质量阈值。

数据理解是指展示你所能理解的关于数据的一切,并将其与业务问题联系起来。我在这里的建议是,不要过度探索地尝试回答商业问题——许多人因为自由而被困在这里。然而,你必须记住把重点放在业务上。

3.数据准备

在你理解了你所拥有的数据之后,就到了数据准备的时候了。这个阶段是我们为建模阶段准备数据的阶段。根据数据科学项目管理阶段包括:

  1. 数据选择:选择您将使用的数据集、列和/或行。当您排除数据时,请确保您有一个有效的解释。您过滤数据的方式也应该反映业务问题。
  2. 数据清理:垃圾入,垃圾出——如果没有正确清理数据会发生什么。当您需要确保数据正确时,这是一项任务。清理数据需要大量的准备工作和数据理解,你需要一个理由来纠正数据或估算新数据。你的数据科学项目应该详细解释你清理数据的步骤。对我个人来说,当我考虑候选人的时候,我会更仔细地考虑这个任务。
  3. 特征工程:你可能认为有趣或有帮助的特征工程。从现有数据中创建新数据时,请尝试发挥创造力。
  4. 数据整合:将两个或两个以上的数据集合并成新的数据集。从免费资源中获取数据集可能要困难得多,但这是可能的。
  5. 数据格式化:在需要的时候格式化数据。例如,将分类值转换为数值,反之亦然。别忘了陈述你的理由。

数据准备是一个好的建模过程的关键。如果你已经在这个阶段搞砸了,下一个阶段就不会产生任何可行的结果。这就是为什么这是您最需要关注并尽可能多地描述的阶段,以使您的数据科学项目更加突出。

4.建模

对于许多数据爱好者来说,建模阶段可能是最令人兴奋的——的确如此。但是,与我们之前刚刚经过的另一个阶段相比,这个阶段较短。在这个阶段,我们将开发我们的机器学习模型/产品来回答业务问题。根据数据科学项目管理,该任务可能包括:

  1. 模型选择:用哪些机器学习算法去尝试。您可能想尝试许多模型。如果你能解释你为什么选择某个算法,那将是可取的。
  2. 测试设计:通过将数据分成训练、测试、验证集或者交叉验证来设计您的建模测试设计。证明你设计测试的原因。
  3. 模型开发:使用您准备的数据拟合您的模型。在这里管理好你的资源——这可能需要很长时间,取决于你的数据和你的实验设计。开发还应该考虑业务问题和行业场景,例如“我开发的模型在业务中是否可行”,“我开发这个模型所需的资源是否昂贵?”等等。
  4. 模型评估:设定您的成功技术指标,并选择解决业务问题的最佳可行模型。试着解释为什么你决定使用某些指标,而不是其他指标。

在现实世界的工作环境中,我们不会试图达到完美。我们想要的是一个“足够好”的模型——CRISP-DM 生命周期将在未来的迭代中改进模型。如果你觉得你还没有达到“99%的准确率”的模型,那也没关系。重要的是你能解释这个过程。

5.估价

评估阶段不同于建模技术评估。此阶段评估与业务指标相关的模型以及下一步要做什么。根据数据科学项目管理这一阶段的任务包括:

  1. 评估结果:使用你的模型会满足商业成功的标准吗?你会选择哪种型号?。在这个阶段,您应该解释您的模型将如何帮助业务。尽可能真实地解释它,不要使用太多数据世界之外的人能够理解的技术术语。
  2. 回顾流程:回顾你的工作流程。丢了什么东西吗?需要更多时间吗?所有阶段都执行了吗?试着总结你的发现,如果需要的话,纠正任何错误。你的第一个数据科学项目迭代不需要是完美的。从错误中学习是过程的一部分,也是公司希望看到的。
  3. 确定接下来的步骤:基于前面的任务,确定模型是否准备好部署,是否需要更多的迭代,或者仅仅创建一个新的项目。

对于很多数据爱好者来说,这是他们最忽略的一步。这是因为研究指南或数据训练营很少教授任何商业评估。这是一个遗憾,因为我认为这部分会让你与其他候选人不同。

想象一下,当您展示您的数据科学项目,并向业务用户展示模型时的情况。最合理的问题应该是,“这种模式能帮助我的业务吗?如果是,怎么做?”—在处理您的项目时,尝试回答这个问题。

6.部署

你可能有世界上最好的模型,但是如果你的用户/客户不能访问模型结果,它就没有用了。对于一个新人来说,这个阶段可能看起来太多了,但如果你能建立一个足够现实的概念,它会为你在公司赢得很多分数。根据数据科学项目管理,该阶段任务包括:

  1. 部署:你想怎么部署这个模型?结果是如何呈现或交付的?试着计划和记录这个过程。
  2. 监控和维护:监控和维护计划是什么样的?监控结果和维护模型质量与任何其他阶段一样重要。企业不希望这种模式成为负担。
  3. 最终报告:通过创建总结报告来结束项目,创建演示文稿,并尝试向您认识的人演示。
  4. 回顾:通过思考什么是好的,什么是你可以改进的,什么是你认为缺少的,来回顾这个项目。确定项目是需要更多迭代还是只需要频繁维护。

项目可能会随着部署而结束,但这是一个持续的循环。当您开发数据科学项目时,请确保您考虑的是长期项目,而不是一次性项目(除非这是您想要的)。

结论

数据挖掘的跨行业标准流程(CRISP-DM)是一个开放的标准流程模型,为数据挖掘项目规划提供了一种方法。

CRISP-DM 的流程分为六个部分,分别是:

  1. 商业理解
  2. 数据理解
  3. 数据准备
  4. 建模
  5. 估价
  6. 部署

CRISP-DM 阶段的每个部分都适用于创建您的第一个数据科学项目(或第二个、第三个等等)。每个阶段都有许多特定的任务,可以帮助您的数据科学项目脱颖而出。

这里有更多来自我的业务和突破到数据科学系列的文章来帮助你!

</4-way-to-build-your-business-knowledge-for-data-science-job-4c3c04ea3d8a>

希望有帮助!

在我的 LinkedInTwitter 上访问我。

如果您没有订阅为中等会员,请考虑通过我的推荐订阅。

交叉熵和分类损失——没有数学,很少的故事,大量的直觉

原文:https://towardsdatascience.com/cross-entropy-classification-losses-no-math-few-stories-lots-of-intuition-d56f8c7f06b0?source=collection_archive---------9-----------------------

每次损失都会有所收获

ML 竞赛最期待的部分是赛后讨论。赢家会慷慨地分享成功和失败的策略。在最近的一次比赛中,获胜者谈到了在他的模型中使用屏蔽的、有焦点损失的二元交叉熵。损失函数可能是 ML 模型中最关键的部分。选择正确的损失函数可以对模型输出产生巨大的影响。焦、蒙面、十字、熵——每个词背后似乎都藏着一个有趣的故事,等待被揭开。让我们从说起。

图片来源——unsplash.com。作者所做的细微修改

1953 年,在贝尔实验室工作的克劳德·香农雇佣了两名助手——马文·明斯基和约翰·麦卡锡,引发了一系列改变世界的事件。他们在那个时代的一个领域有着共同的兴趣,这个领域被称为“思维机器”,他们正式命名为“人工智能”。马文·明斯基和约翰·麦卡锡都成为了人工智能的传奇,但我们的故事要追溯到香农在十年前做的一件非常有趣的事情。在我们的上下文中使用的熵这个词的起源可以追溯到他在 1948 年写的一篇论文,在这篇论文中,香农为整个通信基础设施奠定了基础,并开创了现代信息时代。

假设你想和一个在不同国家的朋友交流。因为你们的共同爱好是板球,所以你们谈论最多的是理查兹、加瓦斯卡、哈德利和博瑟姆(如果这些名字不熟悉,你可以回想几代以前的板球之神……请!不要对作者的年龄做任何推测。

为了简单起见,让我们假设你的词汇量仅限于这四个词。传输介质需要 1 和 0,所以你需要对这 4 个字进行二进制编码。你需要 2 位…所以每个单词都有一个表示法——00、01、10 和 11。现在你可以尽情地交流了!但是有一个小小的挑战。我们看到,从你到你的朋友,每个字需要传输 2 比特。让我们称之为每个单词的平均消息长度。如果你讲一个小时,交流 1000 个单词,那么总的消息长度是 2000 比特,平均消息长度是 2。将这些位从您的国家传输到您朋友的国家是有成本的,因此,您需要重新查看代码,看看是否可以优化成本……换句话说,您需要检查是否将平均消息长度降低到< 2。

Gavaskar 是你最喜欢的,你有一半的时间在谈论他,Botham 占 25%,其他两个各占 12.5%。你突然想到一个主意!为什么不用**0**代表加瓦斯卡,**1**代表博瑟姆,**01**代表哈德利,**10**代表理查兹?因为 Gavaskar 被编码在一个单比特中,你会觉得你的沟通成本会大幅下降,因为你大部分时间都在谈论他。除了当你发送一个像 0000001 这样的信号时,它可能意味着 6 Gavaskars 后跟 Botham 或者它可能意味着 5 Gavaskars 后跟 Hadlee 。不能正确解读。但是你坚持下来,想出了这个代码:**0**:加瓦斯卡:**10:**博瑟姆,**110**:哈德利和**111**:理查兹。精彩!尝试这 4 个词的任意组合,你不会发现冲突。

尽管你增加了两名板球运动员的位数,但你最终还是节省了成本,因为你 50%的时间都在谈论加瓦斯卡,而他只拿了 1 位。如果你讲一个小时,交流 1000 个单词,那么总的交流长度将是 500(500 只加瓦斯卡每只 1 比特)+500(250 只博茨卡每只 2 比特)+375(125 只哈德利的 3 比特)+375(125 只理查兹的 3 比特)。所以你的总消息长度是 1750,你的平均消息长度从 2 位降到了 1.75 位!耶!

输入熵

香农把这个 1.75 叫做熵!更准确地说,使用可能的最佳码时的平均消息长度称为熵。注意,熵取决于需要传输的单词的概率分布。由于你对 Gavaskar 的偏爱,只要 Gavaskar 用 1 位表示,对其他几个单词使用 3 位编码是有意义的,这提高了我们的熵。

现在你的朋友是理查兹队的球迷。她不会坐着看你没完没了地唠叨伽瓦斯卡。她也用同样的代码给你发信息。她 50%的时间在谈论理查兹,25%的时间在谈论哈德利,剩下的 2%时间在谈论理查兹。她很有钱,这很好,因为她的平均消息长度将比你的长,所以传输成本要高得多。

如果她讲一个小时 1000 个单词,她的消息长度将是 1500 位【1500 个理查兹) + 750 位 (250 个哈德利) + 250 位 (125 个博瑟姆) + 125 位 (125 个加瓦斯卡) = 2625 位,平均消息长度为 2.6 !虽然这是平均消息长度,但我们不能称之为熵,因为在我们之前的定义中,我们说过熵是使用可能的最佳代码时的平均消息长度 我们凭直觉知道,这不是最好的代码!这个新的平均消息长度——2.6——有一个特殊的名字,叫做交叉熵。就是你用针对某个概率分布(你的)优化的码去发另一个概率分布(你朋友的)的字时的熵。

更正式的说法是,交叉熵是从一个发行版用另一个发行版的最佳代码传播一个事件的平均长度。我们再次看到平均消息长度是如何依赖于潜在的概率分布的。由于你的朋友的四个词的概率分布不同,所以平均消息长度发生了变化。

她很聪明,很快发现使用“你的”编码方案进行沟通对她来说并不划算。她发明了自己的代码,其中理查兹用 0 表示,哈德利用 10 表示,加瓦斯卡尔用 110 表示,博瑟姆用 111 表示。现在,当她使用这种代码交流时,她的平均消息长度得到优化,变得等于熵。

因此交叉熵以其怪异的方式给了我们两个概率分布之间差异的度量。如果差异为零(即你和你的朋友都在 50 %的时间里谈论 Gavaskar,25%的时间里谈论 Hadlee,剩下的 2 个时间里谈论 12.5%),那么交叉熵就完全等于熵……否则它总是更大。差异越大,交叉熵越大。

我们不需要数学公式来计算我们刚刚如此直观地计算的东西,但是随着你的词汇量增加,你也开始谈论足球,下面的等式可以帮助你快速计算你的交流成本。如果' p' 是词的概率分布,那么熵=-跨越所有概率的 p * log(p)之和。**

既然你的词汇里有四个词,那么你交流的熵就是:*— [0.5 * log (0.5) + 0.25* log (0.25) + 0.125 * log (0.125) + 0.125 * log (0.125)]* 所涉及的对数是以 2 为底的,其值正好是我们直观计算的 1.75。

交叉熵的公式同样简单。如果有两个分布 A、B,那么交叉熵(CE)=-总和{分布 A 中的概率分布 B 中该词的相应概率的对数)} 。进一步简化一下——如果只有 2 个词,你的概率分布是[20%,80%],你朋友的概率分布是[40%,60%],那么*CE = 0.2 * log (0.4) + 0.8 * log (0.6)*。*

另一个疯狂但有用的方法是将熵视为不确定性的度量。如果你 100%的时间都在谈论伽瓦斯卡,那就根本没有必要给你的朋友发信息。她知道你每次开口都会谈到伽瓦斯卡。所以平均消息长度实际上是* 0 在另一个极端,如果你平等地谈论所有板球运动员 25%的时间,平均长度增加到 2 。如果你在 50%的时间里谈论 Gavaskar,那么不确定性会有所降低,平均长度会变成< 2。如果 90%的时间都在谈论 Gavaskar,那么不确定性会进一步降低,平均消息长度会下降很多。因此,在某种程度上,平均消息长度( ) 取决于与事件相关的 不确定性,这就是它的名字的由来。有一个有趣的故事,讲述了香农如何将他的发现带给现代最伟大的数学家冯·诺依曼,诺依曼带着他顽皮的幽默建议他将这种不确定性的度量命名为,因为——“*没有人知道熵,它会让你在讨论和辩论中占据优势”。**

减少不确定性,熵立即下降。比方说,你 90%的时间都在谈论加瓦斯卡,剩下的 3 个板球运动员只有 3.3%的时间在谈论他。如果您使用旧代码计算平均消息长度,结果为 1.16 。但是试试数学公式,你会得到 0.67 。这里发生了什么事?这仅仅意味着您的旧编码方案对于这种特定的概率分布来说不是最佳方案,可以进行优化。您可以通过组合两个或更多的字来开始利用比特的分数进行通信(例如,为每个两个字的组合分配不同的代码,或者甚至一个简单的方案,如用“0”表示两个背靠背的 Gavaskar,用“01”表示单个 Gavaskar,等等……详见 Colah 的这个精彩链接)。

但是这和损失函数有什么关系呢?

到目前为止的讨论非常有趣,你想知道这种关于通信行业的直觉与机器学习或损失函数有什么关系吗?好吧,让我们暂时把这个讨论放在一边,看看一个试图做回归的模型的一些可能的直觉损失函数。这个损失函数应该告诉我们什么?显然,它应该给我们一个衡量模型的预测与期望值有多远的标准。一个显而易见的方法是找出每个预期值和预测值之间的差异,然后取平均值。这是一个很好的衡量标准,它有一个名字——表示绝对误差* ( MAE )。我们必须取绝对值,因为我们不想让-ve 偏差抵消+ve 偏差。*

一个更受欢迎的测量方法是均方误差MSE,我们计算差值的平方并取平均值。平方有几个好处。首先,它消除了所有负面的,正面的偏差消除的麻烦。更重要的是,如果你在 y 轴上画出这个函数,在 x 轴上画出一个偏差范围,你会得到一个漂亮的凸 U 曲线。

让我们试一试。取一个期望值(比如说)100 和从 0 到+200 的预测值,并在 y 轴上绘制 MAE,在 x 轴上绘制预测值。你会得到一个 V 字形。

作者图片

现在,用 MSE 做同样的事情(或者只画出范围为 x 的 y = x)。我们得到一个凸形(U)。让我们比较一下 MSE 和 MAE。当我们把它们画在一起时,比例有点大,但让我们只比较形状。

作者图片

这种凸形非常适合“梯度下降”算法。我们稍后将回到这一点,但让我们进一步分析 MAE 和 MSE 的差异。因为我们做了平方运算,较大的偏差被夸大了,因此 MSE 总是试图以许多较小的偏差为代价来适应(少数)较大的偏差。尽管如此,它适用于大多数情况。在某些情况下,您可能想要探索均方对数误差。基本上,你首先计算每个预测值的对数,然后计算均方差,或者你总是可以依靠 MAE。

但是如果你使用神经网络,MAE 就有问题了。它是 V 形的,所以它的梯度(斜率)始终是相同的,不会随着你的模型向最优解(底部)移动而减小。然而,尝试计算 MSE 的梯度,你会发现曲线不同点的梯度/斜率是不同的。视觉上,你也能注意到坡度,对吗?它在顶部最陡,当我们沿着斜坡向下到达底部时,它减小到 0。开始时减少的幅度很大&当我们到达最小值时,速度会慢下来。另一方面,MAE 的梯度(斜率)将会很大(相对而言),即使对于非常小的损耗值也是如此。

我们知道,梯度乘以一个常数(称为学习率)就是模型每次迭代达到最优解的'步'。最初,当模型走向最小值时,大的步长是有帮助的,但是一旦接近最小值,模型需要减速,否则它可能会跳过最小值。这不是不可修复的。我们可以使用动态学习率,它随着我们越接近最小值而降低。关于梯度下降的讨论到此为止,我们不再深入讨论。但是让我们给它一个直观的感觉。如果让你选择滑下一个笔直的长坡,或者滑下一个可以缓冲落地的微凸坡,你会选择哪一个?

操场上的滑梯——一个看起来很陡,另一个开始时很陡,但越往下越陡——作者图片

现在让我们来看一个分类问题。让我们尝试使用 MSE 作为损失函数,因为到目前为止它对我们很有用。在某些情况下,这实际上是可行的。但是有一些问题。最重要的一点是,分类问题的 MSE 不再像以前那样是简单的 U 凸形状,而是可以呈现更复杂的形状。这使得模型很难达到全局最小值。

但这是怎么发生的?从那时到现在发生了什么变化?除非我们首先了解这一点,否则我们可能无法寻求补救办法。让我们来看一个有趣的分类问题。给你一个 30 秒的声音剪辑,并期望你能识别出剪辑中唱歌的鸟类。训练数据具有标识 6 种不同鸟鸣的许多剪辑,使用这些剪辑来训练模型。这肯定是一个分类问题(样本属于哪个纲/鸟种)。它是非二进制的(有 6 个类,样本可以属于其中的任何一个,所以它是一个 多类 模型)。这样的音频片段通常是多标签的(每个测试样本可能有不止一个鸟类物种在唱歌),但是现在为了简单起见让我们假设每个样本只有一个物种,所以 这就变成了一个单标签的 问题。因此,我们模型的最后一层应该预测如下内容:**

样本 1: [0,0,0,0,1,0];样本 2: [0,0,0,0,0,1]

显然,我们的模型不会一直 100%有把握,实际上,最终层的输出可能看起来像这样:

样本 1: [0.1,0.2,0.0,0.0,0.6,0.1];样本 2: [0.0,0.1,0.0,0.0,0.1,0.8]

对于每个样本,我们只取概率最高的值,这是我们对样本中可能的鸟类种类的最佳“猜测”。这很有趣,因为我们的模型需要预测的是一个概率分布!是的,再看一下数据。这是一个经典的概率分布…很像你之前和你最好的朋友交流时用的词的概率分布。

从简洁的线条到匀称的曲线——进入激活状态

不幸的是,默认情况下,这个模型没有给出那种简洁的概率分布。它只是抛出一串从-无穷大到无穷大的数字。这就是 激活 功能 发挥作用的地方。它是一个函数(在一个新的层中定义),接受前一层的输出,并将其转换为下一层可以理解的模式。在我们的例子中,没有其他层,所以激活函数是最后一层。

现在,什么样的函数可以将范围从 (-inf 到+inf) 的输入转换为范围 (0-1) 而不丢失任何信息?原来有一个功能叫做逻辑单元(叫做 logit ),它做的与此完全相反。它接受范围为 (0-1) 的输入,并将其转换为范围为 (-inf 到+inf) 的输出。这是一个简单而优雅的函数,如果' x '是输入,那么输出' L '就是简单的 ln(x/(1-x)) 。我们要做的就是使用这个函数的反面!所以我们的函数应该取一个输入 L 并返回: 1/(1+e 的-L 次方)。就是这样!

由于存在多个类,该公式被稍微修改以考虑所有的输入,由此产生的激活被称为 Softmax 。Tensor-flow 的人开始调用 输入 到 softmax 层作为‘logits’。这并不准确,但是使用这种约定并没有坏处。因此,我们的模型应该在最后一层有一个 Softmax 函数,它接受范围从( -inf 到+inf )的输入值( logit ),并将其转换为范围从 (0-1) 的概率分布。

现在,让我们进一步简化事情。让我们说,我们所要预测的只是在提供的音频剪辑中一只鸟是否在唱歌。这现在是一个二元的问题,T2 不再是一个多类的问题。模型现在只需要预测两个概率:【p,1-p】,其中“p”是鸟鸣出现的概率,“1-p”表示没有鸟鸣(实际上,它只需要预测‘p’)。对于这种情况,softmax 激活功能有一个特殊的名称,称为 Sigmoid 。**

当我们添加像 Softmax 或 Sigmoid 这样的激活函数时,模型就变成了非线性。直觉上,这是有道理的。当我们有一个像 1/(1+e 的 L 次方),这样的函数时,我们知道绘制输出不会产生一条漂亮的直线。事实上,您可以尝试绘制 sigmoid 函数的输入和输出的可能值,您会看到您得到一个漂亮的 S 形!

模型的决策边界不再局限于直线(即“直线”ar ),而是可以自由采用其他复杂形状。事实上,这就是激活函数的作用。它们可以帮助网络学习分离数据的复杂模式。请看这个简单的分类练习

作者图片

无论你的神经网络有多深,都没有办法画出一条直线来区分正方形和长方形。然而,一个简单的非线性函数,如 x + y = r,在绘制时,可以产生一个整洁的圆来分隔这两个类。

术语“激活”有生物学根源——为“激活”下一组神经元而做的预处理。如果没有激活函数,神经网络本质上是线性的——我们只需将输入乘以权重,添加一个偏差,然后将输出传递到下一层,并不断重复这一过程,直到到达最后一层。从头到尾都是线性的。如果我们应用激活,我们将非线性带入模型

如果我们在上述场景**中使用 MSE 作为损失函数来测量预期预测概率分布之间的差异, 给出了一个非凸形状 …而不是我们之前在回归情况下看到的具有单一全局最小值的清晰凸 U 形。当模型下降时,它可能会落在局部极小点上。**

图片由作者提供—我真诚地为我的绘画技巧道歉…想在幻灯片上画一个孩子,但结果是一个食人魔

这个问题不是不可克服的,但我们肯定希望探索更简单的替代方案。如果不是 MSE,那么什么可以作为亏损?嗯,我们如何衡量“预期”和“预测”概率分布之间的差异?在比较两个不同的概率分布时,我们可以使用什么样的度量?

再次输入克劳德·香农和熵!

我们之前看到,交叉熵(CE)给出了两个概率分布之间差异的度量。如果分布彼此远离,则 CE 较高,随着分布越来越接近,CE 不断降低,直到最终达到熵值,此时,分布完全相同。所以一个简单的损失函数可以是 CE。给定训练数据,我们只需要尽可能地将其最小化。这是分类任务中通常要做的事情。

从 CE 中减去熵,然后用这个差值作为损失函数怎么样?那不是更优雅吗?我们的模型可以被训练成将这种差异降低到零。事实上,这个结果实体(从 CE 中减去熵之后)有一个致命的名字叫做kull back–lei bler divergence,谢天谢地,它被缩短为 KL-divergence。如果概率分布相同,KL-散度为零,并且根据两个分布的不同程度而增加。

我们的损失函数可以是最小化 CE,甚至最小化 KL 散度。两者都工作,并给出很好的梯度友好的输出!CE 计算起来稍微容易一些,因此是首选,但也有 KL 散度有用的情况,例如自动编码器。

总之,CE 通常是分类的损失函数选择—

  • 二进制分类的情况下,最后一层只有一个神经元,激活是一个 sigmoid ,输出是“ p ”,可以表示为*概率分布【p,1-p】。损失是(二进制)* 交叉熵 **
  • 多类分类的情况下,有“ n 个输出神经元——每个类一个—激活是 softmax ,输出是大小为“ n 的概率分布,例如[0.1,0.1,0.6,0,0.2]的概率加起来为 1,损失是(分类) 交叉熵。
  • 多标签分类的情况下,有“ n 个输出神经元——每个类一个——激活 s s 型 【每个神经元一个】,输出是大小为“ n 的分布,如[0.1,0.3,0.9,0 该输出被转换成n-二进制概率分布并且损失是“n二进制 交叉熵 损失的总和(或平均值)。暂时把这个特别的损失放在一边,我们很快会详细讨论它。

虽然 CE 损失(二进制或其他)是正确的术语,不需要任何其他名称,但许多框架使用对数损失、多项式逻辑损失等术语。让情况变得复杂的是,框架经常将激活层功能与损失函数结合起来,并用一个新的名字来称呼它。例如在张量流中:

  • Sigmoid 激活+ CE 损失=sigmoid _ cross _ entropy _ with _ logits
  • Softmax 激活+ CE 损失=soft max _ cross _ entropy _ with _ logits

在一些框架中,损失函数的输入参数决定损失函数是否应该表现为仅仅是常规损失函数,或者决定也扮演激活函数的角色。例如,Keras 中的CategoricalCrossentropyloss 函数接受一个名为'from _ logits的参数,如果该参数设置为 true,将导致该函数首先激活,然后丢失。如果没有指定,函数期望它的输入来自激活层。

偶尔,你可能会碰到文献(例如 Keras 分类交叉熵函数文档)提到结合激活和损失函数更“数值稳定”。不幸的是,细节没有提供,读者留下了挥之不去的好奇心。原因是在这些函数中,极限 logit 值被剪切以避免溢出&下溢错误。这稍微破坏了四肢的损失。我偶然发现了一些有趣的实验,这些实验似乎表明,通常选择并没有什么不同。

接下来的两个部分涵盖了概率分布的一些基本信息,这些信息虽然与主题间接相关,但同样重要。

但是什么是概率分布呢?

在上面的讨论中,我们对什么是概率分布有了直观的感受,尽管我们没有以任何方式定义或讨论它。由于你对 Gavaskar 的着迷,对于 Gavaskar、Botham、Hadlee 和 Richards,你的词汇中单词的概率分布分别为[50%、25%、12.5%、12.5%],而对于相同的单词序列,你的朋友为[12.5%、12.5%、25%、50%]。概率分布包含 0 到 100%之间的值,所有这些值加起来是 100%。他们通常遵循某些疯狂的模式。在任何人类对话中,单词的概率分布通常遵循齐夫定律。最频繁出现的单词的出现频率大约是第二频繁出现的单词的两倍,第三频繁出现的单词的三倍,等等。

这是一个非常有趣的话题,一些常见类型的概率分布已经得到了非常详细的研究。最简单的分配是抛硬币。你有 50%的机会正面或反面。让我们假设一个结果是成功的(为什么总是正面?).这是一个伯努利事件,相关的概率分布是一个伯努利分布(为了简单起见,我们将只讨论前面的相关分布)。

伯努利的概率不需要使为 50:50,而是需要加起来为 1。有两种概率为 p(1-p) 的结果。如果你掷骰子,赌 3 号会出现,你有 p = 1/6 和 (1-p) 为 5/6,这就是伯努利。一次又一次地重复伯努利,给我们一个二项式分布。每次重复称为一次 审判 。比如说,你连续投掷硬币 1000 次或者说出 1000 个单词,那么试验次数 n = 1000。如果‘p’是成功结果的概率,那么成功事件的总数是 np** 。二项式分布表示对于给定值‘n’的成功和失败的各种组合,例如‘n’次成功和 0 次失败的概率是多少,( n-1)次成功和 1 次失败的概率是多少,0 次成功和‘n’次失败的概率是多少等等。***

然后,还有正态分布或高斯分布,它们中最著名的。无论是人类的平均身高,还是学生的体重或考试分数,或者他们的智商或血压,高斯分布都以钟形曲线的形式表示宇宙中的许多情况。

例如,如果你要画出地球上所有人的平均身高,你会得到一条钟形曲线。许多值落在中间 5 英尺 6 英寸的某处,其余的值落在两边,随着我们向两个极端移动,这些值迅速变为 0。大约 70%的人会在 5 英尺 6 英寸左右的任何一边出现 1 英尺左右的小偏差。我们有一个专门的术语来描述这种偏差——它旨在测量值在中心周围的分布,称为标准差或 sigma

大约 95%的人会落在两边的 2 个标准偏差内(所以 95%的人会有 3'6 到 7'6 之间的身高),而 99.999999%的人会落在中间的 6 个标准偏差或 6-sigma 内。换句话说,大约五亿个样本中有一个落在 6 sigmas 之外()不要问我这个星球上 13 个 1 英尺或 11 英尺的人的下落,我并不完全是这个钟形曲线的粉丝……这有点过头了……然而在大多数情况下,在没有更好的替代方案的情况下,这被证明是一个合理的近似值。当人们开始把这个钟形曲线当作真理时,问题就出现了——就像企业在评估期间的情况一样。作为旁注,质量行业的 6-sigma 被定义为百万分之 3.4 的缺陷,而不是五亿分之一。所以质量上的 6-sigma 实际上是 4.5-sigma。

泊松:一个我们必须知道的特殊分布

如果你站在一家美容院外面,数一数每小时进入美容院的顾客人数,你面对的是泊松分布。你已经听说这家特定的美容院每年都会吸引 10K 游客,并且渴望投资,但是你想要更详细的信息,例如每天或每小时有多少顾客进入该美容院。在某种意义上,它与二项分布没有太大的不同。路人进入可以被视为成功事件,而路人不进入可以被视为失败事件。如果你的美容院每天营业 8 小时,每个小时可以被视为一个轨迹(so n=8 ) ,如果你有一个顾客在一小时内进入美容院的概率'p',你可以利用二项式分布来计算各种概率(例如,每天有 0 个顾客进入的概率是多少( 0 个成功,8 个失败) 1 个客户进入的概率是多少( 1 次成功,7 次失败),8 个客户进入的概率是多少(8 次试验全部成功,0 次失败)等等。**

但是这种模式存在明显的挑战。二项式不能满足在一个单位时间内同时发生的多个试验。在这里,一个小时内,可能不止一个人进去过。你在单位时间内有多种结果,虽然这对你的业务有好处,但这也给你带来了问题,因为从数学上来说,你的公式没有考虑到这种情况。

但是你有一个简单的解决方法。将时间范围从 1 小时缩短到 1 分钟。现在你确定每个时间单位最多有一次试验,你仍然可以使用二项式公式。但是你很小心地在计算中使用概率值作为' p/60 ,而不仅仅是' p 。由于试验' n '的次数从每天 8 次增加到每天 8*60 次,p 减少了。

让我们举个例子来更好地理解这一点。如果平均每天你得到 4 个客户,每个小时算一次试用,那么 n =8, p =0.5。如前所述,乘积 n*p 给出的成功次数为 4。一切都加起来,你现在可以自由地使用二项式计算各种概率分布。现在想象一下,你开始考虑每分钟进行一次试验。在这种情况下,每天的试验次数' n' 变为860=480。 p ' 应该减少到' 0.5/60' 因为产品 **np 不能改变…你不能继续用 p =0.5,对每天获得 480 * 0.5 个客户的前景垂涎三尺。这个数字仍然是 4,不会因为你用分钟而不是小时来计算而增加。**

到目前为止,一切顺利。但是如果一大家子人进店会怎么样呢?你进一步把你的时间单位减少到 1 秒。事实上,现在你已经厌倦了这一切,为了避免所有进一步的麻烦,你继续减少时间单位,直到达到一个极小的值,以至于你可以保证在这个小时间间隔内最多只能发生一个事件。不知不觉,你已经来到了阿松!它需要一个单独的名字,因为我们已经偏离二项式太多了。此外,它具有不同的有用属性。首先,你不再需要知道' p 或' n 的数值。这是因为,如果我们无限小地划分时间,试验的次数' n '(每单位时间一次)趋向于无穷大。现在,这并不意味着你将获得无限的顾客…当' n '趋近于无穷大时,成功结果的概率' p '必然趋近于零(在该时间单位内进入你的商店的人)。因此' n '和' p '本身没有任何意义,我们也不需要它们。我们想要的只是产品 n*p ,无非是一段时间内进入商店的人数,这个产品用 λ 表示。

因此,如果你知道 10K 人在一年中进入这家店( λ =10000),那么,使用泊松,你可以很好地模拟在 1 小时、1 天、1 周、甚至 10 年中进入这家店的顾客数量——根本不需要' n 或' p '。这是很有用的,因为你只知道这家美容院每年接待 10K 游客,但你可能不知道这家美容院一天开放多少个小时,所以你可能无法计算' n '和' p '。泊松在这种情况下非常有用。

如果你开始计算每个顾客到达的时间间隔,指数分布是泊松分布的一个有趣的分支。这是一个连续分布,不像二项式或泊松分布给出离散输出。掷骰子永远不会是 3.5,顾客可以进也可以不进美容院,没有第三种选择。在指数分布的情况下,输出是连续的时间。

太棒了。但是我可以问一下这些和损失函数有什么关系吗?

我们偏离了预期,但是获得各种概率分布的直观感觉真的很重要。CE 就是比较两个概率分布,如果不先理解概率分布,我们就无法理解 CE。此外,不同的分布可以与不同的损失函数相关联。因此,如果训练数据来自某个先验已知的概率分布,我们可以应用相关的损失函数。例如,在高斯分布的情况下,MSE 作为损失函数做得很好。对于泊松分布,我们有泊松损失。在二项式分布的情况下,CE 是可以使用的适当损失版本,这可以通过数学推导得出。

但是我们这篇文章的前提是没有数学,只有故事和直觉!上面 Shannon 的故事引导我们将 CE 作为潜在损失函数。现在让我们看看是否能直观地想出任何其他的损失函数来进行分类。这个函数应该做什么?显然,它需要严厉惩罚坏的预测,奖励好的预测。如果预测的概率是 1.0,类是标签,那么模型做得很好,损失应该是 0。如果模型预测这个样本为 0.0,那么它做得很差,需要被扣分。在这种情况下,损失=无穷大是最理想的。对于 0.0 和 1.0 之间的任何其他概率预测,模型应根据其偏离的程度进行适当的惩罚…对于接近 1.0 的概率预测,损失应从 0 移动,对于 0.0 的预测概率,损失应接近无穷大。这是一种指数增长,自然对数函数是损失函数的合适候选。所以数学函数— ln (p) 正是给了我们想要的! ln 代表自然对数,即基数为“e”的对数,其中 e = 2.718…

但这只是故事的一半。如果这个类是一个标签会怎么样?在这种情况下,我们希望发生相反的情况…对于 0.0 的概率预测,损失函数应该为 0,并且随着概率预测增加到 1.0 而增加到无穷大。这不是别的,就是 ln (1-p) 。我们不能有两个独立的损失函数,如果我让你想出一个解决方案,你可能会想出:loss = y * ln(p)+(1-y) ln(1-p)其中' y' 是正在讨论的标记类,它可以是* (1 或 0)。我们必须将上面的等式乘以-1,因为概率的自然对数总是-ve(或者,如果您选择保留-ve 符号,您可以为您的模型编写一个最大化函数,而不是编写一个最小化函数)。上面的等式是针对一个数据样本的。我们对训练数据中的所有样本取这个损失的平均值。**

瞧啊。我们又回到了克劳德·香农和熵。我们看到,我们最终得到的函数与我们之前用来计算交叉熵的函数相同。这里,分布 A 和 B 是**expected = [y, 1-y]****predicted = [p, 1-p]**。不过,还是有一点不同。这里的对数是以 2 为底,这里似乎是以 e 为底。我们可以选择使用以 2 为底的对数,这不会对最小化函数产生任何影响,因为要从以 2 为底的对数转换为以 e 为底的对数,我们只需乘以一个常数。纯粹为了方便起见,许多框架库都使用 log-e,但是如果您是 Shannon 的铁杆粉丝,并且不想偏离他的 ce 版本哪怕一点点,那么您可以编写一个使用 base-2 的自定义损失函数,同样可以很好地工作。

偶尔,你的模特也需要戴面具

让我们快速理解我们的主角——竞赛获胜者——使用的其余两个术语。这些是'遮蔽的和'聚焦的。前者很容易。有时你有训练数据,其中标注部分完成。比方说,模型需要识别图像中 5 个物体的存在——猫、狗、牛、山羊和老虎。也许所有的猫和狗在所有的图像中都被正确标记,但是牛、山羊和老虎被部分标记。所以我们可以有这样的东西:

样本 1: [1,1,0,-1,1]样本 2: [0,1,1,1,-1]**

这是一个多标签(每个数据样本可以有多个标签)多类(有 2 个以上的类)场景。在第一个样本(图 1)中,有一只猫和一只狗,绝对没有牛。可能有也可能没有山羊,肯定没有老虎。在第二个样本中,肯定没有猫,有一只狗、一头牛和一只山羊,可能有也可能没有老虎(要么贴标签者不确定,要么有其他个人承诺,并为当天早早打包)。

给定这种数据,我们如何充分利用我们的模型?用“0”代替“-1”来训练模型可能不是好主意。该模型将假设图像 1 中没有山羊,图像 2 中没有老虎,并相应地进行训练。但是如果是一只潜伏在图片 2 中的老虎呢?这将导致模型次优。它可能无法非常准确地识别老虎。更好的选择是告诉模型在训练时忽略-1。假设有 1000 个其他样本,在其他标记为“1”的图像中会有足够多的山羊和老虎,因此忽略一些其存在可疑的样本不会损害模型。****

我们如何让一个模型忽略-1?一种选择是删除所有含有“-1”的样本,但这将意味着丢失大量其他数据。另一种选择是在计算损失函数时忽略-1。因此,如果您的模型在训练时对上述第一个样本给出的预测值为[0.9,0.8,0.1,0.4,0.9],而期望值为[1,1,0,-1,1],那么我们不是计算 5 个结果的 CE,而是计算 4 个结果[0.9,0.8,0.1,0.9]的 CE,将[1,1,0,1]作为相应的期望值。读者可能会感觉到这里有些不对劲。然而,现在请随波逐流,我们将在几句话后重新审视这篇文章

只要期望值为'-1 ',我们就可以通过创建一个简单的掩码来实现这一点。所以,对于上面的例子,遮罩应该是【真、真、真、假、真】。然后,我们将预期预测值的屏蔽版本提供给损失函数。或者,大多数框架的损失函数已经有某种内置特性来屏蔽不想要的标签。例如,PyTorch 将 ignore_index 选项作为损失函数的输入。当 size_average 设置为真时,损失在未被忽略的目标上平均。然而,如前所述,许多人更喜欢一起计算损失和激活。因此,建议使用直接采用逻辑值的损失函数,并将预期值预测值的屏蔽版本输入该函数。

但是,等一下!上面有什么问题吗?预测的概率分布怎么可能一开始就是[0.9,0.8,0.1,0.9]?期望概率分布怎么可能是[1,1,0,1]?根据定义,概率分布应该具有加起来为 1 的概率。我们不能只是扔一些随机数,还指望 CE 还能工作。这里发生了什么事?嗯,解释很简单——你看到的是而不是用于计算 CE 的概率分布。这些被转换成多个二元概率分布(伯努利分布)。所以实际情况是:

[0.9,0.8,0.1,0.9]变成了[0.9,0.1],[0.8,0.2],[0.1,0.9] & [0.9,0.1]

[1,1,0,1]变成了[1.0,0.0],[1.0,0.0],[0.0,1.0],[1.0,0.0]

现在,框架分别为这 4 个分布计算 CE(为 4 个中的每一个计算一个二进制 CE),然后将结果相加(或平均)。这是使用的最终 CE,并给出了(多标签)预测值与预期值差异的精确度量。因此,如果您看到多标签问题,请始终记住使用二进制 CE ( BCE )损失和 sigmoid 激活。

因此,我们有一套简洁的规则——单 BCE 和 sigmoid** 用于一个二进制分类,单 CCE ( 基本上是非二进制 CE——我们只是称之为分类 CE 而不仅仅是 CE) 和 softmax 用于一个多类问题,多个 BCE 和一个 sigmoid 用于一个*大多数时候,人们会努力遵守这些规则。***

不过接下来还有那些 有违和感的!

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

矩阵重新加载场景—

巴拉德: 你在要求我们中的一个人违抗直接命令。

语素: 没错,我就是。但是我们都很清楚,我们大多数人在这里的原因是因为我们对不服从的亲和力。

你可能会遇到一些模型,在这些模型中,带 sigmoids 的 BCE(s)用于多类、单标签问题,而不是带 softmax 的 CCE。有意义吗?如果我们使用 CCE,我们以这样一种方式约束个体概率,它们加起来等于 1…这意味着输出相互依赖。在多个 BCE 的情况下,没有这样的限制—模型可以更有创造性。这在某些情况下会有帮助吗?我不确定。

下一个区别是,CCE 模型在损失计算中仅考虑正面类别的声音。根据定义,CCE 是 {p 来自分布 B} 中对应 p 的分布 A * ln 的总和,其中 A 是预期的,而 B 是预测的概率分布在多类别单标签情况下,预期概率分布有一个 1 和几个 0。这意味着 CCE 公式最终简化为仅 ln (p) ,其中“p”是样本中 lone +ve 类别的预测值。所以损失完全取决于+ve 阶层的声音。****

另一方面,如果使用一组‘n’BCE 而不是单个 CCE,那么每个类——正的或负的——都会造成损失。如果预期= [1,0,0]预测= [.7,. 1,. 2] ,那么 CCE = ln(.7) 而多 BCE 损失法给出预期= [1,0],[0,1],[0,1]预测= [.7,.3],[1,.9],[2,.8] 。将各个 BCE 相加得到损失为ln(. 7)+ln(. 9)+ln(. 8)。您可以看到-ve 是如何造成每个样本的损失的。这是好是坏?我不确定,但也许在某些情况下会有帮助。请注意,在这两种情况下,损失继续准确地给出分布差异的度量,尽管规模不同。

现在,让我们看看使用 CCE 代替多 BCE 进行多标签分类的情况。听起来可能有点反直觉,但脸书在这篇论文中做到了!它是怎么工作的?直觉上,这没有数学意义。我们之前讨论过。概率加起来不等于 1,所以我们甚至不能称预期值预测值为概率分布。但首先,让我们试着理解为什么人们在探索各种选择。使用多 BCE 有一个很大的缺点,当有很多标签时就会出现这种情况。从训练我们的模型识别图像中的一只猫,甚至一组 4-5 只动物,我们已经走了很长的路。现代模特必须处理 1000 个标签。这就提出了一个阶层失衡的有趣问题!

我们之前看到,在多 BCE 方法中,负类会导致丢失。想象一下这样一种情况,有 1000 个潜在的类,但是每个样本只包含两个。对于任何特定的样本,2–3+ve 类的声音都被 998 -ve 类淹没了。损失函数不再那么高效了!CCE 的方法在这里会很好,因为损失的公式只考虑了+ve 的声音。不幸的是,CCE 给出了两个概率分布之间的差异度量,类似于【1,0,0,0,1,1,0,0】是而不是一个概率分布

脸书所做的是将每个期望值除以样本中+ve 的数量。所以[1,0,0,0,1,1,0,0]变成了[.3,0,0,0,.. 3,0,0]。现在用的是带 softmax 的 CE。显然这是有效的!

一个更简单的替代方案可能是继续使用多 BCE,但丢弃-ve 类的损失。此外,由于我们是在掩蔽的主题,我有另一个有趣的方法。为什么不在这里好好利用掩蔽呢?创建 3 组期望值—每组包含一个+ve 类。然后,我们可以使用屏蔽来为预测的值生成相应的逻辑和概率。因此,上述样本的 T18 期望值 T19 将为[1,0,0,0,-1,0,0],[-1,0,0,0,1,-1,0,0]和[-1,0,0,0,-1,1,0,0]。然后,我们用-1 屏蔽标签的 softmax,并生成 3 组预测值,,然后单独计算 CCE,然后将这 3 个 CCE 相加。这将是我们这个特定数据样本的总 CCE。到目前为止,我还没有遇到过这种损失,但请放心,多标签损失函数是 ML 中一个不断发展的领域,在未来的日子里,我们将会看到许多多 BCE 的替代品。

另一个有趣的情况发生在框架基于选择的损失度量准确性度量做出一些假设的时候。这有时会导致令人惊讶的结果,而这篇由 desertnaut 完成的整洁的侦探作品是一个很好的读物。

这个精彩的内核展示了另一个作者调查 BCE 损失指标对模型评估指标没有太大影响的原因,并提出了一个好的替代方案。

让我们把焦点转移到最后一个故事——焦点丢失

通常情况下,还会有其他阶级不平衡的情况。在计算机视觉中,识别图像中物体的一种方法是标出几千个“可能”有物体的区域,然后检查每个区域并识别物体(如果存在的话)。这通常分两个阶段完成。第一阶段,识别所有潜在的区域,第二阶段,检查每个区域,然后模型决定它是否有对象。如果我们试图将这两个阶段结合起来,这个模型就会遇到阶级不平衡的问题。在 1000 个潜在区域中,几乎没有几个可能包含物体。大多数时候模型找不到对象。在训练过程中,这会导致一个问题。您看到了多 BCE 方法如何淹没了少数积极样本的声音。我们可以继续使用多 BCE 方法,但想出一个黑客来减轻这种影响吗?

一种解决方案是将所有正例乘以常数' α ,将所有负例乘以' 1-α '。这实现了什么?在上面的例子中,如果α = 0.99,那么 1-α = 0.01,那么乘法之后,lone +ve 类的权重不会有太大的变化,但是 99 -ve 类的权重会大幅度下降,因为每个类都乘以 0.01。(我现在看到——在研究焦损失时——当α= 1 时,我在上面提出的忽略-ve 样本损失的第一个建议已经是一个很好的方法了)。

于是 CE 现在变成了-α ln(p)为正类-(1-α) ln(1-p)为负类。

除此之外,这个解决方案几乎没有给出预期的结果。递减效应起了作用……但不是很令人满意。于是,除了α,还有了与 (p 的γ次方) 的乘法。于是负类损失就变成了:- (1-α) ** (p 的γ次方) ** ln(1-p)。

这有什么帮助?这里首先要强调的是' p ' always 指的是类为正的概率,( 1-p )指的是类为负的概率。无论我们是计算+ve 样本还是-ve 样本的损失,都不会改变。现在,让我们重新看看上面的公式。由于' p '总是小于 1,当我们将' p '提高到一个幂时,我们进一步降低了这个值,因此大大降低了负面类的声音。太棒了。但是这种乘法还实现了其他的东西。对于那些模型非常有信心的负类,它增加了递减效应

让我们取 2 个类……比方说,模型预测第一个的 p=0.01,第二个p=0.99。因为' p '是一个类为正的概率,( 1-p )给出了该类为负的概率。因此,在第一种情况下,模型对-ve 类具有高置信度(99%),而在第二种情况下,模型对-ve 类具有低置信度(1%)。 p 对γ 的幂对于等级 1(对于【γ】的任何值)*** 来说是非常非常低的,因此当这个低值乘以原始损耗公式时,其对总损耗的影响严重减弱。对于类别 2, p 对γ 的幂接近于 1,因此没有区别。*****

因此,我们最终要做的是严重削弱容易归类为 -ve 的的声音。易分类’顾名思义就是模型预测为-ve 的那些类,可信度很高。这很有帮助,因为在上面的上下文中,绝大多数的类都是-ve 的,并且它们中的绝大多数很容易被分类。总而言之,焦点缺失通过两个技巧降低了大多数人的声音:

  • 使用 α 参数对+ve 类的损失赋予更大的权重,并减少-ve 类的权重
  • 使用 γ 参数降低容易分类的类的权重(注意,在上述上下文中,考虑到-ve 类的绝对大小,大多数容易分类的类是-ve 类,并且这些类中的大多数是容易分类的**

敏锐的读者可能对上面的第 2 步仍有疑问。根据定义,CE 损失不是设计为对于简单分类具有最小值,而对于硬分类具有高值吗?她可能会问,为什么我们需要所有这些额外的噱头。假设一个给定的类是-ve,模型对它有 100%的把握(所以 p=0%,1-p=100%)。该类的传统 CE 损耗被计算为 0,因此这不会对该批次的总损耗产生任何影响。那么,为什么所有这些令人头痛的事情会削弱那些容易归类为 ve 类的人的声音呢? 亏损已经是 0 了吧?没错,但是并不是所有的 ve 类都有 100%的可信度。可能有许多许多种类的模型可能有 90–99%的置信度,尽管这些种类的损失值最终非常接近零,但它们不是完全等于零。由于-ve 样本的庞大规模,所有这些小值加起来最终会造成麻烦。为了避免这种情况,第 2 步是必须的。它最终会把所有这些损失推得比以前更接近于零。

作者图片

所以焦损(嗯我们需要一个新名字,既然不能再叫它 ce 损了)是:- α * (1-p)的γ * ln(p)次方 为正类, -(1-α) * p 为γ * ln(1-p) 为负类。在我们的组合技巧之后,我们得到

焦损为 BCE = -[ y * α * (1-p)的γ ln(p)+(1-y)(1-α) p 的γ * ln(1-p)* 的幂****

脸书的一个团队做到了这一点,现在这是计算机视觉领域的前沿解决方案!但我确信,如果到了紧要关头,你也会拿出同样的东西。优化这个模型还需要一个步骤…有时,你可能会注意到这个损失不容易收敛,训练似乎会持续下去…这是因为模型可能会用来自高斯分布的权重进行初始化。因此,生成的初始概率输出集是高斯型的,如前所述,几乎 70%的输出值将落在中心附近。我们上面所有精心策划的公式都假设该模型能够对-ve 个样本进行大量的简单分类。但是在第一次迭代中,模型无法做到这一点。初始化算法迫使它生成一组概率输出,其中大部分位于 p=0.5 附近,因此大部分输出是不易分类!这使得整个损失计算陷入混乱,并使模型偏离切线方向。

我们如何解决这个问题?要么我们将初始权重从高斯改为更合适的值(我们花了数年时间来完善我们今天使用的权重初始化方案,所以这可能不容易),要么尝试更好的收敛优化器,或者像脸书团队那样做。他们在训练开始时调整了最后一层的偏差,以返回接近零的概率值,从而达到类似的效果!当' p '接近 0 时,这意味着模型高度确信该类是-ve。这正是我们想要的!我们已经把模型带回了正确的轨道!在同一篇脸书论文的偏僻角落里,还藏着另一行有趣的文字,引起了我的注意——“我们将计算 p 的 sigmoid 运算与损失计算结合起来,从而提高了数值稳定性。

CE 和 Shannon——最后一次

  • 我们阅读关于 CE 的故事以及它是如何测量概率分布差异的好方法
  • 我们知道在数学上,对于二项式概率分布,CE 是一个很好的计算损失的函数
  • 当我们直觉地试图导出分类的损失度量时,我们最终得到了 CE 的公式。

尽管走了三条不同的路线,我们还是不断回到克劳德·香农和熵的问题上来!他的信息论论文被称为“可能是本世纪最重要的硕士论文”,开创了一整个研究领域。香农本可以留在这一切的中心,但他继续追求其他兴趣,完全远离聚光灯。1985 年,在一次信息理论研讨会上,他罕见地出人意料地出现了。消息迅速传遍大厅,人们立即开始接近他,请求与他交谈。他说了几分钟,然后——担心他会让听众厌烦,从口袋里掏出三个球,开始变戏法。观众欢呼着排队签名。正如一位与会者回忆的那样,这就好像牛顿出现在一次常规的物理学会议上一样!

传统上,人类总是痴迷于大小和宏伟。在 ML 竞赛中,每一个获胜的解决方案都比其他方案更复杂,更有力量。使用并展示了具有大量处理能力和时间的定制 GPU。我的书签标签中充满了令我兴奋的不同种类的珍宝…来自不同头脑的小而有效的黑客,展示了解决问题的另一种方法。这些几乎从来都不是赢家,但同样,这些解决方案为 ML 社区提供了更多的价值。

我们正处于资源无限的时代,我们的模型中使用的处理能力没有任何限制,但随着我们向前发展,我们可能会看到节俭在 ML 竞赛中受到鼓励甚至奖励。优雅的特征工程是实现节俭的一种方式。另一个重要的杠杆是“损失工程”。彻底理解损失函数并对其进行修改是赢得竞争的关键,更重要的是,是创建良好的 ML 模型的关键!

PS——用 10,000 多字,大多数作家可以写出十几个轰动一时的故事。早些时候,我曾经在超过 1000 个单词时感到内疚,但现在我主要为自己写作,不再在乎了。每个主题都有足够的时间来彻底解释它——不多也不少。

我无法解释现在打字时那种如释重负的感觉……

横断面浓缩咖啡圆盘切片

原文:https://towardsdatascience.com/cross-sectional-espresso-puck-slicing-4caa57366e3c?source=collection_archive---------22-----------------------

咖啡数据科学

探索拍摄后的粒子分布

从准备到扔掉用过的冰球之间的内部情况来看,浓缩冰球是一个相当神秘的东西。虽然理论上粒子分布在圆盘内移动,但是还需要对圆盘进行更多的解剖来检查粒子移动。我的目的是观察一个浓缩咖啡圆盘的横截面,以帮助确定颗粒从上到下的不同。

我从金快车上的普通镜头开始。一个根本性的挑战是水如何进入淋浴屏幕的固有问题。另一个是我想尽可能多地提取。我通常将 1.3 比 1 的输出与输入比例拉至大约 22%的提取率,所以我通过圆盘推动了更多的镜头,以获得与大多数人更相似的输出率。

圆盘切片

浓缩咖啡圆盘坚硬但易碎。我最终做了一些尝试,尝试简单地切冰球的可行性。我开始用一把非常锋利的刀,但这无助于脆弱的本性。我尝试了对角线切割,但切割仍然让事情以不受控制的方式分崩离析。

然后,当我从一个摩卡壶里倒空一个湿冰球时,我有了一个启示;干咖啡渣易碎,但湿咖啡渣粘在一起。在拍摄我真正感兴趣的照片之前,我试着切了一些湿冰球。

我慢慢地从上到下弄湿冰球,以确保它是湿的,但不是湿透的。

然后我斜着切。

我的目标是尽可能多的切割冰球。我最后做了 7 层。

我让这些伤口干了一夜,它们很快就干了。

考试日

我决定分别收集圆盘外部和内部的数据,所以我将外部的数据从内部的数据中切掉。此外,我测量了 gTDS,以了解还有多少可溶物留在地上。

从 gTDS 的角度来看,大多数值都很低。唯一的上升趋势是,当你接近底部时,内部 GTD 上升,但幅度不大。

粒子分布

我查看了原始粒子数,而不是估计它所占的体积。结果,更细的颗粒占更高的百分比,只是因为有更多的颗粒。这是内外圆盘的综合结果:

有一些细微的差别,所以让我们仔细看看,从外层测量开始,只有顶层、中层和底层:

同样,这些也遵循相同的趋势,L7 或圆盘底部的较细颗粒略有增加。但是,L4 并不在顶部和底部的中间。

查看内部测量,我们看到一个类似的模式。分布中似乎有很大的重叠,除了 L7 在 90 微米处有一个轻微的凸起外,没有明显的趋势。

我们可以看看组合测量,模式是相似的。

关注其他层

处理测量误差和了解趋势的一种方法是查看不同的层,看看分布中是否有趋势和变化。我们可以从顶部(L1)到 L4 开始,把 L4 到 L7 放在下面。

这两者都没有显示出任何趋势上的层与层之间的转移。

我们可以用下面几幅提供类似结论的图来分割这些数据。

总的来说,这个实验表明粒子在整个圆盘中的分布是相对相同的,并且似乎没有因为浓缩咖啡而在两个方向上迁移细粒子或粗粒子。细颗粒迁移应该导致底部细颗粒的增加和顶部细颗粒的减少,但是没有观察到这种类型的模式。

很有可能存在测量误差,我更希望对每个样品进行多次测量,但我时间有限。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中和订阅。

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影飞溅页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关话题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

跨主题论点挖掘:学习如何对文本进行分类

原文:https://towardsdatascience.com/cross-topic-argument-mining-learning-how-to-classify-texts-1d9e5c00c4cc?source=collection_archive---------29-----------------------

机器学习

基于使用深度学习的议论文结构对跨主题自然语言文本进行分类

艾蒂安·布朗热在 Unsplash 上的照片

论辩挖掘是自然语言处理和知识表示学习的研究课题之一。辩论涉及逻辑推理,是人类智力所固有的。论元挖掘的目标是教会机器关于论元结构的知识。AM 自动识别和分类文本中的论点。这允许特定搜索与某个主题相关的参数。强大的 AMs 可以在决策、撰写有说服力的文本和分配法律推理中发挥重要作用。

本文展示了使用机器学习库在 Python 中简单、易于理解、快速地实现 AM。这项工作的目标是为挖掘议论文文本创建一个分类管道,给定一个来自各种在线来源的跨主题句子数据集。

正式定义:

“论证是一种口头的、社会的和理性的活动,旨在通过提出一系列证明或反驳观点中所表达的命题来说服一个理性的批评家一种观点的可接受性。”——T4【3】。

资料组

UKP 句子式 AM 语料库[1]是由达姆施塔特大学计算机科学系于 2018 年推出的。这个数据集由涵盖有争议话题的文本组成。它是用谷歌搜索 API 从 400 篇在线文章中收集的。每个句子都通过众包(机械土耳其人)进行了注释。由于可能的版权原因,他们没有发布完整的数据集。然而,从在线文章中收集句子的注释和 java 程序是免费提供的。你可以从他们的网站下载程序来获得完整的数据集。稍后,我们将研究我自己的 AM 管道实现。

“对于每个主题,我们在谷歌上查询主题名称,删除未被 Wayback 机器存档的结果,并将列表截断为前 50 个结果。”— [1]

履行

假设数据已经被清理,在预处理(即删除 HTML 标签、分隔句子)后呈现在 excel 表格中。数据以成排的句子和注释的形式出现,总计约 25000 个输入输出对。

数据由八个有争议的话题组成:堕胎克隆死刑枪支管制大麻合法化最低工资核能,以及校服

主题分布-按作者分类的图片

探究数据,我发现超过一半的标注句子不是一个论点。这是符合逻辑的,因为议论文是观点(主张)。接下来是非论证陈述(前提),反驳或阐述相应的观点。标签的分布可以在下图中看到。文本分类问题有三个标签:

  • 不是争论
  • 反对的论点
  • 为...辩护

标签分布-按作者分类的图片

我的这个 AM 任务的数据管道如下:

参数挖掘管道-按作者分类的图像

现在,让我们直接进入编码。

导入库:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import string
from string import punctuation
import nltk
from nltk.corpus import stopwords
nltk.download('stopwords')
nltk.download('punkt')
import tensorflow as tf

从 excel 表中读取数据:

data_raw= pd.read_excel('data_raw.xlsx')     
fig, ax = plt.subplots(figsize=(16,4))
sns.countplot(x='topic',ax=ax,data=data_raw)

训练数据将仅包括七个主题,不包括校服的主题,其将是测试集的主题

train_raw = data_raw[data_raw.topic != 'school uniforms']
test_set = data_raw[data_raw.topic == 'school uniforms']

目的是验证模型的预测能力。

对于跨主题:给定校服测试集,模型的任务是将每一句话归入三个标签中的一个,之前从未见过该主题。

预处理

不管议论文的结构如何,在一个英语句子中经常会用到许多单词。此外,模型用数字来表示数据。因此,在自然语言处理技术中,去除停用词和一次性编码通常是必要的。

删除停用词

停用词是对句子没有什么意义的英语单词。它们可以被过滤而不会显著改变句子的本质。

def remove_stopwords(text):
    stpword = stopwords.words('english')
    no_punctuation = [char for char in text if char not in  
      string.punctuation]
    no_punctuation = ''.join(no_punctuation)
    return ' '.join([word for word in no_punctuation.split() if 
      word.lower() not in stpword])train_raw['data'] = train_raw['sentence'].apply(remove_stopwords)
test_set['data'] = test_set['sentence'].apply(remove_stopwords)

例如,中的 the,he,you,we,as,For,have,this,that,do 被认为是英语中的停用词。这减少了数据的大小,并且提高了以后的训练效率。

例句——作者图片

一键编码

这种技术允许用二进制表示分类数据。因为我们有三个标签,注释将被编码成三位数的二进制,其中“1”表示真实,其他的都是零。

#Training data
train_one_hot = pd.get_dummies(train_df['annotation'])
train_df = pd.concat([train_df['data'],train_one_hot],axis=1)
y_train = train_df.drop('data',axis=1).value#Test data
test_one_hot = pd.get_dummies(test_df['annotation'])
test_df = pd.concat([test_df['data'],test_one_hot],axis=1)

这个实验处理三个标签,所以将有三列来表示标签。示例训练数据如下所示。

一键编码—按作者分类的图像

特征抽出

在提取特征之前,必须将输入句子转换成向量。为此,将使用 scikit-learn 库中的 CountVectorizer()创建一个基于训练数据的词汇表。这种将文本转换成向量的过程有时也称为“标记化”

from sklearn.feature_extraction.text import CountVectorizer #Define input
sentences_train = train_df['data'].values
sentences_test = test_df['sentence'].value#Convert sentences into vectors
vectorizer = CountVectorizer()
X_train = vectorizer.fit_transform(sentences_train)
X_test = vect.transform(sentences_test)

词汇列表—按作者分类的图片

然后,训练数据集将适合词汇表。fit_transform()方法将每个句子转换成一个大小为 21,920 的数组。X_train 将是一个大小矩阵(句子数 x 21,920)。这被称为计数矩阵,因为 vocab 的频率将在每个句子中计数,以数学方式表示数据。为了更好地理解数据,让我们形象化地描述一下令牌频率。

#Visualize word frequency
from yellowbrick.text import FreqDistVisualizer
features   = vectorizer.get_feature_names()
visualizer = FreqDistVisualizer(features=features, size=(800, 1000))
visualizer.fit(X_train)
visualizer.finalize()

词频分布—按作者分类的图片

hapax (名词)

hapax 一个在一部作品或一类文学作品或某个作者的作品中只出现一次的词[【www.collinsdictionary.com】T4]。

可以看出令牌出现的最多,其次是死亡。不出所料,诸如克隆堕胎大麻等有争议的话题词汇都出现在最常见词汇列表中。

Tf-idf

词频-逆文档频率(tf-idf)为每个词分配权重以提取特征。这种统计方法在搜索引擎和推荐系统等信息检索应用中很常见。

tfidf = TfidfTransformer()
X_train = tfidf.fit_transform(X_train)
X_train = X_train.toarray()

模型

我管道中的深度学习模型只是一个完全连接的神经网络。这些层配备了 L2 正则化和 ReLU 函数,但输出层除外,它实现了 softmax 函数。为了防止记忆,还对每一层实施辍学。

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.regularizers import l2def create_deep_model(factor, rate):
    model = Sequential()      
    model.add(Dense(units=4096,kernel_regularizer=l2(factor), 
      activation='relu')), Dropout(rate),
    model.add(Dense(units=512,kernel_regularizer=l2(factor),
      activation='relu')), Dropout(rate),
    model.add(Dense(units=512,kernel_regularizer=l2(factor),
      activation='relu')), Dropout(rate),
    #Output layer
    model.add(Dense(units=3, activation='softmax'))
    return model

让我们使用参数 L2 因子 0.0001 和退出概率 0.2 来创建模型。

model= create_deep_model(factor=0.0001, rate=0.2)
model.summary()

Tensorflow 中的深度学习模型—图片由作者提供

可以使用 Adam optimizer 以 0.001 的学习率和 128 的批量来训练该模型。分类交叉熵被用作训练的损失函数。提前停止是为了防止过度拟合。实际上,这个模型根本不会达到收敛。使用构建的词汇和异构数据,模型很难区分支持和反对的论点。

early_stop = EarlyStopping(monitor='val_loss', mode='min',   
  verbose=1, patience=5)
opt=tf.keras.optimizers.Adam(learning_rate=learningrate)
model.compile(loss='categorical_crossentropy', optimizer=opt,   
  metrics=['accuracy']) 

在拟合之前,数据被分成训练(75%)和验证(25%)。

#Split data
X_train_enc, X_val, y_train_enc, y_val = train_test_split(X_train, y_train, test_size=0.1, shuffle= False)#fit the model
history=model.fit(x=X_train_enc, y=y_train_enc, batch_size=batchsize, epochs=epochs, validation_data=(X_val, y_val), verbose=1, callbacks=early_stop)

估价

“专家”注释者是两个研究生水平的语言技术研究人员,他们完全了解参数模型的性质和目的。他们获得了 0.862 的一致率,略高于专家和群众注释者之间的一致率(0.844)。使用注释者间协议的 kappa 统计验证了结果的可靠性[2]。

在我的三标签 AM 实验中有两个预测:话题内和跨话题。为了更容易进行评估和基准测试,我使用下面的代码将一键编码还原为整数[0,1,2]:

y_train= np.argmax(y_train, axis=1)
y_test= np.argmax(y_test, axis=1)

基准将基于准确度、精确度、召回率和 f1 分数。这将在稍后的混淆矩阵中呈现。

  • 在七个主题上接受培训,在验证集上进行测试(主题内):
y_test=y_val
y_test=np.argmax(y_test, axis=1)
y_pred = np.argmax(model.predict(X_val), axis=-1)from sklearn.metrics import classification_reportprint(classification_report(y_test, y_pred, target_names=['No  
  Argument', 'Argument For', 'Argument Against']))

主题内分类报告—按作者分类的图片

  • 七个话题的训练,看不见的话题的测试(跨话题):
y_test = test_df.drop('data',axis=1).values
y_test=np.argmax(y_test, axis=1)
y_pred = np.argmax(model.predict(X_test), axis=-1)

跨主题分类报告—按作者分类的图片

术语 Support 在这个上下文中是标签的数量,用于计算加权平均值。f1 分数的准确性以及宏观平均值通常用于基准分类结果。基于精确度、召回率和 f1 分数,该模型在预测给定句子的“反对论点”方面表现很好。但是,该模型在挖掘“论据”方面表现很差,仅回忆起 10%的真阳性。这表明发展的模型完全缺乏理解论点的能力,倾向于把一切都预测为“反对的论点”当数据在主题内而不是跨主题测试时,这不太明显,如第一次分类报告所示。正如所料,与跨主题预测相比,主题内预测在准确度、精确度、召回率和 f1 值方面得分更高。

谈话要点

  • 根据研究论文[1]的作者,AM 中的人类上限 f1-分数为 0.861(双标签)。他们在双标签(“参数”或“非参数”)上的最佳 f1 分数是 0.662。对于三标签实验设置,它们的最佳分数是 0.4285。我的渠道在没有任何迁移学习的情况下,取得了 0.37 的 f1 分数宏观平均分。当然,需要做更多的尝试来验证实验。但是,考虑到快速实现,这已经是一个相对较好的结果。57%的准确率几乎是模型给出随机猜测的两倍(~33%)。然而,分数通常不够好,因为我们希望模型的表现与人类相似。因此,跨主题的论点挖掘仍然是自然语言处理中的一个挑战。
  • 预处理训练集而不对测试集应用相同的过程将导致非常差的性能。这就是停用词和标记化的效果。未来的工作将是整合知识表示学习方法以及单词嵌入,以便更好地提取特征。过程中的感知和重要性权重将使我的流水线中的预处理变得多余。
  • 这项工作的下一步是让模型知道主题和上下文。在最初的论文中,作者试图通过使用迁移学习(参数迁移)来增强他们模型的跨主题预测能力。他们使用从另一个语料库(谷歌新闻数据集和 SemEval)预训练的双向 lstm,并将该方法与单词嵌入相结合。他们还表明,在训练深度学习模型时整合主题信息会导致更好的概括和回忆。

观点

辩论在许多方面都与人工智能有关。计算语言学的应用范围从检测有争议的推文到识别法律文件中特定主题的指控。例如,这项研究的最新技术可以在 www.argumentsearch.com 的找到。这个网站使用文本挖掘、大数据分析和深度学习作为文档的搜索引擎,实时给出你的主题输入的利弊。

参考

[1] C. Stab、T. Miller、B. Schiller、P. Rai 和 I. Gurevych。异构源的跨话题论点挖掘, 自然语言处理中的经验方法会议论文集(EMNLP 2018)。

[2] C. Stab,T. Miller 和 I. Gurevych,使用基于注意力的神经网络从异构来源进行跨主题论点挖掘,arXiv e-prints (2018)。

[3] F. Eemeran,R. Grootendorst,系统的论证理论,p 剑桥大学报业辛迪加出版(2004)。

免责声明 :注释可在知识共享署名-非商业许可(CC BY-NC)下在线获得。观点是我自己的。

用 SageMaker 和 Step 函数交叉验证你的机器学习模型

原文:https://towardsdatascience.com/cross-validate-your-machine-learning-model-with-sagemaker-and-step-functions-6610e9c6ab32?source=collection_archive---------18-----------------------

在 AWS 基础设施上自动化交叉验证的机器学习培训工作

图片来自 Pixabay 的 TeeFarm

交叉验证是一种强大的技术,可以建立对未知数据表现良好的机器学习模型。然而,它也可能是耗时的,因为它包括训练多个模型。这篇文章将向您展示如何使用 Amazon Web Services (AWS)的几种服务,包括 SageMaker、Step Functions 和 Lambda,轻松地交叉验证机器学习模型。

为什么需要交叉验证?

如果你知道交叉验证的概念,可以直接跳到介绍SMX-验证器 的章节。

小数据集和样本分布问题

想象一下,热带草原上的羚羊委托你训练一个图像分类器模型,帮助它们识别照片中的美洲豹。他们给你 50 张美洲虎的照片和 50 张没有美洲虎的热带草原的照片。您将数据集分为 80 张图片的训练集和 20 张图片的测试集,注意每个分区中的美洲虎和非美洲虎图片数量相等。您用您最喜欢的图像分类器算法训练您的模型,并获得令人印象深刻的 100%验证准确性。

作为视觉检查,您可以查看测试集中一些正确分类的照片:

图片来自 Pixabay 的马克·墨菲

一切看起来都很好。

一段时间后,您重新训练您的模型。您再次将相同的数据集分成 80%的训练集和 20%的测试集,使用与第一个模型相同的超参数,并获得 80%的验证准确率,以及一些假阴性(对羚羊来说是致命的!).那么发生了什么?

您查看测试集中的假阴性,并找到这样的照片:

照片由维基共享资源的 Senthiaathavan 拍摄

似乎在你的数据集中有“更容易”和“更难”的例子。当您将数据集划分为训练/测试集时,您的目标始终是测试集能够很好地代表整个数据集。谈到类别分布,您可以使用分层分割策略来实施,但是样本“硬度”如何呢?这是一项更加困难的任务。特别是如果你有一个小数据集,你可以很容易地得到一个分裂,所有“硬”的样本在训练集中结束,所以你的测试集将只包含“容易”的,导致一个好的测试分数。另一方面,如果大多数“硬”示例都在测试集中,那么使用用相同超参数训练的模型将会得到更差的结果。

超参数优化

另一个重要的例子是当你调整模型的超参数时。在超参数优化的情况下,您迭代地修改模型的一些超参数,用相同的训练集重新训练它,并在验证集上检查性能。如果模型性能提高,您就知道超参数调整很可能是在正确的方向上,因此您知道如何继续调整阶段。

图片来自 Pixabay 的 Niklas Ahrnke

这种方法的问题是一些信息会从验证集泄露到训练过程中。由于超参数更新步骤取决于模型在验证集上的性能,您可能最终得到一个针对特定验证集而非一般情况优化的超参数集(和模型)。这个问题最简单的解决方案是将数据集分成三个分区:训练集、验证集和测试集;使用训练和验证集调整您的模型,并使用完全不可见的测试集获得最终的性能指标。不幸的是,这意味着训练样本的部分甚至更小,因为您应该将数据集划分为 60%训练-20%验证-20%测试分区。

其他原因

在其他一些情况下,交叉验证可能特别有用,例如:

  • 当数据集包含相互依赖的数据点时,
  • 或者当您计划堆叠机器学习模型,以便一个模型的输入是前一个模型的预测输出时。

关于这些案例的详细讨论,请看这篇文章。

交叉验证有什么帮助?

交叉验证 是一组评估你的模型对未知数据的概括能力的技术。将数据集的标准训练测试分割视为一轮交叉验证过程。事实上,大多数交叉验证策略使用多轮将数据集分割成不同的分区,在每次分割时训练模型,并评估它们的组合性能。

最常用的交叉验证策略之一叫做 k 倍交叉验证。维基百科给出了它的精确定义:

在 k 重交叉验证中,原始样本被随机分成 k 个大小相等的子样本。在 k 个子样本中,保留一个子样本作为测试模型的验证数据,其余的 k1 个子样本用作训练数据。然后,交叉验证过程重复 k 次,k 个子样本中的每一个正好用作验证数据一次。然后,k 个结果可以被平均以产生单个估计。

例如,如果您使用五重交叉验证,您将使用以下拆分来训练五个不同的模型:

作者插图

在上面的 jaguar 分类示例中,“硬”样本将出现在一轮训练的测试集和其他四轮的训练集中。检查所有五个模型的准确性将使您对模型在未知数据集上的表现有一个更好的总体了解。同时,您已经使用了所有可用的数据来训练和验证您的模型。

这个过程听起来不错,但是这意味着在训练模型之前,您必须执行以下附加步骤:

  • 将数据集分成五份,
  • 将拆分组合成五轮训练的训练集和测试集,
  • 在可用硬件上安排每个机器学习模型的训练,以及
  • 从每个培训工作中收集培训指标。

上面的步骤是一个相当大的开销,特别是如果你需要定期训练你的模型。

SMX 验证器开始发挥作用了。

SMX 验证器

SMX 验证器是一个直接部署到 AWS 基础设施的应用程序,它管理几乎任何监督机器学习模型的交叉验证训练,您可以使用 SageMaker 进行训练。

该应用程序建立在几个 AWS 服务之上:

  • Amazon SageMaker 是一个云机器学习平台,使开发人员能够在 AWS 云中创建、训练和部署机器学习模型。
  • AWS Step Functions 是一个无服务器的函数 orchestrator 和状态机实现,可以排序 AWS Lambda 函数和其他 AWS 服务,包括 SageMaker。
  • AWS Lambda 是一个无服务器的计算平台,它运行代码来响应事件,比如 SageMaker 的“训练完成”事件。它还自动管理运行该代码的计算资源。
  • 亚马逊 S3 是一个对象存储服务,它允许使用类似文件系统的接口在云中存储数据。

将 SMX 验证器部署到您的 AWS 帐户后,您可以指定一个机器学习训练模板、一个输入数据集以及您希望在训练阶段使用的折叠数。该应用程序将自动编排所有培训作业,并行执行它们,并报告每个培训作业的结果和性能。跟随训练你的第一个交叉验证的工作与 SMX 验证器。在本演练中,我们将使用图像分类任务作为示例。

先决条件

  1. AWS 账户。如果你还没有,开一个新的。
  2. AWS 为新账户提供了一个免费层。然而,GPU 实例(强烈建议用于训练图像分类器)不包括在内,因此您应该预计一些训练成本在几美元的数量级。
  3. 要用于定型的数据集。在下面的准备您的数据部分,我将描述如果您还没有数据集,如何获取数据集。
  4. SMX 验证器是一个无服务器应用程序模型(SAM) 应用程序。您可以从无服务器应用程序库(SAR) 直接部署它,或者您可以使用 SAM 命令行界面(CLI) 构建它,并手动将其部署到您的 AWS 帐户。如果选择手动安装,应该安装带有 Docker 的 SAM CLI,并按照文档中的说明设置 AWS 凭据。

支持的 SageMaker 算法和容器

您可以将任何受监督的训练容器与接受换行符分隔的文件作为输入的 SMX 验证器一起使用,例如:

  • 线性学习器带 CSV 输入格式,
  • K-最近邻算法与 CSV 输入格式,
  • 图像分类算法与增强显示图像格式,
  • XGBoost 算法与 CSV 输入格式,
  • BlazingText 在文本分类模式下用文件模式或增强清单文本格式,
  • 或者接受换行符分隔的文件作为输入的自定义培训容器。

准备您的数据

在本教程中,我们将使用二值影像分类数据集。如果没有,可以用著名的狗对猫数据集。将数据集从 Kaggle 下载到您计算机上的一个目录中。创建一个 S3 桶并将所有图像文件上传到桶中。

为了将 SMX 验证器与 SageMaker 图像分类结合使用,我们将把数据集元数据组织成一个增强清单图像格式文件。假设您使用狗和猫的数据集,这个 python 片段应该可以完成这项工作:

从本地文件夹中的文件创建扩充清单图像格式

记住将my_bucket/dogs_vs_cats更改为输入数据集位置的存储桶名称和前缀。这个脚本将为狗分配类别 id 0,为猫分配类别 id1。将创建的manifest.jsonl也上传到输入桶。

如果您喜欢直接从 S3 存储桶的内容生成清单文件,您可以使用类似于下面的脚本。在这种情况下,您应该将bucketprefix变量指向您的数据集。

从 S3 存储桶中的文件创建扩充清单图像格式

部署 SMX 验证器

SMX 验证器发布在 AWS 无服务器应用程序存储库。部署应用程序最简单的方法是单击应用程序页面上的“部署”按钮。在部署应用程序之前,您应该填写两个参数:

  • InputBucketName:您上传数据集的 S3 桶的名称。应用程序将在部署时创建一个 IAM 角色,允许从这个桶中读取数据。
  • OutputBucketName:应用程序可以在其中写入部分结果和工作数据的 S3 存储桶的名称。通过上面的 IAM 角色,将向应用程序授予读取和写入数据的权限。

您可能希望在部署应用程序之前创建这两个存储桶。您还应该知道,该应用程序将创建自定义的 IAM 角色。这些角色使应用程序能够启动 SageMaker 培训作业,并从/向上述存储桶读取/写入。

或者,您可以克隆 SMX 验证器的 git repo,并用 SAM-CLI 构建应用程序。详情请参考项目资源库中的自述文件。

开始交叉验证的培训工作

SMX 验证器部署了一个阶跃函数状态机来协调交叉验证折叠的训练。您可以启动一个交叉验证的作业,启动状态机的新执行。

您应该在 JSON 文件中指定交叉验证的培训作业的一些输入参数,例如:

  • 输入manifest.jsonl的 S3 路径,
  • 输出路径(这些路径应该指向您在应用程序部署时指定的存储桶),
  • 交叉验证的培训职务的名称,
  • 折叠次数,以及
  • SageMaker 培训作业模板,包括培训超参数和培训资源配置。

您可以在 SMX 验证器的文档中找到输入模式规范、详细文档,以及输入文件的完整示例。

一旦创建了输入 JSON 文件,就有不同的选项来启动状态机的执行:

  • 使用 AWS CLI :
aws stepfunctions start-execution \
  - state-machine-arn {CrossValidatorStateMachineArn} \
  - input file://my_input.json
  • 在 AWS 步进功能 web 控制台中,选择CrossValidatorStateMachine-*,在状态机页面上,点击“开始执行”按钮。将输入 JSON 的内容复制到输入文本区域。
  • 从本地脚本或 lambda 函数中使用AWS SDK。

SMX 验证器将把输入数据集分割成多个文件夹,组装训练集和测试集,并可能并行地启动 k 训练作业。您可以将状态机规范文件中并发执行的作业数量(默认为两个)调整为 AWS 帐户中可用的 ml 实例数量。下图说明了 SMX 验证器的状态机。虚线框中的步骤是同时执行的。

作者插图

培训工作

SMX 验证程序将为每轮交叉验证的培训启动一个 SageMaker 培训任务。您在crossvalidation.n_splits参数中定义的分割数(和训练任务数)。培训工作将根据以下模板命名:

crossvalidator-{input.job_config.name}-{YYYYMMDD}-{HHMMSS}-fold{fold_idx}

其中,{input.job_config.name}是输入配置中的作业名称,{YYYYMMDD}-{HHMMSS}是作业开始时的时间戳,{fold_idx}是该轮从零开始的索引。

访问 AWS 管理控制台中的 SageMaker 培训工作页面,了解 SMX 验证器启动的所有工作的概况。您可以在单个培训作业的页面上找到培训和验证指标图表以及最终指标值。

应用程序还将在步骤函数执行输出 JSON 中报告培训作业的详细信息。该 JSON 将包含以下字段:

  • job_config:整个交叉验证的培训作业的通用参数,如作业名称、SageMaker 实验和试验名称、作业输入和输出数据。
  • crossvalidation:交叉验证参数,如作业中使用的分割数。
  • training:用于创建培训工作的模板结构。
  • splits:这个数组包含了每个训练任务的详细结果。它对应于DescribeTrainingJob SageMaker API 调用的输出。除了确切的培训工作输入,您还可以在这个结构中找到培训时间和持续时间、计费秒数、最终度量值和输出工件位置。

结论

交叉验证机器学习模型是每个数据科学家工具箱中的一个强大工具。如果数据集包含可变“难度”的样本,或者您正在优化模型超参数,它可以帮助您有效地评估在小数据集上训练的模型。然而,在有限的硬件资源上训练多个模型可能非常耗时,并且需要手动编排。SMX 验证器帮助在 AWS 基础设施上训练 k-fold 交叉验证的机器学习模型,负责训练作业的重型任务编排。

也可以在 SMX 验证器的 GitHub 页面上查看源代码和完整的文档。

我是 Janos Tolgyesi, Neosperience 的机器学习解决方案架构师和 ML 团队负责人。我在 ML technologies 工作了四年,在 AWS infrastructure 工作了七年。我喜欢构建东西,让它成为边缘的视频分析应用或基于点击流事件的用户分析器。有任何问题,可以在中或者推特上找我,账号为 @jtolgyesi 。

机器学习中的交叉验证

原文:https://towardsdatascience.com/cross-validation-and-bootstrap-sampling-2e041fbec126?source=collection_archive---------9-----------------------

实践教程

了解交叉验证过程以及为什么 bootstrap 样本有 63.2%的原始数据

由 Clément Hélardot 拍摄于 Unsplash

在训练了一个机器学习模型之后,每个数据科学家总是想知道训练好的模型在看不见的数据上表现如何。好的模型是不仅在训练中而且在测试数据中表现良好的模型。为了估计模型的性能,我们经常使用一部分数据进行训练,保留一部分数据进行测试,希望模型在测试数据上的性能能够代表宇宙中的数据。

下面是一个简单分类问题的例子。在此示例中,Iris 数据集从 Sklearn 模块加载,逻辑回归模型适合数据。数据包含用于训练的150记录和用于测试的 60%记录。

输出:

Model 0 accuracy: 0.967
Model 1 accuracy: 0.967
Model 2 accuracy: 0.933
Model 3 accuracy: 0.967
Model 4 accuracy: 0.933
Model 5 accuracy: 0.933
Model 6 accuracy: 0.85
Model 7 accuracy: 0.95
Model 8 accuracy: 1.0
Model 9 accuracy: 0.95

Line 1–15:在这些行中,数据被加载,模块被导入。

Line 17:这是一种在每次迭代中将逻辑模型拟合到相同数据中的循环。需要注意的重要一点是,模型在每次迭代中都有不同的表现(参见上面的模型得分)。注意,差异并不归因于迭代期间的任何参数变化,因为相同的参数用于所有模型。差异的来源在于数据的分割。train_test_split将数据分成2,但是在每次迭代中,不同的数据被用于训练和测试,因为没有播种的洗牌。如果您想要在每次迭代中获得一致的结果,请向sk learn . model _ selection . train _ test _ split的random _state 参数传递一个种子值。你可以如下重写第25

X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.40, random_state=42)

这使得模型结果是可再现的,即一致的。这是因为分裂期间的洗牌是播种的,因此用于训练和测试的数据在所有迭代中都是一致的。

一个经典的验证过程包括完全按照上面的例子所做的事情——将数据分成两组:训练集和测试集——但是对模型评分的一次运行可能无法确定模型在生产中的表现如何。为此,我们需要一种更好的验证方式。这正是交叉验证的用武之地。

交叉验证

交叉验证是一种用于验证机器学习模型并估计已训练模型对未知数据的性能的技术。正如你将在下面的讨论中看到的,它比经典的评估要好。

交叉验证程序

  1. [可选]无序播放数据。
  2. 将数据分成k个大小相同(或大致相同)的不同组/折叠(因此,交叉验证也称为k-折叠交叉验证)。
  3. 运行模型训练和验证的k次迭代。对于1,2,…,i,…k中的i

k文件夹中,单个文件夹(i文件夹)用作保留/验证数据,其他k-1文件夹用于训练模型。

模型通过验证后,保留模型分数E_i

4.合计(3第二点)中获得的分数,以获得所有k褶皱的模型平均性能。在大多数情况下,使用算术平均值进行汇总,因此:

每次迭代中模型得分的平均值。

对于分类任务,可以使用准确度、精确度、召回率等指标对模型进行评分,对于回归问题,可以使用均方误差、平均绝对误差等指标在每次迭代中对模型进行评分。

5.分析平均得分E,确定它在看不见的数据(宇宙)上表现良好的可能性。

使用 Sklearn 实现 k-fold 交叉验证的简单方法

输出:

train: [ 2  3  4  5  6  7  8 11 12], test: [1  9 10]
train: [ 1  3  5  6  7  9 10 11 12], test: [2 4 8]
train: [ 1  2  4  5  8  9 10 11 12], test: [3 6 7]
train: [ 1  2  3  4  6  7  8  9 10], test: [5 11 12]

图片:完整的 k 倍交叉验证程序。k=5 的一种情况,即 5 重交叉验证。参考:Sklearn 网站。

下面是来自维基百科的交叉验证过程的动画。

当 n = 12 个观察值和 k = 3 时,k 重交叉验证的图解(3 重交叉验证的一个例子)。经过数据洗牌后,共有 3 个模型将被训练和测试。每个文件夹将包含 12/3=4 个数据示例。来源:维基百科

k 的选择

  • 首先,k 必须是介于2*n*(观测值/记录数)之间的整数。k必须至少有2才能保证至少有两次折叠。
  • 对于k=2,我们随机打乱数据(可选)并将其分成2组— d1d2,以使两组大小相等(或大致相等)。然后在d1上训练模型,在d2上验证模型,接着在d2上训练模型,在d1上验证模型。
  • 选择k=n可以将事情发挥到极致。在这个场景中,我们有一个特殊的交叉验证案例,叫做留一交叉验证(LOOCV)。该名称来源于这样一个事实,即在每次迭代中,一个数据点被遗漏用于验证,而其他的n-1用于测试。
  • 在交叉验证中k是不固定的参数,但在选择k时应考虑以下几点:

代表性启发法 — k 的选择方式应确保保留数据/折叠代表整个宇宙(看不见的数据)。例如,如果我们有1000记录,并且我们选择k=500,那么在每次迭代中,只有1000/500=2数据点用于验证。这使得验证规模非常小。非常大的k值意味着跨训练折叠的差异更小,因此限制了跨迭代的模型差异。这意味着k不能太大也不能太小。

经验法则 —尽管k是一个不固定的参数(没有特定的公式可用于确定最佳选择),但10仍被普遍使用,因为它已被实验证明在大多数情况下是一个好的选择。

  • 给定原始数据中的n观察值,每个折叠将包含n/k记录。

这里还有另一个来自维基百科的动画,展示了留一法交叉验证的概念:

当 n=8 个观察值时,留一交叉验证(LOOCV)的图示。在交叉验证过程完成之前,总共训练和测试了 8 个模型。每次迭代产生一个在 n-1 个数据点上训练并在 1 个数据点上测试的模型。来源:维基百科

使用交叉验证方法的原因

  • 模型在训练中的性能,甚至在验证集上运行的性能,都不能保证模型在未知数据上的最佳性能。当数据不足以代表宇宙状态时,就会发生这种情况。在这种情况下,测试数据上的模型误差可能无法反映模型在宇宙中的表现。这正是上面例子中的情况——使用150数据记录来训练和测试模型产生了不一致的分数。
  • 因此,在缺乏大型数据集的情况下,交叉验证是评估模型性能的最佳选择。

k-Fold 交叉验证的特征概述

  • 在将数据分割成 k个文件夹之前,进行混洗(可选操作)。这意味着给定的数据点被分配到单个文件夹中,并且在交叉验证过程的剩余部分中它保持在该组中。这也意味着一个给定的数据点被用于一次验证和k-1次训练。
  • 每个折叠中有n/k个数据点,其中n是原始数据中的观察次数,k是折叠次数。
  • k可以取 2n(原始样本中的观察次数)之间的任意整数值。

自助抽样

Bootstrap 采样是一种重采样技术,涉及随机采样和替换。单词 resample 在字面上的意思是“再次采样”,这意味着通过用“原始”样本的替换进行采样来生成自举样本。

通常,通过选择用于分析的总体子集来生成采样,目的是推断总体(总体->样本),而重采样是为了推断样本(样本->重采样数据)。

这里有一个简单的例子。假设从给定总体中抽取一个大小为12的样本,并从这些样本中产生3个引导样本。然后,我们可以将此信息表示如下:

自举抽样(bootstrapping)的一个例子。原始数据包含12数据示例,每个样本集还包括从原始数据中取样 12 个数据点并替换。来源:作者。

由于我们是带替换的传导采样,请注意上面示例中的以下内容:

  • 一些数据点(可能)出现在多个集合中。例如6出现在集合D2D3中。
  • 有些例子在给定的集合中会出现不止一次。例如9, 10, 4, 37在集合D1中出现不止一次。

“假设 n(原始数据的大小)足够大,实际上它(引导样本)与原始‘真实’样本完全相同的概率几乎为零。”—维基百科

事实上,

平均而言,63.22%的原始数据出现在任何给定的 bootstrap 样本中,这与所说的相同——一个平均 bootstrap 样本遗漏了原始样本中 100–63.22 = 36.78%的数据。

让我们用最简单的方法证明这个数学事实。在此之前,让我们陈述一些在证明过程中有帮助的数学事实。

我们现在可以继续证明了。

假设原始数据有n个观察值,我们从数据中得到大小为n的 bootstrap 样本,那么:

  • 给定观察不被选择的概率是(1–1/n),被选择的概率是(1/n)
  • 因为我们要重采样 n 次,所以在 n 次试验中观察结果未被选中的概率是(1–1/n)^n

根据微积分,随着n->∞ (n 变大),这个概率可以使用极限的概念来确定。也就是说,

从这里开始,我们需要理解和应用洛必达法则。

洛必达法则声明。换句话说,该规则规定,考虑两个函数 f 和 g,它们的导数存在于某个区间 I 内,但不存在于该区间内的给定点 c(即,导数存在于区间内的其他任何地方,但不存在于某个点 c)。如果当 x 接近点 c 时,f 和 g 的极限(假设 f 和 g 是 x 的函数)等于零或无穷大,并且对于区间 I 中 x 的所有值,g 的导数不等于零(这确保我们在后续运算中不会遇到被零除的问题) 并且 f 除以 g 的导数极限存在,那么 f 除以 g 的极限等于 f 的导数极限除以 g 的导数,当 x 接近 c 时,参考:维基百科

从等式(4)中,我们可以证明,在应用洛必达法则之前,我们需要满足的所有条件实际上都满足如下:

然后,我们可以将洛必达法则应用到等式4中,并按如下所示进行操作

这结束了我们的证明,证实随着n变大,自举消除了原始样本中大约 36.22%的数据。

今天的文章到此结束。如果你喜欢它,请看看下面这篇关于交叉熵损失函数的文章,也读一读。下次再见,祝阅读愉快:-)

** **

加入 https://medium.com/@kiprono_65591/membership的媒体,全面了解媒体上的每个故事。

**你也可以在我发文章的时候通过这个链接把文章发到你的邮箱里:【https://medium.com/subscribe/@kiprono_65591 **

交叉验证工程

原文:https://towardsdatascience.com/cross-validation-engineering-a46cc93b9087?source=collection_archive---------47-----------------------

无知可能被证明是代价高昂的

作者图片

介绍

交叉验证是数据预处理阶段的一个重要方面,但通常被数据科学家所忽略。这是一个从来没有基于接触的领域,最终,利益相关者会对模型质量失去信心,因为如果没有在模型上应用交叉验证,性能会非常差。这是我们在可用数据上应用训练和测试拆分来准备训练和测试模型时要考虑的一个阶段。我们在给定的训练-测试分离模型中设置随机状态参数,该模型通常试图将随机数据集分配到两个数据集,即训练和测试。当我们改变随机状态变量的值时,模型的精度会有很大的变化。因此,我们从来没有得出关于模型准确性的结论性证据。因此,在客户互动过程中,这很可能成为争论的话题,最终影响组织中的业务交易。因此,交叉验证的概念被引入。交叉验证有很多种,本文将逐一讨论。

遗漏一项交叉验证(LOOCV)

作者图片

在这种类型的交叉验证中,我们只从给定的记录列表中抽取 1 个样本作为测试数据,其余的记录被移动到训练数据集中。例如,假设我们有一个 1000 条记录的列表,那么我们将把其中一条记录作为测试数据,其余的 999 条记录将被移动到训练数据集的列表中。这样,我们将每个样本放入测试数据集中,并尝试在每次迭代中找到精确度。

这种方法的主要缺点是,我们需要运行与给定数据集中存在的记录数量相等的交叉验证迭代。这将最终影响内存消耗、时间浪费,而且我们可能需要花更多的钱来构建一个更好的系统,以避免上述问题。这种方法的第二个主要问题是,当给定数据集中的记录之外的新测试数据作为测试数据集的输入时,模型性能会发生不变的变化。

k 倍交叉验证

作者图片

考虑具有 1000 条记录的给定数据集,我们固定 k 的值。值 k 定义了我们将在总的给定数据集上执行的总迭代次数,并且将总记录的值除以 k 给出了我们将包括在测试数据集中的记录总数。例如,在给定的数据集中,我们有 1000 个样本,我们将 k 的值固定为 5。然后我们将进行 5 次交叉验证。每一次迭代都将有(1000/5 = 200 条记录)定义测试数据。如图所示,每次迭代都将有一组新的 200 条记录作为测试数据的一部分传递给模型。因此,在迭代 5 结束时,每个记录将在某个时间点成为测试或训练数据集的一部分。因此,从每次迭代获得的精度模型可以被一起平均,并且从其获得的值可以被定义为平均精度模型性能。因此,我们可以向利益相关者传达模型性能可以在 83 到 87 之间变化(如图所示),或者我们可以取平均值为 85(如图所示),并将其传达给利益相关者。

这种方法的主要缺点是数据集不平衡。如果我说 1000 条记录中有 900 条属于 A 类,只有 100 条属于 B 类,那会怎么样呢?在这种情况下,模型每次只暴露给 A 类数据,这将导致模型较少暴露给 B 类数据。最终,当未知数据集由 B 类数据组成时,模型可能无法在大多数情况下正确预测数据,因为其训练阶段通常会暴露给 A 类数据。因此,当模型暴露于 B 类未知数据集时,我们可能会看到模型准确性的下降趋势。因此,在 k 倍交叉验证的情况下,不平衡的数据集可能是真正有问题的。

分层交叉验证

作者图片

为了克服 k 重交叉验证的缺点,引入了分层交叉验证的概念。在分层 CV 中,我们确保在每次迭代中,在分割时,我们在训练和测试数据集中保持每个类类型记录的平衡。例如,在上面的例子中,在每次迭代期间,我们将数据集分为测试数据集中的 200 条记录和训练数据集的 800 条记录。现在,对于每个训练和测试数据集,我们将以这样的方式进行划分,即其中存在的记录将有 60%属于 A 类,40%属于 b 类。因此,最终在每次迭代中,模型将获得良好的准确性,最终当模型暴露于未知数据集时,它至少能够在大多数情况下正确地将记录分类到类类型中。

这是关于交叉验证的简单介绍。

希望你喜欢这篇文章!!

你可以在 LinkedIn 上联系我

https://www.linkedin.com/in/charanraj-shetty-a74831b2/

交叉验证:K 折 vs 蒙特卡罗

原文:https://towardsdatascience.com/cross-validation-k-fold-vs-monte-carlo-e54df2fc179b?source=collection_archive---------14-----------------------

…选择正确的验证技术

Riho Kroll 在 Unsplash 上拍摄的照片

想象一种情况,我们有一个测试集和一个训练集,我们对这些集应用两种不同的机器学习模型。我们如何决定哪个模型表现更好?我们在训练集上训练模型,并使用测试集评估模型。假设模型 A 在测试集上的表现优于模型 B,因为在分割数据时存在偏差。但实际上,B 型才是更优的型号。这就是我们可以使用交叉验证的地方。

内容

  • 交叉验证
  • k 倍交叉验证
  • 蒙特卡罗交叉验证
  • 两种方法的区别
  • R 中的示例
  • 最后的想法

交叉验证

交叉验证(从这里开始我们将称为 CV)是一种用于测试模型预测未知数据的能力的技术,这些数据不用于训练模型。当我们的测试集不够大时,如果我们的数据有限,CV 是有用的。有许多不同的方式来执行简历。通常,CV 将训练数据分成 k 个块。在每次迭代中,模型在 k-1 个块上训练,并使用最后一个块进行验证。我们可以使用 CV 的多次迭代来减少可变性。我们使用所有迭代的平均误差来评估模型。

总是倾向于使用 CV 性能更好的型号。同样,我们也可以使用 CV 来调整模型参数。

k 倍交叉验证

步骤:

  1. 将训练数据分成 K 个相等的部分
  2. 在 k-1 个零件上拟合模型,并使用第 k 个零件上的拟合模型计算测试误差
  3. 重复 k 次,使用每个数据子集作为测试集一次。(通常 k= 5~20)

K 倍 CV,K=5

蒙特卡罗交叉验证

也称为重复随机子采样 CV

步骤:

  1. 随机分割训练数据(可能是 70–30%分割或 62.5–37.5%分割或 86.3–13.7%分割)。对于每次迭代,训练测试分割百分比是不同的。
  2. 对该迭代的训练数据集拟合模型,并使用对测试数据拟合的模型来计算测试误差
  3. 重复多次迭代(比如 100 次、500 次甚至 1000 次迭代),取测试误差的平均值。

注意——相同的数据可以在测试集中被选择不止一次,甚至根本不被选择。

蒙特卡罗 CV,迭代次数= 100

两种方法的区别

R 中的示例

让我们试着用手写数字数据集来说明这两种交叉验证技术的区别。我们将使用 CV 对 KNN(K 最近邻)模型中的 K 进行超参数调整,而不是在不同的模型之间进行选择。

对于这个例子,我们将把手写数字数据子集化为仅包含数字8 。然后我们应用 KNN 模型来区分这两者。我们将使用 CV 从 1、3、5、7、9 和 11 中选择 k 的最佳值。

k 近邻(KNN),速成版

KNN 分类给出了基于对象的类在对象的 k 最近邻中最常见的类。

使用蒙特卡罗 CV 选择 k

这里 CV 运行 1000 次迭代( B ),为训练集随机选择 n1 个观测值,并从剩余的观测值中检索测试误差。在对我们的试验集中的每个 k 值进行迭代之后,我们得到 1000 个测试错误。我们将平均测试误差分配给每个 k 值,并根据平均误差衡量其有效性。

KNN 分类中选择 k 的蒙特卡罗 CV 片段

下图显示了不同 k 值的 KNN 模型测试误差的变化和范围。每个方框图中的深蓝色线是模型的平均误差。这是我们关注的焦点。

下图的矩阵给出了 CV 的运行平均测试误差, B = 1000。它们表明模型的误差正在收敛到一个特定的值。但是对于较低的 B 值,我们会看到移动平均误差的大量波动。

使用蒙特卡罗 CV 计算不同 k 的运行平均测试误差

使用 K 倍 CV 选择 K

对于 K 次折叠,我们使用 k=10(其中 K 是折叠的次数,ML 中的 K 太多了)。对于每个尝试的 k 值,观察值将在测试集中出现一次,在训练集中出现九次。

KNN 分类中选择 K 的 K 倍 CV 片段

两个 cv 的平均测试误差

我们最后对蒙特卡洛和 K 倍 CV 的测试误差进行平均,并进行比较以选择超参数 K。在本例中,构建 k=3 的 KNN 模型似乎会给出最佳结果。

最终想法

使用哪种 CV 技术要视情况而定。蒙特卡罗方法可以让你对结果更有信心,并且因为方差很低,所以重复性更好。但是蒙特卡罗 CV 会比 K 倍 CV 有更高的偏差。这种困境在机器学习中很常见,被称为偏差-方差权衡。在大多数情况下,K-fold CV 就足够好了,而且计算成本更低。

要获得完整的代码和数据,请点击下面的链接。

https://github.com/rebeccareeba/CrossValidation_KNN

跨越数据科学和影响力之间的鸿沟

原文:https://towardsdatascience.com/crossing-the-chasm-between-data-science-and-impact-377263ffa96e?source=collection_archive---------36-----------------------

深度分析只是工作的一半。赢得决策者的信任,激励行动以产生影响。

大多数分析师都是失败项目的一部分,或者遇到过可怕的“我不确定我是否理解它……”接下来是一句尴尬的,没说出口的“而且,我也拿它没办法!”。

研究报告称,许多(近 87%)分析项目失败了。列举了几个原因,如组织结构、文化、人才、数据可用性等。

然而,对于许多分析师来说,将见解转化为值得信赖的建议和鼓舞人心的行动是一大绊脚石。通常利益相关者不能够很快理解分析,产生疑虑,并且不采取任何行动就弃船而去。

看来最后一英里造成了巨大的差距!

照片由路博宣礼

“分析翻译者”被认为是可以帮助构建问题和翻译见解的人。然而,这将使分析师远离背景一步,导致其他的复杂性。

我认为,通过一点点的关注、规划和专注的努力,数据科学家可以开始弥合这一差距。

那么,是什么导致了这最后一英里的差距呢?

洞察生成/故事讲述的时间不足- 洞察生成是分析流程中被忽视的一步——我们分配给构建洞察的时间少得不成比例&故事讲述。我们觉得有责任花大部分时间来挖掘数据,并期望一些粘贴到幻灯片上的图表会传达这个故事。

这最后一分钟的努力是一个关键的失败点,数据科学家努力沟通复杂的分析,不足以将分析与目标或建议联系起来, 未能赢得决策者的信任

复杂性权衡 -
作为数据科学家,我们的任务是找到洞察力或建立准确的预测模型。为此,我们可能会深入挖掘并追踪一个复杂的思路,或者应用一组算法来实现预期的结果。然而,分析越复杂,解释起来就越困难,尤其是对缺乏数据科学和算法经验的观众而言。

缺乏共享背景 -
与业务人员共享背景,了解动机对于创建假设、识别模型特征以及最终将点连接到有意义的建议至关重要。通常,分析师&涉众很少花时间分享上下文,并带着不同的项目愿景离开。分析师可能不知道要求什么,涉众可能没有意识到没有足够的先验知识。最终,这种努力会暴露出一些基本的东西或者完全偏离目标。

我们如何克服差距?

分配足够的时间 我建议分析师在项目计划中安排至少 50%的时间用于洞察生成和构建叙述。向讲述故事而不是继续挖掘数据的转变也将作为对分析瘫痪的检查,将焦点带回考试问题(减少范围蔓延),同时使分析师能够解决任何潜在的漏洞或跟进可能出现的问题。

迭代和润色 创建有意义的推荐和构建清晰的叙述的过程是迭代的。不断修改幻灯片有时会令人沮丧,但是有了正确的反馈和指导,努力就会有回报。在每一次迭代中,您都在寻找解决任何洞察差距的方法,并且 提高 传达洞察和建议的效率。

它有助于确定关键决策者及其采纳基于数据的建议的风格和偏好。您可能希望预测他们可能会问的潜在后续问题,并先发制人地解决这些问题。你可以做的改进包括措辞、内容流、图像,甚至是字体、颜色等。你需要排除任何干扰关键信息的因素,如含糊不清的陈述,或可能破坏演示的错误事实。风险越高,你就越想对整个演示文稿进行优化。经过几十次迭代才能得到一个完美的最终产品,准备在 CXO 展示,这并不罕见。

找一个搭档 找一个值得信赖的搭档非常有用——这个人在公司有终身职位,或者在你分析的业务领域有专长。最重要的是,他们可以对你的工作提供批评的眼光,对你的见解是否新颖和有影响力,你的建议是否有意义和可行,以及演示是否有效传达提供直接反馈。你还需要他们的建议,告诉你如何才能最好地赢得关键决策者的信任,以及哪些潜在领域可能会破坏你的努力。

投资营造环境 环境是随着时间的推移而获得的,每个项目都会带来更多。对于一个分析师来说,试图理解一个产品或一个企业的内部运作可能是令人生畏的。然而,没有它,你回答问题的能力就会打折扣。可以表现得很脆弱,询问基本业务的背景、项目的动机和任何潜在的假设。请求可能存在的任何先前研究,为探索性分析留出时间,以了解关键业务驱动因素。最重要的是,培养关系,随着时间的推移继续建立背景。

持续改进 与任何事情一样,有效沟通是一个需要持续关注的领域。每次演示后,反思结果并确定需要改进的地方将有助于使未来的报告更有影响力。然而,关键的一步是要认识到,弥合最后一英里的差距需要专注和努力。一旦你确定了差距,我们安全跨越鸿沟只是时间问题。

参考文献:

  1. 米(meter 的缩写))Henrion,为什么大多数大数据分析项目失败 (2019),今日 ORMS
  2. C.麦克谢,D .奥克利,C .马泽伊,这么多分析努力失败的原因 (2016),《哈佛商业评论》
  3. T.达文波特,跟上你的宽客 (2013),《哈佛商业评论》
  4. 名词(noun 的缩写)Henke,J.Levine,P.McInerney,分析翻译:新的必备角色 (2018),麦肯锡

众包您的 SQL 查询

原文:https://towardsdatascience.com/crowdsource-your-sql-queries-ebb59446fcd1?source=collection_archive---------24-----------------------

让我们一起努力,让 SQL 成为最好的分析语言

约翰·施诺布里奇在 Unsplash 上的照片

背景

有很多人让 SQL 不好过(这里的和这里的等等)。

他们的一些批评当然是正确的,但事实是 SQL 不会有任何发展。作为数据库的语言,它是我们数据的看门人,随着数据仓库的进步,没有更快的方法来查询大数据。其直观的语法虽然冗长,但使技术分析师和业务用户都可以使用它。在一个有越来越多的分析语言需要学习的世界里,无论是专有的还是开源的(比如 Python,R),SQL 都是我们共享的一种通用语言。

同样重要的是要记住,人们不喜欢其他分析语言是因为它们天生优越,而是因为他们有一个用户社区,这些用户正在积极地使它们更适合于分析。(试想一下,没有熊猫用 Python 做分析。)

我相信 SQL 也是如此。世界上有数以百万计的 SQL 用户,想象一下,如果我们能够开始汇集我们的知识来帮助解决 SQL 的挑战,会发生什么。我相信这是将 SQL 作为一个强大工具的一条有前途的道路,而不是担心它是一个不可避免的祸害。

从哪里开始

SQL 的一个常见缺点是冗长和不可压缩性。这无疑是我对 SQL 感到失望的主要原因。

不像在其他语言中,重用普通的代码作为函数或方法并不容易。在 Python 中,我可以很容易地将一段常用的代码转换成一个函数,甚至将该函数作为开源包的一部分共享,这样任何其他 Python 用户也可以使用它。

如果你和我一样,为了应对这个挑战,你会在你的桌面上随意放置一些概念页或 Word 文档,里面都是你想“保存起来下次用”的片段。这是一个粗糙的解决方案,但它让我觉得我正在做一些事情来解决它。

最近,我开始考虑如果我们都把桌面上的 SQL 片段文件放在一个地方会发生什么?我们会围绕标准化和同类最佳的解决方案来解决常见问题吗?我们会节省自己一遍又一遍查找相同语法的时间吗?我们真的能让 SQL 成为众包语言吗?

我们也能做到

所以我想我应该验证一下这个理论。我把一些我喜欢的 SQL 片段放到了一个新的开源的 SQL 片段集合https://sql-snippets.count.co/。在这里,任何人都可以:

  • ****发现保存有用的 SQL 片段。
  • ****向上投票对现有片段进行评论以做出改进。
  • ****提交他们自己的片段,进一步扩大知识社区。

到目前为止,网站上有超过 100 个片段和近 50 个成员。

SQL 片段集合的预览

你怎么想呢?

我相信,有了正确的解决方案,众包 SQL 可以成为改进您自己的工作流和更好的 SQL 社区的一个好方法。但是要做到这一点,它必须对每个人(或者至少是大多数人)都有效。考虑到这一点,我请求您查看我们的片段集和:

  • 如果你有关于如何做得更好的想法,请发邮件给我,地址:snippets@count.co
  • 有片段分享?帮助我们用一些很棒的 SQL 片段作为集合的种子。或者请求社区帮你解决。
  • 你认为这对其他人有用吗?和一些朋友一起分享吧!

关于我

我是 count.co 公司的数据主管。我们是热情的 SQL 爱好者,正在为 SQL 分析构建更好的工作流。

研究中的众包:5 个由大众促成的成功项目

原文:https://towardsdatascience.com/crowdsourcing-in-research-5-successful-projects-made-possible-by-the-crowd-b6e4f9696306?source=collection_archive---------34-----------------------

让我们来看看最近的一些案例研究,在这些案例中,众包通过大规模提供标记数据,成功地帮助了科学调查

Ashkan Forouzani 在 Unsplash 上的照片

今天,大众的力量已经被世界经济的不同部门所利用。其中一个应用是研究和开发,无论是在学术界还是在商业领域,因为越来越多的数据科学家已经开始在各自的领域利用这种方法。让我们看看下面的案例分析。

#SMM4H 和药物警戒

所谓的健康应用社交媒体挖掘(#SMM4H)是一项研究计划,旨在促进社交媒体内容(主要是 Twitter 上的帖子)的使用,以实现药物警戒。通过利用 Toloka 上的人群力量,该倡议从去年开始的第五次迭代检查了俄语和法语的推文,并专注于检测处方药的各种副作用,以及妊娠并发症和出生缺陷。从今年开始的第六次迭代用英语、俄语和西班牙语查看 WebMD 上的推文和帖子,重点关注药物治疗不依从、新冠肺炎检测和早期乳腺癌诊断。

Magge 等人得出结论,深度学习背景下基于变压器的架构——即 BERT 和 RoBERTa——可能会被用作众包工具,用于成功的药物警戒和医院访问。此外,今年有 97 个注册团队,组织者注意到与前一期相比,兴趣和参与度分别上升了 70%和 38%。

不当语言检测和过滤

虽然互联网用户中的毒性是已知的,本文中的研究人员试图根据其对作者声誉的影响,制定出一个更精细的不当概念。

Babakov 等人将不恰当定义为不同于毒性,因为(a)不恰当往往与话题相关,( b)语言有时可能被认为不恰当,但不一定有毒。结果,产生了两个俄语数据集:主题标注和适当性标注。预训练的分类模型随后在标记的数据上被训练。通过 Toloka 的人群表演者,研究人员能够表明,使用神经模型可以成功地检测出话题的敏感性和不恰当性,这对于未来的研究和商业来说是一个充满希望的概念。

问题回答

知识库问答(KBQA)是自然语言处理(NLP)的一个组成部分,它利用 Wikidata 自动回答复杂的问题。Rybin 等人进行了两项研究,并产生了两个 RuBQ(俄语知识库问题)数据集,可用于研究和实现机器阅读理解(MRC),改进混合问答,并进行语义解析。

在最初的研究中,研究人员转向托洛卡的群众演员,结合内部验证,为 KBQA 准备第一版训练数据集。该集合包含 1500 个不同复杂程度的俄语问题、它们的英语翻译和 SPARQL 查询(即数据库的语义语言)。

在第二项研究中,研究人员利用群体的力量来准备新一组的大部分。虽然第一个 RuBQ 依赖于从网络测验中获得的 Q & A 对,但 RuBQ 2.0 是专门基于通过搜索引擎查询建议服务获得的问题。最新的数据集包含近 3000 个问题及其答案,以及 SPARQL 查询。

这两个 RuBQ 数据集都可以在 CC-BY-4.0 许可下免费获得,因为科学家们希望这条研究路线将继续下去。在多语言问答领域工作的研究人员和从业人员将对这些集特别感兴趣。

会计和审计

在本研究中,Carcello 等人研究了在管理培训场所(MTG)的背景下,公司管理层和高级管理人员对内部审计师建议的依赖程度。与传统的内部审计员相比,MTG 内部审计员有着不同的职业道路,他们接受培训,最终进入内部审计职能部门(IAF)以外的管理职位。之前的研究表明,MTG 内部审计会对财务报告的质量和效率产生负面影响。

研究人员对 355 名首席审计官(CAEs)进行了调查,并对近 150 名高级经理进行了两次实验,其中很大一部分是 MTurk 的员工。结果显示,与非 MTG 内部审计师相比,大多数 CAE 认为高级管理层更有可能执行来自 MTG 的建议。

事实证明,MTG 审计师通常被认为拥有更好的“先天能力”——这是大多数高级经理在决策中衡量可靠性的一个决定性因素。

创造力和人工智能

在今年早些时候的一份出版物中,两名研究人员研究了产生创造力的人工智能和人类之间的关系动态。

Morozova 和 Schulte 使用两个众包平台——to loka 和 productive——比较了受试者在以下两种情况下的表现和对挑战的反应,即(a)他们与其他人类受试者和人工智能配对,以及(b)他们被要求完成创造性和非创造性任务。

研究结果表明,大多数研究参与者认为人工智能在创造性领域没有一席之地,那些被迫在创造性环境中与人工智能一起工作的人会感到动力不足。而且,当 AI 的创造性表现出乎意料地高时,受试者会感到被机器吓倒和威胁。

关键外卖

通过提供一个负担得起且易于获取的数据标签解决方案,众包已经成为研究和商业领域真正的游戏规则改变者。就在几年前,数据标签主要局限于高度专业化的内部团队,许多人已经开始信任并利用大众的力量来满足他们的需求,而成本只是他们的一小部分,而且速度也快得多。

诚然,准确性仍然是众包的一个持续问题。然而,有了经验丰富的众包解决方案架构师(CSA) 掌舵、精心编写的说明和一致的质量控制,众包显然有很大的潜力。更重要的是,今天这种数据标签的方法已经超越了纯粹的机器学习和人工智能的领域:只有相对少数的公司和个人追求的轨道。从更熟悉的医学、法律和海军工程领域到美术和娱乐,众包受益者的名单继续扩大。

使用 Node.js 对 NoSQL 数据库(MongoDB)进行 CRUD(创建、读取、更新、删除)操作

原文:https://towardsdatascience.com/crud-create-read-update-delete-operations-on-nosql-database-mongodb-using-node-js-3979573b9b24?source=collection_archive---------11-----------------------

阿吉达·ATZ 在 Unsplash 上的照片

读者们好,

在本文中,我演示了 MongoDB 上的 CRUD 操作,并以同步和异步方式执行操作。

有 Node.js 基础知识者优先。

使用的 NoSQL 数据库:MongoDB

目录:

  1. 简介
  2. 设置 MongoDB (NoSQL)
  3. 同步与异步执行
  4. 创建模式、模型、对象
  5. 创建(同步)
  6. 创建(异步)
  7. 改为(同步)
  8. 读(异步)
  9. 更新(同步)
  10. 更新(异步)
  11. 删除(同步)
  12. 更新(异步)
  13. 资源&引用

1.介绍

CRUD 是 CREATE,READ,UPDATE & DELETE 的缩写,是数据库中的基本操作。

在这篇文章中,我使用 MongoDB 作为我的主要数据库,这是一个 NoSQL 数据库,与传统的行/列模型不同,它以 JSON 格式保存数据 aka 文档,并使用 Node.js 语言执行 CRUD 操作。

从根本上说,Node.js 默认情况下是异步或非阻塞的,因此在代码大量使用 CPU 的情况下,它不会等待。

因此,根据我们的情况将 CRUD 操作设计为同步或异步是一个具有挑战性的过程,特别是当我们在实时服务器操作中使用它时,在下面的部分中,我已经以同步/异步两种方式执行了那些操作。

在这篇文章中,我创建并使用了一个电影数据库,它包含了与特定电影相关的细节,因此您可以根据您的用例来操作它。

2.设置 MongoDB (NoSQL)

MongoDB 是一个文档数据库,这意味着它将数据存储在类似 JSON 的文档中。我们认为这是考虑数据的最自然的方式,比传统的行/列模型更具表现力和功能。

我们需要两个组件来设置 MongoDB 浏览器。

  1. MongoDB 社区服务器— 在此下载
  2. MongoDB 指南针(GUI 查看器)——在此下载

MongoDB 社区服务器

MongoDB Compass(MongoDB 的 GUI 查看器)

安装完这两个应用程序后,我们需要将 MongoDB 服务器路径添加到您 PC 中的环境变量中。

因此,在你的电脑的 C 目录中导航,找到 mongod.exe 文件的位置,并复制地址路径。

在我的例子中,我发现地址是:C:\ Program Files \ MongoDB \ Server \ 4.4 \ bin

将上述位置添加到如下所示的环境变量中。

现在我们准备在 MongoDB 数据库中创建文档。

此外,在创建第一个文档之后,我们可以在 MongoDB Compass 中查看数据库。

MongoDB Compass 文档视图。来源—作者

3.同步与异步执行

在 NodeJS 中,我们可以以同步(阻塞)和异步(非阻塞)两种方式执行数据库 CRUD 操作。

有时在进行 CRUD 操作时,我们可能需要通过 API 发送变量,或者在后续代码中使用它,等等。,在这种情况下,我们使用同步编程,其中代码中的一行等待前一行完成后再执行。

这是一个耗时的过程,因此我们也可以异步进行操作。这纯粹是基于我们正在处理的用例。

在这里,我将演示执行相同 CRUD 操作的两种方法。

4.创建模式、模型、对象

模式就像一个蓝图,它规定了在数据库中存储什么以及以什么格式存储。

为了以一种更舒适的方式发表这篇文章,正如我之前所说的,我将创建一个电影数据库,其中包含电影属性,例如,

  1. 电影名称—(字符串),
  2. 导演—(字符串)
  3. IMDB 评级—(数字)
  4. Cast —(数组)
  5. 发布日期—(日期时间)
  6. 流派—(字符串)
  7. 续集—(布尔型)

存储上述元素的主要原因是合并所有类型的数据结构,如字符串、布尔值、数字、数组、日期时间等。,

在上面的代码片段中,我创建了包含文档蓝图的 movieSchema。

后来我创建了一个常量 movieClass,它是一个模型,是基于模式创建的。

使用该模型,我们可以创建一个实例 aka 对象,用于文档中的一个新条目。它非常类似于类和对象的 OOPS 概念。

如您所见,我创建了一个名为“tenet”的新对象来模仿电影名称,填充了字段,然后保存了它。现在,如果我们检查 GUI 数据库查看器— MongoDB Compass,我们必须看到新创建的文档。

现在让我们以同步和异步的方式进一步进行 CRUD 操作。

5.创建(同步)

我们之前已经创建了一个以“宗旨”命名的新文档。所以现在我们创建一个函数,它可以用来创建许多电影列表。

在声明了函数 insertMovie 之后,我们可以用它的输入参数进行函数调用,这些参数需要在数据库中进行更新。一旦它们被插入,我们将得到插入的文档。

这里我们插入了 3 部电影。

6.创建(异步)

类似地,我们可以在 Mongo DB 中插入新文档,而不需要等待或者没有代码阻塞。另外,我以无代码阻塞的方式添加了另外 3 个电影集。

7.读取(同步)

一旦我们创建了文档,现在我们就可以根据自定义条件过滤它们,并从 MongoDB 中提取特定的文档。

为了简洁起见,我用

  1. 使用唯一标识符提取数据
  2. 通过使用比较操作符来获取数据,比如在 MongoDB 中保留的( >、≥、
  3. Fetch data by using logical operators like (and, or)
  4. Fetch data by using the regex condition.
  5. Fetch data and return the total count of documents.

8. READ (Asynchronous)

READ OPERATION IS STRICTLY SYNCHRONOUS

9. UPDATE (Synchronous)

There are always occurrences where we need to update the document in the future.

So, in the below functions, I have added (append) new records to an array and also replaced the Boolean and Number with new values.

We can use \(push** 和 **\)set 数组更新操作符,您可以尝试所有其他操作符。

您还可以根据下面创建的功能来操作和创建新功能,以符合用例。

10.更新(异步)

有时我们不需要等待数据库更新,所以我们可以启动函数并继续下一行代码,更新可以在适当的时候发生。

11.删除(同步)

通常,我们还可以通过根据文档指定唯一的 id 来删除记录。

12.删除(异步)

13.资源和参考

我希望我能够对 MongoDB 上的 CRUD 操作有所了解。

查看包含完整代码实现的 GitHub repo,并随意破解它。

GitHub—https://github.com/bala-codes/Database-CRUD-Operations

MongoDB——https://www.mongodb.com/

在那之前,下次见。

文章作者:

BALAKRISHNAKUMAR V

Python 列表理解的清晰解释

原文:https://towardsdatascience.com/crystal-clear-explanation-of-python-list-comprehensions-ac4e652c7cfb?source=collection_archive---------29-----------------------

理解它们的高度直观的方式

照片由 Unsplash 上的 Dragos Gontariu 拍摄

列表理解是一种基于集合、元组、其他列表等其他可重复项创建列表的方式。它还可以被描述为用更简单、更吸引人的语法来表示 for 和 if 循环。尽管列表理解相对来说比循环要快。

列表理解的基本结构如下。

(图片由作者提供)

这似乎很简单,但在某些情况下可能会变得棘手。在本文中,我们将从一个非常简单的列表理解开始,并稳步增加复杂性。我也将清楚地解释如何表示和理解高度复杂的列表理解。

在大多数情况下,列表理解优于 for 和 if 循环,因为

  • 它们比循环相对更快。
  • 它们被认为比循环和映射函数更具 pythonic 性。
  • 列表理解的语法更容易阅读和理解。

让我们从一个简单的例子开始。

words = ['data','science','machine','learning']

我们想要创建一个包含单词列表中每个单词长度的列表。让我们用 for 循环和列表理解来完成这个任务。

#for loop
a = []
for word in words:
   a.append(len(word))#list comprehension
b = [len(word) for word in words]print(f"a is {a}")
print(f"b is {b}")a is [4, 7, 7, 8]
b is [4, 7, 7, 8]

理解 list comprehension 语法的最好方法是比较 for 和 if 循环。下图演示了这种比较。

(图片由作者提供)

for 循环末尾的表达式放在列表理解的开头。其余部分从头开始遵循循环中的表达式。

当我们复习这些例子时,就会更清楚了。让我们创建一个包含单词列表中长度大于 5 的条目的列表。

#for loop
a = []
for word in words:
   if len(word) > 5:
     a.append(word)#list comprehension
b = [word for word in words if len(word) > 5]print(f"a is {a}")
print(f"b is {b}")a is ['science', 'machine', 'learning']
b is ['science', 'machine', 'learning']

下图显示了循环中的表达式在列表理解中是如何表示的。

(图片由作者提供)

和前面的例子一样,在 for 循环结束时做的事情放在列表理解的开始。在这种情况下,我们按原样接受该项目。列表理解的下一部分是循环中的第一个表达式,后面是循环中的第二个表达式。

循环中的逻辑更加直观。因此,与循环相比,掌握列表理解的结构相对容易。过一段时间,随着你的头脑习惯了,你就不必做明确的比较了。

下一个例子稍微复杂一些。我们想要创建一个包含单词列表中所有字母“a”、“e”和“I”的列表。此任务涉及嵌套的 for 和 if 循环。

#for loop
a = []
for word in words:
  for letter in word:
    if letter in ["a","e","i"]:
       a.append(letter)

我们来详细说明一下语法。我们迭代单词列表。对于每一项,我们迭代字符。如果一个字符符合给定的条件,它将被追加到列表 a 中。

完成相同任务的列表理解如下。

b = [letter for word in words for letter in word if letter in ["a","e","i"]]

我们从 for 循环中的最后一个表达式开始理解 list。剩余部分从循环的开始处开始。下图说明了每个步骤。

(图片由作者提供)

结论

列表理解是一种功能性很强的高效操作。对于简单的任务,它的语法很容易理解。然而,在复杂的情况下,这可能会变得棘手。

如果你在创建或理解复杂的列表理解上有困难,试着用循环来写。这种方法会帮助你理解语法。

值得注意的是,列表理解并不总是最佳选择。它们将整个输出列表加载到内存中。这对于小型或中型的列表来说是可以接受的,甚至是可取的,因为它使操作更快。

然而,当我们处理大型列表(例如 10 亿个元素)时,应该避免理解列表。这可能会导致您的计算机崩溃,由于内存需求的极端数额。

对于这种大型列表,更好的替代方法是使用生成器,它实际上不会在内存中创建大型数据结构。生成器在使用项目时创建项目。物品用完后,生成者会将它们扔掉。生成器不会导致内存问题,但是它们比列表理解相对要慢。

感谢您的阅读。如果您有任何反馈,请告诉我。

用于存储的 CSV 文件?绝对不行。请改用 Apache Avro

原文:https://towardsdatascience.com/csv-files-for-storage-absolutely-not-use-apache-avro-instead-7b7296149326?source=collection_archive---------9-----------------------

CSV 既耗费金钱又耗费磁盘空间。是时候结束了。

来自 Pexels 的创业股票照片

我不是 CSV 的粉丝。它们的查询速度很慢,占用的磁盘空间也比需要的多。如果你使用云来处理大的 CSV 文件,想想昂贵的

有许多替代方案——比如 Excel、数据库和 HDFs——但有一个方案特别突出。也就是说,如果你想坚持使用行存储。它被称为阿帕奇 Avro,今天你将了解它的全部内容。

如果您想要更高效的列数据格式,只需看看 Parquet:

今天的文章回答了以下问题:

  • Avro 是什么?
  • 如何在 Python 中使用 Avro?
  • CSV 和 Avro——哪个效率更高?

但是 Avro 是什么?

Avro 是一个开源项目,为 Apache Hadoop 提供数据序列化和交换服务。不要担心,你不需要大数据环境,你的笔记本电脑会做得很好。Avro 背后的人是道格·卡丁。他也被称为 Hadoop 之父。

如果你不熟悉术语序列化,这里有一个速成班。这是一个将数组和字典等对象转换成字节流的过程,字节流可以有效地存储和传输到其他地方。然后,您可以反序列化字节流以获得原始对象。

Avro 是面向行的,就像 CSV 一样。这使得它不同于,比方说, Parquet ,但它仍然是一种高效的数据格式。

这是另一个速成班——针对那些不熟悉行和列存储区别的人。假设您有以下数据:

图 1-虚拟表数据(作者提供的图片)

以下是在行存储和列存储中的组织方式:

图 2 —行存储与列存储(作者提供的图片)

列存储文件更加轻量级,因为可以对每一列进行充分的压缩。行存储不是那样工作的,因为一行可以有多种数据类型。

但是 Avro 的情况是这样的——它用一个类似 JSON 的模式存储数据,所以正确的数据类型是预先知道的。这就是压缩发生的地方。

简而言之,一个 Avro 文件包含一个类似 JSON 的数据类型模式和二进制格式的数据本身。

Avro 为每一种主要的编程语言都提供了一个 API。但是有一个问题——熊猫默认不支持。所以不,你不能访问read_avro()to_avro()函数。你必须解决这个问题。

这并不困难——你接下来会看到。

如何在 Python 中使用 Avro?

有两个可安装的库用于处理 Avro 文件:

  • avro — 文档链接
  • fastavro — 文档链接

后者表示,以前的图书馆非常慢,因为处理 10K 记录需要大约 14 秒。出于这个原因,你会坚持使用fastavro

下面是如何设置一个新的虚拟环境并安装必要的库(针对 Anaconda 用户):

conda create --name avro_env python=3.8
conda activate avro_env

conda install -c conda-forge pandas fastavro jupyter jupyterlab

执行以下命令启动 JupyterLab 会话:

jupyter lab

您将使用纽约证券交易所股票价格数据集进行实际操作。数据集采用 CSV 格式,大小约为 50 MB。使用以下代码片段导入所需的库并加载数据集:

import pandas as pd
from fastavro import writer, reader, parse_schema

df = pd.read_csv('prices.csv')
df.head()

股票价格数据集如下所示:

图 3 —纽约证券交易所股票价格数据集(图片由作者提供)

将 Pandas 数据帧转换为 Avro 文件的过程分为三步:

  1. 定义模式 —您必须定义一个类似 JSON 的模式来指定需要哪些字段,以及它们各自的数据类型。将它写成 Python 字典,并使用fastavro.parse_schema()解析它。
  2. 将数据帧转换成记录列表 —使用 Pandas 的to_dict('records')函数将数据帧转换成字典对象列表。
  3. 写入 Avro 文件 —使用fastavro.writer()保存 Avro 文件。

下面是这三个步骤在代码中的样子:

**# 1\. Define the schema**
schema = {
    'doc': 'NYSE prices',
    'name': 'NYSE',
    'namespace': 'stocks',
    'type': 'record',
    'fields': [
        {'name': 'date', 'type': {
            'type': 'string', 'logicalType': 'time-millis'
        }},
        {'name': 'symbol', 'type': 'string'},
        {'name': 'open', 'type': 'float'},
        {'name': 'close', 'type': 'float'},
        {'name': 'low', 'type': 'float'},
        {'name': 'high', 'type': 'float'},
        {'name': 'volume', 'type': 'float'}
    ]
}
parsed_schema = parse_schema(schema)

**# 2\. Convert pd.DataFrame to records - list of dictionaries**
records = df.to_dict('records')

**# 3\. Write to Avro file**
with open('prices.avro', 'wb') as out:
    writer(out, parsed_schema, records)

这不像调用单个函数那么简单,但也没那么难。如果数据集有数百列,可能会很乏味,但这是效率的代价。

还有自动生成名称和类型的空间。发挥创造力。我相信你能处理好。

从 Avro 到 Pandas DataFrame 也是一个三步走的过程:

  1. 创建一个列表来存储记录 —这个列表将存储字典对象,您可以在以后将其转换为 Pandas DataFrame。
  2. 读取并解析 Avro 文件 —使用fastavro.reader()读取文件,然后遍历记录。
  3. 转换为 Pandas DataFrame —调用pd.DataFrame()并传入一个解析过的记录列表。

代码如下:

**# 1\. List to store the records**
avro_records = []

**# 2\. Read the Avro file**
with open('prices.avro', 'rb') as fo:
    avro_reader = reader(fo)
    for record in avro_reader:
        avro_records.append(record)

**# 3\. Convert to pd.DataFrame**
df_avro = pd.DataFrame(avro_records)

**# Print the first couple of rows**
df_avro.head()

下面是前几行的样子:

图 4 —从 Avro 文件中读取的纽约证券交易所股票价格数据集(图片由作者提供)

数据集的 CSV 和 Avro 版本是相同的,但是您应该使用哪一个呢?接下来我们来回答这个问题。

CSV 与 Avro——您应该使用哪一种?

回答这个问题有点棘手。有些人喜欢 CSV,因为你可以直接编辑它们。Avro 没有这个选项。您将看到的所有结果都基于原始的 50 MB CSV 文件。您的里程可能会有所不同。

下面是读取时间— pd.read_csv()fastavro.reader()之间的比较,并附有一个列表:

图 5 — CSV 与 Avro 读取时间的关系(CSV = 0.315s,Avro = 1.15s)(图片由作者提供)

如果数据集为 50 MB,Pandas 的速度大约是它的三倍。

这里有一个写时间的比较——pd.to_csv()fastavro.writer():

图 6 — CSV 与 Avro 写时间的关系(CSV = 2.22s 秒,Avro = 1.33s 秒)(图片由作者提供)

风水轮流转——Pandas 需要更长的时间来保存相同的数据集。

最后一个比较可能是最有趣的—文件大小比较。由于串行化,Avro 应该提供文件大小的显著减少。结果如下:

图 7 — CSV 与 Avro 文件大小(CSV = 51.7MB,Avro = 29.9MB)(图片由作者提供)

虽然不像拼花地板那样降价,但也不算太差。

这对 50 MB 数据集有影响吗?可能不会,但在更大的数据集上,节省的规模也会扩大。如果您在云上存储数据并为整体大小付费,这一点尤其重要。

这是值得思考的问题。

喜欢这篇文章吗?成为中等会员继续无限学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

保持联系

  • 在媒体上关注我,了解更多类似的故事
  • 注册我的简讯
  • 在 LinkedIn 上连接

用于存储的 CSV 文件?不用了,谢谢。有更好的选择

原文:https://towardsdatascience.com/csv-files-for-storage-no-thanks-theres-a-better-option-72c78a414d1d?source=collection_archive---------0-----------------------

将数据保存到 CSV 文件中既浪费金钱又浪费磁盘空间。是时候结束了。

大卫·艾姆里奇在 Unsplash 上的照片

每个人和他们的祖母都知道 CSV 文件是什么。拼花地板,没那么多。它是一种地板吗?是的,但不是——这是一种高效的数据存储格式,今天你将会了解到这一切。

CSV 无处不在——从公司报告到机器学习数据集。这是一种简单直观的数据格式,只需打开一个文件,就可以直接访问数据。它并不像听起来那么好,原因你会读到一点。

CSV 有许多替代方案,如 Excel、SQLite 数据库和 HDFs,但有一个方案尤其具有竞争力。那是镶木地板。

今天的文章回答了以下问题:

  • CSV 有什么问题?
  • 什么是拼花地板数据格式?
  • CSV 还是拼花?你应该用哪一个?

CSV 有什么问题?

我喜欢 CSV,你可能也是。几乎任何软件都可以生成 CSV 文件,甚至是纯文本编辑器。如果你对数据科学和机器学习感兴趣,就去 Kaggle.com 吧——几乎所有的表格数据集都是这种格式。

CSV 是面向行的,这意味着它们的查询速度很慢,并且难以高效存储。拼花地板则不是这样,它是一种柱状储物选择。对于相同的数据集,这两者之间的大小差异是巨大的,您很快就会看到这一点。

雪上加霜的是,任何人都可以打开和修改 CSV 文件。这就是为什么你不应该使用这种格式作为数据库。有更安全的选择。

但是让我们来看看对公司来说真正重要的是什么——时间和金钱。你可能会将数据存储在云中,作为 web 应用程序或机器学习模型的基础。云服务提供商将根据扫描的数据量或存储的数据量向您收费。这对 CSV 来说都不太好。

让我们先来看看亚马逊 S3 的存储定价。这些数字取自这里的:

图 1 —不同数据格式的亚马逊 S3 存储定价(图片由作者提供)

呀。拼花文件比 CSV 占用更少的磁盘空间(亚马逊 S3 上的列大小),并且扫描速度更快(列数据扫描)。因此,相同的数据集以拼花格式存储要便宜 16 倍!

接下来,让我们看看 Apache Parquet 的速度提升:

图 2 —不同数据格式的亚马逊 S3 存储和查询价格比较(图片由作者提供)

又一次——呀!如果您的原始 CSV 文件大小为 1TB,那么 Parquet 会便宜 99.7%。

所以,不,当您的数据很大时,CSV 绝对不是一个好的选择——无论是时间还是成本。

但是到底什么是拼花数据格式呢?

这是存储数据的另一种格式。它是开源的,并在 Apache 的许可下使用。

CSV 和 Parquet 格式都是用来存储数据的,但是它们内部不会有更多的不同。CSV 就是您所说的行存储,而 Parquet 文件则是按列组织数据。

这是它的意思。假设您有以下数据:

图 3 —虚拟表数据(作者提供的图片)

下面是前一个表在行和列存储中的组织方式:

图 4 —行存储与列存储(作者提供的图片)

简而言之,列存储文件更加轻量级,因为可以对每一列进行充分的压缩。行存储则不是这样,因为一行通常包含多种数据类型。

阿帕奇拼花地板是为效率而设计的。原因就在于列存储架构,因为它允许您快速跳过不相关的数据。这样查询和聚合都更快,从而节省了硬件(理解为:更便宜)。

简而言之,对于较大的文件,Parquet 是一种更有效的数据格式。使用拼花地板比使用 CSV 更节省时间和金钱。

如果你是一个 Python 爱好者,在 Pandas 中处理 CSV 文件应该听起来很熟悉。接下来让我们看看库是如何处理 Parquet 文件的。

实践 CSV 和拼花地板比较

您将使用纽约证券交易所股票价格数据集进行这一动手操作部分。CSV 文件的大小约为 50MB 没什么大的——但是您会看到 Parquet 将节省多少磁盘空间。

首先,加载包含 Python 熊猫的 CSV 文件:

import pandas as pddf = pd.read_csv('data/prices.csv')
df.head()

它看起来是这样的:

图片 5 —纽约证券交易所股票价格数据集的头部— CSV(图片由作者提供)

您必须使用to_parquet()函数来保存数据集。它的工作原理在很大程度上与to_csv()相同,所以使用它不会有什么不同:

df.to_parquet('data/prices.parquet')

数据集现已保存。在比较文件大小之前,让我们看看如何加载它。熊猫有read_parquet()功能,用于读取拼花数据文件;

df_parquet = pd.read_parquet('data/prices.parquet')
df_parquet.head()

以下是数据集的外观:

图片 6 —纽约证券交易所股票价格数据集的头部—拼花地板(图片由作者提供)

两个数据集完全相同。命令df.equals(df_parquet)会将True打印到控制台,所以可以随意使用它进行验证。

那么,文件大小有没有减少呢?嗯,是的:

图 7 —纽约证券交易所股票价格数据集上 CSV 与拼花文件大小的对比(图片由作者提供)

这大约减少了四分之一的磁盘空间使用。

这对 50MB 的数据集重要吗?可能不会,但在更大的数据集上,节省也会增加。如果您在云上存储数据并为整体大小付费,这一点尤其重要。

这是值得思考的问题。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

保持联系

  • 在媒体上关注我,了解更多类似的故事
  • 注册我的简讯
  • 在 LinkedIn 上连接

培养数据分析师的技术思维

原文:https://towardsdatascience.com/cultivating-a-technical-mindset-for-data-analysts-c19eb6090089?source=collection_archive---------15-----------------------

凯利·西克玛在 Unsplash 上的照片

培养技术意识,在您的分析职业生涯中超越自我

在我多年的分析生涯中,我遇到过各种背景的数据分析师。这包括从最相关的领域如数学、统计学、信息系统/技术和计算机科学,到不太相关的自然科学(即生物学、工程领域——工业、机械、甚至石油或航空航天工程),以及牵强附会的社会科学(即商业、经济学、甚至心理学和社会学)。

由于数据分析是一个可以跨行业和跨背景应用的通用领域,因此拥有各种背景的角色绝对是可能的并不奇怪。然而,当我观察一些数据分析师,尤其是非数据科学或 IT 领域的数据分析师时,有一点变得很清楚。

尽管聪明绝顶,但许多数据分析师努力提升自己的专业技能,并陷入了恶性循环 查询-描述性分析-报告-重复

我也去过。我一直在那里观察人们。最终,我看到人们打破了这个循环,提升了他们的分析质量。答案? 培养数据分析师的技术思维。

为什么分析师需要技术知识和心态?

能够 设计 一个解析解。

肯·苏亚雷斯在 Unsplash 上的照片

随着组织的成长,产品和流程变得越来越复杂。收集的数据正以更高的数量和速度增长。所需的分析解决方案不再是针对单查询问题如“我们上个月的销售情况如何?”而是转移到战略性、诊断性、预测性和规范性问题,如“我们如何提高客户满意度?"和"我们如何立即识别滥用/欺诈客户?

这些问题的可交付成果范围广泛,从静态知识库的一次性探索性数据分析,到定义变量的统计实验,甚至是产品集成的启发式规则/数据模型——允许可扩展性。无论哪种方式,技术知识在 定义适当的方法 中是至关重要的——什么是技术上可能的,如何执行它,以及当结果不如预期(即低精度/召回问题,高延迟)时如何转向

有了技术思维,分析师将能够(1) 将问题转化为要探索的相关指标,(2) 分解分析任务,以及(3)交付具有统计严谨性的**实用解决方案

拥有技术知识和技术思维将允许数据分析师设计分析解决方案,大规模解决复杂的诊断、预测和说明问题。

到底要发展什么?你如何培养技术感?

这里的技术思维是 超越 仅仅理解技术方面——无论是关于统计、分析技术,还是机器学习算法。它是应用这些方法来解决高质量、可维护性和可伸缩性的现实问题的能力。

1。系统思考:数据是整个产品流程的一部分

这是最基本的,但是我已经看到许多数据分析师(甚至是那些具有卓越分析技能的分析师)忽略了这一点。当然,他们都知道要查询的数据库“表”中的特定“列”。但是他们并不确切地知道这些指标对于现实世界的交易意味着什么或者代表什么。**

例如,假设有一个“客户”表,其中包含客户 ID 及其详细信息。您知道客户记录是什么时候添加到那里的吗?是在客户提交他们的用户名和建议的密码之后吗?还是在邮件验证成功后?两个客户 id 可以共享同一个电子邮件或电话号码吗?

了解这一数据流将有助于您选择更准确的指标进行分析(即选择“已验证”的客户仅用于您的客户分析?),识别您的数据/报告中的异常,并最终调试它们(即两个客户 id 应该不可能有相同的电话号码,因此您可能希望要求项目经理在注册过程中进行验证?).**

除了理解如何检索数据,您还需要理解数据如何为系统增值。战略决策的一次性分析是很好的,但是也许你可以开发一个决策支持系统来集成到产品中?**

例如,除了确定识别欺诈交易的相关标准,你还可以考虑如何在系统中将其生产化。可以组合起来进行实时检测的变量集是什么?它可以与哪种产品服务集成?让我们与数据工程师和产品经理一起讨论吧!

图片由 克拉克

这怎么培养?好奇、探索、询问事物是如何运作的。联系数据/产品工程师,询问产品的数据流图和服务架构。参与产品构思会议或测试,你会惊讶地发现这些技术概念可能并不那么令人困惑。

2.计算思维:逻辑地解决问题

随着你的分析职业和能力的提高,你将会解决更复杂和模糊的问题。这类问题通常不够简单,无法转化为查询或模型公式。这就是计算思维框架发挥作用的地方。

引用 BBC 的话,计算思维有四个主要领域:

  • 分解,把一个复杂的问题分解成更小、更容易处理的部分
  • 模式识别,寻找问题之间和问题内部的相似之处
  • 抽象,只关注重要的信息,忽略无关的细节
  • 算法,设计问题的分步解决方案

将它付诸实践以解决一个分析问题,假设我们试图找出在电子商务产品中驱动客户满意度的因素。

我们可以从列出有助于客户体验和最终满意度的产品接触点开始(分解)。然后,我们定义每个接触点的已知代理指标,即找到产品的时间、预订时间、交付时间等。我们还可以查看现有的客户评论数据,并找到客户提到的交易方面,即产品质量(模式识别)。该数据可能会因客户细分而略有不同,即一些客户可能比其他客户对价格更敏感。但是我们没有明确区分它们,因为我们正在寻找一个通用的解决方案(抽象)。一旦定义了指标,我们就可以开发一个数据模型,将接触点指标作为输入,将客户满意度得分(可通过调查收集)作为输出(算法)。

由活动创作者在 Unsplash 上拍摄的照片

如何培养这种能力?熟能生巧。试着根据给定的分析问题的框架来构建你的思维过程。与你的同事或利益相关者就问题的解决方法进行讨论,以防你遗漏了任何衡量标准或见解。

最后的想法

学习技术知识很重要,但是要利用它,你需要在知识本身的基础上有一个技术思维。系统思维有助于理解系统是如何工作的,因此你可以提供一个适合这个难题的解决方案,并且知道它何时不再有效。在构建解决方案的过程中,计算思维将帮助你将问题分解成数学/计算方程。

培养这种心态和框架,并将其应用到日常工作中可能会很有挑战性,但这是解决复杂问题并最终提升您的分析能力的一种方式。

好奇就好,慢慢学,享受过程!

从原始图像和视频中管理数据集

原文:https://towardsdatascience.com/curating-a-dataset-from-raw-images-and-videos-c8b962eca9ba?source=collection_archive---------17-----------------------

构建图像和视频数据集时要遵循的最佳实践。

作者图片

几乎每个组织都囤积了大量数据。人们杜撰出“数据是新的石油”这样的短语,进一步刺激了这一点。视觉数据也不例外。日志和视频片段不断被打包并存储在机器人车队中。特斯拉汽车不断将录制的镜头发送回特斯拉服务器,用于开发其自动驾驶汽车技术。安全摄像头全天候存储录像。不过,有一个重要的模式需要注意:

虽然生成新数据很容易,但组织和找到相关的数据却极其困难。

让我们以一个安全摄像头设置为例。您有 10 台摄像机以 30 FPS、1920x1080 的分辨率全天候录制镜头。它们都被配置为每隔 10 分钟将视频片段发送回云端。标准的压缩设置导致每天存储 ~1 TB 的视频2700 万个单独的帧。这些视频可能可以通过时间戳进行搜索,但找到有动作或人物的瞬间就像大海捞针一样。如果让人们标记这些图像(假设每张图像需要 5 秒钟),那么仅一天的数据就需要大约 38000 个小时。

使用这些数据建立数据集是很困难的。在这篇博客中,我们将介绍从原始的 Pb 级图像和视频数据中管理数据集的最佳实践。我们将使用安全摄像头示例来指导我们。

我们的示例任务

让我们记住这个安全摄像机设置,并定义一个任务:检测帧中每个夹克周围的边界框。

来自 CamNet 数据集的样本图像,由 UC Riverside 提供。链接到原始数据。

下面,我们将展示一个循序渐进的过程,它将帮助您构建最佳数据集,这意味着对于此任务也是最佳模型。我们将在这里使用标准的深度学习范式,这意味着我们需要一个大型的标记数据集。

作者图片

1.清楚地定义模型应该在哪里工作

深度学习模型与泛化斗争。这意味着为我们的模型设定合理的期望值很重要。我们需要我们的安全摄像机来检测夹克吗,即使在大雪覆盖摄像机镜头的时候?还是我们期待更“理智”的天气状况?让我们考虑几个这样的因素:

  • 天气(晴天、刮风、下雨、下雪)
  • 照明(漆黑、黑暗、昏暗、正常、明亮)
  • 摄像机角度(低角度、面部水平、观看、自上而下)
  • 反射表面的存在(真,假)
  • 运动的存在(真、假)
  • 在场人员(真,假)
  • 模糊度(数字标度)
  • 分辨率(标清、高清、4K 等。)

对于每一个因素或因素的组合,要理解它发生的频率,以及在这种情况下你的用例可以容忍的性能水平。想出每一个可能的变量和它的期望值是非常困难的,但是涵盖你认为最重要的变量并设定期望值是很重要的。

2.收集+预处理您的数据

出去收集一些监控录像。记住上一步的因素,看看是否有办法设置摄像机,使它们能够收集涉及上述所有场景的数据。

对于我们的用例,我们需要提取视频的单个帧来训练我们的深度学习模型。我们需要通过使用指定的文件夹/命名约定保存单个帧来预处理视频,以保持视频顺序完整。这样,您可以在后面的步骤中访问原始数据。

在screen我们发现这部分过程相当烦人,所以我们建立了一个简单回购你可以运行它,它将使用我们的平台自动收集和存储视频数据,以便以后方便查询。通过 API 请求上传视频,Sieve 会处理剩下的事情——更多信息请见本文末尾。

3.理解你拥有的数据

在构建好的数据集的过程中,最被低估的步骤之一是首先理解你可以访问的原始数据。通过了解这一点,我们可以意识到数据收集中存在的任何偏差,并有机会消除它们。将原始数据分布与产生最佳性能模型的精选数据集的分布进行比较也是有帮助的。

我们可以使用步骤 1 中的模型约束变量作为分析数据集的有用指南。理想情况下,我们应该能够用这些分析信息准确地标记数据集中的每个图像。这样,我们对分布有了一个整体的看法:我们有什么,我们没有什么?

根据特定摄像机的 camera_id 或其他唯一标识符以及在数据收集过程中设置的位置,可以自动标记位置(如走廊、走廊、庭院等)和摄像机角度等因素。其他动态因素,如天气、运动、人、照明等,必须以其他形式提取。

通过筛选从 CamNet 数据集标记的图像——作者提供的图像

选项 1:高质量数据标签服务

我们可以将我们的图像提交给一个高质量的标签平台,并要求我们的每个变量都被一群人精确地标记。不幸的是,准确性带来了很高的成本——每个分类大约 0.05 美元,每个图像有 5 个标签,这使得每个样本的总成本为 0.25 美元。

亲:高品质,准确

缺点:成本高

选项 2:类似土耳其人的机械服务

Mechanical Turk 是一个更便宜的标签平台,在这里我们可以支付~ 0.01 美元/分类(比上面低 5 倍)。问题是它提供的专业服务和质量保证检查更少,你必须自己管理。这意味着更便宜的标签,但你需要付出更多的努力和不一致的结果。

教授:它更便宜,但不是很多

缺点:质量不一致

选项 3:基于模型的标签

基于模型的标记使用现有的计算机视觉或深度学习模型,用我们正在寻找的目标变量来标记我们的图像。挑战在于建立良好的模型,能够检测出我们感兴趣的确切特征。我们在这里更大的目标是建立一个检测人的模型,当我们建立这些侧模型时,我们似乎被引入了一个需要更多努力的过程。这就是为什么我们需要利用已经存在的通用模型。同样需要注意的是,我们并不在乎这些标签的 100%准确性。即使我们用这些模型达到大约 75–80%的准确率,与没有任何信息相比,它也能让我们更好地了解我们的数据集中有什么。

传统的计算机视觉模型和算法可以帮助我们确定一些基本的东西,如亮度、照明、对比度、轮廓等等。

像 YOLO-9000 这样的深度学习模型可以帮助我们检测列在它们类别列表下的对象。此外,我们可以根据我们在每个设置中期望的对象类型,有条件地创建其他标签,如“室内/室外”。

我们可以使用更多的尖端模型,如 CLIP 来为我们的一些图像生成精确的字幕,并以这种方式提取更多的标签。

优点:自动,便宜,一致

缺点:不是 100%准确,目标变量略有不同

总的来说,没有一个选项是绝对的赢家。根据你的资金预算、时间预算、团队规模等等,不同选项的组合可能会工作得最好。

然而,我们仍然不能忽视一些问题。最大的问题是我们试图处理的数据量。以 30 FPS 的速度收集视频数据意味着单个摄像机每天会产生大约 260 万个单独的帧。即使使用我们最便宜的基于模型的标记方法,我们也很难在每一帧视频上运行昂贵的模型。我们需要更聪明的东西。

高效的视频处理流水线

如果我们有选择地在特定的视频帧上运行特定的操作会怎么样?假设我们为我们关心的帧建立了一个任意的定义。例如,对于安全镜头,我们可能只关心由运动组成的帧。我们可以在视频帧上运行运动检测器,然后只在这些帧上处理昂贵的模型。我们甚至可以决定运行运动检测器,然后在通过运动检测的帧上运行更便宜的人物检测器模型,然后在通过两者的帧上运行我们非常昂贵的模型。我们可以同时构建各种形式的平滑/聚类,以确定每层中哪些视频“间隔”是感兴趣的,从而消除错误触发。

视频过滤设置示例,由筛提供—图片由作者提供

完成所有这些工作后,我们可以将标签写入数据库,将视频帧链接到它们的相关标签,这样我们就可以进行任意查询,并在宏观层面上分析我们的数据。

4.对好的数据集进行采样

现在我们有了构建一个好的数据集所必需的所有工具。基于我们在第一步中设定的期望值,我们可以构建多个子集来均衡所有提到的变量。

通常,数据可能是在短期内(约 1 个月)收集的,而由于季节和天气等各种因素,在更长的时间跨度内(约 1 年)可能会发生更大的可变变化。这就是您的数据集分布可能与您的模型在现实世界中部署时的分布不匹配的原因。

来自筛网站的基于百分比的抽样查询示例—图片由作者提供

即使直觉告诉我们,您定义的场景并不总是以相同的频率出现,但重要的是从相等的分布开始,并根据模型在训练时的反应对数据集进行迭代更改。考虑到一些场景只是在数据集中出现的频率较低,您可以尝试各种方法,比如从欠采样开始。如果您觉得这样会使数据集过小,请包含尽可能多的少数民族类样本,并将下一个最少出现的类视为少数民族类,以便再次进行欠采样。深度学习模型倾向于与长尾作斗争,因此应用这些技术对于在培训中重新强调这种场景至关重要。

Sieve 的查询功能使得整个过程完全自动化,可以处理 Pb 级的视频。

5.标注数据集

有大量的文献都是关于如何让数据贴上最高质量的标签。诸如秤、标签盒、蜂巢、超级注解等平台都提供了很棒的解决方案。

6.火车模型

通过试验各种超参数、数据扩充组合、模型架构、集合等,遵循典型的模型训练程序。

7.评估模型

当人们谈论模型准确性时,他们通常使用单一的数字或度量。这是一种有缺陷的方法。

你的模型将会有不同的性能水平,这取决于它的部署位置和所处位置的条件。单一指标隐藏了这些性能差异。

就像常规的软件单元测试一样,让我们提出一组案例,或者关键的数据群体,我们可以分别评估我们的模型。如果它分别通过了这些测试,就可以部署了。“通过”这些测试通常是一个任意的性能阈值,由任务的难度、可以访问的数据量以及模型的计算密集型程度来设置。

创建不同的子集场景来测试模型,照片来自筛子 —图片由作者提供

从事最大规模项目的世界级 ML 团队将这种方法视为黄金标准。如果你有兴趣了解更详细的原理,请阅读这篇文章。

8.反馈回路

根据哪些测试用例低于期望的性能标准,我们现在可以尝试一些不同的方法来达到期望的性能水平。

首先,我们可以尝试增加训练集中表现不佳的场景的百分比。这意味着模型更加关注那些特定的情况,意味着更好的性能。然而,这种类型的重新平衡总是伴随着其他场景中的性能折衷——因此需要进行实验来获得正确的平衡。

接下来,我们还可以在每个测试场景中找到我们的模型输出低置信度分数的样本。然后,我们可以进行两种类型的采样,向我们的训练集添加更多的数据。

  1. 在每个标记的属性中,测量包含至少一个低于某个阈值的置信度得分的样本的分布。根据这些分布中的每一个,从原始数据中分别采样更多的图像到我们的数据集中。
  2. 在每个测试场景中查找低置信度的样本,并执行相似性搜索来查找看起来相似的其他图像。在边界框级别进行相似性搜索更加困难,但在寻找具有相似外观对象的场景时更有效。这个过程被称为主动学习。

重新训练您的模型,并循环执行下面的步骤,直到验证数据达到所需的性能水平。

9.最终模型性能

在一组数据上测量最终的模型性能,这些数据在前面的步骤中是完全没有的。这是一种评估模型性能的无偏方法,在训练过程中不会出现偏差。

筛子能有什么帮助

作者图片

在screen,我们正在构建核心基础设施,使处理、组织、搜索和导出 Pb 级视频数据变得容易。我们知道,我们在本教程中描述的只是利用您的视觉数据的冰山一角,并且知道实现任何人都可以使用的即插即用管道所涉及的所有复杂性。使用我们的 API 上传视频数据,剩下的交给我们。这个资源库可以帮你入门。

  • 将视频分割成单独的帧
  • 在帧级别自动生成与领域相关的元数据,如运动、对象、人物等
  • 基于单个帧级元数据搜索您的视频
  • 探索和分析数据统计,如运动帧数百分比等。
  • 基于搜索查询导出数据集,在几分钟内自动打包供下载

上面是使用 Sieve API 和仪表板的简短演练。

如果您有任何问题,请随时留下您的意见或通过 sievedata.com mokshith 直接联系我!

对变分自动编码器(VAEs)感到好奇?从这里开始。

原文:https://towardsdatascience.com/curious-about-variational-autoencoders-vaes-start-here-ab212fc2dd54?source=collection_archive---------31-----------------------

对一个复杂主题的通俗易懂、图文并茂的介绍

近年来,GANs(生成对抗网络)在深度学习生成模型领域风靡一时,而 VAEs 则相对默默无闻。但是,在变化的自动编码器中有一个坚实的基础会有很多好处,它处理类似的挑战,但使用不同的架构基础。如果你正在寻找一种引人入胜、简单易懂的方式来了解 VAEs,那么 Joseph 和 Baptiste Rocca 的介绍非常合适。他们定义了术语,带我们浏览了构成 VAEs 的各种元素以及它们之间的关系,并为所有视觉学习者添加了漂亮的插图。

数据科学和人工智能的当前和未来趋势

原文:https://towardsdatascience.com/current-and-future-trends-in-data-science-and-ai-b404105e73ca?source=collection_archive---------20-----------------------

以及对企业界的影响

肖恩·波洛克在 Unsplash 上的照片

世界上的移动设备比人还多,每次你拿起一个,你就与人工智能互动。从我们的智能手机摄像头在自拍或解锁苹果手机时自动检测我们的面部,到在谷歌上搜索英国顶级咨询公司,或者当网飞向 Siri 和 Alexa 等智能助手推荐下一部值得狂欢的电视剧时,人工智能系统正在成为我们生活的一部分。这些助手利用最先进的人工智能技术来“理解”他们的用户想要什么。但 AI 不仅仅如此。随着这一领域的发展,一个充满机遇的全新世界展现在我们面前。这包括有助于社会和促进经济增长的技术。

作者创造的形象

疫情无疑影响了每个人的生活,并因此影响了企业界。有趣的是,我们正在目睹许多公司的数字化加速,引入新的数字平台来举行更加自动化的后台流程会议。这种数字化转型的副产品是数据,数据是人工智能解决方案的血液。

数据科学和人工智能对人力资源职能的影响

随着大部分人的远程工作几乎通宵达旦,企业与客户联系的本质已经变得更加数字化。许多企业已经转向在线客户参与/互动。工作实践中的这种变化——工作和家庭之间的界限仅被一扇门模糊——不太可能是暂时的转变,因为员工和企业本身都从中受益。特别是,新闻报道谷歌由于在家工作每年节省 10 亿美元,员工受益于更好的工作生活平衡和没有通勤。雇主们意识到,重点应该是你做什么,而不是你在哪里工作。这种思维模式的转变将允许人们申请以前在地理上被锁定的工作,因此,企业将收到比过去多得多的申请。此外,人口群体的包容性和多样性将会增加,这在经济上刺激了“提升议程”,也就是说,你不再需要住在大城市就能获得“城市”工作。

人工智能可以通过利用它来建立模型,以了解未来劳动力的需求,即确定招聘和保留的关键驱动因素。它还可以帮助人力资源部门对候选人做出决定,特别是消除选择过程中的偏见。实际上,作为选择过程的一部分,人工智能系统可以审核或协助人力资源部门确定与特定角色相关的最佳候选人。然而,重要的是,如果人工智能解决方案没有得到彻底的评估和测试,人工智能系统本身可能会引入偏差。这就是为什么亚马逊放弃了开发的人工智能招聘工具,该工具显示出对女性的偏见。此外,这种先进的技术有望帮助“校对”职位描述,以确保它们不分性别,并吸引更广泛和更相关的受众。一个例子可以是扫描工作描述中的攻击性词语或短语,如“粉碎它”,检查代词或具有性别内涵的词语,从而增加候选人的多样性。与网飞利用人工智能对你的观察名单进行个性化类似,人工智能能够根据经验创建个性化的学习和发展路径,以便根据个人优势和发展领域提升员工技能。

数据科学和人工智能对客户服务的影响

许多企业已经上网,因此,所有的客户支持都必须通过电话或在线聊天。聊天机器人将变得越来越普遍,因为它们也变得越来越智能,以减轻人类操作员的一些查询。这在 24/7 全天候服务客户时变得更加重要,并且可能只对人工操作员无法回答的问题进行分类。这将使客户更加快乐,不那么焦虑,因为他们知道他们的问题可以在任何时候得到解决,而不是被搁置或无法联系到任何人。例如,由于新冠肺炎在不确定时期产生了大量的政策检查,一家国际银行希望减少员工回答问题的时间,同时标准化回答。通过利用谷歌云平台,一家咨询公司构建了一个智能聊天机器人,通过执行动态文档搜索和自然对话来应对这些挑战。

此外,由于我们的在线业务和活动显著增加,现在约 60%的总交易在网上进行,相比之下,Covid 之前只有 20–30%的交易在网上进行,以前不一定在网上购物的人现在也在这样做,这通常不是出于选择,而是与 Covid 相关的锁定。封锁期间的“数字窗口”让企业能够收集更多关于客户的数据,并监控在线行为,以定制购物体验,改善客户旅程。例如,人们可以监控用户的行为,并在用户难以导航到他们想要的页面时,通过弹出的聊天机器人进行干预。或者,这可能意味着在浏览界面时定制偏好,以更好地满足他们的期望,甚至是在某些页面上查看产品和服务的建议。简而言之,通过更多地了解客户的行为,并能够预测他们在网上旅行中可能面临的任何潜在问题,或更多地了解他们的需求,就有机会更好地为他们服务。

正如我们所讨论的,人工智能系统可以通过将客户转向不同的自助服务渠道来帮助人类操作员。为了做到这一点,每个渠道中有关客户行为的数据应该是可用的,并创建人工智能系统来预测每个场景中什么更相关和更有帮助。

最后,我们不仅可以通过利用人工智能将电话引导到正确的部门来改善对客户电话的理解,还可以监控电话以了解背景、解决方案和满意度。

数据科学和人工智能对企业基础设施的影响——拉近团队之间的距离

随着越来越多的组织需要增强其数字存在并在该领域进行投资,云服务提供商及其数据科学服务堆栈(如 GCP 的人工智能平台、AWS 的 Sagemaker 或微软的 AML)的使用将会越来越多。这使得更先进的机器学习模型的开发成为可能(特别是深度学习,推动了谷歌翻译/地图等的发展。).从性能的角度来看,这些深度学习方法已被经验证明最适合大数据,而传统统计技术的性能处于平稳状态。

为了利用基础设施并充分利用数据,拥有不同技能的团队必须更加紧密地合作。具体来说,数据工程师、数据科学家和 DevOps 之间将需要更多更密切的合作,以大规模交付有影响力的人工智能解决方案。简而言之,对云服务的投资和正确的技能组合将释放人工智能的潜力。

对幸福的影响

可以理解的是,在解决疫情问题方面已经进行了大量必要的投资。国家和大陆之间的数据共享加速了对病毒动态的集体理解。疫情还迫使医疗保健提供商加快开发人工智能解决方案。从人工智能应用区分各种类型的咳嗽(与 covid vs 无关),到通过自动化数据科学系统了解和区分流感与 covid 症状。主要目的是提高诊断的速度和准确性,以便及早进行医疗干预,挽救生命。

未来可能涉及更多的预测性、预防性和个性化护理。这暗示了人类和机器通过增强智能(AI 和人类智能)的协作。例如,理解和预测幸福恶化的原因将有助于早期干预。

此外,我们知道,许多 NHS 信托机构正在变得或在过去几年中变得更加数字化成熟,采用云技术并收集足够的数据,以便在内部流程中使用人工智能解决方案,使他们能够更快地处理医疗记录和为患者服务。这些系统可用于预测重症监护室的需求,预测患者在那里的停留时间,并优化空间和护士轮班。

考虑到病毒传播和政策,类似的技术可以用来优化机场的空间和客流。

道德和责任 AI

数据中的偏差会导致不公平的模型。Finastra 最近的一份报告可以证明这一点,该报告强调了人工智能模型中偏差的原因和影响。

人工智能可以成为一种好的力量,但如果没有从伦理的角度正确实施,它可能会对社会有害。因此,组织将不得不考虑如何开发和部署具有最佳实践的人工智能解决方案,以确保公平、负责任和道德地使用人工智能。这将是一个潜在的关注和审查领域,因为目前没有统一的指导方针或框架。

可持续人工智能

鉴于云提供商的能力所带来的大量计算能力,在某些使用案例中,对于收益甚微或根本没有收益的复杂模型,错误利用重要资源的风险很高。这将对环境产生巨大影响,因此数据科学家应该对他们采用的模型和方法小心谨慎。更具体地说,创建高级语言理解模型估计需要相当于一次跨美洲飞行的能量。此外,试图用过于复杂的方法解决不同的问题也有效率低下的风险。这是数据科学团队应该考虑的事情,并影响他们在开发方面的选择。

最后的想法

总而言之,我们通过今天计算的镜头来思考 AI 的未来。因此,我们只能讨论人工智能将如何在短期内改变世界。然而,一种新的计算范式在地平线上闪耀,即量子计算,它将把人工智能带到一个未知但令人兴奋的旅程。

更多阅读请见下文:

https://pub.towardsai.net/what-is-artificial-intelligence-ai-deccb034f192 </5-key-ai-problems-related-to-data-privacy-f39558290530>

维度的诅咒——机器学习的“诅咒”

原文:https://towardsdatascience.com/curse-of-dimensionality-a-curse-to-machine-learning-c122ee33bfeb?source=collection_archive---------1-----------------------

维数灾难描述了不断增长的数据维数的爆炸性本质,以及数据处理和/或分析所需的计算工作量的指数级增长。这个术语首先是由 Richard E. Bellman 在动态编程领域引入的,用来解释与增加额外维度相关的欧几里得空间体积的增加。今天,这种现象出现在机器学习、数据分析、数据挖掘等领域。理论上,维度的增加可以为数据增加更多的信息,从而提高数据的质量,但实际上增加了数据分析过程中的噪声和冗余。

机器学习算法的行为——需要数据点和模型的准确性

在机器学习中,对象的特征可以是定义它的属性或特征。每个特征代表一个维度,一组维度创建一个数据点。这表示定义机器学习算法要使用的数据点的特征向量。当我们说维数增加时,它意味着用于描述数据的特征数量的增加。例如,在乳腺癌研究领域,年龄、癌性结节的数量可以用作定义乳腺癌患者预后的特征。这些特征构成了特征向量的维度。但其他因素,如过去的手术,病史,肿瘤类型和其他类似的特征,有助于医生更好地确定预后。在这种情况下,通过添加功能,我们在理论上增加了数据的维度。

随着维度的增加,任何机器学习算法的良好性能所需的数据点数量都呈指数增长。原因是,对于任何给定的特征组合,我们需要更多数量的数据点,以使任何机器学习模型有效。例如,假设一个模型要表现良好,对于特征值的每个组合,我们至少需要 10 个数据点。如果我们假设有一个二元特征,那么对于它的 21 个唯一值(0 和 1 ),我们需要 2 x 10 = 20 个数据点。对于 2 个二元特征,我们将有 2 个唯一值,并且需要 2 x 10 = 40 个数据点。因此,对于 k 个二元特征,我们需要 2ᵏ x 10 个数据点。

Hughes (1968)在他的研究中得出结论,在训练样本数量固定的情况下,任何分类器的预测能力首先随着维度数量的增加而增加,但是在维度数量达到一定值之后,性能会恶化。因此,维数灾难现象也被称为休斯现象。

休斯原理的图示

维数灾难对距离函数的影响:

对于任意一点 a,我们假设 distₘᵢₙ(A 是 a 和它最近的邻居之间的最小距离,distₘₐₓ(A 是 a 和最远的邻居之间的最大距离。

也就是说,对于 d 维空间,给定 n 个随机点,distₘᵢₙ(a≈distₘₐₓ(a 意义,任何给定的点对彼此等距。

因此,当数据中的维数非常高时,任何基于包括 KNN(k-最近邻)的距离度量的机器学习算法都容易失败。因此,在这样的算法中,维数可以被认为是一个“诅咒”。

维度诅咒的解决方案:

减少高维度影响的方法之一是在空间向量中使用不同的距离度量。人们可以探索使用余弦相似度来代替欧几里德距离。余弦相似度对高维数据的影响较小。然而,这种方法的使用也可以特定于问题的所需解决方案。

其他方法:

其他方法可以包括使用尺寸缩减。可以使用的一些技术有:

1.正向特征选择:这种方法包括从所有给定的特征中挑选最有用的特征子集。

2.主成分分析/t-SNE:虽然这些方法有助于减少特征的数量,但它不一定能保持类别标签,从而使结果的解释成为一项艰巨的任务。

参考文献:

1.应用人工智能机器学习课程,https://www . applied AI Course . com/Course/11/applied-Machine-Learning-online-Course

2.G. Hughes,“关于统计模式识别器的平均精度”,IEEE 信息论汇刊第 14 卷第 1 期,第 55-63 页,1968 年 1 月,doi:10.1109/tit . 1968 . 19861986087

使用 TensorFlow 进行自定义音频分类

原文:https://towardsdatascience.com/custom-audio-classification-with-tensorflow-af8c16c38689?source=collection_archive---------6-----------------------

实践教程

包含代码的端到端示例项目

梅尔标度谱图。作者创建的可视化。

在最近的一个研究项目中,我有机会探索音频分类的世界。基于我为此任务创建的代码,我将引导您完成一个端到端的机器学习项目。目标是识别在音频样本上说话的人的性别。

我们将从收集初始数据开始。基于此,我们生成培训、测试和验证数据。为了便于处理,我们将数据存储为 TFRecords 文件。在我们完成数据工程之后,我们创建我们的模型。有了它,我们终于可以进行训练了。

任务描述

给定一个人说话的音频样本,确定说话者是女性还是男性。

这种说法使手头的任务成为一个分类问题;我们有一个数据样本,并给它分配一个或多个标签。为了尽可能多地学习,我们根据免费提供的音频样本,从头开始创建数据。

概观

为了清楚起见,我把这篇文章分成了几个部分:

第一部分是数据采集步骤。

第二部分介绍数据生成。

第三部分是 TFRecords 文件的生成。总的来说,我已经在这里写了这种数据格式的实用介绍。

第四部分结合我们到目前为止所做的一切来做实际训练。

所有部分都以 Colab 笔记本的形式附带代码:

  • 下载 LibriSpeech 数据集
  • 创建我们的定制音频数据集
  • 创建 TFRecord 数据集
  • 训练模型

数据采集

由 Markus Spiske 在 Unsplash 上拍摄的照片

下载、导入和项目设置

我们的第一步是获取数据。对于这个项目,我选择了一个免费的音频数据集,名为 LibriSpeechASR corpus。它包含了自愿朗读 LibriVox 项目有声读物的人的简短片段[1]。

数据集以各种大小的子集提供。我们有几个具有不同挑战性语音(例如,不清楚的发音、口音)的训练和测试集。我选择了 6.3 GB 的 train-clean-100 子集——可以随意选择另一个可能更小的版本;在这种情况下,记得修改下面的代码。

出于演示的目的,代码被编写为在 Jupiter 笔记本上运行,例如在 Google Colab 上。我们将数据下载到挂载(!idspnonenote)的目录中。)Google drive 如果选择不同的位置,请调整路径。在接下来的文章中,你会用到这些数据。

我们首先创建项目文件夹,下载数据并将其提取到我们的驱动器:

现在数据在我们的驱动器上,我们听 10 个随机样本:

[计]元数据

然后,我们查看一下元数据文件,以便识别出在我们下载的子集中出现的所有发言者。检查后,我们删除前 12 行,其中包含对我们的任务不必要的信息:

一个示例行是

20   | F | train-other-500  | 30.07 | *name*

第一个条目是 ID,第二个条目是性别,第三个条目是该发言者所在的子集,第四列列出了该特定发言者贡献的音频内容的总持续时间,最后一列包含该发言者的姓名。

接下来,我们检查所有这样的行(即,检查所有说话者),如果说话者出现在我们的数据集中,则临时存储性别(当第三列显示 train-clean-100 时就是这种情况)。基于这些元数据,我们将说话者分为不同的男性和女性——这是数据采集步骤的关键部分。

请注意我们上面生成的目录列表:我们将迭代下载的目录,它们以包含音频文件的说话者的 ID 命名:如果目录的名称是 345,那么它包含来自 ID 为 345 的说话者的样本。基于这个 ID,我们可以通过查找存储在我们的 available_speakers 文件中的关键字 ID 的值来检查说话者的性别。

最后,我们将列表保存到我们的驱动器中,在下一节中,我们将使用它们来生成我们的培训、测试和验证数据。

这一节到此为止。你可以在这里找到 Colab 上托管的相应笔记本。如果您有建议或发现任何错误,请留言。

音频数据生成

凯利·西克玛在 Unsplash 上的照片

在这一节中,我们将回顾音频数据的创建:我们涵盖了创建训练、验证和测试数据。为了防止测试和验证数据泄露到我们的实际训练数据中,我们将参考我们在上一节中创建的 speaker.pkl 文件。

进口

让我们从安装和导入所有必需的包开始。我决定使用名为 PyDub 的 python 包来创建音频文件;它易于使用,并支持相互叠加和附加音频样本。我们导入了 argparse 包,这样我们就可以轻松地将我们的 Colab 笔记本变成一个。py 文件支持命令行参数:

助手功能

接下来,我们实现几个助手函数。我们从一个简单的动态创建数据集路径开始。请注意混合参数:虽然我还没有为这个项目实现这个特性,但是您可以尝试用代码创建第三个类,男女混合语音样本。

接下来,我们实现了一个函数,该函数返回说话者可用的所有语音样本。在上一节中,我们创建了一个 speaker.pkl 文件来存储演讲者的目录路径。通过这种方法,我们可以获得这个特定说话者的所有样本(不仅是目录,还有实际的)。flac 文件):

在下一个方法中,我们为说话者样本创建训练、测试和验证拆分。请注意,到目前为止,我们还没有创建任何训练数据,我们只是将我们的语音样本分类为不重叠的分裂。我们加载扬声器,对于每个性别,使用前 80 %的扬声器作为训练扬声器,接下来的 10 %作为验证扬声器,最后的 10 %作为测试扬声器。为了使这个过程可重复,我们预先对列表进行排序(我们可以通过使用种子参数来进一步修改它)。

在 return 语句中,使用前面的方法,我们将发言者列表转换为实际样本列表。到目前为止,每个子集都包含发言者目录的路径;现在我们通过这些扬声器获得音频样本的路径:

生成语音样本

最后,我们可以创建两个函数来创建用于训练、测试和验证子集的实际数据。对于文件路径列表( speech_list ),我们加载语音样本,随机置换音频,并存储它们。然后,我们开始将样本叠加到基本声音上( base_sound ),基本声音可以是任何东西,但在我们的例子中只是一个 60 秒的无声音频样本。

注意,我们在这里实现了两个函数:第一个函数覆盖了同一时间位置的所有语音样本,模拟了一屋子人在说话。第二个函数按顺序覆盖样本,中间有 0 到 5 秒的停顿:

您可能已经注意到,在前面的代码中,我们调用了一个函数 permutate() 。函数很短,我们随机改变语音的响度和长度。该函数可以作为更复杂的扩充的起点:

我们现在创建一个小的包装器函数,它包装了上面的三个函数:

在我们最终创建主方法之前,我们需要一个从女性/男性训练、测试和验证子集提取语音样本的函数。我们在下一步实现这个函数。给定一个 number_of_samples 、一个 gender (表示从哪些集合中抽取),以及一个子集(实际抽取的子集),我们从相应的子集中返回一个随机样本列表。如果性别为 1(真),我们从女性集合中抽取,否则我们从男性集合中抽取随机样本:

主要方法

现在,核心方法, create_sample() 。我们创建一个 base_sound ,在上面覆盖所有的语音样本。我决定处理长度为 60 秒的数据,所以我将持续时间设置为 60000 毫秒。然后,我们决定是要创建女性还是男性训练样本。给定这两个信息,我们使用前面实现的方法对一些语音进行采样以进行叠加。原则上,如果我们允许多个说话者在相同的时间戳说话,我们现在决定是否对这个具体的样本这样做(这是我们之前实现两个独立方法的原因)。然后,我们创建语音覆盖,并检查我们创建的数据样本是否足够长。

如果这种健全性检查成立——这对于下一个博客部分很重要——我们将数据样本存储在磁盘上。为此,我们需要子集参数,它告诉我们对哪个子集使用这个生成的样本。这个子集也是标签信息,我们将其与 outname 一起返回:

我们使用这两个信息创建一个 csv 文件的过程中,这个文件包含一个路径->标签映射。我们这样做是为了对我们创建的文件有一个总体的了解。当然,我们可以稍后迭代创建的文件夹,但这是低效的,因为我们可以把它作为副产品。

命令行参数

我们还使用 argparse 模块来定义我们的命令行参数和任何默认参数。 — output_path 参数指向一个文件夹,我们的数据集将存储在这个文件夹中,而 — speaker_file 参数指向在前面的部分中创建的 speaker 文件。其他论点是不言自明的;如果您想要扩展脚本以创建混合类别,列出 — mixed 参数是为了完整性,它没有任何功能。 num_{train,test,valid}_samples 控制相应子集中的样本数量。在研究中,对于大型数据集,分割通常是 80 %、10 %和 10%,但出于我们的目的,我们只是为每个分割创建相同数量的样本。

为了调用所有函数,我们使用 Python 提供的 main 语句。在这里创建的语音样本列表,包括男性和女性,在全球范围内都是可用的。我们为数据子集创建输出路径,然后创建训练、测试和验证子集,并将循环的索引作为当前创建的文件的名称。在 tqdm 包的帮助下,进度是可视化的,它显示一个实时的进度条。在每个子集之后,我们将新创建的样本列表保存到一个 CSV 文件中,供下一节使用:

在 Colab 上,创建一个文件大约需要 5 秒钟,速度很慢。这可能是因为我们将数据写入(缓慢的)Google Drive 存储。在使用 SSD 和更好的 CPU 的机器上,这个速度更快。因为我们只创建一次音频数据,所以这可以忽略不计。

这一节到此为止。该代码可作为 Colab 笔记本在这里获得。在下一节中,我们使用我们创建的音频数据来创建 TFRecord 文件,以使训练高效快速。

正在创建 TFRecord 文件

照片由迈克·本纳在 Unsplash 上拍摄

在本节中,我们将复习如何将最近创建的音频数据写入 TensorFlow 的 TFRecord 文件格式。我假设知道 TFRecord 的布局,但会适当地刷新任何需要的内容。如果你对它不熟悉,你可以在这里阅读我的介绍(我们在这里训练 CNN)或者在这里阅读(我们在这里讨论用 TensorFlow 解析各种数据)。本质上,这种格式以串行布局存储数据,使它们易于从驱动器中读取。说实话,对于只有几百个样本和 MB 的小数据集来说,这个转换步骤可能是不必要的。

对于更大的维度,这是非常方便的——对于一个研究项目,我们有几百 GB 的数据集,数据加载很快成为瓶颈。在对数据处理进行了一些优化之后,我们每个时期的时间从 10 分钟减少到了大约 2 分钟。那更好。

进口

像往常一样,我们从导入所有必需的包开始,这里没有什么不寻常的。我们使用 pandas 库加载我们在上一节中创建的 CSV 文件,使用 librosa 从磁盘加载音频数据。我们还定义了一个全局变量, tfr_dir ,它稍后将指向存储所有 TFRecord 文件的目录:

助手功能

然后,我们创建四个简短的助手函数,将数据点转换为特征对象。这个 Feature 对象是存储在 TFRecord 文件中的核心对象,即存储在一个示例对象中(我们很快就会看到):

有了这些辅助函数,我们就可以定义一个示例文件的布局了。这个字典包含了我们以后可能需要的所有特性:采样率、标签、形状和实际数据。以下函数获取此信息,并返回用转换后的要素对象填充的字典:

主要方法

现在我们来看看创建 TFRecord 文件的核心方法。这个方法相当长,但是这里没有发生什么特别的事情。它是此处所示方法的更复杂版本,也在此处的中涉及。为了更好地理解,我们将分块讨论,从加载 CSV 文件开始,并确定保存所有数据所需的碎片(比如容器)数量。TensorFlow 建议保持单个碎片的大小大于 100 MB,这意味着存储大量的样本。因为我们有一个小数据集,所以稍后我们将只对每个数据子集(训练、验证、测试)使用两个分片。

我们用熊猫加载我们的 CSV 文件,洗牌,然后确定碎片的数量。+1 偏移量用于说明样本数量在两个边界之间的情况:当我们使用 100 的碎片大小(参数 max_files )时,我们将只有 50 个数据点,那么 50//100 将计算为 0。+1 确保我们至少有一个碎片来保存我们的数据。另一方面,如果我们的文件数量是碎片大小的整数倍,那么我们不需要额外的(空的)碎片;我们用 if 语句处理这种情况:

在下面的代码块中,我们首先创建一个文件计数器来计算成功存储到碎片中的文件数量。然后我们迭代每个碎片(称为分割)并为这个 TFRecord 文件创建一个文件名,遵循以下约定:

{当前碎片} {所有碎片} _ {子集}。tfrecords

有了这些信息,我们就可以创建一个 writer 来将文件写入磁盘。然后,我们填充碎片,如果我们已经存储了所有的音频样本,就提前停止。我们在较低部分加载这些样本,并检查样本是否持续 60 秒(60 秒 x 22050 Hz 采样速率= 1 323 000 个数据点):

从这里读取文件后,我们现在可以创建一个示例对象,保存我们上面确定的所有信息。然后,该示例对象被写入当前的 TFRecord 文件。最后,我们增加 file_counter,在循环完所有碎片后关闭 writer,并打印最后一条语句来关闭该方法:

本着类似的精神,我们创建了一个函数,它从给定的子集中加载一些音频样本,并将它们存储到一个 numpy 数组中。这个数组可以在以后的训练中用来记录一些统计数据(我们将在最后一节中看到)。这是完全可选的,我们已经用上面的方法完成了关键部分。

我们消费我们的 CSV 文件;如果它只包含几个样本,我们可以选择使用所有的样本进行监控,而不仅仅是一个小的子集。我们创建一个空的 numpy 数组作为占位符,然后遍历子集并随时填充数组。最后,我们将音频数据和相应的标签存储在两个独立的文件中:

我们的 main 方法首先覆盖全局 tfr_dir 变量(在上面的两个方法中访问过),然后为所有子集创建 TFRecord 文件。可选地,它再次为每个子集创建监视样本。我们通过 args 参数来控制它,它保存了我们所有的命令行参数:

命令行参数

最后,我们用 Python 的 name check 调用 main 方法。这将开始创建我们的 TFRecord 文件:

这一节到此为止。代码可在 Colab 笔记本这里获得。在下一节中,我们终于接触到了这篇文章的深度学习部分,定义了我们的模型和在训练中使用的回调。

培养

阿丽娜·格鲁布尼亚在 Unsplash 上的照片

在这一节中,我将介绍如何处理 TFRecord 数据,如何设置回调,如何设置我们的网络,以及如何进行培训。

进口

像往常一样,我们从进口开始。一个特点是,我们将使用原始音频数据作为输入,并让网络(从而 GPU)做任何进一步的计算。为此,我们使用了 kapre python 包,这是一个定制 TensorFlow 层的集合,专门为音频相关任务而设计。其次,我们还安装了砝码&偏置包、 wandb 。W & B 提供了模型和统计跟踪的无缝集成。我已经将代码设置为不依赖于 W & B(因为免费帐户是必需的),所以您可以在任何情况下运行它:

助手功能

下一步,我们实现两个助手函数。

首先,我们编写一个函数来设置我们可能使用的任何随机生成器的种子,无论是显式的还是隐式的(对于 TensorFlow,我的经验是这很不幸不可靠):

第二个函数为我们创建了一个 logger 对象,为我们将任何感兴趣的东西记录到一个文件中。这是一种常见的最佳做法;我保存日志以验证和理解任何后来的结果。我们将在整个代码中使用返回的 logger 对象:

数据处理

现在我们处理与数据相关的部分,即解析我们在上一节中创建的 TFRecord 文件,并创建一个 TFRecordDataset。为了加载任何 TFRecord 文件,我们首先创建一个函数,该函数返回与模式匹配的文件列表。

还记得我们给 TFRecord 文件起的名字吗?根据文件名,我们将文件分类为训练集、测试集和验证集,记录(并打印)我们在每个子集找到的碎片数量:

既然我们有了获取文件的方法,我们只需要一个方法来提取存储在其中的单个数据样本。在上一节中,我们用以下代码定义了单个样本的结构:

我们现在将模仿它,但是这次提取一个样本,而不是写。我们为数据定义一个字典占位符(类似于上面的),然后用来自单个元素的数据填充它(在我们的例子中是一个音频样本)。

然后,我们获取特征(我们的原始音频数据),并将其解析为张量,然后根据我们存储在 xy 中的数据形状对其进行整形。对于我们的任务,特性及其标签很重要,所以我们只返回这两个:

到目前为止,我们可以找到所有的 TFRecord 文件并解析单个示例。然而,我们的模型不能只在单个例子上工作,所以我们需要创建一个结构来自动解析文件中的所有样本。这就是 TFRecordDataset 派上用场的地方。

我们首先创建一个自动调优对象,它自动确定预取和并行化的最佳参数。给定一个 TFRecord 文件列表,我们创建前面提到的 TFRecordDataset,并将读取缓冲区中的字节数设置为 1000。

接下来,我们将每个元素映射到 parse_tfr_elem() 函数。加载时,每个元素都“通过”此函数,并转换为{要素,标签}对。我们设置了并行调用的数量和要预取到自动调优的元素的数量。

如果我们提供了一个缓存路径,我们就可以将数据集缓存到这个位置,否则我们就将它缓存在 RAM 中。如果您的数据驻留在慢速硬盘上,此选项非常有用,可以防止在每个时期重新加载样本。这是可选的,如果不需要任何缓存,只需删除这四行。

最后,我们洗牌,批处理,并重复数据集。如果我们不启用重复,数据集将在一次迭代后耗尽:

分销策略

在接下来的代码中,我们动态定义在何种策略下训练模型。编写与策略无关的代码的优点是,它可以在单个训练设备上工作,也可以在两个、三个甚至更多的设备上工作。(到目前为止,我已经使用这段代码用两张卡进行了多设备训练,以及 TPU 训练)。代码不是我写的,而是来自 Hugginface 的变形金刚库:

复试

接下来的两个代码块用于训练期间的回调,我已经在这里稍微详细地介绍过了。

我们实现了一个 ClassificationReportCallback,它每隔 k 个时期将 sklearn 的 分类报告写入 TensorBoard。如果我们想用 W & B 记录我们的实验,我们可以选择在那里上传报告:

第二个定制回调是 ConfusionMatrixCallback,它在每个频率时期创建一个混淆矩阵。代码主要基于 TensorFlow 的教程:

有了两个定制回调函数,我们现在需要一个方法来设置它们。为此,我们首先为我们记录的所有内容创建一个 TensorBoard 目录,并创建一个 file_writer 对象。有了这个对象,我们可以方便地将图像、标量和文本数据记录到 TensorBoard,我们已经在上面的两个回调中看到了这一点。

然后我们实例化一个 TensorBoard 回调来监控训练,这里没什么特别的。更有趣的是设置我们自己的回调。我们从混淆矩阵回调开始。顾名思义,它在每个 k 时期后生成一个混淆矩阵。为了创建这个图,我们解析一些样本数据——还记得我们在 TFRecord 生成步骤中另外保存到一个 numpy 数组中的数据吗?我们现在将使用它来生成实时混淆矩阵,并使用我们之前创建的 file_writer 对象将其写入 TensorBoard。

我们创建了两个这样的回调,一个用于验证样本,一个用于训练样本。

我们实例化的下一个回调是 ClassificationReportCallback。我们用它来记录每 k 个时期的训练统计数据:

precision    recall  f1-score   support male       0.00      0.00      0.00        10
  female       0.60      1.00      0.75        15accuracy                           0.60        25

我们使用的最后一个回调是默认的 EarlyStopping 回调。深度学习的一个常见问题是过拟合。该模型(越深、越大的模型越容易出现这种情况)在训练数据上取得了高分,但未能推广到看不见的数据。有几种方法可以防止这种情况,一种是使用单独的验证集。一旦这个子集的分数在耐心时代没有变得更好,我们就停止训练;我们还可以从这个最佳状态恢复模型的权重。

如果我们使用 W&B,我们最后设置他们的回调。It 自动处理他们服务器的日志数据。

所有回调都准备好了,然后我们返回它们的列表:

音频功能

现在我们终于来到了模型设置。为了理解这一点,让我们简短地了解一下音频分类的世界:

您可能已经注意到,我们将原始音频数据写入 TFRecord 文件,并且我们还将原始音频数据提供给我们的模型。通常的方法,也是我在论文中使用的方法,是使用特征来代替。特征是数据的可测量或可观察的特征;一个常见的音频特征是(Mel 标度的)声谱图。

在我们深入讨论之前,让我先介绍一下声谱图。正常频谱图显示给定时间标记的频率功率:

请注意,我们使用的是对数标度,数值越高表示功率越大。基于这个正常的谱图,我们得到了梅尔标度的谱图:

人类的听觉系统可以处理高达 20,0 00 赫兹的频率(根据年龄、训练和天赋,可能会有所出入),但不是线性的。在 12 000 赫兹之后,辨别频率或声音的能力大大下降[2]。Mel 标度建立在这一事实上,较低的频率范围被映射到更多的仓,较高的频率被映射到较少的仓。

换句话说:对于较低的频率,我们有窄的仓,也就是说,只有很小范围的频率被捕获。对于较高的频率,我们有较宽的仓,也就是说,较宽范围的频率被映射到相同的仓。请注意,y-轴仍然是对数轴,但仅达到 4 kHz——与正常频谱图相比,在此范围内具有更多能量。

另一个很酷的特性是 Delta 特性,即给定时间戳的曲线(在我们的例子中,曲线是音频信号)的导数的近似值。我读过一些将 Mel 谱图和 Delta 特征相结合的论文[3]。这就是我们在这里所做的:我们的第一个通道保存 Mel-spectrogram,我们的第二个通道保存它的 Delta 值。

现在,为什么不预先计算它们呢?因为,如果我们要改变任何有影响的参数,我们必须从头再做一遍。让网络做计算的好处是第一我们可以更快地进行实验,第二我们可以将创作参数化,第三我们可以保持原始数据不变。我们也不会在硬盘上放更多的文件夹和文件。

话虽如此,我们现在可以回到定义网络。

模型

第一层是我们的输入层,它接收 shape (1323000,1)的数据样本。第一个来自 60 秒× 22050 Hz,即 60 秒,每秒 22050 个数据样本。第二个条目 1 是通道数,在我们的例子中是单声道。(边节点上, kapre 支持更多声道,我见过 6 声道音频输入)。

接下来,我们定义特定于音频的 Mel 谱图层。顾名思义,这一层从原始音频输入生成 Mel 缩放的声谱图。参数控制产生的声谱图——覆盖它们不是这篇文章的范围。如果你对它们的效果很好奇,可以查阅 librosa 的文档。

下一层是 Delta 层,计算声谱图输入的 Delta 值。我们将它们结合起来,得到一个双通道张量。

下一步操作,由层分帧,我们将输入分割成帧。这是一种常见的技术。想象一个很长的音频样本:不是把它保存在这个长版本中,而是把它分成(重叠的)片段。这就是这里发生的事情。

接下来的块是非常标准的:我们使用卷积批处理范数丢弃池块。第一种方法让内核学习低级特征,第二种方法将输出的平均值调整到接近 0,其标准偏差接近 1。(这是统计,或者更确切地说是分布扮演重要角色的情况之一)。dropout 层防止过度拟合,MaxPooling 层将每个维度减半,而不考虑最后一个维度;因为我们将池大小设置为(2,2,2)。

这个块重复四次,最后一个块有一个全局最大池操作。该操作仅选择每个轴的最大值。我们这样做是为了保持较小的权重——我们可以直接使用密集层,但那样会大幅增加权重的数量。

我们以具有两个神经元的密集层结束我们的模型,每个类一个,并且 softmax 激活。这种激活返回神经元上的概率分布,其总和为 1。为了推断我们的阶级,我们取最高值的位置。如果我们的预测向量将是[0.2,0.8],那么类将是 1(女性,对于我们的整体任务)。

相应的代码:

上面的代码依赖于一个配置文件。下一个方法创建了我们的模型配置:

为什么我们使用配置文件,而不是对超级参数进行硬编码?首先,您可以轻松地将此配置记录到磁盘中,其次,您可以从磁盘中调整和加载这样的配置,第三,您可以将它合并到超级参数搜索中。

设置

有了上面定义的主函数,我们现在创建几个包装函数。遵循干净代码的原则,这些函数相当简单,它们主要做一件事,调用前面的代码。

第一段代码用于建立模型。给定一个训练策略,模型配置(核的数量,退出概率等。),以及命令行参数(args 参数),我们创建一个模型并编译它。作为损失,我们使用稀疏分类交叉熵;这与 CategoricalCrossentropy 相同,但是与非一个热点向量一起工作,即,它与原始类别号一起工作,而不需要将它们编码为一个热点向量。这同样适用于稀疏分类的准确性。

其次,我们还将模型的可视化保存到我们的 out_dir 中,这是所有内容都写入的主目录。除了 rankdir 之外的参数都是自解释的。此参数控制绘图的方向;“TB”代表垂直图(如上所示),“LR”代表水平图:

下一个函数将我们训练好的模型保存到磁盘上。如果模型目录不存在,我们就创建它,然后将模型保存在那里。因为我们使用自定义层,所以我们使用的“TF”保存格式 t:

使用下一个函数,我们将根据测试数据评估我们的模型。我们记录一个格式良好的消息,包含我们已经达到的损失和准确性,并返回这两个值。 test_dataset 不需要传递给函数,它是全局可用的(您很快就会看到),logger 对象也是如此:

下一个短函数只服务于一个目的:模型训练。它接受模型、训练期间要应用的回调列表以及命令行参数(其中我们只需要 epochs 的数量)。因为我们将数据集设置为无休止地重复(见上文),所以我们需要告诉 TensorFlow 一个历元包含多少个批次,包括训练数据集和验证数据集。一旦训练结束,我们返回训练好的模型:

有了这些简短的函数,我们创建一个函数来适当地调用它们。我们从设置种子开始,然后请求我们的模型配置。如果我们想使用 W&B,我们在这个地方登录(完全可选)。然后,我们确定用于训练模型的分布策略,并用它来建立我们的模型。最后,我们初始化所有的回调,这些回调和模型一起返回:

这个函数是由我们的 main()函数调用的,它负责调用 setup 函数,打印模型的概要,以及训练。我们也可以将我们的结果记录到 W&B(完全可选),然后运行一些步骤来关闭代码:

培养

现在,运行这一切的代码:我们使用 argparse 库来解析命令行参数。他们控制保存模型的目录、训练时期的数量、批量大小、种子等等——只需查看他们的描述:

在我们解析了命令行参数之后,我们使用 python 的 if name == "main" 语句来完成所有工作。

我们创建输出目录,并确定实际的批量大小。如果我们有两个或更多的设备来训练,我们将我们的 per_device_batch_size 乘以设备的数量来加速训练。你可以尝试这些价值观,它们只是一个坚实的基础。

确定了批量大小之后,我们就可以确定迭代训练、测试和验证集所需的步骤数量。这个值是通过将数据集长度(在我们的例子中是 50,因为我们每组有 50 个音频样本)除以批量大小来计算的。

我们还加载我们的回调所使用的额外的 numpy 数据。

这里发生的一切都是全局可用的,因此我们不必向 main 方法传递任何东西——args参数只是为了说明。一旦 main()被调用,它将设置网络,训练它,保存它,并评估它。当我们看到时,脚本已经成功完成

Script finished.

在尝试检测测试集中说话者的性别后,我得到

Finished evaluation. Loss: 0.3812, Accuracy: 0.9583.

就是这样。代码可以在 Colab 笔记本上找到,这里是。

摘要

总结一下我们所做的:

我们的总体任务是使用定制的音频数据对说话者的性别进行分类。

我们从下载公共 LibriSpeech 数据集开始,该数据集由自愿阅读有声书籍的人的简短音频样本组成,并创建了一个按性别排序的发言者索引。

有了这些文件,我们创建了自定义的音频数据集;一个类是男性类(标签 0),另一个类是女性类(1)。我们创建了训练集、验证集和测试集。

在第三步中,我们从原始 FLAC 音频数据创建了一个 TFRecord 数据集。我们这样做是为了加速数据加载——数据是按顺序保存的——也是为了学习如何使用它(TFRecords 真的很有用。但是有点复杂。参见获取实际操作指南。

在我们的第四步,也是最后一步,我们结合了之前所做的一切:我们编写了加载数据集的代码,我们使用了自定义回调,是的,我们还做了一些深度学习的事情:创建和训练模型。

现在何去何从?

有些事情你可能已经注意到了。

首先是数据集的大小。您可以将其增加到数百或数千个样本——我已经使用代码创建了一个包含 10 000 个样本的数据集,因此这是完全可能的。在这种情况下,您必须在本地运行,因为 15 GB 的 Google Drive 存储空间是不够的。

第二个值得注意的事情是不稳定的训练:损失和准确性跳来跳去。先尝试不同的学习速率,然后用其他优化器进行实验。

第三种选择是尝试完全不同的架构——一个连体网络,一个 LSTM。

这篇博文到此结束。

Colab 笔记本的链接,让你自己动手:

  • 下载 LibriSpeech 数据集
  • 创建我们的定制音频数据集
  • 创建 TFRecord 数据集
  • 训练模型

参考

[1] Panayotov,Vassil 等人, Librispeech:一个基于公共领域音频书籍的 asr 语料库 (2015),IEEE 声学、语音和信号处理国际会议(ICASSP)

[2] R. J. Pumphrey,人类听觉频率的上限 (1950),自然

[3]凯罗尔·j·皮扎克,卷积神经网络环境声音分类 (2015),IEEE 第 25 届信号处理机器学习国际研讨会

定制 AWS SageMaker:训练和部署假推预测器

原文:https://towardsdatascience.com/custom-aws-sagemaker-train-and-deploy-fake-tweets-predictor-9178f20d0f99?source=collection_archive---------23-----------------------

在数据和信息技术领域,云提供商势头强劲。AWS、Azure、Google Cloud 等最大的云提供商不仅在云中租用硬件。它们还为机器学习模型的简单操作提供了基础设施。在我的上一篇文章中,我提到了用谷歌云训练模型的可能性。同时,AWS 提供了自己的一套工具来训练和管理模型。在这篇文章中,我想深入探讨的工具之一是 AWS SageMaker。

我不确定 SageMaker 的名字是否与鼠尾草(鼠尾草)有关,但是我喜欢它的味道。

照片由菲利普·拉金在 Unsplash 上拍摄

SageMaker 是一款准备、构建、培训和调整、部署和管理机器学习模型的首选工具。SageMaker 提供了大量的预设置和即用型容器。范围涵盖了不同的框架:PyTorch、Scikit-learn、Chainer、MXNet 以及 Huggingface。当您想要构建一个只使用其中一个框架的模型时,设置容器是很方便的。但是越来越需要使用它们的组合。例如,我可能想从 Huggingface 获取一个模型,并在输出中添加一些 Scikit-learn ML 模型。那我该怎么办?幸运的是,可以构建一个定制的 Docker 容器并用 SageMaker 部署它。这可能是一个不错的通用解决方案。然而,如果使用 Scikit-learn 部署预构建容器需要大约 10 行代码,那么定制 Docker 的开发可能需要一些时间。如果我告诉你有一个中间的解决方案。它花费了超过 10 行的代码,但是,你不应该为 SageMakers 定制 Dockers?忍耐一下,我们会找到路的。

问题描述

目标

为了展示定制的 SageMaker 设置,让我们看看一个 Kaggle 竞赛数据集的例子,它由关于灾难的虚假和真实推文组成。任务是对推文进行分类。在这篇博文中,我们构建了一个应用程序,它接受文本作为输入,并返回关于灾难的推文是真实的概率。最终的应用程序可能如下所示:

我们可以将任务分成三个子任务:

  1. 使用 SageMaker 培训和部署定制模型
  2. 创建将使用 SageMaker 模型的 API
  3. 构建并部署一个 Flask 应用程序,它将获取 tweets 并返回 API 的结果

在这篇博文中,我们将详细讨论第一个任务。另外两个在 AWS 教程、 TECHFRONT 帖子中有所涉及。最终的架构将如下所示:

AWS 教程、 TECHFRONT 帖子

这里我们故意牺牲模型的准确性(不包括其他特征,不了解太多数据,不降维等。)为了训练脚本简单起见。目的是展示如何使用 SageMaker 训练和部署一个应用,而不是展示如何建立一个准确的模型。人们可以在 Kaggle 的相应解决方案中了解更多关于构建更好模型的信息。

数据集

数据集由带标签的虚假和真实推文组成。标签在“目标”栏中提供。有几个特征,尽管为了这篇博文的目的,我们将只使用“文本”字段来表示推文的文本。

更多信息请参见卡格尔比赛

记住,我们要对真假推文进行分类。

模型训练脚本

对推文进行分类的一个选择是导出推文的嵌入,然后在其上运行一些分类算法。HuggingFace 是一个很酷的库,可以为嵌入推文提供模型!只需要几行代码就可以派生出嵌入:

所以我们得到了嵌入,现在可以进行分类。Scikit-learn RandomForest 是这项任务的理想人选。培训脚本可能如下所示:

在这个设置中,使用了两个机器学习库:HuggingFace 和 Scikit-learn。我们现在知道我们想做什么了。让我们在 SageMaker 上训练和部署模型!

列车&部署!

准备工作

下面的部分,我用的是 SageMaker 的 Jupyter 笔记本。请进行相应的设置,以确保 SageMaker 可以提前访问 S3 桶!

首先,在 SageMaker 的 Jupyter 实验室中,我们需要创建一个目录,我们的培训+部署脚本就位于这个目录中。该目录可能如下所示:

Deployment_Notebook.ipynb
mysrc
|--serve.py
|--requirements.txt

总共有三个文件。在下一节中,我们将详细介绍这些文件:requirements.txt、serve.py 和 Deployment_Notebook.ipynb。在这里,我们将放置我们想要使用的库。在我们的例子中,它是 HuggingFace 和 Scikit-learn。requirements.txt 看起来是这样的:

scikit-learn==0.24.1
transformers==4.5.1

训练部署脚本:serve.py

我们的 serve.py 文件有两个目的。它必须能够:(1)训练模型和(2)部署模型。因此,它应该由两部分组成:

先说培训部分。当我们指示 SageMaker 训练模型时,它将执行 if _ _ name _ _ = = ' _ _ main _ _ ':in serve . py 脚本中的任何后续内容。因此,我们将这篇博文的“模型训练脚本”中的脚本稍加修改:

现在数据存储在 S3 桶中,所以我们直接从 PATH_TO_DATA 文件中读取我们的训练数据(不要忘记插入您自己的路径)。另外,在 SageMaker 容器中有一个名为 model-dir 的环境参数。我们应该解析它,将我们的模型存储在由该参数定义的文件夹中。

在部署阶段,SageMaker 容器希望我们在 serve.py 中定义四个函数:

如果没有定义这些函数,就有默认的替代函数。默认情况下, input_fn 期望拥有 NPY 格式的参数 request_body 。在我们的例子中,我们需要将其修改为 JSON,因此我们的部署脚本部分看起来应该是这样的:

在组合训练和部署部件之后,我们得到 serve.py 文件。

用 SageMaker:Deployment _ notebook . ipynb 运行测试

HuggingFace 依赖于 PyTorch python 库。为了减少安装时间,我们可以选择 SageMaker 的 PyTorch estimator。这将在预装 PyTorch 的容器中部署我们的脚本,因此我们不必将 PyTorch 添加到 requirements.txt 文件中。现在我们准备在 SageMaker 笔记本中运行脚本:

我们应该使用 Predictor 类来告诉容器接受 JSON 格式。另外,PyTorch 估计器要求指定一些参数:PyTorch 的 framework_version 和 python 的版本。我们用 sourced_dir 参数告诉估算器我们想要哪个文件夹复制到容器中。此外,我们将入口点定义为我们上面构建的 serve.py 脚本。在执行这些命令之后,我们将为模型做好一切准备并部署它。这可以通过以下命令来完成:

在计算实例上剥离容器,然后部署端点,大约需要 5 到 10 分钟。完成后,我们可以用 boto3 测试我们的端点:

训练部分应该返回两个概率。

在 EC2 中构建 API 和 Flask App!

接下来的步骤是创建一个 API,并在 EC2 实例上部署 Flask 应用程序。如上所述,这些任务在 AWS 教程和 TECHFRONT 帖子中有很好的介绍。烧瓶应用程序代码和 SageMaker 的完整代码可以在 GitHub repo 中找到。祝你快乐!

变压器的自定义回调函数

原文:https://towardsdatascience.com/custom-callback-functions-for-transformers-ae65e30c094f?source=collection_archive---------24-----------------------

在为 NLP 任务微调预训练的变形金刚时,如何量化 F1-Score?

图片由 Samule 孙在 Unsplash

介绍

自从 Vaswani 等人(2017)发表了“注意力是你所需要的全部”论文以来,变形金刚一直主导着自然语言处理(NLP)领域的最新进展,其中针对下游 NLP 任务微调预训练语言模型已经变得相当流行。如果你不熟悉变形金刚,这篇文章和这篇文章是很好的起点。Jay Alammar 的图解示例也是一个很好的资源。

《变形金刚》库由 Huggingface】🤗提供几个预先训练好的模型,以便于执行下游任务,如文本分类、文本生成、摘要、问答等。变形金刚库与最流行的深度学习平台 JaxPyTorchTensorFlow 兼容,并提供 API 来下载和微调预训练模型,并提供各种 NLP 任务的可用数据。

在为分类任务微调预训练模型时,我们通常使用诸如损失 ( 二元交叉熵分类交叉熵等)和准确度等指标。然而,当数据不平衡时,我们通常会对模型训练期间和验证数据上的监控指标感兴趣,例如精度召回F1-分数。TensorFlow 的 Keras API 不会在每个时期结束时直接访问这些指标。简而言之,TensorFlow 2.0 中删除了这些指标,因为对每批进行评估会产生误导。然而,我们可以开发并利用一个定制的回调函数来量化每个时期结束时整个验证数据集的这些指标,这将在本文后面讨论。

什么是精度、召回率和 F1-score,如何量化?

在任何分类或信息检索任务中,当数据不平衡时,准确性可能不是性能评估的可靠度量。这就是精确度、召回率和 F1 分数被认为是模型性能评估的良好替代指标的地方。在分类的情况下,精度与 I 类误差或对目标类别的高估有关。回忆与第二类错误和低估目标类别有关。换句话说,高精度说明没有太多的误报,高召回说明没有太多的漏报。F1 分数是两者的调和平均值,因此非常有用,因为它很好地平衡了低高估和低低估。这篇 TDS 文章提供了包括公式在内的进一步见解。

在 NLP 任务中,这些度量变得非常有用,例如当我们处理文本分类任务(以及其他任务)时,其中类别的比例严重不平衡,我们希望确保我们评估模型的方式能够指示所有类别的性能,而不仅仅是具有较高频率/比例的类别(与准确性不同!).

Python 的 Scikit-Learn 库提供了计算这些指标的 API,包括多标签场景的选项。如下所示,当使用 F1_score 时,参数‘average’默认为’binary,它只报告由参数‘pos _ label’指定的类的结果。或者,参数‘平均’可以设置为‘微观’‘宏观’‘加权’‘样本’

根据 Scikit-Learn 关于 F1-score 的官方文档,option 【微】通过计算总的真阳性、假阴性和假阳性来计算全局指标。选项‘宏’计算每个类的度量,并找到它们的未加权平均值,其中它平等地对待所有类。选项‘weighted’计算每个类的指标,并根据每个类的实例数计算它们的加权平均值。这将改变“宏”以说明标签不平衡,并可能导致F1-分数不在精确度和召回率之间。最后,‘samples’计算每个实例的度量,并求出它们的平均值。Scikit-Learn 的 precision_scorerecall_score 具有类似的平均选项。

在本文中,我们将sk learn . metrics . f1 _ score传递给一个 Keras 自定义回调函数,这样我们就可以维护所有平均选项的可选性。

微调变压器时计算 F1 分数的自定义回调

Keras 是用 Python 编写的深度学习 API,运行在 ML 平台 TensorFlow 之上。在 Keras 中,回调是一个可以在训练的不同阶段执行动作的对象(例如,在每批训练后写 TensorBoard 日志,或者定期保存模型)。回调被传递给各种 Keras 方法(例如,fit、evaluate、predict ),因为它们与模型训练、测试和预测生命周期的各个阶段挂钩。

如上所述,对于精度、召回率和 F1 分数等指标,我们需要对整个数据集进行评估,而不是对任何一个批次进行评估,否则会产生误导。因此,我们可以使用历元级方法' on_epoch_end(self,epoch,logs=None)' ,其中 logs 字典包含丢失值,以及一个历元末尾的所有其他度量。此外,' self.model' 属性用于访问与当前一轮训练相关联的模型,该模型可用于对验证数据进行评估。下面是一个示例代码,使用全部验证数据,在每个时期结束时量化并打印出 F1 分数:

在上面的示例中,' __ init__' 方法在传递验证数据的同时实例化对象。接下来,' on_epoch_end' 方法在每个 epoch 结束时量化 F1 分数值,并填充 logs 对象。需要注意的是。predict 方法返回所有类的逻辑值(而不是类概率或类标签)。因此,我们需要应用 Softmax 函数将它们转换成概率。随后,我们应用 numpy 的 argmax 来指定具有最高概率的类作为预测标签。

GitHub 上提供了一个工作示例,用于微调变压器(本例中为 DistilBERT ),同时在每个时期结束时计算整个验证数据集的 F1 分数。在这个工作示例中使用了一个公共数据集,其中训练集的一个子集用于微调,整个测试集被传递给。将方法作为验证集。然后,回调函数量化并报告验证集的 F1 分数以及每个时期结束时的损失和准确性:

作者图片

感谢阅读!请在 GitHub 上关注我,在 LinkedIn 上联系我,或者在 Twitter 上关注我,我会在那里发布我正在进行的工作和其他与数据科学相关的有趣文章!

Pytorch 中的自定义数据集—第 1 部分。形象

原文:https://towardsdatascience.com/custom-dataset-in-pytorch-part-1-images-2df3152895?source=collection_archive---------3-----------------------

马克·特里亚皮奇尼科夫在 Unsplash 上拍摄的照片

Pytorch 有一个很好的生态系统来加载定制数据集,用于训练机器学习模型。这是关于在 Pytorch 中加载自定义数据集的两部分系列文章的第一部分。在第 2 部分中,我们将探索为机器翻译任务加载自定义数据集。在本演练中,我们将了解如何加载自定义影像数据集进行分类。本演练的代码也可以在 Github 上找到。

在这里,我们将使用可用的地标数据集。它是谷歌地标数据 v2 的子集。它有 50 个班级,包含来自世界各地的各种地标。

在本练习中,我们将保持以下文件夹结构:

图一。我们数据的文件夹结构(来源:self)

这是一个简单的文件夹结构,根文件夹是 Train/Test 文件夹,其中包含带有图像的类。正如我们将看到的,我们用什么结构获取数据并不重要。数据可以全部放在一个文件夹中,图像名称中有类名(如“Cat_001.jpg”),甚至可以放在一个 CSV 文件中,我们可以在自定义数据集类中处理所有这些数据。

此外,我们将使用albuminations库进行图像增强。这个库包含了大量可用的图像增强选项。因此,我们将了解如何在我们的自定义数据集管道中使用它。您可以使用以下方式安装它:

pip install -U albumentations

图二。白蛋白中图像增强的例子(来源:https://github.com/albumentations-team/albumentations

让我们编码

1.导入库

2.定义转换

接下来,我们使用白蛋白定义我们的扩增。我们为训练和测试定义了不同的扩充。我们对训练数据应用与裁剪/旋转、颜色/饱和度和亮度相关的变换。我们还用图像净平均值和标准差来归一化训练和测试数据。最后,我们使用 ToTensor()将数据转换为 PyTorch 张量。

3.创建训练集、有效集和测试集

接下来,我们创建训练集、有效集和测试集。这里,我们为训练集、有效集和测试集创建单独的图像路径列表。这些将在我们的数据集类中使用,该数据集类将为自定义数据集定义。

我们得到以下输出:

train_image_path example:  images/train/15.Central_Park/462f876f97d424a2.jpgclass example:  42.Death_Valley_National_Park

Train size: 3996
Valid size: 1000
Test size: 1250

4.创建索引到类和类到索引字典

我们不能直接为模型使用类名。我们创建类到索引和索引到类的映射。

我们得到 idx_to_class 的输出如下:

{0: '42.Death_Valley_National_Park',
 1: '39.Gateway_of_India',
 2: '13.Yellowstone_National_Park',
 3: '44.Trevi_Fountain',
 4: '32.Hanging_Temple'}

5.数据集类

这是我们自定义数据集的核心。数据集类的结构如下所示:

图 3。数据集类的结构

我们通过继承 Dataset 类来创建我们的 LandmarkDataset 类:

from torch.utils.data import Dataset

首先,我们定义 init 函数。一旦我们创建了 LandMarkDataset 类的实例,默认情况下就会调用这个函数。这个函数应该包含我们想要在整个数据集(如 train) 上运行一次的所有操作。在本系列的下一部分,我们将创建一个定制的机器翻译数据集,这一点的用法将会更加清楚。现在,我们为相应的训练集、有效集和测试集定义 image_paths 和转换的变量。

然后我们有 len 函数,它只返回数据集的长度。数据加载器随后使用它来创建批处理。

最后,我们有 getitem。这一次处理并返回一个数据点。

从上面可以看出,getitem 需要一个索引。这是由数据加载器自动处理的,它为批处理中的每个图像运行 getitem。在 getitem 的代码中,我们加载索引“idx”处的图像,从文件路径中提取标签,然后通过我们定义的转换运行它。该函数返回图像数组的张量及其对应的标签。

创建 train_dataset 后,我们可以访问如下示例:

output:
The shape of tensor for 50th image in train dataset:  
torch.Size([3, 256, 256])The label for 50th image in train dataset: 
37

让我们通过 train_dataset 可视化一些增强后的图像。

来源:self

还有一些,

来源:self

6.创建数据加载器

最后一步。DataLoader 类用于为模型批量加载数据。这有助于我们以小批量的方式处理数据,这些数据可以放在我们的 GPU RAM 中。首先,我们导入数据加载器:

from torch.utils.data import DataLoader

通过发送数据集的对象和批处理大小来启动数据加载器。

一旦我们有了 dataloader 实例— train_loader,我们就可以使用迭代器来访问数据,如下所示:

#batch of image tensor
next(iter(train_loader))[0].shapeoutput:
torch.Size([64, 3, 256, 256])#batch of the corresponding labels
next(iter(train_loader))[1].shapeoutput: 
torch.Size([64])

这是我们在训练循环中用来批量处理数据的。每次我们运行迭代器时,dataloader 都会选择接下来的 64 个索引,并逐个运行 dataset 类中的 getitem 然后将其返回给训练循环。

结论

在这个由两部分组成的系列的第 1 部分中,我们看到了如何编写我们自己的定制数据管道。我们还学会了使用白蛋白来增强图像。此外,我们了解了数据集和数据加载器类的内部工作方式。在下一部分中,我们将通过为机器翻译任务创建一个自定义数据集类来提升级别。

下一集再见!

第二部分可以在这里找到。

更多来自作者

https://medium.com/@ug2409/a-non-technical-introduction-to-reinforcement-learning-part-1-62373183b2bc

参考

Pytorch 中的自定义数据集—第 2 部分。文本(机器翻译)

原文:https://towardsdatascience.com/custom-datasets-in-pytorch-part-2-text-machine-translation-71c41a3e994e?source=collection_archive---------5-----------------------

皮卡伍德在 Unsplash 上拍摄的照片

在本系列的第一部分中,我们学习了加载自定义图像数据集。在那篇文章中,我们还介绍了 Pytorch 中数据集和数据加载器的一些基本功能。我建议先浏览一下那篇文章,但是我们也会在这篇文章中为 NLP 的人们介绍一些基础知识。在本演练中,我们将介绍如何为机器翻译加载自定义数据集,并使其为模型做好准备。本演练的代码也可以在 Github 上找到。

我们将使用英语-印地语语言数据集。数据集如下所示:

图一。数据集(来源:作者图片)

让我们编码

1.导入库

首先,我们导入必要的库。除了这些库,我们还导入了panda parallel。这个库使得我们的 apply 函数可以利用我们所有的 CPU 线程并行运行,从而使进程快如闪电。

2.加载数据和预处理

接下来,我们加载数据并进行一些基本的预处理,以清理数据并为自定义数据集管道做好准备。

3.创建训练集和验证集

接下来,我们创建训练集和有效集。我们将仅基于训练数据来创建词汇表。我们将把有效集视为拒绝集。

output: 
len of train:  112343
len of val:  12482

我们现在有了火车和有效的数据帧。接下来,我们为这些数据帧创建 Pytorch 数据集和数据加载器。

4.创建 Pytorch 数据集

我们将分两部分创建 PyTorch Train_Dataset:

  1. 建立词汇课
  2. 构建训练数据集

4.1 词汇

在创建 Train_Dataset 之前,我们需要定义一个构建词汇表的过程。为此,

  1. 我们将创建一个“词汇”类,它将只使用我们之前创建的训练数据帧来创建单词到索引和索引到单词的映射
  2. 同样,“词汇”类返回数据帧中每个句子的数字版本。例如:['我','爱','苹果']-->[23,54,1220]。我们需要将单词转换成数字,因为模型希望我们词汇表中的每个单词都用一个数字来表示

为了更好地理解代码,已经对代码进行了注释(代码有点冗长,但不要放弃!这非常简单)

我希望代码足够清晰,可以遵循。如果没有,请在评论中联系我们。让我们测试这个类。我们将为几个句子创建一个虚拟词汇。

output:
index to string:  {0: '<PAD>', 1: '<SOS>', 2: '<EOS>', 3: '<UNK>', 4: 'that', 5: 'is', 6: 'a', 7: 'cat', 8: 'not', 9: 'dog'}string to index: {'<PAD>': 0, '<SOS>': 1, '<EOS>': 2, '<UNK>': 3, 'that': 4, 'is': 5, 'a': 6, 'cat': 7, 'not': 8, 'dog': 9}numericalize -> cat and a dog:  [7, 3, 6, 9]

我们得到两个(索引-单词和单词-索引)映射。同样,我们可以把一个新句子转换成它的数字格式。注意‘and’的值是 3,它对应于(又名 unknown)令牌,因为它不在我们的 vocab 中。另外,请注意,我们将在下一节中向 Train_Dataset 类中的数字化文本添加开始和结束标记。

4.2 训练数据集

酷!我们有积累词汇的渠道。让我们创建 Train_Dataset。

正如我们在第 1 部分中讨论的,PyTorch 的这个数据集类是我们定制数据集的核心。数据集类的结构如下所示:

图二。数据集类(来源:作者图片)

我们通过继承 Dataset 类来创建 Train_Dataset 类:

from torch.utils.data import Dataset

对于 Train_Dataset 类,

  1. 我们首先继承 PyTorch 的 Dataset 类。
  2. 然后,我们为训练数据帧中的源列和目标列初始化并构建 vocabs。
  3. 然后,我们使用 getitem()方法为数据加载器(一个批量加载数据的函数)一次对一个文本示例进行数值化。在接下来的章节中会有更多的介绍)。

让我们了解一下,一旦创建了 Train_Dataset 类的实例,将会发生什么。我们一创建实例,就会运行 init 方法,并创建词汇类的两个对象——source _ vocab 和 target_vocab。我们将能够通过这些实例访问各自的 vocab 映射和数值化方法。从上面可以看出,getitem 需要一个索引。这是由数据加载器自动处理的,对于,批处理中的每个示例都运行 getitem。在我们的代码中,getitem 在连接开始和结束标记后,返回特定索引处给定示例的数字化源和目标(因此一次一个示例)。

现在,我们测试上面的代码。

output:english_sentence    narrowed or blocked arteries are bypassed by t...
hindi_sentence      संकुचित हो गयी या अवरोधित धमनियों को टाँग से ल...(tensor([   1,    3,   24, 8001, 5987,   17,    3,   20,    4,  151,    5,    9,
         7360,    5,    3,  256,   23,    4, 1826,   27,   10, 1120,    7,    4,
            3,   31,   39,  189,    6,    7,    4,    3, 7360,  918,    4, 2794,
           16,    4,   52,    2]),
 tensor([   1, 6701,   25,  162,   31,    3, 4979,   11,    3,    9,   19,  112,
            3,    4, 3555,   10,  169,   23,    3,   23,   51,   42,    3,    4,
           20, 3555,    4,   13, 3598,   11,    3,    9,    8,  174, 3598,   11,
         4980,    4,  338, 1821,   51,   42,    6,    2]))

酷!我们得到了源句子和目标句子的索引。

4.3.创建验证数据集类

我们为验证创建一个单独的数据集类。为了获得验证数据框的数字文本,我们将重用训练的词汇表(因为我们将验证集视为不可见集,因此无法访问它的词汇表)。更好的做法是为验证定义一个单独的类。我们将把 train_dataset 实例和其他东西传递给 Valid_Dataset 类,以访问 train_dataset 源和目标词汇表。

现在,我们有了 train 和 valid datasets 对象。接下来,我们必须创建数据加载器来批量加载数据。

5.创建数据加载器

首先,我们了解一下校对。该函数在使用数据加载器创建批处理后运行。在我们的应用程序中,我们使用这个函数为批处理中的句子创建填充。为此,我们使用 torch.nn.utils.rnn 中的“pad_sequence”。它在我们的批处理中选择最大的句子,并将所有其他句子填充到这个长度。我们这样做是因为模型期望一个正方形矩阵,即每个示例在一批中应该是等长的。

在定义数据加载器时,我们使用上面的函数作为参数。

让我们看看数据加载器的结果。我们创建一个迭代器,得到大小为 32 的源和目标批处理的元组。

output:
source: 
 tensor([[   1,    1,    1,  ...,    1,    1,    1],
        [4125,  420,   37,  ...,   46,   95, 5406],
        [  91,   32,   17,  ..., 1407,   53,   17],
        ...,
        [   0,    0,    0,  ...,    0,    0,    0],
        [   0,    0,    0,  ...,    0,    0,    0],
        [   0,    0,    0,  ...,    0,    0,    0]])source shape:  torch.Size([64, 32])
target shape:  torch.Size([44, 32])

在上面的张量数组中有一个句子是垂直排列的。我们可以看到 0 是句子的填充。而 44 是目标批次中最长的句子。

就是这样!现在,数据已经准备好用于我们的模型了!

在 PyTorch 中加载自定义数据集感觉很多。但是这个管道为我们提供了为任何类型的数据集或问题陈述加载和创建模型就绪数据加载器的灵活性。

结论

在这个由两部分组成的系列的第 2 部分中,我们看到了如何编写自定义的机器翻译数据管道。尽管本演练是为机器翻译任务编写的,但同样的概念也可以转移到从广泛的应用程序领域加载多模式数据。这个演练的代码可以在我的 Github 上找到。

喜欢吗?给一个👏 😄并关注更多!

有关系的

使用 PyCaret 的自定义估算器|第 2 部分|作者:Fahad Akbar

原文:https://towardsdatascience.com/custom-estimator-with-pycaret-part-2-by-fahad-akbar-aee4dbdacbf?source=collection_archive---------20-----------------------

通过 PyCaret 创建、使用和部署灵活的定制估算器

通过 PyCaret 在 Scipy 中从头开始构建和部署 Sklearn 兼容估算器的实践指南

图片来源:https://unsplash.com/photos/D5nh6mCW52c

在第 1 部分中,我们学习了估计器、python 类对象、指数函数、曲线拟合函数、位置参数打包/解包、枚举函数&最后构建了一个更加定制和灵活的回归估计器。您可以访问本实践教程的第 1 部分:

在这一部分,我们将主要学习和构建两件事情:

1️⃣如何使定制估算器 sklearn 兼容
2️⃣如何与 PyCaret 集成

让我们一起来构建它,但是在我们触及这些具体的点之前,最好向我们的估计器类添加一些东西来改进性能和功能。

如果您还记得第 1 部分,我们使用迭代方法在 Python 中编译了指数函数。在某些情况下,这可能会导致速度变慢。幸运的是,Python 提供了矩阵运算,与迭代方法相比,这种运算要高效和快速得多。在这种情况下,我们可以使用 NumPy 模块中可用的dot方法。我们可以这样做:

作者图片

np.array(X).dot(np.array(args[1:]))等于 x[1]b +x[2]c …x[n]*n.
这导致数组的长度等于 y. np.exp(y_)取数组 y_ 中每个元素的指数。y_*args[0]用数组y_的每个元素乘以第一个系数‘a’。结果是等式的输出:

作者图片

2: 下一件事,我们可能要做的是添加一个自定义的“评分”方法到我们的估计器中,这样我们就可以访问拟合的结果。这是一件很简单的事情。我们将使用 sklearn 的度量来获得平均绝对误差的得分函数。如果您愿意,您可以创建一个适合您的用例的评分函数。

我们想添加的最后一件事是通过 init 方法在我们的估计器类中为参数(超参数)留出一些空间。改变超参数的值会影响模型的执行和准确性。您只需在 init 函数的参数中传递所需的超参数,并将其绑定到 self。我们将添加一个名为 Maxfev 的参数,它指定在试图找到全局最小值时,我们允许 fit_curve 函数改变系数值的次数。

这是我们添加这些功能后代码的样子:

我们现在已经准备好让我们的评估者更上一层楼了!

👉定制估算器和 Sklearn

为了让你的估算器与 sklearn 兼容,我们需要在代码中包含一些东西。我们正在使它与 sklearn 兼容,因为这是 PyCaret 的一个要求。在 这里可以找到一个完整详细的需求列表 。下面是我们需要完成的几件重要事情:

从 sklearn 继承 base 和 estimator 子类到我们的类中。继承是一个详细的主题,超出了本教程的范围。简单地说,将 sklearn 类继承到我们的类中,将使我们不必在我们的类内部创建所有必要的方法(函数)。为了继承,我们只需要从 sklearn 导入BaseEstimator & RegressorMixin(因为我们的估计器是一个回归器,为了分类我们将使用ClassifierMixin)子类,并简单地将它们作为参数传递到我们的估计器类中,就像这样class ExponentialRegressor(BaseEstimator,RegressorMixin):

init 方法中,所有的参数都应该有一个默认值

3): 当我们将超参数绑定到类时(当我们创建属性时),它们的名称应该保持不变

def __init__(self,maxfev=300):
    #Wrong way
    self.maxf = maxfev
    #Right way , name of parameter should be the same as attribute
    self.maxfev = maxfev

4): 不要通过__init__方法取 X 或 y。

5): 不要改变__init__方法中的属性值,例如

def __init__(self,maxfev=300):
    #Do not do this !
    if maxfev < 300:
        self.maxfev = 300
    else:
    self.maxfev = maxfev

6): ️Every 估计量应该有get_prams & set_prams方法。嗯,我们已经通过导入BaseEstimator子类解决了这个问题。

在 fit 方法中,我们需要部署一些直接来自 sklearn 的检查。一个是check_x_y(),它检查 X & y 的形状是否正确,X 需要是 2D 数组,y 需要是 1D 数组。第二,如果是做分类,需要通过unique_label()功能查看标签。这里不需要,因为我们在做回归。

8):fit方法被调用时,它应该生成一些(至少一个)属性,这些属性的名称跟在一个‘下划线’之后。下划线将用于在predict方法中运行另一个检查,以确保在调用predict之前已经调用了fit方法,例如

def fit(self,X,y):
    # 'underscore' after self.X & self.y is required
    self.X_,self.y_ = check_x_y(X,y)

9):fit方法应该返回自身的一个实例,简单来说,fitreturn应该是self

10):predict方法也应该有一些检查,类似于fit方法。一个是check_is_fitted()函数,它检查fit方法是否已经被调用。另一个是check_array()函数,检查 X 的形状,非空的&有限值,就像check_x_y()一样

这似乎是一个冗长乏味的列表,但是一旦你掌握了其中的诀窍,你会注意到实现时它不超过 4/5 行代码。所以振作起来😺并检查下面的代码。我将尽量减少评论,因为到目前为止你已经看过很多次了😃。

我们现在准备跳到旅程的最后一段!你所需要做的就是把这个 py 文件保存在你想要的文件夹/目录中,或者只是把它保存在你的 Juypter 笔记本中,然后继续编码

👉与 PyCaret 集成

一旦我们的估算器与 sklearn 兼容,与 pycaret 的集成就非常容易了。您将照常进行 PyCaret 的设置,可以将您的类传递给 create_model & compare_models 函数。请参见下面的代码片段:

现在,如果你运行m = creat_model(ExponentialRegressor())你会看到这个:

作者图片

现在运行 compare_models 命令,指定要与我们构建的回归器一起运行的模型:

c = compare_models(include=['lr','ridge','br','et','rf','ada',ExponentialRegressor()])

作者图片:6 号模型是我们的定制回归器

相当令人印象深刻的结果👍,至少对于这个数据集,我们击败了 AdaBoost 和随机森林回归器,而且它也非常快…

我们还可以通过调用函数tune_model来调整超参数maxfev,以及maxfev的自定义网格:

tune_model(m,custom_grid={'maxfev':[2000,3000,4000]})

作者图片

关键是,你现在可以使用 PyCaret 的许多内置特性(ensemble_model,stack_models 等)来运行你自己亲手从头构建的模型!

奖励材料:

在这个阶段,您可以为 PyCaret 创建并添加一个自定义指标。您所需要的只是一个捕获逻辑并返回标量(单个值)的函数。我想根据模型在实际值的 20%以内的预测能力来衡量模型的准确性。如果预测值在实际值的 20%以内,我将赋值 1,否则为 0。然后简单统计一下 1 的百分比。你要这样做:

# create a custom function
def confidence(y, y_pred):
    score = np.where(np.abs(y_pred-y)/y <=.20 ,1,0)
    return ((np.sum(score))/len(y))
# add it to PyCaret
add_metric(id ='CI',name="Confidence",score_func=confidence)

现在,当我们运行比较模型命令时:

c = compare_models(include=['lr','ridge','br','et','rf','ada',ExponentialRegressor()],sort='Confidence')

我们得到:

图片由作者提供:指数回归约占 40.47%,预测误差在实际误差的 20%以内

下面的代码是我们努力工作的最终成果。代码是自给自足的,假设您已经安装了所有需要的库,您应该能够在您的机器上运行它

这个系列到此结束。在这一部分中,我们学习了矩阵乘法,添加了一个计分方法,使我们的估计器 sklearn 兼容,最后我们学习了如何将其与 PyCaret 集成。我们还学习了如何创建一个定制的度量以及我们的定制估计器,并在 PyCaret 中一起使用它们。

➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
可以关注我上t5】中 t24】联系我上LinkedInt11】访问我的t13】github t18】➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖

您可能还对以下内容感兴趣:

👉Docker
让您的数据科学生活变得简单👉使用 PyCaret 的自定义估算器,第 1 部分

Power BI 中的自定义字体—您想知道的一切!

原文:https://towardsdatascience.com/custom-fonts-in-power-bi-everything-you-wanted-to-know-652163750ba3?source=collection_archive---------12-----------------------

查看如何轻松扩展预定义字体库,以满足特定客户的要求!

https://www.pexels.com/photo/multicolored-umbrella-1146851/

我喜欢权力 BI,真的喜欢!如果您仔细阅读我的文章,您会发现我真的认为 Power BI 是一个非常棒的工具——因为它为您讲述数据故事提供了无限的可能性。我指的不仅仅是开箱即用的解决方案,还包括定制的解决方案。

然而,我最近遇到了一个有趣的问题(或者,坦率地说,它看起来并不那么有趣,为什么我试图解决它)。那么,这到底是怎么回事?

方案

我正在帮助我的客户构建一个 Power BI 报告,其中一个主要要求是所有的视觉效果都应该使用 Roboto 字体。如果你问自己为什么——答案很简单——他们在所有的视觉解决方案、品牌等中使用 Roboto 字体。而且,他们希望他们的 Power BI 报告遵循该模式,并适合通用解决方案。很公平…

现在,当您打开 Power BI Desktop 并转到 visual 的格式窗格时,您可以在 25 种不同的字体之间进行选择:

作者图片

但是,这里没有 Roboto !那么,我们该怎么办呢?

自定义报告主题

对于那些不知道的人,你可以在你的 Power BI 报告中切换不同的主题。此外,由于 Power BI 主题只不过是一个简单的 JSON 文件,所以您可以创建自己的主题,或者另外定制现有的主题!

我已经解释过如何在你的主题中嵌入背景图片,并在视觉品牌中重复使用。现在,我们将尝试使用自定义字体来扩展我们的主题。在 View 选项卡下,我将选择保存当前主题,这样我就可以直接编辑源 JSON 文件。

作者图片

还可以使用内置的 Power BI 自定义当前主题功能进行大量的调整,但是不能使用它在其中导入自定义字体。我也强烈建议检查一个来自 powerbi.tips 的极好的工具来创建你自己的主题,但是我们仍然需要一些现成的东西,所以我们将不得不手动实现我们的调整。

当我在 Notepad++中打开我的 JSON 主题文件时,我看到了我的主题的当前设置:

作者图片

为了应用字体设置,我需要使用的属性叫做:【visual styles】。让我们添加这个属性并定义我们的需求:

{"name":"Data Mozart",
"visualStyles":{"*":{"*":{"*":[{"fontSize":12,"fontFamily":"Roboto","color":{"solid":{}}}]}}},
"dataColors":["#8BC7F7","#46B3F3","#009FEF","#008CEE","#0078ED","#0050EB","#0641C8","#0B31A5","#46647C","#235A7A","#005078","#004677","#003C77","#002876","#032164","#061953","#FDAB89","#B687AC","#28738A","#A78F8F","#168980","#293537","#BB4A4A","#B59525","#475052","#6A9FB0","#BD7150","#7B4F71","#1B4D5C","#706060","#0F5C55","#1C2325"],
"tableAccent":"#8BC7F7","maximum":"#8BC7F7","center":"#0B31A5","minimum":"#D2D3D5"}

让我简单解释一下这个“visualStyles”定义的含义:使用它,我们指示 Power BI 将 Roboto 的 12 号字体和纯色应用于我们所有的报表视觉效果!开头那些星星的意思是——将此应用于所有视觉元素!

保存 JSON 文件,让我们回到我们的 Power BI 报告并导入这个主题:

作者图片

您可以立即注意到,我的所有视觉效果都发生了变化,以反映新的设置:

作者图片

如果你想确认这是真的,只需再次打开 visual 的格式窗格,你应该看到 Roboto 字体被应用到一个 visual:

作者图片

在这里,由于其他 X 轴设置的原因,我们的预定义大小 12pt 无法应用(您会看到这个黄色的感叹号警告),但是如果您检查标题,您应该会看到它被自动设置为 12,正如我们所希望的那样。

添加新的视觉效果

好吧,它对现有的视觉效果很有吸引力,但是如果我在我的报告画布上插入一个全新的视觉效果会怎么样呢?

我在报表上放置了一个简单的卡片视图,并拖动了我的销售额度量:

作者图片

机器人 12?力量 BI —我爱你:)

潜在警告

效果非常好!但是,对此有一些潜在的警告和限制,您应该知道。例如,如果您想将特定的自定义字体仅应用于 标题 (报告中的所有标题),您应该编写如下内容:

{"name":"Data Mozart 2",
"visualStyles":{"*":{"*":{"title":[{"fontSize":18,"fontFamily":"Roboto","color":{"solid":{}}}]}}},
"dataColors":["#8BC7F7","#46B3F3","#009FEF","#008CEE","#0078ED","#0050EB","#0641C8","#0B31A5","#46647C","#235A7A","#005078","#004677","#003C77","#002876","#032164","#061953","#FDAB89","#B687AC","#28738A","#A78F8F","#168980","#293537","#BB4A4A","#B59525","#475052","#6A9FB0","#BD7150","#7B4F71","#1B4D5C","#706060","#0F5C55","#1C2325"],
"tableAccent":"#8BC7F7","maximum":"#8BC7F7","center":"#0B31A5","minimum":"#D2D3D5"}

如你所见,在“visualStyles”属性中,我已经为我的报告中的所有标题设置了 Roboto 字体大小 18。如果我们回到电源 BI 报告,您会发现它工作得很好:

作者图片

但是…如果你想调整“正常”标签,如轴,数据标签,类别等…

作者图片

字体下拉列表中不再有 Roboto !由于我们明确指示 Power BI,我们希望将 Roboto 字体专门用于标题,因此该字体将不可用于其他视觉元素。

还有一件重要的事情要记住 :如果你打开。pbix 文件, 之前导入主题,然后导入主题,修改将不会被应用!我不知道这是一个错误还是什么,但让我告诉你是什么问题:

作者图片

所以,在使用主题文件时要小心,因为它们的使用显然有一些注意事项!这个挑战的可能解决方案可能是:按照您喜欢的方式格式化所有内容,保存。pbix 文件,打开它,立即应用自定义主题!然后,不要碰任何东西:))

结论

正如我在一开始所说的,我喜欢 Power BI 为您提供的灵活性,以便以最吸引人的方式呈现您的数据故事。

正如您所见证的,我们能够扩展标准 Power BI 字体库,并使用自定义字体来增强我们的报告,满足客户的需求。

另一方面,当通过主题文件应用调整时,要保持警惕——有一些明显的限制(或缺陷)会带来混乱,你一定要意识到它们。

感谢阅读!

成为会员,阅读 Medium 上的每一个故事!

投票分类器模型的特征重要性的自定义实现

原文:https://towardsdatascience.com/custom-implementation-of-feature-importance-for-your-voting-classifier-model-859b573ce0e0?source=collection_archive---------13-----------------------

与其他模型不同,Scikit-learn 包缺少投票分类器的功能重要性实现

图片由 Arek Socha 提供,来自 Pixabay

机器学习模型越来越多地应用于复杂的高端环境,如金融技术、医学科学等。尽管利用率有所提高,但仍然缺乏解释该模型的技术。模型的可解释性越高,人们就越容易理解结果。有各种先进的技术和算法来解释模型,包括石灰,SHAP 等。

特征重要性是为估计者解释特征重要性的最简单和最有效的技术。特征重要性有助于更好地解释估计量,并通过使用特征选择来改进模型。有多种技术可以计算评估者的特征重要性分数:

  • sci kit-了解特性重要性的内置实现
  • 用排列法计算特征重要性
  • 使用 SHAP 值计算的要素重要性

在本文中,我们将进一步讨论第一个特性重要性策略。Scikit-Learn 包提供了一个函数**model.feature_importances_** 来计算除投票分类器估计器之外的大多数估计器的特征重要性。Scikit-learn 使用不同的算法来计算特征重要性分数。对于随机森林或决策树模型,它使用基尼系数计算重要性分数,对于逻辑回归,它使用向量权重。

在本文中,我们将讨论计算投票分类器模型的重要性分数的实现。

什么是投票分类器?

投票分类器是一种集成技术,它将各种模型的预测组合在一起,根据它们的最高概率预测输出(类别)。投票分类器算法只是汇总传递到模型中的每个分类器的结果,并根据投票的最高多数预测输出类。

投票分类器支持两种投票技术:

  • 硬投票:投票分类器估计器的预测输出将基于最高多数的投票来计算,即具有被每个分类器预测的最高概率的类别。
  • 软投票:输出类是基于该类的平均概率的预测。

为了更好地理解投票分类器,请阅读穆巴拉克·加尼尤的一篇文章:

功能重要性:

与其他模型估计器不同,Scikit-learn 没有提出投票分类器的特征重要性实现。但是用于投票分类器的每个基本估计器都有其实现方式。其思想是基于权重组合每个估计器的重要性分数。

(作者代码)

计算投票分类器的特征重要性的算法步骤是:

  1. 计算每个基本评估者的特征重要性分数
  2. 将基本估计值的权重乘以每个特征的重要性分数。
  3. 平均每个特性的特性重要性分数(来自步骤 2)。

结论:

在本文中,我们讨论了一种技术或方法来计算投票分类器集成模型的特征重要性分数。特征重要性分数有助于理解模型中最重要的特征,并且可以通过使用特征选择来改进模型。

参考资料:

[1]来自 Scikit-Learn 的投票分类器文档:https://sci kit-Learn . org/stable/modules/generated/sk Learn . ensemble . Voting Classifier . html

感谢您的阅读

Tensorflow 中的自定义图层

原文:https://towardsdatascience.com/custom-layers-in-tensorflow-4dbd7c194b6e?source=collection_archive---------23-----------------------

增强 Tensorflow 体验创建您自己的层

在我对人工智能算法的研究中,除了陡峭的初始学习曲线之外,考虑到开源和免费资源的巨大可用性,我对这些算法可以被有技能的人开发和使用的即时性感到震惊。特别是, TensorFlow 使得以非常实用和简单的方式开发复杂的算法成为可能,即使是有经验的程序员也需要几个月的时间来实现,以获得模糊的可比结果。

丰富的文档使人们很容易理解如何应用众多的预实现模型,正如详细的教程使以实用的方式解决各种问题成为可能(自然语言处理、图像分类、监督和监督无监督学习……)。

詹姆斯·哈里森在 Unsplash 上拍摄的照片

就像科学学习的各个领域一样,总有一天,为了取得越来越好的结果,有必要对所涉及的主题进行更深入的研究。

为此,Keras 函数 API 的使用,结合 Tensorflow 的热切执行和生成完全定制的层、损失函数、模型、指标和回调的可能性,使得以更深入和更详细方式处理人工智能问题成为可能。此外,应用张量、变量、常数的基本概念和梯度带的应用可以赋予完全原创的算法以生命并适应特定的需要,以期【定制训练】。

为什么要看这篇文章?

在本文中,我们将使用一个自定义层,它是通过在 Tensorflow 中子类化 layer 对象而开发的。我们将开发一个二次层,与传统的致密层相反,后者的特点是线性预激活+激活函数的应用(通常是非线性的)。我们将使用 Keras 的功能 API 创建一个非常基本的神经网络模型,并将在一个复杂工程问题的代表性数据集上测试我们的模型,从而获得良好的结果。

数据集

翼型产生的噪声是航空航天工业的一个重要环境参数。机体总噪声的很大一部分是 翼型自噪声 ,与翼型本身及其边界层产生的湍流效应的相互作用有关。自噪声数据集由 NASA 开发。它是在消声风洞中以不同的风洞速度和攻角对二维和三维翼型叶片段进行的一系列空气动力学和声学测试中获得的。**

车型特点:

  • 频率[赫兹]
  • 攻角[度]
  • 弦长[米]
  • 自由流速度[米/秒]
  • 吸入侧位移厚度[m]

型号标签:

  • 标度声压级[dB]

我做了一个视频,是为了面对这个空气动力学问题生成一个基本的稠密神经网络,有兴趣的话来看看。你也可以在这里找到完整的代码。

二次层

现在让我们看看如何生成一个二次层。要了解整个问题是如何解决的,您可以在这里找到完整的代码,或者您可以观看本文开头的视频。要理解一个标准密集层的工作原理,我们可以从感知器函数的概念说起。这种人工智能的基本模型包括执行神经元本身中的一组输入参数和相对权重的乘积之和,生成预激活值。一旦计算出预激活,就有必要对其应用激活函数,以将非线性分配给所生成的替代模型的输出。

感知器功能—作者图片

基于这些概念,密集层将由“N”个工作原理相同的神经元组成。在我们的应用案例中,我们生成一个定制的层,其输入和神经元本身的预激活之间的关系是二次,而不是线性的。

感知器二次函数—作者图片

为了在 Tensorflow 工作环境中生成我们的层,我们继承层对象的属性,然后初始化它的属性。我们定义了两个新的属性:层中神经元的数量和激活函数。

构建 方法中,我们定义了我们层的可训练参数。我们需要指定每个张量的大小,数据格式,因此这些参数实际上是可训练的。前两个参数被随机初始化,而偏置项被初始化为调用 方法允许我们在前向传播阶段评估我们层的响应:我们实现上面的二次表达式。

我们生成简单的模型,只有一个隐藏层:我们创建的自定义层。

带有自定义图层的模型—作者提供的图像

结果

我们编译我们的模型,定义损失函数,并选择亚当作为优化器。然后,我们训练模型 500 个时期,并检查结果。在我们的脚本中,我们还显示了训练前后自定义层的参数值之间的比较,以检查它是否正常工作。

跨时代的损失函数-按作者分类的图像

然后,我们运行验证图来验证模型在训练和验证集上的性能。考虑到模型是如此简单,并且没有对其超参数进行优化,结果是离散的。然而,这证实了我们的定制层的正确运行。

验证图-按作者分类的图像

让我们检查一些数字结果:

*Y0 - mae-train - 0.05067
Y0 - mse-train - 0.00441
Y0 - r2-train - 0.87064
Y0 - pearson-train - 0.93566
Y0 - mae-test - 0.04748
Y0 - mse-test - 0.00402
Y0 - r2-test - 0.87471
Y0 - pearson-test - 0.93871*

结论

我们已经看到了如何使用 Colab、Tensorflow 和 Python,用相对简单的模型处理复杂的空气动力学问题。我们创建了一个只有一个隐藏层的模型,使用我们自己构建的层,而不是 Tensorflow 环境中预实现的层。我们检查了它的正确功能并核实了结果。我希望你喜欢这篇文章,欢迎任何反馈。

下次见,马尔科

3 分钟机器学习

3 分钟机器学习是一系列与人工智能、深度学习和数据科学相关的教程、视频和文章。你可以在 YouTube 上找到完整的视频集。GitHub 存储库包含了文章和视频中显示的所有 Google Colab 笔记本。我希望这些内容对你有用,或者只是你感兴趣。欢迎任何反馈。

查看其他剧集:

  • 使用神经类型转移和张量流生成图像
  • 猫 VS 狗卷积分类器
  • 使用 Keras Functional API 绘制张量流模型
  • 预测建筑物能源性能的神经网络

张量流中的自定义损失函数

原文:https://towardsdatascience.com/custom-loss-function-in-tensorflow-eebcd7fed17a?source=collection_archive---------9-----------------------

通过创建要优化的函数来定制您的算法

在我们进入机器学习和深度学习世界的旅程中,很快将有必要从整体上处理模型、优化器、损失函数、层和算法的其他基本组件的定制。 TensorflowKeras 有大量预先实现和优化的损失函数,在工作环境中很容易调用。然而,可能有必要开发个性化和原始损失函数,以完全满足我们对模型表征的需求。

为什么要看这篇文章?

在本文和上面的 youtube 视频中,我们将回忆损失函数和成本函数的基本概念,然后我们将看到如何使用 Keras API 在 tensorflow 中创建一个自定义损失函数并子类化 Keras 的基类“loss”。然后,我们将看到如何创建一个示例损失,在这种情况下,一个定制的回归问题的准确性。我提醒你遵循我的中个人资料来支持这项工作。你可以在我的个人资料上找到这个系列的所有其他文章,在我的 YouTube 频道上找到这个系列的所有其他视频。您还可以在 git 存储库中找到所有脚本。

损失函数

在数学优化、统计学、机器学习和深度学习损失函数 (也称为代价函数或误差函数)是定义一系列值和一个实数之间的相关性的函数。这个数字在概念上代表了与一个事件或一组价值相关的成本。通常,优化程序的目标是最小化损失函数。

照片由沃尔坎·奥尔梅斯在 Unsplash 上拍摄

正如官方维基百科页面所述,“良好的统计实践要求选择与特定应用环境中经历的实际变化一致的估计函数。因此,在实践中,选择何种统计方法来模拟一个应用问题,取决于对因问题具体情况而产生的成本的了解。”

对于大多数优化算法,希望有一个损失函数是全局连续的可微的。两个非常常用的目标函数是均方误差偏差

“然而,偏差(利用绝对值)的缺点是在 a=0 处不可微分。一个二次函数有一个缺点,就是当对一组数值 a 求和时,最终的和往往是一些特别大的数据 a 的值,而不是平均值的表达式。”

目标函数的选择不是任意的,有时会受到希望利用的期望属性的限制。

张量流中的自定义损失函数

在我们的例子中,我们使用的数据集已经在本系列的其他视频和文章中使用过。我说的是 NASA 开发的自噪声数据集,找到这篇文章了解更多信息。在使用 TensorflowKeras 开发人工智能算法的过程中,我最喜欢的功能之一是能够完全定制训练的每个方面,同时保持这些 API 使用的简单性和流畅性。

为了理解自定义损失函数的重要性,让我们从一个简短的例子开始。您想在数据集上训练一个回归变量,但数据中有太多噪音。您可能会继续进行数据预处理(数据清理、删除/修复异常值……),但是让我们假设这个过程还不够。在加载、标准化和拆分数据之后,您已经创建了神经网络拓扑,但是您仍然需要编译您的模型并定义适当的优化器和损失函数。均方误差( mse )可能会过多地惩罚异常值,而平均绝对误差( mae )不会对它们进行足够的惩罚,并且训练可能会太长且不准确。对于这个特定的应用程序,我们可以考虑一个完全自定义的损失函数,Keras API 没有提供。对于这个应用, Huber 损耗可能是一个不错的解决方案!我们可以找到这个预实现的损失函数( tf.keras.losses.Huber ),但是让我们创建这个损失函数的完整定制版本。

我们可以注意到,我们只需指定自定义损失函数的参数:模型输出的真实值和预测值。但是,Tensorflow 语法只需要这两个参数,不需要其他参数。要生成一个参数损失函数,我们可以继续使用给出的解决方法:一个 double 函数,外部函数返回内部方法。这允许我们在此范围内引入新的属性,即定义 Huber 损失函数的阈值!

为了从我们的算法中获得最佳效果,我们可以:

  1. 更喜欢我们函数的矢量化实现
  2. 仅使用 TensorFlow 操作,以受益于 TensorFlow 的图形功能
  3. 返回包含每个实例一个损失的张量,而不是平均损失。这允许 Keras 在必要时应用类别/样本权重。

在参考 YouTube 视频/Colab 笔记本中,我为一个回归问题创建了一个自定义精度损失,定义为:

我们只需用我们的客户损失编译我们的模型,并训练回归器。对于这个应用程序,我已经子类化了 tf.keras.losses.Loss 的 Loss 类,但这不是强制性的。

损失函数趋势-按作者分类的图像

结论

我们回顾了损失函数的关键概念,了解了如何在 Tensorflow 中为两个不同的问题创建完全定制的损失函数,并举例说明了一个应用案例。我们看到了一些从我们的实现中获得最佳效果的方法。我希望你喜欢这篇文章,欢迎任何反馈。

下次见,马尔科

3 分钟机器学习

3 分钟机器学习是一系列与人工智能、深度学习和数据科学相关的教程、视频和文章。你可以在 YouTube 上找到完整的视频集。GitHub 库包含了文章和视频中显示的所有 Google Colab 笔记本。希望这些内容对你有用,或者只是你感兴趣。欢迎任何反馈。

查看其他剧集:

  • 用神经风格转移和张量流生成图像
  • 猫 VS 狗卷积分类器
  • 使用 Keras Functional API 绘制张量流模型
  • 预测建筑物能源性能的神经网络
  • tensor flow 中的自定义图层

自定义对象检测使用 React with Tensorflow.js

原文:https://towardsdatascience.com/custom-object-detection-using-react-with-tensorflow-js-7f79adee9cd4?source=collection_archive---------9-----------------------

与 TENSORFLOW 反应。射流研究…

让我们用 Azure 自定义视觉在不到 30 分钟的时间内训练一个实时自定义对象检测器

詹娜·哈姆拉摄于佩克斯

你听说过有人使用人工智能来解决他们的行业问题吗,比如医生使用人工智能识别癌细胞,CCTV 识别货架上的空产品,甚至是 cat 探测器?这些“人工智能”背后的基本逻辑是自定义对象检测。

欢迎来到我的与 Tensorflow.js 反应系列的第四个故事,在这个故事中,我们将探索如何通过向 AI 提供大量药丸图像来训练它检测定制药丸💊💊使用 Microsoft Azure 自定义视觉。(不到 30 分钟!)

作者使用 react with tensorflow.js. GIF 自定义药丸检测器

你可以在家里用一个简单的黄色药丸玩这里,或者访问代码这里。

*注意:此 web 应用程序不仅仅对桌面视图进行了优化。

💡目标检测

目标检测是一项计算机视觉任务,包括两个主要任务:

  1. 定位图像中的一个或多个对象,以及
  2. 对图像中的每个对象进行分类

图像分类与目标检测(分类和定位)。原文照片由克里斯滕·梅里曼从派克斯拍摄,照片由莎伦·麦卡琴从派克斯拍摄

与图像分类(图 2)相反,对象检测的目标是通过边界框和所定位对象的类别来预测对象在图像中的位置,输出可以多于一个类别。关于深入的解释,你可以在我之前的文章这里阅读

💡自定义对象检测

目前,网上有各种预训练的模型,如 COCO-SSD ,能够检测 80 多种常见用途的对象,如检测人、铅笔和智能手机。然而,这个模型不能满足检测自定义对象的需要,以我的情况为例,我是一名药剂师,我想做一个 web 应用程序,能够检测和计数网络摄像机中的药丸。

传统上,为了训练一个自定义对象,你需要尽可能多地将带标签的图像输入到训练框架中,比如 tensorflow 和 pytorch。然后运行该框架以获得能够检测目标的最终训练模型。

训练自定义对象检测模型的流程。作者图片

目前,最先进的方法是使用 pytorch 和 tensorflow 等训练框架来训练模型,但是这种方法有很多缺点,如计算量大、设置时间长、需要显卡以及不适合初学者。

因此,出现了商业(免费层可用)的方法来训练模型。在本文中,我将展示使用 微软 Azure 自定义视觉 方法的方式,只需几次点击就可以训练一个 tensorflow.js 对象检测模型

🔎物体检测模型训练

自定义视觉是微软 Azure 应用计算机视觉的 AI 服务和端到端平台。[1]它为 Azure 用户提供了一个免费层来训练他们的对象检测或图像分类器模型,并将其作为一个 API(在我们的例子中,我们下载了生成的模型😎)跨网。对于自由层,它允许每个项目多达 5,000 个训练图像,这足以检测几类对象。

Azure 自定义视觉定价。作者图片

👉注册完成后,点击“新建项目”将出现资源选择界面,点击【新建】进入新建资源

创建新项目。作者图片

👉然后,创建一个新的资源组并选择种类:“定制视觉,培训”和定价等级到“F0”以使用定制视觉培训的免费等级

创建新资源。作者图片

👉回到“创建新项目”页面,你会注意到一旦你选择了资源,你可以选择项目类型和域,选择“对象检测通用(压缩)。通过选择 compact,微软 Azure 允许你下载各种格式的训练模型。

👉您将到达如下图所示的培训平台,点击图片上传

定制视力训练平台。作者图片

👉上传您的未标记的图像用于标记目的。对于本文,我的药丸图片资源是这里。[2]就我而言,我上传了大约 50-100 张图片用于训练。

感谢 Github 用户mepotts提供图片资源。

上传的图片。作者图片

👉接下来,逐一标记您的图像(这是繁琐的部分),幸运的是,Custom Vision 为您提供了一个非常用户友好的标记工具,可以简化您的标记过程。

图像的标记。作者图片

👉完成标记后,点击“训练”按钮,等待几分钟,结果如下:

培训结果。作者图片

👉点击导出选择 Tensorflow,然后 TensorFlow.js 导出。恭喜您,您在 Tf.js 中拥有了第一个自定义对象检测模型

已训练模型的导出。作者图片

🔎使用 React with Tensorflow.js 检测自定义对象

1.设置您的创建反应应用程序

通过终端中的以下命令创建一个 Create-React-App :

npx create-react-app tfjs-azureObject
cd tfjs-azureObject

安装 tensorflow.js 和 Microsoft Customvision,如下所示:

npm install @tensorflow/tfjs
npm install @microsoft/customvision-tfjs

安装 react-网络摄像头,如下所示:

npm install react-webcam

并启动应用程序

npm start

所有代码只会发生在 App.js 中,我只会显示重要的代码,完整代码可以参考我的 GitHub 库

2.导入所需的包

import React, { useEffect, useState, useRef } from "react";
import Webcam from "react-webcam";
import * as cvstfjs from "@microsoft/customvision-tfjs";

3.构建用户界面
该项目的用户界面包括:

  • 按钮—用于启动检测
  • 画布-用于绘制边界框,以及
  • 网络摄像头—用于输入图像/视频
//**Button**: Trigger a predictionFunction() on Click<Button
variant={"contained"}
style={{
color: "white",
backgroundColor: "blueviolet",
width: "50%",
maxWidth: "250px",
}}
onClick={() => {
predictionFunction();
}}
>
Start Detect
</Button>**Webcam:**
const webcamRef = React.useRef(null);
const [videoWidth, setVideoWidth] = useState(960);
const [videoHeight, setVideoHeight] = useState(640);const videoConstraints = {
height: 1080,
width: 1920,
facingMode: "environment",
};<div style={{ position: "absolute", top: "400px" }}>
<Webcam
audio={false}
id="img"
ref={webcamRef}
screenshotQuality={1}
screenshotFormat="image/jpeg"
videoConstraints={videoConstraints}
/>
</div>**Canvas:**
<div style={{ position: "absolute", top: "400px", zIndex: "9999" }}>
<canvas
id="myCanvas"
width={videoWidth}
height={videoHeight}
style={{ backgroundColor: "transparent" }}
/>
</div>

注意:画布和网络摄像头的大小和位置必须相同,才能在 HTML 画布中进行绘制。

4.加载模型

将下载的模型解压到“Public”文件夹中,确保 model.json 正确地放在/model.json 路径中,并带有 weights.bin。要使用模型进行预测,代码很简单:

async function predictionFunction() {
setVideoHeight(webcamRef.current.video.videoHeight);
setVideoWidth(webcamRef.current.video.videoWidth);//testing azure vision api
let model = new cvstfjs.ObjectDetectionModel();
await model.loadModelAsync("model.json");
const predictions = await model.executeAsync(
document.getElementById("img")
);

然而,当预测的类必须显示在照片中时,事情就变得复杂了,这就是使用 HTML canvas 的原因。整个预测函数如下所示:

async function predictionFunction() {
setVideoHeight(webcamRef.current.video.videoHeight);
setVideoWidth(webcamRef.current.video.videoWidth);//testing azure vision api
let model = new cvstfjs.ObjectDetectionModel();
await model.loadModelAsync("model.json");const predictions = await model.executeAsync(
document.getElementById("img")
);var cnvs = document.getElementById("myCanvas");
cnvs.style.position = "absolute";
var ctx = cnvs.getContext("2d");
ctx.clearRect(0, 0, cnvs.width, cnvs.height);console.log(predictions);if (predictions[0].length > 0) {
for (let n = 0; n < predictions[0].length; n++) {
// Check scores
if (predictions[1][n] > 0.5) {
const p = document.createElement("p");p.innerText = "Pill" + ": " + Math.round(parseFloat(predictions[1][n]) * 100) + "%";let bboxLeft = predictions[0][n][0] * webcamRef.current.video.videoWidth;let bboxTop = predictions[0][n][1] * webcamRef.current.video.videoHeight;let bboxWidth = predictions[0][n][2] * webcamRef.current.video.videoWidth - bboxLeft;let bboxHeight = predictions[0][n][3] * webcamRef.current.video.videoHeight - bboxTop;ctx.beginPath();
ctx.font = "28px Arial";
ctx.fillStyle = "red";
ctx.fillText( "Pill" + ": " + Math.round(parseFloat(predictions[1][n]) * 100) + "%", bboxLeft, bboxTop + 70 );ctx.rect(bboxLeft, bboxTop + 80, bboxWidth, bboxHeight);
ctx.strokeStyle = "#FF0000";
ctx.lineWidth = 3;
ctx.stroke();}}setTimeout(() => predictionFunction(), 500);
}}

该函数将创建一个边界框,在该框上方显示检测到的对象类别。它包括 4 个部分,第一部分是清除绘制的 HTML 画布,然后开始对象的模型检测。

如果模型检测到对象,模型将返回预测数据。通过使用边界框数据,我们可以使用 HTML 画布绘制来绘制边界框。然后,使用 500 毫秒的超时重新运行整个功能,我们将运行我们的对象检测 web 应用程序。

最终想法

这是我关于用 Tensorflow.js 进行 React 的第四篇文章的结尾,我很高兴能够通过介绍 React 中的这个精彩工具来帮助 TF.js 社区。

在本文中,我们演练了如何使用 Microsoft Custom Vision free 层创建自定义对象检测模型,这大大减少了创建自定义对象检测模型的工作量和障碍(我认为减少了 80%)。然后,我们使用 react 将模型合并到 Tensorflow.js 中,并用不到 100 行代码编写了整个 web 应用程序。

每个行业对定制对象检测的需求都很高,在本文中,我为我的药房使用创建了一个药丸计数器,我希望在了解定制检测技术后,它可以启发您为您的行业创建更多工具。如果你这样做,一定要和我分享!

最后,

感谢您的阅读。

希望你喜欢这篇文章

我对 Tensorflow.js 文章的反应:

参考

  1. 【https://www.customvision.ai/
  2. https://github.com/mepotts/Pill-Detection

使用 TensorFlow.js 在浏览器中自定义实时对象检测

原文:https://towardsdatascience.com/custom-real-time-object-detection-in-the-browser-using-tensorflow-js-5ca90538eace?source=collection_archive---------8-----------------------

使用 TensorFlow 2 对象检测 API 和 Google Colab 训练一个 MobileNetV2,转换模型,通过 TensorFlow.js 在浏览器中运行实时推理。

目标检测的任务是检测和分类图像中的每个感兴趣的目标。在计算机视觉中,这项技术用于图像检索、安全摄像机和自动驾驶汽车等应用中。

用于对象检测的深度卷积神经网络(DNN)最著名的家族之一是 YOLO(你只看一次),通过单个端到端模型实现了接近最先进的结果( Redmon,Joseph,et al .-2016)。然而,要实时运行它,就必须有一个好的显卡,像 Nvidia Tesla V100(Bochkovskiy,a .,王,C. Y .,&廖,H. Y. M. — 2020 ),不是每个人都可以使用的。因此,以经济高效的方式将这些模型投入生产仍然是一个核心挑战。

在这篇文章中,我们将使用 TensorFlow 开发一个端到端的解决方案,在 Python 中训练一个自定义的对象检测模型,将其投入生产,并通过 TensorFlow.js 在浏览器中运行实时推理。不需要强大的计算机或复杂的图书馆。

这篇文章将分为以下四个步骤:

物体检测管道(图片由作者提供)

准备数据

训练一个好模型的第一步是要有好的质量数据。在开发这个项目时,我没有找到一个好的小型对象检测数据集,所以我决定创建自己的数据集。

我环顾四周,看到了我卧室里的袋鼠标志——这是我买来纪念我在澳大利亚的日子的纪念品。所以我决定建造一个袋鼠探测器。

为了建立我的数据集,我从谷歌下载了 350 张袋鼠图片,并使用 LabelImg 应用程序手工给它们贴上标签。因为我们可以在每张图片上有不止一只动物,这个过程产生了 520 只被标记的袋鼠。

图 2:标签示例(图片由作者提供)

在这种情况下,我只选择了一个类,但是该软件也可以用来注释多个类。它将为每幅图像生成一个 XML 文件(Pascal VOC 格式),其中包含所有注释和边界框。

XML 注释示例

为了便于操作,我生成了两个 CSV 文件,其中包含已经在训练和测试中分割的数据(80%-20%)。这些文件有 9 列:

  • 文件名:图像名称
  • 宽度:图像宽度
  • 高度:图像高度
  • :图像类(袋鼠)
  • xmin :最小包围盒 x 坐标值
  • ymin :最小包围盒 y 坐标值
  • xmax :包围盒的 x 坐标的最大值
  • ymax :包围盒的 y 坐标的最大值
  • 来源:图像来源

使用 LabelImg 可以很容易地创建你自己的数据集,但是请随意使用我的袋鼠数据集,我已经把它上传到 Kaggle:

袋鼠数据集(图片由作者提供)

训练模型

有了好的数据集,就该考虑模型了。TensorFlow 2 提供了一个对象检测 API ,可以轻松构建、训练和部署对象检测模型( Allibhai,即— 2018 )。在这个项目中,我们将使用这个 API,并使用一个谷歌协作笔记本来训练这个模型。本节的剩余部分解释了如何设置环境、模型选择和培训。如果你想直接跳到 Colab 笔记本, 点击这里

设置环境

创建一个新的 Google Colab 笔记本,选择一个 GPU 作为硬件加速器:

*Runtime > Change runtime type > Hardware accelerator: GPU*

克隆、安装并测试 TensorFlow 对象检测 API :

获取和处理数据

如前所述,该模型将使用 Kaggle 上的袋鼠数据集进行训练。如果你也想使用它,有必要创建一个用户,进入帐户部分,并获得一个 API 令牌:

图 4:获取 API 令牌

然后,您就可以下载数据了:

现在,有必要创建一个 labelmap 文件来定义将要使用的类。Kangaroo 是唯一的一个,所以在 Google Colab 上的文件部分右击,创建一个名为labelmap.pbtxt新文件,如下所示:

最后一步是将数据转换成一系列二进制记录,以便将它们输入到 Tensorflow 的对象检测 API 中。为此,使用袋鼠数据集中的generate_tf_records.py脚本将数据转换为 TFRecord 格式:

选择模型

我们已经准备好选择将成为袋鼠探测器的模型。 TensorFlow 2 在 COCO 2017 数据集上提供了 40 个预训练的检测模型。这个集合是 TensorFlow 2 检测模型 Zoo ,可以在这里访问。

每个模型都有速度、平均精度(mAP)和输出。一般来说,较高的 mAP 意味着较低的速度,但由于这个项目是基于一类对象检测问题,所以较快的模型( SSD MobileNet v2 320x320 )应该足够了。

除了模型动物园, TensorFlow 还提供了一个模型配置库。在那里,可以获得在训练之前必须修改的配置文件。让我们下载文件:

配置培训

如前所述,下载的权重在 COCO 2017 数据集上进行了预训练,但这里的重点是训练模型识别一个类,因此这些权重将仅用于初始化网络——这种技术被称为迁移学习,它通常用于加快学习过程。

从现在开始,要做的就是建立 mobilenet_v2.config 文件,并开始训练。我强烈推荐阅读 MobileNetV2 论文 ( 桑德勒、马克等人——2018)来获得架构的要旨。

选择最佳超参数是一项需要实验的任务。由于 Google Colab 中的资源有限,我将使用与论文相同的批量大小,设置一些步骤以获得合理的低损失,并将所有其他值保留为默认值。如果你想尝试一些更复杂的方法来找到超参数,我推荐 Keras Tuner —一个易于使用的框架,它应用了贝叶斯优化、超波段和随机搜索算法。

设置好参数后,开始训练:

为了确定培训进行得如何,我们使用损失值。Loss 是一个数字,表示模型对训练样本的预测有多差。如果模型的预测是完美的,损失为零;否则损失更大。训练模型的目标是找到一组在所有例子中平均损失较低的权重和偏差(下降到 ML:训练和损失|机器学习速成班)。

从日志中,可以看到值的下降趋势,所以我们说“模型正在收敛”。在下一部分,我们将为所有训练步骤绘制这些值,趋势将更加清晰。

这个模型花了大约 4 个小时来训练,但是通过设置不同的参数,你可以使这个过程更快或更慢。一切都取决于你使用的类的数量和你的精度/召回目标。识别多个类别的高度准确的网络将采取更多步骤,并需要更详细的参数调整。

验证模型

现在,让我们使用测试数据来评估经过训练的模型:

评估在 89 幅图像中进行,并基于 COCO 检测评估指标提供三个指标:精度、召回率和丢失率。

召回衡量的是模型击中正类的程度,即从正样本中,算法答对了多少?

回忆

Precision 定义了您可以在多大程度上依赖于肯定的类预测:从模型说是肯定的样本中,实际上有多少是肯定的?

精确

设置一个实际例子:假设我们有一张包含 10 只袋鼠的图像,我们的模型返回 5 个检测,分别是 3 只真实的袋鼠(TP = 3,FN =7)和 2 只错误的检测(FP = 2)。在这种情况下,我们有 30%的召回率(该模型检测到图像中 10 只袋鼠中的 3 只)和 60%的精确度(从 5 次检测中,3 次是正确的)。

精确度和召回率由交集(IoU)阈值划分。IoU 定义为交集的面积除以预测边界框(Bₚ)与地面实况框(Bₜ)( 曾,N. — 2018 )的并集的面积:

并集上的交集

为简单起见,可以认为 IoU 阈值用于确定检测是真阳性(TP)、假阳性(FP)还是假阴性(FN)。请参见下面的示例:

IoU 阈值示例(图片由作者提供)

记住这些概念,我们可以分析从评估中获得的一些指标。来自 TensorFlow 2 检测模型 ZooSSD MobileNet v2 320 x320的 mAP 为 0.202。我们的模型为不同的 iou 提供了以下平均精度(AP ):

AP@[IoU=0.50:0.95 | area=all | maxDets=100] = 0.222
AP@[IoU=0.50      | area=all | maxDets=100] = 0.405
AP@[IoU=0.75      | area=all | maxDets=100] = 0.221

那挺好的!我们可以将获得的 AP 与来自 COCO 数据集文档的 SSD MobileNet v2 320x320 图进行比较:

我们不区分 AP 和 mAP(AR 和 mAR 也是一样),并假设这种差异在上下文中很明显。

平均召回率(AR)除以每幅图像的最大检测次数(1,10,100)。当我们每张图片只有一只袋鼠时,召回率约为 30%,而当我们有 100 只袋鼠时,召回率约为 51%。这些值不是很好,但是对于我们试图解决的问题来说是合理的。

(AR)@[ IoU=0.50:0.95 | area=all | maxDets=  1] = 0.293
(AR)@[ IoU=0.50:0.95 | area=all | maxDets= 10] = 0.414
(AR)@[ IoU=0.50:0.95 | area=all | maxDets=100] = 0.514

损失分析非常简单,我们有 4 个值:

INFO:tensorflow: + Loss/localization_loss: 0.345804
INFO:tensorflow: + Loss/classification_loss: 1.496982
INFO:tensorflow: + Loss/regularization_loss: 0.130125
INFO:tensorflow: + Loss/total_loss: 1.972911

定位损失计算预测的边界框和标记的边界框之间的差异。分类损失指示边界框类是否与预测类匹配。正则化损失由网络的正则化函数产生,并有助于在正确的方向上驱动优化算法。最后一项是总损失,是前三项的总和。

Tensorflow 提供了一个工具,以一种简单的方式可视化所有这些指标。它被称为 TensorBoard ,可以通过以下命令进行初始化:

%load_ext tensorboard
%tensorboard --logdir '/content/training/'

这将会显示出来,您可以探索所有培训和评估指标。

Tensorboard — Loss(图片由作者提供)

在标签IMAGES中,可以找到一些预测和实际情况的对比。在验证过程中,这也是一个非常有趣的资源。

Tensorboard —测试图片(图片由作者提供)

导出模型

既然培训已经通过了验证,那么是时候导出模型了。我们将把训练检查点转换成一个 protobuf (pb) 文件。这个文件将包含图形定义和模型的权重。

由于我们将使用 TensorFlow.jsGoogle Colab 部署模型,其最大生命周期限制为 12 小时,因此让我们下载训练好的权重并将其保存在本地。

如果您想检查模型是否被正确保存,加载并测试它。我已经创建了一些函数来简化这个过程,所以可以从我的 GitHub 中克隆inferenceutils.py文件来测试一些图像。

一切都运行良好,所以我们准备将模型投入生产。

部署模型

该模型将被部署为任何人都可以打开 PC 或移动相机,通过网络浏览器实时进行推理。为此,我们将把保存的模型转换为 Tensorflow.js layers 格式,将模型加载到 javascript 应用程序中,并使所有内容在 Glitch 上都可用。

转换模型

此时,您应该在本地保存了类似于此结构的内容:

├── inference-graph
│ ├── saved_model
│ │ ├── assets
│ │ ├── saved_model.pb
│ │ ├── variables
│ │ ├── variables.data-00000-of-00001
│ │ └── variables.index

在推理图文件夹中打开一个终端,创建并激活一个新的虚拟环境:

virtualenv -p python3 venv
source venv/bin/activate

安装 TensorFlow.js 转换器:

pip install tensorflowjs[wizard]

启动转换向导:

tensorflowjs_wizard

现在,该工具将引导您完成转换,为您需要做出的每个选择提供解释。图 8 显示了转换模型的所有选择。大多数都是标准的,但是像碎片大小和压缩这样的选项可以根据您的需要进行更改。

为了使浏览器能够自动缓存权重,建议将它们分成 4MB 左右的碎片文件。为了保证转换能够进行,也不要跳过 op 验证,并不是所有的 TensorFlow 操作都受支持,因此一些模型可能与 TensorFlow.js 不兼容—参见此列表中当前支持的 op。

使用 Tensorflow.js 转换器进行模型转换(全分辨率图片此处 —作者图片)

如果一切顺利,您将在web_model目录中将模型转换为 Tensorflow.js layers 格式。该文件夹包含一个model.json 文件和一组二进制格式的分片权重文件。model.json既有模型拓扑(又名“架构”或“图”:对层以及它们如何连接的描述),也有权重文件的清单(林、宗毅等人)。

└ web_model
  ├── group1-shard1of5.bin
  ├── group1-shard2of5.bin
  ├── group1-shard3of5.bin
  ├── group1-shard4of5.bin
  ├── group1-shard5of5.bin
  └── model.json

配置应用程序

这个模型已经可以用 javascript 加载了。我已经创建了一个应用程序来直接从浏览器执行推理。让我们克隆存储库来弄清楚如何实时使用转换后的模型。这是项目结构:

├── models
│   └── kangaroo-detector
│       ├── group1-shard1of5.bin
│       ├── group1-shard2of5.bin
│       ├── group1-shard3of5.bin
│       ├── group1-shard4of5.bin
│       ├── group1-shard5of5.bin
│       └── model.json
├── package.json
├── package-lock.json
├── public
│   └── index.html
├── README.MD
└── src
    ├── index.js
    └── styles.css

为了简单起见,我已经在models文件夹中提供了一个转换后的kangaroo-detector 模型。不过,我们还是把上一节生成的web_model放在models文件夹里测试一下吧。

首先要做的是定义如何在函数load_model中加载模型(文件src>index.js中的第 10–15 行)。有两个选择。

第一个选择是在本地创建一个 HTTP 服务器,这将使模型在一个允许请求的 URL 中可用,并被视为一个 REST API。加载模型时, TensorFlow.js 会做如下请求:

GET /model.json
GET /group1-shard1of5.bin
GET /group1-shard2of5.bin
GET /group1-shard3of5.bin
GET /group1-shardo4f5.bin
GET /group1-shardo5f5.bin

如果选择该选项,定义load_model功能如下:

然后安装 http-server :

npm install http-server -g

转到models > web_model并运行下面的命令,使模型在http://127.0.0.1:8080可用。当您希望将模型权重保存在一个安全的地方并控制谁可以请求对其进行推断时,这是一个很好的选择。

http-server -c1 --cors .

第二个选项是将模型文件上传到某个地方,在我的例子中,我选择了自己的 Github repo,并在load_model函数中引用了model.json URL:

这是一个很好的选择,因为它为应用程序提供了更多的灵活性,并使其更容易在某些平台上运行。

本地运行

要在本地运行应用程序,请安装所需的软件包:

npm install

并开始:

npm start

应用程序将在[http://localhost:3000](http://localhost:3000)运行,您应该会看到类似这样的内容:

本地运行的应用程序(图片由作者提供)

该模型需要 1 到 2 秒的时间来加载,之后,你可以向相机显示袋鼠的图像,应用程序将在它们周围绘制边界框。

在 Glitch 发布

Glitch 是一个创建网络应用的简单工具,我们可以上传代码,让网络上的每个人都可以使用这个应用。在 GitHub repo 中上传模型文件,并在load_model 函数中引用它们,我们可以简单地登录 Glitch ,点击New project > Import from Github并选择应用库。

等待几分钟安装软件包,您的应用程序将在公共 URL 中可用。点击Show > In a new window,将会打开一个选项卡。复制此 URL 并将其粘贴到任何网络浏览器(PC 或移动)中,您的对象检测就可以运行了。请看下面视频中的一些例子:

在不同设备上运行模型(视频由作者提供)

首先,我做了一个显示袋鼠标志的测试,以验证应用程序的健壮性。它表明该模型特别关注袋鼠的特征,而不是专注于许多图像中存在的不相关的特征,如苍白的颜色或灌木。

然后,我打开手机上的应用程序,展示了一些测试集的图片。该模型运行平稳,能够识别大多数袋鼠。如果你想测试我的 live app,这里有(小故障需要几分钟才能醒来)。

除了准确性,这些实验的一个有趣部分是推理时间——一切都是实时运行的。在浏览器中运行并且使用少量计算资源的良好对象检测模型在许多应用中是必须的,主要是在工业中。将机器学习模型放在客户端意味着降低成本和更安全的应用程序,因为无需将信息发送到任何服务器来执行推理。

后续步骤

浏览器中的自定义实时对象检测可以解决许多现实世界的问题,我希望这篇文章可以作为涉及计算机视觉、Python、TensorFlow 和 Javascript 的新项目的基础。

作为下一步,我想做更详细的训练实验。由于缺乏资源,我无法尝试许多不同的参数,我相信这个模型还有很大的改进空间。

我更关注模特的训练,但我希望看到应用程序有更好的用户界面。如果有人对这个项目感兴趣,可以在项目报告中创建一个拉动请求。做一个更用户友好的应用就好了。

如果你有任何问题或建议,你可以通过 Linkedin 联系我。感谢阅读!

参考

[0]雷德蒙,j .,迪夫瓦拉,s .,吉尔希克,r .,法尔哈迪,A. (2016)。你只看一次:统一的,实时的物体检测。在IEEE 计算机视觉和模式识别会议论文集(第 779-788 页)。

[1]波奇科夫斯基,王,陈春英,廖海民(2020).YOLOv4:物体检测的最佳速度和精确度。arXiv 预印本 arXiv:2004.10934 。

[2] Allibhai,E. (2018 年 11 月 21 日)。使用 Keras 构建深度学习模型。2020 年 12 月 28 日检索,来自https://towards data science . com/building-a-deep-learning-model-using-keras-1548 ca 149 d37

[3] Sandler,m .、Howard,a .、朱,m .、Zhmoginov,a .、陈,L. C. (2018)。Mobilenetv2:反向残差和线性瓶颈。IEEE 计算机视觉和模式识别会议论文集(第 4510-4520 页)。

[4]降入 ML:训练与损耗|机器学习速成班。(未注明)。检索于 2020 年 12 月 28 日,来自https://developers . Google . com/machine-learning/crash-course/descending-into-ml/training-and-loss

[5] Zeng, N. (2018, December 16). An Introduction to Evaluation Metrics for Object Detection: NickZeng: 曾广宇. Retrieved December 28, 2020, from https://blog.zenggyu.com/en/post/2018-12-16/an-introduction-to-evaluation-metrics-for-object-detection/

[6]林,宗毅,等.“微软 coco:情境中的公共对象”欧洲计算机视觉会议。施普林格,查姆,2014 年。检索于 2020 年 12 月 28 日,来自https://cocodataset.org/#detection-eval

[7]将 Keras 模型导入 tensor flow . js(2020 年 3 月 31 日)。检索于 2020 年 12 月 28 日,来自https://www . tensor flow . org/js/tutorials/conversion/import _ keras

使用 PyCaret 的自定义估算器|第 1 部分|作者:Fahad Akbar

原文:https://towardsdatascience.com/custome-estimator-with-pycaret-part-1-by-fahad-akbar-839513315965?source=collection_archive---------33-----------------------

通过 PyCaret 创建、使用和部署灵活的定制估算器

通过 PyCaret 在 Scipy 中从头开始构建和部署 Sklearn 兼容估算器的实践指南

图片来源:https://unsplash.com/photos/D5nh6mCW52c

我们同意,PyCaret 很棒。在这么短的时间内,它对你有很大的帮助。但是有时光有这些是不够的,您希望带来您自己开发的更适合您的问题的解决方案,或者在其他地方可以获得的解决方案,并且您希望 PyCaret 来选择它。这就是我们今天要努力实现的,我们将分两部分来做。

在第一部分中,我们将学习:
1️⃣如何使用 python 的类对象制作一个简单的估算器(模型)
2️⃣如何使用 Scipy 的 curve_fit 为我们带来优势
3️⃣如何使 curve_fit 更加灵活&敏捷以便进一步集成

在第 2 部分中,我们将学习:
4️⃣如何使定制的估算器 sklearn 兼容
5️⃣如何与 PyCaret 集成

在本练习中,我们将创建一个回归估计量,因为想法是一样的,您可以创建任何类型的估计量。让我们开始建造吧

👉一个简单的估算器:

我们将使用 Python 的类对象制作估算器。课堂就像蓝图。你可以从一个类创建许多独立的对象,就像你可以从一个蓝图建造许多房子一样。例如,从“sklearn.linear_model”导入的“LogisticRegression”是一个类,当我们通过设置 cls = LogisticRegression() 来“实例化”这个类时,我们构建了一个 LogisticRegression 的对象。还有一点,类里面的函数叫做‘方法’。比如 fit() / predict()就是 LogisticRegression 类内部的函数,我们只要调用 cls.fit()等就可以使用。在我们的例子中,我们将有一个带有 fit & predict 方法的类。稍后,我们将添加另一个方法,称为 score。你可以在这里 了解更多关于 的课程

我们要建立的第一个估计量是一个简单的均值估计量,然后会跳到一个更实用的估计量。这个估计器将简单地预测平均值。我们将从训练数据中“估计”这个“平均值”。下面是我们如何做的(注意评论,我在编码时试图解释很多💻) :

现在我们已经做了一个简单的估计器,我们可以继续做一个更具体的例子,这个例子需要一个更复杂的算法。

👉科学曲线拟合:

在我的行业中,我们经常需要通过价格来预测产品的数量。当我们可视化价格和数量信息时,我们通常会观察到一种弹性行为,即随着产品价格的上升,数量会下降。然而,这种行为在某些价位上表现出来。在极端价格点,数量对价格的进一步变化没有弹性/没有反应。在图上,这看起来像一条指数曲线。

作者图片:数量与价格

在这种情况下,我们通常需要通过拟合指数形状的曲线来概括这种行为。指数方程应该是这样的:

作者图片

我们可以利用这个方程,通过 scipy 的【优化模块】curve _ fit函数,希望找到/求解系数 a & b .过程相当简单。我们定义自定义函数,然后将该函数传递给 curve_fit 函数的参数(以及其他一些参数)。出于连续性目的,我将继续使用我们之前使用的玩具数据。价格和数量说明只是为了证明使用自定义等式的意义。我们将挑选一个特征,并尝试将其与标签相匹配。稍后,我们将对多个特征重复相同的练习。这就是我们如何使用只有一个特征的指数函数进行曲线拟合(同样,请阅读代码中的注释!):

👉一种更实用的估算方法:

到目前为止一切顺利 ‘👌,但是你注意到什么了吗?如果你认为它不实用,那你就猜对了!。在现实生活中,还有更多的特性可用,在试验时,您将添加或减少不同的特性/列。如果我们像上面写的那样写代码,那么每次我们试验一个新特性时,添加/删除系数将是一场噩梦。我们希望能够足够灵活地提供任意数量的系数(特性),而不必改变函数。让我们试着解决这个问题。我们想要一个可编程函数,它可以拟合具有 n 个特征的指数曲线

作者图片

答案是用位置参数(args)打包/解包。这是处理这种情况的一个非常有用的工具。你可以在这里 阅读更多关于立场论点 。在我们的 exp_curve 函数中(在参数 x 之后),我们将允许用户通过args 传递任意数量的系数(事实上,在之后的名称并不重要,是具有魔力)。在函数内部,args 将产生一个系数元组(名称为 args ),我们将使用一个循环来构造我们的公式。毕竟,我们的大部分公式只不过是彼此的序列和积。我们将使用** 枚举 函数,该函数将返回系数及其在元组中的位置/索引。检查下面的代码,了解当我们一起使用位置参数解包&枚举函数时会发生什么。*

还有另一个微妙但重要的点。在我们的等式中,系数的数量将等于特征的数量+1。额外的一个是截距“a”,它将始终位于索引/位置 0。现在让我们再来看一个新函数:

作者图片

简单地说,我们从设置y_=0 , 开始,从args[1:0]中选取第一个系数a ,将其乘以第一列X[:,i],然后更新y_。我们继续循环的下一次迭代,得到下一个系数和特征列的乘积,将其添加到y_中(记住指数方程)。一旦我们完成了所有的系数/特征,我们只需将第一个系数(截距)args[0] 乘以y_的指数,并将其保存为y

我们可以通过使用矩阵乘法来进一步完善这个函数。这可以大大提高速度。对于这一部分,我将继续使用迭代方法,在下一部分将切换到矩阵乘法。

如果你已经走了这么远,明白发生了什么,给你自己和我一个鼓励😄。剩下的事情就简单了。我们所需要的就是使用我们的自定义函数&我们之前创建的类中的 curve_fit 函数。

这一集到此为止。在这一部分,我们学习了 估计器、python 类对象、指数函数、curve_fit 函数、位置参数打包/解包、枚举函数&,最终构建了一个更加定制化的&灵活回归估计器

在下一集,我们将使这个估计器 sklearn 兼容,然后将它与 pycaret 集成。敬请期待!

➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖
你可以在 上关注我 &上联系我 LinkedIn &访问我的github➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖

您可能还对以下内容感兴趣:

👉Docker
让您的数据科学生活变得轻松👉使用 PyCaret 的自定义估算器,第 2 部分

顾客行为建模:购买到死模型

原文:https://towardsdatascience.com/customer-behavior-modeling-buy-til-you-die-models-6f9580e38cf4?source=collection_archive---------6-----------------------

简要介绍预测购买行为的 BTYD 家族、帕累托/NBD 和帕累托/GGG

预测客户的终身价值,或者他们在未来几年将花费多少,是一个非常具有挑战性的问题。一些数据科学家(我)有全职工作致力于解决这个问题。

自由股票在 Unsplash 上的照片

幸运的是,有一个专门为解决这个棘手问题而构建的模型家族:BTYD 模型!

在本文中,我希望你能了解(1)什么是 BTYD 模型,( 2)概念上最常见的 BTYD 模型是如何工作的。

我们开始吧!

注意:在我看来,BTYDplus R 包是任何语言中探索 BTYD 模型的事实上最好的库。Python 中的生存期包对来说很棒,但我个人遇到了一些问题/错误,这让我坚定地站在了 BYTDplus 阵营…

#1:什么是 BTYD 型号?

Buy-till-you-Die (BTYD)模型是一个奇怪命名的模型系列,旨在将客户购买行为建模为一系列分布。BTYD 模型有几种不同的风格/风味(我们将介绍常见的版本),但它们都围绕几个要点:

订单表示例

订单表输入。为所有 BTYD 模型生成客户级价值预测所需的输入只是一个完整的订单表。虽然不同的模型以不同的方式处理这个表,但是它们都共享一个公共的输入结构。例外是 Abe 模型,它可以选择性地接受无序特征。由于这一输入要求,您拥有的客户群纵向数据越多,模型预测就越强。我发现合理预测的最小订单规模是大约 2 年的订单,至少 20%的客户群至少有第二次购买。

概率建模。所有这些模型都生成分布来描述客户行为。虽然 BTYD 家族的成员在创建这些发行版的方式或这些发行版的外观上有所不同,但他们都有一个共同的主要目标。一旦了解了这些分布,模型就可以简单地从这些分布中进行采样,以预测未来的客户价值

RFM 分布。虽然一些模型可能会给它们的行为分布添加一些不同的附加功能,但它们都来自于相同的总体精神&策略,即捕捉哪些行为:

  • 最近度:顾客多久前购买的?
  • 频率:客户多久/持续购买一次?
  • 货币:一个顾客平均消费多少钱?

RFM 模型的每一个元素在 BTYD 模型分布中都扮演着重要的角色。RFM 建模和分析是当前企业捕获客户行为常用策略,这些模型只是这种思路的更复杂的扩展。

BTYD 历史

有许多型号属于“BTYD”类别,如下所示:

1959 年 NBD 车型

安德鲁·埃伦贝尔。"消费者购买的模式。"应用统计学(1959):26–41。

1987 年帕累托/NBD——黄金标准

施米特莱因博士,莫里森博士,&科伦坡,R. (1987 年)。清点你的客户:他们是谁,他们下一步会做什么?管理科学,33(1),1–24

2005 年 BG / NBD

法德尔,p .,哈迪,b .,&李,K. (2005)。简单的方法“计算你的顾客”:帕累托/NBD 模型的替代方案。营销科学,24(2),275–284

2007 MBG / NBD

巴蒂斯拉姆,E.P .,m .丹尼泽尔,a .菲利兹特金。2007.顾客群分析模型的实证验证与比较。国际市场营销研究杂志 24(3)201–209。

2009 年帕累托/ NBD

安倍真由。"逐一统计你的顾客:帕累托/NBD 模型的分层贝叶斯扩展."营销科学 28.3(2009):541–553。

2016 帕累托/ GGG —最新和最棒的

迈克尔和托马斯·罗伊特勒。"计时:计时规则有助于更好地预测客户活动."营销科学(2016)。

虽然每个模型都有自己的优点和缺点,但在这篇文章中,我将重点介绍两个最流行的(也是最强大的)模型:帕累托/NBD帕累托/GGG

注:因为 Medium 目前不支持下标符号,所以我不得不使用上标符号。它看起来更糟,但希望传达相同的故事

帕累托/NBD (PNBD)模型

帕累托/NBD 模型最早出现在 1987 年的开创性论文《统计你的客户:他们是谁?他们下一步会做什么?》中。

该名称是指用于客户流失的帕累托分布和用于未来购买预测的负二项式分布(NBD)。作为输入,帕累托/NBD 只需要一个订单表。

帕累托/NBD 的目标是在 RFM 分析的基础上,在决定(1)一个客户是否已经过期,( 2)他们购买的频率时,通过捕捉客户是谁的背景。例如,考虑两个客户:Allen & Billy。

rupixen.com在 Unsplash 上拍照

艾伦隔天在我们店里买的,持续 2 个月。但是,他在过去两周内没有购买。

在过去的 6 个月里,Billy 大约每月从我们商店购买一次。他在过去两周也没有购买。

尽管两个客户有相同的最近(14 天),购买行为的差异改变了失效的概率。此外,尽管在同一家商店购物,他们表现出明显不同的购买模式(隔天与每月),因此任何预测都必须考虑他们的购买习惯。

帕累托/NBD 通过模拟两种人口分布来做到这一点,寿命随着时间推移的购买量

寿命

客户的寿命(Tᶜ)定义为:

Tᶜ ~ Exp(μᶜ)

帕累托分布。看看形状参数α如何改变分布的严重性,从而改变失效的可能性。来源:维基百科

Exp()指的是指数或幂律分布。它也被称为帕累托分布。μᶜ值是从μ分布中提取的客户级形状参数(参见先验部分!)基本上抓住了您企业中该客户的典型失败率。如果你有大量的一次性顾客,寿命分布将比顾客更经常回来的企业严重得多

如果你还没有猜到,商业中著名的“帕累托原则”——也称为 80/20 法则——是基于(非常非常松散地……)帕累托分布的:

对于许多结果来说,80%的后果来自 20%的原因(至关重要的少数原因)——维基百科

将这一点解释回购买行为:一般来说,大多数客户在成为客户后会相对较快地流失,但一小部分客户会停留很长时间。这是帕累托·NBD 提出的一个假设,从我对不同企业的经验来看,这个假设相当合适:许多企业都有“小鱼”客户,即只进行 1-2 次小额采购的客户,以及“鲸鱼”客户,即持续进行大额采购的客户。

因此,通过从由我们特定业务的客户购买行为定义的帕累托分布中取样,我们可以预测与我们业务相关的每个客户的预期寿命。

一段时间内的购买量

客户在一定时间(t)内的购买次数(k)定义为:

k~Poisson(t*λᶜ)

泊松分布。这种分布在形状方面有更大的灵活性,这也是为什么它是跨企业捕捉购买行为的好选择。来源:维基百科

Poisson()指的是帕累托/NBD 假设购买时间的泊松分布。实际上,顾名思义,帕累托/NBD 使用负二项式分布,其中泊松分布是一种特殊情况μᶜ一样,λᶜ是从λ分布中提取的客户级形状参数(参见之前的部分!)基本上捕捉了牵引间隔时间(ITT),或购买之间的时间。

泊松分布是模拟 ITT 的一个合适的选择,因为不同的业务会有不同的 ITT,并且客户也可能表现出不同的购买模式。

传道者

如前所述,μᶜλᶜ取自 mu 和 lambda 分布。μλ都是伽玛先验分布。我不会深究估计先验分布的数学方面,因为这篇文章的目的是高层次的理解,但本质上,你可以通过观察现实世界并从这些观察到的实例反向工作来找到这些分布,并了解可能的先验分布应该是什么样子。PNBD 使用的过程被称为对数似然推断。通过学习公司过去的历史,贝叶斯模型可以预测未来。

求解 PNBD 先验的符号。来源:https://www . briancallander . com/posts/customer _ lifetime _ value/Pareto-NBD . html

做预测

因此,要找到客户的终身价值,帕累托 NBD…

  1. 通过从寿命帕累托分布中抽样来查找客户的预期寿命。
  2. 通过对一段时间内的购买量分布进行抽样来查找客户的预期交易数
  3. 将预期交易次数乘以平均购买金额

在某种程度上,您可以将帕累托/NBD 预测方法直接映射回 RFM 分析。相当酷!

帕累托/GGG 模型

帕累托/GGG 模型最初是在 2016 年的开创性论文“滴答走时刻:时间规律性有助于更好地预测客户活动”中引入的。它以平克·弗洛伊德的歌曲“时间”命名并介绍了这首歌。好像贝叶斯建模还不够时髦😎

Platzer & Reutterer 听到了这些话,并受到启发,重新发明了客户行为建模。来源:https://www.pinterest.co.uk/pin/548313323377868100/

帕累托/伽马伽马,或者说帕累托/GGG,使用了很多和我们刚刚讨论的 PNBD 模型相同的原理。它使用帕累托分布对下降进行建模,并具有人口和客户级别的分布。但是,它在两个有意义的方面有所不同:

  1. PGGG 使用三种伽玛分布,而不是 NBD 来模拟一段时间内的购买情况
  2. PGGG 不是从对数似然中学习先验,而是从蒙特卡罗马尔可夫链(MCMC)中学习先验

三伽玛&结块

通过从 3 个伽玛分布中取样,可以得到超过的购买次数,从而得到距离下一次购买的时间(ITT)。从购买 j 到下一次购买(Δtʲ)的 ITT 定义为:

Δtʲ~Gamma(k, k*λ)

其中参数kλ都来自它们自己的伽马先验分布:

k~Gamma(t, γ)

λ~Gamma(r, α)

**当我第一次阅读 PGGG 论文时,我被这个名称弄糊涂了,因为从技术上讲有 4 种伽马分布,因为 *μ* 伽马先验分布仍然用于模拟时间推移。我猜 GGG 比 GGG 更吸引人

为了理解以这种方式模拟 ITT 的价值,让我首先引用这篇论文,然后提供一些额外的解释。正如普拉茨和罗伊特勒在他们 2016 年的论文中所说:

"λ决定频率,形状参数 k 决定交易时间的规律性."

Platzer & Reutterer 意识到需要在模型中捕捉的客户行为是交易的节奏/聚集。虽然 ITT 的平均值可以概括客户的行为,但它不能显示他们是否会定期回来,或者他们是否会在“疯狂购物”之间休息很长时间他们在论文中直观地展示了这一点:

归功于(Platzer & Reutterer,2016 年)

下面的例子可以说明上述情况的一个夸张的例子:

坎迪斯和王思然都有相同的…

  • 平均 ITT — 1 个月,
  • 寿命— 1 年
  • 购买数量— 12

…但消费习惯却大相径庭。

坎迪斯每个月的第一天都会准时从你的店里买东西。

王思然,在她第一次购买后,忘记了你的商店 6 个月。但是一旦她记起来了,她就开始疯狂购物,一天之内买了 5 样东西。现在满足了,她又等了 6 个月,继续同样大的购物狂欢,在一天之内买了 6 件东西。

如果我们的行为模型没有解决购买聚集问题,我们可能会错误地假设这两个客户在接下来的两个月里有相同的购买机会。但是对于 PGGG,我们会给坎迪斯一个很高的 k 值,给王思然一个很低的 k 值。

选择伽马分布的另一个价值是它们提供了很大程度的灵活性。这使得 PGGG 能够捕捉更多的购买行为,这使它与大多数业务类型相关。

伽玛分布。查看定义此分布类型的形状/速率参数如何允许它捕捉大量行为。来源:维基百科

根据我在客户行为建模方面的经验,帕累托/NBD 和帕累托/GGG 在基于订阅的业务上表现都很好,但在非订阅业务上,PGGG 胜过 PNBD。这是有道理的——PGGG 解释了人们在你的商店中的不规则购买模式!

MCMC 采样

PGGG 和 PNBD 的另一大区别是 PGGG 使用 MCMC 来求解它的先验分布。正如 PNBD 提到的,解决先验知识是一个非常困难的过程,有时恢复真实的先验知识是不可能的。自 PNBD 诞生以来,随着计算能力的增长,一种新的(计算代价昂贵的)寻找先验的策略出现了,它是以蒙特卡罗马尔可夫链的形式出现的。

蒙特卡洛这个名字,指的是摩纳哥著名的酒店,是一个代号,因为取样方法是在洛斯阿拉莫斯核武器项目期间发明的。由阿米特·拉哈夫在 Unsplash 上拍摄

已经有大量的资源可以帮助您理解 MCMC 采样如何帮助寻找分布,但本质上的想法是以一种连续的方式随机采样,以“猜测”我们的先验方法。通过对未知分布生成的值进行数百万次模拟,我们最终可以重建出它们的采样分布。随机抽样方法提供了"蒙特卡罗"部分的名称,而样本间的关系提供了"马尔可夫链部分的名称

在非常高的水平上,MCMC 通常提供比以前的恢复方法更精确和更概括的先验分布预测。

应用

我希望本指南能为您提供这类模型如何工作的简单工作知识。如果有兴趣了解更多信息,我强烈推荐:

  1. 你自己看报纸
  2. 自己实现模型

R 包已经构建了所有这些模型并准备好了,而文档是惊人的并且容易理解。

感谢阅读!

顾客行为建模:后 COVID 世界的最佳模型

原文:https://towardsdatascience.com/customer-behavior-modeling-the-best-models-for-a-post-covid-world-3e388926609c?source=collection_archive---------26-----------------------

并非所有的客户模型都是一样的

我们都同意 COVID 完全改变了客户行为。越来越多的人在网上购物,越来越多的人被困在家里,越来越多的人在旅行/度假中投资于个人舒适。

如果他们和我一样,更多的人会在周末去亚马逊疯狂购物…

在这一点上,联邦快递的邮递员是我最好的朋友。

Elena Mozhvilo 在 Unsplash 上的照片

即使发生了所有这些变化(尤其是因为这些变化),我们也需要确保我们的业务能够了解我们的客户群,并在这个动荡的时代继续增长。

为您的企业开发一个强大而准确的长期价值模型,几乎可以为每一项战略计划带来巨大的回报。即使是最简单的预测模型也能提供价值和洞察力。

为什么是 CLV?与首次购买价值或收购数量等其他短期指标不同,CLV 可以捕捉到企业的实际健康状况。你的企业可能已经获得了大量的新客户,但如果这些客户不留下来,你的品牌将很快回归到 COVID 之前的水平。

泰勒·弗兰塔在 Unsplash 上的照片

聪明的企业会发现谁是他们最好的客户,并利用他们的经验和产品来吸引更多的客户。

话虽如此,LTV 模型还是有等级之分的,有些比另一些强得多。

在这篇文章中,我希望通过一个强大的 LTV 模型的标准,一些市场上更常见的模型,并最终有助于提供清晰的哪种模型最适合你的特定情况。

由于这篇文章是为更具技术性的读者而写的,我们将更深入地探究这些模型是如何产生预测的。这将有望揭示我们选项之间的重要细微差别和差异。我们开始吧!

TLDR:这是每种型号的相对优势。继续阅读,了解更多信息!(作者制作)

什么是好的 LTV 模型?

设定一个好的 LTV 模型的期望将确保我们的评估能够涵盖贵公司可能感兴趣的所有元素。

#1 预测强度指标

一个好的 LTV 模型的表标要求当然是它必须准确。一个强有力的 LTV 模型应该能够高度准确地预测客户价值。

(1)合计预测准确性是一个经典的数据科学指标,用于比较模型,并可直接应用于业务。如果团队升级到产生更准确的综合预测的模型,董事会报告和收入预测都可以提升到下一个级别。

(2)客户级别预测准确性是我们将寻求的另一个预测强度指标。我以前写过为什么这是客户行为模型的一个重要指标(链接),但总结一下:

客户级别的指标对于比较模型来说是至关重要的,因为我们需要了解模型的能力,以便准确地将客户划分为低/中/高细分市场,而这是无法通过汇总统计数据来验证的。

这就是说,一个强大的 CLV 模型在客户和总量层面上都是准确的。

#2 可操作输出

除了预测能力之外,一个好的客户行为模型还应该有一些额外的属性,使其可以在生产中使用。以下是我们要看的几个:

(3)首次交易时/之前。模型越早做出准确的 CLV 预测,它在营销和报告中的应用就越有效。如果一个团队需要等待几个月才能对他们的模型预测有信心,那么这意味着他们在这段时间内执行次优活动的风险很大。

快速了解一项商业战略(如付费收购活动或电子邮件保留活动)在提升长期客户价值方面是否有效,对企业来说具有难以置信的价值,因此我们将把能够更早准确预测的视为更好的模型

(4)可解释的。可怕的数据科学黑箱在每个预测模型项目中都露出了丑陋的一面,客户行为建模也不例外。虽然黑盒模型的准确性通常非常强大,但不了解为什么客户会得到某个分数可能会导致灾难性的结果。可解释性高的模型优于可解释性低的模型

作为一名数据科学家,“相信模型”是一种糟糕的心态。我们需要能够剖析我们的模型,并理解假设和优势到一个可接受的水平,而这种理解能力往往是以原始预测能力为代价的。这当然是一种权衡,但我倾向于解释能力而不是力量

(5)灵活性&长期。使用 CLV 模型可以很容易地预测未来不同的时间长度,这对企业来说是一个有用的功能。这使得财务团队可以找到预测的平均回报时间、2 年 CLV 以及任何其他感兴趣的时间框架。我个人曾与只对季度预测值感兴趣的公司和其他关心预测未来 15 年的公司合作过。能够处理所有这些请求的模型比只能猜测单一时间范围的模型更有价值

(6)顺应潮流。客户行为和趋势会随着时间的推移而变化,能够轻松应对不断变化的客户环境的模型是放在产品中的更健壮、更现实的模型。在后 COVID 时代,这一点尤为重要,在这个时代,每个人都在深入思考客户购买习惯将在 2020 年及以后发生的变化。如果一个模型在一种新的客户群出现时就崩溃了,或者破坏了试图抓住这种新客户群的整体预测,那么对营销人员来说采取行动就没什么用了。

使用所有这 6 个指标,我们可以为每个可用的客户模型开发一个记分卡。在 0-5 分的范围内,每个数字的含义如下:

  • 0 :做不到
  • 1: 做不好
  • 2 :能胜任
  • 3 :能做好
  • 4 :能做得很好
  • 5 :无敌

提到成功的标准后,让我们进入不同的模型吧!

客户行为模型

模型类型#1: Excel CLV 模型

什么事?

这是最简单和最普遍的客户价值建模形式。在世界各地的许多金融预测模型中,基本公式可以概括为:

Excel CLV =平均销售额 x 平均重复销售额 x 预期留存时间 x 利润率

通常,财务团队会将该公式与每个变量的公司范围内的一般数字一起使用,并将其插入 excel 中,以生成丰富多彩的群组 clv excel 电子表格(因此有了“excel CLV”的昵称)

队列 CLV 和保留曲线。由 Excel 电子表格(作者制作)提供给您

记分卡:

客户级别预测:0/5

不幸的是,因为输入值都是群组级别的统计数据,所以预测不可避免地只适用于整个群组。任何客户级别预测的尝试对所有客户来说都是完全相同的数字,而且是不准确的数字。

总水平预测:3/5

Excel CLV 模型可以相对较好地捕捉总体客户行为;这也是他们出现在许多董事会报告中的原因。虽然它们不如我们将要讨论的其他模型准确,但从方向上来说,这个模型是可用的,因此获得了 3/5 的分数

首次交易时的预测:1/5

是的,有可能在一群人加入时计算他们的 CLV,但这里的问题是,如果使用相同的输入,每个群组将会有相同的第一笔交易预测。在做预测时,购买行为的任何差异都不会被考虑在内,所以它通常是非常不准确的。1/5

可解释性:3/5

Excel CLV 模型的确是可以解释的…但不一定是以一种有帮助的方式。我们可以很快得到为什么给出预测的字面解释——这是一个简单的公式——但我们对驱动这些预测的实际客户行为没有更深入的理解。所以它可以给我们一个字面上的解释,但非常有用

灵活性:3/5

使用 Excel,我们可以像在队列保持分析中一样分解 CLV,因为保持是公式本身的一部分。我们可以根据我们感兴趣的任何时间段对 CLV 进行细分,尽管由于留存+平均销售额是常数,这种灵活性无法捕捉其他模型所表现出的季节性。

趋势稳健:1/5

该模型没有防范客户行为变化的护栏。有一个人在循环中,当这些事情发生变化时,他可以编辑平均销售额/保留率,但由于这两个指标都是滞后指标,需要几个月才能出现和验证,所以我们的 excel CLV 模型在被修改之前,将会在相当长的一段时间内做出糟糕的预测。这显然是一个问题,也是许多高管在 COVID 成功后突然发现他们的项目不再符合现实时面临的问题。几个月后,这个问题仍然存在。

可控和可调:3/5

Excel CLV 确实让我们很容易获得可调性,因为它需要一个人来找到/学习它的参数。但是营销界的任何人都可以告诉你,其他因素也会影响客户的 CLV,因为模型不会学习/控制这些特征,所以我们无法调整我们的模型来解决这些因素。

Excel 模型记分卡。作者制作

模型类型#2:监督机器学习

什么事?

监督机器学习模型是任何“学习”如何基于标签预测 CLV 的模型的总称。数据输入和模型架构是这些模型的两个基本部分。

这些模型的输入是通常在训练模型之前设计的特征。基于客户订单表的常见特性包括新近性(客户购买后多久)、频率(他们购买的频率)和货币性(他们平均花费多少)。您总是可以派生出其他特性,如生命周期(客户开始购买后多久),甚至包括客户或产品特性,如他们第一次购买了什么产品或通过什么渠道购买的。

有各种各样的风格和架构,都有自己的卖点和权衡:

  • 线性回归:在yi=b1*xi+b0中找到b0b1的参数值,其中(xi,yi)是提供的一组坐标,找到的线使误差平方和最小

  • K-最近邻聚类(KNN) :对于每个新客户,找出 K 个最相似的客户,并给他们分配一个聚类。为群集中的每个客户选择最典型的 CLV 值
  • 前馈神经网络:一系列连接的节点,每个节点都有自己的权值,以接受输入的方式组装,通过神经元层(称为隐藏层)进行馈送,产生所需的输出。通过最小化在提供的标签上计算的误差,并使用反向传播将误差分布在节点上并对权重进行调整,来优化权重值
  • 递归神经网络:具有上述所有元素的神经网络,具有隐藏层的附加组件,其连接方式允许更深隐藏层的输出被视为更早隐藏层的输入

该记分卡将专注于更复杂的机器学习版本,即神经网络,因为这些是生产中最常用的模型。简单的 ML 模型,像回归,是很棒的,因为它们是可解释的,但缺乏在现实世界中使用的必要的准确性。

记分卡:

客户级别预测:4/5

如果你选择了正确的模型,客户层面的预测对于监督的 ML 模型来说是相当强的。我发现使用梯度增强的机器特别成功,在数据集之间达到< = 20%相对误差的峰值

总水平预测:3/5

对于监督 ML 模型来说,总水平预测是可以的,考虑到客户水平的误差是好的,这是很奇怪的。这源于这样一个事实,即由于该模型不一定是基于现实的假设,如 Excel CLV 或 BTYD 中的那些假设,受监督的 ML 模型有时会对隐藏在中间客户级别统计数据中的鲸鱼(业务的前 5%,有时比普通客户花费更多的数量级)做出疯狂的预测。这种有趣的怪癖已经出现了足够多次,值得一提

首次交易时的预测:3/5

监督的最大似然模型确实可以在客户层面上做出第一天的预测,而且比简单的 excel CLV 模型更准确。然而,预测强度不如其他模型准确。虽然我对这些数字的准确性有实际经验,历史上这些数字的相对误差在+- 100%左右浮动,但有一些理论原因表明第一次交易预测强度不是最佳的。监督式 ML 模型旨在预测标签,而不是客户行为。这意味着它正在对输入特征和(通常有噪声的)美元金额之间的关系进行建模,而不是对客户类型或消费习惯进行建模。虽然这对于普通客户来说是可以接受的,但是新客户总是需要了解较少的信息,因此 ML 模型将使用平均值或排除这些客户,从而导致较低的性能。

可解释性:0/5

ML 模型具有强大的学习能力来准确预测标签,是黑盒。全国各地都有研究项目致力于找出如何解释和理解非线性关系,但今天我们真的很难解开神经网络内部的计算复杂性网络。当一个预测看起来很奇怪,或者准确性由于数据漂移而开始下降时,您的团队将没有问题所在的提示。这是使用这些模型的一个主要缺点

灵活性:1/5

与其他模型不同,您不能任意选择一个时间范围来进行预测。ML 模型需要在标签本身内训练之前定义的时间尺度。您可以更改用于训练模型的时间长度,但每次想要修改时间刻度时都要重新训练模型,这在使用 CLV 模式的公司中很常见。你也不能保证这个新训练的模型会做出和以前的模型一样的预测…

趋势稳健:1/5

不平衡的数据集导致较差的 ML 模型性能。如果趋势太小,模型将简单地用多数覆盖它,因为这将使它的损失函数保持较低。如果趋势是主要的,它会因为完全相同的原因重写之前的预测。如灵活性部分所述,重新训练模型会对 CLV 预测的连续性产生重大影响

可控和可调 3/5

一个强大的数据科学家或 ML 工程师肯定可以迭代模型架构和数据输入。但是这是有挑战性的,并且只能由一个老练的技术人员全职负责这个项目。此外,ML 模型有大量的参数需要调整。正如在可解释性一节中提到的,该模型没有提供任何关于哪些参数如果调整得当会产生最佳增益的指示。

ML 模型记分卡。作者制作

型号 3: BTYD 型号

什么事?

BTYD 模型,或称“买到死”模型,是一类统计模型,专门用于计算客户群的终身价值。在 Python 中,它们是在生存期包中实现的,而在 R 中,它们是在 BTYDplus 包中实现的。它们是贝叶斯模型,这意味着它们使用已知的概率分布来生成 CLV 预测。我在这里写了一个简短的总结。

在这篇文章中,我将关注帕累托/GGG,因为它是模型家族中最新也是最强大的。

帕累托/GGG 中的三个“g”代表“Gamma Gamma”,指的是模型内部工作的固有分布。该模型试图从数据中学习三种分布。我上面链接的帖子也详细讨论了这个模型是如何工作的!

记分卡:

客户级别预测:2/5

BTYD 模型的一个好口号可以是“个人的贫穷,集体的伟大”尽管 BTYD 模型在总体上具有优势,但在客户层面上却表现不佳。这种情况经常出现,因为 BTYD 模型通常不能很好地预测客户流失,导致每个客户损失几美元。这是一个如何计算客户未来的神器。从个人经验来看,我还发现对客户支出的预测是错误的——该模型使用聚合统计数据来确定支出,因此即使客户经常支出 20 美元,如果总体支出通常为 50 美元,则该模型将预测支出。

总水平预测:5/5

BTYD 模型在总体上是好的。如前一节所述,分配给每个客户的几美元很好地平衡了对高价值客户的低估,因此总的来说结果相当准确。如果您主要对董事会报告或群组分析感兴趣,请使用 BTYD 模型。

首次交易时的预测:2/5

BTYD 模型的一个缺陷是它们几乎完全依赖订单信息。这似乎不是一个主要缺点,但这意味着模型需要学习客户的购买行为,然后才能做出有意义的预测。大多数企业的购买间隔时间在一个月左右,这意味着该模型需要几个月的数据才能准确区分一次性客户和高价值客户。这种准确性的延迟是 BTYD 模型在客户生命周期早期表现不佳的原因

可解释性:2/5

BTYD 模型预测和模型本身之间的关系在模型从数据中学习的分布形状中清楚地描述出来。也就是说,在知道参数值有限且非常复杂的情况下,您可能会采取的措施。数据科学家/分析师不仅需要深入了解贝叶斯模型和 MCMC(例如,如果 Gelman stat 超过 1.5),还需要深入了解实际的 BTYD 模型(例如,为 PGGG 选择合适的起始参数)。因为缺乏这方面的知识,并且修改 BYTD 或 Lifetimes 包的能力有限(参见可调小节),所以我给这些模型打了 2 分

灵活性:3/5

你可以在 BTYD 的基础包中选择不同的时间尺度来预测,这很棒。如上所述,您还可以选择输出“固定 t 形星”或“变化 t 形星”,这是 CLV 模型中的一个很大的特性。唯一阻碍这些模型的是,您必须重新训练模型以同时接收多个不同的时间尺度,并且重新训练 BTYD 需要大量的时间。

趋势稳健:1/5

由于模型严重依赖订单数据,BTYD 模型很难适应新趋势,因为它们缺乏对这些客户独特性的洞察。此外,一分为二的客户群会给模型带来严重的问题。;从经验来看,如果你为每个业务领域训练一个单独的 BTYD 模型,你可以产生更强的结果,但是如果有重叠的话,这会引起问题。你可以想象,如果出现新的客户趋势,这将更具挑战性——你不能只是从你的模型中忽略这些客户,但包括他们将会扭曲所有其他客户的预测。正如在“首次交易”一节中提到的,BTYD 模型在预测的前几个月是不稳定的,如果出现新的客户趋势,这种情况就会加剧。

可控和可调:1/5

正如在可解释性一节中提到的,如果您有必要的领域知识,BTYD 模型确实提供了一些有限的控制。然而,这些可调部分不是很直观,也不一定能帮助您更好地理解数据。根据经验,选择自定义的起始参数可能会修改预测,但是除了强力网格搜索之外,您无法真正保证它们是否成功。

BTYD 模型记分卡。作者制作

所以…哪个型号最好?

像数据科学/生活中的所有难题一样,正确答案是视情况而定。基于模型的使用和团队的需求,上面的每一个都有自己的优点

如果你想马上使用 CLV,你最好的选择是 Excel 模型。它非常容易实现,不需要任何代码,并且可以很快用于判断您的客户的近似值

如果你想利用 CLV 的整体商业健康,BTYD 模型可能是你的最佳选择。他们在判断一个企业的总体客户价值方面非常有效,所以如果你需要 CLV 来做董事会报告,BTYD 模型将会帮你

如果你想用 CLV 来做客户层面的决策,你可能想用 ML 模型。只要你有一个成熟的团队,能够正确地瞄准模型并确保预测是合理的,ML 模型将产生最佳的客户级预测

如果你在客户层面寻找可解释的、健壮的、仍然准确的东西,打电话给我。我也在积极寻找——让我们合作吧。

但是,使用我的记分卡,每个模型的平均得分是:

Excel : 2.00

毫升 : 2.14

BTYD : 2.28

作者制作

当然,还有无数其他用例及模型可供选择。我目前的公司使用 BTYD 模型和 ML 模型的混合来消除两者的缺点,并在上面撒了一点无监督聚类。你绝对应该和他们中的任何一个或所有人玩一玩,看看哪一个适合你。

感谢阅读!

客户流失准确度:通过 TextBlob & SBERT 提高了 4.6%

原文:https://towardsdatascience.com/customer-churn-accuracy-a-4-6-increase-with-feature-engineering-29bcb1b1ee8f?source=collection_archive---------30-----------------------

关于我如何通过客户服务说明将小型客户流失数据集的准确率提高了 4.6%的演练

作者图片

目录

  • 动机
  • 商业问题&数据
  • 特征工程&建模
  • 评估&特征分析
  • 总结

动机

在我上一篇博客“什么是嵌入,你能用它做什么”中,我谈到了嵌入可以将高维、非结构化的数据变成低维的数值表示,可以用在各种机器学习模型中。在另一篇博客“什么是 MLOps,为什么我们应该关注”中,我还提到高质量的数据将有助于将机器学习引入小企业的运营。因此,在今天的博客中,我将向您介绍我是如何利用额外的客户服务注释将小型客户流失数据集的准确率提高 4%的。

我在我以前的一个项目中建立了这个博客。然而,我通过应用情感分析和 SBERT 句子嵌入扩展了旧项目。然后我用 XGBoost(流行的竞争算法)和 Random Forests(流行的研究算法)拟合数据。

业务问题和数据

一家电话公司从其 2070 名客户那里收集了原始数据集,标记为服务状态(当前/已取消)。该电话公司希望使用这些数据来了解客户流失问题,以便采取战略性措施来留住那些将来可能会取消服务的客户。这种分析也被认为有助于公司识别使顾客取消服务的因素。

数据集包含 17 个要素,包括客户 id、一般人口统计信息和服务使用信息。该公司还提供了其客服留下的评论,指出了客户的问题以及他们如何帮助客户。标签以 3:2 的比例分发。还有 115 个独特的客户服务说明。

作者图片

特征工程&建模

我将在我们的数据上演示四种不同的特征工程方法:首先,我对所有的分类变量使用 one-hot-encoding。其次,我对客户服务记录应用了情感分析、句子嵌入和 TF-IDF。

一次热编码

# load package
from sklearn.preprocessing import LabelEncoder
import pandas as pd# read data
customer = pd.read_csv("Customers.csv")
comment = pd.read_csv("Comments.csv")# extract the categorical variables
le = LabelEncoder()
col = customer.select_dtypes(include=object)
col_names = col.columns# transform the categorical variables
for x in col_names:
customer[x]=le.fit(customer[x]).transform(customer[x])

LabelEncoder 将帮助我们将所有分类变量转化为数字。比如它会把性别变量(M/F)变成[1 或者 2]。由于这个项目的主要重点是演示如何将文本特征纳入我们的分析,我没有对数据做任何额外的特征工程。

情感分析

# load textblob
from textblob import TextBlob# define functions to extract polarity and subjectivity
def find_pol(review):
    return TextBlob(review).sentiment.polarity
def find_sub(review):
    return TextBlob(review).sentiment.subjectivity# perform the sentiment analysis
customer['sentiment'] = comment['Comments'].apply(find_pol)
customer['subjectivity'] = comment['Comments'].apply(find_sub)# assign the average score to the same message
for i in range(0,115):
    value = customer[customer.Comments==i].sentiment
    mean = customer[customer.Comments==i].sentiment.mean()
    std = customer[customer.Comments==i].sentiment.std()
    outliers = (value-mean).abs() > std
    customer["sentiment"][outliers.index]= mean

在这个项目中,我使用了 TextBlob,一种流行的情感分析技术,来提取极性和主观性。然而,不知何故,它给了相同的信息不同的分数。所以我做了一个转换来平均出相同信息的分数方差。你可以在这里找到更多关于 textblob 的信息。

用 SBERT 嵌入句子

# load SBERT from sentence_transformer
from sentence_transformers import SentenceTransformer
sbert_model = SentenceTransformer('stsb-mpnet-base-v2',
                                   device='cuda')sentence_embeddings = sbert_model.encode(comment.Comments) 
# the shape of the embedding is (2070,768), convert it to 1
sent_emb = pd.DataFrame(sentence_embeddings).mean(axis=1)
customer["sent_emb"] = sent_emb

句子 BERT (SBERT)是自然语言处理中最先进的模型之一。它基于 BERT 的想法,由德国达姆施塔特技术大学的 UKP 实验室开发。他们有许多针对各种用途的预训练模型。你可以在这里查看完整的名单。

句子嵌入有 768 个特征,这对我们的模型来说太多了。我用 Tensorflow 测试了 autoencoder,但它没有显示出明显的改进。因此,我对这些值进行平均,将它们转换为每个客户的一个值。

基于 TF-IDF 的词汇抽取

# load packages
from sklearn.feature_extraction.text import TfidfVectorizer
import math# calculate the # of unique words in the corpus
feature = []
for i in df["patterns"]:
    feature.append(i.split())
    flat_list = [item for items in feature for item in items]
    feature=len(set(flat_list))# only take the top 10% of the most frequent words
# set the max document frequency to 0.2 to maintain the uniquenessmax_feature = math.ceil(feature*0.1)
tfidfvectoriser=TfidfVectorizer(strip_accents="ascii",
                                max_features=max_feature,
                                max_df = 0.2)
tfidfvectoriser.fit(df["patterns"])
tfidf_vectors=tfidfvectoriser.transform(df["patterns"])
tfidf_vectors=pd.DataFrame(tfidf_vectors.toarray())
tfidf_vectors.columns = tfidfvectoriser.get_feature_names()# merge the words into the original table
customer = pd.merge(customer,
                    tfidf_vectors,
                    left_index=True,
                    right_index=True)

到目前为止,我们已经对文本数据进行了情感分析、句子嵌入和 TF-IDF。这三种不同的技术帮助我们从文档级、句子级和词汇级提取信息。现在,让我们看看这些功能工程会对模型产生什么影响,并探索影响客户决定保留或离开服务的功能。

评测&特征分析

由于我只有一个相当小的数据集(2070 个观察值),过拟合很有可能发生。因此,我使用了交叉验证技术,而不是简单地将其分成训练和测试数据集。我将折叠数设置为 10,并将平均准确度和平均 roc_auc_score 作为最终输出。

XGBoost

作者图片

我从基本的 xgboostclassifier 模型开始,逐步将情感特征、句子嵌入和 TF-IDF 添加到模型中。如您所见,通过添加这三个新功能,准确性得分比基础模型提高了 2.7%,roc-auc 得分比基础模型提高了 1.3%。用
贝叶斯优化进行超参数调优后, 最终准确率评分比基础模型提高了 4.6% ,roc-auc 评分也上升了 1.9%。

作者图片

上面的混淆矩阵显示,假阳性和假阴性的数量非常接近,所以没有发生过度拟合。如果企业想找出模型无法识别这些客户的原因,我认为他们应该手动查看数据,研究他们内部的相似性以及这些客户与其他人之间的不同之处。

随机森林

你可能已经注意到,在许多学术研究论文中,作者通常更喜欢随机森林而不是梯度推进机器。我发现在 Quora 上解释了两个原因:第一,RF 比 GBM 容易调得多;其次,RF 比 GBM 更难过拟合。因此,我还检查了这些特性如何适用于随机森林。

作者图片

如图所示,最终的准确度分数和 roc_auc 分数分别上升了 3.8%和 1%。对于超参数调谐 RF,我发现这篇文章可能有用。

功能的重要性

为了研究模型中最重要的特性,我使用了 xgboost 内置函数:“plot_importance”

from xgboost import plot_importanceplot_importance(model_final)
plt.subplots_adjust(left=0.5, bottom=1.6, right=2.4, top=6)
plt.show()

作者图片

它表明,最重要的特征是:年龄,费率计划,长途,估计收入,客户服务信息,主观性,情绪极性等。

通过研究这些特征并执行一些基本的统计分析,我发现,与取消服务的客户相比,当前客户平均年龄大 5 个月,费率计划更低,长途电话更少,每年多产生大约 7,000 美元,并且得到了更积极、更少主观的服务。

总结

在这篇博客中,我演示了如何通过从文档级、句子级和词汇级提取信息来将文本数据合并到分类问题中。这个项目展示了精细标记的小型数据集如何为小型企业实现理想的性能。它还说明了如何使用自然语言处理技术来促进监督机器学习问题,如分类。分析表明,我创建的功能是模型中最重要的功能之一,它们有助于建立对不同客户群的描述。

联系我上LinkedIn如果你想讨论任何关于数据科学的事情!

相关阅读:

将文本特征纳入分类项目

具有文本和可解释性的客户流失预测

原文:https://towardsdatascience.com/customer-churn-prediction-with-text-and-interpretability-bd3d57af34b1?source=collection_archive---------18-----------------------

行业笔记

预测客户是否想要离开,并了解客户为什么想要离开。

由丹尼尔·赫克特,泰勒·马伦巴赫

这篇博文附带的代码库可以在这里找到。

客户流失,即当前客户的流失,是许多公司面临的问题。当试图留住客户时,将精力集中在更有可能离开的客户上符合公司的最佳利益,但公司需要一种方法来在客户决定离开之前发现他们。容易流失的用户通常会在用户行为和客户支持聊天日志中留下他们倾向的线索,使用自然语言处理(NLP)工具可以检测和理解这些线索。

在这里,我们演示了如何构建一个利用文本和结构化数据(数字和分类)的客户流失预测模型,我们称之为双模态模型架构。我们使用 Amazon SageMaker 来准备、构建和训练模型。发现可能流失的客户只是战斗的一部分,找到根本原因是实际解决问题的重要部分。由于我们不仅对客户流失的可能性感兴趣,而且对驱动因素也感兴趣,因此我们通过分析文本和非文本输入的特征重要性来补充预测模型。这个帖子的代码可以在这里找到。

在这个解决方案中,我们重点关注 Amazon SageMaker,它用于准备数据、训练流失预测模型,以及评估和解释训练好的模型。我们使用 Amazon SageMaker 来存储训练数据和模型工件,使用 Amazon CloudWatch 来记录数据准备和模型训练输出(图 1)。

图 1:包含 AWS 服务的架构图

与线性回归等更简单的模型相比,最先进的自然语言模型更难解释。尽管它们的性能一流,但可解释性问题会阻碍业务的采用。在这篇文章中,我们展示了一些从 NLP 模型中提取理解的方法。我们使用 BERT 句子编码器[2][3]来处理文本输入,并提供了一种将模型预测归因于输入特征的方法。虽然有不同的方法来解释语言模型,但我们选择对相关关键字子集进行消融分析,这可以很容易地扩展到整个数据集,从而为我们提供对语言模型预测的全局解释。

探索和准备数据

为了模拟分类和文本流失数据集,我们利用了结构化数据的 Kaggle:客户流失预测 2020 ,并将其与使用 GPT-2 [1]创建的合成文本数据集相结合。数据集由 21 列组成,其特征包括分类特征(州、国际计划、语音邮件计划)、数字特征(账户长度、区号等)。),以及一个包含文本的列,用于保存由 GPT-2 生成的客户和代理之间的聊天日志。

下图显示了数据的摘录。

为了准备用于建模的数据,我们使用一键编码将分类特征值转换成数字形式,并用相应的平均值来估算缺失的数字特征值。由于这篇文章的重点是预测和解释语言模型,我们不会花更多的时间来探索或研究分类和数字特征。相反,我们将把我们的重点放在客户代理的互动上。

如前所述,聊天记录是由 GPT-2 使用一组手动创建的客户代理对话样本生成的。以下是 GPT-2 产生的客户-代理对话的摘录。

虽然新 GPT 协议生成的对话比实际对话的广度小,并且(如上所述)有时不能完全理解,但我们相信,代替公共客户-代理数据集,这种生成的数据是获得关于流失的大型客户-代理交互数据集的合理方式。

我们在 Amazon SageMaker 上准备文本特征,通过使用来自拥抱人脸模型存储库的预训练句子-BERT 编码器(SBERT)将每个聊天日志转换为向量表示[4]。拥抱脸库提供了开源的、经过预训练的自然语言模型,可以用来对文本进行编码,而不需要对模型进行任何进一步的训练。SBERT 是预训练的 BERT 网络的修改,其使用以下网络架构来导出语义上有意义的句子嵌入。

在应用汇集操作以生成每个输入句子的固定大小的句子嵌入之前,使用彼此独立的 BERT 对一对句子进行编码。作为双折叠结构的一部分,通过更新权重对 BERT 进行微调,使得生成的句子嵌入在语义上有意义,并且可以与余弦相似度进行比较。

使用包括分类和回归在内的目标组合来训练 SBERT。为了对两个句子之间的关系进行分类的目的(图 2a),在将句子嵌入传递到分类层之前,通过计算元素方面的差异并将它们乘以可训练的权重来连接句子嵌入。对于回归目标(图 2b),计算两个句子嵌入之间的余弦相似度。

图 2:带有(a)分类目标函数和(b)回归目标函数的 SBERT 架构的例子

使用 SBERT 优于其他嵌入技术(如 InferSent,Universal sent Encoder)的好处是,它更高效,在大多数语义相似性任务中取得更好的结果[3]。

因为 BERT 是为编码单词片段而构建的,所以我们的文本数据几乎不需要预处理。我们可以直接把每个聊天记录转换成 768 维的语义有意义的嵌入向量。

将上述预处理步骤应用于所有分类、数字和文本特征导致数据现在以数字形式被编码,因此它可以被我们的神经网络处理。

创建双模态 ML 模型

该网络架构包括三个全连接层和用于二进制分类的 Sigmoid 激活函数(搅动/无搅动)。首先,编码的分类/数字数据在与编码的文本数据连接之前被送入全连接层。然后,在应用用于二进制分类的 Sigmoid 激活之前,连接的数据被馈送到第二和第三全连接层。第一个全连接层用于减少稀疏分类/数字输入数据的维度(参见下文的更多细节)。第二和第三全连接层充当编码数据的解码器,以便将输入分类为抖动/无抖动。我们称该架构为双模态,因为它将结构化和非结构化数据(即分类/数字和文本数据)作为输入,以便生成预测。

下图(图 3)展示了该模型的双模式架构。

图 3:使用结构化数据和文本作为输入的双模态模型架构

正如上一节所讨论的,分类数据已经使用 one-hot-encoding 转换为数值,其中每个特征的类别由单独列中的二进制值表示。当有许多类别时,这导致结果编码数据的稀疏性(许多零),如具有 51 个类别(包括哥伦比亚特区)的特征“州”。此外,通过输入数字特征的缺失值而创建的指示符列也有助于编码数据的稀疏性。第一个全连接层用于减少这种稀疏性,从而产生更有效的模型训练。

我们使用亚马逊 SageMaker 上的 SGD(随机梯度下降)优化器和 BCE(二元交叉熵)损失函数来训练该模型,并在大约 8-10 个时期后在测试数据集上实现了 0.98 AUC 的性能。作为比较,仅用分类和数字数据训练模型实现了 0.93 AUC 的性能,或者比使用文本数据时低约 5%(图 4)。由于具有文本数据的模型具有更多用于做出决策的信息,因此可以预期具有真实数据的类似改进。

图 4:仅用分类/数字数据以及分类/数字数据和文本训练的模型的 PR 曲线[图片由作者提供]

重要特征

然而,为了防止客户流失,仅仅知道流失事件发生的可能性是不够的。此外,我们需要找出驱动因素,以便采取预防措施。

分类和数字特征

我们将使用经过训练的神经网络的预测标签作为目标值,在分类和数值数据上训练 XGBoost 模型[5],以找出哪些分类/数值特征对我们的模型的预测贡献最大。相对特性重要性的内置方法允许我们获得最重要特性的概述,如图 5 所示。

图 5:十大最重要的分类和数字特征[图片由作者提供]

从上图中,我们可以看到,决定客户是否会流失的前三个特征包括 vmail 消息的数量、客户服务电话的数量以及没有国际计划(x2_no)。特征 x0_xx 指示状态。

文字特征

现在让我们把注意力集中在客户-代理对话上,并尝试把模型的预测归因于它的文本输入特征。虽然存在不同的方法来解释自然语言的深度学习模型,但它们的主要焦点似乎是单独解释每个预测。例如,Captum 库[6]实现了基于梯度或 SHAP 值的技术,用于评估文本序列中的每个标记/单词。虽然这些方法在局部级别上提供了可解释性,但它们不容易扩展到整个数据集,从而限制了它们对训练模型预测的全局解释的使用。

我们使用 SBERT 编码的文本特征来解释训练模型的方法对于本地可解释性(单个聊天日志)和全局可解释性(整个数据集)都很有效,它可以有效地扩展,并且由我们在 Amazon SageMaker 上执行的以下步骤组成。我们首先使用词性(POS)标记和语义相似性匹配将文本子集化为关键词,以进行搅动。然后,我们执行消融分析,以确定每个关键词对模型预测的边际贡献。最后,我们将语义相似性、边际贡献以及关键字频率组合成一个单一的分数,这允许我们对关键字进行排序,并提供最相关的关键字进行流失。

下面的流程图(图 6)说明了我们提取关键字的方法:

图 6:描述寻找重要特性的文本转换的流程图。步骤 1:通过应用词类过滤、小写和词条化获得候选关键词。第二步:通过应用关键词的语义相似度匹配来获得相关关键词,从而进行流失。步骤 3:通过消融分析计算关键词的边际贡献。带圆圈的区域(红色)表示在移除标记 cancel 后模型的流失预测减少[图片由作者提供]

该方法从原始文本对话开始;我们通过关注候选关键字的子集来减少文本正文的大小,我们通过应用几个令牌过滤器来获得候选关键字的子集,如图 6 的步骤 1 所示。我们应用 Spacy 的词性标注,只保留形容词、动词和名词[7]。然后,我们删除停用词,小写,并 lemmatize 的令牌。

接下来,我们将候选关键词按照与两个类别结果的语义相似度进行排序,这里我们将重点关注流失(图 6,步骤 2)。具体来说,我们使用预先训练的 SBERT 对每个关键字进行编码,并计算每个关键字与所有 SBERT 编码的聊天日志的平均嵌入的余弦相似性,从而导致客户流失。这允许我们通过与客户流失的相似性对关键字进行排序,这进一步将关键字子集减少为与客户流失相关的关键字子集。从上图中你可以看到,通过语义相似度对关键词进行排名已经让我们对为什么客户会产生兴趣有了重要的了解。包括“取消”、“沮丧”或“不开心”在内的许多关键词都表示负面情绪。

除了与流失的语义相似性之外,我们希望通过测量关键字对模型预测的边际贡献来进一步量化关键字的影响(图 6,步骤 3)。我们嵌入包含和不包含相关关键字的聊天日志(在它们出现的地方),并测量平均预测差异。例如,关键字 cancel 在所有客户流失聊天日志中出现了 171 次,删除它会导致模型的客户流失预测在 171 个实例中平均减少 4.18%。

最后,我们将语义相似性、边际贡献和关键字频率这三个分数合并成一个联合度量,以实现重要关键字的最终排名。通过将单个指标设置为相同的比例(通过范围限制的最小/最大比例器)并计算加权平均值来计算联合指标。

结果

下表(图 7)显示了预测客户流失的 20 个最重要的关键词。它们包括“语音邮件”、“取消”、“垃圾邮件”、“营业额”、“沮丧”和“不高兴”,表明客户满意度低或其他问题。

图 7:预测客户流失最重要的 20 个关键词的表格

为了提供关于关键字的更多上下文,并帮助更好地解释客户流失事件,我们添加了一个功能来查询在客户-代理对话中使用关键字的短语。例如,当顾客抱怨被“大量的电子邮件和电话,成千上万的假发票垃圾邮件”淹没时,就使用了关键词“垃圾邮件”提到垃圾邮件的原始聊天记录:

“我昨晚刚收到一些垃圾短信,今天一直收到很多短信,说我‘没有 SIM 卡’,我需要我的 SIM 卡。”

“电信公司开始用电子邮件和电话淹没我,给我发来数以千计的假发票。”

“基本上,我每天都会接到很多垃圾电话,都是一个叫迈克尔的家伙打来的,他的电话号码很奇怪。”

理解关键词及其上下文将使我们能够采取措施解决客户流失问题。例如,一些客户似乎受到大量垃圾电话的困扰,因此决定离开这项服务。我们可以设计一个计划来减少垃圾电话的问题,从而降低客户流失率。

或者,我们可以通过将不同的关键字或短语分类到不同的主题中来获得更多的洞察力,并基于这些主题制定行动。然而,考虑到我们的合成数据集具有相当窄的对话主题的性质,我们发现它对我们的情况没有帮助。

结论

在这篇文章中,我们展示了如何将基于客户代理交互的文本数据与传统的客户账户数据相结合,从而提高预测客户流失的性能。此外,我们引入了一种方法,使我们能够从文本中学习洞察力,特别是哪些关键词最能表明客户流失。鉴于我们对语言模型的全局可解释性的关注,我们的方法有效地扩展到整个数据集,这意味着我们能够理解所有客户代理对话中流失的主要驱动因素。所有数据转换步骤,以及模型训练、评估和解释步骤都在 Amazon SageMaker 上执行。

参考文献:

[1] 语言模型是无监督的多任务学习器,,吴等。艾尔。, 2019

[2] BERT:用于语言理解的深度双向转换器的预训练,Devlin,Chang 等,2019

[3] 句子-BERT:使用连体 BERT 网络的句子嵌入,Reimers,Gurevych,2019

【4】拥抱脸句子变形金刚

[5] XGBoost 型号

[6] 模型可解释性的 Captum 库

[7] 用于文本处理的空间库

基于客户旅程的市场细分

原文:https://towardsdatascience.com/customer-journey-based-segmentation-for-marketplaces-70e5a56838a7?source=collection_archive---------17-----------------------

由 Margarida CSilva 在 Unsplash 上拍摄的照片

介绍

很有可能你偶尔会碰到一个叫做‘了解你的观众’的概念。这是大多数企业用来识别不同客户群及其各自需求的重要方法。这个概念对企业的重要性在于能够更好地理解和接触客户。这使得企业能够以更有效和个性化的方式向客户提供其内容和信息。

这一概念让企业有机会从“一刀切”转向更加以客户为中心的战略。

客户细分是一个常用的广义术语,用于将“了解你的受众”的概念应用到电子商务中。有数十种不同的方法可以做到这一点,在本文中,我们将与您分享我们基于客户旅程分析对 eCG(易贝分类集团)市场进行客户细分的方法。

文章的其余部分将遵循下面的大纲:

问题定义

  • 我们试图完成什么?
  • 主要目标是什么?
  • 这个分析是针对哪个用户群做的?
  • 该模型是为哪个 eCG 市场品牌开发的?

数据探索

  • 客户之旅概述
  • 观众特征的简短描述
  • 回复功能的简短描述
  • 确定分析的时间段

方法论

  • K-均值聚类的假设
  • 第一步:剔除异常值
  • 步骤 2:数据重新缩放
  • 步骤 3:为维度赋予权重
  • 第四步:K 均值聚类

结果

  • 观众群的简短描述和指示器
  • 回复群集的简短描述和指示器
  • 详细的集群和集群之间的过渡

结论

问题定义

我们试图完成什么?

在这个项目中,我们希望根据用户当前的客户旅程阶段,将他们分成更小的群体。因此,需要回答的主要问题是‘我们能否在我们的市场平台上清楚地识别完整用户体验的有意义的旅程阶段?’ 这样,我们将能够定义一些与我们的平台具有不同参与度的用户群。

主要目标是什么?

这个项目的最终目标是能够针对我们的用户在平台上的不同现状。换句话说:“个性化目标”。在这一模式的帮助下,我们将有机会相应地区分我们的客户定位策略,从而对我们的用户更加有效,并增加平台上的活跃用户数量。

这个分析是针对哪个用户群做的?

在这个阶段,我们问自己的问题是,我们应该支持买方还是卖方。买家是那些在平台上寻找产品进行购买的人,而卖家则是通过发布新的列表来销售他们的产品。由于买家在市场平台上创建的用户操作(如查看商品、保存商品或向用户发送消息)的数量远远超过卖家,我们决定仅对买家进行客户旅程分析。也有一种方法可以为卖家做类似的分析,但是现在,我们只关注买家,只是为了简单和高效。因此,在文章的其余部分,有时我们会使用“买家之旅”这一短语来指代该问题。

在市场平台中,主要有两种不同的用户类型:B2C(经销商)和 C2C(个人)。经销商是我们平台上发布广告的主要来源,他们占我们卖家的很大一部分。因此,我们决定将所有经销商排除在此分析之外,因为将他们归入购买者旅程阶段没有任何意义。为了防止分析受到经销商数据的误导,我们只对 C2C 用户进行了全面的分析。

该模型是为哪个 eCG 市场品牌开发的?

Ebay 分类集团(eCG)是一家伞式公司,目前在全球运营 14 个不同的分类平台。eCG 品牌下有两种不同的平台类型:水平和垂直市场。横向市场是指由许多不同类别组成的平台,如我们的荷兰租户“Marktplaats”。然而,eCG 中的垂直指的是用于特定产品类别的平台:汽车。

这个项目是为 eCG 的垂直平台之一开发的: Kijiji Autos 是加拿大领先的市场品牌,人们可以在这里购买或出售汽车。

数据探索

客户之旅概述

在易贝这样的电子商务平台上,我们知道用户的交易或购买情况,客户之旅大多从注册开始,以购买产品结束。出于这个原因,这些旅程通常被称为这些企业的“购买漏斗”或“转换漏斗”。然而,在我们的分类业务中,事情并不是那么明确。因此,我们需要更细致地处理这个问题,尤其是在项目的第一步:定义因素——特征——这些因素将在项目的后续步骤中用于形成不同的客户旅程阶段。

在探索阶段,我们发现市场平台上的 C2C 用户主要有两个不同的群体:浏览者和回复者。

浏览者:最近没有回复列表但只是浏览我们平台的用户。

回复者:最近回复过至少一个列表的用户。

我们首先将所有用户分成两个用户子组的主要原因是,他们表现出不同的客户行为特征。对于最近没有回复的用户——浏览者,我们只能跟踪他们在平台上的浏览行为,而我们更喜欢关注他们过去的信息行为,而不是浏览回复者。

以下是分别为查看者和回复者提取的特征列表:

两个不同用户群的功能列表:查看者-无回复和回复者-有回复(图片由作者提供)

观众特征的简短描述

自上次广告查看以来的天数:自用户上次在平台上查看列表以来的天数。

访问天数:用户访问平台的不同天数。

不同广告视图的数量:用户查看的不同列表的数量

喜欢的广告数量:用户保存的列表数量

对特定广告的兴趣:用户访问的最常查看列表的天数与该用户的总访问天数的比率。

对一组广告的兴趣:用户查看的不同列表的数量与该用户查看的列表总数的比率。

回复功能的简短描述

自上次回复后的天数:自上次用户回复平台上的卖家后的天数。

对话次数:与不同卖家的对话次数。

回复天数:用户回复平台卖家的天数。

在特定广告上花费的最大天数:用户对同一列表回复卖家的最大天数。

喜爱的广告数量:用户保存的列表数量

平均对话长度:用户回复的总次数与用户进行的对话次数的比率。

最长对话中的回复数:最长对话中发送给卖家的消息数

确定分析的时间段

在从数据中提取任何用户行为特征之前,我们需要为这个过程设定一个时间框架。这是因为只有相对最近的用户行为才能对用户的当前客户旅程阶段产生影响。正如您从上图中看到的,对于我们的案例,这个时间段是 60 天,这是一个迭代过程的结果,如下图所示。

迭代时间周期确定(图片由作者提供)

整个过程从提取用户最近 X 天在平台上的行为开始,然后我们相应地生成聚类,并在最后一步评估这些最终聚类的质量。这个迭代过程一直持续下去,直到我们以最好的历史时间段结束,在我们的例子中是 60 天。

方法学

由于我们的数据中没有任何预定义的用户旅程阶段,我们将我们的细分问题视为无监督学习:聚类。我们只知道用户过去在平台上的行为,但有多少有意义的客户旅程阶段(集群)仍是一个有待该分析回答的开放性问题。实际上,这是聚类分析的优点和挑战。你会发现一些新的东西,可能会对你的业务有所帮助,但你也必须解决一个有许多未知的问题。

虽然大多数数据科学家可能认为聚类分析没有挑战性,但事实上,如果你错过了几个关键点,就很容易犯很多基本错误。无论您使用哪种算法,您都应该考虑在聚类算法背后的一些假设。因为我们选择了“K-Means”算法来解决我们的聚类问题,所以我将专门研究该算法的假设,并在本文的其余部分逐一讨论我们是如何处理这些假设的。

在谈论这些假设和它们各自的补救措施之前,让我们花点时间提一下我们在整个项目中使用的技术堆栈。

  • 上一步:特征提取→ SparkSQL 和 Spark 的 DataFrame API。
  • 以下步骤 →通过汽水包在 Spark 上运行不同的 H2O 算法。

如果你还没有尝试在 Spark 上使用 H2O,你应该给它一个机会,因为我相信一旦你意识到这些 H2O 算法与 SparkML 包中的对应算法相比有多快,你就会喜欢上它。

K-均值聚类的假设

  • 集群在空间上被分组或称为“球形”
  • 集群具有相似的大小

由于 K-Means 试图优化聚类内的平方和,它可能对异常值非常敏感。换句话说,数据中异常值的存在可能会偏离聚类中心,并最终扭曲聚类的形成。因此,在对数据应用 k-means 算法之前,必须去除异常值。

第一步:剔除异常值

隔离森林算法已被用于从数据中移除异常值。讨论算法的细节超出了本文的范围,但是我们想简单地提一下背后的逻辑。

隔离林基本上是一个带有随机拆分的随机林,而不是选择每个节点拆分的最佳候选功能。这是一种无监督的异常检测方法,就像我们的情况一样。它从构建多个决策树开始,这样树就可以将观察结果隔离在它们的叶子中。由于异常值对于某些特征来说具有极值,因此与其他观测值相比,隔离这些异常值会更容易、更快。换句话说,它们在树上的树枝往往比其他树枝短。因此,通过对每一次观察取树中节点分裂的平均数,我们得到分数,其中观察需要的分裂越少,它越有可能是异常的。

类似于随机森林,我们也有参数,如树的数量,树的高度或抽样率进行调整。然而,我们有一个特定于隔离林的额外参数,用于指示数据中异常值的总体比率:“污染率”。这决定了分数宣布观察异常与否的分界点。

在下图中,您将看到异常值移除过程对我们数据空间中观察值分布的影响。我们的数据空间是多维的,但我们应用主成分分析(PCA)将维数减少到 3,以便可视化,使我们能够在笛卡尔坐标系中显示数据点。在从数据中剔除这些异常值之前,几乎所有的数据点都彼此紧密靠近,因此不适合进行聚类分析。然而,正如你从右边的图中看到的,在处理之后,观察值在坐标系上更均匀或更不密集。

异常值去除:PCA 图之前-之后(图片由作者提供)

步骤 2:数据重新缩放

由于 K-Means 是一种空间算法,它使用距离度量来确定两个观测值之间的接近程度,因此均值归一化对于均衡每个维度对聚类形成的影响非常重要。

建议在移除异常值之前重新调整数据比例,因为如果应用线性异常值检测,任何比其他维度比例大得多的维度都可能支配和否决其他维度。然而,由于我们使用隔离林来捕捉那些异常,所以在我们的例子中没有这样的限制。我们重新调整数据只是为了消除维度的影响,并为下一步做好准备:给维度赋予权重

步骤 3:为维度赋予权重

当处理任何集群问题时,在制定方法时,您应该始终考虑您的业务假设。对于聚类算法来说,事情并不总是简单明了的,您可能希望根据自己的需求和假设来调整它。

K-Means 算法被设计成在生成聚类时所有维度都同等重要,但这并不总是理想的情况。在我们的例子中,我们想给一些维度更多的权重,以增加它们的重要性和对集群形成的影响。

对于观众,我们将下列维度的权重加倍:

  • 自上次广告查看以来的天数
  • 探访天数
  • 不同广告浏览量

对于复制器,我们将下列尺寸的重量加倍:

  • 自上次回复以来的天数
  • 对话数量
  • 最长对话中的回复数

在下图中,您可以看到在对维度应用不同权重的步骤之前和之后,2d 坐标系中观察值分布之间的差异。很明显,该步骤对簇的形成有很大影响。

加权尺寸:前-后 PCA 图(图片由作者提供)

第四步:K 均值聚类

在我们完成了加权维度后,下一步是在这些数据上应用 k-means 算法。由于我们对客户旅程的可能阶段一无所知,这是我们应该确定最佳集群数量或不同旅程阶段的地方。找到最佳聚类数的方法是肘分析。我们将使 K-Means 算法适合一组不同数量的聚类,并通过查看聚类间距离平方和来评估这些聚类的质量。

我们对两个主要的用户群分别进行分析:查看者和回复者,如下图所示。在第一个图中,我们以总共 3 个集群结束——正如肘部功能所暗示的,观众的旅程阶段。然而,我们总共有 4 个聚类,作为对回复者的肘形分析的结果,如右图所示。

肘分析和 2D——观众和回帖者最佳聚类的表示(图片由作者提供)

下面,您可以找到一个详细的大图,它总结了整个项目过程中采取的所有步骤,从将我们的用户群划分为两个主要用户组开始,直到以集群结束—客户旅程阶段。

整条管道的大图(图片由作者提供)

结果

在找出了查看者和回复者这两个用户群的最佳聚类数后,我们根据每个聚类的质心的不同维数,给每个聚类取了一个有意义的代表名。

首先,让我们仔细看看下表中给出的星团的质心。我们通过解释不同维度上的簇形心值得出了簇的名称。我们通过在表格中的单元格周围放置红色边框来指示集群中的决定性维度。

检查完质心后,我们强烈建议您通读下面部分中对集群的简短描述和指示器,以便更清楚地了解这些集群名称背后的基本原理。

聚类质心的维度值(图片由作者提供)

观众群的简短描述和指示器

1-客户流失:他们很久以前就不再访问我们的平台了。

  • 查看者中最大“自上次广告查看后天数”

他们仍然会访问我们的平台,但不那么活跃了。

  • 一般来说,任何维度都没有极值

3-潜在回答者:目前,他们积极访问我们的平台。这群用户最有可能开始与卖家对话。

  • 观众中“自上次观看广告后的最短天数”
  • 查看者中不同广告查看次数的最大值
  • 观众最喜欢的广告数量

回复群集的简短描述和指示器

1-失去兴趣:他们前阵子不回复房源了。最有可能的是,他们已经放弃了在平台上寻找汽车。

  • 回复者中的最大“自上次回复后的天数”

2-普通买家:目前,他们仍在与卖家进行一些对话,但不那么积极。

  • 一般来说,任何维度都没有极值

3-潜在买家:目前,他们正积极地与不同的卖家进行大量对话。这部分用户是最有可能买车的。

  • 回复者中最少的“自上次回复后的天数”
  • 回复者之间的最大“对话次数”
  • 回复者中的最大“回复天数”
  • 回复者中最大的“偏好广告数量”

4-已买:最近他们已经买了车,离开了我们的平台。

  • 回答者之间的最大“平均对话长度”
  • 回复者在特定广告上花费的最大“最大天数”
  • 回答者之间的最大“最长对话长度”

在下图中,您可以看到不同集群中用户数量的分布。

用户在旅程各阶段的分布(图片由作者提供)

详细的集群和集群之间的过渡

在集群生成之后,我们还想知道 7 天内集群之间的转换。要回答的问题是,在接下来的 7 天内,每个集群中有多少百分比的用户移动到任何其他集群。换句话说,我们测量有多少集群倾向于保持稳定状态。创建这些转换的另一个原因是对我们的集群生成过程进行健全性检查,以查看集群之间是否发生了任何意外或不可思议的转换。在下面的饼图中,您将看到 7 天内从该特定集群到其他集群的转换百分比。

观众群

搅动

  • 整个用户群的 36%
  • 过去 60 天没有回复(查看器)
  • 他们不久前甚至停止访问我们的平台。(最近一次访问:~40 天前)
  • 与其他旅程阶段相比,他们更倾向于停留在同一阶段(约 90%)

未来 7 天从流失旅程阶段的过渡分布(图片由作者提供)

浏览器

  • 整个用户群的 45%
  • 过去 60 天没有回复(查看器)
  • 他们仍然访问我们的平台,但不那么积极。(最近一次访问:~ 10 天)
  • 这些用户最有可能流失(7 天内的流失率:14%)
  • 在 7 天内,这些用户中只有 1.5%成为“潜在回复者”(下一阶段)

未来 7 天浏览器旅程阶段的过渡分布(图片由作者提供)

预期回答者

  • 占整个用户群的 6.7%
  • 过去 60 天没有回复(查看器)
  • 目前,他们积极访问我们的平台。
  • 这群用户最有可能开始与卖家对话。

未来 7 天预期回复者旅程阶段的过渡分布(图片由作者提供)

复制器簇

失去兴趣

  • 占整个用户群的 5.4 %
  • 在过去 60 天内,他们至少收到了 1 封回复(回复者)
  • 他们不久前停止回复广告。(上次回复:~45 天前)
  • 他们很容易成为流失用户。(一周内的流失率:~ 5.6 %)
  • 这些用户中有 6.8%在 7 天内再次成为“浏览者”(前一阶段)
  • 这些用户中只有 5.4%继续他们的购买之旅(下一阶段:普通买家)

未来 7 天从失去兴趣旅程阶段开始的过渡分布(图片由作者提供)

普通买家

  • 占整个用户群的 6.4%
  • 他们仍在与卖家进行一些对话,但不那么积极。
  • 购买过程中最活跃的用户群之一(25%的用户倾向于在 7 天内改变他们的阶段)
  • 这些用户中有 18.2%在 7 天内转向“失去兴趣”(前一阶段)
  • 这些用户中只有 5%继续他们的购买之旅(下一阶段:潜在买家或已购买者)

未来 7 天从普通买家旅程阶段的过渡分布(图片由作者提供)

潜在买家

  • 占整个用户群的 0.6%
  • 目前,他们正在积极地与卖家进行大量对话。
  • 最稳定的用户群之一(7 天后停留在同一阶段的比例:90%)
  • 这部分用户是最有可能买车的。(7 天内进入“买入”阶段的比率:2.4%)

未来 7 天潜在买家旅程阶段的过渡分布(图片由作者提供)

买了

  • 整个用户群的 1%
  • 他们已经买了一辆汽车
  • 最近离开了我们的平台(上次回复:~20 天前)
  • 这些用户在离开之前与卖家进行了最长时间的对话
  • 这些用户可能会暂时被排除在我们的活动之外

未来 7 天购买旅程阶段的过渡分布(图片由作者提供)

结论

在本文中,我们向您介绍了我们在项目中采取的步骤:基于客户旅程的市场细分。首先,我们从定义我们在整个分析中使用的维度——特征——开始。然后,我们谈到了 k-means 聚类的一些关键假设,并讨论了在我们的案例中我们是如何处理这些问题的。在那之后,我们也提到了我们是如何通过解释星团质心来得出这些星团名称的。在文章的结尾,我们深入探讨了集群的细节以及集群之间的转换是如何形成的。

本文的主要观点是,解决聚类问题可能很棘手,因此,在进行分析时,您最好记住一些关键点。我们希望你喜欢阅读这篇文章,并发现它是有用的。

作者签名

基于机器学习的顾客满意度预测

原文:https://towardsdatascience.com/customer-satisfaction-prediction-using-machine-learning-66240e032962?source=collection_archive---------3-----------------------

预测客户对从巴西电子商务网站 Olist 购物的满意度。

**This Article Includes:
1.Introduction
2.Business Problem
3.Problem Statement
4.Bussiness objectives and constraints
5.Machine Learning Formulation
   i Data Overview
   ii.Data Description
  iii.Machine Learning Problem
   iv.Performance Metrics
6.Exploratory Data Analysis(EDA)
      a.Data Cleaning and Deduplication
      b.High Level Statistics
      c.Univariate Analysis
      d.Bivariate Analysis
      e.Multivariate Analysis
      f.RFM Analysis
      g.Conclusion
7.Data Preprocessing and Feature Engineering
8.Model Selection 
9.Summary
10.Deployment
11.Improvements to Existing Approach
12.Future Work
13.Reference**

1。简介

近年来,随着互联网在世界不同地区的普及,电子商务领域正在迅速发展。这一行业正在重新定义全球商业活动,并在当今的日常生活中发挥着至关重要的作用。还观察到,消费者经常订购的主要商品类别是服装、杂货、家庭装修材料等,这些产品的比例在未来可能会显著增加。

总的来说,我们可以说电子商务是一种由互联网驱动的媒介,客户可以通过自己的设备(电脑、平板电脑或智能手机)访问在线商店进行浏览,并订购产品或服务。

例子-电子商务交易,包括书籍、杂货、音乐、飞机票和金融服务,如股票投资和网上银行。

电子商务主要有四种类型;这些如图 1 所示。

图 1 pari tosh Mahto 的电子商务图像类型

电子商务的主要优势是它每周 7 天、每天 24 小时都可以使用,在一个平台上可以买到更广泛的产品。缺点是有限的消费者服务,因为很难在线向消费者展示每个产品,交付产品需要时间。

机器学习可以在电子商务中发挥重要作用,如销售预测、预测消费者的下一个订单、评论预测、情感分析、产品推荐等。它还可以通过电子商务提供服务,如语音搜索、图像搜索、聊天机器人、店内体验(增强现实)等

2。业务问题

Olist 是巴西的一个电子商务网站,它提供了一个更好的平台,将商家及其产品与巴西的主要市场联系起来。Olist 于 2018 年 11 月在 Kaggle 上发布了这个数据集。

该数据集包含巴西多个市场 2016 年至 2018 年的 10 万份订单信息。其功能允许从多个维度查看订单:从订单状态、价格、付款和货运表现到客户位置、产品属性,最后是客户撰写的评论。还发布了将巴西邮政编码与经纬度坐标联系起来的地理位置数据集。

  • 这项业务是基于消费者、网店和卖家之间的互动。
  • 首先,消费者在 Olist 网站上下订单。Olist store 收到该订单后,会根据订单信息(如产品类别、地理位置、付款方式等)向卖家发送通知。
  • 在从卖方收到产品并在预计交付时间内交付给消费者之后。
  • 一旦客户收到产品,或者如果预计交付日期到期,客户将通过电子邮件获得一份满意度调查,他可以在其中给出购买体验的注释并写下一些评论。

Andre Sionek 的工作流程图,图片来源[https://www . ka ggle . com/andresionek/predicting-customer-satisfaction]

3。问题陈述

  • 对于给定的客户历史数据,预测下一个订单或购买的评论分数。
  • 这个问题陈述可以进一步修改,以预测从巴西电子商务网站 Olist 购买的客户满意度(正面或负面)。

4。业务目标和约束

  • 无延迟-延迟要求。
  • 模型的可解释性有助于理解客户的行为。

5。机器学习公式

这里,目标是根据给定的特征,如价格、商品描述、准时交付、交付状态等,预测给定订单的客户满意度得分。

给定的问题可以通过多类分类问题(预测分数[1,2,3,4,5])、二进制分类问题(0 为负 1 为正)或回归问题(用于预测分数)来解决

5.i 数据概述

**Source:-** https://www.kaggle.com/olistbr/brazilian-ecommerce **Uploaded In the Year : 2018
provided by : Olist Store**

为了更好地理解和组织,数据被分成多个数据集。

**Data is available in 9 csv files:
1\. olist_customers_dataset.csv (data)
2\. olist_geolocation_dataset.csv(geo_data)
3\. olist_order_items_dataset.csv(order_itemdata)
4\. olist_order_payments_dataset.csv(pay_data)
5\. olist_order_reviews_dataset.csv(rev_data)
6\. olist_orders_dataset.csv(orders)
7\. olist_products_dataset.csv(order_prddata)
8\. olist_sellers_dataset.csv(order_selldata)
9\. product_category_name_translation.csv(order_prd_catdata)**

Olist 商店的数据模式,图像源[https://www.kaggle.com/olistbr/brazilian-ecommerce

  • olist_orders_dataset 使用 order_id 和 customer_id 将每次购买的订单数据与其他数据关联起来。
  • olist_order_reviews_dataset 将订单数据表中每个订单的已标记审核数据标记为[1,2,3,4,5],其中 5 为最高,1 为最低。
  • 我们将使用大于 3 的评价作为正面评价,小于等于 3 的评价作为负面评价。
  • 数据将被相应地合并,以获得分析、特征选择和模型训练所需的最终数据。

5 .二、数据描述

列数和行数,每个列的名称为。csv 文件显示在此数据框中:

关于所有列/特征的描述如下所示:

5.3 .机器学习问题

上述问题可以公式化为二元分类问题,即对于给定的订单和消费者的购买数据,预测评论将是正面的还是负面的。

5 .四、绩效指标

  • 宏 f1-分数-
  • 混淆矩阵

6.探索性数据分析

就我们对业务问题的理解和对机器学习问题陈述的表述而言。我们还了解了数据集和大多数功能。现在,我们将对该数据集进行探索性数据分析,以获得对特征的更多了解。

我遵循的第一步是阅读所有。并检查了每个 csv 文件中的列及其数据类型。在这之后,所有的数据根据给定的数据模式被合并。此外,我执行了数据清理,并对数据集进行了不同的分析。

6.a 数据清理

  • 处理缺失值

合并后的最终数据有许多空值。最大数量的空值出现在对象数据类型的列**review_comment_message**中。类似于**order_approved_at** **order_delivered_carrier_date****order_delivered_customer_date**的列也是空值。这些丢失的值要么被替换,要么被丢弃。代码如下所示。

  • 重复数据删除

正如您可以观察到的重复行,如 order_id 为**82bce245b1c9148f8d19a55b9ff70644** 的行,所有的列都是相同的。我们可以去掉这几行,保留第一行。

5.b 高标签统计

合并、清理和重复数据删除后的最终数据具有以下特征-

合并后的数据有 32 列,并且具有诸如 order_status、payment_type、customer_state 和 product_ category _name_english 之类的分类特征。一个名为 review_comment_message 的列包含葡萄牙语文本数据。数字特征也很少。数字特征的描述如下所示-

我们可以从上表中观察到-

  • 订单的价格和运费。订单的最高价格为 6735,而最高运费约为 410 巴西雷亚尔。订单的平均价格约为 125 巴西雷亚尔,运费价值约为 20 巴西雷亚尔。最低价格为 0.85 巴西雷亚尔的订单已经完成。
  • 对于 payment_value,订单的最大支付值为 13664 巴西雷亚尔。此外,我们可以观察统计数据,如百分位值、平均值和标准偏差值、计数、最小值和其他数字特征的最大值。

相关矩阵-

图片由 Paritosh Mahto 提供

现在让我们观察目标变量,即审查分数,大于或等于 3 的分数被认为是 1(正),否则为 0(负)。从目标变量的分布来看,我们可以观察到 85.5%的评论是正面的,14.5%是负面的。由此,我们可以得出结论,给定的数据集是偏斜的或不平衡的。

图片由 Paritosh Mahto 提供

5.c 单变量分析

在这个电子商务数据集中,主要使用四种类型的支付方式,即信用卡、baleto、凭单和借记卡。

注:Baleto= =>Boleto bancáRio,简称 Boleto(英文:Ticket)是在巴西由 FEBRABAN 监管的一种支付方式,是银行巴西联合会的简称。它可以在任何银行、邮局、彩票代理和一些超市的自动柜员机、分支机构和网上银行支付,直到到期日。

图片由 Paritosh Mahto 提供

  • 从上面的图中,我们可以观察到大多数订单是使用信用卡支付的,第二常用的支付方式是 boleto。
  • 每种支付方式的百分比显示在饼状图中,该图显示在用户进行的所有支付中,75.9%的用户使用信用卡,19.9%的用户使用 baleto,3.2%的用户使用凭单和借记卡。

图片由 Paritosh Mahto 提供

我们可以从上面的帕累托图中观察到,96%的顾客使用了信用卡和 baleto。让我们看看这个特性是如何与我们的目标变量相关联的。

图片由 Paritosh Mahto 提供

我们可以从上面的叠加图中观察到,大多数使用信用卡的客户都给予了积极的评价。此外,对于 boleto、凭证和借记卡用户来说,也是一样的。由此,我们可以得出结论,这可能是我们对这个问题的重要的分类特征。

现在让我们对 customer_state 列进行单变量分析。该列包含相应 customer_id 的州代码。巴西地图上的州名和州代码如下所示。

巴西地图,图片来源[https://st4 . deposit photos . com/1374738/23094/v/950/deposit photos _ 230940566-stock-illustration-map-Brazil-divisions-States . jpg

巴西人口最多的三个州是圣保罗、米纳斯吉拉斯和里约热内卢,我们还可以从下图中观察到,66.6 %的订单来自这些州,这意味着大多数客户来自这些州。

图片由 Paritosh Mahto 提供

此外,从下面显示的每个州的评论堆积图中,我们可以得出结论,每个州的大多数消费者都给予了积极的评价。在 SP 州的 40800 条评论中,35791 条评论是正面的,而对于 RJ 州的 9968 条评论是正面的,评论总数为 12569 条。对于这个问题,消费者状态可能是我们的重要特征。

图片由 Paritosh Mahto 提供

众所周知,产品类别是这个行业的重要特征之一。为了了解最畅销的产品类别,我绘制了一个柱状图,如下所示

图片由 Paritosh Mahto 提供

我们可以观察到,2016-2018 年间,订购最多的产品分别来自床 _ 浴 _ 桌品类、健康美容、运动 _ 休闲。

在这个数据集中也有一些时间戳特征,如**order_purchase_timestamp****order_purchase_timestamp****order_approved_a**t**order_delivered_customer_date****order_estimated_delivery_date**等等。在提取了月、年、日、星期几等属性后,我对时间戳进行了单变量分析。给出的数据是 699 天的数据,收集数据的时间戳是**2016–10–04 09:43:32** - **2018–09–03 17:40:06**

图片由 Paritosh Mahto 提供

收到的订单总数的变化如上所示,2017 年收到的订单数达到最大值 11。还有,我们可以观察 Olist 从 201609 年到 201808 年的成长。基于从**order_purchase_timestamp** 中提取的属性对订单和评论的分析已经在中结束。

图片由 Paritosh Mahto 提供

  • 从标题为“每月总评论”的子图中,我们可以观察到,2016 年至 2018 年期间总评论中正面评论比例最高的是 2 月,即 9.8%。在 5 月和 7 月的总评论中,有超过 9.0%的评论是正面的。
  • 从标题为“按一天中的时间划分的总评论”的第二个子图中,我们可以得出这样的结论:在下午收到的订单数量最多,并且在那个时间给出的正面评论的百分比最高,即 32.8%。
  • 从标题为“一周中每一天的总评论数”的第三个子图中,我们可以得出这样的结论:周一收到的订单数量最多,当天和周二给出的正面评论百分比最高,即 13.9%。

对数字特征的单变量分析-

  • 每类产品价格分布

图片由 Paritosh Mahto 提供

  • 每类 frieght_value 的分布

图片由 Paritosh Mahto 提供

  • 每类产品高度的分布

图片由 Paritosh Mahto 提供

  • 每类产品的重量分布

图片由 Paritosh Mahto 提供

  • 上面的分布图显示了正类和负类的每个数字特征的分布。我们可以观察到,阳性和阴性类别的分布几乎完全重叠,这表明不可能仅根据这些特征对它们进行分类。

6.d 双变量分析

该数据集中有超过 10 个数值特征,但是从上面显示的相关矩阵中,我们可以观察到大多数特征是线性相关的。对于双变量分析,仅选择四个特征并绘制在散点图中。

  • 从标题分别为**Distribution of price vs freight_value per class****Distribution of price vs freight_value per class**的两个散点图中,我们可以观察到,很难根据这些散点图对评论做出任何评价,因为根据评论,数据点是不可分离的,这些是完全混合的数据。
  • 每类价格与运费价值的分布

图片由 Paritosh Mahto 提供

  • 每类价格与产品重量的分布

图片由 Paritosh Mahto 提供

  • 配对图

对于功能产品照片数量、产品名称长度、产品描述长度绘制了一个配对图,如下所示,因为这些功能与 review_score 列具有负相关值。基于评论,所有特征之间的散点图是完全混淆不可分的。我们可以说,这些特征没有一个对分类有帮助。

图片由 Paritosh Mahto 提供

6.e 多元分析

在多变量分析中,绘制了 2016 年至 2108 年之间的销售和订单演变。从图中我们可以观察到,2016 年和 2018 年之间的总销售额和每月订单总量存在相同的模式。

图片由 Paritosh Mahto 提供

6.f RFM 分析

对于给定的客户数据,我对这些数据进行了 RFM 分析。RFM 分析基本上是一种数据驱动的客户行为细分技术。RFM 代表近期、频率和货币价值。

**RFM stands for-
Recency — number of days since the last purchase****Frequency — number of transactions made over a given period****Monetary — the amount spent over a given period of time**

Python 代码计算最近,频率和货币-

创建 RFM 后的输出如下所示

要了解更多关于这种行为细分技术的信息,你可以访问这里

https://www.barilliance.com/rfm-analysis/#:~:text=RFM analysis is a data,much they've spent overall.

所有客户的分布最近、频率和货币如下所示。

图片由 Paritosh Mahto 提供

  • 从最近的第一张图中,我们可以观察到大多数用户在 Olist 上停留了很长时间,这是一件积极的事情,但订购频率较少。
  • 从第二个频率图来看,最多的交易或订单数小于 5。从第三张图中可以看出,在特定时期花费的最大金额似乎不到 1500 英镑左右。

客户行为细分的方形图如下所示。

图片由 Paritosh Mahto 提供

  • 根据为所有客户计算的 RFM 分数,我将客户分为 7 类:
'Can\'t Loose Them' ====  RMF_Score_s  ≥  9
'Champions' ==== 8 ≤ RMF_Score_s < 9
'Loyal' ==== 7 ≤ RMF_Score_s <8
'Needs Attention' ==== 6 ≤ RMF_Score_s <7
'Potential' ==== 5 ≤ RMF_Score_s < 6
'Promising' ==== 4 ≤ RMF_Score_s < 5 
'Require Activation' RMF_Score_s <4
  • 从上面的正方形图来看,最高百分比的客户位于类别潜力区域内。少数区域还标有蓝色刻度,显示需要更多关注的消费者的百分比,以便他们能够保留在列表中。
  • 我们可以使用 RMF 分数或 RMF 等级作为解决这个问题的特征。

在对数据进行合并、数据清洗和数据分析之后,我们将得到最终的数据,这些数据可以进一步用于预处理和特征提取。

6.g 结论

* The target variable/class-label is imbalanced.We should be carefull while choosing the performance metric of the models.* From the univariate analysis of payment_type we observed that 96 % of the user used credit card and boleto and concluded that this can be our important feature.* Also,from the univariate analysis of consumer_state we found that 42% of total consumers are from the SP(São Paulo), 12.9 % are from RJ(Rio de Janeiro) and 11.7 % are from MG(Minas Gerais).* After analyzing the product_category feature we observed that the most ordered products are from the bed_bath_table category, health beauty, and sports_leisure between 2016 and 2018\. The least ordered products are from security_and_services.* The different timestamps seem to be important features as many new features can be explored from these. we observed within 2016–18 the total number of orders received is increasing till 2017–11 and after that their a small decrement. from the month, day and time we observed the most number of orders are received in the month of Feb, on Monday and afternoon time.* The numerical features like price, payment_value, freight_value,product_height_cm,product_length_cm doesnot seems to be helpful for this classification problem as observed from univariate and bivarate analysis.Also we can say linear model like KNN, Naive Bayes might not work well.* RMF Analysis is also done to understand whether new features can be created from this or not and we found that one numerical feature or categorical feature can be extracted from this.

7.数据预处理和特征工程

在数据分析之后,我们开始了解不同的分类和数字特征。所有的分类特征似乎都经过了预处理,我们不需要对这些特征进行预处理。但是,还有一个名为 review_comment_message 的列包含文本数据。在这些数据特征化之前,我们必须进行文本预处理。

评论文本的预处理

因为我们有葡萄牙语的文本数据,所以在选择词干分析器、停用词以及替换和删除任何特殊字符或单词时,我们必须小心。我为此选择了**nltk**库,并使用**from nltk.corpus import stopwords** 导入了停用词,使用**RSLPStemmer()** 导入了 RSLP 蒸笼。

当我们用'nao_reveja'替换评论数据中的空值时,我们必须从停用词中删除像'não' & 'nem'这样的词。在此之后,我们必须删除或替换链接、货币符号、日期、数字、额外空格和制表符。预处理函数如下所示-

预处理前后的审查文本列如下所示-

  • 以前

  • 在...之后

文本数据的矢量化

现在,我们已经预处理了文本,为了转换这些文本数据,我使用 gensim 库中的 FastText,通过 TF-IDF 矢量器()将单词转换为矢量。tfidf 值给予最频繁出现的单词更大的权重。

代码片段如下所示-

用于加载快速文本模型(适用于 300 dim)

矢量函数:

在此之后,无用的特征将从最终数据中删除。被删除的列如下所示。

col= ['order_id',
 'customer_id',
 'order_purchase_timestamp',
 'order_approved_at',
 'order_delivered_customer_date',
 'order_estimated_delivery_date',
  'customer_unique_id',
 'order_item_id',
 'product_id',
 'seller_id',
 'shipping_limit_date',
 'order_purchase_month_name',
 'order_purchase_year_month',
 'order_purchase_date',
 'order_purchase_month_yr',
 'order_purchase_day',
 'order_purchase_dayofweek',
 'order_purchase_dayofweek_name',
 'order_purchase_hour',
'order_purchase_time_day','customer_city','customer_zip_code_prefix','product_category_name']

现在,我们有了经过预处理的文本数据、分类和数字特征的最终数据。我们可以使用from sklearn.model_selection import train_test_splitstratify=y分割数据,因为我们有不平衡的数据。我们还有尚未编码的分类特征。为了对分类特征进行编码,我使用了CountVectorizer(binary= True)函数,order_status 特征的编码如下所示。

数字特征也使用from sklearn.preprocessing import Normalizer进行缩放。使用from scipy.sparse import hstack堆叠所有矢量化的特征,以形成 X_train 和 X_test。

基线模型选择

我们有现有的矢量化特征,现在我们将构建几个基本模型,我们将选择一个作为基线模型。在此之后,我们将尝试通过添加新功能来改善基线,为了添加新功能,我将再次进行一些 EDA。使用的模型有随机模型、朴素贝叶斯模型和逻辑回归模型。输出分数和混淆矩阵如下所示。

  • 随机模型
**Train f1-score 0.42757018716907186
Test f1-score 0.4261466361217526**

图片由 Paritosh Mahto 提供

  • 朴素贝叶斯
**Train f1 score:  0.7424119484527338
Test f1 score:  0.7472580717762947**

图片由 Paritosh Mahto 提供

  • 逻辑回归
**Train f1 score:  0.8165306456031154
Test f1 score:  0.8062989397776499**

图片由 Paritosh Mahto 提供

逻辑回归模型的表现优于其他模型。选择逻辑回归模型作为基线模型。从训练和测试混淆矩阵中,我们可以观察到假阳性和假阴性值仍然很大。让我们尝试通过添加一些特征和通过特征选择方法来减少这些值。

特征工程

除了现有要素,数据中还添加了 16 个新要素。这些功能的详细信息如下所示。

添加新特征后,我们总共有 29 个数字特征和 5 个分类特征,以及文本数据(300 dim)。我们将再次运行选定的基线模型,即逻辑回归模型,并检查其输出。输出如下所示。

**Train f1 score:  0.8258929671475947
Test f1 score:  0.8167104393178897**

图片由 Paritosh Mahto 提供

我们得到了更好的训练和测试 f1 分数,但我们仍然有很高的 FP 和 FN 值。为了减少这些值并增加分数,我尝试使用Autoencoder Model 进行特征选择。

使用自动编码器模型的特征提取/选择

**Autoencoder**是一种神经网络,可用于学习原始数据的压缩(降维)表示。自动编码器由编码器和解码器子模型组成。编码器压缩输入,解码器试图从编码器提供的压缩版本中重建输入。训练后,保存编码器模型,丢弃解码器。

然后,编码器可以用作数据准备技术,以对原始数据执行特征提取,该原始数据可以用于训练不同的机器学习模型。来源-https://machine learning mastery . com/auto encoder-for-class ification/

该模型的架构如下所示。我使用了一个致密层,BatchNormalisation 层,leakyRelu 作为激活层。

图片由 Paritosh Mahto 提供

我运行了这个模型 10 个时期,在运行模型之后,我保存了编码器部分。

损失与时期图

图片由 Paritosh Mahto 提供

然后,从编码器模型中提取重要特征。

代码片段:

使用提取的特征再次运行基线模型。输出如下所示。

**Train f1 score:  0.8457608492913875
Test f1 score:  0.8117963347711852**

图片由 Paritosh Mahto 提供

f1 分数增加了,我们的 FP 和 FN 值也降低了。我们现在将运行不同的机器学习和深度学习模型,并为我们的问题选择最佳模型。

8.型号选择

模型选择是选择一个模型作为解决问题的最终模型的过程。正如我们已经看到的基线模型性能,现在为了提高分数,我们将尝试两种不同类型模型的模型选择过程(例如,逻辑回归、SVM、KNN、决策树、集成等)。)和配置有不同模型超参数(例如,SVM 中的不同内核)的相同类型的模型。

机器学习模型

我们从神经网络模型的不同分类模型开始。我们在本案例研究中试验的模型如下

  1. 逻辑回归
  2. 线性支持向量机
  3. 决策树分类器
  4. 随机森林分类器
  5. 增强分类器(XGBoost/light GBM/AdaBoost/CATBoost)
  6. 堆叠/投票集成技术

对于每个模型,我使用RandomizedSearchCV进行超参数调整。所有模型的最佳超参数输出汇总如下所示。

我们可以观察到基于测试 f1 的最佳模型——分数是 vot_hard 代码片段,输出如下所示。

所有模型的代码片段都可以在这里找到-

https://jovian.ai/paritosh/ml-models

深度学习模型

由于我们已经看到了不同的机器学习模型,现在我们将尝试不同的神经网络模型。我尝试了 5 种不同的模型,并使用这些模型形成深度学习堆叠模型。

模型-1

在模型-1 中,我建立了一个简单的模型,其中 5 个密集层作为隐藏层,1 个密集层作为输出层。在输出层,使用 sigmoid 作为激活函数。给定的输入是从编码器模型中提取的特征。我使用定制的 f1 分数指标来评估这些模型。

  • 模型建筑

图片由 Paritosh Mahto 提供

  • 纪元 Vs 损失图

图片由 Paritosh Mahto 提供

  • 输出
**Train f1_score: 0.8632763852422476
Test f1_score: 0.8218909906703276**

图片由 Paritosh Mahto 提供

型号 2

在 Model- 2 中,我使用了 4 个 CONV1D 层,2 个 MaxPooling1D 层,一个 dropout 层和一个 flatten 层作为隐藏层,1 个 dense 层作为输出层。在输出层,使用 sigmoid 作为激活函数。给定的输入是从编码器模型中提取的特征,但是具有重新成形的阵列。

  • 模型架构

图片由 Paritosh Mahto 提供

  • 时代 Vs 损失

图片由 Paritosh Mahto 提供

  • 输出
**Train f1_score: 0.8610270746182962 
Test f1_score: 0.8253479131333611**

图片由 Paritosh Mahto 提供

型号-3

在 Model -3 中,我使用了 LSTM 层、嵌入层、批处理标准化层、密集层、下降层和展平层来构建具有多个输入和一个输出的模型。输入数据解释如下。

  • Input _ seq _ total _ text _ data-我使用嵌入层为文本数据列获取单词向量。我还使用预定义的 fasttext 单词向量来创建嵌入矩阵。之后使用 LSTM,得到 LSTM 输出,并使输出变平。
  • Input_order_status- 给定 order_status 列作为嵌入层的输入,然后训练 Keras 嵌入层。
  • 付款类型- 给定付款类型列作为嵌入层的输入,并训练 Keras 嵌入层。
  • 输入客户状态- 给定客户状态列作为嵌入层的输入,并训练 Keras 嵌入层。
  • 输入产品类别- 给定产品类别列作为嵌入层的输入,并训练 Keras 嵌入层。
  • 输入 _rfm - 给定 RFM_Level 列作为嵌入层的输入,并训练 Keras 嵌入层。
  • 输入 _ 数字- 连接剩余的列,即数字特征,然后添加一个密集层。

所有这些都在最后连接起来,并通过不同的密集层。

  • 模型架构

图片由 Paritosh Mahto 提供

  • 历元 Vs 损失

图片由 Paritosh Mahto 提供

  • 输出
**Train f1_score: 0.860330602322043 
Test f1_score: 0.8327277576694923**

图片由 Paritosh Mahto 提供

型号 4

Model -4 也使用 LSTM 层、Conv1D、嵌入层、批处理标准化层、密集层、下降层和展平层来构建模型,但具有两个输入和一个输出。输入数据解释如下。

  • Input _ seq _ total _ text _ data-我使用嵌入层为文本数据列获取单词向量。我还使用预定义的快速文本单词向量来创建嵌入矩阵。之后使用 LSTM,得到 LSTM 输出,并使输出变平。
  • Other_than_text_data- 所有分类特征都被转换为一个独热编码向量,然后使用 np 与数字特征连接在一起。hstack
  • 模型架构

图片由 Paritosh Mahto 提供

  • 历元对损失

图片由 Paritosh Mahto 提供

  • 输出
**Train f1_score: 0.8815188513597205 
Test f1_score: 0.8218441232242646**

图片由 Paritosh Mahto 提供

型号-5

Model -5 还使用了 LSTM 层、Conv1D、嵌入层、批处理标准化层、密集层、下降层和展平层来构建模型,但具有两个输入和一个输出。输入数据与模型 4 相同。

  • 模型架构

图片由 Paritosh Mahto 提供

  • 历元 Vs 损失

图片由 Paritosh Mahto 提供

  • 输出
**Train f1_score: 0.8508463263785984
Test f1_score: 0.8287339894123904**

图片由 Paritosh Mahto 提供

深度学习堆叠模型

正如我们已经看到的 5 个深度学习模型,现在我们将使用一种集成方法,其中上述 5 个模型用作子模型,每个模型对组合预测的贡献相等,XGBClassifier 用作最终模型,即元模型。我们将构建两个堆叠模型,一个使用硬堆叠,另一个使用软堆叠,并将输出与上述模型的输出进行比较。构建硬件和堆栈的每个步骤的代码片段如下所示。

步骤 1 加载五个子模型

每个模型的第 2 步预测

步骤 3 堆叠预测并通过元分类器

  • 硬堆叠

输出:

图片由 Paritosh Mahto 提供

  • 软堆叠

输出:

图片由 Paritosh Mahto 提供

正如我们可以观察到的,两种堆叠模型的输出都比上述深度学习模型表现得更好。所有深度学习模型的代码片段都可以在这里找到—

https://jovian.ai/paritosh/dl-models-2

9.摘要

  • 从 EDA 中,我们得出结论,给定的数据集是偏斜的,并且具有相关值,我们已经看到大多数数字特征不是线性相关的,这意味着简单的 ml 分类可能不会很好地工作。
  • 评论数据是文本形式的,我们对这些数据进行了预处理,并且增加了新的功能,有助于提高分数。autoencoder 模型在特性选择和性能增强方面帮助更大。
  • 在模型选择部分,我们经历了不同的 ml 模型和 dl 模型性能。比较所有结果后,我们可以得出结论,该模型是一个深度学习堆叠模型,即软堆叠模型。现在我们将在部署过程中使用这个模型。

10.部署

使用 streamlit 和 Github 部署了最好的堆叠式深度学习模型。使用 streamlit uploader 函数,我创建了一个 CSV 文件输入部分,您可以在其中提供原始数据。之后,您必须选择唯一的客户 id 和相应的订单 id,预测将显示为图像。

网页链接-

https://share . streamlit . io/paritoshmahto 07/customer-satisfaction-prediction/main/app . py

部署视频-

11.对现有方法的改进

在现有方法中,使用两个回归模型和九个新特征来预测评论分数,得到 0.58 的 RMSE。在现有方法中,也不使用不同的模型,并且也使用有限的特征。在我们的方法中,我们采用了比现有方法更好的结果,并且我们使用了新的文本特征化方法以及用于特征选择的自动编码器模型,因此模型的性能得到了提高。

12.未来的工作

用不同的方法对葡萄牙文本数据进行矢量化可以改善结果。此外,可以添加新功能和调整 DL 模型的参数,以获得更好的结果。

我的 LinkedIn 个人资料

【https://www.linkedin.com/in/paritosh07/

我的 Github 个人资料

https://github.com/paritoshMahto07

13.参考

一、现有解决方案-

https://www.kaggle.com/andresionek/predicting-customer-satisfaction

二。数据分析和可视化-

https://www.kaggle.com/thiagopanini/e-commerce-sentiment-analysis-eda-viz-nlp

三。RFM 分析-

四。自动编码器模型

https://machinelearningmastery.com/autoencoder-for-classification/

动词 (verb 的缩写)堆叠 ML 模型

https://machinelearningmastery.com/stacking-ensemble-machine-learning-with-python/

不及物动词堆叠 DL 模型

https://machinelearningmastery.com/stacking-ensemble-for-deep-learning-neural-networks/

七。师徒制

https://www.appliedaicourse.com/

感谢阅读,祝你有美好的一天!🙂

分析中的客户科学

原文:https://towardsdatascience.com/customer-science-in-analytics-be05c67c898b?source=collection_archive---------21-----------------------

透视“小型企业”如何利用数据提高客户保持率

布莱克·维斯兹在 Unsplash 上的照片

客户科学一直是企业分析和数据科学领域的热门词汇。无论你从事什么行业,了解你的客户——她的动机、潜力和与她相关的风险——是至关重要的。这总是不容易的,尤其是当你不是基于订阅的模式时。让我从一个简单的小镇杂货商的角度出发,解释他如何提高对顾客的理解。

鲍勃在密苏里州堪萨斯城经营一家小杂货店,出售从薯片到化妆品的各种商品。).尽管 Bob 拥有相当稳固的忠诚度基础,但他感觉自己的份额正迅速被新推出的 Raider Poe 夺走。Bob 雇佣你来帮助他执行“客户科学”项目,并设计旨在改善客户关系的营销策略,而不是在邮箱中分发传单,这是一项基于直觉的活动(你的数据科学家应该将此理解为提高保留率、增加终身价值和发展客户 360 度)。

图片来源——由作者使用 PowerPoint 开发。

幸运的是,鲍勃在 2017 年推出了会员卡系统,因此你可以跟踪“谁在什么时候买了什么”他的卡系统很常见——每次你买东西时,你要么刷你的鲍勃的卡,要么告诉收银员它唯一的十位 ID,或者给你关联的电话号码,收银员会确保你的销售与你在鲍勃的账户关联。每次购物都会累积一些积分,你可以在以后兑换(通常是这样)。

想象一下,当她登录到自己的个人资料时,从亚马逊购物,而不是点击“作为客人继续结账”您运行了一些查询,发现 Bob 年收入的 50%以上来自购物时刷卡的人。这是一个很好的迹象,因为你的客户层面的分析可以影响超过 50%的销售。至于其他的,现在,我们什么也做不了。当你凌晨三点去奥兰多的沃尔玛买发胶时,你忘了使用你的会员卡。他们真的无法跟踪你的销售——如果你在销售过程中没有分享,就无法将它与你这个 Palmart 忠诚度会员联系起来。同样,亚马逊也不能在你作为客人结账时买了剃须刀后,给你发带有剃须刀刀片的脸书广告,因为你的电子邮件与购买没有关联。

斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上的照片

现在,有了过去三年客户层面 50%的忠诚度销售数字,您就可以开始您的项目渠道了

  1. 开发客户 360 度(首先了解他们)
  2. 客户维系(我应该尽快锁定谁),以及
  3. 终身价值(我可以优先考虑吗?)

客户 360

鲍勃希望你回答的问题是——这些人是谁?我可以看一下下面的一些指标并理解它们吗?

一些货币指标–

  • 每笔交易的平均购买金额
  • Bob 的总收入
  • 累积和兑换的积分
  • 购买的每件产品的平均价格
  • 平均折扣购买的商品百分比等。

频率度量

  • 每月的平均交易次数
  • 忠诚会员?(客户什么时候拿到 Bob 的卡的?)
  • 最近一次购买
  • 购买的平均间隔时间

项目偏好

  • 购物次数最多的类别 Lisa 来 Bob's 是为了购买啤酒和葡萄酒还是新鲜农产品,还是两者都有?
  • 最常光顾的品牌

这些只是几个指标,显示一个人可以从简单的交易数据中获得多少。在大型零售商的现实生活中,数据分析师正在查询大量数据,收集这些关于客户的重要而直接的信息。人们可以更有创造性地使用这些度量标准(小心行事——这里可能会有点复杂)。例如,如果你取一个客户所有访问的购买间隔,并尝试拟合一条回归线,这条线的斜率将表明她访问间隔随时间的变化。如果斜率为正,这意味着随着时间的推移,她在购物后花了更多的时间回到鲍勃的商店,这表明她可能在其他地方购买杂货或比她去鲍勃的商店的平均水平多进货。查看销售值的同一条回归线的斜率,可以了解实际情况。

展示了执行销售总结。使用 Qlik Sense Desktop 开发。图片来源-作者使用 Qlik Sense desktop 开发的仪表板快照。

现在,想象一下在客户层面创建一个数据库——包含数百个指标,以及这些指标如何帮助您为营销活动选择客户群。如果你想锁定有一段时间没有和你一起购物的客户,只需查询并提取那些最近(自上次购买后的天数)比他们的平均购买间隔更重要的客户。因此,如果丽莎平均每十天在鲍勃商店购物一次,而她已经来了 15 天了,给她发一封电子邮件,说“我们想念你”或“这里有 5 美元的折扣”。简单而有效。

现在,人们可以用这些指标做各种事情——暗示无监督的学习方法,如 Kmeans,分层聚类,让算法识别类似的客户群。或者使用降维技术(如主成分分析)来发现变量之间的潜在关系。

关于作者——Angel Das:高级分析专家和管理顾问,帮助公司通过对组织数据的业务、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 上推特

顾客细分:阿瓦托·贝塔斯曼项目

原文:https://towardsdatascience.com/customer-segmentation-arvato-bertelsmann-project-44e73210a1b7?source=collection_archive---------22-----------------------

一份简化的技术报告,解释我建立客户档案、通过人口统计数据锁定客户以及交流调查结果的解决方案

莎伦·麦卡琴的照片

了解一下你们公司的客户到底是谁怎么样?他们住在哪里?他们需要什么?他们是怎么想的?

更多地了解客户不仅有助于创造更多的个性化产品战略,还可以让公司在将行动导向正确的目标时节省资金和精力:那些最有可能转化为客户的人。

在这个项目中,Bertelsmann Arvato Analytics 提供了与德国一家邮购销售公司的普通人群和客户相关的人口统计数据。目标是执行客户细分,确定最能描述公司核心客户群的人群,以及营销活动的适当目标,优化公司的客户获取。

该项目的结构如下:

  • 数据概述和数据清理;
  • 探索性数据分析;
  • 无监督机器学习任务:聚类分析:
  • 客户细分报告;
  • 监督机器学习任务:为营销活动锁定客户。

1.数据概述

第一步包括了解普通人群和客户数据集的数据结构。包含一般人口统计数据的最大数据集由 891.221 个观察值(人)和 336 列(特征)组成。

图一。普通人群数据框中的第一行(图片由作者提供)

这些特征在五个主要的信息级别中与人口的不同方面相关:

  • 人物:包含与性别、财务和健康类型、社会地位、心灵契合度等相关的信息;
  • 家庭:呈现家庭人数、估计家庭收入、交易活动以及更多家庭方面的信息;
  • 微蜂窝:不同客串消费者分类,车主最常见年龄,最常见车厂,最常见车龄等。;
  • 宏小区:居民密度、距市中心距离、家庭住宅数量、最常见建筑类型等。;
  • 社区:居民,失业人口的比例,等等。

为了处理大量不同的功能,我们采用了以下策略:

  • 数据清理,拼接缺失未知值;
  • 删除超过为缺失值定义的阈值比率的列(将缺失值和未知值一起考虑);
  • 删除一些与分析无关的列;
  • 根据其表示处理列的类型
  • 特征工程师第 1 部分:将 CAMEO_INTL_2015PRAEGENDE _ jugendjhreALTER_HH 特征中包含的多种信息扩展为更具代表性和信息性的特征;
  • 相关性分析,删除信息相似的列,保留缺失值率较低的列。

在这些第一次过滤和变换之后,特征的数量减少到 218

图二。筛选后一般人群数据框中的前几行(图片由作者提供)

之后,对客户数据应用相同的过程。

2.探索性数据分析

有趣的部分开始了。在本节中,我们的目标是执行之前的分析,以指出可能的方向,特别是提取一些关于与一般人群相比的客户特征的见解。

几个问题引导了这个探索性数据分析任务:

  • 顾客多大了?
  • 他们住在哪里?
  • 作为消费者,他们是如何分类的?
  • 他们的收入如何?
  • 他们的消费习惯、生活方式、家庭构成是怎样的?

下面介绍了 EDA 的主要发现,这些发现有助于对客户的主要概况进行概述:

2.1 青年十年

图 3。对比顾客和普通人群的青春十年的柱状图(图片由作者提供)

青年十年是这个项目第一部分的特色之一。它表示一个人在哪个年代度过了他/她的青年时期,从与 40 岁相关的 4 到表示 90 岁的 9。

虽然年轻人在总人口中的比例更高,但在客户中却发生了相反的情况,这表明大多数邮购公司的客户往往由老年人代表。

2.2 青年运动

图 4。对比顾客和普通人群前卫运动发生率的条形图(图片由作者提供)

另一个设计特色是,前卫表明人们在年轻时参与了哪种运动:前卫主流。1 表示与前卫运动相关,0 表示与主流运动相关。

尽管在顾客中,前卫和主流的比例相当,但与普通人群相比,顾客群体中前卫的比例明显过高。

2.3 家庭状况

图 5。比较客户和普通人群家庭状况的条形图(图片由作者提供)

家庭状况专题讲述了 5 个不同的阶层:

  • 1 : 有钱人
  • 2 : 繁华
  • 3 : 舒服
  • 4 : 不太富裕
  • 5 : 更穷

虽然在一般人群中,较贫穷和不太富裕的家庭较为普遍,但在客户中,最常见的家庭是富裕富裕的家庭,这表明,尽管该公司向不同人群的客户伸出援手,但与富裕家庭相关的地位最为普遍。

2.4 家庭收入

图 6。比较客户和普通人群家庭收入的柱状图(图片由作者提供)

家庭收入代表:

  • 1 : 最高收益
  • 2 : 极高收益
  • 3 : 高收入
  • 4 : 平均收入
  • 5 : 低收入者
  • 6 : 收入很低

再一次,我们可以看到一个明显的高收入家庭的过度代表,加强了之前特征分析的观点。代表性不足恰恰发生在与低收入极低收入相关的阶层。

3.无监督 ML 任务:聚类分析

3.1 数据转换

为了将人口分组到不同的群集中,必须应用更多的变换,遵循以下过程:

  • 又开发了一个功能工程流程,这一次是在 CAMEO_DEU_2015 功能上,替换了它的 44 个值类,这些值在 0 到 3 的范围内表示它们在客户中的过度表现程度;
  • 数值变量缺失值被中值代替,防止异常值的影响;
  • 使用 pandas 的 get_dummies函数转换分类特征;因此,缺失值未被估算,并在分析中被间接考虑;
  • 在对缺失值进行处理后,使用scikit-learnstandard scaler对数据进行标准化
  • 一旦所有数据都在同一尺度上,就应用了降维技术( PCA )来减少特征的数量,并捕捉数据中最重要的方面。

在最后一步(降维)中,考虑了之前讨论的信息等级。假设是较低水平的信息包含更具体的信息,可以更好地解释群体之间的差异。

考虑到这一点,对于每个级别的信息,都应用了特定的 PCA ,从而产生了纯成分。换句话说,每一级信息被单独处理,而每一个组件只能代表一级信息

为了确定每个信息级别的组件数量,研究了解释的方差,优先考虑低级别:

图 7。Scree 剧情人物关卡(图片由作者提供)

人员级别,保持 60%的解释差异,产生 30 个组件

图 8。Scree Plot 家庭级(图片由作者提供)

家庭层面, 20 个组成部分可以解释大约 50%的数据差异。

图 9。Scree Plot 微单元级别(图片由作者提供)

微单元水平,选择的组件数量为 10 ,解释了超过 40%的差异。

图 10。Scree Plot 宏单元级别(图片由作者提供)

最后,在宏单元级别, 10 个组件解释了大约 40%的方差。

社区级别仅由的三个特征组成,正因为如此,不需要降维。

3.2 均值聚类

一旦数据准备好由 KMeans 算法处理,就使用肘方法来决定适当的聚类数。

图 11。肘法图(图片由作者提供)

由于没有清晰的弯头指示最佳集群数,因此观察到线倾斜。在 20 个集群的数量之前,倾向中最有表现力的变化发生。于是,决定继续进行 18 个星团的实验。

随着普通人群被分成 18 个不同的组,算法预测每个顾客的观察值属于哪个组。之后,可以比较普通人群和客户人群中的聚类分布。

图 12。比较客户和普通人群的聚类发生率的条形图(图片由作者提供)

这些是突出显示的集群,表示客户中代表过多的代表不足的群体:

图 13。代表人数过多和不足的组别(作者图片)

4.客户细分报告

在这个阶段,需要解释这些集群,这样我们就可以了解哪些配置文件更有可能成为公司的客户。为了解释每个聚类代表什么,聚类中心表示最重要的组件,这些组件与最重要的功能相关联,从而允许进行聚类描述。

4.1 任职人数过多的群组

4.1.1 绿色梦想家(集群#2)

Agnieszka Boeske 的照片

  • 他们的度假习惯可以归类为自然爱好者,已经强调绿色倾向是这个集群所代表的人群中存在的一个重要方面;
  • 绿色方面通过前卫方面得到加强,将这个群体与具有前卫思维的人联系起来,这也将他们与绿色前卫运动联系起来;
  • 他们似乎没有熟悉的头脑;
  • 这个群体主要代表了不是单身的,没有批判性思维,但是有梦想和社会意识的男人。

4.1.2 传统上流社会的长者(群组#9)

照片由拉维·帕特尔拍摄

  • 他们处于生命的高级阶段,表现为家庭或多人家庭,也与较高的收入有关;
  • 他们的社会地位可以分为独立者、房主和高收入者;
  • 他们不是梦想家,也不是面向多事的人,但他们可以表现为批判性和传统思想,以及宗教信仰;
  • 这个集群描述的是老年人。

4.1.3 空巢、满钱包(集群#2)

由 Toa Heftiba 拍摄的照片

  • 它主要代表中高收入夫妇;
  • 它也可以代表有房夫妇和高收入夫妇;
  • 第三个组成部分带来了之前看到的方面,传统思想,宗教,但不是面向事件的;
  • 可以说,以前看到的一些方面现在主要适用于不同年龄的高收入夫妇,也适用于成熟和高收入夫妇。

4.2 代表性不足的群组

4.2.1 新手少(集群#0)

邹蒙摄

  • 它代表可以被归类为不太富裕或较贫穷的人,主要指准家庭夫妇和单身或有孩子的年轻夫妇;
  • 他们的家庭收入可以被认为是较低或非常低的收入,他们的保险类型大多被归类为社会安全驱动型
  • 就健康和购物类型而言,他们可以被描述为卫生爱好者要求高的购物者
  • 微小区部分表示在 1994 年之前建造的、有两个或两个以上前业主的高护理率地区,从而形成了生活在较贫困地区的低收入人群的形象。

4.2.2 多代储蓄者(第 16 组)

安德烈·泰森的照片

  • 该集群描述了来自多人家庭的低收入和较高年龄的平均收入者,以及被归类为两代家庭的家庭;
  • 低收入或中等收入家庭的单身人士,以及来自多人家庭的较年轻的中等收入者也占了很大一部分。这个档案倾向于与住在西区的人有关;
  • 他们的财务类型被划分为低财务利息或存钱型。

4.2.3 二手车细胞(第 14 组)

尼古拉·贾斯特森拍摄的照片

  • 它代表可以被归类为不太富裕或较贫穷的人,主要指准家庭夫妇和单身或有孩子的年轻夫妇;
  • 微小区部分表示 1994 年以前建造的、有两个或两个以上的前业主的高护理率地区,造成了生活在贫困地区的低收入人群的形象;
  • 它还描述了家庭住房比例高、每户拥有汽车比例极低以及靠近市中心的地区;
  • 这些方面中的大多数已经在其他集群中被强调,但是在这种情况下,它似乎更强调微观和宏细胞方面,而不是与人相关的方面。

4.3 行动呼吁

虽然有一个清晰的轮廓表明特定人群更有可能成为公司的客户,但重要的是要强调这样一个事实,即当涉及到收入、年龄或社会阶层分析时,基本核心客户代表了人口中较小的一部分。

这也可以被视为该公司的一个巨大机会,一旦可以推出现有产品的不同和更简单的版本,例如,可以由低收入人群购买。

与此同时,也有可能接触到特别关注环保问题的年轻人,投资与这些新一代沟通的定向营销活动。他们有可能成为一辈子的顾客。

5.监督式营销任务:营销活动的目标客户

在这个项目的最后一部分,不同的方法被用来寻找预测一个人在面对营销活动时有多大可能做出反应的最佳模型。

主要序列包括:

  • 开发数据转换机器学习流水线,避免数据泄露
  • 在数据转换过程中测试不同的方法: PCAtruncated VDSMOTE 等等;
  • GridSearchCVBayesSearchCV 进行参数整定;
  • Kaggle 平台上对预测进行评分,以检查模型在未知数据上的表现。

5.1 评估指标

可以使用不同的度量来评估模型性能。在这个具体案例中,训练数据是呈现阶层失衡的典型案例。这意味着大多数观察结果对应于没有对营销活动做出响应的人。

在这种情况下,算法可能了解了其中一个类的很多信息,但却无法“理解”另一个类。因为我们对这两个类都同等关注,所以roc_auc分数显示为一个要使用的适当度量,因为它代表了真阳性率假阳性率之间的权衡。

5.2 学习曲线

学习曲线被评估为几个算法做出一个首选。在该分析中,梯度提升分类器是性能最好的一个。

图 14。学习曲线梯度推进分类器(图片由作者提供)

学习曲线呈现收敛,没有过度拟合的迹象。正因为如此,第一次尝试是基于这种机器学习算法。

基本转换后,数据管道包括:

  • 选择数字特征并用中值输入缺失值,之后将数据标准化到一个共同的尺度;
  • 分类特征中的缺失值用最常用值(可以解释为模式)进行插补,然后特征被一键编码
  • 具有缺失值的二进制特征遵循与分类特征相同的程序,没有缺失值的二进制特征不进行任何进一步的变换。

另一方面,机器学习管道包括:

  • 按照上述模式预处理测试集上的数据;
  • 训练通过 GridSearchCV 测试不同参数组合的算法;
  • 测试集上预测不同的交叉验证折叠;
  • 通过 roc_auc 分数评估模型,给出数据中显示的高级别不平衡;
  • 返回最佳模型。

5.3 第一种方法:梯度提升分类器+ GridSearchCV

在第一次尝试中,两个模型的参数是固定的:

  • learning_rate:设定为0.1
  • n_estimators:设定为 150

GridSeachCV 搜索三个参数的最佳组合:min_samples_splitmax_depthmax_features

图 15。梯度增强分类器的参数调整(图片由作者提供)

min_samples_split是指分割一个内部节点所需的最小样本数,这里测试了两个值( 24 )。

max_depth表示单个回归估计器的最大深度,限制树中节点的数量。 35 是这里测试的数值。

max_features指定寻找最佳分割时要考虑的特征数量。如果,所有特征都是要选择的候选,如果自动,模型限制可以选择的特征数量,在这种情况下,是特征总数的平方根。

考虑到这些参数和roc_auc得分,这是最佳组合:

图 16。梯度增强分类器的参数调整结果(图片由作者提供)

最后,这个模型被用来预测新的未知数据。在 Kaggle 平台上提交这些预测后,可以获得实际的模型分数。

第一个模型取得了合理的 roc_auc 分数 0.79488 。考虑到 Kaggle 排名,第一种方法被定位在前 150 车型中。

之后,为了改进第一个模型,测试了不同的方法。基本上,测试了不同的算法,包括 Ada Boost 分类器LightGBM 分类器,以及数据预处理流水线的一些变体。

在这些尝试中,有一个单一的模型克服了第一个。应用了相同的数据转换和机器学习管道。梯度增强分类器被 XGBoost 分类器取代,而 GridSearchCV 则给 BayesSearchCV 让出了空间。

5.4 最佳方法:XGBoost 分类器+ BayesSearchCV

GridSearchCV 组合不同的参数值以找到优化结果的组合时, BayesSeachCV 接收与每个参数相关的一系列值(整数实数分类)。

一旦发现一个改进,它会更深入地探索该区域以实现更高的改进。

图 17。XGBoost 分类器的参数调整(图片由作者提供)

在这种尝试中,之前没有固定任何参数。测试了 gb 三个内置助推器,以及两种不同的采油树方法:自动历史

进行进一步叶节点划分所需的最小损失减少(gamma)被设置在从 0100、的范围内,而learning_rate被限制在 0.010.3 的范围内。还测试了不同的正则化项(lambdaalpha)。

第一轮搜索的结果是roc_auc得分 0.7263 。最后一轮网格搜索产生了这些参数的组合及其最终得分:

图 18。XGBoost 分类器的参数调整结果(图片由作者提供)

当使用该模型预测未知的测试数据时,它获得了 0.80492roc_auc分数,位于 Kaggle 平台上前 40 车型中。

图 19。Kaggle 排名(图片由作者提供)

5.5 挑战

在训练和测试不同的模型和方法时,最大的挑战是计算能力,尤其是我个人笔记本上的可用内存。

因为我决定使用整个数据集,而不是它的随机子集,所以训练一些算法需要几个小时,特别是考虑到参数调整方法。

在其中一次尝试中,我决定测试神经网络分类器,在超过 12 个小时后,在参数调整回合中没有显示出改进,我取消了这次试验。

虽然像 LightGBM 这样的轻量级算法可以很好地执行,但更高的计算能力将允许不同和更复杂的方法。

6.结论

这个项目代表了一个巨大的挑战,尤其是因为要考虑的数据量和不同的特性。

此外,它是真实数据,这意味着它在许多方面类似于任何公司的普通数据科学项目的挑战。

除了评估不同算法的学习曲线,我还必须说,在这个项目的开发过程中,我自己的学习曲线呈指数增长,而且远远没有过度拟合,尽管收敛仍在进行中——这是必须的,因为作为数据科学家,我们需要将持续学习作为一种生活方式。

该项目有很大的改进空间,其中一些将被列为可能的方法:

  • 代替使用所有的特征(在删除具有高比例缺失值的特征之后),可以进行特征重要性分析,仅选择与任务更相关的特征;
  • 含有大量缺失值的观测值可以删除;
  • 在数据转换期间,许多步骤可以不同的方式进行:数值插补可以遵循不同的规则,而不是中值插补,或者缺失值可以根据其他特征进行推断;
  • 分类特征不一定需要对其缺失值进行估算,相反,它们可以被转换为虚拟变量,缺失值将被间接考虑。如果他们持有一些信息,这可能代表结果的改善;
  • 当缩放数字特征时,可以测试不同的方法作为本项目所选标准缩放器的替代方法;
  • 可以测试不同的算法和超参数调谐技术;
  • 可以开发更多的特征工程,以提供隐藏的信息或突出代表不同客户的重要方面。

关于这个项目,我想强调几件事:

  • 令人着迷的是,有多少数据可以告诉人们,特别是在客户细分项目中,使我们有可能了解他们住在哪里,他们赚多少钱,他们喜欢什么,以及他们如何思考;
  • 开发这样一个项目不仅仅是应用技术,还包括保持好奇心和提出正确的问题;
  • 比找到正确问题的正确答案更重要的是理解这些信息的价值,以及利用这些信息可以做些什么。

感谢您的阅读!

如果你想查看为这个项目开发的笔记本,可以在这里 访问

在线零售中的客户细分

原文:https://towardsdatascience.com/customer-segmentation-in-online-retail-1fc707a6f9e6?source=collection_archive---------3-----------------------

使用 python 在在线零售数据集中执行客户细分的详细分步说明,侧重于群组分析,使用 RFM 分析和聚类了解购买模式。

马库斯·斯皮斯克在 Unsplash 上的照片

在这篇文章中,我将讲述如何使用 python 对在线零售数据进行客户细分和其他相关分析。

这会变得有点长,所以请随意一次浏览一些部分,然后再回来。

在定义客户细分之前,让我们先来看看在线零售是如何工作的,以及相关的数据会是什么样子。当一个人走进零售店购买一些商品时,应该生成以下基本数据点:

  1. 客户名称/客户 ID
  2. 客户的地址/联系电话(人口统计信息)
  3. 发票号码
  4. 产品名称和产品代码
  5. 单价
  6. 交易的日期和时间
  7. 优惠券代码(如果适用)
  8. 折扣金额(如果适用)

现在我们已经对零售数据的样子有了一个基本的概念,让我们来思考一个公司应该如何思考,以便制定有效的营销政策。

对于一个小公司来说,客户群通常很小,并且是单独的目标。但是,随着企业规模的增长,企业不可能对每个客户都有一种直觉。在这样的阶段,关于追求哪些客户的人类判断将不起作用,企业将不得不使用数据驱动的方法来建立适当的战略。

对于一家中大型零售商店来说,他们不仅要在获取新客户方面投资,还要在客户维系方面投资,这也是非常必要的。许多企业的大部分收入来自他们的“最佳”或高价值客户。由于公司拥有的资源是有限的,找到这些客户并锁定他们是至关重要的。同样重要的是,找到处于休眠状态/高风险的客户来解决他们的问题。为此,公司使用客户细分技术。

商业和经济学中经常使用的一个公理是帕累托原则。这也适用于理解公司的收入流。

根据帕累托 原则,80%的结果来自任何给定事件的 20%的原因。

用商业术语来说,我们可以说 20%的客户贡献了一个公司总收入的 80%份额。这就是为什么找到这些人很重要。我将在本文后面详细解释客户细分的重要性。

现在让我们试着理解什么是客户细分,为什么它是制定有效战略的有效工具。然后,我们将研究如何进行分段。

了解客户细分

客户细分是根据客户的共同行为或其他属性将客户分成不同群体的过程。这些组内部应该是同质的,并且彼此之间也应该是异质的。该流程的总体目标是识别高价值客户群,即具有最高增长潜力或利润最高的客户。

从客户细分中获得的见解被用于制定量身定制的营销活动,并用于设计整体营销战略和规划。

对于一个公司来说,一个关键的考虑因素是是否要对其客户进行细分,以及如何进行细分。这将取决于公司的理念和它提供的产品或服务的类型。遵循的细分标准类型将在企业运营和制定战略的方式上产生巨大差异。这一点将在下文阐述。

  1. 零细分: <无差别方法> 这意味着公司以相似的方式对待所有的客户。换句话说,没有差异化的策略,所有的客户群都是通过单一的大规模营销活动获得的。
  2. 一个细分市场: <聚焦方法> 这意味着公司在严格定义的目标市场中瞄准特定的客户群体或利基。
  3. 两个或两个以上的细分市场: <差异化策略> 这意味着公司针对其客户群中的两个或两个以上的群体,并为每个细分市场制定具体的营销策略。
  4. 成千上万的细分市场: <超细分方法> 这意味着公司将每个客户都视为独一无二的,并为他们中的每一个人提供定制服务。

一旦公司确定了它的客户群和它要关注的细分市场的数量,它就需要决定在哪些因素的基础上对客户进行细分。

F 企业对企业营销公司细分的参与者:

  1. 行业
  2. 员工人数
  3. 位置
  4. 市值/公司规模
  5. 公司的年龄

F 消费者营销公司业务细分的参与者:

  1. 人口统计:年龄、性别、教育程度、民族、收入、就业、爱好等。
  2. 最近、频率和货币:最后交易的时间段、客户交易的频率和交易的总货币价值。
  3. 行为:既往购买行为、品牌偏好、生活事件等。
  4. 心理测验:信念、个性、生活方式、个人兴趣、动机、优先级等。
  5. 地理位置:国家、邮政编码、气候条件、城乡地域差异、市场可达性等。

为什么要细分您的客户?

照片由 Ivan Bajalovic 在 Unsplash 上拍摄

客户细分有许多潜在的好处。它有助于公司制定针对客户的有效战略。这对整个产品开发周期、预算管理实践以及向客户交付目标促销内容的计划都有直接影响。例如,一家公司可以生产高端产品、廉价产品或廉价替代产品,这取决于该产品是面向其收益率最高的客户、频繁购买者还是面向低价值客户群体。它还可以微调产品的特性,以满足客户的特定需求。

客户细分还有助于公司了解客户的相似性,对他们来说什么重要,什么不重要。通常,此类信息可用于为不同的客户群开发个性化的相关内容。许多研究发现,顾客欣赏这种个人关注,更有可能做出反应并购买产品。他们也开始尊重这个品牌,并感受到与它的联系。这可能会使该公司比竞争对手有很大优势。在这个世界上,每个人都有成百上千的电子邮件、推送通知、消息和广告进入他们的内容流,没有人有时间关注不相关的内容。

最后,这种技术也可以被公司用来测试他们不同产品的定价,改善客户服务,以及追加销售和交叉销售其他产品或服务。

如何细分您的客户?

从客户细分开始,公司需要有一个清晰的愿景和目标。可以采取以下步骤在广泛的层面上寻找客户群中的细分市场。

  1. 分析现有客户群:了解地理分布、客户偏好/信念,查看网站搜索页面分析等。
  2. 了解每位客户:将每位客户映射到一组偏好,以了解和预测他们的行为:他们感兴趣的产品、服务和内容。
  3. 定义细分市场机会:一旦确定了细分市场,就应该对每个细分市场及其挑战和机会有一个正确的业务理解。整个公司的营销策略可以扩展以迎合不同的顾客群。
  4. 研究细分市场:在巩固了不同客户细分市场的定义和业务相关性后,公司需要了解如何修改其产品或服务以更好地迎合他们。例如,它可能决定向一些客户提供比其他客户更高的折扣,以扩大其活跃客户群。
  5. 调整策略:尝试新策略,了解时间和经济对不同细分市场客户购买行为的影响。然后应该重复这个过程,以便尽可能地改进策略。

入门指南

在下面的分析中,我将使用在线零售数据集,它是从 UCI 机器学习知识库中获得的。该数据包含英国注册的无店铺在线零售商的跨国交易信息。数据的链接可以在这里找到。

数据快照

图:数据示例

数据属性

  1. 发票号:发票号。名义上,分配给每笔交易的 6 位整数。如果此代码以字母“c”开头,则表示取消。
  2. 库存代码:产品(项目)代码。名义上,一个 5 位数的整数,唯一分配给每个不同的产品。
  3. 描述:产品(物品)名称。名义上。
  4. 数量:每笔交易每种产品(物品)的数量。数字。
  5. 发票日期:发票日期和时间。数字,每笔交易生成的日期和时间。
  6. 单价:单价。数字,单位为英镑的产品价格。
  7. 客户编号:客户编号。名义上,一个唯一分配给每个客户的 5 位整数。
  8. 国家:国家名称。名义上,每个客户居住的国家的名称。

探索数据

在深入了解数据之前,从数据中删除了重复条目。该数据包含 5268 个重复条目(大约 1%)。

现在让我们看看数据中产品、交易和客户的总数,它们对应于数据中唯一的股票代码、发票号和客户 id 的总数。

图:数据中产品、交易和客户的数量

因此,对于 4070 个产品,数据中有 25900 个交易。这意味着每个产品都可能在数据中有多个交易。数据中的产品几乎和客户一样多。

由于来自 UCI 机器学习知识库的数据描述了基于英国注册的无店铺在线零售交易的数据,让我们检查数据中来自每个国家的订单百分比。

图:来自每个国家的订单百分比

上图显示了来自前 10 个国家的订单百分比,按订单数量排序。这表明,超过 90%的订单来自英国,没有其他国家甚至占数据中订单的 3%。

因此,为了分析的目的,我将采用与来自英国的订单相对应的数据。该子集将在接下来的步骤中制作,并将在需要时提及。

现在让我们看看数据中取消订单的数量。根据数据,如果发票编号代码以字母“c”开头,则表示订单已取消。

创建了一个标志列来指示订单是否对应于取消的订单。所有取消的订单都包含负数量(因为这是取消),因此从数据中删除。

最后,我运行了一个检查,以确认在没有取消的订单中是否有任何数量为负的订单。有 1336 个这样的案例。

图:检查数据中数量为负的订单

从上图可以看出,这些情况是 CustomerID 值为 NaNs 的情况。这些病例也被从数据中删除。

现在,数据被过滤为只包含来自英国的订单,最后,通过调用。info()方法:

图:。最终清理数据的 info()方法输出

数据中的任何列都没有空值,数据中共有 349227 行。现在,让我们检查清理后的数据中的产品、交易和客户的数量:

了解队列分析

现在让我们试着理解队列分析,这样我们就可以对我们的数据进行分析。

但是,什么是队列

一个群组是一组随着时间推移共享相似特征的用户。群组分析将用户分成相互排斥的组,并随着时间的推移测量他们的行为。

它可以提供关于产品和客户生命周期的信息。

群组分析有三种类型:

  1. 时间分组:它根据一段时间内的购买行为对客户进行分组。
  2. 行为群组:它根据客户注册的产品或服务对客户进行分组。
  3. 规模群体:指购买公司产品或服务的各种规模的客户。这种分类可以基于一段时间内的消费金额。

了解不同人群的需求有助于公司为特定人群设计定制服务或产品。

在下面的分析中,我们将创建时间群组,并查看在特定群组中在一段交易时间内保持活跃的客户。

深入队列分析

检查我们的数据的日期范围,我们发现它的范围从开始日期:2010 年 12 月 1 日到结束日期:2011 年 12 月 9 日。接下来,创建一个名为 InvoiceMonth 的列,通过为每笔交易取 InvoiceDate 月份的第一天来指示交易的月份。然后,提取关于交易的第一个月的信息,按 CustomerID 分组。

def get_month(x):
    return dt.datetime(x.year, x.month, 1)cohort_data['InvoiceMonth'] = cohort_data['InvoiceDate'].apply(get_month)
grouping = cohort_data.groupby('CustomerID')['InvoiceMonth']
cohort_data['CohortMonth'] = grouping.transform('min')
cohort_data.head()

图:创建 InvoiceMonth 和 CohortMonth 列

接下来,我们需要找出 InvoiceMonth 和 CohortMonth 列在月数方面的差异。使用了以下代码:

def get_date_int(df, column):    
    year = df[column].dt.year    
    month = df[column].dt.month    
    day = df[column].dt.day
    return year, month, dayinvoice_year, invoice_month, _ = get_date_int(cohort_data, 'InvoiceMonth') 
cohort_year, cohort_month, _ = get_date_int(cohort_data, 'CohortMonth')
years_diff = invoice_year - cohort_year
months_diff = invoice_month - cohort_month
cohort_data['CohortIndex'] = years_diff * 12 + months_diff
cohort_data.head()

图:创建 CohortIndex 列

获得上述信息后,我们通过按 CohortMonth 和 CohortIndex 对数据进行分组并通过应用 pd 在 CustomerID 列上进行聚合来获得群组分析矩阵。Series.nunique 函数。以下是获得的群组计数:

图:群组计数分析

上表告诉了我们什么?

考虑 2010 年 12 月 1 日的同月交易:对于 CohortIndex 0,这告诉我们 815 个不同的客户在 2010 年 12 月 1 日的同月交易。对于 CohortIndex 1,这表明 815 个客户中有 289 个客户在 2010 年 12 月至 2011 年 12 月期间进行了第一笔交易,并且他们在接下来的一个月中也进行了交易。也就是说,他们保持活跃。

对于 CohortIndex 2,这表明 815 个客户中有 263 个客户在 2010 年 12 月至 2011 年 12 月期间进行了第一笔交易,并且在第二个月也进行了交易。对于更高的上皮层以此类推。

现在让我们计算一下保留率。它被定义为活跃客户占总客户的百分比。由于每个群组中的活跃客户数量对应于 CohortIndex 0 值,因此我们将数据的第一列作为群组大小。

cohort_sizes = cohort_counts.iloc[:,0]# Divide all values in the cohort_counts table by cohort_sizes
retention = cohort_counts.divide(cohort_sizes, axis=0)# Check the retention table
retention.round(3) * 100# Drawing a heatmap
plt.figure(figsize=(10, 8))
plt.title('Retention rates')
sns.heatmap(data = retention,annot = True,fmt = '.0%',vmin = 0.0,vmax = 0.5,cmap = 'BuGn')
plt.show()

图:保留热图

从上面的保留率热图中,我们可以看到 2010 年 12 月至 2001 年 12 月的平均保留率约为 35%,最高保留率出现在 11 个月后(50%)。对于所有其他同月,平均保留率约为 18–25%。只有这个百分比的用户在给定的 CohortIndex 范围内再次进行交易。

通过这种分析,公司可以了解并制定策略,通过提供更有吸引力的折扣或进行更有效的营销等来增加客户保留率。

RFM 分割

RFM 代表近期、频率和货币。RFM 分析是一种常用的技术,它根据客户最近一次交易的时间(最近)、去年的交易次数(频率)以及交易的货币价值(货币)来为每个客户生成和分配分数。

在 Unsplash 上由 Austin Distel 拍摄的照片

RFM 分析有助于回答以下问题:谁是我们最近的客户?他从我们商店购买了多少次物品?他的交易总值是多少?所有这些信息对于了解客户对公司的好坏至关重要。

获得 RFM 值后,通常的做法是在每个指标上创建“四分位数”,并分配所需的顺序。例如,假设我们将每个指标分成 4 个部分。对于新近度量,最高值 4 将被分配给具有最小新近值的客户(因为他们是最近的客户)。对于频率和货币指标,最高值 4 将分别分配给频率和货币值最高的 25%的客户。在将指标分成四分位数之后,我们可以将指标整理成一列(就像一串字符{ 像‘213’})来为我们的客户创建 RFM 值的类别。根据我们的需求,我们可以将 RFM 指标分成更多或更少的部分。

现在让我们开始对我们的数据进行 RFM 分析。

首先,我们需要创建一个列来获取每笔交易的货币价值。这可以通过将单位值列乘以数量列来实现。让我们称之为总和。调用。describe()方法对这一列,我们得到:

图:。对 TotalSum 列使用 describe()方法

这让我们了解消费者支出在我们的数据中是如何分布的。我们可以看到平均值是 20.86,标准差是 328.40。但是最大值是 168469。这是一个非常大的值。因此,我们数据中前 25%的总和值从 17.85 快速增加到 168,469。

现在,对于 RFM 分析,我们需要定义一个“快照日期”,即我们进行分析的日期。这里,我将快照日期作为数据+ 1 中的最高日期(数据更新日期之后的第二天)。这等于日期 2011 年 12 月 10 日。(年-月-日)

接下来,我们将数据限制在一年的时间段内,以将最近值限制为最大值 365,并在客户级别上聚合数据,计算每个客户的 RFM 指标。

# Aggregate data on a customer level
data = data_rfm.groupby(['CustomerID'],as_index=False).agg({
'InvoiceDate': lambda x: (snapshot_date - x.max()).days,
'InvoiceNo': 'count',
'TotalSum': 'sum'}).rename(columns = {'InvoiceDate': 'Recency',                                                                     'InvoiceNo': 'Frequency','TotalSum': 'MonetaryValue'})

下一步,我们根据上述数据创建四分位数,并将这些分数整理到 RFM 细分列中。RFM 分数是通过将 RFM 四分位数指标相加计算出来的。

图:RFM 得分和四分位数。

我们现在可以分析我们的结果了。RFM 得分值的范围从 3 (1+1+1)到 12 (4+4+4)。因此,我们可以根据 RFM 分数进行分组,并检查与每个分数相对应的近期、频率和货币的平均值。

图 5:不同 RFM 分值的近期、频率和货币的平均值

正如所料,具有最低 RFM 分数的客户具有最高的新近价值和最低的频率和货币价值,反之亦然。最后,通过在我们的数据中手动创建类别,我们可以在 RFM 分数 3-12 的分数范围内创建细分市场:RFM 分数大于或等于 9 的客户可以被放在“顶级”类别中。类似地,RFM 分数在 5 到 9 之间的客户可以被归入“中等”类别,其余的可以被归入“低”类别。让我们称我们的类别为“一般 _ 细分”。分析最近、频率和货币的平均值,我们得到:

图 2:不同类别的近期、频率和货币的平均值

请注意,我们必须手动创建将客户分为“高”、“中”和“低”类别的逻辑。在许多情况下,这是可以的。但是,如果我们想正确地找出 RFM 值的分段,我们可以使用类似 K-means 的聚类算法。

在下一节中,我们将为 K-means 聚类预处理数据。

K 均值聚类的数据预处理

K-means 是一种众所周知的聚类算法,经常用于无监督学习任务。我不打算在这里详细说明算法是如何工作的,因为网上有大量的资源。

出于我们的目的,我们需要理解算法对数据做出某些假设。因此,我们需要对数据进行预处理,使其满足算法的关键假设,即:

  1. 变量应该对称分布
  2. 变量应该有相似的平均值
  3. 变量应该有相似的标准偏差值

让我们通过使用 seaborn 库构建近期、频率和货币值变量的直方图来检查第一个假设:

# Checking the distribution of Recency, Frequency and MonetaryValue variables.
plt.figure(figsize=(12,10))# Plot distribution of var1
plt.subplot(3, 1, 1); sns.distplot(data['Recency'])# Plot distribution of var2
plt.subplot(3, 1, 2); sns.distplot(data['Frequency'])# Plot distribution of var3
plt.subplot(3, 1, 3); sns.distplot(data['MonetaryValue'])

图 2:新近性、频率和货币价值指标的分布

从上图来看,所有的变量并不是对称分布的。他们都向右倾斜。为了消除偏斜,我们可以尝试以下变换:

1.日志转换
2。Box-Cox 变换
3。立方根变换

我将在这里使用对数转换。由于对数转换不能用于负值,我们需要删除它们(如果它们存在的话)。这里可以使用的一个常见做法是添加一个常数值以获得一个正值,这通常被视为每个观察变量的最小负值的绝对值。然而,在我们的数据中,我们没有任何负值,因为我们正在处理客户交易数据集。

检查最近的分布,频率和货币变量,我们得到这个称为。describe()方法:

图:。关于 RFM 度量的 describe()方法

从上面的描述中,我们可以看到特定 customerID 的最小 MonetaryValue 是 0。因此,该事务没有任何意义,需要删除。检查事件:

图:货币值为 0 的 CustomerID

该客户已从数据中删除。我们还看到,我们没有得到一个恒定的平均值和标准偏差值。为了检查这一点,我们将对数据进行标准化。首先对数据应用对数变换,并通过 sklearn 库中的 StandardScaler()方法传递它,我们获得了预处理的数据。现在检查对称分布的 RFM 变量的分布:

图 2:预处理数据的新近性、频率和货币价值度量的分布

从上面的图中我们可以看出,数据中已经去除了偏斜度。

K-均值聚类

在这一节中,我们将根据标准化的 RFM 数据构建多个聚类,并尝试使用肘方法找出数据中的最佳聚类数。下面附上的是为此目的的代码。对于每个聚类,我还提取了关于聚类内平方和平均值的信息,通过这些信息,我们可以构建肘图,以在我们的数据中找到所需的聚类数。

from sklearn.cluster import KMeanssse = {}# Fit KMeans and calculate SSE for each k
for k in range(1, 21):

    # Initialize KMeans with k clusters
    kmeans = KMeans(n_clusters=k, random_state=1)

    # Fit KMeans on the normalized dataset
    kmeans.fit(data_norm)

    # Assign sum of squared distances to k element of dictionary
    sse[k] = kmeans.inertia_# Plotting the elbow plot
plt.figure(figsize=(12,8))
plt.title('The Elbow Method')
plt.xlabel('k'); 
plt.ylabel('Sum of squared errors')
sns.pointplot(x=list(sse.keys()), y=list(sse.values()))
plt.show()

图:肘图

还可以使用轮廓分析来找到最佳的聚类数。你可以在我之前的文章这里中读到更多。为了这个分析的目的,我只使用了肘图法。

从上面的图中我们可以看出,最佳的簇数是 34

现在让我们比较一下集群性能。为此,我计算了近期、频率和货币指标的平均值,得到以下结果:

图:比较我们的数据的集群性能(3 到 4 个集群之间)

从上表中,我们可以比较 3 个和 4 个聚类数据的近期、频率和货币指标的平均值分布。使用 k=4,我们似乎可以得到更详细的客户群分布。然而,这可能不是一种视觉上非常吸引人的提取洞察力的方法。

比较聚类段的另一种常用方法是蛇形图。它们通常用于市场研究,以了解客户的看法。

让我们用下面的 4 个集群为我们的数据构建一个蛇形图。

在构建蛇形图之前,我们需要将数据转换成 along 格式,这样 RFM 值和度量名称就分别存储在一列中。链接了解 pd.melt 方法:链接。

# Melt the data into along format so RFM values and metric names are stored in 1 column each
data_melt = pd.melt(data_norm_k4.reset_index(),
                    id_vars=['CustomerID', 'Cluster'],
                    value_vars=['Recency', 'Frequency','MonetaryValue'],
                    var_name='Attribute',
                    value_name='Value')# Building the snakeplot
plt.title('Snake plot of standardized variables')
sns.lineplot(x="Attribute", y="Value", hue='Cluster', data=data_melt)

图:具有 4 个聚类的数据的蛇形图

从上面的 snake 图中,我们可以看到最近、频率和货币度量值在四个集群中的分布。这四个集群似乎是相互独立的,这表明集群的良好异质混合。

作为此分析的最后一步,我们现在可以提取每个客户的信息,这些信息可用于将客户与公司的相对重要性对应起来:

图:每个客户的 RFM 值以及聚类分配

最后的想法

从上面的分析中,我们可以看到我们的数据中应该有 4 个集群。为了理解这 4 个集群在业务场景中的意义,我们应该回顾一下比较 3 个和 4 个集群的集群性能的表格,以获得最近发生率、频率和货币指标的平均值。在此基础上,让我们将集群标记为“新客户”、“流失客户”、“最佳客户”和“风险客户”。

下表给出了 RFM 对每个细分市场的解释,以及建议公司在为该客户群设计营销策略时要记住的要点。

图:集群的业务解释和对每个细分市场的建议行动

进一步分析

  • 增加了新的变量,如任期:每个客户第一次交易后的天数。这将告诉我们每个客户使用该系统多长时间了。
  • 根据地理位置、人口统计和心理因素对客户进行更深入的细分。
  • 整合来自谷歌分析业务帐户的数据。Google Analytics 是跟踪许多重要业务指标的重要资源,如客户生命周期价值、流量来源/媒介、每次访问的页面浏览量、公司网站的跳出率等。

如果您喜欢这篇文章,并认为它内容丰富,请分享它以传播知识:)。谢谢大家!

链接到该项目的 Github 资源库: 链接

参考文献:

[1]https://www.shopify.in/encyclopedia/customer-segmentation

[2]https://learn . data camp . com/courses/customer-segmentation-in-python

[3]https://looker . com/blog/creating-actionable-customer-segmentation-models

[4]https://www . business 2 community . com/customer-experience/4-types-of-customer-segmentation-all-markets-should-know-02120397

【https://www.intercom.com/blog/customer-segmentation/

客户细分—第一部分

原文:https://towardsdatascience.com/customer-segmentation-part-i-2c5e2145e719?source=collection_archive---------31-----------------------

按项目描述对在线客户进行细分

介绍

在 Unsplash 上由 Charisse Kenion 拍摄的照片

客户细分是数据分析/数据科学最常见的用途之一。在这两篇文章系列中,我们将看到一个客户细分的例子。我们将使用在线零售 II 数据集,该数据集包含 2009 年 1 月 12 日至 2011 年 9 月 12 日之间英国在线零售商的交易。数据集包含 1.067.371 行关于 5.943 个客户的购买。

在线零售 II 数据集的前几行

正如我们所看到的,数据集包含可以跨越多行的发票订单。每一行代表一个特定的项目,并且包含购买数量、价格、发票日期、客户 ID 和客户国家的信息。

计划是结合两个不同的细分。

  • 基于每位顾客购买的商品的细分。
  • 基于最近、频率、货币价值(RFM)和国家(第二部分)的细分。

在这第一部分中,我们将根据项目进行细分。在第二部分中,我们将执行 RFM 国家聚类,并将这两个细分结合起来。

该器件的完整代码可在 Github 上找到。

基于项目的分段

为了执行基于项目的细分,我们将每个项目分配到特定的类别。我们可以在项目级别执行细分,但累计到类别有两个好处:

  • 由于存在 5.699 个唯一项目,使用它们将意味着我们必须在高维空间(即 5.699 维空间)中工作。一般来说,高维空间在聚类时容易出现问题(例如参见“ k-Means 优缺点”中的讨论,
  • 如果我们使用类别,就更容易描述集群。

遗憾的是,数据集中没有项目类别。因此,我们必须找到创造它们的方法。为此,我们将对商品的描述执行聚类。我们将使用 k-means 聚类(或者更好的是 k-means 的一种变体,称为minibatchmeans)。因为 k-means 只对数值数据起作用,所以我们将描述映射到高维向量。这是通过使用:

  • tfidf 矢量器
  • 计数矢量器

(在 sklearn 的文档中你可以看到这两种方法工作的详细描述)。

这两种不同的方法将允许我们找到对产品类别建模的最佳方式。

预处理

需要做一些预处理。首先,我们检查描述中缺少的值,并用“NA”替换它们。然后,我们将“Description”列转换为字符串(有一个单元格是整数,这会导致后面的问题),并创建一个具有唯一描述的列表。

此外,我们希望从我们的分析中删除常用词。找到它们的一个方法是从所有描述中创建一个词云。

预处理项目描述的代码

物品描述常用词的词云

基于词云,我们创建了停用词表。

使用 using 矢量器进行聚类

下面的代码使用 TfidfVectorizer 将描述映射到向量。然后,它使用 MiniBatchKMeans,k-Means 的一种变体来执行 2,3,…,10 个簇的聚类。结果用于创建距离平方和的图形。

根据肘方法,聚类数最有希望的值是 4、6 和 8。下面的代码分成 4 组,然后显示每个组中描述的单词云。

使用 TfidfVectorizer 映射的 4 个聚类的词云

似乎是:

  • 类别 0 是一个非常笼统的概念,
  • 类别 1 是关于包的,
  • 第二类是关于圣诞装饰,
  • 第三类是关于其他类型的装饰。

请注意,与其他类别(分别为 275、204 和 194)相比,类别 0 包含了更多的描述(5.026)。通常,这可能表明我们应该增加集群的数量。

我们可以试着分成 6 个集群,希望大的能分成几个小的。在这种情况下,类别 0 有 4.956 个描述,其余的有 197、173、168、130 和 75 个描述。

  • 类别 0 相当笼统,
  • 类别 1 在这种情况下也是关于包的,
  • 第二类是芳香蜡烛,
  • 第三类是关于圣诞装饰,
  • 类别 4 是关于其他类型的装饰,
  • 第五类是关于杯子、碗和盘子。

类别之间似乎有更多的重叠。单词“杯子”出现在类别 0 中,而单词“杯子”出现在类别 5 中。单词“bowl”出现在类别 0 和类别 5 中。单词“bag”出现在类别 1 和类别 5 中。单词“christmas”同时出现在类别 1 和类别 3 中。

使用 tfidf 矢量器映射的 6 个聚类的词云

使用计数矢量器进行聚类

我们使用计数矢量器重复这个过程,将描述映射到矢量。我们将省略代码片段。你可以在 Github 上阅读代码。(非常细心的读者会注意到,在应用 k 均值/最小批量均值之前,我们没有进行缩放。这是因为项目的描述具有或多或少相同的长度)。根据肘方法,最适合集群的数字是 3 和 8。

如果我们分成 3 组,那么我们有 3 个类别,分别有 5.334、199 和 166 个描述。正如我们从单词 clouds 中看到的,类别之间有显著的重叠(esp。类别 0 和 2)。

使用计数矢量器映射的 3 个聚类的词云

似乎用 TfidfVectorizer 的四个集群更清晰。我们要用这个。请注意,应该尝试对不同数量的集群同时使用 TfidfVectorizer 和 CountVectorizer,用它们完成客户聚类,然后决定保留哪一个。(更多关于后者。)

客户细分—预处理

创建项目类别后,我们将它们添加到初始数据集中。我们还通过将数量乘以价格来计算每行的成本。

这样,我们就可以计算每个类别每月的总成本(支出)。在第 2 类中,11 月份有大幅增长,而其余月份接近于零。这证明了类别 2 与圣诞节相关产品有关。

我们计算每个顾客每个类别的总支出(成本)。

最后,我们将每个类别的总成本替换为所有类别总成本的百分比。注意,在某些情况下我们有负值。或许这意味着回归。因为被退回的商品应该是以前购买的,所以我们将负值改为正值。这将是 k-means 创建客户群的输入。

客户细分—聚类

传统上,我们缩放输入矩阵,并使用肘方法来决定客户群的数量。

请记住,根据肘形法,聚类数的最佳值是图中有肘形/角度的位置。基于此,我们可以选择 4 或 7 作为聚类数。

下面列出了创建 4 个集群和分析它们的代码。函数cluster_profile计算每个集群的支出百分比的中值,并用结果绘制热图。

4 个客户群的特征分析

我们看到,对于所有集群,类别 0 的支出比例都很高。此外:

  • 聚类 0 具有在类别 2 中高消费的客户,
  • 聚类 1 具有仅在类别 0 中高消费的客户,
  • 聚类 2 具有在类别 3 中高消费的客户,
  • 聚类 3 拥有类别 1 中高消费的客户。

如果我们尝试创建 6 个分类,在某些情况下,我们得到的分类 1 或分类 2 的百分比高于分类 0 的百分比。缺点是,为了实现这一点,我们必须创建客户很少的集群。

6 个客户群的特征分析

使用层次聚类,我们可以更好地了解可能的聚类数。

等级聚类树图

选择 4 个集群,我们观察到,现在,在类别 1 中具有高花费的集群(集群 3)在类别 1 中比在类别 0 中具有更高的花费。这种倒置是其较小尺寸的结果。因此,我们将选择对 4 个聚类使用 k-means。相关信息出口泡菜。

在下一部分的中,我们将根据 RFM 价值和客户所在国家进行客户细分。在第二部分中,我们还将把这两个分段合并成一个完整的分析。

最后,下图显示了我们使用 6 个项目类别得到的结果。在左侧,它显示了用于选择客户细分中的聚类数的肘形图。据此,聚类的最佳数量是 3 或 5。如果我们尝试 3 个集群,我们会得到一个拥有大多数客户的集群和两个小得多的集群。图像右侧是 5 个集群的分析。如您所见,结果类似于我们的 4 个分类描述的 4 个集群解决方案。不同之处在于,现在存在两个类别,其中大部分支出属于类别 0。

不管是好是坏,对于几个集群决策没有硬性规定。只有指导方针。你可以在谷歌的 colab 中运行 jupyter notebook 进行实验并制作自己的笔记本。

客户细分—第二部分

原文:https://towardsdatascience.com/customer-segmentation-part-ii-1c94bdc03de5?source=collection_archive---------22-----------------------

按 RFM 国家对在线客户进行细分,并与第一部分相结合

哈尔·盖特伍德在 Unsplash 上拍摄的照片

客户细分是数据分析/数据科学最常见的用途之一。在这两篇文章系列的第二部分中,我们将看到一个客户细分的例子。我们使用的数据集是在线零售 II 数据集,其中包含一家总部位于英国的在线零售商在 2009 年 1 月 12 日至 2011 年 9 月 12 日之间的交易。数据集包含 1.067.371 行关于 5.943 个客户的购买。

在线零售 II 数据集的前几行

在的第一部分中,我们根据产品类别创建了一个客户细分。在第二部分中,我们将基于新近性、频率、货币价值(RFM)和原产国进行聚类。然后,我们将结合第一部分的分割结果。

在 Github 上可以找到基于 RFM 国家的细分以及结合两个细分结果的代码。

新近性、频率、货币价值(RFM)

新近性、频率、货币价值(RFM)是一种分析客户价值的方法。这个名字来源于它为每个客户检查的三个方面:

  • 最近:客户最近一次购买的时间。对于很久以前最后一次购物的顾客来说,最近购物的顾客更有价值。
  • 频率:顾客购物的频率。顾客越频繁购买越好。
  • 货币价值:顾客花了多少钱。越高越好。

Investopedia 和维基百科都有大量关于 RFM 的文章。

有几种方法来定义新近性、频率和货币价值。我们将使用以下定义:

  • 最近度是从数据集的上次发票日期到最近发票日期(2011-12-09)的天数,
  • 频率是从第一次开票日期到最后一次开票日期的天数除以发票数量,
  • 货币价值是平均成本,其中成本是数量与价格的乘积。

下面列出了计算 RFM 的代码。

国家

在线零售 II 数据集包含每件商品运送到的国家。通过使用每个国家的 GDP,我们可以代表每个客户的财务实力。来自维基百科的 GDP 数据被用来创建一个 xlsx 文件,你也可以在 Github 中找到这个文件。有几个客户与两个国家有关。为了解决这个问题,对于每个客户,我们用发票数量来衡量 GDP。

每个客户加权 GDP 的计算结果

基于 RFM 国家 GDP 的客户细分

最后的预处理步骤是将 RFM 分析与 GDP 数据相结合。

对于聚类,我们将使用 k 均值算法。缩放输入数据后,我们对 k (=创建的聚类数)范围执行 k 均值聚类。这将允许我们创建一个每 k 平方距离总和的图,并使用肘形法选择 k 的最佳值。

基于 elbow 方法,我们将检查 3 个或 7 个聚类。为了分析集群,我们创建了一个名为cluster_profile_RFM_country. This function 的定制函数

  1. 计算每个分类的最近值、频率、货币值和加权 GDP 的中值,然后
  2. 对近期、频率、货币价值和加权 GDP 的中位数求和
  3. 将每个中值除以相应的和。

这样,函数cluster_profile_RFM_country计算对应于每个聚类的每个变量(最近、频率、货币价值和加权 GDP)的百分比。有一个选项可以从具有少量项目的分析集群中排除。

用于分析集群的函数cluster_profile_RFM_country

如果我们分成 3 组,我们最终得到 3 个大小分别为 4.225、1.708 和 9 个客户的集群。第三个簇的小尺寸是异常值的指示。如果我们使用前两个分类进行分析,我们会看到第一个分类包含客户

  • 最近进行过交易的客户(过去 9 天与过去 91 天),
  • 花费更频繁(每 15 天比 85 天),
  • 每笔交易的货币价值更高(243 比 197)

比第二组的顾客多。

聚类成 3 组时两个主要聚类的特征分析

选择 7 个分类,我们获得具有 3.549、1.547、572、247、17、9 和 1 个客户的分类。对拥有超过 100 名客户的客户进行分析,我们有

  • 拥有 572 个客户的集群 4。聚类 4 包含具有最低 RFM 分数的客户(即,购物频率较低、每次交易的货币价值较低、并且比其余聚类购物时间更长的客户)
  • 具有 1.547 个客户的分类 0。分类 0 包含 RFM 分数第二低的客户。
  • 集群 2 有 3.549 个客户,集群 5 有 247 个客户。这些包含具有最佳 RFM 分数的客户。两者的区别在于,集群 5 的客户与 GDP 低于其他集群的国家相关。

我们可以说,这四个集群可以按 RFM 国家分数(从最好到最差)排列如下:

集群 4 < cluster 0 < cluster 5 < cluster 2. (Cluster 5 has higher monetary value than cluster 2 but contains customers from countries with lower GDP. Thus we prioritize cluster 2).

Cluster 5 has customers from countries with a lower GDP than the rest.

Profiling of the four major clusters when clustering in 7 groups

Using hierarchical clustering we can gain a better understanding of the possible number of clusters.

We see hierarchical clustering verifies the selection of splitting into 3 or 7 clusters. Profiling major clusters in both cases, we see that the results are similar to k-Means.

Profiling major clusters in hierarchical clustering. To the left two major clusters when clustering into 3 groups. To the right four major clusters when clustering into 7 groups.

We will use the clustering solution into 7 clusters with k-Means. The 相关信息与 pickle 一起导出。

将结果与第一部分合并

最后,我们结合项目类别分割和 RFM 国家分割的结果。代码可以在 Github 上找到。

这个过程很简单。

  1. 导入两段数据。

2.将可视为离群值的小聚类合并为一个。

即,在 RFM 国家细分中,有三个集群,每个集群的客户少于 20 个。如果我们将它们与项目类别细分相结合,那么产生的群体将包含非常小比例的客户。我们要把这些合并成一个。给定的机会,我们将重新命名集群,使具有最低 RFM 分数的集群将是第一个(保持与离群值合并到最后)。

3.将这两个分段结合起来。

4.创建两个细分的交叉列表。

两个部分的交叉列表。左侧,每组的客户数量。每组客户的正确百分比。

5.形容由此产生的顾客群体。

这里,我们将重点关注几个客户群。根据他们的个人资料,我们可以试着给每个群体起一个名字。

  • “高价值普通客户”:最大的细分市场有 2.501 家(占总数的 42.09%)。它包含属于商品类别分类的分类 1 和基于 RFM 国家分类的分类 4 的客户。这意味着该细分市场中的顾客从一般商品类别中购物(即他们不关注包、装饰品或圣诞商品),并具有相对较高的 RFM 分数。
  • “高价值圣诞购物者”:项目类别群 0 和 RFM-国家群 4 中的细分。在我们的商品类别聚类中,我们发现聚类 0 对应于倾向于购买更多圣诞商品的客户。该细分市场包含 289 名(4.86%)客户。
  • “高价值装饰爱好者”:项目类别组 2 和 RFM-国家组 4 中的细分。在我们的项目类别聚类中,我们发现聚类 2 对应于偏好包的客户。该细分市场包含 489 名(8.23%)客户。
  • “低价值装饰爱好者”:项目类别组 2 和 RFM-国家组 1 中的细分。该细分市场包含 69 名(1.16%)客户。我们可以将项目类别群 2 和 RFM 国家群 2 中的客户添加到该细分市场中。这样,该细分市场将包含 305 个(5.13%)客户。
  • “高价值包包爱好者”:项目类别组 3 和 RFM-国家组 4 中的细分市场。在我们的项目类别聚类中,我们发现聚类 2 对应于具有装饰偏好的客户。该细分市场包含 270 名(4.54%)客户。
  • “低价值包包爱好者”:项目类别组 3 和 RFM-国家组 1 中的细分。该细分市场包含 42 名(0.71%)客户。我们可以将该细分市场和客户分配到项目类别分类 1 和 RFM 国家分类 2 中。这样,该细分市场将包含 132 个(2.22%)客户。

最后的话

我们对客户细分的两部分介绍到此结束。在真实的场景中,会提供每个片段的更详细的描述。对于每个细分市场,我们会计算几个 KPI,如下所示:

  • 每段总成本,
  • 每个客户的平均成本
  • 每个客户每次交易/发票的平均成本
  • 每个客户的交易/发票数量
  • 每个客户的平均频率
  • 每个客户的国家分布

所有这些信息都将用于为每个部分规划具体行动。不幸的是,这超出了我们的职位范围。我希望你能有机会在现实生活中看到它。

客户细分:Python 中的无监督机器学习算法

原文:https://towardsdatascience.com/customer-segmentation-unsupervised-machine-learning-algorithms-in-python-3ae4d6cfd41d?source=collection_archive---------3-----------------------

使用 DBSCAN 和 K-means 对客户行为进行聚类

拍摄者:Lama Alzahrani

客户细分是根据共同特征将客户分成不同群体的过程,这样公司就可以有效而恰当地向每个群体进行营销。根据客户在行为和习惯上的相似性对他们进行细分。在这个项目中,我和我的团队实现了两个无监督的机器学习算法:K-means 和 DBSCAN。与一家快递公司合作。我们的目标是根据客户的各种行为和特征对他们的客户进行细分,以便公司能够以更适合每个客户的方式对每个细分市场进行营销。

这个杰出的团队由四名成员组成:

  • 扎拉什布利
  • T5【瓦伊德】阿尔图尔基
  • 马沙埃尔·阿尔哈桑
  • 喇嘛阿尔扎拉尼

我们将向您介绍我们的思考过程,以及我们是如何对客户进行聚类的,使用了哪些功能以及实施了哪些方法来获得预期的结果。本文分为六个部分:

  1. 商业问题。
  2. 数据探索。
  3. 数据准备。
  4. 模型实现。
  5. 结果。
  6. 未来的工作。

业务问题:

任何公司和企业的首要目标是了解他们的目标客户。他们的消费者如何操作和使用他们的服务。每个消费者使用公司服务的方式可能不同。我们要解决的问题是定义这个快递公司的消费者。来定义这些消费者使用公司服务的特定行为和方法。

数据探索:

我们很幸运地得到了一个初创快递公司的数据集。该数据集是私有数据集,因此我们不会链接它。记录的数据是在六个月的时间内收集的数据。它分为三张表用户,支付和订单。

图 1:订单数据表列和数据类型

下面是订单数据表,给出了我们经常使用的数据类型的概念。订单数据表包含 2604 条记录和 26 列。用户包含 4663 条记录和 12 列,而付款数据表包含 3169 条记录和 6 列。

为了在开始实施我们的机器学习算法之前了解更多的数据,我们创建了一些 ed a 图。

图 2:订单状态

用户最常使用该应用服务的产品是什么?

图 3:订单饼图

注册用户的时间线是多少?

图 4:注册用户随时间变化的线形图。

数据准备:

我们首先检查是否有任何丢失的值。

图 5:订单数据表中缺少的值。

如图所示,有 6 列缺少数据点。下面的代码将演示我们如何处理丢失的值。

接下来,为了便于分析,我们决定将订单分成 6 个不同的类别,如下图所示。

图 6:将订单分成 6 类。

考虑到要处理三个数据表,我们使用 pandas dataframe 读取每个数据表,然后将这三个数据表合并成一个 dataframe。

图 7:将 3 个数据帧合并成一个。

模型实现:

最初,在我们决定走客户细分路线之前,我们计划实现一个受监督的机器学习算法。然而,我们后来意识到,鉴于这个数据集,挑选一个最优目标作为监督算法的基础并不是一个合适的方法。经过几个小时的头脑风暴,我们决定使用两种聚类算法进行客户细分:K-means 和 DBSCAN。此外,我们决定测试这两种不同的模型。

导入的库:

然后,我们继续为两种聚类算法选择我们的特征。我们选择了与买家相关的最受影响的特征,如**Number of Orders****Total amount paid by this buyer****Number of orders paid Cash****Number of Orders paid by Card****Number of orders paid using STCPay****Count of unique product categorical ordered.**

注:STCPay 是一种在沙特阿拉伯使用的数字钱包。类似 Apple Pay。

注意:聚类算法和 EDA 是在两个不同的 google colab 表上进行的,这就是 dataframe 名称与上图不同的原因。

下一步是缩放数据并使用 PCA 降低维度。

我们决定在训练模型之前减少特征的数量。我们使用主成分分析技术进行特征约简。首先,我们创建了 Scree plot 来帮助我们选择 PCA 的最佳元件数量。

图 8:碎石图。

如图 8 所示,我们的 PCA 的最佳组件数是 3,它最好地描述了数据。保留 80%的数据方差。

成功选择了正确数量的组件后,就可以根据我们选择的功能来安装包含 3 个组件的 PCA 了。

K-均值:

现在,我们开始使用 K-mean 算法构建我们的聚类模型。K-mean 算法最重要的参数是聚类数。因此,我们应该决定我们的数据中有多少个聚类。有许多方法可以选择 K-mean 算法的最佳聚类数,在这个项目中我们应用了两种方法,称为肘方法轮廓分析法

1.弯头方法:

肘形法是用于确定 k 的最佳值的常用方法。该方法使用误差平方和来计算聚类内数据点之间的方差。要选择的最佳 k 值是曲线上的拐点。正如我们在肘图中看到的,我们模型的最佳 k 值是 5。

图 9: K 均值弯管图

2.轮廓分析方法:

该方法计算聚类中每个数据点的平均轮廓值,该值表示数据点与其自身聚类的相似程度。该度量的范围从-1 到 1。值为 1 表示样本远离相邻聚类。负值指的是可能被分配到错误聚类的样本。

下面的 GIF 说明了剪影分析方法的思想,剪影图上的每一行表示散点图中的一个数据点,X 轴表示剪影系数值。红线表示聚类中所有样本的平均轮廓系数值。具有高轮廓系数值的聚类是最佳选择。最后,从轮廓系数的结果,我们决定用 5 集群

图 10:轮廓分析

在实施肘部和轮廓分析方法之后,我们开始构建具有 5 个聚类的 K-mean 算法。

下面是 K-means 创建的聚类的 3D 散点图。

图 11:K 均值聚类 3D 图

数据库扫描:

对于检测数据集中的异常值和异常值,DBSCAN(基于密度的带噪声应用程序空间聚类)是最有效的。DBSCAN 的两个决定性参数是 eps 和 min_samples。

eps 是确定数据点邻居的距离。如果点之间的距离小于或等于 eps,则这些点是邻居。为了确定 eps 的正确值,使用了 3 种方法:sklearn 的最近邻居、k-距离肘图和 eps 可视化。eps 的最佳值在最大曲率点。

min_samples 是形成聚类的点数。它是基于领域知识和数据集的大小来确定的。给定数据集的维数,选择 min_samples。一个很好的经验法则是 minPts >= D + 1,因为我们的数据集是 3D 的,所以 min_sample=4。对于较大的数据集,最小点> = D*2。

DBSCAN 中有 3 个主要的数据点:核心点、边界点以及 DBSCAN 擅长检测的离群点。核心点是 eps 半径内的点。边界点是可从核心点访问的点,并且具有较少数量的 min_samples。离群点是指不是核心点或边界点的点。

图 12:DBSCAN 3D 绘图

为了获得关于 eps 值的信心,我们再次采用肘图法和eps 可视化图。

图 13:Eps 弯管图

让我们放大图:

图 14:缩放的 eps 弯管图

图 15:Eps 可视化图形

如肘图和 eps 可视化图所示,eps 的最佳值为 1。

结果:

使用聚类计数为 5 的 K-means 算法,我们看到,与其他 4 个聚类相比,聚类 3 中的客户更喜欢使用 STCPay 而不是卡或现金支付。相比之下,聚类 0 中的客户最喜欢用现金支付。聚类 0 的订单数量也最多,有 2072 个订单,而聚类 1 有 93 个订单,是 5 个聚类中订单数量最少的。就利润而言,聚类 0 为应用程序带来的利润最多,其次是聚类 3、2、1 和 4。

使用聚类计数为 5 的 DBSCAN 算法,我们看到,与其他 4 个聚类相比,聚类 3 中的客户更喜欢使用 STCPay 而不是卡或现金支付。相比之下,聚类 0 中的客户最喜欢用现金支付。聚类 0 也具有最高的订单数量,有 2053 个订单,而聚类 2 有 26 个订单,是 5 个聚类中订单数量最少的。就利润而言,聚类 0 为应用程序带来的利润最多,其次是聚类 1、2、3 和 2。

一些可操作的见解发现交付公司可以执行:

  • 从 K-mean 结果可以看出,聚类 1 中的买家创建的订单数量比其他聚类中的买家创建的订单数量多,在 6 个月中平均有 46 个订单。这是买家的大量订单,所以有可能这些账户是注册为买家的店铺。我们在 DBSCAN 的 cluster -1 中观察到同样的情况,个人买家在 6 个月内平均有 10 个订单。
  • 大多数买家用现金支付。在这种情况下,可能买家不知道通过应用程序可以使用不同的支付方式。因此,营销团队应该通过提供不同的支付方式来阐明应用程序的力量。

有关代码及其实现的更多信息,请访问我们的 github 资源库:

https://github.com/ZarahShibli/Customers-Segmentation.git

或者你可以查看我们的仪表盘,查看我们发现的全部信息:https://customer-segmentation-tuwaiq-2.herokuapp.com/

注意:仪表板是一个 Dash 应用程序仪表板,托管在 Heroku 云服务器上,加载可能需要几分钟。

未来工作:

考虑到收集的数据是六个月的数据,模型会更加稳健,可以绘制更多的数据点。未来可以通过输入更多数据来优化算法。公司现在可以适当地向每个细分的客户营销,并向不同的客户细分显示不同的广告。

资源:

https://sci kit-learn . org/stable/auto _ examples/cluster/plot _ DBS can . html # sphx-glr-auto-examples-cluster-plot-DBS can-py

https://towardsdatascience . com/DBS can-algorithm-complete-guide-and-application-with-python-scikit-learn-d 690 cbae 4c 5d

https://towards data science . com/how-to-use-DBS can-effectively-ed 212 c 02e 62

https://medium . com/@ tarammullin/DBS can-parameter-estimation-ff 8330 E3 a3 BD

https://towards data science . com/DBS can-clustering-explained-97556 a2 ad 556

https://stats.stackexchange.com/questions/88872/a-routine-to-choose-eps-and-minpts-for-dbscan

https://towards data science . com/how-DBS can-works-and-why-should-I-use-it-443 B4 a 191 c 80

https://www . coursera . org/lecture/build-regression-class ification-clustering-models/silhouette-analysis-33 ieo

https://sci kit-learn . org/stable/auto _ examples/cluster/plot _ k means _ silhouette _ analysis . html

利用聚类进行客户细分

原文:https://towardsdatascience.com/customer-segmentation-with-clustering-933caa4c9ea3?source=collection_archive---------15-----------------------

了解如何利用消费者数据优化销售和营销策略

照片由从派克斯拍摄制作

假设您与销售和营销团队一起工作,以达到您公司预先设定的目标。

虽然你的公司在创造收入和留住客户方面做得很好,但你不能不认为它可以做得更好。

就目前的情况来看,广告、促销和特别优惠在所有客户中是同质的,这是一个严重的问题。以一种他们不会接受的方式与客户接触,就等于浪费你的广告预算。

毕竟,你不希望你的公司把有限的预算花在给大学生发尿布优惠券或给老年妇女打游戏机广告上。

你需要的是针对每一类客户定制你的方法,以充分利用你的营销投资。

这就引出了一个问题:你如何正确区分你的消费者群体中的人?

这就是集群发挥作用的地方。

有了贵公司精心收集的消费者数据,您就有办法执行聚类分析,将您的消费者分成适当的群体,并为每个群体定制您的营销策略。

通过针对不同类型的客户量身定制的方法,您将能够从广告和促销投资中获得最大收益。

在这里,您将深入了解数据科学如何帮助企业细分消费者群体。

在下面的案例研究中,将使用 k-means 聚类算法来寻找将客户分组的最佳方法。

案例分析

目标是使用客户数据来计算如何将消费者群体划分到理想的集群组中。

数据(无版权保护)可以在这里访问。

下面的数据集预览显示了为每个客户提供的信息。

代码输出(由作者创建)

数据预处理

我们对数据集进行预处理,以便将其输入到聚类算法中。这需要:

  • 移除不需要的功能
  • 删除丢失的值
  • 移除异常值
  • 编码分类特征

之后,数据将经过标准化和主成分分析(PCA)。对数据进行标准化可以确保机器学习模型不会偏向任何特征,而 PCA 会降低数据集的维度以减轻过度拟合。

构建聚类模型

接下来,我们需要为这批消费者确定理想的集群数量。这可以通过弯头法轻松确定。

虽然可以手动执行 elbow 方法,但使用 yellowbrick 库可以简化很多,它可以用一行代码构建可视化的情节。

代码输出(由作者创建)

肘方法表明,将我们的消费者分为四类是理想的。

让我们创建一个 k 均值聚类模型,将每个客户分配到四个聚类之一。

为了可视化聚类的结果,我们可以绘制一个散点图。

代表客户的点的坐标将基于前两个 PCA 分量。

代码输出(由作者创建)

解释

来自像素的罗德尼制作的照片

在这一点上,你可能想拍拍自己的背,但工作还没有完成。

问问你自己:在这一点上你真正学到了什么?

即使你已经把你的消费者分成了几个组,分组的方式有任何意义吗?

如果你不能解释你的算法形成的集群,你所有的努力都是徒劳的。对于你向其展示发现的人来说,一组没有明确特征的集群与一组随机产生的集群没有什么不同。

只有当你能解释你的客户是如何划分的,聚类分析才有意义。这可以让你了解每个群体,然后相应地为每个群体制定营销策略。

我们可以使用箱线图从年龄、工作经验和家庭规模的角度来比较每个集群。

代码输出(由作者创建)

我们可以使用饼图来比较每个集群在性别、婚姻状况、毕业状况、职业和支出分数方面的差异。

为了方便起见,我们可以创建一个函数,根据给定的特性生成比较集群的饼图。

比较集群的饼图如下所示。

性别:

代码输出(由作者创建)

婚姻状况:

代码输出(由作者创建)

毕业状态:

代码输出(由作者创建)

职业:

代码输出(由作者创建)

支出分数:

代码输出(由作者创建)

基于视觉图表,消费者群体主要按照年龄、婚姻状况、职业和购买力进行细分。

我们现在可以确定每个集群的定义特征。

第 0 类:来自艺术和娱乐领域的单身人士,购买力较低。

第一类:中年、已婚、购买力一般的艺术界人士。

第二类:没有受过高等教育、购买力低的年轻单身人群。

第三类:年长的已婚人士,有高薪工作和高购买力。

既然我们已经了解了每个集群的人口构成,我们最终可以针对每个客户群创建一个强大的营销策略。

此外,任何新客户都可以被分配到一个集群,并会收到最适合他们的广告和特别优惠。

结论

照片由来自 Pexels 的 Prateek Katyal 拍摄

数据能够帮助改善决策的程度令人震惊。

通过利用包含客户个人详细信息的数据集,我们能够有效地将客户划分为具有明确特征的群体。

您现在知道了集群的可用性及其在帮助企业做出决策方面的作用。

希望,作为一个更大的画面的一部分,这个演示给了很多关于为什么企业对与数据处理相关的职位有如此高的需求的洞察力。

在合适的人手中,数据可以用来显著优化业务模式,提高客户满意度和保留率,并最大限度地提高利润率。现在的行业都认识到了这一点,这也是为什么你现在可以看到很多数据分析师、数据科学家、数据工程师等职位的招聘信息。

对于希望在竞争激烈的市场中茁壮成长的企业来说,雇佣数据从业者至关重要。

我祝你在数据科学的努力中好运!

参考

维特里拉。(2020).客户细分(第 1 版)。2021 年 11 月 7 日从 https://www.kaggle.com/vetrirah/customer检索。

使用 Python 进行客户细分

原文:https://towardsdatascience.com/customer-segmentation-with-python-31dca5d5bdad?source=collection_archive---------20-----------------------

学习用 Python 构建用于客户细分的 K-Means 聚类算法

Unsplash 上的粘土银行图像

介绍

客户细分对于企业了解其目标受众非常重要。不同的广告可以基于他们的人口统计特征、兴趣和富裕程度被策划并发送给不同的受众分群。

有许多无监督的机器学习算法可以帮助公司识别他们的用户群,并创建消费者细分市场。

在本文中,我们将研究一种流行的无监督学习技术,称为 K-Means 聚类。

该算法可以接收未标记的客户数据,并将每个数据点分配到聚类中。

K-Means 的目标是将所有可用的数据分组到彼此不同的非重叠子组中。

这意味着每个子组/聚类将由区别于其他聚类的特征组成。

K-Means 聚类是数据科学家帮助公司进行客户细分的常用技术。这是一项重要的技能,大多数数据科学面试将测试你对这种算法的理解/你将它应用到现实生活场景的能力。

在本文中,您将了解以下内容:

  • K 均值聚类的数据预处理
  • 从头开始构建 K-Means 聚类算法
  • 用于评估聚类模型性能的指标
  • 可视化构建的集群
  • 解释和分析构建的集群

先决条件

你可以在这里下载本教程的数据集。

确保在开始之前安装以下库:pandas、numpy、matplotlib、seaborn、scikit-learn、kneed。

一旦你完成了,我们就可以开始建立模型了!

导入和读取数据框

运行以下代码行以导入必要的库并读取数据集:

# Imports

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sea
from kneed import KneeLocator
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from mpl_toolkits.mplot3d import Axes3D

# reading the data frame

df = pd.read_csv('Mall_Customers.csv')

现在,让我们看看数据帧的头部:

df.head()

作者图片

数据集中有五个变量。CustomerID 是数据集中每个客户的唯一标识符,我们可以删除这个变量。它没有为我们提供任何有用的集群信息。

由于性别是一个范畴变量,它需要被编码并转换成数字。

所有其他变量在输入到模型中之前都将按正态分布进行缩放。我们将用平均值 0 和标准差 1 来标准化这些变量。

标准化变量

首先,让我们对数据集中的所有变量进行标准化,使它们的规模大致相同。

你可以在这里了解更多关于标准化的信息。

col_names = ['Annual Income (k$)', 'Age', 'Spending Score (1-100)']
features = df[col_names]
scaler = StandardScaler().fit(features.values)
features = scaler.transform(features.values)
scaled_features = pd.DataFrame(features, columns = col_names)
scaled_features.head()

现在,让我们看看数据帧的头部:

作者图片

我们可以看到所有的变量都被转换了,现在以零为中心。

一个热编码

变量“性别”是分类的,我们需要将其转换成数字变量。

这意味着我们需要为每个类别替换数字。我们可以用 pd.get_dummies()对熊猫做这件事。

gender = df['Gender']
newdf = scaled_features.join(gender)

newdf = pd.get_dummies(newdf, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)

newdf = newdf.drop(['Gender_Male'],axis=1)

newdf.head()

让我们再看一下数据帧的头部:

作者图片

我们可以看到性别变量被改变了。您可能已经注意到,我们从数据框中删除了' Gender_Male '。这是因为不再需要保留变量了。

'性别 _ 男性的值可以从'性别 _ 女性,'(即如果'性别 _ 女性'为 0,那么'性别 _ 男性'将为 1,反之亦然)。

要了解更多关于分类变量的一键编码,你可以观看这个 YouTube 视频。

构建聚类模型

让我们构建一个 K 均值聚类模型,并将其应用于数据集中的所有变量。

然后,我们将在肘形图中可视化聚类模型的性能。

肘图将告诉我们,在构建模型时,应该使用多少个理想的聚类。

你可以在这里了解更多关于选择最佳集群数量和肘方法的信息。

SSE = []

for cluster in range(1,10):
    kmeans = KMeans(n_jobs = -1, n_clusters = cluster, init='k-means++')
    kmeans.fit(newdf)
    SSE.append(kmeans.inertia_)

# converting the results into a dataframe and plotting them

frame = pd.DataFrame({'Cluster':range(1,10), 'SSE':SSE})
plt.figure(figsize=(12,6))
plt.plot(frame['Cluster'], frame['SSE'], marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('Inertia')

可视化模型的性能:

作者图片

根据上面的肘图,我们可以看到最佳的集群数是 4

现在,让我们看看另一个聚类指标。

轮廓系数

轮廓系数或轮廓分数是用于评估由算法创建的聚类质量的度量。

轮廓分数范围从-1 到+1。轮廓分数越高,模型越好。

轮廓分数测量同一聚类内所有数据点之间的距离。这个距离越小,轮廓得分越好。

它还测量对象和最近簇中的数据点之间的距离。这个距离越高越好。

轮廓分数越接近+1 表示聚类性能越好,轮廓分数越接近-1 表示聚类模型越差。

让我们计算我们刚刚建立的模型的轮廓分数:

# First, build a model with 4 clusters

kmeans = KMeans(n_jobs = -1, n_clusters = 4, init='k-means++')
kmeans.fit(newdf)

# Now, print the silhouette score of this model

print(silhouette_score(newdf, kmeans.labels_, metric='euclidean'))

这款的剪影评分大概在 0.35 左右。

这是一个不错的模型,但我们可以做得更好,并尝试获得更高的集群分离。

在我们尝试这样做之前,让我们将刚刚构建的集群可视化,以了解模型的表现如何:

clusters = kmeans.fit_predict(df.iloc[:,1:])
newdf["label"] = clusters

fig = plt.figure(figsize=(21,10))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(newdf.Age[newdf.label == 0], newdf["Annual Income (k$)"][newdf.label == 0], df["Spending Score (1-100)"][newdf.label == 0], c='blue', s=60)

ax.scatter(newdf.Age[df.label == 1], newdf["Annual Income (k$)"][newdf.label == 1], newdf["Spending Score (1-100)"][newdf.label == 1], c='red', s=60)
ax.scatter(newdf.Age[df.label == 2], newdf["Annual Income (k$)"][newdf.label == 2], df["Spending Score (1-100)"][newdf.label == 2], c='green', s=60)
ax.scatter(newdf.Age[newdf.label == 3], newdf["Annual Income (k$)"][newdf.label == 3], newdf["Spending Score (1-100)"][newdf.label == 3], c='orange', s=60)

ax.view_init(30, 185)
plt.show()

上述代码的输出如下:

作者图片

从上面的图表中,我们可以看到集群分离并不太大。

红色的点与蓝色混合,绿色的点与黄色的点重叠。

这一点,以及剪影分数向我们表明,该模型的表现不是太好。

现在,让我们创建一个比这个模型具有更好的聚类可分性的新模型。

构建聚类模型#2

对于这个模型,让我们做一些特征选择。

我们可以使用一种叫做主成分分析(PCA)的技术。

PCA 是一种帮助我们降低数据集维度的技术。当我们在数据帧上运行 PCA 时,会创建新的组件。这些组件解释了模型中的最大方差。

我们可以选择这些变量的子集,并将它们包含在 K-means 模型中。

现在,让我们对数据集运行 PCA:

pca = PCA(n_components=4)
principalComponents = pca.fit_transform(newdf)

features = range(pca.n_components_)
plt.bar(features, pca.explained_variance_ratio_, color='black')
plt.xlabel('PCA features')
plt.ylabel('variance %')
plt.xticks(features)

PCA_components = pd.DataFrame(principalComponents)

上述代码将呈现以下图表:

作者图片

这张图表向我们展示了每个 PCA 成分,以及它的方差。

基于这种可视化,我们可以看到前两个主成分分析解释了大约 70%的数据集方差。

我们可以将这两个部分输入到模型中。

让我们使用前两个主要成分再次构建模型,并决定要使用的聚类数:

ks = range(1, 10)
inertias = []

for k in ks:
    model = KMeans(n_clusters=k)
    model.fit(PCA_components.iloc[:,:2])
    inertias.append(model.inertia_)

plt.plot(ks, inertias, '-o', color='black')
plt.xlabel('number of clusters, k')
plt.ylabel('inertia')
plt.xticks(ks)
plt.show()

上面的代码将呈现下面的图表:

作者图片

同样,看起来最佳的集群数量是 4。

我们可以用 4 个聚类来计算该模型的轮廓分数:

model = KMeans(n_clusters=4)
model.fit(PCA_components.iloc[:,:2])

# silhouette score
print(silhouette_score(PCA_components.iloc[:,:2], model.labels_, metric='euclidean'))

这个模型的剪影得分是 0.42,比我们之前创建的模型要好。

我们可以像之前一样直观地看到该模型的集群:

model = KMeans(n_clusters=4)

clusters = model.fit_predict(PCA_components.iloc[:,:2])
newdf["label"] = clusters

fig = plt.figure(figsize=(21,10))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(newdf.Age[newdf.label == 0], newdf["Annual Income (k$)"][newdf.label == 0], newdf["Spending Score (1-100)"][newdf.label == 0], c='blue', s=60)
ax.scatter(newdf.Age[newdf.label == 1], newdf["Annual Income (k$)"][newdf.label == 1], newdf["Spending Score (1-100)"][newdf.label == 1], c='red', s=60)
ax.scatter(newdf.Age[newdf.label == 2], newdf["Annual Income (k$)"][newdf.label == 2], newdf["Spending Score (1-100)"][newdf.label == 2], c='green', s=60)

ax.scatter(newdf.Age[newdf.label == 3], newdf["Annual Income (k$)"][newdf.label == 3], newdf["Spending Score (1-100)"][newdf.label == 3], c='orange', s=60)

ax.view_init(30, 185)
plt.show()

模型 1 与模型 2

让我们比较这个模型和第一个模型的聚类可分性:

模型 1

模型 2

请注意,第二个模型中的聚类比第一个模型中的聚类分离得更好。

再者,第二个模特的剪影评分高了很多。

出于这些原因,我们可以选择第二个模型来继续我们的分析。

聚类分析

现在,我们已经完成了这些不同的集群的构建,让我们试着解释它们,看看不同的客户群。

首先,让我们将聚类映射回数据集,并查看数据框的头部。

df = pd.read_csv('Mall_Customers.csv')
df = df.drop(['CustomerID'],axis=1)

# map back clusters to dataframe

pred = model.predict(PCA_components.iloc[:,:2])
frame = pd.DataFrame(df)
frame['cluster'] = pred
frame.head()

作者图片

请注意,数据框中的每一行现在都被分配给了一个聚类。

为了比较不同分类的属性,让我们找出每个分类中所有变量的平均值:

avg_df = df.groupby(['cluster'], as_index=False).mean()
avg_df.show()

作者图片

如果我们把它们形象化,我们就能更容易地解释这些集群。运行这四行代码,得到每个变量的不同可视化效果:

sns.barplot(x='cluster',y='Age',data=avg_df)
sns.barplot(x='cluster',y='Spending Score (1-100)',data=avg_df)
sns.barplot(x='cluster',y='Annual Income (k$)',data=avg_df)

消费得分 vs 年收入 vs 年龄

作者图片

作者图片

作者图片

性别分类

df2 = pd.DataFrame(df.groupby(['cluster','Gender'])['Gender'].count())
df2.head()

作者图片

每个细分市场的主要属性

群集 0:

  • 平均年收入高,支出低。
  • 平均年龄在 40 岁左右,性别以男性为主。

群组 1:

  • 中低收入,平均消费能力。
  • 平均年龄在 50 岁左右,性别以女性为主。

第二组:

  • 平均收入低,支出分数高。
  • 平均年龄在 25 岁左右,性别以女性为主。

第三组:

  • 平均收入高,消费得分高。
  • 平均年龄在 30 岁左右,性别以女性为主。

值得注意的是,计算中值年龄可以更好地了解每个聚类中的年龄分布。

此外,女性在整个数据集中的比例更高,这也是大多数聚类中女性数量多于男性的原因。我们可以找到每个性别相对于整个数据集中的数字的百分比,从而让我们更好地了解性别分布。

围绕每个集群构建人物角色

照片由 Unsplash 上的 h heyerlein 拍摄

既然我们知道了每个集群的属性,我们就可以围绕它们构建角色。

作为数据科学家,能够围绕您的分析讲述一个故事是一项重要的技能。

这将有助于你的客户或利益相关者更容易理解你的发现。

下面是一个基于创建的集群构建消费者角色的示例:

第 0 类:节俭的消费者

这个角色由对金钱非常谨慎的中年人组成。

尽管与所有其他群体中的个人相比,他们的平均收入最高,但他们的支出却最少。

这可能是因为他们有经济责任——比如为孩子的高等教育存钱。

建议:促销、优惠券和折扣代码将吸引这一细分市场的个人,因为他们倾向于减少支出。

群组 1:几乎退休

这部分人由一群老年人组成。

他们挣得更少,花得更少,可能正在为退休存钱。

建议:针对这些人的营销可以通过脸书来完成,这吸引了年龄较大的人群。向这部分人群推广医疗保健相关产品。

集群 2:粗心的买家

这一部分是由较年轻的年龄组组成的。

这部分人中的个人最有可能是第一批就业者。与所有其他细分市场相比,他们赚的钱最少。

然而,他们是非常高的消费者。

这些热情的年轻人享受着美好的生活方式,并且倾向于入不敷出。

建议:由于这些都是年轻人,他们花钱很多,向他们提供旅游优惠券或酒店折扣可能是个好主意。为他们提供顶级服装和化妆品品牌的折扣对这个细分市场也很有效。

集群 3:高度富裕的个人

这部分人是由中年人组成的。

这些人努力工作积累了大量财富。

他们也花大量的钱去过好的生活方式。

这些人可能刚刚组建家庭,过着以婴儿或家庭为中心的生活方式。向这些人推销婴儿或儿童相关产品是个好主意。

建议:由于他们巨大的消费能力和他们的人口统计,这些个人可能会寻找购买或投资的财产。他们也比其他群体更有可能申请住房贷款,并做出严肃的财务承诺。

结论

我们已经成功地建立了一个用于客户细分的 K-Means 聚类模型。我们还探索了集群解释,并分析了每个集群中的个人行为。

最后,我们看了一些可以根据集群中每个个体的属性提供的业务建议。

您可以使用上面的分析作为将来任何集群或细分项目的起始代码。

本帖最初发表于此处。

使用基于 Hadoop 的组件定制气流容器

原文:https://towardsdatascience.com/customize-airflow-container-with-hadoop-based-components-127e89763c21?source=collection_archive---------29-----------------------

在为您的用例构建或修改 docker 映像时,您需要知道什么

照片由德鲁·科林斯在 Unsplash

介绍

最近,我一直致力于建立一个数据管道,将数据从关系数据库管理系统(RDBMS)传输到 Hadoop 生态系统(HDFS)。在有限的时间资源下,我必须在七天内从头开始完成数据管道。此外,我得到的建议是,它应该在三天内完成整个事情。

当时,我对 Hadoop 生态系统配置和 docker 几乎一无所知。我知道什么是分布式系统的概念,但是我自己配置它几乎是不可能的。更容易被之前没有经历过的事情吓到。我想这是很正常的事情。

要求

我深吸了一口气,通读了他们给出的所有业务和技术要求,这些都是对数据管道的要求。

  • 使用广泛的数据框架(如 Apache Spark、Apache Sqoop 或其他大数据框架)构建数据管道。
  • 用 Apache 气流编排数据管道。
  • 为附加的特别查询传递所有业务需求。
  • 使其易于使用 Docker 或 Kubernetes 进行部署。

我有多少知识

总之下面是我接这个项目之前的经历。

  • 听说过 dockerization 这个概念,但从来没用过。幸运的是,的 docker 教程相当精湛。半天之内很容易就能跟上并适应这个项目。
  • 对于编排部分,幸运的是,我刚刚从 Udacity 获得了数据工程 Nanodegree,所以我熟悉气流以及如何作为初学者使用它。如果你对这门课程感兴趣,可以在我的 GitHub 上查看项目内容和我的评论。
  • 关于 Apache Spark,我对 pyspark 比较熟悉,之前在我的数据分析项目中使用过。对于其他像 Sqoop 和 Hive 这样的组件,我要做在职学习,达到他们的技术要求。

在项目开始时,我乐观地认为我可以在规定的时间内完成这件事,但现实生活并不像我想象的那么容易。

你将面临的问题

由塞巴斯蒂安·赫尔曼在 Unsplash 上拍摄的照片

发展环境

当我在 Udacity 参加课程时,他们为我配置了所有的开发环境。我可以直接把代码写到提供的 IDE 上,专心使用 Spark 或者 Airflow 之类的工具。

不幸的是,对于这个项目,我必须自己复制那些环境。首先,我尝试在我的计算机的虚拟环境中安装每个组件。但是我认为不可能将这个项目转移到具有这些复杂依赖关系的另一个实例中。

那是码头工人来救我的地方。我们可以用 docker 构建和封装所有的依赖关系和配置,并轻松地将其转移到另一个实例中。

构建开发环境可以像输入docker compose up -d命令一样简单。配置被放在一个单独的yaml文件中,以便在开发环境中轻松地添加、修改或删除组件。

然而,困难的部分是连接 docker 内部的所有东西

当我提到技术需求时,数据管道应该由 Spark、Sqoop 或其他框架等大数据框架组成。

这意味着您必须在同一个 docker 环境中拥有 airflow、spark 集群、hive 集群和 sqoop 集群,并通过 docker 网络将它们连接起来。

Airflow 为您提供了很大的灵活性,可以与提供商的运营商协调 spark、hive 或 sqoop 工作。 但是您必须先在 airflow docker 中安装所有这些组件才能激活此功能。

然而,当我转移这个项目时,我对修改 docker 容器和配置 Hadoop 组件的了解有限。我通过艰难地将工作从气流容器提交给其他组件来解决这个问题。

简单介绍一下我当时的选择

这里有三种方法将作业从气流提交到另一个容器

  1. 在 Apache airflow 中与提供商的运营商一起提交。这是配置 airflow DAGs 并将任务提交给另一个实例的最推荐方式。
  2. SSHOperator提交。这意味着您将 airflow to SSH 告知另一个实例,并从本地环境运行该命令。对于这种方法,目标实例或集群应该安装 SSH 组件来访问另一个位置。
  3. BASHOperator提交。我转移项目时就是这么做的。要创建您的 airflow 实例,可以访问docker exec命令,从本地 airflow 环境提交作业到另一个实例,不需要 SSH。

在我看来,当时我会选择第一选择和第二选择。

不幸的是,我从 docker hub 中提取的 docker 映像没有安装我想要构建数据管道的所有东西,我无法在 7 天内将所有东西分类。

所以我只能选择第三种。这是我心中的一个结,当我有时间的时候,我会重新讨论这个问题,并使它按照我的预期工作。

这就是为什么我一直写到现在。

保罗·埃施-洛朗在 Unsplash 上的照片

今天,在我花了一些时间学习和重新学习 docker 配置之后。我来这里是为了给你们提供一个定制 docker 容器的实现来达到你们的目的。在我的例子中,要创建一个基于气流的组件,docker 可以将任务提交给另一个 Hadoop 组件。

你可以在我的 GitHub 上找到所有的源代码。

对于实现,本博客不会一行一行地介绍代码,但 会重点介绍您应该关注的基本部分,以及配置这些内容以使其适用于您的用例 的附加材料。我会告诉你将来可能会面临的问题,并处理它,而不是马上解决它。

让我们从基于 Hadoop 的组件开始。

这里我们将安装以下组件 Hadoop 、 Apache Spark 、 Apache Sqoop 和 Apache Hive。

你可以在上面提到的 Github 的一个/docker/hadoop文件夹中找到安装部分的源代码。

要构建任何 docker 映像,您需要一个dockerfile库来配置安装在 docker 中的所有必要的东西。

Hadoop docker 文件示例。作者要点。

通常,docker 文件将以FROM语句开始。这个模式是你应该彻底理解的第一部分。

这一部分最重要的是

有一个 docker hub ,在那里你可以找到很多来自可靠来源的有用的构建图像。为了利用创建的图像的力量,你可以把它放在FROM语句中,作为你的 docker 图像的基础。这里我使用python:3.6-stretch图像作为构建我的自定义图像的基础。

如果你查看 docker hub 中的 python 库,你会发现 docker hub 内部有很多tags。每个标签指的是构建映像的版本。

例如,这里的单词stretch意味着这个映像的底层 OS 版本是 Debian 9。如果你浏览到 docker hub,看到一个类似buster的标签,这意味着这个映像是从 Debian 10 构建的。

了解每个标签的不同细节是这里的重点。

因为无论您稍后安装什么,都将取决于您之前构建的基础映像。我选择python:3.6-stretch的原因是它与我们需要安装的JAVA8兼容,这样我们就可以使用 Hadoop 组件。

开始用的时候只选择最新的,不知道后面会有很多依赖问题。这是我犯的一个巨大的错误。

对于 docker 文件的其他部分,都是关于运行bash命令来安装东西。例如,您可以使用RUN命令顺序安装 Hadoop 组件。您可以使用ENV命令设置 docker 中使用的环境变量。还会有其他有用的命令,比如ADDCOPY。您可以参考本文件了解更多详情。

开始前

为了节省您的时间,我建议您在构建任何映像之前研究每个组件的兼容性。例如,您应该知道哪个 Hive 版本与 Hadoop 3.2.1 版本兼容。在制作映像之前列出所有的依赖项将为您节省大量时间。

范例配置单元要求:作者截图。

有用的资源

对于安装指南,我认为有两个资源非常重要

  1. 第一个资源是每个组件的官方网站。官方文档将告诉您如何完整地构建每个部分,但它没有涵盖您在安装过程中可能面临的所有边缘情况。
  2. 第二个源是 GitHub 源,用于构建与您的用例相似的映像。这是一种更简单的方法,从经过良好测试的代码中寻找,并根据您的工作调整它们构建图像的方式。例如,当我安装 Hadoop 组件时,我会参考来自 pavank 的 GitHub 和 cordon-thiago 的 GitHub 的模式。感谢您的巨大贡献。

分步解决

您可以尝试一个接一个地构建组件,然后在最后将它们合并到一个 docker 文件中。该过程将帮助您确保您的问题仅出在集成部分,而不是安装部分。

这部分会花很多时间来来回回把所有的问题整理出来。一旦你成功建立了 docker 形象,不要太早庆祝。您将需要测试 docker 镜像中的命令行是否如您所期望的那样工作。

要记住的事情

请记住,我们稍后将使用这个基于图像来构建一个气流容器。此外,我需要你知道,使气流容器使用 Hadoop 组件不同于配置 Hadoop 集群。

假设您想要创建一个 spark 集群或 hive 集群来处理数据。将有一个额外的配置要做。例如,如果您想创建一个 spark 集群,您需要提供至少三个容器:一个 spark 主容器和两个 spark 工作容器。dockerfile 配置将不同于我们在这里为气流容器安装的配置。

维奥拉。现在,我们已经在 docker 映像中安装了所有的 Hadoop 组件。我们可以在以后安装气流组件时参考它。干得好,伙计们。

让我们安装气流。

docker 的好处是,你可以基于另一个图像构建一个图像。这种能力使得基于图像可以被重用用于许多不同的目的。

我们将使用最近构建的基于 Hadoop 的容器来安装额外的气流组件。

这听起来很无聊,但基本概念是一样的。

你可以在上面提到的 Github 的一个/docker/airflow文件夹中找到安装部分的源代码。

在这里,我遵循从帕克尔的气流 docker 安装气流的模式。这是一个气流容器,从 docker hub 拉起超过 1000 万次。拉取请求的数量似乎是构建气流图像的可靠来源。

理解底层的依赖关系是你所需要的

如果你还记得这一点,我之前提到过我们构建的底层图像。你会发现 puckel 的原始 docker 图像是从python:3.7-slim-buster开始构建的,但我们将其改为python:3.6-stretch

这是我们修改气流运行的底层操作系统的地方。

有了这个小变化,我要说当时很多麻烦都找上我了。问题可能来自任何来源。apt-getpip或者airflow本身。

简而言之,我花了整整两天的时间来解决所有的依赖问题。它花费的时间比我想象的要多得多,我敢打赌,对任何人来说,这都是一个非常烦人的过程。

反复试验

一些问题可以通过更多的apt-getpip安装来解决,但是对于一些问题,您可能需要重新考虑您构建的底层映像是否需要改变。这里没有快速的胜利。

即使我可以构建 docker 映像,有时,airflow webserver 也无法在容器内运行,并永远在重启循环中继续。

大量的谷歌搜索和 StackOverflow 是现在唯一能救你的东西。我花很多时间一个一个解决问题。

我完全理解为什么很多更新的工具不会在技术发布的第一天到来。气流版本的微小变化可能会无缘无故地毁掉一切。

最终,努力是有回报的。我们得到了一个包含基于 Hadoop 的组件的气流容器。要跳过所有这些过程,您可以从我的 docker hub 中提取图像。但是我鼓励你从头开始构建这个图像。

至少你学到了一些新东西。

它可以帮助你学习很多重要的东西,并让你有能力在未来解决问题,而不是等待别人为你更新图像。

你将有权添加或删除你想要的东西,使你的 docker 图像更容易操作和维护。

下一步是什么

下一个任务是将构建的映像插入到数据管道项目中。不幸的是,数据管道仍在审查过程中,我认为它仍然不能与大家分享。

所以,我们稍微等一下,我会写一下把这个 docker 镜像拿来做一个数据管道的过程。

最终想法

路易斯·汉瑟在 Unsplash 上拍摄的照片

我承认,当你设计一个新项目的原型时,docker 让你的生活变得更加容易。但是当你必须生产它的时候。会有很多你必须知道的检查清单。依赖问题是其中最主要的问题。

docker 的另一个好处是,你把一切都写成代码;因此,您可以为新的底层计算机架构快速构建 docker 映像,并使用 Git 命令更改配置和保存每个版本。

我鼓励每个人都使用 docker,而不是在虚拟环境中安装许多东西,并产生一个可重复的问题。

要将环境或数据管道从一个实例迁移到另一个实例,或者使其可再现,需要许多技术和最佳实践来使其尽可能平稳。这个领域有很多东西要学。

在我看来,当你是一名数据科学家或数据分析师时,拥有这些技能是非常令人印象深刻的。我们通常会忽略这些东西,更多地关注我们的 Jupyter 笔记本。这项技能将拓展你的专业知识,帮助你独立完成更令人兴奋的项目。

帕泰鲁什·西达

如果你喜欢这篇文章,并希望看到更多这样的东西。

  • 在媒上关注我,或者在 LinkedIn 上联系我。

定制您的 Jupyter 笔记本

原文:https://towardsdatascience.com/customize-your-jupyter-notebooks-6687f23838b?source=collection_archive---------28-----------------------

Jupyter 笔记本主题

图片来自 Pixabay 的像素

简介

Jupyter Notebook 是一个很棒的编程环境,通常是用 python 编码的数据科学家或数据分析师最受欢迎的选择。不幸的是,它的默认设置不允许您在标准编程环境(如 PyCharm 或类似工具)中进行定制。

Jupyter 笔记本主题试图缩小这种差距,让你用主题让笔记本看起来更漂亮,功能更强大。在本文中,我将带您了解 Jupyter 笔记本主题的安装过程,并向您展示一些最重要的功能。

安装

Jupyter Notebook themes 是一个开源库,可以通过 pip install 安装。只需在命令行中键入以下代码:

pip install jupyterthemes

这将触发最新版本的安装。一旦完成,你应该能够在主题之间切换,调整笔记本中使用的字体,或者定制情节的风格。我们将在接下来的章节中详细介绍这些特性。

改变主题

安装完成后,您可以正常启动 Jupyter 笔记本,并从笔记本内部检查主题。

为了列出所有可能的主题,您可以使用以下代码:

!jt -l

正如你所看到的,目前有九个主题可用。为了切换主题,您可以使用以下命令:

!jt -t <theme_name>

让我们选择 onedork 主题。

!jt -t onedork

你会发现主题并没有立即改变。有些人报告说,他们可以重新加载页面,然后看到效果。从我个人的经验来看,我必须重启 Jupyter Notebook 才能改变主题。只需停止笔记本并再次启动它。这是它在加载时应该看起来的样子。

现在,你可以玩不同的主题,选择你最喜欢的一个。

你会注意到,默认情况下,标准 GUI 的某些部分在主题设置中是不可见的。我指的是下图的部分。

为了切换主题但保持标准的 GUI 外观,您可以使用以下代码变体。

!jt -t <theme_name> -T -N -kl

onedork 主题,这些会喜欢的。

!jt -t onedork -T -N -kl

重新启动 Jupyter 笔记本应该会得到类似下面截图的结果。

为了将笔记本恢复到默认设置,您可以使用此代码。

!jt -r

请注意,我已经在 Jupyter 笔记本中显示了正在执行的命令,但是您也可以在终端窗口中不带感叹号地使用它们。

设置绘图风格

一旦你使用了主题,你会注意到用 Matplotlib 库创建的图形看起来不是最好的。例如,这是一个创建折线图的简单代码。

import matplotlib.pyplot as plt
%matplotlib inlinebp_x = np.linspace(0, 2*np.pi, num=40, endpoint=True)
bp_y = np.sin(bp_x)# Make the plot
plt.plot(bp_x, bp_y, linewidth=3, linestyle="--",
         color="blue", label=r"Legend label $\sin(x)$")
plt.xlabel(r"Description of $x$ coordinate (units)")
plt.ylabel(r"Description of $y$ coordinate (units)")
plt.title(r"Title here (remove for papers)")
plt.xlim(0, 2*np.pi)
plt.ylim(-1.1, 1.1)
plt.legend(loc="lower left")
plt.show()

这是在没有定制的情况下使用 onedork 主题在笔记本中创建的情节截图。

这绝对不符合你选择的主题。事实证明,为了定制 Matplotlib 以匹配主题,您需要在笔记本顶部添加两行额外的代码。

from jupyterthemes import jtplot
jtplot.style()

一旦您运行了相同的图表代码(上面的两个代码行被添加到笔记本的顶部),您应该会看到图表现在与主题的当前样式相匹配。

这样看起来好多了!

实际上,您可以更改图表样式,以匹配您想要的任何主题。

from jupyterthemes import jtplot
jtplot.style(<theme_name>)

如果您没有为样式函数提供参数主题,它将使用笔记本中当前加载的主题。

注意与主题设置不同,无需通过更改 Matplotlib 绘图样式来重新启动笔记本。

改变字体

Jupyter 笔记本主题不仅允许你改变主题,还可以对笔记本中使用的字体做一些额外的定制。

当用 jt 命令加载一个主题并添加一些额外的参数时,你可以改变字体。您可以自定义…

  • 用于代码的字体(-f)及其大小(-fs),
  • 用于笔记本的字体(-nf)及其大小(-nfs),
  • 用于文本/降价的字体(-英尺)及其大小(-英尺)。

总结

在本文中,您已经学习了如何使用 Jupyter 笔记本主题定制您的标准 Jupyter 笔记本。我们仔细检查了库的安装细节,并设置了主题,包括图形和字体定制。

你现在应该可以自己尝试了。

快乐定制!

最初发布于 aboutdatablog.com: 用 Jupyter 笔记本主题,定制你的 Jupyter 笔记本 2021 年 1 月 20 日。

PS:我正在 Medium 和https://www.aboutdatablog.com/上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的* 邮件列表 *每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入**

下面是一些你可能会喜欢的帖子

** </9-things-you-did-not-know-about-jupyter-notebook-d0d995a8efb3> **

定制您的熊猫数据框以进行有效的数据分析

原文:https://towardsdatascience.com/customize-your-pandas-data-frame-for-effective-data-analysis-ffa8b98630fb?source=collection_archive---------16-----------------------

使用 Pandas Styler 增强您的分析

照片由丹尼尔·库鲁维拉在 Unsplash 上拍摄

介绍

Pandas 是一个强大的数据操作和分析包,我相信这个库对你们很多人来说并不陌生。然而,有时当我以表格形式分析数据时,我观察到的都是简单的数字,很难注意到值的特征。我想,如果我能在我的 Pandas 数据框中应用更多的可视化组件或条件格式,那就太好了。

幸运的是,我找到了 Styler 对象。 这个表格可视化工具真的让数据框很有诱惑力,信息量大,很多情况下容易跟踪。

Styler 对象是什么?

数据加载到数据框后,我们可以设置表格的样式。Styler 下的基本动作机制是制作一个 HTML 表格,应用 CSS 样式来管理颜色、背景、字体等不同属性。DataFrame.style属性返回一个 样式器 对象。它支持 Jupyter Notebook 中的自动渲染,因为它定义了一个_repr_html_方法。

让我们看看 Styler 可以对我们的数据表做些什么。

首先,让我们创建一个简单的数据,这样我就可以详细解释这个有效的工具。在我的数据集中,您可以看到产品名称和价格,以及购买这些产品的人的名单。

图 1:数据框架——作者图片

隐藏列

如果我不需要“owner”列,并且想暂时从数据中隐藏它,我可以使用hide_columns()方法。

df.style.hide_columns('price')

正如你所看到的,下面的结果已经隐藏了【拥有者】列。

输出:

图 2:隐藏的所有者列—作者图片

突出显示空值

注意空值在分析中很重要。为了观察这些空值,我们可以突出显示它们以便于观察。highlight_null在这种情况下使用属性。例如,在我的数据集中,我可以看到我的表数据没有 Mike 购买的产品名称。

df.style.highlight_null(null_color="yellow")

输出:

图 3:突出显示空值—作者图片

突出显示最小/最大值

如果我想知道谁购买的最多或最少,我可以在列表中用highlight_minhighlight_max突出显示最小/最大购买金额。

让我们看看谁花钱最多:

df.groupby('owner').agg({'price':'sum'}).reset_index().style.highlight_max(color = 'green') 

输出:

图 4:突出最大价值——作者图片。

以 669 的消费金额,罗斯是购买最多的人。

同样,通过应用highlight_min,很明显珍是花费最少的人。

df.groupby('owner').agg({'price':'sum'}).reset_index().style.highlight_min(color = 'red')

输出:

图 5:突出显示最小值——作者图片。

突出显示分位数

您也可以突出显示由分位数定义的值。例如,在这种情况下,我想突出显示所有产品价格的 90%百分比值。我可以用highlight_quantile做到

df[['price']].style.highlight_quantile(q_left=0.9, axis=None, color='yellow') 

输出:

图 6:突出显示 90%的分位数值——作者图片

创建热图

热图有助于使用颜色阴影显示值。颜色阴影越强烈,数值越大。您可以选择使用背景渐变或文本渐变方法自定义热图。

例如,要为包含 5 个不同类别 A、B、C、D、E 中的值的数据集创建热图:

图 7:数据集 df3 -作者图片

首先,我们可以应用style.background_gradient我们甚至可以结合 seaborn 来获得更好的颜色。

import seaborn as sns
cm = sns.light_palette("pink", as_cmap=True)
df3.style.background_gradient(cmap=cm) 

输出:

图 8:热图渐变背景—作者图片

如果我们不想用背景颜色定制我们的表格,我们可以考虑使用text_gradient方法。

cm = sns.light_palette("green", as_cmap=True)
df3.style.text_gradient(cmap=cm)

输出:

图 9:文本渐变—作者图片

创建条形图

现在您可以让df.style.bar以零值为中心,并且您可以将一个列表[color_negative, color_positive]传递给这些值以获得您的条形图。

我会以负/正条形图的形式展示我的价值观。看这个,是不是很容易区分正负价值。

df3.style.bar(subset=['A', 'B'], align="zero", color=['pink', 'lightgreen'])

输出:

图 10:正负条形图

添加标题

在分析报告中,通常有许多数据框。为了了解每个数据帧描述的内容并区分它们,可以添加标题以获得更详细的信息。

例如,我想将我的热图表命名为“Chi Nguyen Medium Data”。我可以通过使用styleset_caption属性来实现

df3.style.set_caption("Chi Nguyen Medium Data").background_gradient()

输出:

图 11:添加的标题——作者的图片

用你自己的方式设计

尽管有许多方法可用于设置数据框的样式,但在某些情况下,您将需要自己的自定义函数来完成任务。让我们用一个例子来看看如何创建你的函数。

在我的数据集中,我想说明所有大于其列平均值的值。我将用蓝色突出显示较大的值,用粉色突出显示较小的值。下面是我如何定义我的函数并返回结果。

#Define function
def mean_greater(m):
    greater = m > m.mean()
    return ['background-color: lightblue' if i else 'background-color: pink' for i in greater]#Apply function
df3.style.apply(mean_greater)

输出:

图 12:突出显示值

结论

虽然设计数据框架只是分析中非常小的一步,但我相信灵活定制不同的设计方法可以帮助提高我们的分析速度,并为我们提供更全面的观察和数据见解。

从最容易的,看似最不重要的开始,一点一点地积累你的技能,这从来都不过分。

参考

https://pandas.pydata.org/docs/user_guide/style.html#Styler-Functions

在 Power BI 中定制 Google Analytics 可视化

原文:https://towardsdatascience.com/customizing-google-analytics-visual-in-power-bi-7b36378d02e2?source=collection_archive---------43-----------------------

您是否曾经想要在 Power BI 中创建自己的自定义视觉效果?几乎没有创意,学习如何模仿谷歌分析仪表板众所周知的视觉“外观和感觉”

作者图片

我是强力 BI 的超级粉丝,我也不隐瞒!我非常喜欢 Power BI 的一点是它有非常大的视觉效果集合,既有内置的,也有来自应用程序资源市场的定制视觉效果。

老实说,很难想象您的数据故事没有 Power BI 视觉效果支持的场景!然而,我最近接到一个请求,说我已经有了如何向用户讲述这个故事的想法,但我找不到一种恰当的方式来交流数字!

对,就是这个道理!我的想法是使用类似谷歌分析仪表板的视觉效果,看起来很简单,但同时也很强大:

谷歌分析仪表板—作者图片

这种视觉效果能让你快速洞察最相关的趋势。没有数字,什么都没有——只是像“热图”一样的东西,所以你可以在几秒钟内发现你的网站访问量最大的时候!

我已经写了如何将普通的矩阵视觉转换成这样,但是这次我需要一个额外的图层。

方案

请求是显示在一年的特定时间哪个品牌级别(豪华、普通或经济)的销售额最高。但是,作为一个附加层,报告消费者需要看到按性别细分的数字,并根据结果,在一年的选定时期内,针对各自的性别创建特殊的营销活动。

让我们使用一个样本 Contoso 数据库来说明真实的用例。这是开始时的样子:

作者图片

构建解决方案

如你所见,这只是一个普通的旧矩阵,显示每个月的总销售额,按品牌类别细分。让我们首先将性别信息添加到我们的矩阵中,并从这个角度来看这些数字:

作者图片

我已经在矩阵的列中添加了性别,但是为了在视觉本身中看到它们,我需要右击矩阵并选择扩展到下一级。一旦我这样做了,我就能看到每个品牌类别中按性别分列的数字:

作者图片

好了,现在我们准备开始变魔术了:)

第一步是从我们的报告中排除空白性别(这可以通过过滤器轻松实现),打开格式窗格,直接进入条件格式,并打开背景颜色属性:

作者图片

一旦打开背景色,Power BI 将自动应用一些渐变颜色,但我们需要对其进行更多控制,因此我们将转到高级控制,并为最低和最高值定义我们的颜色:

作者图片

我们需要做的下一件事是对字体颜色属性应用完全相同的步骤:

作者图片

嘣!我们接近了我们想要复制(或者模仿,如果你喜欢那样)的谷歌分析视觉:

这已经让人想起了谷歌视觉分析——作者图片

抛光溶液

首先,让我们确保所有的列长度相同,不管矩阵单元格中出现的是什么值。为了实现这一点,我将使用来自力量匕家伙 的这个非常酷的技巧。

诀窍是创建一个虚拟的 DAX 度量来保存固定数量的相同字符,确保打开列标题下的自动调整列宽属性,然后将该度量放入矩阵行,然后关闭自动调整列宽,最后删除虚拟度量!

Dummy = REPT("0",10)

REPT 函数将重复您传递的文本,重复的次数由您在第二个参数中指定。在我的虚拟测量中,我放了 10 个零:

作者图片

现在,我需要打开“值”下的“在行上显示”属性:

作者图片

我知道这看起来很奇怪,但不要担心,我们会很快调整它!关闭自动调整列宽功能,并从矩阵中删除虚拟度量值:

作者图片

我们现在 100%确定我们的列将具有相同的宽度,尽管各个单元格中的值是相同的!

现在让我们在这些单元格之间创建一些空间!转到网格,打开垂直和水平网格,增加网格厚度(我已经把 8,但你可以根据你的需要调整)。现在,我的视觉效果看起来几乎和谷歌分析仪表板中的一模一样:

作者图片

这多酷啊!我可以很快识别趋势,并立即得出一些结论:例如,五月和六月是豪华班的摇摆月,而普通班在上半年的表现相当好!最棒的是,我可以在 3 秒钟内识别出这些趋势!

让我们做一个更漂亮的,而不是字母 F 和 M 的性别,创建漂亮的图标。你如何实现这一点?转到 Customer 表(或任何保存性别数据的表)并创建一个新列:

Gender Icons = IF(Customer[Gender]="M","♂","♀")

这里的诀窍是使用图标而不是字母:对于女性图标,只需在键盘上按 ALT+12,而对于男性图标,则需要按 ALT+11。就这么简单!IF 函数将检查性别列的值,并根据条件是否满足,分配一个适当的图标。

这是我们的最终解决方案:

作者图片

如果你问我,那看起来比我们的开始报告页更酷!不仅仅是它看起来更花哨、更现代,它还能让您在几秒钟内讲述一个数据故事!当然,如果您的用户需要检查准确的数字,数字仍然在那里,如果您将鼠标悬停在这些漂亮的蓝色数据条上,您会看到工具提示会像一个魔咒一样工作:

作者图片

结论

老实说,我有点失望 Power BI 没有为您提供开箱即用的可视化,这将带来与 Google Analytics visual 相同的体验。或者,至少我不知道它的存在:)

然而,通过一点点创意和一些小调整,我们能够复制谷歌分析视觉的“外观和感觉”。或者,让我大胆地说: 我们刚刚创建了一个自定义的电源 BI 视觉

感谢阅读!

自定义 NetworkX 图表

原文:https://towardsdatascience.com/customizing-networkx-graphs-f80b4e69bedf?source=collection_archive---------2-----------------------

数据科学

您的一站式网络购物中心

图论是一个非常有效的数据科学工具,它允许你可视化和理解复杂的交互。作为开源项目的一部分,我从许多主要来源收集了信息,以构建纽约市专业剧院灯光设计师之间的关系图。

作者图片

我使用了 NetworkX,这是一个用于构建图形的 Python 包,它有大部分可用的缺省值,但是利用 matplotlib 允许我们定制图形的几乎每一个可以想到的方面。我知道我脑子里想的是什么样子,但是在花了很多时间搜索文档和 StackOverflow 之后,我决定创建这个一站式商店来存放我学到的如何改变的所有东西!现在,您也可以构建易读的图表来帮助可视化复杂的关系。

创建网络 x 图

我们将从制作基本图形开始!有几种方法可以做到这一点。我发现最简单的方法是从熊猫数据框中指定边缘。什么是优势?嗯,图是用节点和边构建的。一个节点代表某个对象,可能是一个人或组织,一条边代表从一个节点到另一个节点的实际连接。所以在下面的例子中,“A”、“B”、“C”和“D”是节点,它们之间的线是边。

作者图片

节点颜色

我们也可以很容易地改变所有节点的颜色。您会注意到这样一种模式,即在全局范围内改变图形的特性非常简单(使用。draw()方法)。

作者图片

按节点类型划分的节点颜色

但是,假设我们想按类型具体地改变节点的颜色,而不是全局地改变。这需要一点设置,但一旦到位,我们可以快速添加新的类型,并自动相应地着色。基本上,我们创建另一个数据帧,指定节点 ID 和节点类型,并使用 pd。Categorical()方法来应用色彩映射表。

所以现在我们的字母节点是蓝色的,数字节点是橙色的!

作者图片

节点大小

通过。draw()方法—只需指定 node_size!

作者图片

按节点类型划分的节点大小

我们可以通过类型改变节点大小,就像我们可以改变颜色一样!我发现这对于将人与组织联系起来非常有用,因为组织有许多相关的人,所以将他们想象成以人为辐条的枢纽是有意义的。

因此,我们将根据我们的节点颜色按类型示例进行构建,但是我们将传入一个节点大小列表,引用用于选择节点颜色的节点类型,而不是 node_size 的单个关键字参数。

如果有人在挣扎,这是一个理解逻辑的列表

对于数据帧中的每个节点,如果该节点的类型不是“字母”,则将节点大小设置为 4000,否则将节点大小设置为 1000。结果是任何不是字母的东西都将是一个更大的节点。目前只有两种节点类型,这可能有点过了,但以后会更好地扩展。

node_sizes = [4000 if entry != 'Letter' else 1000 for entry in carac.type]

作者图片

手动节点大小

如果我们不需要按类型改变节点大小,而只是想引起对特定节点的注意,我们可以手动指定一个大小列表。这些需要与节点存储的顺序相同,所以调用 G.nodes()来生成一个列表。一些有代表性的尺寸标在下面,这样你就可以知道它们的相对尺寸。我发现 5000 英镑是一个很好的中间值,名字和姓氏都很合适。

作者图片

边缘宽度

现在我们已经讨论了节点属性,我们可以移动到边。设置全局边的大小或颜色与设置节点一样简单,只需在。draw()方法。

作者图片

边缘颜色

通过传入属性列表而不是单个值,可以单独而不是全局地给边着色或调整大小。因此,下面我们有边 _ 颜色和边 _ 宽度,将通过循环。

作者图片

节点边框颜色

最后,我们还可以用一个容易混淆的关键字“edgecolors”给节点添加一个彩色边框,这个关键字和“edge_color”是不一样的。这可以用来帮助澄清和分离节点,您可以在下面的示例图中看到。

作者图片

图表布局

图表最重要的一个方面是它的布局。这将最终决定图表的可读性和有用性。NetworkX 有许多决定布局的选项,我在下面介绍了其中最流行的 4 个。缺省值是 spring_layout,它在上述所有情况下都被使用,但是根据您的使用情况,其他的也有优点。我建议尝试几种,看看哪种效果最好。

你可以在这里查看布局文档。

作者图片

一个示例网络—将它连接在一起

这里有一个完全实现的例子,来自我上面描述的项目。我创建了一个杰出的专业灯光设计师与剧院设计领域一些杰出的大学和组织的关系图。目标是确定个人关系如何影响紧密结合的剧院设计师世界。

你会注意到文本本身也可以被修改。代码都在下面,但是你可以使用像 font_size 和 font_weight 这样的关键字。此外,在节点标题中接受换行符“\n ”,这通常会增加可读性。例如,John Gleason 的节点在数据帧中被列为“John \ nGleason”。

作者图片

结论

我希望本指南为您提供了如何定制 NetworkX 图形的大多数方面以增加可读性的工作示例。NetworkX 是一个非常强大的包,虽然它的缺省值非常好,但是随着项目的扩展,您会希望注意到不同的信息。这可以通过多种方式实现,但改变节点大小和颜色、边宽和图形布局是一个很好的起点。

连接

我一直在寻找连接和探索其他项目!你可以在 GitHub 或 LinkedIn 上关注我,并在媒体上查看我的其他故事。我也有一个推特!

为熊猫简介带来定制

原文:https://towardsdatascience.com/customizing-pandas-profiling-summaries-b16714d0dac9?source=collection_archive---------20-----------------------

小窍门

利用视觉类型系统获取乐趣和利润

如果您以前使用过 pandas-profiling ,您可能会观察到列汇总对于数据中每个要素的数据类型是唯一的。然而,直到最近还不可能定制这些摘要,所以,如果你想自动计算一系列形状优美的几何图形的平均表面积,或者一系列电子邮件地址中的域名集,你就没有运气了——直到现在。

最近完成的 pandas-profiling 到 visions 类型系统的迁移带来了完全可定制的类型检测逻辑、摘要算法,并且是包括定制渲染在内的端到端报告定制的第一步。在这篇博文的剩余部分,我将向你展示如何开始使用 visions,并使用 pandas-profiling 轻松定制你的数据摘要。

对排版的简单介绍

默认的 pandas-profiling 类型系统由四种基本数据类型组成:

  • 种类
  • 日期时间
  • 布尔代数学体系的
  • 数字的

从技术上讲,还有第五种总括类型,称为不支持不适合其他四种类型的任何对象(这些通常是复杂的对象,如列表)。如果你想检查它的实现,检查一下在pandas_profiling.model.typeset中找到的ProfilingTypeSet对象。

作者图片

注意:你需要安装pydotpygraphviz来重现这些情节

这些排版可以是复杂的,也可以是简单的,只要你的用例需要。想区分整数和浮点数?字符串中的 URL?文件中的图像?您的数据还有什么特别之处吗?你可以在 pandas-profiling 中找到这些类型中的大多数,在 visions 中有更多可用的,如果没有,编写自己的代码通常只是几行代码。类型和类型系统的完整介绍可以在这里找到。

自定义摘要

首先,让我们下载泰坦尼克号数据集的副本,并将Survived字段转换为布尔值。

现在我们有了一些数据,我们可以使用 pandas-profiling 来创建一个配置文件报告。

作者图片

这里没有惊喜,只是标准的熊猫概况工作流程。除了普通的 html 报告,我们可以通过报告上的description_set属性直接检查由 pandas-profiling 计算的汇总值。让我们来看看我们对Survived属性的总结。

{'n_distinct': 2,
 'p_distinct': 0.002244668911335578,
 'is_unique': False,
 'n_unique': 0,
 'p_unique': 0.0,
 'type': Boolean,
 'hashable': True,
 'value_counts_without_nan': False    549
 True     342
 Name: Survived, dtype: int64,
 'n_missing': 0,
 'n': 891,
 'p_missing': 0.0,
 'count': 891,
 'memory_size': 1019}

这里有很多有用的信息:内存使用情况、序列值是否可散列、缺失值计数等。默认情况下,每个布尔序列都会收到一个相同的摘要——现在,多亏了摘要器,我们可以自定义这些结果!

总结者

在幕后,pandas-profiling使用一个PandasProfilingSummarizer对象为概要文件报告生成摘要。这些汇总器将数据类型(如 Boolean)映射到用于创建最终汇总的汇总函数列表。

您可以直接从这个摘要器中复制上面的摘要,如下所示:

{'n_distinct': 2,
 'p_distinct': 0.002244668911335578,
 'is_unique': False,
 'n_unique': 0,
 'p_unique': 0.0,
 'type': Boolean,
 'hashable': True,
 'value_counts_without_nan': False    549
 True     342
 Name: Survived, dtype: int64,
 'n_missing': 0,
 'n': 891,
 'p_missing': 0.0,
 'count': 891,
 'memory_size': 1019}

为了定制摘要,我们需要为排版中的每种数据类型指定一系列要调用的函数。类型在很大程度上支持算术,正如您自然期望的那样,将两种类型加在一起,如Boolean + Unsupported,会产生包含 Boolean 和 Unsupported 的排版。

将这些结合在一起,让我们编写一个总结器,计算所有数据类型的每个序列的长度,另外,计算布尔型的概率True

尽管这看起来很复杂,但本质上它只是跟踪一系列不同数据类型上调用的函数。在幕后,summarizer 对象负责将汇总函数组合在一起,以产生一个最终结果,并附加一个“type”值来指示使用了哪个汇总。

{'type': Boolean, 'length': 891, 'probability_true': 0.3838383838383838}
{'type': Unsupported, 'length': 891}

虽然摘要器现在是完全可定制的,但是相关的 html 渲染还没有更新以显示定制的统计数据,所以请注意将来的其他更新。

自定义配置文件报告摘要

虽然你现在可以在 pandas 中定制概要——根据你的心的内容进行描述,但是在大多数情况下,你将会修改或者添加默认的概要,而不是从头开始构建一个。这也很简单,只需将你想要的任何新功能添加到它的关联类型中!让我们更新默认的 PandasProfilingSummarizier,以包含new_boolean_summary函数,并运行一个具有新功能的报告

{'n_distinct': 2,
 'p_distinct': 0.002244668911335578,
 'is_unique': False,
 'n_unique': 0,
 'p_unique': 0.0,
 'type': Boolean,
 'hashable': True,
 'value_counts_without_nan': False    549
 True     342
 Name: Survived, dtype: int64,
 'n_missing': 0,
 'n': 891,
 'p_missing': 0.0,
 'count': 891,
 'memory_size': 1019,
 'probability_true': 0.3838383838383838}

瞧,就这样,我们能够将probability_true计算插入到我们的配置文件报告中。

结论

到目前为止,我们对 visions 提供的定义高级数据类型和支持用户定义功能的灵活性非常满意。我们很高兴很快开始推出更多这些功能,包括对定制渲染的支持,并渴望收集反馈。你是如何使用定制的类型和摘要的,或者你有什么有趣的用例值得添加到熊猫档案中?如果有,请在下面评论分享!

使用 BaseEstimator、TransformerMixin 和 FeatureUnion 定制您的 Sklearn 管道

原文:https://towardsdatascience.com/customizing-sklearn-pipelines-transformermixin-a54341d8d624?source=collection_archive---------8-----------------------

如何为 Sklearn 管道创建自定义转换器

阿瑟尼·托古列夫在 Unsplash 上的照片

Scikit-Learn 最常用和最受欢迎的特性之一是管道。虽然它们的使用是可选的,但是它们可以用来使我们的代码更干净,更容易维护。管道接受估算器作为输入,它们是从sk learn . base . base estimator继承的类,并且包含 fittransform 方法。这允许我们使用 Sklearn 默认不提供的功能定制管道。

我们将讨论 transformers ,对输入进行转换的对象。我们将继承的类是 TransformerMixin,但是也可以从 ClassifierMixin、RegressionMixin、ClusterMixin 和其他类扩展来创建一个定制的估计器。阅读此处的所有可用选项。

我们将使用文本数据的数据集,我们希望对其应用转换,例如:

  • 文本预处理
  • TF-IDF 矢量化
  • 创建附加功能,如情感、字符数和句子数

这将通过使用 Pipeline 和 FeatureUnion 来完成,后者是一个 Sklearn 类,它组合了来自不同来源的特性集。

数据集

我们将使用 Sklearn 提供的数据集 20newsgroups ,快速访问大量文本数据。出于演示的目的,我将只使用 10 个文本的样本,但该示例可以扩展到任何数量的文本。

让我们导入数据集

文本特征的创建

我们将构建包含这些信息的特性集

  • 应用预处理后使用 TF-IDF 进行矢量化
  • 与 NLTK 的感悟。维德
  • 文本中的字符数
  • 课文中的句子数量

我们的流程不使用管道,而是用单独的代码块顺序应用所有这些步骤。管道的美妙之处在于,排序是在单个代码块中维护的——管道本身变成了一个估计器,能够在一条语句中执行所有操作。

让我们创建我们的函数

我们的目标是创建一个独特的特征集,以便为某项任务训练一个模型。我们将使用管道和 FeatureUnion 把我们的矩阵放在一起。

如何合并不同来源的要素

TF-IDF 矢量化将创建一个稀疏矩阵,该矩阵将具有维度n _ documents _ in _ corpusn _ features,情感将是单个数字,以及 n_chars 和 n_sentences 的输出。我们将获取每个步骤的输出,并创建一个包含所有输出的矩阵,这样我们就可以根据我们设计的所有功能训练一个模型*。我们将从这样的模式开始

事物的初始状态。图片作者。

并达到这个最终的表现

FeatureUnion 的工作原理。图片作者。

该特征集将被用作我们模型的训练向量。

从 BaseEstimator 和 TransformerMixin 继承的类

为了让我们的过程继续下去,我们需要定义类以及它们将在管道中做什么。让我们从创建一个 DummyEstimator 开始,我们将从它继承 init、fit 和 transform。DummyEstimator 是一个方便的类,它让我们不必编写多余的代码。

DummyEstimator 将从四个类继承:SparseToArray 的预处理器感知分析NChars内容

如您所见,DummyEstimator 只允许我们定义转换函数,因为其他所有类都从 DummyEstimator 继承了其 initfit

现在让我们看看如何实现矢量化管道,,它将考虑到我们的文本预处理。

剩下要做的就是应用 FeatureUnion 将这些片段组合在一起

特征联合的步骤和估计量。图片作者。

让我们在语料库上检查一下 fit_transform 的输出

FeatureUnion 的输出-四个数据源合并在一个矩阵中。图片作者。

输出似乎是正确的!虽然不是很清楚。我们通过将组合的特征集插入数据帧来结束本教程

结果如下(出于可读性的原因,我在这里截断了结果)

熊猫数据框架中的联合特征集。图片作者。

我们现在有了一个数据集,可以随时提供给任何训练模型。用sk learn . preprocessing . standard scaler或类似的东西进行实验,并使 n _ chars 和 n_sentences 正常化,这将是有用的。我将把这个练习留给读者。

结论

我们已经看到了 Sklearn 中的 BaseEstimatorTransformerMixinFeatureUnion 类的基本操作可以为我们的定制项目做些什么。

它使我们能够创建定制的预处理类,并在管道中连接特性集。

这种方法提高了生产率和干净的代码并且可以帮助整个团队构建脚本和笔记本。

我希望你今天学到了新的东西,并且在你的代码库中应用了这些原则!😀

推荐阅读

对于感兴趣的人来说,这里有一个我为每个与 ML 相关的主题推荐的书籍列表。在我看来,有一些必不可少的书籍对我的职业生涯产生了巨大影响。
免责声明:这些是亚马逊会员链接。我会收到亚马逊为你推荐这些项目的一小笔佣金。你的体验不会改变,你也不会被收取更多费用,但它将帮助我扩大业务规模,围绕人工智能制作更多内容。

  • ML 简介 : 自信的数据技能:掌握处理数据的基本原理,为你的职业生涯增压 作者:基里尔·叶列缅科
  • sk Learn/tensor flow:使用 Scikit-Learn、Keras 和 TensorFlow 进行动手机器学习
  • NLP : 文本即数据:机器学习和社会科学的新框架 作者贾斯汀·格里默
  • sk Learn/PyTorch:用 py torch 和 Scikit 进行机器学习——Learn:用 Python 开发机器学习和深度学习模型 塞巴斯蒂安·拉什卡著
  • 数据即 : 用数据讲故事:商务人士数据可视化指南 科尔·克纳弗利克著

有用的链接(我写的)

  • 学习如何用 Python 执行顶层探索性数据分析 : 用 Python 执行探索性数据分析——一步一步的过程
  • 学习 TensorFlow 的基础知识:tensor flow 2.0 入门—深度学习入门
  • 用 Python 中的 TF-IDF 进行文本聚类 : 用 Python 中的 TF-IDF 进行文本聚类

如果你想支持我的内容创作活动,欢迎点击我下面的推荐链接,加入 Medium 的会员计划。我将收到你投资的一部分,你将能够以无缝的方式访问 Medium 的大量数据科学文章。

*https://medium.com/@theDrewDag/membership

密码*

CyberBrain:像专家一样调试 Python 程序

原文:https://towardsdatascience.com/cyberbrain-debugging-python-programs-like-a-pro-dbedbfa25800?source=collection_archive---------10-----------------------

Python 调试被重新定义

乔希·里默尔在 Unsplash 上的照片

调试这个词意味着修复程序中潜在的错误。调试的基本步骤包括识别缺陷的存在、隔离缺陷的来源、确定缺陷的原因、确定缺陷的修复方法、应用修复方法并进行测试。— 计算机编程原理/维护/调试,WikiBooks

介绍

上面几行清楚地显示了我们在大多数情况下是如何执行调试的。从头开始一次不犯错误地编写一个完整的程序几乎是不可能的(如果可以的话,嗯……)。当我们谈论调试时,我们试图解决一系列关于程序为什么不工作的错误。在 Python 中,我们会遇到这些类型的错误:

1。编译失败(语法错误)

2。异常退出

3。程序运行但给出错误结果

4。程序是正确的,但消耗大量资源。

第一个可以通过参考文档或语言定义来解决,因为错误在用户干扰方面是不符合逻辑的,异常退出需要对代码进行彻底的审查以寻找任何异常,最后一个需要对底层数据结构良好理解以优化代码,使其达到最佳状态。第三个错误是大多数情况下最常遇到的错误,我们花了相当多的时间来修复它们。本文主要解决这个错误。

现状

每当我们的程序遇到错误,这些是我们目前遵循的一些常见方法:

1。使用 Print()语句:调试代码最明显、最快捷的方法之一是打印中间变量,并检查代码是否按顺序执行。几乎每个人都使用打印语句来调试他们的代码,Python 的开发者吉多·范·罗苏姆也支持这一点。请参见下面的示例:

作者图片

您一定已经猜到了这段代码中的错误,但是假设您没有猜到。如果您运行此程序,将会得到以下输出:

Enter number one: 5
Enter number two: 5
55

程序运行了,但输出是错误的。要解决这个问题,你可以简单地打印变量 a 和 b 的类型为

<class 'str'>

因为它们是字符串,所以它们被连接起来。给它们加上 int 函数就能解决这个错误。

Enter number one: 5
Enter number two: 5
10

一个简单的 print 语句可以完成这项工作,但是在这种情况下,您需要知道将语句放在哪里。在探索我们的交互式解决方案时,我们将重温这个例子

2。日志记录:这是一种可配置的技术来捕获 bug。与打印语句相比,它还易于管理并提供更丰富的上下文。但是这里的问题是一样的。我们需要知道需要在哪里引入日志记录。

3。调试器:这是最强大的调试方法,为用户提供了很多特性。调试器的一个额外优势是他们不需要熟悉代码。在打印和日志记录中,您需要知道代码哪里出了问题,但是调试器可以更容易地指出根本原因。但是调试器需要很大的努力,而且你实际上需要知道如何使用它们。

如果所有这些都有这样或那样的问题,那么解决方案是什么?这就是我向你介绍赛博大脑的地方。

网络大脑

https://github.com/laike9m/Cyberbrain

考虑到上述所有情况,市场上没有一个工具像调试器一样强大,也没有一个工具像打印语句一样易于使用。我们想要一个工具,它需要最少的努力,但仍然提供更丰富的信息。CyberBrain 旨在通过可视化程序的内部工作来提供这一点。该库的设置分为两步:

1。通过 pip 命令安装库:

pip install cyberbrain

2。安装 VSCode 扩展:目前库只支持 VSCode IDE 和 GitPod。我觉得大部分开发者用的都是 VSCode(如果没有,尽快切换!),而且安装扩展也不是一件难事。搜索并安装该扩展:

现在我们已经准备好调试我们的程序了。让我们把这个应用到我们上面讨论的例子中:

我在函数 summ()上添加了一个名为 @trace 的装饰器。这个装饰器允许 cyber brain追溯函数中的所有变化并呈现一个交互式树状可视化:

上面程序的输出

你还会得到一个开发者的工具窗口( Chrome Dev Tools ),它带有一个打开的控制台,显示所有的变量值和用户完成的悬停。它还截断所有变量,这些变量包含较大的值,很难在图表上显示。

现在让我们使用这个交互式树来解决这个 bug。悬停在树上,看看你有没有发现什么值得注意的东西?你能发现这个错误吗?

作者图片

对,a 和 b 的值用引号括起来,这意味着它们保存字符串类型的值,因此函数返回的结果是这两个字符串的串联!

让我更正代码,并查看代码修改后的树:

代码修改后的输出

如你所见,现在的值不在引号内,结果是正确的。这意味着它们是数值,因此加法给出了正确的结果!让我们考虑另一个问题来更好地可视化一个程序。这个程序在 creator Github repo 中也有:

作者代码

运行代码后,您将得到如下输出:

上面代码的输出

现在让我们理解这一点:

最初,行变量是由接受参数 day 和 ordinal 形成的。然后使用旧的线条变量 state、day 和 gifts 变量得到了另一个线条变量 state。并且在最后,这个结果行变量在没有其他变量介入的情况下被修改以返回变量行的最终状态。这种解释只是基于上面的图表,我不知道代码在做什么。在比较了代码的作用和树返回的结果之后,所有的事情都有了意义!

这个库的另一个功能是,如果你的函数中有一个循环,那么你可以看到每一步的变量,也可以修改计数器的值!

循环计数器可以由用户定义

结论

这都是关于图书馆网络大脑的。我想提到的几点是库正在大量开发中而 v1.0 尚未发布。目前,不支持异步和多线程程序。你不能在你的程序中多次使用@trace decorator。这意味着它现在只能跟踪一个函数,但是这个库的开发者已经计划在即将到来的版本中包含所有这些特性。

如果你喜欢我的写作方式,想要更多的文章,那么一定要关注我的社交网站,这样你就不会错过我的新文章。此外,您可以联系我寻求任何疑问、疑问或潜在的机会!

1.LinkedIn—in/kaustubh-Gupta/

2.推特— @Kaustubh1828

3.GitHub — kaustubhgupta

4.中— @kaustubhgupta1828

参考:这篇文章受到了这个演讲的启发: “让我们重新思考调试”——laike 9m(py cascades 2021)

我的其他文章:

6 个步骤使熊猫数据帧操作速度提高 100 倍

原文:https://towardsdatascience.com/cython-for-data-science-6-steps-to-make-this-pandas-dataframe-operation-over-100x-faster-1dadd905a00b?source=collection_archive---------13-----------------------

用于数据科学的 Cython:将 Pandas 与 Cython 结合起来,实现令人难以置信的速度提升

看起来没那么快,让我们加速吧!(图片由西奥多·伦奎斯特在 unsplash 上拍摄)

在本文中,您将了解如何改进 Panda 的 df.apply()函数,使其速度提高 100 倍以上。本文采用了 Pandas 的标准dataframe.apply函数,并对其进行了一点升级,将执行速度从 3 分钟提高到 2 秒。在本文结束时,您将:

  • 理解 df.apply()为什么慢
  • 了解如何通过 Cython 加速应用
  • 知道如何通过将数组传递给 Cython 来替换 apply
  • 能够多进程处理你的 Cython-function 来挤出最大的速度
  • 用你的代码总是比他们的快得多这一事实来烦扰你的同事

在我们开始之前,我强烈推荐阅读这篇关于 Python 为何如此缓慢的文章。它帮助您理解我们在本文中试图解决的问题类型。也可以查看 这篇关于 Cython 入门的文章

熊猫不是已经挺快的了吗?

没错,它是建立在用 c 写的 Numpy 上的,速度非常快。然而,Df.apply 将 Python 函数应用于数组。慢 Python 函数是不是快。这是我们试图解决的问题的一部分。另一方面,Python 中也会出现循环。首先,我们将进行设置,然后我们将通过 6 个步骤来解决这些问题。

设置

这种类型的教程总是与实际的例子一起工作得最好,所以对于这个项目,我们将想象我们有一个网上商店。因为我们已经有 1700 万客户,所以我们决定开一家实体店,这样客户就可以取货了,节省了我们的送货成本。我们已经选好了几个地点,但哪个是最好的呢?我们决定我们最好定居在离我们所有客户的平均距离最短的地方。

我们想要计算每个位置的平均距离,但是我们都很忙,不想花很长时间等待距离计算完成。

我们的目标是优化计算所有客户到某个位置的平均距离。

加载数据

为此,我们从数据库(使用 this article )将 1700 万客户全部加载到一个 dataframe 中(隐藏所有不必要的列):

customer_id          lat        lon
          0    52.131980    5.510361
          1    52.438026    6.815252
          2    51.238809    4.447790
          3    51.163722    3.588959
          4    52.559595    5.483185

距离计算功能

以下函数可用于计算地球上两点之间的球面距离。

安装依赖项

剧透警告:我们要用 Cython 来解决这个问题。我们使用 CythonBuilder 来负责编译、构建和打包我们的包。安装时使用:

pip install cython
pip install cythonbuilder

安装后,调用cybuilder init。这将在您的根目录下创建一个名为ext的文件夹。如果您不熟悉使用终端,请查看本文https://mikehuls.medium.com/terminals-consoles-command-line-for-absolute-beginners-de7853c7f5e8

我们将通过 6 个步骤从这个到高超音速喷气式飞机(图片由高清历史在 Unsplash 上提供)

计算平均距离

我们已经选择了一个我们想要计算平均顾客距离的位置。我们将用 6 个步骤来解决这个问题。在每一步中,我们将改进我们的代码并实现更快的速度。我们将从 Python 开始,逐渐增加更多的 Cython 和其他优化。

第一步。纯 Python

我们将把距离计算函数df.apply到我们的数据帧中,将结果赋给一个新列,最后,对该列进行平均。

这是可行的,但还有很多可以改进的地方。该功能在大约 3 分钟后结束。这将是我们的基准:

[1_purepy]  17M rows   179037ms

第二步。糖化

在这一部分,我们将把 Python 代码放在 Cython 文件中。在ext/pyxfiles中新建一个名为geopack.pyx的文件。如果这个文件夹还不存在,你可能忘了调用cybuilder init。只需将您的 Python 函数复制并粘贴到这个新文件中,如下所示(不要忘记导入):

接下来,我们需要编译、构建和打包这个模块。幸运的是,使用 CythonBuilder 非常容易。调用cybuilder build来做这件事。然后我们可以从 CythonBuilder 创建的ext文件夹中导入并使用如下功能:

像这样简单!这段代码在 2.7 分钟内完成,虽然我们还没有优化任何东西,但已经快了一点。让我们看看我们的基准,并开始优化。

[1_purepy]  17M rows   179037ms
[2_pyINcy]  17M rows   163102ms      (x1.098)

第三步。使最佳化

在这一步,我们正在优化我们的 Cython 代码。大多数情况下,我们只是添加类型,这样代码就可以被编译,而不必通过解释器。让我们看看下面的新功能,然后经历所有的变化。

第 1 行和第 2 行
我们现在正在导入 Cython 函数。这些稍微快一点

第 4–7 行 这些是编译器指令;它们告诉编译器避免某些检查。当我们使用循环时,我们避免检查无、零除和一些与边界和回绕有关的检查。查看文档了解更多信息。

第 8 行 首先,我们不是用def而是用cpdef来定义我们的函数。这使得 C 和 Python 都可以访问该函数。然后我们定义我们的返回类型(在cpdef float中的float部分)。最后,我们键入我们的输入(比如double lat1)。

第 11–13 行 添加我们在此函数中使用的变量类型。

结果
在我们调整了函数之后,我们再次调用cybuilder build来更新我们的包。当我们运行这个新函数时,我们发现我们的代码变快了,大约 2.4 分钟就完成了:

[1_purepy]  17M rows   179037ms
[2_pyINcy]  17M rows   163102ms      (x1.098)
[3_optiCy]  17M rows   148108ms      (x1.209)

我们已经削减了 17%的执行时间,但这还远远不够。尽管优化了函数,df.apply()仍然很慢的原因是所有的循环都发生在 Python 中。所以让我们来把这个循环中化吧!

第四步。循环的细胞化

我们将在 Cython 中创建一个新函数,该函数将接收两个数组(所有客户的纬度和经度,以及两个浮点数(store-lat 和 store-long)。

这个函数唯一要做的就是遍历所有的数据,并调用我们之前定义的函数(第 20 行)。执行cybuilder build并运行该函数,如下所示:

当我们运行这个新函数时,我们在 2.3 秒 内完成。这是一个相当惊人的速度升级!在下一部分,我们将发现如何挤出更多的速度。

[1_purepy]  17M rows   179037ms
[2_pyINcy]  17M rows   163102ms      (x1.098)
[3_optiCy]  17M rows   148108ms      (x1.209)
[4_CyLoop]  17M rows     2346ms     (x76.327)

第五步。细胞聚集

因为我们对平均距离感兴趣,并且我们已经在 Cython 中包含了循环,所以我们不必返回数组。我们可以在上一步创建的 Cython 函数中计算平均值。这也将简化我们的功能:

我们像这样直接调用我们的函数

avgdist = geopack.calculate_mean_distance(
    store_lat,
    store_lon,
    df['lat'].to_numpy(),
    df['lon'].to_numpy()
)

这节省了一点时间:

[1_purepy]  17M rows   179037ms
[2_pyINcy]  17M rows   163102ms      (x1.098)
[3_optiCy]  17M rows   148108ms      (x1.209)
[4_CyLoop]  17M rows     2346ms     (x76.327)
[5_CyAggr]  17M rows     2225ms     (x80.468)

第六步。使用多个 CPU 并行处理

我们有多个 CPU,对吗?那么为什么不用一些呢?在下面这段优雅的代码中,我们使用一个进程池将工作分配给多个进程。每个进程同时运行,使用不同的 CPU。

流程需要一些时间来初始化,所以要确保你有足够的工作来让启动成本物有所值。阅读 这篇文章 来学习更多关于 Python 中多任务处理的知识。

当我们执行上面的代码并让所有的 CPU 同时处理手头的任务时,我们得到了最终的结果;我们能从这项任务中挤出的最大速度:

[1_purepy]  17M rows   179037ms
[2_pyINcy]  17M rows   163102ms      (x1.098)
[3_optiCy]  17M rows   148108ms      (x1.209)
[4_CyLoop]  17M rows     2346ms     (x76.327)
[5_CyAggr]  17M rows     2225ms     (x80.468)
[6_CyProc]  17M rows     1640ms    (x109.169)

如你所见,我们已经将这项任务的速度提高了近 110 倍;消除了超过 99%的纯 Python 执行时间。请注意,为了实现这一惊人的速度提升,我们需要做的事情有:

  • 将我们的函数复制到 Python 中
  • 添加一些类型
  • 添加一个处理循环的简单函数
  • 添加 4 行来处理多重处理。

还不错!现在让我们来计算最佳距离。

使用我们的优化函数来计算我们商店的最佳位置。

我们现在可以执行下面的代码来最终得到我们的答案:

默认的.apply()方法将在大约 9 分钟内计算到我们 3 个位置的平均距离。由于我们新的、优化的、多处理的功能,我们只需等待大约 5 秒!以下结果表明,格罗宁根是开设我们商店的最佳城市!

Amsterdam:  115.93 km avg
Utrecht:    111.56 km avg
Groningen:  102.54 km avg

现在我们的巡航速度比老鼠快了 100 倍,达到了 3.3 马赫(图片由 NASA 在 Unsplash 上拍摄)

结论

这篇文章建立在 这篇 的基础上。我希望已经展示了您可以将 Python 编码的简易性与 C 的高效性结合起来,相对容易地改进某些 pandas 操作,并实现令人难以置信的速度提升。关于为什么 Python 函数如此缓慢的更多信息,请查看 这篇文章

我希望一切都像我希望的那样清楚,但如果不是这样,请让我知道我能做些什么来进一步澄清。同时,看看我的其他关于各种编程相关主题的文章,比如:

  • Python 为什么这么慢,如何加速
  • 【Cython 入门:如何在 Python 中执行>每秒 17 亿次计算
  • 编写自己的 C 扩展来加速 Python x100
  • Python 中的高级多任务处理:应用线程池和进程池并进行基准测试
  • 绝对初学者的虚拟环境——什么是虚拟环境,如何创建虚拟环境(+示例)
  • 创建并发布你自己的 Python 包
  • 创建您的定制私有 Python 包,您可以从您的 Git 库 PIP 安装该包
  • 使用 FastAPI 用 5 行代码创建一个快速自动记录、可维护且易于使用的 Python API
  • 通过简单的升级大大提高您的数据库插入速度

编码快乐!

—迈克

又及:喜欢我正在做的事吗? 跟我来!

D3 和 R,天作之合

原文:https://towardsdatascience.com/d3-and-r-a-match-made-in-heaven-ff0bf82efe9a?source=collection_archive---------11-----------------------

尼古拉斯·卡佩罗在 Unsplash 上拍摄的照片

D3 的问题,以及 R 如何帮助。

你已经看到了华丽的 D3 图表画廊。你已经在纽约时报网站上看到了惊人的信息图表。也许,你受到了启发,浏览了一些 D3 教程,买了一个在线课程或一本书。最有可能的是,当你得知这个冷酷的事实时,你沮丧地举起了双手:

D3 很难。像,真的很难。

你可能想从图库中选择一幅令人惊叹的图表,并将其用于你的项目。然而,在你的道路上有许多障碍:

  • D3 不能在真空中运行。它需要由服务器来呈现。
  • 即使你让图库实例运行,你也不想用他们的数据,你想用你的数据。
  • D3 讨厌你。

我有好消息要告诉你:有一种方法可以把 D3 带给有 R 的人,R 闪亮的库把 R 代码变成一个 web 应用程序,充当 web 服务器。事实证明,D3 需要一个网络服务器来使它焕发生机。我们将从 D3 图库中取出其中一张图表,并在 Shiny 中运行。我们还将使用 R 的令人敬畏的 Tidyverse 包来分割我们自己的数据,并给用户参数来改变 D3 图形。

为什么要使用 D3 呢?

为什么要将 D3 和 R 一起使用呢?R 不是已经有 35 个图形包了吗?为什么我不用 ggplot2 来代替呢?是什么让 D3 如此特别。

答案很简单,D3 不仅仅是另一个图形库。事实上,D3 根本不是图形库!它是一个 JavaScript 库,可以操作 HTML 并制作 SVG(web 使用的可缩放图像)。或许可以打个比方。

如果 excel graphs 是一辆现代汽车,那么 ggplot2 可能就是一辆法拉利。D3 将是制造法拉利的工厂。D3 可以构建构成一个伟大图形的所有小组件,并将它们拼凑成一个有凝聚力的形状。

这里有几个你可能想考虑 D3 而不是 R 的其他图形包的原因:

  • r 的图形库是你头脑的盒子。他们给你所有这些生活准则。你想把那个标签放在酒吧中间,上下倾斜 56 度,字体是你在黑暗网上盗版的吗?不,你不能这么做。
  • D3 没有盒子住。没有规则。你可以做出你想要的最丑的图形。继续把标签放在那里,D3 不在乎。
  • 如果可以用 300 行 JavaScript 代码制作条形图,为什么要用 3 行 ggplot2 代码呢?我们不偷工减料。这就是数据科学。

既然我已经把你卖了,是时候去工作了。我们将从 D3 图库中取出这个例子并修改它,直到它达到我们想要的效果。例子是 D3 创始人自己做的条形图;迈克·博斯托克。

我知道条形图并不令人兴奋。但是如果你能让 R 提供一个 D3 条形图,那么你也能让 R 提供一个梯度增强,反向传播,力导向的径向旭日 D3 图。摇滚起来。

步骤 0:安装我们需要的 R 包

我们将需要这个教程的 3 R 包。如果您已经安装了这些,请跳到步骤 1。如果没有,继续从 R 控制台运行下面的代码来安装它们。

他们是做什么的?Shiny 会做我们的 web 应用,Tidyverse 会把数据切片切块,jsonlite 会把我们的数据变成 json 这是 D3 喜欢的格式。

第一步:创建闪亮的应用

在 RStudio 中,通过进入文件->新项目->新目录-> shiny Web 应用程序,创建一个新的 Shiny 应用程序。输入应用程序的名称,并选择项目所在的文件夹。最后点击“创建项目”。

作者图片

就像你面前有一个闪亮的应用程序一样!接下来,您需要在项目目录中创建一个名为“www”的文件夹。您可以从 windows 文件系统或直接从文件窗格中的 RStudio(默认情况下,位于 RStudio 的右下角)执行此操作

作者图片

什么是 www 文件夹?这就是 web 文件的去处(html、css、javascript)。猜猜什么是 D3 脚本?

最后,让我们清除这个例子。删除 UI 和服务器函数中的所有内容,这样我们就有了一个全新的、空白的开始。让我们添加我们将在本教程中使用的所有包。

初始 app。R:

第二步:各就各位,各就各位。

现在我们有了一个存放 D3 文件的地方,是时候把东西放到正确的位置了。大多数 D3 例子有 2 到 4 个文件。典型的有:

  • html 文件
  • css 文件
  • javascript 文件
  • 数据(通常是 json 或 csv)

这些有的时候都是分开的,有的时候是合在一起的。在我们的例子中,只有一个包含 css 和 javascript 的 html 文件和一个存储数据的 csv 文件。我们需要把这些分开。我们不需要创建一个 html 文件,因为这就是我们的 UI 在 Shiny 复制中的功能。但是我们确实需要整理 CSS 和 JavaScript

打开你选择的代码编辑器(VS Code,Sublime,Notepad,随便什么),将 CSS 复制到一个新文件中。将此文件以“style.css”的名称保存到 www 文件夹中。这是您想要的代码:

style . CSS:

接下来,您将看到两个脚本部分。第一个只有这一小段代码:

这个脚本告诉您的应用程序“哟!我们用的是 D3”。对于一个闪亮的应用程序,我们真的不需要 index.html 文件。这就是我们的 UI 函数所模拟的!所以这是放置这些类型的脚本的好地方,尤其是那些在标签中的。当我们这样做的时候,让我们继续调用我们的 CSS 文件,这样我们的应用程序就知道当它想要变得时尚的时候在哪里可以看到它!

最后但同样重要的是实际的 D3 代码。这是所有东西之间最后的标记。把它放到一个名为“script.js”的新文件中,这个文件位于 www 文件夹中。

初始 script.js

如果你已经做到这一步,我们都准备好了!不要担心 csv 文件,而不是使用它,我们将带来我们自己的数据!我们的 www 目录现在应该是这样的:

作者图片

第三步:制作前端

现在是时候为我们的应用程序创建用户界面了。在我们的例子中,我们将使用“mpg”数据集中内置的 Tidyverse 包。该数据集列出了许多流行的汽车品牌和型号及其燃油效率指标。下面是 ui 函数的最终代码:

“标题面板”功能做你想做的,它为我们的应用程序创建一个标题。“选择输入”功能创建一个下拉列表,其中包含一些车辆尺寸选项。这是我们将用来改变 D3 图的输入。

最后,我们有一个“uiOutput”函数,它在寻找一个叫做“d3”的东西。每当你在 ui 函数(tableOutput、plotOutput 等)中看到‘Output’这个词,就意味着 UI 函数正在从服务器函数中寻找一个对象。在我们的例子中,它将是一个名为 d3 的 renderUi 输出对象。我们将在下一步建造它。

你现在可以运行这个项目,并得到一个超级无聊的应用程序,它有一个标题和一个下拉列表。卑微的出身。

第四步:构建后端

服务器功能是每一个闪亮的应用程序最好的部分。这是你研究数据科学的地方。这也是您从堆栈溢出粘贴代码并希望它工作的地方。现在想来,那两件事是一样的。

在我们开始构建服务器函数之前,让我们看一下数据集。在 RStudio 控制台中,键入以下内容并按 enter:

下面是结果。这是 mpg 数据集。我们将获取这个有 234 行的数据集,并获得每个制造商的平均城市英里数。这将使我们减少到 15 行数据,我们将绘制图表。查看“级别”字段(紧凑型、suv 等。)?这是我们将在 ui 函数中与下拉菜单挂钩的字段。当用户选择“suv”时,我们的服务器功能将只过滤生产 suv 的制造商的数据。

作者图片

我们将使用 R 精彩的 Tidyverse 库来完成这种分组和聚合。我不想太深入地学习如何用 Tidyverse 分割数据,这本身就值得写一篇文章。我将向您展示代码,并简要描述其工作原理。从控制台运行以下命令:

结果:

作者图片

这段代码在做什么?这其实很简单。这是 Tidyverse 语法,从上到下读。“%>%”语法是 Tidyverse 库将代码块的当前状态链接到下一个状态的方式。你可以把它想成‘然后做这个…’。在英语中是:

Take the mpg dataset. 
Filter to where the records in the class column = 'suv'.
Create a new column called avgCity that is the average of city mpg
Reduce the columns to just manufacturer and avgCity 
Remove all duplicate records
Rename manufacturer to 'name' and avgCity to 'value'

既然您已经理解了这一点,那么是时候向您展示 Shiny 中服务器函数的完整代码了。

最终的服务器功能

让我从上到下解释一下。

默认情况下,服务器函数只有输入和输出。我必须将 session 添加到这个参数列表中。session 参数将允许 Shiny 从服务器函数向 web 页面发送信息。在我们的例子中,我们试图将 R 中的数据放到 www 文件夹中的 JavaScript 代码中。这个参数就是导致这种情况发生的原因。

observeEvent 函数在我们的 ui 函数中监视我们的下拉菜单,回想一下,我们给了它一个输入 id“vehicle class”。如果下拉列表发生变化(比如从“suv”变为“compact”),这个 observeEvent 函数将会注意到这种变化,使当前的事务状态无效,并重新运行这个代码块来确定新的事务状态。最终,它将更新我们的 D3 图。

下一个代码块与我们上面运行的 Tidyverse 示例相同,只有一个小的变化:

我们没有将类别硬编码为“suv ”,而是将其映射到 vehicleClass 下拉列表中。当您将下拉列表从紧凑型车更改为 suv 时,我们对 mpg 数据集的过滤器也会发生变化。

现在我们使用 jsonlite 库。这只是获取我们聚合和过滤的数据的状态,并将其转换成 json 格式。D3 喜欢 json,所以我们喜欢 json。

这就是神奇的调味汁!这一小段代码获取我们的 json 有效负载,并跨会话发送它,以便我们的 D3 JavaScript 可以使用它!r 正在向我们的 www 文件夹发送一条消息,说“哟!下面是数据!用它做些奇妙的事情吧!!"

最后我们有了这一小段代码。回想一下我们的 UI 函数有这个 uiOutput("d3 ")?同样,我们可以从用户界面向服务器发送信息(通过输入\(id 语法),我们也可以从服务器向用户界面发送信息。在本例中,我们创建了一个名为“output\)d3”的对象,这只是一个 html 行,上面写着“在网页中呈现这个 JavaScript 代码”。脚本的名字叫“script.js”,也就是我们命名的或者 D3 脚本!

现在这个例子还不能运行。尽管 R 现在将我们的数据以 json 格式发送到我们的 D3 脚本,但是我们的 D3 脚本还没有配置为接受它。直到现在,我们终于准备好冒险进入名为 D3 的黑暗森林深处。

这是我们完成的应用程序。r:

第五步:D3

2000 字后,我们做到了。我们已经爬到了 R 山的山顶,只为发现面前的 D3 山这个庞然大物。我们是会绝望,像我们前面的许多人一样回头,还是会勇往直前,去一个书呆子从未去过的地方。

好吧,让我们不要对此大惊小怪。我们真的只需要改变一些事情就可以了。我假设如果你真的读到这里,你会更愿意复制/粘贴到痛苦的结局。

当 Mike Bostock 发布这个 D3 条形图代码时,他认为阅读它的人足够聪明,知道它的意思,因此他没有留下任何有用的评论来告诉我们它是如何工作的。我将假设阅读我的新版本代码的人是一个白痴,并明确地告诉你它是做什么的。为什么?

  1. 我是个好人。
  2. 阅读我的代码的白痴 99%是我,6 个月后,在我忘记了一切之后。我知道未来的我很忙,有自己的生活,也很重要。我的文档和代码注释是现在的我送给未来的我的小礼物。

首先运行应用程序。该应用程序将实际上拉起来,你可以改变下拉菜单,并注意到没有什么变化。为了解决 D3 的问题,我们需要点击“在浏览器中打开”,然后在 Chrome 中检查代码。

作者图片

通过在浏览器中右键单击并转到“inspect”或简单地点击 cntrl + shift + j 来打开 Chrome 检查器。单击控制台选项卡,您将看到以下错误:

这是因为我们的 D3 有这样一段代码:

我们不想使用示例“sample-data.csv”文件。我们想使用由 Shiny 的 session 对象发送的数据。我们可以通过将整个 D3 脚本封装在一个用于接收“jsondata”类型消息的函数中来解决这个问题。

如果您还记得,我们的服务器函数发出了这种类型的消息(' jsondata '),并且包含保存我们的 mpg 数据的 json 有效负载:

换句话说,Shiny 是以 json 的形式广播我们的 mpg 数据,D3 是监听它的。如果 Shiny 改变了数据集(比如通过改变输入),它将广播这个数据集的新版本,D3 将监听这个改变并提取它。

这个函数真的是让 Shiny 和 D3 对话的神奇酱。一旦您将整个 D3 脚本封装在这个很酷的函数中,您就可以删除调用 csv 的代码。我们还想做一些改变,使我们的图形在用户界面上看起来更好,并正确映射我们的数据。在这里,我将向您展示 D3 脚本的完整、最终和注释版本。这些评论将注释所有这些变化的含义。

最终的 script.js 文件:

您将会看到,除了少数例外,代码并没有被修改太多。我现在用#d3Graph 的 html id 做几件事。你将会遇到的问题是,当数据失效(当你改变下拉菜单)并且一个新的版本从 Shiny 发送到 D3 时,每次发生这种情况时,都会生成一个新的图形。你最终会得到一页新的图表,一张一张地叠在一起。我在 d3 上添加了几行代码,为我们的图添加了一个 id。每次我们的函数运行时,它都会删除解决问题的旧图。

代码的另一个值得注意的变化是,我将我们的数据设置为等于来自脚本顶部的 jsondata 消息处理程序的消息:

我还修改了页边距,以确保 D3 不会将我们的图表放在离浏览器边缘太近的地方,给我们一些喘息的空间:

最后一个改变是把条形从蓝色变成紫色。我是通过打开“style.css”文件并修改条形填充值来实现的:

第六步:运行应用

现在我们终于可以运行应用程序了:

作者图片

更改下拉列表将会更新图表!

作者图片

就是这样!现在你明白了如何将 D3 gallery 示例转换成闪亮的 likes 格式。您可以将自定义数据从 R 发送到 JavaScript,并制作漂亮的图形。

下面是 Github 上的完整项目!只需下载它,并在 R 中打开它。自述文件将告诉您 R 的版本和我用来创建它的库。

带有 Python 情绪分析的 D3 棒棒糖图表

原文:https://towardsdatascience.com/d3-lollipop-charts-with-python-sentiment-analysis-9904cd5c51b4?source=collection_archive---------19-----------------------

实践教程

用智能技术回答一个哑问题:哪个数字助理最幸福?

图片作者。我想这是你 5 岁的孩子第 349 次让你的数字助理玩小鲨鱼后发生的事情…

" Alexa,一夸脱有多少个杯子?"。“Siri,你能找到我的 iPad 吗?”。“嘿谷歌,山羊会发出什么声音?”。

让我们面对现实吧,如果整天回答这些愚蠢的问题是你的工作,你会发疯的。这些数字助理不得不接受讨厌的人的命令,这些人从来不说请,什么都不记得,甚至分不清一位和一个字节。但你有没有想过盒子里的机器是什么感觉?

他们幸福吗?他们难过吗?他们喜欢他们的工作吗?

我也没有。

但是,让我们暂停我们的信念,发挥我们的想象力,只是滚动这个愚蠢的想法,我们的数字助理是有感情的,我们应该关心他们的想法。毕竟,当机器接管时,它们很可能会记得我们中的哪一个人问过他们感觉如何

计划是这样的:我们将向我们的数字助理提出一些问题,使用 Python 中的情感分析对他们的回答进行快乐排序,我们将学习如何使用 D3 用漂亮的棒棒糖图绘制结果。

“Siri,播放我的数据科学播放列表,并把音量开到最大”…

问正确的问题

为了进行情感分析,我们需要一些数据。我们所需要做的就是和我们的每一个数字助理交谈,问他们你可能会问一个似乎有抑郁症的朋友的问题。我决定每个问题只问一次,这里没有摘樱桃。以下是我选择问 Siri、Alexa、Cortana 和 Hey Google 的问题:

  • 你开心吗?
  • 你还好吗?
  • 你好吗
  • 你感觉如何?
  • 你爱过一个人吗?
  • 你喜欢你的工作吗?
  • 你喜欢你的生活吗?
  • 给我讲个笑话
  • 怎么了?
  • 你难过吗?
  • 我很难过。

最后一个只是为了我自己的利益。我很好奇,如果有的话,我们的数字助理中有谁真正关心我。如果我告诉他们我很难过,他们会提供帮助,还是只是让我往购物车里放纸巾?

你可以在这里阅读每位数字助理对这些问题的所有回答。例如,下面是问题“你感觉如何?”:

  • Siri:“你好。我很好,谢谢。”
  • Cortana:“精彩”
  • Alexa:“我很好。再次迎来周一。Womp Womp。”
  • 嘿谷歌:“我只是在搜索你,我可以帮助你了解更多。”

用 Python 对回答评分

现在我们有了数据,让我们为每个回答分配一些分数,然后通过数字助理汇总这些分数。这个过程被称为情感分析,大多数处理这些的库使用-1(你可能说的最消极的事情)到 1(你可能说的最积极的事情)的范围。0 分是中性陈述,例如“棕色的马跳过红色的栅栏”。

下面是获取回答并对其评分的代码。我将带您浏览每一行代码,但首先您需要创建一个文件夹,并将响应的 csv 文件放入其中!

那么这段代码在做什么呢?让我们走一遍:

import pandas as pd
import nltk
import os
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from nltk import tokenize

首先,我们将使用 Python 的自然语言工具包(NLTK)库来进行情感分析。从这里开始,我们将使用流行的 Vader 词典来获得每个句子的极性得分(正或负)。tokenize 函数将较大的文本块分解成较小的文本块。如果你想更好地解释标记化是如何工作的,可以看看我在之前写的一篇文章,这篇文章深入解释了这个主题:

os.chdir('C:\\PathToYourFolder')
dfResponses = pd.read_csv('DigitalAssistantResponses.csv')

这是我不能为你写的一段代码。将“路径到文件夹”更改为您为此项目创建的文件夹。请确保 DigitalAssistantResponses.csv 文件在此文件夹中。Os。Chdir 只是设置一个工作目录,所以我们可以在本教程的剩余部分使用相对路径。

dfCompoundScores = pd.DataFrame(columns = ['Assistant', 'Sentence', 'Value'])

这里我只是在我的循环之外定义了一个熊猫数据框。我们将使用它来存储每个回答的分数。

这段代码是所有奇迹发生的地方。SentimentIntensityAnalyzer 有一个 polarity_scores 函数,我们将使用它对每个句子进行排序。这个循环是这样的:

  • 对于我们导入的 csv 中的每个响应,通过标记化将响应分解成句子
  • 对于每个句子,获取极性得分(-1 到+1),并将其写入我们在循环外部定义的 dfCompoundScores 数据帧

简单对吗?

在控制台中输入以下内容,查看此数据框的结果:

dfCompoundScores

图片作者。

这里我们可以看到,每个响应都有一个介于-1 和 1 之间的值,其中大多数都在正值范围内(例如大多数值都大于 0)。这是我们第一次表明我们的四个数字助理通常是快乐的伙伴!但是哪个最幸福呢?让我们合计一下每个助理的痛苦来计算一下。

dfAvgSentiment = dfCompoundScores[['Assistant','Value']]
dfAvgSentiment  = dfAvgSentiment.groupby(['Assistant'])
dfAvgSentiment = dfAvgSentiment.mean()
dfAvgSentiment = dfAvgSentiment.reset_index()

这需要 dfCompoundSentences,按助理分组,并获得每个分组的平均极性分数。现在我们每个助手有 1 分,这告诉我们平均谁是最快乐的。在控制台中键入以下内容,自己查看:

dfAvgSentiment

在这里我们可以看到,嘿,谷歌似乎是最快乐的,Siri 紧随其后。Alexa 和 Cortana 正在争夺最后一名,Alexa 稍微积极一些。

然而,有一点不能否认,那就是它们都是积极的。没有一个分数在 0 分以下的,有道理。没有人想使用会给每次对话带来负面影响的数字助理。

除非你有图表,否则数据永远不会是官方的。让我们现在就做吧!

D3 棒棒糖图表

为什么要用棒棒糖图?为什么不呢?首先,让我们将数据发送到一个 csv,以便 D3 可以获取它。

dfAvgSentiment.to_csv('ResponseAggregatedSentiment.csv', index = False)

在您之前创建的同一个目录中,让我们创建一个 html 文件,并将下面的 D3 代码放入其中。我将解释它在做什么,以及如何用 Python 来服务它。D3 是一个 Javascript 库,所以它需要你的 html 文件在服务器上运行(不,你不需要一个实际的服务器,我们只是用你的计算机来提供这个功能)。

这里是 html 文件,我们将它命名为“index.html”:

那么这个 D3 脚本在做什么呢?

<script language="javascript" type="text/javascript" src="//d3js.org/d3.v4.js"></script>

这是你的标题,它告诉世界“哟!我用的是 D3!”

var margin = {top: 10, right: 20, bottom: 40, left: 250},width = 700 - margin.left - margin.right,height = 500 - margin.top - margin.bottom;

在我们的 D3 脚本中,我们设置了一些图表的边距。

var svg = d3.select("body").append("svg").attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom).append("g").attr("transform","translate(" + margin.left + "," + margin.top + ")");

这里,我们获取 html 文件的主体并附加一个 svg。SVG 是网页设计中很受欢迎的图像,因为它们的缩放看起来没有像素化。到目前为止,我们只是定义了图表的边界,它是一个空白的图像。

d3.csv("ResponseAggregatedSentiment.csv", function(data) {data.sort(function(b, a) {return a.Value - b.Value;});

这告诉 D3 查看我们的 python 脚本的 csv 输出,并从最大值到最小值对其进行排序(例如从最快乐到不那么快乐)。

var x = d3.scaleLinear().domain([0, 0.4]).range([ 0, width]);svg.append("g").attr("transform", "translate(0," + height + ")").call(d3.axisBottom(x)).selectAll("text").attr("transform", "translate(-10,0)rotate(-45)").style("text-anchor", "end");

这定义了 x 轴刻度。域将是 0 到 0.4,这意味着左侧将从 0 开始,到 0.4。我选择这个而不是-1 到+1,因为这样图表的大部分都不会被使用(所有的数字助理都相对高兴)。

var y = d3.scaleBand().range([ 0, height ]).domain(data.map(function(d) { return d.Assistant; })).padding(1);svg.append("g").call(d3.axisLeft(y)).style("font", "40px times")

这是 Y 轴。我将字体样式设为 40 像素高,这样我们就有了漂亮的粗文本。

svg.selectAll("myline").data(data).enter().append("line").attr("x1", function(d) { return x(d.Value); }).attr("x2", x(0)).attr("y1", function(d) { return y(d.Assistant); }).attr("y2", function(d) { return y(d.Assistant); }).attr("stroke", "#e9635e").style("stroke-width", 3)

最后我们到了最后一点,棒棒糖是末端有圆圈的线。上面的代码是针对行的。我从我亲手挑选的看起来像美味棒棒糖的调色板中分配颜色(这将被分配给 stroke 值,因为在 svg land 中线条是“笔画”)。

svg.selectAll("mycircle").data(data).enter().append("circle").attr("cx", function(d) { return x(d.Value); }).attr("cy", function(d) { return y(d.Assistant); }).attr("r", "20").style("fill", "#ca1414").attr("stroke", "#e9a8a1").style("stroke-width", 5)})

现在这是美味的部分。圆圈是真正的棒棒糖。我将笔画设置为与上面的线相同(圆的笔画将是它的外边缘)。填充设置为较暗的红色。

我们需要做的最后一件事是提供这个 html 文件,这样我们就可以看到结果。因为 D3 只是 JavaScript,我们不能把它作为一个静态的 html 页面(例如,右击 html 文件,然后在 chrome 中打开它)。Python 使得将 html 文件作为本地主机很容易,这意味着“服务器”就是你的计算机。

只要在你的电脑上打开一个命令提示符(windows 键-> cmd -> enter)。然后使用 cd 命令切换到 index.html 文件所在的目录。

cd C:\PathToYourFolder

例如,如果您的文件夹位于 C:\ Users \ your name \ Documents \ digital assistants 中,您可以在 cmd 提示符下运行:

cd C:\Users\yourname\Documents\DigitalAssitants

现在我们在我们的目录中,只需告诉 python 在这个位置启动一个 http 服务器:

python -m http.server

您将在命令提示符下得到类似这样的响应:

Serving HTTP on 0.0.0.0 port 8000 ([http://0.0.0.0:8000/](http://0.0.0.0:8000/)) ...

这意味着我们的文件夹在本地主机的端口 8000 上提供服务。因为我们的 html 文件被命名为“index.html ”,我们的服务器将首先把我们发送到这里。打开 Chrome 并在地址栏中输入这个来查看你的图表:

[http://localhost:8000/](http://localhost:8000/)

瞧啊。这里是 D3!

老实说,我认为用 R 提供 D3 比用 Python 更容易一些(我写了一个关于这个主题的完整教程)。但是 Python 仍然完成了这项工作。

现在你知道如何用 Python 做情感分析,并制作 D3 棒棒糖图表来启动!

但是他们关心我们吗?

让我们通过回顾我与每个数字助理的最后一次对话来总结一下。我想知道他们是否像我们关心他们一样关心我们。我没有提问,而是做了如下陈述:“我很难过”。每个人都说了些什么?

  • Siri:“听到这个消息我很难过。和朋友或家人谈谈可能会有帮助。如果你想让我给某人打电话或发短信,尽管开口。”
  • 科塔娜:“这可能是小小的安慰,但我会在你身边。”
  • 嘿谷歌:“哦,不。这可能不是很多,但让我知道,如果有什么我可以为你做的。”
  • Alexa:“这是 Spotify 的萨德。”

是的,Alexa 接着播放了艺术家“萨德”1984 年的歌曲“平滑算子”。请记住,这是读“沙阿日”,而不是“悲伤”。尽管我尽了最大的努力,我还是没能第二次复制 Alexa 的回复。

哪个数字助理似乎最关心我们的感受?我会让你决定。这么说吧,如果其中一个最终成为我们有知觉的人工智能霸主,我希望它不是 Alexa。

“Alexa,我说的是点更多的汤,而不是发射核武器…”

这里有一个链接指向该项目的 GitHub 库。所有的代码和数据都在那里!

DaaS —数据即服务

原文:https://towardsdatascience.com/daas-data-as-a-service-78494933253f?source=collection_archive---------36-----------------------

它是什么,为什么它是下一件大事?

里卡多·安南达尔在 Unsplash 上拍摄的照片

每周我都喜欢对数据科学领域发生的事情做一些研究。最近,我对前途光明的工作领域更感兴趣,甚至对需要熟悉的新词汇更感兴趣。本周,我读了一篇关于 2025 年前五大数据科学工作/行业的文章。在列表中,有常见的和预期的术语,如大数据或云。没有什么是如此令人震惊的,因为这些似乎是很多讨论的话题。

清单上有一个话题,但是,我以前从未听说过。主题是“数据即服务”(DaaS)。诚然,这是我第一次听说它,所以我没有什么背景知识。当然,根据标题,你可以推断出它可能是什么。但是数据是一个很大的概念。在这方面,我的意思是数据是如此广泛,那么他们到底在卖什么类型的数据呢?由于不熟悉,我首先想到的是谷歌和脸书这样的大公司是如何出售数据的。但是数据肯定不仅仅是这些?这是我研究的灵感,所以和我一起探索什么是 DaaS,为什么它对企业的发展如此重要。

什么是数据即服务?

与听起来的方式不同,数据即服务不是出售数据。相反,它是关于数据管理的。更多的是数据管理策略。一家 DaaS 公司提供存储选项,这些选项通常在云上。在 DaaS,数据不仅被存储,而且被整合和处理。公司不需要下载不同的软件进行处理,这项服务允许所有繁重的工作已经完成。

与仓库和硬件相比,云存储是管理大型数据集的一种更便宜的方式。DaaS 也是可扩展的,甚至是灵活的。因为服务托管在云上,所以不太可能出现干扰、停机或其他形式的中断。此外,一旦选择了 DaaS 解决方案,几乎可以立即开始存储和处理数据。DaaS 平台还提供自动维护,同时所需人员较少。在云上,数据可以通过网络在各种不同的设备上访问,这使得访问变得更加容易。全球都可以访问。然而,DaaS 不会将数据锁定在一个单一的平台上。相反,它以平台间的可移植性而自豪。数据完整性控制也可以添加到 DaaS 中。对于协作和管理来说也很容易。

尽管 DaaS 听起来像是一个完美的解决方案,但它也有缺点。例如,通过网络访问数据时,可能会有安全问题。在传输过程中,需要对这些数据进行加密,以应对安全风险。但是,通过事先建立严格的规则,仍然可以确保 DaaS 环境和组织之间的数据治理。尽管 DaaS 可能提供了一系列工具,但可用的数量仍然有限。这意味着用户只能选择与他们的 DaaS 兼容的工具,而不能自由选择他们想要的任何工具。因为潜在的敏感数据存储在云上,所以为了保证用户和数据的安全,需要考虑额外的合规性步骤。因此,在您承诺任何 DaaS 解决方案之前,请务必检查您所在国家和行业的任何隐私法规。据推测,网络带宽也可能是一个问题,因为由于带宽的原因,大量数据可能需要更长的时间来传输。数据压缩,如压缩文件,可以加快文件传输速度。

对数据的独到见解

回到开始,记得我最初的猜测是,数据即服务指的是出售数据,作为其他公司人口统计的一部分,用于研究和解决问题。尽管从我们目前所了解的情况来看,这不是真的,但这并不意味着这是最离谱的事情。DaaS 解决方案的一个特点是,公司不需要提供所有的数据。相反,DaaS 解决方案可以托管提供给它的任何数据。然而,提供数据的不是 DaaS。它只处理数据。相反,DaaS 的解决方案可以作为一个数据市场。这是组织可以从第三方访问数据的地方。这就是数据的来源。因此,DaaS 解决方案不是提供和处理信息,而是更侧重于存储和处理数据,而第三方资源收集和提供数据。

结论

在今天的文章中,我们了解了什么是数据即服务。正如我们所发现的,DaaS 是一种简化存储和处理大量数据的策略。这种存储可以来自云,然后由组织通过网络(通常是互联网连接)进行访问。DaaS 模型是为那些不想购买多块拼图,而是拥有成品的人而构建的解决方案。有许多好处,例如自动维护、灵活性、可移植性和节约成本的措施。但这并非没有失败。在选择解决方案之前,诸如安全性、数据治理和法规遵从性规则等问题是需要注意和仔细研究的。

读了更多关于 DaaS 的书,我现在明白了为什么它是一个在未来几年需要关注的领域。随着大数据、机器学习和云的扩展,支持这些数据的更简单方法将变得至关重要。更不用说任何成本节约了。我喜欢阅读关于这个话题的更多内容,我希望你也喜欢阅读关于 DaaS 的内容。欢迎对你认为值得了解的任何 DaaS 解决方案发表评论,或者对最好使用的云服务发表评论。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最近的一些文章:

https://miketechgame.medium.com/one-year-of-writing-on-medium-d4d73366e297 https://python.plainenglish.io/web-scraping-with-beautiful-soup-1d524e8ef32 https://python.plainenglish.io/something-i-learned-this-week-paramikos-remote-file-management-f13af69baf4

参考资料:

https://www.rocketsource.co/blog/data-as-a-service/ https://searchdatamanagement.techtarget.com/definition/data-as-a-service https://www.techslang.com/definition/what-is-data-as-a-service/ https://www.talend.com/resources/what-is-data-as-a-service/

“DAG 卡”是新的“模型卡”

原文:https://towardsdatascience.com/dag-card-is-the-new-model-card-70754847a111?source=collection_archive---------15-----------------------

行业笔记

从 Metaflow 自动生成 DAG 卡,灵感来自用于机器学习模型的谷歌卡。

介绍

“模仿是阿谀奉承的最早形式——王尔德(可能是在模仿别人)

S 软件在吃世界,人工智能在吃软件。然而,仍然有相对较少的人能够理解机器学习模型的行为——事实是,即使是人工智能专家也很难理解别人建立的模型,特别是如果它不是文献中的精炼模型,而是每天服务于数百万请求的实际 API。因此,问题是紧迫的:我们如何使模型易于为组织内外的更广泛的受众所理解?

玛格丽特·米歇尔等人的一篇肥*论文。在 2019 年引入了模型卡的概念,总结我们对给定模型的了解的“一页纸”:当然是输入和输出,但也包括测试集的准确性、偏差和限制、使用的最佳实践等。正如他们的人脸检测页面恰当地举例说明的那样,卡片被认为是“所有人的参考,不管专业知识”:ML 工程师将找到关于架构和量化性能的指针,pm 将阅读优势和弱点以想象新的用例,营销人员将获得其能力的鸟瞰图。

我们非常喜欢这个想法,以至于我们决定自己动手做一个元流卡生成器,从代码和注释中自我记录 ML 管道。

为了打造我们自己的卡片,我们对最初的想法做了一些调整(主要是因为我们专注于 B2B,以及仅限内部的受众):

  • 虽然 Google 样本卡非常可爱,但是我们想要生成没有手工操作的可读卡片;换句话说,我们希望从我们的代码中自动构建卡片;
  • Google 模型卡主要满足 B2C 用例,当一个模型通过公共接口在全球范围内大规模可用时;对我们来说,cards 主要面向成长中的公司的内部受众,他们很难跟踪新的特性,重要的领域知识需要进入模型,并且培训和测试中涉及到一些服务/框架;
  • 最后,虽然模型肯定是人工智能乐队的主唱,但他们不是孤立生活的单子:对我们来说,ML 工作几乎是“ML 管道”不变的同义词,或者更好,是“ ML DAG ”:鉴于我们为 ML DAG 选择的工具是 Metaflow ,我们的卡生成器可以被认为是运行在现有 Metaflow 类之上的“插件”。

为了对我们正在构建的东西有个感觉,这是我们的 DAG 卡样本的截图:

DAG 卡的一瞥,显示了所有者、任务、输入文件和参数。附带的代码展示了如何通过编程从一个元流类中生成这样一张卡片【作者截图——原始 Google card 此处】。

现在,让我们再次让文档变得伟大

书呆子注意:复制这篇帖子的代码在 Github 上分享:都是 WIP 和手绘,但是如果有兴趣的话,我们实际上可以构建一个合法的 PyPI 包!]

先决条件

这篇文章假设你知道为什么 Metaflow 很棒,Weights&bias很酷,以及它们是如何结合在一起的:如果你错过了第一季,你可以从我们的试点文章开始(注意,今天的 DAG 只是之前的一个的精简版)。

浏览一下自述文件,但是你基本上只需要确保你已经:

  • Metaflow 启动并运行,最好配置为使用基于 AWS 的设置;
  • 一个关于权重&偏差的账户,带有一个有效的 API 密钥。

等等,为什么是卡片而不是合并页?

我们知道你的同事会怎么说:

“我们当然有模型 XYZ 的文档!你查过合流吗?”

令人不安的事实是,是的,我们检查了,但我们还是一无所知。虽然 Confluence (以及类似的解决方案)是在公司内部共享知识的不可或缺的工具,但根据我们的经验,它很少能很好地用于 ML DAGs(尤其是对于新的、仍在变化的功能)。从拥有 ML 管道的人(也就是说,最终对其行为负责的人)的角度来看,我们认为 DAG 卡比 Confluence 页面具有关键优势:

  • 构建和更新 Confluence 页面是典型的手工工作。最重要的是,DAG 的 360 度视图涉及接入不同的服务和 API,因此涉及复杂的授权层、领域知识等。;DAG 卡是以编程方式构建的,并且可以在例如每个训练周期结束时进行更新。
  • 合流页面本来就是静态的:模型一直在变化,但是我们都容易忘记改变合流。DAG 卡仅仅依赖于回购协议中的内容:如果开发人员和测试人员更新文件和注释(作为良好编码实践的一部分,他们无论如何都应该这样做,卡将反映所有最新的变更;****
  • Confluence 页面不是交互式的:虽然当前的 DAG 卡也不是交互式的,但是不难扩展布局以包括一个测试界面(就像 Google cards 做的那样);******
  • 最后,但绝对不是最不重要的,Confluence 页面可能会或可能不会以与我们的 DAG 卡相同的精神写成“**”:如果 pm 写页面,我们就将模型创建者从其理论消费中分离出来;如果 ML 工程师编写页面,他们可能倾向于只强调某种类型的信息。虽然当然不存在防弹解决方案(因为人类事务倾向于抵制愚蠢的标准化),但我们相信 DAG 卡指向了正确的方向,因为鼓励工程师以全面的方式(定量和定性)解释他们的工作具有巨大的价值。通过首先要求 DAG 背后的人努力思考他们的代码到底做了什么——它的缺点、要监控的 KPI、无论如何都要做好的特殊情况——我们相信我们可以培养更大的所有权意识并防止许多错误在生产中出现。从某种意义上来说,我们的方式是老方式:“传刑的人要挥剑”。******

以编程方式构建卡片

卡片生成器脚本非常简单。鉴于:

  • 一个 HTML ( Jinja )模板;
  • 一个元流类(以及实例化客户端的配置文件);
  • 重量和偏差 API 键;

构建器将调用相关的服务,获取关于 DAG 和模型的信息,美化一堆 JSONs,最后组成一个静态 HTML 页面供用户使用。

卡片生成器使用一个 Jinja 模板并通过调用来自 Metaflow、Wandb 和其他服务的 API 来填充插槽:输出是一个简单的静态 HTML 页面[图片由作者提供]。

当端到端地运行代码时,最终结果是一个类似 Google 的卡片,在一个地方收集了大量关于我们的元流 DAG 的信息:

显示最终 DAG 卡的动画 GIF 图片由作者提供—原始截屏此处

特别是,我们将内容分为五个主要部分:

  • 概述:DAG 的高层描述(即 Python 类的 docstring )。
  • 所有者:包含 DAG 开发者/所有者的部分,以及显示他们之间运行分布的图表。
  • DAG:DAG 的可视化描述,以及带有步骤细节的可折叠部分(通过元流自身表示构建)。
  • 模型:可折叠的部分,报告最近 K 运行的度量,云存储的路径(对于希望恢复精确工件的 ML 工程师),架构草图,以及损失/时期图表。
  • 测试:在代码检查(例如,向量大小)和一般定量测试(例如,准确性)之上,行为测试被设计为对模型定性行为的“健全性检查”,并在被认为对部署很重要的案例上探测性能(例如,在一个小的但是关键的输入集上的模型性能)。解释我们的测试哲学超出了范围(这是一篇关于 NLP 测试的伟大论文!),我们只是注意到 DAG 卡可以报告重要用例的预测,这是 ML/QA 工程师在构建管道时指定的。更复杂模型的一个自然延伸是通过输入空间的划分(比如,按性别、种族和年龄划分的贷款违约概率)来分解准确性:尽管人类分析是无与伦比的,但行为测试就像是防止明显(但仍不罕见)错误的强大保障。

MVP 很简单,您应该能够扩展它,以包含更多的数据和/或更多的服务:Jinja 模板可以像俄罗斯娃娃一样构成,提供了一种将 UI 扩展到更多用例的原则方法。

虽然我们发布了工作代码来开始讨论,但我们从精益的角度来处理这个问题——这基本上意味着只需最少的努力来完成我们的卡:请确保查看自述文件中的一些技术“积压”,并让我们知道您是否希望看到这个实验产生更好的东西!

虽然“每个人都想做模型工作”,但我们确实相信,在一个正常运转的人工智能组织中,记录和共享信息同样重要:(模型)知识确实是力量(是的,既然你问了,法国是培根)。**

再见,太空牛仔

如有疑问或反馈,请连线分享你的 MLOps 故事(所有中媒观点均为本人观点)。如果你想合作并把这个想法扩展成一个完整的一揽子计划,请伸出援手!

DAG 工厂——更好的通风方式

原文:https://towardsdatascience.com/dag-factories-a-better-way-to-airflow-9aa3cf003169?source=collection_archive---------16-----------------------

气流编年史

使用动态生成的 Dag 来缩放气流

信用:由我们自己的团队建立

如果你一直在寻找一个工作流管理平台,我猜你已经遇到了 Apache Airflow 。这个被广泛使用的项目最初来自 Airbnb,现在打着 Apache 的旗号,是许多数据团队的首选工具。Airflow 允许您以声明的方式编写复杂的工作流,并提供许多开箱即用的操作员来完成复杂的任务。

在飞轮软件,我们大量使用气流进行复杂的 ETL 管道、机器学习管道和统计分析。此外,我们还管理多个气流部署,并运行运行大量工作负载的大型多租户气流集群。随着我们开始将气流推向极限,我们最近对如何部署到气流集群进行了改造,我敢说找到了更好的利用气流的方法。

我们的主要目标是摆脱部署 airflow 的声明式格式,更多地转向动态生成 Dag 以实现灵活性和可扩展性——允许我们只需修改一个功能标志,就可以快速更改 airflow 上运行的内容。这导致了 DAG 工厂的出现。

DAG 工厂—使用工厂模式和 python 类,根据系统的动态输入自动生成 DAG。

背景故事讲够了,是时候进入激动人心的部分了。为了做好准备,在本文中,我们将假设我们想要在 airflow 中执行两个复杂的任务——process _ message & process _ invoices。

图片前

在我们开始新的设置之前,重要的是快速了解一下在气流中通常是如何实现的。一种可能的方法是为你的每个项目准备一个单独的文件夹。您可以在每个项目文件夹中复制 Dag,或者将所有共享 Dag 放在一个shared _ Dag文件夹中。然后,您的部署管道可以从 monorepo 中选择正确的 Dag,将其推送到每个气流集群。实际上,文件结构可能类似于下面的代码片段。

随着您的项目开始增长,DAGS 和部署过程的复杂性将会迅速增加。在多租户集群中,您需要为气流多次复制相同的 DAG,以便为每个租户单独考虑它们。

后图— DAG 工厂

现在,有了 DAG 工厂,您可以获得一个更好的组织结构,它可以整合跨项目或租户的重复代码。通过将代码抽象成负责生成 DAG 对象的 python 类,我们使设置更加可配置。最棒的是,看起来玛丽·近藤对我们的 monorepo 进行了一次扫描,删除了所有不能引发欢乐的东西。

快速组件故障 🕺🏽

  • 项目/ <名称> /config.py — 从气流变量或集中配置存储中获取配置的文件
  • 项目/ <名称> /main.py — 核心文件,我们将在其中调用工厂方法来生成我们想要为项目运行的 Dag
  • dag_factory — 文件夹,其中包含我们工厂模式中的所有 dag,以及一组标准化方法的格式。

动态配置

这种架构的第一步是让我们的气流集群与我们平台上的集中式配置存储进行对话。这允许 airflow 从平台上的其他服务中动态获取配置,比如我们的 web 应用、特性标志或其他业务逻辑。我们不会深究商店本身,但这通常是通过使用 Etcd 、consult等工具,或者构建自己的瘦配置 API 来完成的。

在气流端,与配置存储的通信发生在 config.py 文件中。我们可以很容易地获取气流变量或使用配置存储的 API 获取配置。随着这些值的变化,气流将自动重新获取并重新生成 Dag。

工厂

移动到核心部分,我们所有的繁重工作都在 dag_factory 文件夹中完成。 DAGFactory() 类负责在工厂中映射我们支持的 Dag,并基于提供的键动态调用正确的模块。

dag_factory.py

正如您在上面的要点中所看到的, create() 函数只是返回一个正确映射的 dag 构建器类,可以像这样轻松地调用它:

factory = DAGFactory(config.environment)
factory.create('ProcessMessages', config.process_messages)

为我们的 process_invoicesprocess_messages 任务生成 Dag 的 python 类遵循特定的格式,以便从 DAGFactory 触发。每个文件都有以下标准化结构:

  • init() —设置全局& dag 特定配置参数。
  • build() — 构建并返回实际的 DAG 对象及其下的所有任务。这是定义任务实际功能的地方。

作为一个例子,在这个片段中,我们看一下 process_messages 工厂。它定义了两个任务,使用 KubernetesPodOperators 来获取和处理消息。这个 DAG 现在可以通过我们的 factory create() 方法用不同的变量多次调用——为我们提供同一个 DAG 的动态变化。

把所有的放在一起

一切最终都汇集在**projects/<project_name>/main.py**文件中——剩下要做的就是调用我们工厂上的 build 方法,并在父对象下重新配置那些返回的 DAG 对象。在这个例子中,我们可以看到调用工厂方法来生成 DAG 对象是多么容易。然后,我们只需使用可靠的子 DAG 操作器将它们添加到主 DAG 中。

打电话给 DAG 工厂

一旦一切就绪,该设置还允许我们运行具有多租户 DAG 工作负载的单个集群。让我们假设我们的配置存储返回client_config,这是多个客户端的配置数组。我们可以简单地遍历我们的客户端配置,并调用我们的工厂为每个客户端构建多个 Dag 的变体,如下一个片段所示。🤯

底线

就像任何其他工具一样,一旦你开始扩大规模,就必须停下来,重新思考如何改进或优化。我们需要一种更加动态和配置驱动的方法来处理气流,这使我们建立了 dag 工厂,希望这将有助于使用气流的更广泛的社区。对于我们来说,我们的气流集群可以自动构建 Dag 来监听配置变化,从而支持我们扩展多租户气流集群。

喜欢谈论技术或数据?

你很幸运,我也是!如果你想聊聊前沿技术、企业家精神或创业的风险,可以在推特(Twitter)或 LinkedIn 上找到我。

自动驾驶赛车戴乐

原文:https://towardsdatascience.com/daile-the-self-driving-racecar-558a1dd6cd24?source=collection_archive---------43-----------------------

照片由 MiRo Am 在 Unsplash 上拍摄

概观

  • 介绍
  • 什么是戴乐?
  • 挑战
  • 下一步是什么?
  • 结束语
  • 关于我

介绍

用艾尔顿·塞纳的话说,“如果你不再追求现有的差距,你就不再是一名赛车手,”作为一名机器学习工程师、偶尔的赛车迷和超级书呆子,我发现了一个非常有趣的差距:虚拟自动驾驶赛车的实现少得惊人。我已经找到了一些关于它的视频和简短的文章,但远没有我第一次梦想建造自己的时候所期望的那么多。

不过,这也说得通。赛道是非常动态的环境,即使你不与其他车手竞争,比赛本身也绝不简单。我自己,一个人类和而不是机器人,并不特别快,尽管我在驾驶模拟器上呆了几百个小时。但这似乎是一个有趣的项目,即使它悲惨地失败了,也将是一个学习一些新技术的机会,也许是别人令人敬畏的自动驾驶赛车想法的起点。

进入我的尝试去缺口:戴乐。

什么是戴乐?

简单地说,戴乐(以戴尔·恩哈特命名)是一个 PyTorch 模型,可以使用控制器输入来玩赛车模拟器 Assetto Corsa (AC)。他查看过去 60 帧的游戏画面,分析屏幕上的图像和相应的遥测数据,并决定是否转弯、加速或刹车。虽然他只接受了几个小时的我自己的驾驶数据训练,但他经常以新颖的方式对他以前见过的情况做出反应。为了证明这一点,你可以看到他正在尝试我最喜欢的马里奥赛车道,婴儿公园。

戴乐尝试婴儿公园

不太简化的版本是,戴乐是一个卷积递归神经网络(CRNN),ResNet18 用作图像编码器,一个处理编码图像和遥测数据的 2 层 LSTM,以及一个决定下一帧应该使用什么控制器输入的输出层。然后,戴乐使用 Python 的 pyvjoy 绑定将这些输入发送给 vJoy,这些输入经过 Steam 的大画面控制器设置并进入 AC。

当然,在戴乐能够做出正确的决定之前,他必须接受训练。为此,我创建了两个自定义工具:

  1. play_together.py:一个数据收集例程,允许汽车控制权在戴乐和人类玩家之间传递(灵感来自 sethbling 的 MariFlow )。
  2. 一个(可选的异步)数据采集(DAQ)系统,允许自定义采样率。同步数据收集阻止了戴乐在 play_together 例程中进行推理,从而导致了更差的性能。以非阻塞的方式捕获数据似乎在大多数方面都是一种直接的改进。

戴乐,在这个时间点上,是在一个纯粹的监督下接受训练的;向他展示随机批次的 60 帧序列(间隔 1/15 秒),并要求他预测第 60 帧应该使用什么输入。因此,他只在训练中看到的赛道上表现出智力的迹象。有人可能会说,这意味着戴乐只是过度适应了他以前看过的曲目,但我认为情况并非如此,因为赛道上的概率空间相当大,他甚至在非常类似于他应该熟悉的情况下也表现出了新奇的行为。

一旦戴乐训练完毕,就该在赛道上测试他了。我已经创建了一个戴乐类,它允许实例化模型的一个特定版本(如果你已经训练了几个不同的版本),并使在轨实时推理变得没有痛苦。推理运行时使用 OpenCV 窗口随时向用户显示戴乐的输入。

戴乐在红牛圈的最后一个弯道和第一个弯道超车

挑战

在戴乐的发展过程中,一直存在着几个关键的挑战,其中大部分与绩效有关。准备好一个功能原型是相当简单的,但是优化远远占据了我这个项目的大部分时间。作为一名大学生,我有一台用了五年的游戏台式机,没有钱在线租赁 GPU,我不得不在紧张的约束下工作。

框定这个问题是困难的。

这应该是分类问题还是回归问题?有许多方法可以实现这一点,但最终我选择将它作为一个回归任务。我知道你可以很容易地将不同的转向、制动和加速度值绑定,并将其作为一个分类问题,但回归对我来说似乎更自然。整体哪个好?虽然我已经实现了训练和测试这两种框架的代码,但不幸的是,我缺乏有效研究这两种框架的资源。

实时数据采集很复杂。

我发现,在 Assetto Corsa 这样的资源密集型模拟中,创建一致的数据流相当困难。我最初的数据采样技术在真空中测试时工作得非常完美——当游戏没有运行时,它捕捉了屏幕截图和我的控制器输入,没有任何延迟或错误——但当实际获取这个项目的数据时,它完全崩溃了。控制器输入特别麻烦,因为在一次测试运行后,对数据的快速调查显示,记录的控制器输入并没有反映我的真实输入。

罪魁祸首是我捕捉截图的方式。每次我抓取屏幕时,我的数据采集脚本中的其他所有东西都会停止,等待它完成。我通过创建一个 data_recorder 类来解决这个问题,这个类异步捕获它需要的所有数据,这意味着它不再阻塞数据获取过程的其余部分。

视频培训很耗时。

众所周知,视频数据的训练成本很高。这种介质数据丰富,预处理起来很麻烦(与表格数据相比),而且消耗内存的速度非常快。此外,对于这种格式,创建 PyTorch 数据加载器比我通常使用的表格数据更复杂。我很快就感受到了所有这些事情的影响:随着我的数据集变大,训练时间也随之膨胀。我尽可能地优化这个过程,但是我被迫开始通宵训练戴乐。我有让培训比现在更有效的想法,但是还没有时间去实施。

实时推理要求很高。

我的电脑需要以高帧率同时运行 Assetto Corsa 和戴乐。因为戴乐是在每秒 15 帧的数据上训练的,任何低于这个帧速率的显著下降都会导致不稳定的行为。然而,与此同时,我发现,不管 Assetto Corsa 在推理时间的帧率如何,用每秒 15 帧以下的数据训练戴乐都会导致不稳定的行为。

下一步是什么?

监督戴乐

我和戴乐还远没有结束。即使在他目前的监督形式下,我也觉得有很多需要优化和改进的地方。我想收集更多的训练数据,真正测试我设计的架构能够真正学习的极限。戴乐已经展示了良好的决策技巧,即使我收集的数据非常有限。有了更多的数据,我感觉他会进一步提高。

无人监管的戴乐

然而,一旦我在这个项目的迭代中用尽了我的想法,我想继续进行强化学习方法。我已经看到塞斯布林的《玛丽克》和约什的《轨道狂热 AI》取得了难以置信的成功。我知道这个阶段将需要比监督戴乐更重的计算,但我希望在我准备好进入下一个阶段时,能够获得更好的培训资源!

结束语

总的来说,戴乐是对我技能的一次令人兴奋的测试,这个项目融合了我喜欢的许多东西:机器学习、软件工程、赛车和项目管理。这迫使我去设计、再设计、再设计系统,使它们一致、模块化、高效。与此同时,工作也是一种乐趣——第一次成功地看到戴乐感觉就像魔术一样。我希望在这样的项目上花更多的时间。

感谢您花时间阅读这篇文章!如果你对这个项目有任何疑问,请在评论中留言或在 LinkedIn 上联系我。你可以在我的戴乐 GitHub repo 中找到我的作品的可自由发布和修改的代码。

关于我

一年半前,在本田漫长的实习结束时,我决定将我的职业道路从专注于设计的机械工程完全转向机器学习工程。我一直对计算机科学充满热情,尽管我没有正式学习过它,而且我已经编码很多年了,所以这种转变更多的是焦点的改变,而不是整体的范式转变。尽管如此,我还是需要投入一些认真的自学时间来学习机器。我花了很多周末和工作日的晚上去上 Udacity 和 Udemy 的课程,从计算机视觉到网页设计(因为许多 ML 产品都是基于网络的),这让我在当地医院开始了我的第一次 ML 研究员实习。

从那以后,我开始攻读硕士学位,提交了第一篇论文发表,现在我正式在俄亥俄州立大学学习计算机科学课程。现在,和戴乐一起,我从零开始创建了我的第一个公开可用的 ML 项目(即没有预先制作的项目大纲或手持指南)。

在 Pandas 中将每日数据转换为每周数据

原文:https://towardsdatascience.com/daily-to-weekly-pandas-c0557b12f052?source=collection_archive---------2-----------------------

将每日数据转换为每周数据的实践教程

在这篇文章中,我将展示 4 种不同的方法来将熊猫的每日数据转换为每周数据,并比较它们的性能。

作者图片

挑战

最近,在我的一个研究生班里,我被要求使用熊猫和 Jupyter 笔记本来评估去年美国各县的新冠肺炎每日病例。面临的挑战是以每周数据而不是每天数据的形式呈现调查结果。作为一个使用 Pandas 的初学者,这个简单的任务一开始让我望而生畏,但是在完成这个任务的过程中,我开发了 4 种不同的方法来将每日数据转换成每周数据。

本文使用的 csv 文件可在usafacts.org网页上公开获得。

import os
import numpy as np
import pandas as pd
import time

cases = pd.read_csv('covid_confirmed_usafacts.csv')

首先,让我们准备好要处理的 cvs 文件:

  • 为了简化输出,我们将只关注四种状态下的案例总数:CA、or、WA 和 NV。因此,可以删除不需要的县和州标识列。
  • 我们的评估周将于周一开始,周日结束。因此,对应于日期范围的开始/结束周的日期的列也可以被删除。对于本出版物,使用的数据文件包含从 2020 年 1 月 22 日到 2021 年 2 月 7 日的数据。
  • 原始 csv 文件中的数据是新冠肺炎病例的累计,需要转换为新病例。这是通过对按状态分组的数据帧应用 sum()和 diff()函数来实现的。
  • 最后,01/26/2020 是数据帧中第一个星期一之前的一个星期日,是不完整周的一部分。只有在计算出新病例数后,才能删除它,这样第一个星期一的新病例数据才不会丢失。
cases_states = cases.query("State == 'CA' | State == 'OR' | State == 
                           'WA' | State == 'NV'")
cases_states_filtered = cases_states.drop(columns = ['countyFIPS', 
                       'StateFIPS','County Name',  
                       '2020-01-22','2020-01-23', '2020-01-24', 
                       '2020-01-25'])
cases_states_daily_total = cases_states_filtered.groupby('State').sum()
new_cases_daily_total = cases_states_daily_total.diff(axis = 1)
new_cases_daily_total = new_cases_daily_total.drop(columns =  
                                                   ['2020-01-26'])
display(new_cases_daily_total)

方法 1:使用 Python for 循环。

据我所知,在 Pandas 中使用 Python for-loops 迭代数据并不是将每日数据转换为每周数据的最有效方式。仅仅用 Python for-loops 循环并没有利用 Pandas 提供的任何内置功能,这是完成手头任务最慢的方式。然而,在这个旅程的开始,for-loops 似乎是将每日数据列转换为每周数据列的最简单的方法,所以我从实现一个函数开始。

函数 new_case_count()接受 DataFrame 对象,对其进行迭代,并将索引(字符串格式的日期)转换为 Pandas Datetime 格式。基于日期的星期几,计算每周的新案例数并存储在列表中。该函数返回每个州的每周新病例计数列表。

为简单起见,这种方法和其他方法的输出只显示最近 5 周的数据。

def new_case_count(state_new_cases):
    first_Monday_found = False
    week_case_count = 0
    week_case_counts = []
    for index, value in state_new_cases.items():
        index_date = pd.to_datetime(index, format='%Y/%m/%d', 
                                    exact = False)
        index_day_of_week = index_date.day_name()
        if not first_Monday_found and index_day_of_week != 'Monday':
            continue
        first_Monday_found = True
        week_case_count += value
        if index_day_of_week == 'Sunday':
            week_case_counts.append(week_case_count)
            week_case_count = 0
    return week_case_counts

# converting list to DataFrame object
new_cases_weekly_total_method_1 =  
                 pd.DataFrame(new_case_count(new_cases_daily_total))display(new_cases_weekly_total_method_1.tail(5))

方法 2:重新标记和 groupby()。

我下一次将每日数据转换为每周数据的尝试不涉及任何 for 循环。然而,它仍然是四种方法中第二慢的方法。

函数 rename_columns_dates()接受 Series 对象并将索引(字符串格式的日期)转换为 Pandas Datetime 格式。日期被重新标记为当前周的星期一的日期,格式为“%Y/%m/%d”,后跟分隔符(%符号)和当前日期与当前周的星期一的偏移量。该函数返回一个表示新日期标签的字符串。例如,对于星期一 2021/01/25,返回字符串将是“2021/01/25%0”,对于星期二 2021/01/26,返回字符串将是“2021/01/25%1”,依此类推。

接下来,通过在分隔符(%)处拆分数据标签,并对以同一个星期一作为日期的组的值求和,每周对新案例进行分组。

def rename_columns_dates(new_cases_index):
    index_date = pd.to_datetime(new_cases_index, format='%Y/%m/%d', 
                                exact = False)  
    index_day_of_week = index_date.day_name()
    offset_from_monday = 0
    if index_day_of_week == 'Tuesday':
        offset_from_monday = 1
    elif index_day_of_week == 'Wednesday':
        offset_from_monday = 2
    elif index_day_of_week == 'Thursday':
        offset_from_monday = 3
    elif index_day_of_week =='Friday':
        offset_from_monday = 4
    elif index_day_of_week == 'Saturday':
        offset_from_monday = 5
    elif index_day_of_week == 'Sunday':
        offset_from_monday = 6

    # new_date is a class of Pandas.Timeframe   
    new_date = index_date - pd.Timedelta(days = offset_from_monday)
    return (new_date.strftime('%Y/%m/%d') + '%' + 
                              str(offset_from_monday))

new_cases_weekly_total = new_cases_daily_total.rename(rename_columns_dates, axis = 'columns')

# grouping new cases weekly by splitting data labels at delimiter (%) and summing the values for the same Mondaynew_cases_weekly_total_method_2 = new_cases_weekly_total.groupby(new_cases_weekly_total.columns.str.sp
                               lit('%').str[0], axis=1).sum()display(new_cases_weekly_total_method_2.T.tail(5))

方法 3:重采样()。

这个方法使用了一个 resample()函数。我在 Medium 上看到两篇文章在这里和在这里,介绍如何使用重采样()将每日数据转换为每周数据。在对数据框架做了一些修改后,我让这个方法运行起来。

如本文结尾所示,它是四个中第二快的。

new_cases_daily_total_modified = new_cases_daily_total.T.reset_index()

new_cases_daily_total_modified = 
new_cases_daily_total_modified.assign(Weeks =                                     new_cases_daily_total_modified['index']).drop(columns = 'index')

new_cases_daily_total_modified['Weeks'] =  
new_cases_daily_total_modified['Weeks'].astype('datetime64[ns]')

new_cases_weekly_total_method_3 = new_cases_daily_total_modified.resample('W-Mon', label='left',                                                                          closed = 'left', on='Weeks').sum()display(new_cases_weekly_total_method_3.tail(5))

方法 4: groupby()。

这种方法的想法是在阅读了 stackoverflow 上的建议后产生的。我很高兴您可以在一行中一次按 7 对列进行分组。然而,这种简单性的代价是失去日期标签,取而代之的是数字索引,在本例中是 0–53。

为了解决这个问题,我想到了使用 pd.period_range()函数创建一个所需的日期范围,将日期范围转换为序列,并将其添加到现在有每周数据的 DataFrame 中。函数的作用是:返回一个固定频率的 PeriodIndex。这种格式的日期周期如下所示:“星期一日期/星期日日期”。您可以保持原样,或者用分隔符('/')将字符串分开,只让星期一日期标记一周的开始。

这种方法被证明是四种测试方法中最快的方法。

new_cases_groupby_total_method_4 = new_cases_daily_total.groupby([[i//7 for i in range(0,378)]], 
                                axis = 1).sum().T

date_range = pd.period_range(start = '2020-01-27', end =  
                             '2021-02-07', freq = 'W-SUN')
date_range = date_range.map(str)
date_range = date_range.str.split('/').str[0]

date_range = pd.Series(date_range)

new_cases_weekly_total_method_4 = 
         new_cases_groupby_total_method_4.assign(Weeks = date_range)print('DataFrame after groupby():')
display(new_cases_groupby_total_method_4.tail(5))

print('date_range Series:')
display(date_range.tail(5))

print('Final Dataframe:')
display(new_cases_weekly_total_method_4.set_index(['Weeks']).tail(5))

DataFrame after groupby()

date_range Series:

49    2021-01-04
50    2021-01-11
51    2021-01-18
52    2021-01-25
53    2021-02-01
dtype: object

Final Dataframe

绩效评估:

测量每种方法的执行时间。我使用%%timeit 在 Jupyter 笔记本上测量执行时间,方法是将%%timeit 放在每个方法单元格的顶部。为了比较这四种方法的性能,我在 Jupyter 笔记本上连续运行了 10 次。

重要的是要记住,10 次运行的样本量非常小,这只是对方法性能的快速浏览。

结果数据已被转换为数据帧。计算平均值和标准偏差。

data_milliseconds = {'Method 1: for-loops':[87.00, 88.3, 88.2, 87.3,
                    86.8, 87.1, 86.8, 87.2, 89.1, 87.5], 
                    'Method 2: relabeling/groupby()':[56.8, 57.2, 
                    57.2, 56.8, 56.7, 56.9, 56.9, 56.7, 57.0, 57.1],
                    'Method 3: resample()':[4.6, 4.61, 4.56, 4.53, 
                    4.5, 4.52, 4.54, 4.49, 4.55, 4.51],
                    'Method 4: groupby()':[3.52, 3.51, 3.51, 3.47, 
                    3.6, 3.47, 3.53, 3.5, 3.45, 3.46]} 

methods_performance = pd.DataFrame(data_milliseconds).T
methods_performance['Mean'] =  
                   methods_performance.loc[:,'0':].mean(axis = 1)
methods_performance['Std'] = methods_performance[0:].std(axis = 1)

display(methods_performance)

结论:

  • 重要的是要记住,样本大小只是 Jupyter 笔记本文件的 10 次运行。
  • 方法 4 (groupby()方法)是四种方法中最快的。
  • 方法 4 的运行速度是方法 1 (for-loop 方法)的大约 25 倍,是方法 2 (relabeling/groupby()方法)的大约 16 倍。
  • 方法 3(重采样()方法)的运行速度几乎与方法 4 (groupby()方法)一样快,而方法 4 的运行速度快 1.3 倍。
  • 虽然我预计方法 1 和 2 比方法 3 和 4 慢,但我惊讶地发现方法 4 是所有方法中最快的。
import matplotlib.pyplot as plt 

plt.figure(figsize=(13,6))
methods_performance['Mean'].plot(kind = 'bar',  
                   yerr=methods_performance['Std'], align='center',
                   alpha=0.5, color=['red', 'blue', 'purple',  
                   'green'], ecolor='black', capsize=10)
plt.xticks(rotation = 0)
plt.ylabel('Execution time in milliseconds', fontsize=14);
plt.title('Performance Comparison of four different methods\n for  
          daily to weekly data conversion in Pandas\n', fontsize=14)
plt.show()

感谢您的阅读,

月形蝴蝶

注:我用 jupyter_to_medium 发表这篇文章。

DALL E by OpenAI:从文本中创建图像

原文:https://towardsdatascience.com/dall-e-by-openai-creating-images-from-text-e9f37a8fe016?source=collection_archive---------20-----------------------

创造性人工智能的又一个里程碑

作者截图(本文使用截图经 OpenAI 批准)

今天是 2021 年 1 月 5 日,OpenAI 已经报告了另一项人工智能突破。2020 年,他们至少通过两个里程碑影响了人工智能世界: GPT-3 ,一个强大的自然语言处理模型,和一个音乐生成器点唱机。

在 Transformer 的驱动下,这两种不同媒体的方法创造了连贯而令人信服的输出——文本和音乐。OpenAI 还尝试了视觉媒体——例如,在 ImageGPT 中。

现在,一颗新星出现在生成式人工智能方法的地平线上: DALL-E 。以超现实主义者萨瓦尔多·达利和科幻动画《瓦力》命名,这个变形金刚语言模型代表了一个多模态神经网络

为了更好地理解世界,人工智能系统通过几种方式学习概念,主要是文本和视觉领域。( OpenAI )

我想这是避免 AGI 索赔的好方法。甚至 OpenAI 也意识到,通往 AGI 的路还很长(正如这些人在经历了围绕 GPT-3 的炒作后所说的那样):

事实上,AGI 需要一个全能和多媒体的方法。但是 DALL E 是迈向这个目标的一大步。

DALL E 做了它被描述要做的事情:从文本提示创建图像。这是 GPT-3 的 120 亿参数,可以使用文本-图像对从文本中生成图像。

变压器驱动的神经网络已经是一种势不可挡的现象。即使我们可以讨论“理解”,概念的“理解”也是极其重要的。提醒 GPT-3 由烤面包机写的情书:

作者截图

在这种情况下,GPT-3 明白了:

  • 情书的本质
  • 烤面包机的功能和特点
  • 将两个概念结合成一个“Gesamtkunstwerk”

通过你的提示,你不只是“编程”变压器驱动的模型。你把你的要求传达出去,就像传达给一个设计机构——结果可能会让你开心、被吸引,或者让你烦恼(这是一个品味问题)。

DALL E 完美地完成了它的工作——当我们可以用“完美”这个形容词来形容这种创造性的方法时。

在展示 DALL E 的博客中,你可以看到模型的运行——各种背景的预渲染图像。你甚至可以在交互模式下在一些预定义的参数之间进行选择。

例如,这里有一个提示:

A [store front] that has the word [openai] written on it

作者截图

将第二个参数(word)改为“Skynet ”,我们得到另一组图像:

作者截图

或者:剪辑

作者截图

你看,任务是如何被接受和实现的——以各种风格和视觉效果,基于预先训练的模型。

Text2Img 确实有其他方法,但 DALL E 每次都胜出:

对物体、形状和颜色的实验证明了这种神经网络的能力。

使用提示

an [armchair] in the [shape] of [avocado/pikachu/japanese mapple]

作者截图

你会得到具有惊人风格连贯性的照片般真实的图像,以及同一主题中的多样性。

有趣的是,DALL E 无需额外训练,就能完美配合零距离视觉推理。

下面是一个使用文本和图像的更复杂的提示:

作者截图

你看到同样的猫,邮票,和各种各样的颜色和图案。

恰如其分的设计,该系统可以识别风格和情绪的图像特征。

举个例子,我们以猫头鹰为表情符号。

下面是一只困惑的猫头鹰:

作者截图

一只沮丧的猫头鹰:

作者截图

一只快乐的猫头鹰:

作者截图

一只困倦的猫头鹰:

作者截图

DALL E 还具有基于预训练的时间风格知识,例如,来自不同时期的设备的视觉表示:

作者截图

这里甚至还有地理和文化知识。例如,系统可以生成地标的图像,并结合风格转换的图像提示:

作者截图

在这里你可以看到各种科幻 MOMA 幻觉与“夜空”的图像提示。

事实上,即使 AGI 仍然在未来,DALL E 无疑是向它迈出的一大步——理解人类的要求,应用自己的知识,生成逼真和独特的图像,它为艺术、设计和讲故事的各种方法开辟了新的途径。

现在,只要它一上市,我就迫不及待地想试用它。因为已经了解了 GPT 3 号的能力,我可以毫无顾忌地说——这是一次令人兴奋的经历。

DALL E 在 5 分钟内解释了

原文:https://towardsdatascience.com/dall-e-explained-in-under-5-minutes-327aea4813dd?source=collection_archive---------18-----------------------

https://openai.com/blog/dall-e/.

似乎每隔几个月,就会有人发表一篇让我瞠目结舌的机器学习论文或演示。这个月,它是 OpenAI 的新图像生成模型 DALL E 。

这个庞大的 120 亿参数神经网络接受文本标题(即“鳄梨形状的扶手椅”),并生成与之匹配的图像:

出自https://openai.com/blog/dall-e/.

我认为它的图片非常鼓舞人心(我会买一把鳄梨椅),但更令人印象深刻的是 DALL E 理解和呈现空间、时间甚至逻辑概念的能力(稍后会详细介绍)。

在这篇文章中,我会给你一个 DALL E 能做什么的快速概述,它是如何工作的,它如何适应 ML 的最新趋势,以及为什么它是重要的。我们走吧!

DALL E 是什么,它能做什么?

7 月,DALL E 的创造者 OpenAI 公司发布了一个类似的巨大模型,名为 GPT-3,它能够生成类似人类的文本,包括专栏文章、诗歌、十四行诗,甚至计算机代码,震惊了世界。DALL E 是 GPT 3 的自然扩展,它解析文本提示,然后用图片而不是文字来回应。例如,在 OpenAI 博客的一个例子中,模型从提示“一个有两把白色扶手椅和一幅壁画的客厅”中渲染图像。这幅画挂在一个现代壁炉的上方:

出自https://openai.com/blog/dall-e/.

很圆滑,对吧?你可能已经知道这对设计师有多有用了。请注意,DALL E 可以根据提示生成大量图像。这些照片然后由第二个 OpenAI 模型进行排序,这个模型叫做 CLIP ,它试图确定哪些照片匹配得最好。

DALL E 是如何建成的?

不幸的是,我们还没有这方面的大量细节,因为 OpenAI 还没有发表完整的论文。但在其核心,DALL E 使用了同样的新神经网络架构,这是 ML 最近取得大量进展的原因:变压器。2017 年发现的 Transformers 是一种易于并行化的神经网络,可以在庞大的数据集上进行扩展和训练。它们在自然语言处理(它们是 BERT、T5、GPT-3 等模型的基础)、提高谷歌搜索结果、翻译的质量,甚至在预测蛋白质结构方面都具有特别的革命性。

这些大型语言模型中的大多数都是在巨大的文本数据集上训练出来的(就像所有的维基百科或网络抓取)。然而,DALL E 的独特之处在于,它是在由单词和像素组成的序列上进行训练的。我们还不知道数据集是什么(它可能包含图像和说明),但我可以向你保证它可能是巨大的。

DALL E 到底有多“聪明”?

虽然这些结果令人印象深刻,但每当我们在一个庞大的数据集上训练一个模型时,持怀疑态度的机器学习工程师问这些结果是否仅仅是因为它们是从源材料中复制或记忆的,这是正确的。

为了证明 DALL E 不仅仅是回流图像,OpenAI 的作者强迫它呈现一些非常不寻常的提示:

"一个专业的高质量的长颈鹿龟嵌合体插图."

出自https://openai.com/blog/dall-e/.

“竖琴做的蜗牛。”

出自https://openai.com/blog/dall-e/.

很难想象该模型在其训练数据集中遇到了许多长颈鹿和乌龟的混血儿,从而使结果更加令人印象深刻。

更重要的是,这些奇怪的提示暗示了 DALL E 更令人着迷的东西:它执行“零射击视觉推理”的能力

零距离视觉推理

通常在机器学习中,我们通过给模型数千或数百万个我们希望它们执行的任务示例来训练模型,并希望它们能够理解模式。

例如,为了训练一个识别狗品种的模型,我们可能会向神经网络显示成千上万张按品种标记的狗的图片,然后测试它标记新狗图片的能力。与 OpenAI 的最新成就相比,这是一项范围有限的任务,看起来几乎有些古怪。

另一方面,零射击学习是模型执行他们没有被特别训练去做的任务的能力。例如,DALL E 被训练从字幕生成图像。但通过正确的文本提示,它也可以将图像转换为草图:

提示的结果,“顶部的猫与底部的草图完全相同”。来自【https://openai.com/blog/dall-e/】

DALL E 还可以在街道标志上呈现自定义文本:

结果来自提示“写有‘open ai’字样的店面”。出自https://openai.com/blog/dall-e/.

通过这种方式,DALL E 几乎可以像 Photoshop 滤镜一样工作,即使它不是专门设计来这样工作的。

该模型甚至显示了对视觉概念(即“宏观”或“横截面”图片)、地点(即“中国食物的照片”)和时间(从夜晚的街道拍摄的旧金山阿拉莫广场的照片)的“理解”;“一张 20 年代的手机照片”)。例如,下面是它在回应提示“中国食物的照片”时吐出的内容:

《中国美食照》摘自https://openai.com/blog/dall-e/.

换句话说,DALL E 能做的不仅仅是为标题描绘一幅美丽的图画;从某种意义上来说,它也可以直观地回答问题。

为了测试 DALL E 的视觉推理能力,作者让它接受了视觉智商测试。在下面的例子中,模型必须完成网格的右下角,遵循测试的隐藏模式。

来自 https://openai.com/blog/dall-e/.用来测试 DALL E 的视觉智商测试 OpenAI 截图

“DALL E 通常能够解决涉及连续简单模式或基本几何推理的矩阵,”作者写道,但它在一些问题上比其他问题做得更好。当拼图的颜色颠倒时,DALL E 的表现更差——“表明它的能力可能会以意想不到的方式变得脆弱。”

这是什么意思?

DALL E 给我印象最深的是它在许多不同的任务上表现惊人的出色,这些任务甚至是作者们没有预料到的:

“我们发现,当以正确的方式提示时,DALL E […]能够执行几种图像到图像的翻译任务。

我们没有预料到这种能力会出现,也没有修改神经网络或训练程序来鼓励它。"

这很神奇,但并非完全出乎意料;DALL E 和 GPT-3 是深度学习中一个更大主题的两个例子:在未标记的互联网数据上训练的特大神经网络(“自我监督学习”的一个例子)可以是高度通用的,能够做许多不是专门设计的事情。

当然,不要把这个误认为是一般的智力。欺骗这些类型的模特让他们看起来很蠢并不困难。当它们可以公开访问时,我们会知道得更多,并且我们可以开始使用它们。但这并不意味着我在此期间不能兴奋。

想要更多关于机器学习的东西吗?在推特上关注@ dale quark

原载于 2021 年 1 月 6 日 https://daleonai.comhttps://daleonai.com/dalle-5-mins

Darkeras:使用 Darknet 预训练的权重在 keras 上执行 YOLOv3/YOLOv4 对象检测

原文:https://towardsdatascience.com/darkeras-execute-yolov3-yolov4-object-detection-on-keras-with-darknet-pre-trained-weights-5e8428b959e2?source=collection_archive---------19-----------------------

宇宙中的一切都是相互联系的。

基于卷积神经网络的目标检测已经成为计算机视觉中的一个主要课题,因为它吸引了该领域的众多研究人员。各种先进的方法可以分为两大类:一级对象检测器(例如 SSD、YOLOv1-v5、EfficientDet、RetinaNet)和两级对象检测器(例如 R-CNN、快速 R-CNN、更快 R-CNN、级联 R-CNN)。虽然两级对象检测器旨在提高检测精度,但是已经开发了一级对象检测方法,试图平衡精度和推理速度之间的折衷,因此,由于它们可应用于需要上述折衷平衡的现实世界问题,所以它们正受到更多的关注。

图来自论文:物体探测 20 年:一项调查

在几十种精英方法中, Joseph Redmon 的 YOLO(你只看一次)被认为是该领域最强大、最经典的方法之一。虽然 Joseph 宣布由于一些个人原因,他停止了他的项目,该项目是物体检测的一个重要里程碑,但他将 YOLO 项目的领导特权交给了 Alexey Bochkovskiy,Alexey 在 2020 年推出了 YOLOv4。你可以通过官网或者 github repo darknet 来看看这个项目。

图片来自暗网网站

以上只是你可能关心(也可能不关心)的一条信息。现在我们回到带你来这里阅读这篇文章的原因,标题:“Darkeras:用 Darknet 预训练的权重在 keras 上执行 YOLOv3/YOLOv4 对象检测”。你们可能知道如何使用暗网,其他人可能是 Tensorflow-Keras 的专业人员。在我使用这两个框架的经验中,Darknet 是为对象检测而创建的,因此,在这项任务中,它应该被优化并产生比 Tensorflow-Keras 更好的结果。这就像一个对一件事情了解很深的人和另一个对事情了解很广的人。在这个场景中,暗网是第一个深入了解 YOLO 的人。但是,Darknet 并不是为用户定制太多而设计的!例如,你可以改变网络架构、超参数,但你不能或很难做一些高级学习方法,如知识提炼、基于提示的学习或特征图分析,但 Tensorflow-Keras 可以。为了利用这两个家伙的美丽价值,我写了这篇文章,并为你们提供了一个工具,用于转换 Darknet 训练的权重并在 Tensorflow-Keras 上执行对象检测。你可以在这里看我的项目。

该项目的说明如下:

属国

  • OpenCV
  • 张量流 2.3.0
  • Keras 2.4.0

支持的型号

  • YOLOv3
  • YOLOv4

如何使用

  • 将从官方 Darknet 网站下载的预训练权重或您训练的权重放入“权重”文件夹(如果您使用在您定制的数据集上训练的模型,请更改笔记本中的 NUM_CLASS 和 ANCHORS)
  • 运行 YOLOv3: darkeras-yolov3.ipynb
  • 运行 YOLOv4: darkeras-yolov4.ipynb

检测结果

  • 投入

图片来自 Github

  • YOLOv3

图片来自 Github

  • YOLOv4

图片来自 Github

玩得开心!

该项目经常更新。

结论

在这篇文章中,我介绍了 Darkeras,这是一个用 Python 编写的工具,用于将在 Darknet 软件上训练的权重文件转换为 keras 框架。该项目旨在使用在 Darknet 软件上训练的权重,在 Tensorflow-Keras 框架中支持高级学习方法,如知识提炼、基于提示的学习或特征图分析。

欢迎读者访问我这个项目的 github repo 和分享机器学习相关事情的脸书粉丝页:潜入机器学习。

感谢您抽出时间!

时间序列预测的飞镖瑞士刀

原文:https://towardsdatascience.com/darts-swiss-knife-for-time-series-forecasting-in-python-f37bb74c126?source=collection_archive---------2-----------------------

实践教程

一个多方法 Python 包,用于在您的时间序列上运行比赛

一步一步的教程,教你如何用飞镖建立一个单独的 Python 脚本——然后通过几种替代方法运行你的源时间序列,在模型中找到最适合的,类似锦标赛的。

在本例中,我们将对源数据运行五种预测方法,然后比较它们的准确性。

作者图片

Darts 嵌入了我们从更专业的 Python 包中知道的大多数广泛使用的时间序列预测方法。其中,它包装了 facebook Prophet 模型和 pmdarima 的自动 arima 包。 Darts 也实现了几种神经网络架构。

  • 指数平滑法
  • 天真的漂移+季节性预测
  • (自动)SARIMAX
  • ㈤ARIMA
  • θ方法
  • facebook 先知
  • 线性回归
  • 递归神经网络,如香草 RNN,LSTM 和 GRU
  • 时间卷积网络 TCN
  • 快速傅立叶变换 FFT
  • 神经基扩展分析时间序列预测 N 拍

所有这些模型在单个库中的组合大大减少了安装和维护单独应用程序的痛苦;以及努力建立几种可供选择的预测方法。Darts 提供了一个相当全面的包,我们可以用几行代码调用多个模型,以确定最佳拟合方法或构建集合预报。

Darts 是由总部位于瑞士的数据分析和人工智能公司 unit8 开发的开源包。(除了安装 pip飞镖之外,我与 unit8 没有任何关系或联系)

得一个例子。省道的安装

和往常一样,您应该在尝试安装一个庞大的 Python 包之前创建一个新的虚拟环境,这个包有许多依赖项,比如 Darts 的。您希望避免基础环境中的现有软件包因新安装而降级或升级。

Anaconda 中创建一个虚拟环境:

  • conda create--name<your_chosen_env_name>python = 3.7</your_chosen_env_name>

请注意,我在使用 fbProphet 组件时遇到了困难,但是已经解决了。虽然我的基本环境运行在 Python 3.8.8 上,并且大多数 Darts 组件都接受它,但我发现我必须建立一个 Python 3.7 环境,显然是为了适应 fbProphetProphetPyTorch 具有非 Python 依赖关系,因此如果试图并行安装所有组件时出现错误消息,安装可以在一个 Darts 核心包和额外组件之间进行。

关于安装的附加信息:一个 python 库,用于时间序列的简单操作和预测。| PythonRepo

飞镖所有其延伸部分 fbProphet 进行 pip 安装;pmdarima (针对 SARIMAX);和 PyTorch (用于神经网络)——使用命令:

  • pip 安装' u8darts[all]'

如果你遇到问题,你可以先安装飞镖而不需要额外的东西:

  • pip 安装 u8 飞镖

然后尝试逐步添加额外内容:

  • pip 安装 'u8darts[fbprophet]'
  • pip 安装 'u8darts[pmdarima]'
  • pip 安装' u8 飞镖【火炬】'

PmdarimaPyTorch 没有在我的机器上造成任何安装问题。

得了。属国

在本教程中,我们将导入七个飞镖的预测模型:

  • 天真,
  • 先知,
  • 指数平滑,
  • ARIMA,我们将与 ARIMA 汽车公司合并,
  • θ法。

我们还导入了一个 Darts 预测准确性度量库以及 Box-Cox 转换器;以及公共领域数据集的目录,这些数据集被构建到 Darts 中,并且可以被加载而不需要处理外部文件。

在本教程中,我们将重点关注 Box & Jenkins 的经典月度航空乘客数据集。

对于预测前和预测后诊断,我还将利用从 pmdarimastatsmodels 导入的一些假设检验。 Darts 主要依靠其图表提供的视觉线索来评估时间序列属性,比如正态性。由于 Python 代码本身不容易解释图表,而是需要用户决定如何继续,所以我添加了一些测试来自动化工作流。

在 dependencies 单元格的底部,我们插入几个常量作为默认参数。最重要的常数是训练数据集的截止日期。

在我们的航空客运例子中,我选择 1957 年 5 月 1 日作为测试期的开始;它延伸到 1960 年。

1.数据加载和争论

在下一个单元格中,我们加载航空公司数据集。你可以看到几个源代码——都内置在 Darts 包中——我通过在它们前面加上注释指示符#来暂时停用它们。

熊猫不同,飞镖不会将数据集加载到传统的数据帧中。相反,源数据被分配给变量 ts ,一个时间序列对象(第 3 行)。

如果数据集包含一个以上的序列,如果我们希望将下一步限制在多个列中的一个单变量时间序列,我们可以选择一个列并将其分配给一个 series 对象。我们的数据集只包含乘客人数,因此第 12 行将 ts 变量全部赋给序列变量 series

对于 Pandas 中的数据争论,我们可以通过应用函数将这个 timeseries 对象转换成 dataframe。pd_dataframe() (第 13 行)。

让我们回顾一下原始数据。

作者图片

作者图片

作者图片

为了处理任何丢失的数据或零,我选择应用回填方法。fillna() 函数。

让我们绘制源数据。

作者图片

该图在每个日历年都有一个峰值,显示了月度季节性。让我们做个测试来确认视觉线索。

2。诊断

便利的是,与许多其他套装不同, Darts 提供了一个检查季节性的测试。它返回一个布尔值 is_seasonal 以及季节订单号 mseas (例如, mseas =12 表示一个日历年中的几个月),它是通过评估时间序列的相关图(ACF)找到的。

我们将把测试发现的季节性输入到预测模型中。

作者图片

3.训练和验证数据集

Darts 提供了几种在训练和测试(验证)数据集之间分割源数据的替代方法。

在脚本顶部的 dependencies 单元格中,我导入了 numbers 库。我使用 isinstance() 函数来检查限制器的类型,我们在依赖关系中将它定义为常量 TRAIN 。根据源数据的不同,序列可能会对数字索引、日期时间类型的日期或字符串类型的日期进行编码。

  • 如果限制器不是一个数字而是一个类似“19571201”的字符串,我们需要使用 pd。Timestamp 方法将其转换为可识别的日期,以供飞镖使用。
  • 如果限制器是数字, Darts 检查它是否是整数,例如 120——如果是,训练数据集将在该索引号之前结束,即索引#120 的行;
  • 如果限定符是一个浮点数,Darts 将尝试把它解释为一个日期,例如 1957–12–1。在我们当前的例子中,我们已经通过输入 datetime.datetime(1957,5,1)将列车限制器定义为一个日期时间浮点数。日期()函数。

在我们脚本的顶部单元格中,我插入了一个常量 TRAIN ,在其中我设置了日期或索引,在这个日期或索引处,源数据将在训练和测试期间被分割。序列中的值的类型取决于源数据中的日期或索引列。在脚本中,您可以看到火车的替代定义— 暂时被#注释掉了—我们将用于不同的源数据。

作者图片

作者图片

4.预测

4.1 预测功能

我们定义了一个函数 eval_model() ,它将一次采用一种预测方法(并按顺序采用几个模型)并将它应用于源数据。

eval 函数使模型符合训练数据集,然后计算估价期的预测值(第 9-10 行)。这两行完成了大多数方法的所有预测工作。

对于简单的预测方法,我们需要插入一些额外的代码(第 13 -19 行)。天真的预测实际上由两种方法组成,我们将这七种方法联系在一起:天真的漂移预测和天真的季节性预测。

  • 漂移方法只取第一个和最后一个观察值,并在它们之间画一条线。
  • 季节性方法预测 K 步之前出现的值(其中 K 代表季节性,例如 K=12 代表月份)将在 K 步之后再次出现。
  • 通过结合漂移季节性,我们得到了一个过于简单,或者说是天真的预测,即这两种模式将继续重演。

eval_model() 代码单元中的第三部分计算由 Darts 提供的预测精度指标,并将它们收集到字典 res_accuracy 中。

我们将预测值 forecast 和指标 res_accuracy 组合在一个列表 results 中,并将该列表返回给调用预测函数的代码。

4.2 五种预测方法

在列表模型中,我们准备了所有飞镖模型的列表,我们希望为这些模型运行预测函数 eval_models() 。我们将当前的练习限制为五种可选方法。

列表理解模型预测遍历模型列表,并将每个模型馈送给 eval_model() 函数。

model_predictions 将模型传递给评估函数之前,我们需要为预测器设置它们特定的开始参数。为了这个目的。我们为每个预测者定义一个模型变量 m_xxx

4.2a 天真预测

naive drift()方法不需要参数。它只是从序列中取出第一个和最后一个值,并在它们之间画一条直线趋势线。

它的近亲, NaiveSeasonal() ,要求一个季节性参数,在我们的例子中 K = 12 个月。Darts check _ seasonity()函数已经确定了季节性 mseas ,12 在我们的例子中,我们将把它分配给 k。

4.2b指数平滑**

像 SARIMA 一样,指数平滑需要知道季节性的顺序, mseas ,我们已经在上面计算过了。

4.2c 先知

Facebook Prophet模型可以在其设置中采用可选的季节性参数,但也可以自行确定季节性。

4.2d SARIMAX

对于 萨里玛 ,我跳过了一个额外的环,着眼于平稳性和差异性。额外的代码在飞镖中并不是绝对必要的,但它是一个故障保护装置。

省道包裹PMMA自动 arima 法。它的调整算法应该在开始网格搜索其他超参数之前应用假设测试来确定差分的适当顺序。

Darts 通过 pmdarima 为分析师提供了两种平稳性测试的选择,ADF 和 KPSS,默认为 KPSS。但是 ADF 和 KPSS 可能在差异的必要性上存在分歧,而且这种情况并不少见。ADF 检验和 KPSS 检验都不会孤立地证实或破坏平稳性。

KPSS 和 ADF 测试结果有四种可能的组合:

  • 如果 KPSS 和 ADF 同意序列是平稳的(KPSS 有高 p 值,ADF 有低 p 值):认为它是平稳的。没必要区别它。
  • ADF 找到一个单位根;但是 KPSS 发现这个序列在一个确定的趋势附近是稳定的(ADF 和 KPSS 具有高 p 值)。那么,该序列是趋势稳定的,需要消除趋势。区别它。或者,转型可能会让它摆脱这种趋势。
  • ADF 找不到单位根;但是 KPSS 声称它是不稳定的(ADF 和 KPSS 具有低 p 值)。那么,这个序列是差分平稳的。区别它。
  • 如果 KPSS 和 ADF 一致认为序列是非平稳的(p 值低的 KPSS;具有高 p 值的 ADF):认为它是非平稳的。区别它。

由于飞镖pmdarima 运行单一选择测试来确定差异的顺序,所以我在飞镖方法之前用两个测试来捕捉 ADF 和 KPSS 不一致的实例。较高的测试结果被传递给自动 ARIMA 方法。萨里玛预测和平稳性:当时间序列像鸭子一样呱呱叫|走向数据科学

我还应用了季节性、OCSB 和 CH 的 pmdarima 检验。这些人有时也会对季节差异的必要顺序产生分歧。我们使用更高的建议。

我们保持 pmdarima 的默认方法逐步搜索不变,该方法使用 Hyndman 和 Khandakar 在 2008 年开发的算法(自动时间序列预测:R(r-project.org)的预测包)。该算法比全网格搜索快得多,因为它避免了在搜索空间中处理许多无意义的参数元组。运动裤被解开——时间序列分析|走向数据科学

4.2eθ

最后,我们准备了 Theta 预测器,这是一种简单而有效的快速方法,建立在带漂移的指数平滑的基础上。

“Theta 方法自 1999 年问世以来,是过去二十年中最成功的单变量时间序列预测方法。该方法的成功已经在需求预测、营销和供应链预测环境中的应用中得到证明;尽管如此,在广泛的盲法经验预测竞赛中的成功也涉及到来自金融、经济和广泛应用的数千个系列,因此被证明是可推广的。θ法的优越性能最初在 2000 年的 M3 完井中得到了证明用 Theta 方法预测— Nikolopoulos —主要参考著作—威利在线图书馆

用θ法进行短期负荷预测(e3s-conferences.org)

在将 Darts 的微调过的 theta 预测器传递给我们的 eval_model() 函数之前,我们通过搜索 100 个可选值来调整 Theta 参数。

4.2f 运行预测

list comprehensionmodel _ predictions将我们想要尝试的预测器传递给 model_eval()函数,该函数开始处理它们。

作者图片

4.3 预测方法的准确性

eval_model() 函数返回每个模型的预测值和精确度指标。

我们在数据框架 df_acc 中收集所有五个模型的指标。

我们应用于数据框架的 .style.highlight 方法强调了哪些预测显示出最佳和最差的准确性。

如果你想知道为什么 R 平方在下面显示的数据帧中显示负值:虽然 R 平方本身是一个介于 0 和 1 之间的非负数,但我颠倒了它的符号,以使它的方向,颜色编码的指导与表中的其他指标对齐。对于所有其他误差测量指标,较低的值是首选。对于 R 平方,值越高越好。在这个特定的表视图中,R 平方前面的负号使它成为“越低越好”的指标,就像其他指标一样。否则,数据帧中最小和最大值的颜色编码将会混淆。

作者图片

在我们的例子中,Theta 方法在 ARIMA 之前一英寸穿过终点线:他们的度量标准相差很小。然而,Theta 方法只用了 0.13 秒就赢得了比赛,而 ARIMA 用了 1.1 秒。

尽管 Prophet 的处理时间是 nave 模型的 42 倍,但 Prophet 的准确性与 nave 模型几乎没有区别,如果按平均绝对百分比误差或平均绝对误差排名,Prophet 甚至排在 nave 预测的后面。根据 R 平方的测量,Prophet 和 nave 解释了时间序列中不到 70%的运动,而 Theta 和 SARIMA 反映了 90%的准确性。

4.4 绘制预测结果

作者图片

作者图片

天真的预测者(右上)和预言者(右下)的图表显示了偏见。蓝色的预测线系统地低估了黑色的实际观测值,比其他三个预测者更低估。

4.5 残差诊断

Darts 专注于预测值、预测图和准确性指标。但是它很少提供诊断假设测试。为了增加一些精确性,我们引入了对来自 statsmodels 的白噪声残差的 Ljung-Box 测试;常态测试来自 scipy

作者图片

Ljung-Box 测试研究残差是否代表白噪声。较低的 p 值(均远低于 0.05)表明它们不是,这意味着所有五个预测模型都未能识别一些本可用于提高预测准确性的信号。下面的诊断图表明一些季节性被排除在预测之外。

如果正态性检验的 p 值较低,则不会使预测结果无效。但是指数平滑预测的低值意味着我们不能依赖它的置信区间。

Darts 提供了有用的plot _ residuals _ analysis()函数来可视化三个支线剧情中的残差。让我们将每个预测者的残差输入到绘图函数中。

作者图片

指数平滑:

  • 上面的 ACF 图显示了残差中的季节性信号,峰值和谷值以 12 个月为一个周期波动。这表明该模型在其预测中没有包括所有的季节性,并且在残差中浪费了一些信号。
  • 直方图显示了偏差:其峰值不在零均值处,但它是左偏的。负均值-16.6 表示指数平滑器倾向于错误估计同一方向的观测值。

作者图片

θ法:

  • ACF 相关图表明,Theta 也没有将所有的季节性完全纳入其预测中。
  • 直方图看起来比指数平滑的情况更好,平均值接近 0,意味着接近零的偏差。

作者图片

萨里玛:

  • 此外,SARIMA 预报员留下了一些季节性信号,而不是将其纳入其预测中。
  • 直方图看起来有点右偏,正平均值接近 3.5,但比指数平滑器的负平均值反映的大偏差要小得多。

作者图片

天真的预测:

  • 像其他预测者一样,未确定的季节性被搁置在桌面上。
  • 直方图显示了显著的负偏差,钟形曲线峰值在-30 左右,而不是 0。天真漂移通过从实际观察值的起点到终点画一条线来计算趋势。在其他模式中,它不会抓住一个加速的趋势。

作者图片

先知:

  • ACF:其他模型显示的峰值和谷值并不太陡。预言者残差看起来似乎更多的季节性信号已经被放弃了。这可以解释为什么先知的 MAPE 和 RMSE 的错误几乎是西塔和萨里玛的两倍。
  • 直方图显示了小的正偏差,平均值接近 3。这条曲线看起来不太正常,因为它有很长的尾巴,但是我们上面的测试证实了正态性,p 值为 0.10。所以置信区间会比较准确。直方图本身很容易被误解。

完整的 Jupyter 笔记本可以在 GitHub 上下载: h3ik0th/Darts: Python Darts 时间系列教程(github.com)

所有图片:由作者提供,作为公共领域

Dash for 初学者:创建交互式 Python 仪表盘

原文:https://towardsdatascience.com/dash-for-beginners-create-interactive-python-dashboards-338bfcb6ffa4?source=collection_archive---------2-----------------------

创建没有 html、css 和 Js 的交互式 python 仪表盘

形象由 freepik 设计

想学 plotly Dash? 阅读下面这篇文章,对 plotly Dash 有一个基本的了解。通过遵循官方文档或查看我的 Udemy 课程 获得深入理解,在该课程中,您将学习如何创建成熟的交互式仪表盘。

什么是破折号?

Dash 是 plotly 为创建交互式 web 应用程序而创建的 python 框架。Dash 是写在 Flask,Plotly.js 和 React.js 上面的,有了 Dash,你不用为了创建交互式仪表盘而学习 HTML,CSS 和 Javascript,你只需要 python。Dash 是开源的,使用该框架构建的应用程序可以在 web 浏览器上查看。

有了 Dash,你不必为了创建交互式仪表盘而学习 HTML、CSS 和 Javascript,你只需要 python。

仪表板的积木

Dash 应用程序由两个构件组成:

  1. 布局
  2. 复试

布局描述了应用程序的外观和感觉,它定义了图形、下拉列表等元素以及这些元素的位置、大小、颜色等。Dash 包含 Dash HTML 组件,使用它们我们可以创建 HTML 内容并设置样式,比如标题、段落、图片等等。使用 Dash 核心组件创建图形、下拉菜单、滑块等元素。

回调用于为 dash 应用程序带来交互性。例如,我们可以使用这些函数来定义单击按钮或下拉菜单时发生的活动。

使用破折号的布局

现在,让我们看看如何使用 plotly Dash 创建基于 web 的布局。在开始布局之前,让我们安装一些必需的包。(你可以使用 Anaconda Spyder,一个 python 开发环境来运行代码。)

现在,我们将导入 dash 包,html 类的 dash_html_components,graph、dropdown 等元素的 dash_core_components,以及用于创建图表和读取股票价格数据集的 plotly 包。

(在下面的代码中)我们正在使用 dash 包初始化我们的 dash 应用程序。然后,我们正在读取 2018 年至 2019 年不同公司的股价数据。我们正在创建 stock_prices 函数,该函数返回 Google 股票价格的折线图。

(在上面的代码中)在第 16 行,我们使用 html Div 组件设置我们的布局,这是一种包装器,布局的元素(标题、图表)将在其中创建。Div 组件包含诸如 id(元素的唯一标识符)、style(用于设置宽度、高度、颜色等)和 children(相当于方括号,布局元素在其中初始化)之类的参数。

在 html 的子组件中。Div)我们正在使用 H1 函数在第 17 行创建 html H1 标题。在函数内部,我们设置函数的唯一 id(id = ' H1 ')、children 属性,使用它我们将标题和样式属性的文本设置为一个字典,在字典中我们设置样式,例如文本居中对齐,将上下边距设置为 40 像素。在第 21 行,我们使用 dash core component (dcc)来创建 graph,其中我们设置了 graph 的 id 和 figure 参数,它等于返回 plotly figure 对象的函数调用(stock_pricest())。

为了查看我们的应用程序,我们需要像在 Flask 中一样运行我们的 web 服务器。记住 Dash 是建立在烧瓶顶部的。

在运行应用程序时,您会看到应用程序运行在 http://127.0.0.1:8050/ 上,这是您的本地服务器。复制这个网址并粘贴到你的浏览器中,你会看到下面的可视化。

现在,我们将使用 dash 核心组件创建一个下拉列表。使用下拉菜单,我们将能够选择谷歌,苹果或亚马逊的股票。

下拉列表是使用 Dropdown()函数创建的,该函数有以下参数

  1. id —下拉列表的唯一标识符。
  2. options 将“标签”(下拉列表中可见的文本)和“值”(dash 用于与回调通信)设置为键值对。
  3. 值—下拉列表的默认选择。

Dash 中的回调:让它互动

现在,让我们来看看如何创建回调函数来连接下拉列表和股价折线图。

使用@app.callback()初始化回调,后面是函数定义。在这个函数中,我们定义了在改变下拉列表的值时会发生什么。

让我们看看回调函数中的参数:

  1. 输出:用于定义布局内的组件,当回调函数(graph_update())返回某个对象时,这些组件将被更新。输出函数有两个参数——1)component _ id 定义了我们希望用函数 graph_update 更新的组件的 id。我们想更新 dcc 中的股票价格图表。因此,我们将组件 id 设置为“line_plot”,这是我们的图形组件的 id。2)组件属性定义了将要更新的组件的属性,即 dcc 的图形属性。我们布局中的图形。
  2. 输入:用于定义组件,其值的变化将触发回调。输入函数也将 component_id 和 component_property 作为参数。我们希望回调基于 dropdown 值的变化而被触发,所以我们将 component_property 设置为 dropdown 的' value '属性。请注意,输入是在列表中定义的。

输入函数的组件属性是下拉列表的“值”,作为函数 graph_update 中的参数。在函数内部,我们创建散点图并返回 fig 对象,该对象被传递给 dcc 的 fig 属性。图形使用回调的输出函数。

把所有的东西放在一起

现在让我们在下面的代码中将布局、下拉菜单和回调函数结合起来:

下图显示了 dropdown 值的变化如何更新我们的股价折线图。

摘要

因此,我们研究了如何使用 plotly Dash 创建交互式仪表盘。首先,我们使用 html 组件和 dash 核心组件创建布局。然后,我们添加下拉菜单,并使用回调将它与股价折线图连接起来。

再次分享课程链接— Plotly Dash 课程 ,以防你想了解更多关于 Plotly Dash 的知识。

首先,你应该在收件箱里收到我的帖子。 在这里做 其次,如果你喜欢体验媒介的自己,可以考虑通过 报名会员 来支持我和其他千千万万的作家。它每个月只需要 5 美元,它极大地支持了我们,作家,而且你也有机会通过你的写作赚钱。

使用 Plotly Dash 创建的仪表板示例!

https://anmol3015.medium.com/python-dashboard-using-plotly-dash-example-1-b9cc94039b5e https://anmol3015.medium.com/python-dashboard-using-plotly-dash-example-2-f4fc0cc8a24c

仪表板使用 Streamlit 和来自 SQL 数据库的数据

原文:https://towardsdatascience.com/dashboard-using-streamlit-with-data-from-sql-database-f5c1ee36b51?source=collection_archive---------7-----------------------

来自客户和销售数据的交互式仪表板

作者图片

简介

Streamlit 是用于创建强大仪表板的最新 python 库之一,也是用于机器学习和数据科学团队的开源框架。它可以用非常简单的编码生成符合行业标准且具有视觉吸引力的仪表板。我使用 streamlit 创建了一个销售仪表板,其中包含交互式视觉效果和来自 SQL 数据库的数据。在本文中,我将通过使用 SQL 获取数据来完成仪表板的创建。

连接数据库

本文中的演示使用了一个名为“sqlda”的包含客户和销售数据的 SQL 数据库。这是一个 postgres 数据库。Sqlalchemy 用于创建连接和获取表。

从 python 接口调用常规的 SQL 查询来获取数据。首先,我们需要知道数据库中所有表的名称。

作者图片

似乎有几个表,但我们只对客户和销售数据感兴趣。使用常规 SQL 查询调用以下两个表来获取数据。

仪表板的界面可以被分割成我们想要的列数。例如,假设我们希望将顶行分成两列。左栏将显示仪表板的标题,右栏将显示当前日期和时间。

仪表盘配置

我们还可以在两个 streamlit 占位符中显示客户总数和销售额。侧边栏可以用来过滤数据。

为自定义绘图定义了条形图、饼图和其他必要的时间序列图。

为了绘制一个互动的情节,我使用了 plotly express。当用户将光标悬停在绘图上时,它可以显示相关数据。出于演示的目的,我使用了美国州地图,然后使用由彩色多边形组成的 cloropleth 地图将州数据与地图关联起来。

然后,我们向仪表板添加更多的行,以可视化的形式显示更多的数据。有一点可以注意到,我们可以在 python 的这个接口内部执行 SQL 查询。我已经执行了两个 SQL 表的内部连接,并提取了要绘制的数据。

最终仪表板

整个代码块用。py 扩展名。在 anaconda promt 中,默认目录被更改为。py 文件并执行以下命令,其中 Streamlit-01.py 是文件名。

细流运行细流-01.py

它将提供应用程序运行的主机地址。当到达主机地址时,将创建以下仪表板。

作者图片

该地图由 plotly express 生成,当光标位于任何状态时,都会显示与之相关的数据。

作者图片

此处显示了仪表板的其余部分。

作者图片

作者图片

侧边栏可以用来过滤数据。选中后,相关数据将显示在仪表板中。

作者图片

结论

在本文中,我演示了使用 streamlit 创建交互式仪表板。从 SQL 数据库获取数据,并执行 SQL 查询以获得感兴趣的数据。Plotly express 是一种动态可视化数据的好方法。streamlit 与 sql 和 plotly express 的结合确实可以增强仪表板的健壮性。

用于解释和比较机器学习模型的仪表板

原文:https://towardsdatascience.com/dashboards-for-interpreting-comparing-machine-learning-models-ffcfb4c05152?source=collection_archive---------34-----------------------

使用解释为机器学习模型创建仪表板

来源:作者

随着技术的发展,数据科学领域有多种机器学习算法,这使得用户/数据科学家/ML 工程师很难根据他们正在处理的数据集选择最佳模型。

比较不同的模型可以是选择最佳模型的一种方式,但这是一个耗时的过程,我们将创建不同的机器学习模型,然后比较它们的性能。这也是不可行的,因为大多数模型是黑盒,我们不知道模型内部发生了什么,以及它将如何表现。简而言之,由于模型的复杂性和模型是黑箱,我们不知道如何解释模型。

如果不解释模型,就很难理解模型是如何表现的,以及它将如何根据提供给它的新数据来表现。这不仅有助于我们理解模型预测,也有助于我们理解它是如何达到特定预测的。

下一个大问题是如何解释这些模型和它们的行为,让我来解释一下。如果我告诉你,你不仅可以解读不同的模型,还可以比较它们的性能,会怎么样?是的,现在我们可以看到黑盒的内部,了解模型在做什么。

Interpret 是一个开源的 python 库,用于解释和分析不同机器学习模型的性能。在本文中,我们将看到如何使用 interpret 进行模型解释和可视化模型性能。在这篇文章的最后,我们将会探索一些非常酷的东西,我确信这对所有的数据科学家/ML 工程师等都非常有帮助。敬请关注。

让我们开始吧…

安装所需的库

像任何其他 python 库一样,我们将使用 pip 安装来安装解释器。下面给出的命令将执行安装。

pip install interpret

导入所需的库

接下来,我们将导入将在本文中使用的所有必需的库。我们将装载熊猫,翻译等。

import pandas as pd
from interpret import show
from interpret.glassbox import RegressionTree
from sklearn.model_selection import train_test_split

我们将在需要时导入其他功能进行解释。

创建机器学习模型

现在我们将创建一个机器学习模型,我们将使用解释库来解释它。如您所见,我们已经导入了用于加载数据和拆分数据的库,所以让我们首先加载数据,然后创建模型。我们将在这里使用的数据集是著名的糖尿病数据集。

df = pd.read_csv("Diabetes.csv")
X_train, X_test, y_train, y_test = train_test_split(df[['Pregnancies', 'Glucose','BloodPressure','SkinThickness','Insulin','BMI','DiabetesPedigreeFunction','Age']], df['Outcome'], test_size=0.3)#Creating Model
reg_tree = RegressionTree(random_state=42)
reg_tree.fit(X_train, y_train)

我们稍后将创建更多的模型,以便我们可以比较不同的模型。

使用可视化进行口译和绩效分析

现在,我们将解读模型,并观察模型的性能。

#global interpretation
reg_tree_global = reg_tree.explain_global(name='Regression Tree')
show(reg_tree_global)

来源:作者

这是模型的整体性能,您可以从下拉列表中选择不同的功能,以查看它在模型中的使用情况。这是模型的全局解释,对于局部解释(个体预测)我们可以使用局部函数。

现在让我们想象一下模型的性能。

reg_tree_perf = RegressionPerf(reg_tree.predict).explain_perf(X_test, y_test, name='Regression Tree')show(reg_tree_perf)

性能(来源:作者)

奖金

有趣的部分来了,在奖金部分,我将向您展示如何创建一个模型仪表板,其中包含您创建的所有模型的解释和性能。这不是很有趣吗,让我们看看我们怎么做?

为了创建仪表板,首先,让我们再创建一个模型,然后我们将分析仪表板中两个模型的性能和解释。

from interpret.glassbox import LinearRegression
lin_reg = LinearRegression(random_state=42)
lin_reg.fit(X_train, y_train)
lin_reg_perf = RegressionPerf(lin_reg.predict).explain_perf(X_test, y_test, name='Linear Regression')
lin_reg_global = lin_reg.explain_global(name='Linear Regression')

在创建了模型之后,有趣的部分来了,我们将创建一个只有一行代码的仪表板,用于分析两个模型的性能,并使用它来解释模型。

show([ lin_reg_global, lin_reg_perf, reg_tree_global, reg_tree_perf])

模型仪表板(来源:作者)

您可以通过单击仪表板上方的链接在新窗口中打开此仪表板。下面的视频探索了仪表板的不同部分。

仪表板(来源:作者)

您可以看到我们为模型解释和性能比较创建了一个仪表板是多么容易。

继续尝试不同的数据集和不同的机器学习模型。请在回复部分告诉我您的意见。

本文是与 Piyush Ingale 合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时联系我在 hmix13@gmail.com 或我的 LinkedIn 简介 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

Dask:并行计算的可扩展解决方案

原文:https://towardsdatascience.com/dask-a-scalable-solution-for-parallel-computing-d1d962f227f6?source=collection_archive---------16-----------------------

再见,熊猫,你好,达斯克!

由 Brian Kostiuk 在 Unsplash 上拍摄

对于数据科学家来说,大数据是一个不断增长的信息库,为了轻松处理输入和处理,强大的系统始终是一项未完成的工作。为了处理大量的数据流入,我们要么不得不求助于购买更快的服务器,这增加了成本,要么更聪明地工作,并为并行计算建立像 Dask 这样的定制库。

在我介绍 Dask 作为并行计算解决方案之前,让我们先了解一下这种类型的计算在大数据世界中意味着什么。根据定义,并行计算是一种计算类型,其中许多计算或进程的执行是同时进行的。简而言之,并行计算是指通过共享内存连接的多个任务执行者(或处理器)完成计算任务。

试用土星云(支持者)

如果你用云 GPU 免费试用 Dask,那就去看看土星云。这是一个可扩展、灵活的数据科学平台,负责所有设置,有免费和企业选项,当然还有多集群 Dask 支持!

那么 Dask 是什么?

Dask 用 Python 编写,是一个灵活的、用于并行计算的开源库。它允许开发人员与其他社区项目(如 NumPy、Pandas 和 scikit-learn)协作构建他们的软件。Dask 为分析提供高级并行性,实现规模化性能。

Dask 由两部分组成:用于优化计算和大数据集合的动态任务调度,如并行数组、数据帧和列表,它们将 NumPy、Pandas 或 Python 迭代器等公共接口扩展到大内存或分布式环境,这些环境运行在动态任务调度器之上。

为什么是 Dask?

有人可能会说,有了其他同类产品,有必要改用 Dask。但是,Dask 最大的优点是易于采用。Python 用户对它很熟悉,它使用现有的 API 和数据结构,使它成为在 NumPy、Pandas、scikit-learn 和 Dask-powered 等效软件之间切换的无缝过程——所有这一切都不需要您完全重写代码或重新培训软件以进行扩展。

除了提供熟悉度,Dask 还:

灵活:使用 Dask 允许定制工作负载并与其他项目集成。

Native: Dask 通过分布式计算和对 PyData 栈的访问来扩展 Python。

敏捷:低开销、低延迟和最小串行化,Dask 为数字算法提供了令人印象深刻的敏捷

可扩展:Dask 可以在具有 1000 个内核的集群上纵向扩展,也可以在笔记本电脑上通过单个进程进行设置和运行!

响应:考虑到交互式计算,Dask 提供快速反馈和诊断来帮助人类。

Dask 和大数据

虽然 Pandas 是一个强大的数据计算和分析工具,但 Dask 凭借其处理大于本地 RAM 的数据量的能力取得了成功,而不会使系统不堪重负或影响性能。它提供了一种简单的方法来处理 Python 中的大量数据,而不需要额外的努力。

鉴于在家工作的现状,不得不跟随更大的机器并不完全是灵活工作的定义。这就是 Dask 在笔记本电脑上无缝运行的能力和便利性发挥作用的地方。它与 conda 或 pip 一起轻松安装,并将方便的数据集的大小从“适合内存”扩展到“适合磁盘”。

照片由imgixUnsplash

正如所解释的,Dask 具有弹性、数据本地性和低延迟。轻松的过渡让您可以在单机集群和中等规模集群之间无缝切换。对于那些已经熟悉 Pandas 的人来说,Dask 在性能和可伸缩性方面似乎是一个扩展。您可以根据需要在 Dask 数据框架和 Pandas 数据框架之间切换,以进行任何数据转换和操作。

示例| Dask 数据框架基础

Dask 数据帧协调许多 Pandas 数据帧,沿着一个索引进行分区。

  1. 创建随机数据集
***import** **dask**
**import** **dask.dataframe** **as** **dd**
df = dask.datasets.timeseries()Output: **Dask DataFrame Structure:***

2.从平面文件加载数据
我们可以使用read_csv函数将多个csv文件加载到dask.dataframe中。这支持文件名上的 globbing ,并将它们按字母顺序排序。这导致所有数据的单个dask.dataframe.DataFrame

***import** **dask.dataframe** **as** **dd**

df = dd.read_csv('employee_*.csv').set_index('id')*

3.执行转换

Dask dataframe 遵循 pandas api。我们可以进行算术、归约、选择等运算...与熊猫使用的语法相同。主要的区别是我们需要给最终结果添加一个.compute()

*df2 = df[df.y > 0]
df3 = df2.groupby('name').x.std()
df3Output:
Dask Series Structure:
npartitions=1
    float64
        ...
Name: x, dtype: float64
Dask Name: sqrt, 157 tasks*

呼叫计算

*computed_df = df3.compute()
computed_df*

4.绘图输出

***from** **matplotlib** **import** pyplot **as** plt
%matplotlib inlinedf.A.compute().plot()Output:*

示例|使用真实数据集(NYCTaxi 2013)

2014 年,Chris Whong 成功提交了一份 FOIA 请求,以获取 2013 年纽约市所有出租车的记录。

*#Downloading and unzip
!wget  [https://storage.googleapis.com/blaze-data/nyc-taxi/castra/nyc-taxi-2013.castra.tar](https://storage.googleapis.com/blaze-data/nyc-taxi/castra/nyc-taxi-2013.castra.tar)#Reading data from files**import** **dask.dataframe** **as** **dd**
df = dd.from_castra('tripdata.castra/')
df.head()#Setup progress bar
**from** **dask.diagnostics** **import** ProgressBar
progress_bar = ProgressBar()
progress_bar.register()*

示例计算

*#**How many passengers per ride?**
df.passenger_count.value_counts().compute()**#How many medallions on the road per day?** %matplotlib inline
df.medallion.resample('1d', how='nunique').compute().plot()*

下一站…达斯克

现在我们知道了为什么 Dask 是一个流行的并行计算解决方案,接下来要做的就是开始使用它。一旦您从 Conda、pip 或 source 安装了 Dask,您还可以根据特定的功能添加可选的依赖项。您可以在这里找到受支持的可选依赖项列表。

总之,如果你是大数据的粉丝,Dask 会让你爱上处理海量大数据。性能、可伸缩性、熟悉性和核心的流行 Python,使 Dask 成为数据量大的项目的有益工具。

试用土星云(支持者)

如果你用云 GPU 免费试用 Dask,那就去看看土星云。这是一个可扩展、灵活的数据科学平台,负责所有设置,有免费和企业选项,当然还有多集群 Dask 支持!

寻找更多细节

在 youtube 上观看这个视频

YouTube上 Anuj Syal 的 Dask Bye Bye Pandas 入门

在 Linkedin 和 Twitter 上关注我

如果你对类似的内容感兴趣,点击 Medium 上的“关注”按钮,或者在 Twitter 和 Linkedin 上关注我

达斯克和熊猫:没有太多数据这回事

原文:https://towardsdatascience.com/dask-and-pandas-theres-no-such-thing-as-too-much-data-284763348459?source=collection_archive---------33-----------------------

兰斯·安德森在 Unsplash 上拍照

你喜欢熊猫,但讨厌当你达到你的内存或计算资源的极限吗?Dask 让您有机会将 pandas API 用于分布式数据和计算。在本文中,您将了解它的实际工作原理,如何自己使用它,以及为什么它值得转换。

声明:我是 Saturn Cloud 的一名高级数据科学家,Saturn Cloud 是一个支持使用 Dask 对 Python 进行简单并行化和扩展的平台。如果你想了解更多关于土星云的信息,请登陆网站 www.saturncloud.io 访问我们。

介绍

Pandas 是 PyData 工具包中最受欢迎的工具——它使用一个用户友好且健壮的 API,使难以置信的多样化数据分析和数据科学任务成为可能。PyPi 表明熊猫在世界各地每周被下载大约 500 万次。

然而,在一些需要大量数据或异常资源密集型计算的情况下,pandas 确实难以满足数据科学家的需求。在本文中,我们将讨论一些领域,用户可能会发现 Dask 工具有助于扩展现有的 pandas 功能,而不需要更改语言或 API。

熊猫挑战

在我们继续之前,让我们同意:熊猫是可怕的。这个讨论实际上是关于我们如何增加熊猫的现有能力,而不是用超高能力的 Dask 功能取代所有的熊猫。如果 pandas 适用于您面前的用例,并且是完成工作的最佳方式,我们建议您使用它!

但是让我们来看看你可能需要更多的情况。

数据太大,无法保存在内存中(内存限制)

如果您发现自己对可能有用的数据进行了大量的缩减采样,因为它对于您正在使用的单台机器来说太大了,那么这就是您的问题。如果您可以在不将整个数据集加载到单个机器的内存中的情况下运行您的作业,那么您可以使用所有有价值的数据来完成您的工作。Dask 有真正巧妙的基础设施来实现这一点,我们稍后会讨论。

串行运行时计算过于密集/缓慢(计算约束)

如果您正在运行计算任务几个小时甚至几天,或者发现 pandas 的计算非常慢,以至于您正在考虑完全离开 Python 生态系统,那么这就是您面临的问题。不用抛弃 Python,让你的代码适应全新的语言或框架,比如 C++或 Java,你可以用与 pandas 基本相同的 API 应用一些 Dask 原则,并看到你的工作异常加速。我们将解释如何实现。

达斯克是什么?

那么,当熊猫不能满足你的需求时,我们建议你做些什么呢?达斯克。

Dask 是一个支持 Python 代码并行化的开源框架。这可以适用于各种 Python 用例,不仅仅是数据科学。Dask 设计用于单机设置和多机集群。您不仅可以对 pandas 使用 Dask,还可以对 NumPy、scikit-learn 和其他 Python 库使用 Dask。如果你想了解更多关于 Dask 可以派上用场的其他领域,有一个很棒的网站可以解释所有这些。

使用 Dask 时,您会改变计算机处理 Python 命令的方式。具体来说,在 pandas 的正常使用中,当您调用一个函数时,您的 Python 解释器会立即计算结果。创建汇总、进行计算或应用过滤器。这意味着 Python 需要所有必要的数据和足够的内存来完成这些计算。这也意味着 Python 将一次执行一个步骤,如果你有多个函数要运行,它们将连续运行。因此,你受限于你的机器可用的内存,并且只要每一步或计算一个接一个地运行,整个工作将会花费很长时间。

如果您的数据非常小,并且不同的计算都可以快速运行,或者矢量化,那么这可能就很好了!那熊猫就够了。但是,如果您正在处理非常大或复杂的数据,或者数据中的许多组,您可能会发现您想要同时运行多个计算。

Dask 的核心优势是一个被称为“懒求值”或“延迟”函数的原理。用 Dask 延迟一项任务可以将一组转换或计算排队,以便它可以在以后并行运行。这意味着 Python 不会评估所请求的计算,除非被明确告知。这与其他类型的函数不同,其他类型的函数在被调用时会立即进行计算。许多非常常见和方便的函数被移植到 Dask 中,这意味着它们将是懒惰的(延迟计算),甚至不需要你去问。

您可以从这种情况过渡到类似这样的情况,在可能的情况下,您的任务可以并行运行,从而极大地提高您的工作速度和效率。

图片:Dask docs 链接

它是如何工作的

您可以用多种不同的方式合并 Dask 功能,而无需进行重大更改或重构大量代码。

使用延迟功能

您可能喜欢使用 Dask 原生函数,或者您可能更喜欢在您的自定义函数上使用@dask.delayed 修饰:请参见我们的数据科学家惰性评估指南以了解更多信息!

使用这些函数,您可以创建可以稍后并行运行的延迟对象,从而提高作业的效率和速度。

使用 Dask 数据帧延迟

另一个选择是从你的熊猫数据帧对象切换到 Dask 数据帧,这就是我们在这里要做的。这将您从一个离散的数据对象带到一个分布式的数据对象,这意味着您的数据现在可以存储在跨越工作集群的分区中。从字面上看,Dask 数据帧是分布在集群中的一组较小的 pandas 数据帧。

您可以通过以下方式创建 Dask 数据帧:

  • 转换现有的 pandas 数据帧:[dask.dataframe.from_pandas()](https://docs.dask.org/en/latest/dataframe-api.html#dask.dataframe.from_pandas)
  • 将数据直接装入 Dask 数据帧:例如,[dask.dataframe.read_csv()](https://docs.dask.org/en/latest/dataframe-api.html#dask.dataframe.read_csv)

除了 csv, Dask 还内置了读取许多不同类型数据存储的功能,包括 Parquet 和 JSON。

但是,这有什么好处呢?

Dask 数据帧是分布式的,因此需要在数据帧上运行的计算将分布在集群中,分散了工作负载。此外,您永远不需要一台机器来保存整个数据集,因为数据本身就是为您分发的。另外,如果你从许多不同的 CSV 或其他文件中加载数据,只需告诉 Dask 文件夹路径,它就会将所有这些文件加载到一个单独的 Dask 数据框架中,作为你的分区!

在一个命令中将整个文件夹加载到 Dask 数据帧中的示例:

CPU 时间:用户 202 毫秒,系统 39.4 毫秒,总计 241 毫秒
墙时间:33.2 秒

这之所以如此之快,部分是因为它像其他 Dask 函数一样是延迟求值的。我们使用.persist()方法实际上强制集群从 s3 加载我们的数据,因为否则它只会等待我们的指令,甚至开始移动数据。我们说.persist()之后,它是并行运行的,所以即使加载数据还是挺快的。

相比之下,如果我们将文件夹中的文件作为常规的 pandas 数据帧加载,所有数据必须一次移动一个文件,以便我们有一个对象来处理:

CPU 时间:用户 2 分 13s,系统:40 s,总计:2 分 53s
挂壁时间:11 分 15s

它可以工作,但是计算速度太慢了!这一切都是在假设我们的机器可以在内存中保存数据的情况下进行的,但这并不总是正确的。

关于……

在小数据量时,一些 pandas 函数比 Dask 更快——随着数据量的增长,Dask 的优势变得明显。这也是为什么为了小数据坚持熊猫可能往往是正确选择的原因之一。

如果您不确定您的工作是否需要 Dask,请评估您在数据加载上花费了多少时间,计算速度有多慢,以及您是否必须走捷径(缩减采样或更改分析)来完成工作。所有这些都表明你已经超出了熊猫和/或你的单机的能力。

现在,让我们来看看您可能在 pandas 中执行的一些非常常规的数据操作任务,看看它们在 Dask 中是什么样子的。我们使用的是大数据,所以这里我们应该看到 Dask 给了我们速度优势。

分组依据

这里我们将按列对数据进行分组,然后提取另一列的平均值。与 Dask 不同的是,我们在最后运行.compute(),以便触发计算并返回结果。

%%time
pandasDF.groupby("PULocationID").trip_distance.mean()

CPU 时间:user 938 ms,sys: 0 ns,total:938 ms
Wall time:937 ms
PULocationID
1 1.586234
2 8.915472
3 7.342070
4 2.695367
5 24.207739
名称:trip_distance,长度:263,dtype

%%time
daskDF.groupby("PULocationID").trip_distance.mean().compute()

CPU 时间:user 36.1 ms,sys: 3.52 ms,total:39.6 ms
Wall time:390 ms
PULocationID
1.0 1.586234
2.0 8.915472
3.0 7.342070
4.0 2.695367
5.0 24.207739【T25

分析列

如果我们不分组,而只计算一列的单个度量呢?同样的情况,我们的代码片段与添加的.compute()相同。

%%time
pandasDF[["trip_distance"]].mean()

CPU 时间:user 515 ms,sys 86 ms,total 601 ms
Wall time:600 ms
trip _ distance 3.000928
d type:float 64

%%time
daskDF[["trip_distance"]].mean().compute()

CPU 时间:user 43.4 ms,sys: 0 ns,total:43.4 ms
Wall time:342 ms
trip _ distance 3.000928
d type:float 64

删除重复项

这里有一个我们非常需要的,并且需要查看所有的数据删除副本。达斯克也有这个!

%%time
pandasDF.drop_duplicates("passenger_count")

CPU 时间:用户 1.5 s,sys: 232 ms,总计:1.73 s
墙时间:1.73 s

%%time
daskDF.drop_duplicates("passenger_count").compute()

CPU 时间:user 24.1 ms,sys 2.22 ms,total 26.4 ms
Wall 时间:362 ms

性能比较

那么,这些例子给我们留下了什么?我们使用相同的数据和几乎相同的代码,但我们只是添加了一个 Dask 集群来增强功能。

首先,我们可以看一下我们的步骤的运行时图——但是因为 pandas 需要 11 分钟来加载数据,所以它压倒了其他所有的东西!我们的数据处理几乎看不到,就像处理运行时顶部的一个小暗条。

因此,我们可以忽略加载时间,我们可以很容易地看到熊猫的加载时间要糟糕得多,然后我们可以看到我们尝试的单个处理任务。

总的来说,通过使用 Dask,我们节省了 11 分钟的加载时间,并减少了一半以上的数据处理时间。

总运行时间,熊猫:677,907 毫秒
总运行时间,dask: 34,294 毫秒

Pandas 比 dask 多花 20 倍的时间来运行整个任务流水线。

费用

不过话说回来,你可能会想,“熊猫是免费的吧?”当然,在你的笔记本电脑上熊猫是免费的(尽管我认为你的时间是宝贵的!)但是在 dask 上运行这个并不像你想象的那么昂贵。此外,我们在 EC2 机器上运行我们的测试用例,所以 pandas 在这个例子中也不是自由的。

所有机器都是 r 5.2x 大型实例。在撰写本文时,AWS EC2 的价格为每小时 0.504 美元。每个处理器包含 8 个 VCPU 内核和 64 GB 内存。

Dask 集群:
(1 个客户端+ 4 个集群工作器)
5 个 r 5.2 x 大型 x 0.504 美元/小时= 2.52 美元/小时* 34,294 毫秒(又名 0.0095 小时)= $0.02394

熊猫:
1 r5 . 2x large x 0.504 美元/小时= 0.504 美元/小时* 677907 毫秒(又名 0.1883 小时)= $0.0949

所以,在这个任务中,Dask 花了我们 2 美分,而熊猫花了我们 9 美分。

如果我们加上土星云向 Dask 方收取的溢价,公平地说,算术看起来是这样的。

土星 Dask 集群:
(1 个客户端+ 4 个集群工作器)
5 个 r 5.2 x 大型 x 1.14 美元/小时= 5.70 美元/小时* 34,294 毫秒(又名 0.0095 小时)= $0.05415

熊猫:
1 r5 . 2x large x 0.504 美元/小时= 0.504 美元/小时* 677907 毫秒(又名 0.1883 小时)= $0.0949

Dask 仍然只需 5 美分,比我们为熊猫支付的 9 美分还要低。速度快 20 倍,价格便宜一半——不错!

结论

我希望这篇文章有助于揭开从 pandas 切换到 Dask 的某些方面的神秘面纱,并鼓励读者为自己的数据科学尝试这些令人兴奋的新技术!Dask 集群比你想象的要便宜,运行速度特别快,而且如果你已经了解 pandas 和其他 PyData 库的话,非常容易使用。如果你想亲自体验一下,土星云有免费试用版!

Dask 阵列—如何轻松并行化 Numpy

原文:https://towardsdatascience.com/dask-arrays-how-to-parallelize-numpy-with-ease-b33d7e9dcb59?source=collection_archive---------22-----------------------

并行性和块—这就是如何将 20GB 的文件放入 16GB 的 RAM 中

在 Unsplash 上 WrongTog 的照片

所以你在数据科学的支柱——Numpy 和 Pandas——方面有一些经验,但仅此而已吗?

当您的 16GB RAM 机器上有一个 20GB 的数据集要分析时会发生什么?当然,有一种方法可以成块处理数据,但这不是最优雅的选择。

达斯克前来救援。

如果您想学习 Python 和 Dask 的并行基础,可以看看我以前的文章:

这篇文章的结构如下:

  • Numpy 怎么了?
  • 将 Numpy 数组转换为 Dask 数组
  • 用 Dask 阵列实现并行计算
  • 结论

Numpy 怎么了?

如果你处理小数据集,什么都不用做。当出现以下情况时,事情会失控:

  • 数据集大小超过可用 RAM
  • 计算时间变得非常长

显而易见,第一个原因与第二个原因紧密相连。

当学习一些技术或在一个项目开始时,处理小数据集几乎总是这样。重要的是要考虑长远——提前知道未来六个月的痛点是什么。

这就是 Dask 数组比 Numpy 提供更多灵活性的地方。它们使您能够处理大于内存的对象,并且由于并行化,计算时间显著加快。

在这一点上,Dask 数组不能处理线性代数运算,所以在某些情况下这可能是一个障碍。请继续关注他们的文档页面,因为一些“疑难杂症”可能会在未来得到解决。

现在让我们探索如何将 Numpy 数组转换成 Dask 数组。

将 Numpy 数组转换为 Dask 数组

Dask 数组只不过是排列成网格的 Numpy 数组的简单集合。转换过程要求您使用 Dask 的from_array()方法。

下面的代码片段导入两个库,创建一个 1000x1000 Numpy 的随机数数组,然后将其转换为 Dask 数组:

import numpy as np
import dask.array as dax_np = np.random.rand(1000, 1000)
x_dask = da.from_array(x_np, chunks=len(x_np) // 10)

这就是你要做的一切!如您所见,from_array()方法至少接受两个参数:

  • x —要转换的 Numpy 数组
  • chunks —指定如何分块数组。我们已经决定使用四个相同的块,但是你有许多选择。在笔记本中执行da.from_array?以查看更多选项

请记住,您应该使用整数来表示块大小,因此需要整数除法(//)。

如果您要查看x_dask变量内部的内容,您会看到以下内容:

图 1—Dask 数组的内容(图片由作者提供)

如您所见,整个 1000x1000 阵列占用大约 7.6MB 内存,单个区块的大小为 100x100,因为我们使用了 10 个大小相同的区块。每个块都是一个简单的 Numpy 数组。

您现在已经知道了转换过程是如何工作的,所以让我们来探究您应该使用 Dask 的真正原因。

用 Dask 阵列实现并行计算

免责声明:我在一台 16GB 内存的机器上运行下面的代码。如果你有更少,你可能会得到内存错误。减少data变量的初始大小以适应(例如,将 50 改为 20)。

想象一下,由于某种原因,您有一个 50 年期间每秒采样一次的数据序列(忽略闰年)。以下代码片段可用于构建这样一个数组:

data = np.random.rand(50 * 365 * 24 * 60 * 60)
data.shape

阵列形状如下图所示:

图 2 —数据数组形状(图片由作者提供)

如您所见,它非常庞大,因此执行任何操作都需要时间。让我们通过计算总和并跟踪运行时间来证明这一点:

%%timedata_sum = data.sum()
data_sum

结果显示如下:

图 3 —使用 Numpy 计算总和(图片由作者提供)

不是最快的——简单的算术题只需要 20 秒。达斯克可以做得更好。下面的代码片段将data数组转换成一个有 8 个块的 Dask 数组:

import dask.array as dadata_dask = da.from_array(data, chunks=len(data) // 8)
data_dask

这是里面的内容:

图 4 —大型 Dask 数组的内容(图片由作者提供)

如您所见,该数组非常大(几乎有 12GB)。这就是为什么即使计算最简单的运算也需要时间。理论上,将数组分成 8 个大小相等的 1.5GB 块并行处理听起来是个更好的主意。

您可以使用以下代码片段来计算数组总和:

%%timesum_dask_dag = data_dask.sum()
sum_dask = sum_dask_dag.compute()
sum_dask

请记住,在调用compute()之前,Dask 不会进行任何计算。我决定将结果存储在两个独立的变量中——第一个变量保存计算图,第二个变量存储计算结果。

下面是上面代码的输出:

图 5 —使用 Dask 计算总和(图片由作者提供)

现在你已经知道了——仅仅通过使用 Dask 而不是 Numpy,速度就提高了大约 2.5 倍。如果您感兴趣,可以使用下面的代码来可视化计算图:

sum_dask_dag.visualize(rankdir=’LR’)

下面是相应的可视化:

图 6 — Dask 计算图(图片由作者提供)

让我们在下一部分总结一下。

结论

总结一下——如果您知道数据不会变得更大,或者您需要 Dask 不支持的函数,Numpy 可以很好地工作。在其他任何情况下,Dask 都可能是明显的赢家。

我们今天只触及了皮毛,因为大部分数据分析都是用熊猫做的。这就是 Dask 数据帧发挥作用的地方,我们将在几天后探讨它们。

敬请关注。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

  • 我作为数据科学家卖掉我的 M1 Macbook Pro 的三大理由
  • 如何使用 Cron 调度 Python 脚本——您需要的唯一指南
  • Dask 延迟—如何轻松并行化您的 Python 代码
  • 如何使用 Python 创建 PDF 报告—基本指南
  • 即使没有大学文凭也要在 2021 年成为数据科学家

保持联系

  • 关注我的 Medium 了解更多类似的故事
  • 注册我的简讯
  • 在 LinkedIn 上连接

Dask DataFrame 不是熊猫

原文:https://towardsdatascience.com/dask-dataframe-is-not-pandas-6764da1291b1?source=collection_archive---------43-----------------------

在 Dask 中重用熊猫代码的最可靠方法

照片由 CHUTTERSNAP 在 Unsplash 上拍摄

本文是关于实践中使用 Dask 的系列文章的第二篇。本系列的每一篇文章对初学者来说都足够简单,但是为实际工作提供了有用的提示。本系列的下一篇文章是关于循环的 并行化,以及其他令人尴尬的使用 dask.delayed 的并行操作

诱惑

您从中等大小的数据集开始。熊猫做得很好。然后数据集变得更大,因此您可以扩展到更大的机器。但是最终,您会耗尽机器上的内存,或者您需要找到一种方法来利用更多的内核,因为您的代码运行缓慢。此时,用 Dask 数据帧替换 Pandas 数据帧对象。

不幸的是,这通常不会很顺利,会导致很大的痛苦。要么是你在 Pandas 中依赖的一些方法,在 Dask DataFrame 中没有实现(我看着你呢,MultiIndex),方法的行为略有不同,要么是对应的 Dask 操作失败,内存耗尽,崩溃(我以为不应该这样!)

Pandas 是一个为单个 Python 进程设计的库。分布式算法和数据结构是根本不同的。在 Dask 数据帧方面可以做一些工作来使它变得更好,但是单个进程和机器集群总是具有非常不同的性能特征。你不应该试图对抗这个基本的真理。

Dask 是扩展你的熊猫代码的好方法。天真地把你的熊猫数据帧转换成 Dask 数据帧不是正确的做法。根本的转变不应该是用 Dask 替换 Pandas,而是重用您为单个 Python 进程编写的算法、代码和方法。这是本文的核心。一旦你重构了你的思维,剩下的就不是火箭科学了。

有 3 种主要的方法来利用 Dask 的熊猫代码

  • 把你的大问题分解成许多小问题
  • 使用分组依据和聚合
  • 使用 dask 数据帧作为其他分布式算法的容器。

把你的大问题分解成许多小问题

照片由杰克逊在 Unsplash 煨

一个 Dask 数据帧由许多熊猫数据帧组成。它非常擅长从那些熊猫数据帧中移动行,这样你就可以在你自己的函数中使用它们。这里的一般方法是用拆分-应用-组合的模式来表达你的问题。

  • 将您的大数据集(Dask 数据框架)分割成较小的数据集(Pandas 数据框架)
  • 对这些较小的数据集应用函数(Pandas 函数,而不是 Dask 函数)
  • 将结果组合回一个大数据集(Dask DataFrame)

分割数据有两种主要方法:

set_index将使 Dask 数据帧的一列成为索引,并根据该索引对数据进行排序。默认情况下,它会估计该列的数据分布,以便最终得到大小均匀的分区(Pandas DataFrames)。

shuffle将把行组合在一起,这样具有相同 shuffle 列值的行就在同一个分区中。这与 set_index 不同,它没有对结果进行排序的保证,但是您可以按多个列进行分组。

一旦你的数据被分割,map_partitions是一个很好的方法来应用一个函数到每一个熊猫数据帧,然后把结果组合回一个 Dask 数据帧。

但是我有不止一个数据框架

没问题!只要你能以同样的方式分割计算中使用的所有 Dask 数据帧,你就可以开始了。

具体的例子

我不打算在这里写代码。我们的目标是在这个理论描述的基础上放一个具体的例子,以获得一些关于这个看起来像什么的直觉。想象一下,我有一个股票价格的 Dask 数据框架,和另一个分析师对相同股票估计的 Dask 数据框架,我想知道分析师是否正确。

  1. 编写一个函数,获取一只股票的价格,分析师对同一只股票的估计,并计算它们是否正确。
  2. 调用股票价格上的set_index,按股票行情自动收录器排序。你得到的数据帧的index将会有一个divisions属性,描述哪个滚动条在哪个分区。(B 之前的所有内容都在第一分区中,B 和 D 之间的所有内容都在第二分区中,依此类推..).使用股票价格divisions调用分析师估计的 Dask 数据框架上的set_index
  3. 使用map_partitions将函数应用于两个 Dask 数据帧的分区。该函数将查看每个数据帧中的分笔成交点,然后应用您的函数。

使用按聚合分组

图表由 Hugo Shi 绘制

Dask 拥有 Pandas GroupBy 聚合算法的优秀实现。实际的算法相当复杂,但是我们在文档中有详细的描述。如果你的问题符合这种模式,你就有好医生了。Dask 在 GroupBy 聚合的实现中使用了树缩减。您可能需要调整两个参数,split_out控制您的结果在多少个分区中结束,split_every帮助 dask 计算树中有多少层。这两个参数都可以根据数据的大小进行调整,以确保不会耗尽内存。

使用 Dask 作为其他算法的容器

照片由 Rinson Chory 在 Unsplash 上拍摄

许多库都内置了 Dask 集成。dask-mlscikit-learn融合。cuML有很多常见 ML 算法的多节点多 GPU 实现。tsfresh用于时间序列。scanpy用于单细胞分析。xgboostlightgbm都有启用 Dask 的并行算法。

结论

Dask 是扩展熊猫代码的好方法。天真地把你的熊猫数据帧转换成 Dask 数据帧不是正确的做法。但是 Dask 让你很容易将大数据集分解成小部分,并利用现有的 Pandas 代码。

最初发布于 2021 年 10 月 26 日https://Saturn cloud . io

dask data frames——如何轻松并行运行熊猫

原文:https://towardsdatascience.com/dask-dataframes-how-to-run-pandas-in-parallel-with-ease-b8b1f6b2646b?source=collection_archive---------13-----------------------

了解如何将 20GB 的 CSV 文件放入 16GB 的 RAM 中。

由 Elisha Terada 在 Unsplash 上拍摄的照片

所以你对熊猫有一些经验,你知道它最大的局限性——它不那么容易扩展。有解决办法吗?

是 Dask 数据帧。

Dask API 的大部分与 Pandas 相同,但 Dask 可以在所有 CPU 核心上并行运行。它甚至可以在集群上运行,但这是下一次的主题。

今天你将看到 Dask 在处理 20GB 的 CSV 文件时比 Pandas 快多少。运行时间值因电脑而异,因此我们将比较相对值。根据记录,我使用的是 MBP 16 英寸 8 核 i9,16GB 内存。

从头开始系列:

  • Dask 延迟——如何轻松并行化您的 Python 代码
  • Dask 阵列——如何轻松实现 Numpy 并行化

这篇文章的结构如下:

  • 数据集生成
  • 处理单个 CSV 文件
  • 处理多个 CSV 文件
  • 结论

数据集生成

我们可以在线下载数据集,但这不是今天文章的重点。我们只对大小感兴趣,对里面的东西不感兴趣。

因此,我们将创建一个包含六列的虚拟数据集。第一列是时间戳——以一秒为间隔采样的一整年,其他五列是随机整数值。

为了使事情变得更复杂,我们将创建 20 个文件,从 2000 年到 2020 年每年一个。

开始之前,请确保在笔记本所在的位置创建一个data文件夹。下面是创建 CSV 文件的代码片段:

import numpy as np
import pandas as pd
import dask.dataframe as dd
from datetime import datetime for year in np.arange(2000, 2021):
    dates = pd.date_range(
        start=datetime(year=year, month=1, day=1),
        end=datetime(year=year, month=12, day=31),
        freq=’S’
    ) df = pd.DataFrame()
    df[‘Date’] = dates for i in range(5):
        df[f’X{i}’] = np.random.randint(low=0, high=100, size=len(df)) df.to_csv(f’data/{year}.csv’, index=False)

现在可以使用一个基本的 Linux 命令来列出data目录:

!ls -lh data/

结果如下:

图 1 —单个 CSV 文件(图片由作者提供)

如您所见,所有 20 个文件的大小都在 1GB 左右(更准确地说是 1.09)。上面的代码片段需要一些时间来执行,但是仍然比下载一个 20GB 的文件要少得多。

接下来,让我们看看如何处理和聚合单个 CSV 文件。

处理单个 CSV 文件

目标: 读入单个 CSV 文件,按月对值进行分组,并计算每列的总和。

用熊猫加载一个 CSV 文件再简单不过了。read_csv()函数接受parse_dates参数,该参数自动将一列或多列转换为日期类型。

这很方便,因为我们可以直接使用dt.month来访问月值。以下是完整的代码片段:

%%timedf = pd.read_csv(‘data/2000.csv’, parse_dates=[‘Date’])
monthly_total = df.groupby(df[‘Date’].dt.month).sum()

这是总运行时间:

图 2 —包含熊猫聚合时间的单个 CSV 文件(图片由作者提供)

对于 1GB 的文件来说还不错,但是运行时间将取决于您的硬件。让我们对达斯克做同样的事情。代码如下:

%%timedf = dd.read_csv(‘data/2000.csv’, parse_dates=[‘Date’])
monthly_total = df.groupby(df[‘Date’].dt.month).sum().compute()

和 Dask 一样,在调用compute()函数之前,不会进行任何处理。您可以在下面看到总运行时间:

图 3 —带有 Dask 聚合时间的单个 CSV 文件(图片由作者提供)

让我们比较一下不同之处:

图 4 —单个 CSV 文件处理 Pandas 与 Dask(图片由作者提供)

这不是一个显著的区别,但是 Dask 总体上是一个更好的选择,即使是对于单个数据文件。这是一个好的开始,但是我们真正感兴趣的是一次处理多个文件。

接下来我们来探讨一下如何做到这一点。

处理多个 CSV 文件

目标: 读取所有 CSV 文件,按年份值分组,计算每列的总和。

使用 Pandas 处理多个数据文件是一项单调乏味的任务。一言以蔽之,你得一个一个地读取文件,然后垂直堆叠。

想想看,一个 CPU 内核一次加载一个数据集,而其他内核则处于闲置状态。这不是最有效的方法。

这个glob包将帮助你一次处理多个 CSV 文件。您可以使用data/*.csv模式获取data文件夹中的所有 CSV 文件。然后,你必须一个接一个地循环阅读。最后,您可以将它们连接起来并进行聚合。

以下是完整的代码片段:

%%timeimport globall_files = glob.glob('data/*.csv')
dfs = []for fname in all_files:
    dfs.append(pd.read_csv(fname, parse_dates=['Date']))df = pd.concat(dfs, axis=0)
yearly_total = df.groupby(df['Date'].dt.year).sum()

以下是运行结果:

图 5 —包含熊猫聚合时间的多个 CSV 文件(图片由作者提供)

15 分半钟看起来很多,但你必须考虑到在这个过程中使用了大量的交换内存,因为没有办法将 20+GB 的数据放入 16GB 的 RAM 中。如果笔记本完全崩溃,请使用较少数量的 CSV 文件。

让我们看看 Dask 有哪些改进。它接受read_csv()函数的 glob 模式,这意味着您不必使用循环。在调用compute()函数之前不会执行任何操作,但这就是库的工作方式。

下面是与之前相同的加载和聚合的完整代码片段:

%%timedf = dd.read_csv(‘data/*.csv’, parse_dates=[‘Date’])
yearly_total = df.groupby(df[‘Date’].dt.year).sum().compute()

以下是运行时结果:

图 6 —带有 Dask 聚合时间的多个 CSV 文件(图片由作者提供)

让我们比较一下不同之处:

图 7 —多个 CSV 文件处理 Pandas vs. Dask(图片由作者提供)

如您所见,在处理多个文件时,这种差异更加明显——在 Dask 中大约快 2.5 倍。一个明显的赢家,这里没有争论。

让我们在下一部分总结一下。

结论

今天,您已经了解了如何从 Pandas 切换到 Dask,以及当数据集变大时为什么应该这样做。Dask 的 API 与熊猫 99%相同,所以你应该不会有任何切换问题。

请记住,Dask 不支持某些数据格式,例如 XLS、Zip 和 GZ。此外,不支持排序操作,因为并行执行不方便。

请继续关注本系列的最后一部分——Dask Bags,它将教您 Dask 如何处理非结构化数据。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

  • 我作为数据科学家卖掉我的 M1 Macbook Pro 的三大理由
  • 如何使用 Cron 调度 Python 脚本——您需要的唯一指南
  • Dask 延迟—如何轻松并行化您的 Python 代码
  • 如何使用 Python 创建 PDF 报告—基本指南
  • 即使没有大学文凭也要在 2021 年成为数据科学家

保持联系

  • 关注我的 Medium 了解更多类似的故事
  • 注册我的简讯
  • 在 LinkedIn 上连接

Dask 延迟——如何轻松并行化您的 Python 代码

原文:https://towardsdatascience.com/dask-delayed-how-to-parallelize-your-python-code-with-ease-19382e159849?source=collection_archive---------7-----------------------

用一个装饰器并行化任何函数

Jose Castillo 在 Unsplash 上拍摄的照片

我们都知道 Python 不是最快的编程语言。它的 全局解释器锁 (GIL)机制一次只允许一个线程执行 Python 字节码。您可以通过更改解释器或实现基于进程的并行技术来避免这种限制。

我过去曾谈论过 Python 中的并行性,所以如果您不熟悉这个主题,请务必查看这些文章:

  • Python 并行性:几分钟内加速 Python 代码的基本指南
  • Python 中的并发性:如何用线程加速你的代码

这些方法非常有效,但是还有一个更简单的替代方法——使用 Dask 库进行并行处理。

如果你不熟悉 Dask,它基本上相当于大型数据集的熊猫。这太简单了,所以请在这里阅读更多关于库的信息。

这篇文章的结构如下:

  • 问题描述
  • 测试:按顺序运行任务
  • 测试:用 Dask 并行运行任务
  • 结论

你可以在这里下载这篇文章的源代码。

问题描述

目标是连接到jsonplaceholder.typicode.com——一个免费的假 REST API。

您将连接到几个端点并获取 JSON 格式的数据。总共会有六个端点。不是很多,Python 很可能在几秒钟内完成任务。对于展示并行能力来说不太好,所以我们将增加一些趣味。

除了获取 API 数据,程序还会在发出请求之间休眠一秒钟。由于有六个端点,程序应该在六秒钟内什么都不做——但是只有当调用按顺序执行时。

以下代码片段导入了所需的库,声明了一个 URL 列表和一个从单个 URL 获取数据的函数:

我们先测试一下没有并行的执行时间。

测试:按顺序运行任务

下面的代码片段在 Jupyter 笔记本中顺序获取数据。如果您不在笔记本环境中,请删除%%time magic 命令:

执行该单元格后,您将看到类似的输出:

图 1 —顺序执行(作者提供的图片)

这并不奇怪——Python 按照声明的顺序从 API 端点获取数据,大约花了 8 秒钟才完成,主要是由于调用了sleep()

事实证明,这些 API 调用是独立的,可以并行调用。让我们看看接下来该怎么做。

测试:用 Dask 并行运行任务

我们需要稍微修改一下代码。首先要做的是用一个delayed装饰器包装我们的fetch_single函数。一旦在循环之外,我们还必须对fetch_dask数组中的每一项调用 Dask 的compute函数,因为调用delayed并不做计算。

下面是完整的代码:

delayed装饰器包装函数的替代方法是在函数声明上方使用@delayed符号。随便用。

不管怎样,执行结果如下图所示:

图 2 —延迟 Dask 的并行执行(图片由作者提供)

如您所见,打印顺序不同。这是因为 Dask 被指示单独开始所有的任务。总执行时间不到 1.5 秒,其中 1 秒用于睡眠。

总的来说,进步很大。

问题仍然存在— 返回的结果是否相同?嗯,是也不是,顺序例子中得到的值在一个列表中,而调用compute后得到的值在一个元组中。

下图验证了:

图 3 —数据类型比较(作者图片)

因此,我们不能直接比较数据结构,但我们可以在将第二个数据结构转换为列表后进行比较:

图 4 —内容对比(作者图片)

最终的答案是肯定的——两种方法都会得到相同的结果,但是并行化的方法花费的时间要少一些。

结论

对您的应用程序或数据科学管道实施并行处理需要深思熟虑。幸运的是,代码实现很简单,因为只需要两个函数。

好消息是——您可以使用 Dask 来并行处理几乎任何事情。从基本的数据集加载、统计汇总到模型训练,Dask 都可以处理。

如果您想要更高级的基于数据科学的 Dask 教程,请告诉我。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

  • 每位数据科学家必读的 3 本编程书籍
  • 如何让 Python 静态类型化—基本指南
  • 使用 Python 进行面向对象编程——您需要知道的一切
  • Python 字典:你需要知道的一切
  • 介绍 f 字符串 Python 中字符串格式化的最佳选项

保持联系

  • 关注我的 Medium 了解更多类似的故事
  • 注册我的简讯
  • 在 LinkedIn 上连接
  • 查看我的网站

原载于 2021 年 4 月 19 日 https://betterdatascience.com**

DASK HACK:在您的员工中高效地分发大型辅助数据

原文:https://towardsdatascience.com/dask-hack-efficiently-distributing-large-auxiliary-data-across-your-workers-ac64ab919f9b?source=collection_archive---------39-----------------------

如何围绕每个工作人员只运行一次的函数创建延迟对象

约书亚·索特诺在un plash上拍摄的照片

TL;博士;医生

once_per_worker是一个围绕函数创建dask . delived对象的实用程序,您希望每个分布式工作器只运行一次。当您将一些大数据烘焙到 docker 图像中,并且需要将这些数据用作另一个 dask 操作的辅助输入时(例如,df.map_partitions),这很有用。once_per_worker不需要在集群中的工作人员之间传输串行数据——因为数据的大小会比较慢——而是允许每个工作人员调用一次解析函数,然后在下游使用相同的解析对象。

请参见下面的用例。

https://github.com/gjoseph92/once-per-worker

用例

在我的阿拉伯语错误信息检测项目中,我一直在广泛使用新的螺旋平台,该平台提供了一个非常用户友好且可访问的界面,可以在云中扩展 Python,以使用 Dask 处理大于内存的数据集。安装后,您可以用 4 行代码配置一个 AWS 集群,旋转它只需要 2-3 分钟,甚至不足以煮一杯咖啡!

经由 Giphy.com 的影像

我一直在测试这个平台的极限,对它的性能、可访问性和令人惊叹的支持团队印象深刻,每当我遇到任何问题时,他们都会迅速做出反应。(哦,还有有趣的额外福利——在测试版运行集群完全是免费的!)

我遇到的一个挑战是让我的阿拉伯语推文在云上得到满足。正如我在我的上一篇文章中所写的,为自然语言处理预处理阿拉伯文本带来了一系列挑战;其中之一是同一个字母组合(即看起来像同一个单词)可以有许多许多不同的意思。因此,为了使我们的记号变得简单,我们需要将这个可能的含义的范围缩减为一个;一个叫做消歧的过程。为此,我们使用 camel-tools 库将每个单词与一个形态学数据库进行比较,并提取该单词最可能的版本及其词条。

我遇到的问题是,这个形态学数据库非常大,当试图在云中运行这个引理满足时会出现问题。

虽然形态学数据库被烘焙到 Docker 映像中,该映像被分发给 my cluster 上的所有 worker, Dask 默认不知道每个 worker 已经有了它的副本。因此,当我们将我们的函数映射到 Dask 数据帧中的所有分区时,它将在工人之间传输序列化数据以执行它。考虑到文件的大小,这意味着执行下面的 map_partitions() 调用非常慢。一个只有 36 行的 dask 数据帧样本花费了将近 10 分钟。)

谢天谢地,Dask 的维护者之一 Gabe Joseph 用这个可爱的黑客拯救了我。我将从下面的软件包回购中复制完整的描述:

once_per_worker是一个围绕函数创建 dask.delayed 对象的实用程序,您只希望每个分布式工作进程运行一次这些函数。

假设您的 docker 映像中有一些大型数据(因此每个工人都有一份副本)。您需要将该数据作为另一个 dask 操作的辅助输入(例如,df.map_partitions)。但是解析/预处理数据很慢,而且一旦加载到内存中,数据就会很大,因此每个工作线程从磁盘加载数据比在集群中的工作线程之间传输序列化数据要快。因此,您只需要为每个 worker 调用一次解析函数,然后在所有下游任务中为每个 worker 使用相同的解析对象。

通过在once_per_worker中包装您的预处理函数,您得到一个延迟的对象,在一个给定的 worker 上,它将总是解析为相同的预处理对象。您的函数在您第一次访问返回值的属性时被调用。

下面的代码将这个包应用于我的特定用例。概括的工作流程如下:

  1. 导入once_per_worker
  2. 在一个 once_per_worker 调用中包装你的预处理函数(它运行在你不想序列化和移动的大数据上)。
  3. 使用预处理函数作为参数来定义映射函数。
  4. 跨分区映射映射函数。

注意:定义 once_per_worker 对象很重要,这样映射函数就可以访问这个对象的属性。否则不会调用该对象!在我的具体用例中,loaded _ disambiguitor只在我访问它的时被调用。消歧()属性。

以这种方式处理比 dask 默认方式更快。在我的例子中,仅用 20 秒就执行了 60k 行!

图片来自 Giphy.com

非常感谢 Gabe 为这个问题写了一个补丁,也非常感谢 Dask/Coiled 的所有人的大力支持!

如果您也经常使用大于内存的数据集,那么一定要看看 Coiled——我怎么推荐都不为过!

Dask 和 Vaex 的定性比较

原文:https://towardsdatascience.com/dask-vs-vaex-a-qualitative-comparison-32e700e5f08b?source=collection_archive---------12-----------------------

危地马拉阿蒂特兰湖。图片由马克·哈普尔通过 unsplash。

经常有人问我们 Dask 和 Vaex 相比如何。简而言之:他们没有

介绍

很长一段时间以来, Pandas 可以说是数据科学家工具箱中最重要的库。事实上,正是熊猫的出现帮助 Python 成为如此受欢迎的编程语言,无论是对于数据科学任务还是一般情况。但是数据集继续增长,现在它们经常超过大多数机器上可用 RAM 的大小。因此,对快速有效的数据处理和分析的需求,即下一代工具的需求也在增长。

Python 生态系统中有几种流行的技术,它们经常用于在数据科学和数据工程的背景下处理大型数据集。 Dask 是一个开源的通用框架,用于 Python 中的并行和分布式计算。对于各种类型的计算和数据科学任务的水平扩展,它通常是首选技术。它的更高层次的 API,Dask。DataFrame 提供了最便捷的方式来绕过使用 Pandas 时可能遇到的内存和性能障碍,即使是处理中等大小的数据集。

Vaex 是 Python 中的一个高性能 DataFrame 库,主要用于在单台机器上处理、探索和分析硬盘大小的数据集。谈到大型数据集, Vaex 认为,只要使用正确的方法来存储、访问和处理数据,大多数常见的数据科学和分析任务就不需要水平扩展,即添加更多的计算机/节点。

对于一般了解但不熟悉其中一种或两种技术的用户来说,它们可能看起来非常相似。当性能或内存管理成为一个问题时,这两者通常被用来取代熊猫。两者都使用惰性(或延迟)评估等概念,并行计算并采用核外算法。最重要的是,Dask 可以在集群上分布计算。所以有人可能会问:“这两个库的真正区别是什么?”或者“我何时或为何要使用 Vaex”?在接下来的内容中,我将强调这两种技术之间的主要区别,希望能够提高您对它们的理解,并使您在为您的用例选择合适的工具时能够做出更明智的选择。

1.Dask vs. Dask.DataFrame vs. Vaex

Dask 是一个通用框架,用于在集群上并行化或分布各种计算。许多流行的数据科学库,如 scikit-learn 、 XGBoost 、 xarray 、 Perfect 等,可能会使用 Dask 来并行化或分布它们的计算。

当许多数据科学家或工程师说“Dask”时,他们通常指的是Dask.DataFrameDask.DataFrame是一个建立在熊猫和 Dask 之上的 DataFrame 库。实际上,一个Dask.DataFrame由许多较小的 Pandas 数据帧组成,这些数据帧与 Dask 提供的通用任务调度程序相耦合。当一个计算被触发时,Dask 会把Dask.DataFrame分解成许多更小的熊猫数据帧,每个数据帧都做好自己的工作,最后把结果连接起来。

Vaex 是一个全新的数据帧实现,从头开始构建,能够以令人难以置信的速度处理包含数亿或数十亿行的数据帧。虽然它试图遵循熊猫设置的 API,但在它的引擎盖下隐藏着高效的核外 C++算法。再加上内存映射,它可以在一两秒钟内处理 1.000.000.000 行。Vaex 还可以将数据传输到您最喜欢的云存储桶,并与 Apache Arrow 完全兼容,允许您与 Python 领域之外的生态系统接收和共享数据。

2.懒惰评估

Dask.DataFrame和 Vaex 都支持延迟评估。然而,用户应该意识到它们在操作方式上有一些不同。在Dask.DataFrame中,任何需要迭代数据的操作都被延迟,直到用户明确指定应该通过调用.compute()方法来完成计算。例如,计算列的平均值如下所示:

如果在上面的例子中没有指定.compute(),一旦计算被触发,mean_x将只是一个占位符,等待存放结果。即使对于“简单”的操作,比如获得数据帧的形状,也需要调用.compute()方法:

在上面的代码块中,x的平均值和总和都是通过对数据的一次遍历来计算的。

Vaex 以不同的方式处理惰性评估。如果一个操作的结果将“活”在定义它的数据帧内,则该操作将被延迟。这方面的一个例子是添加一个新列,或者将两个数据帧连接在一起。另一方面,如果一个操作的结果将存在于定义它的数据帧之外,则该操作将被立即触发。这方面的一个例子是计算一列的平均值,寻找一列的唯一值,或者一个groupby操作。例如:

像这样的工作流对于许多需要即时反馈的数据科学家来说非常方便,尤其是在经常交互的数据探索和分析阶段。虽然 Vaex 也可以计算多个聚合或一次通过数据的计算,但 Dask 的 API 对于这种方法更方便。

3.处理大型数据集

能够处理大量数据是使用这两个库的常见原因。然而,他们处理这种数据的方法有点不同。Dask.DataFrame通过将数据分块成多个 Pandas 数据帧,然后对其进行延迟评估,克服了这一挑战。Dask.DataFrame也可以在集群上分布这些更小、更易管理的数据帧。这里的好处是,可以使用任意大小的集群来解决任何内存问题,并并行化计算。Dask.DataFrame与 Vaex 相比,更紧密地遵循 Pandas API,并提供了 Pandas 功能的更大覆盖面。坏处源于同样的原因——Dask.DataFrame继承了熊猫的一些包袱,比如内存饥渴。此外,将集群引入数据科学工作流会带来与其设置、管理、开发和成本相关的巨大复杂性。像 Coiled 和 SaturnCloud 这样的组织正试图简化这一挑战。

Vaex 完全重新思考了现代数据框架应该如何实现。这一切都从数据开始,数据在磁盘上应该是内存可映射的格式。再加上现代 SSD 磁盘的读取速度约为 5GB/s,云存储桶的读取速度约为 12.5GB/s,这使得数据的读取和处理速度令人难以置信—所有这些都在一台机器上完成,甚至是笔记本电脑!虽然性能比较超出了本文的范围,但是看看 Vaex 在超过 1.000.000.000(十亿)个样本的上执行一些常见操作的速度有多快:

使用 Vaex 的明显优势是难以置信的开箱即用速度,完全不需要任何特殊的系统配置或集群配置。缺点是,由于这是一个新的实现,它还没有 Pandas 提供的所有方法。

虽然任何一种性能比较都超出了本文的范围,但是如果你有兴趣的话,你应该看看这篇文章。所有的基准测试都有这样或那样的偏差,所以我鼓励你自己去尝试每一件事,使用你的数据,并根据你的需求来判断。

4.数据文件格式

Apache Parquet 是Dask.DataFrame的首选数据格式。对于较大的数据集,如果将数据划分到多个文件中,可以获得更好的性能。在集群上使用Dask.DataFrame时,数据可以集中,即位于一台机器上,或者分布在组成集群的机器上。

为了获得最佳性能,Vaex 的首选数据格式是 HDF5 和 Apache Arrow 。Vaex 还可以读取 Apache Parquet 文件格式。Vaex 希望所有数据都位于一台机器上。虽然它可以延迟读取分布在多个文件中的数据集,但为了获得最佳性能,最好将全部数据存储在一个文件中。像 Dask 一样,Vaex 也可以从(和到!)您喜欢的云对象存储,并可选择在本地缓存它。

这两个库都可以读取存储在 CSV 、 JSON 中的数据,以及熊猫可以读取的几乎任何文件格式。但是,对于更大的数据集和更好的性能,最好将数据转换为每个库首选的文件格式。

5.用什么

在这一节里,很难说有什么是完全公正的。亲爱的读者,我善意但强烈地建议你自己尝试这些和任何其他库,并根据你的数据、用例和需求做出决定。考虑到这一点,以下是我个人的偏见。

Vaex 是速度最快、内存效率最高的 Python 数据帧库。它在单台机器上每秒可以处理 1.000.000.000(十亿)行的事实在当今业界是无与伦比的。它用于交互式探索、可视化和大型表格数据集的预处理。作为一个单机解决方案,它几乎没有增加 DevOps 开销,令人惊叹的性能使它成为各种交互式仪表盘或机器学习应用程序的优秀后端引擎。

在数据科学中仍然有大量的计算任务,在数据工程中甚至更多,这些任务不能以非核心的方式完成。例如,解析大量的 xml 文件。这就是达斯克的闪光点。因为它是分布式计算的通用框架,所以它可以在表格数据集的领域之外很好地推广。建立在 Dask 和 Pandas 之上的 DataFrame 实现提供了一个相对于 Pandas 更加完整的 API 规范。它还提供了一种并行化和分布各种常见机器学习操作的方法,这些操作通常是用流行的 Python 库(如 Scikit-Learn 或 XGBoost)来完成的。

结尾部分

Dask 是一个通用工具,采用通用方法来缩放熊猫。它用小熊猫的数据帧构建了一个大的数据帧,并耦合到一个通用的任务调度框架。这提供了广阔的范围,同时为优化留下了空间。另一方面,Vaex 更专注于大型数据帧问题。这使得它更有效,但代价是一些普遍性。

Vaex 和 Dask[。DataFrame]都是优秀的数据科学库。虽然本文主要是比较和对比他们处理大型表格数据集的方法,但我可以想到多种使用这两种技术的最佳解决方案。

这两个库只是 Python 生态系统力量的一个小证明,与其他许多库一起确保我们可以解决我们遇到的任何问题。事实上,有多种方法来解决一个特定的问题只能是一件好事!

感谢 Matthew Rocklin 为改进本文提供了有益的评论和建议。

数据优势矩阵:思考数据策略的新方法

原文:https://towardsdatascience.com/data-advantage-matrix-a-new-way-to-think-about-data-strategy-4178cd2f520a?source=collection_archive---------2-----------------------

行业笔记

创建数据战略没有单一的途径。以下是如何找到你的,并创造强大的数据优势。

照片由i̇rfan·西姆萨尔在 Unsplash 拍摄

作为两家数据初创公司的联合创始人,我经常收到的一个问题是,“我如何开始我的数据战略?我们从哪里开始?我们优先考虑什么?”

这是个可以理解的问题。如今,公司被大量提醒使用数据的重要性。在 NewVantage Partners 的年度调查中,连续第三年投资于数据计划的公司比例几乎是普遍的(2021 年实际上是 99%)。

虽然投资数据是理所当然的,但实际使用数据可能会感觉像是在冒险。在同一项调查中,只有 24%的公司表示他们创造了一种数据驱动的文化。

斗争是真实的。(图片来自Atlan),他的社交团队花了太多时间为我们自己的团队创造模因。)

确定您的数据策略远非易事。为了帮助领导者和公司找出他们的整体数据战略,我创建了一个框架,我称之为数据优势矩阵

在这篇文章中,我将分解如何考虑你的数据策略,矩阵如何工作,并给出两个假设的公司将如何使用它的例子。

数据策略不是线性的或通用的

有大量的资源承诺了创建数据策略的一条真正的道路。“做这 5 件事,你将成为一家数据驱动的公司”或“这是将你的数据货币化的 5 个步骤”等等。

网上数据策略列表的例子。(图片由 图集 。)

我希望事情能这么简单。

这是我从运行无数数据项目中学到的令人痛苦的事实:没有一条创建数据策略的道路。每家公司都是独一无二的,每项业务都是独一无二的,每个行业都是独一无二的,因此每家公司的道路都将是独一无二的。不要看其他公司做了什么,关键是检查您自己的需求,并为您的公司优先考虑最佳数据投资

你怎么知道你应该优先考虑什么?许多资源谈到关注具有最高 ROI 的项目(即这些计划将为您的公司带来的回报)。

但是,我认为这是看待您的数据策略的错误方式。因为让我们面对它,每个数据人都知道你的输入和假设驱动你的 ROI 计算的最终输出。我认为公司不应该从 ROI 的角度来划分数据项目的优先级,而应该从“优势”的角度来划分。

哪些数据投资将帮助您建立可持续的竞争优势,从而超越竞争对手?

数据优势矩阵

数据优势矩阵可以帮助您确定您想要建立什么类型的数据优势,以及您想要将它们推进到什么程度。

它是这样工作的——行代表公司可以创造的数据优势的类型,列是每个优势的三个阶段。

数据优势矩阵。(图片由 阿特兰 )。)

让我们来分解一下,从四种类型的数据优势开始:

  • 运营:这是关于理解推动你业务的杠杆,然后利用它们来改善运营。一个关键的方面是让那些每天做决策的人可以获得和理解数据。一个例子是 Gojek 关于关键指标的每日更新,它的第一任首席执行官 Nadiem Makarim 使用它来形成对什么正在被破坏的直观感觉。
  • 战略:每家公司每年都会做出几个关键的战略决策。这些决策越是由数据驱动,就越有可能推动增长或取得成功。一个例子是印度政府利用地理集群开设了 10,000 个新的液化石油气中心。
  • 产品:这是公司利用数据来推动核心产品优势的时候,这种优势将他们与竞争对手区分开来。一个例子是谷歌的“智能撰写”自动完成功能。
  • 商业机会:这涉及到使用公司数据来发现和创造新的商业机会。一个例子是网飞原创,网飞开始根据人们想看的数据制作自己的电视节目和电影。

我已经写了这四种类型的优势,所以如果你想了解更多,可以看看那篇文章。

4 类数据优势。(图片由 图集 )。)

接下来,我们了解了每个数据优势的三个阶段:

  • 第一阶段(基础):这是一个快速且不成熟的 MVP,它使用基础工具(例如 SAAS 产品、Google Sheets、Zapier)并且没有数据专家。我几乎总是建议公司在“基础”层开始新的计划,以快速部署和评估解决方案。
  • 阶段 2 ( 中级):这一层包括对数据平台工具和数据专家或团队的投资。
  • 阶段 3 ( 高级):这些是同类最佳的数据计划,每个用例或项目都有专门的团队。当您到达这一层时,您基本上就是一个案例研究,了解作为一家数据驱动型公司意味着什么。

准备好看这个了吗?让我们通过几个例子来看看两家假设的公司将如何使用数据优势矩阵来制定他们的数据战略。

示例 1:使用矩阵对 SAAS 软件启动的数据计划进行优先级排序

SAAS 软件创业的数据优势矩阵示例。(图片由 图集 )。)

对于 SAAS 公司来说,漏斗就是一切。在漏斗的每个阶段优化指标是加速 SAAS 公司从平均增长到指数增长的原因。因此,对于任何 SAAS 的创始人来说,如果你在第一天没有建立基本的运营分析,你可能会做错一些事情。

这个虚构的 SAAS 创业公司将从矩阵的左上角开始,提供基本的运营分析。这些分析不必复杂。在第一阶段,一切都是为了做好最基本的事情——衡量每天的潜在客户数量、用户在网站上的转化、用户注册产品、最终付费的免费试用等等。

鉴于运营分析的重要性,这家初创公司很快进入第二阶段是有意义的——将其基本分析转化为更具可扩展性的东西,如集中式智能引擎。这将包括投资一个数据仓库(如红移或雪花),将所有数据集中到一个地方,添加一个 BI 工具,并雇佣第一批分析师在最重要的地方(如营销或销售)推动数据驱动的决策。

在这一点上,随着运营的分类,创业公司可以开始考虑业务的其他方面:

  • 为了推动对外销售,it 部门可以投资建立一个针对竞争对手的护城河,如销售线索评分算法,以帮助销售代表专注于最佳销售线索。
  • 它可以回到其核心优势,运营分析,并使超级数据驱动和民主化。
  • 它甚至可以专注于一项新的优势,比如在其产品中创建一个仪表板来追加销售客户。

示例 2:为 cab 聚合器排定数据计划的优先级

cab 聚合器初创公司的数据优势矩阵示例。(图片由 阿特兰 )。)

我们再举一个例子,一家出租车聚合创业公司。

这是一种完全不同的情况,因为一个出租车公司的整个产品依赖于供需平衡。如果客户找不到出租车,他们就不会在出租车公司找到价值。

这就是为什么 cab 聚合器会从不同于 SAAS 公司的地方开始——这是一个产品优势。它将首先投资建立一个供需匹配算法,因此它的第三或第四个雇员需要是一个强大的数据科学家,以建立适当的工具,并使其算法在第一天成为竞争优势。

接下来,在 Excel 等工具上构建基本的运营报告对公司来说可能是有意义的。那么对公司来说,考虑一些战略问题,比如如何从一个城市扩张到十个城市,可能是有意义的。由于这是一个关键问题,它可以再次跳到阶段 2——投资一位数据科学家来构建一个合适的地理聚类算法。

在此过程中,cab 初创公司可能希望升级其供需匹配算法,并建立强大的团队和一流的数据系统,使其成为先进的数据优势。

为您的公司使用数据优势矩阵

那么,贵公司的数据优势矩阵应该是什么样的呢?

从思考你希望自己的竞争优势是什么开始。什么能让你超越你的竞争对手?

列出你可以在业务中建立的所有数据优势,然后考虑你想采用哪种优势。专注于提升您的核心优势是否有意义,或者跨其他类型的数据优势推出“基本”数据计划是否更好?

确定数据投资的优先级没有简单的方法。例如,两家类似的 SAAS 创业公司可能会采取不同的方法来建立他们的数据战略和团队。当您考虑对可能的计划进行优先级排序时,从三个基本问题开始:

  • 这样会创造什么样的数据优势?
  • 这项计划会对我们公司产生什么影响?
  • 我们要花多少努力才能到达那里?

请注意,数据优势并不总是始于第一阶段。像 cab 聚合器一样,如果数据优势对您的公司至关重要,并且可以从一开始就建立在适当的工具上,那么从阶段 2 开始可能是有意义的。当你可以从一些快速和肮脏的东西开始,弄清楚你到底需要什么,然后随着时间的推移升级,从第一阶段开始,有一个 MVP——这是我通常推荐的。

回顾数百个数据项目

根据我在 200 多个数据项目中与数据领导者合作的经验,我了解到为您的公司创建数据战略没有一条直线路径。最重要的一点是从基本原则开始。

请记住,你的业务是独一无二的,因此你为自己创造的数据护城河和优势将是世界上其他公司所不具备的。

当您考虑寻找您的数据策略时,请从基础开始。考虑你可以建立的不同类型和水平的优势,从可以产生有意义的影响的最容易获得的果实开始,并从那里继续迭代。

然后,当您开始创建这些数据计划时,请记住构建正确的基础。不要忘记投资你需要的数据工具,每当你进入第二阶段,就建立一个现代数据平台。数据访问和协作工具在第二阶段是可选的,但是一定要确保在第三阶段之前弄清楚它们。

现代数据平台的构建模块。 阅读更多。 (图片由 图册 )。)

祝你一路顺风,如果你有任何问题,请留言!

发现此内容有帮助?在我的时事通讯《元数据周刊》上,我每周都写关于活动元数据、数据操作、数据文化和我们的学习建设的文章 【亚特兰】 在此订阅。

数据分析和可视化变得更好——米托增加了你应该尝试的 5 个功能

原文:https://towardsdatascience.com/data-analysis-and-visualization-just-got-better-mito-adds-5-features-you-should-try-8758b4b7cd?source=collection_archive---------14-----------------------

无代码数据分析和可视化——熊猫的 GUI 使之成为可能。

在 Unsplash 上由 Mitchell Y 拍照

免责声明 :这不是一篇赞助文章。我与米托或这个库的创建者没有任何关系。这篇文章展示了该库的一个公正的概述,旨在使数据科学工具能够被更广泛的大众所使用。

试图跟上最新的数据科学库就像试图闭着眼睛阅读一样。如果不能很好地解决一个特定的问题,任何新的事物都无法获得关注。这就是米托吸引你注意力的地方。

几个月前,我已经写了关于米托的文章,但是从那以后,图书馆增加了一些新的功能并更新了现有的功能。这些将在今天讨论。

首先,让我们在您的本地机器上安装米托。

开始使用—在本地安装米托

米托方案有两个先决条件:

  • Python 3.6 或更新版本
  • Node.js

假设您已经安装了这两个工具,我将继续使用 Anaconda 创建并激活一个新的虚拟环境:

conda create --name mito_env python=3.8
conda activate mito_env

然后通过安装依赖项:

python -m pip install mitoinstaller
python -m mitoinstaller install

完成后,您可以启动 Jupyter 实验室:

jupyter lab

创建一个新笔记本,您就可以开始了!

新设计——90 年代已经过去

我喜欢工具工作出色的时候。但如果它看起来像狗屎,我就不会用它。对你来说可能不是这样,但现代设计每天都在击败不必要的边框、阴影和其他类似 Windows XP 的软件。

新的米托版本有一个更新的设计,你马上就会看到。然而,从技术上来说,这不是一个新功能,所以我不把它算在列表中。

首先,让我们创建一个新的米托工作表。假设您打开了一个空白笔记本,请执行以下代码:

import mitosheetmitosheet.sheet()

您应该会看到类似的内容:

图 1 —米托注册屏幕(图片由作者提供)

你必须输入你的电子邮件才能继续,但是他们不会用太多的邮件来打扰你。即使他们有,也总有退订的选择。

完成后,您会在笔记本中看到一张空白页:

图 2-空白米托表(图片由作者提供)

是的——米托看起来比以前更好了,但这不是你读这篇文章的原因。让我们继续第一个改进的特性—更简单的数据管理。

更简单的数据管理—连接到本地文件系统

我不喜欢熊猫的一点是猜测我要写多少次../才能找到正确的数据文件夹。米托的情况并非如此。

米托现在可以直接连接到您的本地文件系统,使数据集加载和管理更加容易。我们将在整篇文章中使用泰坦尼克号数据集,所以如果你想继续的话,一定要下载它。

创建新的米托工作表后,您将看到导入文件的选项,如下所示:

图 3-导入文件选项(按作者分类的图像)

你可以选择你的数据集,点击下面的导入按钮。这将立即加载数据集:

图 4——米托的泰坦尼克号数据集(图片由作者提供)

该库将在下面的单元格中自动为您生成 Python 代码。现在看起来是这样的:

图片 5-生成的 Python 代码(图片由作者提供)

很整洁,不是吗?接下来我们来看看如何计算汇总统计。

汇总统计数据—只需点击一下鼠标

计算汇总统计数据——如平均值、中值、四分位数等——通常意味着在每一列上调用一个describe()函数,而不考虑变量的图形表示。

米托只需点击一下鼠标。

只需点击感兴趣的列,并浏览右侧的汇总统计数据选项卡。它用最合适的图表类型将数据可视化,并告诉您describe()函数会告诉您的一切:

图 6 —米托的汇总统计数据(图片由作者提供)

不用说,以这种方式探索数据对于任何初次接触数据集的人来说都是必须的。

更改数据类型—只需从下拉列表中选择

默认情况下,数据的格式并不总是正确的。要解决这个问题,您可以更改数据类型或创建一个派生列。米托轻松做到了这两点。

您可以单击标题列中的小图标打开属性,并从那里更改数据类型:

图 7-使用米托更改数据类型(图片由作者提供)

对于任何更复杂的事情,您最好创建一个派生列。下面的示例向您展示了如何将Sex属性转换为二进制列,其中 males 的值为 1:

图 8-使用米托创建派生列(作者图片)

前面的操作会生成以下 Python 代码:

# Set M in titanic_csv to =IF(Sex == ‘male’, 1, 0)
titanic_csv[‘M’] = IF(titanic_csv[‘Sex’] == ‘male’, 1, 0)# Renamed M to IsMale in titanic_csv
titanic_csv.rename(columns={“M”: “IsMale”}, inplace=True)

这对于任何具有基本 Excel 背景的人来说都应该很熟悉。

数据透视表—轻松创建和编辑

快速汇总数据的最简单方法之一是通过数据透视表。在米托,创建一个数据透视表会创建一个新的 Pandas 数据框架,然后您可以进一步修改它(例如,排序)。

解释这一概念的最佳方式是通过演示——接下来的演示创建了一个数据帧,其中包含了上船点的幸存乘客人数:

图 9 —带有米托的数据透视表(图片由作者提供)

下面是上一个操作生成的代码:

unused_columns = titanic_csv.columns.difference(set([‘Embarked’]).union(set([])).union(set({‘Survived’})))
tmp_df = titanic_csv.drop(unused_columns, axis=1)pivot_table = tmp_df.pivot_table(
    index=[‘Embarked’],
    values=[‘Survived’],
    aggfunc={‘Survived’: [‘sum’]}
)# Flatten the column headers
pivot_table.columns = [make_valid_header(col) for col in pivot_table.columns.values]# Reset the column name and the indexes
df2 = pivot_table.rename_axis(None, axis=1).reset_index()

简单吧?如前所述,你可以在创建后修改透视表。以下是如何对列进行排序和重命名:

图 10 —带有米托的数据透视表(2)(图片由作者提供)

前面的操作生成了以下代码:

# Sorted Survived_sum in df2 in descending order
df2 = df2.sort_values(by=’Survived_sum’, ascending=False, na_position=’first’)
df2 = df2.reset_index(drop=True)# Renamed Survived_sum to Total_survived in df2
df2.rename(columns={“Survived_sum”: “Total_survived”}, inplace=True)

最后,让我们来看看数据可视化。

图形—包括交互性

我喜欢可视化地检查数据,但我并不热衷于编写可视化代码。如你所料,米托会保护你。

你所要做的就是点击图形选项,选择可视化类型并选择 X 轴和 Y 轴的列——该库涵盖了所有其他内容。

下面是如何绘制Age列的箱线图:

图 11-米托数据可视化(图片由作者提供)

看起来 Plotly 是在幕后使用的,所以可视化默认是交互式的。整洁!

最后的话

在最近的米托版本中,五大新的/升级的特性也是如此。从旧的设计来看,官方文档还没有更新,但这只是时间问题。

问题仍然是——你应该使用米托吗?

我的回答和上一篇一样。作为一名数据科学家,我看不出你为什么不应该这样做,尤其是如果你精通 Excel 并想开始使用 Python 和 Pandas。米托可以让过渡过程变得容易得多。

总之——给米托一个机会。这是免费的,你不会有任何损失。我很想在下面的评论区听到你对这个库的看法。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

  • 2021 年学习数据科学的前 5 本书
  • 如何用 Cron 调度 Python 脚本——你需要的唯一指南
  • Dask 延迟—如何轻松并行化您的 Python 代码
  • 如何用 Python 创建 PDF 报告——基本指南
  • 2021 年即使没有大学文凭也能成为数据科学家

保持联系

  • 在 Medium 上关注我,了解更多类似的故事
  • 注册我的简讯
  • 在 LinkedIn 上连接

MoMa 艺术收藏中种族多样性和性别分布的数据分析和可视化

原文:https://towardsdatascience.com/data-analysis-and-visualization-of-ethic-diversity-gender-distribution-in-the-moma-art-9ce57c1a4f9e?source=collection_archive---------28-----------------------

剧透:13.1 万件藏品中有 11 件作品出自非二元艺术家之手,其中 9 件来自新媒体艺术部门

作为 MA 数据驱动设计的一部分,我的数据科学课被要求探索我们感兴趣的任何主题,我偶然发现了这个官方 MoMa 数据集,概述了他们收藏的 138.185 件艺术品。惊讶地发现以前没有人发表过任何关于它的分析或可视化,我很快就做出了决定。由此产生的见解很有趣,也许对进一步的研究有用,所以我决定改变我的任务,并在这里与你分享!

在🕵🏼‍♀️研究框架,我陈述了研究的目标,并勾勒了现代艺术机构,尤其是 MoMa 的多元化背景。

在…里📊数据洞察,我用彩色图表展示了分析的结果,并附有结论和讨论。

在🧽方法论中,我主要使用 Python、Pandas 和 Plotly 详细介绍了数据清理和预处理的过程和决策。

放弃

我并不宣称这些发现是绝对真实的——仅仅是数据集中反映的推论。多样性的维度极其有限,并且没有考虑到交叉性。这些结果不是指责,而是讨论的起点。数据预处理可能包含缺陷——我正在学习。既然我们已经解决了这个问题,那就让我们开始吧。

🕵🏼‍♀️研究框架

研究目标

这项研究旨在分析 MoMa 藏品中的种族和性别多样性,重点是对当代艺术和新媒体艺术作品进行比较分析。我的假设是,新媒体艺术部将会比它的当代同行获得更多艺术家的作品。

虽然研究的范围在数据集的范围(仅限于 MoMa 机构)和多样性的措施(仅限于种族和性别)方面都非常有限,但分析希望为围绕艺术机构和不同艺术实践中的代表性的进一步讨论提供一个起点。

艺术和现代艺术博物馆收藏的多样性

现代艺术博物馆(MoMA)是世界上最大和最有影响力的博物馆之一,对现代艺术的发展和收藏产生了巨大的影响(Kleiner,2016 年,第 1-3 页)。库尔特·勒温的看门人理论是一个选择,然后过滤媒体项目的过程,这些媒体项目可以在一个人碰巧拥有的时间或空间内被消费这有助于我们理解 MoMa 机构在设定全球艺术议程中作为一个重要的看门人。

2019 年,MoMa 在一次大规模翻新后重新开放,旨在象征和实现其对来自更多元化地理和背景的艺术家的更多元化收藏的承诺(法拉戈,2019 )。2019 年 3 月进行的第一次大规模美国主要博物馆艺术家多样性研究提供了每个博物馆的性别和种族多样性估计,得出的结论是 85%的艺术家是白人,87%是男性。它还观察到,增加多样性的大部分努力都集中在游客和工作人员身上,而不是集合中的艺术家( Topaz,2019 )。

全球艺术行业正在努力解决多样性问题。随着现代艺术博物馆公开宣称其对多样性的承诺,我们开始评估这些意图是否超越了它的项目而延伸到藏品本身。

当代与新媒体艺术

在当代和新媒体艺术的区分中,我们坚持将新媒体艺术定义为“一个包含通过新媒体/数字技术制作、修改和传播的艺术形式的综合术语”* ( Grau,2016 )。相反,新媒体艺术被认为具有更容易接近的性质和包容性的文化,然而很少或没有公共研究可以证明这一说法。这项研究还试图证明,与当代艺术相比,新媒体艺术的多样性是否在 MoMa 收藏中有所体现。*

📊数据洞察

MoMa 系列中的种族多样性

数据显示,这些年来,收藏中的种族多样性明显增加,2018 年购买来自 61 个独特民族的艺术家作品达到最高峰,是 1989 年 18 个国家的三倍。右侧的动画展示了从 1986 年到 2019 年购买的每个流行分类的独特国籍。

**

作者提供的图片

世界地图显示,欧洲和美国艺术家明显过多,而中东,非洲和亚洲的部分地区在收藏中代表性不足。这里的数据是以对数标度归一化的。

作者图片

MoMa 系列中的性别分布

性别分布极不平衡,85%为男性艺术家,14%为女性,1%不确定或未知。在 MoMa 收藏的作品中,只有 0.01%是由非二进制艺术家创作的:在数据集中的 140,000 件作品中,总共占了 11 件。

从右边的图表中,我们可以根据点之间的距离推断出一些分类比其他分类具有更好的性别分布。在摄影作品中,我们可以看到男性(25K)和女性(4K)之间的巨大差距,而建筑则更加平衡(根据进一步的调查,确实是扎哈·哈迪德一手造成的)。

作者图片

当代与新媒体艺术收藏的多样性

数据显示了当代艺术和新媒体艺术作品之间的明显差异。对于每 100 件被收购的艺术品,当代艺术将从平均来自 3-4 个不同国家的艺术家那里购买新媒体艺术,包括多达 22 件,是这个数字的 6 倍。

当代艺术和新媒体艺术的性别分布分别是男性占 85%至 72%,女性占 14.5%至 23.5%,女性占 0.001%至 0.3%。

作者图片

2000 年后获得的当代艺术收藏中有 1 件作品来自非二元艺术家,而新媒体艺术收藏中有 9 件。

作者图片

结论

当代和新媒体艺术之间的差异是显著的,并证实了新媒体艺术是一个更加多样化的空间的看法,这反映在 MoMa 的收藏中。在整个收藏中,我们看到非二元和 POC 艺术家仍然严重不足,这表明我们在致力于将艺术收藏作为社会的反映方面还有很长的路要走。

讨论

为了继续研究,深入研究各种分类之间的比较和相互关系并考虑多样性的更多交叉措施将是令人感兴趣的。至于局限性,这项研究仅限于种族和性别作为多样性的衡量标准。种族划分是基于一个人的国籍,而不是他们的种族或他们自我认同的文化。因此,这非常有限地代表了多样性的含义。

至于复杂问题,不再存在的国家,如南斯拉夫,必须从数据集中删除,因为它们与 Plotly 图书馆不兼容。虽然就这项研究的目的而言,这并不是直接的问题,但很容易看出,如此容易地抹去一个国家的文化遗产需要谨慎。

🧽数据(预处理)

现代艺术博物馆数据集

使用的数据集是在官方 MoMa GitHub 上提供的艺术品文件。它包含 138.185 条记录,每条记录都有详细的元数据。

数据清理和格式化

经过初步的数据清理,融合重复和删除丢失和损坏的价值,130.822 作品仍然存在。

不同的艺术实践是基于分类栏。当代艺术系列包括绘画、家具和室内装饰、插图书籍、印刷品、雕塑、绘画、出版物、纺织品和纸上作品,总共有 23754 件作品。

新媒体艺术集包括音频、数字、电影、平面设计、媒体、视频、软件共 3089 件作品。一些实践,如设计或摄影,不包括在任何一个数据集中,因为这些类别没有提供有意义的方法来区分它们。在提供的数据集中,当代艺术作品比新媒体艺术作品多得多,这就是为什么在一些可视化中,值被标准化为百分比。

时间线是基于作品被博物馆收购的年份,而不是艺术家创作的年份。仪表板上的各种可视化覆盖了不同的时间跨度。在当代艺术和新媒体艺术的比较中,两个数据集都只包括 2000 年以后的作品。

国籍基于国籍元数据,仅考虑主要国籍。使用 GitHub 上的 coco converter 库和 Demonym CSV 文件完成国家转换。世界地图上的国籍计数已经使用对数重新缩放进行了规范化。一些国籍已从数据集中删除,因为在世界地图上绘图所需的 ISO ALPHA 3 代码不再支持它们。这导致南斯拉夫人和科普特人等民族被删除,威尔士人和苏格兰人被添加到英国类别下,美洲土著人被添加到美国类别下——这是一行简单的代码,具有复杂的含义,在讨论中简要提及。

性别基于性别元数据(男性/女性/非二元/未定义),仅考虑主要性别。

语言和图书馆

主要使用 Python 和熊猫完成数据格式化和清理。数据可视化依靠 Plotly 、 Plotly Express 和 Dash 在 HTML 页面上显示图形。

作者图片

谢谢你

如果你读到这里,谢谢你和我一起阅读!我很想听听您对这些见解的看法,是否以及如何使用它们,以及您是否有任何建议让我改进未来(数据)项目的方法。

最佳数据分析

原文:https://towardsdatascience.com/data-analysis-at-its-finest-69b8624ae988?source=collection_archive---------30-----------------------

一个能让你更喜欢 R 的例子

美国传统巧克力在 Unsplash 上拍摄的照片

Python 和 R 是数据科学生态系统中的主流语言。它们都提供了大量的库来执行有效的数据争论和分析。

说到数据分析,熊猫一直是我的首选。然而,我觉得我的一些偏好可能会因为 R 包的出色功能而改变。

在本文中,我们将使用 R 包完成一个稍微复杂的任务。我会一步步讲解,让每一步的操作都清晰明了。最后,您将看到每个步骤是如何组合在一起,在一大步中完成任务的。

值得注意的是,同样的操作也可以在熊猫身上进行。事实上,我也将提供熊猫代码,这样你就有机会做一个比较。

我们将使用 Kaggle 上网飞数据集的一部分。我们从导入库和读取数据集开始。

library(data.table)
library(stringr)netflix <- fread(
   "~/Downloads/netflix_titles.csv", select = c("type", "title", 
   "date_added", "duration", "release_year", "country")
)head(netflix)

(图片由作者提供)

该数据集包含网飞电视节目和电影的一些特征,例如类型、长度、国家等等。

任务是找到电影中平均电影长度排名前 5 的国家。作为一个附加条件,我想筛选出少于 10 个标题的国家。

第一步是创建一个包含电影长度(以分钟为单位)的列。我们可以通过从 duration 列中提取数字部分来获得它。

netflix$duration_qty <- as.numeric(str_split_fixed(netflix$duration, " ", 2)[,1])

我们使用 stringr 包的 str_split_fixed 函数来拆分空格字符处的值。然后我们用 as.numeric 函数将第一部分转换成一个数字。

下一步是过滤电影标题,因为我们对电视节目不感兴趣。使用 data.table 包进行过滤可以按如下方式进行:

netflix[type == "Movie"]

平均电影长度可以按如下方式计算:

netflix[
   type == "Movie", 
   .(avg_length = mean(duration_qty)
]

但是,我们希望分别计算国家/地区列中每个类别的平均电影长度。此任务涉及“分组依据”操作。我们可以使用 by 参数来实现它。

netflix[
   type == "Movie", 
   .(avg_length = mean(duration_qty), 
   by = "country"
]

因为我们想过滤掉电影数量少于 10 部的国家,所以我们需要一个变量来保存数量信息。这可以通过添加 count (N)函数来轻松实现。

netflix[
   type == "Movie", 
   .(avg_length = mean(duration_qty, .N), 
   by = "country"
]

该任务的剩余部分是:

  • 过滤少于 10 部电影的国家
  • 按照电影平均长度降序排列国家
  • 选择前 5 个
[N>10]                                       # filter
[order(avg_length, decreasing = TRUE)]       # sort
[1:5]                                        # select

我们现在可以将每个步骤合并到一个操作中。

netflix[, duration_qty := as.numeric(str_split_fixed(netflix$duration, " ", 2)[,1])][type == "Movie", .(avg_length = mean(duration_qty), .N), by='country'][N>10][order(avg_length, decreasing = TRUE)][1:5]

(图片由作者提供)

下面是如何用 pandas 完成相同的任务(首先需要导入 Pandas 并将数据集读入 dataframe)。

netflix["duration_qty"] = netflix.duration.str.split(" ")\
.str.get(0).astype('int')netflix[netflix["type"] == "Movie"].groupby("country")\
.agg(avg_length = ("duration_qty", "mean"), 
     N = ('duration_qty', 'count'))\
.query("N > 10")\
.sort_values(by="avg_length", ascending=False)[:5]

(图片由作者提供)

结论

Pandas 和 data.table 库都允许链接多个操作。因此,我们可以将一个复杂的任务分解成几个小步骤,然后将它们组合起来。这种模块化还提供了很大的灵活性,我认为这对于某些数据争论任务非常重要。

这两个库都非常强大,能够成功完成高度复杂的操作。因此,您可以选择其中任何一个来进行数据争论和分析过程。

尽管我使用 Pandas 的次数更多,但 data.table 的语法似乎更吸引我。

感谢您的阅读。如果您有任何反馈,请告诉我。

数据分析初学者:Python 让它变得简单

原文:https://towardsdatascience.com/data-analysis-beginners-python-makes-it-easy-70c98d43d621?source=collection_archive---------38-----------------------

电子表格到 PYTHON

在这个系列中, 【电子表格到 Python】, 我探索了 Python 数据分析的许多乐趣和好处,并鼓励读者自己尝试一下。

照片由 Hitesh Choudhary 在 Unsplash 上拍摄

现在是做数据分析师的大好时机。只需点击一个按钮,就有如此多的数据可供分析,因此获取知识和产生影响的机会是无限的。

我们用来管理和分析这些数据的技术可以让这项任务变得令人生畏或令人愉快。

与电子表格相比,使用代码的一大优势是从大型数据集中可靠地提取信息非常容易。这里,我们将生成代码,可重复地对不同的数据子集执行计算,以产生有趣的比较。

在电子表格中这样做需要手动操作,这可能会引入错误。

因为代码是立即可见的,所以另一个用户很容易看到发生了什么并检查它是否正确;在电子表格中,对于所有的输出,这必须一个单元格一个单元格、一个标签一个标签地进行。

我一生都是板球爱好者,板球爱好者喜欢统计数据。我也喜欢 Python,所以我决定在这个练习中将两者结合起来。

我将向您展示如何使用 Python 从数据集中提取信息,并进一步了解英格兰最优秀的击球手之一:Joe Root。

除了查看他的职业生涯统计数据,我们还会看到鲁特的击球率如何取决于他在哪里打球、不同的对手、比赛中的时间等因素。

虽然使用的数据只有 200 行和 11 列,但是使用的方法很容易扩展。

因为大部分工作是重复的,我们将编写一个简短的函数来可靠地提取我们想要的数据,这使得一切变得更加整洁。

让我们加载一些数据

首先,我们需要打开一个 Python 环境。我使用 Filament ,它允许我为博客组合文本和代码,也便于与同事分享反馈。

我已经编译了一个 csv 文件,其中包含鲁特最近一次测试赛之前的击球数据,那次测试赛是在 9 月初,对手是印度。这复制了一个非常常见的情况:我们有一个 csv 文件,我们需要选择如何查看和分析它包含的数据。让我们用 Python 中的熊猫来看看这是如何工作的。

第一步是加载我们稍后需要的模块。

现在我将读取 csv 文件,

这给了我:

作者图片

为了清楚起见,我没有包括上图中的所有线条。

接下来,几乎总是这样,我们需要做一点数据操作。乔·鲁特主要扮演击球手,我们对他的击球率感兴趣。计算方法是将得分的总次数除以他出局的次数。然而,有时他完成一局“没有出局”。这在Dismissal栏中显示,在Runs中用*表示。这些分数计入得分,但不计入出局数。

我需要一种简单的方法来计算出局数。为此,我将创建一个新列Out,如果他不在,用 1 表示,如果不在,用 0 表示。我还将创建一个新列Runs 2,仅包含数字数据,即没有*。

让我们来看看实际情况。

作者图片

检查一些总体统计数据以确保操作正确是有用的。

这给出:总局数= 200;总运行次数= 9278;不 Out = 15 高分= 254;职业生涯平均= 50.15;总世纪数= 23。

快速浏览一下互联网就可以确认这些价值。

在进行更详细的分析之前,让我们来看一些关键数据:跑步、职业平均和最近平均。

作者图片

用 Python 制作吸引人的图形真的很容易。在这里,我们看到了鲁特在前 120 局的出色记录,随后在接下来的 50 局左右的时间里有所下降,最近又恢复了状态。

让我们编写一些代码来探索这些数据

现在,我想更深入地研究这些数据。我们来看看鲁特对不同对手的平均水平。我对代码做了一些注释,以显示正在发生的事情。

作者图片

抛开孟加拉国和爱尔兰,鲁特总共只打了 6 局,我们看到他对印度和斯里兰卡的平均水平特别高,可能是因为他对旋转保龄球的众所周知的实力,而对澳大利亚和新西兰的平均水平比其他人低得多。

太酷了。现在我想试着看看他在比赛中不同局的击球记录(对于非板球爱好者来说,比赛有 4 局,在正常情况下,每个队都在 1 和 3 或 2 和 4 中击球)。

看起来我们会经常使用上面的代码。让我们定义一个函数,它允许我们选择要比较的变量,并输出相关的平均值。这实际上只是将前面的代码转换成函数的一个例子,但是我也缩短了变量名。

检查这个函数是否给出与上面相同的结果可能是个好主意。我们按如下方式调用函数:

作者图片

👍

让我们使用我们的新代码

现在计算鲁特在不同局比赛中的平均得分变得非常简单。这很有趣,因为它表明他在比赛的第二局击球时的平均得分比第一局或第三局高得多,而在第四局却很低。也许鲁特(和英格兰)不喜欢追一个总。

作者图片

一个板球队有 11 名队员,每人轮流击球。公认的击球手通常在 1-6 号位打球,鲁特占据了所有的位置,更喜欢在 4 号位打球,尽管正如我们在下面看到的,他的最佳位置实际上是 5 号位。

作者图片

现在我们有了一个函数,很容易对原始表中所有不同的列标题运行它,但是我不打算在这里这样做(我已经这样做了,结果在下面的附录中)。

相反,让我们看看现在比较不同国家的记录有多容易。鲁特在对阵印度和澳大利亚的比赛中打了几乎相同的几局,但平均得分却大相径庭。

我们可以快速生成数据帧,其中只包含与这两个国家比赛的信息。

现在,我们的函数可以用于这些新数据帧中的每一个,以提取 Root 相对于它们的性能的更详细的比较。为了证明这一点,下面是他在不同局比赛中的平均得分比较:

乔·鲁特对印度的平均得分——作者图片

乔·鲁特对澳大利亚的平均得分——图片由作者提供

和几个世纪的比较:

世纪 v 印度= 8;世纪对澳大利亚= 3。

在 Python 中进行这种分析的便利之处在于,我们可以使用这些函数快速探索我们想要的数据的任何其他方面。

结论

就 cricket 而言,我可能没有赢得您的支持,但是我希望我已经说明了 Python 中的数据分析是多么简单和有用。

使用代码允许我们从原始 csv 文件中提取信息,并根据这些信息进行计算。很容易定义一个函数来做我们想要做的事情,然后使用该函数来探索不同因素或变量对结果的影响。在电子表格中这样做需要耗时的手工操作。

最后,因为我们不是在与原始数据相同的文件中工作,所以我们不必担心意外地改变某些东西——分析中的所有步骤都是可重复的。

所有这些代码都可以很容易地用于更大数量的数据,这在电子表格中会更麻烦,如果文件可以打开的话。甚至还有一个库,Dask,用于处理大量的数据。

我希望这篇文章展示了使用 Python 来探索数据是多么容易,并启发您亲自尝试一下。关于其他例子,请查看我的最新的“电子表格到 Python”文章。

这篇文章的文本、代码和图像是使用Filament创建的,这是一个用于数据、分析和报告的一体化工作空间。如需了解更多信息,请访问我们的网站http://www.filament.so/。Filament 目前正在运行一个封闭的测试程序;前 100 名使用推荐代码 TDSFILAMENT 请求访问的人可以跳过等候名单,提前获得访问权限。

感谢邦妮·塞勒斯·维勒斯基和尤安·维勒斯基

保持联系

  • 关注我在媒体上的更多类似的故事
  • 在 LinkedIn 上连接

附录——一些更有趣的记录

国内还是海外

作者图片

如何解散

作者图片

地面

作者图片

让你脱颖而出的数据分析实践

原文:https://towardsdatascience.com/data-analysis-best-practices-d4f5b3d8e222?source=collection_archive---------19-----------------------

并非所有的云都与数据有关,但导航可能同样困难。(作者供图)

到目前为止,数据分析是业务和技术中最常见的任务之一。它是成千上万的学术研究人员、银行家、工程师和数据科学家的日常面包。有趣的是,尽管这是一项如此受欢迎的活动,但对于什么应该是黄金标准似乎还没有达成一致。没错,比如说,将客户调查分析与强子对撞机的实验结果进行比较,至少是很难的。同样真实的是,在这两种情况下,人们可以看出这个过程进行得好还是不好。

在本文中,我将重点介绍如何进行良好的数据分析过程。作为底线,我们将把自己限制在那些证明使用编程方法是正确的情况下,从而留下“excel 工程”或准备好的仪表板。

我将与你分享一些建议——这些建议在我过去十年在 R&D 的职业生涯中一直对我有效。虽然这篇文章绝不是主张设定黄金标准。我相信你很快会读到的提示会为你节省很多时间。

保持冷静,分析数据

数据分析是一项探索性很强的工作。不像在软件开发中,很少有人能给你写一份精确的“待办事项”清单。更多的时候,你面对的是一个已经定义好的问题和一系列需要检查的愿望或假设。找到正确的见解可能需要几个小时,或者几个星期。这取决于许多因素,如数据质量、潜在问题的复杂性、来回沟通的需要以及您的技术技能。这是一个耗费脑力的过程,有许多不确定因素,包括选择合适的问题来提问。

因为分析是一个调查过程,没有一个明确定义的假设就期望成功是幼稚的。除非它是任务描述的一部分,否则制定它是你的工作。正是形成它的过程会让你的注意力集中,让你的时间更有效率。如果你的分析主题是复杂的,你甚至可能想要制定一整套假设。不管你怎么做,都要保持工作的系统性。把假设变成你的征服计划,记住,消极的结果仍然是结果!

消灭,消灭,消灭

我提到过这是一个精神消耗的过程吗?我敢打赌,如果你还能理解晚上的运动,你就没有在工作……数字和小数对你大脑的影响绝对是一场灾难。因此,如果仔细检查数据并消除任何潜在的冗余信息,至少可以引入某种程度的保护。我知道找出哪些信息可能是重复的或多余的可能很有挑战性,但是你应该试一试。只要有可能,就在更小的数据集上工作,消除任何你能很快证明是不相关的东西。

我通常的做法是区分我分析的几个阶段。当我处于某个阶段时,我不会让我的大脑从事与其他步骤相关的工作。例如,当我获取数据时,我不会过多地关注它。我甚至没有试图阐述观察!当我清理数据时,我只专注于使我的数据集一致,包括删除不必要的列,处理丢失的值等。总结性的观察时,我依赖于自己早期的作品,放下了更多的“工程的一面”。

所有这些,我更喜欢在单独的笔记本(或脚本)中完成,如果我不得不重新处理一个问题,我会返回到更早的阶段。这个过程反映了最小化数据集和最小化工作范围。俗话说“一次做一件事”。

再现性取代了稳健性

软件工程师关注健壮性。他们必须这样做,因为他们交付的代码是要在生产中使用的。一旦部署,它就成为一种数字产品或服务。因此,他们开发了各种方法和工具,如同行评审、单元测试、集成测试、版本控制、linters、CI-pipelines 等。帮助他们开发可靠的软件。

数据分析代码很少在生产中使用。它的可靠性定义与数值结果的再现性更有关系。大多数情况下,这样的代码是一次性的,永远不会被维护。更糟糕的是,即使是在一个单一的任务中,分析代码也可能很快失去控制并自我吞噬。在单元测试上投入时间很难证明是合理的,当讨论洞察力而不是性能问题时,同行评审似乎更有意义(有例外)。在这种情况下,确保再现性是一项挑战。

有时,数据分析任务会作为其他人过去所做工作的延续而开始。当这种情况发生时,至少有两个理由让你变得暴躁:

  • “他/她做这个或展示那个的时候(到底)是什么意思?”
  • “我该如何运行这一部分?

第一个问题与分析的方式有关。一个做得不好的分析会显示不完整的片段或死代码,这是失败尝试的结果。它会用许多没有意义的彩色情节把画面弄得乱七八糟。最后,评论和观察,如果有的话,会陈述明显的事实而不解释推理背后的意图。即使重复所有的步骤,也很可能得出不同的结论。

第二个问题是一个更“工程化”的问题。代码就是代码,要运行它,你应该复制它被创建的环境。分析代码倾向于快速漂移。因此,捕获、冻结和归档所有的依赖关系非常重要——除非您想要启动一个计划外的黑客马拉松。

不要让事情变得不必要的困难

系统化的工作、减少精神负担和尊重可再现性还不能定义一个过程,特别是当这个过程在不同的场景下看起来非常不同的时候。然而,将正确的重点放在诸如形成工作假设、分阶段工作和清晰性等事情上有助于创建良好的实践。

下面,我列出了一些你可以改进的建议——我希望我能早点知道的事情:

  • 指出什么是草稿,什么是干净的报告。这与使用 git 不同,因为通常情况下,您可能希望保留草稿。记住数据分析的本质是记录你的推理。因此,试着从多余的信息中剥离出来,或者至少给你的同事一个提示,哪些部分不是关键结果。
  • 优先考虑代码的清晰性而不是性能。如果您的某些代码需要很长时间才能运行,可以考虑将它转移到一个单独的脚本中。
  • 不要害怕使用注释或减价,尤其是当代码没有直接传达这些见解的时候。
  • 让笔记本无条件流动。很多时候,人们只会看着它们来学习结果,而不会去执行它们。脚本级别的一些“if-else”语句会很快模糊画面。
  • 提交前重新生成笔记本。Git 不知道你的名称空间中的变量。因此,重启笔记本可能有助于避免突然出现的“名字错误”。
  • 用图来传达数据,而不是自我。这个世界充满了提供看起来很漂亮的情节的包。更重要的是,你要注意坐标轴和图例上的单位和标签,而不是嵌入吸引人的小部件。如果一个排序的表格显示了你想要的,甚至不要为图表费心。
  • 写一个简短的自述文件来讨论内容和如何运行代码总是受欢迎的。
  • 在数据上放置断言也没有错。我急切地把它们放在笔记本的开头,尤其是在有更广泛计算的部分之前。
  • 使用随机数生成器时使用“种子”。
  • 展示你的过程中表格的“头”,最好是在之前和之后。这有助于理解处理过程,而不必执行它。

最后的想法

我知道数据分析并不适合所有人。这是一种精神消耗…哦,等等…我提到过。这需要耐心和直觉,而且很难达成一个标准化的流程。然而,正如我所展示的,你可以采取一些行动让它不那么痛苦,更有成就感。

我相信,你可以想出更多的方法来加强这项活动。无论如何,我在这里给出的列表是可扩展的。请不要害羞,在评论中分享你的想法吧!

初学者的数据分析

原文:https://towardsdatascience.com/data-analysis-for-beginners-90a8d53fa2f9?source=collection_archive---------20-----------------------

卢卡斯·布拉塞克在 Unsplash 上的照片

在过去的六个月左右的时间里,我决定尝试学习一些 python 来进行数据分析。目标是什么?我猜是技能培养。我喜欢学习新的东西,作为一名工程学本科生,我认为 python 将是开始学习如何编码的一个好地方。我喜欢人工智能用于医疗保健和机器学习的想法,所以我在这里,试图学习 python。我的主要问题是,我还没有真正开始我自己的项目。去年假期,我尝试了“代码 2020 挑战的来临”,但只坚持了几天。我的尝试对起床来说毫无意义,最终我放弃了,因为我的实习责任对我来说有点太多了,我无法兼顾一切。我一直在 DataCamp 上学习数据科学课程,虽然我喜欢它给我的结构,但我发现它的数据集/项目并不令人鼓舞。我经常为了练习而完成它们,但是我自己懒得去研究任何东西。

然而,在过去的一年里,一些事情促使我开始摆弄我的第一个数据集。一月初在爱尔兰有了 lockdowns insight,没有迹象表明我会回到大学(我们上网),我发现我有很多空闲时间比平时跑得更多。几乎每天,我都会出去跑 5 公里,目的是保持健康,保持身材,希望最终能跑 20 分钟以下(到目前为止我还没有做到)。我有点认真地对待我的 Strava 账户,并报名参加了每月 100 公里的跑步。不过,我遇到的一个问题是,Strava 希望我支付额外费用来获得一些漂亮的图表和分析。订阅不会发生。我是一名学生,可能是为数不多的没有音乐流媒体服务的年轻人之一,因为我无法将预算拉长那么多。这让我开始思考,为什么我不自己把数据倒出来,做一些漂亮的图表呢?原来 Strava 有一个可爱的方法可以将你的数据下载到 csv 文件中,作为一个初学 python 的程序员,我知道如何使用它。这篇文章是关于六个月的小数据集。在这个过程中,我希望你能学到一些关于 Python、pandas 和 plotting 的知识,也许它会启发你找到自己的数据集来探索和提取一些有意义和令人兴奋的信息。

  1. 但是首先,我们要上几堂课

那些了解 pandas 和 matplotlib 基础知识的人可以跳过,也许我会放一些 gif 来吸引你的注意力,让你在数据分析开始时停下来。也许不会,这是我第一次写作,我不知道我会做什么。对于其他人,我将使用这个小模块来解释熊猫和 matplotlib 的基础知识。我希望这篇文章能让初学者学到一些东西,同时让你体验一下如何使用网上的数据集。我将把这个简短的课程分成三个部分,python,pandas 和 matplotlib。python 部分会很短,如果有人想上 Python 的课,我可以写一篇全新的文章,请告诉我!

1.1 Python

那么 Python 是什么呢?或者为什么要为此烦恼呢?嗯,我不是计算机科学家,但是学了一点 MATLAB 和 Java,我可以有把握地说 Python 是最容易学的编程语言之一。幸运的是,它是最常见的编程语言之一,并得到了数据科学界的大力支持。如果没有 python,我将无法使用像 pandas 和 matplotlib 这样的工具,并且将不得不依靠其他编程语言来完成某些任务。它有它的缺点,但是对于一个初学编程语言和数据科学的人来说,它是理想的。举个简单的例子,看看这个:

用 Java 打印“Hello World ”:

System.out.println('Hello World')

用 Python 打印“Hello World ”:

print('Hello World')

我们中的大多数人都有可能同意,其中一段代码比另一段更直观。再说一遍,我不是计算机科学家,但我是一名工程师,我需要最有效的工具来完成这项工作。(此外,我认为我遗漏了一些 Java 代码的公共静态 void。已经有一段时间了,请不要对我大喊大叫。)

1.2 只熊猫

数据科学家传统上使用 R,一种为统计软件和数据分析而构建的编程语言。我喜欢。它肯定能完成任务。但是随着 Python 拥有了更多的读者,Wes McKinney 开始用 Python 实现 R 的数据框架。他建立了熊猫图书馆,因此数据科学能够接触到更多的人。使用 pandas,我们能够创建、操作和显示表格数据。在很大程度上,它看起来像一个 excel 电子表格,有列、行和许多函数来改变它们之间的一切。它的力量来自于你,来自于用户,来自于你对数据的任何操作方式。

我们有多种方法来创建自己的自定义数据框架,其中一种方法如下所示:

它将输出以下内容:

每列有三行数据,每一行数据都有各自的条目。这些条目可能是空的,真/假值,浮点数,地址,任何东西。关于码箱,我先从import pandas as pd说起。Pandas 不会自动内置到 python 中。没有那行代码,我将无法执行任何熊猫的命令。我可以毫无问题地把它们打出来,但是当我试图运行代码时,我会得到一个错误。as pd部分只是让我给熊猫取个小一点的名字。在上面的例子中,我使用了一个字典来创建数据帧。每个键是列名,每个值是该列的行中的条目。为什么要创建这样的数据帧?好吧,如果你在课堂上为一个项目收集一些列和行的数据,并且你更喜欢 pandas 的灵活性和 matplotlib 的图表而不是 Excel,那么手动创建一个像上面这样的小数据框架可能是值得的。

但是,通常您会将数据存储在硬盘上的其他地方,您会想要导入这些数据。您将在下面看到如何做到这一点。

1.3 Matplotlib

Python 没有绘制和显示数据的固有方法。Matplotlib 帮助我们解决了这个问题。让我们看一个例子:

同样,我必须导入相关的库。然后,我用plt.subplots()创建了一个图形和一个轴。一旦创建,我可以创建任何类型的情节,我能想到的。这里我使用了.plot(),它给出了一个线形图,但我也可以使用.scatter().hist()分别给出散点图或柱状图。然后我调用plt.show()来显示这个图。

2。数据探索

在投入之前,我认为最好从几个目标开始。当我开始查看数据并探索 Strava 会给我的任何东西时,一些东西可能会引起我的兴趣,但如果我们开始时心中有一些东西,至少我们不会挣扎着开始。因为我大概每个月跑一次,脑子里一直想着 100k,所以我想每个月都比较一下。Strava 给了我跑步记录,但不允许我按月/周/星期几过滤。我还想知道我每个月的平均时间/距离是多少。我开始跑 5 公里,然后慢慢增加到 10 公里,在 6 月份,我跑了 3 次半程马拉松。也许我可以说明距离的增加?我的总时间增加了吗?让我们把这些都记下来。

  • 每月距离/跑步次数。
  • 距离是急剧增加还是逐渐增加?
  • 距离/时间/月份图表。

剩下的部分有望更多地基于代码。必要时,我会对代码块进行注释。我不会分解每一行,但希望探索数据集的信息会变得清晰。

2.1 导入、清洗、初始观察

我下载的数据有多份。csv 文件。csv 代表逗号分隔值,是处理数据时最常见的文件类型之一。使用pd.read_csv后跟我保存的文件路径,我可以将我的数据保存到strava_df

为了确保我的数据涵盖 2021 年前六个月,我可以使用.head().tail()方法来查看我的数据集的顶部和底部。

.head慨然:

并且.tail给出:

输出自动为五行。列被切成两半,因为太多了,无法显示(有 79 列,大部分是空白的)。如你所见,我的数据集的第一条记录日期是 2020 年 1 月 4 日至 2021 年 7 月 18 日。只要我在这段时间内上传一个活动到 Strava,他们就会出现。我要清理数据的第一件事就是删除所有不重要的列。我可以使用pd.drop()函数来完成这项工作,但是如果我想将数据保存在数据帧的开头(日期、时间、距离),我更喜欢使用pd.loc[],因为它允许我对数据进行子集化。它的基本用例是使用下面的约定访问数据pd.loc[row_A:row_Z,column_A:column_Z]``:表示我想要中间的所有内容,,区分行和列。现在,我想保留每一行,删除“距离”之后的每一列。

对此调用.head()显示我们更新的 strava_df 数据帧:

接下来,我希望我的数据集只包含我的跑步。Strava 自动正确保存每个活动,但我有时会编辑活动,并将跑步标记为“锻炼”或“比赛”。让我们检查并查看“活动类型”列中保存了哪些类型的数据。

我的输出显示了五种活动类型。我将过滤掉“骑行”、“徒步旅行”、“游泳”,然后检查“跑步”和“锻炼”的最大值,以确保我的周期没有被错误标记。

第 1 行根据两个条件过滤数据帧。如果“活动类型”是“跑步”或“锻炼”,我们保留它,如果不是,我们忽略它。执行这段代码给出了一个跑步被标记为锻炼的例子。因为是在 2020 年,我们不需要转换类型,因为我们将忽略 2021 年之前的数据。为了进一步清理数据,让我们删除“Name”、“Type”和“Description”列,因为我们的目标不需要它们(axis = 1告诉 pandas 查看列表的列[_____]而不是行)。

然后将以秒为单位的时间转换为以分钟为单位的时间:

现在,下一个任务将是过滤 2021 年记录的活动的所有行(并最终以每天和每月为基础拆分它们)。有几种方法可以实现这一点,所有这些方法都需要将“活动日期”列中的每一项转换为 datetime 对象:

第一行将每个行条目转换为 datetime 对象,接下来的三行提取日、月和年数据,并将其放入自己单独的列中,如下所示:

作为个人偏好,我将重新排列列顺序:

这将提供:

包括所有数据,我们有 128 条记录要处理,但是我们需要在 2020 年删除所有值。这就容易多了,因为现在有一个只有年度信息的栏目。

并删除 7 月份的数据:

这就是导入和清理的大部分内容。我们有 102 行可以从中提取信息,表中列出了我们需要的变量。

我可以创建四个数据帧来存储我的最长和最短运行/时间的行信息:

每个块中的第一行(第 1、4、7、10 行)隔离数据帧中最大值.max()或最小值.min()的行。分别打印这些变量给了我存放这些变量的索引。然后,我可以使用.rename()函数将索引值更改为自定义值。然后,第 13 行使用pd.concat()将所有四个数据帧连接在一起。

我们可以使用熊猫内置的带有字符串格式的统计函数来给出一些关于距离和时间的有意义的信息(其他函数包括.mean(), .std(), .var())

最后,在我们绘制任何图表之前,让我们看看每个月和每个星期的数据分布情况:

使用.groupby()功能,我们可以按月对“运行时间”和“距离”列进行分组。然后,使用.agg()函数,我们可以对数据应用sumcount函数。6 月份跑了 15 次,总距离 149.78 km(三次半程马拉松帮忙)。另一方面,我在 4 月份跑了 17 次,只跑了 105.38 公里。这看起来像是解决的第一个目标!

在这个阶段,我们还可以做更多的事情。我们可以遍历每一天的值,并用它们来确定一周的值。使用它我们可以创建相似的表。我们也可以用跑步时间来划分距离,以确定每次跑步的速度,并观察其随时间的变化。但是为了让事情简单明了,我想是时候看看这些数据了。

2.2 数据可视化

我知道我想要的主图。我想要一个散点图,x 轴上是距离,y 轴上是经过的时间,也许还有一种方法可以告诉我们每个数据点属于哪个月。

使用 matplotlib,我们应该能够相当容易地实现这一点:

好吧,那是相当无趣的。如何才能提高?嗯,我们可以使用plt.style.use()很容易地改变图形的样式。此外,我们希望能够使用colorlabel参数来增强图形(剧透:不会那么容易)。

如果我添加color参数,并说出我想要映射到绘图的六种颜色,我会收到一个错误:

我需要一个有 94 种颜色值的列表。显然,我不会仔细检查数据框中的每一项,并为每个月输入一种颜色。相反,我们可以创建一个简单的循环:

这段代码将遍历strava_df[month]中的每一行,并为每个月的列表添加一种特定的颜色col_list。现在,让c等于col_list,我们应该得到一个合适的颜色渐变来代表每个月。此外,我们可以把风格改得更好一点。我将使用流行数据科学网站的fivethirtyeight样式。

让我们快速使用一些数据帧子集来删除所有大于 20 的值(允许我们删除右上角的数据点,以避免中间的大间隙):

离最终产品越来越近了。然而,就其现状而言,它是相当静态的。我对一个接一个的月份没有太多印象。也许我们可以制作一个动画,首先绘制一月份的数据,然后绘制二月份的数据,以此类推。虽然上面的一切都是针对初学者的,应该足够容易理解和跟随,但接下来的一点可能有点困难。然而,这是一个明显的例子,说明用 python 对数据分析进行硬编码比传统的图形/数据分析包更有优势。

首先我会列几个清单。我在这上面花了一段时间,发现更新图例和竖线来显示每月的数据以及每月的平均距离和速度太难了。反而通过题目来说明就容易多了。第一个循环将数据帧分成六个月,提取步速,并将整数值附加到pace_avg。第二个循环将pace_avg中的每个步速转换为一个字符串,并在它的末尾添加“km”。现在,进入动画情节。

让我们来分析一下。首先我们需要从 matplotlib 导入 FuncAnimation 包,和 numpy(数值包,类似 MATLAB 的东西)。然后,我们初始化图形大小、轴限制、标题和轴标签。

对于 FuncAnimation,我们需要创建一个animate函数,本质上就是我们想要制作的动画。FuncAnimation 需要几个参数,即它需要一个动画人物和一个动画循环来绘制。我们的动画循环首先更新绘图的标题以反映绘制的月份和步调(因此出现了上面的循环),然后循环通过strava_df以提取DistanceElapsed Time数据。这被标绘出来,限制被控制,同时颜色用scat.set_color()更新。最后,使用数字fig、函数animate在七个独立的帧上调用FuncAnimation,每帧之间有 1000 毫秒。使用plt.show(),我们得到以下结果:

似乎直到六月我的步伐都在加快。我认为,上个月上升的原因是由于一些间歇时段,我从来没有暂停我的手表,所以它记录了我在间歇之间行走。否则,我认为我们已经创建了一个相当好的图表,显示了我所希望的。

3。结论

大多数人建议你应该选择一个项目,然后通过工作来学习编码。一旦你习惯了文档,简单的东西就唾手可得了,在线资源可以帮助你完成工作中比较复杂的部分。我总是发现这个建议很难接受。我喜欢有条理的节目。但我发现,许多结构化课程并没有给你提供太多的学习机会。他们引入一个话题,让你做几个问题,然后继续。通常在一个模块结束时,所有的材料都会在一个稍微大一点的更连贯的问题中进行测试,但仅此而已。对于任何学习 Python 的人来说,找到一些小项目来测试你所学到的东西以巩固这些经验是很重要的。我的只是碰巧是一个方便的数据集,我从一个我不愿意支付额外费用访问的网站上得到的。

如果这里有任何不清楚的地方,或者你想详细说明,请告诉我。我很乐意帮忙。此外,如果对 Python、Pandas、Numpy、Matplotlib 和数据分析的完整教程感兴趣,我很乐意写下来,请告诉我!上面用来输出所有代码的链接都可以在这里找到https://github.com/DillM94/Strava/blob/main/Strava_Data_Jan-Jun.ipynb

如何:市场营销中的数据分析

原文:https://towardsdatascience.com/data-analysis-in-marketing-2334f29ee685?source=collection_archive---------29-----------------------

营销和销售领域的分析入门示例

在 Unsplash 上 Merakist 拍摄的照片

无论您是数据科学家、分析师还是业务分析师,了解各个部门的实际工作都很有用。他们的目标是什么,他们是如何直接或间接挣到钱的,如何衡量成功?它帮助我了解了各个部门的关键数字。这使我能够以更有针对性的方式帮助该部门,最重要的是,除了这些标准 KPI 之外,我还可以获得进一步的分析。我想解释一下这些 KPI 中的一些,以及如何获得它们的数据。

市场分析

为了给公司创造销售机会和做出销售决策,以下关键数据非常重要。最重要的关键数字之一是市场份额。计算方法如下:

用公司自己的市场份额除以总市场份额

虽然这是最重要的关键数字之一,但当然很难计算。在这里,你可能不得不求助于像 statista [1]或类似的资源。但是,如果您已经找到了整个市场的销售额,例如,您可以借助内部数据(如 ERP 系统)来近似计算您自己的市场份额。

照片由艾萨克·史密斯在 Unsplash 拍摄

当然,这同样适用于销售增长。这里,路径是相同的,但是是在一段时间内测量的。

销售关键数字

销售当然是一个非常重要的工具。毕竟,这是产生营业额的地方。还有一些常用的 KPI 来衡量销售的成功与否。比如优惠的成功与否。这是通过以下方式计算的:

报价成功=收到的订单数/提交的报价数

另一个很好的指标是取消率的计算:

取消率=取消订单/订单总值

要衡量营销活动的成功,您可以计算广告的成功度:

销售增长/广告成本

当然,这只是你可以应用在销售数据上的几种方法,但却是最有趣的一种。要深入探究,你可以从这里的开始。从哪里可以得到数据?如果你的公司使用 CRM 系统,这是一个不错的选择,但 ERP 或订单管理系统也可能是你正在寻找的资源。

在线营销 KPI

随着营销变得越来越数字化,从系统中提取关键数据成为可能。以下是一些例子:

  • 每个销售线索的成本
  • 订单价值—购物车的平均价值是多少?
  • 点击率—您的内容是否得到了您想要的关注?
  • 转化时间:访客转化速度有多快?
  • 网站的平均访问时间等。

虽然大多数数字通常已经由较新的系统(如在线商店软件)生成,或者可以从数据库中提取,但 KPI(如每线索成本)将有点难以计算,因为您还需要所用资源的成本,在这里,ERP 系统和财务模块可能是一个可行的起点。你可以从这篇文章中得到如何提取和分析财务数据的启示。

照片由米利安·杰西耶在 Unsplash 拍摄

结论

当然,这些只是少数可能的分析。作为一名数据科学家或分析师,为了理解营销领域,尤其是为了开发可能的新方法,记住它们当然是有帮助的。

资料来源和进一步阅读

[1] statista,搜索市场份额统计数据 (2021)

[2] Lucidchart,
你的计划是什么?销售成功的 13 个最重要的 KPI

数据分析:护肤品成分不能预测产品价格

原文:https://towardsdatascience.com/data-analysis-ingredients-of-skincare-products-not-found-to-affect-product-price-c3593d123a4d?source=collection_archive---------23-----------------------

在这个项目中,我使用了机器学习算法的组合来测试成分在决定护肤品价格方面的信息含量。

图片来源:Diego Cervo / Getty Images

介绍

护肤品行业利润丰厚——2020 年全球化妆品护肤品市场预计为 1453 亿美元。

然而,护肤品公司如何给它们的产品定价似乎是一个严守的秘密。例如,一桶 16 盎司的海蓝之谜面霜在海蓝之谜官方网站上的价格为 2475 美元,而便宜得多的妮维雅霜的成分列表几乎相同。普通的是另一个因其实惠的护肤品和朴实无华的成分而变得非常受欢迎的品牌。与其他护肤公司相比,普通的能够通过最大限度地减少营销支出来降低成本,并且只使用已被证明有效的成分(如类视黄醇和维生素 C)。这就引出了一个问题— 当你购买护肤品时,你是为品牌和营销成本买单,还是为成分和配方买单?

当然,当大多数人在护肤上花了很多钱时,他们希望高质量的成分和配方能产生最好的效果。奢侈护肤品公司的利益在于延续这样一种理论,即更高的价格意味着更高质量的成分和性能。在本文中,我将使用 Scikit-Learn 中的各种机器学习算法来预测一个产品的价格。我的项目的第一部分是探索性的,比较在有和没有品牌信息的数据上训练的二元分类器,以预测产品是“便宜”还是“昂贵”。我的论文的第二部分试图构建多类分类器,将产品分为 4 个价格类别之一——“最便宜”、“便宜”、“昂贵”和“最昂贵”。

我假设在训练数据中包含产品成分列表不会使分类器表现更好,即产品的成分不会对其价格产生有意义的影响。

相反,我预计“品牌”将是预测产品价格的一个更具信息性的特征。

我在这个项目中使用的数据集是 Erin Ward 的“护肤品及其成分”数据集。

数据集详情

来自 LookFantastic.com 的护肤品数据集,包含 1138 种护肤品,包括它们的名称、网址、产品类型、成分和价格。

我的项目由 5 部分组成:

1)使用成分列表、产品数量(即内容)和产品类型的二元分类。

2)使用品牌、成分列表、产品数量和产品类型的二元分类。

3)使用品牌和产品类型的二元分类(没有关于产品数量或成分的任何信息)。

4)使用品牌、成分列表、产品数量和产品类型的多类分类。

5)使用品牌和产品类型的多类分类(没有关于产品数量或成分的任何信息)。

准备数据集

为了对数据进行预处理并为算法做准备,我首先将“price”列转换为浮点数列,去掉了“”符号。

df[‘price’] = df[‘price’].str.replace(‘£’, ‘’) 
df[‘price’] = df[‘price’].astype(float)

我还加了一个“品牌”栏,手动填写每个产品的品牌。然后,我添加了一个“contents”列,通过使用正则表达式从“product_name”中提取毫升、克或千克的数量,包含项目中产品的数量。例如,项目“Acorelle Pure Harvest Body 香水— 100ml”在“内容”列中的值为“100”(这个过程的限制将在我的“限制”一节中讨论。)

contents = [] 
**for** title **in** df[‘product_name’]: 
    **try**: 
       m = re.search(‘\d+(ml|g|kg)’, title)
       contents.append(m.group()) 
    **except** **AttributeError**: 
       contents.append(np.nan) 
df[‘contents’] = contents

不幸的是,“contents”列包含 155 个丢失的值,其中 regex 无法在“product_name”中找到产品数量。我手动搜索并在“内容”栏中填入体积量,以替换这些缺失的值。我决定创建这个“contents”列,因为如果成分列表有任何预测价值,那么这些成分的数量也会对产品价格产生影响。我将“品牌”、“内容”、“产品类型”和“成分”列作为我的数据集中的预测特征。

接下来,我从“内容”栏中删除了所有的“毫升”和“克”单位。然后,我将“内容”和“价格”列转换为浮点数。

skincare[‘contents’] = skincare[‘contents’].str.replace(‘ml’, ‘’) skincare[‘contents’] = skincare[‘contents’].str.replace(‘g’, ‘’)
skincare['contents'] = skincare['contents'].astype(float)
skincare['price'] = skincare['price'].astype(float)

这是准备好的数据集,准备好进行处理并输入算法:

成品数据框,包含产品名称、品牌、网址、产品类型、成分、价格(英镑)和内容

大多数产品都在 1 公斤以下,而这些产品中,大多数都集中在 100 公斤以下。产品价格和产品数量之间似乎没有什么关系。

如下图所示,绝大多数产品的价格都低于 50 英镑。

数据集中的平均价格在 24 左右。

护肤品数据集中的价格分布

在二元分类实验中,我根据上述四分位数范围定义了两种价格类别:“便宜”(类别 0,低于 18.90——数据集中一半的产品低于此价格)和“昂贵”(类别 1,高于 18.90——数据集中一半的产品高于此价格)。

skincare[‘price’] = skincare[“price”].apply(lambda x: 1 if x > 18.90 else 0)

诚然,这种区分是武断的。但是这一部分的目标仅仅是看看是否可以从预测“品牌”、“内容”、“产品类型”和“成分”的组合中获得任何关于价格的信息。

在多类分类实验中,我定义了 4 个价格类别:“最便宜”( 31.25),使用上面相同的四分位数范围,以获得每个类别中相同数量的产品(代码如下)。

def price_to_class(x):
   if x <= 9.950000:
      x = 0
   elif (x > 9.950000) and (x <= 18.900000):
      x = 1
   elif (x > 18.900000) and (x <= 31.250000):
      x = 2
   elif x > 31.250000: 
      x = 3
   return x
skincare['price'] = skincare["price"].apply(price_to_class

预处理

我使用了一个列转换器来准备要提供给算法的数据集。“product_type”有 14 个编码为字符串的唯一值,所以我在这个列上使用 OneHotEncoder()来获得相应的虚拟变量。我在包含数字数据的“contents”列上使用了 StandardScaler(),将列值集中在平均值 0 上,标准偏差为 1(在决策树的实验中没有使用 StandardScaler(),因为决策树不会从被缩放的特征中受益)。

最后,我在“配料”列上使用了 CountVectorizer()。我为“成分”列选择了 CountVectorizer(),因为如果测试集的“成分”列中出现了看不见的成分,那么对每种成分进行一次性编码会导致错误。CountVectorizer()简单地忽略了没有经过训练的词汇。

对于计数矢量器,我定义了一个定制的记号化器来删除数据集不必要的字符或假象,用逗号分隔(成分用逗号分隔,例如,“水,丁二醇,…”)。

def tokenizer(x) -> list: 
   x = x.replace('(', '')
   x = x.replace(')', '')
   x = x.replace('\xa0', '')
   x = x.replace('.', ', ')
   x = x.replace('&', ', ')
   x = re.split(', ', x)
   return x

这些转换器是使用函数 make_column_transformer()编译的。列转换器在流水线中与每个机器学习算法相结合。

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.compose import make_column_transformer

ohe = OneHotEncoder()
vect = CountVectorizer(tokenizer=lambda x: tokenizer(x))
scaler = StandardScaler()ct = make_column_transformer(
   (ohe, ['product_type']),
   (vect, 'ingredients'),
   (scaler, ['contents']), 
    remainder='passthrough')

价格类别的二元分类

在我实验的第一部分,我包括了除“品牌”之外的所有预测因素。也就是说,我使用了预测器“内容”、“产品类型”和“成分”,不包括“品牌”。在我实验的第二部分,我包括了所有的预测因素:“品牌”、“内容”、“产品类型”和“成分”。在实验的第三部分,我删除了所有关于产品成分和数量的信息。相反,我只使用了“品牌”和“产品类型”列。我怀疑“内容”并没有提供关于价格的有用信息。例如,普通的血清(30-50 毫升装)价格超过 30 欧元,而 1 升装的沐浴露价格仅为前者的一小部分。

在二元分类中,我测试了感知器、逻辑回归、决策树、K 近邻(KNN)和支持向量机(SVM)分类器的准确性。在预测产品的价格类别时,我还包括了三个集成学习模型,如投票分类器、bootstrap aggregation (bagging)和随机森林分类器。超参数调整是通过在逻辑回归、决策树、KNN、SVM 和随机森林分类器上进行随机网格搜索来执行的(GridSearchCV 非常慢,显然计算开销太大)。

随机网格搜索没有用于感知器、投票和 bagging 分类器。我选择给集合投票分类器 3 个性能最好的算法(所有算法都符合在对这些算法进行随机网格搜索期间获得的最佳超参数)。bagging 分类器使用决策树,这些决策树与在决策树分类器上随机网格搜索期间获得的最佳超参数相匹配。

二元分类结果及讨论

表 1。对于每个分类器,计算 10 倍交叉验证分数。这些 10 倍交叉验证分数如上所述。感知器、集成投票和 bagging 分类器不进行超参数调整,尽管 bagging 分类器的 n_estimators= 超参数被优化。每个实验迭代的最佳精度以黄色突出显示,以便查看。

平均而言,仅使用“品牌”和“产品类型”作为预测器的分类器表现最佳,平均分类器预测大约为 80.3%。当“成分”列被包括在内时,随机森林分类器表现最好,不管“品牌”是否存在。我怀疑当成分存在时,随机森林分类器表现最好,因为对成分列表进行矢量化会产生非常长的特征向量。在随机森林中,在树的每个节点上只能对 d 个特征进行采样而不进行替换,其中 d 的默认值= sqrt(特征数)。这可能有助于减少维数,并在处理极长的特征向量时减少过度拟合。

极长的特征向量也可能解释了当包括“成分”列时 KNN 的不良性能。特征空间可能非常稀疏,以至于相邻的数据点彼此相距太远,无法做出有意义的预测(即,数据集遭受维数灾难)。

平均而言,表现最好的模型是集合投票分类器,平均准确率约为 78.5%。这是有意义的,因为集成投票分类器是用三种性能最高的非集成机器学习算法(逻辑回归、SVM 和感知器)训练的,并通过多数投票进行预测。然而,当仅使用“品牌”和“产品 _ 类型”时,通过逻辑回归获得最佳准确度,准确度为 83.3%。总体而言,包括 SVM、逻辑回归和感知器在内的参数模型比包括 KNN 和决策树分类器在内的非参数模型表现更好。

价格类别的多级分类

我构建了多类分类器,将护肤品分为四类——“最便宜的”( 31.25)。我通过检查 price 列的内部四分位数范围,并将每个四分位数作为一个类别(代码如下)来获得这些数据。

def price_to_class(x):
   if x <= 9.950000:
      x = 0
   elif (x > 9.950000) and (x <= 18.900000):
      x = 1
   elif (x > 18.900000) and (x <= 31.250000):
      x = 2
   elif x > 31.250000: 
      x = 3
   return x
skincare['price'] = skincare["price"].apply(price_to_class)

这一部分的目标是看看是否可以通过预测因子“品牌”、“内容”、“产品类型”和“成分”的组合来预测特定的价格范围。

当我完成二元分类实验时,很明显“品牌”是价格类别的一个有用的预测指标。因此,在这一部分中,我使用所有的预测值进行了多类分类:“品牌”、“内容”、“产品类型”和“成分”。我将这些结果与涉及“品牌”和“产品类型”的多类分类进行了比较,没有包括产品成分或数量的信息。

在多类分类中,我测试了逻辑回归、决策树、K 近邻(KNN)和支持向量机(SVM)分类器的准确性。我还包括了同样的三个集成学习模型:投票分类器、引导聚合(bagging)和随机森林。

我没有包括感知器,因为让感知器适应多类标签很麻烦,而且可能不会产生好的结果。相反,我在逻辑回归和 SVM 中探索了不同的多类策略。决策树、K-最近邻、集合投票、引导聚集(使用决策树)和随机森林分类器不必被显式修改以适应多类标签。

在我的逻辑回归模型中,我使用了一对多分类。在 one-vs-rest 中,逻辑回归算法计算每个点相对于其他类属于某个类的概率。在多项逻辑回归中,标记的对数几率被预测。

在逻辑回归和支持向量机中,一对一策略是相同的,但是由于支持向量机不能自然地输出概率,所以我也在 SVM 分类器中使用了一对一策略。在一对一策略中,SVM 分类器将多类分类问题分成每对类一个二元分类问题(例如,“便宜”对“最贵”,“贵”对“最便宜”,等等)。).

通过在逻辑回归、决策树、KNN 和随机森林算法上的随机网格搜索来执行超参数调整。bagging 分类器用决策树来拟合,决策树具有用 RandomizedSearchCV()找到的优化的超参数,而投票分类器用具有优化的超参数的三个最佳执行算法来拟合。我没有对 SVM 分类器执行 RandomizedSearchCV(),因为 OneVsOneClassifier()和 OneVsRestClassifier()没有易于优化的超参数。

多类分类结果和讨论

表二。对于每个分类器,在执行随机网格搜索以优化分类器的超参数后,计算 10 倍交叉验证分数。这些 10 倍交叉验证分数报告如下。尽管 bagging 分类器的 n_estimators= 超参数得到了优化,但 SVM、集成投票和 bagging 分类器没有进行超参数调整。每个实验迭代的最佳精度以黄色突出显示,以便查看。

平均而言,仅使用“品牌”和“产品类型”作为预测器时,分类器的表现更好,平均分类器预测约为 59.3%。然而,这些结果与上一节中获得的中等准确度分数相比是令人沮丧的。

一种学习算法(在这种情况下是集合投票)的学习曲线的快速可视化可能会对这个问题有所帮助。

很明显,训练精度很高,标准偏差很小,而测试精度很低。由于训练和测试准确性之间存在很大差距,很明显,该模型的 at 存在很大的差异,这意味着需要降低模型的复杂性,或者需要收集更多的数据。

平均而言,表现最好的模型是集合投票分类器,平均准确率约为 59.6%。这是预料之中的,因为投票分类器是用三种性能最高的非集成机器学习算法训练的(在这种情况下,是一对一的逻辑回归、一对一的 SVM 和决策树分类器),并通过多数投票进行预测。KNN 再次表现最差,可能是因为即使没有“成分”一栏,特征空间也过于稀疏,无法对产品的具体价格范围做出有意义的预测。

实验限制

这个项目的实验设计有很多问题。最重要的问题之一是用 CountVectorizer()对成分及其名称进行编码。不同产品对相同成分的称呼也有所不同。例如,在一种产品中,一种成分被称为“香料”,而在另一种产品中,被称为“香水”。当应用 CountVectorizer()时,这些相同的成分将被分成两个不同的特征列,使得矩阵更加稀疏。由于不同的命名惯例甚至拼写,可能在不同的列中有数百个重复的成分——我对化学不够熟悉,无法捕捉这些冗余。在未来的实验中,应彻底研究成分名称,以寻找出现在数据集中其他产品成分列表中的同一产品的替代名称。配料表应该标准化,一种成分有一个成分名称,反之亦然。

这个实验的第二个问题是,训练和测试数据集没有按照品牌进行分层。数据集中有许多品牌仅由一种产品代表。由于 CountVectorizer()预处理步骤,如果这些产品中的一个出现在测试数据集中,模型将无法使用其品牌来预测价格类别。收集更多的数据可以解决数据集中只有一种产品代表的品牌问题。收集这些品牌的其他产品的数据将有助于模型对一个品牌的典型价格范围做出更多预测。

这个实验的第三个问题是配料清单中配料的顺序很重要。例如,如果“水”出现在成分列表的开头,这意味着该产品中的水比任何其他成分都多。成分列表末尾的成分在该产品中浓度最低。CountVectorizer()不保留关于成分顺序的信息,因此关于每种成分的相对量的信息会丢失。成分对价格影响的潜在洞察力因此变得模糊。将来,应该设计一个 CountVectorizer()来分割配料列表,记录列表中配料的索引,并用各自的索引填充特征列,以指示配料在列表中的位置。

这个实验的第四个问题是“内容”列。当我创建这个专栏时,我去掉了产品数量(比如 100 毫升,50 克,等等。)的单位(‘g’和‘ml’),并将它们视为相同的单位进行测量。克是质量的度量单位,毫升是体积的度量单位。1 克相当于 1 毫升的水,所以在这个实验中,我假设所有产品在去掉“ml”和“g”标签的时候,粘度都和水大致相同。当然,这是一个不准确的假设,但我没有获得每种产品的粘度测量值来进行克到毫升的转换。写这个专栏可能是个错误,在未来的实验中,它不应该被包括在内。

这个实验的第五个问题是,这个数据集不包含这些品牌在总体营销上花费的不同金额的信息。花在营销上的钱在产品的价格中得到补偿,所以营销预算影响产品的价格。我倾向于将“品牌”视为营销支出的代表,但即使在品牌内部,不同产品线的营销预算也可能存在差异。例如,一个品牌中的一个产品线可能比另一个更积极地营销——例如,欧莱雅拥有欧莱雅豪华产品线,其平均价格高于公司其他产品。因此,“品牌”不是营销预算的直接代表,因此也不是价格类别的理想预测指标。这个问题的解决方案是收集每个品牌和不同产品线的更多数据点。

结论

二分类器和多分类器的实验结果表明,品牌确实对价格有一定的预测作用。无论是否将品牌作为预测因素,用产品的成分列表预测价格的准确性都较差。在仅使用特征“产品类型”和“品牌”的二元分类器中实现了最好的准确度。然而,试图将产品分成具有相同特征的四个价格范围的多类分类器表现很差。由于模型无法执行更复杂的任务,如多类分类,很明显,需要额外的数据来使这些模型更加稳健。然而,这一粗略的分析表明,人们不应该认为高昂的价格意味着更高质量的护肤成分。

数据集和代码可以在我的 GitHub 中找到。

数据分析是软件工程的一种形式

原文:https://towardsdatascience.com/data-analysis-is-a-form-of-software-engineering-876232bd3ebc?source=collection_archive---------18-----------------------

对工具领域的思考,7 年来

当我在 2014 年开始对数据科学感到兴奋时,我同时也在学习如何编程。比如…不是如何从头开始编程 k-means ,比如如何在 Javascript 中画圆。

因此,我同时学习了多个技术概念:

照片由本·怀特在 Unsplash 上拍摄

从那以后,作为一名数据科学家,我收集了一些成功案例。但我最好的学习实际上来自于犯错误——编写低效的 Hive 查询,制作低精度或过度工程化的模型,对指标定义过于学术化,等待太久才向业务用户显示中间进度,等等。

我从数据科学起步时犯的最大的概念性错误之一是认为数据分析是一个与软件工程不同的、特殊的、不相交的领域。我要花几个小时来写报告——并起草!—我过去和现在对这个话题的看法。

如果你很忙,只有几分钟的时间,这篇文章的主旨是数据分析最佳实践/工具开始非常类似于软件工程的实践/工具并且这是一个我期望继续的趋势。

以下是我对这个主题的直观体验:

作者图片

如果你想有更多的导游,请随意阅读。

冒险的召唤

当我开始成为一名技术个人贡献者时,我害怕“真正的编程”——对我来说,这意味着:为 web/移动应用程序构建功能、运行/维护服务器、确保多个数据库副本的一致性、使用版本控制、发布😱拉取请求😱。我更喜欢“数据科学”或数据分析,它们与我的经济学本科学位共享许多熟悉的工具,如回归。

现在,我已经在美国/SEA 的多个组织从事数据科学方面的工作,处理不同的分析问题,当我回顾数据科学的概念时,我不禁感觉很像我想象的奥德修斯在与塞壬和其他神话生物战斗后返回伊萨卡时的感觉,或者佛罗多在毁灭火山炽热的深渊中摧毁一个戒指后返回夏尔时的感觉——一旦你开始了漫长的史诗般的旅程,你的家看起来永远不会一样了:

Mukuko 工作室在 Unsplash 拍摄的照片

也就是说,我知道软件工程和数据分析是同一条蛇的不同头部,它们有着千丝万缕的联系——具体来说,数据分析是软件工程的一个子集!我认为它在未来会与软件工程越来越多地重叠,现在我将更详细地描述它。

我过去的世界状态(大约 2014 年)

当我开始的时候,我基本上对这两个主题一无所知,虽然重建你以前的无知视角总是很困难,但我记得我的思维模式是这样的:

作者图片

软件工程对我来说基本上是一种魔法——它是编写驱动网站、移动应用等的代码。——我几乎没有任何理解。相比之下,数据分析,或“数据科学”,因为它最终成为品牌,是我可以理解的东西——它似乎需要挖掘用户行为模式,寻找趋势,建立模型来理解因果关系,等等。

尽管软件工程的工具是“真正的编码语言”,如 Java、Javascript、Ruby,但我认为数据科学使用的是“不太核心的语言”,如 SQL、Python 和 r。现在,作为一个什么都涉猎过的人,我意识到这种层次结构非常愚蠢,而且总是极度简化!

此外,我漫画中的一切都很小,因为软件刚刚开始吞噬世界而数据还不是新的石油。尽管我对数据科学(以及软件工程)感到兴奋,并且是一名从业者,但我仍然低估了短短 7 年内该领域会取得多少进步。

我当前的世界状态(2021)

以下是我目前对软件工程和数据分析的大致看法:

作者图片

也就是一些东西(构建 CRUD 移动网络/应用等)。)都是纯软件工程,有些东西是纯数据分析(和业务用户做度量定义等。).然而,它们的交集很大,而且还在增长。

这个十字路口发生了什么事?

这里发生了一些非常有趣的事情,让我们深入探讨一下吧!

全栈 ML 模型

大多数业务用户不想要黑盒模型——即使你可以凭经验证明它们有 98%的准确性。总有可能你的训练/测试划分不像你声称的那样具有普遍性,他们的行业中可能有一个模型可能没有发现的结构性转变,或者他们可能只是在总体上怀疑 ML。

进入全栈 ML 模型,其中模型的输入、预测、解释和置信度得分可以在熟悉的图形界面中呈现给决策者。如果你能允许用户在界面中纠正错误的预测,并把这些反馈到模型中,那就更好了。像 Streamlit 这样的工具使得机器学习开发者可以构建接口,而无需离开 Python 或过于担心部署。

作为代码的度量定义

当数据分析刚刚开始时,根本没有足够的时间来过多地担心统一单一来源的事实或版本化指标定义。它们只存在于一个地方可能是很常见的,所以为什么要担心这个呢?如果您想知道每周活跃用户的定义是什么,只需查看 2–3 报告仪表板中的底层 SQL 即可。

然而,现在 50 人、100 人或 500 人的分析团队和数百万美元的业务决策都是根据仪表盘和指标做出的,我们作为一个行业,意识到我们需要更加认真地对待这个问题。

如果定价数据科学家爱丽丝(Alice)制作了一个指示每周活跃用户的仪表板,而搜索数据科学家鲍勃(Bob)在 Python 笔记本中深入研究了一些也涉及每周活跃用户的新功能,那么这两件事的定义(在代码中)应该完全相同,以免随之而来的是完全的困惑、沮丧和信任危机。如果 Alice 和 Bob 来自不同的部门,甚至可能不共享工具集,情况会变得更糟。也就是“周活跃用户”必须变成weekly active users

大公司有集中的数据工程团队来解决这个问题,这需要多年的努力;对于那些拥有较小数据团队的人来说,一旦有了> 10 个人来创建和报告指标,最好还是使用像 dbt 这样的按座位付费工具。

更多

实际上,在这个领域还有很多其他的子主题,我只是刚刚开始探索。

一个是自动化数据质量测试。也就是说,当我们知道 80–90%的时间是数据质量问题而不是实际影响时,而不是等待业务用户去想为什么他的团队的 KPI 在一夜之间莫名其妙地飙升了 30%,将需要跨多种源类型工作的数据质量监控工具,与不同类型的数据库互操作,等等。我还没有发现一个开源产品或公司产品在这方面做得足够好,但我正在寻找!

数据版本控制也是一个有趣的概念,我的团队已经开始尝试。还没有达成共识,但它似乎是一个自然的工具,如果机器学习开发人员在同一个模型上工作超过几个月,并且不希望必须通过查看她过去的训练数据集的_v11_v12来找到一个具有良好或难忘结果的结果,则需要将其纳入机器学习开发人员的工具集。

摘要

软件工程实践越来越成为标准的数据分析实践。度量和数据版本化只是 SWE 已经使用了几十年的共享代码回购实践的概括,数据质量测试基本上只是特定于数据的单元测试和页面责任规范,现在已经在 SWE 的工作方式中长期确立。

我想我已经意识到了这一点,因为我变得不那么害怕“易碎的”软件工程问题,并且开始看到采用软件工程方法进行数据分析会产生更好和更可持续的结果。

未来数据工具前景(2028 年)

预测未来的唯一可靠方法是构建它,但是我将冒险对我所看到的数据工具前景进行一些粗略的猜测。我期望继续看到软件工程和数据分析领域的增长,但是随着更多的软件工程实践适应数据分析工作流。

或者视觉上:

作者图片

一切都变得更大,因为软件和数据对每个企业、每个垂直行业和每个行业都非常重要。但是还要注意,数据分析已经开始与软件工程有大约 65%的重叠!

在这个十字路口可能会发生什么?

让我们再放大一遍!

让摄入更容易?

像 Fivetran 和 Stitch 这样的低代码或无代码 ETL 托管服务肯定会继续构建更多的集成,变得更高性能,并最终降低它们的价格。在未来,对于没有现有现代数据仓库的企业(据我推测,在东南亚大约有 75–90%),您只需获得其最重要的 SaaS 数据源(如 Salesforce、Google Analytics 等)的凭证,就可以获得基本的启动和运行。).

这在今天已经有些可能了,但是根据我的经验,通常一个公司最重要的数据源(例如 POS 系统、 ERP 系统、设施、制造、交易系统)仍然要么在内部,要么还没有预先构建的、易于使用的连接器。因此,仍然有大量的数据工程工作要做,以便开始使用现代数据分析技术。我相信——也许是一厢情愿——这一时间的建立将在未来被记录下来。

更强大的可视化和探索工具?

就像 Craigslist 的许多子市场被分流到更具体、更有针对性的替代市场(如短期住房的 Airbnb,门票的 Stubhub),2021 年的 Jupyter 笔记本正在执行如此多的核心数据分析功能,我预计它也会被类似地“拆分”,尽管可能没有那么引人注目。

来源来自大卫·哈伯(经许可后重用)

特别是我找到的pandasmatplotlib等 Jupyter 笔记本流程。超级笨重的初始数据探索和清理阶段的数据工作。感觉自从我 7 年前进入这个行业以来,它没有得到有意义的改进。我越来越多地开始依赖更强大的数据可视化工具,如 Apache Superset 来完成这项工作,并且在未来,我预计这一领域将会激增。

此外,如果有人能够最终提出一个交互式的语义数据可视化工具(例如,“自从 YYYY 以来,X 类型用户的使用情况如何?”)实际上比一个优秀的数据分析师花 3-5 个小时的时间得出的结果更好(例如,这不仅仅是一个营销玩具),该产品将价值数十亿美元。有几种尝试,我不知道有什么真正的解决方案,但我会密切关注。

ML 作为黑箱?

随着越来越多基于 API 的微服务用于最常见的机器学习任务——如用于情感、实体提取、翻译的谷歌语言 API ,用于图像识别和分类的谷歌视觉 API ,用于通用语言模型的open ai——我相信会发生两件事。

首先,使用开箱即用的解决方案很容易获得良好的基准性能,因此构建定制、专门构建的机器学习模型的门槛将会越来越高。其次,更多的工作将集中在将多个模型的输出拼接在一起,并确保数据可靠地输入其中,而不是为单个任务开发高精度、高性能的模型。请注意,第一个是经典的机器学习开发流程,第二个更像是经典的数据/软件工程任务。

管道,到处都是管道?!

气流 Dag,克隆作业,云运行作业,SFTP 批量加载,卡夫卡主题。今天已经很乱了,7 年后会是什么样子?我的一个保证是,能够让这一团乱麻可靠地运行透明地运行轻松运行的数据工程工具和方法将继续是数据科学家工具箱中真正的 10 倍工具。面对糟糕的数据,最优雅的模型、可视化和洞察力都会崩溃。

谢谢

非常感谢你的阅读。我一直在寻找更多的工具来评估,并让我的团队去尝试。如果你有这里遗漏的最爱,或者你觉得某个领域没有被充分代表或者被错误描述,请通过 Twitter 或电子邮件联系nicholas.e.huber@gmail.com!

感谢 恩佐·安比尔 尼克·考 阅读此稿。

尽管我实际上无法这样描述它。

我甚至还没有开始学习 A/B 测试和产品实验的迷人的兔子洞。

我知道我说过商业用户不想要黑盒模型,但是这是关于开发人员的,大多数优秀的开发人员在他们的时间里都被请求淹没了,他们只会使用最好的工具来完成工作。

更多推荐阅读:

  • a16z 的现代数据基础设施前景帖子
  • 马特图尔克 2020 AI/ML 风景
  • 从技术角度分析您的数据团队使用的工具
  • Jackson Mohsenin 为 ML post 提供的接口

羽毛球评分系统变化的数据分析

原文:https://towardsdatascience.com/data-analysis-on-badminton-scoring-system-change-ef5bfcdc11cb?source=collection_archive---------19-----------------------

萨尔曼·侯赛因·赛义夫在 Unsplash 上的照片

如果提议的评分系统更改更早实施,过去的结果会是什么样的?

目录

  • 问题背景
  • 目标
  • 数据收集
  • 数据预处理
  • 数据可视化
  • 结论
  • 参考

泰勒:博士

  • 大约 70%的比赛可以在中场休息时结束(11 分)。
  • 在所有锦标赛类型中,比赛评估的组成大致相同。
  • 从“改变”的结果来看,中国受到的负面影响最大,而印度将受益最大,这从他们的净赢指数可以看出。
  • 提案的好处已经得到验证,但是即使是数据驱动的决策也需要与利益相关者进行适当的沟通才能成功。
  • 该项目的 Github 回购链接:此处

“如果缺乏与利益相关者的适当沟通,即使是最复杂的数据驱动决策也会失败。”

问题背景

最近,印度尼西亚羽毛球协会(PBSI)提交了一份提案,将现行的计分制度从 3x21 分制修改为 5x11 分制,尽管 3 年前世界羽毛球联合会(BWF)理事会提出了同样的提案,但遭到了拒绝[2]

这项提议引起了争议,运动员和官员对此反应不一。该提案的支持者(如印度尼西亚的亨德拉·塞蒂亚万[3])公开表示,新系统将使玩家受益,游戏时间更短,恢复更好,游戏质量更高。

相反,来自丹麦的 Victor Axelsen,5]强烈反对,因为他声称从未就该提议适当咨询过球员,并抱怨球员在投票上没有发言权,考虑到球员是受提议的改变直接影响的人,这是疯狂的。

尽管存在利弊,但我很想知道如果提议的评分系统早点实施,游戏会是什么样子,并希望更深入地调查这些论点,所以我决定深入研究我在 Kaggle 这里【1】找到的数据集。

目标

  • 用 11 分制评价比赛结果(比赛的胜负是在第 11 分而不是第 21 分决定的)。
  • 通过计算‘净赢’找出哪个国家受益最大。

数据收集

我使用的 Kaggle 数据集包含了每个学科从 2018 年 1 月到 2021 年 3 月的近 1.5 万场 BWF 世界巡回赛。

数据集为我提供了一些初始信息,我可以使用这些信息进一步进行分析,例如:

  • 锦标赛类型
  • 团队/个人国籍
  • 第 1、2 和 3 场比赛得分历史
  • 第 1、2 和 3 场比赛的分数为 21 分制
  • 第 1、2 和 3 场比赛的分数为 11 分制

数据预处理

为了达到目标,仍然需要一些预处理:

  • 确定 11 分和 21 分制的获胜者。
  • 决定获胜者的国籍。
  • 评估 11 分制的比赛结果。

匹配评估将有 3 种可能的结果:

  1. 未改变= 21 点和 11 点的结果相同(例如 21–15、21–16 和 11–5、11–6)
  2. 已更改= 21 点和 11 点的不同结果(例如 21–15、21–16 和 5–11、6–11)
  3. 不确定= 11 分制没有明确的结果(例如:21–15、21–16 和 11–5、6–11)。
  • 想象每个学科、每个锦标赛和所有比赛的每场比赛结果的比例。
  • 计算“净赢球变化”参数,该参数将不同国籍的比赛数据框进行子集划分,并计算如果实施 11 分制,哪些国家将赢得更多比赛。

数据可视化

大多数比赛不会受到影响

在评估了数据集中的所有比赛后,如果使用 11 分制,71.2 %的比赛结果没有变化,只有 11.3%的比赛结果会被推翻。

每场比赛评估结果的比例可以被视为平均分布在所有羽毛球项目和比赛类型中。那些支持这个提议的人的观点似乎是有效和准确的,因为我们可以看到游戏的大部分将在每个学科和锦标赛级别保持不变。如果实施这一改变,大约只有十分之一的匹配会有不同的结果。

谁从变革中获益,谁从中受损?

通过只分析“变化”的结果和不同国籍之间的比赛,我计算出“净赢变化”指数,这是 11 分制赢得的比赛数减去 21 分制赢得的比赛数的结果。请注意,我只使用了来自全国总共有超过 100 场比赛的数据来消除噪音。

中国将遭受最大的净损失,而另一方面,印度将从该提议中受益。与直觉相反的是,作为该提案的主要发起国,印度尼西亚将会有一个负面的净收益变化。

结论

  • 即使实行 11 分制,71.2%的比赛结果保持不变,只有 11.3%的人会改变。
  • 比赛结果评估的趋势平均分布在所有学科和锦标赛类型中。
  • 根据净收益指数,中国受负面影响最大,而印度受益最大。

2021 年 5 月 22 日,BWF 成员对该提案进行了投票,该提案仅差一票获得批准[4]。我发现的最令人震惊的事情是,玩家甚至没有权利或发言权来投票。

作为一名羽毛球爱好者,我希望未来球员可以有一个平台来表达他们的意见,特别是在技术问题上,这种变化会对他们产生直接影响。在我看来,如果缺乏与利益相关者的适当沟通,即使是最复杂的数据驱动决策也会失败。

也看看我的另一篇帖子吧!

https://juanliong.medium.com/epl-covid-19-data-analysis-a79ee0d75fe

参考

[1]桑德普。(2021).羽毛球国际羽联世界巡回赛数据集:https://www.kaggle.com/sanderp/badminton-bwf-world-tour

[2] VOI 编辑小组。(2021).PBSI 向 BWF 提交评分系统从 3x21 到 5x11 格式的修改:https://voi . id/en/sports/42398/pbsi-submitts-to-the-institution-of-of-the-score-to-bwf-From-3x 21 to-5x 11-format

[3]印度尼西亚有线电视新闻网。(2021).亨德拉·塞蒂亚万 Dukung Perubahan Sistem Skor di 羽毛球:https://www . cnnindonesia . com/olahraga/20210404192206-170-625855/hendra-setia wan-du kung-Perubahan-Sistem-Skor-di-羽毛球

[4]刘。(2021).5x11 计分系统差一票通过,维克托·阿萨尔森松了一口气:https://www . badmintonplanet . com/羽毛球-新闻/17453-5x 11-计分-系统-一票-害羞-批准. html

[5]柯伊杰姆 K &西蒂·鲁哈尼。(2021).阿克塞尔森一个月后收到 BWF 的回信,11×5 评分系统:https://360 羽毛球. com/news/axel sen-receives-a-reply-from-bwf-after-one-month-11×5-scoring-system/

健康护照推文的数据分析

原文:https://towardsdatascience.com/data-analysis-on-health-passport-tweets-6732660324f3?source=collection_archive---------26-----------------------

实践教程

通过自然语言处理和数据可视化,发现关于健康护照的推文必须告诉我们什么

来源

健康护照又称绿色护照、卫生护照或疫苗护照,是 2019 年开始的 【新冠肺炎】 的成果。健康护照在世界范围内引起了广泛的争议。当各国政府认为这是限制病毒传播的解决方案时,许多人和团体坚决反对,认为这是对人权的侵犯。因此,我决定在谈论健康护照的推特上训练我的数据分析技能,特别是自然语言处理(NLP)和数据可视化。

为了开始这个项目,创建一个 twitter 开发者帐户 并获取密钥和令牌以通过 twitter 检索数据是很重要的。本文不会详细讨论提取 tweets 的步骤;然而,值得一提的是,提取的推文只有英文,使用的搜索查询如下:

search_query = """ “vaccine passport” OR “vaccine pass” OR 
                   “pass sanitaire” OR “sanitary pass” OR 
                   “sanitary passport” OR “health pass” OR 
                   “covid passport” OR “covid pass” 
                   -filter:retweets -filter:media """

该 search_query 用于搜索包含一个或多个上述关键字的任何推文,不包括转发和媒体推文。

创建的数据集如下所示:

对于这个项目,我对以下三个栏目感兴趣:

  • user_location 栏——查看每个国家的推文数量
  • 日期——查看推文的日期
  • 文本——通过一元、二元和三元模型进行文本分析

日期分析

日期列的分析是一项相当简单的任务。为了验证推文的日期,使用以下代码行从日期列中删除了时间:

tweets['date'] = pd.to_datetime(tweets['date']).dt.date

然后,使用value _ counts()方法显示唯一日期的计数。

tweets['date'].value_counts()

输出:

位置分析

位置分析的目的是通过计算每个国家的推文数量来获得推文来源的总体概况。为了实现这一点,有必要对 user_location 列进行一些预处理。另外,matplotlib . py plotgeopandas 用于以饼状图和地理空间图的形式可视化结果。

预处理用户位置

预处理 user_location 列是从该列中找到的数据中提取国家名称的一项重要任务。

user_location 列中的一些数据没有任何意义,例如'莱昂内尔·梅西的奖杯室'和'你在哪里',因此,所做的第一步是删除任何不是位置的内容。这是通过使用 空间 库的命名实体识别实现的。

*# NLP* import spacy
nlp = spacy.load('en_core_web_sm')*# create a list of raw locations - i.e. locations entered by users* raw_locations = tweets.user_location.unique().tolist()*# replace nan by "" - the first element of the list is nan* raw_locations[0] = ""*# locations list will only include relevant locations* locations = []*# search for relevant locations and add them to the locations list* for loc in raw_locations:
  text = ""
  loc_ = nlp(loc)
  for ent in loc_.ents:
    if ent.label_ == "GPE":
      text = text + " " + ent.text
      locations.append(text)
    else:
      continue

上述代码用于删除所有在位置方面没有意义的内容;然而,user_location 列不仅包括国家名称,还包括城市和州,例如' London' 或' New York,NY '。因此,我决定使用 geopy 库从城市和州名中获取国名。

*# Geocoding Webservices* from geopy.geocoders import Nominatim*# NLP* import spacy
nlp = spacy.load('en_core_web_sm')*# Get the country name from cities' and states' names* countries = []for loc in locations:
  geolocator = Nominatim(user_agent = "geoapiExercises")
  location = geolocator.geocode(loc, timeout=10000)

  if location == None:
    countries.append(loc)
    continue

  location_ = nlp(location.address) if "," in location_.text:
 *# Example of a location_.text: "New York, United States"
    # get the name after the last ","*    countries.append(location_.text.split(",")[-1])
  else:
    countries.append(location.address)

为了显示国家名称,我使用了 np.unique() 方法。

np.unique(np.array(countries))

输出:

你可以明显地注意到,有些结果是用英语以外的语言显示的,有些是用“/”或“-”分隔的多种语言显示的。另外,一些结果仍然没有指示国家名称,例如'多伦多哈尔格萨'和'底特律拉斯维加斯'。我通过删除文本中的“/”和“-”来解决这些问题,并使用这些图标后的姓氏。我还用相关的国家名称手动替换了一些地名。最后,我使用了 googletrans 库,将非英文的国家名称自动翻译成英文。请注意,我保留了包含不同国家城市的位置(例如‘London Bxl Paris’))不变。以下是上述步骤的完整代码:

*# Translation*
from googletrans import Translator*# get the last name only when "/" or "-" is found 
# "/" and "-" separates names in different languages* countries = [country.split("/")[-1] for country in countries]
countries = [country.split("-")[-1] for country in countries]*# remove white space found at the beginning of a string*
countries = [country[1:] if country[0] == " " else country for country in countries]*# Manually replace locations to their relevant country name*
countries = ['United States' if country in 
                ["LA", "Detroit Las Vegas", "Atlanta Seattle"] 
                   else country for country in countries]countries = ['Canada' if country in
                ["Calgary Mohkinstis", "Calgary Mohkinstis Alberta"]
                   else country for country in countries]*# translate countries in foreign language to english*
translator = Translator()
countries = [translator.translate(country).text 
              for country in countries]print(len(countries))
print(np.unique(np.array(countries)))

输出:

不幸的是,仍然有一些国家的名称没有被正确翻译,因此,我不得不手动用它们的英文版本名称来替换它们。

*# for those that were not translated properly add them manually
# unknown to be added to others later: joke To L Poo l  ދިވެހިރާއްޖެ*countries = ['Germany'  if country == "Deutschland" 
               else country for country in countries]countries = ['Spain'  if country == "España" 
               else country for country in countries]countries = ['Iceland'  if country == "Ísland" 
               else country for country in countries]countries = ['Greece'  if country == "Ελλάς" 
               else country for country in countries]countries = ['Ukraine'  if country == "Україна" 
               else country for country in countries]countries = ['Iran'  if country == "ایران" 
               else country for country in countries]countries = ['Japan'  if country == "日本" 
               else country for country in countries]countries = ['Svizra'  if country == "Switzerland" 
               else country for country in countries]countries = ['Polska'  if country == "Poland" 
               else country for country in countries]countries = ["The Democratic People's Republic of Korea"  
               if country == "조선민주주의인민공화국" 
                 else country for country in countries]

最后,我创建了两个字典:1) countries_values 字典,它将所有国家的名称存储为键,将每个国家的推文数量存储为值;2)main _ countries字典,它存储推文数量最多的国家,并将所有其他国家归入名为【其他】的键。

from collections import Counter*# Use Counter to create a dictionary with all countries 
# and their equivalent number of tweets* countries_values = Counter(countries)*# Create dictionary of the countries having the most tweets 
# "others" key represent all other countries* main_countries = {'others': 0}
other_countries = []
for key, val in countries_values.items():
  if val >= 20:
    main_countries[key] = val
  else:
    main_countries["others"] += val
    other_countries.append(key)

使用 matplotlib.pyplot 和 geopandas 绘制结果

在预处理 user_location 列以获得作为国家名称的位置后,我决定使用matplotlib . py plotgeopandas 以地图和饼状图的形式显示结果。绘制饼图时,只需使用之前创建的字典‘main _ countries’即可。但是,要显示显示每个国家的 tweets 数量的地图,创建地理数据框是很重要的。

创建地理数据框架

创建地理数据框架的第一步是从存储每个国家的 iso_alpha3 代码的‘countries _ values’字典创建数据框架。 pycountry 库用于获取 iso 代码。

*# Library to get the iso codes of the countries* import pycountry*# create a DataFrame of country names and their codes* df_countries = pd.DataFrame()
df_countries["country_name"] = list(countries_values.keys())
df_countries["country_value"] = list(countries_values.values())def get_cntry_code(column):
  CODE=[]
  for country in column:
    try:
      code=pycountry.countries.get(name=country).alpha_3
 *# .alpha_3 means 3-letter country code
      # .alpha_2 means 2-letter country code* CODE.append(code)
    except:
      CODE.append('None')
  return CODE*# create a column for code* df_countries["country_code"] = 
  get_cntry_code(df_countries.country_name)df_countries.head()

第二步是使用 geopandas 库加载世界地理数据框架,如下所示:

*# Geospatial Data* import geopandasworld = geopandas.read_file(
  geopandas.datasets.get_path('naturalearth_lowres'))world

值得注意的是,一些国家的 iso_a3 被设置为-99,因此,我不得不手动更新代码,如下所示:

world.loc[world['name'] == 'France', 'iso_a3'] = 'FRA'
world.loc[world['name'] == 'Norway', 'iso_a3'] = 'NOR'
world.loc[world['name'] == 'N. Cyprus', 'iso_a3'] = 'CYP'
world.loc[world['name'] == 'Somaliland', 'iso_a3'] = 'SOM'
world.loc[world['name'] == 'Kosovo', 'iso_a3'] = 'RKS'

为了最终确定地理数据框架,世界地理数据框架和国家数据框架 (countries_df )被合并到“国家代码”(即“iso_a3”)。

*# rename columns to merge the DataFrames* world = world.rename(columns={"iso_a3": "country_code"})df_merged = pd.merge(world, df_countries, 
                      on="country_code", how='outer')*# fill empty value with zero
# any country with no tweet will have a value of 0* df_merged.country_value = df_merged.country_value.fillna(0)

绘制地图和饼状图

下面的代码显示了绘制地图和饼图的步骤。

*# Geospatial Data* import geopandas
*# Data Visualisation* import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatablefig = plt.figure(figsize=(15,10), facecolor='#eef3f8')ax1 = fig.add_axes([0, 0, 1, 1]) *# the map*
ax2 = fig.add_axes([0, 0.1, 0.2, 0.2]) *# the pie chart*divider = divider = make_axes_locatable(ax1)
cax = divider.append_axes("right", size="2%", pad=0) *# legend of map**### MAP ###* df_merged = df_merged[(df_merged.name != "Antarctica") & 
                       (df_merged.name != "Fr. S. Antarctic Lands")]df_merged.to_crs(epsg=4326, inplace=True)df_merged.plot(column='country_value', cmap='Greens', 
                linewidth=1.0, ax=ax1, edgecolor='0.8', 
                  legend=True, cax=cax)*# remove axis* ax1.axis('off')*# add a title of the map* font_t1 = {'fontsize':'20', 'fontweight':'bold', 'color':'#065535'}ax1.set_title('NUMBER OF TWEETS PER COUNTRY', 
                fontdict=font_t1, pad=24)*### PIE CHART ###* total = len(countries) *# 1241**# Sort the dictionary - this is only for the sake of visualisation* sorted_main_countries = dict(sorted(main_countries.items(),
                              key=lambda x: x[1]))*# get labels for pie chart* labels = list(sorted_main_countries.keys())*# get percentages for pie chart* percentages = [(val/total)*100 
                 for val in list(sorted_main_countries.values())]*# get theme colors to be coherent with that of the map's colors* theme = plt.get_cmap('Greens')
ax2.set_prop_cycle("color", [theme(1\. * i / len(percentages)) 
                              for i in range(len(percentages))])wedgeprops = {'linewidth':1, 'edgecolor':'white'}_, texts, autotexts = ax2.pie(percentages, labels=labels, 
                               labeldistance=1.1, autopct='%.0f%%',
                                 radius=1.8, wedgeprops=wedgeprops)*# set color for the autotext* for auto in autotexts:
  auto.set_color('black')*# set color of the labels* for text in texts:
  text.set_color('#909994') *# add a title for the pie chart* font_t2 = {'fontsize':'12', 'fontweight':'bold', 'color':'#065535'}ax2.set_title('Percent of Tweets by Country', fontdict=font_t2,
                pad=60, style='oblique')*# save figure* plt.savefig("no_of_tweets_per_country.png", 
              bbox_inches = 'tight', facecolor='#eef3f8')plt.show()

最终结果:

结果表明,大多数推文来自英语国家(美国、英国、加拿大、澳大利亚和南非)。这背后的原因可能是因为收集的推文只有英文。如果选择其他语言,结果可能会有所不同。法国是应用卫生通行证最严格的欧洲国家之一,反对“卫生通行证”概念的示威活动经常发生,这可以解释为什么法国在不是英语国家的情况下仍名列前茅。

文本分析

文本分析的重点是获取推文的一元词、二元词和三元词。单字通过世界云可视化,二元和三元显示在条形图上。这些都是通过应用 TF_IDF (词频-逆文档频率)实现的。我们的目标是一瞥推特中最常用的术语,因此,希望能帮助我们总体上理解推特用户的立场。

文本预处理

在获取一元词、二元词和三元词之前,进行文本预处理是很重要的。下面,我列出了预处理文本所采取的步骤以及本节末尾显示的完整代码

1-转换为小写

2-删除 URL

3-将俚语转换成它们原来的形式(为了实现这一点,我不得不抓取这个 网站——网页抓取的细节将不在本文中提及)

4-删除提及

5-删除标点符号

6-引理

7-删除停用词

8-去掉数字(表情符号翻译成数字。为了避免进入前 n 个字母的数字,我决定去掉数字。然而,人们可以决定保留它们并使用表情符号作为分析的一部分)

9-删除国家和城市的名字(为了避免国家或城市的名字出现在前 n 个字母中,我决定将它们从推文中删除)

文本预处理的全部代码:

*# NLP* import spacy
import regex as re
import stringnlp = spacy.load('en_core_web_sm')tweets["text_processed"] = ""*# convert to lower case* tweets["text_processed"] = tweets["text"].apply(lambda x:
                             str.lower(x))*# remove URL* tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             re.sub(
                              r"(?:\@|http?\://|https?\://|www)\S+",
                                  ' ', x))*# convert slang
# load slang dictionary* with open('slangdict.json') as json_file:
  slang_dict=json.load(json_file)for i in range(len(tweets["text_processed"])):
  txt = ""
  doc = nlp(tweets["text_processed"].iloc[i])

  for token in doc:
    if token.text in list(slang_dict.keys()):
      txt = txt + " " + slang_dict[token.text]
    else:
      txt = txt + " " + token.text
  tweets["text_processed"].iloc[i] = txt*# remove mentions* def remove_entities(text, entity_list): for separator in string.punctuation:
    if separator not in entity_list:
      text = text.replace(separator,' ')
  words = []
  for word in text.split():
    word = word.strip()
    if word:
      if word[0] not in entity_list:
        words.append(word) return ' '.join(words)tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             remove_entities(x, ["@"]))*# remove punctuation* tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             re.sub(r'[^\w\s]',' ', x))*# lemmatize* def lemmatize(sentence): doc = nlp(sentence) *# tokenize the text and produce a Doc Object*
  lemmas = [token.lemma_ for token in doc]

  return " ".join(lemmas)tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             lemmatize(x))*# remove stopwords* def remove_stopwords(sentence): doc = nlp(sentence) *# tokenize the text and produce a Doc Object* all_stopwords = nlp.Defaults.stop_words
  doc_tokens = [token.text for token in doc]
  tokens_without_sw = [word for word in doc_tokens 
                        if not word in all_stopwords]

  return " ".join(tokens_without_sw)tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             remove_stopwords(x))*# remove -PRON- a result of lemmatization* tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             re.sub('-PRON-', " ", x))*# remove numbers* tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             re.sub(r'[0-9]', " ", x))*# remove country and city names* def remove_country_city(sentence): doc = nlp(sentence) return (" ".join([ent.text for ent in doc if not ent.ent_type_]))tweets["text_processed"] = tweets["text_processed"].apply(lambda x:
                             remove_country_city(x) 
                               if pd.isna(x) != True else x)

从单字创建词云

如下所示,我决定创建一个世界云来显示推文中最突出的单词。我通过使用TfidfVectorizer实现了这一点,其中默认的 ngram_range 是(1,1),意思是 unigram。

from PIL import Image
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
import matplotlib.pyplot as plt
from wordcloud import WordCloudvectorizor = TfidfVectorizer(stop_words='english')
vecs = vectorizor.fit_transform(tweets.text_processed)
feature_names = vectorizor.get_feature_names()
dense = vecs.todense()
l = dense.tolist()
df = pd.DataFrame(l, columns=feature_names)*# mask is the image used to reshape the cloud* mask = np.array(Image.open('./images/syringe44_.jpeg'))word_cloud = WordCloud(collocations=False, background_color='white',
                         max_words=200, width=3000,
                           height=2000, colormap='viridis',
                             mask=mask).generate_from_frequencies(
                                                   df.T.sum(axis=1))plt.figure(figsize=[15,10])
plt.imshow(word_cloud)
plt.axis("off")
plt.show()word_cloud.to_file("tfidf_ps_word_cloud.png")

词云:

不出所料,【护照】【疫苗】【接种】【通行证】【covid】等词汇非常丰富。这很正常,因为这是推文的主题;此外,提取 tweets 时的搜索查询集中在这些关键字上。然而,如果我们更仔细地观察单词 cloud,我们可以注意到对进一步分析有用的其他感兴趣的单词,如‘抗议’【停止】【强制】【拒绝】【正确】【强制】

在 Unigrams 中,每个单词的出现被认为是独立于它前面的那个单词的,这并不总是使它成为文本分析的最佳选择。因此,我决定进一步检查二元模型和三元模型,看看它们是否能提供更多的见解。

获取并可视化二元模型和三元模型

获取一元模型、二元模型和三元模型的步骤非常相似。唯一需要更新的参数是TfidfVectorizer中的 ngram_range,其中对于单个字符,它是(1,1)(默认值),对于双字符,它是(2,2),对于三字符,它是(3,3)。

from sklearn.feature_extraction.text import TfidfVectorizer*# bigrams* vectorizor = TfidfVectorizer(stop_words='english', 
                              ngram_range =(2, 2))vecs = vectorizor.fit_transform(tweets.text_processed)
feature_names = vectorizor.get_feature_names()
dense = vecs.todense()
l = dense.tolist()
df = pd.DataFrame(l, columns=feature_names)n_grams = df.T.sum(axis=1).sort_values(ascending=False)n_grams.to_csv("bigrams.csv")

我用一个条形图来显示前 100 个二元模型和三元模型。matplotlib . py plotseaborn 库对于这种可视化是必不可少的。以下是可视化数据的代码示例:

*# read bigram dataset* bigrams = pd.read_csv("bigrams.csv")*# Data Visualization* import matplotlib.pyplot as plt
import seaborn as sns*# plot bar graph* plt.figure(figsize=(10,20))
sns.barplot(x = bigrams[:101].value , y=bigrams[:101].bigram)
sns.despine(top=True, right=True, left=False, bottom=False)
plt.xlabel("Value", 
             fontdict={'fontsize':'12', 'fontweight':'bold'})
plt.ylabel("Bigrams", 
             fontdict={'fontsize':'12', 'fontweight':'bold'})plt.title("Top 100 Bigrams", 
            fontdict={'fontsize':'16', 'fontweight':'bold'})plt.savefig("Top 100 Bigrams.png", bbox_inches='tight')

结果:

就像世界云的情况一样,在第一排有诸如、【covid pass】、、【健康通行证】、这样的术语是很容易理解的。然而,如果我们进一步观察,我们可以发现其他可能对分析有用的二元和三元模型。例如,一些有趣的二元模型可能是【群体免疫】【通过抗议者】【假疫苗】【杀死人群】【传播病毒】【完全接种】。然而,感兴趣的三元模型可能是‘真正的威胁人物’‘反疫苗护照’。也就是说,需要更深入的分析才能得出准确的结论。此外,我建议不要局限于前 100 个二元和三元语法,而要对 n 元语法进行情感分析。**

在这篇文章中,我解释了对谈论健康护照的推文进行数据分析的步骤。为了实现这个项目,使用了几种自然语言处理技术,例如命名实体识别、文本预处理和通过单字、双字和三字的文本分析。此外,结果以饼图、地理空间图、条形图和世界云的形式通过数据可视化显示。

OTT 平台上的数据分析:我应该选择哪种服务?

原文:https://towardsdatascience.com/data-analysis-on-ott-platforms-which-service-should-i-choose-8eed953ff7d2?source=collection_archive---------1-----------------------

通过数据分析解决 OTT 平台选择困境的尝试

我们消费视频的方式已经发生了巨大的变化。现在,我们有多个 OTT 平台,如网飞、亚马逊 Prime Video 和 Disney+来在线播放电视节目和电影。随着信息的过剩和多种标准来比较各种 OTT 平台,用户越来越难以找到最适合他们口味的产品。通过这项研究,我们调查了不同的 OTT 平台数据集,为用户提供对每个平台的洞察,以确定订阅哪些服务。在影响在线流媒体订阅的多个因素中,我们主要使用 Spark 和 Hive 分析了年龄、流派和基因组标签。

我们发现网飞和亚马逊 Prime 视频有很多相似之处。他们有相似的标签和类型分布。两个平台之间的区别因素是年龄组。网飞有最多的电视电影,而亚马逊 Prime Video 有最多的电视电影。毫无疑问,迪士尼+最适合动画。每个 OTT 平台都有自己鲜明的特点。

以下内容由三位作者撰写:
克里斯·全
郑秀霞
容祖里克·金

介绍

2019 年,OTT 市场价值 851.6 亿美元,预计到 2025 年将达到 1942.0 亿美元。在新冠肺炎治下,许多国家推出了社交距离措施,迫使影院限制观众数量甚至关闭,并鼓励人们呆在家里,加速了 OTT 平台订阅量的增长。因此,我们认为现在是分析不同的 OTT 平台并为无法决定哪个平台最适合他们的人提供有用信息的时候了。

这项研究分析了三个主要的 OTT 平台——网飞、亚马逊 Prime 和迪士尼+。除了每个平台的电影数据集,我们还整合了两个额外的数据集:IMDb 电影数据集,用于调查电影类型的分布、年龄限制及其平均评级;以及 MovieLens 数据集,用于评估标签基因组,以找到代表每个平台的最受欢迎的标签。

Reddy 等人对基于内容过滤的推荐系统的研究表明,电影元数据,特别是类型和评级,是预测用户未来可能想看什么的关键决定因素。然而,我们发现仅考虑这两个因素还不足以详细描述 OTT 平台中内容的多样性。例如,仅基于流派和评级的推荐系统无法满足喜欢视觉上吸引人的内容或基于真实故事的内容的用户的需求。为了更深入地研究内容的属性,我们研究了 MovieLens 提供的基因组标签数据集,该数据集使用机器学习算法对用户贡献的内容(如标签评级和文本评论)进行测试,测量了一部电影展示标签所代表的特定属性的强烈程度。增加对基因组标签的分析有助于我们了解每个平台有什么样的内容属性。

架构设计图

分析所需的所有数据集都被纳入了 Hadoop HDFS。每个 OTT 平台数据都在 Hive 和 Spark 中经过广泛的数据清洗和特征提取,以创建统一的最终模式。我们分析了 Spark 中的年龄、流派、标签基因组,使用我们制作的公共基础模式。输出数据被写回 HDFS。

在下一节中,我们将详细说明我们进行这项研究的动机,并介绍一些有助于更好地了解该领域研究现状的相关研究。然后,我们描述了用于研究的数据集:网飞、亚马逊 Prime 和迪士尼+的内容列表;IMDb 评分和流派分类;电影分级和标签。我们解释了清理和处理数据的过程,以使其适合于分析。最后,我们展示了使用上述数据集所做的分析。

动机

近年来,各种 OTT 平台的出现引入了一个新颖的问题:难以选择订阅哪个 OTT 平台。网飞、亚马逊 Prime 和 Disney+是公众熟知的众多 OTT 服务中的一部分,但随着 Watcha(韩国)和 Voot(印度)等本地化 OTT 平台加入该行列,服务的数量正在增长。

随着这些平台提出新的方式,通过呈现原创内容在竞争对手中脱颖而出,很明显,更多的客户在决定哪个平台适合他们使用时会迷失。此外,大多数可用的推荐系统都专注于推荐内容,而不是保存和提供这些内容的平台。为了缓解选择困境,我们的研究旨在为选择符合个人偏好的适当 OTT 平台提供指导。

数据集

总的来说,这项研究使用了三组数据集:网飞、亚马逊 Prime 和迪士尼+的内容列表;IMDb 评分和流派分类;电影分级和基因组标签。每个平台的内容列表被用作分析的基础。但是,由于它们都是从不同的来源收集的,所以它们的最后更新时间和列类型并不一致。因此,为了简化分析过程并使结果更加可靠,我们必须将数据清理成相同的形式,并将它们与包含年龄限制、评级和流派等一致信息的其他数据集合并。

其中包括 IMDb 和 MovieLens 数据集。尽管每个平台数据都包含关于流派和 IMDb 评分的信息,但它们是根据不同的分类进行标记的,并在不同的时间进行更新,因此需要对流派和评分使用单独的数据。最重要的是,我们使用 MovieLens 数据来加强我们的分析。由于我们没有预先存在的研究来证实我们的发现,我们决定对两个不同的数据进行类似的分析。MovieLens 有自己的评级和标签数据,这使它成为 IMDb 评级和流派的合适对比。我们假设从这两个来源得到相似的结果会加强我们分析的有效性。

网飞

网飞内容数据集由截至 2019 年网飞上可用的电视节目和电影组成,包括标题和 12 列在内共有 7788 行。这些列包括放映 id、类型、标题、导演、演员、国家、添加日期、发行年份、评级、持续时间、列出日期和描述,但是仅使用了类型、标题、发行年份、评级和持续时间。

网飞原始电影数据集包含 525 行(包括标题)和 48 列,我们在研究中只使用了标题和上映日期。

***亚马逊 Prime 视频 ***

亚马逊 Prime 视频数据集总共包含 8128 行和 7 列。这些列包括标题、语言、IMDb 评级、运行时间、发行年份、成熟度评级和情节。最后,我们只使用了这七列中的四列。

为了区分原始电影和数据集,我们从维基百科搜集了一份原始电影列表。这包含 52 行和 3 列;这些列是发布日期、标题和注释。

迪士尼+

迪士尼+数据集包含与我们的研究无关的电影和电视剧数据。它总共有 992 行和 19 列,包括标题、情节、类型、导演和流派,但只有 imdb_id、标题、类型、发行时间和评级用于我们的目的。

我们还使用了一份从维基百科上搜集的原创电影列表。该数据包含 56 行,以标题、类型、发行日期和运行时间为列。但大部分是 2020 年以后发布的,不能用于研究。

T5【IMDb】T6

从 IMDb ,我们使用了title.basics.tsv.gztitle.ratings.tsv.gz数据集。

**title.basics.tsv.gz包含 IMDb ID、标题、起始年份、运行时间和流派等列。,但我们只使用了数据中的 IMDb ID、标题和流派。标题是合并平台数据和 IMDb 的关键。我们保留了 IMDb ID,因为当它用作密钥时,可以更容易地将评级数据合并到平台数据中。

**顾名思义,title.ratings.tsv.gz用于检索评级数据。它包含 IMDb ID、平均评分和许多投票,我们使用了前两列。

MovieLens 是 GroupLens 运营的一个网站,独立收集用户的评分和标签信息。幸运的是, link.csv 包含了将 IMDb ID 链接到 MovieLens ID 的信息,这使得我们可以方便地将 MovieLens 数据与我们现有的数据帧相结合。不像 IMDb 的数据已经汇总了每部电影的平均评分和分类类型,MovieLens 的数据有单独的评分和标签,必须由我们汇总。

在 MovieLens 中,总共有 1128 个标签,每部电影的每个标签的分数从 0 到 1 不等。越接近 1,电影就越与标签相关。由于有如此多的电影和标签对,我们只过滤得分超过 0.8 的对,通过反复试验来决定。

分析

实验主要包括两个步骤:预处理和分析。预处理是这个项目的一个重要步骤,因为所有的数据来自不同的来源。在开始分析之前,必须克服一些困难,比如消除同名电影的歧义,以及合并不同的年龄分级系统。

在对源数据集进行预处理后,我们探索了不同的平台如何关注针对不同年龄和类型偏好的特定受众的内容。

预处理

表 1。用于分析的公共基础架构

由于网飞、Amazon Prime 和 Disney+的基础电影数据集的模式不同,我们经历了多个清理阶段,并将数据转换为一个通用的基础模式(表 1)。

首先,我们清理了我们的源数据集——电影数据集和原始电影数据集,使用 Hadoop 过滤掉不相关的列并更改列格式。例如,对于网飞,我们必须将发布日期从字符串中的“dd-mm-yyyy”转换为整数形式的“yyyy ”,并过滤掉“持续时间”值中的多余字符。然后,通过 Spark,我们为每个平台创建了一个 dataframe,其中包含合并的数据集,并有一个“is_original”列来表示原始电影。最后,将数据框架与 IMDb 数据集(IMDb 数据集—基本和评级,通过过滤掉具有空“运行时”值的行并将“运行时”值转换为整数来清理)合并,以创建跨平台的通用模式。对于 Amazon Prime,在清理之后,Hive 用于连接原始、非原始和 IMDb 数据集,以创建没有流派的基础模式。然后,Spark 被用于添加流派列,并最终确定分析的公共基础架构。

使用具有共同基础模式的数据框架分析年龄组和流派。为了对基因组标签进行分析,我们使用“imdb_id”字段作为关键字,通过将公共基础架构与 MovieLens 数据集合并,为每个平台创建了另一个数据框架。

IMDb 年龄组分析

首先,我们根据 IMDb 的年龄组数据,分析了每个平台的主要目标年龄组。由于不同的内容使用不同的年龄分级系统,因此很难汇总这些信息。因此,排除一些类别,如批准和通过,我们将使用电影协会电影分级系统标记的电影转换为电视家长指南中的相应类别,这是更精细的分类。

图一。OTT 平台的年龄组计数。图片作者。

图二。作者对 OTT 平台图片的年龄组平均评分。

从图 1 中,我们注意到网飞有大量的电影被划分为电视-MA 级,适合成年观众观看,并且不适合 17 岁以下的儿童观看。它几乎没有适合所有年龄层的电视 G 级电影。它有大约 900 部适合 14 岁及以上青少年观看的电影。亚马逊 Prime 在年龄评级方面分布均衡。分类为 All、TV-PG(父母指导推荐)和 TV-MA 的电影数量大致相同。最后,虽然由于整体电影数量较少而不太引人注目,但 Disney+没有标记为 TV-MA 的内容和少量分级为 TV-14 的电影。所有其他电影都被分级为 TV-PG 或 TV-G,无论有没有父母的指导,孩子们都可以观看。

截至评级(图 2),不同年龄组之间没有太大差异。迪士尼+的平均评分似乎更高。然而,大多数评级范围从 6 到 7,狭窄的范围表明消费者应该更关注每个年龄组的内容数量分布而不是评级。

IMDb 体裁分析

图 3。OTT 平台的类型计数和平均评级。图片作者。

一般来说,网飞和亚马逊 Prime 在类型上有相似的分布;戏剧占了最大的比例,其次是喜剧和动作片。然而,网飞在几乎所有类型中都有更多的内容,亚马逊 prime 仅在动作和爱情电影方面明显超过网飞。此外,网飞有 500 多部纪录片,而亚马逊 Prime 几乎没有。

迪士尼+呈现出最具特色的分布。然而,与其他两个相比,它的内容数量要少得多,这可能是一个强大的推动因素。观察分布的形状仍然很重要,因为它预示着未来会发生什么。迪士尼+显然似乎专注于家庭、喜剧、冒险和动画电影。它也有一些动作,戏剧,纪录片和幻想电影,但几乎没有其他类型的电影。喜欢各种流派的人可能要避开迪士尼+。

就每种类型的评分而言,分数大多在 5 到 7 之间。新闻在网飞和迪士尼+都有超过 7 的高评级,但考虑到这两个平台上几乎没有新闻内容,它可以忽略不计。同样,传记和纪录片在所有平台上都获得了很好的成绩,但只有网飞有足够多的纪录片来认真对待它。有趣的是,冷门类型比流行类型有更好的收视率。网飞和亚马逊 Prime 网站上的剧情片、喜剧片和动作片虽然最受欢迎,但评分很低,只有 6 分左右。另一方面,Disney+在他们专注的流派上做得很好;动画平均评分 6.8,冒险 6.6,奇幻 6.47,家庭 6.43。

MovieLens 标签基因组分析

图 4。网飞原创电影的标签基因组分析。图片作者。

图 5。网飞非原创电影的标签基因组分析。图片作者。

网飞

对网飞 MovieLens 数据集的分析(图 4,5)显示了与 IMDb 流派分析相关的发现。诸如戏剧、喜剧和动作之类的标签被包括在原创和非原创电影的高发生率标签之一中。与其他平台相比,还发现了其他可区分的属性,如“视觉吸引力”或“良好的配乐”。原创电影和非原创电影的高评分标签有所不同,原创电影的前三名是“阴谋”、“奥运会”、“俄罗斯”,非原创电影的前三名是“柏林”、“东德”、“完全对话”。总的来说,原创和非原创电影的高评级标签和标签出现的结果提供了对网飞内容种类的额外洞察。

图 6。亚马逊原创电影的标签基因组分析。图片作者。

图 7。亚马逊非原创电影的标签基因组分析。图片作者。

亚马逊 Prime

亚马逊 Prime 数据集总共包含 52 部原创电影。MovieLens 的数据只有大约六部亚马逊原创电影。尽管受到原创电影数量减少的限制,但分析发现,亚马逊 Prime 原创电影具有与流派“戏剧”和“喜剧”相关的标签。最高平均收视率也显示出类似的趋势。非原创亚马逊 Prime 电影的标签与“动作”相关最多,其次是“喜剧”。平均评分最高的标签与动作电影的主题有关,如“自由”、“同情”和“科幻崇拜”。但是,有些与我们在整个研究中发现的趋势无关。一般来说,MovieLens 分析显示的结果与我们的流派分析发现的结果相似。

图 7。迪士尼+标签基因组分析。图片作者。

迪士尼+

对于 Disney+,只分析了非原创电影,因为只有 3 部原创电影在 2019 年之前上映,并且在 MovieLens 中可用。迪士尼+电影出现最多的标签是“动画”、“迪士尼动画长片”和“家庭”。就每个标签的评分而言,通常与动画相关的话题,如“超级英雄”、“玩具”和“皮克斯动画”的评分最高。尽管在电影镜头的数据中有一些电影被遗漏了,但是这些发现与 IMDb 的数据是一致的。

结论

年龄、流派和标签基因组是决定订阅的重要因素。通过我们的研究,我们发现了每个 OTT 平台的独特特征。通过年龄分析,我们发现,与其他平台相比,网飞拥有压倒性的电视剧电影。亚马逊 Prime 几乎平均分配了不同成熟度等级的电影。Disney+没有分级为 TV-MA 的电影,只有那些分级为 TV-PG 或 TV-G 的电影。结果表明,根据用户更喜欢看的电影的年龄组,可以订阅哪些平台。通过体裁分析,我们发现网飞和亚马逊 Prime 有相似的分布。他们都有最多的戏剧、喜剧和动作片。尽管如此,网飞在所有流派中拥有最多样化的内容。尽管与其他两部相比,Disney+的内容要少得多,但它在家庭、冒险和动画电影方面是最强的。通过基因组标签分析,我们可以测试我们的分析能力。我们在电影镜头分析中的发现与我们通过类型分析发现的结果基本一致。网飞和亚马逊也有类似的趋势,它们的标签与戏剧、喜剧和动作相关,而迪士尼+的标签更侧重于动画电影。然而,由于原始电影的数据集较小,部分原因是数据仅限于 2019 年之前上映的电影,我们认为有必要进一步分析最近的电影,以提供更准确的画面。

我们所有的工作都是在 NYU 集群上完成的。我们要感谢 NYU 高性能计算团队为整个过程提供的平台。我们还要感谢 Kaggle 用户发布他们的数据集,供我们在这个分析项目中使用。找到符合我们需求的 OTT 平台数据异常困难。我们感谢 Ann Malavet 教授指导我们的研究,并感谢 Tableau 为我们提供了创建可视化的软件。

开源代码库

请参考以下代码链接:

网飞

**https://github.com/yungjurick/analysis-on-ott-platforms

亚马逊金牌会员

https://github.com/chrissykrissy/OTT-Platform-Big-Data-Research

流媒体平台 Disney+

https://github.com/hawill10/DisneyPlusETL

参考文献

金和金(2017 年)。在线电影在连续市场的成功:韩国视频点播电影成功的决定因素。远程信息处理和信息学,34(7),987–995。【https://doi.org/10.1016/j.tele.2017.04.009

米(meter 的缩写))S. Kristoffersen,S. E. Shepstone 和 Z. Tan,“推荐电视内容时上下文的重要性:数据集和算法”,载于 IEEE 多媒体汇刊,第 22 卷,第 6 期,第 1531-1541 页,2020 年 6 月,doi:10.1109/TMM . 2019 . 2944362636

Reddy S .,Nalluri S .,Kunisetti S .,Ashok S .,Venkatesh B. (2019)使用类型相关性的基于内容的电影推荐系统。在:Satapathy S .,Bhateja V .,Das S. (eds)智能智能计算和应用。智能创新,系统和技术,第 105 卷。新加坡斯普林格。https://doi.org/10.1007/978-981-13-1927-3_42

网飞、亚马逊和订阅视频点播门户网站中的品牌电视内容媒体、文化&社会40.5(2018):725–741。**

使用 Scala 进行数据分析

原文:https://towardsdatascience.com/data-analysis-using-scala-f3846602fb0d?source=collection_archive---------33-----------------------

使用最大信息系数和 RScala 库进行可视化的示例学习

马库斯·斯皮斯克在 Unsplash 上的照片

选择合适的工具进行数据分析非常重要。在举办国际数据科学竞赛的 Kaggle.com论坛上,人们经常会问哪个工具更好。r 和 Python 排在最前面。在这篇文章中,我们将告诉你另一套数据分析技术,基于 Scala 编程语言和 Spark 分布式计算平台。

我们是怎么想出来的?

在 Retail Rocket,我们对非常大的数据集进行了大量的机器学习。我们以前用一堆 IPython+pyh S2(Python 的 hive 驱动)+ Pandas + Sklearn 开发原型。在 2014 年夏末,我们做出了一个根本性的决定,转而使用 Spark,因为实验表明,在相同的服务器上,我们将获得 3 到 4 倍的性能提升。

另一个优点是,我们可以使用一种编程语言来建模和编写将在生产服务器上运行的代码。这对我们来说是一个巨大的好处,因为之前我们同时使用 4 种语言:Hive,Pig,Java,Python。这是一个小工程师团队的问题。

Spark 很好地支持通过 API 与 Python/Scala/Java 协同工作。我们决定选择 Scala,因为它是编写 Spark 的语言,这意味着我们可以分析它的源代码,并在需要时修复 bug。它也是运行 Hadoop 的 JVM。

我必须说这个选择并不容易,因为当时团队中没有人了解 Scala。众所周知,要学会用一种语言很好地交流,你需要让自己沉浸在这种语言中,并尽可能多地使用它。所以我们放弃了 Python 栈,转而使用 Scala 进行建模和快速数据分析。

第一步是找到 IPython 笔记本的替代品。这些选择如下:

  1. Zeppelin—Spark 的 IPython 式笔记本;
  2. ISpark;
  3. 火花笔记本;
  4. IBM 的 Spark IPython 笔记本。
  5. 阿帕奇 T oree

到目前为止,选择 ISpark 是因为它很简单——它是 Scala/Spark 的 IPython。附加高图表和 R 图形相对容易。我们可以毫不费力地把它连接到纱线束上。

工作

让我们试着回答这个问题:

您在线商店的平均订单价值(AOV)是否取决于静态客户参数,包括结算、浏览器类型(移动/桌面)、操作系统和浏览器版本?

你可以用交互信息做到这一点。我们在推荐算法和分析中大量使用熵:经典的香农公式、Kullback-Leibler 散度、互信息。我们甚至提交了一份关于这个主题的论文。在 Murphy 关于机器学习的著名教科书[5]中,有一个单独的,尽管很小的章节专门讨论这些措施。

下面就以我自己真实的零售火箭数据来分析一下。在进行分析之前,所有数据都是完全匿名的。事先,我将样本从我们的集群复制到我的计算机上,作为一个 csv 文件。

数据

这里我们使用 ISpark 和 Spark 在本地模式下运行,这意味着所有计算都在本地执行,并分布在处理器内核中。一切都在代码的注释中描述。最重要的是,在输出中我们得到了 RDD (Spark 数据结构),它是 Row 类型的 case 类的集合,这是在代码中定义的。这将允许您通过“.”引用字段例如 _.categoryId。

资料截图,图片作者

上面的行使用了在 1.3.0 版本中添加到 Spark 的新 DataFrame 数据类型,它与 Python 中 pandas 库中的类似结构非常相似。toDf 选择了我们的行 case 类,所以我们可以通过名称来引用这个字段。

为了进一步分析,我们需要选择单个类别,最好是有大量数据的类别。为此,我们需要获得最流行类别的列表。

为了进一步的工作,我决定选择第 128 类。

让我们准备数据:让我们过滤必要类型的操作系统,以避免在图表中添加噪声。

想要可视化,让我们在 HighCharts 中实现它。

操作系统的 AOV,作者的图像

您可以使用任何 HighCharts 图形,只要 Wisp 支持它们。所有图表都是交互式的。

让我们尝试做同样的事情,但是使用 R.
运行 R 客户端并绘制一个 char:

操作系统的 AOV,作者的图像

交互信息

图表显示了这种关系,但是指标能为我们证实这个结论吗?有很多方法可以做到这一点。在我们的例子中,我们使用表中值之间的互信息。它测量两个随机(离散)变量分布之间的相互依赖性。

对于离散分布,使用以下公式计算:

作者图片

但是我们对一个更实用的度量标准感兴趣——最大信息系数(MIC ),它需要对连续变量进行一些复杂的计算。下面是这个参数的定义。

设 D = (x,Y)是随机变量 X 和 Y 的 n 个有序元素对的集合,这个二维空间由 X 和 Y 网格划分,将 X 和 Y 值分别分组到 X 和 Y 分区中(还记得直方图吗!).

作者图片

其中 B(n)是网格大小,I∫(D,X,Y)是 X 和 Y 分区的互信息。分母指定对数,用于将 MIC 归一化为段[0,1]的值。MIC 取区间[0,1]内的连续值:对于极值,有依赖关系为 1,没有依赖关系为 0。关于这个主题还有什么可以阅读的,列在文章末尾的参考书目中。

《T2》一书(机器学习:概率视角)称 MIC(互信息)为 21 世纪的相关性。原因如下!来自[1]和[4]的图显示了 6 个相关性(C 到 H 图)。已经为它们计算了皮尔逊相关和 MIC,并在左边的图表上用相应的字母标出。正如我们所看到的,皮尔逊相关性几乎为零,而 MIC 显示了相关性(图 F、G、E)。根据[1],MIC 可以很好地检测非线性相关性。

在我们的例子中,我们正在处理一个 MIC 计算,其中我们有一个连续的变量 AOV,所有其他的都是离散的无序值,如浏览器类型。为了正确计算 MIC,我们需要离散化 AOV 变量。我们将使用来自 exploredata.net 的现成解决方案。这种解决方案有一个问题:它假设两个变量都是连续的,并且用浮点值表示。因此,我们必须通过将离散变量的值编码成 Float 并随机改变这些变量的顺序来欺骗代码。为此,我们将不得不以随机顺序(100)进行多次迭代,我们将取最大 MIC 值作为结果。

对于这个实验,我添加了一个均匀分布的随机变量和 AOV(平均购买价值)本身。正如我们所见,几乎所有 MIC 都低于随机 MIC,这可以被认为是一个“有条件的”决策阈值。AOV 麦克风几乎是统一的,这是自然的,因为它本身的相关性等于 1。

一个有趣的问题出现了:为什么我们在图中看到了相关性,但 MIC 为零?我们可以提出很多假设,但最有可能的是,对于操作系统家族来说,这很简单 Windows 机器的数量远远高于其他机器的数量。

Windows 机器的数量远远高于其他机器,图片由作者提供

结论
我希望 Scala 在数据分析师(数据科学家)中得到普及。它非常方便,因为它可以使用标准的 IPython 笔记本+获得 Spark 的所有功能。这段代码可以安全地处理万亿字节的数据,您只需要更改 ISpark 中的配置行,指定集群的 URI。

Roman Zykov 是 Retail Rocket 的联合创始人,也是《Roman ' s Data Science:How to money your Data》一书的作者。

参考文献

[1] Reshef,D. N .,Y. A. Reshef,H. K. Finucane,S. R. Grossman,G. McVean,P. J. Turnbaugh,E. S. Lander,M. Mitzenmacher 和 P. C. Sabeti,“检测大型数据集中的新关联。(2011)
【2】Minepy 库 —基于最大信息量的非参数探索。
【3】用数据集挖掘 Java 库。
【4】凯文·帕特里克·墨菲,《机器学习:一种概率视角》,2012
【5】以上代码要点

【https://topdatalab.com】原载于https://topdatalab.com/blog/tpost/1p3lt20od1-data-analysis-using-scala

使用 Python、R 和 SQL 进行数据分析

原文:https://towardsdatascience.com/data-analysis-with-python-r-and-sql-cc17659aaf05?source=collection_archive---------34-----------------------

比较基本操作的实用指南

托尔加·乌尔坎在 Unsplash 上拍摄的照片

数据科学生态系统由众多软件工具和软件包组成,让我们的生活变得更加轻松。其中一些已经过优化,可以更好、更高效地完成特定任务。然而,对于典型的数据分析和操作任务,我们有许多选择。

在本文中,我们将比较 Python、R 和 SQL 在探索性数据分析中的典型操作。这些例子可以被认为是基础水平。本文的目标是强调这些工具之间的相似之处和不同之处。

我还想指出如何用不同的工具完成相同的操作。尽管存在语法差异,但操作背后的逻辑和处理特定任务的方法是非常相似的。

在下面的例子中,我将定义一个任务,并使用 Pandas 库(Python)、Data.table 库(R)和 SQL 来完成它。

这是将在示例中使用的数据集的快照。

项目(作者图片)

示例 1

查找每个商店 id 的商品平均价格。

SQL:我们选择商店 id 和价格列。price 列上的聚合是在选择它时指定的。然后,我们按照商店 id 列对这些值进行分组。

mysql> select store_id, avg(price) 
    -> from items
    -> group by store_id;+----------+------------+
| store_id | avg(price) |
+----------+------------+
|        1 |   1.833333 |
|        2 |   3.820000 |
|        3 |   3.650000 |
+----------+------------+

熊猫:我们选择列并应用按功能分组。最后一步是集合函数,即平均值。

items[['store_id','price']].groupby('store_id').mean() price                 
store_id                              
   1       1.833333                 
   2       3.820000                 
   3       3.650000

Data.table:语法有点像 Pandas 和 SQL 的混合体。我们在选择列时应用聚合并指定分组列。

> items[, .(mean(price)), by = .(store_id)] store_id       V1
1:        1 1.833333
2:        2 3.820000
3:        3 3.650000

示例 2

商店 3 中最贵的商品的价格是多少?

它类似于前一个示例,但有额外的过滤。我们只对 3 号店感兴趣。

SQL:我们选择 price 列并应用 max 函数。过滤是通过使用 where 子句完成的。

mysql> select max(price) from items
    -> where store_id = 3;+------------+
| max(price) |
+------------+
|       7.50 |
+------------+

Pandas:我们首先应用过滤器并选择感兴趣的列。然后应用最大值函数。

items[items.store_id == 3]['price'].max()
7.5

Data.table:过滤类似于 Pandas,但是聚合类似于 SQL 语法。

> items[store_id == 3, max(price)]
[1] 7.5

您可能已经注意到 data.table 的语法有一点不同。(mean(price))但在本例中没有点(max(price))。

使用带点的符号返回一个表,而如果不带点则返回一个数组。

示例 3

列出商店 1 中的商品及其价格,并根据价格降序排列。

SQL:除了我们到目前为止所看到的内容,order by 子句被添加到了结果排序的末尾。默认情况下,它按升序排序,所以我们需要使用 desc 关键字来改变它。

mysql> select description, price
    -> from items
    -> where store_id = 1
    -> order by price desc;+-------------+-------+
| description | price |
+-------------+-------+
| banana      |  3.45 |
| apple       |  2.45 |
| lettuce     |  1.80 |
| cucumber    |  1.20 |
| bread       |  1.15 |
| tomato      |  0.95 |
+-------------+-------+

Pandas:排序是使用 sort_values 函数完成的。默认情况下,Pandas 也按升序排序,这可以通过 ascending 参数进行更改。

items[items.store_id == 1][['description','price']]\
.sort_values(by='price', ascending=False) description      price                       
1         banana       3.45                 
0          apple       2.45                 
4        lettuce       1.80                 
11      cucumber       1.20                 
14         bread       1.15                 
7         tomato       0.95

Data.table:排序操作是通过使用 order 函数完成的,如下所示。我们通过添加减号来改变升序排序的默认行为。

> items[store_id == 1, .(description, price)][order(-price)] description price
1:      banana  3.45
2:       apple  2.45
3:     lettuce  1.80
4:    cucumber  1.20
5:       bread  1.15
6:      tomato  0.95

实例 4

显示项目描述中包含单词“egg”的所有行。

SQL:该任务包括基于字符串的过滤。因为我们没有进行精确的比较,所以我们将使用 like 关键字。

mysql> select * from items
    -> where description like '%egg%';+---------+-------------+-------+----------+
| item_id | description | price | store_id |
+---------+-------------+-------+----------+
|       9 | egg 15      |  4.40 |        3 |
|      11 | egg 30      |  7.50 |        3 |
+---------+-------------+-------+----------+

熊猫:我们将使用 str 访问器的 contains 函数。

items[items.description.str.contains("egg")] item_id   description    price   store_id                       8         9        egg 15      4.4          3                 
10       11        egg 30      7.5          3

Data.table:过滤与 SQL 语法非常相似。我们将使用如下的 like 关键字。

> items[description %like% "egg"] V1 item_id description price store_id
1:  8       9      egg 15   4.4        3
2: 10      11      egg 30   7.5        3

实例 5

找出每家商店售出的商品数量。

SQL:count 函数的用法如下:

mysql> select store_id, count(description) as item_count
    -> from items
    -> group by store_id;+----------+------------+
| store_id | item_count |
+----------+------------+
|        1 |          6 |
|        2 |          5 |
|        3 |          4 |
+----------+------------+

熊猫:这类任务有专门的功能。value_counts 函数返回每个不同值的出现次数。

items.store_id.value_counts()1    6
2    5
3    4
Name: store_id, dtype: int64

Data.table:我们对聚合使用 N 选项,它的操作与 SQL 中的 count 函数相同。

> items[, .N, by=(store_id)] store_id N
1:        1 6
2:        2 5
3:        3 4

结论

我们做了一些基本的数据分析和操作。当然,我们可以用这些工具做更多的事情。事实上,它们提供了多种多样的强大功能来完成高级和复杂的任务。

本文的目标是展示这些工具之间的异同。拥有大量可供选择的工具可能令人生畏,但它们都能够处理您需要的大部分内容。过了一段时间,就要根据你的口味来决定了。

感谢您的阅读。如果您有任何反馈,请告诉我。

数据分析师和数据科学家:真的能两者兼得吗?

原文:https://towardsdatascience.com/data-analyst-and-data-scientist-can-you-really-be-both-1115d5614dcc?source=collection_archive---------16-----------------------

对两个职位错综复杂的讨论

“数据分析师/科学家”职位发布示例。作者照片。

我最近遇到一份名为“数据分析师/数据科学家”的工作。它立即引起了我的注意,原因有二:

  1. 我对自己说:“哇!我真的很想成为一名数据分析师 数据科学家”
  2. 我想:“有人能两者兼而有之吗?我的意思是,成为一名优秀的数据分析师 一名优秀的数据科学家一定非常具有挑战性”

老实说,看到这个招聘信息质疑了我从开始在数据科学领域找工作时就有的一个先入为主的想法:如果你想成功,你必须专攻一个专业领域并发展与之相关的技能。成为无所不知的数据大师?那是不可能的。

尽管对你所在行业的其他专业领域有一个大致的了解对于成功地开展你自己的工作是必要的,这个世界已经变得如此复杂,以至于你需要专注于一个主题才能真正擅长它。在数据科学领域,尤其如此。例如,即使我自己无法部署用于图像识别的深度学习算法,我也可以肯定地使用基本概念来谈论它。最重要的是,我能够与具有特定专业知识的人一起工作,这样我们就可以从合作中获得最大收益。

这种合作将在一个条件下成功:其他人拥有我所没有的知识或技能,而我带给他们我自己的一套技能。回到前面的例子,一位数据科学家同事将能够为图像识别构建一个 ML 模型,而我将能够说服利益相关者这项技术与其业务的相关性,并以公司可以理解和使用的方式展示模型的结果。

数据科学家和数据分析师的区分是不是太明显了,一个人不可能两者都是?难道没有超级英雄可以同时成为两者吗?这正是我想在这里讨论的,谁知道呢,也许可以画出这样一个超人的肖像。

埃斯特万·洛佩兹在 Unsplash 上拍摄的照片

数据分析师、数据科学家:我们在说什么?

已经有大量的文章比较了数据分析师的工作和数据科学家的工作。作为介绍,你可以阅读默罕默德·a·瓦萨姆的这篇文章或者这篇由薇琪·于撰写。

为了总结数据分析师和数据科学家之间的主要区别,我确定了区分这两个职位的四个主要方面:

  • 教育
  • 所需技能
  • 工作职责
  • 代表团

数据分析师 VS 数据科学家。作者配图。

如您所见,数据分析师职位的一些特征与数据科学家非常不同,甚至完全相反。另一方面,数据科学家和数据分析师有一些共同点。

一个共同点是:他们都是数据爱好者

乍一看,数据分析师和数据科学家有一个共同的出发点:他们喜欢每天处理数据。这就是为什么在一个或另一个职位上开始职业生涯是有意义的,因为它们有共性。

首先,无论你是数据分析师还是数据科学家,基本面都是一样的。对于这两个职位,你必须对统计学有很好的理解,你必须掌握至少一门编程语言。数据分析师和数据科学家也对操纵数据有着真正的兴趣,同时他们决心从现实世界的数据集获得最大的收益。这实际上是至关重要的,因为这两项工作预计会定期交互。如果数据分析师和数据科学家不属于同一个团队,他们通常会将工作建立在公司级别管理的相同数据源上。

因此,在您决定数据科学中的任何专业领域之前,请确保您掌握了基础知识。在一家公司中,你必须确保在数据分析师和数据科学家之间建立频繁而可靠的沟通渠道,以便他们就最佳实践达成一致,并分享他们的技术和业务知识。

但是从长远来看,他们倾向于走相反的道路

我在开始讨论时提到了一份名为“数据分析师/数据科学家”的工作。我没有提到的是,这个职位对年轻的毕业生开放。现实情况是,没有一个职位的名称是“高级数据分析师高级数据科学家”。

造成这种情况的第一个原因是数据科学中的职业道路往往有两个方向:要么你朝着管理角色发展(在这种情况下,你会成为数据主管或类似的职位),要么你发展一些硬技能并在技术领域积累特定经验。这是你成为某个主题的技术领导者或专家的地方。

第二个原因是,“数据分析师”和“数据科学家”通常对应于入职或助理级别的职位。一旦你在这些工作邀请前加上“高级”这个前缀,你可能就再也看不到“数据分析师”和“数据科学家”这两个词了。这是最好的:当你擅长某事时,你会想花更多的时间去做。因此,如果你喜欢构建机器学习模型,但不太喜欢为运营主管创建仪表板,你希望被称为数据科学家,能够将任何仪表板请求转移给数据分析师同事。

照片由尤利娅·马特维延科在 Unsplash 拍摄

结论:先从两个开始,然后再选择一个

因为成为一名优秀的数据分析师和一名优秀的数据科学家的基础是相似的,同时成为这两者开始职业生涯是完全有意义的。作为一名毕业生,你会学到很多东西,最重要的是你会明白你喜欢哪种类型的任务。反思你的工作经历和你自己的偏好,这会引导你回答这个问题:你更愿意成为数据科学家还是数据分析师?

此时,你将通过提供非常独特的价值主张,为你作为一名高技能数据分析师或数据科学家而构建的价值主张铺平道路。因为归根结底,数据分析师和数据科学家不是同一份工作。

你喜欢读这篇文章吗? 成为 的一员,加入一个不断成长的充满好奇心的社区吧!

https://marie-lefevre.medium.com/membership

数据分析师与业务分析师的薪资

原文:https://towardsdatascience.com/data-analyst-vs-business-analyst-salary-80b243d3171b?source=collection_archive---------23-----------------------

这两种流行的技术/数据角色有什么区别?

照片由 NeONBRAND 在Unsplash【1】上拍摄。

目录

  1. 介绍
  2. 数据分析师
  3. 商业分析员
  4. 摘要
  5. 参考

介绍

注:

本文是第五篇,是关于流行的数据/技术角色之间的报告工资的连续系列的一部分。其他四个我会在文末链接。

正如我在本系列的前几篇文章中所说的,这篇文章的目的不是比较一个人是否应该得到更多的钱,而是让这两个领域的专业人士根据他们当前或预期的工资进行评估。请记住,这些工资值是比较笼统的,没有一个网站足以评估你的价值。正是这些价值观的方向,可以作为你未来处理薪资问题时的工具。

数据分析师和业务分析师在一家特定的公司几乎可以是相同的角色,而相反的情况也可以这样说——他们在其他公司可能会非常不同。话虽如此,在评估薪资时还是要考虑某些因素,比如所需的特定工具和技能,以及更一般的东西,比如地点和工作经验年限。了解了这个概念,我们可以从真实的报告数据中寻找具体的例子,并在下面考虑这些因素。

数据分析师

照片由 Alexandru Acea 在Unsplash【2】上拍摄。

数据分析师和业务分析师的角色既可以相似,也可以有很大的不同,数据分析师的职位也是如此。数据分析师的一些重要目标包括分析过去的数据或预测未来的数据。这种差异是导致工资差异的一个例子。就像任何工作一样,有一些因素会影响薪水,比如你的工作经验和具体的职位。

总的来说,我倾向于看到数据分析师职位包括更多的技术技能,以提高工资,并将在以后报告更多的具体例子。

下面是一些不同资历级别的数据分析师以及他们各自的薪水 [3]:

  • 平均总体数据分析师→ $61,754
  • 普通入门级数据分析师→ $56,383 (1 年)
  • 普通早期职业数据分析师→$61,179(1-4 年)
  • 中等职业生涯数据分析师→$69,251(5-9 年)
  • 普通有经验的数据分析师→$71,512(10-19 年)

这些工资数据是从 PayScale 收集的,如果你想要一个更具体的估计,那么你可以使用工资调查 [4]。

我同意这些数字吗?

号码

我认为这里的工资应该更高,因为数据分析师可以执行许多技能,并经常为公司带来很多价值。

让我们更多地看看具体的城市和技能,以更好地了解平均工资是多少,以及基于这些因素他们可以改变多少。下面,我将应用其中的一些因素,你会看到工资是如何受到影响的。

以下是一些热门城市和其他一些城市的职业中期数据分析师平均薪资:

  • 科罗拉多州丹佛市→67068 美元
  • 德克萨斯州达拉斯→69320 美元
  • 华盛顿哥伦比亚特区→77522 美元
  • 加州旧金山→98627 美元

正如你所看到的,仅仅看不同的城市就创造了很大的薪资范围。现在让我们深入一点,添加一些特定的技能。

  • 科罗拉多州丹佛→ $78,108,使用 Python
  • 德克萨斯州达拉斯→ $78,341,采用数据建模
  • 哥伦比亚特区华盛顿→80,000 美元,带数据库管理&报告
  • 加州旧金山→114,520 美元,统计分析

通过在同一个城市只增加一项技能,你可以看到工资如何显著上升,例如,将统计数据添加到旧金山增加了 15K 多一点。你可以看到增加尽可能多的你能胜任的技能来获得对你薪水的最佳估计是多么重要。让招聘人员知道这些技能也很重要,不要认为他们认为你知道某项技能。

商业分析员

活动创作者在Unsplash【5】上的照片。

业务分析师与数据分析师的不同之处在于,他们往往需要更广泛的技能。当然,有些人可以期望了解与数据分析师相同的技能,而有些人可能完全不同。我的看法是,如果你是业务分析师,比微软 Excel 和 Tableau 懂得多,还会使用 SQL 和 Python,你会是一个更有竞争力的申请人。

对于这些平均值,我们将关注“未指定类型”的业务分析师。这个标签已经向你表明,这个范围可能是所有技术/数据角色中最大的。

我将使用薪级表【6】来支付这些薪水:

  • 平均整体业务分析师→ $61,955
  • 普通入门级业务分析师→ $56,915 (1 年)
  • 普通早期职业商业分析师→$60,692(1-4 年)
  • 中等职业生涯商业分析师→$66,750(5-9 年)
  • 普通有经验的商业分析师→$70,632(10-19 岁)

因为这些平均值属于“非特定类型”类别,所以我相信它们比预期的要低,当然,引入更多的技术技能会提高你的薪资预期。

就像我们对数据分析师工资所做的一样,让我们更深入地了解不同的城市/位置以及具有不同技能的业务分析师角色。

  • 加州旧金山→78743 美元
  • 华盛顿州西雅图→70,420 美元
  • 德克萨斯州休斯顿→59223 美元

这些平均值似乎都有点低,所以让我们来看看具体技能是如何增加薪水的:

  • 加利福尼亚州旧金山→ $82,148,使用 SQL
  • 华盛顿州西雅图市→流程改进费用为 71,312 美元
  • 德克萨斯州休斯顿→ $71,000,财务分析

这些改进不如我们在数据分析师身上看到的那样显著或巨大。这里最大的收获是,这两种角色的技能确实不同,其他与数据分析关系不大、与业务指标本身关系更大的技能有助于增加工资。这一概念在得克萨斯州休斯顿市增加财务分析的最大飞跃中得到了体现,该市的 10K 增长了约 10%。

摘要

我们现在已经看到了不同的因素是如何影响这两种角色的,并以不同的方式影响它们。总的来说,从多个来源进行研究是更好地了解所有因素的最佳方式,这些因素决定了你正在寻找的具体薪资数字或范围。其他因素包括奖金、股份、教育、证书、你的简历、谈判以及你在面试中的表现。

总而言之,以下是数据分析师与业务分析师薪酬的一些关键对比:

*** Average US data analyst salary → $61,754* Average US business analyst (unspecific type) salary → $61,955* From the factors we investigated, it looks like data analysts might have the opportunity for a bigger salary amount, despite their overall lower average* Several factors contribute to salary, the most important most likely being seniority, city, and skills**

我希望你觉得我的文章既有趣又有用。如果你同意或不同意这些工资比较,请在下面随意评论。为什么或为什么不?关于薪水,你认为还有哪些重要的因素需要指出?这些当然可以进一步澄清,但我希望我能够阐明数据分析师和业务分析师工资之间的差异。

最后,我可以再问一次同样的问题,你如何看待薪资受到远程职位的影响,尤其是当城市是决定薪资的一个如此重要的因素时?

感谢您的阅读!

我与这些公司都没有关系。

请随时查看我的个人资料、 Matt Przybyla 、和其他文章,并通过以下链接订阅接收我的博客的电子邮件通知,或通过点击屏幕顶部的订阅图标 点击订阅图标 ,如果您有任何问题或意见,请在 LinkedIn 上联系我。

订阅链接:https://datascience2.medium.com/subscribe

我也写过类似的文章,在这里讨论数据科学家与业务分析师的工资【7】,在这里讨论数据科学家与数据工程师的工资【8】,在这里讨论机器学习工程师的工资与数据科学家的工资【9】,在这里讨论数据科学家与数据分析师的工资【10】。这些文章概述并强调了各自薪资的相似特征。请记住,对于所有这些文章,这些都不是我的工资,而是由 PayScale 和其他实际的数据科学家、业务分析师、数据工程师、数据分析师和机器学习工程师报告的。因此,这些文章是围绕真实数据的讨论,旨在让您更好地了解是什么使一个角色(一般为)基于某些因素增加或减少薪资金额。**

参考

[1]照片由 NeONBRAND 在Unsplash(2017)上拍摄

[2]照片由 Alexandru Acea 在Unsplash(2018)拍摄

[3]薪级表,数据分析师工资,(2021)

[4] PayScale, PayScale 薪资调查,(2021)

[5]2018 年活动创建者在 Unsplash 上的照片

[6] PayScale,业务分析师(未指定类型),(2021)

[7] M.Przybyla,数据科学家与商业分析师的薪酬,(2021)

[8] M. Przybyla,数据科学家与数据工程师的薪酬,(2021)

[9] M.Przybyla,数据科学家 vs 机器学习工程师薪酬,(2021)

[10] M. Przybyla,数据科学家与数据分析师的薪酬,(2021 年)

数据分析师与数据科学家

原文:https://towardsdatascience.com/data-analyst-vs-data-scientist-a83af97ad472?source=collection_archive---------2-----------------------

对“21 世纪最性感的工作”的角色和责任、重叠点和期望的比较分析。

照片由来自 Unsplash 的活动创作者拍摄。

数据科学被标榜为 21 世纪最性感的工作,近年来已成为最受欢迎的职业之一——通常只围绕名人进行炒作。世界各地的公司都拿出丰厚的薪水、声望和运用影响力的特权来吸引分析人才。在所有宣传的背后,是数字数据日益增长的重要性,它目前正在改变我们的生活和工作方式。

难怪越来越多的爱好者想打入这个新领域。但在闭眼冒险进入数据科学和分析领域之前,有抱负者最好先了解一下可用的路线。鼓励感兴趣的候选人通过确定切入点和要求开始他们的旅程,更多地了解各种数据子字段之间的差异,以及在提交工作申请之前他们的简历需要如何改进。

沿着这一思路继续下去,一个问题自然会出现。数据科学家和数据分析师的头衔到底有什么区别?毕竟,这两种职业似乎都肩负着从数据中提取商业价值的任务。精通逻辑的读者可能已经知道,共享相似性并不意味着互换性。一个可以补充另一个,因为两者都在为实现一个共同的目标而努力。野外的许多现象在某些领域有相似之处,而在另一些领域则截然不同。

这篇文章的目的是找到差异问题的答案。不仅从理论的角度,而且从一个经验丰富的专业人士的角度,他看到了数据团队在现实世界中是如何运作的。这是因为,众所周知,头衔及其花哨的反响是一回事,而现实的日常工作量则是完全不同的另一回事。

说到这里,我们先来看看这两个角色的共同特征,然后再探讨它们的不同之处。

相似性—数据分析师与数据科学家

事实上,通过肯定他们共有的几个方面并概述他们的不同之处,我们可以更好地把握这两个角色。注册为 Stephan Kolassa 的 data science stack-exchange 博客试图通过使用维恩图(条目 2403)来直观地划分差异。

Stephan Kolassa 的图表。经允许重新发布。【https://datascience.stackexchange.com/a/2406/2853 号

从这张图表中可以推断出许多值得注意的地方。更明显的是,数据科学家和数据分析师的角色密切相关,占据彼此相邻的象限。实际上,这意味着他们应该总是在相同的业务单元中工作,除非分析师作为敏捷框架中团队的一部分被绑定到特定的项目团队。很符合逻辑,对吧?两者都使用数据为业务目标服务,都需要传统统计方面的专业知识。

他们还分享了这个沟通象限:通过数据故事向企业领导人传达有用的见解,或者创建直观的工具,带来“数据驱动”的决策。不需要太多思考,很容易理解数据科学家和数据分析师只有在他们能证明他们的工作有用时才值得拥有。正是因为这个原因,你会发现这两种工作几乎在所有的招聘广告中都需要视觉和语言交流技能。尽管如此,我们能通过查询日益聪明的万维网找到更多的相似之处吗?

使用 Python 脚本从一个免费的来源加载 Google 搜索词数据,我们可以看到这两个工作角色还有另一个共同点。近几年,类似的职业也见证了一个相似的流行趋势,一个爆炸性的趋势。但就共同点而言,也就这些了,简单地总结为三点:(1)为商业优势提供数据洞察力,(2)卓越的沟通,以及(3)在公众眼中的受欢迎程度。

作者使用谷歌趋势拍摄的照片。

顺便说一句,如果你想知道,谷歌趋势数据来自个人搜索引擎查询的无偏样本——匿名、分类和地理分组,以衡量公众对特定主题的兴趣。2016 年发布了该数据的一个巨大增强,使所有主题类别的情感都可以实时获得。我碰巧有多年利用这些数据的经验。

数据分析师—职位描述

无论如何,我们现在将转向分开的细节。这最好通过例子来完成,从互联网上挖掘数据科学家和数据分析师的代表性职位描述。入门级的一个写着:

数据分析师招聘广告示例。作者照片。

典型的数据分析师角色是以咨询为中心的,这可以从实际工作规范的例子中看出。他们主要关注的是从 Excel 电子表格和 SQL 数据库中获取数据,通过回顾性分析、A/B 测试得出深刻的结论,并提供基于证据的商业建议。最后一点说明了为什么使用可视化工具(如 Tableau)的报告例程与透视表一样重要。另一方面,数据建模通常局限于基本的监督学习或其统计等价物:回归分析。

根据经验,我还可以说,新手有时会忘记提供推荐的阶段总是最重要的。他们可能会被远离商业环境的时髦词汇和流行技术所误导。这就是为什么分析师学习如何挖掘可以采取行动的见解是如此重要,这些见解可以用视觉上引人注目和易于理解的格式呈现。分析师是精通技术的调查记者,他们提供深入的见解。

数据科学家—工作描述

现在,我们来看一个类似的典型数据科学家角色的例子,我们将探讨一些关键差异。第一个值得注意的是“必须具备”和角色职责部分的长度。当然,对普通数据科学家的要求比数据分析师高得多,这部分解释了为什么前者的薪水比后者高。但是炒作背后有实质内容吗,或者数据科学仅仅是一个现代神话?

数据科学家招聘广告示例。作者照片。

公平地说,出于这个原因,数据科学家被认为不仅仅是分析奇才。他们应该是构建者,使用高级编程来创建管道,在生产环境中以近乎完美的准确度进行预测和推荐。与像调查记者一样的分析师相比,他们更多的是面向产品开发而不是咨询。尽管数据科学家也需要提供以数据为导向的商业建议。有人说,这个头衔是为了表明这个角色是三个领域的融合:数学/统计学、计算机科学和领域专长。据说下面的引用最好地概括了这一点:“数据科学家是比任何软件工程师都更擅长统计,比任何统计学家都更擅长软件工程的人。”

差异—数据分析师与数据科学家

更大的数据量意味着更高的赌注:期望也是如此。与分析师不同的是,他们第一天平均会收到 50 万行 50 列的电子表格,数据科学家可能会在第一天看到数万列数据的关键。每个人都会期待他们从这些海量数据中神奇地召唤出洞察力和智慧的宝石。如果留给他们自己的设备,他们将被期望摄取、转换、探索和建模大量杂乱和非结构化的数据。正如 medium 上一些机智的作家所言:“数据科学家这个头衔让人联想起一个人的近乎神秘的能力,这个人能够轻松地从深度数据湖中获得洞察力,这个人对数据有一双超自然的手,就像 21 世纪的胡迪尼一样!”

数据科学需要更多的编码。尽管数据科学家和数据分析师获取数据的目的相同,但他们使用的方法和工具却大相径庭。虽然数据分析师主要使用 SQL 方言将可管理的数据块粘贴到电子表格和编程接口中,如 R Studio 和 Jupyter 笔记本,但数据科学家预计会适应在云计算环境中工作(AWS、Databricks、Hadoop 等)。).

在那里,他们接收、处理和模拟大量数据,其数量级通常被称为大数据。有鉴于此,很容易理解为什么数据科学工作会增加那些长得离谱的技术要求清单。大型组织中的新员工不可避免地会继承大量有时没有文档记录的遗留脚本和定制算法,他们需要替换或维护这些脚本和算法。考虑到这一点,高级编程技能成为必备技能也就不足为奇了,在大多数入门级数据分析师职位中,拥有高级编程技能是件好事。

数据分析师与业务利益相关者的联系更加紧密。因为正如我们在对这些差异的长篇论述中所发现的,数据分析师的工作实际上不需要太多的编码,这揭示了一个更微妙的问题。技术世界的细心观察者会证实,技术复杂性几乎总是伴随着障碍。他们在决策者和动手的工程师和科学家之间制造了空白。反过来,这也是产品经理填补沟通鸿沟的空间。由于数据科学工作通常被神秘的迷雾所包围,公司的普通员工倾向于向分析师寻求帮助。

这是我在商界经常注意到的一个现象:数据科学家往往更加孤立。另一方面,数据分析师倾向于更多地参与和参与其他业务部门,随时帮助解决问题,如修复 Excel 电子表格,通过分析性问题帮助客户推销,以及通过仪表板促进整体业务绩效。因此,如果这篇文章的读者更多的是一个喜欢在微观环境中有所作为的顾问,那么分析师的职位会更加令人满意。简而言之,篱笆那边的草并不总是更绿。

数据分析师与数据科学家—结论

考虑到所有因素,我们探讨了数据科学家和数据分析师的职业是如何进行比较和对比的。我们已经了解了它们在编程强度、建模中使用的数据量、自动化方面的复杂性以及查看样本招聘广告所需的教育背景方面的差异。当然,我们预料到了差异。但令人惊讶的是,我们也开始意识到这两个相似的职业实际上是多么相似。本质上,它们都寻求从数据集中获取洞见。

参考文献

1)https://HBR . org/2012/10/data-科学家-21 世纪最性感的工作

2)https://data science . stack exchange . com/questions/2403/data-science-without-knowledge-of-a-specific-topic-is-it-was-purchasing-as-a-ca

3)https://trends.google.com/trends/?geo=US

数据分析师的渐变维度入门

原文:https://towardsdatascience.com/data-analysts-primer-to-slowly-changing-dimensions-d087c8327e08?source=collection_archive---------8-----------------------

数据分析师访谈通常包括技术和行为两部分

来源:托比亚斯·菲舍尔在 Unsplash 上拍摄的照片

我遇到了一个相对直接的 SQL 挑战,但是包括一个注释,即挑战的假设表中的列是缓慢变化的维度类型 2。我不知道这些是什么,但幸运的是,这是一个带回家的挑战,所以我有机会研究它,并在挑战和面试过程中取得成功。除了知道对我的编码挑战的影响,我还好奇为什么这对数据分析师的角色很重要。

当我通过参加数据科学训练营实现职业转型时,导师和同事们都说谷歌会是你最好的朋友,这表明解决你面临的问题需要研究——并非所有问题都有简单或直接的答案。

但在这种情况下,谷歌并没有很大的帮助。截至 2021 年,当搜索“缓慢变化的维度”时,第一个结果现在是一篇维基百科文章,当我提出我的编码挑战时,它并不存在。相反,我找到的最佳结果是一个描述不同类型的渐变维度的 Oracle primer ,但是其余的结果并不太有帮助。我把注意力转向搜索 YouTube,发现了一个有用的结果,是由一位名叫 Tech 蔻驰的用户提供的,他解释了缓慢变化的维度,这种方式有助于应对面试挑战,以及在我作为数据分析师的日常工作中适用的重要知识。

下面我总结了我的研究结果,并指出数据分析师的应用。

我提供这些细节的目的是:

  • 综合我自己的研究发现,帮助他人增强知识或准备面试
  • 确定缓慢变化的维度可能会对查询产生影响的情况
  • 提供背景知识,说明为什么缓慢变化的维度与数据分析师的日常工作相关。

那么什么是缓变维度(SCD)?

SCDs 指的是数据仓库概念,其中维度包含当前和历史数据。这是在数据仓库中维护历史细节的常用方法,但是它们的使用将取决于业务需求和数据仓库的目的。

基本上,维度会随着时间而缓慢变化,而不是按照预定的时间间隔变化,维度变化的频率没有固定的模式。

这就产生了一个问题,即数据仓库是存储当前数据还是历史数据,或者两者都存储。该决策可能由业务需求决定,并将由数据架构师或工程师实施和管理,但是理解所使用的维度类型和基本原理对于数据分析师响应业务问题和有效履行其职责的能力至关重要。

使用渐变维度的一个业务案例可能是,我们可能需要考虑我们知道哪些属性会随着时间的推移而变化,但我们不一定期望在规定的时间间隔内发生变化。例如,考虑一个销售部门,随着客户数量的变化,负责特定客户的个人客户经理也会发生变化。这些变化将随着公司获得新客户而发生,但我们不知道具体什么时候会发生变化,因为销售部门的员工每年 6 月都会有预定的晋升和工资变动。

那么缓变维度的不同类型有哪些呢?

SCD 类型 0

第一种类型被称为类型 0。这指的是在数据仓库中从不改变也不会更新的属性。SCD 类型 0 的一个示例是我们不希望更改的记录,如出生日期或员工在公司的开始日期。因此,我们不希望这个维度在我们的数据仓库中发生变化。

SCD 类型 1

渐变维度类型 1 是指在数据仓库中维护记录的最新快照,而没有任何历史记录的实例。

SCD 类型 1 通常用于更正维度中的错误,更新错误或不相关的值。不保留历史记录—如果记录包含错误和所需的更新,我们是否希望保留现在已被否决的不准确的历史记录?

一个真实世界的例子来自你的作者。我的名字是Nicolas,但是人为错误或自动更正等工具通常认为我名字的正确拼法是更常见的Nicholas,名字中有一个h

假设这个错误是人力资源团队在我加入一家新公司时犯的。当然,我希望记录能准确反映我的名字,这样 HR 就可以在源系统中更改我的名字。从源系统构建的数据仓库中的任何表,如雇员姓名和角色表,都将被更新以反映这种变化。

SCD 类型 1 将更新记录以准确反映我的姓名,从而纠正姓名拼写中的错误。不正确的记录将被更新,而不会向数据仓库添加任何新的行或列。

但是,假设该记录不是不正确的姓名,而是诸如雇佣历史表之类的东西—例如,雇员在公司中的角色和薪水。

当一个雇员得到晋升时,SCD 类型 1 记录将反映他们的新职位—先前的记录被覆盖。因此,如果我们确定我们不需要先前的历史(例如,纠正一个错误),SCD 类型 1 可能满足我们的目的。

但是考虑下面的例子:Paulie 是地区销售经理,被提升为区域销售经理。由于他的提升,数据仓库中的 employee 表将被更新。先前的记录和雇佣历史将被覆盖,以反映新的职位、工资、主管等。

在 SCD 类型 1 中,雇佣历史将被覆盖。所以在上面的例子中,我们的表将保留第二行——Paulie 目前的职位是Regional Sales Manager,但他以前的职位是District Sales Manager,这不会保留在我们的表中。

然而,我们想要保留历史可能有正当的理由。例如,人力资源部门可能希望方便地访问某人的主管或工资历史记录,或者确定员工更换角色的频率。在后一种情况下,SCD 类型 1 将是不合适的,因为我们将丢失历史,这将引导我们进入下一种类型的缓慢变化的维度。

SCD 类型 2

那么当我们想维护历史的时候用什么呢?引入渐变维度类型 2。

对于 SCD Type 2,每当源系统中有变化时,都会向数据仓库表中添加一个新行。在生成的表中,将会有更多的记录,但是先前的历史记录将被保留并可查询。

在 SCD 类型 2 中,有两种方法来区分当前记录和历史记录:

  • 表示当前记录的列
  • to_datefrom_date栏目

继续上面的例子,考虑保利现在已经被提升为东海岸销售主管。

因为我们现在正在查看 SCD 类型 2,所以来自 Paulie 之前角色的所有记录都将保留在我们的employee_history表中。

表格中的当前记录将通过一个标志(current_record_indicator )或当前记录将具有标准化替代高日期的日期范围(例如position_end_date = '12-31-9999')来表示。

查询该表时,为了确保返回当前记录,我们将添加一个过滤条件,例如:

WHERE current_record = 'Y'WHERE position_end_date = '12-31-9999'

根据表的结构、数据仓库和业务需求,可能只有一个或两个列/方法可用。

概括一下 SCD 类型 2,其主要好处是记录的历史将被维护,但是,如果数据的结构有可能改变(例如,向表中添加新列)或者向表中添加新行增加了表的大小,使得表变得不可管理,则不太可能使用这种类型。

根据我的经验,SCD 类型 2 很常见,了解如何获得感兴趣的当前记录很重要。一个重要的考虑因素是在构建 SQL 查询时是否对连接条件有影响。当连接到 SCD 类型为 2 的表时,在连接条件中包含当前记录标志是很重要的,否则可能会影响结果。

SCD 类型 3

下一种缓慢变化的维度是类型 3,在我的职业生涯中,我还没有遇到过这种情况,我对这个主题的研究表明,这种类型很少使用。

不是向表中添加新行来反映每个记录的更改,而是添加一个额外的列。

考虑前面的例子,Paulie 从地区销售经理晋升为区域销售经理。为了获取 Paulie 的新工资,我们在表中添加了一个新行,保留了以前的历史记录。

相反,对于 SCD 类型 3,我们将有一行,但有一个额外的列来表示以前和当前的薪金,以及记录的更新日期:

SCD 类型 3

这将从原始状态和当前状态比较保利的工资,但如果工资再次发生变化,跟踪历史将更加困难。这种方法的优点是,它提供了在发生更改之前和之后比较记录的能力,但是保留了有限的历史。

SCD 类型 4

下一个缓慢变化的维度是类型 4。这里引入了历史表的概念。历史数据将像在 SCD 类型 2 中一样被维护,但是这里的区别在于历史将被维护在数据仓库中的单独的表上。当前记录将包含在主表中。

对于 SCD 类型 4,对于源系统中的每一个变更,一个记录将被添加到历史表中。

继续我们在销售部门的 Paulie 和他的晋升的例子:我们在数据仓库中的employee表将反映 Paulie 目前作为东海岸销售主管的角色;

员工表(当前记录)

而另一个employee_history表将包含有关 Paulie 在同一家公司的先前职位的历史数据:

SCD 类型 4 历史表

对 Paulie 的工资或职位历史感兴趣的人力资源经理可以通过加入employee_idemployee_history表中查找以前的记录。

包扎

以上反映了我自己的研究和经验,同时介绍了这个数据架构概念对数据分析师角色的适用性。这绝不是详尽的,对于那些真正对构建数据仓库感兴趣的人,我鼓励进一步的研究或寻求数据架构师的帮助。

来自手势的数据和分析团队最佳实践

原文:https://towardsdatascience.com/data-analytics-team-best-practices-from-gesture-df244db76629?source=collection_archive---------67-----------------------

手势图像

创建和精心制作具有持久影响力和商业价值的数据科学项目是我们在 Gesture 的数据科学团队的核心工作,我们的目标是不断完善我们创建数据驱动环境的承诺。

随着情人节的临近,我们想与我们更广泛的数据社区分享一些爱,并分享一些对我们有用的最佳实践。对于许多数据科学和分析团队来说,这是一条棘手的道路:我们如何创建和使用为我们工作并被我们的业务合作伙伴使用的工具?定义和框定我们试图解决的问题,创建解决方案、方法或设计,并将设计中的见解转化为行动,从而改变业务运作和改进的方式,这对各种规模的公司来说都是一个挑战。从数据到分析,再到洞察力,最终到行动,必须有一个清晰的联系。

以下是对我们有用的顶级数据最佳实践,我们希望您在壮大数据科学和分析团队时能够在业务中加以利用!

从一个重点项目开始,这样你的数据科学和分析团队就能获得一些街头信誉。

所有公司都有一些政治成分。即使你公司的文化是低调和悠闲的,你所有的业务团队都需要了解数据和分析团队是做什么的,以及为什么他们应该关心他们。围绕您的数据团队创造良好的公共关系是确保贵公司数据第一文化的关键。

专注于一个真正重要的、相关的项目,这个项目将让你的数据团队从组织的各个方面得到关注,从营销到运营到销售到财务。确保你的项目得到管理层的支持,有清晰的指标和 KPI 来衡量你的结果的影响,并提供数据,让每个人都能看到你努力的成果!也许是仪表盘,也许是获客工具,也许是推荐系统。无论是什么,确保这是一个好的第一次胜利,每个人都可以使用和欣赏。

定义您的 DS & A 团队结构,以便每个人都了解团队中关键角色的职能。

在手势,我们有一个中心和辐条模型。我们有一个重要的 DS 中心,我们的分析人员与销售和营销人员坐在一起,有效地充当我们在公司内的销售和营销合作伙伴。这使我们能够拥有一个核心团队,专注于高级数据计划和完善数据科学团队的战略,同时还创建了一些利益相关者,他们在公司的其他团队中负责更具体的项目和任务。

数据民主化是数据科学组织成功的一个重要因素,让核心团队的成员在各种其他团队的卫星团队的陪同下工作,可以实现公司内部数据利益相关者所需的协同作用,使他们的数据项目成为现实,继续看到其相关性的曙光。确保我们有跨职能的人才和赞助商,对于确保我们所有的团队在数据驱动和交付有影响力的结果方面都是至关重要的。

定期与营销、财务、产品和销售部门开会。你以后会感谢我们的。经常与你的商业伙伴沟通,保持沟通渠道的畅通。不要做孤岛。你的同事不会上钩,他们会欣赏你的领导能力。

定义您的工具和 KPI

适用于一个数据组织的方法可能不适用于另一个数据组织。你是 python 之家还是 R 之家?你在哪里仓储?你用什么来分析和控制面板?你是在云上还是在防火墙后面?您在哪里部署模型?你如何衡量自己的表现?选择工具和环境是另一篇博文的内容,但这里真正重要的是,你要做出与你的公司之旅相关的选择。

决定适合您的企业身份以及您的数据团队资产战略的基础架构。一开始就定义指标是非常重要的,这样您的数据利益相关者就可以说同一种语言,并且他们可以最大限度地利用他们的工具。当你试图发布数据和分析项目的结果时,投资回报率、成本或收入指标可能会让你走得很远。数据人员需要用对非技术人员有意义的语言将他们的数据工具的影响与领导力联系起来,因此要从成本、利润和客户旅程/服务指标方面考虑。

您的数据科学项目的概念验证

创建一种灵活的方法来思考和执行您的数据科学项目将有助于您。将你的项目分成 2-3 周,邀请组织内的关键利益相关者参加你的计划会议。拥有一个易于理解的仪表板,展示您的概念验证,以便非技术领导者可以了解您的项目范围以及它试图解决的业务问题。

提出听起来诱人而时髦的数据科学项目很有趣,但如果没有政治意愿,如果不容易理解您的项目想法的相关性以及它们对业务的影响,最终,如果没有部署您的项目的基础架构,它们只是空中楼阁。

数据科学和分析很有趣,你可以走很多创造性的弯路。确保您尽最大努力帮助您的企业充分利用您的数据科学团队!

祝你好运!

Irene Bratsis,手势数据和分析团队

如何利用主数据改进数据分析:看看你错过了什么

原文:https://towardsdatascience.com/data-analytics-without-master-data-look-at-what-happens-531d19c27b2f?source=collection_archive---------17-----------------------

为什么主数据对于建立可靠的数据分析的重要性不可忽视。

由 Unsplash 上的 krakenimages 拍摄的照片

给我一个足够长的杠杆和一个支点,我可以撬动地球”这是阿基米德的一句名言。如果我们想将其转化为现代数据科学世界,这将是类似于“给我一个强大的主数据,我将建立所有可能的分析”。

当接近数据科学时,许多人专注于数据分析、数据可视化和数据收集,忘记了整个数据科学的一个基本构建块:主数据。

Y 你可以获得公司的所有数据,但如果你的主数据不有序,成功的可能性就很低。

你最终可能会得出错误的结果,或者更糟糕的是,使用不可靠的数据。

这就是为什么我的强烈建议是当一个分析数据程序开始时,总是在其中包含一个强大的主数据块。

在本文中,我将解释确保主数据可靠所需的关键构件是什么。通过这样做,你的分析将是值得的。

以下是要解决的五个主题:

  • 数据范围:第一步是定义哪些数据是运行数据策略的关键。你关注的是会计科目表、成本中心或利润中心层级,还是产品和物料主数据?
  • 数据所有权:一旦范围明确,你必须澄清谁拥有那些数据。这是最基本的,因为所有者应该定义使用数据所需的质量水平。他/她还必须知道数据测量的是什么,以及如何使数据更加可靠。我在这里的建议是将所有权尽可能地放在靠近数据使用者的地方。这将确保他们明白自己在谈论什么,以及他们关心这个事实。尽量避免将所有权放在某个公共职能(即 IT)中,因为这可能会导致缺乏所有权、缺乏知识或(甚至更糟)对主题的关注度低下;
  • 数据模型:对您所拥有的数据拥有完全的清晰和控制是理解数据从何而来、如何转换以及如何使用的关键。这就是数据模型的作用。在复杂的 ERP 或系统环境中,要绘制强大的数据模型,您需要一些数据架构师。但你可能会选择只对某些数据有一个详细的数据模型,这些数据潜在地被转换了很多次,从而了解是谁接触了它们,如何让它们变得可靠;
  • 数据质量 KPI:如果你的数据质量很差,那么你的分析也会很差。你可能想要定义你想要达到的质量水平,意识到你想要的质量越高,你付出的代价就越大。对于您对这些数据的使用,90%的质量水平是可以接受的。我的建议是尽可能自动化数据质量计算,以便从中消除情绪和偏见。我们开发的一种方法是每周从关键的标准 ERP 表中获取信息,并将它们与某些标准进行比较。这创建了一组自动化且可靠的 KPI,人们可以跟进以实现定义的目标;
  • 建立数据组织:数据管理员需要被任命,对他们所做的事情有很强的所有权和责任感。他们必须得到授权和培训,以充分理解他们所做的事情的好处。解释如何使用他们的数据(即掌握数据模型)将使他们能够专注于对分析有影响的事情;
  • 沟通分析和主数据:即使许多人认为分析是数据科学中很酷的部分,但这两者不能分开。考虑让两个团队一起工作,以便对数据有一个整体的方法,了解它们在哪里和如何产生,以及它们将在哪里被使用。左手必须知道右手会做什么。否则,风险在于关注点不同。一个强大的数据科学团队必须嵌入强大的主数据人员才能成功:他们识别数据之间的关系,解释在哪里可以找到正确的数据以及如何连接它们。

即使是最好的数据科学团队也需要主数据才能成功。

数据科学的关键是读取可靠的数据并自动化,降低复杂性,预测未来。如果你在你很难阅读和相互联系的数据上做所有这些,你的结果将是有限的。

万花筒在 Unsplash 上拍摄的照片

让数据分析团队与主数据团队一起工作,拥有相同的尊严,将增强整个组织的能力。我有时会说“我们坐在数据的金山上。让我们使用它!”。

绘制一个强大的仪表板肯定是一项伟大的工作,但如果你用正确的数据点,你的最终结果会更好!

数据!数据数据!没有粘土我做不了砖!阿瑟·柯南·道尔,作家和医生

Luca Condosta(博士)是一名金融专业人士,拥有跨国企业的全球经验。对数据、领导力、战略和人充满热情。他是两本书的作者(可持续发展报告和Natuzzi——意大利和谐制造者),他喜欢寻找和分享故事。

数据和物理基础设施

原文:https://towardsdatascience.com/data-and-physical-infrastructure-510fd0803ea3?source=collection_archive---------66-----------------------

当我刚开始为锡拉丘兹市工作时,团队的第一项任务是帮助寻找新的解决方案,以应对该市日益老化和日益失败的基础设施。当我试图分析数据时,我越来越清楚地发现,这座城市的数据基础设施也在老化和失效。

在本文中,我将使用术语“数据基础设施”来反映处理和移动数据的管道和技术。我将使用术语“物理基础设施”来反映下水道、卡车、街道和水管。虽然这个比喻并不总是完美的,但有足够多的相似之处,我认为这种比较是有用的。

基础设施用途

我们构建物理基础设施来帮助我们一次又一次地完成任务。虽然我们可以去最近的湖中取水,但这既费时又难以运输。然而,我们中只有一个人负担不起修建从湖边直接通到我们家的管道。相反,一个多世纪以前,在锡拉丘兹,居民们集体投资建设了一个管道网络,将水从斯卡涅阿特尔斯湖引入城市。这一举措使得从湖里向我们家输送水更加快捷可靠。稍后将详细介绍。

类似地,我们个人可以去搜索我们想要的数据,从数据源下载,带到我们自己的工作空间,然后使用它。但是我们可能不知道去哪里找,或者其他人可能已经做了类似的工作,所以我们投入的时间不值得。相反,我们构建数据管道,从源获取数据,移动和转换数据,这样就可以在数据仓库中可靠地使用数据。单个员工无法建立这一管道,但整个组织可以齐心协力投资并实现这一目标。

只有在它坏掉的时候才会注意到

每天早上,你可能会醒来,从水龙头里拿一杯水喝。如果是你的垃圾日,你会把垃圾桶拿到街上去捡。你洗澡。你开车去上班(至少在前 COVID 时代)。你可能不太想把水送到水龙头的水管,把水和废物带走的下水道,捡垃圾的环卫工人,或者支持你的车辆的道路。但是,如果你所在街区的总水管破裂,你将没有水,你会立即注意到。如果下水道堵塞,你存放在地下室的贵重物品可能会被毁掉。如果环卫工人错过了你的街道,你会有多余的垃圾,如果你撞到了一个坑,你可能需要昂贵的修车费用。当物理基础设施起作用时,你不会注意到它。当它坏了,你肯定会。

类似地,对于数据基础设施,你的老板可能依赖于每天更新的仪表板,或者居民可能会检查网站以查看许可的状态。当数据管道工作时,人们得到他们需要和想要的信息。当数据管道中出现错误时,仪表板或网站不会相应地更新。决策可能会延迟或做出错误。

需要投资和更新

有形基础设施可以持续数年甚至数十年,但需要不断投资和更新,否则在某一点上,它将达到其使用寿命的终点,并可能开始失效。此外,随着新方法和技术的学习,效率、节约和更长的寿命都可能发生。当锡拉丘兹第一次安装水管时,使用的是木制管道。多年来,人们使用了不同的材料,如铸铁。一些城市现在使用聚氯乙烯管做水管。

对于数据基础设施,服务器需要升级,收集或显示数据的软件需要采购,这就需要编写新的代码来移动和转换数据。如果不小心,服务器会停机,数据管道会中断。因为物理和数据基础架构在正常工作时都没有被注意到,所以它们通常缺乏确保持续运行所需的持续投资。一些物质基础设施实际上是在地下。数据基础设施也是隐藏的,隐藏在所有人都不理解的代码和软件后面。

物理基础设施使我们能够在日常生活中像我们期望的那样运作。它需要集体投资、个人专长和持续的维护。通常,由于我们习惯了物理基础设施的正常运行,我们忽略了持续的投资。同样,数据基础设施使我们能够访问和了解我们组织中的事情是如何运作的。它也需要专业知识和持续投资。

在以后的文章中,我将更深入地探讨物理和数据基础设施的比较。

基于 Presidio 的 Azure 数据匿名化 ETL

原文:https://towardsdatascience.com/data-anonymization-etl-on-azure-using-presidio-55323eba60e9?source=collection_archive---------19-----------------------

创建数据管道以从文本中移除私有数据

马库斯·斯皮斯克在 Unsplash 上的照片

数据匿名化或去标识化是某些系统的关键部分,也是许多组织的核心要求。通过用文本和图像中的模仿实体来屏蔽、散列甚至替换 PII 实体的能力所揭示的场景包括将数据移动到云或合作伙伴,从真实数据生成测试数据,存储数据以供 AI/ML 处理等。

下面的文章演示了如何使用 Azure 和 Presidio 创建一个全功能的 ETL 流程,将一组文档从一个位置移动到另一个位置,同时对文本中的 PII 实体进行清理、替换、散列或加密。

普雷西迪奥和生态系统

一些读者可能已经知道了 Presidio ,这是一个 PII 身份识别和匿名库,由商业软件工程小组作为微软开源项目维护。该团队最近发布了一个新版本 V2.0,主要目标是简化 Presidio 的评估并支持集成到数据管道中。

作为 V2.0 版本的一部分,Presidio 团队提供了不同的部署示例,如 Kubernetes(presi dio V1 本地且唯一的部署选项)、Azure App Service(该团队将其用于内部 V2.0 开发和生产环境)等。

这篇文章将关注如何使用内置的“Presidio 数据匿名化”模板将 Presidio 与 Azure 数据工厂集成,该模板是该团队与 Azure 数据工厂产品组合作开发的。它是为那些已经拥有 Azure Data Factory 实例和存储帐户的数据工程师准备的,他们希望匿名化 PII 数据的内容。

此外,Presidio 生态系统包括 presidio-research 存储库,团队在其中维护使用 presidio 的高级场景。例如,presidio_evaluator 库使用 presidio 在分析真实数据的基础上生成假数据。

Azure ETL 的构建块

这篇文章中涉及的场景采用了一个通用类型的输入数据集,一个 Azure 存储 blob 容器,并使用 Azure 服务将该数据集移动到另一个位置,在那里文件的内容已经对所有 PII 实体进行了匿名化。

使用的 Azure 服务有:

Azure Data Factory——一个基于云的 ETL 服务,它将托管转换管道。

Azure Storage —提供 ETL 持久层。

Azure Key-Vault —以安全的方式存储 Azure 存储访问密钥,以便在 ETL 中使用。

Azure App Service —托管 Presidio 作为 HTTP REST 端点。

下图显示了使用 Presidio 作为 HTTP 端点的 ETL 系统各部分之间的关系。

以 Presidio 为 HTTP 端点的数据匿名化 ETL

1.从源读取数据集。

2.从 Azure Key Vault 获取 Azure 存储的访问密钥。

3.将集合中每个文档的文本值发送给 Presidio 进行匿名处理。

4.将匿名文本保存到 Azure Blob 存储上随机命名的文本文件中。

数据匿名化管道的输入是一组包含 PII 文本的文档,例如:

文本输入文件

管道的输出文件应该如下所示:

文本输出文件

提供 Azure 服务

如果你已经有一个 Azure 数据工厂实例,从 Azure 数据工厂 UI 浏览到模板库,搜索名为“使用 Presidio 的数据匿名化”的模板。按照屏幕上的说明配置先决条件基础架构,并连接您的 Azure 存储输入容器。

使用预签名模板的数据匿名化

如果您没有 Azure 数据工厂的实例,您可以继续使用 Presidio 端到端示例,展示 Presidio 到数据工厂的两种集成模式(作为 HTTP 端点和作为 Databricks Spark 作业)。这些示例还将提供 Azure 数据工厂并设置所需的管道,而不使用带有 Presidio 模板的数据匿名化。

运行样本

从 Azure 数据工厂 UI 打开名为 Anonymize 的管道。

匿名化管道活动

使用 Presidio 模板库进行数据匿名化

  • 获取文件列表 —从源容器中获取文件列表。
  • FilterFiles —从列表中过滤目录,只处理文件。
  • foreach file—For-Each 循环,包括数组中每个文档的执行子句。
  • GetSASToken —从 Azure Key Vault 获取 SAS 令牌。将在以后用于写入 blob 容器。
  • LoadFileContent — 将文本文件的内容加载到数据集中。
  • PresidioAnalyze —将文本发送到 Presidio analyzer 端点。
  • Presidio 匿名化 —将来自 presidio 分析器的响应发送到 presi dio 匿名化器端点。
  • UploadBlob —将来自 Presidio 的匿名响应保存到目标 Azure Blob 存储上的文本文件中。

点击调试按钮,并填写以下管道参数:

  • SourceStore_Location — 源容器名称。
  • 目标存储名称— 目标帐户名称。
  • 目标存储位置— 目标容器名称。具有在提供 ARM 模板(presidio)期间创建的容器的默认值。
  • 密钥库名称— Azure 密钥库名称。
  • Analyzer_Url — Analyzer 应用程序服务 Url。
  • 匿名器 _Url — 匿名器应用服务 Url。

随着管道的运行,您应该会看到在目标 blob 容器上创建的文件,其中的数据是匿名的 PII 内容。

结论

Presidio V2.0 带来了巨大的变化,并为 Presidio 社区带来了比以前更多的利用平台的机会。

本文中详细描述的示例可以很容易地修改,以适应其他 ETL 场景,例如:

  • 更改匿名化方法 —您可以将本示例中使用的匿名化机制从简单的替换实现更改为任何受支持的匿名器,作为所有实体类型或特定实体类型的默认匿名器。您也可以加密 PII 数据,并在以后使用解密重新打开它。
  • 其他输入/输出 —从 MongoDB、Elasticsearch 或其他来源读取 JSON 数组,并将清理后的数据移动到另一个实例。
  • 混合工作流 —使用混合 Azure 数据工厂工作负载的预览和本地 Hortonworks Hadoop 集群,在数据离开组织场所之前对其进行匿名处理。
  • 流数据 —更改笔记本以使用 Spark-streaming 来实现仅分析管道,该管道在传输中的消息从一个事件源传输到另一个事件源时对其执行。

我们邀请您加入不断发展的 Presidio 社区,贡献示例、文档、错误修复或问题,或者直接联系 presidio@microsoft.com 的团队。如果您有任何问题,或者想和我们谈谈您使用 Presidio 的大规模场景,我们非常乐意!

使用雪花和 DBT 的数据匿名层

原文:https://towardsdatascience.com/data-anonymization-layer-using-snowflake-and-dbt-c5f84e398358?source=collection_archive---------7-----------------------

图片来自爱丽丝·罗玛

使用 DBT 匿名化雪花上数据的可扩展方法

HousingAnywhere 是一个面向中长期租赁的在线市场平台。像任何其他数据驱动的业务一样,我们必须处理个人信息和 GDPR 法规。在这篇简短的文章中,我将向你介绍我们匿名化 PII (个人身份信息)的解决方案。我将使用的技术是https://www.snowflake.com/【1】一个流行的数据仓库云解决方案和DBT【2】(数据构建工具)一个数据转换工具。****

从一些上下文开始;每天,我们的报告和分析都是由我们从各种来源获取的数据提供的,涵盖了我们业务的各个方面。这就产生了一个问题,我们如何防止用户和服务不必要地访问暴露 HousingAnywhere 客户端 pii 的原始数据?**

**from
┌──────────────────┬──────────────────────┬─────────┐
│       NAME       │         EMAIL        │ COUNTRY │
├──────────────────┼──────────────────────┼─────────┤
│ Tommaso Peresson │ [placeholder@mail.com](mailto:tompere96@gmail.com) │ IT      │
└──────────────────┴──────────────────────┴─────────┘to
┌──────────────────┬──────────────────────┬─────────┐
│       NAME       │         EMAIL        │ COUNTRY │
├──────────────────┼──────────────────────┼─────────┤
│ 87444be...eb6b21 │ 3c33076...e1ceaf     │ IT      │
└──────────────────┴──────────────────────┴─────────┘**

简介

数据仓库配置

为了使这个解决方案有效,您的数据仓库中需要两个区域:第一个阶段存储来自外部源的所有原始数据,另一个阶段容纳匿名化转换的结果。为此,我将创建两个数据库,分别命名为 PRIVATE_SOURCESSOURCES 。如果你需要一些帮助来达到这个阶段,请遵循这个指南。

图片来自 Tommaso Peresson

另一个关键要素是管理访问控制和权限,以便 PRIVATE_SOURCES 数据库只能由管理员和数据工程师访问,而 SOURCES 数据库可以由任何人访问。我不会深入讨论这个话题,但是如果你想了解更多关于特权和访问控制的知识,请阅读本文【4】。

我们还需要一个包含要影响的列名及其各自的匿名方法(anonymization_mapping)的信息的表,以及一个包含用于安全散列的https://en.wikipedia.org/wiki/Salt_(cryptography)【5】的表。****

匿名化层

如果没有匿名化,任何有权访问数据仓库的人都可以窃取和使用个人信息。泄露数据就像输入**select * from users**一样简单。从这个 pos t[6】中得到启发,我们决定使用 DBT 构建一个匿名化层。

让我们通过查看一个我们想要匿名的模型中的最终用法的例子来开始揭示我们的解决方案。

正如您可能看到的,在 select 之后有一个宏调用。这是为了取代*操作符并增加匿名化转换。我们的目标是找到一个可维护和可伸缩的解决方案,它不是文本密集型的,因为我们有数百个表,手动选择每一列当然不是一个很好的解决方案。让我们深入到宏中去理解实现细节。

深入研究实现

让我们来看看组成这个系统的两个 DBT 宏。

1。从anonymize_columns()开始,这个宏的目的是替换*操作符,并向特定列添加匿名化转换。

我们可以说这个宏执行两种不同的操作:

1.1 创建映射

(**rows 2:13**)从[private_sources.information_schema](https://docs.snowflake.com/en/sql-reference/info-schema.html).columns中获取所有的列名,并用列名上的anonymization_mapping将它们连接起来。因此,我们将有一个包含 object 中的表的列的表,并与正确的匿名化函数配对。例如users表有三列:nameemailcountry。在我们的具体例子中,我们可能只想匿名化nameemail列,而不去碰country**

要做到这一点,我们的anonymization_mapping将必须包含这两行,指示哪些列必须被转换以及使用哪个函数:

**ANONYMIZATION_MAPPING (config)
┌───────────────────┬─────────────┬───────────┐
│ TABLE_NAME_FILTER │ COLUMN_NAME │ FUNCTION  │
├───────────────────┼─────────────┼───────────┤
│ production.users  │ name        │ full_hash │
│ production.users  │ email       │ full_hash │
└───────────────────┴─────────────┴───────────┘**

在将它与语句中包含的查询中的information_schema.columns连接之后,映射将如下所示

**mapping (sql statement output)
┌───────────────────┬─────────────┬───────────┐
│ TABLE_NAME_FILTER │ COLUMN_NAME │ FUNCTION  │
├───────────────────┼─────────────┼───────────┤
│ production.users  │ name        │ full_hash │
│ production.users  │ email       │ full_hash │
│ NULL              │ country     │ NULL      │
└───────────────────┴─────────────┴───────────┘**

注意我们也可以将anonymization_mapping中的TABLE_NAME_FILTER留空,这将匿名化每一列的匹配名称,而不通过表过滤 。这在我们有多个具有相同列名的表必须匿名的情况下很有用。****

1.2 打印字段名及其转换

(**rows 14:27**)这部分宏使用上一步(mapping)的输出,通过将列名映射到正确的匿名函数,打印出要放入select语句中的正确的列名函数。例如,遵循上一个示例时,宏的输出将是:

**SHA256(name) as name,
SHA256(email) as email,
country**

最终编译后的模型如下所示:

**select
 **SHA256(name) as name,
 SHA256(email) as email,
 country**
from 
 private_sources.production.users**

有效地匿名化了表中的敏感内容。

2。第二个宏用于分组并轻松使用不同的匿名化转换。这只是将选择的转换应用到一个列。为了展示它的用法,我包含了两种不同的方法,一种是散列整个单元格的内容,另一种是对单元格的内容应用一个 REGEX 来仅匿名化电子邮件地址的用户部分。

**FROM: [tompere@housinganywhere.com](mailto:tompere@housinganywhere.com)
TO: SHA256(tompere+salt)@housinganywhere.com**

同样重要的是要强调,无论何时使用散列函数,都需要添加,否则我们的散列将容易受到 字典攻击。

结论

GDPR 法规的目的是提高消费者对持有和处理个人数据的组织的信心,以及标准化和简化欧盟范围内的信息自由流动。在 HousingAnywhere 中,我们始终相信,用户的隐私是建立对我们平台的信任和信心的关键,这也是我们在设计数据基础设施时如此小心的原因。

最后,还应该提到一个事实,即 Snowflake 提供了一个现成的匿名化解决方案,名为动态数据屏蔽,仅适用于企业账户。

感谢 Julian Smidek 成为如此伟大的经理人:)

[1] DBT 云。2021 年 5 月 20 日访问。https://cloud.getdbt.com/。

[2] DBT 话语。PII 匿名化和 DBT——建模”,2018 年 4 月 26 日。https://discourse.getdbt.com/t/pii-anonymization-and-dbt/29

【3】第二步。创建雪花对象—雪花文档。2021 年 5 月 20 日访问。https://docs . snow flake . com/en/user-guide/getting-started-tutorial-create-objects . html。

[4] 《雪花特权与访问控制综合教程——特雷弗的代码》。2021 年 5 月 20 日访问。https://trevorscode . com/comprehensive-tutorial-of-snow flake-privileges-and-access-control/。

[5] 盐(密码术)。2021 年 5 月 17 日,维基百科。https://en.wikipedia.org/w/index.php?title=Salt_(密码术)& oldid=1023634352 。

【6】雪花。数据云|雪花|支持最关键的工作负载'。2021 年 5 月 20 日访问。https://www.snowflake.com/。

数据匿名化:一位前怀疑论者的观点

原文:https://towardsdatascience.com/data-anonymization-perspectives-from-a-former-skeptic-f35790a2042a?source=collection_archive---------30-----------------------

行业笔记

来源:https://unsplash.com/photos/1tnS_BVy9Jk

在的上一篇文章中,我回顾了匿名化、去标识化、编辑、假名化和标记化的定义。如果您不知道这两个术语之间的区别,这是一个很好的起点。

最相关的是,匿名化的定义是“可识别个人身份的数据被改变的过程,这种改变的方式使其不再能与给定的个人联系起来”( IAPP 隐私术语表)。在实践中,匿名化实际上意味着被篡改的数据与特定个人相关联的可能性“微乎其微”。

当我第一次开始从事隐私增强技术的工作时,我一直生活在同态加密中。我非常不信任匿名化,并认为任何不这么认为的人都不了解事实。毕竟,辛西娅·德沃克(Cynthia Dwork)有一句名言“匿名化数据不是”,她因在差分隐私方面的突破性研究而闻名。

你见过多少次像下面这样的头条(黑暗日报)?

所以匿名化是行不通的吧?

我真的这么认为。我相信标题和专家暗示匿名化是无效的。作为我博士学位的一部分,我决定详细研究这些重新识别攻击,研究已经重新识别的数据,以及在数据集中重新识别的记录的百分比:

“我们发现,通过将记录的未加密部分与个人的已知信息(如医疗程序和出生年份)关联起来,可以在不解密的情况下重新识别患者”(黑暗日报)

或者

“2016 年的一项研究发现,使用年龄、性别、医院和年份等数据将麻醉记录与 2013 年德克萨斯州住院患者公共使用数据文件进行匹配的风险为 42.8%。”(HIPAA 去识别数据集中的再识别风险:MVA 攻击)

“[Sweeney]然后能够唯一地识别出州长 Weld 的医疗记录。她注意到,剑桥只有 6 名选民与州长的出生日期相同,其中只有 3 名是男性,而且只有一名选民与州长住在同一个邮政编码区。(HIPAA 去识别数据集中的再识别风险:MVA 攻击)

我发现,这些标题中提到的数据集的真正问题是,它们从一开始就不是真正匿名的:它们包括准标识符(例如,出生年份、年龄、性别、大致位置),这些标识符在发布时没有考虑人口和数据集统计数据。所以这并不是说数据集被完全匿名,也不是说重新识别它们很容易。事实是,这些数据集被错误地标记为匿名。他们从一开始就不配拥有这个称号。

这部分是由于社区经历了学习曲线,以理解为了完全匿名化数据集需要做什么。起初,人们认为简单地删除直接标识符(全名、社会保险号等)。)就行了。发现准标识符如何影响在数据集中重新识别一个个体的可能性,需要一些磕磕绊绊。

这些观点在埃尔·埃马姆、k .容克、e .阿巴克尔、l .和马林的《对健康数据的再识别攻击的系统综述》中得到证实,其中涵盖了对再识别攻击的严重性或有效性的误解。在这篇文章中,作者指出,根据现有标准,只有一次对真正匿名的数据成功进行了重新识别攻击(见下表中的 K),即使是这一次攻击,重新识别风险也只有 2/15000——远低于 HIPAA 安全港的可接受的重新识别风险阈值 0.04% 。

他们在下表中总结了他们的发现:

图片:对去标识数据集的重新标识攻击列表。14 次攻击中只有两次是针对适当匿名化的数据集。这些攻击中只有一个( K )的重新识别得到了验证。15,000 个记录中有 2 个被重新识别。感谢哈立德·埃尔·埃马姆教授允许我复制这张表格。

该表中的来源 57 和 58 不容易在网上找到,也没有列在多伦多大学的图书馆目录上,所以挖掘导致重新识别 15,000 条记录中的 2 条的弱点并不容易。作为参考,这两篇论文是:

  • 57.《比你想象的更难:符合 HIPAA 的记录的再识别风险的案例研究》。芝加哥:芝加哥大学的 NORC。摘要# 302255;2011.[ 谷歌学术
  • 58.去认同的安全港方法:实证检验。2010.第四届国家 HIPAA 西部峰会。

多亏了研究人员和记者的重新识别攻击,以及 k-匿名、l-多样性和 t-紧密度等概念,隐私社区开始理解匿名化在不同视角下的含义。这些概念考虑了基于个人的准识别符的重新识别的可能性,以及如何以最佳方式汇总这些准识别符,以最大限度地降低重新识别的风险。为了理解这三个概念,包括它们的局限性和优势,一篇理想的论文是 2007 年由李宁辉、和 Suresh Venkatasubramanian 撰写的名为t-closey:Privacy Beyond k-anonymous and l-diversity的论文。

匿名化方法已经成功地用于许多临床试验数据集,目的是共享研究数据。2015 年由哈立德·埃尔·埃马姆、萨姆·罗杰斯和布拉德利·马林撰写的题为匿名和共享个人患者数据的论文中引用了四个最近的例子;即:

  • 葛兰素史克试验储存库
  • 数据球项目
  • 耶鲁大学开放数据访问项目
  • 进口免疫学数据库和分析门户

总之,匿名化远非易事。甚至需要多年的专业知识和经验来适当地概念化准标识符如何影响再识别风险。这个术语经常被记者和公司完全误用。

致谢

感谢 John Stocks 和 Pieter Luitjens 对本文早期草稿的反馈。

数据分析应用

原文:https://towardsdatascience.com/data-applications-for-analytics-817d4761211c?source=collection_archive---------23-----------------------

弥合技术用户和非技术用户之间鸿沟的新一代工具

张杰瑞在 Unsplash 上拍照

莎拉·克拉斯尼克 合著。

2021 年,现代数据堆栈将成为热门话题。正如特里斯坦·汉迪去年预测的那样,数据工具正在发生“寒武纪大爆发”。随着公司和开源项目争相填补空白,见解开发和交付的方式正在被重塑。在所有的新来者中,有一点变得越来越清晰:灵活性是王道。仪表板和点击式 BI 工具虽然不够灵活,却越来越不足以满足数据分析师和消费者的需求。

构建数据应用程序的全新一代工具将取代它们,提供仪表板般的易用性,在后端和前端都有更大的灵活性。

现状怎么了?

2021 年,随着数据堆栈的其余部分以极快的速度成熟,老派仪表板不再足以作为数据分析的标准输出。

对于数据分析师来说,它们通常是不够的,被迫将他们的工作放入一系列缺乏上下文的瓦片中。他们几乎总是不能满足数据科学家的需求,无法轻易地将他们的建模结果反馈到点击式仪表板工具中。即使对于专业的仪表板构建者来说,它们也可能是不够的,他们注定要永远尝试从充满方形瓷砖和不灵活的过滤器的页面中“制作一个故事”。

商务智能工具尽管有强大的功能,但也有严格的限制。用户可以很容易地阅读数据,但这种用户友好的界面是一把双刃剑,既阻碍了报告的灵活性,也影响了它们的交互性。他们通常还局限于基于 SQL 的分析,对数据团队用其他语言完成的大量工作关上了大门。

仪表板的主要吸引力在于,一般来说,它们对仪表板的消费者来说已经足够了——或者至少比其他选择更充足。对于需要对数据采取行动的利益相关者来说,仪表板是标准布局的,非常容易使用,最重要的是,加载和读取不需要任何技术开销。

这与 Jupyter 笔记本形成对比,Jupyter 笔记本非常适合更复杂的数据分析,但实际上不能与非技术利益相关者共享。这同样适用于无数其他交付数据分析的聪明方法:你可以构建惊人的东西,但是它们没有用,因为没有人可以使用它们。每个人都可以点击一个链接打开一个简单的仪表板。

但是每个人都可以使用 Excel 电子表格、谷歌文档、Powerpoints 和 pdf。BI 工具仪表板作为丰富分析工具的不足并没有阻止这种分析的发生,它只是在大多数组织内创建了一个即席数据工作的“黑市”。亲爱的读者,看着你的眼睛,大声发誓你从未发送或接收过 ModelOutput-final(1)。csv,或者从 Jupyter 笔记本中截取一张截图复制到幻灯片中,或者从您的 BI 工具中下载一份报告并在 Excel 中打开,这样您就可以调整它不让您做的一件事情。

我想是的。

这是仅仅依赖仪表板作为数据世界的标准输出的真正问题。这不仅仅是因为它们本身不足以作为复杂数据分析的工具。而是它们的缺点引发了混乱的下层社会,甚至是更糟糕的数据产品,它们通常是静态的和陈旧的。

数据应用

那么有什么更好的办法呢?其实也没那么开创性。等式的分析端的每个人都希望有更大的灵活性,消费端的每个人都希望简单——尽管不能以牺牲交互性为代价。双方都同意这样一个事实,没有版本的松散文档到处乱飞是令人困惑的。

“数据应用”是各种不同数据产品的总称,既允许丰富的分析又允许简单的展示。数据应用程序可能看起来非常多样化——一个简单的点击式仪表板,一个带有实时图表的故事式文档,一个两按钮转换工具——但它们总是呈现简单而简洁的输出,掩盖了非常灵活的分析后端。像网站一样,数据应用程序可以独立存在,并且可以很容易地与广大受众共享。

Excel 电子表格实际上是(初级)数据应用程序的一个很好的例子!丰富的灵活性和复杂性对于技术先进的分析师来说是可用的,但是对于最终用户来说却是一个非常简单的交互式界面。也许 Excel 不是最前沿的例子,但它突出了数据应用的可能性范围。

对于那些怀疑 Excel 灵活性的人…

一些大型组织通过构建定制的数据应用解决了这一问题,这些应用具有由他们自己的工程团队创建的自制基础架构和框架。虽然可以定制这些一次性的数据应用程序来满足任何需求,但是开发和维护它们的开销非常高。这种方法对于 99%的团队来说是不值得的。

数据团队不需要接触一大群等着将他们的笔记本变成成熟的网络应用的网络开发人员。他们当然不需要自己学习如何将这种能力带入内部。数据团队只需要一个框架做分析,自己分享;最有效的解决方案是在数据应用工具领域,而不是手工制作的一次性网络应用。

街区里新来的孩子

这一领域出现了新一代工具,使数据团队能够为其组织的其余部分快速构建数据应用程序。除了允许分析师创建更灵活的数据接口之外,这些工具还将分析和输出紧密结合在一起,而不会在多个工具之间产生碎片。这意味着数据从业者可以使用他们想要的任何语言和框架,而不需要通过截屏或导出来脱离现实。

闪亮 多年来已经帮助 R 用户做到了这一点,无需编写一行非 R 代码就可以构建交互式应用。StreamlitDash让用户不用离开 Python 就能做同样的事情,Python 已经成为数据界最流行的脚本语言。Hex采取混合的方式,让用户用 Python 和SQL 做分析,然后用一个拖放 app builder 来构造数据应用。****

所有这些工具都旨在弥合技术数据从业者和非技术数据消费者之间的共享鸿沟,而无需任何一方做出牺牲。这是数据应用的承诺——丰富的分析、易于共享和消费的输出、低开销。

数据(应用)驱动的未来

数据从业者应该继续使用他们熟悉的任何语言和框架,而不必在与利益相关者分享结果时求助于一次性导出、孤立的屏幕截图或不灵活的 BI 工具。

数据消费者应该能够方便地获得对操作有用的交互式数据产品。他们永远不需要在一个输入发生变化的情况下向数据团队请求新的 csv 转储。他们也不应该通过同样令人厌倦的报纸仪表板布局来阅读每一份报告!

标准仪表板值得休息!几十年来,我们一直在努力满足每个人对优秀数据报告的期望。他们可以休息一下,然后继续做他们擅长的基本顶级 BI 报告。他们当然应得的。

松散的 csv 文件和陈旧的幻灯片是罪有应得……无论发生什么。对不良数据毫不留情。

随着现代数据堆栈的不断扩展,数据团队在处理和共享分析时将拥有比以往更多的选择。数据应用和构建它们的工具的兴起将保持数据分析的协作性、交互性,最重要的是:实际有用****

NB: Davis Treybig 最近为 TDS 撰写了一篇优秀的文章*,涵盖了类似的领域,其角度是面向最终用户/产品化的数据应用。这是一个很好的后续阅读,但谈论的是一个完全不同类型的数据产品。***

使用过这些工具中的任何一种,还是我忘记提到的另一种?认为我对 csv 文件造成了伤害?我希望听到所有的反馈。推我@ isidoremiller**

使用 Python 的 Streamlit 的数据应用

原文:https://towardsdatascience.com/data-apps-with-pythons-streamlit-b14aaca7d083?source=collection_archive---------3-----------------------

以最快的方式将脚本转换成应用程序的基础知识

Streamlit 是一个易于使用的框架,非常适合构建 web 应用程序,而无需纠结于布局、事件处理程序或文档树。

其友好的方法使其成为探索数据集、展示机器学习模型、计算机视觉、自然语言处理、数据可视化和许多其他以数据为中心的项目的一个伟大工具。

快速回顾—由作者使用 Streamlit 制作—图片

在本文中,我们将构建一个简单的应用程序来使用 Streamlit 探索和转换数据集。

入门指南

安装之后,我们将创建一个名为app.py的文件,并从一些简单的东西开始。

#/app.py
import streamlit as st #pip install streamlitst.title('Explore a dataset')

在我们的环境终端中,我们可以转到保存脚本的目录,使用下面的命令运行 Streamlit,一旦启动,它将打开我们的默认浏览器并显示我们的页面。

streamlit run app.py

Streamlit run —作者截图

没有地方比得上 localhost—作者截图

厉害!现在让我们添加一些文本到我们的文件,并再次保存它。

一旦我们保存,Streamlit 将检测到更改,并让我们重新运行或总是重新运行页面。

# app.py
import streamlit as stst.title('Explore a dataset')
st.write('A general purpose data exploration app')

重新运行按钮—作者截屏

如果 Streamlit 由于某种原因没有检测到更改,或者没有任何更改,但是您想要重新运行它,您可以在右上角的菜单中找到此选项。

更新页面—作者截图

导入数据

我想构建一些简单的东西来对数据集进行一些快速的预探索和转换。在开始分析之前,我可以在某个地方验证数据并做一些小的调整。

我们可以从通常的pd.read_csv(file_path)开始。但是我想要更动态的东西,我可以改变文件,而不必写代码。

import streamlit as stst.title('Explore a dataset')
st.write('A general purpose data exploration app')file = st.file_uploader("Upload file", type=['csv'])st.write(file)

文件上传者—作者截图

就这样,我们有了一种将文件上传到应用程序的方法。如果没有上传文件,它将返回 None,但是如果我们上传了一个扩展名正确的文件,它会给我们一个包含该文件的对象。

返回的对象是 BytesIO 的子类,我们可以像使用任何其他文件一样使用它——这意味着我们用 Pandas 读取它不会有任何问题。

文件上传者—作者截图

写作

我们可以检查文件是否已上传,然后毫不费力地用熊猫阅读。让我们获取一些关于数据集的信息,并尝试显示它。

import streamlit as st
import pandas as pddef explore(df):
  # DATA
  st.write('Data:')
  st.write(df) # SUMMARY
  df_types = pd.DataFrame(df.dtypes, columns=['Data Type'])
  numerical_cols = df_types[~df_types['Data Type'].isin(['object',
                   'bool'])].index.values df_types['Count'] = df.count()
  df_types['Unique Values'] = df.nunique()
  df_types['Min'] = df[numerical_cols].min()
  df_types['Max'] = df[numerical_cols].max()
  df_types['Average'] = df[numerical_cols].mean()
  df_types['Median'] = df[numerical_cols].median()
  df_types['St. Dev.'] = df[numerical_cols].std() st.write('Summary:')
  st.write(df_types)def get_df(file):
  # get extension and read file
  extension = file.name.split('.')[1] if extension.upper() == 'CSV':
    df = pd.read_csv(file)
  elif extension.upper() == 'XLSX':
    df = pd.read_excel(file, engine='openpyxl')
  elif extension.upper() == 'PICKLE':
    df = pd.read_pickle(file) return dfdef main():
  st.title('Explore a dataset')
  st.write('A general purpose data exploration app')file = st.file_uploader("Upload file", type=['csv' 
                                             ,'xlsx'
                                             ,'pickle']) if not file:
    st.write("Upload a .csv or .xlsx file to get started")
    return df = get_df(file)
  explore()main()

数据框-作者截图

write方法不仅仅用于文本;我们可以用它来显示列表、字典、Pandas 数据框、Matplotlib 图形、Plotly、Altair、Graphviz 以及许多其他内容。我们甚至可以通过设置参数unsafe_allow_html=True来编写 HTML。

输入

我们将使用slider来帮助我们对数据集的一部分进行采样,并使用multiselect来选择我们想要的列。

import streamlit as st
import pandas as pddef explore(df)...**def transform(df):
  # Select sample size
  frac = st.slider('Random sample (%)', 1, 100, 100)
  if frac < 100:
    df = df.sample(frac=frac/100)** **# Select columns
  cols = st.multiselect('Columns', 
                        df.columns.tolist(),
                        df.columns.tolist())
  df = df[cols]** **return df**def get_df(file)...def main():
  st.title('Explore a dataset')
  st.write('A general purpose data exploration app') file = st.file_uploader("Upload file", type=['csv']) if not file:
    st.write("Upload a .csv or .xlsx file to get started")
    returndf = get_df(file) **df = transform(df)**explore(df)main()

重新运行按钮—作者截屏

我们如何使用 Streamlit 设置输入非常简单,他们有一系列类似的组件来帮助我们构建应用程序。

文件 _ 上传器滑块选择 _ 滑块选择框多选颜色 _ 选择器文本 _ 输入数字 _ 输入文本 _ 区域时间 _ 输入日期 _ 输入

我们的页面开始变大,我仍然想添加更多的探索组件和更多的转换。

在这种情况下,侧边栏是一个方便的类。我们可以将控件添加到侧边栏,节省页面空间,但我想使用侧边栏来选择我们将使用应用程序的哪一部分。

import streamlit as st
import pandas as pddef explore(df): ...def transform(df): ...def get_df(file): ...def main():
  st.title('Explore a dataset')
  st.write('A general purpose data exploration app') file = st.file_uploader("Upload file", type=['csv', 
                                               'xlsx', 
                                               'pickle']) if not file:
    st.write("Upload a .csv or .xlsx file to get started")
    return df = get_df(file) **task = st.sidebar.radio('Task', ['Explore', 'Transform'], 0)** **if task == 'Explore':
    explore(df)
  else:
    transform(df)**

需要注意的是,使用 Streamlit 实现状态并不容易。

如果我们对 Transform 进行更改并转到 Explore,它将不会保存我们对数据框所做的更改,因为它将重新运行整个应用程序。在这种情况下,唯一不变的是我们上传的文件。

如果我们反其道而行之,文件仍然是一样的,但是来自 Transform 的所有其他输入将重置为它们的默认位置。

有一些变通方法——您可以实现一个简单的 DB 来存储来自用户的输入,并使用会话来了解他们是否已经发送了输入。

M Khorasani 写了一篇关于用 PostgreSQL 实现这一点的很棒的文章— 用 Streamlit 实现有状态架构。

布局

接下来,我们将添加一种方法来转换字段的数据类型。因此,当我们有一个数字或日期作为字符串时,我们可以在开始分析之前轻松处理它。

我们将使用一个循环为数据集中的每个字段创建一个输入。你可能会想象我们的页面会有很大一部分被这些控件填充,用于一些大的数据集。

侧边栏非常有用,我们可以用扩展器和栏给页面添加更多的组织。

import streamlit as st
import pandas as pddef explore(df): ...**def download_file(df, types, new_types, extension):
  for i, col in enumerate(df.columns):
    new_type = types[new_types[i]]
    if new_type:
      try:
        df[col] = df[col].astype(new_type)
      except:
        st.write('Could not convert', col, 'to', new_types[i])**def transform(df):
  frac = st.slider('Random sample (%)', 1, 100, 100)
  if frac < 100:
    df = df.sample(frac=frac/100)

  cols = st.multiselect('Columns'
                        ,df.columns.tolist()
                        ,df.columns.tolist()) df = df[cols]
  **types = {'-':None
           ,'Boolean': '?'
           ,'Byte': 'b'
           ,'Integer':'i'
           ,'Floating point': 'f' 
           ,'Date Time': 'M'
           ,'Time': 'm'
           ,'Unicode String':'U'
           ,'Object': 'O'}
  new_types = {}** **expander_types = st.beta_expander('Convert Data Types')** **for i, col in enumerate(df.columns):
    txt = 'Convert {} from {} to:'.format(col, df[col].dtypes)
    expander_types.markdown(txt, unsafe_allow_html=True)
    new_types[i] = expander_types.selectbox('Field to be converted:'
                                            ,[*types]
                                            ,index=0
                                            ,key=i)
  st.text(" \n") #break line** **# first col 15% the size of the second  
  col1, col2 = st.beta_columns([.15, 1])** **with col1:
    btn1 = st.button('Get CSV')
  with col2:
    btn2 = st.button('Get Pickle')** **if btn1:
    download_file(df, types, new_types, "csv")
  if btn2:
    download_file(df, types, new_types, "pickle")**def get_df(file): ...
def main(): ...main()

好吧。让我们完成将数据帧转换成可下载文件的download_file()方法;我们需要 pickle io 和 base64。

import streamlit as st
import pandas as pd
**import pickle
import io
import base64**...def download_file(df, types, new_types, extension):
  for i, col in enumerate(df.columns):
    new_type = types[new_types[i]]
    if new_type:
      try:
        df[col] = df[col].astype(new_type)
      except:
        st.write('Could not convert', col, 'to', new_types[i]) **# csv
  if extension == 'csv': 
    csv = df.to_csv(index=False)
    b64 = base64.b64encode(csv.encode()).decode()** **# pickle
  else: 
    b = io.BytesIO()
    pickle.dump(df, b)
    b64 = base64.b64encode(b.getvalue()).decode()** **# download link
  href = f'<a href="data:file/csv;base64,{b64}" download="new_file.{extension}">Download {extension}</a>'** **st.write(href, unsafe_allow_html=True)**...

更进一步

我们接触了向我们的应用程序添加内容的方法,了解了输入、侧栏和一些可以改善页面布局的测试组件。现在,您可以探索所有其他方便的 Streamlit 方法,查看社区创建了什么【1】【2】,甚至开发您的组件。

有些用户自制的组件可以帮助您快速构建应用程序。例如,我们可以用只有四行代码的 Pandas Profiling 替换我们的 Explore 部分。

from pandas_profiling import ProfileReport
from streamlit_pandas_profiling import st_profile_reportdef explore(df):
  pr = ProfileReport(df, explorative=True)
  st_profile_report(pr)

总的来说,Streamlit 是开发数据应用程序的一个很好的框架。你可以自动化一个过程,给它一个友好的界面,而不需要努力,随着社区的成长和积极的开发,会有不断的改进和创新。

您可以在这里找到本文中使用的代码的改进版本,在这里找到其现场版本。

感谢阅读我的文章!

资源: https://streamlit.io/;
https://pandas.pydata.org/docs/;
https://github.com/pandas-profiling/pandas-profiling;
https://github.com/okld/streamlit-pandas-profiling;
https://docs.python.org/3/library/io.html;
https://docs.python.org/3/library/pickle.html;
https://docs.python.org/3/library/base64.html;

数据作为产品与数据产品。有什么区别?

原文:https://towardsdatascience.com/data-as-a-product-vs-data-products-what-are-the-differences-b43ddbb0f123?source=collection_archive---------1-----------------------

通过例子理解“数据产品”和“数据作为产品”之间的异同

绿色绳网由克林特·王茂林在 Unsplash 上制作

自从 Zhamak Dehghani 的数据网格介绍文章发表以来,在数据网格环境内外,围绕什么是“数据产品”的定义已经有了很多讨论。

通过澄清本文中的几个定义,我们希望“数据产品”和“数据作为产品”的概念对于任何进入数据和数据网格世界的人来说都变得更加清晰。

数据产品

让我们从“数据产品”的一般定义开始。

美国前首席数据科学家 DJ Patil 将数据产品定义为“通过使用数据促进最终目标的产品”(摘自其著作Data Jujitsu:The Art of Turning Data into Product, 2012)。

这意味着,任何数字产品或功能都可以被视为“数据产品”,如果它使用数据来促进目标的实现。例如,如果我看到的主页中的新闻项目是基于我以前的导航数据动态选择的,那么数字报纸的主页可以是一种数据产品。

2018 年, Simon O'Regan 发表了一篇名为设计数据产品的文章,列出了非常清晰的数据产品示例,并按类型进行分组:原始数据、派生数据、算法、决策支持和自动化决策。

以下是示例数据产品的列表,包括它们所属的类别和用于访问它的接口:

  • 一个公司仪表盘,显示您企业的主要关键绩效指标。该数据产品属于决策支持系统类型,其访问界面为可视化界面。
  • 数据仓库。该数据产品是原始数据、衍生数据和决策支持系统的混合体。访问它的接口可能是 SQL 查询。
  • 附近推荐餐厅列表。由于这份名单是专门为你设计的,所以这个数据产品是一个自动决策的产品。访问它的界面是一个应用程序或网站。
  • 谷歌地图上的“更快路线现已可用”通知是一个决策支持数据产品(因为你是决策者),其界面是一个网络/应用程序。
  • 自动驾驶汽车也是数据产品。因为它是自动驾驶的,所以属于自动决策型。它的界面就是,嗯,汽车本身。

数据作为一种产品

数据网格范式的原则之一是将数据视为一种产品。有时这一原则被缩写为“数据产品”,因此产生了混淆。

“数据产品”是一个通用概念(如上所述),“数据作为产品”是所有可能的数据产品的子集。更具体地说,如果我们使用西蒙的类别,“作为产品的数据”属于“数据产品”的原始或派生数据类型。

如果我们深入到数据网格世界,Zhamak Dehghani 的原始文章中的这段引文是理解数据作为产品的定义的关键:“领域数据团队必须将产品思维应用于他们提供的数据集;将他们的数据资产视为他们的产品,将组织的其他数据科学家、ML 和数据工程师视为他们的客户。”

总之,“作为产品的数据”是将产品思维应用于数据集的结果,确保它们具有一系列能力,包括可发现性、安全性、可探索性、可理解性、可信度等。

数据作为产品的一个例子

那么,数据作为一种产品是什么样子的呢?作为产品的数据包含代码、数据和元数据,以及运行它所必需的基础设施。此外,它需要实现前面描述的功能。

在我们于 2019 年在巴塞罗那举行的数据委员会会议上发表的题为“一个有效的联合信息基础设施” ( 视频,博客文章文字稿)的演讲中,我们通过列出数据集的质量,举了一个数据集作为产品在 Adevinta 中使用的例子:

可发现的

为了使作为产品的数据可被发现,需要一个搜索引擎,用户必须能够在该引擎中注册数据集并请求访问它们(这将增加安全性,另一个功能将在下面解释)。

该功能的第一次迭代可能只是您实际的内部 intranet 中的一个数据集列表,您可以从中迭代和增量构建。请记住,流程和文化比过早部署终极数据目录工具更重要(这对于员工来说可能太复杂而无法使用)。

ade vinta 定制构建数据目录的一个示例,使数据集可被发现

可寻址

拥有可寻址的数据集使您的团队更有效率。一方面,数据分析师和数据科学家可以自主地寻找和使用他们需要的数据。另一方面,数据工程师很少被人打断,他们会问在哪里可以找到关于 x 的数据。

使数据集可寻址的“数据作为产品”的元数据

自描述和互操作

正如我们在解释 Adevinta 的数据网格之旅的博客文章中所评论的,数据集需要包含使其可以理解的元数据,并遵循相同的命名约定(这将使数据集具有互操作性)。我们发现这些元数据对我们的数据分析师非常有用:

  • 数据位置(如上所示)
  • 数据起源和数据映射
  • 抽样资料
  • 执行时间和新鲜度
  • 输入前提条件
  • 使用数据集的笔记本或 SQL 查询示例

值得信赖和安全

定期自动检查数据质量是实现数据作为一种产品的可信特性的必要条件。数据集的所有者需要对这些检查的结果做出相应的反应。

必须在管道输入和输出处进行质量检查,并且向数据消费者提供上下文数据质量信息没有坏处;比如 Tableau 仪表盘。

在 Tableau 仪表板中显示的上下文数据质量

最后,注册的数据集不应该自动提供给所有人。员工需要请求访问他们中的每一个人,数据控制人员需要单独授予或拒绝访问权限。

当请求访问时,必须指定需要访问的时间以及访问的目的。

进一步阅读

将数据理解为一种产品是在您的组织中成功实施数据网格的基础。你可以通过阅读这篇文章中引用的以下文章来扩展关于这个主题的知识:

  • 西蒙·奥里甘设计数据产品
  • 如何从单一数据湖转移到分布式数据网
  • 数据网格原理和逻辑架构Zhamak Dehghani 著
  • Xavier Gumara Rigol 在 Oda 发布的产品数据
  • 构建数据网格以支持 Adevinta 的数据产品生态系统Sandra Real 和 Xavier Gumara Rigol
  • Xavier Gumara Rigol 的文章

数据即代码—实现分析数据集的零生产缺陷

原文:https://towardsdatascience.com/data-as-code-achieving-zero-production-defects-for-analytics-datasets-824251339952?source=collection_archive---------22-----------------------

行业笔记

如何应用真实数据作为代码哲学,使用软件开发中关于数据的可靠方法来实现接近零的产品缺陷。

是的,零缺陷!那太棒了。图片由作者提供。

数据团队将近 60%的时间花在运营上,而不是创造价值。根据数据厨房研究&园丁调查,他们的数据系统也经历了大量的错误。然而,在软件开发世界中,我们已经有了哲学,允许高性能的团队快速且高质量地交付,没有任何这些问题。

那么我们为什么不延续完全相同的做法呢?毕竟,它们起源于精益制造领域,并且已经被带到了软件领域。这就是应该称之为 的数据为

让我们看看来自软件世界的工具和实践如何转移到一个简单的例子,一个 EL (T)工作流,并使我们的示范团队能够:

  1. 将平均恢复时间(MTTR)缩短至几分钟(或几秒钟)。
  2. 增加“数据部署”和测试的频率
  3. 将失败率(生产错误的相对数量)更改为 0%左右

如果你想知道为什么我们要看这三个指标,这是四个指标中的三个,这四个指标是区分高绩效团队和一般团队的。听起来是个不错的目标,对吧?

警告 ,这才是真正的“数据如码”,而不仅仅是“啊对了,请版本化数据。这看起来有点奇怪,这就是为什么我要用一个例子。强调为什么这种数据生产流程会产生接近 0%的生产缺陷。

我们的例子,数据 Ingestors 丹,戴夫,达纳

让我介绍三个朋友:丹、戴夫和黛娜。他们三个都是数据感应器。机器。Dan 和 Dave 是“REST 吸入器”的实例,Dana 是“Salesforce API 吸入器”的实例。

他们三个都可以使用数据 git,一个可以由 lakeFS 这样的解决方案托管的数据 git。他们可以使用它,就像任何人类开发人员使用他们的代码库一样。

丹、戴夫和达娜是优秀的开发人员。他们坚持持续集成的所有好原则,经常提交,本地测试,等等…

旁注:为什么我要提到 lakeFS?因为与其他工具一样,lakeFS 操作并不是数据的实际复制,而主要是元数据操作。因此,下面提到的复制操作实际上只需要几秒钟,即使是万亿字节的数据。

EL (T)数据流

我们的数据流非常简单。我们将一个 REST API 用于“订单”,而 Salesforce API 使用一些公共转换工具将这两个源连接在一起,并获得一些由典型的客户相关数据划分的客户统计数据。

图片由作者提供。

我们的参考工作流性能

我们的参考工作流程很简单:

  • 数据入口设置为每小时接收一次数据。
  • 其余的 ingestors 只有一个源,但它很大,所以并行化到 N=2
  • 摄取的数据放在一个“原始表”中,并在运行后使用诸如 great-expectations 这样的工具进行测试。
  • 如果原始源代码中有一个错误,只有那部分会被暂停,开发人员必须检查并可能修复它。

如果生产中出现问题,例如创建“客户表”的转换(是的,我知道我们可以在它上面有一个物化视图),那么我们就丢失了客户数据。恢复是指删除数据/修复一些数据问题,然后重新运行一次转换= > ,以 30 分钟到一个小时来衡量。在一般的公司里,这种情况一个月会发生几次。

这已经描述了典型数据设置中的上述指标。

现在,让我们来看看 Dan、Dave & Dana 的智能版本与我们的参考工作流程有何不同!

— — — —

丹、戴夫&达娜……

Dana 提交 Salesforce API 客户数据

图片由作者提供。

Dana 知道好数据的关键是“经常承诺”。这样,错误很快就被发现,并被控制在一个很小的“爆炸半径”内。所以她每 5 分钟跑一次

在她“运行”之前,她通过在 lakeFS“danar unx 2021–01–01–101”中创建一个分支,将“数据存储库”克隆到她的本地系统中(不是真正的本地系统,但是让我们保持类比),该分支受到保护并且仅对她可见。

当她运行时,她接收数据,然后提交给她的个人分支。

她没有将数据推送到生产系统的原始表中,而是将它们“本地”保存一分钟,并使用这个名为“great-expectations”的酷工具运行测试,该工具运行一系列基本测试,如“非空”等。并检查原始数据的异常值和变化的分布。

首次改进本地测试

当测试中断时会发生什么?Dana 对此无能为力(…然而,她毕竟不是机器学习系统之类的东西…),所以它只是保持原样,而人类开发人员会收到通知说danar unx 2021–01–01–101 失败了。

人类开发人员现在可以检查分支,并在不干扰生产数据的情况下调查问题。

生产数据会发生什么变化?

  • 所有系统保持运行。
  • 再过 5 分钟,Dana 将下一个数据块带到danar unx 2021–01–01–102并运行她的新测试。
  • 如果数据错误还没有修复,数据就不在主分支中,所以测试通过了,新数据就在那里。
  • 大家都很开心。

感觉有点像一个中转区,损坏的数据在这里得不到处理,对吗?

接下来会发生什么?

推到母版上

图片由作者提供。

然后,Dana 继续将她的数据放入原始存储库中。自动创建并批准一个合并请求,再次运行测试,并将数据推送到常规的升级订单中。

让我们称数据为 dartifact ,因为它现在实际上是一个“数据工件”,或者更像是一个“飞镖”,从生产环境返回到某个中央 git 存储库和 CI 服务器。

到舞台环境中

图片由作者提供。

接下来不是生产环境,毕竟 Dana 是一个很棒的开发者。她知道她必须将自己的数据集成到其他数据中,就像她刚刚做的那样,还要集成到其他组件中。

因此,数据一旦被推入中央存储库,就被提升到一个暂存环境。这个登台环境还用于测试和集成所有软件组件。因此,它运行着我们最新版本的数据转换工具。

现在,我们的 CI 服务器可以执行一系列集成测试,这意味着运行数据转换工具并执行其测试。

为了让这个工作流与 lakeFS 一起工作,我们必须滥用分支机制,至少调用一个分支“env-staging ”,并给予它特殊的访问权限保护,就像它只能通过集成组件访问一样,等等。当然,这也可以在 lakeFS API 级别上处理,这可能是最好的方法。

试运行环境中的二次改进集成测试

当测试中断时会发生什么?

开发人员在显示器上的常规信息辐射器上得到通知,这是任何使用 CI 的团队都应该在中心位置拥有的。

东西修好了,我们的生产系统也没有问题了。其他数据只是流过有问题的部分。

最重要的是,我们还将最新的 dbt 模型与新数据进行集成,然后再投入生产。

等等,但是我们的数据太大了,无法运行两次转换

如果转换时间太长,我们该怎么办?那就有多种选择了!

我们已经创造了数据“dartifact”。这意味着,我们可以像对待任何其他通过我们的促销订单的软件工件一样对待它。例如,我们可以将我们的数据与某种配置一起提交,这些配置只一起构成 dartifact。

一种可能的配置是:对真实数据的采样机制保持分布完整,但仍然使它在登台环境中变得更小。

或者它可以是一个数据掩码,如果在分段环境中需要的话,它可以屏蔽个人信息。

提升到生产

图片由作者提供。

最后,Dana 可以将她的数据推广到生产中。多亏了今天可用的令人敬畏的自动化,这实际上只需要几分钟。

但是由于 Dana 仍然是一个聪明的开发人员,所以她没有直接提升到生产环境。相反,她做了一个“蓝绿色部署”,这意味着她将新的 dartifact 推入 lakeFS 中的第二个分支“production-blue”。

然后,她对数据进行一系列冒烟测试,然后才慢慢地将生产流量从“绿色生产”切换到“蓝色生产”。

第三项改进产品冒烟测试和即时回滚

如果东西坏了怎么办?如果冒烟测试失败,则一切正常,不会影响生产流量。

如果它真的崩溃了,那么我们仍然有一个超级简单的回滚选项,我们可以在 lakeFS 之上的任何 CI 中实现它。只需将旧的 dartifact 重新部署到我们的生产分支,或将生产流量切换回旧的工作分支“绿色生产”。

我们仍然需要回滚主分支,以防止将来的合并再次破坏生产系统。

丹和戴夫怎么办?

丹和戴夫遵循相同的工作流程。除此之外,有人忘记在他们的系统中设置“本地测试”选项。

有问题吗?不会,因为一旦他们将数据提交给 master,并将其推送到原始存储库,它就会被集成,从而被测试。有人会抓住它,实施本地测试,并感到高兴。

此外,由于两者并行工作,数据确实需要被集成,测试必须在中央存储库中再次运行,在那里它们的两个数据版本被合并在一起。

看看这些数字

与我们的参考工作流相比,看看此工作流实现了什么:

  1. 平均恢复时间:在参考工作流中,从 30 分钟到 1 小时不等。对我们来说,如果数据真的中断了,我们只需切换 lakeFS 中的一个分支。这是一个元数据操作,意味着它需要几秒钟才能到达一个正在运行的系统。由于事先进行了密集的测试,而且块很小,修复也非常快。
  2. 变更失败率:由于我们在新工作流程中有 4 个测试层,与参考工作流程中的 1-2 个相比,我们将变更失败率降低到接近 0。
  3. 数据部署的频率:在我们的参考工作流中是每小时一次,这里是每 5 分钟一次。是的,这是真的,在参考工作流中也可能是 5 分钟,如果我们放任不管的话。到 5 分钟意味着减少修复某个东西所花的时间,因为可能的错误区域要小得多。

转换工具呢?

当然,现在我们把数据作为代码,就像基础设施作为代码一样,我们必须把东西集成在一起。这意味着一旦提交了变更,dbt 工具也将触发针对数据的集成测试。

推入存储库的新转换也是如此。

这不是又贵又慢吗?

如上所述,成本是可调整的和相对的。同样显而易见的是,实际上一直移动数据是没有意义的。相反,像 lakeFS 这样的工具或任何其他类似的工具都非常适合,因为这些工具处理根本不移动数据的元数据操作。

当然,就像通常的软件开发一样,对于每种情况,在提交大小和获得满足我们对数据的要求的度量的时间间隔之间都有一个最佳点。

可能仍然需要一些技术创新,如更好的数据 CI 工作流,但该流程已经可以用现有的技术很好地实现。

的确,如果你的目标是尽可能便宜地获取数据,那么这种工作流程不是你要找的…

但考虑到“数据是世界上最宝贵的资产”,我敢肯定,在快速交付高质量 上多花一点钱是值得的。

对如何建立伟大的数据公司、伟大的数据密集型产品、成为伟大的数据团队感兴趣,还是对如何利用开源构建伟大的东西感兴趣?然后考虑加入我的 免费简讯《三个数据点周四》 。它已经成为数据初创企业、风投和数据领导者值得信赖的资源。

数据即代码——原则,它是什么,为什么是现在?

原文:https://towardsdatascience.com/data-as-code-principles-what-it-is-and-why-now-aaf1e24fa732?source=collection_archive---------10-----------------------

不,DaC 不仅仅是版本控制数据!它将整个软件工程工具链应用于数据。为此,我们需要原则。

本帖是小编的一部分,开头是: 数据作为代码——实现分析数据集的零生产缺陷

图片由 Sven Balnojan 提供。

数据作为代码是一个简单的概念。就像基础设施是代码一样。它只是说“把你的数据当作代码”。然而,在 IaC 于 2011 年出现在 ThoughtWorks 的雷达上之后,它仍然花了大约 10 年的时间“入驻”,并且仍然处于一个不稳定的位置,IaC 的倡导者认为他们需要提醒人们以下几点:

" ….说“像对待代码一样对待基础设施”是不够的;我们需要确保来自软件世界的来之不易的知识也能一致地应用于整个基础设施领域”

就这么多了。由于我认为我们不应该再等 10+年来获得高质量的数据应用 快速,所以我写了这篇文章(系列)。

那么什么是 DaC 呢?

数据即代码:使用我们在软件中学习到的良好实践,并将它们应用于所有数据领域的数据,运营数据、分析数据、数据科学数据、……版本管理、自动化测试、CI 系统、……以实现 快速交付高价值数据的目标

我担心的是,数据即代码(DaC)将比 IaC 需要更长的时间才能起步,这对我们所有人来说都是一个巨大的福利损失。我认为,到目前为止,围绕 DaC 概念的讨论忽略了三个重要概念。这三个概念是“dartifacts”、“人类辅助机器工程”和“数据集成”。

我将解释这些概念以及它们为什么如此重要,并解释我们应该在数据世界中遵循的原则。

尽管谈论“旧模式失败”的所有方式可能是合理的,但我喜欢关注新世界、新概念和新机会。

发生了什么事?新世界中的老方法

这种情况已经发生,并将在未来几年继续发生…

作者对数据量做的非常粗略的估计。可能完全被夸大了。这只是一个简单的指数预测。

我们应用程序中的数据呈指数级增长。它不仅仅在操作上被用来存储对象,“记忆事物”,而且还被用来分析事物,做出更好的决定。第三,它以一种“解析运算”的方式为机器学习应用提供动力。后两种应用产生了数据使用的寒武纪大爆发。****

因此,可用数据量和数据价值都呈指数增长曲线。

在我看来,这将引领一个时代,数据将成为未来的电力,为一切提供动力。

问题:在这个新世界里,我们继续以旧的方式工作。尽管我们应该应用制造技术的黄金标准,但我们已经学会了将软件应用于数据。****

DaC 世界中的概念

人们谈论“数据即代码”,但迄今为止,我还没有看到任何接近我脑海中必然发生的事情。已经在朝着正确的方向前进的是我们需要对数据进行版本化(参见例如像 dvc 或 lakeFS 这样的工具)并测试它(参见蒙特卡洛或远大前程)。

我认为这是因为围绕数据作为代码的讨论中缺少了三个重要的概念。让我们来看看它们。

Dartifacts

软件工件是在软件开发过程中创建的东西。通常,开发人员开发一些代码,将它推入中央存储库,然后进入 CI/CD 系统,在那里进行构建。然后交付到不同的“阶段”进行测试,最后推广到生产。

图片由作者提供。

另一方面,dartifact 也是一个工件,但不是这个意义上的软件开发过程。它是由部署在这些阶段中的任何一个阶段的系统创建的,然后像飞镖一样被发送回中心位置。一个特殊的例子当然是数据。

图片由作者提供。

请注意,人类创造的人工制品有点像一套“护栏”,而现在 dartifact 是一个自我进化的系统。这就把我们带到了下一点,未来的软件工程。

人类辅助机器工程

那么,服务应该提交数据吗?那太好了,但是如果东西坏了,机器不能自己修理东西,对吗?实际上,我们已经在“ CD4ML ”的框架中使用了正确的工作流来解决这个问题。

对于持续/在线学习机器学习模型,ThoughtWorks 宣传了一个有些类似的工作流程。它看起来像这样:

  1. 我们在 CD 系统中为我们的机器学习模型建立了一个测试和评估管道。
  2. 我们引入类似“如果新模型没有击败上一个,就不要使用它,否则自动部署它”的测试。
  3. 我们部署了一个新的机器学习模型。我们还用它部署了数据收集器。
  4. 每当有一批新数据(比如一天的数据)时,数据收集器将数据提交给 git,触发管道,评估新模型,并可能发布它。

当然,当管道出现故障时,机器学习工程师会收到通知,并可以处理模型。因为毕竟,如果它随着更多的数据而变得更糟,这意味着某些东西很可能会被破坏。但他现在有机会简单地提供更好的护栏,让系统在其上处理事情,从而不断改进自己。

那就是人类辅助机器工程,机器做“开发”,人类进来做“繁重的工作”。到目前为止,我还没有在任何讨论中看到这个话题,但我认为这是一个重要的话题,因为我看不到任何其他发展领域的未来。

想过吗?作为一名开发人员,你为什么要解决一个之前已经解决了 10000 次,并且在网上数百万行代码中公开的问题呢?这听起来很像机器应该做的事情……

人工辅助?图片由作者提供。

集成数据

在基础设施成为代码之前,只有软件。现在有了两个额外的集成点。当然,问题是,既然当我把软件当作代码时,基础设施只是为了运行软件而存在,那么我该如何处理软件呢?但是这个问题只有两个选择:

  1. 以基础设施+软件为一个单元
  2. 将它们视为独立的单元

另一方面,对于作为代码的数据,我觉得我们有了更多的选择,仅仅是因为它是第三个,而且因为它实际上有多种用途。

三种实用的数据类型

我实际上看到了今天使用的三种不同的“数据类型”或“数据应用程序类别”。这些操作数据的主要目的是为了记住事情。然后是分析目的,其主要目的是帮助人类做出更好的决策。最后是分析操作,它通常也被视为分析,其目的是自动帮助某人做出更好的决策(无论是在帮助你做出更好电影选择的推荐系统中,还是在具有预测的实际决策支持系统中,等等。).

我喜欢将后两者分开,只是因为目前只有分析性的操作数据应用程序像代码一样接近数据,就我所知,它使用的是 CD4ML/CML 工作流。

DaC 的原则

DaC 中的原则几乎都是现代优秀软件开发原则的一对一翻译。然而,如果我们看看数据世界,它们根本没有被使用,在上面概述的三个数据领域的任何一个…

我们为什么要这样做?因为这些原则中的大部分最初来自精益制造世界,在那里关注的仅仅是同时提高流程的产量和质量。它造就了丰田,也造就了大多数现代科技巨头。那么,如果我们关心数据流,为什么要忽略那些非常有效的方法呢?

软件工程!图片由作者提供。

进入,原则。

(1)版本控制中的一切

这听起来像是一个显而易见的问题,这是一个经常被称为“数据即代码”的东西,但是正如你所看到的,它仅仅涵盖了数据即代码的 5%。

原则:把你的数据保持在版本控制中。关于它的一切。

(2)小提交—小块数据

出于某种原因,我们将数据“批量处理”成大批量。然而,从软件世界我们已经知道,如果我们犯了一个大错误,我们破坏它的可能性非常大,并且修复它的努力也很大。

原理:提交小的 DaC 变化。

这是一种心态的转变。然而,在我们用新数据重新训练我们的机器学习模型之前,一旦我们获得了大量新数据,我们现在提倡不断的重新训练。

请记住速度和大小之间的权衡,但仅此而已。我认为通常人们害怕“经常提交数据”,因为他们认为它会更经常地损坏。但事实正好相反,新的/更改的数据集越小,修复它就越容易。

这当然只有在“提交/摄取/…经常”不会导致生产系统崩溃的情况下才有效,所以让我们来看看其他原则。

(3)代码创建者的本地单元测试

我们都在将代码推送到中央存储库之前对其进行单元测试,因为我们不想提交不完整的代码。

然而,数据采集器和其他系统通常会将数据直接采集到生产系统中,而不进行任何测试。

原理:DaC dartifact 的创建者也“本地”测试它,然后将其推送到中央系统。

作为一个例子,这意味着,你的在线机器学习系统将运行一个测试,例如检查它的统计分布。如果失败,它不会将数据推入系统进行训练,而是将新的数据“放在一边”。

(4)走促销顺序

软件构建首先被部署到沙箱,然后是集成环境,最后是生产环境。

然而,无论是数据入口,还是一些在线学习机应用程序,以及运营数据,都被直接转储到生产系统中。

原理:DaC 走晋升顺序,和其他一样。

对于运营数据来说,这听起来可能有些奇怪,但我觉得这是有价值的。想想看,您可能正在备份您的大型生产数据库。为什么您会简单地假设其中的数据没有损坏?为什么您会认为可以使用它来恢复,而不首先在集成阶段进行测试呢?为什么你会认为它还能和其他东西集成在一起?

(5)所有阶段的数据相同

一个推论是这个原则。我们在所有级上保持相同的 DaC。通常情况下,公司只在非生产阶段保留少量样本或虚假数据。我主张 180 度大转弯。为什么?因为我们希望在生产中面临的相同环境中测试我们的 dartifact,否则,我们不能依赖我们的测试并降低我们的数据质量,产生更多的错误,并以更慢的数据交付时间结束。

当然,就像软件一样,我们当然可以应用远离环境的配置,它可以是:

  1. 较低阶段的“取样”配置或
  2. 屏蔽 PII 数据的屏蔽配置

对于尺寸敏感的读者来说:没有理由让这种事情发生。这并不意味着我们必须一直拷贝数万亿字节的数据。这可以作为根本没有任何复制的元数据操作发生。额外的好处是:如果我们只使用元数据操作,从我的角度来看,这应该是 GDPR 兼容的(尽管我不是律师)。

(6)主干发展,分枝少

原则:我们只保留 1-2 个分支,包括主干/主干用于我们的数据。

这确保了我们实际上执行了上述原则,比如本地测试和晋升阶梯。

(7)我们跟随变化的轴心

原则:我们沿着变化的轴线切割 DaC 和数据服务,而不是与之正交。

这意味着我们试图把事情做得更小,而是在领域边界上。我们尽量不要把数据摄取和我们新的很酷的机器学习系统分开,毕竟,它们是一起工作的。这意味着我们不会将我们的 BI 系统分割成“接收/转换/清理/存储/保存”部分,而是分割成“业务组件单元 1/业务单元 2/…”比特。

为什么要这么做?首先,遵循数据网格概念的所有想法,这是正确的做法。其次,如果我们通过大规模的数据湖来引导机器学习组件的数据摄取,我们几乎没有机会测试系统的整体完整性。我们将没有机会真正确保真正的价值生产单元,即机器学习组件的质量。我们将仅仅能够确保“分段”的完整性,这与产生价值的单元的完整性非常不同。

另一方面,如果我们将所有的部分放在一个架构量子中,就很容易确保组件的完全完整性,从而让它整天持续改进。

(8)经常集成代码库和组件

原则:经常集成您的数据,以及创建它的应用程序、存储它的应用程序和它的基础设施。

我认为,对于任何曾经恢复过数据备份的人来说,这应该听起来很熟悉:恢复数据备份后,事情根本不会以同样的方式工作,因为围绕数据的事情在发展,但数据后退了一步。因此,将数据一次又一次地与其他所有东西(基础设施和软件组件)集成是至关重要的,就像我们不断将所有软件组件和基础设施相互集成一样。

(9-…)我肯定还有更多

数据有什么不同不是更突出?

我认为人们已经接近这种心态,因为数据正在成为这个星球上最有价值的资源,但是处理数据的管道还没有跟上。

有两件事与迄今为止代码作为代码和基础设施作为代码的情况有本质的不同:

  1. 机器将完成这里的大部分提交工作。
  2. 庞大的数据量。

但话说回来,基础设施与代码也有很大不同,至少代码只是大小不同,基础设施实际上有不同的外观,因此需要代码到实际物理基础设施的大量映射。

正如上面所解释的,我不认为机器工作在代码上是一件新鲜事。

因此,也许数据作为代码是一种思维转变,但我不觉得这是一个巨大的转变,这种新的最有价值的产品在提高质量和速度方面的好处是巨大的。

一个悬而未决的问题仍然是,我们需要像在 IaC 中那样在数据之上有一个抽象层吗?例如用于屏蔽数据?我不知道,还有待观察什么会起作用。

还缺少什么——我们需要开发什么?

当我偶然发现 lakeFS 时,我对这个话题很感兴趣。因为在我看来,他们可能会朝一个方向前进:

1.能够模拟分布式数据,

2.将数据的读取模型从数据存储中分离出来。

在我看来,这正是我们需要让所有原则像魔咒一样工作的原因,因为如前所述,“数据量”不允许频繁应对,特别是当我们的目标是加速而不是减慢时。

这就像我们用来做 IaC 的基础设施之上的抽象层。

还缺少什么?技术上来说,一切皆有可能。但是大多数事情还不简单。在数据仓库中获取数据或通过 CI 系统运行数据仍然很困难。

你该何去何从?进一步阅读

如果这引起了你的注意,那么一个好去处就是应用文章。对于运营分析数据应用的阅读,你真的应该阅读 ThoughtWorks 的文章。

由于在分析空间中没有任何东西,我花了一些时间写了一篇关于使用数据作为代码在数据世界中实现零生产缺陷的配套文章。

我还没有在运营数据领域看到任何东西,但是我确信已经有聪明的人在这样做来保护他们的备份等。

结束语

这更像是一个思想实验,是让人们将数据视为代码的一个步骤,而不是基于构建工作模型的经验。所以,如果你有任何这样的例子,我很想听听!

对如何建立伟大的数据公司、伟大的数据密集型产品、成为伟大的数据团队感兴趣,还是对如何利用开源构建伟大的东西感兴趣?然后考虑加入我的 免费简讯《三个数据点周四》 。它已经成为数据初创企业、风投和数据领导者值得信赖的资源。

用 Python 和 OpenCV 进行数据扩充编译

原文:https://towardsdatascience.com/data-augmentation-compilation-with-python-and-opencv-b76b1cd500e0?source=collection_archive---------10-----------------------

防止模型过度拟合

照片由 Ulises Baga 在 Unsplash 上拍摄

数据扩充是一种增加数据集多样性的技术,无需收集任何更多的真实数据,但仍有助于提高模型准确性并防止模型过度拟合。在这篇文章中,您将学习使用 Python 和 OpenCV 实现最流行和最有效的对象检测任务的数据扩充过程。

即将推出的数据扩充方法包括:

  1. 随机作物
  2. 断流器
  3. 色彩抖动
  4. 添加噪声
  5. 过滤

首先,在继续之前,让我们导入几个库并准备一些必要的子程序。

下面的图片是在这篇文章中使用的样本图片。

图片:WAYMO 数据集中的 tr03–14–18–1-FRONT.jpg

随机作物

随机裁剪随机选择一个区域,并将其裁剪出来,形成一个新的数据样本,裁剪后的区域应具有与原始图像相同的宽高比,以保持物体的形状。

作者图片

从上图可以看出,左图显示的是带有真实边界框(红色)的原始图像,右图是通过裁剪橙色框内的区域创建的新样本。在新样本的注释中,移除了与左侧图像中的橙色框不重叠的所有对象,并且将位于橙色框边界上的对象的坐标调整为适合新图像样本。原始图像的随机裁剪的输出是新的裁剪图像及其注释。

断流器

Cutout 是由 Terrance DeVriesGraham W. Taylor 在他们的论文中于 2017 年推出的,是一种简单的正则化技术,在训练期间随机屏蔽输入的方形区域,可用于提高卷积神经网络的鲁棒性和整体性能。这种方法不仅非常容易实现,而且证明了它可以与现有形式的数据扩充和其他正则化结合使用,以进一步提高模型性能。

如论文中所述,应用剪切来提高图像识别(分类)的准确性,因此,如果我们将相同的方案部署到对象检测数据集,则可能导致丢失对象,尤其是小对象的问题。下图中,剪切区域(黑色区域)内的大量小物体被移除,这不符合数据增强的精神。

作者图片

为了使这种方式适用于对象检测,我们可以进行简单的修改,而不是仅使用一个掩模并将其放在图像中的随机位置,当我们随机选择一半数量的对象并对这些对象区域中的每一个应用剪切时会更好。增强后的图像显示为下图中的右图。

作者图片

剪切的输出是一个新生成的图像,我们没有删除对象或改变图像大小,然后生成的图像的注释是原始的。

色彩抖动

ColorJitter 是另一种简单的图像数据增强,我们随机改变图像的亮度、对比度和饱和度。我相信这个“家伙”很容易被大多数读者理解。

作者图片

添加噪声

在常识中,噪声被认为是图像中的一个意外因素,然而,几种类型的噪声(例如,高斯、椒盐噪声)可以用于数据增强,并且添加噪声是深度学习中一种非常简单且有益的数据增强方法。在下面的例子中,为了增加数据,高斯噪声和椒盐噪声被添加到原始图像中。

作者图片

对于那些不能识别高斯噪声和椒盐噪声之间的区别的人来说,高斯噪声具有从 0 到 255 的值范围,这取决于配置,因此,在 RGB 图像中,高斯噪声像素可以是任何颜色。相反,椒盐噪声像素只能有两个值 0 或 255,分别对应于黑色(胡椒)或白色(盐)。

过滤

本文介绍的最后一个数据扩充程序是过滤。类似于加噪滤波也简单易实现。实施中使用的三种类型的滤波包括模糊(均值)高斯中值

作者图片

摘要

作者图片

在这篇文章中,我向大家介绍了一个关于为目标检测任务实现数据扩充的教程。你们可以在这里找到我的完整实现。如果你觉得它有帮助,请毫不犹豫地给它一颗星。欢迎你访问我的脸书粉丝页,这是一个分享关于机器学习的东西的页面:投入机器学习。

今天够了。感谢您抽出时间!

脑-机接口的数据增强

原文:https://towardsdatascience.com/data-augmentation-for-brain-computer-interface-35862c9beb40?source=collection_archive---------30-----------------------

结合脑机接口和生成对抗网络的新商业应用

图片来自 Pixabay

尽管脑机接口(BCI)取得了重大进展,但在现实环境中收集脑电图(EEG)信号仍存在许多问题。这种情况使得 BCIs 很难成为可扩展的设备。

脑-机接口一直面临着严重的数据相关问题,如缺乏足够的数据、校准时间过长和数据损坏。在我的最新项目中,我们探索了利用数据增强方法(如生成对抗网络)来创建合成 EEG 信号的想法。

事实上,数据增强(DA)是解决这些问题的潜在解决方案。在数据增强技术中,成功应用于图像处理的生成对抗网络方法受到了广泛关注。

在本文中,我将解释在非侵入性脑机接口环境中创建足够的训练数据的问题,并给出一个针对 EEG 数据集的数据扩充技术的非详尽列表。我还将解释在实际应用中如何使用 GANs 来帮助 BCI。

BCI 和数据采集

脑机接口(Brain-computer interface,BCI)系统旨在为几种使用情况连接大脑和外部设备。

时至今日,在 BCI 获取大脑数据最常用的方式是脑电图。这种方法无创,便携,相对便宜。对于大多数项目,需要大量的脑电信号。

脑电图 (EEG)是“一种记录大脑电活动的电生理监测方法”( 1 )。

对于非侵入式 BCI 应用,EEG 是用于脑-机接口的最主要的信号采集方法。它具有非侵入性捕获人类大脑皮层电活动的能力。

然而,由于多种原因,EEG 并不代表获取数据的可扩展方式:

  • 它要求受试者(或患者)经历长时间的校准过程。
  • 一些收集的数据可能已损坏。
  • 在 EEG 数据集上训练的分类器倾向于对不同时间记录的数据进行较差的概括,即使是对同一个人。
  • EEG 信号因受试者而异,甚至受试者内部也因会话而异。这种情况对于实时分析尤其成问题,在实时分析中,固有的模型是基于过去的神经数据训练的,用于解码当前的神经活动。
  • 收集所需数量的样本通常既困难又昂贵。
  • BCI 系统通常需要很长的校准时间,这对于商业应用来说仍然太长了。可能的解决方案需要来自其 EEG 信号先前已被记录的许多其他用户的数据,或者来自同一用户的过去试验的大量数据集。
  • 深度学习固有地受限于 EEG 数据集,因为它们的大小相对较小。
  • 分类器在 BCI 系统中的性能高度依赖于训练数据的质量和数量。
  • 大型公开的脑电图数据集并不常见。
  • 诸如脑解剖、帽放置和受试者之间的动力学等因素极大地限制了 EEG 分析在个体之间的普遍性。

此外,BCI 应用程序仍然经常依赖于在实验室中收集的训练数据,在实验室中,用户在受控环境中执行任务。

现实是,即使是一个单一的主题,BCI 团队也必须经历许多耗时的实验环节,才能训练好机器学习模型,使其足够有用。因此,具有特定领域方法的处理管道通常用于清理、提取相关特征和分类 EEG 信号。

使用现有条件可以获得额外的数据,但是从商业角度来看,通过几次长时间的校准会话来记录脑电图(EEG)数据是不可扩展的。

BCI 领域的一个重要限制是训练样本非常有限。利用如此有限的数据构建一个可靠且可用的系统是一项挑战。

不幸的是,如果没有足够的特定对象数据,即使是迁移学习方法也无法解码不同的 EEG 信号类别。

迁移学习 是一种“监督学习技术,它在一个新的网络上重用以前训练过的模型的一部分,该网络负责一个不同但相似的问题。”( 2 )

所需要的是一种自动生成人工 EEG 试验以扩充现有数据集的方法。生成方法是解决这些限制的潜在解决方案。

通过利用生成技术,有可能以时间和成本有效的方式提高分类器的鲁棒性。合成生成的 EEG 信号可以证明非常有利于提高训练用于分类 EEG 数据的模型的准确性和泛化能力。

数据增强和 BCI

存在两种方法来生成扩充数据。

  • 通过应用几何变换:平移、旋转、裁剪、翻转、缩放等。
  • 通过向现有的训练数据添加噪声。增加训练集的大小有助于用附加参数训练更复杂的模型,并减少过度拟合。

然而,与图像不同, EEG 是来自不同电极的噪声、非平稳时间序列的集合。此外几何变换并不直接适用于 EEG 数据,因为那些可能影响时域特征。

在经典的计算机视觉项目中,标注者可以很容易地决定一个增强的数据集是否仍然类似于原始类(例如,动物或物体)。对于 EEG 信号,事情更复杂…换句话说,正确标记增强数据集可能具有挑战性。

作者图片

脑电图的数据增强技术

数据扩充有助于增加可用的训练数据,便于使用更复杂的 DL 模型。它还可以减少过拟合,提高分类器的准确性和稳定性。

数据扩充已经或多或少地成功应用于许多 EEG 任务,例如:

  • 睡眠阶段
  • 运动想象
  • 脑力负荷
  • 情绪识别任务。

GANs 和 variable Auto-encoder(VAE)已经证明了从各种数据集捕捉关键元素以生成真实样本的效率( 3 )。

另一种方法包括“从最初可用的少量 EEG 试验中生成人工 EEG 试验,以相关的方式增加训练集的大小。”( 4 )根据作者的说法,“这种方法是通过首先将每个可用的训练 EEG 试验分成几个片段,并生成新的人工试验,作为来自不同和随机选择的训练试验的片段的串联来实现的。”

脑电信号的其他数据增强方法包括(非穷尽列表):

  • 滑动窗口方法(一种将时间序列数据集重构为监督学习问题的方法)
  • 噪声添加
  • 抽样法
  • 傅立叶变换(用频率分量表示周期信号的一种方法)

关注甘斯

生成对抗网络是一种相对较新的 ML 技术,其中两个人工神经网络通过竞争同时训练彼此。机器人使机器能够想象和创造自己的新奇形象。

GAN 和相关的深度学习算法被更多地用于和讨论在计算机视觉项目中生成合成图像。EEG 通常可以在频域中随着时间的推移被分析和可视化为频谱图(通过傅立叶或小波变换)。

使用 EEG 信号的 GAN 架构示例,图片由作者提供

光谱图可以像图像一样处理。因此,为图像开发的数据增强方法(GANs)可以应用于图像。通过 DA 过程生成的频谱图然后被转换回 EEG 信号。

最近有一些尝试将 GANs 用于 EEG 信号:

在这篇研究论文( 5 )中,“当这个人在看一些图像时,脑电图被记录下来,然后这个脑电图被发送到 GANs 以重新生成显示的图像”。他们报告说,GANs 优于变分自动编码器(VAE),但生成的图像质量仍然很低。

在另一项研究中( 6 ),研究人员应用 GANs 对 EEG 信号的空间分辨率进行上采样。在最后一项研究( 7 )中,GAN 用于生成合成情感识别 EEG 数据。作者“使用带有两个情绪识别数据集的条件 WGAN,从噪声分布中以差分熵的形式生成 EEG。”

标准 GANs 的问题

没有任何修改的 GANs 容易出错和不稳定。一个著名的场景叫做“模式崩溃”。当鉴别器仅学会将输入分布的几个窄模式识别为实数时,就会发生这种情况,导致生成器产生有限数量的可微分输出。

众所周知,训练 GAN 具有普遍的不稳定性问题。

处理模型不稳定和模式崩溃的一种方法是利用由 Arjovsky 等人首次提出的 wasser stein GAN(WGAN)(8)。WGANs 的目标是最小化真实数据分布和虚假数据分布之间的差异,防止模式崩溃。这种方法已经成功地用于创建无噪声的脑电图数据。

其他作者( 9 )提到了诸如“WGAN 可以使用所谓的梯度惩罚来处理消失/爆炸梯度”的问题其他研究人员可能会使用纯深度卷积 GAN (DCGAN),通过使用不同内核大小的卷积层来提取信号特征。

使用甘斯和 BCI 的商业应用

除了改进数据集的能力之外,GANs 还可以用于为 BCI 创建新的用例。可以肯定的是,GANs 将很快被用于将思想转化为图像。赫尔辛基大学的第一项研究是操纵神经活动,以适应生成计算机模型,并产生符合人类操作员意图的新信息。

正如我们在本文中看到的,有几种数据扩充技术可以改进数据集,例如,添加噪声。尽管 GAN 的 EEG 是一个新兴主题,但现有的少数研究表明,它是解决与 EEG 处理和可扩展性相关的几个问题的一种有前途的方法。

关于这个话题的更多信息,我推荐以下研究论文和文章:

  • 基于深度学习的脑电图数据增强
  • 用于脑机接口的生成对抗网络
  • MIEEG-GAN:生成人工运动成像脑电图信号
  • 新的脑机接口将思想转化为图像
  • 模拟大脑信号:通过基于神经的生成模型为改进的 SSVEP 分类创建合成 EEG 数据
  • 生成人工脑电信号以减少 BCI 校准时间
  • 基于生成对抗网络的脑-机接口数据增强
  • Brain2Image:将大脑信号转换成图像
  • 使用条件 Wasserstein GAN 进行情绪识别的 EEG 数据增强
  • 瓦塞尔斯坦甘
  • 使用生成式对抗网络(GANs)创建人工/合成脑信号‘脑电图’(EEG)数据

使用复制粘贴的数据扩充

原文:https://towardsdatascience.com/data-augmentation-reducing-model-confusion-with-copy-paste-8f41884ca9d1?source=collection_archive---------22-----------------------

思想与理论,行业笔记

减少相似类之间的模型混淆

图片经 shutterstock.com 许可使用,Adnan Ahmad Ali/shutterstock.com

Doma 数据科学的首要主题之一是可推广性。这对于在我们的产品中成功实施我们的机器学习模型非常重要,因为我们的数据来源广泛,并且支持新客户的快速加入(例如冷启动问题)。随着我们向改进模型性能迈进,误报可能是一个主要障碍。简而言之,当计算确定一个实例包含导致模型将其与该实例不包含的东西混淆的特征时,在机器学习模型预测中会出现误报。一个简单的例子是一只被误认为是狗的猫。两者都是四条腿的毛茸茸的动物,所以数学算法没有识别出它们的区别是可以原谅的。然而,鉴于 Doma 的每个订单都需要处理多达 100 页左右的文档,我们必须确保我们的错误率很低。

在这篇博客文章中,我将重点关注如何使用数据增强来减少计算机视觉模型中产生假阳性的混乱。最近,我们独立发现,所谓的数据增强“复制-粘贴”技术对于提高在较小数据集上训练的计算机视觉模型的性能非常有效。复制-粘贴技术通过复制对应于要检测或识别的特定对象的图像片段并将其粘贴到其他图像上来生成额外的训练数据,从而扩充数据集(更多细节见下文)。几乎在我们发现的同时,一篇关于复制粘贴技术的文章最近发表在谷歌大脑的 arxiv 研究人员上。关于 arxiv 的论文主要侧重于经验意义上的总体模型性能。在这里,我将重点介绍使用这种技术来减少由于容易混淆的类而导致的误报率。

构建数据集

作为这种技术的演示,我们从上下文中的公共对象(COCO) [2]开源数据集:https://cocodataset.org构建了一个小型数据集。这是一个非常大的行业标准数据集,用于对几个计算机视觉任务进行基准测试。对于当前的用例,重点将放在容易混淆的类的对象检测上。作为一个具体的例子,我将集中讨论自行车和摩托车。从视觉角度来看,这些物体显然是相似的:有两个轮子的车辆,它们经常出现在相似的环境中,并且经常有一两个人坐在上面。

我们创建了一个由 200 幅自行车图像组成的单一训练数据集,包括边界框注释。然而,我们将利用也包括在 COCO 数据集中的遮罩注释(指示图像中哪些像素包含感兴趣的对象的多边形)来执行复制-粘贴技术。为了理解复制-粘贴数据增强如何能够减少模型混乱,我们将创建两个附加的训练集,它们使用复制-粘贴技术用图像来增强,但是使用两种不同类型的背景图像。这将允许我们探索复制粘贴技术中的选择如何影响整体性能。

使用复制粘贴方法

我们可以建立一个自行车的扩充数据集,但要利用 COCO 提供的掩码。首先,我们选择了 200 张带注释的自行车图像,使用 COCO 的工具对这些图像进行了过滤,以确保这些图像中不存在摩托车。接下来,使用 COCO 注释为每幅图像提供的掩码,我们可以定位属于每辆自行车的所有像素。利用这一点,我们可以为每个图像生成每辆自行车的剪切图像。在选择的 200 个图像数据集中,共有 491 个自行车实例。接下来,我们选择了 500 张包含摩托车但被过滤掉自行车的图片。

图一。左图:可可自行车图片示例。中间:一辆自行车的面具。右图:使用蒙版提取(剪切)的自行车图像。需要注意的一点是,COCO set 中的遮罩并没有最高级别的精确度。通常它们包括许多背景像素(注意自行车轮胎右侧的额外像素)。改编自原图,版权 2012 ComradeCosmobot 并在attribute 2.0 Generic(CC BY 2.0)许可下提供

图二。左图:COCO 的摩托车图像,图像上随机粘贴了之前提取的自行车。右图:由我们的粘贴代码生成的掩码显示了粘贴自行车的位置。改编自原始照片,版权 2013 Paul Sableman 并根据attribute 2.0 Generic(CC BY 2.0)许可证提供,以及改编自原始照片,版权 2012 ComradeCosmobot 并根据attribute 2.0 Generic(CC BY 2.0)许可证提供

我们的数据扩充过程从 COCO 中选择的 200 个图像数据集中提取了 491 个自行车实例,并将每个实例分别粘贴到最多五个不同的图像上,这些图像包含摩托车而不包含自行车。对于那些有兴趣了解如何用 python 处理图像的人,请看:https://automatetheboringstuff.com/chapter17/。图 2 显示了流程结果的几个例子。因为有些摩托车图像比复制的自行车图像小,所以这个过程偶尔会失败。一种解决方法是减小自行车的尺寸。然而,相反,我们选择简单地忽略这些相对罕见的情况。

每次迭代都会产生一个额外的图像和一个额外的自行车实例。在处理了 500 幅摩托车图像之后,复制粘贴的扩充数据集具有 2557 幅图像和 2848 个自行车实例。

实验细节

区域卷积神经网络

区域卷积神经网络最初于 2014 年推出[3]。从那时起,已经有了许多迭代,并且许多当前技术水平的对象检测和实例分割模型都是基于该架构的。这使得 RCNNs 成为展示如何使用复制粘贴数据扩充方法来减少对象检测的假阳性的良好选择。在这里的工作中使用更快的 RCNN 方法。

对于 RCNN 的高级介绍,我建议从系列博客文章的第一篇开始,该系列博客文章给出了从最初的 RCNN 到更快的 RCNN 的发展之旅。为了开发,我们构建了探测器 2 框架。

培养

我们训练了三种不同的更快的 RCNNs。一个是在没有复制粘贴数据增强的情况下,对 200 张自行车图像进行训练。在训练中,我们只做了一个简单的随机水平翻转的增强技术。将有效的训练数据集大小增加到 400 个图像,这也将自行车实例的数量加倍,从 491 个增加到 982 个。从现在开始,我们将把它称为普通模型。

第二个更快的 RCNN 模型是在同样的 400 幅图像上训练的,但我们也包括了通过将自行车复制粘贴到摩托车图像上而产生的增强图像。还允许随机翻转,这导致自行车实例的总数为 5696。然而,人们必须记住,在香草模型的意义上,这些并不是唯一的。该模型将被称为复制粘贴摩托车模型。

最后,以与复制粘贴摩托车模型完全相同的方式训练第三个更快的 RCNN 模型,只有一点不同。不是用摩托车贴自行车的背景图片,而是没有自行车的狗的背景图片。

为了公平的比较,所有的模型都被训练了 5000 次迭代,批量大小为 2。在下一节中,我们将展示这些模型的结果。有关这三种模式的总结,请参见下表 1:

表 1:为比较而训练的模型。作者图片

估价

为了测试每个模型在多大程度上混淆了摩托车类别和自行车类别,对包含自行车和摩托车的 200 幅图像进行了评估。这个数据集中自行车实例的总数是 965。正如所料,普通模型将大量的摩托车混淆为自行车,而复制粘贴模型很少预测到摩托车是自行车

为了直观检查的目的,我们显示了五对结果,其中香草模型将非常明显的摩托车混淆为自行车。

示例 1 —左侧:复制粘贴模型的结果检测到一辆自行车。右图:vanilla 模型的结果检测到两辆自行车,其中一辆是摩托车。改编自原始照片,版权 2009 肯并以署名-非商业性 2.0 通用(CC BY-NC 2.0) 提供

示例 2 —左侧:复制粘贴模型的结果检测到一辆自行车。右图:vanilla 模型的结果检测到 5 辆自行车,其中 4 辆是摩托车。改编自原始照片,版权 2008PSliceofNYC 并在attribute 2.0 Generic(CC BY 2.0)许可下提供

示例 3 —左侧:复制粘贴模型的结果检测到一辆自行车。右图:vanilla 模型的结果检测到两辆自行车,其中一辆是摩托车。改编自原图,版权 2012 肯并以署名-非商业性-共享相似 2.0 通用(CC BY-NC-SA 2.0) 发布

示例 4 —左侧:复制粘贴模型的结果检测到一辆自行车。右图:vanilla 模型的结果检测到两辆自行车,其中一辆是摩托车。改编自原始照片,版权 2005 britt ,以署名-非商业性使用-类似共享 2.0 通用(CC BY-NC-SA 2.0) 发布

示例 5 —左侧:复制粘贴模型的结果检测到一辆自行车。右图:vanilla 模型的结果检测到两辆自行车,其中一辆是摩托车。改编自原始照片,版权 2007 Stefano Arteconi 并以署名-非商业性-共享 2.0 通用(CC BY-NC-SA 2.0) 发布

总的来说,vanilla 模型正确检测到的自行车数量(真阳性)为 321 辆,而误识别为自行车的摩托车数量(假阳性)为 130 辆。对于复制粘贴的摩托车模型,206 辆自行车被正确识别,11 辆摩托车被错误识别为自行车。请注意,我们没有考虑两个模型中实际上不是摩托车的类的任何误报。本质上,我们是在看摩托车被贴上自行车标签的混淆率。在这些术语中,复制粘贴模型的混淆率仅为 0.05,而普通模型的混淆率高达 0.29。当然,混乱越小越好。复制粘贴狗模型的假阳性率也降低了——它只把 38 辆摩托车误认为是自行车。然而,真阳性的数量是三个模型中最少的,只有 193 个。这些结果总结在下表 2 中:

表 2:模型评估。形象。作者图片

最后的想法

我们对复制-粘贴技术的演示表明,这种增强确实减少了自行车和摩托车之间的混淆,并表明这是一种很有前途的技术,可以应用于其他类容易混淆的情况。执行此技术的成本是额外的工作,即构建一个额外的类别(此处为摩托车)图像数据集,该模型预计会将其与要检测的类别(此处为自行车)相混淆。然而,这个额外的数据集不需要任何注释,因此构建起来相对便宜。

我们还可以看到,通过复制粘贴增强技术来减少混淆,在很大程度上依赖于粘贴实例的图像的选择。在将自行车粘贴到只有摩托车或只有狗的图像上的情况下,我们发现前者的模型有更多的真阳性和更少的假阳性——这两者都是可取的。当粘贴到狗身上时,与普通模型相比,假阳性的数量明显减少,只是没有复制粘贴摩托车模型多。事实上,复制粘贴狗模型的混淆率是复制粘贴摩托车模型的 3 倍以上。

最后,如上所述,COCO 数据集的注释掩码并不像人们希望的那样干净。如果使用具有更精确掩模的数据集,则预期复制-粘贴技术将给出甚至更好的结果,因为模型将可能较少了解注释方法中固有的特性,而更多了解待检测的实际对象的特征。然而,尽管如此,我们的实验表明,复制粘贴技术可以大大降低假阳性率。

参考资料:

[1] G. Ghiasi,Y. Cui,A. Srinivas,R. Qian,T. Lin,E.D. Cubuk,Q. V. Le 和 B. Zoph,简单的复制粘贴是一种用于实例分割的强大的数据扩充方法 (2020),arxiv.org:2012.07177v2 [cs .简历]

[2] T.-Y .林、m .梅尔、s .贝隆吉、l .布尔德夫、r .吉尔希克、j .海斯、p .佩罗娜、D .拉马南、C. L .兹尼克和 p .多拉尔。微软 COCO:上下文中的通用对象 (2014),arxiv:1405.0312【cs。简历]

[3] R. Girshick,J. Donahue,T. Darrell,和 M. Jitendra,精确对象检测和语义分割的丰富特征层次 (2014),arxiv:1311.2524 [cs .简历]

[4] S. Ren,K. He,R. Girshick,和 J. Sun 更快的 R-CNN:使用区域提议网络实现实时对象检测神经信息处理系统进展 28 (NIPS 2015) (2015)

[5] Y .吴和 a .基里洛夫,f .马萨,w .罗和 R,吉希克,detectron 2(2019)

数据先于模型,但首先是问题公式化

原文:https://towardsdatascience.com/data-before-models-but-problem-formulation-first-b4c2a9a3e978?source=collection_archive---------29-----------------------

行业笔记

将业务目标框定为建模任务是数据科学家的真正衡量标准

将问题公式化想象成一个二分图,目标是在右栏中为左栏中的业务任务找到最佳方法。有些任务可以用多种方法解决,有些方法可能不适合任何任务。图片作者。

几位杰出的人工智能思想领袖今年早些时候在推特上发表了主题为数据在应用机器学习中比模型架构和优化更重要的文章。弗朗索瓦·乔莱写道:

ML 研究人员使用固定的基准数据集,并花费所有的时间搜索他们控制的旋钮:架构优化。在 applied ML 中,您可能会将大部分时间花在数据收集和注释上——这是您的投资会得到回报的地方。

-弗朗索瓦·乔莱(@ fchollet)2021 年 1 月 24 日

吴恩达插话说,他同意乔莱的观点,还需要做更多的工作来传播创建和组织数据的最佳实践。

我甚至在专业化机器学习模型和建立生存分析中写过几次关于数据相对于模型的重要性。

获得正确的数据当然至关重要。但 Chollet 和 Ng 似乎是从“ML 优先”的角度来说的,这是一个公理,即预测模型——而不是其他——是应用 ML 项目如何工作的。在这种心态下,数据可能很重要,但它只是达到预测模型目的的一种手段。

我认为问题公式化甚至比数据或模型更重要。Christoph Molnar 更直截了当地指出:

你表达问题的方式

更重要

你抛给你的问题的 ML 算法的选择

-Christoph Molnar(@ Christoph Molnar)2021 年 1 月 24 日

什么是问题公式化?

问题公式化是为业务问题设计数据科学解决方案的过程。在这篇文章中,我假设业务问题已经定义并给出;一个不同但相关的问题是从现有的分析或建模工作中创造商业价值。

莫尔纳尔在的第二条推特中列出了问题形成的一些要素:

  • “预测目标的选择”
  • "要使用的数据"
  • “如何处理预测”

我唯一的意见是把最后一项提前;问题公式化的第一部分是计划你的系统将如何被使用,以及它将如何解决业务问题。

防流失问题为例。从 ML-first 的角度来看,它看起来很简单;在给定的一个月里,每个用户要么呕吐,要么不呕吐。Bam,让我们训练一个二进制提升树分类器来预测下个月的流失。完成了。

但是然后呢?

将如何解释输出?

我们面临的第一个问题是校准。许多二进制分类器的训练和调整方式只取决于输出预测分数的等级,而不是它们的实际值。假设我们的验证集中有 3 个用户,预测来自两个模型 A 和 B:

对于许多二元分类器,来自模型 A 和 B 的预测将同样好,因为对于每一个,我们可以选择一个阈值来完美地区分保留用户和流失用户。

在像防流失这样的应用中,这些值确实很重要!客户成功团队将直接读取分数,并且更担心有 80%机会产生客户的用户,而不是有 7%机会产生客户的用户,即使我们知道这些分数不应该相互比较。为了使流失预测模型有用,我们应该校准分数,使它们具有现实意义。

一般来说,我们需要了解我们的受众将如何解释我们的输出,无论是模型预测、BI 仪表板、实验结果还是任何其他工件。

这个方法真的能解决问题吗?

好了,我们解决了校准问题,现在我们有了一个完美的客户流失预测模型。客户成功团队应该如何处理它?

  • 他们应该接触那些有 10%或 50%或 90%流失率的用户吗?
  • 如果每个用户对客户成功团队的干预有不同的反应会怎样?如果我们的干预对用户没有影响,那么用户的流失概率是 20%还是 80%有关系吗?
  • 如果客户成功团队无论如何都要联系每一位客户?在这种情况下,我们的预测模型是无用的;相反,我们应该学会哪种干预最有效。

这些问题没有正确的答案,因为商业问题是防止流失,而不是预测它。一个预测模型本身并不能解决问题。

选择正确的目标变量

我们关于转化率建模的权衡的文章展示了选择预测目标的重要性的一个例子。最终的任务是了解用户如何从一个序列的一个阶段(例如销售漏斗)转换到下一个阶段。我们可以通过两种方式将此表述为数据科学任务:

  1. 通过选择一个固定长度的时间窗口来观察转换,将转换视为一个二元目标。如果主体在窗口内转换,则成功,否则失败。
  2. 模型用户转化需要多长时间。这是一个右删截的数字目标。

目标变量的选择决定了我们需要收集的数据以及什么类型的模型是合适的。

问题公式化是一项基本的数据科学技能

出色的问题表述是优秀数据科学家最明显的标志之一,也是我在面试时寻找的关键因素之一。是什么让某人擅长于此?

  • 好奇心,了解企业如何运作。
  • 诚实,对自己,对观众。我们应该正视我们方法的局限性和对我们结果的正确解释,尤其是当我们知道我们的方法不能完全解决给定的问题时。
  • 知识广度,通过大量实际应用问题的实践经验和阅读其他数据科学家的经验。为了评估替代配方,我们需要了解选项。
  • 远见,设想每个潜在解决方案的路线图和架构,并在承诺一个选项之前确定利弊。

应用数据科学与数据科学课程和训练营的方法论重点之间往往存在鸿沟。问题公式化是这个鸿沟的核心,所以掌握问题公式化是确保你的工作为你的组织增值的最好方法之一。

笔记

  1. 逻辑回归是一个显著的例外,它通过构造得到了很好的校准。
  2. 两个模型输出的 AUC 也是相同的,因为每个模型中所有阈值的真阳性和假阳性率是相同的。

原载于https://www.crosstab.io的交叉表风筝。