TowardsDataScience-博客中文翻译-2020-七十四-

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

旧金山湾区是在拉平曲线吗?

原文:https://towardsdatascience.com/is-the-sf-bay-area-flattening-the-curve-303419a0011d?source=collection_archive---------34-----------------------

开始就地避难已经一个月了。数据告诉我们什么?(更新时间:2020 年 4 月 20 日)

Unsplash 上由 Amogh Manjunath 拍摄的照片

3 月 16 日,旧金山湾区的六个县发布了就地安置避难所的命令。这意味着海湾地区的居民已经在原地躲避了大约一个月。让我们看一下数据,看看结果如何。

每日新案件

每天新增病例的数量可以被认为是新冠肺炎增长曲线。在我看来,这是最重要的图表,因为它代表了感染的加速。我会解释——但如果你已经知道这一点,请随意跳过下一段。

尽管总速度很重要,加速度(增长曲线)意味着在城市街道上和在高速公路上的区别。

如果你把它想象成开车旅行,感染的传播用行驶的英里数来表示,那么病例总数就像你行驶的速度(速度),而增长曲线就是汽车加速的速度(加速度)。尽管总速度很重要,加速度(增长曲线)意味着在城市街道上和在高速公路上的区别。也就是说,总病例数代表了一段时间内的变化,但增长曲线显示了病例数的增长速度。

旧金山湾区每日新增病例(更新时间:2020 年 4 月 20 日)。参见诺维湾区冠状病毒仪表盘上的实时可视化。

这张图表显示了新冠肺炎病例的增长情况。x 轴显示了湾区开始出现新冠肺炎病例的日期。y 轴表示增量,即病例总数的变化。或者更简单地说,y 轴显示每天的新案例。堆叠条形图中的不同颜色显示了各县的详细情况。但是要看整个湾区的增长曲线,你只需注意条形的总高度。

看这张图表,你可以看到新病例明显趋于平稳。作为对比,这是伊利诺伊州的增长曲线。

伊利诺伊州每日新病例(2020 年 4 月 20 日更新。点击放大)。来自伊利诺伊州的仪表盘。

根据伊利诺伊州的图表,你可以看到在过去的几天里有稳定的可能,但是最近还没有足够的数据来确定。

所有这些数据需要记住的另一个因素是,这些都是确诊的新冠肺炎病例。所以这些数字会受到测试次数的影响。

案件总数

旧金山湾区的总病例数继续上升,但由于增长放缓,这是线性上升,而不是指数上升。这是我们从上面显示的增长曲线中所期望的。

旧金山湾区新冠肺炎病例的近似线性增长(更新时间:2020 年 4 月 20 日)。从诺维湾区冠状病毒仪表板

这对就地安置的功效意味着什么?

有很多其他的变量涉及到这些结果的归属;比如:人口的总体健康状况、原地住所的遵守情况、人口密度、卫生设施的可用性以及文化因素。另一个要考虑的因素是旧金山湾区已经有了一个重要的在家工作的文化,这可能增加了对就地安置令的遵守。

我们可以使用旧金山湾区的例子来创建一个粗略的时间表,显示就地避难减少感染率需要多长时间以及减少多少。

也就是说,如果我们假设这种模式对其他地区大致相同,那么我们可以使用旧金山湾区的例子来创建一个粗略的时间表,说明就地避难需要多长时间来降低感染率以及降低多少。

整个加州的就地避难法令于 3 月 19 日生效,纽约的就地避难法令于 3 月 22 日生效。旧金山湾区的就地避难所已于 3 月 16 日生效。因此,如果我们按照这个粗略的模型,加州比湾区晚 3 天,纽约比湾区晚不到一周。

正如本文所预测的那样(在更新之前),随着其他地区的就地安置时间表赶上来,我们似乎也看到了类似的结果。

数据源和参考

这篇文章的所有数据和可视化来自 Knowi 冠状病毒数据中心。那里使用的数据来自约翰·霍普斯金,世卫组织,疾病控制中心。
在这里查看他们的数据来源列表。

各州的避难所订单日期可以在纽约时报页面这里找到。

旧金山官方的就地安置避难所命令可以在这里找到。

放弃

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

数据驱动的归因模型背后有什么科学吗?

原文:https://towardsdatascience.com/is-there-any-science-behind-data-driven-attribution-models-1cdf445321e9?source=collection_archive---------26-----------------------

匹配模型能准确估算升力吗?

每个营销渠道声称占总销售收入的一部分(来源: pixabay

归因是将价值分配回公司的各种营销渠道的问题,即使对于一家只在网上做广告并拥有干净、可靠数据的公司来说,这也是一个棘手的问题。例如,让我们想象一个销售花式袜子的网站,一个客户通过三个渠道访问该网站三次,如下所示:

  • 付费搜索
  • 社交媒体(脸书的再营销广告)
  • 附属公司(25%折扣)

在最后一次访问中,消费者用折扣购买了一些袜子。

归因是困难的,因为有太多的未知变量。我们不知道消费者是因为付费搜索广告才找到该网站,还是无论如何他们都会找到该网站。同样,我们不知道折扣是否是决定销售的决定性因素,或者消费者是否会购买袜子。

显然,准确的归属是困难的。大多数公司依靠简单的启发式方法,比如将所有价值分配给最后一个渠道(最后点击)或者将价值平均分配给每个渠道(线性)。

最近,数据科学界提出了许多更复杂的算法。有人声称这些方法比更准确,但是,没有证据支持这些说法。相反,基本原理似乎是,因为该理论比上述简单的启发式方法更“好”,所以结果必须更准确。对于一个以“科学”命名的领域来说,这多少有些令人惊讶。理论是廉价的,证据是黄金。

我写这篇博客是因为 2019 年 Gorden 等人发表了一项研究,该研究将数据驱动方法的输出与一系列大规模随机对照试验(RCT)进行了比较,并揭示了一些非常有说服力的结果。对于那些不知道的人来说,随机对照试验是实验设计的黄金标准,当应用于营销领域时,可以提供对营销渠道价值的准确测量。

在回顾这项研究的结果之前,我将简要回顾一下什么是 RCT,因为如果你不知道,你真的应该知道。

随机对照试验

正如每一个优秀的科学家都会告诉你的那样,给你的频道确定价值的唯一方法就是进行严格的实验。在这种情况下,严谨意味着实验应该是双盲的和随机的。

随机化表示个体被随机分配到控制测试组。目的是确保除了实验操作之外,两组在统计学上是相同的。

双盲是指实验者和受试者都不知道自己是在试验组还是对照组。

为了满足这些标准,在测试在线广告时,我们首先要确定我们的目标用户群。让我们想象一下,我们正在脸书上投放潜在客户广告,我们希望将旧金山湾区 20-29 岁的女性用户作为目标用户。这是我们的目标群体,但是在我们展开全面的广告宣传活动之前,我们想进行一次试验。在这种情况下,我们只会向随机选择的目标群体显示广告。这是测试组,其余用户属于控制组。在运行实验一段时间后,我们将比较两组的转化率并得出我们的结论。简单。

有人可能会问,为什么广告商不总是在他们的营销渠道上运行 RCT。简单的答案是,许多广告渠道不提供这种设施。虽然脸书把如何在他们的平台上运行 RCT 弄得很清楚,但我不知道如何在谷歌的搜索平台上运行 RCT。

证据

前述由 Gorden 等人进行的研究 2019 将数据驱动方法的结果与脸书的一系列大规模 RCT 实验进行了比较。试验规模很大,有 15 个随机对照试验,包括超过 160 万次广告投放。

数据驱动的属性有很多种,本文评估了一种称为匹配方法的类别。这些技术通过识别两组用户来工作,一组是看过广告的用户,另一组是没看过广告的用户。我们可以称这些小组为伪控制组伪测试组。这两个组被匹配,因此它们在多个维度上尽可能相似,例如年龄、性别、社会经济地位或购买倾向,并且每种方法在精确匹配方法上不同。因此,与使用随机化原则来确保测试控制组之间统计平等的随机对照试验不同,数据驱动方法查看历史数据,并明确尝试识别除了暴露于所述广告之外在各种指标上平等的组。

关键的一点是,没有一种数据驱动的评估方法可以复制 RCT 试验的结果,并且最大程度地高估了广告的价值,通常超过 300%。建议感兴趣的读者检查图 10 Gorden 等人 2019 以获得完整的结果分类。

结果是,如果你依靠这些数据驱动的方法来确定你的广告是否成功,你很可能高估了你的广告,甚至误认为是盈利。

事实上,让我推测这就是为什么许多广告门户网站不为您提供运行 RCT 的工具。你可以说我愤世嫉俗,但我怀疑大多数广告门户网站乐于让你高估广告的价值。

广告测量方法的比较:来自脸书大学大型现场实验的证据营销科学 38.2(2019):193–225

活动偏差

这是怎么回事?在科学术语中,一定有一个未观察到的变量未被数据驱动方法解释。算法无法将伪控制伪测试匹配。因此,除了接触广告之外,肯定还有其他因素将这两个群体区分开来。

伪测试组中的用户是那些看过广告的人,所以根据定义,他们在实验期间一定在广告门户上,而在伪控制组中的用户没有,否则他们会看到广告。因此,有一种理论认为,那些在伪测试组的人在实验时比那些在伪控制组的人更活跃,这并不意味着那些更活跃的人也更有可能购买。这个建议最早是由 Lewes 等人(2011) 提出的,值得一读。

如果是真的,那么真正控制这种效果的唯一方法是故意不向访问广告门户的特定比例的人显示广告。因此,进行随机对照试验。

Lewis,RA 等人,“这里,那里,和每一个地方:相关的网络行为会导致对广告效果的高估。”第 20 届国际万维网会议论文集。2011.

摘要

在本文中,我们回顾了一种称为匹配方法的数据驱动属性的有效性。结果很明显,这些方法不起作用,而且往往高估了脸书广告的提升。其他流行的方法存在,如马尔可夫和沙普利方法,我们不能肯定地说这些也不起作用。然而,我们也不能肯定地说它们会起作用,或者说它们比简单的启发式方法更准确。

这是许多数据科学固有的问题。公司拥有爆炸式增长的数据,但是知道如何从这些数据中获取价值是很复杂的。在这个领域游刃有余的公司将拥有在科学和商业领域都有立足之地的人才。人们对上述论点很熟悉。重要的是,这些人将在决策过程中发挥关键作用。

曼哈顿有足够的空间保持六英尺的距离吗?

原文:https://towardsdatascience.com/is-there-enough-space-in-manhattan-to-stay-six-feet-apart-8da530e2c545?source=collection_archive---------36-----------------------

很可能是有的,但在其他人口更稠密的地方,情况似乎并非如此。

人们在纽约州的韦斯特菲尔德 WTC 四处走动。凯·皮尔格拍摄的照片;公共领域。

随着第二波冠状病毒的到来,我参与了一场讨论,与他人保持健康的距离成为一个话题。有人说:

我真的很高兴没有住在曼哈顿——那里人口如此密集,如果每个人都出去,他们甚至不能保持 6 英尺的距离!

虽然这种说法显然只是一种比喻,但它真的激起了我的好奇心:曼哈顿真的人口密集吗——如果人们真的不适合在街上,如果他们想保持适当的距离怎么办?我决定利用公开的地理数据来研究这个问题。

用于分析的数据

如果我们想回答我们的研究问题,我们需要三条信息:

  • 最好是小空间单元(例如,街区)的边界,以便能够显示整个城市的变化;
  • 关于这些空间单元的人口信息;
  • 土地覆盖数据。“外部”只是城市面积的一个子集——很大一部分被建筑、水和其他东西占据。

幸运的是,纽约州有一个广泛的开放数据存储库,所有这些都是可用的:空间数据格式的邻里制表区在电子表格中由 NTA填充;和作为空间栅格数据集的土地覆盖数据。我使用 3 英尺分辨率版本的数据进行分析,因为它更小,处理速度更快,但也有更新、更详细 36 倍的数据集(具有更多土地覆盖类型)。

纽约地理数据:邻里多边形;土地覆盖栅格数据;土地覆盖层特写。数据来自纽约开放数据,数字由作者提供。

工具

我是可重复研究的忠实粉丝。因此,我在一个 iPython 笔记本上写了分析,你可以在这里找到。从下载数据到计算统计数据和绘制地图,它什么都有。对于那些熟悉 Python 地理分析的人来说,我的主要工具是 GeoPandasrasterstats 包并不奇怪。

分析和结果

面积和人口

这一分析(和思维实验)的一个关键假设是,当人们离开房子时,他们需要留在他们的社区。如果我们让他们去(并填满)公园、机场、码头、墓地等,我们还不如让他们溢出城市界限(因为行政边界完全是任意的)。反过来,这将确保每个人都有足够的空间,而不可能出现没有空间的情况。

因此,我着眼于社区层面的数据,忽略了那些与其规模相比人口很少的社区——就像我上面举的例子。举个例子,中央公园不在了。

由于我下载的数据得到了很好的维护,我可以简单地将边界地理数据与人口数据连接起来。

可用的室外空间

分析的下一步是确定每个街区的可用室外空间。土地使用层有七个类别:1:树冠,2:草/灌木,3:裸土,4:水,5:建筑物,6:道路/铁路,7:其他铺砌表面。

这些土地覆盖物中的哪一种可用于我们的分析还不是很明显。我决定#1 和#2,虽然不是完全开放的空间,有资格这样做。即使有树,我们也可以把人分散在它们中间,让它们保持距离。关于树木,有一点需要注意:它们的树冠可能会覆盖较矮的建筑,但我认为这可能是个小问题。#3 明显相关,#4 和#5 明显不适用。我也把#7 归类为适合——这些是停车场、庭院等。棘手的类别是第 6 号,“公路/铁路”。

一方面,这一类别很重要,因为道路是人们出门时直接去的地方。然而,并不是所有的路面都是可用的——有些路面实际上是供汽车行驶的。作为专家估计,我把这一类的面积的 50%都考虑进去了。**

包装圈

"将不同大小的圆圈打包在一起的最有效方法并不明显。"——在维基百科的圆形包装页面上,同一张图片的标题如是说。照片由 Scott Bauer 拍摄,公共领域。

由于当地推荐的距离使用英制单位(建议保持 6 英尺的距离,我在分析中使用了这个距离。⁴每个人都需要一个半径为 3 英尺的空圈。然而,由于同样大小的圆圈不可能完全填满——它们之间总会有一些空间——如果我们想确保没有人与另一个人的距离小于 6 英尺,人们将占用更多的空间。

半径为 3 英尺的圆的面积为 r π=28.27 英尺;根据维基百科的说法,我们必须用这个除以 0.9069 来得到圆圈被填满时所占区域的实际大小——结果是 31.18 英尺。

社区密度

最后一步是计算每个居民区有多少可用空间。如果这个空间小于 31.18 英尺,人们将无法在街道上行走。

对我们的突破性成果来说不幸的是,对纽约市的居民来说幸运的是,没有哪个街区没有足够的空间来保持足够的距离。

即使是最密集的社区,约克维尔的居住空间几乎是保持六英尺距离的最低要求的三倍。

最大距离

我们也可以从另一个角度来看我们的研究问题:如果都在街上,人们理论上能保持的最大可能距离是多少?这很容易计算(见笔记本)。对于这个公制,我返回到公制系统(双关语)并以米为单位计算这个距离。

如果每个人都走到街上,人们可以保持的最大距离(米)。作者图。

我在地图上显示了纽约市邻近地区的每个邻近地区的值(除了斯塔滕岛,那里的人口密度比其他四个区低得多)。

这张地图上的数值是“安全圈”半径的两倍:人与人之间的实际距离。我们可以看到,曼哈顿的人们之间大约有 3.5-7 米的距离,这取决于社区。在你家量出 3.5 米:真的没那么多!随着我们远离市中心,人口密度降低,因此人与人之间的最大可能距离增加。

结束语

虽然我在写这篇分析时做了尽职调查,但不应该完全当真——它更像是一个有趣的个人项目,而不是实际的研究。由于对数据有许多假设,结果并不是 100%确定的。

例如,如果我们对土地覆盖使用更详细的数据集(最好是基于矢量的数据集),我们可以获得实际的可用面积,并可以通过放宽整个“安全圈”必须在可用面积内的假设来拟合圆。⁶没有纽约市的相关数据。然而,在世界上的某些地方,例如,荷兰的 基础地理信息系统数据集将适合于此目的

来自荷兰的超详细土地覆盖数据:BGT 数据集。此部分显示“道路部分”图层:铺面区域、行人和自行车道(绿色、黄绿色);停车点(紫色);路面(蓝色);公共交通区域(沙地);以及铁路占用的区域(微红);作者图—使用 QGIS 创建。

无论如何,我觉得这个研究问题在当前的全球疫情中是一个有效的问题:地球上可能很容易有地方没有足够的空间让人们外出并保持距离。毕竟,纽约市甚至不在人口密度最高的 50 个城市之列。曼哈顿是纽约市人口最稠密的区,总人口密度为每平方公里 26,821 人。马尼拉是菲律宾的首都(也是上面表格中人口密度最大的城市),总人口密度为 46,178 ppkm。很有可能它最密集的部分没有足够的户外空间。

或者,一个更极端的例子是达拉维,印度孟买的一个地方,在 2.165 公里的范围内有超过 100 万人居住——人口密度比马尼拉高十倍。在这里,即使整个区域都是空的,人们也无法与外界保持足够的距离。不过也有好消息:根据彭博最近的一份报告,尽管困难重重,达拉维的领导在对抗新冠肺炎方面还是相当有效的。

笔记

只要查查巴黎或者拉斯维加斯的城市界限就行了。这些可能与你脑海中这些城市的地图不一致。
有些人可能会认为这类区域的份额过高(即城市可以有更少(或更窄)的车道。讨论这种说法不是本分析的一部分
上面提到的详细 36 倍的数据集将铁路作为一个单独的类别,但它需要更多的计算能力。此外,使用该数据集无法解决人行道、道路、停车点和其他类型的道路元素的分离问题,其中一些元素可供行人使用,而另一些元素则不能。
这里使用英制单位的另一个原因是源数据使用基于英制单位的投影。 这种设置还假设人们不能站在可用空间的边缘(例如,墙边),但他们的整个六英尺宽的泡泡都在这个区域内。⁶我们可以简单地在相关区域添加一个缓冲区,并用半径为 6 英尺的圆填充这个缓冲的形状。

这个标题是 Clickbait 吗?

原文:https://towardsdatascience.com/is-this-headline-clickbait-86d27dc9b389?source=collection_archive---------31-----------------------

使用机器学习检测点击诱饵

资料来源:Pexels

术语“点击诱饵”指的是一篇文章标题,其唯一目的是使用耸人听闻的语言来引诱浏览者点击进入某个网页。然后,网页通过用户的点击产生广告收入,或者将用户的活动数据货币化。这篇文章本身并不具有新闻的完整性,也没有研究或真正追求任何更深层次的意义——它只是一个将用户点击和数据货币化的工具。

随着社交媒体、智能手机的爆炸式增长和日益数字化的世界,不缺少争夺我们注意力的内容。在社交媒体上分享和转发的便利性让 clickbait 这样的杂乱信息泛滥成灾。

随着 clickbait 在网络上变得越来越流行(还记得当你滚动你的 Twitter feed,只能看到正版内容吗?)—我想看看是否可以使用机器学习对标题进行分类,以及这个过程是什么样子的。我这个项目的目标是为在社交媒体或各种出版商网站上大规模实施“点击诱饵拦截器”(想想“广告拦截器”)提供证据,在观众看到它之前,点击诱饵可以被标记或过滤掉!

数据

对于这个项目,我的数据由大约 2007-2020 年间来自各种点击诱饵和非点击诱饵来源的 52,000 个标题组成。我最终的数据集是从 Kaggle 上的数据集以及我自己对 Twitter 和各种在线出版物的抓取和 API 调用中编译的。数据根据来源被标记为点击诱饵或非点击诱饵,我的最终数据集大体上是平衡的(见下面的分布)。

Clickbait 来源: Buzzfeed、Upworthy、ViralNova、BoredPanda、Thatscoop、Viralstories、PoliticalInsider、Examiner、TheOdyssey

非点击诱饵来源:纽约时报,华盛顿邮报,卫报,彭博,印度教徒报,维基新闻,路透社

标签分布,用 Seaborn 绘制。

数据处理和特征工程

由于我最初只是处理每个标题的文本数据,下面描述了所采取的清理和特征工程步骤。

清洁和处理

  • 使用正则表达式删除了标题中的标点、链接和非字母/非数字字符。数字没有被删除,因为我想说明一个数字的存在。
  • 使用 NLTK 删除了英语停用词。
  • 每一个标题都被转换成小写和符号化——最初的 EDA 使用的是 unigram,建模和后来的 EDA 使用的是 unigram 和 bigrams。
  • 在我最初的 EDA 中使用了词频,但是我的模型依赖于 TF-IDF 分数,使用 NLTK 的实现来处理每个单字和双字。

附加功能工程

我创建了以下功能来评估标题文本数据:

  • headline_words :标题中的字数(在停用词被删除之前创建)。
  • 问题 : 1 表示是& 0 表示否,如果标题以一个疑问词开始并且/或者包含一个“?”(在停用词和标点符号被删除之前创建)。
  • 感叹号:如果标题包含感叹号,则为 1;如果不包含感叹号,则为 0(在删除标点符号之前创建)。
  • starts_with_num :如果标题以数字开头,则为 1,否则为 0。

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

在运行任何模型之前,我分析了点击诱饵标题和非点击诱饵标题的词频。词汇上有一些明显的区别,也有一些重叠,如下面的单词云所示。在 clickbait cloud 中,数字和模糊的术语一起流行。例如,利用这些词的 clickbait 标题可能是“人们实际需要的 19 样最好的东西”,因此读者会想点击阅读特定的人或事……

用 WordCloud 和 Matplotlib 绘制的 clickbait 标题中的前 20 个单词。

非点击诱饵标题中的前 20 个单词,用 WordCloud 和 Matplotlib 绘制。

我还分析了我的工程特性的类分布以及它们在每个类中的相关性。如下图所示,平均而言,点击诱饵标题比非点击诱饵标题略长。

与 Seaborn 密谋。

点击诱饵标题通常也以数字开头,或者在标题中提出一个问题。

与 Seaborn 密谋。

与 Seaborn 密谋。

建模

我训练并测试了以下模型——预测多数类的基线虚拟分类器、朴素贝叶斯分类器、随机森林分类器、线性 SVM 分类器和逻辑回归模型。我用来衡量性能的评估指标是准确率和召回率。我稍微强调了召回,以尽量减少误判,例如将一篇点击诱饵文章归类为非点击诱饵。以下是我的测试预测的准确性和召回分数的快照:

使用 sklearn 对结果建模。

使用 sklearn 的朴素贝叶斯混淆矩阵图。

如上所示,朴素贝叶斯在召回率和准确率得分方面表现最好,但其他模型也相差不远。朴素贝叶斯也是一个很好的最终模型,因为它比其他模型运行得快得多,这将在现实世界的场景中与更多的数据一起工作。

通过评估系数,我能够更仔细地查看模型的过程,并且我获得了关于模型使用什么特征和词来进行分类的有用见解。

总结想法和要点

我能够使用机器学习算法,如朴素贝叶斯、逻辑回归和 SVM,来准确地对点击诱饵和非点击诱饵标题进行分类。结果相当不错——准确率在 90–93%之间,召回率在 90–93%之间。我稍微优先考虑了召回,因为我认为最大限度地减少假阴性(将点击诱饵分类为非点击诱饵)会更有价值。

由于机器学习能够如此有效地工作,因此在读者甚至必须亲自可视化和评估标题之前,部署机器学习解决方案来过滤或标记 clickbait 肯定是一个真实的用例!

通过分析表现最好的模型的系数,我能够解释并深入了解模型如何决定一个标题是否是点击诱饵。

演示

我用 Streamlit 组装了一个简单的 web 应用程序来演示和测试我的带有新标题的模型。

使用 Streamlit 创建的 Web 应用程序。

请随意在 Heroku 上尝试部署版本,并提交您选择的分类标题: clickbait detector

如果你对这个项目背后的代码感兴趣——看看我的 Github:【https://github.com/AlisonSalerno/clickbait_detector

这家初创公司会是下一个 Theranos 吗?

原文:https://towardsdatascience.com/is-this-startup-the-next-theranos-9e8208c9976f?source=collection_archive---------29-----------------------

有社会意识的炒作还是炒作

有了足够的热空气,你可以超越尘世的束缚。由 Unsplash 上的 Farshad Rezvanian 拍摄的照片

十年来最受关注的生物技术创业公司的候选人已经出现。是的,现在才一月,但这一年太棒了。

EQRx 刚刚筹集了 2 亿美元,承诺开发比传统制药公司更快、更便宜的药物。这种说法并不新颖。每一种基于工具或技术的生物技术都能制造它。人工智能是这类炒作的热门话题。

EQRx 还声称,它们将扰乱当前的药品定价机制。他们的药品价格会比竞争对手便宜很多。他们要求我们“想象一个人们可以专注于治疗而不是价格标签的世界”。

而且还能大赚一笔。他们将把廉价药物带给大众,不是通过放弃利润,而是通过利用市场的强大力量。那是一个新的。

更多的嫌隙?

像这样的声明应该让你的狗屁探测器高度警惕。当然,Theranos 是医疗保健颠覆宣传的黄金标准。EQRx 比较怎么样?

像 Theranos 一样,EQRx 声称对一个老问题提出了新的解决方案(血液的手指测试;药物开发成本高)。和 Theranos 一样,EQRx 的目标是增加患者获得医疗保健的机会和负担能力。两家公司都在没有概念验证演示的情况下筹集了数亿美元。两者都有魅力非凡的创始人。两者都是由在各自领域没有经验的风险投资人投资的。

但 Theranos 的创始人是一个毫无头绪的新手。她和她的副手们从未建立过任何东西,也没有他们想要破坏的行业的经验。EQRx 由一个拥有数十年生物技术经验和成功的团队领导。他们可以更认真地对待。

你可以看出这个人是认真的,因为他双臂交叉。来自 Pixabay ,免费用于商业用途。

让我们开始吃吧

EQRx 的价值主张由两部分组成:

  • 以比现有公司低得多的成本开发药物
  • 将节省的费用与患者分成,从而在保持高药品利润的同时降低药品价格。

这样看来,这听起来很学究气,而不是破坏性的。仔细观察就会发现它非常有野心。

将药物推向市场的平均成本现在是 26 亿美元。推动这一成本的不是临床前开发,临床前开发主要是药物发现和动物试验。那最多花几百万或者几千万美元。成本也不是由临床试验推动的,临床试验耗资数千万至数亿美元。成功的药物开发只需要两个逗号。

药物开发成本是由失败推动的。大约有六分之一的候选药物通过了临床测试并获得了 FDA 的批准。对于肿瘤学来说,这个数字更像是 1/20。每一种成功的药物都要付出五次失败的代价。消除这些失败,你就可以将产品价格减半,同时还能获得利润。

候选药物成功的概率。2015 年的利率可能会被边界效应夸大。来自对临床试验成功率和相关参数的估计知识共享协议 CC BY 许可

EQRx 计划如何减少故障?主要是通过追求有效的药物靶点。药物靶标是被假设导致疾病的细胞蛋白质。候选药物结合并阻断药物靶标的活性,并且在临床前研究中证实了这一点。但这并不能证明他们能治愈疾病。在临床试验中会发生这种情况。如果一种已知能与靶标结合的药物也能治愈某种疾病*,它就被认为是有效的。

制药界的我也是

EQRx 的计划是让其他公司来承担验证药物靶点的重任,然后快速配制结合已验证靶点的新药。这就是众所周知的“快速跟随者”策略,而且并不是新的。最畅销的降胆固醇药物立普妥就是一个很好的例子。事实上,大多数新药都是“人云亦云”的药物。它们的工作原理与一流药物的作用靶点相同,但略有不同。

模仿药物确实有更高的成功率。新药与现有药物越相似,越有可能被批准。

1999-2014 年与现有药物的化学相似性和批准可能性之间的关系。自己的工作,数据来自药物开发中缺失的新颖性

最相似的药物获得批准的可能性几乎是普通药物的两倍(绿线)。制药公司注意到了这一点,新药与旧药越来越相似。

药物越来越像它们的前辈。自己的工作,数据来自药物开发中缺失的新颖性

仿制药物出现的平均时间是其前身出现后 2.5 年。为什么这个数字意义重大?因为从最初的药物发现到批准的平均时间是 7 年。当第一个同类药物被批准时,大多数模仿药物已经处于临床试验阶段。模仿药物研发者在开始研发前不会等待目标验证。他们刚刚输掉了争夺第一的比赛。

这都是关于专利寿命的

制药公司不会等到一流药物获得批准后才开始研究追随者。他们不能。现在专利有效期是 20 年。在那之后,药物就成了仿制药。当他们这样做时,价格在一年内下跌超过 50%。

回想一下,从一种药物被发现(并获得专利)到获得批准大约需要 7 年时间。那就剩下 13 年的专利时间。在此期间,药厂收取溢价。这些高昂的价格为药物的开发、失败药物的成本,当然还有利润买单。

EQRx 计划在投资药物开发项目之前等待验证。这意味着一流的药物将在 13 年后成为仿制药。如果 EQRx 再花 7 年时间获得批准,那么在面临仿制药竞争之前,它将只剩下 6 年时间。仿制药不必为 R&D 或失败的临床试验买单。没有一家制药公司能在价格上与他们竞争。

MBA 梦遗

唯一可行的方法是缩短开发时间,降低失败率。两者兼而有之。这些并不是什么新目标。几乎每个制药公司的高管都曾经尝试过。都失败了。

药物开发成本不可阻挡地上升。这种增长是如此有规律——每年 9%——以至于它有一个名字:Eroom 定律(摩尔定律的反向)。数以千计非常聪明的 MBA 认为他们有补救办法。他们中没有人知道。

自 20 世纪 50 年代以来,药品上市成本每年复合增长 9%。自那以后,技术、管理或监管方面的变革都没有改变这一轨迹。自己的工作,数据来自诊断药物研发效率&下降

也许 EQRx 的人会在其他人失败的地方取得成功。但是他们这样做的计划听起来并不乐观。根据创始人Alex Borisy 的说法,“今天,你可以对十亿种化合物进行虚拟筛选,按需合成所有这些化合物,而且你可以在云中一夜之间完成。”

啊,是的,虚拟生物技术公司。在那里,你可以省去 R&D 的所有麻烦和费用,计算或外包你的问题。德瑞克·洛夫详细剖析了这个幻想。我要指出的是,我工作过的每家公司都沉迷于此。从来没成功过。

EQRx 不仅承诺在其他人失败的地方取得成功,他们还将大规模地这样做。该计划是在 10 年内推出 10 种药物。

坚果

概括来说,EQRx 将

  • 创造新药的速度比以往任何人都要快
  • 以更高的临床成功率去做
  • 不要侵犯现有专利
  • 以前所未有的规模去做
  • 做得又快又便宜,这样他们就可以和仿制药竞争了

希望 EQRx 成功。十年内以低廉的价格开发出十种突破性药物,将会真正造福人类。但这是不可能的。

预测 EQRx 的失败既容易又便宜。超过 90%的生物技术创业公司最终都倒闭了。如果你预测每一次冒险都会失败,即使你只是一个反对者,你也会看起来像一个预言家。我不想成为那样的人。但是,这里的难度太大了。

EQRx 不是骗局,只是幻想。但是 Theranos 也是这样开始的。让我们希望 EQRx 带着尊严(也许在将一两种药物推向市场后)而不是凶残地倒下。

*尽管并不总是如此。有时药物也会结合其他靶标,结果发现这些其他靶标才是致病的靶标。药品行业没有消除风险的方法。

披露:自 1999 年吉利德收购我的雇主(NeXstar Pharma)以来,我一直持有该公司的股票,自 2000 年我帮助创立 SomaLogic 以来,我一直持有该公司的股票。

对 AI 的信任值得信任吗?

原文:https://towardsdatascience.com/is-trust-in-ai-trustworthy-88e2eb2ae5d6?source=collection_archive---------28-----------------------

科技世界和人工智能有一个信任问题。但是在我们开始用制造问题的同样的蛮力来解决它之前,让我们停下来问一下,我们值得信任吗?

法兰克诉Unsplash 上拍摄的照片

在我上一篇关于 信任人工智能 的文章中,我写了如何在人工智能中建立信任需要包括 1)技术和人工智能背后的人和机构(那些销售、制造和使用它的人)以及 2)人工智能系统和解决方案的技术。但是,在我们跑去集体开一家“信任”商店或规划蓝图并开始将信任编码到我们的行为或技术中之前,让我们花点时间来理解信任。

第一个群体是人民,他们应该而且总是对信任负有主要责任。为什么?因为无论我们在技术中直接或间接地构建了什么工具和方法,它们总是我们目标的产物。以微软最近的衍生产品 Xiaoice (或者它的早期版本, Zo )为例,这是一个有问题的聊天机器人,有一个十几岁的女孩角色。开发这个聊天机器人的几个版本花了五年多的时间。为什么在这个生态系统中领导可信人工智能的任何人都不能提出足够的关注,即在十几岁的女孩之后建模一个聊天机器人?这些产品不仅让微软,也让整个聊天机器人行业——以及人类——离信任越来越远。难道他们不能创新,展示他们的才华,甚至用一种不同的、问题更少的、投机取巧的角色来赚钱吗?

为什么我们总是弄错呢?是因为我们不懂信任吗?这是因为做出技术和商业决策的人被困在他们孤立的世界里,除了闪亮的可能性之外,无法感知任何东西吗?因为法律领域之外的责任和义务不是技术建设生态系统的一部分?即使当我们插入每个城市、每个家庭、每个招聘决定、刑事司法系统,与人工智能进行越来越多的互动和交易时,我们也不会花时间去“倾听”我们想要服务的人?

照片由阿里·帕扎尼派克斯拍摄

根据爱德曼的 2020 年信任晴雨表全球调查:

  • 61%的人认为技术变化的速度太快,政府对新技术的理解不足以有效地管理它们。
  • 66%的人担心技术会使人们无法知道他们看到或听到的是不是真实的。

通过人工智能,我们正在创新现实本身。最大的风险是,我们这些创新者将永远失去公众的信任——到某个时候,我们将没有办法纠正方向。如果我们现在不重新考虑信任技术的必要性,我们可能不会有第二次机会。

信任的复杂本质

信任就是满足我们设定的期望。所以这是关于意图,沟通,清晰,纪律,文化,习惯。很多东西很难精确定位或定义。信任也像倾听或理解。我们想要的比我们愿意付出的多,所以需要努力。

信任是一种有意识和潜意识的计算:当感知的信任成本小于感知的不信任成本时,我们就会信任。当信任的感知价值大于不信任的感知收益或价值时,我们就会信任。这是一种自我利益一致的信念。

我们如何准确地计算出这些感知的成本和价值?试试这个练习。想想你非常信任的人或事。到底是什么让你信任他们?什么会让你失去信任?随着时间的推移,你的信任有所改变或演变吗?下面是我从观察和分析中收集到的一系列特征,这些特征让信任变得令人兴奋、有价值且难以驾驭:

  1. 信任是一场赌博。它需要我们去猜测,去相信,去相信。
  2. 参差不齐。我们想要拥有的比我们想要给予的多。
  3. 信任需要时间和注意力。不能操之过急。
  4. 这需要努力。深思熟虑的工作。
  5. 信任随着时间和互动而发展。它随着我们的改变或学习而改变。
  6. 它是易碎的。更容易坏,更难修复。
  7. 这不是完全由你控制的。这是相互关联和相互依赖的。其他各方必须愿意并准备好。
  8. 信任对未来和社会都有影响——包括收益和成本。
  9. 信任不是一切。有时候,兴奋、一笔好交易、奖励或生存比信任更重要
  10. 信任不同于关心。你可以关心某人却不信任他们,反之亦然。
  11. 信任更多的是关于真实性(某人的价值观)而不是诚实。信任是关于理解;如果需要,让你保守秘密。
  12. 信任是难以捉摸的。我们对它越严厉,它就越躲避我们。

我对这些特征有一个单独的更深入的分析,但是对于这次讨论,我们可以将它们分成三个关键点。信任包括:

  1. 缺乏确定性和高度可变性。
  2. 对自我意识的需要,以及对他人和未来影响的认识。
  3. 灵活自律,愿意付出努力,但放弃控制的欲望。

那是棘手的工作。为什么我们还要担心信任?因为信任是无价的。它能够更快、更低风险地做出决策。它使具有不同自我利益和目标的不同群体能够合作实现更大的集体价值和机会。信任可以产生新的想法,并形成生态系统,将想法付诸行动并形成规模。

什么时候信任很重要?当我们在不确定的情况下或与我们不确定的人群或机构一起做决定时,这很重要。想想你从哪里获得关于冠状病毒、工作适应力或在家上学的信息和指导。我们根据已知的东西来导航“未知”的元素。基本上,我们对未来的决定是基于我们从现在和过去所能预测或推断的。信任有助于我们做一个精心计算的赌注,以驾驭风险和回报。这就是信任如此珍贵、令人害怕和令人兴奋的原因。

完全理解信任的关键是“感知的”价值或成本。还记得信任特征列表上的最后两行吗?对我们来说,很难对复杂的相互联系和一个情况的每个角度有一个完整的了解。我们的信任程度基于我们对现实的了解和理解,以及我们的局限和偏见。我们的感知。这就是为什么我们说后知之明是 20/20。这就是为什么我们在一次大采购后会后悔,或者后来意识到我们所认为的一笔好交易、一份好工作或一个好伙伴并不是这样。

我们不想被人耍,更不想让大家发现我们自己耍了。这种对我们脆弱性的社会认知让我们更加烦恼。我们对自己的信任能力失去了信任。 这就是为什么失信的成本如此之高且难以修复。

狡猾的骗子

我与技术决策者的大多数讨论似乎都集中在:

  1. 我如何区分真实和炒作?也就是说,哪种技术(5G、对话式人工智能、差分隐私)已准备好采用,适用于哪种用例?
  2. 我应该购买或投资什么公司和工具?
  3. 什么策略可以“让”消费者和企业信任我的产品,“让我们远离麻烦?”
  4. 我如何在不减缓成长的情况下把自己从“坏演员”或“错误”中分离出来?

所有实际和公平的问题。我们需要回答这些问题来做出日常决策。但是另一组重要的问题没有人问过我:我值得信任吗?用户或公众应该信任我吗?他们什么时候应该或者不应该信任我?

让我们打开这个。我们什么时候值得信任?基本上,个人或集体的利己主义是信任和值得信任的最大动力。这种自我利益可以是无形的,如我们的价值观、社会地位、品牌、声誉,也可以是有形的,如工作、财产、定居点、商业股份。但是成本和价值都是可以感知的。信任还取决于我们如何以及与谁一起填充这个公式。是习惯性自动的,一切照旧吗?它是否对多个利益相关者进行了深思熟虑和反思,是否考虑了长期影响和短期影响?现在,人工智能创新完全是关于自动化、采用率和估值。能让我们产生信任的变量在哪里?

我们需要停止将图灵测试作为人工智能的目标和获取新闻头条的方式。对人工智能的终极渴望不应该是它欺骗我们的能力。我们应该关注它帮助我们、理解我们和回应我们需求的潜力。在 XiaoiceZo 青少年聊天机器人的例子中,重点似乎是展示一个看起来像人的商业上可行的聊天机器人。一个写诗,办画展,很“时髦”,穿校服,不介意成年男人向她表白的聊天机器人。在技术的巧妙中,长期的成本迷失了。想一想在一个高度资助和宣传的产品中滥用少女角色及其固有的性别偏见,这个产品的制作历时五年多。有这么多的时间来改变或纠正航向。我们想知道为什么没有更多的女性对科技感兴趣。

我们如何增加破坏这种基本信任的成本,降低针对弱势群体或走捷径的产品、技术和企业的价值?目前,它们之所以繁荣,是因为有一个群体或人群愿意支付高价来使用这些产品。在我们解决这个问题之前,我们怎么能开始信任人工智能背后的人呢?在这些人的手中,“值得信赖的人工智能”的标签会成为方便的幌子并制造混乱吗?它会一点都不值得信赖吗?

我们对信任的态度是不是完全错误的?

照片由伯纳德·赫尔曼Unsplash 上拍摄

我们都知道,给一个聪明人一份没有约束的说服蓝图,就像给他们一份如何操作的指南。你认为我们最初是如何“迷上”并“沉迷”于技术的?对信任的担忧已经进入市场。产品、咨询服务、技术工具和领导力教练正在进入信任的 业务战略

事实是,没有关心和同情的信任会导致对自我利益的信任,这意味着我们可以相信人们会受自我保护本能的引导,即使以他人为代价。没有尊重的信任导致傲慢和操纵。没有意识的信任可能是危险的。没有喜悦的信任,无聊。

这里是对 NPS 设计者和一些多样性和包容性项目的一些集体反馈——大多数人都明白。他们得到了在调查和培训中需要说的话(显性文化)和他们能够或应该如何表现(隐性文化)之间的差异。见鬼,我们教孩子们这个。我们说“不要撒谎”,然后当着别人的面撒谎,说我们的年龄、薪水以及为什么迟到。在这样的环境下,信任是如何发挥作用的?

员工信任隐性文化——通过观察领导在做什么。如果接受采访或在公共场合演讲,什么时候鼓掌,什么时候保持在他们的公关指导点上。但是爱德曼的调查结果显示普通大众也知道这一点。最终,我们都明白了。问题是我们还有什么其他选择,以及我们在多大程度上摆脱了我们的习惯模式去做一些事情。

记住,信任是关于我们或对方的感知价值和感知成本。我们所能理解和看到的,作为我们的得失。有时候随波逐流,随大流也是应该的。我们不能假设我们得到了他们的信任。你有没有听到有人说“它不知从哪里冒出来的”?但你比他们早看到了?很少有事情是凭空出现的——这取决于我们在追踪谁和什么。

这一切意味着什么?

如果有人出卖你的信任,赶紧跑。或者慢下来足够理解利益的对齐。因为他们可能会有利益冲突。如果有人向你展示如何骗取别人的信任,赶紧跑。除非你是一个游牧民族,并计划赚快钱和隐藏起来。那样的话,我不是给你建议的人。但如果你真的在深思熟虑地思考信任,那么首先从这个问题开始:我信任自己吗?为什么或什么时候我不值得信任?谁或什么可以帮助找出丢失了什么?练习你对自己的信任度。

问题和答案一开始可能会感觉不舒服。但是根据我的经验,我可以告诉你,它们也会给你一种解脱感。或者至少是清晰的。你不必去忏悔。肯定的,不要发微博。但是要知道自己的目标。如果你从事制造、购买或使用技术的行业,尤其是人工智能,在构思或决策阶段,问这些重要的问题。你有一个选择。人工智能系统既复杂又可靠;并使用经过彻底测试的、符合伦理道德的、准确的数据。也就是说,如果它们不是为了标记偏见或匿名或对数据源透明而设计的,系统就不会自动指出这些问题。当然,这并不是终点。人工智能系统正在发展。即使是用大量资源和对细节的关注构建的东西,也可能被其他拥有不同系统和不同目标的人重新构建、破解或打乱。

我们有科学和建筑评论,它们是很好的反思模型。但往往连认知多样性都没有。我让一些严肃、严厉的评论家评论了这篇文章。我还让一个不是来自技术领域的人,为了清晰起见,对它进行了审查。够了吗?

信任是结果。这是一个决定,一个措施,一个标准。与其试图建立信任,不如我们用责任和信任来设计?设计“具有信任的人工智能”是关于一个一致的、负责任的决策框架,该框架牢记关于受影响的人的考虑。

而不是“我们如何让人们信任 5G 或 AI,以便他们更快地采用它?”,如果我们问:

  • 为什么人们不信任某种技术的使用——5G、人工智能、数据分析或神经技术?
  • 哪些人或者哪些群体不信任?
  • 他们为什么不信任它?
  • 他们什么时候不应该相信它?
  • 他们会失去什么?他们的担忧是什么?
  • 是否咨询了该团体或该团体的支持者?
  • 我们如何创新来解决他们的担忧?

我们能做什么?

我经常与积极而关切的人工智能专家、商业领袖、研究人员、教育工作者、工程师和产品经理交谈,他们问:但我能做什么?他们雄心勃勃,他们想在经济上和职业上做得更好。但他们厌倦了不得不妥协自己的价值观,或以他们认为存在根本缺陷的方式做事。他们问我,为什么我们一直让世界变得更糟。他们正在寻找替代品。他们希望重新审视我们的技术制造框架,而不影响他们的愿望。他们希望他们的领导人将这一转变作为优先事项。他们希望指标有所改变。他们希望别人改变。我知道,从很多方面来说,我过去和现在都是这样的人。

这是我告诉自己的:到 2030 年,人工智能预计将为全球经济增加超过 13 万亿美元。这意味着它将触及人类系统和环境的每个部分,将产生持久的影响,并将产生足够的收入,我们没有借口而不是带着责任和信任投资建设。监管监督会阻碍创新。我们甚至还没有提到资金的关系,这是许多利益冲突的根源。不要对推动问责制感到内疚,好像我们在某种程度上背叛了公司或经济。我们通过回归基本面——我们的价值观来帮助他们和我们。这一切到底是为了什么——人民。

这就是我告诉技术和商业领袖的:对我有用的是意识到缺少什么,并重新构建问题陈述。我们正走向认知超载。我们需要信任来帮助我们驾驭世界。无论是人工智能还是其他技术,如果我们没有办法看到或理解对所有利益相关者的影响,我们将会做出可怕的事情。我告诉他们不要低估或高估他们拥有的资源、权力和技能。不管他们知道什么或者有什么,利用它。向他人学习或交流想法。加入一个有着不同想法和共同价值观的人的社区。关心是可以的。关心很重要。让我们让关心变得可以接受。平衡它与我们的需求。找出如何满足我们成功的专业和智力驱动力,并创新平衡的饮食。让我们成为我们想成为的人,为我们想创造的未来做出贡献。问,我错过了什么?什么能让我更值得信任?谁能帮我弄明白?

这激励我启动了负责任的创新项目,并为产品和技术的构思、开发和评估创建了一个框架。但这仅仅是一个开始。我们不能单独或孤立地做到这一点。从生存到繁荣的转变必须成为科技文化的准则。如果我们要制造值得信赖的技术或人工智能,我们必须将信任整合到我们的流程中,并以值得信赖的方式制造它。但在此之前,我们必须花时间去理解信任,并问问我们缺少什么。为此承担责任。这是我们唯一可以相信的转变。

加州大学伯克利分校 MIDS 分校值得吗?

原文:https://towardsdatascience.com/is-uc-berkeley-mids-worth-it-5ac645aa79f8?source=collection_archive---------6-----------------------

我是如何在 MOOCs、证书和其他大学中选择这个数据科学硕士项目的,是否值得。

本周有人联系我,询问我对加州大学伯克利分校信息与数据科学硕士(MIDS)项目的看法。这是我过去一年一直在积极追求的非全日制在线硕士课程。“总的来说,我感兴趣的是,你是否会从价格和价值的角度推荐它,”他问道,“如果你研究了其他项目,你最终是如何选择 MIDS 的?”

(也见我入节目两年更新: 一个非全日制数据科学硕士项目如何改变我的人生)

南大厅,加州大学伯克利分校信息学院的所在地。图片由维基共享,用户:Falcorian/CC BY-SA

“总的来说,我感兴趣的是,你是否会从价格和价值的角度推荐它——如果你探索了其他项目,你最终是如何选择 MIDS 的?”

两年前,当我评估包括伯克利在内的各种数据科学项目选项时,我也有同样的问题。在 MOOCs 和自学的时代,为什么有人要付出更高的成本去攻读正式的硕士课程?在硕士项目中,伯克利也不是最便宜的。伊利诺伊大学厄巴纳-香槟分校(UIUC)提供类似的课程,费用仅为 2 万美元,而伯克利的课程费用接近 7 万美元。那么是否情有可原呢?当我在网上搜索答案时,我只能找到一些过时的 Quora 帖子,这些帖子没有什么有用的信息。我今天快速搜索了一下,看到了同样的帖子。所以我想给你一个内幕消息,截止到 2020 年夏天。

这篇文章的目的是描述为什么我选择了这个项目,为什么它对我来说是值得的,作为一个已经完成了一半多一点的学生。这个项目对你是否有价值取决于你的个人情况和目标,但在分享我的情况时,我希望能让你的决定更容易。

我从数据分析师做起。在 Unsplash 上由 Carlos Muza 拍摄的照片

为什么我想学习数据科学

关于我:我的职业生涯一直处于商业判断和数据分析的交汇点。作为毕马威风险咨询业务和优步内部审计团队(财务和会计)中少数精通 SQL 的人之一,我将法律术语翻译成查询,从支持审计建议的数据中提炼故事。我使用本福德定律、关键词搜索和基本统计来识别欺诈计划和其他风险,并以用数据解决复杂难题为荣。

然而,我发现仅仅诊断过去的事件从长远来看是没有效率的,在智力上也是不令人满意的。到 2017 年,我已经尝到了学习基本 Python 给我的工作流带来的额外灵活性,这使我能够扩展到关系数据库之外。我亲眼目睹了我那才华横溢的同事丹尼尔·皮尔斯,用人工智能算法为一项调查提供了一个关键的证据。传统上专注于描述性或诊断性分析的风险管理行业正在适应更具预测性和规范性的分析。最新的欺诈监控工具利用机器学习来检测伪造文件或可疑的费用报销。我想站在这场革命的最前沿。

我开始通过 MOOC 在数据科学方面训练自己,但很快意识到它的局限性。首先,我必须建立自己的课程,但问题是我不知道自己不知道什么。我也很难找到高质量的内容来映射到我的学习计划中,因为我不知道如何评估它们。我尝试的课程往往侧重于工具,而我需要更多一点的帮助来培养数据科学思维。最后,我没有足够的动力或压力来让自己负责并完成我开始的课程。所以我决定寻找替代方案——数据科学硕士项目。

我要做一些决定。照片由莱蒂齐亚·博尔多尼Unsplash 上拍摄

我需要从数据科学项目中得到什么

具有品牌价值和信誉的合法硕士学位

如果我要奉献时间和金钱,这对我来说是不够的,但是其他人可以告诉我学到了一些东西。我考虑过更短、更便宜的 DS 证书课程,但我不知道它们会给我的简历增加多少可信度。因此,我决定专注于知名高等教育机构的硕士项目。

兼职和远程

我在优步的职业轨迹很棒,我不打算放弃。虽然发展 DS 技能很重要,但发展领导技能和领域专业知识也很重要。一个兼职项目将允许我保持我的收入,继续我目前的职业轨迹,并继续深造。

我不在乎学校在哪里,只要我能从旧金山的家里到学校。这就排除了芝加哥大学和华盛顿大学,这两所大学有兼职项目,但只在校园内。

技术技能进入门槛较低,但有机会学习

我主修商科,对分析略知一二。当然,在我的生活中,我写过一些关于循环的,但是我不能评论任何数据结构和算法。我最后一次接受统计学的正规教育是在大学三年级,最后一次是数学,高中 IB 微积分。对我来说不幸的是,一些项目要求申请者熟悉线性代数。我想我可以从路易斯安那州立大学或其他地方自学,但我渴望开始学习,所以我很快排除了那些课程。这些包括 UIUC,UCLA 和约翰霍普金斯大学。

我也不想太深入另一端,也就是商业分析。我已经知道商业分析。所以我排除了哥伦比亚大学这样的项目(面对面和在旧金山,但也是 8 万美元!)和印第安纳州。

网络和社区

我的哲学是,我不可能学到所有该知道的东西,但我可以随时打电话给朋友。因此,我想要一个能让我以有意义的方式与学生和教师交流的项目。这就是为什么许多 MOOCs 对我不起作用的主要原因。

伯克利吸引我的是它的社区。 MIDS 2017 年状态报告称:

2016 年,一项计划调查表明,72%的学生同意这一说法,“我觉得自己是我大学社区的一员”,83%的学生同意这一说法,“这个计划帮助我发展了与同学的关系网。”

我被卖了。

在 it 行业呆了一年后,我完全同意——远程学习不能阻止我完全融入社区。小型直播课堂(< =15 名学生)、与教师频繁的办公时间、关于各种主题的活跃 Slack 频道以及偶尔的本地聚会都增加了归属感。

最终的选择

根据我的电子表格,只有三所学校符合我的所有条件:圣母大学、西北大学和伯克利大学。因为我在伯克利完成了我的本科学业,并且喜欢上了它,所以它在我心中的分数自然就更高了。我还知道,如果有任何校园活动,我可以很容易地从旧金山访问。所以我决定先申请伯克利,其他的留在我的口袋里。我被录取了。

我该怎么办?停止投资我的事业?没想到会这样。Avel Chuklanov 在 Unsplash 上拍摄的照片

伯克利的经历

2019 年 3 月拿到录取通知书后,我还是不确定。我只拿到了一份很少的奖学金,勉强够支付学费,并且需要自己掏腰包支付剩余部分,所以我犹豫了。我花了很多时间浏览 Quora,并在 LinkedIn 上联系现在或以前的 MIDS 学生。数据科学似乎是我可以在 YouTube 或 Coursera 上自学的东西,只要我能建立一个强大的投资组合,我就能在其中发展我的职业生涯。但是后来我反思了我过去几年的旅程,思考决定我必须知道什么是多么困难。我需要指导,我需要一个社区。所以我决定报名。“我总是能放下它,”我想。最坏的情况是,我会花一个学期的时间与美国顶尖公立大学的学生交流。我会带着对项目课程的良好理解离开,这样我就知道自己下一步该学什么了。

三个学期后,我对我的经历感到非常高兴。在项目的前几周,我开始将在学校学到的知识运用到工作中。去年夏天,我努力解释什么是置信区间,但是现在,我已经写了两篇统计学的小论文。今天,我可以训练 ML 模型,解释它们的内部工作原理,并应用超参数调整或维度缩减。然而,我成长的最重要标志是我的抱负。过去,我想成为一名精通数据科学的商业专家,但现在,我希望成为一名精通商业的数据科学家。我参加这个项目的时候想,如果我能和 ML 工程师明智地谈论这些概念,并讨论如何将它用于商业,那就足够了。今天,我正在考虑更深入地参与 ML 算法的职业。

学者们

伯克利分校在申请时对数学或编程没有硬性要求,但提供桥梁课程,并为建立坚实的基础提供支持。伯克利分校帮助弥合这一差距的能力是一项不可思议的资产,也是该项目的优势。它允许像我这样的商业人士带来有趣的观点,这样更多的技术人员可以向我们学习,反之亦然。MIDS 项目在管理思想、学科和背景的多样性和包容性方面非常出色。

内容的质量很高,这是不言而喻的。这些课程讲述永不过时的基础知识以及最新的数据科学趋势。从教授到大公司的顶级数据科学家,顶尖的导师们不断创新程序,以保持领先地位。

与 MOOC 不同,Cal 在项目中建立了问责制,使我可以轻松地每周投入 20-30 小时进行学习。只有 15 名学生参加的现场会议激励我及时完成所有的每周材料,以便我能够参与讨论。现场会议和办公时间给了我提问的机会,这是我学习的第三好方法。第二个最好的方法是通过做,这是由动手项目来完成的。我学习的最好方式是通过教学,通过注册成为一名编程课的助教,我也可以做一点——不完全是通过教学,而是通过提供对其他学生代码的反馈。如果这些还不够,我敬业的学生顾问会定期检查我,确保我拥有在 MIDS 成功所需的一切。

社区

信息学院还提供优秀的职业咨询服务。我已经和出色的劳里·哈斯克尔-沃纳——我们的职业顾问——进行了两次私人咨询,并从她的见解中受益匪浅。我们讨论了一些短期计划,比如提高我在 LinkedIn 上的地位和长期职业战略。她帮我联系了几个校友,他们可以就具体的话题给我进一步的建议。接受这种量身定制的高质量护理就像拥有了一位个人职业教练和导师。

最后但同样重要的是,社区参与度超出了我的预期。我交了很多朋友,因为有足够的机会与人们面对面交谈并了解他们。我喜欢学生主导的学习会议。我欣赏来自各行各业的学生:工程师、统计学家、教师、金融领袖、企业家和建筑师。Slack 增强了体验。我在 Slack 上做的第一件事就是寻求一些职业建议,于是很多学生都跳出来帮忙。我也喜欢#咖啡,#音乐,#酷数据-即,#伦理,和#不愚蠢的问题。来自世界各地、各行各业、各年龄段和各行各业的学生和教师分享他们的观点。挺好看的。

时间、金钱和努力工作?是的。转型?还有,是的。苏珊·d·威廉姆斯在 Unsplash 上的照片

那么,值得吗?

是的。

我很高兴我没有让价格标签阻止我追求我的梦想和我的职业生涯。亲爱的读者,我个人并不了解你,也不能说这对你是否会像对我一样富有成效。然而,我看到一群不同的聪明人正在享受这个项目。MIDS 似乎有适合每个人的东西。拥有博士学位或辉煌商业生涯的人;以前赢得过 Kaggle 比赛的人或者刚刚开始涉足 scikit-learn 的人;一个快到退休年龄的人或者一个刚从大学毕业的人。每个人的目标和旅程都与我不同,但在伯克利这里有适合他们的东西。

如果你正在读这篇文章,是因为你对 MIDS 持观望态度,我要说,去吧!如果你之前对在线研究生项目有任何疑问,请记住,MIDS 早在疫情时代之前就已经投资远程学习技术了。是的,在线学生得到了和其他伯克利学生一样的待遇和福利——图书馆、学生折扣、选举学生官员的权利,应有尽有。我甚至去伯克利拿了一张学生证,在博物馆展出,并用作 AC Transit 的免费乘车证。

这个项目给了我比我预想的更多的东西,对此我很感激。我唯一的遗憾是没有早点开始。

(注:经过进一步的研究,我发现了王巍在 2020 年 4 月写的这篇伟大的新帖。看看吧!)

(更新:看看这篇名为“ 的新文章:佐治亚理工学院 OMSA 分校 vs 加州大学伯克利分校 MIDS 分校 ”作者是我的同学和他的朋友。写于 2020 年 6 月。)

颠倒强化学习=模仿学习吗?

原文:https://towardsdatascience.com/is-upside-down-reinforcement-learning-imitation-learning-4a9d346f9f98?source=collection_archive---------53-----------------------

理解和实现 UDRL 算法

什么是颠倒强化学习?

我是在参加 NeurIPS 2019 的 RL 研讨会时发现这项工作的。老实说,这是我在会议上偶然发现的最酷的想法之一。你可以在这里看看我在会议上最喜欢的其他想法。无论如何,这个帖子是关于检查倒挂强化学习更多。你可以在这里阅读完整的论文,但是这里是摘要所说的:

传统的强化学习(RL)算法要么用价值函数来预测回报,要么使用策略搜索来最大化回报。我们研究了一种替代方法:倒置强化学习(倒置 RL 或 UDRL),它主要使用监督学习技术来解决 RL 问题。在这里,我们提出了 UDRL 的第一个具体实现,并证明了它在某些情景学习问题上的可行性。实验结果表明,其性能可以与经过几十年研究开发的传统基线算法相媲美,甚至超过后者。

如果你想更深入地了解这篇论文,你可以观看这个优秀的视频。但是 TL;dr——他们设计了一种新的监督学习算法来解决强化学习任务。没有政策梯度,没有价值函数估计,只是简单的旧的监督学习。下面是论文中的一个图表,可以更好地说明这一点:

行为功能试图预测的是— 根据这一观察,在这一期望的时间范围(总时间步长)内,采取什么样的最佳行动来实现这一期望的回报(总回报)。它们不是学习/模拟奖励,而是被用作直接预测行动的输入(命令)。

为了更好地理解整个算法,我进行了一些快速实验。这篇文章记录了我的发现。

我特别想回答以下两个问题:

  1. 既然实现大多数 RL 算法是极其重要的,那么让这个算法运行起来有多容易呢?
  2. 只是巧妙伪装的模仿学习算法吗?

要解决的任务—稀疏月球着陆器

为了回答上述问题,我实现了算法来解决稀疏月球着陆器任务(论文中提到的任务之一)。任务是学习一个代理人能够成功地登陆月球情人,如下所示:

我通过修改奖励函数将 OpenAI Gym 的“LunarLander-v2”环境手动转换为稀疏环境,如下所示:

  • 0 奖励所有非终端步骤
  • 最后一步的每集总奖励

实施说明

  • 所有的学习组件都是使用 Pytorch 实现的
  • 论文列出了他们在实验中扫描的所有超参数值。我根本没有调过音。只是选择了每一个的中间值。
  • 模型架构:

这个实验的代码可以在这里获得。现在,让我们来看看实验结果。

让算法发挥作用有多容易?

回答——出奇的快。我能够在我的第三个(!)运行尝试;而不需要对超参数进行太多的修改。我不记得任何基于策略梯度的算法上一次出现这种情况是什么时候了。

当然,这需要半信半疑,因为“月球着陆器”是一项相对简单的任务。但是如果你看看代码中实现的算法,你会同意这个算法简单得可笑!

只是变相的模仿学习吗?

我读这篇论文的第一印象是,这个想法听起来非常类似于模仿学习。考虑描述重放缓冲策略的论文中的以下摘录:

因此,随着训练的进行,通过设计,存储在缓冲器中的轨迹开始越来越像专家轨迹(高回报的剧集)。仅仅学习从状态到这些专家轨迹上的行为的映射(模仿学习)就足够了。这个想法实际上在之前的工作中得到更好的表达,叫做自我模仿学习

为了测试这一假设,我进行了以下实验——试图通过屏蔽行为功能的命令输入(保持其他一切不变)来了解要采取的最佳行动。所以有效地,仅仅学习仅仅从观察中预测行动。事情是这样的:

显然,将命令作为行为函数的输入会产生不同。我的猜测是,拥有这些命令有助于代理进一步区分不同类型的高回报轨迹,从而帮助它学习得更快。这显然需要在更复杂的环境中进一步测试,但我的微观实验结果绝对令人鼓舞。

实验的所有代码都可以在这个 Github Repo 上获得

这个帖子最初发布在 bprabhakar.github.io

你的分类器好吗?

原文:https://towardsdatascience.com/is-your-classifier-any-good-796050a36f9a?source=collection_archive---------64-----------------------

不要陷入错误的评价标准

本帖是本书的一部分: 用 Python 动手做量子机器学习

作者弗兰克·齐克特的图片,改编自电影《难忘的一夜》(1958 年,松林制片厂)

在本帖中,我们旨在预测一名乘客是否在泰坦尼克号沉船事故中幸存。但是我们甚至不看数据,而不是训练一个复杂的模型。通过这种方式,我们发现产生看似好的结果实际上毫无价值是多么容易。

预测泰坦尼克号上的幸存者是一项分类任务,因为有不同的结果值。具体来说,这是一个二元分类任务,因为正好有两个可能的预测(surviveddied)。

在我们开发复杂的机器学习算法之前,让我们实现我们可以想象的最简单的算法。猜测的分类器。

随机分类器

我们导入随机数生成器(第 1 行)并初始化它(第 2 行)。

我们的分类器是一个将乘客数据作为输入并返回01作为输出的函数。与我们的数据相似,0表示乘客死亡,1表示乘客幸存。

为了使用分类器,我们编写了一个 Python 函数,为训练集中的每个项目运行分类器。

分类赛跑运动员

该函数将分类器函数作为第一个参数(我们可以稍后替换分类器),将输入数据(如x)作为第二个参数(第 1 行)。

它使用 Python 的map函数来调用带有x中每一项的分类器,并返回一个结果数组。

让我们运行它。

运行分类器

[0, 1, 0, ... 0, 1, 1]

当我们使用train_input运行分类器时,我们会收到一个预测列表。

由于我们的目标是正确预测实际结果,所以我们需要评估预测是否与实际结果匹配。

让我们看看我们预测的准确性。

评估分类器

350 correct predictions out of 711\. Accuracy 49 %

我们定义另一个函数evaluate。它将我们算法的预测和实际结果作为参数(第 1 行)。

术语list(zip(predictions,actual))(第 4 行)创建了一个包含两个条目的列表。2 项列表是预测和相应的实际结果的配对。

我们从预测与实际结果匹配的列表中选择这些item(lambda item: item[0] == item[1])(第 3 行)。这些都是正确的预测。正确预测的列表长度除以乘客总数就是我们的Accuracy

太好了!我们已经在一半的情况下(或多或少)是正确的。当从两个可能的标签中猜出一个时,这并不奇怪。

但是也许我们可以做得更好?我是说毫不费力。我们知道死亡的人比幸存的人多。如果我们总是预测一个乘客的死亡会怎么样?

总是预测有乘客死亡

437 correct predictions out of 711\. Accuracy 61 %

我们预测的准确率高达 61%。不算太坏,是吗?这个值,也就是两个可能的实际值之比,就是患病率。

让我们考虑一个不同的任务。假设你是一名医生,你的任务是预测病人是否患有癌症。你的病人中只有 1%患有癌症。如果你一直预测没有癌症,你的准确率会达到惊人的 99%!但是你会错误地诊断出实际上患有癌症的病人。由于缺乏治疗,他们将会死去。

也许仅仅预测的准确性并不能很好地衡量我们算法的性能。

评估是每个机器学习算法的一个主要部分。乍一看,这似乎是微不足道的。然而,决定正确的措施是非常重要的一步。当你朝着更好的性能优化你的算法时,你将不可避免地在你的评估函数中朝着更好的分数优化。

但是现在,我们保持简单。评估分类器性能的更好方法是查看混淆矩阵。

作者弗兰克·齐克特的图片

总的想法是将预测值与实际值进行比较。在二元分类中,有两个可能的实际值:truefalse。并且有两种可能的预测:true或者false

有四种可能性:

  • 真否定 (TN):一名乘客死亡被正确预测
  • 假阳性 (FN):一名死亡的乘客被错误地预测为存活
  • 假阴性 (FP):一名幸存的乘客被错误地预测死亡
  • 真阳性 (TP):一名幸存乘客被正确预测

我们来看看predict death分类器的混淆矩阵。

预测死亡分类器的混淆矩阵

array([[437,   0],
       [274,   0]])

Scikit-Learn 提供了我们导入的confusion_matrix方法(第 1 行)。它将实际值作为第一个参数,将预测值作为第二个参数(第 3 行)。

它返回一个二维数组。在第一行,它显示了真阴性(TN)和假阳性(FP)。在第二行,它显示了假阴性(FN)和真阳性(TP)。

我们可以将目前测量的精度定义为:

它不关心是否存在系统误差,例如算法不能正确预测幸存的乘客(真阳性),只要它在正确预测死亡的乘客(真阴性)方面表现良好。

混淆矩阵为我们提供了分类器性能的更详细的度量。这些是:

  • 精确
  • 召回
  • 特征
  • 阴性预测值(NPV)

精度是“正面预测的准确性”。它只关注正面的预测,这些是乘客幸存的预测。

让我们看一下代码:

精确分数

The precision score of the predict_death classifier is 0.0

Scikit-Learn 提供了计算precision_score的功能。它将实际值列表和预测值列表作为输入。

因为我们没有一个正面的预测,所以我们的精确度是不确定的。 Scikit-Learn 将此解释为0.0的分数。

召回是“实际阳性的准确性”。它只关注实际的积极因素。

在 Python 中,它是:

回忆分数

The recall score of the predict_death classifier is 0.0

这一次,即使定义了recall(实际阳性的数量大于 0),分数仍然是0.0,因为我们的分类器没有正确预测单个存活。当它总是预示着死亡时,这并不奇怪。

特异性是“实际底片的准确性”。它只看实际的负面(死亡)。

而“负面预测值”(NPV)是“负面预测的准确性”。

这两个功能不是现成的。但是利用我们从混淆矩阵中得到的值,我们可以很容易地计算它们:

特异性和净现值

The specificity score of the predict_death classifier is 1.00
The npv score of the predict_death classifier is 0.61

函数specificity将混淆矩阵作为参数(第 1 行)。它将真阴性(matrix[0][0])除以真阴性和假阳性之和(matrix[0][1])(第 2 行)。

函数npv将混淆矩阵作为一个参数(第 4 行)并将真否定除以真否定和假否定之和(matrix[1][0])。

这四个分数提供了我们的分类器的性能的更详细的视图。

让我们也为我们的随机分类器计算这些分数:

随机分类器的分数

The precision score of the random classifier is 0.40
The recall score of the random classifier is 0.52
The specificity score of the random classifier is 0.51
The npv score of the random classifier is 0.63

虽然predict death分类器完全没有精确度和召回率,但它具有完美的特异性,并达到与我们测试数据集中的阴性百分比(患病率)相匹配的 NPV 分数。

随机分类器产生更平衡的分数。每次运行分类器,你都会得到一点点不同的分数。但是这些值似乎停留在一定的范围内。虽然这个分类器的精度通常低于0.4,但是 npv 高于0.6

混淆矩阵和相关度量给你很多信息。但是有时候,你需要一个更简洁的度量标准。事实上,机器学习算法中的评估函数必须返回它可以优化的单个度量。

这个单一的测量应该揭露一个没有真正增加任何价值的分类器。

本帖是本书的一部分: 用 Python 动手做量子机器学习

在这里免费获得前三章。

你的社区为抗击新冠肺炎做了足够的努力吗?

原文:https://towardsdatascience.com/is-your-community-doing-enough-to-fight-covid-19-aa745b424eb1?source=collection_archive---------45-----------------------

谷歌的移动性报告告诉我们什么是应对新冠肺炎的行为变化

根据美国疾病控制和预防中心的说法,防止新冠肺炎病毒传播的最好方法是与其他人保持足够的距离,至少 6 英尺。这有助于避免被感染者通过咳嗽、打喷嚏和说话时从鼻子或嘴里喷出的飞沫传播疾病。作为回应,许多国家鼓励居民呆在家里,只在必要或必要的工作时才离开。

上周,为了追踪人类行为如何因新冠肺炎而改变,谷歌发布了移动报告,该报告汇总了一段时间内匿名化的地理移动趋势。这些数据是通过手机定位历史记录获得的,可以跟踪多种类别的活动,包括零售和娱乐、杂货店和药店、公园、公交车站、工作场所和住宅区。通过这些报告,我们现在可以看到美国和全球的居家条例是如何影响行为的,以及我们可以在哪些方面继续做得更好以阻止这种传播。

全球行为的变化

根据 4 月 9 日发布的最新报告,减少人类互动的全球倡议正在对行为产生巨大影响。全球平均值显示,所有公共聚会活动减少,在家人数增加。具体而言,报告强调了以下几点。

  • 零售和娱乐活动平均减少 60.5%
  • 工作场所出勤平均减少 35.5%
  • 杂货店和药店平均降价 38.6%
  • 在家时间平均增加 16.8%

虽然这些数字代表全球平均水平,但在国家一级,我们看到对新冠肺炎的反应存在差异。下图描绘了目前谷歌数据集中包括的所有国家在居住空间花费时间的变化。

我们可以看到,尽管几乎所有国家都增加了在家的时间,但人们呆在家里的程度各不相同。巴拿马、玻利维亚、秘鲁和博茨瓦纳等国家已经做出了重大改变,居家活动增加了 34%以上。要查看其他类别的统计数据,如购物、工作出勤和参观公园,请滚动国家/地区。

在美国的影响

根据避免社交聚会和人与人之间近距离接触的建议,仅在美国,42 个州至少有 3 . 16 亿人受到地方政府的指示,尽可能待在家里。这相当于大约 95%的美国人口。谷歌的报告揭示了这些法令如何影响了美国各地的行为。

随着全国各地的餐馆、酒吧、商店和其他工作场所关闭,我们看到工作场所的出勤率平均下降了 40%,零售和娱乐活动平均下降了 49%。然而,人们仍然经常出于各种原因离开他们的家,包括因为他们是必要的工人,他们需要食品杂货和其他必需品,或者他们正在参观一个公园。在全国范围内,我们只看到居住时间平均增长了 13%,低于全球 16.8%的平均水平。下图显示了美国各地住宅活动的变化情况。在新泽西州和加利福尼亚州等州,我们看到住宅活动增加了 16%,而尚未实施居家条例的州,如阿肯色州和爱荷华州,住宅活动仅增加了 8%。

虽然上面的地图只显示了居住活动的变化,但我们看到居住活动和涉及公共互动的类别之间存在强烈的负相关。下面的热图显示,在人们居住时间越长的州,他们花在购物、工作和公共交通上的时间越少,这意味着他们接触病毒的频率越低。

Molly Liebeskind 绘制——来源谷歌移动报告

让你的社区变得不同

我们正在全球和全国范围内大力限制公众互动,但上面的图片显示我们仍有很大的改进空间。在谷歌移动报告的帮助下,你现在可以看到你的社区是如何回应新冠肺炎的。滚动浏览您所在的县,查看您所在社区行为的详细信息,以及您可以在哪些方面做得更好,以帮助阻止新冠肺炎的传播。

Choropleth 着色源自娱乐和零售活动。滚动一个县,查看更多详细信息。注意:灰色的县没有足够的信息供谷歌匿名报告。由于缺乏信息,一些县缺少信息,这在叠加图中以空%表示。

帮助阻止疾病传播是我们所有人的责任。以下是一些方法,你可以采取行动,帮助阻止新冠肺炎在你的社区传播。

  1. 减少购物次数,将购物旅行整合成一次大型采购
  2. 接入网上杂货配送系统或路边取货
  3. 转向邮购药物
  4. 通过更新您的脸书个人资料图片来激励他人
  5. 当你确实需要离开房子时,遵循疾病预防控制中心的指导方针来帮助保护自己和他人

本文的数据由 Google 以 PDF 文档的形式发布,这些文档由 active commendation 抓取并聚合成 csv 文件。完整的数据集可以在这里找到。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

参考

https://www.cdc.gov/coronavirus/2019-nCoV/index.html

https://www . nytimes . com/interactive/2020/us/coronavirus-stay-at-home-order . html

你的机器学习模型还能准确预测吗?

原文:https://towardsdatascience.com/is-your-machine-learning-model-still-predicting-accurately-177f2d353153?source=collection_archive---------42-----------------------

使用直接比率来衡量“模型漂移”——以比特币价格为例

塞尔吉奥·马丁内斯在 Unsplash 上的照片

当我们建立一个机器学习模型时,我们以各种方式验证和测试它的准确性/性能。虽然在测试集中准确率相当高,但是预测最终会随着时间漂移。这通常是由于将来的数据“漂移”到与训练数据集不同的状态。但是我们如何有效地检测这种漂移呢?这篇博文展示了使用直接比率估计来检测比特币每日价格数据的变化点。

这篇文章的代码可以在我的 GitHub repo 上找到。

目录

1。变化点检测概念

2。直接比率(KL 散度和相对无约束最小二乘重要性拟合)估计

3。比特币价格数据示例

3.1。比特币及其数据简介

3.2。应用 KL 散度估计来检测状态变化

3.3。使用 Bolinger 带的状态变化阈值

4。结论和后续步骤

5。参考文献

  1. 改变点检测概念

正如我上面提到的,变化点检测(CPD)基本上是试图发现时间序列序列的不相似性。

刘等(2013)将 CPD 问题定义为测量两个连续子序列 y(t)y(t+n)之间的差异。这些子序列有一定时间段的窗口 k 来评估。下图展示了 PCD 的概念。

来自刘等人(2013)的 PCD 概念图像

例如,假设上图中的“a”是 2020–04–01,那么“b”是 2020–04–02,“c”是 2020–04–03,以此类推。同样设窗口‘k’为图中的 3,则 Y(t)包含 a、b 和 c,Y(t+1)包含 b、c 和 d,包含从 2020–04–02 到 2020–04–05。设 n = 2,则 y(t) 是由 y(t)和 Y(t+1)组成的子序列。我们想知道由 from Y(t+n)=[2020–04–06,2020–04–08]和 Y(t+n+1)=[2020–04–05,2020–04–07]组成的 y(t)y(t+n) 的不同之处。

这也可以通过使用统计假设检验来正式化(Harchaoui 等人,2009)。

H _ 0:y(t)= y(t+1)= y(t+2)=…= y(t+n-1)= y(t+n)

H_1:存在 1 个< k 个< n 使得

y(t)= y(t+1)=……= y(t+k)≠y(t+k+1)=……= y(t+n-1)= y(t+n)

以上是对 CDP 概念的简单介绍。下一节将介绍我们如何计算直接比率估计值。

2。直接比率(KL 散度和相对无约束最小平方重要性拟合)估计

这里我们将讨论这两种直接比率估计方法。首先,给定概率分布 p(x)和 p’(x)的著名的 KL 散度方程可以表示如下。

KL 散度是非负的和非归一化的度量,例如KL[p(x)| | p '(x)]in[0,inf+) 。较高的值表明这些概率分布更远。

在我们讨论相对无约束最小二乘重要性拟合之前,让我们先来看看无约束最小二乘重要性拟合(uLSIF)。这使用皮尔逊(PE)散度如下。

然而,根据 p’(x)的条件,PE 散度值可以是无界的。为了克服这个性质,RuLSIF 将凸组合引入到第二个给定的概率分布中,可以表示如下。

,其中0≤𝛂<1**

当取凸组合时,RuLSIF 的计算值总是有界的。

当我们计算上述值时,窗口的长度也是这种方法的关键点之一。当您将窗口设置得较小时,它对变化更敏感。它可以快速检测甚至很小的变化,但是也可以捕获假阳性情况,例如变量的暂时漂移。另一方面,当你设置一个更大的窗口时,它的估计会更稳定,得到更少的假阳性情况。然而,实际检测状态变化需要一段时间。因此,找到合适的窗口来使用这种方法至关重要。如果即使是很小的状态变化对机器学习模型预测也是至关重要的(例如,基于最小值的股票价格预测),那么使用较小的窗口更合适。如果你的机器学习模型没有受到影响或者可以容忍很小的状态变化,那么最好应用更大的窗口。

由于 KL 散度和 RuLSIF 值都没有归一化,也没有正式的阈值,因此有必要决定如何使用这些值来检测变化点。例如,我们可以应用 95%的置信区间。,2007),还有一些更像金融技术分析工具的东西——比如说博林格带和移动平均线。使用适当的决策规则来发现状态变化是非常重要的。

下一节将展示如何使用这些直接比率估计方法来检测比特币价格数据的状态变化的示例。

3。比特币价格数据示例

安德烈·弗朗索瓦·麦肯齐在 Unsplash 上的照片

3.1 比特币及数据简介

那么比特币是什么?比特币是目前最受欢迎的去中心化虚拟货币。它的价格仅仅由供求关系决定(来自bitcoin.org)。所以简单来说,当对比特币的需求高时,比特币的价值增加,然后需求低时,价值降低。此外,比特币的数量是有限的,并将以可预测的递减速度新创造出来,这意味着为了保持比特币价格稳定,它需要有轻微的通货膨胀。此时此刻,由于市场容量与其可能达到的规模相比仍然相对较小,比特币的价格波动很大——与股票市场相比,它相对更容易受到需求的影响。

现在我们来看看比特币的数据。数据是从 CoinMarketCap 中检索的。它包括 2013 年 4 月 29 日至 2020 年 3 月 28 日的日期、开盘价、最高价、最低价、收盘价、成交量和市值(所有价格均以美元计)。在这篇文章中,我们将使用接近的价格。

这是数据框的外观

这是比特币每天的收盘价。

我们可以看到比特币的价格波动很大。如上所述,价格由供需决定,当需求增加时,价格就会上涨,例如,在 2013 年底左右,因为塞浦路斯的金融危机,而在 2020 年初,由于冠状病毒造成的不确定性,价格就会下跌。

3.2。应用 KL 散度估计来检测状态变化

这里我们尝试使用直接比率估计方法来机器学习模型漂移。为了使 CPD 问题适合这种设置,我们需要修改上面的公式。我们将在训练集中使用固定窗口,而不是使用移动窗口来获得原始概率分布。以便我们可以计算训练集和看不见数据有多相似。

这里假设我们建立了一个机器学习模型,通过使用其 2013 年 4 月 29 日至 2018 年底的数据,可以预测第二天的比特币收盘价。因此,我们将比较火车设置和看不见的未来价格的一些子序列。在这里,我们将尝试查看月水平的模型漂移,因此将窗口设置为 30。

让我们计算每个日期的 KL 散度,并绘制这些值。

*from scipy.stats import entropy
from datetime import date, timedelta start_date = date(2019,2,1)
end_date = date(2020,3,28)
delta = timedelta(days=1)kl = []
date = []while start_date <= end_date: kld = entropy(np.array(df[df['date'] < 
                  '2019-01-01'].close.tail(30)), 
                   np.array(df[df['date'] <= 
                   start_date].close.tail(30))) kl += [kld]
    date += [start_date]
    start_date+=delta kl = pd.DataFrame(list(zip(date,kl)),columns=['date','kl'])*

正如我们可以观察到的那样,2019 年几乎每个月都有相当多的峰值。然而,峰值在一段时间后下降,所以这些可能只是由季节性引起的。然而,在 2020 年 3 月有一个巨大的峰值。这显然是由于冠状病毒的冲击。

现在我们可以比较 KL 散度图和实际的比特币价格分布,看看它们是如何相互关联的。

**

在比特币价格图中,假设的“训练集”中的子序列显示为红色,其余为未知价格。因此,这些直接比率估计是用 30 天窗口的红色子序列对蓝色子序列计算的。

我们注意到,当价格在短时间内大幅上涨时,估计价值也会飙升。有趣的是,尽管比特币价格自 2019 年初以来一直呈上升趋势,直到 2019 年 7 月左右达到最高值,然后呈下降趋势,但估计的 KL 散度值在 2020 年前显示出“恒定波动”。这可能是因为训练集的分布已经考虑了比特币价格的波动性和理论上的常数通货膨胀帐户,因此估计的 KL 散度值并没有真正响应价格的逐渐增加,而是突然的价格变化。

3.3。带 Bolinger 带的状态变化阈值

最后,我们将探讨状态变化检测的决策阈值。在这里,我们将尝试看看如何博林格带可以用于这一目的。Bolinger 波段常用于金融技术分析。它应用了简单的移动平均线和移动标准差。下面是计算 Bolinger 波段的代码片段。

*# Bolinger bandskl['ma21'] = kl.kl.rolling(21).mean()
kl['mstd2'] = kl.kl.rolling(2).std()
kl['bolinger_high'] = kl.ma21+(kl.mstd2*2)
kl['bolinger_low'] = kl.ma21-(kl.mstd2*2)*

这里,我们使用 21 天简单移动平均线和 2 天移动标准偏差,通过使用每个定义的 2 个标准偏差(95%区间)来计算“波段”。此外,我们只对作为问题特征的 Bolinger 带的上界感兴趣(我们只想知道分布何时变得远离),我们只画出上界。

正如我们可以看到的,有几个时间段,估计的 KL 散度超过了 Bolinger 带的上限,这意味着状态发生了变化。通过这种方法,我们可以系统地辨别变化点,并且通过改变移动平均的窗口,我们可以修改检测的灵敏度(窗口越小,对变化越不敏感)。

4。结论和后续步骤

这篇博文经历了以下几点:

  • CPD 旨在检测时间序列概率分布中两个子序列的不相似性。
  • 因为 KL 散度和 RuLSIF 都不是标准化的比率,并且没有明确的阈值来确定“状态变化”。因此,确定适当的规则来检测变化是很重要的。
  • 窗口的长度也是这种方法的关键点之一。当您将窗口设置得较小时,它对变化更敏感。它可以快速检测甚至很小的变化,但是也可以捕获假阳性情况,例如变量的暂时漂移。另一方面,当你设置一个更大的窗口时,它的估计会更稳定,得到更少的假阳性情况。然而,实际检测状态变化需要一段时间。
  • 仅仅通过检查目标变量,我们并不知道是什么导致了状态变化,通常我们感兴趣的是是什么导致了变化。其中一个解决方案是监控模型中的所有特征,这样我们就可以看到模型的哪个部分正在发生变化。

希望你对这篇文章感兴趣。如果你想和我联系,这是我的 LinkedIn 页面

5。参考文献

哈尔查乌伊,z .,穆林斯,e .,,巴赫,F. R. (2009)。内核变点分析。在神经信息处理系统的进展(第 609–616 页)。

刘,s .,山田,m .,柯里尔,n .,杉山,M. (2013)。用相对密度比估计检测时间序列数据中的变点。神经网络43 ,72–83。

Sebastiã,r .,& Gama,J. (2007 年 12 月)。从数据流中学习直方图的变化检测。在葡萄牙人工智能会议(第 112-123 页)。斯普林格,柏林,海德堡。

估计量及其效率

原文:https://towardsdatascience.com/is-your-model-efficient-845abce5c2f3?source=collection_archive---------25-----------------------

无偏估计量的方差/均方误差的 Cramer-Rao 下界介绍

澳门图片社Unsplash 上拍摄的照片

简介——什么是评估者?

假设你在抛硬币,你想凭经验估计正面的概率。为此,你决定抛硬币 n 次,根据你得到的是正面还是反面,记录 1 或 0。

估计概率最直接的方法是计算你在 n 次投掷中获得的正面的比例,我们称之为p̂.n变得越大,你就越确定 准确地估计了 p ,即获得正面的真实概率。在统计学中,我们说 p估计量。直观地说,估计器只是在给定一些数据的情况下,估计统计模型中未知参数的一种方式。

维吉尔·卡亚萨在 Unsplash 上拍摄的照片

估计量是统计学的基础。在上面的例子中,我们的估计量是无偏的,这意味着它的期望值就是我们试图估计的参数。除了让我们的估计量无偏之外,我们的估计量尽可能接近期望值也非常重要,即方差最小化。

hat 的方差,θ的估计量

当使用无偏估计量时,方差与均方误差(MSE) 相同,这对于之前有机器学习经验的人来说应该很熟悉。

马克 A 在 Unsplash 上的照片

这里有一个非常直观的例子,通常用来解释估计量。假设你在射箭。目标是击中靶心(参数)。粘在棋盘上的单个飞镖是你的评估者(你,扔飞镖的人)做出的评估。不偏不倚只是意味着你的飞镖的预期位置是靶心,实际上并没有说你平均会有多接近靶心。这就是我们关注 MSE 的原因。在这种情况下,高 MSE 只是意味着从单个飞镖到靶心的平均距离相当高。成为一个好的玩家(评估者)意味着你的飞镖聚集在中心周围——也就是说,你的 MSE 非常小。

既然我们理解了为什么我们需要我们的估计量具有最小的 MSE,问题就变成了:给定一个估计量,我们如何知道它是否是最有效的估计量,即具有最小 MSE 的估计量?这就是 Cramer-Rao 界派上用场的地方。

克莱姆-拉奥界

Cramer-Rao 界产生于 20 世纪 40 年代,它给出了无偏估计量的方差/均方误差的一个下界。这意味着给定参数的最佳可能估计量将具有由界限规定的 MSE。

假设我们想从 n 个样本中估计 θ 。克莱姆-拉奥定理陈述如下(在 iid 假设和其他正则性条件下):

克莱姆-拉奥界

如果我们在界上有等式,那么我们知道估计量是有效的!这并不意味着总是存在这样的估计量;然而,它确实声明了最佳可能估计量的 MSE 将大于或等于由界限给出的 MSE。

费希尔信息

现在,你可能想知道等式中的 I(θ) 到底代表什么。它被称为费希尔信息,直观地说,它是我们对样本来自哪个数据分布有多少信息的一种度量。

iid 假设下,大小为 n 的样本中的费希尔信息是单个样本中的信息乘以 n 。我们期望,随着我们获得更多的数据和 n 变得更大,我们应该有更多的关于数据是从什么分布抽样的“信息”,因此,我们应该能够更好地估计 θ

现在让我们努力理解费雪信息的公式。我们首先需要定义什么叫做得分函数。如果我们考虑一个随机变量X∞f(X;θ) ,则得分由下式给出

分数函数

然后,Fisher 信息被定义为得分平方的期望值。

费希尔信息

或者,通过一些简单的操作,我们可以获得 Fisher 信息的替代表达式:

Fisher 信息的替代表达

根据这些表达式,计算费希尔信息相对简单。

结论

我希望你现在对估计量的 Cramer-Rao 界有了更好的理解。此外,我希望你现在准备好计算和评估你自己的估算器的效率。

参考文献

[1]马丁,《统计理论讲义》(2015),http://home pages . math . UIC . edu/~ rg Martin/Teaching/stat 411/Notes/411 Notes . pdf

你的模型是否过拟合?或者不合身?使用神经网络的示例

原文:https://towardsdatascience.com/is-your-model-overfitting-or-maybe-underfitting-an-example-using-a-neural-network-in-python-4faf155398d2?source=collection_archive---------13-----------------------

过拟合,欠拟合,泛化能力,交叉验证。一切都简单解释了。我还提供了一个使用神经网络的 python 示例。

作者创作的人物。

1.介绍

大多数时候,机器学习(ML)模型的 性能的原因要么是过拟合要么是欠拟合。一个好的模型应该能够推广并克服过拟合和欠拟合问题。但是什么是过度拟合呢?但是什么是不适合呢?对于一个模型来说,什么时候能够概括学习到的功能/规则?

继续读下去,你就能回答所有这些问题。

2.ML 中的泛化是什么

ML 模型的泛化是指如何很好地ML 模型学习的规则/模式/功能,应用于模型学习时没有看到的具体例子。这通常被称为

一个好的 ML 模型的目标是从训练数据很好地推广到来自问题领域的任何数据。这允许对模型以前从未见过的一些数据进行预测(即,对未来进行预测)。

如果你想在交互式路线图和活跃的学习社区的支持下自学数据科学,看看这个资源:https://aigents.co/learn

3.什么是机器学习中的过拟合

过度拟合意味着我们的 ML 模型对训练数据建模(已经学习)得太好了。

从形式上来说,过拟合指的是模型学习数据以及作为训练数据的一部分的噪声的情况,其程度是负面地 影响模型在新的未知数据上的性能

在其他世界中,训练集中的噪声(即随机波动)被模型学习为规则/模式。然而,这些有噪声的学习表示不适用于新的看不见的数据,因此,模型的性能(即准确性、MSE、MAE)受到负面影响。

过拟合的一个教科书案例是当 模型的错误 上的 训练 设定(即训练期间)是 但接着,模型的 错误

4.机器学习中的不足是什么

欠拟合意味着我们的 ML 模型既不能对训练数据建模,也不能推广到新的看不见的数据。

数据拟合不足的模型在训练数据上的性能会很差。例如,在有人使用线性模型来捕捉数据中的非线性趋势的情况下,该模型会对数据进行欠拟合。

欠拟合的一个教科书案例是当模型的误差对训练 测试 集合(即在训练和测试期间)非常高时。****

5.最佳位置和好的模型

很明显,过拟合和欠拟合之间存在权衡。

理想情况下,一个好的模型是在欠拟合和过拟合之间找到最佳平衡点的模型。

哪个是最佳点?

最佳点被定义为模型在训练集和测试集(不可见)上的误差都保持较低的点。

换句话说,最佳点是测试集上的误差开始增加的点,同时,模型在训练集上的误差是可接受的(低)。

6.如何(潜在地)限制过度拟合

ML 学习领域最常见的问题是过拟合

能够(潜在地)限制过度拟合的行动:

  1. 我们可以使用交叉验证** (CV)方案。**
  2. ****降低模型的复杂度(使模型不那么复杂)。

说到方案 1 即交叉验证的使用,最著名的 CV 方案就是 KFolds 交叉验证。使用 KFolds 方案,我们在训练数据的不同子集上训练和测试您的模型 k 次,并使用测试(看不见的)数据估计性能指标。其他选项包括留一个留一个交叉验证( LOOCV )、留一个 P 出来交叉验证( LpOCV )等。**

KFold 的视觉表现。作者创作的人物。

说到方案 2 即 降低模型的复杂度 有助于减少过拟合。例如,如果有人使用 RBF 核的 SVM 模型,那么降低复杂度就意味着使用线性核。在另一种情况下,如果有人用多项式来拟合一些数据,那么降低复杂性就意味着用线性模型来代替(线性回归)。

7.如何(潜在地)限制欠拟合

在这种情况下,有两种黄金标准方法:

  1. 尝试另一种模式
  2. 增加当前模型的复杂性

解决方案 1 很简单。关于解决方案 2,一个例子如下:如果有人对一些数据进行线性回归拟合,那么增加的复杂度将意味着拟合多项式模型。

8.结论

过拟合 或欠拟合是大多数机器学习(ML)模型性能 的最常见原因。此外,过度拟合比欠拟合更常见。

  • ****过度拟合是指模型在训练集(即训练期间)上的误差非常低,但模型在测试集(即未知样本)上的误差很大!
  • 欠拟合**是指训练测试**集合(即在训练和测试期间)的模型误差非常高。****

为了克服这些问题,通常使用交叉验证来估计模型在未知数据上的表现。

额外收获:Python 中的工作示例

数据集

我们将使用 Iris 数据集,正如我们在我以前的所有帖子中所做的那样。数据集包含鸢尾属三个品种四个** 特征(萼片和花瓣的长度和宽度) 50 个样本(鸢尾属 setosa 、鸢尾属 virginica 和鸢尾属 versicolor )。******

模型

我们将使用一个多层感知器【MLP】。MLP 是一类前馈 人工神经网络 (ANN)。术语 MLP 使用含糊,有时不严格地指任何前馈神经网络,有时严格地指多层感知器组成的网络。********

********from sklearn.neural_network import MLPRegressor 
from sklearn.metrics import mean_absolute_error
import numpy as np
from sklearn.model_selection import validation_curve
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
from sklearn.model_selection import KFold
np.random.seed(0)
plt.style.use(‘ggplot’)********

让我们加载虹膜 数据:****

******iris = load_iris()
X, y = iris.data, iris.target******

我们将使用 KFolds 交叉 - 验证与 20 折( K=20) 来评估我们模型的泛化 能力在每个文件夹中,我们将分别使用训练和测试集来估计训练和测试误差。********

******kf = KFold(n_splits=20)
list_training_error = []
list_testing_error = []for train_index, test_index in kf.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    model = MLPRegressor()
    model.fit(X_train, y_train)
    y_train_data_pred = model.predict(X_train)
    y_test_data_pred = model.predict(X_test) fold_training_error = mean_absolute_error(y_train, y_train_data_pred) 
    fold_testing_error = mean_absolute_error(y_test, y_test_data_pred)
    list_training_error.append(fold_training_error)
    list_testing_error.append(fold_testing_error)******

绘制培训阶段的 MAE 和测试阶段的 MAE:

******plt.subplot(1,2,1)
plt.plot(range(1, kf.get_n_splits() + 1), np.array(list_training_error).ravel(), ‘o-’)
plt.xlabel(‘number of fold’)
plt.ylabel(‘training error’)
plt.title(‘Training error across folds’)
plt.tight_layout()plt.subplot(1,2,2)
plt.plot(range(1, kf.get_n_splits() + 1), np.array(list_testing_error).ravel(), ‘o-’)
plt.xlabel(‘number of fold’)
plt.ylabel(‘testing error’)
plt.title(‘Testing error across folds’)
plt.tight_layout()plt.show()******

现在让我们解释结果,并尝试找出过度拟合和欠拟合点。

提醒:

  • 过度拟合是指模型在训练集(即训练期间)上的误差非常低,但模型在测试集(即看不见的样本)上的误差很大!
  • 欠拟合是指模型在训练集和测试集(即在训练和测试期间)的误差都非常高。

在折叠编号 10 处可以识别出一个欠拟合点。在第 10 次折叠期间,训练集和测试集上的误差同时很高!因此,该模型对传入 fold 10 中用于训练的那部分训练数据进行了欠填充。****

在折叠 20 处可以看到一个过度拟合点(不是真正的极端)。训练 MAE 约为 0.16,对于相同的倍数,测试集上的 MAE 高于 0.20。****

免责声明:这些都不是过度拟合/欠拟合的极端情况,但我只是想表明我的观点,并将其与我在本文中讨论的理论联系起来。

那都是乡亲们!希望你喜欢这篇文章!

敬请关注并支持这一努力

如果你喜欢这篇文章并且觉得它有用,那么关注我就可以看到我所有的新帖子。****

这是我的简介。点击关注!****

****** [## Serafeim Loukas -走向数据科学

阅读 Serafeim Loukas 在《走向数据科学》中的文章。电气和计算机工程文凭(NTUA)。主人…

towardsdatascience.com](https://towardsdatascience.com/@seralouk)

有问题吗?把它们作为评论贴出来,我会尽快回复。******

最新帖子

****** [## 时间序列预测:用脸书的先知模型预测股票价格

使用可从《先知脸书》公开获得的预测模型预测股票价格

towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-facebooks-prophet-model-9ee1657132b5) [## 用新冠肺炎假设的例子解释 ROC 曲线:二分类和多分类…

在这篇文章中,我清楚地解释了什么是 ROC 曲线以及如何阅读它。我用一个新冠肺炎的例子来说明我的观点,我…

towardsdatascience.com](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [## 支持向量机(SVM)解释清楚:分类问题的 python 教程…

在这篇文章中,我解释了支持向量机的核心,为什么以及如何使用它们。此外,我还展示了如何绘制支持…

towardsdatascience.com](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [## PCA 清楚地解释了——如何、何时、为什么使用它以及特性的重要性:Python 指南

在这篇文章中,我解释了什么是 PCA,何时以及为什么使用它,以及如何使用 scikit-learn 在 Python 中实现它。还有…

towardsdatascience.com](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [## 关于 Python 中的最小-最大规范化,您需要知道的一切

在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它

towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [## Scikit-Learn 的标准定标器如何工作

在这篇文章中,我将解释为什么以及如何使用 scikit-learn 应用标准化

towardsdatascience.com](/how-and-why-to-standardize-your-data-996926c2c832)

和我联系

你的创业公司在负责任地使用 AI 吗?

原文:https://towardsdatascience.com/is-your-startup-using-ai-responsibly-4663ec43f880?source=collection_archive---------39-----------------------

为什么模型的公平性和的可解释性不能满足它

更新:你现在可以用 日文 阅读这篇文章!(感谢 Koki Yoshimoto)。

自从科技公司开始利用这项技术以来,他们已经收到了无数关于不道德使用人工智能的指控。

一个例子来自 Alphabet 的谷歌,它创造了一种仇恨言论检测算法,给非裔美国人的言论分配了比白人更高的“毒性分数”。

华盛顿大学的研究人员分析了数千条被算法视为“冒犯”或“仇恨”的推文的数据库,发现黑人对齐的英语更有可能被贴上仇恨言论的标签。

照片由米卡·鲍梅斯特Unsplash 上拍摄

这是人工智能算法出现偏见的无数例子之一。可以理解的是,这些问题引起了很多关注。关于伦理和偏见的对话是最近人工智能领域的热门话题之一。

各行各业的组织和行动者都在从事研究通过公平、问责、透明和道德(FATE)来消除偏见。然而,仅仅专注于模型架构和工程的研究必然会产生有限的结果。那么,如何解决这个问题呢?

消除对抗人工智能偏见的误解

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

修复模型是不够的,因为这不是根本原因所在。为了找出哪些措施可以产生更好的效果,我们必须首先了解真正的原因。然后,我们可以通过研究我们在现实世界中如何应对这种偏见来寻找潜在的解决方案。

人工智能模型通过研究模式和从历史数据中识别洞察力来学习。但人类历史(以及我们的现在)远非完美。因此,毫不奇怪,这些模型最终模仿并放大了用于训练它们的数据中的偏差。

这是我们大家都相当清楚的。但是,我们如何处理我们世界中这种固有的偏见呢?

在现实世界中,我们必须注入偏见以对抗偏见。

当我们觉得一个社区或一部分人口可能处于不利地位时,我们会避免仅仅根据过去的情况得出结论。有时,我们会更进一步,进行包容,为这些细分市场提供机会。这是扭转趋势的一小步。

这正是我们在教授模型时必须采取的步骤。那么,我们如何注入人类偏见来对抗模型固有的“习得性”偏见呢?以下是实现这一目标的一些步骤。

1。为您的数据科学团队添加不同的角色

照片由丹尼斯·莱昂Unsplash 上拍摄

在构建负责任的人工智能模型时,你需要你的团队超越技术。虽然对数据科学专业人员进行数据隐私教育很重要,但这种做法的好处有限。通过引入来自社会科学和人文学科的人,你可以获得技能和专业知识,这将帮助你减轻人工智能模型中的潜在偏见。

来自这些背景的人将会更好地理解用户和伦理考虑,并从人的角度提供见解。人类学家和社会学家可以发现模型中可能被创建模型的数据科学家忽略的刻板印象,并可以纠正数据中潜在的偏见。

数据科学团队中的行为心理学家可以帮助弥合用户和技术之间的差距,并确保模型结果的公平性。

在构建负责任的人工智能模型时,你必须超越技术。

除了重视不同的技能组合,数据科学团队引入更多不同性别、种族或国籍的成员也至关重要。多元化的团队提供新的视角,质疑可能过时的古老规范,并防止团队陷入群体思维的陷阱。

例如,开发 iOS YouTube 应用程序的谷歌团队在添加移动上传时没有考虑左撇子用户,因为团队中的所有人都是右撇子。

这意味着在左撇子视角下录制的视频会上下颠倒。只需要几个左撇子就能让这款应用对占全球人口 10%的人更加友好。

2。将人类融入循环

Unsplash科普高清照片

无论你的模型有多复杂,都需要人工干预。人类可以是故障安全机制的一部分,或者更好的是,数据科学团队可以在持续的基础上结合人类的判断并逐步丰富模型。

随着人工智能被用于涉及人类健康或生命的关键领域,它应该被视为零容忍的任务关键型——不仅仅是宕机或错误,还包括偏差。实现这一点的唯一方法是让人类负责,以确保避免人工智能偏见。

计划模型的零容忍,不仅仅是停机时间或错误,还有偏差。

佛罗里达州朱庇特一家医院的医生举例说明了永远不要盲目信任人工智能算法的必要性:他们拒绝了 IBM Watson 关于癌症治疗的建议,这些建议可能会产生致命的后果。数据科学团队不断面临构建更好的模型和万无一失的系统的挑战。

然而,这并不意味着人类可以被排除在系统之外。事情确实会出错,即使是在少数情况下。我们必须将人设计到决策过程中,以便在每一个这样的情况下进行控制。

3。让您的数据科学团队负起责任

谢恩·艾弗里在 Unsplash 上拍摄的照片

大多数业务数据科学团队的主要目标都围绕着创造更多收入、设计最精确的模型和自动化流程以实现最高效率。然而,这些目标忽略了某人(或多人)必须确保“正确的”事情正在被做。

数据科学团队必须对结果负责,必须确保他们解决的业务问题不会以牺牲道德准则为代价。扪心自问:您的数据科学团队是否仅仅受到收入和时间表的激励?或者他们是否认为负责任的产品使用和公平的结果是项目成功的标准?

如果是前者,你需要重新思考驱动你的团队的目标。

为了确保负责任地使用人工智能,你必须提升你的数据科学团队的道德品质。

为了确保负责任地使用人工智能,你必须提升你的数据科学团队的道德品质。这需要积极的保护和持续的教育。此外,你还必须为高级职位做好准备,比如首席道德官或 T2 道德委员会,他们将成为你产品的道德监督人。

然而,这并没有消除将责任推给其他相关人员的需要:你需要在所有层面上承担责任。例如,宝拉·戈德曼成为 Salesforce 的首位首席道德和人道使用官。

通过持续讨论人工智能解决方案的质量及其对整个社会的影响,你可以从高层灌输一种责任感,并确保对团队其他成员产生涓滴效应。也有可用的最佳实践和指南,比如谷歌的这些。

虽然大型科技公司普遍存在人工智能道德失误,但我们也看到了一些正确的举措。微软和 IBM 都公开承诺解决他们自己和第三方程序中的偏见。

4。让你的用户知道人工智能并不完美

摇滚猴子Unsplash 上的照片

公司内部和更广泛的消费者群体中的许多个人过于信任人工智能,而不了解它的能力和缺陷。虽然商业领袖经常忽视这一点,但我们不能指望所有消费者都理解今天人工智能的前景。

人们认为人工智能可以创造奇迹,但如果没有数据、人才或正确的流程,它将注定失败。教育团队成员和消费者人工智能仍处于初始阶段——并且应该被如此对待——对于避免导致灾难性结果和更大失望的盲目信任至关重要。

用户必须明白,人工智能解决方案是用来提供信息,而不是发号施令。

对人工智能算法能力的期望必须保持现实。就像你可能不愿意让你的汽车在拥挤的街道上以自动驾驶模式行驶一样,我们今天必须了解它的局限性。人们需要理解,人工智能解决方案应该以同样的方式来看待——它们是为了提供信息,而不是发号施令。

5。建立一种促进好奇心、质疑信念的意愿和改变的灵活性的文化

约瑟夫·罗萨莱斯在 Unsplash 上的照片

最终,为了实现负责任地使用人工智能,你需要在你组织的核心中嵌入某些属性。文化是经年累月形成的,极难改变。渴望成为数据驱动的组织必须在其文化核心中拥有某些属性。当你的创业处于早期阶段,而不是几年后,就播下这些种子。

那么,对于负责任和合乎道德地使用人工智能来说,这些至关重要的属性是什么呢?

好奇心。问自己:所有团队成员都愿意尝试必要的步骤来找到他们需要的答案吗?或者,他们是否乐于执行设计好的步骤和流程?一个好奇的团队将找到让人工智能工作以满足结果的方法。

接下来是质疑信念的意愿:你的公司是否有一个健康的环境让团队质疑既定的实践?上级会听取并鼓励具有挑战性的反馈吗?团队必须有一种开放的文化,当他们看到 AI 的实现方式不符合组织的理想时,他们可以大胆地说出来。

最后,公司文化必须促进改变的灵活性。与技术和数据科学打交道自然会涉及许多变化——无论是在创建解决方案还是采用解决方案方面。团队是否愿意根据他们通过好奇和质疑设定的流程所发现的东西来进行调整?

照片由肖恩·斯特拉顿Unsplash 上拍摄

拥有正确的公司文化为合乎道德的人工智能使用奠定了基础。众所周知,脸书提倡“快速行动,打破常规”的文化考虑到这个科技巨头面临的无数关于用户隐私和滥用数据的丑闻,这个咒语显然没有导致合理的人工智能使用。

负责任地使用人工智能不会仅仅通过对模型进行一些调整就发生。

负责任地使用 AI 不是一蹴而就的事情,也不是简单地对模型进行一次调整就能确保并期待奇迹般的结果的事情。

正如我们在当前席卷科技行业的“道德洗涤的指责浪潮中所看到的,简单地声明你将打击人工智能偏见,而没有什么行动来支持这一声明是不会成功的。

避免人工智能偏差只能通过在不同阶段以多种方式增加人类输入来实现。通过使数据科学团队多样化,将人融入流程,让团队负起责任,对人工智能的能力设定现实的预期,以及最后——也许是最重要的——建立正确的公司文化,你可以为人工智能在你的组织中的道德使用铺平道路。

这篇文章最初是在 TechCrunch 的会员版 ExtraCrunch 上发表的。增加了插图。封面图片由*组成***

你的虚拟聊天机器人是否免受攻击?

原文:https://towardsdatascience.com/is-your-va-chatbot-protected-from-attacks-1e0fdc3e7d8?source=collection_archive---------86-----------------------

随着人工智能的全面接管,近年来人类已经非常习惯于与智能语音助理或聊天机器人交谈。

Freepik 设计

但本质上,VA 到底是什么?

简单来说,聊天机器人或智能虚拟设备是一种模拟人类对话的软件程序。这种互动可以通过语音或书面信息进行。这些自动化 VA 程序利用自然语言处理或 NLP 与客户进行交互,就像真人一样。

聊天机器人的发展前景

越来越多的企业使用增值服务,特别是聊天机器人,来提升他们的客户体验。

聊天机器人营销统计

无论是医疗保健、保险、银行还是客户服务,每个行业都在使用聊天机器人来提升用户体验并提供主动帮助。事实上,预计到 2020 年底,80%的公司将使用虚拟化。

聊天机器人——攻击的棋子

降低客户支持成本、持续连接和即时确认的结合使聊天机器人比其他机器人更胜一筹。然而,在将虚拟设备整合到您的业务中之前,了解它的安全含义是很重要的。虽然这并不广为人知,但有必要建立一个可靠的、详细的、多层的安全解决方案来确保聊天机器人的安全。

借助达美航空 2017 年数据泄露案例,可以轻松证明保护增值服务的必要性。达美航空公司起诉其人工智能供应商,因为其安全政策薄弱。虚拟助理提供公司未能安装多因素认证,这导致黑客能够修改聊天机器人的源代码,并暴露数十万客户的信用卡信息。黑客能够看到达美航空的网站活动,并将顾客转移到一个欺诈网站,在那里他们可以保护用户数据。在当今数据驱动的世界,未能保护您客户的数据可能是一个巨大的疏忽。这就是为什么聊天机器人系统必须有一层监控和保护,以防止机密数据落入坏人之手。

这个案例揭示了当聊天机器人系统被入侵时会发生什么,这是非常必要的,并且对不同形式的攻击进行了更多的研究。在很大程度上,聊天机器人攻击可以分为两种形式——第一种是修改系统行为的内部或操纵攻击,第二种是谨慎检测隐藏信息和攻击系统弱点的外部或提取攻击。

聊天机器人安全-当务之急

越来越多的企业倾向于使用增值服务,这也助长了对这些自动化系统的网络攻击。让我们从更大的角度来看,使用聊天机器人的整个目的是提供一个简化的个性化的客户服务,全天候可用。但是使用无保护的聊天机器人会增加数据窃取和侵犯隐私的可能性。更重要的是,它甚至可能导致消费者集体诉讼,这可能会使公司损失数百万美元,并牺牲其客户和公司数据的完整性。

早期的聊天机器人主要用于提供通用信息,如公开的地址或分支机构信息,但世界已经迅速转向自动化和节约成本。此外,人类在提供准确信息时容易出错。如今,聊天机器人被用来支持或取代许多重要的人类任务。从安全角度来看,这意味着聊天机器人现在可以访问敏感和私人信息。机器学习以极快的速度发展,却没有将安全性视为其关键部分。目前,在世界范围内部署了大量聊天机器人,这些机器人对敏感信息的访问程度如此之高,以至于这些系统的安全性成为一个迫切的要素。

现在,让我们深入到事物的生产方面。市场上挤满了致力于提供更加动态和易于管理的聊天机器人的玩家,但是,明显缺乏提供解决方案来保护聊天机器人免受各种安全风险的供应商。为此,企业忽略了一个具有重大影响的基本方面。

那么,你如何防止你的公司成为下一个反面教材呢?

VAs 像任何其他软件一样容易受到威胁,但在聊天机器人的情况下,这些攻击很难防御,主要是因为机器学习系统的内在构成。聊天机器人被认为是类似人类的物体,但它们不是。他们的智能来自数据集、模型及其超参数,加上他们从周围的环境中学习。机器学习系统的这些核心组件不容易保护,因为它们来自公共存储库,因此这些数据很容易被发现,并且可能在黑客的范围内。需要一个拥有广泛人工智能、机器学习、自然语言处理和数据科学知识的组织来设计一种可以保护这些聊天机器人的产品。

这就是我们的问题所在,我们 Scanta 知道一个简单的网络应用或网络防火墙不足以保护你的虚拟聊天机器人。这就是为什么我们开发了我们的旗舰产品 VA Shield,这是一种聊天机器人安全解决方案,它可以分析系统的请求、响应和对话,以提供增强的监控层。不仅如此,VA Shield 还跟踪分析,以提供关于虚拟助手 Chatbot 使用的更深入的商业见解。

确保聊天机器人或 ML 系统的安全是一个复杂的问题,构建这样的解决方案需要对系统有透彻的了解。机器学习系统不是将安全性作为组件之一来构建的,它们已经深深植根于各种任务关键型系统中。不仅如此,由于 NLP 接口的自由形式,基于 NLP 的接口给安全问题带来了额外的复杂性,并且考虑到 NLP 仍然是一个发展中的领域,还没有人掌握该领域。

我们对机器学习和人工智能根深蒂固的理解,为 VA Shield 的发明奠定了基础。这个聊天机器人安全解决方案为您的虚拟助理聊天机器人系统添加了一个关键的零信任安全框架,使其平稳安全地运行,而不会干扰现有的安全企业。

结束语

本文只是触及了如果您正在部署一个未受保护的虚拟设备会发生什么的表面,其后果是深远的。这就是为什么我们的任务是确保你的虚拟助理聊天机器人得到新的安全级别的加强,以阻止机器学习攻击。

https://scanta.io/了解更多关于我们的信息

零更接近八还是一?

原文:https://towardsdatascience.com/is-zero-closer-to-eight-or-to-one-c6392242b696?source=collection_archive---------62-----------------------

应用 t-SNE 可视化 2D 图中的 MNIST 数字数据集

作者:罗莎丽娅·西里波米莎·利索夫伊 ,克尼梅

零更接近八还是一?这是三分还是五分?几周前,当我们检查一个图像分类应用程序的结果时,我们就在思考这类问题。

是的,事实上,0 更接近于 8 而不是 1,2 更接近于 5 而不是 3——当然,这是从图像识别的角度而不是从严格的数学意义上来说。在我们准备的最后一个数据科学示例中,我们训练了一个机器学习模型来识别手写数字的图像。最后,在检查结果的时候,我们意识到人们的笔迹是多么的潦草,有时很难区分 8 和 0,2 和 5,1 和 7,0 和 3,以及其他有时意想不到的类似数字。

由于时间和其他义务的明显原因,我们不能一个接一个地检查所有的数字图像和它们的错误分类。然而,对数据集中最容易混淆的重叠数字有一个总体的了解是很有趣的。说起来容易做起来难。每个数据行都是一幅图像,由 784 个输入要素描述。试着想象一下!

我们需要将输入维度从 784 大幅减少到 2 或最多 3,以便通过 2D 或 3D 绘图实现数据可视化,同时还能提供信息。如果我们能从一个图表中了解最大的困惑在哪里,哪些数字在书写风格上有最大的延伸,那就太好了。

t 分布随机邻居嵌入(t-SNE)

图一。应用 t-SNE 投影后的可视化示例

t-分布式随机近邻嵌入(t-SNE)是一种相对较新的技术,通常用于在二维或三维空间中以图形方式表示复杂的多维数据集。t-SNE 是一种非线性降维技术,它基于数据点之间的非线性局部关系,将数据集的原始 n 坐标转换为一组新的m = 2–3坐标。具体而言,它将每个高维对象建模为二维或三维点,以这种方式,在新的较低维空间中,相似的对象由附近的点建模,不相似的对象由远处的点建模。

在第一步中,通过数值属性的多元正态分布对数据点进行建模。为高维空间中的对象对创建概率分布。相似的物体被一起拾取的概率高,而不相似的物体被一起拾取的概率低。

在第二步中,这个分布被低维空间中的 t-分布代替,该 t-分布必须尽可能地遵循原始的多元正态分布。第二步的目标是找到具有尽可能相似的 t 分布的低维空间——通过最小化 Kullback-Leibler 散度——然后在新找到的低维空间中投影物体。第二个 t 分布必须模拟在数据集中挑选另一个点作为低维空间中当前点的邻居的概率,就像在高维空间中一样。

困惑度参数将 t 分布的形状控制为“任意点的有效邻点数”较低的困惑值(2)会找到受数据中局部变化支配的聚类形状。较高的困惑值(30)在多次迭代后会产生更稳定的聚类。也就是说,困惑值越大,数据中考虑的全局结构就越多。

这项技术主要用于可视化。事实上,将数据集维度积极缩减到两个或三个坐标,将数据点对的可能性转换为视觉邻域属性,以及由于投影的非线性而能够表现数据组的奇怪形状,这些都使 t-SNE 特别适合大多数数据可视化技术。

请注意,t-SNE 技术仅适用于当前数据集。无法导出模型并将其应用于新数据。事实上,所有可用的数据都必须用来寻找新的低维空间。也就是说,新的数据不能被投影。

MNIST 数字数据集

图二。MNIST 数字数据集中的一些数字图像

位于 LeCun 网站上的 MNIST 手写数字数据库包含 70,000 个手写数字 iii 的 28x28 黑白图像样本。在这个例子中,我们使用了 10,000 个这样的图像的子集。

通常在处理图像时,可以直接从标准格式如 PNG、JPG 和 TIFF 中读取。不幸的是,MNIST 数据集只有非标准的二进制格式。幸运的是,下载数据集并把文件转换成易于阅读的 CSV 格式非常简单。

在将数字图像转换成数字向量后,每个图像由 784 个灰度级的向量表示,即由 784 个输入特征表示。

应用 t-SNE 可视化 2D 图中的 MNIST 数据集

图 3。KNIME 分析平台中的 t-SNE 节点

一方面,我们有一个想要在 2D 散点图上可视化的高维数据集;另一方面,将维度从高的 n 降低到低的 m 的技术(例如 m=2)。然后,我们将 t-SNE 变换应用于 MNIST 数据集,并将结果绘制在 2D 散点图上(图 3)。

这是一个 t-SNE 变换如何帮助在二维图上可视化高维数据集的示例。每个图像的原始尺寸 28×28 = 784 像素仅通过 t-SNE 被减少到二维,并且产生的数据点被绘制在散点图上,其中代表相似图像的数据点被紧密定位。784 个输入特征来自“展开”成单个数组或值序列的 28x28 像素图像。

例如,“6”位于两种不同类型的“0”之间数字“4”和“9”在形状上接近且部分重叠,伸展成类似于“1”的形状“0”和“8”数字的位置也很接近,因为它们的形状通常相似;“3”和“5”也一样因此,图 4 中的散点图是每个数字不同形状的拓扑图。

图 4。t-SNE 变换后散点图上的 MNIST 数据集。

KNIME 工作流程

现在,让我们快速浏览一下在 MNIST 数据集上实施 t-SNE 变换并在 2D 散点图上绘制结果的工作流,该工作流在 KNIME Hub 上以“ t-SNE 对 MNIST 数据集”的形式提供

名为“读取 MNIST 数据”的元节点列出并读取 10,000 个 MNIST 文件,每个文件都包含一个手写数字的图像。然后,通过“预处理图像”元节点中的“图像到数据行”节点,图像被转换成数字(灰度级)的集合。然后将数值向量输入“t-SNE (L. Jonsson)”节点,计算两个 t-SNE 分量。在并行分支中,提取数字类别并用于对不同的数字图像进行颜色编码。最后,使用“散点图(Plotly)”节点在经典的传统散点图上绘制颜色编码的 t-SNE 变换的二维向量。

图 5。工作流"MNIST 数据集上的 t-SNE"实现 MNIST 数字数据的 t-SNE 变换并将结果绘制在散点图上。

结论

t-SNE 是一种非常强大的变换,可以将数据从任何维度空间投影到二维空间,并显示数据集中的数据组有多接近。

在本例中,我们已经将 MNIST 数字数据集从 784 维空间转换到二维空间,但我们仍然可以检查哪些数字最容易与其他数字混淆,如“8”与“0”或“7”与“1”

参考文献

1.Laurens van der Maaten,Geoffrey Hinton,“使用 t-SNE 可视化数据”,《机器学习研究杂志》2008 年第 9 期

2.k .栗田(2018 年 9 月 14 日)。论文剖析:“使用 t-SNE 可视化数据”讲解【博客文章在“机器学习”中讲解】

3.Y. LeCun、L. Bottou、Y. Bengio 和 P. Haffner。"基于梯度的学习应用于文档识别."IEEE 会议录,86(11):2278–2324,1998 年 11 月

2020 年 7 月 8 日首次发表于 Datanamihttps://www . Datanami . com/2020/07/08/is-zero-closer-to-eight-or-to-one/

使用 T-SQL 窗口函数的孤岛冒险

原文:https://towardsdatascience.com/island-adventures-with-t-sql-window-functions-3c2bdf050797?source=collection_archive---------64-----------------------

使用 T-SQL 窗口函数可以轻松解决传统的“间隙和孤岛”问题

拉胡尔从派克斯拍摄的照片

最近,我公司的一位业务用户请求我创建一个报告,显示资金周转率大于 X 值的连续天数。当我开始准备来自 SQL Server 数据库的数据时,有一些棘手的问题需要解决。

抽样资料

为了演示我是如何解决这个问题的,我将使用栈溢出 示例数据库。让我们将业务请求转化为以下内容:找出连续几天有超过 50 篇帖子并且每篇帖子都有超过 50,000 次浏览的情况。

dbo。Posts 包含大约 1720 万行。首先,让我们看看每天有多少帖子的浏览量超过 50,000:

*SELECT convert(date,CreationDate) as CreationDate
    ,count(Id) as TotalPosts
FROM Posts 
WHERE CreationDate >= '20080731'
    AND CreationDate < '20140101'
        AND ViewCount > 50000
GROUP BY convert(date,CreationDate)
ORDER BY CreationDate*

当我运行这个查询时,我得到以下结果:

为了更好地处理正在运行的查询,我在 CreationDate 列上创建了一个非聚集索引,包括 ViewCount 列。现在,当我运行查询来检查有超过 50 篇帖子、超过 50,000 次浏览的日期时,我得到了以下结果:

*;WITH CTE_POSTS as(
select convert(date,CreationDate) CreationDate
    ,count(Id) totalPosts
from Posts 
where CreationDate >= '20080731'
    and CreationDate < '20140101'
    and ViewCount > 50000
group by convert(date,CreationDate)
)

SELECT * 
FROM CTE_POSTS
WHERE totalPosts > 50
order by CreationDate*

正如你所注意到的,从 2008 年 9 月 15 日到 9 月 19 日,所有日期都包括在内。然后,第 20 个和第 21 个不见了……这个问题就是众所周知的 【缺口与孤岛】 问题。在这里,第一桶日期(15 日—19 日)代表“岛”,20 日和 21 日代表“沟”。

欢迎来到这个岛…

让我们首先确定我们的“岛”(满足标准的连续日期的桶:在我们的例子中,超过 50 个帖子的日期有 50.000 以上的浏览量):

*; WITH CTE_POSTS as(
SELECT CONVERT(DATE,CreationDate) CreationDate
    ,COUNT(Id) totalPosts
from Posts 
WHERE CreationDate >= '20080731'
    AND CreationDate < '20140101'
    AND ViewCount > 50000
GROUP BY convert(date,CreationDate)
HAVING COUNT(Id) > 50
)

,starting as (
SELECT CreationDate
    ,ROW_NUMBER() OVER(ORDER BY CreationDate) rnm
FROM CTE_POSTS as CTE1
WHERE NOT EXISTS (
    SELECT * 
    FROM CTE_POSTS as CTE2
    WHERE DATEDIFF(dd,CTE2.CreationDate,CTE1.CreationDate) = 1)
    )

,ending as (
SELECT CreationDate
    ,ROW_NUMBER() OVER(ORDER BY CreationDate) rnm
FROM CTE_POSTS as CTE1
WHERE NOT EXISTS (
    SELECT * 
    FROM CTE_POSTS as CTE2
    WHERE DATEDIFF(dd,CTE2.CreationDate,CTE1.CreationDate) = -1)
    )

SELECT s.CreationDate as startingDate
    ,e.CreationDate as endingDate 
        ,DATEDIFF(dd,s.CreationDate,e.CreationDate) as ConsecutiveDays
FROM starting s
INNER JOIN ending e on s.rnm = e.rnm*

这样,我们确定了我们的“岛屿”,正如您在下面的截图中看到的:

利用领先/落后优势

如果您运行的 SQL Server 版本是 2012 年或更高版本,您可以利用时间偏移函数超前滞后。默认情况下,LEAD 将返回序列中的下一个值,但是也可以使用可选参数来调整偏移量,而后者将执行完全相反的操作,即返回序列中的上一个值(默认情况下)。

让我们看看 LEAD 在我们的场景中是如何工作的:

*; WITH CTE_POSTS as(
select CONVERT(DATE,CreationDate) CreationDate
    ,COUNT(Id) totalPosts
FROM Posts 
WHERE CreationDate >= '20080731'
    AND CreationDate < '20140101'
    AND ViewCount > 50000
GROUP BY CONVERT(DATE,CreationDate)
HAVING COUNT(Id) > 50
)

,CTE_LEAD AS
(
SELECT CreationDate
    , DATEADD(day, -1 * DENSE_RANK() OVER(ORDER BY CreationDate), CreationDate) AS DateGroup
FROM CTE_POSTS
)

SELECT MIN(CreationDate) AS start_range
    ,MAX(CreationDate) AS end_range
    ,DATEDIFF(dd,MIN(CreationDate),MAX(CreationDate)) AS consecutiveDays
FROM CTE_LEAD
GROUP BY DateGroup;*

这个解决方案更加直观,因为您避免了自连接的复杂性,但是更重要的是,这段代码运行得更快。

这里,我从 ROW_NUMBER() 函数开始,而不是 DENSE_RANK() 。但是,后来我从 Itzik Ben-Gan 的书“使用窗口函数的 Microsoft SQL Server 2012 高性能 T-SQL”中找到了一个很好的解释,他在书中阐明了 DENSE_RANK() 保证即使我们的序列中有重复值,代码也会正常工作,而 ROW_NUMBER() 则不会。

结果和预期的一样:

寻找差距

在某些情况下,您希望检查业务请求未得到满足的范围。例如,您希望检查您的销售额低于某个阈值的日期,或者您的系统无法正常工作的日期。

在我的例子中,我将显示不超过 50 个帖子有 50,000 以上的浏览量的日期。

传统 T-SQL 解决方案

与寻找“孤岛”相反,我们需要检查连续的值并检测它们之间的“间隙”在哪里。

*; WITH CTE_POSTS as(
select CONVERT(DATE,CreationDate) CreationDate
    ,COUNT(Id) totalPosts
FROM Posts 
WHERE CreationDate >= '20080731'
    AND CreationDate < '20140101'
    AND ViewCount > 50000
GROUP BY CONVERT(DATE,CreationDate)
HAVING COUNT(Id) > 50
)

SELECT DATEADD(dd,1,CreationDate) AS startDate
    ,DATEADD(dd,-1,(SELECT MIN(t2.CreationDate)
     FROM CTE_POSTS t2
     WHERE t2.CreationDate > t1.CreationDate)) AS endDate
FROM CTE_POSTS t1
WHERE NOT EXISTS (
        SELECT *
    FROM CTE_POSTS t2
    WHERE t2.CreationDate = DATEADD(dd,1,t1.CreationDate)
           AND CreationDate < (SELECT MAX(CreationDate) from CTE_POSTS))*

使用窗口功能变得复杂

至于“孤岛”问题,可以实施类似的逻辑来寻找“缺口”。因此,和前面的例子一样,我们将使用 LEAD 函数来实现我们的目标:

*; WITH CTE_POSTS as(
select CONVERT(DATE,CreationDate) CreationDate
    ,COUNT(Id) totalPosts
FROM Posts 
WHERE CreationDate >= '20080731'
    AND CreationDate < '20140101'
    AND ViewCount > 50000
GROUP BY CONVERT(DATE,CreationDate)
HAVING COUNT(Id) > 50
)
,CTE_LEAD AS
(
SELECT CreationDate AS startDate
    , LEAD(CreationDate) OVER(ORDER BY CreationDate) AS endDate
FROM CTE_POSTS
)
SELECT DATEADD(dd, 1, startDate) AS startDate
    ,DATEADD(dd, -1, endDate) endDate
FROM CTE_LEAD
WHERE DATEDIFF(dd, startDate, endDate) > 1;*

同样,有了的引导,代码更加直观,可读性更好。在这里,我们只是检查连续日期之间的范围,如果它大于 1,这意味着我们的序列中有一个缺口。当满足该标准时,我们只是在序列中的最后一个“岛”日期上加一天,以获得第一个“间隔”日期,同时从下一个序列中的第一个“岛”日期减去一天,以获得“间隔”的最后一个日期。

线性回归如何有资格成为机器学习算法?

原文:https://towardsdatascience.com/isnt-linear-regression-for-machine-learning-d31543f49181?source=collection_archive---------38-----------------------

机器学习,数据科学

线性回归是最知名的简单的统计和机器学习工具。

来源:自己的工作

在本文中,您可以探索线性回归算法,它是如何操作的,以及如何更好地使用它?

线性回归(LR) 是一种简单而强大的监督学习技术。它在很多情况下都有应用。

LR 决定称为解释变量的输入变量如何影响称为响应变量的输出变量。它使用具有最小数量的平方残差的最佳拟合直线,俗称回归线最小平方线

简单线性模型只包含一个自变量,称为简单线性回归。而多元线性回归有多个解释变量。

LR 处理连续变量的研究。这有利于公司根据经验预测未来的市场趋势和薪酬关系。LR 用于预测时间序列因果关系。例如,鲁莽驾驶和道路伤害之间的联系。

LR 可以是正的,也可以是负的。两个变量之间的正关系意味着一个变量的值的增加总是会增加另一个变量的值。

另一方面,两个变量之间的负关系意味着一个变量的值的增加意味着另一个变量的值的减少。

线性回归的假设

Artem SapeginUnsplash 上拍照

  • 因变量 y 和自变量 x 之间的关系总是线性的。x 的系数必须是线性的,不相关的。你不能允许系数是彼此的函数。
  • 在非金融应用中,自变量也必须是非随机的。此外,在金融场景中,只要误差变量和自变量不相关,对随机自变量的近似就可以是准确的。
  • 多重共线性发生在自变量相关联时。其中所有变量的相关系数必须小于 1。容差是多重共线性的另一种度量。公差由 T=1-R2 定义,其中 T < 0.1 可以是多重共线,T < 0.01 是多重共线。对于变量通货膨胀系数 (VIF),VIF > 10 是变量间的多重共线性。
  • 错误这个词通常会被传播。它测试形成直方图或 Q-Q 残差图。直方图应该是对称的钟形,并且 Q-Q 图的点应该在 45 度轴上。
  • 误差定义的方差是常数。这称为同方差约束恒误差方差。它使用散点图进行评估。 Breusch-Pagan 检验用于检验同质性。对独立变量执行额外的平方残差分析。
  • 自相关发生在残基彼此不独立的地方。德宾-沃森 (DW)检查残基不自相关的零假设。低于 2 的 DW 统计表明附近的残差彼此相关。
  • 如果 LR 做出可靠的预测,你的输入输出变量将是高斯分布多元正态性在这种正态性下,所有变量都期望是多元的和正则的。使用直方图或 Q-Q 图识别。此外,使用 Kolmogorov-Smirnov 测试验证体能测试的正常性。当数据通常不用于翻译时,日志转换完成。

预测的准确度等级

Bermix 工作室Unsplash 拍摄的照片

  • 残差的比例给出了一个清晰的例子,说明回归线如何有效地从 X 值估计 Y 值。这种计算被称为估计的标准误差。这是估计值的标准差。数字越小,预测就越精确。
  • 使用公式 R2 测试模型的可靠性,该公式是 x 和 y 之间关联的平方。R2 越强,越适合。现在还在 0 和 1 之间。线性排列越强,R 越接近 1。
  • 调整后的 R2 是一种额外的方法,将 R2 应用于方程中的解释变量的数量。这用于控制额外的解释变量是否是等式的一部分。R2 是这种联系的最强近似。调整后的 R2 可能为负,尽管事实并非如此。在过拟合设置中,实现了导致可预测性降低的高 R2 值。调整后的 R2 并非如此。添加到模型中的每个变量都会增加 R2,而不会减少。而调整后的 R2 仅在新的预测器加强 LR 模型时上升。

建立关系模型的替代方法

兰迪父亲Unsplash 上拍摄的照片

  • 许多可供选择的解释因素是分类的,不能在定量尺度上测试。使用虚拟变量是一个技巧。虚拟变量是潜在值在 0 和 1 之间的变量。性别示例,季度。
  • 你可能有两个解释变量的交互变量组合。在回归方程中包含一个交互变量,如果,你假设一个解释变量对 y 的影响依赖于另一个解释变量的值。
  • 作为散点图中曲率结果的变量的非线性变换。你应该转换因变量 y 或者解释变量 x,或者你可以全部转换。它包括标准对数、平方根、倒数和平方。

为什么要在回归中记录变量?

  • 变量有正确的偏斜,取一个对数将使变换后的变量的分布对称。但是这并不是记录变量的足够借口。没有将自变量或因变量控制为正态的回归规则。如果您的因变量或自变量中有异常值,对数变换会减少这种影响。
  • 回归残差的方差随着回归预测的增加而增加。取因变量或自变量的对数可能会降低异方差
  • 您的回归残差方差随着您的回归预测而增长。取切异方差的因变量或自变量的对数。
  • 你的回归残差不正常。这对你来说可能是也可能不是问题。即使残留物不常见。您应该记录因变量或自变量,并验证对数变换后的残差是否有规律。
  • 如果因变量和自变量没有线性和指数关系。例如,收入的多少与食物消费相关。收入的成比例增长会使消费增加到一定的数量,之后,食品消费要么持平,要么下降。

自变量的相关性

T 他的潜在想法是吝啬用最少的东西展示最多的东西。它支持一个解释变量较少的模型。以下技术可用于确定线性回归方程中解释变量的显著性。

相关系数描述了 x 和 y 之间线性关系的强度和方向。假设检验有助于确定总体相关系数值是否接近零,或者是否不同于零。

当测试确定相关系数不为零时,相关系数很重要。如果测试显示相关系数接近于零,我们假设相关系数不显著。

两种方法来检验使用 p 值和 t 统计量的显著性。

  • 回归系数的 T 值,用于在回归方程中包括或排除解释变量。如果在 95%的置信水平下 p 值 <为 0.05,且回归方程中使用 t 统计量> 2,则假设该变量很重要。如果 t 统计量小于 1,那么这是一个统计事实,即如果该变量被排除在回归方程之外,标准误差将会减小,调整后的 R2 将会增加。
  • F 检验确定已解释的变异相对于未解释的变异是否较高的方法。显著性的 f 检验是对线性关系的假设检验。它有一个允许测试运行的相关 p 值。如果 ANOVA 表的 F 值较大,而相应的 p 值较小。拒绝零假设,假设解释变量有一定的价值。

结论

R 广义上的回归分析。然而,它侧重于量化与自变量调整相关的因变量变化。这是因为所有的线性或非线性回归模型都将因变量与自变量联系起来。

现在,带着你对TwitterLinkedin,以及Github的想法!!**

同意 还是 不同意 与绍拉夫·辛拉的观点和例子?想告诉我们你的故事吗?

他乐于接受建设性的反馈——如果您对此分析有后续想法,请在下面 评论 或联系我们!!

推文@ SauravSingla _ 08,评论Saurav _ Singla,还有明星SauravSingla马上!

隔离森林:一种基于树的异常检测算法

原文:https://towardsdatascience.com/isolation-forest-a-tree-based-algorithm-for-anomaly-detection-4a1669f9b782?source=collection_archive---------11-----------------------

关于异常检测算法的小数据科学

托德·夸肯布什在 Unsplash 拍摄的照片

这是我写的关于异常检测中常用的算法的一系列小文章中的第 10 篇(我会在最后放上所有其他文章的链接)。在今天的文章中,我将重点介绍一种基于树的机器学习算法——隔离森林——它可以有效地从多维数据集中隔离出离群值。

我在这里的目的是给出算法如何工作的直觉,以及如何用几行代码实现它作为演示。所以我不会深入理论,但足以帮助读者理解基础知识。如果您对算法的某个特定部分感兴趣,您可以随时搜索和查找细节。所以让我们开始吧!

什么是隔离林?

隔离森林或 iForest 是较新的算法之一,于 2008 年首次提出[1],后来在 2012 年的一篇论文中发表[2]。大约在 2016 年,它被并入 Python Scikit-Learn 库。

它是一种基于树的算法,围绕决策树和随机森林理论构建。当呈现数据集时,该算法根据随机阈值将数据分成两部分。这个过程递归地继续,直到每个数据点被隔离。一旦该算法贯穿整个数据,它就过滤掉比其他数据点花费更少步骤的数据点,以将其隔离。sklearn中的隔离森林是集合模型类的一部分,它返回每个实例的异常分数来衡量异常。

图:分割数据以隔离隔离林中的异常(来源: Scikit-Learn )

在大多数非监督方法中,首先对“正常”数据点进行分析,如果异常数据点与该分析不相似,则报告异常数据点。另一方面,隔离森林采取了不同的方法;它明确地隔离异常数据点。

值得一提的是,隔离森林是一种无监督的机器学习算法。也就是说,该过程中不涉及实际的“训练”或“学习”,并且在数据集中不存在预先确定的“异常值”或“非异常值”标签。所以没有传统机器学习意义上的精度测试。

现在让我们用 5 个步骤来实现这个算法。

第一步:导入库

你将需要pandasnumpy来处理数据,需要matplotlib来进行数据可视化,当然,还需要sklearn库中的算法本身。

# libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest

第二步:准备数据

为了便于您理解,我没有导入任何外部数据集,而是创建了一个简单的二维numpy数组,其中只有一个异常值,如二维图所示。

# dataset
X = np.array([[1, 2], [2, 1], [3, 2], [0, 1], [25, 30], [3, 5]])# using just numpy array for visualization
plt.scatter(X[:,0], X[:,1], color = "r", s = 50)
plt.grid()

带有异常值的二维 numpy 数组

步骤 3:实例化并拟合模型

像 Scikit Learn 库中的大多数算法一样,实例化和拟合模型只需要几行代码。

构建模型的两个重要参数是 n_estimatorscontaminance,后者指定被识别为异常值的数据的百分比。

# instantiate model
model = IsolationForest(n_estimators = 10)# fit model
model.fit(X)

第四步:预测

当进行预测时,该过程包括向模型显示一个二维数组,该模型将对正常数据给出 1,对异常值给出-1。

# predict on new data 
new_data = np.array([[10, 15]])
model.predict(new_data)>> array([-1])

第五步:异常分数

就像我在开始所说的,算法使用异常分数作为度量,它代表输入样本的平均异常分数。

# average anomaly score
model.decision_function(np.array(new_data))>> array([-0.11147288])

最后一个字

感谢您的阅读,希望这篇文章有助于您直观地了解什么是隔离林以及如何在 Python sklearn库中实现它。我在这份出版物中写了一系列文章,重点关注其他几种算法。如果你有兴趣去看看,下面是链接。和往常一样,请随时通过 TwitterLinkedIn 联系我,并在 Medium 上关注我,获取最新文章的通知。

参考文献

[1]刘,费托尼,丁,,周,张志华.“隔离林。”数据挖掘,2008。08 年的 ICDM。第八届 IEEE 国际会议。

[2]刘,费托尼,丁,,周,张志华.“基于隔离的异常检测。”《美国计算机学会数据知识发现汇刊》6.1 (2012): 3。

隔离森林和 Pyspark 第 2 部分

原文:https://towardsdatascience.com/isolation-forest-and-pyspark-part-2-76f7cd9cee56?source=collection_archive---------28-----------------------

经验教训

调试 PySpark 和隔离森林—图片由作者提供

因此,在使用隔离森林的 PySpark ml 实现运行了几次之后,我偶然发现了一些事情,我想我应该写下来,这样你就不会浪费我在故障诊断上浪费的时间。

只有密集向量

在上一篇文章中,我使用了VectorAssembler来收集特征向量。碰巧我的测试数据只创建了DenseVectors,但是当我在不同的数据集上尝试这个例子时,我意识到:

  • **VectorAssembler**可以在同一个数据帧中创建密集和稀疏向量(这很聪明,其他 spark ml 算法可以利用它并使用它)
  • **Isolation Forest** (或者至少实现发现这里的 ) 不支持上面的,所以输入必须只有DenseVectors

要演示该问题:

目前的解决方法是将所有矢量转换为密集矢量,不幸的是使用了 udf。

避免 OOM 和执行者的沟通问题

为大型数据集设置approxquantilerrelativeerror 阈值 参数

如果你计划在一个大数据集上进行训练,比如超过 10M 行,即使你设置了maxSamplesmaxFeatures这样的参数来降低维数,你也需要将approxQuantileRelativeError参数设置得合理一些,比如0.2。原因是approxQuantile函数是一个使用起来非常昂贵的函数,尤其是如果我们期望approxQuantileRelativeError0.(这是默认值)。这样做,大大减少了训练时间和 OOM 与执行者的沟通问题,而且,到目前为止,我还没有看到预测准确性的任何下降。

从实施的评论来看:

*** The proportion of outliers in the data set (0< contamination < 1).
* It will be used in the prediction. In order to enhance performance,
* Our method to get anomaly score threshold adopts DataFrameStsFunctions.approxQuantile,
* which is designed for performance with some extent accuracy loss.
* Set the param approxQuantileRelativeError (0 < e < 1) to calculate
* an approximate quantile threshold of anomaly scores for large dataset.**

或者,在 fit 中预先设置threshold并避免approxQuantile计算,如下所示:

*model = iforest.fit(df, {**'threshold'**: 0.5})
print(model.getThreshold())> 0.49272560194039505*

希望这对您有所帮助并节省一些时间:)如果您有任何建议、更正或想法,请告诉我。

在此阅读有关如何将隔离林与 pyspark 一起使用的更多信息:

* [## 隔离森林和火花

PySpark 隔离带的主要特点和使用方法

towardsdatascience.com](/isolation-forest-and-spark-b88ade6c63ff)

接下来去哪里?

理解模型的预测:

[## 机器学习的可解释性——带有 PySpark 的 Shapley 值

解读隔离森林的预测——不仅仅是

medium.com](https://medium.com/mlearning-ai/machine-learning-interpretability-shapley-values-with-pyspark-16ffd87227e3)*

从零开始隔离森林

原文:https://towardsdatascience.com/isolation-forest-from-scratch-e7e5978e6f4c?source=collection_archive---------20-----------------------

从零开始实现隔离森林,以便进一步理解算法

最近,我一直在阅读隔离森林及其在异常值/异常检测方面的表现。在仔细阅读了算法之后(并且没有找到任何我喜欢的香草教程)。为了更好地掌握算法,我决定用最简单的方式从头开始编码。

这篇文章的目的是在阅读后,你可以深入了解隔离森林,它的优点,缺点,参数,你可以随时使用它,只要你考虑与算法的知识。

对于这个博客/实现,我使用了这篇关于隔离森林的论文作为伪代码,这篇扩展的隔离森林论文作为可视化(与另一篇博客文章相对应),并使用了这个 youtube 教程示例来自 Sebastian Mantey 的随机森林实现

一点理论背景

在开始写代码之前,我认为需要一点理论。

什么是隔离林?

  • 隔离林用于异常值/异常检测
  • 隔离森林是一种无监督学习技术(不需要标签)
  • 使用二进制决策树 bagging(类似监督学习中的随机森林)

假设

该方法将异常与正常情况隔离开来,为此,对异常进行了以下假设:

  • 它们是由较少实例组成的少数
  • 它们具有不同于普通实例的属性值

换句话说,异常是“少数和不同的。”

由于前两个假设,异常很容易被隔离,这使得它们更接近树根。

简要描述

隔离林为给定数据集构建一个二叉树集合。异常,由于它们的性质,它们在树中有比正常情况下最短的路径。

隔离森林使用非常少的树快速收敛,子采样使我们能够在计算高效的同时获得良好的结果。

代码

总体编码策略如下。首先对一棵树进行编码,然后进行树的森林(集合),最后测量某个实例在每棵树中走了多远,并确定它是否是离群值。

让我们从树开始

隔离树:对树进行编码

[1]中的隔离树伪代码

输入将是数据样本、当前树高和最大深度。

对于输出,我们将有一个构建好的树。

为了更容易理解,我正在使用熊猫数据框,即使它在性能方面不是最佳的,也能让普通用户更容易理解。

  • 选择数据的特征(列)
def select_feature(data): 
    return random.choice(data.columns)
  • 在范围内选择一个随机值
def select_value(data,feat):
    mini = data[feat].min()
    maxi = data[feat].max()
    return (maxi-mini)*np.random.random()+mini
  • 分割数据
def split_data(data, split_column, split_value): data_below = data[data[split_column] <= split_value]
    data_above = data[data[split_column] >  split_value]

    return data_below, data_above
  • 一起:隔离树。

其思想如下:选择一个特征、该特征的值以及分割数据。如果分支中只有一个数据点,或者树已经达到最大深度:停止。

def isolation_tree(data,counter=0, max_depth=50,random_subspace=False):

    # End Loop if max depth or isolated
    if (counter == max_depth) or data.shape[0]<=1:
        classification = classify_data(data)
        return classification

    else:
        # Counter
        counter +=1

        # Select feature
        split_column = select_feature(data)

        # Select value
        split_value = select_value(data,split_column) # Split data
        data_below, data_above = split_data(data,split_column,split_value)

        # instantiate sub-tree      
        question = "{} <= {}".format(split_column, split_value)
        sub_tree = {question: []}

        # Recursive part
        below_answer = isolation_tree(data_below, counter,max_depth=max_depth)
        above_answer = isolation_tree(data_above, counter,max_depth=max_depth)

        if below_answer == above_answer:
            sub_tree = below_answer
        else:
            sub_tree[question].append(below_answer)
            sub_tree[question].append(above_answer)

        return sub_tree

隔离森林

[1]中的隔离林伪代码

一旦我们有了自己的树,我们就要把它们变成一片森林。伪代码如下:

给定一个输入数据、一些树和一个采样大小(每棵树有多少数据),我们根据需要拟合尽可能多的树并返回一个森林。

实际代码:

def isolation_forest(df,n_trees=5, max_depth=5, subspace=256):
    forest = []for i in range(n_trees):
        # Sample the subspace
        if subspace<=1:
            df = df.sample(frac=subspace)
        else:
            df = df.sample(subspace) # Fit tree
        tree = isolation_tree(df,max_depth=max_depth)

        # Save tree to forest
        forest.append(tree)

    return forest

路径长度

在构建了隔离林之后,我们必须评估实例,为此我们定义了路径长度

来自[1]的路径长度伪代码

给定一个实例和一个隔离树,我们计算每个实例在被隔离或达到最大深度之前要经过多少个节点。

伪代码摘自隔离林论文。

def pathLength(example,iTree,path=0,trace=False): # Initialize question and counter
    path=path+1
    question = list(iTree.keys())[0]
    feature_name, comparison_operator, value = question.split()

    # ask question
    if example[feature_name].values <= float(value):
        answer = iTree[question][0]
    else:
        answer = iTree[question][1]

    # base case
    if not isinstance(answer, dict):
        return path

    # recursive part
    else:
        residual_tree = answer
        return pathLength(example, residual_tree,path=path)return path

这只是根据以前存储数据的方式来计算一个实例经过了多少个节点。

估价

让我们四处看看

mean = [0, 0]
cov = [[1, 0], [0, 1]]  # diagonal covariance
Nobjs = 2000
x, y = np.random.multivariate_normal(mean, cov, Nobjs).T
#Add manual outlier
x[0]=3.3
y[0]=3.3
X=np.array([x,y]).T
X = pd.DataFrame(X,columns=['feat1','feat2'])
plt.figure(figsize=(7,7))
plt.plot(x,y,'bo');

数据样本

我们将用我们的数据进行训练和评估。

iForest = isolation_forest(X,n_trees=20, max_depth=100, subspace=256)# Evaluate one instance
def evaluate_instance(instance,forest):
    paths = []
    for tree in forest:
        paths.append(pathLength(instance,tree))
    return paths

我们选择数据的一个正常实例(随机选择)和一个异常值(记得我们在开始时硬编码了一个异常值作为第一行)。我们看它在树上落下多远,然后画出结果。

outlier = evaluate_instance(X.head(1),iForest)
normal  = evaluate_instance(X.sample(1),iForest)

蓝色表示随机正态样本,红色表示异常值。

np.mean(outlier)
# 4.85
np.mean(normal)
# 12.55

异常值和正常样本的每棵树的树深度

我们可以看到,在正常样本和异常值之间,在每个树中实例的深度方面存在视觉和统计差异。

扩展隔离森林的论文中,有另一种放射状的可视化形式,提供了对离群值的清晰直觉

如果节点深度(a)和径向深度(b)由[2]形成,则为正常与异常值

评估森林的更正式的方法是使用实例(x)的异常分数:

异常分数

其中 H(i)是谐波数,可以通过 ln(i) + 0.5772156649(欧拉常数)来估算。由于 c(n)是给定 n 的 h(x)的平均值,我们用它来归一化 h(x)。

def c_factor(n) :
    """
    Average path length of unsuccesful search in a binary search     tree given n points

    Parameters
    ----------
    n : int
        Number of data points for the BST.
    Returns
    -------
    float
        Average path length of unsuccesful search in a BST

    """
    return 2.0*(np.log(n-1)+0.5772156649) - (2.0*(n-1.)/(n*1.0))def anomaly_score(data_point,forest,n):
    '''
    Anomaly Score

    Returns
    -------
    0.5 -- sample does not have any distinct anomaly
    0 -- Normal Instance
    1 -- An anomaly
    '''
    # Mean depth for an instance
    E = np.mean(evaluate_instance(data_point,forest))

    c = c_factor(n)

    return 2**-(E/c)

使用这种方法,我们可以得到异常值的数学定义,但我相信,到此为止,您已经可以直观地了解算法是如何工作的,参数是什么,以及在哪些情况下它可能会成功。

请随意发表任何评论或给我发短信,告诉我你的建议或其他任何事情。

参考

这个博客已经完成如下

完整的代码、笔记本和图片可以在这个资源库中看到

[## cmougan/IsolationForest

隔离林存储库。通过在 GitHub 上创建帐户,为 cmougan/IsolationForest 的发展做出贡献。

github.com](https://github.com/cmougan/IsolationForest)

隔离森林是目前针对大数据的最佳异常检测算法

原文:https://towardsdatascience.com/isolation-forest-is-the-best-anomaly-detection-algorithm-for-big-data-right-now-e1a18ec0f94f?source=collection_archive---------6-----------------------

理解大数据

照片由西蒙·戈弗雷Unsplash 上拍摄

Isolation forest 或“iForest”是一个非常漂亮、非常简单的算法,可以用很少的参数识别异常。原始论文面向广大读者,包含最少的数学内容。在本文中,我将解释为什么 iForest 是目前针对大数据的最佳异常检测算法,提供该算法的摘要、该算法的历史,并分享一个代码实现。

为什么 iForest 是目前大数据的最佳异常检测算法

同类最佳的性能概括了。基于 ROC 性能和精度,iForest 在各种数据集上的表现优于大多数其他离群点检测(OD)算法。我从PythonOut lierDdetection package(PyOD;原始论文)并在 Excel 中应用了逐行绿-红渐变条件格式。深绿色表示数据集的最佳算法,深红色表示性能最差:

我从 PyOD(PythonOut lierDdetection toolbox)获取基准数据,并在 Excel 中应用行范围的绿-红渐变条件格式。绿色表示“好”,红色表示“坏”。我们看到,iForest 在大多数数据集和总体上领先,如均值、中值和标准差颜色所示。图片来源:作者。数据来源:https://pyod.readthedocs.io/en/latest/benchmark.html

我们看到,iForest 在大多数数据集和总体上领先,如我计算的均值、中值和标准差行的颜色所示。iForest 的出色结果同样适用于 precision @ N 性能:

图片来源:作者。数据来源:【https://pyod.readthedocs.io/en/latest/benchmark.html

扩展性。就其性能而言,iForest 是执行速度最快的算法。PCA 和基于直方图的异常值分数(HBOS论文海报)在所有数据集上都比预期的要快。k-最近邻(KNN)要慢得多,并且随着更多的观察而可怕地扩展。

在集群环境中,我已经成功地用包含 100 万个观察值的数据集构建了隔离森林,这些观察值有 36 列,数量级为几分钟。我不能对 sk-learn 的 KNN 说同样的话。

图片来源:作者。数据来源:https://pyod.readthedocs.io/en/latest/benchmark.html

算法要点/总结

我将提供一份 10 页纸的简要总结,概述如下:

  1. 大多数其他异常值检测(OD)算法试图建立“正常”实例的轮廓,然后标记不符合该正态轮廓的实例。iForest 通过利用异常的固有属性来明确隔离异常记录:它们对于协变量集具有不寻常的值。
  2. 由于计算开销,现有方法局限于低维数据和小数据量。例证:有没有在大数据上尝试过[sklearn.neighbo](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.neighbors)r.KNeighborsClassifier ?😃
  3. 此外,iForest 具有“低常数和低内存需求”,即低开销。细节:外部节点的数量是 n ,因为每个观察值 n 都是独立的。内部节点总数明明是 n-1 ,节点总数是 2n-1。因此,我们看到了为什么内存需求是有限的,并且随着 n. 线性增长
  4. 隔离树节点定义: T 或者是无子外部节点,或者是具有一个测试和恰好两个子节点的内部节点(Tₗ,Tᵣ).为了构建一个 iTree,我们通过随机选择一个属性 q 和一个分割值 p 来递归分割 X ,直到(I)树达到一个高度限制,(ii)所有的观察值在它们自己的外部节点被隔离,或者(iii)所有的数据对于所有的属性具有相同的值。
  5. 路径长度。观察值 x 的路径长度 h(x) 由从根节点到外部节点终止的横向遍历 iTree 的边数 x 测量。 E(h(x)) 是来自隔离树集合的 h(x) 的平均值。异常分数 s(x,n) 可以从平均路径长度 E(h(x)) : s(x,n) = 2^[− E(h(x)) / c(n)】中导出。基本上, sE(h(x)) 之间存在单调关系(详见最后的附录和说明它们关系的帮助图)我不会讨论术语 c(n) ,所以我可以保持简短,但它对于任何给定的静态数据集都是常数
  6. 仅要求用户设置两个变量:要构建的树的数量和子采样大小。作者提出了使用生成的高斯分布数据的实验,该实验显示了如何用很少的树和小的子样本相对快速地实现平均路径长度的收敛。
  7. 小的子采样(样本中的样本)解决了淹没和掩蔽问题。淹没和掩蔽是由对于异常检测目的而言太大的输入数据引起的。淹没是当一个“正常”的观察被误认为是一个“异常”的观察,因为它被异常所包围,而掩蔽是相反的。换句话说,当一棵树被提供了一个包含大部分异常的样本时,一个正常的数据点可能看起来是异常的。作者提出了这种现象的乳房 x 线照片数据的例子。
  8. 小的子样本允许每个隔离树特殊化,
    因为每个子样本包括一组不同的异常或
    甚至没有异常
  9. iForest 不依赖任何基于距离或密度的措施来识别异常,因此它速度快,计算成本低,这就引出了下一点
  10. 线性时间复杂度,O(n)。通俗地说,这意味着运行时间最多随着输入的大小线性增加这个不错:

11.对于具有相关背景的读者来说,论文中的以下图表清楚地说明了算法是如何工作的:

图片来源:刘、汀、周的《隔离林》。

算法历史

博览群书的读者都知道,一个伟大的新想法和更广泛的采用之间的时滞可能长达几十年。例如,逻辑函数在 1845 年被发现,在 1922 年被重新发现(阅读更多),现在被现代数据科学家定期用于逻辑回归。近几十年来,一个新想法和它被更广泛地采用之间的时间差已经缩短了,但仍然可以说是一段很长的时间。iForest 于 2008 年首次共享,商业上可行的应用程序直到 2018 年底才发布!下面的时间线:

2008 年 12 月— iForest 发布的原始论文(论文)
2009 年 7 月—I forest 作者最后一次修改他们的代码实现(代码)
2018 年 10 月— h2o 团队向 R 和 Python 用户提供 I forest(代码)
2019 年 1 月— PyOD 为 Python 用户发布离群点检测(OD)工具包(代码论文)

代码实现

因为本文是关于大数据的,所以我假设一个集群环境。我下面的实现可以处理存储在 AWS S3 中的数据,但只需稍加修改就可以在其他地方使用。代码搭建(QA 对象、调试等的代码。)大多省略。需要为 AWS 集群环境安装软件包的帮助吗?参见我的中型文章:如何为 SparkSQL 设置经济高效的 AWS EMR 集群和 Jupyter 笔记本

我发现 iForest 可以轻松快速地处理 750 万行和 36 个特征,在几分钟内完成计算。

Python (h2o):

下面的直方图由上面的代码生成。对于我的数据框predictions_fullX中的观察结果,大多数观察结果并不异常,如较大平均路径长度的频率所证明的。

图片来源:作者使用专有数据集

如果您的数据有您想要用 iForest 确证的标签,您可以将正常实例集的分布与异常实例集的分布进行比较,并与原始数据集进行比较,以便进一步推断。例如,您可以通过原始数据集中要素的不同组合来查看计数,如下所示:

N = df.count()
df[['v1', 'v2', 'id']].groupby(['v1', 'v2']).count() / N
df[['v1', 'v3', 'id']].groupby(['v1', 'v3']).count() / N
...

并与 iForest 确定的正常/异常实例集进行比较,如下所示:

我完成了所有这些工作,还将我的数据导出到 Excel 中,以快速生成一些累积分布函数,如下所示:

图片来源:作者本人作品。绿线代表 label=1,或已知的正态观测值;红线代表标签=1 的观察值,确认为可能异常或可能不异常。

Python (pyod) (如果评论中有要求,我会添加代码!)

更新(2020 年 12 月 15 日),PyOD 代码:

在 PyOD github ( link )上有很多很棒的例子,所以我不认为我有必要编造一个。如果你对 GitHub repo 上没有的 PyOD 代码有特殊要求,请在评论中告诉我。Github 不会向您显示结果应该是什么样子,所以我的增值功能可以向您显示代码应该输出什么,以防您在这方面遇到困难。

https://github . com/yzhao 062/pyod/blob/master/examples/ocsvm _ example . py 的输出应该类似于:

图片来源:作者

Scala (即将推出)

我使用 LinkedIn 团队对 Scala 的 iForest ( github )实现,因为 PyOD 和 h2o 是针对 Python 的。目前还不能让它工作,但当我可以的时候会更新。

参考

  • F.刘铁男、丁国明、周志宏。隔离林。摘自:《第八届 IEEE 数据挖掘国际会议论文集》(ICDM'08) ,意大利比萨,2008 年,第 413–422 页。本文获得了 2008 年 IEEE ICDM 会议理论/算法亚军最佳论文奖
  • 赵,杨,纳斯鲁拉,和李,2019。PyOD:用于可伸缩异常检测的 Python 工具箱。机器学习研究杂志(JMLR),20(96),第 1–7 页。

关于作者

安德鲁·杨是 Neustar 的 R&D 数据科学家经理。例如,Neustar 是一家信息服务公司,从航空、银行、政府、营销、社交媒体和电信等领域的数百家公司获取结构化和非结构化的文本和图片数据。Neustar 将这些数据成分结合起来,然后向企业客户出售具有附加值的成品,用于咨询、网络安全、欺诈检测和营销等目的。在这种情况下,Young 先生是 R&D 一个小型数据科学团队的实践型首席架构师,负责构建、优化和维护一个为所有产品和服务提供信息的系统,该系统为 Neustar 带来了超过 10 亿美元的年收入。在 LinkedIn 上关注 Andrew,了解数据科学的最新趋势!

更多热门文章:

附录

算法要点/总结,第 5 点细节:

  • 当 E(h(x)) → c(n),s → 0.5(观测不是明显异常)
  • 当 E(h(x)) → 0,s → 1(异常)
  • 当 E(h(x))→n1,s → 0 时(非异常)

所以用这篇论文的话来概括上述内容:

  • (a)如果实例返回的 s 非常接近 1,那么它们肯定是异常,
  • (b)如果实例的 s 远小于 0.5,那么它们被视为正常实例是相当安全的,并且
  • 如果所有实例都返回 s ≈ 0.5,那么整个样本实际上没有任何明显的异常。

说明异常分数 s 和平均路径长度 E(h(x)) 之间关系的有用图

图 2 来自隔离林纸。

It from Bit:人工智能如何塑造我们的物理世界

原文:https://towardsdatascience.com/it-from-bit-how-ai-is-shaping-our-physical-world-2fbf3c5df27?source=collection_archive---------28-----------------------

人工智能只是一个“数字事物”,还是它正在彻底改变我们的物理世界?

它只是“一点”?

先驱物理学家约翰·阿奇博尔德·惠勒曾用诗意的“比特的信息”总结了信息的“空灵”概念和我们的物质物理现实之间错综复杂的相互联系。像充斥在我们电子设备中的由 1 和 0 组成的无形实体,实际上正在“构成”和塑造我们的物理世界。

人工智能:一堆比特……以及它如何影响物理世界。

人工智能是一个同样虚无缥缈的概念,由 0 和 1 构建的抽象数学实体组成,这些实体对模拟神经元和突触的结构和功能进行编码,最终赋予人工智能学习和预测真实世界的能力,这些真实世界类似于我们生物大脑产生的世界。

然而,我们生活在一个由物质构成的世界:人、房子、桌椅、建筑、飞机、火车和汽车。人工智能这个抽象的东西对我们日常的物理现实有什么真正的影响?

虽然人工智能已经被证明能够为聊天机器人提供动力,能够与客户互动,查看安全摄像头,寻找你心爱的亚马逊包裹的可能小偷,并帮助脸书和谷歌了解如何为你看到更多广告,但它对我们的物理世界有何影响?

很微妙,但是很大。让我给你举一个例子,我认为这是地球上存在的最有形的“东西”之一……制造业,正是这个过程构建了构成我们人类世界的万物。

人工智能如何塑造我们建造事物的方式

人工智能正在改变我们的物理世界的一个主要领域是制造业,从产品一致性到质量控制,在简化制造供应链和主动设备维护方面。

人工智能是真实的…例如,在制造业。

想象一个充满制造机器的现代化工厂。例如,在质量控制方面,人工监督只能做这么多,而机器每小时生产数百种产品。人类工人,在制造业中是一种微不足道的商品,根本不能也没有能力发现每一个不完美和缺陷。

人工智能在制造车间的引入极大地改变了工厂提高产品缺陷检测和质量保证的方式,将生产率提高了 50%或更多。这些都是真实的,人工智能的物理效果,每个人都可以触摸和量化!

而这只是冰山一角!根据 IDC 的数据,到 2021 年,20%的领先制造商将依赖人工智能和其他技术,麦肯锡发现,在未来五到七年内,将人工智能嵌入数据密集型制造流程的 50%的公司将有机会使现金流翻倍。

除了制造业中精致的物理例子,影响我们物理世界的其他人工智能包括,例如,零售业,智能软件能够理解客户行为,帮助商店在销售点向他们提供更有针对性的有趣产品。或者医疗保健,在人工智能的帮助下,我们的身体将得到更好、更快、更普遍的诊断。由于物联网中集成的高级人工智能,我们的家正在通过管理照明、温度和其他设置来改变我们大部分时间所在的物理环境。此外,最重要的是,我们自己的钱包将受到人工智能的好处(积极)影响,人工智能可以根据用户的风险偏好准确有效地优化股票投资组合。

数字化正成为我们现实中越来越不可或缺的一部分,数十亿物联网传感器、移动设备和联网机器正在进入我们的物理世界,重新融入 it 动作、见解,并从根本上改变它,人工智能技术是其核心。

所以,下次你坐在咖啡店里阅读下一篇关于人工智能的文章时,记住它不仅仅是比特。相反,它是夹在真实物理系统之间的一个非常重要的软件,在真实物理系统中,信息一直被不断地获取、理解和处理。

欢迎来到无处不在的物理智能时代。

学习“如何学习数据科学”是一门技能

原文:https://towardsdatascience.com/it-is-a-skill-to-learn-how-to-learn-data-science-fb5e49507b7d?source=collection_archive---------39-----------------------

有助于你轻松学习的有用建议

数据科学领域发展迅速,导致员工供不应求。尝试实施和利用数据科学的企业数量也在不断增加。因此,越来越多的人选择在数据科学领域开始职业生涯。在大多数情况下,在开始数据科学职业生涯之前,您需要学习一定程度的知识。根据你的策略,学习过程可以是顺利的、愉快的或彻底的。

这篇文章的目的不是给你一个学习的指南或者你需要知道的事情的清单。我宁愿分享一些在学习过程中对我帮助很大的小技巧。

Jelleke Vanooteghem 在 Unsplash 上拍摄的照片

资源的数量实在是太多了。你可能会遇到这样的帖子:

  • 你必须阅读的 5 本书…
  • 你应该参加的 10 门在线课程…
  • 阅读 12 篇博客…
  • 关注 20 个 youtube 频道…

去学数据科学。

这样的例子不胜枚举。轻松获取资源学习绝对是好事。大量的资源使自学过程成为可能。然而,你需要一个结构良好的计划来学习而不浪费时间,因为时间(最重要的资源)是有限的。我们当然应该利用各种容易获取的资源,但是要以一种系统的、结构良好的方式。

我不会分享一个需要学习的东西的清单或者为你画一个路线图,而是分享我作为一个喜欢学习新事物的人的经验和想法。

数据科学领域是一个新兴领域。这个领域正在进行大量的研究,因此这个领域的进步和新技术不断涌现。新的库和框架很快就会发布。现有的正在不断更新。一个常用的框架可能会在很短的时间内失去其受欢迎程度或被一个新的框架所取代。我绝对不反对这些更新或新版本。跟上技术的进步是非常好的,每个新版本都在现有版本的基础上增加了一些东西。然而,我们不可能用数据科学所有子领域的每一个新版本来更新自己。

照片由盖尔·马塞尔Unsplash 拍摄

数据科学是一个广阔的领域,存在特定于领域的技术。例如,BERT 是一种用于自然语言处理(NLP)的技术。如果你不打算在 NLP 工作,你不必学习 BERT。数据科学中也有特定于某个领域的技术。因此,请不要对这巨大的资源感到疲惫。我们不能什么都学,而应该专注于我们所在的领域或计划工作的领域。

学习基础知识

我们需要对基础知识有一个全面的了解。所有这些技术的基础构件是线性代数。数据可以是数字、文本、图像、声音或视频的形式,但计算机只有一种形式的数据源。那是数字。每一个数据源都必须转换成数字,以便计算机或模型进行分析。这些数字可以是很长的数组或高维矩阵的形式。这是线性代数的领域。如果我们彻底学习线性代数,我们可以很容易地适应新技术,并理解背后的理论。

另一个非常重要的学习主题是统计学,它有助于我们理解数据。统计数据可以推断出乍一看很难看出的趋势。它提供了关于数据底层结构的有用而强大的见解。例如,概率和频率分布的概念允许很好地使用和感知数据。无论您使用什么工具,全面的统计学知识在任何数据科学领域都是至关重要的。

欺骗没有任何好处!

我在网上看到了很多熊猫,小熊猫,Scikit Learn 或者其他一些小抄。你不应该试图用小抄来学习,除非你自己做。浏览小抄似乎更容易,你会觉得你理解了上面的一切。是的,你理解但不学习。如果你总是使用小抄来学习,你可能最终不得不经常看它们。然而,如果你准备自己的小抄,你就在准备的时候学习。

理解和学习是不一样的!

我想在这里举个例子。假设你有一节数学课。讲师会在课堂上解释这个主题,并给你 20 个问题来巩固你的知识。你有一个朋友是这方面的专家,你有两个选择:

  • 请你的朋友帮忙。他在一小时内为你解释并解决 20 个问题。
  • 你试着自己解决问题。你花了 5 个小时,只能完成 3 道题。

我坚信你在第二种选择中学到了更多。我不是神经科学家,但我认为当我们努力学习时,我们的大脑建立了强大的连接。请记住,我们的大脑是一个巨大而复杂的神经网络。

根据尼克·达姆的这篇文章

当学习经历不活跃时,作为大脑学习基础的神经连接的变化似乎不会发生。许多研究表明,积极参与是大脑变化的先决条件。

因此,积极的体验对学习来说是至关重要的,很明显,按照小抄做并不是积极的体验。

主动学习的一个好方法是做个人项目。

做个人项目!

你可能会在许多博客文章、故事甚至是工作面试中遇到这个建议。是的,做个人数据科学项目非常关键。我不会提到个人项目是展示你知识的有力方式,这个话题留给招聘经理吧。

我想提一下个人项目如何帮助学习过程:

  • 您将了解从数据收集到模型评估的典型数据科学项目流程。
  • 您将学习如何收集和清理原始数据。
  • 如果你提出一个问题,并使用数据科学技术来解决它,那就更好了。通过这种方式,您还将了解数据科学为什么有用以及如何有用。你甚至可能会想出一个绝妙的主意。
  • 你肯定会遇到一个问题,却不知道如何解决它。当你在 medium、stackoverflow 或其他网站上搜索答案时,你不仅找到了问题的解决方案,还找到了许多其他有用的东西。这类似于花几个小时在一个数学问题上。你最终会学到永远不会忘记。
  • 熟能生巧。

结论

最后,我想总结一下我的建议:

  • 不要因为大量的信息和工具而感到疲惫。你不必学所有的。
  • 准备好自己的学习路线图。
  • 掌握线性代数和统计的基本概念。
  • 准备你自己的小抄。
  • 做个人项目。

一如既往,熟能生巧。

感谢您的阅读。如果您有任何反馈,请告诉我。

使用 Python 进行意大利新冠肺炎分析

原文:https://towardsdatascience.com/italian-covid-19-analysis-with-python-1bdb0e64d5ac?source=collection_archive---------24-----------------------

照片由 Gerd AltmannPixabay 拍摄

本教程分析了意大利民间保护组织发布的关于新冠肺炎的数据,并建立了流行病结束的预测。在下面的文章中描述了这个预测器背后的一般概念:https://medium . com/@ angelica . lo duca/predicting-the-end-of-the-coronavirus-epiderations-in-Italy-8da 9811 f 7740。代码可以从我的 github 资源库下载:https://github . com/alod 83/data-science/tree/master/data analysis/新冠肺炎

本教程的主要目的在于建立一个预测器,用于预测意大利新冠肺炎疫情新发病例的可能结束时间。建议的教程是基于意大利的数据,但它也可以推广到其他国家的数据。例如,关于西班牙的数据可在此链接获得:https://github . com/data dista/datasets/tree/master/COVID % 2019

到目前为止,已经提出了不同的方法,例如 R0 传染指数(详见此处)。然而,在新冠肺炎流行病的情况下,估计 R0 并不简单。相反,本教程中提出的模型是基于对真实数据的观察,并且使用哪条曲线来拟合数据的决定是基于这样的观察。

本教程的一个可能的扩展是构建一个预测意大利整个流行病结束的预测器,即没有新的阳性病例登记的时间。这方面将是未来文章的主题。

笔记本利用了pandasscikit-learn库。

输入数据

从 Github 存储库导入 CSV 并构建 EPI

首先,我们从意大利 Protezione Civile 的 Github 库导入数据,然后计算流行病进展指数(EPI)。我们提取列totale_casi,其中包含自疫情开始以来的新冠肺炎感染总数,以及tamponi,其中包含自疫情开始以来的新冠肺炎拭子总数。我们将 EPI 存储在y变量中。最后,我们打印所有有数据的日期列表(data['data'])。

data = pd.read_csv(“[https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-andamento-nazionale/dpc-covid19-ita-andamento-nazionale.csv](https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-andamento-nazionale/dpc-covid19-ita-andamento-nazionale.csv)") 
tc = data[‘totale_casi’]
tt = data[‘tamponi’]
y = []
tt_increase = []
for i in range(1, len(tt)):
 current_epi = (tc[i] — tc[i-1])/(tt[i]-tt[i-1])*100
 tt_increase.append(tt[i]-tt[i-1])
 y.append(current_epi)
data[‘data’]

现在我们计算有数据的日子。我们可以使用变量data['data']。但是,这个变量是一个字符串,所以很难用它来拟合预测值。因此,我们使用一个通用变量X,它包含一个数字序列,从 1 到样本总数。

X = []
for i in range(1, len(y)+1):
 X.append([i])

初步情节

绘制 EPI 与天数的关系图,以及两条垂直线,分别代表限制法的开始及其效果

现在我们可以绘制 y 对 X,也就是绘制 EPI 对天数。我们还绘制了两条额外的线:1)对应于限制法则开始的日期,2)曲线开始下降的日期(一周后)。这两条线在剧情展示的时候就可以理解了。

在意大利,限制法律始于 3 月 9 日,相当于第 14 天。换句话说,它对应于yX变量中的 14 行。从 3 月 9 日开始的一个星期后,限购令的效果就会显现出来。他们就这样在第 21 天开始了。

# vertical line corresponding to the beginning of restriction laws. 
di = 14
restrictions_x = [di,di,di,di,di,di]
restrictions_y = [0,10,20,30,40,50]# vertical line corresponding to the beginning of effects of restriction laws (after a week)
de = di + 7
effects_x = [de,de,de,de,de,de]
effects_y = [0,10,20,30,40,50]
de

现在我们可以绘制图表。我们可以通过xticks()函数将X值转换成日期。

import matplotlib.pyplot as pltplt.scatter(X, y, color=’black’)
plt.plot(restrictions_x,restrictions_y, color=’red’, linewidth=2)
plt.plot(effects_x,effects_y, color=’green’, linewidth=2)
plt.grid()
plt.xlabel(‘Days’)
plt.xlim(0,40)
plt.ylim(0,50)
plt.xticks([0,5,10,15,20,25,30,35,40],
 [“24 Febr”, “29 Febr”, “5 Mar”, “10 Mar”, “15 Mar”, “20 Mar”, “25 Mar”, “30 Mar”, “4 Apr”])plt.ylabel(‘Epidemics Progression Index (EPI)’)
plt.savefig(“EPI-all.png”)
plt.show()

我们注意到 EPI 从 3 月 16 日开始下降,也就是限制法令颁布后整整一周。因此,我们可以用线性回归来逼近从 3 月 16 日开始的曲线,该曲线递减。

建立模型

建立代表 EPI 的线性回归方程,拟合回归方程并计算分数

我们从sklearn库中导入linear_model。然后我们从 3 月 16 日之前的Xy数据中剔除,并用Xy拟合LinearRegression模型。最后,我们通过score()函数计算模型的得分。

import numpy as np
from sklearn import linear_model
X = X[de:]
y = y[de:]print(X)
# Linear Regression
linear_regr = linear_model.LinearRegression()# Train the model using the training sets
linear_regr.fit(X, y)linear_regr.score(X,y)

预测未来趋势

使用回归变量预测未来趋势。也计算误差

拟合后,我们通过函数predict()建立代表数据的线性曲线,并通过应用于y的真实值和预测值y_pred的函数max_error()计算模型的最大误差。该误差将用于构建两条新的线,最大线和最小线,这两条线将定义新样本移动的范围。

from sklearn.metrics import max_error
import mathy_pred = linear_regr.predict(X)
error = max_error(y, y_pred)
error

现在,我们可以应用该模型来预测未来几天的 EPI。我们构建了一个变量X_test,它包含过去的日子(即数据已经可用的日子)和未来的日子。我们定义包含预测天数的变量gp

然后我们将我们的模型应用到X_test

X_test = []gp = 40for i in range(de, de + gp):
 X_test.append([i])y_pred_linear = linear_regr.predict(X_test)

变量y_pred_linear包含未来几天的预测 IPE。然而,我们也应该考虑模型产生的误差。因此,我们构建两个新变量y_pred_maxy_pred_min,分别包含y_pred + errory_pred - error

y_pred_max = []
y_pred_min = []
for i in range(0, len(y_pred_linear)):
 y_pred_max.append(y_pred_linear[i] + error)
 y_pred_min.append(y_pred_linear[i] — error)

绘图结果

画三条线,分别代表预测的输出,最大误差和最小误差

现在我们准备绘制数据(y_predy_pred_maxy_pred_min)。为了让情节更吸引人,我们应该将数字(由X_test变量表示)转换成日期。因此,我们维护两个变量x_ticksdate_prev,它们分别包含X_test和相应标签的子集..

为了建立x_ticksdate_prev之间的映射,我们从变量data['data']中提取限制的日期,并通过函数datetime.strptime()将其转换为日期。我们将结果存储在变量data_eff中。

我们构建x_ticks,通过对X_test的每一个step物品进行抽样。我们定义date_prev[0] = data_eff。对于每一项,我们可以通过将step添加到前一项来构建date_prev

from datetime import datetime
from datetime import timedeltadata_eff = datetime.strptime(data[‘data’][de], ‘%Y-%m-%dT%H:%M:%S’)
# date previsione
date_prev = []
x_ticks = []
step = 5
data_curr = data_eff
x_current = de
n = int(gp/step)
for i in range(0, n):
 date_prev.append(str(data_curr.day) + “/” + str(data_curr.month))
 x_ticks.append(x_current)
 data_curr = data_curr + timedelta(days=step)
 x_current = x_current + step

现在我们可以画出所有的线。

plt.grid()
plt.scatter(X, y, color=’black’)plt.plot(X_test, y_pred_linear, color=’green’, linewidth=2)
plt.plot(X_test, y_pred_max, color=’red’, linewidth=1, linestyle=’dashed’)
plt.plot(X_test, y_pred_min, color=’red’, linewidth=1, linestyle=’dashed’)plt.xlabel(‘Days’)
plt.xlim(de,de+gp)plt.xticks(x_ticks, date_prev)
plt.ylabel(‘Epidemics Progression Index (EPI)’)
plt.yscale(“log”)plt.savefig(“EPI-prediction.png”)
plt.show()

EPI 的 0 值预测

预测 EPI 何时为 0,即代表 EPI 的线何时穿过 X 轴

首先,我们计算一个辅助函数,它将数字转换为日期。该功能将视为开始日期data_eff

def n_to_date(n):
 return data_eff + timedelta(days=n-de)

现在我们可以计算这条线何时穿过 x 轴。提醒一下,一条线的方程是 y = ax + b,x 轴的方程是 y = 0。因此,我们必须求解包含这两个方程的系统。结果 x = -b/a。

data_zero = round(- linear_regr.intercept_ / linear_regr.coef_[0])
n_to_date(data_zero)

前面的计算只对回归定义的直线进行。现在我们还应该计算y_pred_maxy_pred_min的值。我们定义一个辅助函数,叫做build_line(),从两点构建一条线,返回这条线的系数。

def build_line(x1,y1,x2,y2):
 m = float(y2 — y1)/(x2-x1)
 q = y1 — (m*x1)
 return [m,q]

现在我们可以计算出y_pred_miny_pred_max的结束日期。我们将 max 的零日期近似为获得值的ceil(),将 min 的零日期近似为获得值的floor()

import math
line_max = build_line(X_test[0][0], y_pred_max[0], X_test[1][0], y_pred_max[1])
data_zero_max = math.ceil(- line_max[1] / line_max[0])
n_to_date(data_zero_max)line_min = build_line(X_test[0][0], y_pred_min[0], X_test[1][0], y_pred_min[1])
data_zero_min = math.floor(- line_min[1] / line_min[0])
n_to_date(data_zero_min)

预测一般日期的 EPI 值

通过添加代码来计算一般日期的 EPI 值,从而扩展本教程

我们定义了一个名为date_to_n()的辅助函数,它将一个通用日期转换为自开始日期起的天数。然后,我们将模型应用于获得的值。

def date_to_n(my_date):
 initial_date = datetime.strptime(data[‘data’][0], ‘%Y-%m-%dT%H:%M:%S’)
 return (my_date — initial_date).days + 1my_date = datetime.strptime(“2020–04–05”, ‘%Y-%m-%d’)
n = date_to_n(my_date)
predict = linear_regr.predict([[n]])

预测感染的最大数量

在 EPI 的基础上,用逆方程计算感染总数。情节也是结果

现在我们可以建立感染总数的最大值。我们可以利用 EPI 的公式:y_pred[i] = (tc[i] - tc[i-1])/(tt[i]-tt[i-1])*100来计算tt[i] = y_pred[i]*/(tt[i]-tt[i-1])*100) + tc[i]的值。差值tt[i]-tt[i-1]代表i时刻的拭子数量,因此我们可以将其近似为data['tamponi']的平均值(存储在变量tt_increase中)。或者,我们也可以将差值计算为最小值或最大值。因此,我们计算tt(称为avg_tt)的平均值作为tt_increase[de:]的度量。度量作为函数的参数传递。

def average(mylist):
 return sum(mylist)/len(mylist)# calculate the plateau considering the average increase of swabs
def plateau(y_pred,data_end,metrics):
 avg_tt = metrics(tt_increase[de:])np_avg = []
 #np_start = data[‘totale_casi’][len(data[‘totale_casi’])-1]
 np_start = data[‘totale_casi’][de]
 np_avg.append(np_start)for i in range(0, data_end-de):
 np = y_pred[i]*avg_tt/100 + np_avg[i-1]
 np_avg.append(np)

 last_value = max(np_avg)
 for i in range(0, gp-len(np_avg)):
 np_avg.append(last_value)
 return np_avg

现在,我们可以通过将最大值视为度量来计算y_pred_miny_pred_maxy_pred_linear的平稳状态。

plateau_min = plateau(y_pred_min,data_zero_min, max)
plateau_max = plateau(y_pred_max,data_zero_max, max)
plateau_avg = plateau(y_pred_linear,int(data_zero), max)

最后,我们绘制结果并打印最大值。

plt.plot(X_test,plateau_min, color=’red’, linewidth=1, linestyle=’dashed’)
plt.plot(X_test,plateau_max, color=’red’, linewidth=1, linestyle=’dashed’)
plt.plot(X_test,plateau_avg, color=’green’, linewidth=2)
plt.scatter(X,tc[de+1:], color=’black’, linewidth=2)
plt.xlabel(‘Days’)
plt.xlim(de,de+gp)
#plt.ylim(0,50)
plt.xticks(x_ticks, date_prev)
#plt.yticks([0,20,30,40,50,60])plt.ylabel(‘Total number of positives’)
plt.grid()
plt.show()

吸取的教训

本教程描述了一个简单的方法来建立一个预测意大利新冠肺炎流行病的结束。从本教程中,我们了解到:

  • 在构建预测器之前,必须进行初步的数据探索。事实上,如果我们在所有可用数据上建立预测器(即从 2 月 24 日开始),我们就不会使用线性回归来建立它;
  • 预测器的建立还应考虑到现实生活(在我们的案例中,是意大利政府引入的限制法及其一周后的效果);
  • 一旦建立了预测器,也应该考虑误差。因此,必须计算误差范围,以便有更准确的预测;
  • 真实(新)数据和预测值之间的比较总是受欢迎的,因为它允许您验证模型是否正确。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

Python 中的迭代器和迭代器

原文:https://towardsdatascience.com/iterables-and-iterators-in-python-849b1556ce27?source=collection_archive---------17-----------------------

Python 中的可迭代对象、迭代器和迭代

凯文·Ku 在 Unsplash 上的照片

在本文中,我们将学习迭代、可迭代和迭代器之间的区别,如何识别可迭代和迭代器,以及为什么这样做是有用的。

什么是可迭代的?

广义地说,iterable 是可以循环的东西。循环遍历某物,或者一个接一个地获取其中的每一项的过程,就是迭代。例如,当我们使用 For 循环来循环遍历一个列表时,循环遍历这个列表的过程就是迭代(或者我们正在迭代遍历这个列表),这个列表就是 iterable。元组、字典、字符串、文件和生成器也是可迭代的,因为它们也可以被迭代。

例如,我们可以使用 For 循环来循环或迭代列表,如下所示:

num_list = [1,2,3,4,5]for num in num_list:
    print(num)

但是是什么让一个东西成为可重复的呢?

换句话说,是什么使得某些东西能够被迭代,比如在 for 循环中?要成为可迭代的,一个对象将有一个 iter()方法。因此,如果一个对象有 iter()方法,那么它就是 iterable,因此我们可以使用 for 循环来遍历它。

从技术上来说,如果一个对象有 getitem()方法,它也可以是 iterable。然而,我们在这里将关注 iter()方法,因为它是 python 中迭代的较新协议。

如果我们在 num_list 上使用 dir()函数,它将显示列表对象的所有方法和属性:

列表对象的方法和属性

注意列表对象 num_list 有一个 iter()方法,这使它成为可迭代的。具有双前导和双尾随下划线的方法因此被称为 dunder 方法(也称为魔术方法或特殊方法)。这些方法旨在被间接调用,因为大多数 python 操作符都有相关的魔法方法。

那么这个 iter()方法是做什么的呢?

iter()方法将返回一个迭代器对象。要循环遍历一个 iterable,比如一个 list,我们通常不会手动这么做。例如,For 循环首先调用对象上的 iter()方法,该方法返回一个迭代器对象。然后 for 循环遍历这个迭代器。所有这些都是在后台完成的。

这就把我们带到了迭代器。

[## Python 中的列表理解

用 python 创建列表的更优雅、更简洁的方式

towardsdatascience.com](/list-comprehensions-in-python-28d54c9286ca)

什么是迭代器?

列表是可迭代的。但它不是迭代器。如果我们在列表上运行 iter()方法,它将返回一个迭代器。迭代器是一个对象,它有一个在迭代过程中记得自己位置的状态。迭代器也知道如何获得它们的下一个值。它们通过 next()方法获得下一个值。因此,要知道一个对象是否是迭代器,我们可以检查它是否有 next()方法。

我们可以先调用 num_list 上的 iter()函数(iter()函数调用传入的对象上的 iter()方法),返回一个迭代器,然后我们将在迭代器上使用 dir()函数查看其属性和方法:

迭代器的方法和属性

注意我们的迭代器 num_list_iterator 有一个 next()方法。列表对象不是迭代器,因为它没有 next()方法。因此,在列表上调用 next()函数(如果有对象的话,它会在对象上调用 next()方法)会导致类型错误,因为我们的列表对象不是迭代器,因此没有 next()方法。但是,list 对象是可迭代的,因为它有一个 iter()方法,调用该方法时,返回一个迭代器,该迭代器将有一个 next()方法。

注意 num_list_iterator 也有一个 iter()方法。因此,迭代器也是可迭代的,或自迭代的,因为在迭代器上调用 iter()方法会返回 self。

下一个方法是做什么的?

在迭代器上调用 next()方法将返回迭代中的下一个值。因此,在我们从 num_listnum_list_iterator 创建的迭代器上调用 next()方法,将返回迭代器中的第一个值。在同一个迭代器上调用 next()方法将返回迭代器中的第二个值(记住迭代器有一个状态,它能记住它在迭代过程中的位置)。一旦我们遍历了迭代器的所有值,在迭代器上再次调用 next()方法将导致 StopIteration 错误,因为我们的迭代器现在已经用完了。一旦一个迭代器用完了,我们必须通过 iterable 的 iter()方法创建一个新的迭代器。

注意:迭代器只能向前。这意味着我们只能通过 next()方法获得迭代器中的下一个值。为了从头开始,我们必须通过在我们想要迭代的 iterable 上调用 iter()方法来创建一个新的 iterator 对象。

[## * Python 中的 args 和**kwargs

理解什么是*args 和**kwargs 以及如何使用它们

towardsdatascience.com](/args-and-kwargs-in-python-6d991a3c1b5e)

for 循环是如何工作的?

for 循环的工作原理是在后台执行上述操作。使用 for 循环遍历 list(或其他 iterable)首先通过 iter()方法创建一个迭代器对象,然后调用该迭代器上的 next()方法,返回值,直到返回 StopIteration 错误(它没有向我们显示),这让它知道迭代器已经用尽,因为迭代器中没有更多的值了。这可以从下面看出:

在 for 循环的背景中

请注意,我们可以使用内置的 iter()和 next()函数,而不是键入 dunder 方法,这些函数为我们调用 iter()和 next()方法。但是,我们也可以像下面这样调用方法:

num_list.__iter__()num_list_iterator.__next__()

如果您熟悉 while 循环和 try/except 语句,那么上面的 for 循环类似于下面的 while 循环:

类似于 while 循环和 for 循环

为什么知道这些很有用?

在用 python 编码时,知道一个对象是可迭代的(还是可被迭代的)会非常有帮助。例如,知道一个对象是否是 iterable 将告诉我们一个对象是否可以在 For 循环中使用。

在上面的例子中,我们使用了一个 for 循环来遍历 num_list ,这是一个从 1 开始到 5 结束的整数列表,即[1,2,3,4,5]。好吧,不像上面那样创建 num_list 并遍历它,我们可以检查一下是否可以使用 range()函数来创建一个 range 对象,我们可以使用 for 循环来遍历它,给我们相同的数字序列来迭代:

range 对象的方法和属性

正如我们所看到的,range 对象是一个可迭代的对象,因为它有 iter()方法!因此,可以使用 for 循环对其进行迭代,因为 for 循环将首先创建迭代器对象,然后使用 next()方法对该迭代器对象进行迭代。

for num in range(1,6):
    print(num)

如果你喜欢阅读这样的故事,并想支持我成为一名作家,考虑注册成为一名媒体成员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你用我的 链接 注册,我会赚一小笔佣金。

[## 通过我的推荐链接加入媒体——卢艾·马塔尔卡

阅读卢艾·马塔尔卡的每一个故事(以及媒体上成千上万的其他作家)。您的会员费直接支持…

lmatalka90.medium.com](https://lmatalka90.medium.com/membership)

结论

在本教程中,我们讨论了迭代、可迭代对象和迭代器的含义。我们了解了 iterable 是一个具有 iter()方法的对象,该方法将创建一个迭代器对象。我们还了解到迭代器是一个对象,它有一个在迭代过程中记得它在哪里的状态,并且知道如何通过 next()方法获得下一个值。最后,我们看到了将一个对象标识为 iterable 是如何帮助我们编写更多 pythonic 代码的。

高效迭代您的 R 代码!

原文:https://towardsdatascience.com/iterate-your-r-code-efficiently-3c621998eaea?source=collection_archive---------10-----------------------

在 r 中执行干净有效的迭代的一步一步的指南。

因纽特人实际上并没有一百个关于雪的名字。原来这是部分神话和部分误解。将类似的类比扩展到 web speak,大约有一百种迭代代码的方法!除此之外,语法可能会令人困惑,我们中的一些人还会冒险懒散地求助于复制粘贴代码 4 次。但重要的是要认识到,这是一条次优路线,坦率地说不切实际。根据一般经验,如果我们需要运行一个代码块两次以上,迭代是一个好主意!这有两个原因可以让你的代码更加丰富

  1. 它将注意力吸引到不同的代码部分,从而更容易发现操作的意图。
  2. 由于其简洁的本质,您可能会遇到更少的错误。

可能需要一些时间来理解迭代的概念,但是相信我,这是值得的。

既然你已经被说服去迭代——让我们直接开始吧!

让我们挑选内置的 R 数据集- 空气质量。以下是其中的一个片段-

 Ozone Solar.R  Wind Temp Month Day
    41     190    7.4   67     5   1
    36     118    8.0   72     5   2
    12     149   12.6   74     5   3
    18     313   11.5   62     5   4
    23     299    8.6   65     5   7
    19      99   13.8   59     5   8

问题 1 :你想求数据集中每个变量的标准差-

你可以为每一列复制粘贴相同的代码

sd(airquality$Ozone)
 *33.27597*sd(airquality$Solar.R)
*91.1523*sd(airquality$Wind)
*3.557713*sd(airquality$Temp)
*9.529969*sd(airquality$Month)
*1.473434*sd(airquality$Day)
*8.707194*

然而,这对于大型数据集来说是不切实际的,并且打破了相同操作不运行两次以上的经验法则。我们有一个坚实的案例来迭代!

我们可以写一个for()循环-

stddev = vector("double", ncol(airquality))for(i in seq_along(airquality))             
{
 stddev[[i]] = sd(airquality[[i]])          

}
stddev
*33.275969 91.152302  3.557713  9.529969  1.473434  8.707194*

该循环消除了任何重复,确实比第一种方法更有效。

还必须暂停一下,注意虽然seq_along()length()在 for 循环中通常交替使用来构建序列,但是有一个关键的区别。在零长度向量的情况下,seq_along()做正确的事情,但是length()取 0 和 1 的值。虽然您可能不会故意创建零长度向量,但很容易意外地创建它们。如果你使用1:length()而不是seq_along(),你可能会得到一个令人困惑的错误信息

或者你可以跳过循环,用只用一行来自 base R 的apply()系列的sapply()代码来完成这个技巧

sapply(airquality, sd) Ozone      Solar.R      Wind      Temp     Month     Day 
*33.275969 91.152302  3.557713  9.529969  1.473434  8.707194*

这是对 R 函数式编程能力的一个很好的应用,确实非常灵活地完成了工作。

现在让我们在复杂性的阶梯上再跨一步,看看另一个问题。

问题 2 :你想求出你的数据集中每一列的标准差中位数。

因为我们已经确定第一种方法复制粘贴是不切实际的,我们权衡我们的迭代选项。

我们从编写一个for()循环开始-

stddev =vector("double", ncol(airquality))
 median =vector("double", ncol(airquality))for(i in seq_along(airquality))
 {
   stddev[[i]] = sd(airquality[[i]])
   median[[i]] = median(airquality[[i]])
  } stddev
 33.275969 91.152302  3.557713  9.529969  1.473434  8.707194
 median
 31.0 207.0   9.7  79.0   7.0  16.0

接下来,我们走函数式编程路线。这里,不像前面的例子,我们可以直接使用 R 的内置sd()函数来计算标准偏差并通过sapply()传递,我们需要创建一个自定义函数,因为我们需要计算标准偏差和中位数。

f <- function(x){
    list(sd(x),median(x))
 }sapply(airquality, f)Ozone    Solar.R Wind     Temp     Month    Day     
33.27597 91.1523 3.557713 9.529969 1.473434 8.707194
31       207     9.7      79       7        16

这是一个非常坚实的想法!将用户构建的函数传递给另一个函数的能力令人激动,并且清楚地展示了 R 解决各种任务的函数式编程能力。事实上,经验丰富的 R 用户很少使用循环,而是求助于函数式编程技术来解决所有的迭代任务。如上所述,在 base R 中应用函数族(apply()lapply()tapply()等)是一种很好的方式,但是即使在函数式编程领域,也有一个包成为了人们的最爱——Purrrpurrr 系列函数具有更加一致的语法,并且内置了执行各种常见迭代任务的功能。

Map() 函数构成了 purrr 迭代能力的基础。这是它的一些表现形式-

  • map()列清单。
  • map_lgl()做一个逻辑向量。
  • map_int()生成一个整数向量。
  • map_dbl()生成双向量。
  • map_chr()生成一个字符向量。

让我们用这个想法来解决我们之前计算每一列的中值和标准差的问题-

map_df(airquality, ~list(med = median(.x), sd = sd(.x)))

接下来,为了在复杂性阶梯上的另一个飞跃,让我们从 gapminder中挑选 gapminder 数据集。下面是其中的一个片段。(注:如果你没有听说过 gapminder 基金会,请点击这里查看它的网站。该基金会在将基本的全球事实放入背景中做了一些开创性的工作)

 country   continent year lifeExp  pop  gdpPercap
  Afghanistan Asia     1952   28.8  8425333  779.
  Afghanistan Asia     1957   30.3  9240934  821.
  Afghanistan Asia     1962   32.0  10267083 853.
  Afghanistan Asia     1967   34.0  11537966 836.
  Afghanistan Asia     1972   36.1  13079460 740.
  Afghanistan Asia     1977   38.4  14880372 786.

问题三:我想知道各大洲,各年份,哪个国家的人均 GDP 最高?

使用for()循环方法-

list = c(“continent”, “year”)
DF= data.frame()for( i in list)
{
 df = gapminder %>% group_by_at(i) %>% 
 top_n(1, gdpPercap) %>% 
 mutate(Remark = paste0(“Country Max GDP Per capita in the “,i)) %>% 
 data.frame()
 DF = rbind(df,DF)
}
DF

使用Apply()方法-

do.call(rbind, lapply(list, function(x)
{
  gapminder %>% group_by_at(x) %>% 
    top_n(1, gdpPercap)%>%
    mutate(Remark = paste0("Country with the max GDP Per capita in the ",x)) %>% 
    data.frame
}))

使用Purrr::Map()方法-

gapminder$year = as.character(gapminder$year)
map_dfr(list, ~gapminder %>% group_by(!!sym(.x)) %>% 
 top_n(1, gdpPercap)%>%
 mutate(Remark = paste0(“Country with the max GDP Per capita in the “,.x)) %>% data.frame()

以上三种方法都产生相同的输出(为了简洁起见,我没有在这里包括输出。你可以在我的 Github 这里看看。同样,虽然您可以选择想要采用的迭代路线,但是函数式编程方式在 cogency 方面是明显的赢家。

Purrr 也有一些处理日常迭代任务的内置函数!下面我列出了几个受欢迎的。

任务 :对每一段数据进行分段回归。(这里,大陆):

Purrr 解决方案 :

gapminder %>% 
 split(.$Continent) %>% 
 map(~lm(gdpPercap ~ lifeExp, data = .))

任务:保持变量基于任意条件。(此处,如果变量是因子):

:

*gapminder %>% 
  keep(is.factor) %>% 
  str()*

任务:检查任意变量是否满足任意条件(此处,任意变量是否为字符):

Purrr 解决方案:

*gapminder%>% 
  some(is_character)*

任务:检查每个变量是否满足任意条件(这里,如果每个变量都是整数):

Purrr 解决方案:

*gapminder %>% 
  every(is.integer))*

一旦你习惯了 purrr 的语法,你将需要更少的时间来用 r 编写迭代代码。然而,你绝不能因为用 r 编写循环而感觉不好。事实上,它们是编程的基本模块之一,并且在其他语言中被大量使用。有些人甚至称循环为慢。他们错了!(好吧至少它们已经相当过时了,至于 loops 已经很多年没慢过了)。使用像map()apply()这样的函数的主要好处不是速度,而是清晰:它们使你的代码更容易编写和阅读。

重要的是你要解决你正在处理的问题,而不是写出最简洁优雅的代码(尽管那绝对是你想要努力的方向!)——哈德利·韦翰

感谢阅读!你可以在我的 Github 这里查看代码,或者在这里联系我

Python 中的迭代器和可迭代对象

原文:https://towardsdatascience.com/iterators-iterables-in-python-e713a55dfe1f?source=collection_archive---------22-----------------------

迭代器和可迭代对象简介

来源

在这篇文章中,我们将讨论 python 迭代器和可迭代对象。我们将回顾每个对象的定义,并努力理解每个对象背后的基本概念。

我们开始吧!

Iterables 是 python 中能够一次返回一个元素的对象。此外,这些对象有一个名为“iter()”的双下划线(也称为 dunder )方法,其中“iter()”方法返回一个迭代器(稍后将详细介绍)。列表就是 iterable 的一个例子。为了帮助我们理解列表作为可迭代对象意味着什么,让我们定义一个列表。让我们根据 滚石 : 来定义一个包含有史以来最好的五张专辑的列表

best_albums = ["Sgt. Pepper’s Lonely Hearts Club Band", "Pet Sounds", "Revolver", "Highway 61 Revisited",  "Rubber Soul"]

我们对 iterables 定义的第一部分指出,它们允许我们一个接一个地返回它们的元素。让我们通过循环我们的列表来演示这一点:

for album in best_albums:
    print(album)

iterables 的这个特性非常明显。我们还指定了“iter()”方法,该方法也将 python 对象限定为可迭代对象。我们可以使用内置的“dir()”方法检查对象可用的方法和属性:

print(dir(best_albums))

我们可以看到“iter()”方法出现在对象的方法和属性列表中。一般来说,任何带有“iter()”方法的对象都可以循环。

此外,当我们在 iterables 上使用 for 循环时,我们调用“iter()”方法。当调用“iter()”方法时,它返回一个迭代器。

现在,让我们定义迭代器。

迭代器是有状态的对象,其中状态指定迭代期间的当前值。迭代器还有一个名为“next()”的 dunder 方法,允许我们访问后续值。如果我们查看列表的属性和方法,我们可以看到没有' next()',这意味着列表不是迭代器。

我们可以通过尝试使用列表中的“下一个”方法来证明这一点:

print(next(best_albums))

我们得到一个错误,告诉我们列表对象不是迭代器。因为我们知道列表对象是可迭代的,这意味着它们有“iter()”方法,所以我们可以在列表上调用“iter()”来返回一个迭代器:

iter_best_albums = best_albums.__iter__()

定义迭代器的一种更简洁的等效方法如下:

iter_best_albums = iter(best_albums)

让我们打印我们的迭代器:

print(iter_best_albums)

我们看到我们的对象确实是一个迭代器。现在,让我们打印迭代器对象的属性和方法:

print(dir(iter_best_albums))

我们可以看到我们的迭代器对象有“next()”方法。让我们在迭代器上调用这个方法:

print(next(iter_best_albums))
print(next(iter_best_albums))
print(next(iter_best_albums))

我们可以看到,每次我们调用“next”时,我们的对象会记住它停止的地方,“next”方法会指向后续的值。让我们看看如果我们调用' next '直到用完所有值会发生什么。我们再打 6 次电话:

print(next(iter_best_albums))
print(next(iter_best_albums))
print(next(iter_best_albums))
print(next(iter_best_albums))
print(next(iter_best_albums))
print(next(iter_best_albums))

我们可以用“StopIteration”异常来处理此错误:

while True:
    try:
        element = next(iter_best_albums)
        print(element)
    except(StopIteration):
        break

我们得到的结果和之前循环链表得到的结果是一样的。当我们用 for 循环遍历列表时,这就是本质上发生的事情。

我就讲到这里,但是您可以自己随意摆弄代码。如果你有兴趣学习更多关于迭代器和可迭代对象的知识,科里·斯查费的 YouTube 教程是一个很好的资源。

结论

总之,在这篇文章中,我们讨论了 python 中的迭代和迭代器。Iterables 是具有方法“iter()”的对象,该方法返回迭代器对象。迭代器是具有方法' next() '的对象,该方法允许我们访问后续值。此外,迭代器有关于迭代过程中状态的信息。简而言之,迭代器是 python 中每个 for 循环背后发生的事情。我希望你觉得这有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

这是官方说法:时间不存在

原文:https://towardsdatascience.com/its-official-time-doesn-t-exist-8c786530eca1?source=collection_archive---------1-----------------------

来源: Pixabay at Pexels —免费源图像

那么我们应该为 ML 模型提供什么样的时间特性呢?

重要的 】:有些人离开文章时以为是关于物理的。如果您只对 ML 中关于如何处理时间特征的部分感兴趣,请随意跳过故事的第一部分,直接进入' 处理我们数据集 中的时间特征。

12 月,我和女友回到了乌拉圭和阿根廷,我们来自那里。在那边,她的祖父,一个我个人觉得很迷人的人,向我推荐了一本书,告诉我这是他一生中读过的最难的书之一。让我解释一下:我们在谈论一个同时阅读两到三本书的超级聪明的人。他自己读的书可能比我们想象的要多。但事情并没有就此结束:在我们离开之前,他给我买了这本书,所以我在圣诞节前后离开了布宜诺斯艾利斯,手里拿着一本大约 150 页的书,书名是《时间的顺序》,作者是意大利物理学家卡尔罗·罗威利。

他让我一读完这本书就给他提意见,所以我就有意识地读了。我确保我已经理解了每一章,并且我突出了所有的书,以便在我读完之后再读一遍最重要的部分。我并不羞于大声说我不得不至少读两遍所有的章节来理解它们。这本书一开始就说,如果两个双胞胎兄弟十年后再次相遇,一个住在山里,另一个住在平原上,前者会更老,因为时间在山里过得更快,在平原上过得更慢。我的朋友们,这可不是童话:在离地心越近的地方,时间确实走得越慢。

简而言之,这本书解释了我们所知道的时间和我们已经学会理解的时间是不存在的。什么是真正的时间。从一个从大学生开始就研究这个课题的专业人士那里读到这一切,让我思考了很多东西。我不会用自我反省之类的想法来烦你,但这本书也让我想到了我们通常在机器学习和数据科学中使用时间的人。因为在他的书里,卡罗说时间本身什么都不是。我们所感知的时间是人类发明的,用来测量地球绕太阳一周需要多少时间。这种测量是通过我们发明的度量来完成的,比如秒、毫秒、小时、分钟等等。

鉴于此,对于一个不知道“分”或“秒”是什么概念,不知道今天是什么日子,更糟糕的是,不知道什么是“日”或“月”的人来说,说现在是晚上 22:48 根本不能说明什么。我知道你在想什么:那种人根本不存在。好吧,即使这是真的,猜猜谁不知道这些:你的机器学习算法。因此,我们处理时间数据并将其输入模型的方式是关键。

对于所有好奇的人来说,首先我要花几段时间对这本书做一个总结。如果你有足够的兴趣,请继续阅读。否则,你可以跳过它。然而,如果你读了它,你想了解更多,这是卡尔罗·罗威利 8 年前的 Ted 演讲,这本书在亚马逊只有大约 6 磅。

正如我之前所说,这本书指出我们所知的时间概念并不存在。我们用来衡量它的标准。它们不存在,因为在物理世界里它们不存在。世界的基本方程没有时间变量。确实存在的是一个物理时间,它的流逝不是均匀的,而是取决于许多因素。

这个物理时间似乎不是一个连续的时间,而是一个颗粒时间,在两个值之间跳跃,而不是流逝。一个特定值下的时间概念并不存在于它更基本的时间概念中。根据对物理时间的理解,在微观层面上,时间是由碰撞的原子组成的。分散在概率云中的原子,我们没有精确的方法知道它们会出现在哪里。它们出现了,并在概率足够高的地方发生碰撞。但是当它真的发生时,宇宙的那一部分会从某种特定的基本结构变成更复杂的结构。然而,这些允许那种微观事件的特殊结构,明确地依赖于我们对世界的模糊或未聚焦的视觉。但是这种不集中的视觉并不依赖于我们可能有的一些精神感知,相反,它是一种相对的属性。它是一个对象相对于另一个对象的属性。时间性的概念与这个模糊或不清晰的世界紧密相连,我们忽略了它最微观的细节。因此,这个物理时间最终是我们对世界无知的表现。

关于最后一个观点,理解它很有帮助,这一章谈到了一个事实,即猫不是宇宙元素的一部分。比这更复杂的东西,不断出现在我们星球的几个地方。同样的,在山顶,我们看到一个被蓝色的白云覆盖的山谷。如果我们爬山,当我们爬山时,云不再是白色的;我们发现自己在雾中。但这种变化不是瞬间的,而是渐进的。任何表面都会发生同样的情况。如果我们能把自己变得足够小,大理石桌子看起来就会像雾一样。在这些例子中,一个真实的东西出现了,一些我们能看到甚至有时能触摸到的东西。他们来自一个最基本的没有猫的世界。同理,时间产生于一个没有时间的世界。

这本书说,没有时间的世界只不过是一个相互关联的事件网络。没有时间并不意味着它是静止不动的。这意味着事情的发生不是按照线性时间线来排序的。如果到了时间,我们只理解发生的事情,那么一切都是时间。但同时,以我的理解,没有什么是太。或者至少,没有什么是过去,也没有什么是未来。在一个比我们所知和理解的要大得多的宇宙中,我们只是相互关联的事件中的一小部分。

我们所理解的过去和未来就在我们自己心中。我们是生活在我们大脑中的故事。从原子不断碰撞的足迹中画出的线条。允许我们预测未来事件的线。举个例子,一个扔给我的球朝哪个方向去,如何移动我们的手去抓住它。这个空间,我们的记忆,以及持续不断的预期实践,是我们对时间和自身感知的来源。

处理数据集中的时间要素

现在,正如我之前所说的,除了所有的自我反思和深刻的想法,所有这些都可以引发,让我们把它带到机器学习的世界。我们确实有预测事物的记忆,比如上面那个球的例子。我们确实知道一月之后是二月,去年是 2019 年,或者晚上 23:59 之后是哪一分钟。此外,就行业而言,我们的记忆让我们知道,例如,春天过后就是夏天,如果我在一家销售啤酒的公司工作,夏天对我们来说可能是一个季节,因此,我们应该会看到销售额的增长。在我工作的 Ravelin,我们可能知道对于某些行业来说,一天中的某些时间比其他时间更具欺骗性。然而,我们的机器学习模型并不知道所有这些。即使我们以一种一次性编码的方式输入一年中的月份,算法也不知道 12 月之后是 1 月。或者午夜过后,整点又从零开始。

那么我们应该如何对待时间戳呢?嗯,正如我不久前在一个 Stackoverflow 问题中读到的:

你并没有真正使用时间戳作为特征,因为它们在对看不见的数据进行分类时没有用。想象一下,用 2018 年获得的数据训练一个模型,并尝试对 2019 年的数据进行分类。信息不在日期上,而在其他特性的值上!

你能看出卡洛在他的书里所说的相似之处吗?在现实生活中,时间本身只不过是我们记忆中可能存在的给它提供上下文的参考,我们的机器学习模型也是如此。我们的时间特征只有在与一些其他日期相关时才有价值,这些日期可能与我们试图预测的任何事情相关。

根据这一点,以下值对于机器学习模型没有任何意义:

  • 日期时间如:2019–12–24t 10:25:11.577 z,
  • 或者像 1578830817 这样的时间戳

我们如何将这转化为对我们的算法有用的东西?首先,我们可以做一些简单的转换,让我们的模型更好地参考如何比较不同日期或时间戳发生的行或事件。例如,我们可以获得:

  • 一年中的某月
  • 一年中的某一天
  • 一周中的某一天
  • 一天中的某个小时
  • 一天中的分钟
  • 小时分钟

Pandas 为我们提供了一个整洁的表格,其中包含许多选项,来自于其关于时间序列/日期功能的文档:

通过这样做,我们的模型将知道八月,一年中的第八个月,在七月之后九月之前。或者在 2020 年,5 月 9 日在 1 月 30 日之后 100 天,8 月 17 日之前 100 天。

我们甚至可以更进一步,做一些其他种类的事情。例如,我们可能知道圣诞节对我们的业务来说是一个合理的日期,事实上,我们的模型本身甚至可以发现像“2019–12–24 08:57:04.927”这样的日期在预测时会发生一些特殊/怪异/奇特的事情。但是,模型如何知道某个其他日期时间恰好在该日期时间的一天或二十四小时之后?我们需要让算法更容易理解这一点。为此,我们可以设置如下功能:

  • 是圣诞节吗
  • 自圣诞节以来的天数
  • 圣诞节以来的几周

或者,如果我们是一家在线快递公司,并且我们知道我们一周中销售最强劲的时刻是周五晚上 20:30,我们可以创建如下功能:

  • 离高峰还有几分钟
  • 自高峰以来的分钟数

再一次,我们试图给我们的机器学习模型同样的背景,这要归功于我们的记忆和我们对时间的理解。然而,我知道你可能会想:好吧,酷,但是一旦我创建了这些特性,我该如何处理它们呢?因为我们会把时间戳转换成分类特征。因为我们在我之前的一个关于分类变量编码的故事中提到过,如果我们没有正确地处理这种特征,一些算法就不会特别喜欢处理这种特征。那我们该怎么办?

嗯,如前所述,我们不想做任何一次性编码或类似转换。如果我们这样做,我们将会失去特征连续性的任何价值。换句话说,该模型将停止识别诸如一年中的第六个月,即 6 月,在 5 月之后 7 月之前这样的事情。然而,让它们保持原样提出了另一个挑战:模型如何知道一旦 12 月结束,1 月又来了?或者在一天的第 23 个小时之后,它又从零开始了?

幸运的是,有一个非常简单的方法来解决这个问题:我们可以使用正弦和余弦变换,将每个变量转换为二维特征。我们来看一个例子。

假设您有一个包含“OriginalClientEventTime”功能的数据集。首先,您希望将特征的类型转换为熊猫日期时间,以便随后获得一天中的小时。您可以这样做:

train[‘OriginalClientEventTime’] = pd.to_datetime(train[‘OriginalClientEventTime’])train[‘hour’] = [x.hour for x in train[‘OriginalClientEventTime’]]

以类似的方式,您可以从 Panda 关于时间序列/日期功能的文档中获得上表中列出的任何属性。

一旦我们这样做了,这些功能将如下所示:

现在我们有了一天中的时间,我们可以将它转换成二维特征,以便模型能够获得原始的性质。我们只用两行代码就可以轻松做到这一点:

import numpy as nptrain[‘sin_hour’] = np.sin(2*np.pi*train.hour/24)train[‘cos_hour’] = np.cos(2*np.pi*train.hour/24)

这是我们的数据集现在使用新功能的情况:

train[[' originalclienteventime ',' hour ',' sin_hour ',' cos_hour']]

如果我们单独绘制正弦或余弦特征,我们不会注意到太多,但这是因为我们需要两个变量来捕捉特征的适当性质。现在看看当我们在 Y 轴和 X 轴上同时绘制两个特征时会发生什么:

train.plot.scatter(‘sin_hour’,’cos_hour’)

整洁,对不对?我们所知道的时间行为似乎反映在一个完美的圆圈中,这个圆圈在一天中的小时值之间循环。我们可以对任何其他时间特性做同样的事情!一年中的月份、一天中的分钟、一年中的某一天、圣诞节前的天数等。

正如我在评论罗维利的书时告诉我女朋友的祖父的那样,书中肯定有很多我不理解的东西。但我确实明白,如果我们能以某种方式记住过去的事情,并预测未来的事情,比如我应该把手移到哪里才能接住别人扔给我的球,这要归功于我们的记忆和我们建立的时间概念。一个由度量组成的时间概念,仅描述事件之间的距离,例如地球绕太阳旋转一周需要多长时间(顺便说一下,是 365.256 天)。

因此,如果我们想让我们的机器学习模型真正学习,让我们试着教它们我们自己随着时间的推移学到的东西。

好了,今天就到这里。请继续关注未来的故事,了解处理分类特征的其他技术。同时,这一年刚刚开始,你会在 2020 年找工作吗?好吧,那么你不能错过我关于获得第一份数据工作的实用技巧的故事。或者你还在寻找给自己的完美圣诞礼物?那就来看看这个关于的故事 9 本数据科学相关书籍来读读。如果这些都不是你的情况,请随时访问我在 Medium 上的个人资料,查看我的任何其他故事。

还有如果你想直接在你的邮箱里收到我的最新文章,只需 订阅我的简讯 😃

回头见!感谢您的阅读!

不是数据科学家也没关系

原文:https://towardsdatascience.com/its-okay-to-not-be-a-data-scientist-e57b8800e62c?source=collection_archive---------59-----------------------

似乎每个人都想成为数据科学家——在数据领域,有其他途径可以成就伟大的事业

卢卡斯·布拉塞克在 Unsplash 上的照片

在过去的几年里,成为一名数据科学家被大肆宣传。Glassdoor 连续三年将它列为美国第一最好的工作,并且不难发现博客帖子谈论成为一名数据科学家有多棒。因此,毫不奇怪,主要数据科学分支似乎主要是人们询问如何成为数据科学家的建议,而不是关于数据科学的建议。

对于我看到的(以及之前给出的)许多建议,我一直感到很矛盾,我担心这些建议会对人们造成伤害。外面的许多建议(以及某些在线课程/训练营的广告)听起来好像成为一名数据科学家唯一需要的是一些技术技能,所以毫不奇怪会有像这样的问题问为什么数据分析师和数据科学家之间的工资差距如此之大,如果他们需要的技术技能列表是相同的。

为什么不是每个人都是数据科学家?

事实是,作为一名数据科学家,除了学习如何导入 sklearn,还有更多事情要做。我必须小心行事。我不想被视为看门人。但我认为,任何人都可以做一个机器学习项目,并将其放在 github 上,以获得一份 6 位数收入的工作,这一想法需要一些现实检查。

根据 2017 Burtch Works 的《数据科学家的薪水》报告,约 90%的数据科学家拥有高等学位(约 40%为博士,~50%为硕士)。在这 10%没有研究生学位的人中,我的猜测(我没有这方面的统计数据)是大多数人都有相当高水平的数据分析或软件工程方面的丰富经验。

研究生学历比例大是有原因的。定量学科的研究生学位(尤其是博士学位)表明一个人在探索抽象概念、发展统计关系的直觉、设计检验假设的方法、将数据转化为故事、交流复杂结果等方面有一定的经验。学习 Python 以及如何在 Pandas 中处理数据和在 sklearn 中建立模型可能只需要几个月的时间,但这只是表面的东西。现实世界很复杂,需要你在数学背后有一种直觉,明白什么可行,什么不可行,以及如何证明它可行或不可行。

我并不是说数据科学家需要博士学位——这在经验上是错误的(毕竟 60%的人不需要)。成为数据科学家有许多不同的途径。但是这条路并不容易走。

关于所有这些数据科学训练营和在线课程,要认识到的一点是:对于大多数在他们之后获得数据科学家工作的人来说,他们在这些课程中学到的技能只是锦上添花。如果你有一个定量的博士学位,或者大量的软件工程经验,或者作为一名数据分析师与数据科学家密切合作多年,也许你所需要的只是一个学习如何使用几个 Python 包的短期课程,这样你就有竞争力了。如果你没有,很可能你成为数据科学家的路会更长。

你不一定要成为数据科学家

获得新的技能很有趣,而且可能对你的职业有好处,不管你最终获得什么头衔。学习能让你做喜欢的事情的技能是值得的。如果你目前不是一名分析专家,在线学习或参加数据科学课程肯定有助于获得第一个数据分析师职位。也许如果你是一名目前在高层工作的数据分析师,学习其中的一些技能并将其融入到你的工作中,最终可能会让你在未来获得数据科学的职位。

但是“向上”的方法不止一种。成为一名数据科学家不一定是你的目标。你可以最终走上管理轨道,并最终领导一个数据分析师团队。这可能会导致管理一个大型数据分析团队,甚至有一天成为首席分析官。我的观点是,很多人对“数据科学家”这个头衔有点太着迷了。这是一份好工作,但我认为人们高估了它,低估了它的预期经验水平。有很多很棒的分析工作(也有很多很棒的非分析工作),我认为让一些人把目光从闪亮的、被夸大的“数据科学家”头衔上移开,更客观地判断他们的选择会有好处。

是时候为“冲击美国”做好准备了——全面审视新冠肺炎的数据显示,我们目前的措施是不够的

原文:https://towardsdatascience.com/its-time-to-brace-for-impact-america-a-comprehensive-look-at-covid-19-in-italy-new-york-china-9e899464ef9?source=collection_archive---------23-----------------------

来自意大利、中国湖北省和韩国疫情的数据显示,从实施强有力的抑制措施开始,每天的新增病例数大约需要 11 到 12 天才能达到峰值,然后下降。在每日新增病例达到峰值后,大约需要 2 周时间才能看到活跃病例数达到峰值,然后开始下降。翻译一下——“使曲线变平”需要大约 26 天的时间,在实施严格和全面的措施阻止传播之前,第一天不会开始——我不是在说洗手和站在 6 英尺远的地方。在我们准备好启动并充分利用全球正在使用的两个选项之一(严格封锁,或积极检测和追踪)之前,美国人应该准备好看到病例继续增长。人口越密集的地区——T4 的增长可能越快。在这一后期阶段,许多州可能没有时间让医院做好充分准备,或采购拯救生命和避免第一波疫情中医疗配给所需的救生保护装置和设备。

让我们看看数据,好吗?

意大利新冠肺炎 2 月 20 日至 3 月 23 日的新增和活跃病例。活跃病例总数用黄色表示,每天新增病例用橙色表示,死亡病例用黑线表示。未校正的表观死亡率在右边的 Y 轴上用灰色表示。红色垂直线代表意大利实施各种缓解措施的日期,以及医疗配给报告开始的日期。数据来源:https://github.com/CSSEGISandData/COVID-19

在意大利,活跃病例的峰值还没有达到,但 3 月 22 日和 23 日的数据表明,它可能最终会到来。3 月 21 日的数据似乎显示,截至 3 月 21 日,每日新增病例达到峰值。意大利增加了检测能力,从 3 月 24 日到 25 日的数字反映了这一点,但是新病例在 3 月 26 日又开始下降。高峰和低谷可能有一个区域组成部分——旧的爆发达到某种程度的控制,而新爆发的数字上升。

3 月 9 日和 11 日是在全国范围内实施重大减排措施的日子。来自湖北的数据表明,从大规模隔离开始,每天的新增病例可能需要 11-12 天才能达到峰值并开始下降,这将大约在 3 月 23 日或 24 日,数据显示目前情况是这样的。在湖北,每天新增病例数开始下降后,又过了 12 天,活跃病例数才开始下降。如果意大利的抑制措施同样有效,并保持到位,这可能意味着我们将在 4 月 5 日左右看到活跃病例的高峰。按照目前的病毒发展轨迹,在指数增长方程 A = A0ert 中简单应用一个缓慢的增长率(在此之前每天计算),表明到 4 月 5 日,意大利的病例总数可能达到 115,000 例左右,按照目前 9.9%的死亡率,这意味着总死亡人数接近 11,300 例。

一旦意大利超过 3 例确诊病例,他们马上开始有非常快速的指数增长,然而他们对当地疫情的反应也非常快。2 月 22 日,该国伦巴第地区只有 62 例病例,他们选择在伦巴第和威尼托地区实施严格的旅行限制——关闭学校、博物馆、商店和餐馆。第二天,病例激增至 155 例,政府将措施扩大到伦巴第和威尼托所有地区,后来包括皮埃蒙特、利古里亚和艾米利亚-罗马涅。到 17 天后的 3 月 9 日,病例数量飙升至 9172 例,促使政府将隔离范围扩大至全国,直至 4 月 3 日。3 月 11 日,全国关闭了除杂货店和药店以外的所有商店。到那时,伦巴第 80%的医院床位都满了,整个系统已经到了崩溃的边缘。

大约在 3 月 9 日,伦巴第的意大利医院因病人过多而不堪重负的报道开始出现,同时还有关于医院制定战场分流协议的报道。战场伤检分类简单地解释为这样一个原则,即接受救命治疗的病人是最有可能生存和康复的人,而不是最需要医疗的人。意大利的医生们不得不做出可怕的选择,定量分配有限的医疗用品和护理,这决定了 T2 的生死。

中国湖北

意大利新冠肺炎 2 月 20 日至 3 月 23 日的新增和活跃病例。活跃病例总数用黄色表示,每天新增病例用橙色表示,死亡病例用黑线表示。未校正的表观死亡率在右边的 Y 轴上用灰色表示。红色垂直线代表意大利实施各种缓解措施的日期,以及医疗配给报告开始的日期。数据来源:https://github.com/CSSEGISandData/COVID-19

湖北的病例高峰出现在 444 例确诊病例后的 27 天左右,中国政府于 1 月 23 日对进出武汉实施了非常严格的限制。1 月 25 日,他们将隔离范围扩大到湖北省的 10 个城市,关闭了除杂货店和药店以外的所有零售商店,并要求人们待在家中,外出购买食物的时间受到限制。2 月 6 日,政府开始对任何有症状的人进行挨家挨户的搜查,这些人被 强行带离家园,带到指定的隔离设施

即使实施了这些非常早期和极端的措施,他们的活跃病例曲线也非常清楚地显示了 11-12 天的滞后时间,直到每天的新病例达到峰值并开始下降。从首次发现该病毒到活跃病例达到高峰,仅持续了 27 天。这意味着湖北在大约 27 天内从 399 例活跃病例增加到 48,510 例。1 月 25 日,当医院被迫拒绝非冠状病毒患者时,首次报道了医疗配给。

2 月份的文章谈到了在高速公路边进行的测试和医院走廊两旁的病人——明确了最坏情况的形象。超过 3300 名医护人员受到感染,许多年轻和中年医生和护士在极端轮班时间和连续工作过多天没有休息以满足前所未有的危急护理需求后,死于疾病和疲惫。

韩国

意大利新冠肺炎 2 月 20 日至 3 月 23 日的新增和活跃病例。活跃病例总数用黄色表示,每天新增病例用橙色表示,死亡病例用黑线表示。未校正的表观死亡率在右边的 Y 轴上用灰色表示。红色垂直线代表意大利实施各种缓解措施的日期,以及医疗配给报告开始的日期。数据来源:https://github.com/CSSEGISandData/COVID-19

韩国最初拒绝在以大邱为中心的疫情爆发的主要增长阶段实施地区或国家隔离或旅行限制,担心这些措施在政治上不受欢迎,并让人想起朝鲜的旅行限制——而是选择建立积极的接触者追踪和检测,并对患者进行隔离。一旦检测结果呈阳性,政府就会积极寻求所有可能的接触者进行检测——包括患者认识的任何接触过的人,以及与此人的信用卡历史和监控录像相关的任何人。如果检测呈阳性,他们将免除检测费用,并继续对潜在疫情进行积极监测。

截至 3 月 17 日,该国已检测了超过 28 万人,相当于每百万人中有超过 5500 次检测。截至 3 月 10 日,该国出现了全国性的社区传播,春川市 Hallym 大学医学院教授 Kim Dong-hyun 博士表示,该市和该国很快将达到一个临界点,即没有足够的流行病学调查人员来有效追踪新病例,“在这一点上,追踪感染如何传播是没有意义的”。韩国公共卫生医生协会(Korean Association of Public Health Doctors)会长 Kim Hyeonggab 表示,截至 3 月 7 日,通过关闭学校、取消音乐会、确保更多医院床位以及“建立分流系统”,工作重点明显从遏制转向缓解。

与湖北相比,韩国最初的疫情总体数字较低,但与湖北类似,活跃病例的峰值仅出现在指数增长开始后的 26 天。这意味着该国在 26 天内从 399 例活跃病例增加到 7577 例。第一份关于医疗配给的报告来自大邱,超过 75%的病例集中在那里。此时,2 名冠状病毒患者在家中等待床位时死亡。根据 Kim Dong-hyun 博士的说法,虽然通过积极的检测和对病人的隔离来分离病毒对控制疫情是有效的,但全国范围内广泛的社区传播的发展很可能导致未来几周活跃病例的重新出现。截至 3 月 23 日,看起来积极的追踪可能导致一种形式的阶段性感染。

纽约

现在让我们来看看纽约州与意大利、中国和韩国相比的活跃案例的增长情况。纽约州是美国活跃病例指数曲线上进展最快的州,也是获得检测机会最多的州。我现在就告诉你,你不会喜欢的。

纽约和意大利新冠肺炎的活动案例(左侧 y 轴)和从那时起每天的新案例(右侧 y 轴)各有 400 多个记录在案的案例,这些案例用图表显示在一起,以便进行粗略的关联。纽约的数据跨度为 3 月 13 日至 4 月 2 日,意大利的数据跨度为 2 月 26 日至 3 月 20 日。纽约每天的活动案例总数用红色表示,意大利的案例用黄色表示。数据来源:【https://github.com/CSSEGISandData/COVID-19

第一天代表每个地点大约有 400 多个病例的第一天,从那时起病例呈指数级增长。第 1 天和第 21 天显示的每个位置的实际数据日期。截至本文撰写之时(2020 年 3 月 24 日),纽约已有 400 个案例的数据。黄色条表示意大利每天的活动案例。红色条表示纽约每天的活动案例。黄线表示意大利每天的新增病例,红线表示纽约每天的新增病例。以下两个图表显示了纽约和湖北的数据,湖北用蓝色表示,纽约和韩国的数据用深蓝色表示。

纽约州和湖北省新冠肺炎市的活动案例(左侧 y 轴)和自时间以来的每日新案例(右侧 y 轴)各有 400 多个记录在案的案例,这些案例用图表显示在一起,以便进行粗略的关联。纽约数据跨度为 3 月 13 日至 4 月 2 日,湖北数据跨度为 1 月 22 日至 2 月 11 日。纽约每天的总活动案例以红色显示,湖北的案例以蓝色显示。数据来源:【https://github.com/CSSEGISandData/COVID-19

纽约州和南韩新冠肺炎的活动案例(左侧 y 轴)和自时间以来每天的新案例(右侧 y 轴)各有 400 多个记录在案的案例,这些案例用图表显示在一起,以便进行粗略的关联。纽约数据从 3 月 13 日持续到 4 月 2 日,韩国数据从 2 月 22 日持续到 3 月 14 日。纽约每天的活动和新病例总数用红色表示,韩国的病例用深蓝色表示。数据来源:https://github.com/CSSEGISandData/COVID-19

从这些图表的第 1 天到第 12 天,纽约每天新增病例数远远超过湖北、南韩和义大利。纽约州目前进行的人均测试是美国最多的,州长科莫估计他们每百万人的测试次数高于韩国——韩国在 3 月 17 日测试了大约每百万人 5500 次。这使得它成为试图预测影响的唯一可靠数据集。该州在短短 12 天内从 421 起案件增加到 26105 起。

州长一直等到他们有超过 700 个案例关闭学校,8310 个案例关闭不必要的企业。居民们仍然被告知这不是一个就地避难的命令。他们使用意大利 3 月 25 日开始的增长率预测的数据估计,到 4 月 3 日,该州将有超过 150,000 例病例(见下图)。然而,纽约目前的活跃病例数和每天新增病例数都比意大利高得多,意大利在 12 天内就有 400 例。如果纽约州预计在 45 天内需要 37,000 个 ICU 床位,正如州长在 3 月 18 日报告的那样,15%的新冠肺炎病例需要紧急护理,那么纽约州预计在 45 天内大约有 250,000 个病例。这几乎是全球疫情中心湖北省病例数的 4 倍。州长表示,纽约目前在整个州有 3000 个 ICU 床位,其中 80%目前已被占用。

茶叶建模

以下数字并不意味着实际预测未来的确切病例,而是根据意大利的增长率在黑暗中尝试一种可能的情况——尽管直到 3 月 24 日,纽约的增长率要高得多。纽约的数据用红色绘制,条形表示已报告的活跃病例,直线表示增长率。纽约的建模数据以粉色条表示从 3 月 25 日到 4 月 3 日的未来几天。

来自纽约州、意大利、湖北和韩国的活动案例以多色条显示(纽约-红色/粉色、意大利-黄色、湖北-浅蓝色、韩国-深蓝色),对应于左侧 y 轴(0 到 160,000 个案例)。对于尚未报告的数据,纽约的建模数据显示为粉红色。意大利(黄色)和纽约(红色)的增长率以直线绘制,对应于右侧的 y 轴(0-1.4)。增长率是指数增长方程 A=A0ert 中的变量 r。彩色竖线表示各国医院被报道不堪重负的日期。数据来源:https://github.com/CSSEGISandData/COVID-19

意大利新冠肺炎 2 月 20 日至 3 月 23 日的新增和活跃病例。活跃病例总数用黄色表示,每天新增病例用橙色表示,死亡病例用黑线表示。未校正的表观死亡率在右边的 Y 轴上用灰色表示。红色垂直线代表意大利实施各种缓解措施的日期,以及医疗配给报告开始的日期。数据来源:【https://github.com/CSSEGISandData/COVID-19

意大利新冠肺炎 2 月 20 日至 3 月 23 日的新增和活跃病例。活跃病例总数用黄色表示,每天新增病例用橙色表示,死亡病例用黑线表示。未校正的表观死亡率在右边的 Y 轴上用灰色表示。红色垂直线代表意大利实施各种缓解措施的日期,以及医疗配给报告开始的日期。数据来源:【https://github.com/CSSEGISandData/COVID-19

如果来自中国和意大利的数据有任何意义的话,美国测试的最新发展和纽约缓解措施的最新应用已经导致了令人难以置信的感染率,这将对纽约应对严重病例的能力产生毁灭性影响,因为该市正在走向其活跃病例数的峰值。

怎么强调都不为过——中国、韩国和意大利迅速做出反应,实施了广泛的遏制措施。所采用的措施采用了两种不同的策略,但都是积极的。韩国对所有确诊病例进行了极端检测、追踪和隔离。在湖北省,他们实施了全面的旅行限制,停止了所有的公共交通,关闭了除杂货店和药店之外的所有企业,命令人们呆在家里,并将生病的公民转移到隔离设施 意大利也实施了公共关闭,关闭学校和非必要的企业,命令公民留在家中。州长科莫可能试图复制韩国控制病毒的明显成功的测试计划,但除了高人均测试外,该县还隔离了所有患者,并进行了远比美国合法或可执行的更严格的接触者追踪。

糟糕的数据意味着我们真的不知道真实的范围

令人心碎的是,纽约也加入了意大利的行列,成为一个警示故事,但在这一点上,数据显示它确实如此。我们非常确定冠状病毒就在这里,它像野火一样在每个社区传播。由于缺乏测试,我们没有准确的国家数据来真正掌握截至 3 月 24 日新冠肺炎在美国纽约州以外的规模。病例的指数增长速度,加上缺乏检测途径和检测处理滞后,意味着报告的病例实际上远远高于报告的病例,因为不管我们确认与否,未受抑制的增长仍在发生。例如,一周多前,田纳西州默弗里斯伯勒一个呼叫中心的 1500 名员工可能暴露于某个有症状确诊病例的人的病毒。这意味着暴露可能在阳性病例出现症状前一周或更长时间就开始了。只有一两个呼叫中心的其他员工接受了测试,与此同时,那里的所有员工都在继续他们的日常工作——与家人互动、购物、去教堂做礼拜。据估计,韩国一名妇女通过她的教堂与 1100 多人接触,引发了大邱的严重疫情。你能想象呼叫中心地区真正爆发的可能范围吗?然而,像大多数其他州一样,只有最严重的病例在田纳西州接受测试。底线是,我们无法确切知道有多少人实际上被感染了,而这一明显较低的病例数可能会诱使我们放慢行动。

领导层未能迅速果断地采取行动

面临的主要问题是领导层决策的滞后,这些决策有效地限制了传播,并解决了未来对重症监护能力的需求。在这一点上,美国已经发布公共留在家中命令的各州在达到伦巴第或湖北政府封锁这些地区时的病例数量后很久才发布命令,有些州根本没有发布命令。不,其他州不太可能有像纽约一样多的病例——毫无疑问,由于人口密度和控制延误,他们可能是世界上受打击最严重的州。然而,如果不及早采取措施来减缓在 T2 出现的指数式增长,世界各地的每一次爆发都会在中国的每一个主要人口中心上演类似的场景。农村人口不会被排除在外——虽然人口密度降低和暴露程度降低可能导致农村总体病例减少,但农村医院普遍关闭将导致这些人口难以获得足够的护理。

对于像先发制人的社会隔离这样的遏制措施的缓慢实施,以及像建设额外的紧急 ICU 容量和使用生产法案来帮助解决预期的防护设备、呼吸机和呼吸器的短缺这样的缓解措施,这是一个非常值得警惕的故事。如果美国要实施这项法律来防止成千上万不必要的死亡,那么当我们看到意大利不堪重负的医院系统的影响时,就应该迅速果断地实施。改变制造设备和获得供应材料的时间不会在一夜之间发生,虽然它目前甚至不在桌面上,但对第一波流行病来说可能已经太晚了。

总统没有迅速采取行动允许私人测试开发,结果美国测试系统仍然被堵塞,严重不足。他没有发起足够强大的全国性回应来阻止传播,而是继续助长混乱和不和发表声明和政策,淡化世界各地顶级医疗顾问统一给出的建议。从所有明显的证据来看,各州没有实施任何有意义的策略来为即将到来的危急情况做准备,而是独自处理阻止传播和照顾病人的问题。迄今为止,这导致了不同的反应速度和严格程度。

美国的医院短缺会是什么样子?

《纽约时报》发表了一份由哈佛大学哈佛全球健康研究所制作的分析报告,下图显示了如果不扩大目前的容量,医院短缺的规模。根据分析,如果 40%的成年人在未来 12 个月内被感染,那么 40%的医院市场将无法扩大足够的能力来治疗新冠肺炎患者。进行分析的团队称 40%的感染率为中度,但他们的估计表明感染率可能会高得多,甚至超过医院通过取消选择性手术和让不太危急的病人回家等措施可以产生的过剩能力。“如果我们不在长期传播疾病和扩大容量方面做出实质性改变,我们将耗尽医院的床位,”哈佛全球卫生研究所所长 Ashish Jha 博士说。在意大利,这导致了前面提到的医疗保健配给,如果医生被迫制定战场分流协议,将对弱势群体和老年人以及患有其他疾病的患者产生影响。

图片来源:https://www . nytimes . com/interactive/2020/03/17/upshot/hospital-bed-abstraits-coronavirus . html

来自其他状态的数据

以下是 11 个州的表格,摘自约翰霍普金斯大学在 github source 上停止按州报告数据之前 3 月 23 日的美国总数据。该表显示了每天的活跃案件,以及各州或其他市颁布的抑制措施。浅蓝色单元格显示的是湖北省发布停业和居家禁止令的最接近案例数(444),浅黄色单元格显示的是伦巴第发布停业和居家禁止令的案例数(62)。亮蓝色表示全州范围的居家命令,橙色表示仅选择主要城市和/或县发布居家命令,浅绿色表示较弱的命令,仅建议但不要求居民居家。该表还假设实际上已知活动案例的数量,然而事实远非如此。正如你所看到的,许多州直到比意大利或中国更深入地了解了其新生的流行病后才颁布这些控制措施。

11 个州的现行案例表,列出了颁布抑制措施的日期,并与湖北和意大利颁布居家禁止令和非必要停业的案例数进行了比较。数据来源:【https://coronavirus.jhu.edu/map.html

以下三个表格显示了每天计算的死亡率、生长率和倍增时间,试图确定一种趋势。死亡率就是死亡人数除以总病例数。死亡率通常是追溯计算的,因为在任何给定的时间,我们可能不知道总病例的实际数目。迄今为止,这些州中的许多州死亡率都很低,其中佐治亚州、路易斯安那州和华盛顿州最高。虽然病例总数仍然相对较低,而且在检测的前几周内,但应谨慎对待这些数字。它们也可能受到其他因素的严重影响,例如疫情是否发生在更脆弱的人群中——就像华盛顿州疗养院疫情那样。

各州未校正的表观死亡率表,按死亡数/总病例数计算。原始数据来源:【https://coronavirus.jhu.edu/map.html】T4。由于缺乏测试来了解以脆弱人群为中心的病例和疫情的实际总数,死亡率可能会更高。

根据等式 A=A0ert 每天计算的增长率表,其中 A0 是一天的病例总数,A 是第二天的病例总数,e 是欧拉数,t 是时间。原始数据来源:https://coronavirus.jhu.edu/map.html

根据等式 A=A0ert 每天计算的增长率表,其中 A0 是一天的病例总数,A 是第二天的病例总数,e 是欧拉数,t 是时间。原始数据来源:https://coronavirus.jhu.edu/map.html

显示增长率的第二个表格试图捕捉数字增长的速度。增长率是基本指数增长计算中的变量“r”。每天使用前一天(A0)到当天(A)的总病例数计算这些值。在意大利和湖北的数据中,高于 0.2 的数字出现在快速指数增长期间,而低于 0.1 的数字出现在这些地区经历新病例快速下降时。

最后,最后一个表格显示了一些文章引用的一个数字,即倍增时间。翻倍时间是总病例数以当前增长率翻倍之前的天数。这是通过等式 ln(2)r 计算的,其中 r 是增长率。倍增时间是一种更直观的衡量流行病增长速度的方法——人类可以用天数来表示,而增长率是一个更抽象的数字。该表显示,倍增时间每天都在变化,但仍然相对较低,倍增时间越短意味着病例增长越快。这些数字对任何的持续限制是缺乏全面的测试。缺乏测试可能会导致重大错误,即低估了一个地区正在经历的实际增长和翻倍时间*。

曲线变平后会发生什么?

伦敦帝国理工学院新冠肺炎反应小组发布的一份报告称,如果像居家命令和企业关闭这样的抑制措施在短期内成功,但没有有效和广泛使用的疫苗,这些抑制措施的放松将导致今年晚些时候出现相同或更大的疫情,因为“群体免疫”的建立不足。群体免疫是对传染病在人群中传播的抵抗力,如果足够高比例的个体具有免疫力,就会产生这种抵抗力。

这对领导人来说意味着,抑制新冠肺炎的传播需要通过社会措施来管理,要么 1)持续保持呆在家里的命令,2)像韩国那样组织一个资源充足、100%充分的检测、追踪和隔离计划,或者 3)制定一个间歇性社会距离的有意循环。为了实现这一目标,我们有意放松抑制传播的居家和企业关闭令,以允许控制感染模式,这种模式永远不会超过我们通过充分的医疗护理有效应对的能力,直到疫苗可用。在这 3 个中,迄今为止只有前 2 个被建模。

对大多数美国人来说,接下来的几天将是暴跌前的深呼吸。截至 3 月 24 日的数据显示,对大多数州来说,要安然无恙地度过这一阶段为时已晚。但是数据显示,可能需要 27 天左右的时间才能使曲线变平,因为 T2 发布了强劲的留在国内订单,并且保持在 T3。成千上万人的生命——包括我们医疗服务提供者的生命——现在取决于国家领导人在未来几天是否会响应日益增长的领导呼声。

为了保护自己的公民,每个国家都必须颁布以下措施:

1) 立即关闭非必要业务。

立即发布并执行留在家中的命令。

3) 与该州的当地医院领导合作,构建一个现实的模型来计算可能需要的医院容量和达到需求峰值的时间。

4) 协助医院为提供者获取救生急救设备和 PPE。

5) 与州医疗和/或医院协会合作,为即将到来的医疗提供者和肺病专家的短缺做好准备。

6) 帮助重要企业获得必要的个人防护设备(PPE)以保证员工的安全。

a. 建议杂货商、药店、饲料商店和其他重要企业现在就开始准备个人防护设备,并制定在疫情高峰期开展工作的协议。

b. 考虑发布一份与美国疾病预防控制中心或州医疗领导指南合作制作的标准化指南。

启动国民警卫队:

a. 根据能力不足的情况,开始为急病患者建造临时医院或准备现有医院,包括将服务扩展到农村地区。

一旦测试变得广泛可用,将有助于减轻医院的压力。随着病例的增加,需求将会显著增加。

c. 帮助高危人群获取食物和药品。

d. 在有疫苗时,帮助接种疫苗

8) 大幅提高信息热线的现场呼叫能力,推送以下方面的最新详细信息:

答:去哪里做测试

b. 国家颁布的现行指南

c. 关于人们在哪里可以获得食物、药品、宠物用品和儿童用品等必需品的信息。

9) 与商会和其他商业实体合作:

a. 鼓励对长期远程业务运营进行物流规划,以尽可能保持商业运作。这将减少因疾病导致的生产力损失和因检疫限制导致的运营能力下降,并有助于保持该州的经济运行。企业在规划中花费的准备时间越多,这种转变就会越顺利。这是促进快速和广泛创新,阻止一切照旧的时候了。

b. 鼓励电信提供商迅速满足对额外网络和远程通信能力的需求。

10) 制定一个短期和长期计划,为州居民提供财政救济,使他们能够:

维持住房和水电等基本服务。

b. 购买基本商品,如食品、个人和儿童护理用品、药品和动物饲料。

11) 制定一个现实的、分阶段的长期计划,以指导企业、学区和公众放松社会封锁指导方针,避免连续爆发疫情,并根据该计划继续执行封锁和居家命令。

行动号召

此时此刻,我向美国的每一个人发出这一呼吁。各级领导——做你被选举出来要做的事情,并领导别人。不要再等着看问题在你那里显现了——数据已经被很好地确定了,医学界正在用一个声音说话。越早实施全面的控制措施,病例高峰就越早到来。

公民们,我现在呼吁成为人类的代言人——是时候让人们停止坐以待毙,从你们在这个系统中的任何地方开始带头了。像淹没卫生纸通道一样,给当地媒体、城市、县、州和联邦代表打电话——要求他们发布居家订单,并提出快速和全面的解决方案,以满足现在对医疗、金融和物流解决方案的需求。为了你的家人、你的社区和你的国家的健康。潮水退去时,我们正坐在沙滩上——很快,潮水就会淹没我们。现在的行动可以拯救无数的生命。我强烈要求你服用它们。

是时候改变维度了

原文:https://towardsdatascience.com/its-time-to-change-dimensions-be3302893dd6?source=collection_archive---------33-----------------------

安东尼·加兰在 Unsplash 上的照片

任何事物都有一个季节,每个目的都有一个时间…让我们用一个缓慢变化的维度(SCD)来记录这些变化。

缓变维度是什么?这是一个随着时间逐渐变化的表,就像一组当选的官员。假设我们将下面一组美国参议员加载到数据库中。

https://the United States . io/congress-立法者/立法者-current.csv

尽管许多人已经在位很长时间,但有些人即将改变。根据我们的宪法第一条,第三节,第二款,这些参议员的三分之一将受到改变。

[合众国参议院]在第一次选举结果产生后,应立即尽可能平等地分成三个等级。第一等参议员的席位应在第二年期满时空出,第二等参议员的席位在第四年期满时空出,第三等参议员的席位在第六年期满时空出,以便每隔一年选出三分之一的参议员

有许多方法可以实现渐变维度。保持一个简单的模式可以简化你决定如何改变的过程。

确定标识唯一行的列以及要跟踪的列。

例如,我希望每个州和每个阶层都有一个独特的参议员。州参议员没有阶级重叠,因此在一个特定的州的选举周期中只有一个人可以参加选举。目前,格鲁吉亚是个例外,但我们不会深入探讨。

假设我们已经将上述 CSV 文件的原始数据存放到一个表中。为了将原始数据处理到当前参议院的表中,我们将行插入到一个维度表中。

注意,我已经将惟一的行标识为我的 MATCH_GUID,将 CHANGE_HASH 标识为 H as 值。我使用散列来最小化 SQL 上的 CPU 处理时间。

MATCH_GUID 对行中的所有更改进行编码,如果有任何更改,它将使用新记录更新维度。

insert into OWLMTN.WAREHOUSE.DIM_CONGRESS_SEAT(CONGRESS_SEAT_GUID,
                                               LAST_NAME,
                                               FIRST_NAME,
                                               FULL_NAME,
                                               BIRTHDAY,
                                               GENDER,
                                               TYPE,
                                               STATE,
                                               DISTRICT,
                                               SENATE_CLASS,
                                               PARTY,
                                               ADDRESS,
                                               PHONE,
                                               CONTACT_FORM,
                                               DW_MATCH_HASH)
with source as (
    SELECT hash(STATE,
                SENATE_CLASS)    MATCH_GUID,
           LAST_NAME,
           FIRST_NAME,
           FULL_NAME,
           BIRTHDAY,
           GENDER,
           TYPE,
           STATE,
           DISTRICT,
           SENATE_CLASS,
           PARTY,
           ADDRESS,
           PHONE,
           CONTACT_FORM,

           hash(
                   LAST_NAME,
                   FIRST_NAME,
                   FULL_NAME,
                   BIRTHDAY,
                   GENDER,
                   TYPE,
                   DISTRICT,
                   PARTY,
                   ADDRESS,
                   PHONE,
                   CONTACT_FORM) CHANGE_HASH
    from OWLMTN.STAGE.CONGRESS_MEMBERS sor
    where type = 'sen'
),
     target as (
         select CONGRESS_SEAT_GUID,
                DW_MATCH_HASH match_hash
         from OWLMTN.WAREHOUSE.DIM_CONGRESS_SEAT tar
         where DW_ACTIVE = 'T'
     )
select source.MATCH_GUID,
       source.LAST_NAME,
       source.FIRST_NAME,
       source.FULL_NAME,
       source.BIRTHDAY,
       source.GENDER,
       source.TYPE,
       source.STATE,
       source.DISTRICT,
       source.SENATE_CLASS,
       source.PARTY,
       source.ADDRESS,
       source.PHONE,
       source.CONTACT_FORM,
       source.CHANGE_HASH
from source
         left outer join target
                         on target.CONGRESS_SEAT_GUID = source.MATCH_GUID
where target.match_hash is null
   or target.match_hash <> source.CHANGE_HASH;

更新查询将找到任何新行,并将它们标记为活动的。

-- Arrange the dimensions on the SCD.
update OWLMTN.WAREHOUSE.DIM_CONGRESS_SEAT new_data
    set new_data.DW_ACTIVE = update_logic.DW_ACTIVE,
        new_data.DW_FROM_DATE = update_logic.new_from_dw_date,
        new_data.DW_TO_DATE = update_logic.new_to_dw_date,
        DW_UPDATE_DATE = current_timestamp()
from (

    with updated_gui as (
        select DIM_CONGRESS_SEAT_KEY, CONGRESS_SEAT_GUID
        from OWLMTN.WAREHOUSE.DIM_CONGRESS_SEAT
        where dw_from_date is null
        )
    select current_row.DIM_CONGRESS_SEAT_KEY,
           current_row.dw_active as old_active,
           case when current_row.DW_FROM_DATE is null
               then TRUE
               else FALSE end as DW_ACTIVE,

           current_row.DW_FROM_DATE,
            case when current_row.DW_FROM_DATE is null
               then CURRENT_TIMESTAMP()
               else current_row.DW_FROM_DATE end as new_from_dw_date,

           current_row.DW_TO_DATE,

           case when current_row.DW_FROM_DATE is null
                 then to_timestamp_ltz('2099-12-31 00:00:00')
               else CURRENT_TIMESTAMP() end as new_to_dw_date,
           current_row.DW_MATCH_HASH
        from updated_gui
        inner join OWLMTN.WAREHOUSE.DIM_CONGRESS_SEAT current_row
            on updated_gui.CONGRESS_SEAT_GUID = current_row.CONGRESS_SEAT_GUID
                   and (DW_FROM_DATE is NULL or current_row.DW_ACTIVE=TRUE)
        left outer join OWLMTN.WAREHOUSE.DIM_CONGRESS_SEAT old
            on current_row.CONGRESS_SEAT_GUID = old.CONGRESS_SEAT_GUID
                   and old.dw_ACTIVE

      ) update_logic
where new_data.DIM_CONGRESS_SEAT_KEY = update_logic.DIM_CONGRESS_SEAT_KEY;

那么 11 月 3 日之后会发生什么,座位状态有变化?让我们追踪一下我最喜欢的科罗拉多州的选举,假设一下席位的变化。

根据 Azri.us 上的数据预测,希肯卢珀比目前占据席位的加德纳多 10 个百分点的优势。

图片由 Google GeoChart 基于 538 个原始数据制作

查看前面的插入查询中的散列比较,我们看到 MATCH_GUID 保持不变(相同的席位),但是 CHANGE_HASH 发生了变化(新参议员)。

SCD 哈希匹配策略

在 insert 检测到一个已更改的记录后,它还不是活动的,我们需要以一种事务方式激活该记录,当新行替换旧记录时,将旧记录设置为非活动的。

运行移动当前活动行上的日期的查询会将非活动行移动到活动行。

对于给定时间点的任何查询,声明为 unique 的项将始终返回一行。

如果我想知道在特定时间谁是科罗拉多州 2 级参议员,我可以指定时间,它永远不会改变。

请注意,DW_FROM_DATE 小于该日期,而 DW_TO_DATE 大于或等于该日期。

select CONGRESS_SEAT_GUID, FULL_NAME, DW_MATCH_HASH, DW_ACTIVE, DW_FROM_DATE, DW_TO_DATE
from owlmtn.WAREHOUSE.DIM_CONGRESS_SEAT
where state = 'CO' and SENATE_CLASS = 2
  and DW_FROM_DATE < '2020-10-30 21:51:58.166000000 -07:00'
  and DW_TO_DATE >= '2020-10-30 21:51:58.166000000 -07:00';

结论

缓慢变化的维度表是数据仓库的基础。它允许分析师跟踪趋势,查看历史,并遵守保存所有数据的原则。

一些 SQL 结构可能比较复杂,一些数据库本身就支持 SCD。然而,使用基本的 SQL SCD 模式将使您的代码具有可移植性和清晰性。

是时候让自己比以往更熟悉 NoSQL 数据库了

原文:https://towardsdatascience.com/its-time-to-familiarize-yourself-with-nosql-databases-more-than-ever-5fb1f65c22b1?source=collection_archive---------9-----------------------

SQL 与 NoSQL:选择合适的数据库的困难(以及如何做好)

万花筒Unsplash 上拍摄的照片

数据是信息系统的核心。其组织和运作的效率是任何公司都关心的主要问题。在大数据的时候,业务专长和了解现有的技术解决方案是非常必要的。技术领域发展非常迅速,公司必须同时继续评估和选择能够满足其未来需求并支持其发展的数据库。

几十年来,关系数据库一直被用来存储数据,对于许多用例来说,它们仍然是一种可行的解决方案。NoSQL 数据库是为了应对关系数据库技术的局限性而创建的。与关系数据库相比, NoSQL 数据库更具伸缩性,提供更高的性能,它们的数据模型纠正了关系模型的几个弱点。在本文中,我将尝试阐明从 RDBMS 迁移到 NoSQL 的挑战、好处和过程。

总的来说, NoSQL 数据库旨在解决大数据环境下的海量、多源、多格式的数据处理问题。它们提供了一种新的方法来满足容量需求
和新的数据类型。

如今,NoSQL 数据库的数量变得越来越重要。必须了解它们的差异,以便为正确的应用采用正确的技术。

1.介绍

- SQL:

SQLS 结构化QueryL语言。长期以来,所有必须在大型关系数据库 (DBMS) 中快速搜索信息的 It 工程师都知道这一点。 SQL 如今被广泛使用,因为它是结构化程度最高、速度最快的数据库组织和查询设备之一;它有不同的名字,这表明有各种各样的适应,如甲骨文的 MySQL 和微软的 SQL Server。此外, SQL 由于其预定义的结构和模式,是许多公司最推荐的选项。

——NoSQL:

首字母缩略词“NoSQL”有两种解释,目前并不明确:

  • 有的则是 【无 SQL】,也就是说使用另一种不同于 SQL 的查询语言。
  • 对于其他人来说,就是 【不仅仅是 SQL】,也就是说 SQL 与其他信息检索工具的结合使用。

因此,这个术语既与技术特征有关,也与出现在 2010 年前后的历史性一代数据库管理系统有关。导致发明 NoSQL 的主要问题是解决网站上的同一个数据库可以被全球数百万用户同时使用的事实;像亚马逊这样的公司的典型问题…

因此,我们试图用 NoSQL 实现的是降低查询语言的复杂性,简化数据库的架构。这些数据库由面向列的面向文档的面向图形的面向键/值的数据组成。 NoSQL 系列由各种产品组成,每种产品都有一套独特的功能。

-主要区别:

  • SQL 数据库有一个预定义的模式,而 NoSQL 数据库有一个非结构化数据的动态模式。
  • SQL 数据库是纵向可伸缩的,而 NoSQL 数据库是横向可伸缩的。 SQL 数据库通过增加硬件的能力来扩展,比如 CPURAMSSD 。数据库 NoSQL 通过增加数据服务器的数量来降低负载。这就像在同一栋建筑上增加更多的楼层和在附近增加更多的建筑。
  • SQL 数据库是基于表的数据库,而 NoSQL 数据库是基于键值对的数据库。这意味着 SQL 数据库以表格的形式表示数据,表格由一定数量的表示数据的行组成,而 NoSQL 数据库是键值对、文档、图形数据库等的集合。
  • SQL 数据库使用 SQL (结构化查询语言) 来定义和操作数据,非常强大。在 NoSQL 数据库中,查询集中在文档集合上。有时也叫 UnQL (非结构化查询语言) 。在不同的现有 NoSQL 数据库之间,使用 UnQL 的语法差别很大。

2.历史元素

来源:照片由国立癌症研究所Unsplash 上拍摄

关系数据库管理系统的历史统治

  • 创建于 20 世纪 70 年代的关系型数据库管理系统已经逐渐成为 20 世纪 90 年代早期占主导地位的数据库范例。
  • 在 20 世纪 90 年代,许多物流公司的销售人员开始使用它来存储他们的业务数据。实际上,他们既没有鼠标,也没有用户界面来搜索存储在服务器上的某些信息,这些服务器通常距离很远,通过专用线路连接:他们被用来用键盘输入 SQL 命令,并能够在几秒钟内检索到关于特定产品或原材料可用性的相关信息。
  • 其他几个数据库模型已经出现,如面向对象的数据库管理系统(DBMS)、层次数据库管理系统(DBMS)对象关系数据库管理系统(DBMS),但是它们的使用非常有限。
  • 2000 年代开始,随着大型互联网公司(亚马逊、易贝、谷歌……)的发展,大量的非结构化数据出现了,并且比结构化数据增长得更快,以至于不再适合 RDBMS 的关系模式。集群计算也有了发展,因此关系模型的统治地位受到了质疑,因为它对这些新的实践有一些禁止性的限制。

NoSQL 模式的先驱

大型网络公司必须处理非常大量的数据,这就是为什么他们首先面临传统关系型数据库管理系统固有的局限性。这些系统基于对属性(原子性、一致性、隔离性、持久性)的严格应用,并且通常被设计为在单台计算机上运行,很快就提出了可扩展性的问题。

为了满足这些限制,这些公司已经开始开发他们自己的数据库管理系统,该系统可以在分布式硬件体系结构上运行,并且可以处理大量数据:

通过简单地增加服务器的数量,性能保持良好,这是一个成本下降的合理解决方案,特别是如果收入随着活动的发展而增长。

3.流行数据库

有几种流行的数据库系统可供使用;付费和免费都有。为了给你或你的组织选择正确的管理系统,了解市场上存在的东西是很重要的。看看下面 5 个流行的 SQL 数据库的列表。

- SQL 数据库产品:

1- MySql:

它是免费的,甚至为免费的数据库引擎提供了很多功能。

来源:https://www.mysql.com/

2-甲骨文:

Oracle 数据库管理工具凭借最新的创新和特性变得异常强大。

来源:https://www.oracle.com/database/

3- Postgres:

这个数据库管理引擎是可伸缩的,可以处理万亿字节的数据,具有各种预定义的功能。

资料来源:https://www.postgresql.org/

4- SQL Server:

它非常快而且稳定。它与微软的其他产品配合得非常好。

来源:https://www.microsoft.com/en-us/sql-server/sql-server-2019

5- SQLite:

SQLite 数据库设置起来非常简单快捷,它还可以用于在智能手机应用程序(iPhone 或 Android)的真实数据库中存储数据。

来源:https://www.sqlite.org/index.html

- NoSQL 数据库产品:

1- MongoDB:

MongoDB 是一个灵活/可靠的数据库,它将把你带到 NoSQL 的世界。它的管理和维护非常简单快捷。

来源:https://www.mongodb.com/

2- Redis:

使用起来非常简单明了。您可以下载 Redis 并在接下来的五分钟内开始使用它。

来源:https://redis.io/

3-卡桑德拉:

Cassandra 提供的线性可伸缩性,允许通过简单地添加/删除服务器来轻松扩展/缩减集群。

来源:http://cassandra.apache.org/

4-h 碱基:

这是一个面向列的数据库,有助于提高查询性能和聚合。

来源:https://hbase.apache.org/

5- CouchDb:

由于其存储序列化(JSON 格式)非结构化数据的能力及其 Restful HTTP API,CouchDB 非常适合 Web 和移动应用程序。

来源:https://couchdb.apache.org/

4.NoSQL 数据库设计

NoSQL 数据库管理系统的主要特点是允许处理大量数据,并允许水平伸缩。然而,大多数公司今天面临的困难是,瞄准最合适的技术,以便对他们的问题和应用作出反应。

要解决这个困难,首先要很好地理解不同类型的 NoSQL 数据库。有一个普遍的误解,认为所有的 NoSQL 数据库都是平等的——这不是真的!实际上,这些数据库可以分为四类:面向文档的数据库、键/值数据库、数据库和面向图形的数据库。它们都有一个共同点:支持比传统关系数据库更灵活、更动态的模型。

事实上,这些类别都有自己的属性和局限性。没有解决所有问题的更好的数据库。您必须根据项目的需要选择数据库。

您必须考虑哪种数据将被操作,以及应用程序最终将如何使用它。

****-面向文档的数据库:混合结构

面向文档的 NoSQL 数据库以键/值对的形式存储和提取数据,但值部分存储为文档。文档以 JSONXML 格式存储。

MongoDBApache couch dbMarkLogic 都是面向文档的数据库。

****-键/值数据库:

面向键-值的数据库有大量的键和值。它代表了 NoSQL 数据库的最简单形式。它们将唯一键与数据中的值相关联,目的是基于相对简单的数据集极大地增强应用程序的性能。

Redis Riak MemcachedAerospike 都是键值数据库的例子。

****-栏目数据库:

列数据库将数据保存在具有大量列的表中。每个存储块包含来自单个列的数据,并且每个列被单独处理。它们在计数、求和、AVG、最大值等聚合查询上提供了高性能。,因为数据很容易在列中获得。

HBaseCassandraAccumulo 都是基于列的数据库的例子。

****-面向图形的数据库:

基于图形的数据库是一种网络数据库,它以“图形”结构存储数据元素,并使在节点之间创建关联成为可能,最终作为推荐引擎或社交网络的基础。

我们可以从图形数据库中获得很多信息。例如,图表技术可用于通过不同人的兴趣来识别他们之间的关系。

推特图|来源:https://neo4j.com/blog/oscon-twitter-graph/

Neo4J 无限图FlockDB 都是面向图的数据库的例子。

4.为您的应用选择合适的数据库类型的 5 个标准

我们如何决定哪种类型的数据库最适合一个项目?这里有一份你可以使用的清单:

  • 要存储的数据类型 : SQL 数据库不适合分层数据存储。然而, NoSQL 数据库更适合分层数据存储,因为它遵循键-值对方法或图形方法。NoSQL 数据库是大型数据集的首选。
  • 复杂查询 : SQL 数据库非常适合需要很多查询的环境,而 NoSQL 数据库不适合复杂查询。因此, NoSQL 中的查询不如 SQL 查询语言强大。
  • ****可伸缩性:在大多数情况下, SQL 数据库是垂直可伸缩的。您可以通过增加处理器、RAM、SSD 等来管理增加的负载。在一台服务器上。另一方面, NoSQL 数据库是水平可伸缩的。你可以简单地添加一些额外的服务器到你的 NoSQL 数据库基础设施来处理大流量。所以你可以根据你的设备选择适合你的数据库类型。
  • 高度事务性应用 : SQL 数据库更适合大量使用的事务型应用,因为它们更稳定,并保证原子性和数据完整性。虽然您可以将 NoSQL 用于事务性目的,但它仍然不具有可比性,但可以用于复杂的事务性应用程序。
  • 属性 : SQL 数据库强调 ACID 属性(原子性、一致性、隔离性、持久性),而 NoSQL 数据库遵循 Brewers CAP 定理(一致性、可用性和分区容差)。

5.从 RDBMS 转换到 NoSQL

Unsplash科学高清摄影

无论您选择哪种 NoSQL 数据库设计,将数据迁移到其中都会面临一些严峻的挑战。在 NoSQL的数据模型的设计有额外的复杂性,因为它需要知道数据的最终用途。知道您的应用程序将处理 账单客户 已经不够了。您现在必须知道这些数据将如何显示给最终用户。因此,在 NoSQL 数据库中进行数据建模,除了需要对最终客户的使用有深入的了解之外,还需要真正的技术专家。****

是时候用 NoSQL 解决方案取代 SQL 了吗?

在我看来,这是一个很难的问题!因为在大多数情况下,这不是用一个 NoSQL 解决方案替换 SQL ,而是,如果应用程序和用例揭示了改变的需要,从一个解决方案过渡到另一个解决方案。一般来说,在构建现代 web 和移动应用程序时,灵活性和可伸缩性的需求将推动这种转变。

通常,许多公司试图支持其 web 应用程序中的负载,因此他们选择简单地在负载平衡器后添加 web 服务器来支持更多用户。毫无疑问,在日益重要的云计算世界中,向上扩展的能力是一个基本的竞争优势,在这个世界中,可以轻松地添加或删除虚拟机实例,以满足不断变化的需求。

关系数据库(RDBMS) 不允许简单的伸缩,也不提供灵活的数据模型。管理更多的用户意味着增加更大的服务器,大型服务器非常复杂和昂贵,不像低成本硬件、【商用硬件】和云架构。组织开始发现现有或新应用程序的关系数据库存在性能问题。尤其是随着用户数量的日益增加,他们意识到对更快、更灵活的数据库的需求变得非常重要。是时候搬到 NoSQL 去了!

从 SQL 过渡到 NoSQL 需要哪些主要步骤?

根据不同的组织,应用程序/项目可能会有很大的不同,因此过渡将取决于您的用例。以下是过渡的一些一般准则:

1-了解您的应用的关键要求:

以下是与拥有一个 NoSQL 数据库的需求相对应的一些要求:

  • ****快速应用开发:不断变化的市场需求&持续修改数据
  • 可扩展性
  • ****稳定的性能:响应时间短,用户体验更好
  • ****运行可靠性:高可用性,以对应用程序影响最小的方式管理错误&集成监控 API,以实现更好的维护

2-了解不同类型的 NoSQL 优惠:

正如我上面所说的,有不同类型的 NoSQL 数据库管理系统。

例如,面向文档的 NoSQL 数据库——带有 CouchbaseMongoDB ,这是两个最著名和最广泛采用的例子。

此外,例如, Cassandra 可能是一个解决方案,您可以使用它的柱状模型进行数据分析。对于需要存储实体间关系的应用程序来说,图形数据库 Neo4j 是一个完美的数据库。

3-构建原型:

一旦缩小了数据库类型的可能选择范围,就尝试开发一个集成了应用程序主要特征的原型。这个原型将帮助您评估响应时间、吞吐量方面的性能以及轻松扩展的能力。

4-文档建模和开发:

对于面向文档的数据库,花几天时间对数据建模,从固定的表格图开始,到灵活的文档模型。

5-部署然后生产:

操作稳定性是交互式 web 应用程序的一个非常重要的方面。像通常使用传统的 RDBMS 系统的应用程序一样测试和重新测试您的部署。

6-紧跟最新潮流:

今天,有太多的高质量培训为 NoSQL 的培训提供实践课程。确保成功实现 NoSQL 的最好方法是获得最新版本。

别担心,你会发现采用某些 NoSQL 技术很容易,尤其是如果你熟悉文档格式的 JSON 。大量使用 SQL 的开发人员可能需要适应和学习文档建模方法。重新思考如何使用文档逻辑地构造数据,而不是将数据规范化到固定的数据库模式中,这成为一个重要的方面。

以下是一些有趣课程的链接:

6.结论

因此,本文的目的是展示存在的主要差异,以帮助您做出正确的决策,并塑造您的信息系统(或您的简单应用程序)的未来。

我们已经看到 SQLNoSQL 数据库最终做了几乎相同的事情(存储数据),但方式不同。因此,对于任何数据项目来说,选择数据库管理系统 (DBMS) 都是一个重要的构建时刻。当然,总是有可能选择一个选项,然后稍后切换到另一个选项。但是在项目开始时进行一点概念性的分析和思考会让你节省时间和金钱。

今天的市场充满了 NoSQL 的数据库——我认为我们每天都要面对两到三个,因为开发人员转用 NoSQL 的数据库有很多好处。更灵活的数据模型和摆脱僵化模式是一个很大的优势。您还可以看到显著提高的性能和水平扩展能力。

但是大多数 NoSQL 产品仍处于产品周期的早期阶段。对于复杂连接这样的特性,开发人员可能更喜欢使用传统的 RDBMS。对于一些项目,一个 混合方法 可能是最好的选择。

总之,根据项目的要求,每个公司都有自己的偏好。因此,确定您的需求和数据库,明智地为您的项目开发提供集成支持。

如果你设法来到这里,恭喜你。感谢阅读,我希望你喜欢它。如需个人联系或讨论,欢迎在LinkedIn联系我。****

参考资料:

是时候去考冠状病毒博士了

原文:https://towardsdatascience.com/its-time-to-get-a-phd-in-coronavirus-cacf7e2e9e9f?source=collection_archive---------21-----------------------

有可靠来源的 Corona-knowledge 的实际在线课程

教育让你保持健康。刘凯潇Unsplash 上拍照

取决于你住在哪里,在过去的几个月、几周或几天里,你可能已经遭受了与电晕相关的焦虑。所有的轻描淡写,假新闻,甚至有趣的模因,都倾向于加剧焦虑,至少对我来说是这样。

如果有一种方法可以治愈所有这些不确定性,那就是知识。我最近写了一篇关于如何利用这些社交距离来自学数据科学的文章。但是,如果你能通过了解引起焦虑的同样的事情来抑制你的焦虑呢?

[## 如果你因为冠状病毒而被锁在家里,11 堂最好的数据科学课

不用花一分钱就可以开始你的职业生涯

towardsdatascience.com](/11-best-data-science-classes-if-youre-locked-home-because-of-coronavirus-ca7d2d74a454)

事实证明,确实有关于冠状病毒的在线课程。这不是废话——他们由来自世卫组织、伦敦帝国理工学院、约翰·霍普金斯大学等机构的世界级健康和流行病学研究人员授课。你甚至可以在其中几门课程结束时获得成绩证书!

我将把重点放在英语课程上,这些课程是免费的,对普通大众来说是可以理解的。有更多针对健康专家的课程,但是因为我不在这个领域工作,我觉得我没有资格评价这些。这些课程的排名不分先后。

约翰霍普金斯大学/ coursera:用流行病学对抗新冠肺炎

所需时间:~5 小时,自定进度
开始时间:2020 年 3 月 31 日(但随时可以加入)

本课程主要关注疾病爆发的流行病学方面:主要关注如何收集和分析关于流行病的正确数据。核心问题是:

  • 有多少人被感染了?
  • 我们如何衡量谁被感染了?
  • 病毒的传染性有多大?
  • 我们能做什么?

该课程还提供了一些实用技巧,教你如何在社交孤立中学习和与他人联系。

如果你有症状,戴上口罩。由Adam nieciorukUnsplash 上拍摄的照片

伦敦帝国理工学院/ coursera:我们来谈谈新冠肺炎吧

所需时间:~19 小时,自定进度
开始时间:2020 年 3 月 28 日(但可随时加入)

虽然上述课程主要关注疫情的定量方面,但本课程也涵盖政府和社会的应对措施。随着疫情的发展,它也在不断更新。

本课程的要点是:

  • 正在出现的疫情的规模和使用可靠的信息来源跟踪趋势的方法,
  • 循证爆发控制方法的关键科学基础,
  • 社区参与、多学科合作和全球合作在疫情应对中的重要性,以及
  • 传染病模型如何为地方、国家和国际层面的战略和操作反应提供信息。

伦敦卫生与热带医学学院/未来学习:应对新型冠状病毒

所需时间:~12 小时,自定进度
开始:任何时间

与前面介绍的两门课程相比,这门课程更加关注医疗保健。课程的核心支柱是:

  • 新冠肺炎是如何出现和被识别的,
  • 新冠肺炎是如何传播的,
  • 新冠肺炎全球公共卫生措施,以及
  • 如何应对新冠肺炎的未来?

像许多其他课程一样,它会不断更新,以提供我们对该病毒的最新了解。完成后,您可以下载一份成就证书来证明您的成功。

世界卫生组织:新型冠状病毒的感染预防和控制

所需时间:~1 小时,自定步调
开始:任何时间

来自世界卫生组织的这一官方课程快速总结了疫情的现状以及在这一困难时期的一般准备指南。其核心目标是:

  • 定义感染预防和控制及其在准备、准备和响应中的作用,
  • 描述当前新冠肺炎的流行病学情况,包括病例定义和体征及症状。
  • 描述源代码控制、管理控制以及环境和工程控制,
  • 描述世卫组织建议的卫生保健机构感染预防和控制措施,包括在处理疑似或确诊新冠肺炎病例时,以及
  • 描述额外的感染预防和控制措施,以帮助医疗机构做好一般准备。

利用你独处的时间去学习新的东西。照片由 Unsplash 上的 Dhaya Eddine Bentaleb 拍摄

世界卫生组织:支持国家准备和应对的业务规划准则和新冠肺炎伙伴平台

所需时间:~2 小时,自定步调
开始:任何时间

本课程与上述课程相似,但更深入地探讨了流行病的准备计划。核心目标是:

  • 让自己和他人了解实施新冠肺炎战略准备和反应计划的重要性,
  • 能够描述公共卫生准备和应对的 8 大支柱以及联合国国家工作队将采取的初步行动,以及
  • 能够获得进行准备水平评估所需的全套行动、绩效指标和资源。

如果你在评分作业中取得了 80%以上的成绩,你也有资格获得成绩记录。

世界卫生组织:包括新冠肺炎在内的新型呼吸道病毒:检测、预防、应对和控制方法

所需时间:~3 小时,自定进度
开始:任何时间

本课程重点关注新冠肺炎病毒爆发的生物学和流行病学,但也涵盖了应对一种新型病毒的某些方面。课程的中心点是:

  • 新出现的呼吸道病毒的性质,如何检测和评估爆发,预防和控制由新型呼吸道病毒引起的爆发的策略,以及
  • 应该使用什么策略来传达风险并让社区参与检测、预防和应对新型呼吸道病毒的出现。

它会根据最新的发现不断更新。目前还没有证书,但将来会有。

底线:呆在家里学习

在我们这个时代,社会隔离和自我隔离可能看起来像中世纪的反应。但由于这种冠状病毒如此新,这是科学在这一点上所能提供的最好的。

这并不意味着你不能做任何事情。第一步是利用可靠的来源来教育自己。尽管在这个充满焦虑的世界里,到处都有一个有趣的电晕迷因不会造成任何伤害…

然后,你可能想把你的知识带到下一个层次:帮助你的邻居,尤其是年轻人、老年人和病人。照看你所在地区的孩子,或者为别人去购物。现在不是自私的时候。

也许这些课程不足以让你获得冠状病毒博士学位。但他们肯定会给你一个人类的伟大。

是时候考虑到公平性来优化数据算法了

原文:https://towardsdatascience.com/its-time-to-optimize-data-algorithms-with-fairness-considerations-9bfe68c7ed38?source=collection_archive---------54-----------------------

为什么预测能力和花哨的模型指标不能说明全部情况…

不可否认的是,我们的社会正越来越多地被大数据所统治。随着我们的生活越来越多地受到数据驱动算法的影响,意识到它们的道德含义很重要。一个普遍的问题是,这些模式往往会延续现有的社会偏见和歧视。虽然这通常是一个无意的过程,但这可能导致产品或服务不能平等地涵盖所有人群,在许多情况下甚至会给他们的生活带来意想不到的后果。

例如,今天存在的面部识别系统是用数据集进行大量训练的,这些数据集对某些人口统计数据的权重更大,导致准确性在种族、地区和年龄之间差异很大。来自少数群体的人的脸可能不被系统识别,或者以有害的方式被曲解。下面显示了三大公司开发的面部识别算法在性别和种族方面的准确性水平:

按人口统计的面部识别准确度;数据来自性别差异:商业性别分类的交叉准确性差异

另一个例子是谷歌搜索某些关键词的结果。下面是谷歌图片搜索“专业发型”和“非专业发型”的对比。

截至 2010 年 5 月 16 日的谷歌图片搜索

专业发型主要展示白人女性的照片。它还显示了相关的关键字,“男性”和一个白人图标。然而,“不专业的发型”展示了更多黑人女性的形象。相关关键词是“黑发”和“自然头发”,带有黑人女性图标。相关关键词“男性”的标志是一个黑人。

本文将讨论:

  • 这种偏见是如何融入模型的
  • 高破坏性有偏模型的关键特征&例子
  • 讨论一些可能的解决方案

模型中是如何引入偏差的?

偏差可以包含在建模的所有步骤中[1,2,4],如下图所示:

如何在模型开发周期中引入偏差

高破坏性模型的关键特征

某些带有偏见的模型极具破坏性。凯茜·奥尼尔所著的《大规模杀伤性武器》一书很好地总结了这一点,因此我将在这一部分大量引用。在她的书中,她描述了有害的模型,或破坏数学的武器,是那些满足以下标准的模型:

  1. 损害——它会损害或摧毁生命吗?

许多模型输出的决策可能会产生有害的后果。例如,它可能导致人们失业,使他们陷入贫困,或者以他们根本无法承受的价格收取产品/服务的费用。

2。比例

一些模型在很大程度上控制着社会,因此对我们的生活有很大的影响。例如,信用评分模型控制着我们的财务选项,这对我们过上稳定生活的能力起着很大的作用。

3。缺乏透明度和问责制:

许多模型是“黑匣子”。这个模型的决策过程很大程度上没有被质疑,也没有被理解。该模型的基本假设甚至可能是错误的,但没有足够的透明度让人们能够指出它的不公平性并进行辩护。

促成破坏性和歧视性模式的关键因素:

  1. 使用代理区分:

很明显,如果模型明确使用人口统计变量,它会有偏差。招聘算法可能会将女性排名靠后,因为做母亲通常会影响职业表现。尽管如此,许多模型隐含歧视。通常很难获得显式数据信号,因此建模者转向隐式提供相同信号的代理。一个模特可能只使用邮政编码,但邮政编码与种族和收入相关。P2P 贷款机构通常根据与邻居、邮政编码、顾客购物的商店的相关性来制定风险评分。这些代理人不仅仅表明了更好地保证贷款偿还的责任。它们代表财富,也与种族相关。贫穷的少数群体可能有更高的借贷成本,尽管他们已经在挣扎,即使他们有责任。在另一个例子中,芝加哥警方小组列出了最有可能实施暴力犯罪的人的名单,不是基于他们的行为,而是基于他们犯罪的邻居和熟人。这些人不是根据他们自己的行为来判断的,而是因为属于社会的一个子群体而受到惩罚。

2。只关注业务目标的优化,如利润

大多数企业建立这些模型来帮助优化利润。我们在现实生活中从来没有看到一个 100%准确的模型,因为数据是有噪声的,但我们可以调整它来优化某些指标,如利润。然而,模型“错误”会给人们的生活带来高昂的代价。一个优秀的员工可能会被模型错误地预测为工作表现不佳而被解雇。此外,模型经常牺牲人性来优化利润。工人的时间表现在由优化软件控制,以实现利润最大化。他们采用在制造业中流行的“及时”原则,即物品及时到达以最小化成本。同样,这些模型预测商店何时需要员工,并根据不断变化的时间表安排员工。这种不稳定的、受商业驱动的时间表让你很难找到第二份工作或重返校园。这反过来又减少了他们通过更好的就业来摆脱这一循环的机会。

3。恶性反馈循环

有偏见的模型产生的输出有助于营造一种强化这种偏见的环境。例如,警察局使用的累犯模型可能会输出一个决定,预测来自某些种族特征的囚犯风险更大,应该被关押更长时间。然而,由于他们在监狱里的时间更长,他们回国后更难找到工作,导致再次犯罪的可能性增加。当他们这样做时,它加强了模型,它确实根据这些因素做出了正确的预测。很少有人评估受影响的最终用户是否得到了公平对待,如果没有,如何调整模型。

4。未经测试的假设

模型往往基于假设。上面解释的警察局累犯风险模型假设社会,甚至囚犯本身都会从被关更长时间中受益。然而,后来的一项研究实际上声称,将他们关押更长时间实际上会增加累犯的可能性。另一个例子是,一位名为莎拉·威索基的老师被解雇了,因为 DCPS 的“影响力”算法——用于评估教师的表现——给她打了“表现不佳”的分数。尽管如此,大多数学生对她评价很高。该模型的决定是由她的学生每年较低的标准化考试成绩驱动的。尽管没有足够的技能,学生们还是以前一年虚假的高分入学。这伤害了莎拉提高分数的能力,不管她的教学技巧如何。分数增加作为教师绩效指标背后的假设没有得到验证。

5。逆向工程使游戏系统成为可能

因为模型是基于规则做出决策的,所以那些能够逆向工程这些规则的人可以击败系统,成为误报。美国新闻学院排名是由录取率、毕业率等指标驱动的。可以说,这迫使学校提高质量。然而,这些排名往往不能反映学校的质量。操纵排名的一个方法是通过拒绝那些可能不会被录取的顶尖学生来降低录取率。此外,学校可以通过把学生算作被雇佣者来欺骗 10%的就业率,即使他们是咖啡师.或者,他们可以通过更多地关注工程和科学部门,而不是教育和社会工作部门来提高平均收入。

6。利用最终用户的漏洞

算法可以用来暴露人们的弱点,并利用他们的需求或无知。以营利性大学的丑闻为例,比如科林斯大学的。他们利用算法来锁定来自最贫困地区的学生,并点击了发薪日贷款等广告。这个群体迫切需要多挣钱的方法,所以向他们推销私人教育的帮助是很容易的。点击流数据可以提供关于他们兴趣的信息,自然语言处理可以分析他们在社交媒体上发布的关于他们关注的词语。A/B 测试可以用来优化广告以引起他们的注意。这些学院的收费比社区学院高很多倍,以吸引那些可以获得政府贷款的学生。这些学生最终背负了巨额债务,没有高质量的教育来增加收入。

可能的解决方案

提高认识: 很多人根本就不知道这个问题的存在。意识不仅对数据科学家或建模师很重要。其他角色,如投资者、商业战略家、产品经理、消费者——任何参与数据驱动产品或公司的人(目前可能占大多数%)都同样有责任塑造行业。

在建模过程中纳入公平性考虑: 建模者需要在建模过程的每一步评估公平性[2,4]。数据收集需要确保多样化的数据集,让少数群体有平等的培训机会。特征工程需要考虑显性或隐性偏差。模型需要在其他传统指标的基础上用公平指标进行评估,以确保所有群体的平等绩效和影响。当模型做出错误判断时的反馈需要回到模型中重新调整。劳动力构建这些模型是多样化的。通过这种方式,那些意识到不公平会影响到与他们相似的人的少数群体将会推动解决这个问题。

LinkedIn 在优化候选人搜索结果的排名模型时,已经努力引入公平指标。正如他们在论文 中所解释的,搜索中的公平感知排名&推荐系统及其在 LinkedIn 人才搜索中的应用【3】,他们引入了额外的约束条件,以最小化对每个属性(如种族、性别等)的期望代表比例的偏离。)显示在搜索结果中,以确保不同群体拥有平等的个人资料曝光机会。他们使用 A/B 测试进行验证,结果显示> 95%的搜索是有代表性的,而业务指标(如发送/接受的邮件数量)没有显著变化。

同样,谷歌已经开始解决他们语言翻译中的性别偏见问题[5]。他们的翻译很多都倾向于选择一个性别,比如在谈论保姆的时候选择代词‘她’,在谈论医生的时候选择‘他’。他们建立了一个模型来检测默认翻译是否做出了性别特定的选择,并建立了另一个语言模型来重写包含两种性别的版本。

自 2010 年 5 月 16 日起,谷歌将搜索翻译成土耳其语。

对这种方法的评估是通过引入一个公平性度量——偏差减少来完成的。这衡量了从以前的模型中选择性别的翻译减少了多少%。新方法减少了从匈牙利语、芬兰语、波斯语、土耳其语到英语翻译中超过 90%的偏差。

让透明度和问责制成为标准: 消费者应该能够要求大公司在如何使用分数来评判他们方面更加透明,并了解他们的分数中包含哪些内容,有权修正不准确的内容。有一些治理良好的分数的例子。信用评分虽然有时会被滥用,但它是透明的、可问责的[2]。他们结合反馈来调整模型的不准确性。它们是相对透明的——消费者有合法权利知道他们的分数是多少,他们的分数中包含什么,并被告知如何提高分数(例如减少债务)。消费者可以要求改正错误。大规模治理的模型需要更多地转向这个方向。

消费者透明度工具: 我们将受益于更多构建工具的计划,这些工具对公众开放并可供公众使用,以模拟如果他们采取某种行动,他们在各种模型中的分数会发生什么(例如,如果他们有未支付的账单,他们的信用分数会发生什么,以及较低的分数会在多大程度上影响她的买车计划)[2]。

揭露模型中偏见的举措: 模型中的偏见可以通过类似Proppublica 的消息机 众包活动这样的举措得到更多的揭露[2]。这个众包收集了不同的人从奥巴马竞选中收到的信息,用于逆向工程定向政治广告的模型。再比如 普林斯顿的网络透明与问责项目 。该项目提供了一个平台来测试自动化系统,如搜索引擎和就业安置网站,它们将如何对待不同的人物角色(例如,富人、穷人、男性、女性、精神疾病)。另一个倡议是 算法正义联盟,这是一个讨论模型偏见的平台,人们可以分享他们经历的偏见,公司可以要求对他们的模型进行偏见审计。**

政策&规定: 规定保护数据的使用需要保护新类型分数的使用情况[2]。例如,我们需要规范性格测试、健康评分、声誉评分在招聘决策中的使用。此外,需要重新考虑数据收集条例。目前,欧洲政策要求收集的任何数据都必须得到用户的批准,作为一种选择,并禁止为其他目的重复使用数据。此外,法规应要求对大规模模型进行第三方审计。

商业模式需要融入公平&包容性目标: 尽管这可能会让公司损失一些利润,但这与今天的企业社会责任努力或日益道德的商业模式(如环保)没有什么不同,它们实际上为品牌增加了价值。通过服务更广泛的人群,企业甚至可能变得更加有利可图。如果企业希望进入拥有巨大增长潜力的新兴市场,就需要为这些人群提供可获得的包容性产品。正如汉斯·罗斯林、在《真实》一书中所写的,“只关注富裕的传统市场的投资者实际上正在错失良机。有数十亿潜在的新消费者,他们的购买力在不断增长。投资者可能会错过最大的经济机会,因为他们仍然认为这个群体是“少数”或“仍然太穷”。**

来源:

[1] Krishnaram Kenthapadi, LinkedIn 在人工智能/人工智能系统中的公平和隐私 (2019) Pinterest 技术演讲

[2]凯茜·奥尼尔,大规模杀伤性武器 (2016)

[3] Sahin Cem Geyik,Stuart Ambler,Krishnaram Kenthapadi,搜索中的公平意识排名&推荐系统及其在 LinkedIn 人才搜索中的应用 (2019)

[4] Neelima Kumar,人工智能中的偏见 (2017)格蕾丝·赫柏会议

[5]梅尔文·约翰逊,减少谷歌翻译中性别偏见的可扩展方法 (2020)谷歌人工智能博客

你不用再用 Docker 了

原文:https://towardsdatascience.com/its-time-to-say-goodbye-to-docker-5cfec8eff833?source=collection_archive---------0-----------------------

意见

Docker 不是唯一的集装箱工具,可能会有更好的替代工具…

在古代的集装箱时代(真的更像 4 年前)码头工人是集装箱游戏中唯一的玩家。但现在情况不同了,Docker 不是唯一的 T4,而是另一个容器引擎。Docker 允许我们构建、运行、拉取、推送或检查容器图像,但对于这些任务中的每一项,都有其他替代工具,它们可能比 Docker 做得更好。所以,让我们探索一下前景,并且(仅仅是也许是)卸载并完全忘记 Docker

照片由妮可陈Unsplash 上拍摄

为什么不使用 Docker 呢?

如果你已经是 docker 用户很长时间了,我认为你需要一些说服来考虑转换到不同的工具。所以,现在开始:

首先,Docker 是一个单体工具。它是一个尝试做所有事情的工具,这通常不是最好的方法。大多数情况下,最好选择一个专门的工具,它只能做一件事,而且做得很好。

如果您害怕切换到不同的工具集,因为您必须学习使用不同的 CLI、不同的 API 或不同的概念,那么这不是问题。选择本文中显示的任何工具都可以是完全无缝的,因为它们都(包括 Docker)遵循 OCI 下的相同规范,这是开放容器倡议的缩写。该计划包含容器运行时容器分发容器映像的规范,涵盖了使用容器所需的所有特性。

有了 OCI,您可以选择一套最适合您需求的工具,同时您还可以享受使用与 Docker 相同的 API 和 CLI 命令的乐趣。

所以,如果你愿意尝试新的工具,那么让我们比较一下 Docker 和它的竞争对手的优缺点和特性,看看是否真的有必要考虑放弃 Docker 而使用一些新的闪亮的工具。

集装箱发动机

当将 Docker 与其他工具进行比较时,我们需要按组件对其进行分解,首先我们应该谈论的是容器引擎。Container engine 是一个工具,它提供了处理图像和容器的用户界面,这样您就不必去弄乱诸如SECCOMP规则或 SELinux 策略之类的东西。它的工作也是从远程存储库中提取图像,并将它们扩展到您的磁盘上。它看似运行容器,但实际上它的工作是创建容器清单和带有图像层的目录。然后它将它们传递给容器运行时,比如runccrun(我们稍后会谈到)。

有许多容器引擎可用,但 Docker 最突出的竞争对手是由红帽开发的。与 Docker 不同,Podman 不需要守护进程来运行,也不需要 root 权限,这是 Docker 长期关注的问题。根据名称,Podman 不仅可以运行容器,还可以运行pod。如果您不熟悉 pod 的概念,那么 pod 是 Kubernetes 的最小计算单元。它由一个或多个容器组成——主容器和所谓的侧容器——执行支持任务。这使得 Podman 用户以后更容易将他们的工作负载迁移到 Kubernetes。因此,作为一个简单的演示,这就是如何在一个单元中运行两个容器:

最后,Podman 提供了与 Docker 完全相同的 CLI 命令,因此您可以只做alias docker=podman并假装什么都没有改变。

除了 Docker 和 Podman,还有其他的容器引擎,但是我认为它们都是没有前途的技术,或者不适合本地开发和使用。但是为了有一个完整的画面,让我们至少提一下那里有什么:

  • LXD——LXD 是 LXC (Linux 容器)的容器管理器(守护程序)。这个工具提供了运行系统容器的能力,这些容器提供了更类似于虚拟机的容器环境。它位于非常狭窄的空间,没有很多用户,所以除非你有非常具体的用例,那么你可能最好使用 Docker 或 Podman。
  • CRI-O —当你在谷歌上搜索什么是 CRI-O 时,你可能会发现它被描述为容器引擎。不过,它确实是容器运行时。除了它实际上不是一台发动机之外,它也不适合的“正常”使用。我的意思是,它是专门为用作 Kubernetes 运行时(CRI)而构建的,而不是供最终用户使用的。
  • rkt — rkt ( “火箭”)是由 CoreOS 研发的集装箱发动机。这里提到这个项目实际上只是为了完整性,因为项目结束了,它的开发也停止了——因此它不应该被使用。

建筑图像

对于容器引擎,除了 Docker,真的只有一种选择。当涉及到构建图像时,我们有更多的选择。

首先,我来介绍一下 Buildah 。Buildah 是由 Red Hat 开发的另一个工具,它与 Podman 配合得非常好。如果您已经安装了 Podman,您甚至可能已经注意到了podman build子命令,它实际上只是 Buildah 的伪装,因为它的二进制文件包含在 Podman 中。

至于它的功能,它遵循与 Podman 相同的路线——它是无后台和无根的,并生成 OCI 兼容的图像,因此它保证您的图像将与用 Docker 构建的图像以相同的方式运行。它还可以从Dockerfile或者(更恰当的名称)Containerfile构建图像,这是不同名称的同一事物。除此之外,Buildah 还提供了对图像层的更好的控制,允许您将许多更改提交到单个层中。与 Docker 一个意想不到但(在我看来)很好的区别是,Buildah 构建的图像是特定于用户的,因此您将只能列出您自己构建的图像。

现在,考虑到 Buildah 已经包含在 Podman CLI 中,您可能会问为什么还要使用单独的buildah CLI?嗯,buildah CLI 是podman build中包含的命令的超集,所以你可能不需要接触buildah CLI,但是通过使用它,你可能还会发现一些额外的有用特性(关于podman buildbuildah之间的具体区别,请参见下面的文章)。

说到这里,让我们来看一个小演示:

从上面的脚本中可以看到,您可以简单地使用buildah bud构建映像,其中bud代表使用 Dockerfile* 构建,但是您也可以使用更多的脚本化方法,使用 Buildahs fromruncopy,它们是 Dockerfile 中的命令(FROM imageRUN ...COPY ...)的等价命令。*

接下来是谷歌的 Kaniko 。Kaniko 也从 Dockerfile 构建容器映像,与 Buildah 类似,它也不需要守护进程。与 Buildah 的主要区别是 Kaniko 更关注 Kubernetes 中的建筑图像。

Kaniko 应该作为一个映像运行,使用gcr.io/kaniko-project/executor,这对于 Kubernetes 来说是有意义的,但是对于本地构建来说不太方便,而且有点违背了初衷,因为您需要使用 Docker 来运行 Kaniko image 来构建您的映像。也就是说,如果您正在寻找在 Kubernetes 集群中构建映像的工具(例如在 CI/CD 管道中),那么 Kaniko 可能是一个不错的选择,因为它是无后台的,而且(也许)更加安全。

从我的个人经验来看,我使用 Kaniko 和 Buildah 在 Kubernetes/OpenShift 集群中构建图像,我认为两者都能很好地完成工作,但是在 Kaniko 中,当将图像推送到注册表时,我看到了一些随机构建崩溃和失败。

这里的第三个竞争者是 buildkit ,也可以称为下一代* docker build。它是莫比项目的一部分(Docker 也是如此),可以使用DOCKER_BUILDKIT=1 docker build ...通过 Docker 作为实验特性来启用。好吧,但这到底能给你带来什么?它引入了许多改进和很酷的特性,包括并行构建步骤、跳过未使用的阶段、更好的增量构建和无根构建。然而另一方面,它仍然需要守护进程来运行(buildkitd)。所以,如果你不想摆脱 Docker,而是想要一些新的特性和不错的改进,那么使用 buildkit 可能是一个不错的选择。*

与上一节一样,这里我们也有一些“荣誉奖”,它们填补了一些非常具体的用例,但不是我的首选:

  • Source-To-Image (S2I) 是一个不用 Dockerfile 直接从源代码构建图像的工具包。这个工具对于简单的、预期的场景和工作流工作得很好,但是如果你需要太多的定制或者如果你的项目没有预期的布局,它很快就会变得令人讨厌和笨拙。如果您对 Docker 还不是很有信心,或者如果您在 OpenShift 集群上构建您的映像,您可以考虑使用 S2I,因为使用 S2I 构建是一个内置特性。
  • Jib 是谷歌的另一个工具,专门用于构建 Java 映像。它包括 MavenGradle 插件,可以让你轻松构建图像,而不需要弄乱 docker 文件。
  • 最后但同样重要的是 Bazel ,这是谷歌的另一个工具。这不仅仅是为了构建容器映像,而是一个完整的构建系统。如果你只是想要建立一个形象,那么深入 Bazel 可能有点矫枉过正,但绝对是一个很好的学习经历,所以如果你准备好了,那么 rules_docker 部分对你来说是一个很好的起点。

容器运行时

最后一大难题是容器运行时,它负责运行容器。容器运行时是整个容器生命周期/堆栈的一部分,除非您对速度、安全性等有非常具体的要求,否则您很可能不会去弄乱它。所以,如果你已经厌倦了我,那么你可能想跳过这一节。另一方面,如果你只是想知道有哪些选择,那就这样:

runc 是基于 OCI 容器运行时规范创建的最流行的容器运行时。它被 Docker(通过 containerd )、Podman 和 CRI-O 使用,所以除了 LXD(使用 LXC)之外,它几乎什么都用。我没有什么可以补充的了。它是(几乎)所有东西的默认设置,所以即使你在读完这篇文章后放弃了 Docker,你也很可能仍然会使用 runc。

runc 的一个替代物被类似地(并且令人困惑地)命名为 crun 。这是 Red Hat 开发的工具,完全用 C 编写(runc 用 Go 编写)。这使得它比 runc 更快,内存效率更高。考虑到它也是 OCI 兼容的运行时,如果你想自己检查的话,你应该可以很容易地切换到它。尽管它现在不是很受欢迎,但它将作为 RHEL 8.3 版本的替代 OCI 运行时出现在技术预览版中,并考虑到它是我们最终可能会看到的 Podman 或 CRI-O 的默认红帽产品

说到 CRI-O,我之前说过 CRI-O 不是真正的容器引擎,而是容器运行时。这是因为 CRI-O 不包括像推送图像这样的功能,而这正是你对容器引擎的期望。CRI-O 作为一个运行时在内部使用 runc 来运行容器。这个运行时不是您应该尝试在您的机器上使用的运行时,因为它被构建为在 Kubernetes 节点上用作运行时,您可以看到它被描述为“Kubernetes 需要的所有运行时,仅此而已”。因此,除非您正在设置 Kubernetes 集群(或者 OpenShift 集群——CRI-O 已经是默认的),否则您可能不应该接触这个集群。

这部分的最后一个是 containerd ,是 CNCF 的毕业设计。它是一个守护进程,充当各种容器运行时和操作系统的 API 门面。在后台,它依赖于 runc,并且是 Docker 引擎的默认运行时。它也被 Google Kubernetes 引擎(GKE)和 IBM Kubernetes 服务(IKS)使用。它是 Kubernetes 容器运行时接口的一个实现(与 CRI-O 相同),因此它是 Kubernetes 集群运行时的一个很好的候选。

图像检查和分发

集装箱堆栈的最后一部分是图像检查和分发。这有效地取代了docker inspect,并且(可选地)增加了在远程注册中心之间复制/镜像映像的能力。

我在这里提到的唯一可以完成这些任务的工具是 Skopeo。它是由 Red Hat 制作的,是 Buildah、Podman 和 CRI-O 的配套工具。除了我们都从 Docker 了解的基本skopeo inspect之外,Skopeo 还能够使用skopeo copy复制图像,这允许您在远程注册表之间镜像图像,而无需首先将它们拖到本地注册表。如果您使用本地注册表,此功能也可以作为拉/推。

作为一个小奖励,我还想提一下 Dive ,这是一个检查、探索和分析图像的工具。它对用户更友好,提供更可读的输出,并且可以更深入地挖掘(或者我猜是潜入)你的图像,分析和衡量它的效率。它也适用于 CI 管道,可以衡量你的图像是否【足够高效】或者换句话说——是否浪费了太多空间。

结论

本文并不是要说服您完全放弃 Docker,而是向您展示构建、运行、管理和分发容器及其映像的整体情况和所有选项。包括 Docker 在内的每一种工具都有其优点和缺点,评估哪一套工具最适合您的工作流和用例非常重要,我希望这篇文章能帮助您。

资源

**本文最初发布于martinheinz . dev

* [## 将任何 Python 项目部署到 Kubernetes

是时候深入 Kubernetes,使用这个成熟的项目模板将您的 Python 项目带到云中了!

towardsdatascience.com](/deploy-any-python-project-to-kubernetes-2c6ad4d41f14) [## 分析 Docker 图像安全性

码头集装箱远没有你想象的那么安全…

towardsdatascience.com](/analyzing-docker-image-security-ed5cf7e93751) [## 你可以用 GitHub API 和 Python 做的所有事情

GitHub REST API 允许您管理问题、分支、回购、提交等等,所以让我们看看您如何使用…

towardsdatascience.com](/all-the-things-you-can-do-with-github-api-and-python-f01790fca131)*

第一次尝试 R

原文:https://towardsdatascience.com/ive-tried-r-for-the-first-time-how-bad-was-it-ba344f22e90b?source=collection_archive---------20-----------------------

空前的 Pythonista 尝试 R——包括与 Python 的比较

我是一个重度 Python 用户,这不是什么秘密。只要看看我的个人资料,你就会发现 100 多篇关于 Python 本身或数据科学中的 Python 的文章。最近,我尝试了很多新的语言和技术,其中 R 是我最抗拒的。下面你会发现我的发现,与 Python 的比较,以及对语言本身的总体看法。

Jason Coudriet 在 Unsplash 上拍摄的照片

我忽略 R 这么久的最大原因是缺乏关于这种语言的信息。我认识的每个使用过它的人都把它严格地作为一种统计语言来呈现。统计学对于数据科学来说是必不可少的,但是如果您不能通过仪表板来呈现它,并将其部署为 REST API ,那么构建模型又有什么意义呢?

这些是我最近的想法,但从那以后我发现了闪亮水管工,它们基本上解决了我最初与 R 之间的问题。也就是说,没有必要再回避这种语言了,本文是 R 系列的第一篇。

今天我们将在探索性数据分析数据可视化的过程中,通过代码和最终输出来比较 R 和 Python。我非常倾向于 Python,但是我的结论可能还是会让你吃惊。请继续阅读,寻找答案。

无论如何,让我们从比较开始,好吗?

探索性数据分析

EDA 是数据科学家花费大部分时间的地方,因此一种易于编写和易于理解的语言是必须的。我在两种语言中都使用了外部库 Python 中的Pandas和 r 中的Tidyverse

数据集加载

在本文中,我们将使用 MPG 数据集。它内置于 R 中,但是 Python 中没有相同的数据集。为了适应这种情况,我将数据集从 R 导出为 CSV 格式,这样我们就可以开始使用两种语言了。

以下是如何用 R 读取 CSV 文件:

mpg <- read.csv(‘mpg.csv’)
head(mpg)

在 R 中使用了head函数来查看前 6 行,最终结果如下所示:

让我们用 Python 做同样的事情:

mpg = pd.read_csv(‘mpg.csv’)
mpg.head()

太好了!看起来我们有一个额外的列——R 中的X和 Python 中的Unnamed: 0,所以接下来让我们移除它们。

移除属性

下面介绍如何移除 R 中不需要的X列:

mpg <- mpg 
  %>% select(-X)

这是 Python 的变体:

mpg.drop(‘Unnamed: 0’, axis=1, inplace=True)

像变量一样指定列名(不带引号)不是我最喜欢的,但事实就是如此。

过滤数据

让我们继续一些更有趣的事情——数据过滤或子集化。我们将看到如何只选择那些柱面数量cyl为 6 的记录。

带 R:

head(mpg %>%
  filter(cyl == 6))

请记住,head函数只是在这里,所以我们不会在控制台中得到大量的输出。它不是数据过滤过程的一部分。

Python 也是如此:

mpg[mpg[‘cyl’] == 6].head()

厉害!让我们看看还能做些什么。

创建派生列

我们将创建一个布尔属性is_newer,如果汽车制造于 2005 年或之后,则为真,否则为假。

下面是 R 语法:

head(mpg %>%
  mutate(is_newer = year >= 2005))

Python 也是如此:

mpg[‘is_newer’] = mpg[‘year’] >= 2005

这就是 EDA 的全部内容。接下来我们就来简单总结一下。

EDA 最终想法

很难选出一个赢家,因为两种语言都很棒。我重复一遍,对我来说不在列名周围加上引号是很奇怪的,但这是我必须习惯的事情。

此外,我非常喜欢在 r 中链接东西的简易性。

mpg <-
  read.csv(‘mpg.csv’) %>%
  select(-X) %>% 
  filter(cyl == 6) %>%
  mutate(is_newer = year >= 2005) %>%
  select(displ, year, cyl, is_newer)

在这里,我们基本上从上面做了所有的事情,所有的都在一个单一的命令中。让我们继续数据可视化部分。

数据可视化

说到数据可视化,有一点是肯定的——Python 毫无胜算!好吧,至少如果我们谈论的是两种语言的默认选项。以下库用于此比较:

  • ggplot2 —用于 R
  • matplotlib —用于 Python

让我们从一个简单的散点图开始,X 轴是发动机排量,Y 轴是公路 MPG。

下面是 R 语法和结果:

ggplot(data = mpg, aes(x = displ, y = hwy)) + 
  geom_point()

作者图片

对于 Python:

plt.scatter(x=mpg[‘displ’], y=mpg[‘hwy’])

作者图片

这两个看起来都不是特别好,但是 R 在这方面遥遥领先,至少在默认风格上是这样。

现在让我们添加一些颜色。这些点应该根据class属性进行着色,这样我们就可以很容易地知道每种类型的汽车所在的位置。

下面是 R 的语法和结果:

ggplot(data = mpg, aes(x = displ, y = hwy, color = class)) + 
  geom_point()

作者图片

没有比这更简单的了,下面的 Python 例子就是一个明显的例子。我还没有找到一种简单的方法来将分类变量映射为颜色(至少用 Matplotlib ),所以我最后得到了以下结果:

def get_color(car_class):
    colors = {
        ‘compact’   : ‘brown’,
        ‘midsize’   : ‘green’,
        ‘suv’       : ‘pink’,
        ‘2seater’   : ‘red’,
        ‘minivan’   : ‘teal’,
        ‘pickup’    : ‘blue’,
        ‘subcompact’: ‘purple’
    }
 return colors[car_class]colors = mpg[‘class’].apply(get_color) plt.scatter(x=mpg[‘displ’], y=mpg[‘hwy’], c=colors)

作者图片

所有这些都是为了一个不那么吸引人的图表。r 点。

现在,让我们通过为轴添加标题和标签来完成图表。下面是在 R 中如何做:

ggplot(data = mpg, aes(x = displ, y = hwy, color = class)) + 
  geom_point(size = 3) + 
  labs(title = ‘Engine displacement vs. Highway MPG’,
       x = ‘Engine displacement (liters)’,
       y = ‘Highway miles per gallon’)

作者图片

同样,语法相当简单,图表看起来很惊人(嗯,有点)。

下面是如何用 Python 做同样的事情:

plt.scatter(x=mpg[‘displ’], y=mpg[‘hwy’], c=colors, s=75)
plt.title(‘Engine displacement vs. Highway MPG’)
plt.xlabel(‘Engine displacement (liters)’)
plt.ylabel(‘Highway miles per gallon’)

作者图片

这取决于你来决定哪个更好看,但在我看来 R 是一个明显的赢家。当然,可视化是可以调整的,但是我特意想使用两种语言的默认库。我知道 Seaborn 看起来更好,在评论区告诉我这些是没有意义的。

对于本文来说,这就差不多了。让我们在下一部分总结一下。

最后的想法

这是在数据科学领域对 R 和 Python 的一个比较。选择一个而不是另一个不是一件简单的事情,因为两者都很棒。在这两种语言中,Python 被认为是一种通用语言,所以如果你想用数据科学来构建软件,而不是直接在数据科学中工作,它是唯一可行的选择。

这两个都不会错——尤其是当我知道 R 支持仪表板、web 抓取和 API 开发的时候。我保证会有更多这样的文章出现。

感谢阅读。

加入我的私人邮件列表,获取更多有用的见解。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

原载于 2020 年 9 月 10 日 https://betterdatascience.com

J.自动驾驶汽车

原文:https://towardsdatascience.com/j-a-c-w-i-b-autonomous-car-9c42bc732279?source=collection_archive---------43-----------------------

作者/开发者 : 乌迪特·加瓦桑罗汉·特冈卡尔阿莫德·萨哈斯·拉布德赫

非常感谢 David Tian ,他在《深度少年派汽车》系列中的工作启发我们开发了一个类似的模型。可以参考他的文章这里

介绍

自动驾驶汽车有多重要?

自动驾驶汽车是未来的事情。许多科技巨头如特斯拉、谷歌和汽车公司如优步、通用、宝马都在投资自动驾驶汽车。人们相信,在不久的将来,自动驾驶汽车将会在路上随处可见。使用经济的工具和零件来建造你自己的能够探测车道并跟随它们的自动驾驶汽车怎么样?这是我们命名为 J.A.C.W.I.B(又一辆拥有智能大脑的汽车)的汽车的清晰图像

硬件组件

  • 遥控车:我们使用了一辆使用了 3 个 DC 马达(一个用于转向,两个用于节流)的遥控车。
  • 树莓 Pi 3 型号 B+
  • 32 GB micro SD:用于部署 Raspbian OS 和 Raspberry Pi 的内存。
  • RaspberryPi 5MP 摄像头模块:支持 1080p @ 30 fps,720p @ 60 fps,640x480p 60/90 录制。
  • 电机驱动器(LM298N):用于控制 DC 电机的方向和速度。支持 1 块板 2 个直流电机的控制,能承受 1.5 A。
  • 电源组:电源组(额定电压为 5V,2.1A)为 Raspberry Pi 模块供电。
  • 电池:9V 锂离子 USB 充电电池,500mAh 容量。用于给电机驱动器供电。
  • 公对公和母对母跳线。
  • 蓝色胶带:这是这个项目的一个非常重要的组成部分,它用于制作两条车道线,汽车将在这两条车道线之间行驶。
  • 拉链
  • 螺丝刀

Raspberry Pi 设置

Raspberry Pi 操作系统

Raspberry Pi 需要一个操作系统来运行不同类型的程序。可以参考这个优秀的指南

设置远程访问

建议您设置远程访问您的 Raspberry Pi,因为您不能在汽车行驶时将其连接到外部显示器。要设置远程访问,您可以参考本指南。你也可以参考这个视频指南

设置远程文件访问

因为我们的 Raspberry Pi 是使用远程访问运行的,所以我们可以轻松地将文件传输到 Raspberry Pi 或从 Raspberry Pi 传输文件也是至关重要的。请参考本指南

在 Raspberry Pi 安装完成后,我们现在可以继续安装必要的库了。

安装 OpenCV

OpenCV ( 开源计算机视觉库)是一个高级库,包含主要针对实时计算机视觉的函数。OpenCV 的使用将使我们能够感知前方的情况,并帮助我们识别车道。在您的 Raspberry Pi 终端中运行命令(粗体)。

#Installing dependent librariespi@raspberrypi:~ $  **sudo apt-get install libhdf5-dev -y && sudo apt-get install libhdf5-serial-dev -y && sudo apt-get install libatlas-base-dev -y && sudo apt-get install libjasper-dev -y && sudo apt-get install libqtgui4 -y && sudo apt-get install libqt4-test -y**# install OpenCV
pi@raspberrypi:~ $ **pip3 install opencv-python**
Collecting opencv-python
[Omitted....]
Installing collected packages: numpy, opencv-python
Successfully installed numpy-1.16.2 opencv-python-3.4.4.19

通过运行以下代码测试 OpenCV 安装。

pi@raspberrypi:~ $ **python3 -c "import cv2"**

如果在运行该命令时没有看到任何错误,则库应该安装正确。

硬件装配

Raspberry Pi +电机驱动器装配示意图

上图显示了 Raspberry Pi、Raspberry Pi 摄像头模块和 LM298N 电机驱动器之间的连接。因为我们希望控制两个马达的节流速度,所以我们将它们连接到同一个端口。这些连接是借助公-公和母-母跳线完成的。摄像头模块安装在汽车的前格栅上。

Raspberry Pi GPIO 引脚配置

  • ENA — GPIO 25
  • IN1 — GPIO 23
  • IN2 — GPIO 24
  • IN3 — GPIO 17
  • IN4 — GPIO27
  • ENB — GPIO22

测试零件

完成所有连接后,我们将测试它们以确保所有连接都是正确的。

测试摄像机

在您的 Raspberry Pi 上打开一个新的 python 文件,并键入以下内容。

import cv2video = cv2.VideoCapture(0)while True:
  ret,frame = video.read()
  cv2.imshow('original',frame)
  cv2.imwrite('original.jpg',frame)

  key = cv2.waitKey(1) #wait for 1 ms for any keyboard button
  if key == 27:
     breakvideo.release()
cv2.destroyAllWindows()

第一行是导入我们的 OpenCV 库并使用它的函数。VideoCapture(0)功能从信号源开始传输实时视频。所提供的参数为“0 ”,这意味着我们使用默认摄像机,即本例中的 Raspberry Pi 摄像机。video.read()将读取来自摄像机的每一帧,并将其保存在一个名为“frame”的变量中。函数 imshow()将显示以单词“original”开头的帧,函数 imwrite()将在我们的存储设备上将“帧”存储为“original.jpg”。如果按下“esc”按钮,将返回十进制值 27,并相应地中断循环。

测试电机

我们需要测试马达,以检查速度并了解马达旋转的方向。在您的 Raspberry Pi 上运行以下代码来检查电机速度和方向。

**import** RPi.GPIO **as** GPIO          
**from** time **import** sleep

in1 = 24
in2 = 23
in3 = 17
in4 = 27
en1 = 25
en2 = 22
temp1=1

GPIO.setmode(GPIO.BCM)
GPIO.setup(in1,GPIO.OUT)
GPIO.setup(in2,GPIO.OUT)
GPIO.setup(in3,GPIO.OUT)
GPIO.setup(in4,GPIO.OUT)
GPIO.setup(en1,GPIO.OUT)
GPIO.setup(en2,GPIO.OUT)
GPIO.output(in1,GPIO.LOW)
GPIO.output(in2,GPIO.LOW)
GPIO.output(in3,GPIO.LOW)
GPIO.output(in4,GPIO.LOW)
p=GPIO.PWM(en1,1000)
q=GPIO.PWM(en2,1000)

p.start(75)
q.start(75)
print(**"\n"**)
print(**"The default speed & direction of motor is LOW & Forward....."**)
print(**"r-run x-stop w-forward s-backward a-left d-right m-medium e-exit f-front"**)
print(**"\n"**)    

**while**(1):

    x=raw_input()

    **if** x==**'r'**:
        print(**"run"**)
        **if**(temp1==1):
         GPIO.output(in1,GPIO.HIGH)
         GPIO.output(in2,GPIO.LOW)
         GPIO.output(in3,GPIO.HIGH)
         GPIO.output(in4,GPIO.LOW)

         print(**"forward"**)
         x=**'z'
        else**:
         GPIO.output(in1,GPIO.LOW)
         GPIO.output(in2,GPIO.HIGH)
         GPIO.output(in3,GPIO.LOW)
         GPIO.output(in4,GPIO.HIGH)

         print(**"backward"**)
         x=**'z'

    elif** x==**'x'**:
        print(**"stop"**)
        GPIO.output(in1,GPIO.LOW)
        GPIO.output(in2,GPIO.LOW)
        GPIO.output(in3,GPIO.LOW)
        GPIO.output(in4,GPIO.LOW)

        x=**'z'

    elif** x==**'w'**:
        print(**"forward"**)
        GPIO.output(in1,GPIO.HIGH)
        GPIO.output(in2,GPIO.LOW)
        temp1=1
        x=**'z'

    elif** x==**'s'**:
        print(**"backward"**)
        GPIO.output(in1,GPIO.LOW)
        GPIO.output(in2,GPIO.HIGH)
        temp1=0
        x=**'z'

    elif** x==**'d'**:
        print(**"right"**)
        GPIO.output(in3,GPIO.LOW)
        GPIO.output(in4,GPIO.HIGH)
        temp1=1
        x=**'z'

    elif** x==**'a'**:
        print(**"left"**)
        GPIO.output(in3,GPIO.HIGH)
        GPIO.output(in4,GPIO.LOW)
        temp1=0
        x=**'z'

    elif** x==**'f'**:
        print(**"front"**)
        GPIO.output(in3,GPIO.LOW)
        GPIO.output(in4,GPIO.LOW)
        temp1=0
        x=**'z'

    elif** x==**' '**:
        print(**"brake"**)
        GPIO.output(in1,GPIO.LOW)
        GPIO.output(in2,GPIO.LOW)   
        x=**'z'

    elif** x==**'m'**:
        print(**"medium"**)
        p.ChangeDutyCycle(50)
        q.ChangeDutyCycle(50)
        x=**'z'

    elif** x==**'e'**:
        GPIO.cleanup()
        print(**"GPIO Clean up"**)
        **break

    else**:
        print(**"<<<  wrong data  >>>"**)
        print(**"please enter the defined data to continue....."**)

使能引脚从 Raspberry Pi 获取脉宽调制(PWM)输入信号,并相应地运行电机。例如,100% PWM 信号表示我们正在以最大速度工作,0% PWM 信号表示电机不旋转。您可以使用 ChangeDutyCycle()函数进行调整。如果万一你的马达在相反的方向上运转,那么只要颠倒极性。如果电机根本不起作用,那么再次测试你的硬件连接。参考此文档了解更多关于 Raspberry Pi GPIO 引脚配置的信息。

我们已经完成了测试。现在是开始实际编程的时候了!

车道导航

使用了由 David Tian 开发的车道检测算法,我们将在这里分模块进行解释。

转换到 HSV 空间

我们将图像使用的颜色空间,即 RGB(红/绿/蓝)转换为 HSV(色调/饱和度/值)颜色空间。这样做的主要优点是通过颜色的亮度来区分颜色。

检测蓝色和边缘

使用蓝色车道的原因是在我们制造汽车的地方不常见。为了从 HSV 帧中提取蓝色,应该提到色调、饱和度和值的范围。为了减少每一帧中的整体失真,使用 Canny 边缘检测器检测边缘。你可以参考更多关于精明的在这里

**def** detect_edges(frame):
    *# filter for blue lane lines* hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)lower_blue = np.array([90, 120, 0], dtype=**"uint8"**)
    upper_blue = np.array([150, 255, 255], dtype=**"uint8"**)
    mask = cv2.inRange(hsv, lower_blue, upper_blue) *# detect edges* edges = cv2.Canny(mask, 50, 100)**return** edges

选择感兴趣区域

我们可以观察到,在我们的框架中也会出现其他蓝色。我们只需要隔离车道,因为这是我们希望关注的部分。

**def** region_of_interest(edges):
    height, width = edges.shape
    mask = np.zeros_like(edges) *# only focus lower half of the screen* polygon = np.array([[
        (0, height),
        (0, height / 2),
        (width, height / 2),
        (width, height),
    ]], np.int32) cv2.fillPoly(mask, polygon, 255) cropped_edges = cv2.bitwise_and(edges, mask)
    cv2.imshow(**"roi"**, cropped_edges) **return** cropped_edges

隔离感兴趣区域

检测线段

霍夫变换用于检测帧中的任何形状,如果我们用数学形式表示它的话。在我们的例子中,我们需要检测线条。它也可以处理轻微扭曲的形状。更多关于霍夫变换的内容可以参考这里的

**def** detect_line_segments(cropped_edges):
    rho = 1
    theta = np.pi / 180
    min_threshold = 10 line_segments = cv2.HoughLinesP(cropped_edges, rho, theta, min_threshold,np.array([]), minLineLength=5, maxLineGap=150) **return** line_segments

HoughLinesP()函数采用以下参数:

  • Frame:是我们要在其中检测线条的框架。在我们的例子中,它是裁剪边
  • rho:是以像素为单位的距离精度。
  • θ:角度精度,单位为弧度(始终= π/180 ~ 1 度)
  • min_threshold 是被认为是线段所需的投票数。如果一条线有更多的投票,霍夫变换认为它们更有可能检测到线段。
  • maxLineGap:被视为一行的两行之间的最大像素间距。

计算转向角度

我们知道直线的方程是 y=mx+b,其中 m 是直线的斜率, b 是 y 截距。将计算使用霍夫变换检测的线段的斜率和截距的平均值。左车道线有 x₁ < x₂y₂ < y₁ 和坡度,m= (y₂ — y₁) / (x₂ — x₁) 会给出负坡度。右边的车道则完全相反。右侧车道有 xt28】x和 yt29】y这将给出一个正斜率。在垂直线的情况下(x = x ),斜率将为无穷大。在这种情况下,我们将跳过所有垂直线,以防止出现错误。为了准确地检测车道,通过边界线将帧分成两个区域,右边和左边。

**def** average_slope_intercept(frame, line_segments):
    lane_lines = [] **if** line_segments **is None**:
        print(**"no line segments detected"**)
        **return** lane_lines height, width, _ = frame.shape
    left_fit = []
    right_fit = [] boundary = 1 / 3
    left_region_boundary = width * (1 - boundary)
    right_region_boundary = width * boundary **for** line_segment **in** line_segments:
        **for** x1, y1, x2, y2 **in** line_segment:
            **if** x1 == x2:
                print(**"skipping vertical lines"**)
                **continue**fit = np.polyfit((x1, x2), (y1, y2), 1)
            slope = (y2 - y1) / (x2 - x1)
            intercept = y1 - (slope * x1) **if** slope < 0:
                **if** x1 < left_region_boundary **and** x2 < left_region_boundary:
                    left_fit.append((slope, intercept))
            **else**:
                **if** x1 > right_region_boundary **and** x2 > right_region_boundary:
                    right_fit.append((slope, intercept)) left_fit_average = np.average(left_fit, axis=0)
    **if** len(left_fit) > 0:
        lane_lines.append(make_points(frame, left_fit_average)) right_fit_average = np.average(right_fit, axis=0)
    **if** len(right_fit) > 0:
        lane_lines.append(make_points(frame, right_fit_average)) **return** lane_lines

make_points()是 average_slope_intercept()函数的辅助函数,它将返回车道线的有界坐标。

**def** make_points(frame, line):
    height, width, _ = frame.shape slope, intercept = line y1 = height  *# bottom of the frame* y2 = int(y1 / 2)  *# make points from middle of the frame down***if** slope == 0:
        slope = 0.1 x1 = int((y1 - intercept) / slope)
    x2 = int((y2 - intercept) / slope) **return** [[x1, y1, x2, y2]]

要在帧上显示车道线,使用以下函数

**def** display_lines(frame, lines, line_color=(0, 255, 0), line_width=6):
    line_image = np.zeros_like(frame) **if** lines **is not None**:
        **for** line **in** lines:
            **for** x1, y1, x2, y2 **in** line:
                cv2.line(line_image, (x1, y1), (x2, y2), line_color, line_width) line_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1) **return** line_image

现在,在将速度应用到我们的电机之前,最重要的步骤是计算转向角。我们需要确保汽车准确地停留在检测到的车道线的中间。我们可能会遇到两种情况:

  • 两条检测到的车道线
  • 单条检测车道线

计算航向线是使用三角函数 tan 和 atan(即 tan⁻)。

**def** get_steering_angle(frame, lane_lines):
    height, width, _ = frame.shape **if** len(lane_lines) == 2:
        _, _, left_x2, _ = lane_lines[0][0]
        _, _, right_x2, _ = lane_lines[1][0]
        mid = int(width / 2)
        x_offset = (left_x2 + right_x2) / 2 - mid
        y_offset = int(height / 2) **elif** len(lane_lines) == 1:
        x1, _, x2, _ = lane_lines[0][0]
        x_offset = x2 - x1
        y_offset = int(height / 2) **elif** len(lane_lines) == 0:
        x_offset = 0
        y_offset = int(height / 2) angle_to_mid_radian = math.atan(x_offset / y_offset)
    angle_to_mid_deg = int(angle_to_mid_radian * 180.0 / math.pi)
    steering_angle = angle_to_mid_deg + 90
    *#print(steering_angle)***return** steering_angle

标题线显示如下。

**def** display_heading_line(frame, steering_angle, line_color=(0, 0, 255), line_width=5):
    heading_image = np.zeros_like(frame)
    height, width, _ = frame.shape steering_angle_radian = steering_angle / 180.0 * math.pi x1 = int(width / 2)
    y1 = height
    x2 = int(x1 - height / 2 / math.tan(steering_angle_radian))
    y2 = int(height / 2) cv2.line(heading_image, (x1, y1), (x2, y2), line_color, line_width)
    heading_image = cv2.addWeighted(frame, 0.8, heading_image, 1, 1) **return** heading_image

使用套筒传递转向角度

既然我们已经计算了转向角度,我们需要利用这个角度来驾驶我们的汽车。从技术上来说,你可以在 Raspberry Pi 上运行车道检测算法。然而,上述处理对于 Raspberry Pi 来说可能太重,可能会导致延迟。这可能会产生不准确的结果。为了解决这个问题,我们使用我们的笔记本电脑/个人电脑的处理能力,并利用插座。因此,输入相机流(使用 Raspberry Pi 相机模块捕获)从插座到达笔记本电脑/PC,在那里执行上述车道检测和转向角计算。以下代码显示了套接字程序的用法以及如何调用通道检测模块。

ser_soc = socket.socket()
ser_soc.bind((**'192.168.2.11'**, 5500))
ser_soc.listen(2)
conn, address = ser_soc.accept()**class** VideoStreamingTest(object):
    **def** __init__(self, host, port): self.server_socket = socket.socket()
        self.server_socket.bind((host, port))
        self.server_socket.listen(1)
        self.connection, self.client_address = self.server_socket.accept()
        self.connection = self.connection.makefile(**'rb'**)
        self.host_name = socket.gethostname()
        self.host_ip = socket.gethostbyname(self.host_name)
        self.streaming() **def** streaming(self): **try**:
            print(**"Host: "**, self.host_name + **' '** + self.host_ip)
            print(**"Connection from: "**, self.client_address)
            print(**"Streaming..."**)
            print(**"Press 'q' to exit"**) *# need bytes here* stream_bytes = **b' '
            while True**:
                stream_bytes += self.connection.read(1024)
                first = stream_bytes.find(**b'\xff\xd8'**)
                last = stream_bytes.find(**b'\xff\xd9'**)
                **if** first != -1 **and** last != -1:
                    jpg = stream_bytes[first:last + 2]
                    stream_bytes = stream_bytes[last + 2:]
                    frame = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
                    edges = detect_edges(frame)
                    roi = region_of_interest(edges)
                    line_segments = detect_line_segments(roi)
                    lane_lines = average_slope_intercept(frame, line_segments)
                    lane_lines_image = display_lines(frame, lane_lines)
                    steering_angle = get_steering_angle(frame, lane_lines) *#pass value through socket* print(steering_angle)
                    server_program(steering_angle)
                    heading_image = display_heading_line(lane_lines_image, steering_angle)
                    cv2.imshow(**"heading line"**, heading_image) **if** cv2.waitKey(1) & 0xFF == ord(**'q'**):
                        **break** **finally**:
            self.connection.close()
            self.server_socket.close()**if** __name__ == **'__main__'**:
    *# host, port* h, p = **"192.168.2.11"**, 8000
    VideoStreamingTest(h, p)

发送套接字程序如下所述:

**def** server_program(data):
    data = str(data)
    conn.send(data.encode())  *# send data to the Raspberry Pi*

你可以在这里了解更多关于套接字编程的知识。

注意:您的 Raspberry Pi 和笔记本电脑需要连接到同一个网络来传输数据。

驾驶汽车

我们现在需要将 Pi 摄像机捕获的视频流发送到我们的主机。为此,我们将编写以下代码。

**import** io
**import** socket
**import** struct
**import** time
**import** picamera

*# create socket and bind host* client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((**'192.168.2.11'**, 8000))
connection = client_socket.makefile(**'wb'**)

**try**:
    **with** picamera.PiCamera() **as** camera:
        camera.resolution = (320, 240)      *# pi camera resolution* camera.framerate = 15               *# 15 frames/sec* time.sleep(2)                       *# give 2 secs for camera to initilize* start = time.time()
        stream = io.BytesIO()

        *# send jpeg format video stream* **for** foo **in** camera.capture_continuous(stream, **'jpeg'**, use_video_port = **True**):
            connection.write(struct.pack(**'<L'**, stream.tell()))
            connection.flush()
            stream.seek(0)
            connection.write(stream.read())
            **if** time.time() - start > 600:
                **break** stream.seek(0)
            stream.truncate()

    connection.write(struct.pack(**'<L'**, 0))

**finally**:
    connection.close()
    client_socket.close()

现在,一旦我们的初始程序计算出转向角,我们需要接收它来执行一些动作。因此,我们将编写以下代码

**import** socket
**import** math
**import** sys
**import** time
**import** RPi.GPIO **as** GPIO

**def** client_program():

    cli_soc = socket.socket()  *# instantiate* cli_soc.connect((**'192.168.2.11'**, 5500))

    **while True**:

        data = cli_soc.recv(1024).decode()  *# receive response* print(**'Received from server: '** + data)  *# show in terminal* steering_angle = int(data)

        speed = 20
        lastTime = 0
        lastError = 0

        now = time.time()
        dt = now - lastTime

        kp = 0.4
        kd = kp * 0.65

        deviation = steering_angle - 90
        error = abs(deviation)

        **if** deviation < 10 **and** deviation > -10:
            deviation = 0
            error = 0
            GPIO.output(in1,GPIO.LOW)
            GPIO.output(in2,GPIO.LOW)
            steering.stop()

        **elif** deviation > 10:
            GPIO.output(in1,GPIO.LOW)
            GPIO.output(in2,GPIO.HIGH)
            steering.start(100)

        **elif** deviation < -10:
            GPIO.output(in1,GPIO.HIGH)
            GPIO.output(in2,GPIO.LOW)
            steering.start(100)

        derivative = kd * (error - lastError) / dt
        proportional = kp * error
        PD = int(speed + derivative + proportional)
        spd = abs(PD)
        print(spd)

        **if** spd > 35:
            spd = 35

        throttle.start(spd)

        lastError = error
        lastTime = time.time()

    cli_soc.close()  *# close the connection* **if** __name__ == **'__main__'**:
    GPIO.setwarnings(**False**)

    *#throttle* throttlePin = 25 *# Physical pin 22* in3 = 24 *# physical Pin 16* in4 = 23 *# physical Pin 18

    #Steering of front wheels* steeringPin = 22 *# Physical Pin 15* in1 = 17 *# Physical Pin 11* in2 = 27 *# Physical Pin 13* GPIO.setmode(GPIO.BCM)
    GPIO.setup(in1,GPIO.OUT)
    GPIO.setup(in2,GPIO.OUT)
    GPIO.setup(in3,GPIO.OUT)
    GPIO.setup(in4,GPIO.OUT)

    GPIO.setup(throttlePin,GPIO.OUT)
    GPIO.setup(steeringPin,GPIO.OUT)

    *# Steering
    # in1 = 1 and in2 = 0 -> Left* GPIO.output(in1,GPIO.LOW)
    GPIO.output(in2,GPIO.LOW)
    steering = GPIO.PWM(steeringPin,1000)
    steering.stop()

    *# Throttle
    # in3 = 1 and in4 = 0 -> Forward* GPIO.output(in3,GPIO.HIGH)
    GPIO.output(in4,GPIO.LOW)
    throttle = GPIO.PWM(throttlePin,1000)
    throttle.stop()

    client_program()

    GPIO.output(in1,GPIO.LOW)
    GPIO.output(in2,GPIO.LOW)
    GPIO.output(in3,GPIO.LOW)
    GPIO.output(in4,GPIO.LOW)
    throttle.stop()
    steering.stop()

这里,由于我们使用 DC 电机作为转动机构,我们计算了偏差。

执行步骤

查看我们的 GitHub 页面,下载项目并参考执行步骤。

怎么开车

  1. 连接:使用远程桌面连接将 Raspberry Pi 连接到主机,以通过主机控制 Raspberry Pi。
  2. 测试:在树莓 Pi 终端执行test_drive.py程序,检查汽车的油门和方向。
  3. 初始化服务器:在主机上,执行computer_server.py
  4. 初始化客户端:在 Raspberry Pi 上同时执行两个客户端程序,分别是raspi_client_1.pyraspi_client_2.py。此时,主机将开始根据raspi_client_2.py从树莓派接收到的视频流计算转向角度,并通过 socket 发送回来,由raspi_client_1.py客户端接收。
  5. 自驾在行动:基于转向角度,程序raspi_client_1.py会给树莓 Pi 的 GPIO 引脚发出指令,让电机运行(电机用来驱动汽车的车轮)。因此,汽车将开始在指定的车道上自主行驶。
  6. 自驾在行动:基于转向角度,程序raspi_client_1.py会给树莓 Pi 的 GPIO 引脚发出指令,让电机运行(电机用来驱动汽车的车轮)。因此,汽车将开始在指定的车道上自主行驶。

结果

查看我们的 YouTube 视频,了解自动驾驶汽车的运行情况!

未来的工作

在写这篇文章的时候,因为新冠肺炎·疫情,我们被封锁了。一旦封锁停止,我们的下一步是在车上安装一个超声波传感器。在这里,我们可以计算汽车和障碍物之间的距离。在此基础上,我们可以调整我们的汽车,使其在检测到障碍物时以某种方式发挥作用。

非常感谢您完整地阅读我们的文章!这碰巧是我们第一次就自己开发的项目写文章,所以这种体验相当令人兴奋。我们希望你喜欢它,并尝试建立自己的类似的东西。如果您对此有任何疑问,请提出问题,我们将尽力回答您的问题。

再次感谢!

雅可比迭代和谱半径

原文:https://towardsdatascience.com/jacobi-iteration-and-spectral-radius-b35d33f95573?source=collection_archive---------18-----------------------

求解大型线性方程组的一种方法。

资料来源:Huskyherz,via pixabay (CCO)

数值分析的主要支柱之一是求解大型线性方程组。为了解决这种系统,数值分析人员实施了多种方法;然而,我们今天要看的是雅可比迭代。

问题陈述:

大型线性系统可以很容易地用“Ax=b”形式的矩阵表示,其中“A”表示包含线性方程组有序系数的方阵,“x”表示所有不同的变量,“b”表示每个线性方程等于的常数。我们希望求解未知的 x 值,我们可以通过使用雅可比迭代来实现。

雅可比迭代:

为了全面理解雅可比迭代,我们必须首先理解不动点迭代。这两种方法使用相同的方案,但是雅可比迭代可以应用于更大的方程组。在不动点迭代中,主要思想是取一个方程,用 Xn+1 = F(Xn)来排列,这样从某个初始 x 值(Xn)开始,代入 F(Xn)方程,我们得到一个新值(Xn+1),然后用这个新值作为下一个 x 值代入 F(Xn),以此类推。我们可以重复这个过程,直到方程的两边变得相等或大致相等,在这种情况下,我们就达到了我们的不动点解。下面是一个算出的小例子。这种方法并不总是收敛,并且有某些测试来确定它是否会收敛;然而,我们将坚持用这个简单的解释来总结现在的主要思想。

现在,让我们看看在下面的例子中 Jacobi 迭代利用不动点迭代原理的方式。

方程组示例:

对于雅可比迭代,就像普通的不动点迭代一样,我们感兴趣的是获得一个方程,并重新排列它,使它采用 Xn+1 = F(Xn)的形式。唯一的区别是,使用雅可比迭代,我们不只是对一个方程进行迭代,而是对方程组中的每个方程进行迭代,因此每个方程都等于一个唯一的变量(一个方程等于 x1,另一个方程等于 x2,依此类推)。方程式的重组如下所示。

左边的方程组和右边的方程组没有什么不同。右边的系统是这样写的,更容易展示我们迭代这些方程的方式,以及它与定点迭代的关系。

为了迭代这个系统,我们可以从 X1、X2 和 X3 的一组初始值开始,并将这些值代入我们的方程。然后,我们可以使用我们的新值,并再次将它们放回等式中。如下所示,对最初的几次迭代重复这个过程。

假设我们的方程组使用雅可比迭代收敛,如果我们继续这个过程,最终我们将收敛到我们的解,或者合理地接近给定的容差。虽然从概念上讲,这个过程非常简单,但是在检查收敛是否实际可行时,还是有一点细微的差别。

形式雅可比迭代方程:

雅可比迭代法可以用下面的等式来概括。“A”变量代表系数矩阵“A”的元素,“x”变量代表我们正在求解的未知 x 值,“b”代表每个方程的常数。

通过应用上面的雅可比迭代方程,我们得到了与之前在讨论不动点迭代和雅可比迭代之间的关系时从概念上导出的结论相同的结论。

我们的雅可比迭代公式的结果(左)。我们的 Jacobi 迭代的结果从概念上导出(右)。两者产生相同的结果,雅可比迭代公式只是使计算更简单,如果我们有一个非常大的线性系统。

什么是“T”矩阵?为什么重要?:

虽然雅可比迭代的实现非常简单,但是该方法不会总是收敛到一组解。由于这个事实,在实现雅可比迭代之前必须进行收敛测试。这个收敛测试完全依赖于一个叫做“T”矩阵的新矩阵。以雅可比迭代的矩阵表示为例。

我们可以把这个方程组重新写成这样,把整个系统分解成“Xn+1 = TXn + c”的形式。换句话说,我们可以将等式右边的矩阵分解成系数矩阵和常数矩阵。流程如下所示。稍后将会展示为什么为了测试收敛性,将我们的方程组变成这种形式(Xn+1=TXn + c)是至关重要的。

对于我们的具体例子,分解成这种形式的雅可比迭代矩阵将完全等价于

其中:

虽然上面的推导对于理解矩阵“T”的来源非常有用,但是没有必要每次都这样做以便实际找出矩阵“T”是什么。更确切地说,下面的步骤可以用来以更加简单和及时的方式填充“T”矩阵的每个元素。

这里小写的“a”代表我们更大的系数矩阵 a 的元素。

“T”矩阵极其重要,因为我们的雅可比迭代方法收敛所需要的就是我们的矩阵“T”的谱半径严格小于 1。

方阵的谱半径简单地定义为其特征值的最大绝对值。下面的证明展示了为什么我们首先求解矩阵“T”是如此重要,以及它与谱半径的关系如何创造了谱半径必须小于 1 的条件,如果我们希望看到我们的方法收敛的话。

雅可比迭代的收敛性检验:

既然我们知道了如何测试收敛性(更重要的是,我们为什么要使用这种特定的测试),我们就可以用我们的示例方程组来这样做了。我们已经解决了前面的“T”矩阵,所以剩下要做的就是找到它的所有特征值,并确保它们的绝对值严格小于 1。

下面列出了我们示例中“T”矩阵的特征值。

因为它们的绝对值都小于 1,我们的 Jacobi 迭代方法将收敛,剩下要做的就是实现一些 Python 代码来为我们运行迭代。

实施:

import math
import numpy as npdef JacobiIteration(n):
    x1 = np.zeros(n)
    x2 = np.zeros(n)
    x3 = np.zeros(n)

    for i in range(0,n-1):
        x1[i+1] = -x2[i] - 0.5*x3[i] + 3
        x2[i+1] = 0.5*x1[i] - 0.5*x3[i] + 1.5
        x3[i+1] = -0.5*x1[i] - x2[i] + 3.5
    print ("Our x1 value is",x1[-1],
           "\nOur x2 value is",x2[-1],
           "\nOur x3 value is",x3[-1])JacobiIteration(60)

在大约 60 次迭代之后,对于我们所有的 x 值,从最初的零猜测开始,我们可以看到,在给定计算机机器精度的情况下,我们已经收敛到我们的解。

在左边的图像中,我们可以看到每次迭代的输出。这仅仅是大约 30 次迭代,我们仍然处于极高的精确度之内。数组从上到下的顺序是 x1、x2、x3。他们一行一行地读,从左到右。

这就是雅可比迭代的全部内容。我们得到一个方程组,稍微重新排列一下,测试一下收敛性,运行一点代码,然后我们就完成了。

引用:

伯顿、理查德·l 和 j·道格拉斯。费尔斯。数值分析,作者理查德·l·伯顿,j·道格拉斯·费尔斯。第 9 版。布鲁克斯/科尔出版社,2010 年。第 452 页

Hector D. Ceniceros,2020 年,第 10.9 章:线性迭代方法的收敛性,讲义,数值分析 104B,加州大学圣巴巴拉分校,2020 年 2 月发表。

数据智商 100 —面试

原文:https://towardsdatascience.com/jan-teichmann-dataiq-100-interview-9339b9572010?source=collection_archive---------45-----------------------

《数据 2020》中最具影响力的人物

https://www.dataiq.co.uk/dataiq100

能够入选 DataIQ 100 最具影响力的数据和分析从业者名单,我感到非常荣幸。更广泛的社区对我的工作、经历和观点的兴趣让我深感谦卑。这是我在采访中不得不说的话(原载于https://www . data IQ . co . uk/data IQ 100/Jan-teichmann-consultant-the train line com):

Jan Teichmann,顾问

通往权力的道路

像许多早期的数据科学家一样,我被好奇心、创新和技术所驱使;这和对数学的热情。起初,我在学术界看到了自己的使命。当我作为一名科学家成熟起来,并完成了我的数学博士学位时,我意识到我也有很强的企业家精神。因此,我与能源行业的朋友共同创办了一家初创公司,目的是利用新兴的云技术提供数据产品,并怀着改造整个公用事业行业的谦卑雄心。梦想远大,从小处着手。我们庆祝了 Enechange.jp 的成功退出,这是一个公用事业比较平台,现在是日本的市场领导者。

今天,数据转换在每个行业都有回响,但在当时,人们大开眼界,看到了数据和机器学习在新兴智能能源领域的力量。这成为我后来工作中反复出现的主题,数据和机器学习继续对企业和消费者体验产生真正的影响。在我建立自己的咨询公司 DataSonic 之前,我为 Rank Group PLC 和 Zoopla 建立并管理数据科学团队。我目前正在与 Trainline 合作一些激动人心的新数据驱动创新项目。

迄今为止,你职业生涯中最值得骄傲的成就是什么?

在数据科学领域,没有一个职业是相同或容易的,我对自己迄今为止的整个旅程感到非常自豪。我喜欢挑战,因此我也有自己的错误和失败。更广泛的社区对我的工作、经历和观点的兴趣让我感到荣幸和谦卑。我从未期望任何人会阅读我的博客帖子,我更没有期望会出现在由 Dataiku 制作的关于数据科学先驱的纪录片中。

谁是你的榜样或你寻求灵感的人?

作为一名数据科学家,我站在一个一流的开源社区的肩膀上,我从这个活跃的社区中汲取了许多灵感和知识。然而,我最初关于商业上成功的大规模数据科学的许多想法是基于 Ted Dunning 和 Ellen Friedman 的书籍和文章,他们是我个人的数据科学英雄。

2019 年的结果是你预想的那样吗?如果不是,在哪些方面有所不同?

2019 年,证明数据变革价值的公司数量继续增长。但是,最重要的是,现在出现了最佳实践、平台和工具包的新兴标准,这大大降低了数据科学团队的准入门槛和价格。这使得公司和从业者更容易接触到数据科学。现在,跨职能团队正在研究算法,一直到全栈数据产品,重点是研究、商业应用、实验、可解释性、算法公平性和数据伦理。2019 年,数据科学终于开始从炒作转向更加务实、注重价值的交付模式。

你认为 2020 年的数据和分析行业会是什么样子?

尽管 2019 年取得了所有进展,但数据专家很难找到工作。在过去的十年中,85%的大数据和数据科学项目未能产生业务影响,许多团队因此被解散。虽然这个领域和行业从膨胀的预期中学到了很多,但我们仍处于谨慎再投资阶段的早期。虽然不缺乏数据科学家,但许多企业很难找到合格的领导者和管理者,他们这次可以开辟一条更加成功和可持续的道路。这可能会阻碍 2020 年的数据投资。

数据和技术正在改变商业、经济和社会——你认为由此产生的最大机遇是什么?

数据科学和机器学习模型极大地降低了 B2B 的风险和成本,并为 B2C 创造了全新的产品和收入流。炒作已经越来越多地证明了自己,人工智能的最新进展正在达到一个从 R&D 到现实世界应用的突破点。

然而,数据科学迄今为止主要受益于 B2B 和高科技公司。最大的机会在于正在进行的数据科学和数据技术的民主化,以更有利于消费者和更广泛的社会的方式重新定义所有数据的价值交换。

在确保数据成为数字化转型战略的核心方面,您面临的最大技术挑战是什么?

重要的是要记住,数据科学是在科学和技术不断创新的基础上不断发展的。然而,这并不是什么新鲜事,技术债务、数据基础设施不足和模型的生产部署等当今的挑战自数据科学家出现以来就一直存在。我确实看到了数据领域不断加速的创新带来的最大挑战。对于企业和从业者来说,保持数据投资的更新和未来证明变得越来越具有挑战性。

在 LinkedIn 上连接:【https://www.linkedin.com/in/janteichmann/】

阅读其他文章:https://medium.com/@jan.teichmann

一月版:强化学习

原文:https://towardsdatascience.com/january-edition-reinforcement-learning-c4501b6e854a?source=collection_archive---------25-----------------------

图片来源: OpenAI

新年快乐,欢迎来到 TDS 的新十年。随着新十年的开始,有必要回顾一下不久前的过去。虽然数据科学和机器学习的大多数理论自 20 世纪 60 年代以来就已经存在,但正是从 21 世纪初开始的“大数据”的可用性推动了数据科学和机器学习在每个主要行业中无与伦比的增长和成功。

今天,这一里程碑已经过去 20 年了,直到 2010 年代中期,大多数进展都是在“经典”机器学习方面,这些机器学习能够通过 100 到 10,000 个训练样本取得良好的结果。然而,从 2010 年代中期开始,数据集规模的爆炸为深度学习模型铺平了道路,这些模型能够显著优于上一代。但从昨天开始,就连深度学习也有了 2010 年的感觉。那么接下来会发生什么呢?

显然,这肯定需要更多的数据。也许是无限数据?向强化学习问好——街区的新成员。强化学习可能是实现人工通用智能(AGI)的最热门候选人,但它对数据的渴望迄今为止一直阻碍着它。强化学习主要应用于游戏或机器人等可以产生几乎无限量数据的场景,这并非巧合。

听起来很酷——但是什么是强化学习,我为什么要关心?好吧,你来对地方了,我们收集了八篇好文章来帮助你开始强化学习之旅。第一篇文章涵盖了基础知识,然后我们提供了一些教程和实践文章,最后,对于已经(或刚刚成为)强化学习专家的人来说,还有一些高级主题。

Anton Muehlemann——determined . ai 的编辑助理/ AMLE

强化学习 101

通过 Shweta Bhatt — 6 分钟读取

开始强化学习(RL)之旅的最佳地点。本文涵盖了 5 个基本的 RL 问题。

耶稣罗德里格斯 — 6 分钟阅读

这篇文章评论了 MuZero,一个通过从零开始学习规则而掌握了几个策略游戏的 AI 智能体。穆泽罗是著名的 AlphaZero 引擎的继任者,该引擎击败了 AlphaGo,alpha Go 本身是第一个击败职业围棋选手的人工智能——这项任务长期以来被认为是任何人工智能都无法完成的。

现实生活规划问题的强化学习

斯特林·奥斯本博士研究员——15 分钟阅读

关于使用 RL 解决数据有限的现实世界问题的综合指南。

具有深度 Q 网络的 Cart-Pole 上的强化学习概念

通过 Vitou Phy — 6 分钟读取

RL 的一个主要例子是车杆问题。在这个游戏中,你要通过左右移动来平衡一根直立的柱子。本文展示了如何使用深度 Q 网络来解决这个问题。

高级 DQNs:玩吃豆人深度强化学习

杰克·格雷斯比——22 分钟阅读

本文介绍了对经典 dqn 的改进,并展示了如何应用它来越好地玩吃豆人游戏。

更聪明地交易和投资——强化学习方式

亚当·金 — 19 分钟读完

厌倦了游戏?赚点钱怎么样?虽然我们不能保证任何财务收益,但您一定会获得关于 TensorTrade 的知识,TensorTrade 是一个使用 RL 进行交易和投资的开源 python 框架。

T3【谷歌新星球强化学习网】你需要知道的一切

通过测测邵 — 8 分钟读取

本文回顾了 Google AI 针对 RL 的深度规划网络。PlaNet 通过潜在动力学模型、基于模型的规划和迁移学习解决了经典 RL 模型的几个缺点。

神经架构搜索—限制与扩展

由亚历克斯·亚当 — 11 分钟读完

神经架构搜索是这样一种想法,它不是让专家为给定的问题找到一个好的模型,而是由 RL 算法为您找到。一个主要的问题是搜索结果的庞大,因此 NAS 算法占用了大量的计算资源。本文强调了这些限制,并展示了一些可能的扩展,以使 NAS 性能更好。

我们也感谢最近加入我们的所有伟大的新作家,安德鲁·郝路易·德·贝诺伊斯豪斯罗伯特·库伯勒博士尼克·霍尔马克罗伯托·桑纳扎罗陈卿丹·西格尔,,马丁·贝克我们邀请你看看他们的简介,看看他们的工作。

使用 Microsoft SQL Server 进行 Java 开发

原文:https://towardsdatascience.com/java-development-with-microsoft-sql-server-ee6efd13f799?source=collection_archive---------34-----------------------

使用 JDBC 从 Java 应用程序调用 Microsoft SQL Server 存储过程

介绍

企业软件解决方案通常结合了多种技术平台。通过微软的。NET 应用程序,反之亦然,从基于 Java 的应用程序访问 Microsoft SQL Server 是很常见的。在本帖中,我们将探索如何使用 JDBC (Java 数据库连接)API 从微软 SQL Server 2017 数据库中调用存储过程,并将数据返回给基于 Java 11 的控制台应用程序。

从 JetBrains 的智能界面查看 post 的 Java 项目

该员额的目标包括:

  • 演示使用静态 SQL 语句和存储过程返回数据的区别。
  • 演示三种返回数据的 JDBC 语句:StatementPreparedStatementCallableStatement
  • 演示如何使用输入和输出参数调用存储过程。
  • 演示如何使用存储过程从数据库返回单个值和一个结果集。

为什么是存储过程?

为了访问数据,许多企业软件组织要求他们的开发人员在代码中调用存储过程,而不是对数据库执行静态的 T-SQL (Transact-SQL)语句。存储过程成为首选有几个原因:

  • 优化:存储过程通常由数据库管理员(DBA)或专门从事数据库开发的数据库开发人员编写。他们了解构造查询的最佳方式,以获得最佳性能和最小的数据库服务器负载。可以把它想象成开发人员使用 API 与数据库进行交互。
  • 安全性:存储过程被认为比静态 SQL 语句更安全。存储过程提供了对查询内容的严格控制,防止对数据库执行恶意或无意的破坏性代码。
  • 错误处理:存储过程可以包含处理错误的逻辑,以免错误上升到应用层,甚至最终用户。

AdventureWorks 2017 数据库

为了简洁起见,我将使用一个现有的众所周知的微软 SQL Server 数据库, AdventureWorks 。AdventureWorks 数据库最初由 Microsoft 针对 SQL Server 2008 发布。尽管在体系结构上有点过时,但该数据库已经预先填充了大量用于演示的数据。

HumanResources模式,AdventureWorks 数据库中的五个模式之一

为了演示,我在 AWS 上创建了一个Amazon RDS for SQL Server 2017 Express Edition实例。部署 SQL Server 有几种选择,包括 AWSMicrosoft AzureGoogle Cloud ,或者安装在本地工作站上。

有许多方法可以将 AdventureWorks 数据库部署到 Microsoft SQL Server。为了这篇文章的演示,我使用了AdventureWorks2017.bak 备份文件,我把它复制到了亚马逊 S3。然后我启用并配置了Amazon RDS for SQL Server 的本地备份和恢复特性,以导入并安装备份。

DROP DATABASE IF EXISTS AdventureWorks;
GO

EXECUTE msdb.dbo.rds_restore_database
     @restore_db_name='AdventureWorks',
     @s3_arn_to_restore_from='arn:aws:s3:::my-bucket/AdventureWorks2017.bak',
     @type='FULL',
     @with_norecovery=0;

-- get task_id from output (e.g. 1)

EXECUTE msdb.dbo.rds_task_status
     @db_name='AdventureWorks',
     @task_id=1;

安装存储过程

为了进行演示,我在 AdventureWorks 数据库中添加了四个存储过程,以便在本文中使用。为了跟进,您需要安装这些存储过程,它们包含在 GitHub 项目中。

JetBrains 的 IntelliJ IDE 数据库选项卡中的新存储过程视图

数据源、连接和属性

使用最新的 Microsoft JDBC 驱动程序 8.4 for SQL Server (版本 8.4.1.jre11),我们创建一个 SQL Server 数据源com.microsoft.sqlserver.jdbc.SQLServerDataSource和数据库连接java.sql.Connection。创建和使用 JDBC 数据源和连接有多种模式。这篇文章不一定关注创建或使用这两者的最佳实践。在这个例子中,应用程序实例化了一个连接类SqlConnection.java,它又实例化了java.sql.Connectioncom.microsoft.sqlserver.jdbc.SQLServerDataSource对象。数据源的属性由单例类实例ProjectProperties.java提供。这个类实例化了从配置属性文件config.properties中读取值的java.util.Properties类。启动时,应用程序创建数据库连接,调用每个示例方法,然后关闭连接。

例子

对于每个示例,我将展示存储过程(如果适用的话),后面是调用该过程或执行静态 SQL 语句的 Java 方法。为了简洁起见,我在本文中省略了数据源和连接代码。同样,本文所有代码的完整副本可以在 GitHub 上获得,包括 Java 源代码、SQL 语句、辅助 SQL 脚本和一组基本的 JUnit 测试。使用下面的命令来git clone项目的本地副本。

git clone --branch master --single-branch --depth 1 --no-tags \
    [https://github.com/garystafford/mssql-sp-java-jdbc-2020.git](https://github.com/garystafford/mssql-sp-java-jdbc-2020.git)

要运行 JUnit 单元测试,使用项目所基于的 Gradle ,使用./gradlew cleanTest test --warning-mode none命令。

JUnit 测试的成功运行

要使用项目所基于的 Gradle 构建和运行应用程序,请使用./gradlew run --warning-mode none命令。

Java 控制台应用程序的输出

示例 1: SQL 语句

在进入存储过程之前,我们将从一个简单的静态 SQL 语句开始。这个例子的方法getAverageProductWeightST使用了[java.sql.Statement](http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/Statement.html)类。根据甲骨文的 JDBC 文档,Statement对象用于执行静态 SQL 语句并返回其产生的结果。此 SQL 语句计算 AdventureWorks 数据库中所有产品的平均重量。它返回一个单独的double数值。此示例演示了从 SQL Server 返回数据的最简单方法之一。

*/**
 * Statement example, no parameters, returns Integer
 *
 ** ***@return*** *Average weight of all products
 */* public double getAverageProductWeightST() {
    double averageWeight = 0;
    Statement stmt = null;
    ResultSet rs = null;try {
        stmt = *connection*.getConnection().createStatement();
        String sql = "WITH Weights_CTE(AverageWeight) AS" +
                "(" +
                "    SELECT [Weight] AS [AverageWeight]" +
                "    FROM [Production].[Product]" +
                "    WHERE [Weight] > 0" +
                "        AND [WeightUnitMeasureCode] = 'LB'" +
                "    UNION" +
                "    SELECT [Weight] * 0.00220462262185 AS [AverageWeight]" +
                "    FROM [Production].[Product]" +
                "    WHERE [Weight] > 0" +
                "        AND [WeightUnitMeasureCode] = 'G')" +
                "SELECT ROUND(AVG([AverageWeight]), 2)" +
                "FROM [Weights_CTE];";
        rs = stmt.executeQuery(sql);
        if (rs.next()) {
            averageWeight = rs.getDouble(1);
        }
    } catch (Exception ex) {
        Logger.*getLogger*(RunExamples.class.getName()).
                log(Level.*SEVERE*, null, ex);
    } finally {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
    }
    return averageWeight;
}

示例 2:预准备语句

接下来,我们将执行与示例 1 几乎相同的静态 SQL 语句。唯一的变化是增加了列名averageWeight。这允许我们按列名解析结果,与示例 1 中使用列的数字索引相比,代码更容易理解。

同样,我们不使用java.sql.Statement类,而是使用java.sql.PreparedStatement类。根据 Oracle 的文档,一条 SQL 语句被预编译并存储在一个PreparedStatement对象中。然后,可以使用该对象多次有效地执行该语句。

*/**
 * PreparedStatement example, no parameters, returns Integer
 *
 ** ***@return*** *Average weight of all products
 */* public double getAverageProductWeightPS() {
    double averageWeight = 0;
    PreparedStatement pstmt = null;
    ResultSet rs = null;try {
        String sql = "WITH Weights_CTE(averageWeight) AS" +
                "(" +
                "    SELECT [Weight] AS [AverageWeight]" +
                "    FROM [Production].[Product]" +
                "    WHERE [Weight] > 0" +
                "        AND [WeightUnitMeasureCode] = 'LB'" +
                "    UNION" +
                "    SELECT [Weight] * 0.00220462262185 AS [AverageWeight]" +
                "    FROM [Production].[Product]" +
                "    WHERE [Weight] > 0" +
                "        AND [WeightUnitMeasureCode] = 'G')" +
                "SELECT ROUND(AVG([AverageWeight]), 2) **AS [averageWeight]**" +
                "FROM [Weights_CTE];";
        pstmt = *connection*.getConnection().prepareStatement(sql);
        rs = pstmt.executeQuery();
        if (rs.next()) {
            averageWeight = rs.getDouble("averageWeight");
        }
    } catch (Exception ex) {
        Logger.*getLogger*(RunExamples.class.getName()).
                log(Level.*SEVERE*, null, ex);
    } finally {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
    }
    return averageWeight;
}

示例 3:可调用语句

在此示例中,平均产品重量查询已被移到存储过程中。该过程在功能上与前两个示例中的静态语句相同。为了调用存储过程,我们使用了java.sql.CallableStatement类。根据甲骨文的文档CallableStatement扩展了PreparedStatement。它是用于执行 SQL 存储过程的接口。CallableStatement接受输入和输出参数;然而,这个简单的例子既不使用。与前两个示例一样,该过程返回一个double数值。

CREATE OR
ALTER PROCEDURE [Production].[uspGetAverageProductWeight]
AS
BEGIN
  SET NOCOUNT ON;WITH
    Weights_CTE(AverageWeight)
    AS
    (
        SELECT [Weight] AS [AverageWeight]
        FROM [Production].[Product]
        WHERE [Weight] > 0
          AND [WeightUnitMeasureCode] = 'LB'
      UNION
        SELECT [Weight] * 0.00220462262185 AS [AverageWeight]
        FROM [Production].[Product]
        WHERE [Weight] > 0
          AND [WeightUnitMeasureCode] = 'G'
    )
  SELECT ROUND(AVG([AverageWeight]), 2)
  FROM [Weights_CTE];
ENDGO

调用的 Java 方法如下所示。

*/**
 * CallableStatement, no parameters, returns Integer
 *
 ** ***@return*** *Average weight of all products
 */* public double getAverageProductWeightCS() {
    CallableStatement cstmt = null;
    double averageWeight = 0;
    ResultSet rs = null;
    try {
        cstmt = *connection*.getConnection().prepareCall(
                "{call [Production].[uspGetAverageProductWeight]}");
        cstmt.execute();
        rs = cstmt.getResultSet();
        if (rs.next()) {
            averageWeight = rs.getDouble(1);
        }
    } catch (Exception ex) {
        Logger.*getLogger*(RunExamples.class.getName()).
                log(Level.*SEVERE*, null, ex);
    } finally {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*SEVERE*, null, ex);
            }
        }
        if (cstmt != null) {
            try {
                cstmt.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
    }
    return averageWeight;
}

示例 4:使用输出参数调用存储过程

在本例中,我们使用了与例 3 几乎相同的存储过程。唯一的区别是包含了一个输出参数。这一次,不是在单个未命名的列中返回带有值的结果集,而是该列有一个名称averageWeight。现在,我们可以在检索值时通过名称来调用该列。

示例 3 和示例 4 中的存储过程模式都是常用的。一个过程使用输出参数,一个不使用,两个过程返回相同的值。您可以使用CallableStatement来选择任何一种类型。

CREATE OR
ALTER PROCEDURE [Production].[uspGetAverageProductWeightOUT]**@averageWeight DECIMAL(8, 2) OUT** AS
BEGIN
  SET NOCOUNT ON;WITH
    Weights_CTE(AverageWeight)
    AS
    (
        SELECT [Weight] AS [AverageWeight]
        FROM [Production].[Product]
        WHERE [Weight] > 0
          AND [WeightUnitMeasureCode] = 'LB'
      UNION
        SELECT [Weight] * 0.00220462262185 AS [AverageWeight]
        FROM [Production].[Product]
        WHERE [Weight] > 0
          AND [WeightUnitMeasureCode] = 'G'
    )
  SELECT **@averageWeight** = ROUND(AVG([AverageWeight]), 2)
  FROM [Weights_CTE];
ENDGO

调用的 Java 方法如下所示。

*/**
 * CallableStatement example, (1) output parameter, returns Integer
 *
 ** ***@return*** *Average weight of all products
 */* public double getAverageProductWeightOutCS() {
    CallableStatement cstmt = null;
    double averageWeight = 0;try {
        cstmt = *connection*.getConnection().prepareCall(
                "{call [Production].[uspGetAverageProductWeightOUT](?)}");
 **cstmt.registerOutParameter("averageWeight", Types.*DECIMAL*);**        cstmt.execute();
        averageWeight = cstmt.getDouble("averageWeight");
    } catch (Exception ex) {
        Logger.*getLogger*(RunExamples.class.getName()).
                log(Level.*SEVERE*, null, ex);
    } finally {
        if (cstmt != null) {
            try {
                cstmt.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
    }
    return averageWeight;
}

示例 5:使用输入参数调用存储过程

在本例中,该过程返回一个类型为[java.sql.ResultSet](http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/ResultSet.html)的结果集,其雇员的姓氏以特定的字符序列开头(例如,“M”或“s a”)。使用CallableStatement将字符序列作为输入参数lastNameStartsWith传递给存储过程。

进行调用的方法遍历存储过程返回的结果集的行,将多个列连接起来,形成一个字符串形式的雇员全名。然后将每个全名字符串添加到一个有序的字符串集合中,即一个List<String>对象。列表实例由方法返回。您会注意到,由于使用了LIKE操作符,这个过程运行的时间会稍长一些。数据库服务器必须对表中的每个姓氏值执行模式匹配,以确定结果集。

CREATE OR
ALTER PROCEDURE [HumanResources].[uspGetEmployeesByLastName]
**@lastNameStartsWith VARCHAR(20) = 'A'** AS
BEGIN
  SET NOCOUNT ON;SELECT p.[FirstName], p.[MiddleName], p.[LastName], p.[Suffix], e.[JobTitle], m.[EmailAddress]
  FROM [HumanResources].[Employee] AS e
    LEFT JOIN [Person].[Person] p ON e.[BusinessEntityID] = p.[BusinessEntityID]
    LEFT JOIN [Person].[EmailAddress] m ON e.[BusinessEntityID] = m.[BusinessEntityID]
  WHERE e.[CurrentFlag] = 1
    AND p.[PersonType] = 'EM'
 **AND p.[LastName] LIKE @lastNameStartsWith + '%'**  ORDER BY p.[LastName], p.[FirstName], p.[MiddleName]
ENDGO

调用的 Java 方法如下所示。

*/**
 * CallableStatement example, (1) input parameter, returns ResultSet
 *
 ** ***@param*** *lastNameStartsWith
 ** ***@return*** *List of employee names
 */* public List<String> getEmployeesByLastNameCS(String lastNameStartsWith) {CallableStatement cstmt = null;
    ResultSet rs = null;
    List<String> employeeFullName = new ArrayList<>();try {
        cstmt = *connection*.getConnection().prepareCall(
                "{call [HumanResources].[uspGetEmployeesByLastName](?)}",
                ResultSet.*TYPE_SCROLL_INSENSITIVE*,
                ResultSet.*CONCUR_READ_ONLY*);**cstmt.setString("lastNameStartsWith", lastNameStartsWith);
**        boolean results = cstmt.execute();
        int rowsAffected = 0;// Protects against lack of SET NOCOUNT in stored procedure
        while (results || rowsAffected != -1) {
            if (results) {
                rs = cstmt.getResultSet();
                break;
            } else {
                rowsAffected = cstmt.getUpdateCount();
            }
            results = cstmt.getMoreResults();
        }
        while (rs.next()) {
            employeeFullName.add(
                    rs.getString("LastName") + ", "
                            + rs.getString("FirstName") + " "
                            + rs.getString("MiddleName"));
        }
    } catch (Exception ex) {
        Logger.*getLogger*(RunExamples.class.getName()).
                log(Level.*SEVERE*, null, ex);
    } finally {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
        if (cstmt != null) {
            try {
                cstmt.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
    }
    return employeeFullName;
}

示例 6:将结果集转换为有序的对象集合

在最后一个例子中,我们将两个输入参数productColorproductSize传递给一个存储过程。存储过程返回包含几列产品信息的结果集。这一次,该示例的方法遍历该过程返回的结果集,并构造一个有序的产品集合,List<Product>对象。列表中的产品对象是Product.java POJO 类的实例。该方法将每个结果集的行级字段值转换为一个Product属性(例如Product.SizeProduct.Model)。使用集合是在应用程序中保持结果集中的数据的常用方法。

CREATE OR
ALTER PROCEDURE [Production].[uspGetProductsByColorAndSize]
 **@productColor VARCHAR(20),
  @productSize INTEGER** AS
BEGIN
  SET NOCOUNT ON;SELECT p.[ProductNumber], m.[Name] AS [Model], p.[Name] AS [Product], p.[Color], p.[Size]
  FROM [Production].[ProductModel] AS m
    INNER JOIN
    [Production].[Product] AS p ON m.[ProductModelID] = p.[ProductModelID]
  WHERE (p.[Color] = @productColor)
    AND (p.[Size] = @productSize)
  ORDER BY p.[ProductNumber], [Model], [Product]
ENDGO

调用的 Java 方法如下所示。

*/**
 * CallableStatement example, (2) input parameters, returns ResultSet
 *
 ** ***@param*** *color
 ** ***@param*** *size
 ** ***@return*** *List of Product objects
 */* public List<Product> getProductsByColorAndSizeCS(String color, String size) {CallableStatement cstmt = null;
    ResultSet rs = null;
 **List<Product> productList = new ArrayList<>();**try {
        cstmt = *connection*.getConnection().prepareCall(
                "{call [Production].[uspGetProductsByColorAndSize](?, ?)}",
                ResultSet.*TYPE_SCROLL_INSENSITIVE*,
                ResultSet.*CONCUR_READ_ONLY*);**cstmt.setString("productColor", color);
        cstmt.setString("productSize", size);
**        boolean results = cstmt.execute();
        int rowsAffected = 0;// Protects against lack of SET NOCOUNT in stored procedure
        while (results || rowsAffected != -1) {
            if (results) {
                rs = cstmt.getResultSet();
                break;
            } else {
                rowsAffected = cstmt.getUpdateCount();
            }
            results = cstmt.getMoreResults();
        }while (rs.next()) {
            Product product = new Product(
                    rs.getString("Product"),
                    rs.getString("ProductNumber"),
                    rs.getString("Color"),
                    rs.getString("Size"),
                    rs.getString("Model"));
            productList.add(product);
        }
    } catch (Exception ex) {
        Logger.*getLogger*(RunExamples.class.getName()).
                log(Level.*SEVERE*, null, ex);
    } finally {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
        if (cstmt != null) {
            try {
                cstmt.close();
            } catch (SQLException ex) {
                Logger.*getLogger*(RunExamples.class.getName()).
                        log(Level.*WARNING*, null, ex);
            }
        }
    }
    return productList;
}

正确的 T-SQL:模式参考和括号

您会注意到,在所有的 T-SQL 语句中,我引用了模式以及表或存储过程的名称(例如,{call [Production].[uspGetAverageProductWeightOUT](?)})。根据微软的说法,用一个模式名和对象名来引用数据库对象是一个很好的习惯,两者之间用句点隔开;这甚至包括默认模式(例如,dbo)。

您还会注意到我将模式和对象名放在方括号中(例如,SELECT [ProductNumber] FROM [Production].[ProductModel])。方括号表示该名称代表一个对象,而不是一个保留字(例如CURRENTNATIONAL)。默认情况下,SQL Server 添加这些以确保它生成的脚本正确运行。

运行示例

应用程序将显示被调用方法的名称、方法描述、检索数据所用的时间以及该方法返回的任何结果。

下面,我们来看看结果。

SQL 语句性能

这篇文章当然不是关于 SQL 性能的,事实证明了这一点,我只是在一个单一的,非常不充分的 db.t2.micro Amazon RDS 实例类型上使用Amazon RDS for SQL Server 2017 Express Edition。但是,我添加了一个定时器特性,ProcessTimer.java类,来捕获每个示例返回数据所花费的时间,以毫秒为单位。ProcessTimer.java类是项目代码的一部分。使用计时器,您应该可以观察到应用程序的第一次运行和后续运行之间对于几个被调用方法的显著差异。时间差是由几个因素造成的,主要是 SQL 语句的预编译和 SQL Server 计划缓存

通过使用 DBCC (数据库控制台命令)语句清除 SQL Server 计划缓存 ( 参见下面的 SQL 脚本)可以轻松演示这两个因素的影响。然后连续运行应用程序两次。第二次,预编译和计划缓存将显著加快预处理语句和可调用语句的运行速度,如示例 2–6 所示。在下面显示的两次随机运行中,我们看到查询时间提高了 5 倍。

USE AdventureWorks;DBCC FREESYSTEMCACHE('SQL Plans');
GOCHECKPOINT;
GO-- Impossible to run with Amazon RDS for Microsoft SQL Server on AWS
-- DBCC DROPCLEANBUFFERS;
-- GO

第一次运行结果如下所示。

SQL SERVER STATEMENT EXAMPLES
======================================
Method: GetAverageProductWeightST
Description: Statement, no parameters, returns Integer
**Duration (ms): 122** Results: Average product weight (lb): 12.43
---
Method: GetAverageProductWeightPS
Description: PreparedStatement, no parameters, returns Integer
**Duration (ms): 146** Results: Average product weight (lb): 12.43
---
Method: GetAverageProductWeightCS
Description: CallableStatement, no parameters, returns Integer
**Duration (ms): 72** Results: Average product weight (lb): 12.43
---
Method: GetAverageProductWeightOutCS
Description: CallableStatement, (1) output parameter, returns Integer
**Duration (ms): 623** Results: Average product weight (lb): 12.43
---
Method: GetEmployeesByLastNameCS
Description: CallableStatement, (1) input parameter, returns ResultSet
**Duration (ms): 830** Results: Last names starting with 'Sa': 7
         Last employee found: Sandberg, Mikael Q
---
Method: GetProductsByColorAndSizeCS
Description: CallableStatement, (2) input parameter, returns ResultSet
**Duration (ms): 427** Results: Products found (color: 'Red', size: '44'): 7
         First product: Road-650 Red, 44 (BK-R50R-44)
---

第二次运行结果如下所示。

SQL SERVER STATEMENT EXAMPLES
======================================
Method: GetAverageProductWeightST
Description: Statement, no parameters, returns Integer
**Duration (ms): 116** Results: Average product weight (lb): 12.43
---
Method: GetAverageProductWeightPS
Description: PreparedStatement, no parameters, returns Integer
**Duration (ms): 89** Results: Average product weight (lb): 12.43
---
Method: GetAverageProductWeightCS
Description: CallableStatement, no parameters, returns Integer
**Duration (ms): 80** Results: Average product weight (lb): 12.43
---
Method: GetAverageProductWeightOutCS
Description: CallableStatement, (1) output parameter, returns Integer
**Duration (ms): 340** Results: Average product weight (lb): 12.43
---
Method: GetEmployeesByLastNameCS
Description: CallableStatement, (1) input parameter, returns ResultSet
**Duration (ms): 139** Results: Last names starting with 'Sa': 7
         Last employee found: Sandberg, Mikael Q
---
Method: GetProductsByColorAndSizeCS
Description: CallableStatement, (2) input parameter, returns ResultSet
**Duration (ms): 208** Results: Products found (color: 'Red', size: '44'): 7
         First product: Road-650 Red, 44 (BK-R50R-44)
---

结论

本文展示了使用 JDBC 和微软 JDBC 驱动程序 8.4 for SQL Server 从 SQL Server 2017 数据库查询和调用存储过程的几种方法。尽管这些示例非常简单,但是同样的模式也可以用于更复杂的存储过程,具有多个输入和输出参数,不仅可以选择数据,还可以插入、更新和删除数据。

您应该通过阅读文档来了解用于 SQL Server 的微软 JDBC 驱动程序的一些限制。但是,对于大多数需要数据库交互的任务,该驱动程序为 SQL Server 提供了足够的功能。

本博客代表我自己的观点,不代表我的雇主亚马逊网络服务公司的观点。

使用 Java 解决您的数据科学问题

原文:https://towardsdatascience.com/java-for-data-science-f64631fdda12?source=collection_archive---------24-----------------------

通过了解这种广泛使用的编程语言的基础知识,快速访问高质量的数据。

Java——一次编写,随处运行。照片由内森·绍特佩克斯拍摄。

Java 提供了多功能性、互操作性,以及开着红色 vespa 环游欧洲的机会。数据科学家被期望拥有良好的 Python(或 R)编码能力。我认为 Java 应该作为一个有用的工具加入到数据科学技能集中。

自 1995 年以来,Java 一直在啜饮浓咖啡,编写杀手级应用程序,偶尔还会向咖啡馆窗外投去渴望的一瞥。很可能已经有一个 Java 应用程序可以帮助你作为数据科学家的工作。

本文将帮助您了解一些基本知识,理解如何使用 Java 来支持机器学习,并查看一些资源以进一步学习。本文并不打算教你这种通用语言的实际语法。本文不会购买您的浓缩咖啡,但 Java 可能会。

在本指南中:

Java 是什么?

Java 是一种通用编程语言,它是基于类的、面向对象的,并且是为互操作性而设计的。说到部署环境,你可以说 Java 有一种不顾一切的态度——用 Java 编写的应用程序可以在任何可以运行 Java 虚拟机(JVM)的操作系统上运行。这种灵活性就是为什么 Java 是应用程序开发人员的最爱,他们寻求创建一个与操作系统无关的工具,并能很好地移植到移动设备上。

java 程序的源代码。java 文件)是用大括号语法编写的。程序被编译成可以在 JVM 上运行的字节码(一个. class 文件)。

通过键入javac pdfParsingApp.java将程序从源代码(如 pdfParsingApp.class)编译成字节码(如 pdfParsingApp.class)

如果你熟悉计算机科学基础中机器码的概念,java 字节码是类似的——但是字节码不是为主机的特定架构编写的,而是为虚拟机编写的。

via 我的教程博客

JVM 将 Java 字节码翻译成平台的机器语言——这就是 Java 的互操作性。JVM 能够从 Clojure、Scala 和其他编译成 Java 字节码的语言进行翻译。

为什么要学 Java?

虽然 Python 可能是数据科学世界的通用语(R 在较小程度上发挥了作用),但就更广泛的开发人员社区而言,估计有 40%的程序员使用 Java。由于 Java 被广泛采用,至少粗略地了解一下 Java 包是如何构造、编写和实现的,可以帮助数据科学家更有效地与他们的软件工程同事交流。

此外,理解 Java 有助于机器学习管道的数据获取和部署阶段。

在数据采集阶段,Java 很有帮助,因为生产代码库通常是用 Java 编写的。作为一名数据科学家,在坏数据进入机器学习管道之前逆流而上修复坏数据的能力是非常宝贵的。在 SQL ( 被 55%的程序员使用)之后,Java 可能是解决后端数据问题和清理数据最有用的语言。

从模型开发到数据清理的倒退——这是我们试图通过数据工程改善数据质量来避免的。由 Wilbur WongUnsplash 上拍摄的照片。

例如,在自然语言处理(NLP)中,我们处理大量非结构化的文本数据,这些数据被设计为人类可读,但计算机不可读。 Apache PDFBox 是一个 Java 库,旨在解决将 PDF 文本转换成可用格式的挑战。这个工具不仅支持内容提取,还可以用来修改现有文档和创建新文档。这将是一种非常酷的方式来报告基于文本分析的机器学习模型的输出。

说到部署, Java 提供了对 Scala 的简单介绍。这种超快的语言运行在 JVM 上,经常被 DevOps 工程师用来将机器学习模型投入生产。

学习 Java 最有力的论据是,它为改进面向对象编程提供了坚实的基础。计算机科学 101 课程通常以 Java 为基础语言,提供关于数据结构&算法的教学。因为 Java 提供的抽象不像 Python 那么多,所以它会提高你对计算机科学基础的整体知识。

一句话:当数据科学在计算机科学实践中得到正确定位时,每个人——数据科学家、软件工程师和他们所在的组织——都会受益。

[## 软件 2.0

我有时看到人们将神经网络称为“你的机器学习工具箱中的另一个工具”。他们有一些…

medium.com](https://medium.com/@karpathy/software-2-0-a64152b37c35)

Python 和 Java 的核心区别是什么?

Python 是一种动态类型的解释语言。编写 Python 代码时,程序员不必声明每个变量的类型——类型是动态的、可变的。在运行时,解释器通过将每个语句翻译成一系列子例程,然后翻译成机器代码来执行 Python 程序。

Java 是一种静态类型的编译语言。在 Java 中创建新变量时,程序员负责声明类型。这种类型是静态的,不能改变。静态类型也意味着错误是在编译时被捕获的,而不是在运行时。我们已经讨论了 JVM 在从中间 Java 字节码(即通过编译创建的类文件)转换成特定于底层计算机硬件的机器代码。

Java 源文件就像一个俄罗斯套娃——它只能包含一个公共类,但可以包含任意数量的非公共类以及任意数量的公共内部类。via Etsy

与使用 Python 相比,使用 Java 有更多的规则——无论是在语法方面(例如静态类型)还是在包结构方面。例如,一个 Java 源文件只能包含一个公共类。源文件必须以其包含的公共类命名。

例如,程序 pdfParsingApp.java 看起来像这样:

**public static void main** 行必须出现在每个 Java 程序中(作为包库一部分的程序除外)。这是 main 方法的开始,它在执行时运行,本质上告诉 Java 程序要做什么。程序中的其他类可以提供 main 方法使用的信息。

摘要

学习 Java 是熟悉企业机器学习管道通常由多种语言组成这一概念的良好开端。您可能会使用与 Java 和 JVM 相关的技术来收集数据、清理数据并生产您的模型。另外,将 Java 添加到您的堆栈中会提高您编写基于类的、面向对象的程序的能力。

希望这篇文章能让您对 Java 如何对您的 DS 工作有用有一点直觉。利用您对 Python(或 R)的熟悉,您可以快速构建对 Java 的更好理解——以及更好的应用程序和模型部署。

资源

如果你喜欢阅读这篇文章,请关注我的 MediumLinkedInTwitter ,了解更多提升你的数据科学技能的想法。

[## 2020 年增强数据科学学习的资源

通过这个有用的期刊、视频和讲座的集合,推进你对机器学习的理解。

towardsdatascience.com](/supercharge-data-science-5bb7376d8572) [## 数据分析师、数据科学家和机器学习工程师有什么区别?

以田径运动会为例,探究这些常见职位之间的区别。

towardsdatascience.com](/data-analyst-vs-data-scientist-2534fc1057c3) [## 演练:在 Python 中映射 GIS 数据

通过 GeoPandas DataFrames 和 Google Colab 提高您对地理空间信息的理解

towardsdatascience.com](/walkthrough-mapping-gis-data-in-python-92c77cd2b87a)

Jupyter 笔记本上的 JavaScript 图表

原文:https://towardsdatascience.com/javascript-charts-on-jupyter-notebooks-dd25f794cf6a?source=collection_archive---------14-----------------------

用漂亮的 JavaScript 可视化将 Jupyter 推向新的高度

照片是我的

作为一名专业人士,我喜欢把自己想象成数据科学家和前端开发人员的混合体。我在工作中真正喜欢的,是处理涉及这两个部分的项目。然而,很多时候,我们没有时间去设计和实现一个完整的 web 应用程序,一个可靠的客户端-服务器架构和一个超级可重用的用户界面:在这种情况下,我们需要回到更快的东西。

在接下来的文章中,我将向你展示如何给 Jupyter 笔记本加类固醇,实现,一个交互式的可过滤的可视化,只需要几行 JavaScript

工具

我们需要为数据可视化选择一个 JS 库。我们有几乎无限的选择;对于本指南,我们希望选择一些易于使用的东西。一些例子包括 HighchartsEChartsd3.js

我们将使用 ECharts ,这是一个允许毫不费力地创建超级花哨的可视化效果的框架。该库最初是在百度开发的,但现在在 Apache 孵化器中。它是根据 Apache-2.0 许可的。

JavaScript 可能并不总是数据科学家的武器库(我发现这种语言的知识在具有计算机科学/编程背景的人中更常见)。如果你不知道 JavaScript,那么考虑一下这些库使图表的生成变得非常容易(如果你正在寻找非常复杂的交互,可能还需要做更多的工作)。ECharts 网站包含了大量复制粘贴的例子,展现了几乎所有的特性

使用这些工具,唯一的“硬”工作就是处理数据,将它们转换成适合我们选择的特定图表类型的格式。

数据

我们将使用 谷歌新冠肺炎社区移动报告 *** 数据这个数据集包含了每个国家在一个地理区域[1],【T25 内去杂货店和公园等地方的百分比变化,它是由谷歌设计来帮助抗击新冠肺炎的。让我们来看一段摘录并描述一下这些列:

  • country_region_code:国家代码。我们将从分析中过滤掉这个字段。
  • country_region:国家名称。
  • sub_region_1sub_region_2:地理区域的两个更精细的视图。对于我们想要实现的图表,我们可以过滤掉这些。我们将只考虑sub_region_1null的行(因此我们只考虑汇总数据,而不考虑每个子区域的信息)
  • date:简单的日期。
  • retail_and_recreation_percent_change_from_baseline : 餐馆、咖啡馆、购物中心、主题公园、博物馆、图书馆和电影院等场所的移动趋势。【2
  • grocery_and_pharmacy_percent_change_from_baseline : 杂货店、食品仓库、农贸市场、特色食品店、药店和药房等场所的移动趋势。【2
  • parks_percent_change_from_baseline : 当地公园、国家公园、公共海滩、码头、狗公园、广场和公园等地的移动趋势。【2
  • transit_stations_percent_change_from_baseline : 地铁、公交、火车站等公共交通枢纽的移动趋势。【2
  • workplaces_percent_change_from_baseline : 工作场所的移动趋势。【2
  • residential_percent_change_from_baseline : 居住地流动趋势。【2

太好了,我们需要的东西都有了,让我们开始研究代码吧!

谷歌有限责任公司“谷歌新冠肺炎社区移动性报告”*。
https://www.google.com/covid19/mobility/访问:<日期>。

你好世界!

本文的主题不是用 ECharts 创建一个超级漂亮的图表,而是展示如何在 Jupyter 笔记本上启用这个功能。出于这个原因,我们将只实现一个可视化:一个多线图,显示数据集中可用的每个 KPI 的时间序列。

Jupyter 单元可以解释各种类型的内容,从 Python 代码到 Markdown。注入 JavaScript 代码有多难?幸运的是,对我们来说,这就像使用一个Jupyter magic一样简单!通过单元格魔术,我们可以指示笔记本以特定的方式读取单元格内容,对于 JavaScript 我们可以使用%%javascript魔术。

太棒了。我们知道如何在单元格中写 JS。工作流程应该如下:

  1. 我们使用 Pandas 读取 CSV,并根据需要对数据集进行预处理。
  2. 虽然仍然在 Python 代码中,但我们将数据转换成 JSON 字符串,这样我们就可以很容易地在 JavaScript 中操作它。
  3. 我们将 JSON 传递给 JavaScript 代码来生成可视化。

只是一个模式来了解数据流

最简单的方法是将所有的 Python 代码组织在一个函数中,在我们的例子中称为get_data()。对于这个第一个示例,我们将只显示与retail_and_recreation_percent_change_from_baseline指示器相关的时间序列。

我们将提供给 JavaScript 的 JSON 将具有以下形式:

{
  "dates":[<array of all the dates (sorted)>],
  "country_data":[
     {"name":"Country Name 1",
      "data":[<array of all the KPI's values, sorted by date>]
     }, 
     ...
     {"name":"Country Name N-1",
      "data":[<array of all the KPI's values, sorted by date>]
     }, {"name":"Country Name N",
      "data":[<array of all the KPI's values, sorted by date>]
     },
   ]
}

此时,我们有了数据:我们只需要在 JavaScript 单元格中访问它们。首先,我们需要导入 ECharts:为此,我们可以使用一个名为requirejs的模块:

稍后,我们将能够使用上面的方法在ech变量中存储 ECharts 对象。

为了让 JS 和 Python 交流,我们必须在某个地方存储 **get_data()** 函数的结果。让所有其他单元格都可以访问数据的一个非常简单的方法是将输出保存在一个window属性中:也就是说,我们将把 JSON 字符串保存在全局变量window.outputVar中。虽然在 **window** 中存储东西几乎从来都不是 JavaScript 开发的最佳实践,但我认为我们可以接受这种妥协来保持代码简单一点

%%javascript单元格中,我们可以使用IPython.notebook.kernel.execute()函数执行 Python 代码。没有深入研究细节(不幸的是,这个函数似乎缺少好的文档),这个函数接受一个字符串作为第一个参数:这个字符串是将要执行的实际 Python 代码(因此我们将所有内容存储在一个函数中,以使这部分更简洁)
第二个参数描述 Python 之后需要执行哪些 JavaScript 回调。

我们之所以不能“简单地返回” [get_data()](https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced) 结果,而是需要一个“回调”和一个全局外部变量,这是我在本文中不谈论的,以免偏离实际主题。然而,上面发生的事情简单如下:

  1. 执行get_data()功能。
  2. 执行之后,一个 JavaScript 函数读取结果,删除一些不需要的字符(快速而肮脏的解决方案,抱歉),将字符串转换为 JSON 对象,并将 JSON 保存在一个变量中,这个变量现在可以在页面中全局访问。

最后,好玩的部分!让我们深入到 ECharts 示例中,找到一个适合我们需要的可视化效果(想法是只复制-粘贴-编辑一些代码):堆积折线图应该是一个很好的起点:

简单来说,ECharts viz 生成分三步进行:

  1. 创建将包含可视化效果的 HTML 元素。
  2. 在元素上初始化 ECharts 对象
  3. 通过setOption方法设置图表选项。“选项”只是一个 JSON 对象,指示 ECharts 做什么。

除了所有视觉上的细微差别(颜色、工具提示等。),最重要的部分在于从上面的 JSON 开始生成数据。我们需要创建两个对象:一个用于 x 轴,另一个用于 y 轴。

x 轴数值 这将包含我们想要显示的所有日期。该列表需要保存在图表选项**xAxis** 属性中:

xAxis: {
        type: 'category',
        data: [<array with all the dates (sorted)>]
       },

系列 这将包含我们想要显示的实际数据。**series**属性由一个对象数组组成,其中每个元素都是图表中的一行:

series: [
    {
            name: 'Country 1',
            type: 'line',
            data: [<Array with values for each date>]
    },
        ...
    {
            name: 'Country N',
            type: 'line',
            data: [<Array with values for each date>]
        },
]

生成 viz 的代码如下:

如您所见,所有代码都保存在一个函数中,这个函数存储在中,同样,在window全局对象中:(最后一步是做最后的调用:

注意,在上面的例子中,我们将element变量传递给了buildChart()函数。EChart 可视化将追加到** **element** (即执行 **buildChart()** 功能的单元格)。输出如下所示:**

添加过滤器

两个问题:第一,图表不可读——线太多——第二,我们只能看到其中一个指标。我们真的希望有两个 HTML 元素来选择想要显示的国家和 KPI。有多种方法可以做到这一点,我们将选择最简单的一种!

我们需要稍微修改 **build_data()** 来返回所有的 KPI。让我们将该功能重命名为build_data_all():

新的 JSON 结构如下:

{
   "dates": [<Dates>],
   "country_data": [
      {
       "name": "<Country Name>",
       "retail_and_recreation_percent_change_from_baseline": [<Array of values for this KPI>],
       "parks_percent_change_from_baseline": [Array of values for this KPI],
       "transit_stations_percent_change_from_baseline": [Array of values for this KPI],
       "workplaces_percent_change_from_baseline": [Array of values for this KPI],
       "residential_percent_change_from_baseline": [Array of values for this KPI]
       },
      ...
   ]
}

想法是在页面中插入两个 HTML 选择元素:

  • ****一个包含国家列表(这将是一个多选,以便我们可以同时显示多个国家)。
  • ****一个包含 KPI 列表

****和前面代码唯一的区别就是我们需要 e 根据用户选择过滤 JSON。每当用户更改一个选项时,UI 都需要更新图表。

虽然对于 JavaScript 开发来说,在window中存储东西几乎从来都不是最佳实践,但我认为我们可以接受这种妥协,让代码简单一点。

下面的代码片段创建了两个 HTML select元素,并将它们附加到单元格中:

注意,我们将事件监听器附加到了选择框,这样每当选择被修改时,viz 就会被刷新。此外,注意所有的函数都存储在window对象中,使它们可以全局访问。

****我们已经准备好实现新的函数来生成图表:

我们就要结束了,让我们写一个函数,当一个输入改变时,它进行刷新:

最后,让我们调用单独单元格中的所有内容:

你可以在这里找到完整的笔记本。

希望你喜欢随时关注我的 Medium!

外卖食品

  • ****JavaScript 可以成为 Matplotlib 或其他图表库的有效替代品;这项技术的主要优点之一是有大量的资源和选择。
  • Jupyter 笔记本可以包含不同类型的代码,包括 JavaScript :使用魔法命令(在本例中为`%%javascript``)可以非常容易地实现这一点
  • 可以包含任何 JS 库,理论上,可以只与独立的笔记本交互(没有外部文件)
  • 没有任何调整,笔记本需要在每次页面刷新时重新运行

看看这些其他的文章!

** [## 火花中加入的艺术

Spark 中加速连接的实用技巧

towardsdatascience.com](/the-art-of-joining-in-spark-dcbd33d693c) [## 聚类波洛克

杰森·布拉克绘画的聚类分析——如何利用 k-means 进行色彩分组

towardsdatascience.com](/clustering-pollock-1ec24c9cf447)**

JAX:谷歌的差异化计算

原文:https://towardsdatascience.com/jax-differentiable-computing-by-google-78310859b4ad?source=collection_archive---------22-----------------------

革命性的机器学习框架

图片由来自皮克斯拜皮特·林福思拍摄

自从深度学习在 2010 年代初起飞以来,许多框架被编写来促进研究和生产中的深度学习。为了记录在案,让我们提一下 CaffeTheanoTorch千层面TensorflowKerasPyTorch 。一段时间后,这些框架中的一些消失了。其他的幸存下来并发展到今天,主要是 PyTorch 和 Tensorflow。随着时间的推移,这些框架演变成具有许多不同功能的大型生态系统。一方面,它们支持新模型的训练,包括在多 GPU 系统上的大规模并行训练。另一方面,它们允许用户在云中或移动设备上轻松部署训练好的模型。

不幸的是,这种精简有时会以机器学习研究人员测试新模型想法所需的灵活性为代价。谷歌通过其名为 JAX 的新框架瞄准的正是这个用户群体。在这篇博文中,我将向你展示 JAX 是如何通过向量化计算和梯度计算提供一个低级的、高性能的接口来鼓励实验的。

JAX 的设计哲学

JAX 的目标是允许用户通过即时编译和自动并行化来加速原始 Python 和 NumPy 函数,并计算这些函数的梯度。为了做到这一点,JAX 采用了功能设计。梯度计算等函数被实现为作用于用户定义的 Python 函数的函数变换(或函子)。例如,要计算绝对值函数的梯度,您可以写:

from jax import graddef abs_val(x):
  if x > 0:
    return x
  else:
    return -x

abs_val_grad = grad(abs_val)

如你所见, abs_val 是一个普通的 Python 函数,由仿函数 grad 转化而来。

为了能够使用 JAX 函子,用户定义的函数必须遵循一些限制:

  1. JAX 处理的每一个函数都要求是纯的。这意味着当用相同的输入调用时,它应该总是返回相同的结果。从功能上来说,可能没有任何副作用。否则,JAX 无法保证使用实时编译或并行化时的正确性。功能纯度实际上并没有被强制。虽然有时可能会抛出错误,但确保这种情况主要是程序员的责任。
  2. 人们不得不使用 jax.ops 包中的替代功能,而不是像 x[i] += 1 这样的就地突变更新。
  3. 实时(JIT)编译对 Python 控制流有一些限制。

就哲学而言,JAX 类似于你在使用纯函数式语言(如 Haskell)时会遇到的情况。事实上,开发人员甚至在文档中使用 Haskell 类型的签名来解释一些转换。

即时编译

JAX 的主要特性之一是能够通过 JIT 加速 Python 代码的执行。在内部,JAX 使用 XLA 编译器来完成这项工作。XLA 不仅能为 CPU 编译代码,还能为GPU 甚至是TPUs 编译代码。这使得 JAX 非常强大和多才多艺。为了使用 XLA 编译一个函数,你可以像这样使用 jit 仿函数:

from jax import jit
import jax.numpy as jnp**def** selu(x, alpha=1.67, lmbda=1.05):
  **return** lmbda * jnp.where(x > 0, x, alpha * jnp.exp(x) - alpha)selu_jit = jit(selu)

或者,您也可以使用 jit 作为函数定义顶部的装饰器:

**@jit
def** selu(x, alpha=1.67, lmbda=1.05):
  **return** lmbda * jnp.where(x > 0, x, alpha * jnp.exp(x) - alpha)

jit 仿函数通过将输入函数的编译版本返回给调用者来转换输入函数。调用原来的卢瑟函数会使用 Python 解释器,而调用卢瑟 _jit 会调用编译后的版本,应该会快很多,特别是对于 numpy 数组这样的矢量化输入。此外, JIT 编译只发生一次,并在其后被缓存,使得函数的后续调用非常高效。

使用 vmap 的自动矢量化

在训练机器学习模型时,通常会计算输入数据子集的一些损失,然后更新模型参数。由于为每个输入顺序计算模型的正向函数会太慢,所以习惯上是将数据的子集一起分批到一个批次中,并在诸如 GPU 的加速器上以并行方式计算正向函数。这是在 JAX 通过使用函数 vmap 完成的:

def forward(input, w, b):
    input = jnp.dot(input, w) + b
    return jnp.max(input, 0)jax.vmap(forward, in_axes=(0, None, None), out_axes=0)(inputs, w, b)

该代码片段采用一个具有 ReLU 激活的全连接层的转发功能,并在一批输入上并行执行该功能。参数输入轴输出轴指定在哪些参数和轴上发生并行化。在这种情况下,(0,None,None)意味着输入在第 0 轴上并行化,而 w 和 b 保持不变。输出在 0 轴上并行化。

计算梯度

让机器学习研究人员对 JAX 特别感兴趣的是它计算任意纯函数梯度的能力。JAX 从 autograd 继承了这种能力,autograd 是一个计算 NumPy 数组导数的包。

要计算函数的梯度,只需使用 grad 变换:

import jax.numpy as jnpgrad(jnp.tanh))(2.0)[0.070650816]

如果您想计算高阶导数,您可以简单地将多个 grad 变换链接在一起,如下所示:

import jax.numpy as jnpgrad(grad(jnp.tanh))(2.0)[-0.13621889]

虽然将 grad 应用于 R(实数集)中的函数会得到一个单一的数字作为输出,但您也可以将其应用于向量值函数以获得雅可比矩阵:

def f(x):
    return jnp.asarray(
        [x[0], 5*x[2], 4*x[1]**2 - 2*x[2], x[2] * jnp.sin(x[0])])print(jax.jacfwd(f)(jnp.array([1., 2., 3.])))[[ 1\.       0\.       0\.     ]
 [ 0\.       0\.       5\.     ]
 [ 0\.      16\.      -2\.     ]
 [ 1.6209   0\.       0.84147]]

这里,我们不使用 grad 变换,因为它只对标量输出函数有效。相反,我们使用类似的函数 jacfwd 进行自动前向模式区分(关于前向和后向模式区分的详细讨论,请参考 JAX 文档)。

注意,我们可以在 JAX 将功能转换链接在一起。例如,我们可以使用 vmap 对我们的函数进行矢量化,使用 grad 计算梯度,然后使用 jit 编译结果函数,例如深度学习中的标准小批量训练循环:

def **loss**(x, y):
    out = net(x)
    cross_entropy = -y * np.log(out) - (1 - y)*np.log(1 - out)
    return cross_entropyloss_grad = jax.jit(jax.vmap(jax.grad(loss), in_axes=(0, 0), out_axes=0))

这里, loss_grad 计算交叉熵损失的梯度,同时在输入(x,y)和单个输出(损失)上并行。整个函数是 jitted 的,以允许在 GPU 上快速计算。产生的函数被缓存,允许用不同的输出调用它,而没有任何额外的开销。

多种转换的组合使得框架非常强大,并为用户设计数据流提供了极大的灵活性。

结论

对于需要额外灵活性的研究人员来说,JAX 为 PyTorch 或 Tensorflow 等更高级的框架提供了一个有用的替代方案。通过原生 Python 和 NumPy 函数进行区分的能力令人惊叹,JIT 编译和自动矢量化功能极大地简化了为 GPU 或 TPUs 等大规模并行架构编写高效代码的工作。然而,我最喜欢 JAX 的是它干净的功能界面。一个成熟的高级 API 生态系统将围绕它发展,这肯定只是时间问题。敬请期待!

Jean Alfonso-Decena:引领对话式人工智能创新,颠覆菲律宾金融科技行业

原文:https://towardsdatascience.com/jean-alfonso-decena-leading-innovation-in-conversational-ai-and-disrupting-the-philippine-fintech-5d213335ad7b?source=collection_archive---------54-----------------------

技术领域的女性系列

采访 Starbutter AI 的运营总监&合作伙伴

在过去的几年里,世界各地的科技公司和研究人员一直在竞相推进人工智能的前沿。随着技术空间的不断扩大和快速发展,很明显,在金融行业利用人工智能是经济发展的关键。现在,比以往任何时候都更加明显的是,计算机科学中的这些理论革命给全球市场带来了人工智能的新应用。

在菲律宾等国家,服务业一直是经济中“最强大、增长最快的部门”之一,人工智能创新有可能增加国家对全球价值链的参与。此外,人工智能的发展和与国家人才合作的跨国公司可以让国家更深入地参与国际服务贸易,并加速人工智能特有的隐性知识的传播。

图片由 Jean Alfonso-Decena 提供

在这个混乱的时代,Jean Alfonso-Decena 在对话式人工智能领域取得了巨大的进步。凭借其“探索和实验”的观点,Jean 正在菲律宾技术领域以及全球金融技术领域的人工智能领域创造价值。作为 Starbutter AI 的运营和合作伙伴负责人,她位于商业、数据科学、产品和工程的交汇处。Starbutter AI 被谷歌评为谷歌助理平台上最佳的 3 个人工智能代理之一,旨在帮助消费者选择金融产品。Jean 负责监督公司的业务运营,管理合作伙伴关系,并帮助设计和构建人工智能虚拟助理,以“帮助消费者挑选金融产品,并通过对话式广告和性能 marketing"⁴.发现(这些产品)”

图片由 Jean Alfonso-Decena 提供

你能告诉我们一些你的背景吗?
Jean: 我在初创企业——客户服务领域工作了十多年,最初在 IBM 工作了 7 年,当时他们投资了菲律宾马尼拉的一个业务流程外包部门。我是先锋团队的一员,帮助培训和提升组织,寻找和培养支持一家美国大型电信公司的人才。在 IBM 经历了一次惊人的领导力成长之旅后,我转到了硅谷,为一家总部位于雷德伍德城的大型电子商务公司做文案工作。仅仅几周之后,我被从内容团队中抽调出来,组建了先锋客户服务团队,在接下来的 4 年里,我领导并帮助这个团队成长。我离开了公司,成为了一名企业家,却发现自己又回到了领导和发展另一个 CS 团队的道路上,为一家总部位于波士顿的媒体巨头工作。

客户服务的场景对我来说是一个巨大的祝福,因为这个空间让我在各个层面上成长,而不仅仅是专业方面。又休息了一段时间,在斯里兰卡和印度获得瑜伽/冥想教学认证。然后 Starbutter AI 出现了。这是一个漫长的吉祥之旅,最终来到了这个叫做 Starbutter AI 的特殊地方。

图片由 Jean Alfonso-Decena 提供

你一直都知道在金融科技领域工作是你想做的吗?是什么激励你在创业界追求职业生涯,并与 Starbutter AI 合作?你在信息和传播研究方面的经验对你的决定有什么帮助?

在 fin-tech 工作从未在我的计划或梦想中,更不用说在 AI 了。我有一个完全不同的轨迹——我准备通过有意识的企业家精神传播爱和光明,同时利用我多年来接受的领导力、电子商务和人员/项目管理培训。在我的精神旅程中,我和 Starbutter AI 取得了联系。这家公司的名字引起了我的兴趣,所以我查了一下,在瑜伽和冥想之间,我越来越多地研究团队、人工智能和金融科技。公司的使命、价值观和创始人激发了我的大脑,俘获了我的心。进入一个非常神秘的(人工智能)领域的可能性,了解金融科技,以及与该领域一些最聪明的头脑一起工作,是我改变策略的主要原因。

简而言之,我当时的自我对话是:当你得到一个千载难逢的机会来帮助建造增强人类生活的机器人时,抓住它。创始人的独特使命是我签约的原因。

图片由 Jean Alfonso-Decena 提供

在你的 DEVCON Lightning 演讲“未来的工作”中,你描述了在人工智能虚拟助手领域创造产品所需的创新和跨学科合作。你还描述了人工智能和机器学习应用程序如何受到构建它们的环境以及构建它们的人的高度影响。为什么你认为技术人员在构建聊天机器人和其他被不同客户群使用的产品时采取这种协作方式是重要的?当我谈到建造聊天机器人时,我总是用“人类婴儿”来比喻。虽然它们不完全相同,但它们有共性。抚养一个婴儿需要一个村庄——我知道,因为我是一个母亲。但是,即使在孩子出生之前,也要做大量的准备工作,以确保孩子在子宫里健康成长。这一旅程最好与母亲的支持网络一起进行,以优化婴儿的生长和分娩,其中包括家庭、健康专家、父母社区和该领域的其他专家。

“当你得到一个千载难逢的机会,来帮助制造能够改善人类生活的机器人时,抓住这个机会。”

构建聊天机器人的整个过程,从端到端,涉及到设计和构建它的精心策划。几个因素开始发挥作用,包括用户体验、机器学习和许多其他考虑因素。建造一个让用户满意的机器人确实需要几个人的智慧和双手。跳过一个就像把一个关键的元素留在了画面之外。机器人出来会不完整,用户体验会感觉不好。你永远不会希望这样,尤其是在对话式人工智能领域。更重要的是,如果你有不同的客户统计数据,我们有。在你把你的机器人带到这个世界之前,你要确保所有的基础都被覆盖,并且从发布开始就不断改进。

我认为这适用于任何产品或工作——但在虚拟助理设计的世界里更是如此。

答: Starbutter AI 旨在帮助客户“尽可能容易地匹配金融产品”。Starbutter AI 是如何实现这一使命的,Starbutter AI 的对话代理在这其中扮演了什么角色?你能描述一下在你作为一名专注于自然语言处理、机器学习和 UI/UX 的高级人工智能培训师期间,你在这个目标上的工作经历吗?就寻找有用的信息而言,金融产品的世界仍然是一个难题。你需要花几周到几个月的时间在网上进行研究,比较文献,拜访银行,打电话或发电子邮件,咨询精通金融的朋友和亲戚,以帮助你决定购买哪种保险或选择哪家银行开立储蓄账户。这涉及到很多资源和给予你的信任,并最终做出这个巨大的人生决定。Starbutter AI 通过部署我们的虚拟助理来简化这一过程,虚拟助理提供一份简短的三到四个问题的表格,并根据他们的答案定制前三家公司的推荐。我们的虚拟代理为用户完成繁重的工作——通常需要几个月的工作,机器人只需不到 30 秒就能完成。用户仍然拥有决定权——我们的代理的工作是在回答表格后提出他们的最佳匹配。

“技术的彻底转变正在从人类手中夺走任务,所以我们需要知道我们将如何利用我们的大学学位和工作经验。我们需要知道哪些内容仍然适用,哪些技能和知识可以在我们前进的过程中加以利用。”⁵

作为一名高级人工智能培训师,我很乐意帮助构建这些机器人——为了让一个机器人启动并运行,我做了大量的研究、分析和设计。我仍然参与到这个过程中,但是作为一名教练,我站在训练和提高他们的第一线。很像训练和指导一个人类代理。

作为 Starbutter AI 的运营和合作伙伴主管,你面临的最大挑战是什么,你是如何克服的?J: 阻止自己向世界推出尽可能多的虚拟助手,并向尽可能多的客户提供解决方案!

说真的,鉴于对话式人工智能仍处于萌芽状态,这一领域有很多机会。构建这些是非常有趣的,并且知道您的解决方案真正为个人和组织带来价值会使整个过程真正有回报。我得提醒自己慢慢来。

图片由 Jean Alfonso-Decena 提供

答:除了在人工智能虚拟助手领域的工作,你在菲律宾的创业社区也非常活跃。菲律宾的创业界有什么让你特别兴奋的创新吗?

J: 正是时候!我有幸在 2019 年马尼拉创业周末指导的一个团体刚刚启动了他们建立的社区,作为对菲律宾素食主义者社区的首次提供,名为世伟。这是一个在马尼拉的素食者和未来素食者的市场,连接了代表不足的商人和顾客。他们的独特之处在于,他们是一个简单明了的社区,旨在连接素食市场的两端。这只是一个开始,世伟在未来几个月内将会有更多的技术储备。我最喜欢这家初创公司的地方在于,它是由甚至不是素食主义者的高中女性创始人创建的。展示了菲律宾年轻人的聪明才智和素食主义信息的力量,让他们从头做起。

我感到兴奋的其他初创公司是目前正在开发的解决精神健康和农业/农民生计问题的几项技术。我还没有时间深入讨论这些,但这些绝对值得关注。

“我们需要与那种完全脱离常规、创造性地思考和生活的人在一起。我们更需要加强人类之间的联系,因为通过这种联系,我们可以建立起能够推动我们朝着正确方向前进的关系。”⁶

A: 您认为对下一代有抱负的技术人员来说,最大的挑战是什么,目前在该行业工作的数据科学家能提供什么帮助?
J: 新老技术专家不会被告知他们所使用的同一项技术的最新创新和发展,除非他们去寻找(或者有积极的导师)。有很多被动的等待和等待,等待现在正在发生的事情,或者下一个将要发生的事情。我们都需要在技术领域拥有自己的学习和发展——我们必须永远渴望并继续渴望世界上的知识和机会。不仅仅是在技术上。其中大多数都不是主动提供的——事实上,我们必须找到并获得它们。

来自一个没有技术背景的人,我热情地提倡[上述],并以真实的网络努力来补充这一点。与技术领域内外的人联系会带来新的想法和机会。如果你呆在角落里,你永远不会知道外面发生了什么,发生了什么,接下来会发生什么。让自己置身事外并与之交谈有很大的价值。

如饥似渴地阅读,不间断地学习,真实地网络。

由 Jean Alfonso-Decena 提供的图片

答:我们的读者如何才能接触到 Starbutter AI?我们的网站https://www.starbutter.com/是一个很好的起点。

除了作为领先的人工智能培训师在人工智能领域掀起波澜之外,Jean 还是菲律宾初创企业的积极导师和思想领袖。她在技术和产品核心领域广泛而深入的经验继续激励女性技术人员在数据科学领域进行创新。今天,Jean 正在领导一场运动,将人工智能和金融可及性民主化。Jean 不仅是菲律宾人的榜样,也让来自不同背景的女性能够利用技术实现积极的社会变革。

特别感谢 Jean Alfonso-Decena 允许我为这个系列采访她,并衷心感谢 TDS 编辑团队对这个项目的支持。

你认识一位鼓舞人心的科技界女性,你希望她出现在这个系列中吗?你是否正在从事任何你希望我写的很酷的数据科学和技术项目?欢迎给我发电子邮件,向 angelamarieteng@gmail.com 寻求意见和建议。感谢阅读!

[1]从菲律宾政府官网http://industry . gov . ph/category/Services/#:~:text = Services % 20 has % 20 been % 20 one % 20 of,6.3% 25% 20 from % 202000% 20 to % 202014。

[2]https://www . HCA mag . com/Asia/news/general/manilas-it-talent-to-target-industry-4.0-challenges/170535

https://www.starbutter.com/ourstory

https://www.linkedin.com/in/jeanalfonsodecena/?[4]originalSubdomain=ph

[5]https://www . HCA mag . com/Asia/news/general/manilas-it-talent-to-target-industry-4.0-challenges/170535

[6]https://www . HCA mag . com/Asia/news/general/manilas-it-talent-to-target-industry-4.0-challenges/170535

参考

“服务——保障菲律宾工业的未来。”n.d .于 2020 年 6 月 20 日进入。http://industry.gov.ph/category/services/.

“(7)谷歌宣布获奖者:助理平台| LinkedIn 最佳 3 款人工智能聊天机器人。”n.d .于 2020 年 6 月 20 日进入。https://developers . Google blog . com/2017/12/introducing-winners-of-actions-on . html

“(7)让·阿方索-德西纳|领英。”n.d .于 2020 年 6 月 20 日进入。https://www . LinkedIn . com/in/jeanalfonsodecena/detail/recent-activity/shares/。

“马尼拉 2019 年创业周末| 2019 年 2 月 8 日|马尼拉| Techstars。”n.d .于 2020 年 6 月 20 日进入。http://communities . tech stars . com/菲律宾/马尼拉/startup-weekend/14045。

“(481)让·阿方索·德西纳——YouTube。”n.d .于 2020 年 6 月 20 日进入。https://www.youtube.com/channel/UC_w-VaL0BMz50EYPzX2nNaw.

" Quickie 1:Jean Alfonso-Decena——人工智能训练者的忙碌|听笔记."n.d .于 2020 年 6 月 20 日进入。https://www . listen notes . com/pt/podcast/hustle share/quickie-1-jean-Alfonso-ytlwmaxotu 0/。

“认识 Jean Alfonso-Decena—block chain conferences . io”,未注明日期,2020 年 6 月 20 日发布。https://block chain conferences . io/speakers/jean-Alfonso-decena。

"(481)Quickie 1:Jean Alfonso-Decena——人工智能培训师的忙碌——YouTube . "n.d .于 2020 年 6 月 20 日进入。https://www.youtube.com/watch?v=513qpCzZZ_I.

"马尼拉的 IT 人才应对工业 4.0 挑战| HRD 亚洲."n.d .于 2020 年 6 月 20 日进入。https://www . HCA mag . com/Asia/news/general/manilas-it-talent-to-target-industry-4.0-challenges/170535。

"我们知道你对人工智能……-谷歌开发团队菲律宾|脸书感到兴奋."n.d .于 2020 年 6 月 20 日进入。https://www . Facebook . com/gdgphilippines/posts/we-know-that-you-excited-about-how-ai-shaping-todays-work force-so-were-Brin/1660848094047115/。

“服务——保障菲律宾工业的未来。”n.d .于 2020 年 6 月 20 日进入。http://industry.gov.ph/category/services/.

"人工智能在 2020 年银行业:银行如何使用人工智能-商业内幕."n.d .于 2020 年 6 月 20 日进入。【https://www.businessinsider.com/ai-in-banking-report.

"人工智能新闻:人工智能技术的最新进展|商业内幕."n.d .于 2020 年 6 月 20 日进入。https://www.businessinsider.com/artificial-intelligence.

“人工智能的下一步是什么——创新方程式。”n.d .于 2020 年 6 月 20 日进入。https://www . IBM . com/Watson/advantage-reports/future-of-artificial-intelligence/ai-innovation-equation . html

“到底什么是 AI 虚拟助手?| Voicera。n.d .于 2020 年 6 月 20 日进入。https://www.voicea.com/exactly-virtual-assistant/.

“我们公司和团队的故事| Starbutter。”n.d .于 2020 年 6 月 20 日进入。https://www.starbutter.com/ourstory.

“(10)让·阿方索-德西纳|领英。”n.d .于 2020 年 6 月 20 日进入。https://www.linkedin.com/in/jeanalfonsodecena/?原始子域=ph.

用轨道刮除工作板

原文:https://towardsdatascience.com/job-board-scraping-with-rails-872c432ed2c8?source=collection_archive---------20-----------------------

用 Ruby on Rails 和 Heroku 构建一个调度作业刮刀

唐纳德·詹纳蒂在 Unsplash 上拍摄的照片

与工作相关的数据是我最喜欢处理的数据之一。解析需求和分析跨时间、公司和地域的变化很有趣。

虽然有一些很棒的公共数据库有与工作相关的信息,但也很容易找到。

我们将在 Ruby on Rails 中构建一个每天自动运行一次的工作板刮刀,托管在 Heroku 的免费层上。

设置

假设你已经安装了 rails,创建一个新的 Rails 应用程序并cd到它的根目录。

$ rails new scraper-2020-03
$ cd scraper-2020-03/

然后修改Gemfile,这里设置了 ruby 依赖关系。注释掉这一行。

# gem 'sqlite3'

加上这一行。

gem 'pg'

然后运行这个来更新已安装的软件包。

$ bundle install

我们刚刚用 Postgres 替换了 Sqlite。

配置数据库

打开/config/database.yml并更新文件,如下所示。

default: &default
  adapter: postgresql
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: scraper_development

test:
  <<: *default
  database: scraper_test

production:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>

这里重要的部分是设置development的数据库名称database: scraper_developmentproduction的 URLurl: <%= ENV[‘DATABASE_URL’] %>

后者对我们部署到 Heroku 很重要。Heroku 默认将 Postgres 插件的 URL 设置为环境变量DATABASE_URL

现在在本地创建一个数据库。它将被命名为我们上面设置的名称。

$ rake db:create

创建 ORM 模型

生成迁移文件。这是我们指定要对数据库进行什么更改的地方。

$ rails g migration CreateJobs

导航到刚刚生成的迁移文件。我的是db/migrate/20200328142555_create_jobs.rb,时间戳会有所不同。

编辑它,如下图所示。

class *CreateJobs* < ActiveRecord::Migration[5.0]
  def change
    create_table :jobs do |*t*|
      *t*.string :location
      *t*.string :team
      *t*.string :job_title
      *t*.string :url

      *t*.timestamps
    end
  end
end

我们正在创建一个名为jobs的表,它有几个字符串列来存储抓取的信息。默认情况下会添加一个主idt.timestamps将添加created_atupdated_at列,当您将记录插入数据库时,这些列会自动填充。

/app/models/中创建名为job.rb的文件。这是我们的模型。应该是这样的。

class *Job* < ApplicationRecord
end

创建一个耙子任务

/lib/tasks中创建一个名为scrape.rake的新文件。Rails 中的 Rake 任务是用于自动化管理任务的命令,可以从命令行运行。如果你想写代码并安排它运行的时间,这里是放代码的地方。

更新scrape.rake

task scrape: :environment do
  puts 'HERE'

  require 'open-uri'

  *URL* = 'https://jobs.lever.co/stackadapt'

  *doc* = Nokogiri::HTML(open(URL))

  *postings* = *doc*.search('div.posting')

  *postings*.each do |*p*|
    *job_title* = *p*.search('a.posting-title > h5').text
    *location* = *p*.search('a.posting-title > div > span')[0].text
    *team* = *p*.search('a.posting-title > div > span')[1].text
    *url* = *p*.search('a.posting-title')[0]['href']

    *# skip persisting job if it already exists in db* if Job.where(job_title:*job_title*, location:*location*, team:*team*, url:*url*).count <= 0
      Job.create(
        job_title:*job_title*,
        location:*location*,
        team:*team*,
        url:*url*)

      puts 'Added: ' + (*job_title* ? *job_title* : '')
    else
      puts 'Skipped: ' + (*job_title* ? *job_title* : '')
    end

  end
end

用 Nokogiri (Ruby 的 html 解析库)导航 html 超出了我们的范围,但是如果你打开网页查看,你可以按照我的方法解析 DOM 树。

本地运行

应用程序都设置好了。本地运行就这么简单。

$ rake scrape

在我的本地数据库中,我现在可以看到数据。如果您没有好的工具来查看本地数据库,可以考虑使用 dbeaver

我们唯一的问题是我们不想每天手动运行它。通过部署到 Heroku 并安排任务来解决这个问题。

部署到生产环境

在浏览器中创建或登录您的 Heroku 帐户。

然后在命令行中键入以下内容。它将使用您的浏览器进行身份验证。

$ heroku login

运行以下命令在 Heroku 上创建您的应用程序。

$ heroku create

Heroku 将输出它给你的应用程序的名字作为响应。我的叫fast-garden-42976

现在在本地设置 git。

$ git init
$ git add . -A
$ git commit -m 'The first and last commit'

使用 Heroku 给你的名称(不是我的名称)添加你的应用程序,以便我们可以部署。

$ heroku git:remote -a fast-garden-42976

并展开。

$ git push heroku master

完成后,迁移 Heroku 上的数据库。

$ heroku run rake db:migrate

在生产中配置调度程序

通过手动运行命令在生产环境中测试它。

$ heroku run rake scrape

现在我们只需要将 rake 任务设置为一个调度作业。

在 Heroku web 控制台中,单击“资源”。

开始键入“schedule”并提供 Heroku Scheduler。

单击您刚刚添加的调度程序,然后单击“创建作业”。

配置rake scrape作业,每天午夜运行一次。

要善良,不要多刮地盘。

瞧啊。你的应用程序现在将每 24 小时添加一次新工作。

当您想要访问这些数据时,可以考虑像 Postico 这样的应用程序,它允许直接连接到 Heroku 中的远程数据库。或者,您可以从 Heroku 下载数据库并将其导入本地。

结论

这是一个快速简单的抓取应用程序。我们获取了每项工作的一些初步信息,并将其存入数据库。

如果你想更进一步,可能还需要补充一些东西。

  • 打开存储的 URL 以获取工作描述。
  • 如果抓取多个工作公告板,请在数据库中添加另一列来存储公司名称。

我希望这是有益的,我很乐意回答评论中的问题。

招聘会正在虚拟化

原文:https://towardsdatascience.com/job-fairs-are-now-going-virtual-6083b0f1c1d?source=collection_archive---------38-----------------------

女性社交活动虚拟化

照片来自 Shutterstock

一个亲自参加社交活动曾经需要精心计划,打印出名片和简历,穿着得体,留出足够的时间往返于活动现场。随着许多科技公司在新冠肺炎期间继续招聘,这些公司正在寻找虚拟招聘员工的方法,从而改变了社交活动的格局。

我最近参加了一个由 WomenHack Los Angeles 主办的网络活动,对虚拟网络的效率和真实性感到惊喜。WomenHack 是一个“通过评论、工作和活动赋予女性技术力量”的组织。该组织在世界各地的城市举办招聘会,由于新冠肺炎的快速传播,这些活动现在都是虚拟的。

我参加的 WomenHack 活动之所以成为可能,要归功于一个在线活动平台 Hopin 。该平台允许在舞台上进行主题演讲、聊天信息、投票、分组讨论以及一对一的交流。

[## 在线活动平台| Hopin

Hopin 是一个在线活动平台,在这里您可以创建引人入胜的在线活动,将全球各地的人们联系起来。

hopin.to](https://hopin.to/)

主旨

活动以出现在霍普金平台专用窗口的主题演讲开始。该平台还包含一个所有与会者和演示者都可以使用的聊天功能。在观看 keynote 的同时,能够看到其他与会者和演示者分享的聊天内容并参与其中,这种体验让人感到协作和包容。通常在大型活动中,大声说出并提出问题可能会令人生畏。让与会者在聊天窗口中提问,让每个人都能感觉到这个过程,即使对于通常躲在房间后面的胆小的人也是如此。

1:1 联网

主题演讲结束后,与会者有机会参加快速网络会议,与正在招聘的公司进行一对一的面对面交流。这无疑是这次经历中最激动人心和最具互动性的部分。作为一名与会者,我被重定向到一个页面,在那里我被随机匹配到一个招聘公司的代表。在屏幕的底部中央是一个“连接”按钮,如果按下并相互作用,会在活动结束后将每个人的联系信息添加到联系人仪表板中。之前给了我们 4 分钟的发言时间,,计时器超时,我被安排到另一家公司的代表。

世博会

该网站的另一部分模仿了一个网络展厅。出席活动的每家公司都有一个分组讨论展位,供那些有兴趣进一步聊天和了解机会的人使用。这是一种协作体验,多名与会者可以倾听并公开参与讨论。

如何在虚拟活动中成功建立关系网

现在你可能想知道如何在虚拟社交活动中取得成功。当考虑是什么造就了一次成功的面对面交流活动和虚拟交流活动时,有很多重叠的地方。首先也是最重要的,你应该在参加活动之前就有一个目标。问问你自己,“我想从中得到什么?”。目标是找工作或与其他与会者建立关系网吗?第二,与公司代表交谈时,提出深思熟虑的问题会给人留下深刻的印象。提前对这些公司进行调查,并列出有意义的相关问题,这将会影响他们对你的看法。

参加虚拟网络活动时,请遵循以下提示:

  1. 与其他与会者和公司代表交谈需要网络摄像头和麦克风设置。建议事先测试麦克风和扬声器,并确保你坐在一个背景干净、光线充足的地方。
  2. 更新你的 LinkedIn 个人资料。与其他与会者和公司代表联系的最佳方式是通过 LinkedIn。大多数虚拟场馆平台可能会允许你创建一个带有 LinkedIn 个人资料链接的个人资料。其他与会者和公司代表将能够看到您的 LinkedIn 个人资料,这可能是您在活动结束后的主要沟通方式。
  3. 做一个有效简洁的介绍。在 WomenHack 活动期间,1:1 网络仅允许您与每位公司代表进行 4 分钟的交流。这是一段很短的时间,你可以介绍自己,了解公司,并提出任何问题。有效利用这段时间!
  4. 网络摄像头上的肢体语言很容易读懂,即使你没有亲自互动。一定要微笑,有良好的眼神交流,和良好的姿势,以显得真诚和更有效地沟通。
  5. 跟进。现在,通过在一对一交流过程中建立联系,您已经获得了该代表的联系信息。如果你对公司的机会或与个人的联系感兴趣,请在活动结束后跟进。

总体印象

无论你是在找工作,还是对建立联系感兴趣,我都强烈建议你参加虚拟社交活动。已经开发并正在开发的支持虚拟场馆的技术在创建与现场活动同义的虚拟体验方面非常强大。如果我亲自参加的话,我会从这个网络会议中获得很多。不必担心运输,交通,印刷名片和简历的物流,举办这些活动实际上使更多的人有机会参加这些类型的活动。

基于 NLP、机器学习和深度学习的工作薪酬预测

原文:https://towardsdatascience.com/job-salary-prediction-with-nlp-machine-learning-and-deep-learning-b87a96336b08?source=collection_archive---------21-----------------------

利用从 Indeed.com 搜集来的职位信息进行工作薪水预测项目的第二部分

Clem Onojeghuo 在 Unsplash 上拍摄的照片

项目背景

找工作最重要的事情之一是知道你现在在哪里,你下一步想去哪里。求职者的心态很像产品经理,试图找到最适合的产品和市场。聪明的产品经理知道他们的客户想要什么。因此,他们仔细地找出客户的需求,这些需求通过职位描述中的“最高资格”、“你必须具备的条件”来表达。在确定了市场上普遍需要的东西之后,聪明的产品经理会定制他们的产品,比如简历、求职信、在线简介、作品集,以尽可能展示这些特点和特质。这个项目是为了帮助你成为那个聪明的产品经理,告诉你什么样的品质和顶级技能是市场所需要的,并进一步帮助你在工资谈判中导航,做出最佳选择!

怎么会?该项目将在美国主要城市的数据/分析领域取消 10000 多个职位,以及职位名称、公司、公司评论、城市、职位描述、薪资范围等信息。我们将从职位描述文本中提取特征,并在机器学习和深度学习模型中使用这些特征。稍后,我们将把文本特征与生活成本指数、购买力指数、位置等其他特征结合起来,为模型添加更多的颜色。

数据集

我放弃了 Indeed.com 的 12,115 份工作,主要集中在数据相关领域,如数据分析、数据科学/数据工程、商业分析、数据库管理等。如果你对我如何收集数据感兴趣,请查看我在这里发布的部分。

在初始数据清理(删除重复项、检查 nan 等)之后。),留下了 964 个工资明确的岗位。Indeed.com 只有 8%的招聘信息有工资条😂。964 不是一个大数字,但对这个项目来说应该没问题。

我还预处理了位置和薪水列。原始工资信息包括小时工资率、月工资率和年工资率。所以我使用了一些正则表达式技术来清理它们,并将其转换为平均年利率。

这是数据现在的样子。

连续的工资数据被转换成更平衡的箱,以获得更好的预测结果。所以现在我们有 6 个箱子:0-50k 美元、50k-70k 美元、70k-90k 美元、90k-120k 美元、120k-150k 美元和 150k+。

连续工资数据被转到工资箱

我还有另一张表,上面有美国主要城市的生活成本指数,房租成本指数,购买力指数。我将在这篇文章的后面使用它们。

建模

现在我们来看建模部分。由于作业 描述将主要用于获取特征和建立分类模型,因此本项目将探索多种文本矢量化技术。我为这个项目建立了 7 个模型,基本上是不同矢量化方法+分类模型的组合。网格搜索应用于整个建模过程,以获得最佳的参数集。

模型 1:计数矢量器+ TF-IDF 变换+分类模型(随机森林/SGD/SVM)

模型二:Word2Vec 嵌入+分类模型(随机森林/SGD)

模型 3:预训练手套嵌入+分类模型(随机森林/SGD)

模型 4:单词嵌入+简单神经网络模型

模型 5:预训练手套嵌入+深度神经网络模型

模型 6:具有城市、费率类型和生活费用指数的混合输入网络模型

模式 7:仅使用职位、城市、生活成本指数+分类

如果我对每一个模型进行扩展,这篇博客文章将会是一篇论文,所以我将在这篇文章中关注以下三点。

在这篇文章中,我将重点关注以下几点:

  1. 使用计数矢量器和 TF-IDF 转换器(相当于 TF-IDF 矢量器)从文本中提取特征
  2. 开发 Word2vec 嵌入并在机器学习管道中使用

3.在 Keras 中建立混合输入网络模型

使用计数矢量器-TF-IDF 转换器提取要素

使用计数矢量器和 TF-IDF 转换器相当于 TF-IDF 矢量器。其思想是首先将一组文本文档转换成一个令牌计数矩阵,然后将一个计数矩阵转换成一个规范化的 TF(术语频率)或 TF-IDF(术语频率-逆文档频率)表示。当分析职位描述以进行薪资预测时,我意识到仅基于计数并不容易找到“决定性”的词,因为所有的职位描述都在数据字段中,因此像“数据”、“分析”、“经验”这样的词出现频率非常高。然而,预测工作工资范围也不同于普通的文本分类,在普通的文本分类中,你可以区分“快乐”和“悲伤”,“真”或“假”。所以我们真的需要 count 和 tf-idf,以及机器学习模型。

编码部分其实很简单:

在分类模型中使用 Word2Vec 嵌入

Word2Vec 是一组用于产生单词嵌入的相关模型。这些模型是浅层的单层神经网络,被训练来重建单词的语言上下文。详细解释可以在这里找到。

为了使用我们自己的数据创建 Word2Vec 模型,我们需要为该模型指定以下参数:
我们想要学习的单词向量的大小训练模型时使用的
窗口大小

  • min_count ,其对应于单词为了被包括在训练中而必须在语料库中使用的最小次数(例如, min_count=5 将只学习在整个训练集中出现 5 次或更多次的单词的单词嵌入)
  • workers ,用于训练的线程数量,这可以加速处理(通常使用 4,因为现在大多数处理器至少有 4 个内核)

在上面的代码中有两个步骤:1)训练 Word2Vec 模型,2)计算平均单词嵌入——想法是获得出现在该文本块中的每个单词的向量,并将它们平均在一起。这样做的好处是,无论文本块有多大或多小,该句子的平均单词嵌入量将与所有其他句子的平均单词嵌入量相同,以确保我们在对向量进行平均后获得相同的维数。

在 Keras 中建立混合输入网络模型

这是我第一次尝试在一个神经网络模型中同时使用文本数据和数值分类数据。从概念上讲,该过程如下所示:

Keras Functional API 使这项任务变得简单。

第一步是检查数字/分类输入和文本输入的维数,并确保它们具有相同数量的目标类。其次,我们可以为每个输入创建单独的网络模型,并将它们连接在一起。最后一步是添加一个输出图层。

在我的 github 上查看完整的项目和代码,如果有任何问题,请随时告诉我!

感谢阅读到目前为止。最后一个问题:你认为哪种型号性能最好😀?

资源:

[## 如何用 Gensim -机器学习掌握在 Python 中开发单词嵌入

单词嵌入是自然语言处理中表示文本的一种现代方法。单词嵌入算法…

machinelearningmastery.com](https://machinelearningmastery.com/develop-word-embeddings-python-gensim/) [## Keras:多输入和混合数据- PyImageSearch

在本教程中,您将学习如何使用 Keras 处理多输入和混合数据。您将学习如何定义一个 Keras…

www.pyimagesearch.com](https://www.pyimagesearch.com/2019/02/04/keras-multiple-inputs-and-mixed-data/) [## 如何使用 Keras Functional API 进行深度学习——机器学习掌握

Keras Python 库使创建深度学习模型变得快速而简单。顺序 API 允许您创建…

machinelearningmastery.com](https://machinelearningmastery.com/keras-functional-api-deep-learning/)

约翰·康威的生活游戏和互动视觉化

原文:https://towardsdatascience.com/john-conways-game-of-life-and-interactive-visualization-9647c82044ef?source=collection_archive---------31-----------------------

庆祝一位伟大的数学家并探索输入数据的方法。

在当前的冠状病毒疫情的悲惨损失中,杰出的数学家约翰·康威于 4 月 11 日去世。他对群论和博弈论做出了重大贡献,但最广为人知的可能是他的人生游戏。《生命的游戏》是一个简单而迷人的细胞自动机练习,最终发展出了自己的生命,远远超出了康威的预期。

生命的游戏发生在一个网格上,某些细胞被标记为“活的”或“活跃的”,而其他细胞被标记为“死的”或“不活跃的”。

一个生命网格游戏的例子,黑色格子被切换为“开”

网格的初始条件由玩家设定,但之后,网格会根据设定的规则演变:

1.如果一个当前不活跃的细胞正好有三个活跃的邻居,它就像在下一轮繁殖时一样被激活。

2.如果一个活细胞的活邻居少于两个,它就像因人口不足而死亡

3.如果一个活细胞有三个以上活跃的邻居,它就像因人口过多而死亡

4.有两个或三个活邻居的活细胞持续到下一回合

先前的初始安排如何在连续的回合中发挥作用

生活的游戏很简单——康威特别选择了尽可能简单的规则,同时满足其他条件——它被证明是一个持久迷人的框架,基本上开创了细胞自动机的领域。这个游戏有趣的,甚至不可思议的特点是,它可以被证明是图灵完全的,因此人们在游戏中“编程”了一些东西——一个数字钟,一个工作版本的俄罗斯方块,生命本身的游戏

上周,作为对康威的讽刺性致敬(他公开表示,他不认为自己的人生游戏有那么有趣,并对他可能因此而获得认可表示了些许不满),我试着编写了自己的人生游戏实现。我意识到,对于任何从事数据图形工作的人来说,这个游戏实际上可能是一个有用的可视化和用户交互练习——游戏的规则非常简单,即使是新参与者也应该能够通过代码来理解它们,但用户如何在开始时有效地设置电路板的问题并不是数据科学世界中最常见的交互式可视化的典型问题。

在初始设置过程中,用户有很多种方式与电路板进行交互,但是允许用户在电路板上选择任意数量的点并不是用滑块或下拉菜单就能很好解决的问题。一种解决方案使用通用图形库 Matplotlib,它具有交互式功能,允许用户单击许多新用户可能不知道的图形,但不清楚这是最简单还是最有效的解决方案。考虑到这一点,我想把康威的《生活的游戏》作为一个互动视觉的小型实用案例来展示,并提出几个可能的解决方案。这绝不是所有的解决方案,我把它看作是一个挑战,让用户找到最简单的方法,尽可能高效地建立一个任意的网格,同时需要尽可能少的外部库。

第一步:设置游戏

我做的第一件事是创建一个简单的面向对象版本的规则。我创建了一个新的类,对应于游戏中的一个单元格,属性对应于它在网格中的位置和状态,还有一个方法根据游戏规则更新单元格的状态。这些对象可能看起来像这样:

如果您非常习惯使用 Python,这个方法对您来说可能有点过于复杂。为什么要创建一整类对象呢?你可以像一个由 1 和 0 组成的 Numpy 数组有一个根据游戏规则更新网格的函数一样简单地表示网格。有几个原因。一个是,我认为游戏内部逻辑的实现根本不应该引用任何外部库,不要假设最终用户会安装什么包,如果可能的话,让整个程序运行起来,而不需要另外安装任何东西。我的第一个实现使用了一个名为诅咒的库,它实际上是随 Python 一起安装在 Mac OS 上的,用来可视化网格,因此它不需要 Python 3 以外的任何东西就可以为许多人运行。

另一个原因与个人对代码组织的偏好有关。我需要一种标准的方法来实现规则和更新网格,不管我用什么来输入起始网格或显示视觉效果,它都可以以同样的方式工作。您的收获可能会有所不同,这取决于您认为使用哪种结构最方便,但是我发现这种方法可以简化代码调试。

无论如何,不管你用什么方法,实际上模拟生活的游戏是非常简单的:定义规则,创建你的网格对象,打开某些单元格,更新单元格的状态,迭代连续的回合。更有趣的问题是如何构建一个简单的输入方法,这样无论网格大小如何,用户都可以轻松地输入起始条件。您可以要求输入一些坐标,但这很麻烦,尤其是对于较大的网格,因此最好是找到一些其他的输入方法。

输入法 1: Matplotlib 交互性

如果您与 Matplotlib 的主要交互是查看笔记本中的静态输出,您可能实际上没有意识到 Matplotlib 具有接收交互式输入甚至跟踪内置鼠标移动的能力。从命令行运行 Python 脚本将在自己的 Python 窗口中打开您的绘图,您可以通过该窗口与绘图进行交互,只要您告诉 Matplotlib 何时会收到某些输入,以及在输入到达后如何处理它们。

对于简单的点击界面,您可以使用函数。ginput(),它将收集单击输入的坐标。一个简单的用法可能是这样的,您可以将鼠标悬停在任何单元格上并单击以激活它们,或者再次单击它们以取消激活它们:

使用 Matplotlib 跟踪鼠标点击的位置来更新网格

在本例中,我使用一个 Numpy 数组来表示棋盘,这既是为了便于索引,也是因为您可以使用 Martplotlib 的 imshow 将数组转换为一行中的图形,它将数组中的值读取为编码显示颜色。生成一个简单网格并跟踪哪些点被选中的代码如下所示:

然后可以将启动点列表输入到一个函数中,该函数初始化 Conway cell 对象的网格(或者您可以简单地使用由 1 和 0 组成的 Numpy 数组),然后就可以计算出游戏的未来回合数并绘制成图表。

我鼓励那些之前不熟悉 Matplotlib 的交互特性的人去体验一下。它们开辟了一系列有趣的可能性,切换或选择数据,改变可视化风格,甚至输入新数据,而无需设置外部仪表板。这种方法工作得很好,很明显,更广泛地使用 Matplotlib 的这些特性有很大的潜力,但我并不完全满意。对于更大的网格或更复杂的起始条件,这种方法也会变得很麻烦。在输入和图形响应之间也有一点滞后,我觉得有点沮丧,所以我继续寻找其他有趣的图形输入方法。

输入法二:带诅咒的乐趣!

我前面提到的 Curses 库提供了另一个有趣的解决方案。Curses 允许您控制将字符输出到终端窗口。这更像是一种古怪的倒退,创造了一种有趣的类似 ASCII 的表示,而不是一个严肃的图形库,但是,正如我提到的,它是为许多人内置的。

使用 curses 在网格上输入位置

除了找出如何让我的生活游戏在诅咒中工作的内在乐趣之外,我最终认为像诅咒这样的工具实际上可能提供一些有用的方法。我已经准备好为我的数据科学工作探索其他有趣且很少使用的包。

Curses 允许你在可用屏幕上的任何地方放置角色,这种方式非常简单,尽管有一些奇怪的地方需要记住。首先,在放置任何东西之前,你需要实际检查屏幕有多大。如果用户扩展终端窗口,Curses 必须处理的画布的大小将会扩展。其次,Curses 从上到下对屏幕进行索引,这是标准打印的延续,在标准打印中,页面顶部的内容首先打印出来。最后,Curses 会收集您想要添加到屏幕上或想要更改的任何角色的位置,但它不会实际显示任何更改,直到您告诉它刷新屏幕,并且它不会更改您没有明确告诉它的屏幕的任何部分。如果你不清除屏幕上的任何字符,它们将一直存在,直到被覆盖。

我的生命诅咒游戏实现的输入页面的代码如下所示:

请注意,它在一个字典中收集所有切换单元格的位置,然后我可以轻松地将它传递给一个函数来初始化生活模拟游戏。我开始想,也许终端中的视觉效果是传递坐标等信息的一种不错的方式,我正在考虑使用它的其他方式。

作为对伟大的约翰·康威的致敬,考虑用你自己的方式来玩生活游戏的实现,思考集合或者只是以你自己的方式进行创造性的创新。

连接熊猫聚合和 SQL 分析函数

原文:https://towardsdatascience.com/join-pandas-aggregate-and-sql-analytic-functions-41a611d2759b?source=collection_archive---------50-----------------------

我们使用聚合函数 sum、average、min 和 max 实现移动平均、等级项目、累积和

Naven Krcmarek : unsplash

SQL 分析函数用于将大型数据集汇总成一个简单的报告。这些功能产生的数据汇总可以很容易地可视化。这些功能有助于数据分析专家轻松分析复杂的数据。

在本文中,我们结合 pandas 聚合和分析函数来实现 SQL 分析函数。

SQL 分析函数有许多种类。我们将逐一介绍这些功能。但首先,让我们了解一下本文中使用的数据。

零售数据集

我们将使用 Kaggle 数据集。以下是对数据集每一列的解释。

该数据集的销售日期从 2010 年 2 月 5 日到 2012 年 11 月 1 日。

商店——商店编号

部门——部门编号

日期—代表一周

Weekly_Sales —每个部门的商店每周销售额

IsHoliday 表示一周内的假期

这里是零售数据集的几行。

现在,让我们从 SQL 分析函数开始。

1.秩和稠密秩函数

秩和密秩提供了有序数据集的秩。这两个函数有一个小的区别。通过这个例子,我们可以很容易地理解这种差异,我将在本节的最后解释这一点。

等级和密集等级的用例

1.您可以使用这些函数来查找世界、大洲或国家的前 N 名亿万富翁。

2.计算商店中前 N 件商品在一天、一周、一月或一年中的销售额。

3.计算一家公司在世界不同地区的增长和业绩。

4.根据 GDP、饥饿指数、人口等对国家进行排名。

SQL 秩和密集秩函数的 Pandas 等价物

  • 由等级和密集等级函数分配给索引 5314 和 6214 的等级是 141。并且由等级和密集等级函数分配给索引 2794 的等级是 143 和 142。这种类型的等级分配将等级函数与密集等级函数区分开来。
  • 将总和替换为中值。agg 函数计算平均每周销售排名和密集排名。
  • 使用 groupby 函数中的其他列可以更好地理解数据和 rank/dense rank 函数。

2.百分比等级函数

Percent rank 函数考虑一组行来计算一行的百分位值。其值范围在 0 到 1 之间。

百分比等级的用例

1.我们在竞争性考试中使用这个函数来根据考生的分数计算他们的百分位数。

2.这些公司使用这种方法计算每个员工的收入,同时考虑其他员工的收入。

SQL 百分位等级函数的 Pandas 等价物

  • 在 2011 年 11 月 25 日,商店 4 的销售额最高,商店 10 的销售额次之。索引 1404 处的 Percent_weekly_sales 值表示商店 10 的销售额超过该商店的 97%。
  • 将平均值替换为中的和。agg 函数根据每周销售总额计算百分比。

3.滚动功能

滚动函数计算指定时间范围内数据的平均值。它添加一个旧的数据点,并添加一个新的数据点来计算平均值和均值。但是指定的时间框架是不变的。

滚动功能使用案例

1.这种方法将帮助你找到股票的 50、100、200 天移动平均线。均线是股票交易者的重要技术指标。这将有助于他们预测股票价格的走向。

2.你可以用这种方法追踪蔬菜的价格。你可以查一下,淡季蔬菜的移动价格是多少。

SQL 滚动功能的熊猫等价物

  • 的。滚动功能输入 5 表示,当前行+ 4 个先前行。的。mean()函数将取 5 行的平均值,并将结果存储在当前行中。也被称为 5 移动平均线周销售量。
  • 若要避免 Weekly_Sales_rolling5 列的起始行为空值,请使用 min_period=1。
  • 第 4 行的 Weekly_Sales_rolling5 列值表示第 0、1、2、3、4 行的 Weekly_Sales 值的平均值。

4.行数函数

行号函数为聚合组的每一行分配一个唯一的编号。

行号功能的用例

1.此函数将有助于查找组织中员工的第五大或倒数第二个薪金值。

2.您可以使用此函数计算一个组中数据点的总数。

Pandas 等价于 SQL 行号函数

  • 熊猫。cumcount 函数为存储组中的每一行提供一个唯一的编号。由于行的编号从 0 开始,因此,我们使用。累计()+1。
  • 此功能将帮助您找出商店 1 中销售额第五高的日期。

结论

SQL 分析函数看起来很难理解和实现。但是,你可以很容易地理解或掌握这些分析功能。还有其他类型的分析函数可用于数据分析。但是大多数情况下,我们在数据分析任务中使用上面的 SQL 函数。

使用这些函数深入研究数据并发现数据中的模式。

加入表格

原文:https://towardsdatascience.com/join-the-tables-ab7fd4fac26b?source=collection_archive---------33-----------------------

了解 Python pandas 中的 merge()和 concat()

照片由来自像素皮克斯拜拍摄

数据科学项目始于数据。从不同的来源收集所需的数据,对其进行评估、清理和存储,以便进一步分析和建模。

数据是数据科学项目的关键要素

然而,在一个项目中有多个数据集是相当混乱的。在数据清理时,需要对所有数据集应用相同的过程,这是一项繁琐的任务。这也可能会导致一些错误。在这种情况下,将所有数据集组合在一起以获得整个数据的单一视图是一个好主意。当原始数据是从不同的文件、工作表、数据表,甚至是从 web 抓取中收集时,这个过程通常是必要的。

[## 网页抓取—制作您自己的数据集

从网页中提取数据并将其存储到 excel 中—只需 4 个简单的步骤

towardsdatascience.com](/web-scraping-make-your-own-dataset-cc973a9f0ee5)

在 Python 中,有两种方法可以组合来自不同数据帧的数据。因此,这就是这两种方法的故事—

熊猫。data frame . merge Vs pandas . concat

DataFrame 是最常用的 pandas 对象,用于以行和列的形式存储不同数据类型的表格数据。

merge()和 Concat()是 pandas 中组合不同数据帧的两个非常有用的方法

让我们创建三个数据帧, df_one,df_two,df_three

countries = {'ID':["EU101","AS101","EU103","EU102","US111"],\
             'Country': ["Germany", "India", "Belgium", "Austria",   "Mexico"]}states = {'Countryname': ["France", "India", "Belgium", "Japan", "Mexico","Spain"],\
         'statecount': [15, 7, 10, 9, 32, 10]}europe ={'ID':["EU101","AS101","EU103","EU102","US112"],\
        'EU_member': ["Yes", "No", "No", "No", "No"],\
        'Airports': [36,126,5,6,77]}df_one = pd.DataFrame(countries, index = [0,1,2,3,4])
df_two = pd.DataFrame(states, index = [1,2,3,4,5,6])
df_three = pd.DataFrame(europe, index = [0,1,2,3,4]) 

样本数据帧

1.Concat()

它沿着一个特定的轴耦合熊猫数据帧。它将数据集按行或列连接在一起。

假设,您想要在行方向上组合三个数据帧 df_one、df_two 和 df_three,以便它们将形成单个数据帧。

使用 Concat(),您只需要在一个列表中传递数据帧的名称。

df_four = pd.concat([df_one, df_two])

默认情况下,两个数据帧简单地缝合在一起,一个在另一个下面。两个数据帧中的所有列和行都将保留。

级联数据帧

要并排连接这些表,必须向 concat()添加一个额外的参数axis = 1

df_four = pd.concat([df_one, df_two], axis = 1)

简单!!

所有数据帧被连接在一起作为单个数据帧。但是等等,我怎么知道,哪个数据来自哪个数据帧??

熊猫对此有一个答案。Pandas 提供了一个用关键字标记数据帧的选项,这样,在连接之后,您将知道数据帧来自哪里。这种数据标记实际上使得提取对应于特定数据帧的数据变得容易。

df_four = pd.concat([df_one, df_two], keys=[“df_one”,”df_two”])

具有源数据帧名称的串联数据帧

在组合来自多个数据帧的数据时,我们确实可以控制在结果数据帧中得到什么。可以使用 Concat()中的join参数来实现。在这场争论中,熊猫给了我们两个选择。

  1. outer:数据帧的联合
df_five = pd.concat([df_one, df_two], axis = 1, join = 'outer',\
                   keys=['df_one', 'df_two'])

带有外部连接的 pandas.concat()

对应于所有索引的行保留在结果数据帧中。

  1. inner:数据帧的交集
df_five = pd.concat([df_one, df_two], axis = 1, join = 'inner',\
                   keys=['df_one', 'df_two'])

带有内部连接的 pandas.concat()

在一个inner连接中,数据帧df_onedf_two共有的所有索引都保留在结果数据帧中。默认情况下,熊猫执行沿行的外部连接。关于它的文档信息可以在这里找到。

2。merge()

它以数据库风格组合数据帧,即数据帧在公共列或索引上连接。通常,我们处理不同的数据集,这些数据集包含关于同一实体的不同类型的数据。这种数据集通常通过一两个公共列相互链接。

merge()根据公共列中的值组合数据帧。

df_four = df_one.merge(df_three)

这就是表格合并的方式

如您所见,df_onedf_three这两个表在两个表中都可用的公共列 "ID" 上连接,并且在两个表中对于列 "ID" 具有相同值的行将保留在结果表中。merge()自动识别两个表中的公共列。

由于它的定制选项列表很长,merge()被认为是连接表或数据帧的最灵活的方法。

我最常听到的关于 merge()的说法是,

merge()以 SQL 风格连接表

你不了解 SQL 或者结构化查询语言???

完全没问题。这里我展示了理解 merge()的最简单的方法。每个人都知道集合论中的维恩图和维恩图的基础知识,如集合的并和交。下面四张图会给你最简单最清晰的 merge()视图。光看颜色,这些图片就一目了然了。

merge()提供了 4 个选项来获得对结果数据集的控制,这些选项可以在 merge()内的 "how" 参数中传递,例如,

df_one.merge(df_three, how="inner")

默认情况下,merge()提供内部连接,因此不需要特别提到它。一个 内部 连接类似于集合 的 交集,而 外部 连接类似于集合联合。

所以,这里有 merge()选项,

这就是 merge()的工作方式

在 merge()中,有一个巨大的可选参数列表,可以在这里进行探索。

熊猫。DataFrame.join() 可以认为是 merge()的一种简单形式,可选参数较少。它确实像 merge()-join 操作一样。与 merge()不同,join()在公共索引上耦合两个数据帧。因此,要将两个表或数据帧连接在一起,我们应该在两个数据帧中设置相同的列作为索引。该表格连接选项也可在文档中找到。

感谢您的时间和阅读!!!

我希望你喜欢这个关于熊猫的简单解释,这是加入数据集的两个重要特征。选择 Concat()还是 merge()完全是我们的选择,但我主要使用 merge(),因为它提供了广泛的选项。如果你喜欢这篇文章,请随时添加反馈,并在 LinkedIn 上与我联系。

[## Suraj Gurav -副机械工程师-康耐视公司| LinkedIn

查看 Suraj Gurav 在全球最大的职业社区 LinkedIn 上的个人资料。Suraj 有 8 个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/surajgurav17/)

在 Knowi-Tutorial 中连接来自两个独立 REST APIs 的数据

原文:https://towardsdatascience.com/joining-data-from-two-separate-rest-apis-in-knowi-tutorial-72fc668d3d53?source=collection_archive---------64-----------------------

连接和可视化来自不同 REST APIs 的数据,自动查询,并用英语询问您的数据问题。

亚当·诺瓦克斯基在 Unsplash 上的照片

目录

介绍

REST API中提取数据在当今的分析世界中是一种非常常见的做法,而且理由充分。API 是强大的工具,允许用户的服务器调用另一个服务器,并直接提取大量数据,而无需离开用户的网站或程序。用户还可以设置自动化 API 调用,这允许他们在指定的时间间隔内从外部服务器获取数据。

虽然来自 REST APIs 的大部分数据都是 JSON 格式的,但也有一些数据是 CSV、SQL 或 NoSQL 格式的。Knowi 不仅与 JSON,还与 CSV、SQL 和 NoSQL 数据进行了广泛的本机集成,这使得 Knowi 能够高效地进行 API 调用,并消除繁琐的 ETL 过程。

将 REST API 设置为数据源

一旦您登录到您的 Knowi 试用帐户,第一步是连接到您的目标 REST API 并确保您已经建立了连接。下面是如何做到这一点:

1.使用屏幕左侧的面板点击“数据源”

2.滚动到底部,在中间的“外部”部分,单击{REST}。

3.确保命名新的数据源。出于本教程的目的,我们称之为“冠状病毒数据源”

4.在右上角输入 API REST 主机的 URL。对于本教程,我们将使用 Github 存储库,其中包含直接来自约翰霍普金斯大学的各种文件。将此链接用于您的 REST 主机:

[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series)

5.向下滚动到底部,找到标题为“测试连接”的蓝色按钮点击这个,一旦你这样做了,你应该会收到一个警告,在你的页面顶部说“连接成功。”

6.一旦你确定你有一个连接,移到“测试连接”按钮的右边,点击“保存”

将 REST API 设置为您的数据源(来源—knowi.com)

恭喜你!您已经设置了第一个数据源。

从 REST API 查询数据

现在您已经完成了第一个数据源的设置,是时候开始对数据进行查询了。你可以这样做:

1.当您保存完数据源后,您应该会在页面顶部收到一个警告,提示“Datasource Added”。配置查询。点击单词查询。(或者,您可以返回到屏幕左侧的面板,单击“数据源”正下方的“查询”,然后从右上角选择“新查询+”。)

2.在开始任何其他操作之前,请确保将查询命名为 Report Name*,如果在保存数据源后没有直接进入查询,请选择数据源。让我们称这个报告为“API 调用”

3.向下滚动到设置,并在“端点”下添加 API 调用的端点我们将在此使用的端点返回一个大型 CSV 文件,其中包含来自美国每个县的每日确诊新冠肺炎病例。使用此端点:

/time_series_covid19_confirmed_US.csv

4.找到屏幕左下角的蓝色“预览”按钮,然后点击右边的向上小箭头。向上滚动到 100 并点击它,快速预览 100 行数据。

从 REST API 查询数据(来源——knowi.com)

5.我们的数据集对每个日期都有一个单独的列,这不是我们想要的。这意味着我们应该使用 cloud 9ql——Knowi 的强大内置查询语言——来查询我们的数据,并以我们想要的形式呈现出来。向上滚动到“Cloud9QL Query”开始使用。

6.假设我们的最终目标是一个有两列的表:日期和当天美国新确诊的新冠肺炎病例。Cloud9QL 将允许我们通过四个简单的步骤来实现这一点:

  1. 反向转置所有列,并添加一个名为“日期”的新列来存储刚刚反向转置的新日期。
  2. 选择一个使用 Cloud9QL 的 str_to_date 函数将日期从字符串转换为日期的新列,以及一个作为事例总数的新列。
  3. 按日期将我们的数据分组
  4. 选择日期和一个新列,该列使用 Knowi 的 delta 函数从当前日期的案例总数中减去前一日期的案例总数。为了执行这些步骤,只需将以下语法复制并粘贴到您的 Cloud9QL 查询中:
select reverse_transpose(UID,iso2,iso3,code3,FIPS,Admin2,Province_State,Country_Region,Lat,Long_,Combined_key,Population,Date,Cases,*);
select str_to_date(date,MM/dd/yy) as Date, sum(Cases) as Cases
group by date;
select Date, delta(Cases) as Cases

7.一旦将该语法粘贴到 Cloud9QL 查询中,返回蓝色的“Preview”按钮,再次预览前 100 行,以确保数据是我们想要的格式。您应该会看到一个包含日期和该日期新新冠肺炎病例数的两列表格。

8.一旦您确认数据是您想要的格式,选择当前预览下方的“数据网格”栏,并将可视化类型更改为“折线图”,以便查看您刚刚预览的 100 行的更引人注目的视图。

9.我们稍后将回到可视化我们的其余数据。现在,单击绿色的“保存并立即运行”按钮保存您的查询。

从 REST API 查询数据(来源——knowi.com)

在保存查询并至少运行一次之后,Knowi 使用查询结果创建了一个虚拟数据集,并将该数据集存储在其弹性数据仓库中。每次你运行这个查询时我都会这样做。

将您的 REST API 中的数据与另一个 REST API 中的数据连接起来

既然您已经将一个 REST API 设置为数据源并查询了它,那么用另一个做同样的事情应该会更容易。首先,我们将重复设置第一个 REST API 的过程:

1.使用屏幕左侧的面板点击“数据源”

2.点击屏幕右上角的橙色按钮“新数据源+”

3.滚动到底部,在中间的“外部”部分,单击{REST}。

4.确保命名新的数据源。我们称之为“股票市场数据源”

5.在右上角输入 API REST 主机的 URL。我们将使用 Alpha Vantage 的 API 为我们提供实时股票市场数据。使用这个网址:

[https://www.alphavantage.co](https://www.alphavantage.co)

6.向下滚动到底部,找到蓝色的“测试连接”按钮。点击这个,一旦你这样做了,你应该会收到一个警告,在你的页面顶部说“连接成功。”

7.一旦你确定你有一个连接,移到“测试连接”按钮的右边,点击“保存”

将您的 REST API 中的数据与另一个 REST API 中的数据连接起来(来源——knowi.com)

现在我们已经建立了两个数据源:冠状病毒数据源和股票市场数据源。是时候把我们的股市数据和我们的冠状病毒数据结合起来了。我们是这样做的:

1.返回屏幕左侧的面板,并返回“查询”

2.我们不是创建新的查询,而是将另一个数据源的查询追加到当前查询中,并将新查询中的数据与我们已经拥有的数据连接起来。通过单击现有查询右侧的铅笔图标开始此过程,以便对其进行编辑。

3.打开查询后,滚动到底部,点击蓝色的“加入”按钮。

4.您会注意到出现了一个新的查询构建器。选择刚刚创建的新股票市场数据源作为这部分查询的数据源。

5.向下滚动到查询构建器中的设置,并设置您的端点。我们将使用/query,它让 API 知道我们将查询它的数据。复制并粘贴,并将其设置为您的终点:

/query

将您的 REST API 中的数据与另一个 REST API 中的数据连接起来(来源——knowi.com)

6.在这种情况下,Alpha Vantage 需要我们希望查询运行的函数、我们希望查询运行的符号、API 键和我们希望查询返回的数据类型。这意味着我们需要在进行 API 调用之前设置我们的 URL 参数。我们希望我们的查询以 CSV 格式从 NASDAQ (NDAQ)返回每日时间序列数据。为了做到这一点,将下面的语法复制并粘贴到你的 URL 参数中:

function=Time_Series_Daily
&symbol=NDAQ
&apikey=YYTO4FCR5F6DCNE1
&datatype=csv

7.单击查询构建器左侧的眼睛图标,仅预览查询的这一部分。如您所见,我们将数据列为“时间戳”,旁边是纳斯达克的开盘价、最高价、最低价和收盘价,以及当天的交易量。

8.向上滚动到您选择第二个数据源的位置,并在您的数据源右侧找到“Join Builder”。单击加入生成器,开始加入过程;Knowi 从每个数据集中检索字段可能需要一些时间。

9.同时,将您的联接类型设置为“内部联接”一旦 Knowi 检索到这些字段,就将“日期”设置为“时间戳”

10.对于本练习,我们只需要三列:日期、当天新冠肺炎案例的数量以及当天纳斯达克的收盘价。为了精简我们的查询,我们将使用 Knowi 的 Cloud9QL Post Query 特性,该特性允许用户在提取和连接所有内容后对他们的数据进行额外的查询。在您的 Cloud9QL Post 查询中输入以下代码:

select Date, Cases, close as Close

11.再次单击“预览”按钮,以确保您获得了所需格式的数据。您应该看到三列:日期、当天的新冠肺炎案例和当天的纳斯达克收盘价。

12.滚动回屏幕右下角,点击“保存并立即运行”

将您的 REST API 中的数据与另一个 REST API 中的数据连接起来(来源——knowi.com)

您刚刚完成了一个查询,该查询调用了两个不同的 API,从每个 API 中提取不同的数据,并将其全部返回到一个表中。干得好!

调度自动 API 调用

在我们开始可视化我们的数据之前,重要的是考虑我们想要可视化什么。我们的最终目标是一个仪表板,使我们能够比较纳斯达克股票交易所和新冠肺炎案例之间的趋势,并监控新趋势的出现。我们可以立即设置一个控制面板,使我们能够直观地看到截至今天已经发生的事情,但是这个控制面板会受到限制,因为最新的数据总是来自我们上次手动进行查询的时间。

因为我们希望实时监控事情,所以我们希望设置我们的查询,以便它自动获取新数据,并允许我们在每次打开仪表板时监控最新数据。Knowi 只需三个步骤就可以轻松实现这一过程的自动化。

1.单击查询右侧的铅笔图标,返回到刚刚创建的查询。向下滚动到底部,找到“日程安排”

2.根据您希望进行此 API 调用的频率来配置调度过程。由于收盘价格每天只更新一次,请将您的查询设置为从明天开始每天更新。

3.不要忘记点击绿色的“保存并立即运行”按钮。

调度自动 API 调用(来源——knowi.com)

您的查询现在设置为每天自动从两个独立的 API 提取数据,并自动连接来自每个 API 的数据。最后一步是为您的数据创建一个可视化,以查看事物如何实时移动。

可视化您的数据

即使你以前不好奇随着新冠肺炎在美国的发展,纳斯达克的股票价格是如何变化的,这篇教程可能已经激起了你的好奇心。Knowi 使从我们的数据集创建可视化变得简单,这样我们就可以快速记录任何关键趋势。我们是这样做的:

1.转到左侧面板的顶部,单击“仪表板”单击橙色的“+”按钮,并命名您的仪表板。我们称之为“联合 API 调用可视化”

2.回到左侧面板,在仪表板下,选择“Widgets”在小部件中,您应该会看到您创建的新小部件。点击它并将其拖到您的仪表板上。

3.点击小工具右上角的 3 个点,然后选择“设置”

4.单击“选项”打开选项菜单,向下滚动到选项菜单左侧的“辅助 Y 轴”,然后选择“关闭”这将为纳斯达克股票价格创建一个第二 Y 轴,让你看到它的趋势。

可视化您的数据(来源——knowi.com)

5.使用 Knowi 的可视化设置使您的图表看起来更专业。使用“修改颜色”将新案例更改为#CE0000 并靠近#CECECE,将图例别名更改为更详细地描述数据的名称,并为主要 X 轴和 Y 轴添加标题。

6.在屏幕的右上角,单击橙色的“保存”按钮。

可视化您的数据(来源——knowi.com)

关闭小部件后,您会看到现在已经设置了一个仪表板,可以直观地监控和比较美国和纳斯达克证券交易所新冠肺炎案例的动向。

可视化您的数据(来源——knowi.com)

因为您已经将查询安排为自动化日常 API 调用,所以您将能够使用仪表板来监控这两个变量久而久之。

使用基于搜索的分析来查询您的数据

现在你已经设置好了你的仪表板,你已经准备好使用 Knowi 的自然语言处理能力,通过基于搜索的分析来查询你的数据。您还可以与他人共享您的仪表板,让他们使用基于搜索的分析来查询您的数据——即使他们不熟悉 Knowi。以下是如何对您的数据运行基于搜索的分析:

1.前往部件的右上角,点击 3 个点,然后向下滚动一点,点击“分析”按钮。这将以表格形式显示您的数据。

2.在这里,使用数据上方的搜索栏来询问您的数据问题,并快速获得答案。假设我们希望看到每个数字的周平均值,以便从每日数字中消除一些干扰。我们需要做的就是在我们的搜索栏中键入“显示平均案例,每周平均成交”来查看每周平均数据,以便快速将我们的数据转换为我们想要的格式。

3.现在是时候用这种新格式来可视化我们的数据了。切换到“可视化”,把你的可视化改成折线图。确保将“平均收盘”设置为辅助 y 轴,这样您也可以清楚地看到该变量的变化。

4.前往右上方,点击“克隆”图标。这将创建一个新的小部件,其中包含我们对原始小部件所做的编辑。

5.完成克隆后,单击橙色的“添加到仪表板”按钮。

使用基于搜索的分析来查询你的数据(来源——knowi.com)

如你所见,这个过程只需要好奇心和英语基础知识。用简单的英语提出数据问题并返回答案的能力有助于弥合数据科学家和管理层之间的差距,并使讲英语并希望了解更多数据的任何人都可以访问 Knowi 的仪表板。

摘要

总的来说,我们只是在 Knowi 中设置了两个独立的 REST API 作为数据源,编写了一个查询来调用每个 REST API 并以可理解的格式返回数据,然后安排该查询每天进行 API 调用并返回新数据。然后,我们从运行查询时创建的数据集创建了一个新的小部件,以及一个新的仪表板,并将新的小部件存储在仪表板中。我们还使用基于搜索的分析来创建一个单独的、更平滑的可视化,向我们显示这两个变量的每周平均值。现在,我们所要做的就是登录我们的 Knowi 帐户,以便监控纳斯达克的股票价格以及美国的新新冠肺炎病例。

用 Python Pandas 连接按子串匹配的数据帧

原文:https://towardsdatascience.com/joining-dataframes-by-substring-match-with-python-pandas-8fcde5b03933?source=collection_archive---------18-----------------------

如何使用笛卡尔积连接两个数据帧,其中一个具有全文值,另一个具有子串。

来源 https://getrefe.tumblr.com/的 REFE

源代码

下一个为 Jupyter 笔记本制作的 Python 熊猫代码在 GitHub 中可用,它回答了这个问题:“哪些任务不匹配?”

数据

代码的第一部分创建两个数据帧: df1df2。

df1 数据帧在 task_name 列中有任务的完整名称。

并且 df2 DataFrame 在 partial_task_name 列中有一个子串。

看, partial_task_name 中的值 BC 是 A BCBC D 的子串,这种情况下预期的结果一定会产生很多行,但是怎么才能得到很多行呢?答案是使用笛卡尔积或交叉连接。

连接

要在 Pandas 中做笛卡尔乘积,请执行以下步骤:

  1. 在每个数据帧中添加一个具有相同值的虚拟列
  2. 通过新列进行联接
  3. 删除每个数据帧中的新列
df1['**join**'] = 1
df2['**join**'] = 1

dfFull = df1.merge(df2, on='**join**').drop('**join**', axis=1)
df2.drop('**join**', axis=1, inplace=True)

这场比赛

如果 partial_task_name 列在 task_name 列中,下一步是在返回的结果数据帧中添加一个新列。我们将使用一个 lambda 和“find”函数,其中结果≥ 0

dfFull['match'] = dfFull.apply(lambda x: x.task_name.find(x.partial_task_name), axis=1).ge(0)

该产品为 dfFull 数据帧

我们按任务名管道名做一个分组,得到匹配的最大值进行过滤。

好答案

为了知道哪些任务不存在于 df2 数据帧中,我们通过匹配列进行了一个负过滤:

不好的答案

如果我们不使用笛卡尔积,而是尝试在 df2 数据帧中添加第一个匹配,然后用 df1 数据帧进行左连接

我们正在犯一个常见的错误,那就是它给了我们错误的答案。

因为我们在用第一个搭配的时候, ABC 搭配的是 BC 而不是 BCD。

有一种更通用的技术叫做近似字符串匹配或者通俗地说叫做模糊查找,它也试图解决相似或部分不连续的子字符串。如果是你的情况,你可以试试 fuzzywuzzy。

感谢 Charles Romestant 给了我写这篇文章的灵感

快乐码!

使用 Python 的熊猫连接数据集

原文:https://towardsdatascience.com/joining-datasets-with-pythons-pandas-ed832f01450c?source=collection_archive---------36-----------------------

如何使用 Pandas 连接、追加和合并数据集

图片来自 PixBay — Nick115

在执行分析时,使用多个数据集的情况并不少见。因此,有大量的方法将这些数据整合在一起。

SQL 将这些操作称为“联接”或“联合”;在其他语言和工具中,您可能会找到类似 Merge 或 LookUp 的功能来完成这项工作。

在本文中,我将介绍一些我们可以用来将数据集与熊猫连接起来的函数。

我将在一个 Jupyter 笔记本中运行我的代码,我们在示例中唯一需要的是熊猫

import pandas as pd

我们将从为示例定义一些虚拟数据开始,为了简化,我将使用列表,但是绝对鼓励您加载数据集

# create 5 lists with the same size
names = ['bob', 'bella', 'blue', 'suzy', 'gunter', 'joe', 'holly', 'coco', 'elliot']species = ['dog', 'cat', 'velociraptor', 'dog', 'penguin', 'squid', 'cat', 'cat', 'horse']age = [1, 6, 70, 8, 3, 1, 2, 13, 3]
weight = [10, 5, 15, 7, 4, 1, 3, 2, 380]color = ['brown', 'black', 'blue', 'black', 'black', 'gray', 'white', 'orange', 'white']

定义列表后,我们可以创建数据框。

# create 3 data frames with the values from the listsdf1 = pd.DataFrame( {'name': names[:3],
                     'species': species[:3],
                     'age': age[:3]})df2 = pd.DataFrame( {'name': names[3:6],
                     'species': species[3:6],
                     'age': age[3:6]})df3 = pd.DataFrame( {'name': names[6:],
                     'species': species[6:],
                     'age': age[6:]})print(df1, '\n')
print(df2, '\n')
print(df3)

三个数据帧

好,我们有三个列和大小相同的数据集。假设我们希望将这些数据分组到一个数据框中。

。串联

为此,我们可以使用。concat,这是一个接受数据帧列表并将它们连接成一个数据帧的函数。

# .concat to join the dataframes, like a 'union all'
df_list = [df1, df2, df3]
df = pd.concat(df_list)df

级联数据帧

很酷,Pandas 匹配了这些列,并毫不费力地返回了一个几乎完美的数据框。

但是如果列名不匹配呢?或者如果我们遗漏了一列呢?

# test with mismatching and missing columnsdf1 = pd.DataFrame( {'name': names[:3],
                     'specie': species[:3],
                     'age': age[:3]})df2 = pd.DataFrame( {'name': names[3:6],
                     'species': species[3:6],
                     'age': age[3:6]})df3 = pd.DataFrame( {'name': names[6:],
                     'age - years': age[6:]})print(df1, '\n')
print(df2, '\n')
print(df3)

数据帧不匹配

对于“物种”一栏,我在第一个 df 中更改了它的名称,并从最后一个中删除了它;我还把“年龄”重新命名为“年龄——年”。

# concat with mismatching and missing columns
df_list = [df1, df2, df3]
df = pd.concat(df_list)df

串联不匹配的数据帧

好吧,熊猫。concat 要求列名完全匹配。如果一个列对于数据集来说是唯一的,就像完全连接一样,它会用空值填充空隙。

我用 Sketch.io 制作——知识共享

还有一件事我们需要注意,索引。

由于我们在创建数据框时没有定义唯一索引,Pandas 为我们设置了一些从零开始的默认值,但当我们使用. concat 时,它不会重置它们。

图片来自 PixBay — Skeeze

唯一的索引总是一个好主意。在这种情况下,我们可以使用。reset_index 创建一个具有适当值的新列,或者使用。set_index 将其中一列定义为索引。

但是让我们尝试一个更简单的适合我们情况的解决方案。

df1 = pd.DataFrame( {'name': names[:3],
                     'species': species[:3],
                     'age': age[:3]})df2 = pd.DataFrame( {'name': names[3:6],
                     'species': species[3:6],
                     'age': age[3:6]})df3 = pd.DataFrame( {'name': names[6:],
                     'species': species[6:],
                     'age': age[6:]})# since we didn't define the indexes when creating the dataframes we can ignore them when concatenatingdf_list = [df1, df2, df3]
df = pd.concat(df_list, ignore_index=True)df

级联数据帧重新索引

对于单个参数,我们忽略了索引,并在连接的结果中获得了新的索引。

另一个方便的参数是“keys ”,它允许我们用一个新的索引级别来标识数据源。

df1 = pd.DataFrame( {'name': names[:3],
                     'species': species[:3],
                     'age': age[:3]},
                     index = [1,2,3])df2 = pd.DataFrame( {'name': names[3:6],
                     'species': species[3:6],
                     'age': age[3:6]},
                     index = [10,11,12])df3 = pd.DataFrame( {'name': names[6:],
                     'species': species[6:],
                     'age': age[6:]},
                     index = [100,200,300])# we can pass 'keys' which creates another index level to identify the concatenated data frames
df_list = [df1, df2, df3, df1]
df = pd.concat(df_list, keys=['df1', 'df2', 'df3', 'df4'])df

添加了索引级别的级联数据帧

默认情况下,。concat 使用列作为键,并将值追加为行。但是如果我们想要将列连接到数据框呢?

图片来自 PixBay — 免费照片

首先,让我们定义一些要连接的新列。

df4 = pd.DataFrame( {'weight': weight,
                     'color': color
                     })
df4

带有额外列的数据框

类似地,我们可以将列表直接添加到数据框中,方法是将它们分配给一个列,如下所示:

df['color'] = color

但是一个数据框可能有很多字段,逐个传递它们并不是最好的选择。

concatenate 函数接受“轴”的参数,这允许我们这样做—连接列。

df = pd.concat([df, df4], axis=1)
df

级联数据帧

我们还可以改变连接的行为。

让我们尝试将“name”列作为我们的索引,并使用额外的一列创建另一个数据集进行实验。

df_list = [df1, df2]
df = pd.concat(df_list)
df.set_index('name', inplace=True)df5 = pd.DataFrame( {'species': species,
                     'age': age,
                     'score': [9,10,10,8,6,9,3,4,10]},
                     index = names)print(df, '\n')
print(df5)

更多数据帧

请注意,我们的第一个数据框比第二个数据框的值少。当我们执行内部连接时,它应该只带来索引匹配的行。

# by default concat behaves like an outer join, or a union all
# we can change that with the 'join' parameter
df_list = [df, df5]
df = pd.concat(df_list, axis=1, join='inner')
df

使用内部连接连接的数据帧

我用 Sketch.io 制作——知识共享

。附加

现在让我们看看另一个名为. append 的函数。

此函数的行为与. concat 类似。前面的函数获取多个数据帧,并将它们连接成一个新的数据帧。追加方法将使用现有数据框添加数据。

两者都将返回数据框,但是调用它们的方式不同。您将使用 Pandas.concat()和 DataFrame.append()。

让我们检查一些例子。

df1.append(df2)

附加到数据帧 1 的数据帧 2

df = df1.append(df2)
df = df.append(df3)
print(df, '\n')df = df1.append([df2, df3])
print(df)

一个接一个附加的数据帧和附加有列表的数据帧

# append a row
df.append(pd.Series(['oliver', 'monkey', 13], index=['name', 'species', 'age']), ignore_index=True) 

带有附加行的数据框

。合并

太棒了。串联和。追加,我们可以执行我们可能需要的大多数连接。现在让我们检查一个更健壮的名为. merge 的解决方案。

图片来自 Dreamstime

从简单的事情开始,让我们看看如何。merge 执行联接。

我将定义另一个数据框,类似于我们已经在使用的数据框,但是多了一列,少了一条记录。

print(df, '\n')df6 = pd.DataFrame( {'name': names[1:],
                     'age': age[1:],
                     'score': [10,10,8,6,9,3,4,10]})
print(df6)

更多用于实验的数据帧

Merge 允许我们选择哪个列将成为键;在这种情况下,让我们使用“名称”。

merged_df = pd.merge(df, df6, on='name')
merged_df

由“名称”列合并的数据框。

与我们之前看到的不同,默认情况下,合并是一个内部连接——这意味着除非另有说明,否则它将只返回两个数据集中匹配的行。

我们还可以注意到,两个数据集中的列是分开的,即使它们包含相同的值。

最后,当我们执行如上所示的内部连接时,两个数据框必须具有相同名称的键列。

图片来自 PixBay — cocoparisienne

可以选择多个列作为键,就像组合键一样,还可以选择使用哪种连接。

merged_df = pd.merge(df, df6, how='left', on=['name', 'age'])
merged_df

姓名和年龄字段左侧的数据框已合并。

我用 Sketch.io 制作——知识共享

merged_df = pd.merge(df6, df, how='right', on=['name', 'age'])
merged_df

姓名和年龄字段右侧的数据框已合并。

我用 Sketch.io 制作——知识共享

太好了!除此之外,合并功能还有助于我们验证和理解正在合并的数据。

# 'one_to_one' or ‘1:1’
merged_df = pd.merge(df6, df.append(df1), how='right', on=['name', 'age'], validate='one_to_one')merged_df

出错信息

例如,如果数据框不符合您选择的标准,验证参数将引发错误。

其他有用的选项有:

‘一对多’‘1:m’—检查左键是否唯一;

'多对一'或' m:1' —检查右键是否唯一;

“指示器”参数向数据框中添加一列,解释键的关系。

merged_df = pd.merge(df6, df.append(df1), how='outer', on=['name', 'age'], indicator=True)merged_df

带有指示器列的合并数据框

*如果您将一个字符串传递给指示器参数,它将被用作创建的列的名称。

我们不需要指定哪一列包含键,因为默认情况下,Pandas 会假设索引是键。

让我们尝试将名称设置为我们的索引,并再次合并这些数据框。

df.set_index('name', inplace=True)
df6.set_index('name', inplace=True)print(df)
print(df6)

按名称索引的数据框

pd.merge(df6, df)

按索引合并的数据框

如果我们不希望熊猫重置索引,我们必须使用 right_index 和 left_index 参数。

pd.merge(df6, df, how='outer', left_index=True, right_index=True)

按索引合并的数据框。

如果我们想一边合并一个索引,另一边合并一个键,我们可以指定 right_on 和 left_on 参数。

它们接受包含键的列名,就像我们之前看到的一样,但是将只应用于特定的一侧,使用另一侧的索引列。

pd.merge(df, df6, how='right', right_on='name', left_index=True)

由索引和键列合并的数据框。

太好了!我们看到了。串联和。append,连接两个数据框的两个方便的函数。然后我们探索了。合并,一个更好的选择,具有很大的灵活性。

图片来自 PixBay — PredragKezic

熊猫有更多的方法来帮助你处理多个数据集;花时间构建解决问题的逻辑,然后在库中找到已经实现的解决方案,这种情况并不少见。

因此,我鼓励大家看看其他一些功能,例如。比较,。combine_first,and。merge_asof。

感谢阅读我的文章。我希望你喜欢它!

参考文献: 用于数据分析的 Python 韦斯·麦金尼
熊猫—Concat
熊猫——合并
熊猫—追加
熊猫——合并、联结、连接、比较

连接、视图和 cte:MySQL 工作台

原文:https://towardsdatascience.com/joins-views-and-ctes-mysql-workbench-c1f64d88447f?source=collection_archive---------20-----------------------

通过 MySQL Workbench 连接多个表并创建视图和 cte 来分析数据

克里斯托弗·高尔Unsplash 上拍摄的照片

MySQL 有七个查询命令( SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY 和 LIMIT ),通过这些命令在数据库中进行数据分析。但是所有这些查询都有助于分析整个数据库中单个表中的数据。在现实世界中,一个数据库包含不止一个表,并且所有这些表都是相互关联的。

为了一次分析多个表上的数据,我们将使用连接、视图和 cte。

我们可以在这里下载文章中使用的数据库。

主键和外键

为了理解连接是如何工作的,我们需要熟悉主键和外键的概念。

主键是唯一定义表的单个字段/列名。该列不应包含任何空值,不应有重复值,并且一个表只能有一个主键。

一个表中的外键引用了另一个表中的列。

让我们看一个简单的例子来更好地理解数据库中的主键和外键。

我们将从数据库中取出两个表。

  • market_fact_full

市场 _ 事实 _ 完整表格

  • prod_dimen

产品维度表

现在,在market_fact_full表中,主键是Market_fact_id,外键是Prod_id,因为Prod_id列用于引用prod_dimen表,而Prod_id列在产品维度表中充当主键。

连接

使用连接从数据库的不同表中检索数据。这些表必须通过使用主键和外键相互关联。

有两种类型的连接:

  • 内部连接
  • 外部连接

内部连接

内部联接选择两个表中的公共列。

如果我们考虑上面的两个表,market_fact_full表包含产品的利润和相关信息,而prod_dimen表包含产品的类别。

如果我们想找出利润最大的产品类别,我们将使用 Inner Join。

让我们分析一下代码,

  1. 选择,我们试图打印Product_Category & Product_Sub_category列,它们属于prod_dimen表,利润列来自market_fact_full表。
  2. 现在使用 from,首先,我们选择prod_dimen表,我们使用inner join关键字连接market_fact_full表。我们还将把这些表分别称为 p & m
  3. 现在,我们必须指定表必须连接哪一列。我们将通过在关键字上使用并提到列名来实现。
  4. 最后,我们将根据我们的需求为代码提供必要的命令。

现在,对于上面的代码,输出将如下所示。

利润最高的产品类别

使用内部连接,我们可以连接两个以上的表。让我们看看下面的代码,它将三个表连接在一起以获得所需的输出。

我们想了解每种产品的产品类别及其运输方式。为此,我们必须使用三个表market_fact_fullprod_dimenshipping_dimen

现在,输出看起来像这样。

内部连接—三个表

外部连接

有两种类型的外部联接。

  • 左(外)连接
  • 右(外)连接

左连接 使用左连接,返回左表中的所有值和右表中的匹配值,如果右表中有任何缺失值,则返回 null。

让我们看一个例子,我们需要打印manuprod_dimen表中的manu_nameprod_id列,以查看产品的制造名称。

首先,让我们看看表格是什么样子的,

  • manu

制造表

  • prod_dimen

产品维度表

上面的问题我们用左连接。

输出将是,

制造商名称

通过以上输出,我们可以得出结论,只有 Wipro manufacture 生产产品,其余两家制造商没有生产任何产品。

右连接 与左连接类似,右连接返回右表中的所有值和左表中的匹配值。

让我们用左连接的例子。

上面代码的输出是,

产品 id w . r . t .制造商名称

如果我们敏锐地观察上面两个程序,就能发现左连接和右连接的区别。左连接给出所有的制造商名称,而右连接给出所有的产品 id。

类似地,我们可以使用 inner join 和 outer join 关键字连接两个以上的表。

视图

视图是不包含任何真实值的虚拟表。假设有一个复杂的查询,我们需要在数据分析中重复使用。我们将创建一个视图,并在需要时随时随地引用该表,而不是频繁地键入该查询。

让我们举个例子,

现在,我们要打印利润超过 1000 英镑的所有订单。为了获得输出,我们将参考上面创建的视图表。

输出是,

这就是我们如何创建视图表并根据我们的需求使用该表。

CTE

公共表表达式(cte)的功能与视图类似,只有一点不同。可以在数据库中访问视图,因为 cte 只在特定查询中出现。一旦查询被执行,我们就不能再使用 CTE 了。

我们来找出前五名,在那五个产品中,亏损最少,产品基础利润率最高的。

首先,我们将找到排名前 5 的产品

排名前五的产品是,

现在,我们必须从上面的输出中找到最高的产品基本利润。为了获得期望的结果,我们将创建 CTE 并确定最高的产品基本利润。

我们通过使用带有关键字的创建了最小损失 CTE,它创建了一个包含前 5 个最小损失产品的表,并使用该最小损失表,我们获得了产品基数的最高利润。输出将如下所示,

一旦我们执行了查询,我们就不能在其他地方使用最小损失 CTE。

结论

这就是如何使用联接、cte 和视图来分析数据库中的数据。在现实世界中,大多数时候,我们会更多地使用内连接而不是外连接,更多地使用视图而不是 cte。

一旦我们知道如何使用 SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY 和 LIMIT 命令,我们必须掌握 Joins、CTEs 和 Views 命令。因为我们经常需要同时分析一个数据库中两个以上表上的数据。

感谢您阅读快乐编码!!!

在这里查看我以前关于 Python 的文章

参考

用幂 BI 和 R 连接

原文:https://towardsdatascience.com/joins-with-power-bi-bde7de3e2181?source=collection_archive---------34-----------------------

连接将一直存在…让我们使它们变得简单

梅尔·普尔在 Unsplash 上的照片

我已经在我的第一篇文章中描述了连接的基础。希望对您有所帮助。在本文中,我将向您展示如何使用 Power BI 的 Power Query 以及在 R 中使用 dplyr 来完成这些连接。

Power BI 有一个“点击”类型的 UI(大量使用鼠标),而 R 有一个“输入”界面(大量使用键盘)。

我两样都喜欢,希望你也喜欢。

让我们回到我们的小简笔画——有用吗?

作者图片

让我们开始吧!

让我们加载我们的数据:)两个很小的数据集,但对我们的例子来说很棒。

作者图片

现在它们已经加载,让我们进入电源查询

作者图片

一旦我进入超级查询端,我就会看到我的两个数据集。

作者图片

让我们开始合并查询吧!

作者图片

对于连接的放置要非常小心,顶部数据集位于连接的左侧,底部数据集位于连接的右侧。如果它们排列不当,你会得到相反的结果。

如果你感到困惑——看看我的第一篇关于左右的文章

作者图片

一件重要的事情——让我们选择想要加入的列或“连接”。

作者图片

我选择了左外部连接,但它与左连接相同。有许多术语——左手边、第一数据集、数据集 A 等。在一天结束时,我们希望看到共同的行,以及在比较时没有发现的行。此外,在这个图像中,只有一个“连接”列。你不仅限于使用它。您也可以选择一个额外的列来支持连接。

在我做出这个选择后,我将得到扩展的选项。

让我们点击扩展按钮。

作者图片

哒哒!

作者图片

这里你可以看到内部连接和左反结果。

让我们简单谈谈 Power Query 上的查询设置窗格。这对我们的例子非常有用。为什么?因为只需一次单击,您就可以返回到合并步骤,并更改您的任何连接选择,如前所述。

作者图片

带您回到这里进行其他连接选择。

作者图片

我明白,这可能看起来过于简单,这里的数据集只有 5 行,没有任何重复,数据类型错误,连接上的打字错误,缺少数据,缺少列..等等,我将在另一篇文章中写更多关于这方面的内容。

请这样想,如果您理解这些基础知识,并且能够在小型数据集上构建查询,Power BI 将会完成繁重的工作。稍作调整后,同样的查询可以从 5 行数据集应用到 50K 行数据集。

嗯……让我们回到简笔画上。

现在让我们看看 r,另一个伟大的工具。

让我们使用“Import data”加载我们的数据和包,并加载 Tidyverse。Tidyverse 是一个 R 包的集合,它使数据争论变得有趣和容易(有时)。

我将使用下面的代码回答我在第一篇文章中提出的同样的问题。只有两条主线,但稍加调整就足够了。

library(tidyverse) # loading Tidyverse package -- for dplyr#who is still with the company?Dataset_2007 %>% 
  inner_join(Dataset_2020, c("Name"))#who is no longer working for the company in 2020?Dataset_2007 %>% 
  anti_join(Dataset_2020, c("Name")) #who is new to the company in 2020?Dataset_2020 %>%  anti_join(Dataset_2019,c("Name"))

我们来分析一下。

你有它!

有些人使用 Power BI 和 r 来加入基础知识。用 Power BI 点击几下,用 r 编写几行代码。这两者都是数据争论的乐趣。

下一篇文章是关于使用 Power BI 中的函数,看看吧!

注意安全,希望你喜欢这篇文章。

使用评论进行推荐的用户和项目的联合深度建模

原文:https://towardsdatascience.com/joint-deep-modeling-of-users-and-items-using-reviews-for-recommendation-50e75d5e10aa?source=collection_archive---------56-----------------------

照片由 vanitjanFreepik 上拍摄

如今,推荐系统经常出现在我们的日常生活中,比如网上购物、阅读文章和看电影。人们可以根据自己的兴趣从推荐系统中看到推荐的商品。许多推荐系统使用协同过滤方法,该方法的技术表明,过去有相似偏好的人将来倾向于有相似的选择。挑战在于很少有用户对物品发表评论。该文章关注深度合作神经网络(DeepCoNN),针对评分预测问题从用户和项目获取评论。

在本文中,你将学习推荐系统的奇异值分解和截断奇异值分解:

(1)模型架构

(2)单词表征

(3) CNN 层

(4)共享层

(5)网络培训

(6)对 DeepCoNN 的分析

(7)基线模型

模型概述

在深度合作神经网络(DeepCoNN)中,有一个用于学习项目属性和用户行为的评论数据集,以及在最后几层组合的两个并行神经网络。一个网络关注用户的评论以从用户的行为中提取特征,另一个网络主要利用物品的评论以突出物品的属性。

模型架构

有两个并行的神经网络,一个用于用户的网络(Netu)和一个用于项目的网络(Neti),这两个网络合并在最后一层。对于两个网络,输入数据是 Netu 中的用户评论,Neti 中的商品评论,然后是作为输出的评级。

对于也称为查找层的第一层,从用户评论中生成单词嵌入,用于语义提取。接下来,使用卷积层、最大池层和全连接层构建模型,以生成用户和项目的要素。最后,最终的顶层实现了用户和物品之间隐藏的潜在因素的交互。

DeepCoNN 计算 426 目标函数以缩小来自 Netu 和 Neti 输出的潜在因子的评级预测误差。我们将详细介绍 Netu 的过程,同样的过程也适用于 Neti,因为 Netu 和 Neti 具有相同的输入。

情节:模型架构

单词表示法

一个单词嵌入 f: M→ N_n .一个把单词字典变换成 N 维分布向量的映射函数。男:单词字典。N_n: n 维分布向量。

利用词的表示来提取评论的语义。评论被转换成单词嵌入矩阵,用于查找层的语义提取。所有用户的书面评论 u 合并成一个文档 du_(1-n)共 n 个单词。下面内置一个字向量矩阵 Vu_(1:n):

等式:单词向量

du_k:文档 d 的第 k 个单词
d
u_(1:n):查找函数
φ(d*u_k):返回单词
⊕:连接运算符对应的 c 维单词向量

与词袋技术相比,在矩阵 V * u(1:n)中保持了词的顺序

CNN 图层

CNN 模型包括卷积层、最大池和全连接层。卷积层中有 m 个神经元,通过对用户 u 的单词向量 Vu_(1:n)应用卷积算子来产生新的特征。在卷积层中,每个神经元 j 在大小为 t 的单词窗口上应用滤波器 Kj ∈ n(ct)。

等式:带内核的卷积层

*:卷积算子
b_j:偏置项
f: relu 激活函数

下面指定了 Relu 激活。具有 ReLU 的深度卷积神经网络的训练周期比 tanh 激活函数快得多。

f(x) = max{0,x}

下面的等式是特征图上的最大池,并从特定内核中提取最大值作为特征。特征图中的最高值是最重要的特征。汇集层可以应用于不同的文本长度。在最大汇集操作之后,卷积结果被转换成固定大小的向量。

o_j = max{z_1,z_2,…,z _(n t+1)}

模型中的多个过滤器生成了各种特征。下面的等式是卷积层的输出向量

O = {o_1,o_2,o_3,…,o_n1 },

o_n1:卷积层中内核的数量

X_u = f(W × O + g)

max-pooling 层输出到下一个具有权重矩阵 w 的全连接层上式是全连接层的输出 xu ∈ n(n_21)。最后,我们可以从用户和项目 x_u 和 y_i 的 CNN 层获得输出。

共享层

作为特征的项目和用户的输出在不同的特征空间中,并且不可比较。共享层被引入到 Netu 和 Neti 之上,以在特征空间中映射它们。单个向量ˇz =(xu,yi)由 Xu 和 yi 连接而成。为了模拟 z 中所有嵌套变量的相互作用,因子分解机(FM)被引入作为相应等级的估计器。下面的等式是给定一批 N 个训练示例 t 的成本。

等式:批量的成本函数

ˇw0:全局偏差
ˇwi:模拟 z 中第 I 个变量的强度

模拟二阶相互作用

网络培训

目标是最小化上面指定的成本函数,并且相对于 z 检索导数 J。

等式:成本函数的导数

通过应用链式法则,可以计算不同层中其他参数的导数。利用 N 元组的训练集 T,通过 RMSprop 对混洗小批量进行优化。RMSprop 是为梯度更新方法引入的,它根据梯度的绝对值自适应地管理步长。当 RMSprop 计算梯度范数的平均值时,权重将被更新。下图显示了网络参数集θ的更新规则。

等式:RMSprop 优化函数

λ:学习率
ε:数值稳定性的小附加值

此外,在两个网络的完全连接层之上应用了脱落层,以防止过度拟合。

DeepCoNN 分析

词序保持

常见的是,推荐系统在用户评论上应用主题建模来建模用户或项目。潜在的主题变量使用单词袋技术,忽略了单词的顺序。然而,对于文本建模应用程序来说,考虑单词的顺序是至关重要的。DeepCoNN 与单词嵌入一起应用,以创建单词嵌入,同时保持单词的顺序,但不使用主题建模方法。因此,卷积层提供了一种在文本建模中表征单词顺序的技术。

在线学习

许多推荐系统注意到可伸缩性和处理项目的动态池。对于推荐系统来说,时间敏感性是在线学习潜在因素的一个具有挑战性的任务。DeepCoNN 可根据训练数据的数据可伸缩性进行调整,并且该模型可以灵活地用神经网络中的新数据进行训练和更新。从历史数据中更新项目或用户的潜在因素是独立的。主题建模不包括考虑时间因素和数据更新。

基线模型

矩阵分解(MF)和概率矩阵分解(PMF)被应用于推荐系统中的评论数据集。此外,大多数推荐系统使用主题建模来支持用户评论。为了比较推荐系统和主题建模,选择了 4 种深度学习模型:潜在狄利克雷分配模型(LDA)、协同主题回归模型(CTR)、主题隐藏因子模型(HFT)和深度推荐系统。推荐系统将引入最新的深度推荐系统——协同深度学习(CDL)。为了改进模型预测,除了 MF 和 PMF 以外,所有基线都在模型中加入了审查信息。在所有的协同过滤方法中,MF 是最流行的一种。输入数据集是评级矩阵,MF 将估计两个低秩矩阵来预测评级。交替最小二乘(ALS)技术用于最小化目标函数。

PMF:该模型应用了用户和项目潜在因素的高斯分布。

LDA:潜在狄利克雷分配是一种流行的主题建模算法。它用于从每个项目的一组评论中学习主题分布。为每个项目的潜在特征提取学习的主题分布。为了优化评分预测精度,通过梯度下降更新每个用户的潜在特征。

CTR:协作主题回归也被应用,并在用户感兴趣或不感兴趣的单类协作过滤问题上表现良好。

HFT:隐藏因素作为主题被应用于主题分布,以从用户或项目评论中提取潜在因素。在实验中,基于项目的主题分发比用户主题分发具有更好的性能。

CDL:协作深度学习的特点是堆叠去噪自动编码器和 PMF 的贝叶斯公式。自动编码器和 PMF 与自动编码器的中间层相连。

python 代码的实践经验

数据描述:

数据是从 Amazon review 数据集中提取的,带有杂志订阅的子类别。链接到数据源。数据集中有各种列,如评论(评级、文本、有用性投票)、产品元数据(描述、类别信息、价格、品牌和图像特征)和链接(也查看过/也购买过的图表)。

DeepCoNN 建模

对于建模方法,DeepConn 模型是卷积神经网络模型,它在 Pytorch 模型中实现。此外,模型的优化是 adam 优化器,损失度量是通过 MSE 评估的。

数据预处理

从 Magazine_Subscriptions.json,我们在评论数据集上实现了一些预处理步骤,如过滤标点符号,保留单词和字符,排除 nan 和 null 值,以及过滤长度大于 1 的单词。在数据集中,有用户多次对相同的产品留下评论。输入数据集也被从相同的 userid 和 itemid 的重复行中排除,因此模型将具有相同的所有条目和用户的评论数据的输入长度。

添加用户和项目功能

在 user_reviews 表中,索引被设置为 userID 和 productID 以及用户评论的列。另一个表是 movie_reviews 表,索引设置为 userID 和 productID 以及电影评论列。数据集还添加了两个附加功能,一个是用户评论列,另一个是电影评论列。

单词嵌入

单词嵌入是手套嵌入的输入,每个单词的向量大小为 200。手套嵌入是一种无监督的学习方法,通过单词的共现来分组单词,以生成单词向量。相似性度量是通过两个单词向量之间的欧几里德距离(或余弦相似性)来计算的。相似的单词放在附近,而没有相似语义的单词放在更远的地方。对于用户和项目的评论数据集,用手套嵌入和 pad 值向量输入单词。用户和项目的评论用相同大小的向量填充。

DeepConn 型号:

对于模型输入,输入的数据结构的嵌入大小为 200,用户序列长度为 61,项目序列长度为 45。有两个独立的数据输入,一个是具有(1910,6,200)的 3d 形状的项目评论输入矩阵,另一个是具有(1910,20,200)的 3d 形状的用户评论输入矩阵。标签是评级栏。该模型根据 80%的输入数据进行训练,并根据 20%的验证数据进行测试。

DeepConn 模型有 1 个卷积层,内核大小为 3,滤波器大小为 2。下一层是 max-pooling 层的输入,以从每个内核中提取最大值作为特征。然后,将特征展平并转发到密集层进行模型预测。最后一层结合了来自项目评审和用户评审矩阵的输入。将组合的特征带入模型,模型将特征和输入连接到最后的密集层。优化函数是 Adam,损失函数是模型评估指标的均方误差。

评估图:

该模型在 100 个时期上用 80%的训练数据分割进行训练,并在 20%的测试数据集上进行测试。训练损失在 0.1514 左右持续下降,测试损失达到 2.6 左右。测试损耗在 60 个周期后变得稳定。

图:训练和测试数据集的损失性能

最后

  • 评论数据集的特点是通过一个映射函数将单词字典转换成 n 维分布向量,从而实现单词的嵌入。单词嵌入是手套嵌入的输入,手套嵌入是一种无监督的学习方法,通过单词的共现来分组单词以生成单词向量。
  • CNN 模型包括卷积层、最大池和全连接层。卷积层中有 m 个神经元,它们通过对单词向量应用卷积算子来产生新的特征。max-pooling 图层从要素地图中提取最高值作为最重要的要素。汇集层可以应用于不同的文本长度。在最大汇集操作之后,卷积结果被转换成固定大小的向量。
  • 作为特征的项目和用户的输出在不同的特征空间中,并且不可比较。共享层被引入到 Netu 和 Neti 之上,以在特征空间中映射它们。单个向量ˇz =(xu,yi)由 Xu 和 yi 连接而成。为了对 z 中的所有嵌套变量交互进行建模,因子分解机(FM)被引入作为相应评级的估计器,它将两个评论的特征连接起来,并在其上对下一个密集层应用点函数。

模型优势

  • 深度合作神经网络(DeepCoNN)是一种使用文本评论对用户行为和项目属性进行建模的方法。存在从共享层连接的两个并行网络,使得用户和项目表示的交互可以预测评级。
  • 评论由 Glove 转化为词嵌入,以语义和评论情感为特征。DeepCoNN 可以通过利用评论来缓解稀疏性问题。

这是推荐系统主题的结尾

参考

约斯特黄金法则

原文:https://towardsdatascience.com/joosts-golden-rules-2c0ee2ec9f8c?source=collection_archive---------27-----------------------

或者,用任何语言写出更好代码的 12 条简单规则。

你不需要了解很多关于编码的知识就能看出可读代码和不可读代码的区别。拿起你匆忙拼凑起来的任何东西,几个月后可能就无法阅读了。你投入时间和精力的代码可能几个月,甚至几年后才可读。这里有一些让你的代码更好的规则。

Ashkan Forouzani 在 Unsplash 上的照片

简史

在我大学的第一份工作中,我非常高兴为 Joost " 工作,鼠标是给用户用的“den Haan——他们在操作电脑时永远不会碰他的鼠标。他精通键盘和他选择的语言 MATLAB。

约斯特是一个有原则的人,他会三思而后行。他总是有一个计划来克服摆在他面前的挑战。他是那种工作精明但不努力的人;早在它变凉之前。早在这个概念被大肆宣传之前,他就已经在编写清晰、整洁的代码了。约斯特是一个超越时代的人。

他有一些简单的规则,任何人都可以应用于任何项目,不管是什么编程语言。一些简单的规则可以帮助你思考你在编码什么以及如何编码。当你敲击键盘上的键时,要记住一些黄金法则。

更好编码的几个简单规则

Joost 黄金法则的第一条规则是,每个程序员都可以局部忽略任何黄金法则,只要这能使工作更快、更容易或更便宜……规则是手段而不是目的。规则是用来指导你的,但永远不会让你停止思考你实际上想做什么。

每个程序员都可以局部忽略任何黄金法则。

1.为别人写代码。

正是如此,你可能会换到一个不同的工作或职位,在将来的某个时候,别人应该会更新你的代码。你不仅是在为未来的自己写代码,也是在为未来的某个人写代码。如果你在编码的时候把他们记在心里,你就帮了他们两个人一个大忙。

2.考虑代码对处理能力的影响。

代码会随着时间的推移而增长,忽略代码对处理能力的影响会在某个时候回来困扰你。趁你还在的时候考虑一下

3.从创建基础设施开始。

当开始一个新项目时,首先要为你的项目建立基础设施。从高层次上考虑代码的结构。建立数据库连接、集成,并为您的功能编写框架。这应该包括测试程序,然后才开始编程的内容。

照片由达科塔·鲁斯Unsplash 上拍摄

4。总是复制代码。

如果你写代码总是复制你创建的名字。这可以防止你打错字,创造 100%的一致性。

5。千万不要复制代码。

永远不要复制代码片段(没有检查),这很容易出错,并且会产生不必要的难以维护的重复代码。所以当你复制的时候,可能有一个更聪明的方法。参见第六条规则。

6.零一无限。

0 — 1 — ∞表示脚本的重复。(顺便说一下,无穷符号叫做双纽线。)你要么使用一个操作零次,要么使用一次。如果你不得不多次重复做同样的事情,你必须想办法把它扩展到无穷大(例如通过创建一个函数)。

潜在的想法是,如果你必须改变代码,你不必同时在两个地方做同样的操作,因为你很有可能会错过一个。

7.创建可重用的功能。

创建可重用的功能。可以从不同来源调用的代码。这并不是因为这利用了您自己的工作,而是更重要的是,它确保了这些功能是简单的、不可变的,并且事后易于管理。让它们尽可能小。

Unsplash 上拍照

8.不写评论。

当然,你可以写评论,但是作为一条规则,你应该写尽可能少的评论。代码和脚本需要不言自明。只允许简单的监督意见。

9.避免不必要的缩写。

编写有意义的变量名没有额外的成本。在给变量命名时使用描述性的名字,这样更容易理解代码。(所以可以用时间的时候就不要用 t)

10.不必要时不要硬编码

命名变量时,将所有硬编码的变量全部大写,这样你就有一种直观的方式来记住这是一个硬编码的变量。对于所有其他变量,选择是使用 camelCase 还是下划线 _case。

11。在可能的地方显式,在需要的地方隐式

显式关联输入参数。即使下面是相等的:

  • 在< 2
  • number_of_arguments_in ≤ 1

The former holds a direct relationship to the number of inputs (i.e., 2), whereas the latter does not. This gives a direct link to between the elements in your program.

Photo by 克里斯多佛·伯恩斯Unsplash

12.内部名称与外部标签

将函数的内部名称和外部标签分开。这使得为客户更改 UI / API 接口变得容易,而不必更改函数的内部工作方式。这也使得调试更加容易。

就是这样…

如果你把这些简单的规则记在心里(或放在身边),从长远来看,你会让你自己的生活和你周围的人的生活变得更容易,还可能节省一些钱和时间。

不言而喻,Joost 确实应该为这些规则受到称赞。可能是他应该写这个或者类似“干净代码”的东西

云计算之旅:如何成为 AWS 认证解决方案架构师

原文:https://towardsdatascience.com/journey-into-the-clouds-how-to-become-a-aws-certified-solution-architect-719cae167e70?source=collection_archive---------7-----------------------

【来源:Pexelbay】

作为一名 IT 解决方案架构师,我一直有兴趣将自己的知识从应用扩展到基础设施,因此我决定准备参加亚马逊 Web 服务认证解决方案架构师助理考试,这是 IT 行业最重要、最受广泛认可的 T2 证书之一。我想分享我成功准备考试的方法,从而在这个过程中帮助其他人。

为什么选择 AWS 解决方案架构?

审视过去 10 年的企业 IT 行业趋势,有一些高增长的领域继续扩张并奖励工程人才:云基础设施数据分析安全。尽管一个人可以通过认证进入数据分析和安全领域,但除非他拥有多年的经验,特别是在数据科学方面,至少拥有两年的 STEM 硕士学位,最好是应用数学、计算机科学或统计学专业,否则财务和专业回报并不显著。由于顶级平台供应商的优秀公开文档和我将在下面分享的全套教育资源,云基础架构有一个更平坦的倾斜和更低成本的学习曲线。

AWS 客户的广度[来源:AWS]

此外,考虑一下云计算不可避免的进步,因为基于传统硬件和软件的传统数据中心由于其资本支出基础、灵活性和技术停滞而衰落。正如 Gartner 的 2019 年报告所建议的,各种规模的组织都在将工作负载迁移到云。数据中心支出从 2017 年的 6%增长放缓至 2019 年的不到 2%;服务器采购在 2019 年下降了 1%,预计在未来五年内每年将进一步下降 3%。与此同时,包括云计算在内的 IT 服务支出的增长速度是 2017 年的两倍,从 2017 年的 4%上升到 2019 年的近 5%。

云平台支出趋势[来源:Statista]

此外,人们必须评估云计算供应商,以了解在哪里进行专业下注。截至 2020 年 2 月,亚马逊网络服务(AWS)、微软 Azure 和谷歌云平台是这一领域无可争议的领导者。AWS 于 2006 年推出,已经领先其竞争对手,例如 AWS 在 2019 年拥有 33%的市场份额,并且每年增长超过 35%。相比之下,2010 年诞生的 Azure 现在已经达到 18%的市场份额,而 2013 年开始的 GCP 已经达到 8%的市场份额。此外,今年有报道称,泄露的谷歌备忘录暗示,如果 Alphabet 不能在市场上排名第一或第二,它可能会在 2024 年之前退出云平台领域。

最后,解决方案架构代表了 IT 劳动力市场中最适合适应 IT 行业不断变化的领域。魔鬼总是在细节中,但是架构是与业务一致的概念和逻辑活动,云计算使人们能够更好地推理和组装计算、存储、数据和网络乐高积木,以设计更好的分布式系统来解决业务问题。将所有这些放在一起,专注于顶级云平台(如 AWS)的解决方案架构不仅会产生良好的业务和常识,而且会令人愉快,因为您正在对组织产生战略影响,并与各种利益相关者进行互动。因此,云解决方案架构师的工资与上述其他领域不相上下,并且工作岗位比上述其他领域更加丰富也就不足为奇了。

在工作中使用 AWS,在家里做实验。

没有什么能代替你在工作中接触现实世界的项目,你会在某些领域获得深度;然而,许多 AWS 服务用户指南都有 10 分钟的教程和半真实的样本,可以拓宽你的知识面,扩大你的舒适区。这一步骤将持续进行,可能需要一年时间,这大约是您可以参加 AWS 考试之前的最低经验量,也是 AWS 服务免费层可以为个人或公司帐户持续的时间长度。

遵循 AWS 证书培训课程。

阅读 RDSEC2Route 53SQSVPC常见问题。阅读关于 AWS 架构良好的框架及其支柱的白皮书;然后,确保您能够设计出平衡并满足其成本、性能、可靠性、操作和安全性限制的技术解决方案。记下手写笔记并绘制图表,以加强您对材料的理解,并构建一个关于 AWS 组件如何组合在一起的强大心理模型。采取免费的 AWS 数字培训视频系列。这个步骤需要一(1)个月。

参加 Ryan Kroonenburg 的 Udemy 课程。

50 万人在 Udemy 上了 Ryan Kroonenburg 的解决方案架构师助理课程。我强烈推荐这门课程,因为 Ryan 是一个优秀的沟通者,云专家的材料是最新的和全面的,模拟 AWS 考试的两个模拟测试非常值得课程本身的价格,根据正在进行的 Udemy 折扣和促销活动,价格从 11.99 美元到 149.99 美元不等。这个步骤需要一(1)个月。

阅读教程道场和数云培训发布的婴儿床笔记

Tutorials Dojo 和 Digital Cloud Training 发布的婴儿床笔记和备忘单非常出色,结合了非凡的广度和深度。它们涵盖了考试中出现的所有主要 AWS 服务,并简化了考试准备期间的复习过程。从这些笔记中获取额外的手写笔记,以补充早期的 AWS 材料,并进一步巩固您的记忆。这一步需要两(2)周时间。

参加 AWS 和 Udemy 模拟考试

我建议在参加真正的考试之前,至少参加 3 次全程模拟考试。Ryan 的 Udemy 课程有两次这样的考试。你也可以花大约 20 美元从 AWS 购买一个官方的实践考试。不过最好的一套练习考试是乔恩·邦森在 Udemy 上主持的 6 套练习考试,价格为 12.99-39.99 美元。Ryan 和 Jon 的考试都包含对正确和错误答案的详细解释,他们的考试报告有助于确定你的优势和劣势。这一步需要两(2)周时间。一旦你经常获得 75%以上的分数,你也应该报名参加考试。

期末考试复习

在正式考试前的最后一周,我建议再参加一次练习考试,多复习一遍笔记,得到锻炼和休息,和家人朋友一起放松,这样你在参加考试的时候就充满了信心。

[来源:Supushpitha Atapattu @ Pexelbay]

人生没有成功的捷径。如果你能投资至少三(3)个月和大约 80 美元参加两门 Udemy 课程和 AWS 实践考试,请放心,你会像我一样通过 AWS 解决方案架构师助理考试。我希望这篇文章能帮助 IT 社区的其他人达到他们的职业目标。祝你好运,让我知道你的想法!

欣赏文章?关注我的 推特 了解更多更新。

理解厚尾分布

原文:https://towardsdatascience.com/journey-to-tempered-stable-distribution-part-1-fat-tailed-distribution-958d28bc20c?source=collection_archive---------12-----------------------

迈向稳定的分销之旅#1

多胖才算胖?

嗨,我是卢先生

T 何系列《钢化稳定分布之旅》旨在帮助人们了解厚尾分布中的一种:钢化稳定分布。因此,本文档的目的是介绍和解释一些概念和工具,这些概念和工具是理解利用调和稳定分布来达到他们自己的目的所必需的。我不会深入每一种厚尾分布的本质,而是试图用一种直观的方式解释相关的统计和数学概念/问题,并在金融中有所应用。我希望有一个有用的外卖给所有不同背景的读者。欢迎通过本文档末尾的电子邮件提出任何问题。

  • 第 0 部分:为什么是缓和稳定(TS)分布?[ 点击
  • Part1:什么是厚尾分布?
  • 第二部分:无限可分分布?【点击

在第 1 部分中,我们讨论随机变量具有“厚尾”分布意味着什么。

远吗?胖?

为了理解厚尾现象,我们需要回答以下两个问题。

1.多远才算远?
2。多胖才算胖?

要谈尾巴,我们需要确定多远才算远,才能决定离中间多远才算远,才能说它是‘尾巴’。换句话说,尾巴从哪里开始?看情况!不幸的是,没有单一的答案。

考虑正态分布。注意有两条尾巴:右边和左边。例如,如果我们想用一个标准差来描述分布的“右”尾,那么阴影部分指的是正态分布的右尾。

图。一

形式上,我们可以这样描述尾巴:

  • 右尾:P(X>x)
  • 左尾:P(X≤-x)

对于一个大的值‘x’。现在,我们知道了“尾巴”的概念。

**[R codes for Tail]**
#For normal distribution with value 'x=a'
a=1
1-pnorm(a) #right tail
pnorm(-a)  #left tail

每个分布都有尾巴吗?

想想[0,1]上的均匀分布。它有尾巴吗?在这个博客中,它说不是每个发行版都有尾巴。

如果你想要“尾部的行为”来描述当“x”变大时 pdf 的特征,那么有界分布没有尾部。然而,尾部的一些特征是可以量化的。特别是,通过使用极限和渐近行为,你可以定义重尾的概念。 SAS 博客

我将在下面解释(指数)有界/无界分布。到了那里请提醒自己制服发放!

我们为什么要关心分配的“尾部”部分?

分布的尾部一直是风险管理的主要关注点。例如,收益或损失分布的两个最常用的风险度量是 【风险值】【预期亏空】

为什么损失不还?

  • 损失实际上是负(-)回报
  • 将极限取负无穷大是不直观的。所以我们取返回值的负值,也就是说,将分布翻转到 y 轴上。

看看 VaR 和 ES 这两个量和‘尾巴’有什么关系就知道了。不需要理解它们背后的数学或含义。


图。2 //资料来源:Ch2,量化风险管理(以下简称 QRM ),作者麦克尼尔等人

考虑损失的分布, L ,相当于(负)回报,在给定的持有期内。为了便于理解,我们假设明天损失的随机变量遵循正态分布:

然后,我们可以通过以下方式计算 VaR:

来源:埃里克·齐沃特的课堂笔记

通过第二条线,我们可以很容易的检查出 VaR 只是一个与胖尾相关的量。关于风险值的更多细节,请查看《量化风险管理:概念、技术和工具》一书的第二章,以及 Eric Zivot 在他网站上的讲座笔记。

**[R codes for VaR]**alpha = 0.95 #significant level
VaR.alpha = qnorm(alpha, mu, sigma)
VaR.alpha = mu + sigma*qnorm(alpha, 0, 1)

同样,我们可以看到预期短缺是一个与分布尾部相关的量:

来源:埃里克·齐沃特的课堂笔记

在第四行中,它表示“ES 是损失分布的上“尾“中的预期损失”。类似于 VaR,在正态分布的情况下,现在计算 ES 很方便,因为它只是一个截尾正态分布的均值。

来源:埃里克·齐沃特的课堂笔记

**[R codes for ES]**
alpha = 0.95
q.alpha.z = qnorm(alpha)
ES.alpha = mu + sigma*(dnorm(q.alpha.z)/(1-alpha))

如果有人好奇我们为什么除以 1 — α,这只是一个归一化常数(或比例因子)以确保截断损失分布的积分为 1,这是概率分布的一个要求。

回到“尾部”的故事,我只想强调尾部分布被广泛用作风险管理工具。

多胖才算胖?多重才算重?

既然我们弄清楚了分布中的‘尾巴’是什么,用在什么地方,现在就该说说‘肥’的部分了。我们都知道正态分布没有厚尾。相反,我们被教导在对金融回报序列建模时使用 student-t 分布和对数正态分布来考虑“厚尾”特性。但是我们需要知道肥尾的定义。不幸的是,脂肪这个词没有统一的定义。

我将试着解释英语、图形和数学的语言中的胖尾巴。希望你至少喜欢这三个中的一个。

在英语中,

  • 重尾分布具有比指数分布更重的尾部(Bryson,1974)
  • 当尾部比指数分布衰减得更慢时,称分布具有重尾。

为什么是指数?

使用指数分布作为参考是很方便的。指数分布的 pdf 以“指数”方式快速接近零。也就是说,pdf 的尾部看起来像(但表现不同于)指数分布。

用图表的语言来说,

我将向您展示 4 个不同的图表,显示在一组不同分布的最右侧尾部发生的情况,如下所示:

  • 指数分布
  • 幂律分布
  • 正态分布
  • 对数正态分布
  • 学生 t 分布
  • 柯西分布
  • 征税分布
  • 威布尔分布

我不会解释每一个发行版。相反,让我们欣赏一下这些分布图,感受一下尾部的情况。第一个图形显示了整个图形中“x”位于[0,5]中的部分

图。5,文档末尾提供了该图的 R 代码

根据上面的图 5,我们无法判断尾巴的行为。但是,这里有一些事情值得一提

  • 正态分布、student-t 分布和柯西分布都是双尾分布。所有其他的都是单尾分布
  • 对于 PL(2.5)和 PL(3.5),在 x=1.7 附近有一个交叉点,说明 PL(2.5)的尾部较粗。

让我们看看当 x 位于[5,8]时是什么样子。请注意,y 轴上的值会变得更小。

图。6

问:你在这个图表中看到了什么?

答:最上面的线会有最粗的尾巴!(但也不尽然!!!)你就知道为什么了!

在此之前,让我们检查一下上面图 6 中的重要事实。

  • 当 x=5 时,正态和 exp(2)分布在 0 附近爬行。尤其对于正态分布,其 5 标准差的 pdf 值为 0.000001486 (=pnorm(5))。这大约是柯西分布的 8000 倍。换句话说,在柯西分布下,5 sigma 事件发生的可能性是正态分布的 8000 倍。
  • 在图 6 中,请记住 exp(0.2)分布位于对数正态分布和幂律分布之上。请检查在扩展“x”值的范围后,它是如何在下图中反转的。

让我们看看当 x 位于[8,100]时是什么样子。同样,请注意 y 轴上的值会变得小得多。

图。七

  • 请注意,蓝线 exp(0.2)在穿过另外两条线 PL(2.5)和 Cauchy 时衰减很快。这就是“衰减慢于指数分布”的含义
  • 看到“x”等于 100 附近发生的情况令人惊讶。其 PL(1.5)的 pdf 值为 0.0005。难怪对于 PL(1.5),一阶矩和二阶矩(均值和方差)都是无穷大。这方面的详细信息将在下一篇文档中介绍。敬请期待!

让我们放大 y 轴来详细看看它是如何表现的!

图。8

  • 令人惊讶的是,蓝线 exp(0.2)通过穿过 PL(3.5)和 LN(0,1)而减小。此外,我们可以看到 LN(0,1)比 PL(3.5)衰减得更快,因为它穿过 PL(3.5)并在它下面。
  • PL(1.5)、PL(2.5)和 Levy 分布甚至没有显示在该图中。

在数学语言中,

‘重’vs‘胖’

厚尾分布是重尾分布的一个子类。这意味着尽管每一个厚尾分布都是重尾分布,但反过来就不成立(例如,威布尔分布)。根据杰伊·泰勒的讲义,他用以下方式区分了胖子和胖子。

重尾的定义

  • 如果尾部是“非”指数有界的,则称分布有一个右重尾

等式 1

我们可以解读为,当‘x’变大时,指数增长的速度快于重右尾上概率下降的速度。花点时间想想吧!

看看它是如何与英语定义联系起来的。

  • 比指数衰减慢的概率分布函数被称为右重尾。

当指数有界时。

如果重的右尾不够重,即,当“x”趋向无穷大时,它衰减得非常快,那么等式 1 收敛到零。一个明显的例子是我们上面讨论的[0,1]上的均匀分布。一旦‘X’超过 1,X 大于 1 的概率变为零,因此它是指数有界的。另一个流行的例子是正态分布。设 X 为标准常态。画出一系列不同λ值的图表

图。3

我们可以看到它收敛到零,所以正态分布的尾部是指数有界的。

**[R codes for Figure. 3]** f_exp = function(x, lambda){return (exp(lambda*x))
cdf_normal = function(x) pnorm(x)
ccdf_normal = function(x) {1-cdf_normal(x)}xs = seq(1,10,length=10000)
plot(xs, f_exp(xs,0.1)*ccdf_normal(xs), type='l', xlab='',ylab='', col='blue', lwd=2)
abline(v=1, lty = 'dashed')
lines(xs,f_exp(xs,0.5)*ccdf_normal(xs), col='purple', lwd=2)
lines(xs,f_exp(xs,1)*ccdf_normal(xs), col='red', lwd=2)
lines(xs,f_exp(xs,1.5)*ccdf_normal(xs), col='orange', lwd=2)
lines(xs,f_exp(xs,2)*ccdf_normal(xs), col='darkred', lwd=2)
lines(xs,f_exp(xs,3)*ccdf_normal(xs), col='darkblue', lwd=2)
grid()
legend(8, 0.15, 
       legend=c("0.1", "0.5","1","1.5","2","3"), title = "lambda",
       col=c("blue",'purple', "red",'orange','darkred','darkblue'), lwd=2, cex=1)

胖尾的定义

  • 如果有一个称为尾部指数的正指数(α),则称分布有一个右厚尾(T1)

“~”的意思是不变的。或者说尾部与幂律成正比。准确地说,它的意思如下。

来源:[ 点击,[ 点击

如果数学对你来说很难,你可以跳过。

因此,厚尾分布的尾部遵循幂律(x 的负α次方)。对于那些不熟悉幂律的人来说,现在不用担心。想想当α等于 2 时的图形。

图。四

提醒自己,尾部看起来类似于我们在上面的图 5-8 中看到的幂律。我将在本系列的[第 2 部分]中更详细地解释幂定律。

摘要

我们在本文中直观地、图形化地和数学地讨论了“厚尾”这个概念。要理解“缓和的稳定分布”,就必须对厚尾有一个基本的了解。希望这份文件有助于提高你的理解。如果你有任何问题,请在下面评论。我希望你对接下来会发生什么感到好奇。下一次,我会带着[回到炼成稳定分布的旅程【部分。2:无限可分分布]](https://medium.com/@corr.roh/infinitely-divisible-distribution-586b18c63670) "

**[R Codes of Figure. 5]**
f_exp = function(x, lambda, xmin) {lambda*exp(-lambda*(x-xmin))}
f_power = function (x, k, x_min) {
            C = (k-1)*x_min^(k-1)
            return (C*x^(-k))
            }
f_cauchy = function(x) dcauchy(x)
f_levy = function(x) dlevy(x) # required package: 'rmulti'
f_weibul = function(x) dweibull(x,shape=1)
f_norm = function(x) dnorm(x)
f_lnorm = function(x) dlnorm(x)
f_t = function(x) dt(x,5)
xs = seq(0.1,100,length=1000)plot(xs, f_exp(xs,0.5,0.1),type='l',xlab='',ylab='', col='blue', lwd=2,
     main='Distributions on [0,5]', cex.main=1,
     xlim=c(0,5),
     ylim=c(0,2.5))
lines(xs,f_exp(xs,1,0.1), col='purple', lwd=2)
lines(xs,f_exp(xs,2,0.1), col='bisque3', lwd=2)
lines(xs,f_power(xs,1.5, 1), col='red', lwd=2)
lines(xs,f_power(xs,2.5, 1), col='orange', lwd=2)
lines(xs,f_power(xs,3.5, 1), col='darkred', lwd=2)
lines(xs,f_norm(xs),col='black', lwd=2)
lines(xs,f_lnorm(xs), col='darkgreen', lwd=2)
lines(xs,f_t(xs),  col='deeppink', lwd=2)
lines(xs, f_cauchy(xs), col='darkblue', lwd=2)
lines(xs, f_levy(xs), col='azure4', lwd=2)
lines(xs, f_weibul(xs), col='springgreen', lwd=2)
abline(v=2, lty = 'dashed')
abline(v=3, lty = 'dashed')
grid()
legend(3.5, 2.5, 
       legend=c("exp(0.2)", "exp(1)", 'exp(2)', "PL(1.5)", 'PL(2.5)', 'PL(3.5)', 'N(0,1)','LN(0,1)','student-t(5)','Cauchy','Levy','Weibull'),
       col=c("blue",'purple', 'bisque3',"red",'orange','darkred', 'black','darkgreen','deeppink','darkblue', 'azure4','springgreen'), lwd=2, cex=0.8)

参考资料:

[1]杰伊·泰勒,重尾分布(2013),讲义,

[2] Eric Zivot,风险度量(2013),课堂讲稿

[3] Aaron Clauset,复杂系统的推理、模型和模拟(2011),讲义

[4]https://blogs . SAS . com/content/IML/2014/10/13/fat-tailed-and-long-tailed-distributions . html

我还为上面所有的参考文献添加了超链接。请查阅参考资料了解详细信息。如果有我错过的任何事情,我将稍后更新参考。

感谢您阅读本文档。如果你觉得这份文件有用,别忘了与你的朋友分享。

使用 Python 的 JSON 和 API

原文:https://towardsdatascience.com/json-and-apis-with-python-fba329ef6ef0?source=collection_archive---------0-----------------------

使用 Python 的 JSON 和 API 介绍

肖恩·林在 Unsplash 上的照片

介绍

在另一个教程中,我们讨论了如何用 python 进行网页抓取。网络抓取的目标是从网站或网页获取数据。嗯,有时候一个网站可以让用户通过 API(应用编程接口)更容易地直接访问他们的数据。这基本上意味着该公司制作了一组专用的 URL,以纯形式提供这些数据(意味着没有任何表示格式)。这种纯数据通常是 JSON (JavaScript 对象表示法)格式,我们可以使用 python 解析并提取我们需要的内容。

对于本教程,我们将使用在 covid19api.com 发现的免费 API,提供冠状病毒的数据。我们将找到每个国家确诊病例的总数,然后我们将创建一个包含这些信息的熊猫数据框架。所以让我们开始吧!

[## 使用 Python 进行 Web 抓取

如何在 python 中使用漂亮的 soup 和请求库进行网页抓取

pub.towardsai.net](https://pub.towardsai.net/web-scraping-with-python-6d01f5e9378f)

检查 API

如果你进入 API 的文档页面,你会看到:

这向我们展示了 API 中的不同 URL、它们提供的信息以及右边这些 URL 的请求/响应示例。

我们可以看到,我们正在寻找的信息在摘要页面。我们可以单击右侧的“查看更多”,这样我们就可以看到来自该 URL 的响应:

这是一个 JSON 对象!如您所见,它非常类似于 python 字典,由键值对组成。事实上,为了让我们解析它并从中提取我们想要的东西,我们最终会将它转换成 python dictionary 对象。经过检查,我们可以看到它看起来像一个嵌套的字典。外部字典具有关键字“Global”(具有字典的值)和“Countries”(具有由字典组成的列表的值,每个字典对应一个特定的国家)。

[## 在 Python 中创建表的两种方法

Python 中制表和熊猫数据帧函数的性能比较

towardsdatascience.com](/two-ways-to-create-tables-in-python-2e184c9f9876)

从 API 发出 HTTP 请求

因此,让我们打开一个 jupyter 笔记本,从那个 URL 请求信息。我们将使用请求库从那个 U RL 发出一个 HTTP 请求,并将响应对象的文本保存在变量 response 下:

response = requests.get(‘https://api.covid19api.com/summary’).text

这显示了 API 对我们的 HTTP 请求的响应。如您所见,这是一个 JSON 格式的长 python 字符串。

[## 在 Pandas 中使用字符串方法

如何将字符串方法应用于 pandas 数据框架中的列

towardsdatascience.com](/using-string-methods-in-pandas-5e4509ff1f5f)

创建 Python 字典

由于响应是 JSON 格式的,我们可以将这个字符串加载到 python 中,并将其转换成 python 字典。我们首先需要导入 json 库,然后我们可以使用 json 库中的 loads 方法,并向它传递我们的字符串:

response_info = json.loads(response)

注意我们的 response_info 变量的类型现在是一个 python 字典!

既然我们的响应是 python 字典的形式,我们可以使用我们所知道的 python 字典来解析它并提取我们需要的信息!

还要注意:requests 库有一个内置的 json 解码器,我们可以用它来代替 JSON 模块,后者会将我们的 JSON 对象转换成 python 字典。但是,我在本教程中使用了上述方法来介绍 json 模块。如果我们在请求模块中使用 JSON 解码器,代码看起来会是这样的:

requests.get(‘https://api.covid19api.com/summary’).json()

解析字典

如前所述,我们希望创建一个包含两列的熊猫数据框架:国家和该国确诊病例总数。我们可以通过循环外部字典的“Countries”键的值来实现这一点:

如您所见,我们的“Countries”键的值只是一个字典列表,每个字典都包含对应于特定国家的键-值对。因此,我们需要遍历这个字典列表,从每个字典中提取“Country”和“TotalConfirmed”关键字的值,然后将它们追加到一个新列表中,如下所示:

country_list = []for country_info in response_info[‘Countries’]:
 country_list.append([country_info[‘Country’], country_info[‘TotalConfirmed’]])

这将遍历字典列表,从每个字典中提取“Country”和“TotalConfirmed”键的值到一个列表中,然后将这个结果列表添加到我们的 country_list 中。我们将以一个列表列表结束,外部列表中的每个列表或元素都包含国家名称和该特定国家的确诊病例总数。

[## 如何在熊猫身上使用 loc

了解如何使用 pandas Python 库中的 loc 方法

towardsdatascience.com](/how-to-use-loc-in-pandas-49ed348a4117)

创建熊猫数据框架

我们现在将使用这个 country_list 和 pandas 数据帧构造函数创建一个 pandas 数据帧:

country_df = pd.DataFrame(data=country_list, columns=[‘Country’, ‘Total_Confirmed’])

成功!我们现在有一个包含两列的数据框架:Country 和 Total_Confirmed!

如果你喜欢阅读这样的故事,并想支持我成为一名作家,考虑注册成为一名媒体会员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你用我的 链接 注册,我会赚一小笔佣金。

[## 通过我的推荐链接加入媒体——卢艾·马塔尔卡

阅读卢艾·马塔尔卡的每一个故事(以及媒体上成千上万的其他作家)。您的会员费直接支持…

lmatalka90.medium.com](https://lmatalka90.medium.com/membership)

结论

在本教程中,我们简要介绍了什么是 API 和 JSON。然后,我们向一个冠状病毒 COVID19 API 发出 HTTP 请求,以获取每个国家确诊的冠状病毒病例总数的信息。然后,我们将这个对我们请求的 JSON 响应转换成一个 python 字典。然后我们解析这个字典,提取我们要寻找的信息,然后创建一个包含这些信息的熊猫数据帧。

JSON 为 Python 用户解释:数据科学版

原文:https://towardsdatascience.com/json-explained-for-python-users-data-science-edition-18e9859944da?source=collection_archive---------18-----------------------

使用 JSON 数据是不可避免的——让我们正确地学习它。

JSON 数据无处不在。它仍然不是数据科学家最广泛使用的数据格式,因为数据集存储在 CSV 或数据库中。今天,您将学习如何处理 JSON,以及如何在您的数据科学项目中使用它。

安德斯·吉尔登在 Unsplash 上的照片

但是 JSON 是什么?

好问题。JSON 代表“JavaScript 对象表示法”,是一种简单且众所周知的数据格式。一旦你习惯了括号,人类很容易读写。此外,每一种主要的编程语言本身都支持它。

JSON 类型建立在两种数据结构之上:

  1. 对象—键/值对的集合
  2. 数组-值列表

并且使用起来非常简单。

这是一篇没有废话的文章,目标是尽快让你的手脏起来。我们一会儿将连接到一个实际的 API,然后讨论基础知识。稍后您将看到我最喜欢的 JSON 功能,从数据科学的角度来看。

我们开始吧。

API 连接

如果您还没有启动笔记本电脑环境,请启动它。我们现在将只使用请求库:

import requests

让我们先来探索一下 API。它可以在此链接上找到,包含一些用户的虚拟数据。完美满足我们的需求。

让我们把它装进去,好吗?这个过程很简单,就像 Python 中的大多数东西一样:

req = requests.get(‘[https://jsonplaceholder.typicode.com/users'](https://jsonplaceholder.typicode.com/users'))
req**>>> <Response [200]>**

这个 200 状态代码意味着请求已经成功,我们已经准备好处理数据了。让我们将 JSON 数据存储到一个单独的变量中:

users = req.json()
users[0]

你看到这有多简单了吗?

现在让我们来看看用户变量。我已经指出 JSON 是建立在两种结构上的——对象和数组——让我们看看这种说法是否成立:

type(users)**>>> list**type(users[0])**>>> dict**

它成立——因为列表和数组是同义词(ish ),而字典可以被解释为对象。接下来将讨论保存和加载 JSON 数据。

保存和加载数据

我们可以使用纯 Python 功能来保存和读取 JSON 数据。以下是如何实现节约的方法:

import jsonwith open(‘json_write_test.json’, ‘w’) as f:
    json.dump(users, f, indent=4)

indent 参数是可选的,它表示单个选项卡应该有多大。非常类似于 Python 的 4 空格缩进语法。我们可以验证文件是否确实被保存了:

读取过程非常相似——我们只需要从写模式切换到读模式,并使用 load() 函数,而不是 dump() :

with open(‘json_write_test.json’) as f:
    data = json.load(f)

我们可以再次验证该过程是成功的:

这几乎涵盖了阅读和写作。

使用 JSON

这将是一个简短的部分。为什么?因为使用 JSON 就像使用 Python 字典一样。我来详细说明一下。

默认情况下,JSON 数据不是 Python 字典的数组。但是当加载到 Python 中时,就变成了一次。因此,我们可以将 JSON 数据视为字典列表。

这里有一个例子:我们想打印每个用户的姓名和完整地址,不包括邮政编码。这很简单:

for row in users:
    print(f”Address of {row[‘name’]} is {row[‘address’][‘street’]} {row[‘address’][‘suite’]}, {row[‘address’][‘city’]}”)

这篇文章看起来有点乱,但是只要把代码复制到你的笔记本上就可以了。你马上就会明白它的要点。这是你应该知道的。下一节将介绍我最喜欢的处理 JSON 的方式——数据科学方式。

JSON 扁平化

用像熊猫这样的库读取 JSON 数据有时会有问题。如果没有嵌套(对象中的对象),那么一切都会好的。大多数真实世界的数据是嵌套的,我们需要以某种方式解决这个问题。

下面是将我们的 JSON 数据加载到一个 Pandas 数据帧时会发生的情况:

pd_data = pd.DataFrame(data)
pd_data.head()

地址列之前看起来还不错,在那里地址本身被分成街道、套房、城市和邮政编码。同样适用于公司栏。

但是我们如何解决这个问题呢?

前段时间我使用定制库进行 JSON 扁平化,但是有几次它们并没有像宣传的那样工作。这就是我想出这个函数的原因,得到了堆栈溢出的一点帮助:

def flatten_json(json):
    output = {}

    def flatten(inpt, name=’’):
        if type(inpt) is dict:
            for elem in inpt:
                flatten(inpt[elem], name + elem + ‘_’)
        elif type(inpt) is list:
            i = 0
            for elem in inpt:
                flatten(elem, name + str(i) + ‘_’)
                i += 1
        else:
            output[name[:-1]] = inpt

    flatten(json)
    return output

该函数几乎是不言自明的,必须应用于数据的每一行。如果您有一个 100 个 JSON 对象的数组,您不能只将函数应用于数组本身,而是要应用于数组的每个元素。方法如下:

flattened = [flatten_json(row) for row in data]

以下是现在数据的不同之处:

原始和展平数据的第一条记录

注意展平的数据中没有缩进,以及所有以前嵌套的元素现在都有前缀。

转换到 Pandas 数据帧的过程现在按预期工作:

今天到此为止。让我们在下一部分总结一下。

在你离开之前

我使用过的大多数 API 都以 JSON 或 XML 的形式返回数据——这由您来选择。JSON 要简单得多,至少在 Python 中是这样。

您还可以将 JSON 存储在数据库中:

  • SQL 数据库的 LOB 格式
  • NoSQL 数据库的“原始”格式

但那是以后的事了。感谢您的阅读,希望对您有用。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

Python 中的 JSON 对象

原文:https://towardsdatascience.com/json-objects-in-python-f45e04281c30?source=collection_archive---------16-----------------------

Python 中 JSON 对象的介绍

来源

Java Script Object Notation (JSON)是一种轻量级数据格式,与 python 字典有许多相似之处。JSON 对象非常有用,因为浏览器可以快速解析它们,这对于在客户机和服务器之间传输数据非常理想。在本帖中,我们将讨论如何使用 python 的 JSON 库来发送和接收 JSON 数据。

我们开始吧!

首先,让我们来看看下面这个 JSON 包,里面有关于甲壳虫乐队的专辑黄色潜水艇的信息:

{
     "album_title" : "Yellow Submarine",     
     "release_year" : 1966,   
     "won_grammy" : false,
     "band" : "The Beatles",
     "album_sale": null
     "musicians" : ["John Lennon", "Paul McCartney", "George   Harrison", "Ringo Starr"],
     "studio" : {"studio_name": "Abbey Road Studios", "location": "London, England"}
     }

在 JSON 对象中,键是字符串,值可以是字符串、数字(浮点数或整数)、布尔值、列表、null 或其他 JSON 对象。从这个例子中可以看出 python 字典和 JSON 对象之间有一些差异。例如,布尔值为小写,而“无”值为“空”。python 字典的等价形式是:

{
     "album_title" : "Yellow Submarine",     
     "release_year" : 1966,   
     "won_grammy" : False,
     "band" : "The Beatles",
     "album_sale": None
     "musicians" : ["John Lennon", "Paul McCartney", "George   Harrison", "Ringo Starr"],
     "studio" : {"studio_name": "Abbey Road Studios", "location": "London, England"}
     }

现在,让我们将示例 JSON 数据保存到一个名为“album.txt”的文本文件中。我是使用终端命令行和“vim”文本编辑器来完成的,但是您也可以使用任何您喜欢的工具。接下来,在 python 脚本中,让我们导入 JSON 模块:

import json

让我们使用“dir()”方法来看看本模块中可用的方法:

print(dir(json))

我们将重点关注加载和转储方法。要继续,让我们使用 open 方法打开文件。在 open 方法中,让我们指定文件名“album.txt”和模式(读或写)。我们将读取文件,因此模式为“r”:

album_json_file = open("album.txt", "r")

接下来,我们可以使用 load 方法从我们的文件中加载 JSON 数据:

album = json.load(album_json_file)

加载 JSON 数据后,我们关闭文件:

album_json_file.close()

我们现在可以打印加载的 JSON 数据了:

print(album)

如果我们打印这个对象的类型,我们会看到它是一个 python 字典:

print(type(album))

让我们看看 JSON 对象和 python 字典之间的区别。JSON 对象中的' won_grammy '值是' false ',而在字典中是大写的' False '。此外,“album_sale”值 Null 在 python 字典中被解析为“None”。

既然我们已经将数据加载为一个字典,我们可以通过键访问解析后的字典中的值。例如,如果我们想要访问“相册标题”,我们执行以下操作:

print("Album Title: ", album['album_title'])

或者如果我们想查看专辑发行的年份:

print("Release Year: ", album['release_year'])

在客户机/服务器应用程序中,JSON 对象通常以字符串的形式出现。例如,我们用于相册信息的 JSON 对象可以是这样的:

album_string = """{"album_title" : "Yellow Submarine",
     "release_year" : 1966,
     "won_grammy" : false,
     "band" : "The Beatles",
     "album_sale": null,
     "musicians" : ["John Lennon", "Paul McCartney", "George   Harrison", "Ringo Starr"],
     "studio" : {"studio_name": "Abbey Road Studios", "location": "London, England"}
     }"""

为了使用 JSON 模块加载这些数据,我们使用' loads()'方法:

album_s = json.loads(album_string)
album_string.close()
print(album_s)

现在,假设我们从字典格式的数据开始,并希望将这些数据以 JSON 格式发送到数据库。我们可以使用 dumps 方法将字典转换成字符串 JSON 对象。让我们定义我们的原始字典:

album2 = {'album_title': 'Yellow Submarine', 'release_year': 1966, 'won_grammy': False, 
 'band': 'The Beatles', 'album_sale': None, 'musicians': ['John Lennon', 'Paul McCartney', 'George   Harrison', 'Ringo Starr'], 
 'studio': {'studio_name': 'Abbey Road Studios', 'location': 'London, England'}}

接下来,让我们使用 dumps 方法打印字符串 JSON 对象:

print(json.dumps(album2))
print(type(json.dumps(album2)))

我们的字典被正确解析为一个字符串 JSON 对象。我们看到“album_sale”值“None”现在为“null”,而“won_grammy”值“false”现在为“False”。

最后,我们可以把这个 JSON 对象写到一个。txt '文件使用转储方法:

file2 = open("album2.txt", "w")
json.dump(album2, file2)

我就讲到这里,但是您可以自己随意摆弄代码。

结论

总之,在这篇文章中,我们讨论了如何使用 python JSON 库发送和接收 JSON 数据。我们讨论了帮助我们接收数据的加载方法和帮助我们发送数据的转储方法。如果你有兴趣学习更多关于在 python 中使用 JSON 对象的知识,我推荐苏格拉底的 YouTube 教程。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

OpenAI 的点唱机。

原文:https://towardsdatascience.com/jukebox-by-openai-2f73638b3b73?source=collection_archive---------9-----------------------

人工智能生成音乐的魅力(附样本和 Colab 笔记本)

作者图片

点唱机——人工智能作曲家。

如果你仔细听,你会听到它们:来自另一个世界的声音。我听到了。嗯,不是直接,而是用点唱机。

JukeBox 是一个生成音乐的神经网络,一个由 OpenAI 团队实现的项目。他们开发了神经框架,并对不同音乐家、作曲家和乐队的 120 万首歌曲和音乐片段进行了训练。

这是一张音乐家地图:

来源:【https://openai.com/blog/jukebox/(截图:作者)

已经有各种各样的方法和人工智能驱动的模型来产生音乐,但直到现在,他们仍然能够创造出一些 MIDI 质量的旋律。

例如,这首曲子是我用 TensorFlow powered Magenta 框架的 Piano Transformer 创作的(试用: Colab Notebook )

钢琴变形金刚像 GPT-3 中的变形金刚一样,使用了自我关注,这给旋律带来了一些内在的连贯性,相当具有算法张力(嗯,JS 巴赫也用算法创作了他的赋格曲)。

JukeBox 使用变压器,但有另一种方法:对音频数据进行采样和上采样。这确实意味着,这个音乐模型“知道”各种风格和声音听起来如何,并写出它的解释。作为音频文件。

我在关于使用人工智能制作播客的教程中写过关于点唱机和其他音乐模型的内容:

在这篇文章中,我想与你分享我的一些惊人发现。

它是如何工作的?

在“ DEVS ”系列中有一个激动人心的时刻,科学家们对不可能的事情有了越来越清晰的认识——随着每一次迭代,他们都能越来越好地看到不可思议的事情。

使用点唱机你可以体验类似的感觉。有一款官方 Colab 笔记本可以用。

但也有 Colab 笔记本,SMarioMan增强,( GitHub )。它允许你在谷歌硬盘上存储数据——以防你的笔记本电脑崩溃。因为你需要时间来创作音乐——长达 8-10 个小时。

这里有一个由 Broccaloo 制作的关于使用点唱机的非常有用的视频教程:

首先,你需要定义一个艺术家和流派。你可以在 OpenAI 生成的巨大的人工智能音乐播放列表中找到 JukeBox 训练的所有艺术家和流派:

[## OpenAI Jukebox 示例资源管理器

浏览所有样品

jukebox.openai.com](https://jukebox.openai.com/)

点唱机播放列表,作者截图

第二次,在 10-30 分钟内 (第 2 级) 生成几个样本(默认为 3 个项目)。如果你不喜欢,你可以重新播放。

第三个,生成您满意的样本— 升级(1 级和 0 级) 。这需要时间,有时是半天。有时笔记本崩溃(连接中断,谷歌服务器问题等。等等。).但是如果你使用 SMarioMan 的笔记本,你所有的进展都存储在你安装的 GoogleDrive 中——你可以继续使用那里保存的检查点。

Colab 笔记本还能做什么?你可以…

  • 重采样现有的音乐片段(AI 可以从指定的时间点继续)
  • 尝试选择不同的艺术家和流派
  • 高档已经完成的音乐作品质量更好
  • 输入你的短信,运气好的话,人工智能生成的歌手会表演出来。

同时,我们可以观察到非常有趣的结果。跟随莱昂纳多·古铁雷斯,他对点唱机做了很多实验。利用我们对 AC/DC 歌词的共同改写,他创作了一个新版本的“在黑暗中拍摄”:

布罗卡罗(他在上面做了一个非常有用的视频教程)也做了有趣的实验:

Discord 上甚至有一个点唱机用户的粉丝社区:

[## 加入点唱机 AI 不和谐服务器!

查看 Discord 上的点唱机 AI 社区-与 469 名其他成员一起玩,享受免费的语音和文本聊天。

discord.com](http://discord.com/invite/6At7WwM)

来自异次元的声音。

点唱机上最让我着迷的是什么?不完全是模仿现有的表演者或演绎著名的作品,而是发现隐藏的宝石。机器的音乐幻觉。独特的声音景观。

恐怖谷已经过时了。这不再是一种怪异或令人毛骨悚然的感觉——这是遇到人工美学的幸福。

事实上,这些作品都是独一无二的:每一次都有一首新的前所未有的音乐作品产生——而且你可以肯定(就像 GPT 3 号的)这个序列永远不会重复。只是给你的。只有现在和这里。

我的第一次实验让我起鸡皮疙瘩。第二层已经很特别了,不是真正的音乐作品。越是向上采样,它就变得越迷人和清晰:

二级:

一级:

0 级:

听起来…很奇怪。就像记录一个未知国家和未知文化的配乐。

的确,点唱机完美地模仿语言。它可以解释你预先设定的文本,但它也可以产生一种语言的音乐解释。

你可以把它和 StyleGAN2 相比,style gan 2 解释文字的视觉效果而不是语义:

由 StyleGAN2 驱动的art breader生成的图像(我将它们用作虚构的 AI 相册的封面),由作者生成的图像

称之为 Brut Art ,称之为 Glitch Art ,但是 JukeBox 生成的一些音频样本却异常强烈。这里是我最喜欢的一些,我非常想知道你对它的看法?

你从未听过的声音。

除了上面的电影配乐,我还有几首音乐特别吸引我的兴趣。暂时忘记机器学习和理论。只要闭上眼睛,听音乐,保持对各种音频现象的关注。为了获得最佳体验,我建议使用耳机。

赛博布鲁斯/自由风格爵士乐

点唱机非常适合爵士乐。尤其是充满了同步和变调的自由式或实验性作品。上面的第一个片段也是用声音传递的——你可以识别单词,你也可以听到它模仿英语,但那是唯一的模仿。第二张唱片也有鼓舞人心的大乐队氛围——乐器的音质令人惊叹。

现象:你在这里观察到的另一个令人兴奋的现象——大部分生成的音乐片段已经完成作曲。它们不会在你设置好音乐长度的那一秒突然结束(至少不是全部)。同样的音乐变压器使旋律连贯的工作往往能使优雅的音乐结束。

声音

听听这把木吉他——你甚至可以听到吉他琴弦的刮擦声,仿佛这里不仅产生了音乐,还产生了音乐家。

现象:在上面的例子中,你会观察到(0:27 分钟)一些尖锐的音调,好像有人在鼓掌。只有两次——从现在开始,旋律节奏与这次鼓掌一致。变压器转换音乐,而不破坏其声学美学。

中世纪音乐剧

这很特别:闭上眼睛,你会想象一个有演员的舞台,他们的表演,甚至观众的反应。

现象:听这首曲子你有什么想象?我几乎看到一个欢闹的国王伴着喇叭声入场(伴随着观众的笑声),然后在一些柴可夫斯基的样本之后是一首情歌(结尾是主角唱“给你!.."(他可能会在他的女士面前跪下),公众无法用热烈的掌声、笑声和口哨来掩饰自己的情绪。一个不存在的戏剧表演的非常有机和现实的视觉。

在峡湾中歌唱

这首曲子是在玛丽莎·纳德勒上训练的,但在开始时,一个女孩的声音用一种不存在的语言演唱。独奏结束后,铿锵有力的音乐开始,脆弱的声音变得浑厚。

现象:强度、回声和气氛令人无法抗拒。我使用的是由 RoseBud 提供的 TokkingHeads 服务。AI (实现 i.a. 一阶运动模型)来可视化该性能:

观察:点唱机产生独特的风格和语言,可以帮助音乐家和作曲家获得新的令人惊讶的想法和灵感。

我没有任何问题(如特雷西·查普曼所唱)

在这两个版本中,我选择了特雷西·查普曼作为表演者。正文是 GPT 为我写的——3:

[## 一块石头和一首诗

非人类诗歌

thecreative .咖啡馆](https://thecreative.cafe/a-rock-and-a-poem-8e14a791a092)

这很有效 Tracy 演唱人工智能生成的歌词的独特声音(我爱上了这首 GPT 3 的诗)。

现象:就像在其他人工智能生成的歌曲中一样,即使你为歌唱指定了歌词,人工智能也不一定会服从并使用你的文本。有时——甚至经常——它用额外的语言错误来扩充文本。这种意想不到的和个人的随机性再次证明,人工智能作为一个创造性的实例,肯定不仅仅是一些算法音乐预测方法。

人生不过是一场梦

为了这首歌,我训练点唱机上的童谣“划划划你的船”和吉米·卡伦作为表演者。还是那句话,你不仅能听到著名韵文的正文,还能听到一些语言故障。

现象:在这个案例中,给我留下深刻印象的不仅仅是声音的爵士配乐和强大的瘴气。但也是无意的,但完美实现的省略号:“仅仅,仅仅,仅仅,仅仅”……而小船正漂向光的海洋。

观察:点唱机可以给我们有趣的音乐隐喻的想法。

顺便说一句。这是另一个版本的“划你的船”,听起来更像是一首爵士冷战情歌“来自俄国的爱”:

管弦乐队的陷阱

这首乐曲听起来令人震惊——它以实验性的管弦乐声音开始,残酷而尖锐的尺八或萨克斯管音调,其他乐器加入了不和谐的声音,但随后出现了和声合唱。

如果我没有从 JukeBox Notebook 获得这首音乐,我会认为它是 UbuWeb 音频部分的某首音乐杰作。

现象:在吉米·卡伦接受训练,但在“经典音乐”流派中带来了有趣而独特的结果——训练基地再也认不出来了。混合方面会导致令人惊讶的效果。

如果你想听更多:收听我的每日 #LatentVoices 频道,或者查看我在 Soundcloud 上的#自动点唱机播放列表

或者创作你的音乐并在这里与我们分享。

Julia 负责数据科学

原文:https://towardsdatascience.com/julia-for-data-science-how-to-build-linear-regression-from-scratch-with-julia-6d1521a00611?source=collection_archive---------29-----------------------

在 Julia 中从零开始建立具有梯度下降的多元线性回归

图片来源:朱丽亚话语

目前,Python 和 R 无疑是机器学习领域使用最广泛的编程语言。不幸的是,这些编程的高级和优雅的抽象通常是有代价的,尤其是在处理大型系统时。在我们开始之前,这篇文章不会对 Python 或 R 进行无休止的抨击,所以任何有这种期望的读者都应该去别处看看。相反,这篇文章旨在启发和告知读者 Julia 可能会加入他们的工具箱。归根结底,所有这些编程语言都只是具有不同用例的工具。

朱莉娅到底是什么?

Julia 被描述为一种动态编程语言,它专注于高性能,即使是高级抽象。因此,这种语言非常适合数字和科学计算。2009 年,4 名计算机科学家(其中 3 人的照片如下)共同创造了 Julia。

Juila 图像信用的共同创造者:麻省理工学院新闻

"说话像 Python,走路像 C ."

这一行是最常用的引用之一,总而言之,这是这种编程语言的主要优点。有些读者可能读过关于臭名昭著的“两种语言问题”的报道。对于门外汉来说,这两个语言问题简单地描述了这种情况;

开发人员必须用 C/C++等低级语言重新编写代码库的关键和性能部分,因为 Python/R 等高级语言由于其高级抽象而在某些任务上可能会很慢

在 Python 和 r 等高级语言中,快速构建新想法的原型相对更容易。这些语言在数据科学生态系统中占据如此主导地位的一个主要原因是,数据科学生态系统严重依赖于尽快尝试新想法。这里的折衷(就速度而言)对于中小规模的应用程序来说是可以接受的,但是对于大规模的系统和应用程序来说非常明显。

Julia 被称为可以解决这种双语言问题的语言,它提供了 Python/R 这样的高级语言的友好性,同时匹配 C/C++这样的低级语言的速度。

gif 信用:https://giphy.com

"足够的速度基准,告诉我如何使用它!"

我听说过朱莉娅,但我总是想知道它的用法。有 Python/R 那么简单吗?

这篇文章简单地通过使用 Julia 的梯度下降从零开始构建多元线性回归来测试这个断言。我使用 Python 和 R 已经有几年了,所以我决定看看用 Julia 来快速解决这样的任务有多快。这篇文章不是 Julia 和其他语言之间的基准测试,因为这样的测试已经被很好地覆盖了,而是关注于这种语言对那些习惯于 Python/R 的人的用户友好性。

数据

将用于该测试的数据集是来自 UCI 数据仓库的联合循环发电厂数据集 ( Sheet5 )。这里的目的是生成一个模型,该模型可以根据 4 个数值(连续)特征预测【EP】:

  • 温度(AT)1.81 摄氏度37.11 摄氏度范围内。
  • 排气真空(V)25.36–81.56厘米汞柱范围内。
  • 环境压力(AP)992.89–1033.30毫巴范围内。
  • 相对湿度25.56%到 100.16%的范围内。

建模工作流

这个实验的攻击计划就像一个典型的建模工作流,其中数据将是:

  • 加载到内存:数据以 DataFrame 对象的形式加载到内存中,大多数读者对这段代码已经很熟悉了:

  • 为算法进行预处理:随着数据成功加载到内存中,现在让我们将它分成一个训练和验证集,使用比例 80% 用于模型的训练,保留 20% 用于生成模型的评估。下面的代码片段实现了这个功能(但是更健壮的方法是打乱索引)。我们的目标是快速启动并运行,所以这就足够了。

正如您可能已经注意到的,这些特征处于不同的标度(从百分比到毫巴),这对于大多数算法来说可能是有问题的,因此常见的做法是标准化特征,以便它们可以处于相同的“标度”。下面代码片段中的两个函数用于标准化训练和测试特性。

我们的数据现在已经过预处理,可以进行建模了。

  • 模型拟合&评估:这里的目标是找到一个线性模型,最好地最小化良好的旧均方差函数。我们的均方成本函数本质上是一个半均方函数,其定义如下:

定义好成本函数后,让我们使用梯度下降法为每个特征(包括常数)找到最佳权重,使成本函数最小化。下一个函数负责处理这个问题:

NB :这个实现实现了没有正则化的梯度下降(我鼓励你添加到你自己的实现中)。

现在,让我们通过绘制成本历史向量𝐉:来检查梯度下降是否有效并最小化我们的成本函数

每个时期的成本

从图中可以看出,随着迭代次数的增加,成本下降,直到在某个点持平。看来梯度下降在寻找最小化我们的成本函数的权重方面做得很好。

gif 信用:https://giphy.com

现在是时候做一些预测并评估我们新的闪亮回归模型的性能了。两个新函数用于生成预测并对训练和测试数据集进行评分。

从评分函数来看,训练集和测试集的均方根误差 ( RMSE )为:

**RMSE** for Training Set: **4.578258826855693**
**RMSE** for Testing Set: **4.473104537374325**

现在让我们看看模型在两个数据集中的预测能力(根据 R 平方值),以及该函数:

**Training R²** score for test sets: **0.9274046053983883**
**Testing R²** score for test sets: **0.9335248094191678**

这些分数似乎表明,一些像样的预测能力( 0.927 & 0.934 )!

gif 信用:https://giphy.com/

然而,测试分数优于训练分数,这似乎表明该模型对数据拟合不足。修改阿尔法项( α )和/或迭代次数( n_iter )应该可以从这个模型中挤出更多的性能,但是我将让读者自己去修改。

基于这个朱莉娅实验的好恶

从这个实验中,我基于之前与 Python 和 r 的互动,自然对 Julia 有了一些好恶。

喜欢

  • 本地 Unicode/符号支持:我最喜欢的 Julia 无疑是它对 Unicode 和科学符号的本地支持。在脚本中使用' θ 而不是'θ',使用'α'而不是' alpha ',这很酷也很简洁。这是一种为科学/数字计算而从头开始构建的语言!我发现每次我不得不使用科学记数法时,我都在微笑。
  • 一种语言的语法在它快速将思想原型化的能力中起着关键的作用。Julia 的语法和 Python 没什么区别。就语法而言,Julia 感觉自己是 Python 和 Matlab 之间的私生子。在大多数情况下,我需要快速查找文档,以避开一些糟糕的语法调用。此外,用真正的科学符号分享和阅读科学代码是非常容易的!
  • 对现有 Python/R 生态系统的支持:作为一门年轻的语言,预计生态系统中会缺少一些急需的包。然而,令人耳目一新的是,现有的 Python/R 包可以在 Julia 中使用。这种功能让朱莉娅享受成熟的生态系统的好处,并避免不必要的重新发明某些车轮。

不喜欢

  • 缓慢的预编译时间:与 Python/R 相比,人们注意到的第一件事是在 Julia 中加载包所花费的时间。每次加载包都需要预编译,这确实需要一些明显的时间(超过 10 秒)。对于习惯于即时导入包的 Python/R 用户来说,这可能会令人沮丧。
  • 年轻的语言/生态系统:无论是 Python 还是 r,几乎都有一些常见的数据角力任务的包,Julia 作为一个新人,自然没有老牌语言享有的那么原生丰富的生态系统。然而,这个问题现在可以通过使用 PyCall & JuliaCall 包支持从 Python 和 R 导入来解决。
  • 缺乏传统的 OOP 支持:Python 对于数据科学应用程序的魅力和广泛采用的部分原因是它用面向对象编程构造函数的简洁而方便的方式。例如,如果所有预处理功能以及所有学习到的参数都可以在一个类中获得,那将是非常简洁的。Julia 采用了" 多重分派 "范例,这有助于它比其他高级语言更快。

结论

Julia 是一种很有前途的语言,它是为数字和科学计算而从头开始构建的。在这篇文章中,我已经展示了在 Julia 中建立原型相对容易,并成功实现了使用梯度下降的多元线性回归。这是每一个数据至少应该保持的一种语言,并且是一个数字眼睛。对于 Julia 来说,有一些令人惊讶的数据科学软件包。拿些数据集,和 Julia 玩玩,让我知道你的想法?在我看来,启动并运行的最佳方式是安装使用 Atom 的 IDE 附带的 JuliaPro。

一如既往,我期待着反馈(好的或坏的!).这个博客的 GitHub 库上可以找到这个post 的所有功能的脚本。最后,你可以在我的个人博客上查看其他帖子。直到下一个帖子,祝你在茱莉亚编码愉快!

Julia For Data Science:正则化逻辑回归

原文:https://towardsdatascience.com/julia-for-data-science-regularized-logistic-regression-667857a7f0ce?source=collection_archive---------21-----------------------

如何在 Julia 中从头构建正则化(L2)逻辑回归

图片来源:https://dzone.com/

用于机器学习任务的惊人的库(如 scikit-learn)使得这些天来生成机器学习模型变得非常容易。必须从头开始编写每个模型的日子已经一去不复返了。这是一件好事,我们已经走过了那些时间,因为大多数问题最终都是优化问题。另一方面,这种“符合和预测”文化会对整个领域的学习文化产生严重的长期影响。一些拾荒者正在利用那些半生不熟的"在 30 天内学会数据科学"计划来喂养"人工智能炒作,这些计划经常导致毫无准备的学生在他们的"拟合和预测"模板背后没有真正的直觉。这是我最近关注的这些“从头创建”帖子的主要动机。

这篇文章建立在 第一篇文章的基础上,在第一篇文章中,我们使用我们新发现的爱,Julia,从零开始建立了多元线性回归。因此,我们将尝试在 Julia 中从头构建最著名的分类算法——逻辑回归(带正则化)!在这个实验的最后,结果将与用 Python 实现的 scikit-learn 进行比较。

逻辑回归和正则化背后的直觉

对于不熟悉正则化和逻辑回归内部工作原理的读者,我强烈鼓励这些读者通过观看加州大学伯克利分校的讲座,对正则化逻辑回归如何工作有一个很好的认识。这个讲座解释了内部工作逻辑回归以及正规化的需要。

对于已经熟悉这个主题的读者,让我们直接进入实现代码。

数据

这个实验的数据集是来自 UCI 机器学习库中的 HTRU2 数据集 。本实验的目的是生成一个二元分类器,它可以根据 8 个连续特征预测一颗恒星是否是脉冲星:

  1. 综合轮廓的平均值。
  2. 综合轮廓的标准偏差。
  3. 积分轮廓的过度峰度。
  4. 综合剖面的偏斜度。
  5. DM-SNR 曲线的平均值。
  6. DM-SNR 曲线的标准偏差。
  7. DM-SNR 曲线的过度峰度。
  8. DM-SNR 曲线的偏斜度。

二进制类显示了负类和正类之间的巨大不平衡,具有16259个负样本和1639个正样本,这在大多数分类项目中非常常见。考虑到与该数据集的不平衡,任何模型都必须超过基本精度分数91%(16259/17898)才能被认为是一个像样的模型。这是一个经典的例子,说明了为什么准确性作为一种衡量标准对于存在巨大阶级不平衡的问题毫无意义。

建模工作流

我真的回到了董事会,为一个正则化的逻辑回归构建各种组件。这个练习非常有助于确定以矢量化为重点的优化实施方案。

梯度下降正则化逻辑回归的矢量化实现

在理论实现的涂鸦之后,是通过 Julia 翻译成代码的时候了。

这个实验的攻击计划就像一个典型的建模工作流,其中数据将是:

  • 为算法进行预处理:为了简洁以及关注实现的需要,训练和测试示例(以及标签)被分开保存,以便我们可以专注于建模。对于感兴趣的读者,代码将在 Jupyter 笔记本的结论链接中提供。通过下面的代码片段,将数据加载到内存非常简单:

加载了各种分区之后,让我们将注意力转向实现阶段。

  • 模型拟合&评估:鉴于所有特征都是连续变量,预处理阶段也将相当简单。因此,训练和验证分区都将通过标准化进行规范化,如下所示:

随着特征现在被归一化,让我们为我们的正则化逻辑回归定义"假设"和"成本函数":

这里的目标是找到权重(θ),该权重使上面使用方向梯度定义的正则化成本函数最小化。这个目标是通过这个函数实现的:

如果梯度下降在这个最小化目标上是成功的,那么成本应该在随后的迭代中开始下降。让我们看看这个实验是不是这样:

每次迭代的成本

该图显示了随着迭代次数的增加,成本值的减少,这是实现正在工作的积极迹象!

图片来源:https://giphy.com/

让我们做一些预测,并测试生成的正则化模型的准确性。

注意:对于分类项目,在面临类别不平衡的情况下,准确性可能不是模型评估的稳健指标。准确性作为一个度量标准就足够了,因为重点更多的是在实现上。

**Training score**: 0.9769
**Testing score**: 0.9788

训练和验证准确度分数几乎相同,这有助于减轻对过度拟合/欠拟合的任何担忧。为了更好地理解这个实现的成功或失败,我们将把这些结果与 Python 中令人惊叹的 scikit-learn 的结果进行比较。

  • 与 scikit-learn 实施方案的比较:使用 scikit-learn 的带梯度下降的正则化逻辑回归构建等效管道相当简单,如下所示:
**Train score for SGDClassifier**:  0.9791 
**Test score for SGDClassifier**:  0.9807

有趣的是,结果非常接近,但毫不奇怪,sklearn 的实现在准确性分数方面超过了它。这是一个更加优化的实现,非常聪明的调整!在这篇文章中,我们在 Julia 中使用梯度下降从零开始成功地实现了正则化逻辑回归。

最后的想法

唷!对于少数几个被选中的人来说,我希望你们喜欢这次旅程。我和 Julia 的旅程仍处于起步阶段,这个实验比之前的线性回归实验耗时更长,难度更大。我开始明白茱莉亚是多么喜欢处理矩阵、标量和向量运算( 那些)符号 )。我计划在以后的文章中用这种有趣的编程语言做更多的实验来解包经典和当代的算法。它可能是最终解决了埃隆·马斯克今天所阐述的“双语”问题的语言!

一如既往的期待反馈(好的坏的!).这篇文章的 Jupyter 笔记本可以在这个博客的 GitHub 知识库中找到。最后,你可以在我的个人博客上查看其他帖子。直到下一个帖子,祝你在茱莉亚编码愉快!

游戏开发的朱莉娅——错失的机会

原文:https://towardsdatascience.com/julia-for-game-development-a-missed-oppurtunity-d702b32aef9f?source=collection_archive---------18-----------------------

如果不是因为这个,朱莉娅的一个意想不到的用途可能是非常可行的…

所以最近我一直在尝试并习惯于将游戏开发作为一种爱好。虽然在某种程度上,它肯定类似于编写任何其他软件,但关于所有部分以一种不可思议的方式发挥作用的一些东西让我对编程一个游戏着迷。下面是我录制的一个简短演示,展示我创建的模块化矢量图像数据加载算法,我把它放在 Youtube 上,供感兴趣的人观看:

但是包括 C#、GDscript (Godot)和 C++ (Steamworks API)在内的一系列不同语言的所有这些开发努力让我对我最喜欢的编程语言想了很多:

美丽的,

宏伟的

毕竟,朱莉娅和游戏编程似乎是天作之合。游戏需要基于数据的快速语言。Julia 现在比游戏编程中的脚本之王要快得多。最重要的是,Julia 代码可以快速有效地编写,尤其是与 C++这样的语言相比。

当前的不足之处

有两种主要的语言用于现代游戏开发(在很大程度上),C#和 C++。几十年来,C++一直是推动计算机行业的主导力量,当然也是一门伟大的语言。C++有相当多的领域优势,因为它是面向对象的,而且是鸭子类型的。这与更常用的另一种语言 C#相比,是一个巨大的进步。C#是一种静态类型的高级脚本语言,可以与 Python 这样的语言相比,

虽然这可能会有点困难。

如果你是一个真正的朱利安,你可能已经意识到,我们可以说朱莉娅同样的事情。

Julia 是一种静态类型的高级脚本语言,可以与 Python 这样的语言相提并论

使用 C#最大的缺点可能是它的专有许可。C#是一个奇怪的例子,其中只有某些组件是开源的,而其他组件是隐藏的。另外,不言而喻,C#确实比 Julia 慢。

另一方面,C++对于游戏开发来说可能远远不够。问题?从 C#或 Python 这样的语言跳到 C++可能会让人不舒服。不管什么原因,我在很小的时候就开始学习 C++作为我的第一门编程语言

这确实令人困惑。

现在使用 C++在某种程度上让我感到沮丧,因为我不能像在高级语言中那样快速完成函数,通常需要 30 分钟编程的操作很快就变成了一个小时到一个半小时。当然,这不是 C++的错,但对我来说,当 Julia 能够做我需要做的事情时,使用 C++做任何事情都没有多大意义。

朱莉娅

我认为 Julia 在游戏开发领域最大的优势之一是它惊人的速度。Julia 的语法比 C#简单得多,但运行速度是 c#的 1.5 倍。从 C#到 Julia 实际上也不会有太大的飞跃。Julia 和 C#都是静态类型编程语言,专注于数据和类型调度的不变性。

朱莉娅在游戏方面也有“恰到好处的慢”。Julia 在速度方面的最大障碍可能是预编译和启动时间。虽然这些问题在某些情况下可能很严重,但 Julia 仍然比 C#快,游戏中的启动时间转化为加载时间。简单地观察一下,大部分加载时间都花在移动数据上,而不是加载模块上,我认为可以肯定地说这种担心是没有的。

已经有 Julia 开发者在开发一些非常酷的 Julia 游戏项目,可能会让你大吃一惊。这是一个地图加载器。BSP 映射文件:

[## jayschwa/Quake2.jl

用 Julia 和现代 OpenGL 写的实验性的 Quake 2 地图渲染器。在黑客学校创建的。这是一个玩具,而不是…

github.com](https://github.com/jayschwa/Quake2.jl)

这是一个用 Julia 写的非常简单的桨球克隆体:

[## NHDaly/PaddleBattle.jl

使用该库构建的一个简单的 pong 克隆。这个回购是一个例子,建立一个完整的游戏,编译和…

github.com](https://github.com/NHDaly/PaddleBattle.jl)

除了这些展示之外,我们还拥有在 Julia 内部进行游戏开发所需的足够的工具。例如,SDL2(低级)和 SFML(高级)都有 Julia 端口,绝对值得一试。

箭头指向膝盖

在目前这个时间点上,Julia 的游戏开发有一个显著的缺点。这不仅是游戏开发者的问题,也是软件工程师、编剧甚至数据科学家的问题。

Julia 确实有一个编译可执行文件的工具链,但是它还没有。看起来很多都还在开发中,不一定被 Julia computing 优先考虑。那我怎么想?

我认为,由于其简单的语法和快速的速度,Julia 绝对有潜力超越 C# mono 或 C++这样的语言,但我认为在这成为现实之前,Julia 仍有一定的距离要走。虽然我当然会一直主要关注 Julia 的统计和分析方面,但如果 1.0 中更好的编译可执行文件能够实现,我会非常高兴。据我所知,Julia 编译的可执行文件(我尝试过,但最终的. x64_x86 文件从未运行过)正在为依赖环境保存某种奇怪的系统状态。我想我会把它留在那里,朱莉娅带走了一切;一个包管理器,一门语言,统计编程,只是让它变得更好。我理解为什么在没有本机支持的头文件的情况下实现像编译的可执行文件这样的东西可能是一个真正的挑战。有鉴于此,我会耐心等待,

但是你不能指望我不兴奋!

Julia Oop Vs. Julia Dispatch:谁是速度王?

原文:https://towardsdatascience.com/julia-oop-vs-julia-dispatch-who-is-the-speed-king-ed0fc809d0d1?source=collection_archive---------32-----------------------

这种拙劣的方法能打败朱莉娅稳健的调度吗?

[## 我如何使用面向对象的函数来进行机器学习

我如何以及为什么将面向对象的范例应用于 Julia 机器学习。

towardsdatascience.com](/how-im-using-functional-oop-for-machine-learning-533c1d764628)

在我之前写的一篇文章中,我在 Julia 的机器学习包中取得了相当大的进步,车床,它允许在主要功能的多范例语言 Julia 中进行面向对象的编程。这个概念本身对 Julia 来说是非常独特的,因为构造的类型是在没有返回的情况下创建的,也没有通常用于构造该类型的结构。

不管这个概念有多有用,为了对已经存在了一段时间的软件做出重大改变,我认为测试是很重要的。车床的利基主要是机器学习大师,他们在寻找以下参数:

  • 快的
  • 使用方便
  • 可扩张的
  • 可攀登的
  • 轻量级选手

这些是车床作为一个软件的支柱,任何修改都需要符合这些参数,并超过在一个或另一个参数中失去阵地的成本。在我们研究“新手”之前,让我们先看看车床目前使用的方法,

朱莉娅的派遣

我们拥有的

Julia 的 dispatch 是一种奇妙的方式,它使用一种泛型编程概念将方法作为结构的属性来应用,这种通用编程概念是从函数范式中建立起来的,并包含在 ML 编程语言参数多态性中。Julia 的 dispatch 没有使用典型的函数式方法(方法与存储在类型中的静态数据进行交互),而是本质上应用了一个通用规则,通过方法将流量导向语言本身。

快的

就速度而言,朱莉娅的调度肯定是最慢的。与使用条件或单个函数相比,使用轻量级调度可以使速度翻倍。首先,Julia 是一种考虑到速度而构建的语言,因此非常快,但是,将语言的自然速度与编写良好、调度良好的代码结合起来,可以使 Julia 在竞争中脱颖而出。

使用方便

使用 Lathe 中的当前解决方案,可以通过一个通用方法(predict()方法)轻松地分派类型,如下所示:

using Lathe.models: predict, FourSquare
yhat = predict(FourSquare(trainX,trainy), testX)

再加上内置的?()文档在车床,我相信这是比较直截了当的,易于使用。最重要的是,已经不太需要异常处理了,因为车床是与数据帧绑定在一起的。JL,并使用 Julia 的基类型。这是我在许多语言中见过的问题,包括 Julia,但最常见的是在 Python 中,因为 Python 作为一种统计语言具有可扩展和极简的特性(没有 Numpy 就没有多少线性代数,所以用其他东西构建的包会自动受到限制。)每当我试图通过列表函数传递 Numpy 数组,以及通过各种函数传递 Pandas 系列时,我肯定会遇到问题。

可扩张的

使用 Julia 的调度允许在显式导入时修改车床。我认为这是召唤一个一致的生态系统的巨大好处。与车床无关的包仍然有扩展车床功能的潜力。所有的扩展都可以很容易地使用 Julia 的调度来完成和重新路由,使得扩展车床变得简单明了。

可攀登的

作为一名数据科学家,对我来说最重要的事情之一是构建一些可以扩展到大型应用程序的东西,同时在较小规模的应用程序中也能做得很好。幸运的是,通过大量艰苦的工作,车床模型是可部署的,并且能够用 Genie 完全自动化。自动化的范围可以从再培训和序列化到测试。

轻量级选手

Julia 的调度相对简单,因为它需要三个关键部分:

  • 派单本身(一行)
  • 要分派到的函数
  • 要分派给函数的类型

这是一个相对轻量级的解决方案,因为它不需要带有几个函数的大型类,而是让语言在使用数据进行实际计算方面对结构的属性负责。

已经很不错了

有了车床的所有这些支柱,让 Julia 进行面向对象编程的晦涩技巧有可能胜过 dispatch 吗?使用 dispatch 的最大问题是缺少初始化。缺少初始化意味着没有训练函数,任何计算出的值都需要在再次使用模型之前重新计算,这是很糟糕的。

然而,在很多情况下,这并不重要,因为 Julia 语言可以弥补我们的罪过。每当大型神经网络在车床的新神经网络框架内被训练时,这个问题就会出现。显然,不能在每次需要访问模型时都计算成本,保存值的状态对于缓解这个问题是绝对必要的。

除了能够在初始化时训练模型之外,测试这将对整体进行预测和调度数据以及扩展数据调度和允许数据变异的性能影响也很重要。

所以我们来测试一下吧!

设置

本次测试的开源笔记本

为了测试这种新的函数方法,我决定加载一个数据集,我坐在我的计算机上进行回归性能测试,正式名称为

天气历史. csv

我们可以在 using CSV.jl 中读取这个 CSV 文件:

**using** DataFrames, CSV
df = CSV.read("weatherHistory.csv")

由于 Julia 省略了列的打印,下一步是显示数据框中的每一列,这样我们就可以知道我们可以使用什么特征来预测特定的目标。我们可以使用 show()方法的参数 allcols (bool 类型)来实现这一点,该方法用于显示数据帧,如下所示:

show(df,allcols=true)

因为我们是在进行性能测试,所以我将我选择的两个特性,温度和湿度,分成两列数据帧。这将使查看数据变得更加容易,同时也使数据整体更加清晰。

df = DataFrame(:Temp => df[Symbol("Temperature (C)")], :Humidity => df[:Humidity])

接下来,我决定我的特性和目标,并使用符号通过变量名访问它们(例如,万一我们以后想改变特性):

target = :Temp
Feature = :Humidity

和训练测试分割:

**using** Lathe.preprocess: TrainTestSplit
train, test = TrainTestSplit(df)

现在它就像插入我们刚刚分配的变量一样简单:

trainx = train[Feature]
trainy = train[target]
testx = test[Feature]
testy = test[target]

现在让我们从车床模型中导入我们需要的东西,并预测:

**using** Lathe.models: predict, LinearRegression

现在使用相同的代码,但是采用超结构形式(我以前的文章给出了源代码):

一直以来,在一系列可能让我的 CPU 想提前退休的压力测试中,Julia oop 的表现超过了 Julia 的 dispatch。更令人吃惊的是分配减少了大约 67%(平均 70%(当重复测试时)),计算时间减少了大约 16%(平均 18%(当重复测试时))。

所以没错,确实是高效了很多。

结论

我认为这种新方法显示了很大的可伸缩性,然而,可能只是可扩展性概念中的一个弹孔。没有明确确定的类型,我们会冒方法普遍无法识别结构的风险,并且需要嵌入与类型相关的所有函数,这很不幸。另一个不幸的副作用是遗留代码的死亡。车床已经正式离开了长期的支持,0.0.1 已经从一开始,这是一种悲哀。幸运的是,我确实相信这种进步利大于弊,并且肯定会允许在预测建模的多个领域进行扩展。

一个紧凑的比较:Julia,R 和 Python——2022 年的数据科学

原文:https://towardsdatascience.com/julia-r-and-python-7cd50c2b0fe4?source=collection_archive---------35-----------------------

如果您对数据科学感兴趣,您可能会注意到这三种语言。问题是,你应该选择哪一个,哪一个最有可能是最先进的?让我们比较一下每种语言的 KNN 算法的实现。

我再一次发现自己正处于考虑学习一门新语言或者仅仅是培养我已经知道的知识的过程中。

每年似乎都是“新”语言的一年,似乎关于“数据科学语言”的讨论比以往任何时候都更加强烈。因此,我将快速浏览所有三种语言,Julia、R 和 Python,同时引导您完成一个基本的 KNN 算法

我们将按以下顺序讨论语言(1) Julia,(2) R 和(3) Python。代码 可以在下面找到。

首先,背景调查。从 Julia开始,这种通用的动态语言于 2012 年推出,迎合了每个愿意学习一种完全适合性能密集型任务的新语言的人。像其他两种语言一样,Julia 遵循多种编程范例,所以不管你有什么编程知识,你都有可能很快赶上。

我个人很欣赏可选输入的合理实现,根据你软件的用途,这可能会非常方便。语法有时看起来有点像介于 R 和 Python 之间的混合体,但是一般来说,如果遇到困难,你不会很难找到帮助自己的方法。

虽然 Julia 的目标是通用和高性能,但似乎主要是数据科学社区真正推动了 Julia 的成功。著名用户的名单已经很长了:Nasa、IBM、BlackRock、Pfizer 或纽约联邦储备银行——仅举几个例子。

前方曲折的道路[0]

R 于 1993 年首次发布,它比以往任何时候都更成为统计计算的主要竞争者之一。除了 Julia,R 被发明出来作为科学目的的编程语言。这种语言成功地(imho)击败了各种大型竞争对手,如 IBM 的 SPSS(它有一个类似电子表格的用户界面,因此对许多人来说更容易使用)和 SAS(一个商业分析软件提供商和语言)(使用相同的名称)。r 通常以一种简单明了的方式来完成任务,同时也是一种出色而简单的方式来展示数据。

大约在 R 出现的同时,吉多·范·罗苏姆发明了 Python ,一种通用的、解释的和面向对象的编程语言。随着时间的推移,Python 已经停滞不前,受到了 Ruby 等公司的激烈竞争(尤其是在 web 开发方面——Ruby on Rails ),但最终成为了许多人的首选。在基本库出现之后,Pythons 在数据科学领域的成功在 2000 年代突飞猛进。根据您比较数据的位置,Python 现在是使用最多的两三种语言之一(取决于来源)。Python 很方便,因为它可以用于自动化之类的简单任务,也可以用于大型程序。

出于数据科学的目的,Python 需要通过 Pandas (2008)和 Numpy/Scipy (2005,2001)做好准备,因为独立的语言不会给你提供必要的工具。

浏览网页时,你可能经常读到的一个问题是,一些语言只是附带了[令人困惑的大量的软件包,这可能是一件好事,但也可能增加复杂性,并让语言偏离所用软件包的“通用标准”。如果这对你来说听起来很奇怪,试着在 Python 中找到一个好的 Grubbs 测试,它对离群点的去除很有用。

由于 Julia 是我们的候选人中最年轻的(即使我们考虑 Python 从 2000 年代后期开始的崛起),包的数量不太多(无论如何稳步增长),R 已经很好地建立起来,并带有许多被用作通用标准的包。Python 做了所有的事情,有一些“主要”的库,但是可供选择的选项似乎是无穷无尽的。

现在够了,让我们进入我们的数据——鸢尾花数据集:

Bye,bye head( ) — Julia 的 first(df,n) 函数

为了使以后的事情具有可比性,这里有一个测试数据点及其引用类。这两个将为我们提供一个机会,将一个“类似于现有的”数据点与我们预测的数据点进行比较。

## Our test data point derived from the reference class
## We can assume that the result must be class = 1[7,3,5,1] ~> 1.0

引用类是 IRIS 数据集中的一个数据点:

## Reference class
sepal_length    7.0 -> **7** (0)
sepal_width     3.2 -> **3** (-.2)
petal_length    4.7 -> **5** (+.3)
petal_width     1.4 -> **1** (-.4)
class           1.0 ≈> 1.0 
Name: 50, dtype: float64

朱莉娅开始了。我们将使用 CSV、数据帧统计数据来计算我们的 knn 结果。

显然,重命名列似乎与我们从 R 和 Python 中了解的有很大不同,相比之下,字典非常好用。一个小提示,使用双引号而不是单引号,因为朱莉娅不会处理单引号(伤心!).

此外,请注意重命名!函数后面跟一个感叹号——理由很充分:这个函数修改它的参数!所以在编写自己的函数时要记住这一点。

就个人而言,我更喜欢在这里使用字典,但是因为我们已经使用字典进行映射,所以我通过数据类型 DataFrame 演示了最近邻的收集和计算。虽然导入非常简单,但循环结构让我想起了古代的 Pascal (RIP ),进一步考虑不要在循环中使用大量的换行符。当使用 IJulia 内核时,我遇到了错误,因为有时找不到结束部分。无论如何,我推荐使用 Atom 进行开发。

结果——只是和其他的比较一下:

**Julia:**
[53, 77, 51, 59, 87]Prediction: 1.0

接下来是 R 大放异彩的时候了。在这一点上值得注意的是,就我的专业背景来看,R 仍然是一条路要走——而且这很可能会保持不变。为什么?r 已经被很好地建立,在数量上是广泛的(机器学习,线性代数, ggplot 等)。),可以用于简单的脚本,并且已经在许多公司中使用,比如脸书、谷歌、Twitter、微软、优步等等,这只是其中最著名的几个——令人印象深刻,对吧?[2]

有趣的事实,IBM 加入了 R 财团集团(记得我之前提到 IBM 是和 SPSS 的竞争对手吗?)

根据我的经验,许多大学也教授 R(我有幸两次)。怎么说呢,R 很棒!

r 语法易于阅读,学习起来也很有趣。我欣赏它与其他语言的相似之处,以及在调试时准确的错误消息。由于 R 从早期就受到支持,所以对于开发,您可能会喜欢使用 Atom 或(钟爱的)RStudio。值得一提是,我经常体验到,当涉及到不准确的代码时,R 就不那么宽容了,忘记一个逗号可能会导致一个小时的头痛。学习曲线相当陡峭。

结果——只是为了和其他的比较。注意,像 Julia 但不像 Python,索引从 1 开始。

**R:**
   X.index.....i X.dist.....distance
53            53           0.5291503
77            77           0.5291503
51            51           0.5385165
59            59           0.6480741
87            87           0.6633250Prediction: 1

最后,让我们来看看 Python🐍。

我喜欢 Python 的原因是它的列表理解力、强大的迭代方法和简洁的数据结构。虽然使用各种工具非常有趣,但这可能会使开始和理解变得相当困难。Python 的 ide 有很多,我会选择 Pycharm (这对于标准目的是免费的!=笔记本和 Web 开发)或者 Atom(第三次)。

我们的 knn 算法非常简洁(可能是因为我学习 Python 的时间最长)..),尽管如此,使用 lambda 和 list comprehension 进行排序可能并不是每个人最好的朋友。在这种情况下,我没有使用数据帧,因为我不想导入🐼给你。

结果——只是和其他的比较一下:

**Python:**
[[52, 0.5291502622129179], [76, 0.5291502622129183], [50, 0.5385164807134504], [58, 0.6480740698407865], [86, 0.6633249580710798], [77, 0.7615773105863908]]
Prediction: 1

tldr

Julia——老实说,我真的很喜欢使用 Julia,但是有时候感觉..复杂,不必要的。在下面的例子中,我任意使用了一个字典(在 R 中没有,在 Python 中更方便)和一个 DataFrame 来操作数据。相比之下,使用大多数数据结构非常有趣,而且看起来确实非常快。朱莉娅可能是一种现代的“一种语言适合所有人”的语言。这可能真的是一个爱情故事的开始!

r 就是坚如磐石。它提供了大量的包,非常成熟,并且用它来编码很有趣。由于它的成熟,有很多文档和例子。如果你对数据感兴趣,选择 R 绝对不会错。

Python 很棒,但它还不是性能最好的,它速度快,易于阅读和学习,并且有各种各样的库。在我看来,主要的优势是 Python 可以用于许多不同的目的。 Python 常常如此直观,你会想事情能有多简单

比较 Python 和(另一种通用语言)Julia,很可能有一天会转向 Julia,尤其是不仅仅是为了科学目的——但是时间会证明一切。

一如既往,下次见!注意安全,待在家里。

[0]图片由费迪南德·斯托尔拍摄(谢谢!)—https://unsplash.com/@fellowferdi?utm_source=medium&UTM _ medium = referral

[1]朱莉娅案例研究—https://juliacomputing.com/case-studies/

[2] R 用户—https://www . datasciencecentral . com/profiles/blogs/list-of-companies-using-R

Julia # R # Rlang # Python # Numpy # Pandas # data science # web development # IDE # Google # IBM # Twitter

Julia 可视化库:哪个最好?

原文:https://towardsdatascience.com/julia-visualization-libraries-which-is-best-e4108d3eeaba?source=collection_archive---------11-----------------------

意见

Julia 语言中常用的可视化库概述

(图片由作者提供)

介绍

Julia 编程语言是一种相对年轻的、新兴的科学和数值计算语言。虽然根据我的经验,Julia 客观上更快,主观上更有乐趣,但它的生态系统是短视的。Julia 的生态系统相对不成熟,主要当然是因为 Julia 是如此年轻的语言。也就是说,朱莉娅的生态系统正在快速进化。

在任何数据科学体系中,最重要的软件包之一是数据可视化软件。虽然 Julia 可能没有像 Bokeh 和 Plot.ly 这样最现代和最完善的 Python 库,但它在数据可视化方面确实有一些相对强大的选项。然而,对于新用户来说,这个新的生态系统可能有点令人生畏,并且很难选择正确的软件包。

我的偏好(前言)

关于图形库和一般的模块,我想解释的一件事是,有时有主观和客观的原因,人们可能更喜欢使用一个而不是另一个。也就是说,虽然这篇文章将主要关注客观点,但我的偏好肯定会在某个时候出现。

在 Julia 的三大数据可视化包中,有许多完全不同的方法在起作用。有时候,某些方法可能会被一些人喜欢,而被另一些人讨厌。说完这些,下面是我的结论和对当今三个最大的 Julia 语言绘图库的比较。

Plots.jl

(图片由作者提供)

Plots.jl 是一个包,可以作为一个高级 API,用于处理几个不同的绘图后端。这包括 GR,Matplotlib。Pyplot,最后是 Plot.ly。该软件包主要用于 Julia 生态系统还不成熟,无法支持纯 Julian 图形架构的时候。话虽如此,但现在情况已经不同了——所以就可用性而言,我当然不会推荐 Plots.jl。

Plots.jl 的第一个也是最明显的缺陷是它本质上是其他软件的接口。有些软件还依赖 PyCall.jl,这意味着 Pyplot 和 Plot.ly 可视化的运行速度要比 Julian 软件包慢得多。此外,PyCall.jl 实际上比使用 Python 本身要慢,因此将 Plots.jl 与 Julia 一起使用,而不是将 Plot.ly 或 Pyplot 与 Python 一起使用,这为 Python 实现提供了客观优势。

这个包的另一个大问题是绝对荒谬的 JIT 预编译时间。这是一个问题的原因,因为需要编译三个不同的包,其中没有一个是本地的 Julia,模块才能工作。

另一方面,Plots.jl 的一个优点是它的可靠性和简单性。事实上,它依赖于古老的后端,这意味着这个包很少被破坏。Plots.jl 包也相对简单易用,尤其是使用默认的 GR 后端。如果你想学习更多关于使用 Plots.jl 的 GR 后端的知识,我在这里有一个完整的教程:

[## 在 Julia 中美化您的 GR 可视化

没错,又是 Julia,我保证 R,Scala,Python 还在这个爱情圈里

towardsdatascience.com](/spruce-up-your-gr-visualizations-in-julia-88a964450a7)

牛虻. jl

(图片由作者提供)

在某种程度上,牛虻. jl 是朱莉娅对 Plot.ly 的回答。从主观上来说,牛虻是该语言中我最喜欢的可视化库,但从客观上来说,与其他竞争模块相比,它也非常棒。牛虻通过 Javascript 集成产生了漂亮的交互式可视化效果,这是这个列表中的任何其他可视化软件包都无法真正感受到的概念。

牛虻也是用纯朱丽亚写的。与 Plots.jl 相比,牛虻预编译只需要几毫秒,并且可以在很短的时间内完成可视化。

虽然《牛虻》在这个列表中是我最喜欢的,但它也有一些明显的缺陷。首先,它不一定是最多样化的包。在可视化中很难得到你想要的确切的东西,因为用牛虻很难从头开始构建东西。也就是说,这个问题主要是 Javascript 实现的结果,并且主要是在与更静态的解决方案进行比较时才会感觉到。如果你想了解更多关于牛虻的信息,我这里有一整篇文章:

[## 牛虻. JL——来自你梦中的纯朱莉娅绘图库

看看朱莉娅对 2020 年统计绘图的最佳选择

towardsdatascience.com](/gadfly-jl-the-pure-julia-plotting-library-from-your-dreams-3ee6ca107a5c)

VegaLite.jl

(图片由作者提供)

另一个为 Julia 准备的很棒的可视化软件包是 VegaLite.jl,VegaLite 可以被认为是对 Python 的 Seaborn 之类的东西的 Julian 回应。与牛虻类似,Julian VegaLite 实现是用纯 Julia 编写的。VegaLite 的伟大之处在于它的包容性和令人难以置信的活力。

虽然 VegaLite 可能没有牛虻的交互性,但它肯定是一个非常棒的可视化库,可以令人难以置信地定制。VegaLite 和牛虻之间的一个显著区别是 VegaLite 由组合在一起形成组合物的模块化部分组成。因此,VegaLite 是一个更加多样化的套餐,有很多选择。

结论

尽管 Julia 在过去没有最好的图形库实现,但很明显这正在迅速改变。不仅有新的纯朱利安选项可供使用,但他们也是相当神奇的选择。这三个中我最喜欢的通常是牛虻。这是因为我喜欢交互式可视化。牛虻的方法也非常简单,这使得用最少的努力就可以很容易地建立和运行一些可视化。也就是说,对于数据分析的深度可视化,VegaLite 可能是 Julia 程序员的最佳选择之一。

JuliaHub:将包和文档放在一起的最好方法

原文:https://towardsdatascience.com/juliahub-the-greatest-approach-to-putting-together-packages-and-documentation-707688a472d2?source=collection_archive---------55-----------------------

JuliaHub 如何自动化所有程序员讨厌做的事情。

(图片由作者提供)

Julia 编程语言是一种年轻的、崭露头角的语言,它采用出色的方法来解决现代编程中的问题。首先,这种语言非常灵活,而且这种语言自带的所有标准软件背后都添加了非常强大的方法论,这使得这种语言变得更加流畅。这种想法可以在很多方面感受到,例如 Julia 对虚拟环境和依赖关系的抢先方法,这使得管理项目语言中的依赖关系变得轻而易举,而不管团队的规模如何。

Julia computing 的一个相当新的前沿功能是新的 Julia Hub 网站,它仍处于测试阶段。如果你想看看这个网站的现状,你可以点击这里查看:

[## JuliaHub

编辑描述

juliahub.com](https://juliahub.com/ui/Home)

每当注册一个 Julia 包时,将包添加到 Julia General registry 的 pull 请求是完全自动化的,由 Registrator.jl bot 完成,这已经非常方便了。每当软件包被添加到 Julia General registry 时,它们也被添加到可从 JuliaHub 网站访问的数据块中。

包搜索

有时候很难找到很棒的软件包来做特定的工作。JuliaHub 用自己的包浏览器解决了这个老问题,它允许用户按名称、学科或功能浏览包。这使得发现新的和令人兴奋的技术变得容易,并使终身学习者保持警觉,等待他们可能遇到的下一个令人敬畏的图书馆。

此外,从软件包的页面上,您可以找到更多关于它的信息!例如,您可以阅读描述,访问 Github 页面,甚至查看文档。更进一步,您可以对特定项目、贡献者、README.md,甚至依赖于它的其他包的所有依赖关系进行概述。只要看看 JuliaHub 上的车床. jl 页面就知道了:

(图片由作者提供)

不用说,这太棒了!能够在一个地方访问所有这些信息非常方便。作为一名程序员,您可能需要的唯一其他东西是您正在查看的包的文档。

等等。

(图片由作者提供)

证明文件

在过去,我曾经谈到过 Documenter.jl,它是一个 Julia 包,可以从代码中提取文档字符串,并将其放入漂亮的 HTML5 模板中,这些模板是可部署的、可搜索的,并且是完全自动创建的。如果您想了解更多关于 Documenter.jl 的内容以及如何使用它,您可以在这里查看那篇文章:

[## 如何用 Documenter.jl 自动化 Julia 文档

没有文档,软件是没有用的,所以用 Documenter.jl 把文档的痛苦去掉吧

towardsdatascience.com](/how-to-automate-julia-documentation-with-documenter-jl-21a44d4a188f)

这种自动化文档在 JuliaHub 网站上采用了一种全新而出色的方法。没错,Documenter 基于 web 的文档是自动生成的,甚至更好——由 JuliaHub 免费托管。这是一个革命性的想法,用一种语言为每个库创建一致的、自动化的和简单的文档,所有这些都可以在一个地方容易地获得。不再需要搜索来找到你需要的文档,现在你可以在一个地方以完全相同的格式找到它们!

结论

JuliaHub 是一种有趣且吸引人的方法,可以解决当今文档和包信息的许多问题。尽管 JuliaHub 可能还处于测试阶段,相对来说还不成熟,但很明显,它正在成为开发人员和有抱负的软件工程师的一个很好的工具。不仅如此,通过舒适地将每个软件包上的信息方便地放在一个地方,这无疑使开发新软件变得更加容易。

自从我开始使用 JuliaHub,我也发现自己拿起包裹的速度很快。像 JuliaHub 这样一个简单而包容的环境,提供了一个近乎完美的环境来促进探索和学习——这是我非常欣赏的,因为我是一个知识迷——尤其是在计算机和其他领域;朱莉娅。

Julia 关于名称空间的大问题

原文:https://towardsdatascience.com/julias-big-problem-with-namespace-996d2e9ed71e?source=collection_archive---------17-----------------------

作为一名 Julia 开发者,这是一个可能会影响你的重大问题。

(图片由作者提供)

背景

J ulia 是一种现代而年轻的编程语言,自 2018 年 8 月发布 1.0 版本以来,它一直在科学计算界掀起风暴。尽管 Julia 作为一种语言有大量对开发人员有用的奇妙属性,如多态性、极其动态的语法和类型,但由于 Julia 是一种如此年轻且相对复杂的语言,所以很容易理解为什么编程语言会出现一些问题。

为了理解为什么 Julia 不擅长处理命名冲突,我们需要看看 Julian 模块是如何工作的。首先,模块的标准标识符是“module”,所以我们可以创建一个类似这样的模块:

module fizz
    function buzz(foo)
        return(foo)
    endend

这将使一个叫做 fizz 的模块具有一个小时候叫做 buzz 的功能。我们可以通过以下任何一种方式访问 buzz:

using fizzfizz.buzz(foo)using fizz: buzzbuzz(foo)import fizzfizz.buzz(foo)import fizz: buzzbuzz.foo

每当我们进口 buzz 而不含 fizz 时,我们使用的是所谓的直接进口。这意味着我们将只使用这个特定的函数,模块的其余部分不会加载到我们的环境中。这是防止命名冲突的一个很好的方法,因为如果我们只需要来自不同模块的特定方法或结构,那么我们可以相应地获取它们。还应注意“进口”和“使用”之间的区别。每当我们使用“导入”时,我们都是显式地导入模块、函数或类型。这意味着我们计划对它进行扩展。例如,我可以有这样一个调度方法:

module fizz
    buzz(foo::Int64) = add_5(foo)
    buzz(foo::Bool) = negate(foo)
end

然后显式导入它并为更多类型提供操作:

function add_10(foo)
    return(foo + 10)
endimport fizz: buzzbuzz(foo::Float64) = add_10(foo)

当然,这将使得如果一个 float 被用于这个方法,我们将调用我的新 add_10 函数,它被用 dispatch 路由到这个函数。

通常,这些命名约定不容易发生冲突。在直接导入时,我们不太可能会遇到问题,如果我们在冲突出现时没有意识到冲突,这种情况肯定不会发生。然而,您可能会遇到的问题是,大多数 Julia 模块完全遵循函数范式。这意味着它们可能会在导出之上使用导出——这将危及您的个人命名约定。考虑以下模块:

module fizz
    buzz(foo::Int64) = add_5(foo)
    buzz(foo::Bool) = negate(foo) export buzz
end

导出参数的不同之处在于,现在只要导入模块 fizz,我们就可以直接访问 buzz。请注意,这是大多数 Julia 包的典型约定。

using fizzbuzz(foo)

记住这一点,考虑两个流行的 Julia 模块:

牛虻. jl 和剧情. jl

这两个都是使用 plot()方法的图形库。虽然它们仍然采用完全不同的参数,但这些都是常规函数,而不是调度操作。另一个需要注意的重要事情是,它们都采用了许多关键字参数,这在 dispatch 中几乎是不可能的。这两个方法都是导出的,这意味着每当我们导入它们时,我们毫无疑问会遇到命名冲突。如果我们使用直接的约定,比如使用Plots: plot ,这可能是不正确的,但是如果我们想一前一后地使用两个包,这仍然是一个问题。

另外,如果你想了解更多关于这两个图形库的知识,我写了一些很好的文章,你可以在这两个库上查阅!:

[## 牛虻. JL——来自你梦中的纯朱莉娅绘图库

看看朱莉娅对 2020 年统计绘图的最佳选择

towardsdatascience.com](/gadfly-jl-the-pure-julia-plotting-library-from-your-dreams-3ee6ca107a5c) [## 在 Julia 中美化您的 GR 可视化

没错,又是 Julia,我保证 R,Scala,Python 还在这个爱情圈里

towardsdatascience.com](/spruce-up-your-gr-visualizations-in-julia-88a964450a7)

截至 1.5.1 的补救措施

W 虽然作为一门语言,这个问题很难解决,但现在 Julia 中有一些东西可以帮助解决这个问题。首先,在处理命名冲突时,dispatch 将会是一个很好的朋友,它有可能帮助您解决在 Julia 语言中可能遇到的大多数命名问题。然而,正如我在上面提到的,分派带有大量关键字参数的方法是相当困难的,有时甚至是不可能的。因此,尽管派遣可能是避免冲突的较好方法之一,但它肯定不是避免上述冲突的万无一失的方法。

考虑如何避免编程语言中的命名冲突的一个很好的方法是环顾四周,看看其他编程语言是如何避免冲突的。在很多方面与 Julia 非常相似的语言的一个很好的例子当然是 Python。Python 使用可由用户定义的别名来非常有效地避免命名冲突。然而,当我们在 Julia 中查看这个相同的概念时,我们看到虽然别名是可能的,但它仍然不能使我们绕过名称冲突:

**import** Queryverse 
**const** qv = Queryverse

虽然这似乎是一个解决方案,但问题仍然存在,因为您已经定义了 Queryverse 及其所有导出的标识符,它们将与以相同名称进入您的环境的新标识符冲突。在这方面,我们可能得到的最接近的方法是显式导入一个特定的方法或类型,然后设置一个与该类型相等的常数。

除了这两个相当简单且不太有用的解决方案之外,真的没有太多的可能来避免命名冲突,就像 Julia 语言中的瘟疫一样。至少据我所知,这两个是预防的最佳选择,但如果你已经在试图解决这个问题,它们不会让你脱离困境。

来自 C++的解决方案

伴随着一些开发人员可能会遇到的这个严重问题,出现了一个非常好的解决方案,Julia 语言有可能从 C++继承过来。C++使用了一个叫做名字间隔的概念,它允许我们总是指示我们想要使用哪个模块,甚至在任何特定的场景中我们想要使用模块的哪个部分。考虑一下 C++中 STD 的例子:

#include <iostream>int main()
{
std::cout <<< 0
}

STD 是名称空间,cout 是包含在名称空间中的函数。这些都包含在我们放在顶部的包中。对于代码中需要调用 cout 的每一点,我们都会调用 std::cout,而不仅仅是 cout。这意味着,如果我们有一个来自不同名称空间的新标识符,比如 foo::cout,我们仍然可以以完全相同的方式使用那个函数。此外,我们还可以在命名空间上调用 using,使对象或函数在全局和局部范围内都可用:

#include <iostream>using std::cout // <- Global Scope
int main()
{using std::cout //<- Local Scope
cout <<< 0 //<- Notice we don't need to use the namespace
}

我认为这将为 Julia 中的 include()方法增加一些扩展的可用性。而不仅仅是能够包含。JL 文件,我们也可以用模块名来调度它。这使得在 Julia 代码中根据它们所在的模块创建名字空间成为可能。Include 可被视为名称空间语法,而 using 仍以其一贯的方式使用。以下是一些理论代码的示例:

include(Gadfly)
using PlotsGadfly::plot(x, y) #< -- This would use Gadfly
plot(x, y) #< -- This would use plots

当前的解决方案

虽然这些关于语言迁移的理论上的建议可能对 Julia 的未来迭代有意义,但重要的是要考虑开发人员现在可能拥有的选项——在 Julia 库之外。这种可取之处当然是以模块的形式出现,这可能有助于避免 Julia 语言中的命名冲突。为此,考虑使用别名避免冲突的 Pythonic 示例。请允许我介绍

ImportMacros.jl

[## fredrikekre/ImportMacros.jl

提供两个宏:@import 和@using,用于加载模块或对象并将其绑定到别名。@导入可以用…

github.com](https://github.com/fredrikekre/ImportMacros.jl)

jl 允许在加载导出之前使用宏创建 Pythonic 别名语法。如果我们在这种情况下使用 Import 宏,我们可以避免在当前范围内定义模块。虽然这不一定适用于导出(因此也不是最好的解决方案),但是您仍然可以直接调用导出,并相应地为它们起别名。尽管这种解决方案可能不是最好的长期解决方案,但在开发或构想出更好的解决方案时,它可能会让您摆脱困境。

结论

Julia 编程语言做了很多非常棒的事情。虽然这种语言很棒,提供了很多有些人可能从来没有想过的东西,但它也带来了一些问题。重要的是要记住,Julia 作为一种语言是非常年轻的,开源社区每天都在开发它。因此,这种语言肯定会在未来得到改进和发展,但肯定会不时出现问题。

我真的很想看看 C++对名字间距的处理方式,看看如何在 Julia 中解决这个问题会很有趣。就解决方案而言,它可能是最连贯的解决方案之一,也不会改变 1.5.1 中语言核心的功能。

不管怎样,Julia 语言是一个不断扩展和引人入胜的东西,我认为它绝对值得一试。感谢您的阅读,我希望至少这些概念是有趣的!

朱莉娅最令人敬畏的特征

原文:https://towardsdatascience.com/julias-most-awesome-features-be51f798f140?source=collection_archive---------20-----------------------

Julia 编程语言中我最喜欢的五个特性。

(茱莉亚 logo src =http://julialang.org,茱莉亚格普 logo src =https://github.com/JuliaGPU)

编程语言的范围包括编程概念和范例。许多语言利用它们的范例以及有趣的泛型编程概念来创建特性,以区别于其他语言。然而,这些特性通常范围有限,有时使用频率不够高,甚至没有存在的理由。

Julia 编程语言是一个有趣的例子,因为与大多数语言不同,Julia 有一些致命的定义特性,这些特性使它能够做各种你可能想不到的事情。虽然 Julia 语言使用了一大堆奇妙的特性,但这是我认为最有用和最吸引人的五个特性。

№1:宏

尽管宏对于编程来说肯定不是一个新概念,但它们在 Julia 中的实现是相当独特的,而且在我看来做得相当好。宏是可以用来快速有效地访问函数的“快捷方式”,在处理 Julia 语言的函数应用程序时非常有用。在 Julia 中,只需使用“macro”就可以定义一个宏。

macro add(num1,num2)
   num1 + num2 
end

我们可以通过在宏名前添加@符号来使用宏。参数可以添加空格,不需要括号或逗号!

№2:调度

如果您熟悉 Julia 语言,并且相对地使用过它,那么您很可能熟悉 Julia 的高性能调度。使用 Julia 中的语法表达式,我们可以创建不同的函数,这些函数使用参数多态以相同的方法处理不同的类型。为此,我们只需使用等号运算符。

exampledispatch(x::Int64) = _int(x)
exampledispatch(x::Float64) = _float(x)

关于 Julia 的调度,你可能没有注意到一个惊人的副作用,那就是所有的 Julia 函数都可以在任何类型上通用。考虑这个例子:

我想创建一个类型,它使用 push 函数将数据添加到包含在结构中的数组中。

用力!()函数是 Julia 基础的一部分,而在大多数其他语言中,为了避免冲突,我们需要为我们的模块编写一个全新的标识符。使用该语言附带的标准库时尤其如此。但是,在 Julia 中,我们可以只发送 push!()处理我们的类型:

push!(data,x::Type{ihavedatainme}) = _pushdata(data,x)

№3:语法表达

甚至一些 Julia 程序员可能没有意识到这一点,但是语法表达式负责我们如何编写 Julia 代码背后的整个方法。本质上,使用语法表达式,我们可以设置任何表达式或变量等于任何表达式或变量。这也是 dispatch 的工作方式,因为我们所做的只是将一个方法的特定参数类型设置为对应的方法。

然而,除了分派之外,我们还可以通过多种方式使用语法表达式。例如,我们可以将一个方法设置为一个表达式:

如果你想学习更多关于语法表达式的知识,并学习一些很酷的方法,我这里有一篇关于它们的文章:

[## 语法表达超赞!

利用朱莉娅语法的力量来断言任何事情。

towardsdatascience.com](/syntactical-expressions-are-awesome-dc9ba5f25911)

№4:元编程

Julia 以一种非常有趣的方式处理像元编程这样的概念。元编程和类似概念的包通常是分段的,但仍然包含在 Julia 的库中。这使得 Julia 的 base 在预编译时花费的时间少得多,同时仍然加载了令人敬畏的特性。为了在 Julia 中进行元编程,您应该从 Meta.parse()和 eval()这两个函数开始。Eval 包含在 Julia 核心中,不需要导入,而 Meta 是包含在 Base 中的一个模块。

using Base.Meta

评估元表达式的第一步是解析它。这将把一个常规字符串转换成 eval()能够处理的表达式类型。

meta_code = "1 + 1"

expression = Meta.parse(meta_code)

№5:并行计算

(src =https://github.com/JuliaGPU

好的,我明白了…并行计算本身并不一定是一个“特性”,但是 Julia 的并行计算令人印象深刻的是 Julia Computing 在这方面做了多么了不起的工作。与许多其他语言不同,Julia 自带了大量的 GPU 支持。核心的 Julia 语言支持图形数组和处理,这是你在其他地方无法得到的。将并行计算紧密集成到 Julia 中,并使用专门设计的类型和函数来处理它,比在大多数语言中(这是事后才想到的)要强大得多。此外,Julia 拥有各种用于并行计算的优秀包,以及 CUDA 和 OpenCL 等行业标准。

结论

Julia 编程语言有一大堆令人难以置信的特性,这些特性绝对让使用这种语言物有所值。有了所有独特的解决问题的方法,很少有时候你不能用这种语言创造性地完成一些事情。除此之外,Julia 还拥有它通常所拥有的所有优势。这些是我最喜欢的,但是我也想知道其他程序员喜欢这种语言的什么。(想分享就留言评论吧!)

朱莉娅的包装经理棒极了

原文:https://towardsdatascience.com/julias-package-manager-is-awesome-23b9c02e3a0b?source=collection_archive---------28-----------------------

为什么 Julia 的 Pkg 是我用过的最好的软件包管理器。

(http://julia-lang.org/和达塔沃基)

在过去的中,我对令人惊叹的多范例统计语言 Julia 赞不绝口。这是有充分理由的,因为 Julia 是一种令人难以置信的高级语言,它扩展了我们认为可能来自这种高级语法的限制。此外,就机器学习的理想性而言,从我使用四大的次数来看,Julia 完全能够超越 Python、R 甚至 Scala。我甚至开玩笑说要在我的头上纹一个朱莉娅的纹身,甚至要对那个东西进行半真实的渲染:

看起来很棒,不是吗?

但是对于我一直以来最喜欢的编程语言之一的炫耀,我忽略了一个让 Julia 变得更好的特性:

包装

Pkg 是 Julia 的包管理器,它不是 Python 或 r 中常见的那种典型的包管理器。事实上,在大多数情况下,我坚信 Julia 的包管理器胜过我用过的所有 Linux 包管理器,包括 Dnf、Apt、Man,可能还有最健壮的:Pacman。有几个关键的好处使得用 Pkg 包管理器管理 Julia 中的包变得轻而易举,你可能会说

“它能做到吗?”在某个时候。

REPL 和包裹

Pkg 的一个巨大好处是它有自己的读取评估打印循环,或 REPL。这是有益的,原因有几个,首先我想提到的是,它可以比库等价物更快地添加包。这是因为它可以简单地通过按键完全跳过重新编译陈旧的缓存文件,

]

此外,这允许非语法的包添加,使得只需一个命令和一个空格就可以超级快速和容易地添加包:

add "Lathe"

然而,除了有一个 REPL,Julia 的 Pkg 也以 Julia 包本身的形式出现。这很有用,因为这意味着您不仅可以从 REPL 中添加包,还可以添加代码本身。每当我创建 TopLoader 时,这就特别有用,这是一个 Python 包,允许你创建一个虚拟的 Pkg 环境,然后使用添加到该环境中的包。

Github 集成

(src = http://github.com/)

Julia 的包管理器完全基于 Github,包被推送到 Registrator.jl 库,你可以在这里看一下

(src =https://github.com/JuliaRegistries/Registrator.jl

这不仅使得通过 Github 推送您的 Julia 包变得非常容易,还允许您添加带有 Git URLs 的未注册包。这使得通常存储在 Git 兼容的存储库中的未发布的软件总是可用的。Julia 的包使用 Github 作为开发的基础,这当然不是一个坏主意,因为即使是非开发人员也很清楚开源开发本质上是围绕 Github 进行的。

虚拟环境

生活中有许多问题尚未得到解答,但一个古老的问题是

“谁的环保做得最好?”

肯定已经有答案了。与 Pip、Package get、Quick Lisp 和数以千计的其他软件包管理器(也称为“Pkg”)相比,Julia 的 Pkg 再次在竞争中脱颖而出。从一开始,您就可以通过 REPL 的两个简单命令或软件包中的一个方法来激活虚拟环境。

using Pkg
Pkg.activate("venv")julia> ]
pkg> activate "venv"

这使得管理和利用这些虚拟环境变得异常简单。如果不与 Julia 的竞争对手之一 Python 的类似选项进行比较,很难证明这种激活虚拟环境的方法是正确的。Python 的包管理器是 Pip,虽然肯定不如 Pkg 健壮,但我认为 Pip 肯定经得起时间的考验,并在 Python 中完成了工作。但是要为 Pip 激活一个虚拟环境,你需要安装一个全新的包,就是 venv,或者类似的东西(有几个不同的选项。)

sudo pip3 install virtualenv
python3 
python3 -m venv venvname

这当然并不可怕,但是从另一方面来说:肯定没有 Julia 等价类那么健壮和简单。重申一下我的 Python 包,它用于在虚拟环境中加载 Julia 模块,开发这个包非常容易,因为我能够使用 activate()方法。

结论

我喜欢 Julia 的 Pkg,我向那些努力开发它的开发人员致敬,他们只是为了让 Julia 的编程体验变得更好。我认为许多其他的包管理器有很多东西要向 Pkg 学习,因为对我个人来说,它一直感觉像是完美的包管理器。我鼓励您尝试一下,因为它感觉像是充斥着 CLI 软件包管理器的世界中的一股新鲜空气。总的来说,我认为 Pkg.jl 为 Julia 做出了很大的贡献,并且使这种语言变得更加有趣。

七月版:嘿 Siri,我是什么意思?

原文:https://towardsdatascience.com/july-edition-hey-siri-what-do-i-mean-4d39db978637?source=collection_archive---------47-----------------------

月刊

自然语言处理与人工智能的未来

照片由埃琳娜·克里玛派克斯拍摄

到目前为止,我们中的许多人已经与设备的内置助手进行了交互。可能是故意的,甚至是说“你是认真的吗?”离 iPhone 太近了。无论是 Alexa,Siri,还是你喜欢的智能设备中的任何人;它使用自然语言处理(NLP)结合语音识别来理解你,为你的问题提供适当的答案,有时甚至进行学习。但是 NLP 到底是什么?很简单,它是一台试图解析、构建和总结文本的机器,就像人类“自然”会做的那样说话或写作。NLP 为许多人经常使用的人工智能提供了实际用途。

那么,它是如何工作的呢?NLP 成功的关键在于深度和递归神经网络。深度神经网络(DNN)和递归神经网络(RNNs)使用数万个单词和句子进行训练,以便在对它尚未看到的短语进行测试时最准确地预测反应。你可以在这里阅读更多关于深度神经网络。与许多机器学习算法一样,DNNs 和 RNNs 在用于预测时也有其缺陷。例如,当你想输入“我要一个奶油奶酪百吉饼”时,你的手机可能会建议你喜欢奶油苍蝇百吉饼或类似于奶酪的按键。随着 NLP 的改进,这些预测也会随之改进。

不管你是在使用智能助理、自动电话菜单,还是只是尝试输入信息,NLP 都被用在我们每天做的许多事情中。

想了解更多关于自然语言处理的知识吗?以下是我们关于这个主题的一些最受欢迎的文章!

索菲·曼,编辑助理

自然语言处理实践指南(上)——处理&理解文本

由迪潘詹(DJ)萨卡尔 — 31 分钟阅读

经过验证和测试的解决 NLP 任务的实践策略

如何用深度学习为任意对象创建自然语言语义搜索

哈默尔侯赛因 & 吴和祥 — 13 分钟读完

这是一个端到端的例子,展示了如何构建一个可以在语义上搜索对象的系统。

用 Python 进行模糊字符串匹配的自然语言处理

苏珊李 — 5 分钟读完

当我们比较不同网站的酒店房价时,我们必须确保我们是在进行比较

文本自然语言处理简介

文茨斯拉夫·约尔达诺夫 — 16 分钟阅读

读完这篇博客后,你会知道一些从一些文本中提取特征的基本技术,所以你可以使用这些特征作为机器学习模型的输入。

您的自然语言处理(NLP)指南

由迭戈·洛佩兹伊塞 — 13 分钟阅读

机器如何处理和理解人类语言

自然语言处理:从基础到使用 RNN 和 LSTM

vibhor nigam — 11 分钟阅读

对自然语言处理领域中流行的所有概念的详细介绍

德雷克——用自然语言处理理解他的歌词

布兰登·彭图罗 — 8 分钟读完

我们知道德雷克的作品很受欢迎,但为什么他的大多数歌曲如此受欢迎呢?是制作的原因吗?是市场营销吗?

新视频

新播客

我们也感谢最近加入我们的所有伟大的新作家 K .德尔菲诺迪夫扬舒·马尔瓦卢克·瓦瑟因内克·马亚契塔陈琦程斯科特·罗戈夫斯基多·李吉伊斯·范·登·多尔米尔科·萨瓦斯塔克莱尔·萨尔 保罗·斯图布莱维多利亚·张马切伊·德·科尔泽克卡兰·普拉哈拉杰阿普茹瓦·乔希埃洛德·帕尔·奇尔马兹伊恩·何乌古尔·厄塔斯约翰·麦卡利斯特等众多。 我们邀请你看看他们的简介,看看他们的工作。

六月版:机器中的偏见

原文:https://towardsdatascience.com/june-edition-bias-in-the-machine-994eadbccec2?source=collection_archive---------60-----------------------

人工智能和机器学习模型中的公平性、偏见和可解释性

照片由岩田良治Unsplash 上拍摄

随着机器学习应用变得越来越广泛,人们对实现算法来转变通常的业务流程以实现效率产生了极大的兴趣。从贷款审批司法判决,消费者和公民面对黑箱模式的现实,成为我们生活中一些最重要决策和事件背后的最终仲裁者。理解我们创建的模型中的偏见和公平问题,并确保它们不会产生意想不到的和/或歧视性的结果,变得比以往任何时候都更加重要。

在数据科学中,机器学习偏见没有得到很好的解决,甚至没有得到很好的理解。但研究人员和其他从业者已经采取措施,强调减少偏见来源并找到解决方案以防止由此造成的伤害的重要性。下面的文章是我们关于偏见、公平和可解释性的最佳故事精选。我们希望它们能丰富您的理解,并在您遇到自己的模型中的偏差时作为最佳实践的资源。

《走向数据科学》的编辑埃利奥特·冈恩。

什么是 AI 偏见?

凯西·科济尔科夫(Cassie Kozyrkov)—4 分钟阅读

人工智能偏见问题始于定义,但并未结束。“偏见”是一个被过度使用的术语,在不同的上下文中,它的意思是非常不同的。

用合成数据减少 AI 偏差

亚历山大·沃森 — 5 分钟阅读

生成人工记录以平衡有偏差的数据集并提高整体模型准确性

解释公平的措施

斯科特伦德伯格 — 11 分钟阅读

通过将现代可解释的人工智能方法应用于公平测量,避免机器学习中公平度量的黑盒使用。

可解释的机器学习

通过 Parul Pandey — 10 分钟阅读

从任何机器学习模型中提取人类可理解的见解

可解释机器学习指南

马修·斯图尔特博士研究员——28 分钟阅读

破除深度学习黑箱神话的技术。

可解读人工智能或者说我是如何学会了不再担心和信任人工智能

由 Ajay Thampi — 13 分钟阅读

构建健壮、公正的人工智能应用的技术

算法偏差的算法解决方案:技术指南

Joyce Xu — 16 min 阅读

我想谈谈减轻算法偏差的技术方法。

新论文:塑造行为的激励机制

瑞安·凯里和埃里克·朗罗伊

因果模型如何描述代理人的动机。

新视频

新播客

我们也感谢最近加入我们的所有伟大的新作家让-马蒂厄·舍尔策拉维·查兰阿图尔·尤尔加斯阿尤什·塔库尔布兰登·洛克哈特迈克尔·达茨马特·马切耶斯基舒尼特·哈威夫·哈基米君特·罗赫里 塞巴斯蒂安·沙尔詹卢卡·金德罗阿克塞尔·泰韦诺马特·布里顿弗洛里安·韦特肖雷克托马斯·汐宫光·克拉克克里斯多夫·吕克蒲进以及许多其他人。 我们邀请你看看他们的简介,看看他们的工作。

朱诺让朱莉娅写作变得很棒

原文:https://towardsdatascience.com/juno-makes-writing-julia-awesome-f3e1baf92ea9?source=collection_archive---------20-----------------------

用于 Julia 的基于原子的 IDE

(http://junolab.org)

除非你一直生活在岩石下,或者根本不为计算机编程,否则你很可能听说过 Atom。Atom 是一个简单、可扩展、漂亮的开源文本编辑器,可以在 Linux、Windows 和 MacOS 上使用。应该注意的是,Atom 本身并不是一个集成开发环境,而仅仅是一个文本编辑器。

Atom 对我来说是一个很棒的文本编辑器,因为它很现代,看起来很好,而且高度可扩展和可调整。Atom 提供了为替代语言应用主题、扩展和语法突出显示所需的所有工具,这些工具都内置在它们的 UI 中,并由免费和开源开发人员开发的扩展库提供服务。在方法论上,这与 Linux 的发布方式非常相似,所以这确实是我的拿手好戏。Atom 在没有任何扩展的情况下,对于所有语言都有很高的终端窗口能力,但是通常安装扩展会突出语法。然而,在 Juno 中,我们得到的不仅仅是简单的语法突出显示。

(http://julialang.org/)

J ulia 是一种高级的、多范例的统计语言。Julia 也是开源的,与 r 等其他统计语言相比有很多优势。虽然 Julia 大部分是函数式的,但与 Lisp 一样,它也可以用于通用目的。Julia 是一种拥有如此高级语法的相对快速的语言。速度通常稍慢,但在某些情况下实际上可以超过 C。当然,这是非常罕见的情况,这种观察有许多变量,因为它是在使用 IPython magic timers 的 Jupyter 内核中测试的,但即使接近 C 的速度也使 Julia 比 R 和 Python 更有优势。此外,Julia 拥有出色的浮点精度,这也让 Julia 领先于 Scala。

Julia 可以成为你的“大数据”语言

(http://junolab.org/

原子+朱丽亚拼图的最后一块是朱诺。Juno 把 Atom 这个简单的文本编辑器改造成了 Julia 的全功能 IDE,真的太牛逼了!Juno 具有许多特性,这些特性使 Julia 成为我在 Atom 内部编写的最令人愉快的语言。

取代

Juno 拥有许多其他扩展所没有的东西:

REPL

您可以通过 Atom 访问 Julia 的 Read Evaluate Print 循环(REPL ),从而方便地包含和编译您的程序。随着朱莉娅 With 的加入,朱莉娅变得非常强大,甚至对于常规软件开发也是如此。

远程过程

您不仅可以通过常规的 REPL 处理 Julia,还可以启动与 Julia 交互的远程进程。这是一个非常棒的特性,因为它将 Atom for Julia 变成了一个现代的 IDE,而不仅仅是一个带有输出窗口的简单 IDE。

格式化

Juno 还附带了一个完全自动化的格式化工具,该工具完全可以通过 Atom 内部的菜单栏来访问。这很有用,因为它创建了一个一致的代码风格,所有 Julia 用户都可以与之交互和阅读,但仍然允许您最初以自己的风格编写 Julia。

运行块

我非常喜欢 Juno 的另一个特性是运行 Julia 块的能力。这可以使体验与 REPL 高度互动,使 Julia 编程体验更像在笔记本内工作。

设置

Juno 设置的包容性令人惊讶。从“设置”菜单中,您可以调整路径、线程数和 Julia 引导模式。Julia 引导模式是一个概念,在这个概念中,您可以让您的 ide 根据您使用的是远程 Julia、集成终端还是外部终端来设置单独的运行时,甚至可以设置一个循环模式来保持所有三个 Julia 进程始终运行,以便加快 IDE 内部的运行速度。另一个很酷的特色是优化级别,虽然优化是拼写

最佳化

在设置中。

优化允许您选择,无论是永久地还是暂时地,您希望编译有多快,以及您希望您的代码有多快。当然,这也非常有用,尽管我不怎么用它,因为我在 Julia 中工作时一般不会遇到性能问题。Julia 中性能最差的部分是过时的缓存文件重新编译,它:

在部署中不是问题。

虽然使用 Genie 确实会使服务器启动时间有点慢,但通常“有点慢”只是大约一分钟。

打开包裹

Juno 还允许您在新窗口中立即打开任何安装了 Pkg 的软件包,让您轻松地根据自己的喜好调整软件包。对于该特定功能,我唯一想做的更改是在没有 REPL 的情况下使虚拟环境更易于管理,这可能与该功能有关。但这并不是说首先很难从 REPL 激活虚拟环境。用 Pkg 激活一个环境只需要 3 个命令,包括]和初始化 Julia。

或者,你也可以

using Pkg;Pkg.activate("dev")

原子底部的 REPL 内部。

文档浏览器

Juno 的另一个很酷的特性是能够从 Atom UI 中快速查找文档。这当然不是什么新鲜事,因为 Julia 在处理文档方面做得非常好。对于大多数包,使用?()函数将打印出所述包的文档——使得访问文档网站成为一种不同语言要处理的事情。

结论

我真的很喜欢并感谢大家为 Atom 在 Juno 上付出的努力。我每天都使用 Atom 作为我的文本编辑器,还有 Gedit 和 Nano,在我实际使用的文本编辑器中,我最喜欢的语言得到如此多的关注真是太棒了。我也很高兴他们决定在 Atom 上支持 Julia,而不是构建他们自己的 IDE。这不仅需要更多的资源,还需要在热键和设置方面的新的学习体验,需要处理的新的用户界面,以及回收的文本编辑应用程序的额外磁盘空间。总的来说,我对 Juno 的结果非常满意,尤其是它让 Julia 的开发变得如此容易!

Juno vs . Jupyter——Julia 的开发环境哪个更好?

原文:https://towardsdatascience.com/juno-vs-jupyter-which-is-the-better-development-environment-for-julia-19e26b36403d?source=collection_archive---------28-----------------------

意见

比较我在数据科学中最常用的两个 ide。

(I Julia logo src =https://github.com/JuliaLang/IJulia.jl,Juno logo src =https://junolab.org/)

影响编程效率的最重要因素之一是您的开发环境。对于数据科学来说尤其如此,因为数据科学家更经常需要在执行作为应用程序一部分的任何代码之前分析和处理数据。拥有一个适合你的好的设置意味着在一小时或一整天内完成一件事的区别。

通常,在讨论 Julia IDE 的数据科学时,有两个主要选择:

伊茱莉亚和朱诺。

伊朱丽亚

IJulia 是 Julia 的 Jupyter 内核,可以用 Pkg 添加:

Pkg.add("IJulia")

优势

Jupyter 笔记本电脑具有许多优于 Juno 的优势。首先,细胞水平的执行棒极了。使用单元格,您可以选择何时运行哪个代码,甚至可以避免运行某些单元格来获得某个结果。此外,Jupyter 输出相当方便,易于处理。

使用笔记本的另一个好处是可以使用 IJulia 的“神奇”命令。虽然这些在技术上并不是“神奇的”命令,而是从 IJulia 导出的 Julia 函数,但它们确实是紧急情况下手头上的一个好东西。最重要的是,使用宏来运行 bash 命令要比困在 REPL 中,像在 Juno 中一样打开第二个终端窗口好得多。

然而,在我看来,使用笔记本电脑的最大优势之一可能是

再现性。

笔记本是教学和传播信息的好工具。如果能够为带有解释的大块文本添加标记单元格,就更是如此。这就是为什么我通常使用笔记本来演示我在 Medium 上的文章中的想法和代码,尽管主观上我更喜欢使用 Juno。

不足之处

在 Jupyter 内核中调试软件包可能非常困难,因为每当需要从 Jupyter 内核中重新加载软件包时,内核都需要重新启动,所有代码都需要重新执行。

与运行一个简单的 Julia 可执行文件相比,内核也是相当费力的。这不仅会导致性能下降,而且在使用 Jupyter 笔记本电脑时,多任务处理也会变得相当困难。最重要的是,杀死一个内核比超时一个 REPL 要容易得多,所以总是有可能遇到不先去 REPL 就无法执行的代码。

使用 Jupyter 的最后一个缺点是你的代码会被保存在笔记本里。虽然这既是一种祝福,也是一种诅咒,但任何不使用笔记本的人都可以感受到这种诅咒。对于任何不从事数据科学的人来说,笔记本可能是一个完全陌生的概念,这意味着您的代码无法到达更多的受众,同时也相当有限,直到它被复制到一个独立的 JL 文件中,或者保存为一个文件。

朱诺

Juno 是 Julia 的集成开发环境,可以作为 Atom 文本编辑器的扩展添加。您可以添加 Julia,方法是进入 Atom 菜单栏中的编辑>首选项,然后选择扩展并搜索“Juno”

优势

拥有一个朱莉娅·REPL 是一个非常强大的工具。使用朱莉娅·REPL,你还可以访问 Pkg REPL,这比导入 Pkg,预编译 Pkg,然后使用 Pkg 方法要方便得多。此外,由于更加关注本地文件系统,管理虚拟环境和。jl 文件变得容易多了。

Juno 的另一大优势是“Plots”窗格。“Plots”窗格从 Julia 获取任何图像输出,并将其放入 iframe 中。这非常方便,因为您可以实时缩放图形。此外,当前会话中使用的所有图都保存在此窗格中,使浏览数据可视化变得毫不费力。

Juno 的另一个优点是启动新会话非常容易。正如我在使用 IJulia 的缺点中提到的,不断地重启内核是非常乏味和烦人的。使用 Juno,您可以通过按 ctrl+D 快速重启 Julia 会话,并出现中断异常。

在 Juno 中,您还可以使用“Documentation Browser”窗格,它提供了一个灵活的 UI 来搜索所有添加的包的 Julia 文档。

另一个很酷的功能是自动格式化。在 Juno 中,您可以随时通过单击 Juno >格式化代码来突出显示和格式化您的代码。最重要的是,您可以执行单个代码块,这使得利用包含 Julia 代码的文本缓冲区变得非常方便。

锦上添花的是,您还可以从 Juno 内部启动远程 Julia 进程。

不足之处

虽然这对我来说肯定不是一个缺点——因为我喜欢 Atom,而且它是我的首选文本编辑器,但那些喜欢 VSCode 或其他替代产品的人可能会觉得使用 Juno 需要 Atom 有点烦人。我可以肯定地看到,对于那些以前没有使用过 Atom 的人来说,Atom 可能需要一些时间来适应。

让我们面对现实吧——在 REPL 中输入函数远不如在文本缓冲区中输入函数方便。虽然把你所有的功能都输入朱莉娅 cell 肯定是可能的,但这肯定比把它们输入一个 Jupyter 单元格要慢。此外,您将失去复制和粘贴的能力。您可以通过将函数放入 Atom 文本缓冲区内的. jl 文件来缓解这个问题,但是每次添加或修改函数时,您都必须包含()或重新运行文件。

结论

Jupyter 和 Juno 都是不可思议的工具,在很多方面,他们都有不足和进步。我希望朱诺拥有朱庇特拥有的许多东西,朱庇特拥有的许多东西我也希望朱诺拥有。总的来说,我不认为这是一个“什么”的问题,而是一个“什么时候”的问题。我认为有些情况下 Juno 是更好的选择,有些情况下 Jupyter 是更好的选择。就我个人而言,我更喜欢使用 Juno,因为它具有惊人的多功能性。在 Jupyter 中开发软件包相当困难,但是在 Juno 中进行数据分析却非常有效。然而,这并不是说我不愿意使用 Jupyter 进行数据分析,而相应地使用 Juno 进行软件包分析,事实上,我通常就是这么做的。

显然,Jupyter 在我的信息性文章中对我也非常有用。首先演示,其次分享我的作品会困难得多。jl 文件和 REPL 会议。Jupyter 最大的缺点可能是死内核,Juno 最大的缺点可能是可重复性。总的来说,在很多方面,我认为你使用的工具可能与你想要做的事情密切相关。

朱庇特和马克登

原文:https://towardsdatascience.com/jupyter-and-markdown-cbc1f0ea6406?source=collection_archive---------11-----------------------

无论您是与朋友和同事分享您的 Jupyter 笔记本,还是更广泛地发布它们,如果它们布局合理、格式正确,将会更受欢迎。

作者图片

您可以在 Jupyter 笔记本代码中添加注释,以帮助读者了解您在做什么。但是较长的注释最好放在与代码分开的文本单元格中。

Jupyter 中的文本单元格支持 Markdown 语言,我们将看看它提供的功能。Markdown 是一组简单的标记代码,可以很容易地转换成 HTML 以便在浏览器中呈现。Markdown 远没有 HTML 那么复杂,但是对于记录一个笔记本来说已经足够了(尽管如果你需要对外观或布局有更多的控制,也可以嵌入 HTML)。

这篇文章最初是用 Markdown 写的(本文末尾有原文的链接),第一段和两个标题是这样的:

# Jupyter and Markdown
## Making your Notebooks look good
Whether you are sharing your Jupyter Notebooks with friends and colleagues or publishing them more widely, they will be better appreciated if they are well laid out and formatted.

很简单。#位于相当于 HTML 中的

的标题之前,其中两个表示二级标题

。#符号越多,标题越小。

因此,下面的 Markdown 代码将显示一个标题列表,其大小逐渐减小。

# heading 1
## heading 2
### heading 3
#### heading 4
##### heading 5
###### heading 6

作者图片

Markdown 支持最常见的样式,如粗体和斜体,您可以构造带编号和不带编号的列表。您可以在段落中嵌入代码或显示完整的代码块。包括超链接,你也可以插入图像。表格可以用非常简单的语法用左对齐和右对齐的列来构造。

Markdown 忽略单行分隔符,因此要分隔段落,需要插入两个换行符。

下面我们来看一些降价代码的例子。对于每个示例,我将向您展示 Markdown 代码,然后按照它呈现后的样子进行操作。

内嵌标记—代码,粗体和斜体

首先,我们来看看一些简单的内联标记。

下面是代码,下面是渲染版本:

This is a paragraph that illustrates some of the Markdown features.
This is a new paragraph that includes some code: `print(123)` you can see that it is enclosed in single back ticks. Other simple markup is *italic which is enclosed in asterisks* and **bold which is enclosed in double asterisks**.

作者图片

您可以使用单下划线或双下划线将文本变为斜体或粗体。所以,通过混合下划线和星号,你可以得到既斜体又

You can also use an _underscore to make things italic_, or two of them for __bold__. This means you can have both _**italic and bold**_ text.

作者图片

大宗报价

块引号前面有一个 v 形符号。

> To include a block quote you precede it with a `>`

作者图片

代码块

如果要包含代码块,请使用三个反斜杠或~字符将代码括起来,如下所示:

~~~python
for i in (1,2,3):
   print(i)
~~~

或者这个

```python
for i in (1,2,3):
   print(i)

你会得到一段代码,可能是彩色编码的:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/458712e911433f3377fe30cdb0984201.png)

作者图片

请注意,使用编程语言这个名称是可选的,尽管它不是 Markdown 规范的一部分,但大多数渲染器中都包含了颜色编码。

# 列表

有序列表和无序列表都有。无序列表中的项目前面有一个星号、减号或加号:

  • item
  • item
  • item

这看起来像

*   项目
*   项目
*   项目

子列表只是缩进一个空格:

  • item
  • item
  • item
  • item

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2dec6c2ad2244e0093a93f2efd037c45.png)

作者图片

编号列表以一个数字开始,后面跟着一个点,你猜对了。你可以混合搭配有序列表、无序列表和子列表。

1. item
2. item
3. item

  • item
  • item
    4. item

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/62511ad3eeac1fe59ec90860a500e161.png)

作者图片

# 形象

图像通过其路径或 URI 来引用。要包含一个图像,该行以一个感叹号开始,后跟一对方括号,用于放置 alt-text,然后是一对大括号,包含图像路径和一个字符串,当您将鼠标悬停在图像上时会显示该字符串。

![alt_text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png “Markdown Logo”)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3086ae34991ab7a3d39c71e7f11cf861.png)

图片由亚当·普里查德提供

# 链接

链接看起来与图像相似,只是方括号中的文本是实际的链接文本。

Here is a link to [Google’s](https://www.google.com “Google’s Homepage”) home page.


其呈现为:

这里有一个到谷歌主页的链接。

# 桌子

在表格中,各列用管道字符(|)分隔,标题后是一行破折号,然后其余的数据逐行排列,如下所示:

Col1 Col2 Col3
Data1 Data2 Data3
Data1 Data2 Data3
Data1 Data2 Data3
Data1 Data2 Data3

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6330c3b9e68cc96f1f37f86b388674e3.png)

作者图片

您也可以通过在标题下划线中放置冒号来对齐列。右边的冒号表示右对齐,左边的冒号表示左对齐,两边各有一个冒号居中。这里有一个例子:

Left aligned column Centered column Right aligned column
Bold data Italic data Normal data

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2d73259146f4deb2acdac91016f504c2.png)

作者图片

正如您所看到的,表格中的条目可以加粗或斜体。

代码的布局不一定要整洁,Markdown 会整理出来。上表的这个乱七八糟的版本被渲染的一模一样。

Left aligned column Centered column Right aligned column
Bold data Italic data Normal data

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/55c90df3247d8b11e18a42e90f6a8c71.png)

作者图片

# 嵌入式 HTML

如果 Markdown 不完全符合您的要求,您可以添加任何您想要的 HTML。

Here’s a bit of Markdown text. Can you see the difference between
Markdown bold and HTML bold?No, you can’t because it’s the same!


这是一小段降价文字。你能看出 **Markdown bold** 和 **HTML bold** 的区别吗?

不,你不能,因为这是一样的!

# 水平线

最后是一条水平线。只需在一行上单独键入三个破折号



(媒体编辑器里没有横线但是我相信你可以想象出一条!)

# 你还想要什么

我认为这足以让你的笔记本成为吸引人的可读文档。

由于 Medium 不支持 Markdown 可以做的所有事情,我在很大程度上依赖于图像。但是,如果你想看这款笔记本的原始版本,你可以查看或下载,点击[这里](https://github.com/alanjones2/Article-code/blob/master/markdownref.ipynb)。

如果您想了解未来的文章,请订阅我的免费 Technofile 简讯[。](https://technofile.substack.com)

# FlashBlade 上的 Jupyter 服务

> 原文:<https://towardsdatascience.com/jupyter-as-a-service-on-flashblade-3c9ec27f8fcf?source=collection_archive---------42----------------------->

## 如何管理大规模数据科学家的开发环境?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/52a1cfe59adcb7fbe0772c45508c4fae.png)

戴维·梅尼德雷在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片

Jupyter 笔记本是数据科学家探索数据集和进行模型开发实验的绝佳工具。它们使开发人员能够轻松地用分析和可视化来补充代码。

与让用户管理他们自己的笔记本服务器的传统做法不同, [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) 可以由一个组织来部署,以提供一个集中的笔记本平台。JupyterHub 还支持基础设施团队为每个用户提供对集中存储的访问:共享数据集、暂存空间和持久 IDE。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7e620faa2b1228659b25e4ac2140b78f.png)

这篇博文展示了一个在[纯存储闪存](https://www.purestorage.com/products/flashblade.html)上部署 Jupyter-as-a-Service 的例子。用户可以在 Kubernetes 集群中通过零接触配置动态创建新的笔记本电脑服务器。IT 团队能够跨用户管理计算和存储资源的高效使用。

# 朱庇特枢纽

JupyterHub 用于管理和代理“单用户”Jupyter 笔记本服务器的多个实例。它在您的网络上提供了一个公共 HTTP 代理,因此用户可以从他们的浏览器登录到一个中央登录页面。一旦用户登录,JupyterHub 就会为该用户启动一个服务器(pod)。它会重新连接到该用户的永久存储。因此,用户可以拥有有状态的开发环境,但是计算节点仅在需要时使用。

我们将把 JupyterHub 部署为 Kubernetes 服务,这样它就可以作为集群的一部分轻松管理。

# Kubernetes 环境中的 FlashBlade

出于几个原因,FlashBlade 是 JupyterHub 的优秀存储后端。

首先,它支持就地访问训练数据集,消除了在节点之间复制数据集的需要。数据科学家可以使用共享数据集,通过最少的数据管理来执行模型的训练和测试。

第二,FlashBlade 支持 Pure 的 CSI 驱动,[Pure Service Orchestrator(PSO)](https://www.purestorage.com/pure-folio/showcase.html?item=/type/pdf/subtype/doc/path//content/dam/purestorage/pdf/datasheets/ps_ds_pure-service-orchestrator_01.pdf)。PSO 完全自动化 Kubernetes 集群中应用程序的[持久卷](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) (PV)的创建和管理,通过消除新用户的手动存储管理,为 JupyterHub 部署带来自助服务。

JupyterHub 只是众多应用程序中的一个,它们共同为数据科学家形成了一个完整的人工智能平台。为了简化管理和高效的数据管理,所有这些应用程序都应该由相同的集中式存储提供支持。

移除存储筒仓。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/818cadd589c93bf62c0e51b388522fbb.png)

# 装置

## 准备步骤

*   克隆我们的 [AI 平台回购](https://github.com/PureStorage-OpenConnect/ai-platform)
*   在您的本地机器上,确保您的集群配置对于 kubectl 是活动的。
*   在您的本地机器上,安装[舵](https://helm.sh/docs/intro/quickstart/)和用于 PSO 的舵回复[和用于 JupyterHub](https://github.com/purestorage/helm-charts) 的[:](https://github.com/jupyterhub/helm-chart)

helm repo add pure https://purestorage.github.io/helm-chartshelm repo add jupyterhub https://jupyterhub.github.io/helm-chart/


*   群集中的每个节点都需要能够访问 FlashBlade 上的数据集。在`/datasets`将数据集文件夹直接挂载到每个集群节点。

## 部署 PSO

**定制:**您需要一个描述您的 FlashBlade 阵列的 psovalues.yaml 文件。最简单的方法是复制我们默认的[。/psovalues.yaml](https://github.com/purestorage/helm-charts/blob/master/pure-csi/values.yaml) 并调整“数组”部分。

定制示例:

arrays:
FlashBlades:
- MgmtEndPoint: "10.61.169.20" # CHANGE
APIToken: "T-c4925090-c9bf-4033-8537-d24ee5669135" # CHANGE
NFSEndPoint: "10.61.169.30" # CHANGE


**安装:**

`helm install pure-storage-driver pure/pure-csi — namespace jhub -f ./psovalues.yaml`

## 为共享数据集部署 PV

**定制:**

的。/datasetpv.yaml 文件用于创建名为“shared-ai-datasets”的[持久卷声明](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims)。调整 datasetpv.yaml 以使用您的 FlashBlade 数据 VIP 和文件系统名称。

nfs:
server: 10.61.169.100 # CHANGE to your data vip
path: /datasets # CHANGE to your filesystem name


**安装:**

`kubectl create -f datasetpv.yaml`

## 部署 JupyterHub

**自定义:**

jupvalues.yaml 文件唯一需要的更改是添加一个安全令牌。生成随机十六进制字符串:

`openssl rand -hex 32`

复制输出,在 jupvalues.yaml 文件中,用生成的字符串替换 SECRET_TOKEN 短语:

proxy:
secretToken: 'SECRET_TOKEN' # CHANGE to 32-digit secret token


**安装:**

`helm install jhub jupyterhub/jupyterhub — namespace jhub — version 0.8.2 -f jupyterhub/values.yaml`

# 用 Jupyter 笔记本!

JupyterHub 现在可以使用了。

安装 JupyterHub 会创建一个代理服务,为最终用户提供流量服务。公共地址(proxy-public)可以通过以下方式找到:

kubectl --namespace=jhub get svc proxy-publicNAME TYPE CLUSTER-IP EXTERNAL-IP
proxy-public LoadBalancer 10.43.197.255. 10.61.169.60


当用户导航到 proxy-public 的外部 IP 地址时,他们将看到 JupyterHub 登录屏幕:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bd9341096672ae867f2866fee0e72e14.png)

当 Victor 登录时,他可以访问共享数据集(如 cifar10 和 openimages)以及个人笔记本、绘图和文件的主目录。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8b57e635a82b0d506f418e7b7c0e4360.png)

# 结论

在 Kubernetes 集群内将 JupyterHub 作为服务运行很容易部署和管理。数据科学家不仅拥有支持其个人环境的持久存储,还可以访问所有共享数据集,而无需耗时的数据复制或复杂的数据管理。

我们的代码在 github 上:【https://github.com/PureStorage-OpenConnect/ai-platform 

尝试这些快速安装步骤,并让我们知道进展如何。

# 从本地到生产的 Jupyter 部署模型

> 原文:<https://towardsdatascience.com/jupyter-deployment-models-from-local-to-production-196da0353dbf?source=collection_archive---------27----------------------->

## 你现在处于哪个阶段?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9e68ffc18492e08d1cf329adaa9360c3.png)

凯文·杰瑞特在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

对于我们这样的书呆子来说,我们的数据分析习惯并不会随着我们合上笔记本电脑而停止。当你坐在数不清的会议上进行无休止的谈话时,你可能已经有了一些认识。对我来说,事实是从我的会议座位上可以看到 90%的开放屏幕显示 Jupyter 笔记本正在运行。

对于我们中的许多人来说,我们的笔记本服务器只是通过`jupyter notebook`或`jupyter notebook --allow-root --no-browser --port=8885`启动的,如果我们喜欢并强行解决我们不想解决的权限和端口问题。

这种方法的科学时间是明确的,但我想快速描绘一些先进的,可扩展的 Jupyter 部署和一些介于`jupyter notebook`和魔法之间的中级水平。

希望你能感觉到什么是可能的。

# 模型 1:在您的笔记本电脑(Mac)上运行 JupyterLab

*(谁在看这个帖子却没有 Mac?)*

如果你只是想增强你的基本 Jupyter 体验,或者你只是想开始,我建议从这里开始。尤其是当你的数据集和实验只存在你的笔记本电脑上的时候。

JupyterLab 是 Jupyter 的一个 web 界面,它允许比传统的“树”视图更广泛的导航和灵活性,如果你启动 vanilla Jupyter,你就会看到它。JupyterLab 让你可以像浏览器一样在多个标签页中工作。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1ff90cc1c235cbf5508d547beda659e9.png)

[JupyterLab](https://jupyterlab.readthedocs.io/en/stable/getting_started/overview.html) 提供了比传统的单一窗格“树”视图更丰富的开发体验。

直接从 mac 终端在 JupyterLab 自己的 [conda 环境](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html)中运行 JupyterLab:

**先决条件:** [安装康达](https://docs.conda.io/projects/conda/en/latest/user-guide/install/macos.html)。
[Conda](https://docs.conda.io/projects/conda/en/latest/index.html) 使您能够轻松管理软件包和环境,以便您可以在笔记本电脑(或另一台机器)上使用不同的库组合。这是一个非常简单的方法来安装所有你想尝试的有趣的新库。

**从你 Mac 终端运行 JupyterLab:** -
-步骤 1:创建一个新的“JupyterLab”conda 环境
`conda create -n jupyterlab ipython jupyterlab python nodejs` -步骤 2:切换到那个新环境
`source activate jupyterlab` -步骤 3:启动 JupyterLab
`jupyter lab`

该命令将自动启动一个浏览器窗口,但是每次您导航到 http://localhost:8888 时,您将获得您的实验室 UI。

服务器将一直运行,直到您手动关闭它(使用 CTRL-C)或关闭终端窗口。关于开始 JupyterLab 的进一步阅读是[这里](https://jupyterlab.readthedocs.io/en/stable/getting_started/starting.html)。

**看中:** 雅各布·汤姆林森[的这篇](https://twitter.com/_jacobtomlinson)[伟大的文章](https://www.jacobtomlinson.co.uk/posts/2019/how-to-run-jupyter-lab-at-startup-on-macos/)讲述了如何在电脑启动时自动启动 JupyterLab。

# 模型 2:在数据集所在的远程服务器上运行 JupyterLab

也许你听说过“数据科学是导致 Excel 崩溃的任何东西”的说法,接下来的阶段是不适合笔记本电脑的任何东西。随着实验规模的扩大,你可能会遇到这两种情况

*   您的笔记本电脑计算能力不足
*   您的笔记本电脑存储空间不足

无论哪种方式,解决方案都可能是从您的开发运维/IT 团队那里获得一个强大的开发服务器。这个开发服务器将被托管在一个你永远看不到的实验室里。你只要远程访问它。

或者可能仅仅是 Covid 期间的 WFH 让你在通常直接工作的机器上远程工作。

在远程机器上启动 Jupyter 的挑战是访问 UI。

## 场景 A:在你和远程机器之间没有防火墙

将`--ip`参数添加到 jupyter 启动命令中。它设置笔记本服务器监听的 IP 地址(默认值=“localhost”)。

`jupyter notebook --ip=<remote server IP address> --port=8888`

在您的笔记本电脑浏览器中,您可以直接连接到 http:// <remote server="" ip="" address="">:8888/服务器,而不是导航到 http://localhost:8888/。</remote>

**想象一下:** 每次你打开笔记本电脑的时候,你会在你的远程主机上重启你的 Jupyter 吗?

你可以使用一个[终端复用器](https://en.wikipedia.org/wiki/Terminal_multiplexer),比如 [tmux](https://github.com/tmux/tmux/wiki) 或者 [screen](https://www.gnu.org/software/screen/) 来分离你的远程主机上的会话。这样,会话就不依赖于来自本地主机的连接。

*关于 tmux 和 screen 的比较,可以看看这个* [*StackExchange 帖子*](https://unix.stackexchange.com/questions/549/tmux-vs-gnu-screen) *,但是正如标题警告所说,这是一个基于观点的问题。*

## 场景 B:您的笔记本电脑服务器运行在防火墙后的某个地方,比如公共云中。

说明因云供应商而异(见下文),但总体步骤如下:

1.  从远程服务器中启动 jupyter
2.  从您的本地机器,配置端口转发。

**端口转发?** 当你启动一个 Jupyter 服务器时,默认情况下,GUI 被托管在****机器上的一个端口**上,在那里服务器被启动**。在这个场景中,[端口转发](https://en.wikipedia.org/wiki/Port_forwarding)告诉您的本地机器接收特定本地端口的任何流量,并将其转发到远程机器上的端口。(*延伸阅读:* [*你 CS 教育的缺失学期*](https://missing.csail.mit.edu/2019/remote-machines/) *)*****

****供应商特定说明:****

**AWS
-官方文档:[为 AWS 深度学习 AMI](https://docs.aws.amazon.com/dlami/latest/devguide/setup-jupyter.html) 设置 Jupyter
-[用户示例](/setting-up-and-using-jupyter-notebooks-on-aws-61a9648db6c5)**

**GCP
-官方文档:[连接到深度学习虚拟机映像的 JupyterLab](https://cloud.google.com/ai-platform/deep-learning-vm/docs/jupyter)
-[用户示例](/running-jupyter-notebook-in-google-cloud-platform-in-15-min-61e16da34d52)(包括更改实例的防火墙设置作为端口转发的替代方案)**

**Azure
-官方文档:[在 Azure 机器学习开发环境](https://docs.microsoft.com/en-us/azure/machine-learning/how-to-configure-environment#jupyter)中配置 Jupyter(使用 [Azure 笔记本](https://notebooks.azure.com/#)作为服务器)**

# **模型 3:在 Kubernetes 集群中运行 JupyterHub,为多个开发人员提供持久的开发环境。**

**这是我的梦想。**

**如果您使用以前的笔记本部署方法之一,**

*   **每次回到电脑前,您需要多长时间才能启动笔记本电脑?**
*   **你能探索多大的数据集?**
*   **你备份你的笔记本吗?**

**如果有人为您提供了一个可靠的开发环境,可以通过浏览器**始终可用**,并且可以访问共享数据集和共享笔记本,会怎么样?(而且,正如 IT 团队可能关心的那样:它是安全的,可跨数十或数百个用户进行管理。)**

**虽然这需要更多的配置——可能由了解您的网络设置的人来执行—[JupyterHub](https://jupyter.org/hub)可能是为整个团队托管自助服务环境的一种很好的方式。**

**JuyterHub 服务持续运行,为用户提供基于浏览器的登录。当用户登录时,会为他们启动一个 Jupyter 服务器,它会自动连接到 a)他们以前登录的个人数据和 b)他们需要试验的任何共享数据集。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/51d1b250983c0e943d9ae661a0e572a4.png)**

**JupyterHub 环境的用户可以快速、持久地访问大型共享数据集和他们自己的私人实验文件夹。**

**这种部署意味着用户不必在服务器之间复制数据,他们可以随时获得高可用性的开发环境,并且他们的实验易于备份和共享。**

**我之前曾[发布过](/jupyter-as-a-service-on-flashblade-3c9ec27f8fcf)关于 IT 团队如何在 Kubernetes 环境中部署 JupyterHub 的详细步骤。我在这里简单总结一下。**

**有 Kubernetes 集群吗?**

****是的,我们今天用 Kubernetes:****

*   **为您的存储服务器安装 [csi 驱动程序](https://kubernetes-csi.github.io/docs/introduction.html)。CSI 驱动程序在后台运行,使 Kubernetes 能够直接使用存储,因此用户可以以完全自动化的自助方式访问数据。**
*   **"[导入](https://github.com/purestorage/helm-charts/blob/master/docs/csi-volume-import.md)"将您的共享数据集 TBs 作为 Kubernetes 卷,这允许您将该数据作为 Kubernetes 集群中的资源进行管理。**
*   **通过头盔部署 [JupyterHub。如果您需要一个示例 JupyterHub values.yaml 文件来进行配置,请随意使用](https://github.com/jupyterhub/helm-chart) [mine](https://github.com/PureStorage-OpenConnect/ai-platform) 。**
*   **您可以将 JupyterHub 与 LDAP 服务器集成,以利用现有的用户帐户。**

**JupyterHub 将在群集外部的 IP 地址上提供登录屏幕,供您网络上的用户使用。当用户登录时,他们可以访问共享数据集以及个人笔记本、绘图和文件的主目录。**

***延伸阅读:* [*Zero to JupyterHub 同 Kubernetes*](https://zero-to-jupyterhub.readthedocs.io/en/latest/) *。***

****我们今天不使用 Kubernetes:** 安装 JupyterHub 更容易!点击查看简单步骤[。](https://tljh.jupyter.org/en/latest/)**

# **结论**

**当你回到电脑前,难道你不想直接跳到你的项目中吗?**

**无论您的实验和数据集位于何处,都有可能消除不断重新部署开发环境的麻烦。用你的时间去做更有用的事情,而不是一遍又一遍地旋转 Jupyter。**

# Jupyter 现在是一个成熟的 IDE

> 原文:<https://towardsdatascience.com/jupyter-is-now-a-full-fledged-ide-c99218d33095?source=collection_archive---------2----------------------->

## 通过 nbdev 和 Jupyter 新的可视化调试器,有文化的编程现在已经成为现实。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9b234b7f1b3a4adaa09e0e6e4fb6e410.png)

在 [Unsplash](https://unsplash.com/s/photos/programming?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上由 [Max Duzij](https://unsplash.com/@max_duz?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍照

笔记本一直是软件思想增量开发的工具。数据科学家使用 Jupyter 来记录他们的工作,探索和实验新的算法,快速勾画新的方法,并立即观察结果。

然而,当时机成熟时,软件开发人员转向经典的 ide(集成开发环境),如 Visual Studio Code 和 Pycharm,以将想法转换为库和框架。**但是有没有办法将 Jupyter 转变成一个成熟的 IDE,将原始的概念转化成健壮的、可重用的模块?**

为此,来自多个机构的开发者,包括 QuantStack、两个适马、彭博和 fast.ai 开发了两个新颖的工具;Jupyter 的 [nbdev](https://github.com/fastai/nbdev) 和[可视化调试器](https://github.com/jupyterlab/debugger)。

> [学习率](https://www.dimpo.me/newsletter)是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!

# 识字编程和 nbdev

1983 年,Donald Knuth 提出了一个新的编程范例,叫做[识字编程](http://www.literateprogramming.com/)。用他自己的话说,有文化的编程是一种将编程语言和文档语言结合起来的方法,从而使程序比只用高级语言编写的程序更健壮、更可移植、更容易维护,并且可以说编写起来更有趣。 ***主要思想是把一个程序当作一篇文献,写给人类而不是写给计算机*** *”。*

去年晚些时候,杰瑞米·霍华德和[西尔万·古格](https://github.com/sgugger)被 nbdev 的设计深深吸引。这个框架允许您在熟悉的 Jupyter 笔记本环境中编写代码,在找到给定问题的有效解决方案之前探索和试验不同的方法。然后,使用某些关键字,nbdev 允许您将有用的功能提取到一个成熟的 python 库中。

更具体地说,nbdev 补充了 Jupyter,增加了对以下内容的支持:

*   遵循最佳实践,从笔记本中自动创建 python 模块
*   在标准 IDE 中编辑和导航代码
*   将任何更改同步回笔记本
*   从代码中自动创建可搜索的超链接文档
*   pip 安装程序很容易上传到 PyPI
*   测试
*   持续集成
*   版本控制冲突处理

nbdev 使软件开发人员和数据科学家能够在不脱离 Jupyter 环境的情况下,遵循最佳实践,开发文档完备的 python 库。nbdev 在 PyPI 上,要安装它,只需运行:

pip install nbdev


对于[可编辑安装](https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install),使用以下:

git clone https://github.com/fastai/nbdev
pip install -e nbdev


首先,阅读由开发者撰写的优秀的[博客文章](https://www.fast.ai/2019/12/02/nbdev/),描述 nbdev 背后的概念,并遵循[文档](http://nbdev.fast.ai/)中的详细教程。

# 缺失的部分

尽管 nbdev 涵盖了 Jupyter 内部 IDE 类开发所需的大部分工具,但仍然缺少一部分;可视化调试器。

因此,来自几个机构的开发人员团队昨天宣布了 Jupyter 可视化调试器的首次公开发布。调试器提供了您对 IDE 调试器的大部分期望:

*   变量资源管理器、断点列表和源代码预览
*   导航调用堆栈的可能性(下一行、进入、退出等。)
*   直观地在感兴趣的行旁边设置断点的能力
*   指示当前执行停止位置的标志

为了利用这个新工具,我们需要一个在后端实现 *Jupyter 调试协议*的内核。因此,第一步是安装这样一个内核。目前唯一实现的是`[xeus-python](https://github.com/jupyter-xeus/xeus-python)`。要安装它,只需运行:

conda install xeus-python -c conda-forge


然后,运行 Jupyter Lab,在侧边栏搜索`Extension Manager`并启用它,如果你还没有这么做的话。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/93c3cf037be8f0208aad66920a0e4fd3.png)

启用扩展管理器

一个新的按钮将出现在侧边栏上。要安装调试器,只需转到新启用的`Extension Manager`按钮并搜索`debugger`扩展。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/dd7f812d6f216f6d7d2a8a49bbfe2137.png)

启用调试器

安装后,Jupyter 实验室将要求您执行构建,以包括最新的变化。接受它,几秒钟后,你就可以走了。

为了测试调试器,我们创建了一个新的`xpython`笔记本,并编写了一个简单的函数。我们照常运行该函数,并观察结果。要启用调试器,请按窗口右上角的相关按钮。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/5b3930aec7a3594f6836197e1523b163.png)

启用调试器

现在,我们准备再次运行该函数。只有这一次,执行将在我们设置的断点处停止,我们将能够探索程序的状态。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e36156e28d41785cbbdc25eb0e40cce1.png)

调试代码

我们看到程序在断点处停止了。打开调试器面板,我们可以看到变量、断点列表、调用堆栈导航和源代码。

Jupyter 新的可视化调试器提供了 IDE 调试器所能提供的一切。它仍在开发中,因此,新的功能是预期的。它的开发者计划在 2020 年发布的一些功能有:

*   在变量浏览器中支持丰富的 mime 类型呈现
*   支持用户界面中的条件断点
*   从 JupyterLab Voilà预览扩展启用 [Voilà仪表板](https://github.com/voila-dashboards/voila/)的调试
*   启用尽可能多内核的调试

# 结论

Jupyter 笔记本一直是探索和试验代码的好方法。然而,软件开发人员通常求助于一个成熟的 IDE,复制工作的部分,以产生一个生产就绪的库。

这不仅效率低下,也是 Jupyter 产品的损失;识字编程。此外,笔记本电脑提供了一个更好的文档环境,包括图表、图像和视频,有时还有更好的工具,如自动完成功能。

nbdev 和 visual debugger 是两个旨在缩小笔记本和 ide 之间差距的项目。在这个故事中,我们看到了什么是 nbdev,以及它是如何使识字编程成为现实的。此外,我们发现了一个新项目 Jupyter 的可视化调试器如何提供缺失的部分。

> **我叫 Dimitris Poulopoulos,是希腊比雷埃夫斯大学***[**BigDataStack**](https://bigdatastack.eu/)***的机器学习研究员和博士(c)。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。如果你有兴趣阅读更多关于机器学习、深度学习和数据科学的帖子,请在 twitter 上关注我的*** *[**中**](https://medium.com/@dpoulopoulos) **、**[**LinkedIn**](https://www.linkedin.com/in/dpoulopoulos/)**或**[**@ james2pl**](https://twitter.com/james2pl)**。****

# Jupyter 准备生产;原样

> 原文:<https://towardsdatascience.com/jupyter-is-ready-for-production-as-is-b36f1d1ca8f8?source=collection_archive---------18----------------------->

## 无需编写一行代码,即可将您的笔记本草稿转化为生产就绪的 Kubeflow 管道

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b66d98154acc72fe27279ca0ed23fbf4.png)

图片由 [16853182](https://pixabay.com/users/16853182-16853182/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5263284) 来自 [Pixabay](https://pixabay.com/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5263284)

机器学习项目通常由多个相互关联的步骤组成:数据采集、数据处理、数据建模、微调、测试等。这些步骤中的每一步都可以是一个独立的过程,以自己的节奏运行,具有明确定义的输入和输出。因此,数据科学家和 ML 工程师倾向于认为这些项目像管道。

> 数据科学家的理想场景是将 Jupyter 笔记本提供的实验环境转变为生产就绪的 ML 管道。

然而,ML 管道是一种很难编码的东西;连接到数据源,将正确的输入传递到每个步骤,序列化输出,检查点,找出依赖关系……**如果我们能够自动化配置工作流执行所需的样板代码的苦差事,那不是很好吗?**

数据科学家的理想场景是将 Jupyter 笔记本提供的实验环境转变为生产就绪的 ML 管道。嗯,我们今天就可以做。此外,我们无需编写任何代码就能做到这一点。

> [学习率](https://mailchi.mp/d2d2d4a109b5/learning-rate-newsletter)是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!

# KubeFlow 简介

Kubeflow 是一个开源项目,致力于使 ML 项目的部署更加简单、可移植和可伸缩。来自[文档](https://www.kubeflow.org/):

> Kubeflow 项目致力于使在 Kubernetes 上部署机器学习(ML)工作流变得简单、可移植和可扩展。我们的目标不是重新创建其他服务,而是提供一种简单的方法来将 ML 的最佳开源系统部署到不同的基础设施上。无论你在哪里运行 Kubernetes,你都应该能够运行 Kubeflow。

但是我们如何开始呢?我们需要 Kubernetes 集群吗?我们应该自己部署整个系统吗?我的意思是,你看过库伯弗洛的[清单回购](https://github.com/kubeflow/manifests)吗?

> 在 Kubeflow 上运行笔记本所需要的只是一个谷歌云平台(GCP)账户和你的旧笔记本文件!

此外,假设我们已经启动并运行了 Kubeflow 我们如何将我们的笔记本电脑转变为库巴流管道(KFP)?我们必须建立 docker 图像吗?你看过 [KFP DSL](https://kubeflow-pipelines.readthedocs.io/en/latest/source/kfp.dsl.html) 吗?我认为重点是消除样板代码。

嗯,我有好消息;我们所需要的只是一个谷歌云平台(GCP)账户和你的旧笔记本文件!

## 部署 Kubeflow

我将保持简单,不使它变得愚蠢。事实是,只需几分钟就可以轻松运行 Kubeflow 的单节点实例。我们需要的只是一个 GCP 帐户和从市场部署应用程序的能力。我们要用 [MiniKF](https://www.kubeflow.org/docs/started/workstation/getting-started-minikf/) !

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6fc0286eb41774f2e9c853baa3cf30ff.png)

MiniKF 部署—作者图片

1.  去你的 GCP *控制台*
2.  搜索市场然后找到 *MiniKF*
3.  点击它并选择*启动*
4.  设置 VM 配置,(由于我的配额,我通常将数据磁盘更改为标准持久磁盘)并单击 deploy。

就是这样!部署最多需要十分钟,您可以按照屏幕上的说明观看进度;ssh 进入机器,在终端上运行`minikf`,等待直到您准备好端点和凭证。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/25c178fec497dcd408eec3f130a4efd5.png)

MiniKF 的提供已完成—图片由作者提供

现在,我们准备访问 Kubeflow 仪表板。点击网址,输入你的凭证,你就可以开始了!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/54f0dbb046cd9a85b6e300ed123ca77e.png)

Kubeflow 仪表板—按作者分类的图像

## 运行 Jupyter 服务器

为了运行我们的实验,我们需要一个 Jupyter 笔记本实例。在 Kubeflow 中创建一个 Jupyter 笔记本相对容易。我们首先需要创建一个 Jupyter 服务器并连接到它。让我们这样做:

1.  从左侧面板中选择笔记本
2.  选择`New Server`按钮
3.  填写服务器的名称,并请求您需要的 CPU 和 RAM 数量
4.  让 Jupyter 笔记本图像保持原样——这对本教程至关重要(`jupyter-kale:v0.5.0-47-g2427cc9` —注意图像标签可能不同)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a20691a51cd2f9d232da52862fe9035d.png)

创建 Jupyter 服务器—作者图片

完成这四个步骤后,等待笔记本服务器准备好并连接。你将被转移到你熟悉的 JupyterLab 工作区。

# Jupyter 到 ML 管道

那么,我们为什么要做这些设置呢?我们的目标是将我们的笔记本电脑转变为生产就绪的 ML 管道。我们如何做到这一点?

在这个例子中,我们将使用众所周知的*泰坦尼克号*数据集来演示一个我们可以遵循的简单工作流程。首先,在 JupyterLab 环境中创建一个新的终端,并克隆这个示例。

git clone https://github.com/dpoulopoulos/medium.git


如果您以前没有在 JupyterLab 中创建过终端,请注意 JupyterLab 终端提供了对系统 shells(例如 bash、tsch 等)的全面支持。)和 Windows 上的 PowerShell。您可以使用终端在系统 shell 中运行任何东西,包括 vim 或 emacs 之类的程序。所以你也可以用它来克隆来自 [GitHub](https://github.com/dpoulopoulos/medium) 的任何回购。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/06b8accd4907807e518048e7280083c9.png)

在 JupyterLab 中克隆泰坦尼克号的例子——图片由作者提供

克隆了回购之后,可以在`medium > minikf > titanic.ipynb`中找到泰坦尼克的例子。您可以花一些时间浏览笔记本,但是有一个关键的步骤您需要首先运行:取消第一个代码单元的注释,并运行它以将必要的依赖项安装到您的环境中。

!pip install --user -r requirements.txt


运行这个单元后,重启内核,就可以开始了。如果你检查笔记本的左面板,你会看到一个紫色的图标。这是有趣的开始…按下它来启用羽衣甘蓝扩展。你会自动看到每个单元格都被标注了。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fdffa7fbc69692b5562248e4de95353b.png)

启用 Kale 扩展-按作者分类的图像

你可以看到笔记本是分节的;导入、数据加载部分、数据处理、模型训练和评估等。这正是我们用羽衣甘蓝注释的。现在,这个笔记本是预先注释好的,但是你可以随意使用。您可以创建新的管道步骤,但是不要忘记添加它们的依赖项。

在任何情况下,你都可以点击位于 Kale 部署面板底部的`COMPILE AND RUN`按钮。无需编写一行代码,您的笔记本将被转换为 Kubeflow 管道,该管道将作为新实验的一部分执行。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fda0361682f18c1e5feec9fcb6c59cc4.png)

从 Jupyter 笔记本到 Kubeflow 管道——作者图片

按照 Kale 提供的链接观看跑步实验。几分钟后,管道将成功完成其任务。这是图表的最终视图(不要忘记切换左上角的`Simplify Graph`选项):

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f7fd895ec11bc08cbe592a252b756c7a.png)

泰坦尼克号管道——作者图片

恭喜你!您刚刚将您的笔记本变成了一个管道,而没有编写一行代码,最重要的是,没有偏离常规程序。

# 结论

最后,您可以对这个数据集做更多的工作;可以多分析一下,添加交叉特征或者训练不同的分类器。事实上,在未来的故事中,我们将看到如何运行超参数调优,而无需添加任何额外的代码行。但是在数据集上实现最佳的准确性并不是本文的重点。

我们看到了如何在不编写任何样板代码的情况下启动单节点 Kubeflow 实例、创建笔记本服务器并将简单的 Jupyter 笔记本转换为 Kubeflow 管道。所以,去吧;实现自己的想法,一键变成 ML 管道!最后,不要忘记停止你的实例,以避免累积成本!

## 关于作者

我叫[迪米特里斯·波罗普洛斯](https://www.linkedin.com/in/dpoulopoulos/),我是一名为[阿里克托](https://www.arrikto.com/)工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 twitter 上关注我的[媒体](https://medium.com/@dpoulopoulos)、 [LinkedIn](https://www.linkedin.com/in/dpoulopoulos/) 或 [@james2pl](https://twitter.com/james2pl) 。

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

# Jupyter 笔记本:机器学习的简短介绍

> 原文:<https://towardsdatascience.com/jupyter-notebook-a-very-short-introduction-for-machine-learning-f1b9de948c2f?source=collection_archive---------20----------------------->

## Jupyter = Julia + Python + R

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8d883dd043cae85c86e6f7724aa0e4db.png)

马里乌斯·马萨拉尔在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

如果你是一名数据科学家,你可能会每天记录完整的分析过程,就像其他科学家使用实验室笔记本记录测试、进度、结果和结论一样。你用什么工具来做同样的事情?我每天都在使用 Jupyter 笔记本,让我给你简单介绍一下。

*   什么是 Jupyter 笔记本?
*   为什么它对数据分析有用。
*   Jupyter 笔记本有什么特点?
*   在机器学习中执行简单的数据分析。

# Jupyter 笔记本简介

## 什么是 Jupyter 笔记本?

Jupyter 项目是 I-Python 项目的一个衍生项目,I-Python 项目最初只为 Python 语言提供了一个接口,并继续为 Jupyter 提供规范的 Python 内核。Jupyter 这个名字本身就来源于 Julia、Python 和 r 的组合。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4e546634f3221185f6eea4811cd00f25.png)

这是使用 Jupyter 时的示例打开页面

## 为什么有用?

Jupyter 项目的存在是为了开发一个开放源代码平台、开放标准和跨多种编程语言(例如 Python、R 和 MATLAB)的交互式计算服务。
Jupyter 是一个基于云生态系统的网络应用,可以从很多地方获得,比如土星云。它也可以在各种各样的装置上本地使用。其中包含实时代码、等式、图表、交互式应用程序和降价文本。

## Jupyter 笔记本的特点?

Jupyter 笔记本基本上是一个带有大量注释的 JSON 文件。笔记本有以下三个主要部分。

*   **元数据:**定义的数据字典,用于设置和显示笔记本。
*   **笔记本格式:**用于创建笔记本的软件的版本号。版本号用于向后兼容。
*   **单元格列表:**有三种不同类型的单元格——降价(显示)、代码(激励)和输出。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/07039c8d2c213af755d1b252d8053ac6.png)

如果在文本编辑器中打开 IPYNB 文件,您将看到 Jupyter 节点的基本内容

## 我们将如何使用 Jupyter 笔记本电脑?

有如下四个步骤。

*   **第一步:**为数据分析创建一个新的笔记本。
*   **第二步:**添加您的分析步骤、编码和输出。
*   **第三步:**围绕你的分析,组织和展示降价,传达整个故事。
*   **最后一步:**其他人可以通过修改参数和数据来使用交互式笔记本,以记录他们所做更改的效果。

# 获得带有土星云的 Jupyter 笔记本

获得 Jupyter 笔记本的最快方法之一是在 Saturn Cloud 上注册一个帐户。它允许您在云中快速启动 Jupyter 笔记本电脑,并根据您的需求进行扩展。

*   它部署在您的云中,因此无需迁移您的数据。通过 Jupyter 使用整个 Python 生态系统。
*   轻松构建环境和导入包(Pandas、NumPy、SciPy 等)。
*   您可以发布笔记本,并在云托管的 Jupyter 上轻松协作。
*   从笔记本电脑到服务器再到集群的可扩展 Dask。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3ac694e96f60f72606e0b289efd90604.png)

以上是在土星云上创建 Jupyter 笔记本的步骤。

进一步见:[https://www . Saturn cloud . io](https://www.saturncloud.io)

# 我们能把 Jupyter 笔记本转换成 Python 脚本吗?

是的,您可以将 Jupyter 笔记本转换为 Python 脚本。这相当于将每个代码块(单元格)的内容复制并粘贴到单个。py 文件。降价部分也作为注释包含在内。

转换可以在命令行中完成,如下所示。

jupyter nbconvert --to=python notebook-name.ipynb


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f748b4ae43f008777677a9a7f386e716.png)

从笔记本到脚本的示例

# 使用 Jupyter 笔记本进行 ML 的一个例子

假设你是一名医生,你正在评估一千人的数据,并预测某人是否会感染冠状病毒。

我们将通过计算 TP、TN、FP、FN、TPR、TNR、PPV、NPV、FPR 和 ACC 等指标来逐步评估我们的算法。让我们假设你熟悉这些指标(如果不熟悉,请进一步阅读 here⁴).

在我们尝试评估我们的算法之前,有两件事。

*   我们预测的:`y_pred`。
*   我们得到的结果:`y_true`。

我们创建一个新的木星笔记本文件— `“coronavirus.ipynb”` 如下。

# 结论

我们学习了如何用土星云把 Jupyter 笔记本放到云上。我们也接触了笔记本的结构。我们看到了开发笔记本电脑时使用的典型工作流程。最后,我们在 ML 中做了一些简单的数据分析。

# 参考

[1] Jupyter 主页:[https://jupyter.org](https://jupyter.org)

【2】土星云:[https://www . Saturn Cloud . io](https://www.saturncloud.io)

[3]Github 上的笔记本:

[https://github . com/house cricket/notebooks/blob/master/coronavirus . ipyn](https://github.com/housecricket/notebooks/blob/master/coronavirus.ipynb)

[4]测试机器学习算法准确性的度量标准[https://medium . com/datadriveninvestor/Metrics-to-Test-the-Accuracy of-Machine-Learning-Algorithms-67 ADF 367 f 60](https://medium.com/datadriveninvestor/metrics-to-test-the-accuracy-of-machine-learning-algorithms-67adf367f60)

# Jupyter 笔记本基本生产力黑客

> 原文:<https://towardsdatascience.com/jupyter-notebook-essential-productivity-hacks-9b7d69073769?source=collection_archive---------53----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3899e7334d0eb06aa0f98c49eba33b74.png)

[来源](https://pixabay.com/photos/computer-laptop-work-place-mouse-2982270/)。图片免费分享。

## 更高效地创建和编码

Jupyter 笔记本是一个动态的流行工具,帮助用户创建可读的分析,同时以一种有组织的方式组合代码、图像、注释、公式和图表。Jupyter 笔记本的前身是 IPython 笔记本,它是为 Ju lia、Python 和 R thon 设计的,已经席卷了编码界。在本文中,您将了解到一些使用 Jupyter 时最有用的生产力技巧。

# 多单元输出

Jupyter notebooks 用户不需要调用`print()`,只需调用单元格末尾的一个函数就可以得到结果。不幸的是,默认情况下,Jupyter 笔记本不能在同一个单元中输出两个输出。为了输出多个单元,需要从`IPython`重新配置外壳。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7bc46dde1ac942dae7a6af0f02205162.png)

# 多光标

使用 Ctrl+单击创建多光标。无论在哪里

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f53605dbee7f6627488457944a6c13b4.png)

或者,例如,考虑更改列的名称。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/89b00bb89de5359219b60d854dd49686.png)

# 列出所有变量

因为 Jupyter 笔记本是基于单元格的,所以很容易忘记变量和它们保存的值。然而,您可以通过调用`%whos`来跟踪所有变量——它们的名称、数据类型以及它们存储的数据。它存储你加载的所有东西——模块、数据帧、数组、函数,所有的东西。这在数据分析中非常方便,因为许多错误通常是由于忘记变量名和值造成的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/77546f7daa14f9c80d28a98145c68b4a.png)

# 乳液

您可以在减价单元格中键入 LaTeX,方法是将 LaTeX 括在美元(`$`)符号中。这在交流公式和变量之间的关系时特别有用。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e1ecdbb427c4c3211723d84e88fa92af.png)

您可以在此了解如何在 LaTeX 中构建更多数学结构:

[](/latex-for-data-scientists-in-under-6-minutes-3815d973c05c) [## 面向数据科学家的乳胶,不到 6 分钟

### 任何数据科学简历的必备技能

towardsdatascience.com](/latex-for-data-scientists-in-under-6-minutes-3815d973c05c) 

# 轻松链接到功能文档

如果你对任何函数的作用有疑问,只需输入`?name_of_function`就可以启动该函数的文档和用法。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bc6b9233a8033e7ecc4cb1415901b378.png)

# 高分辨率绘图

在`matplotlib`和`seaborn`中创建的标准图可以以更高的分辨率变得更加清晰。为了演示,让我们首先创建一个具有正常随机性的标准正弦波图。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f36f1c3e279484cfe85008b821d08d4a.png)

为了创造更清晰的思路,加上`%config InlineBackend.figure_format =’retina’`。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fc320d2c82bdeed66ed6ae78f0dbbf7a.png)

线条、数字、注释和其他情节元素将变得更加清晰。

# 更改单元格语言

要更改单元格的语言,请在单元格顶部键入以下命令之一:

*   `%%bash`
*   `%%HTML`
*   `%%python2`
*   `%%python3`
*   `%%ruby`
*   `%%perl`

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ec9cb5713c048053b3bff5c11a3b3b7d.png)

您还可以使用 HTML 来嵌入视频、图像或显示其他内容。

# 如果你喜欢这个,

你可能会喜欢我的其他一些文章。

[](https://medium.com/analytics-vidhya/styling-pandas-dataframes-more-than-just-numbers-4bbb790fb919) [## 设计熊猫数据框架:不仅仅是数字

### 数据帧是 Python 中操作和存储数据的最标准的方法——但是您知道您可以存储一个…

medium.com](https://medium.com/analytics-vidhya/styling-pandas-dataframes-more-than-just-numbers-4bbb790fb919) [](https://medium.com/swlh/real-artificial-intelligence-understanding-extrapolation-vs-generalization-b8e8dcf5fd4b) [## 真正的人工智能:理解外推 vs 概括

### 机器学习模型不需要智能,它们的大多数应用都需要执行任务,如…

medium.com](https://medium.com/swlh/real-artificial-intelligence-understanding-extrapolation-vs-generalization-b8e8dcf5fd4b)

# 使用 Docker 映像的 AWS EC2 实例中的 Jupyter 笔记本

> 原文:<https://towardsdatascience.com/jupyter-notebook-in-a-docker-container-on-aws-ec2-instance-7efc51459d6f?source=collection_archive---------38----------------------->

## 数据科学和机器学习专业人员的最佳可能世界

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/006cf82df518d388a8640ca27e30b6b0.png)

在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上由 [Zeshalyn Capindo](https://unsplash.com/@zeshalynkristine?utm_source=medium&utm_medium=referral) 拍摄的照片

大多数数据科学和机器学习专业人士都喜欢 Jupyter 笔记本。除了少数异常情况,大多数数据科学和机器学习工作都发生在云中。所以别无选择,只能在云上使用 Jupyter。

在我的上一篇文章中,我解释了如何在 AWS Linux 实例上下载 Jupyter 笔记本,并使用 Xming 和 X11 转发在客户机上访问它。下面是那篇文章的链接

[](/jupyter-notebook-on-aws-ec2-instance-f869f5aa4848) [## AWS EC2 实例上的 Jupyter 笔记本

### 无处不在的云和 Jupyter 可用性的完美结合

towardsdatascience.com](/jupyter-notebook-on-aws-ec2-instance-f869f5aa4848) 

在本文中,我将解释如何通过 Docker 映像直接访问 AWS EC2 实例中的 Jupyter 笔记本。不需要在 AWS EC2 实例中安装 Anaconda 或 Jupyter。

我假设你已经有了一个 AWS EC2 实例,并且知道如何通过 [Putty](https://www.putty.org/) 访问它

**必备工具**

确保您拥有最新版本的默认操作系统包。尤其是检查是否安装和配置了防火墙相关的软件包。我在 AWS EC2 上使用 Redhat Linux 实例。

首先要确认的是 iptables——安装了服务。如果没有,通过 yum 安装

sudo yum install iptables-services


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/798aa9927efd4be0eda54a4be0b7e5eb.png)

作者图片

## 码头发动机安装

现在您已经准备好安装 Docker 引擎了。我按照下面链接的说明在我的 Red Hat Linux 实例上安装了 Docker 引擎。如果您的实例使用不同的操作系统,请查看下面链接中针对该操作系统的步骤。

[](https://docs.docker.com/engine/install/centos/) [## 在 CentOS 上安装 Docker 引擎

### 要在 CentOS 上开始使用 Docker 引擎,请确保您满足先决条件,然后安装 Docker。要安装…

docs.docker.com](https://docs.docker.com/engine/install/centos/) 

a.先做第一件事;运行以下命令安装所有 yum 实用程序

sudo yum install -y yum-utils


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/494ab7fbf3f07232c3554c141c9b4886.png)

作者图片

b.获取最新的 docker 存储库

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0f4c08004ceb871e3ae2334d826b753f.png)

c.现在安装最新版本的 docker 引擎和容器

sudo yum install docker-ce docker-ce-cli containerd.io


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/66df31749a191dacafdf363b534d7299.png)

作者图片

d.启动 docker 服务。

sudo systemctl start docker.service


如果您没有收到任何错误消息,您的 docker 服务已经成功启动。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0c652505b50637089f710d4287f46bdb.png)

作者图片

e.您还可以检查 docker 服务的状态。

sudo systemctl status docker.service


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/83f7ed4b18cad25e6521ecddaeb6b89f.png)

作者图片

恭喜你!!您已经成功安装了 docker 引擎。现在,您已经准备好提取 Jupyter 笔记本图像。

# Jupyter 笔记本

是时候拉 Jupyter 笔记本镜像了。

a.运行下面的命令来提取 docker 映像并启动 Jupyter notebook。

sudo docker run -p 8888:8888 jupyter/scipy-notebook


等待映像下载和提取完成。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/231b51b58d21e0384ffd5774f3d64c1c.png)

作者图片

您将收到一条消息,表明 Jupyter notebook 正在运行,其中包含一个指向 Jupyter notebook 的链接。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9755690e059c5252ace1597c1e572546.png)

作者图片

b.复制链接并删除 127.0.0.1 和您实例的公共 IP 地址。您可以在 EC2 Instance Connect 选项卡中看到您的实例的公共 IP 地址。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/55312ec5eacfe7efb373f83d7dfe2026.png)

作者图片

c.如果您收到超时消息或站点无法访问消息,您的实例可能不允许在端口 8888 连接。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a12f6bc56e0efe5fca94ba0d780f140e.png)

作者图片

d.转到 AWS 实例的 security 选项卡,单击安全组名称。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1a8c6ffc20c0e4758f63d1ae718c3cb5.png)

作者图片

e.单击 Edi 入站规则按钮。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c73e2c5be04d448dd69b05c0fc52f117.png)

作者图片

e.如下所示,为端口 8888 添加一个规则,并保存该规则。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ef074db0f95a68bb9e68a7b2e8ed189a.png)

作者图片

f.现在刷新你的浏览器。朱庇特笔记本会出现。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b2c062a523f157f7ebf661f735617b11.png)

作者图片

恭喜你!!您的 Jupyter 笔记本正在等待您的下一次数据科学或机器学习冒险!

## 结论

云和 Docker 图像正在成为数据科学和机器学习专业人士生活中不可避免的一部分。Docker 图像就像已经为您完成的工作。尽可能地使用它来减少你在项目中的周转时间。

# AWS EC2 实例上的 Jupyter 笔记本

> 原文:<https://towardsdatascience.com/jupyter-notebook-on-aws-ec2-instance-f869f5aa4848?source=collection_archive---------18----------------------->

## 无处不在的云和 Jupyter 可用性的完美结合

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/63c6ca4478d0c1eef1d34e5245d0b927.png)

罗伯特·科林斯在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片

Jupyter 是数据科学和机器学习专业人员使用最多的开发工具。考虑到大多数数据科学和机器学习项目都涉及到在云上处理数据,所以在云上使用 Jupyter 笔记本是有意义的。Jupyter 在无处不在的云实例上的灵活性是一个双赢的组合。

在本文中,我将向您介绍在 AWS EC2 实例上从 Linux 实例安装和运行 Jupyter 笔记本的步骤。

**必备工具**

我假设您已经有了一个 AWS EC2 实例,并且知道如何通过 [Putty](https://www.putty.org/) 访问它。

确保您已经在 Putty 中配置了 X11 转发。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/58258942ac974cb0cc32af632d0059eb.png)

作者图片

为了在 AWS 实例上启动 Jupyter notebook 并在您的计算机上访问它,您还需要 Xming 工具。Xming 可以从下面的链接下载

[](http://sourceforge.net/project/downloading.php?group_id=156984&filename=Xming-6-9-0-31-setup.exe) [## Xming X Server for Windows

### 免费下载 Xming X Server for Windows。系统服务器。Xming 是领先的 X 窗口系统…

sourceforge.net](http://sourceforge.net/project/downloading.php?group_id=156984&filename=Xming-6-9-0-31-setup.exe) 

下载并安装 Xming 后,你应该会在电脑上看到两个图标 **Xming** 和 **XLaunch** 。点击 Xming,它将启动 Xming 服务器。

点击 XLaunch,进入下面的屏幕。

这是您将看到的第一个屏幕。不需要任何操作,请单击“下一步”。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/015cc913d1ffda3c7de2642113d38626.png)

作者图片

此屏幕上不需要任何更改。点击下一步按钮。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/5938c6b65a9614a9698e4abdf05db968.png)

作者图片

此屏幕上不需要任何更改。点击下一步按钮。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/46b82f1c73e4c69ec92b31838574e712.png)

作者图片

此屏幕上不需要任何更改。单击完成按钮。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0b5de0a06adfd7557e61e491c44db0c2.png)

作者图片

圣诞节可以开始了。

**Anaconda:** 与其在 AWS 实例中分别安装 Python 和 Jupyter,我建议安装 Anaconda。我在 AWS EC2 上使用 Redhat Linux 机器。默认情况下,它不附带 Anaconda 存储库。所以,第一步是通过 **wget** 命令获取 Anaconda。

a.首先,检查您的实例中是否安装了 **wget** 。如果没有,通过如下所示的 **yum** install 运行安装。

sudo yum install wget


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3102fcc380b8e0e069ce0186b1d3fa1e.png)

作者图片

b.检查是否安装了 **bzip2** 。如果没有,通过 yum 安装

sudo yum install bzip2


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f84edef84ccb8bb9923d20e644f951b4.png)

作者图片

c.检查是否安装了 **firefox** 。如果没有,通过 yum 安装

sudo yum install firefox


d.检查是否安装了 xorg-x11 驱动程序。如果没有,通过 yum 安装

sudo yum install xorg-x11*


e.打开/etc/ssh/ssh_config 文件,并确保 ForwardX11 选项已取消注释并设置为 yes。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/862f75fafcadef4e23cae896d9a92f0e.png)

f.通过 wget 下载 Anaconda3

sudo wget http://repo.continuum.io/archive/Anaconda3-4.3.0-Linux-x86_64.sh


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/18d8d073c3a55f0357fd95fd3b12c43f.png)

作者图片

这将在目录中创建文件 anaconda 3–4 . 3 . 0-Linux-x86 _ 64 . sh。

g.运行下面的命令来安装 Anaconda 3。

bash Anaconda3-4.3.0-Linux-x86_64.sh


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/21644f3693803d3692f3266b07a4de30.png)

作者图片

点击进入并浏览条款和条件。一旦你得到下面的信息,写是。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7d2ce25939292075a33af8c481b67193.png)

作者图片

提及您想要安装 anaconda3 的位置

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a8739cbc91ed4ae8c1311e5ff3323acd.png)

作者图片

等待 Anaconda3 安装完成。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a0563dbb652816ed6f507662268af863.png)

作者图片

h.添加 Anacond3 二进制文件并在 bashrc 文件中显示变量。我用的是 vi 编辑器,你可以用 nano 或者别的。

sudo vi ~/.bashrc


在此文件中添加以下内容

export PATH=/u01/anaconda3/bin:$PATH
export DISPLAY=localhost:10.0


I .关闭实例并通过 Putty 重新登录。

j.确保 Xming 和 XLaunch 已打开。任务视图中应显示 Xming 图标。

k.让我们确认它已成功安装。检查 Anaconda、Python 和 Jupyter 的版本。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/52345109d0867033cce71160c97e5074.png)

作者图片

恭喜你!您已经完成了所需的设置,并准备启动 Jupyter 笔记本电脑。

## 推出 Jupyter 笔记本

运行以下命令启动 jupyter 笔记本

jupyter notebook


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cb550cf35f95675807560a9b7fcb36b3.png)

作者图片

Jupyter 笔记本将在 Mozilla 浏览器的 X11 窗口中打开。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e5e74746527aa66af823e3f58a3e310e.png)

作者图片

恭喜你!现在您知道如何在 AWS EC2 实例上启动 Jupyter 笔记本了!

我和我的学生已经多次经历过这些步骤,并且已经能够在 AWS 实例上成功运行 Jupyter 笔记本。然而,如果您在任何步骤遇到任何问题,请随时写信给我,我会及时回复。

期待您的反馈。

# 笔记本——投资组合的杀手

> 原文:<https://towardsdatascience.com/jupyter-notebook-the-killer-of-portfolios-8fb70638491?source=collection_archive---------15----------------------->

## 为什么不应该将笔记本电脑作为数据科学投资组合的主要特征。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c6de67b3e4042cb44db4f00585ac79ee.png)

(Jupyter png src =[http://pluspng.com/jupiter-planet-png-2876.html](http://pluspng.com/jupiter-planet-png-2876.html)

T2:笔记本:所有现代科学计算机适应其学科的地方;一个避难所,一个和平的地方。我们都知道笔记本是一种神奇的工具,它不仅使科学计算变得更加容易,而且更加高效。对于机器学习应用来说尤其如此。研究和开发可以用夹在简单的短代码中的 markdown 单元来彻底解释——有什么不喜欢的呢?

笔记本很棒,是任何有抱负的数据科学家的投资组合中非常重要的一部分。很难否认,在现代数据科学和机器学习中,笔记本电脑并不是一个非常重要的必需品。然而,有一种方法可以让你看起来不太可能仅仅因为拥有一个主要由笔记本组成的文件夹而获得一份工作。

# 了解工作

将您的工作限制在笔记本上的部分问题是,大多数数据科学职位通常不会坐在笔记本上,不断地拟合和序列化模型。当然,这将总是非常具体地针对所讨论的职位,但在某种程度上——数据科学的现实可能会相当令人失望,不管你的机器学习武器库有多大。为了首先正确地推断数据,很有可能您将构建大量的基础设施。对于拥有数千员工的公司的初级数据科学家或实习生来说,情况尤其如此。

明确地说,低级别的创业公司在完全不同的战线上陷入了同样的陷阱。即使是唯一的数据科学家也会让你陷入这种境地,因为你需要数据来为一家小型创业公司做任何事情。这份工作可能比大公司的数据科学家职位更难。然而,如果你像我一样,喜欢展示你的创造力,并涉足不同的计算学科,这种环境可能会让我兴奋。

问题是:

> 如果大部分工作是流水线操作和建立数据基础设施,那么笔记本有什么价值呢?

正如我之前所说的,虽然笔记本肯定是创建可重复研究的好方法,但如果招聘经理查看 Github 的个人资料,而它只返回 Jupyter-Notebooks 的存储库,很可能你不会得到这份工作。这是因为你展示的技能只是工作的一部分,而不是全部。我可以假设您可以在笔记本上编写足够的代码,但是

*   可以部署一个模型吗?
*   你能进行 SQL 查询吗?
*   您能做些什么来自动化和控制我们数据系统的后端?

笔记本电脑能够正确提供的唯一信息是您执行操作(如拟合模型)的能力。在投资组合的笔记本部分,我关注的另一个关键是组织。你的代码的可复制性如何,你让你的同事观察你执行的代码有多容易?这些都是关于你的非常重要的信息,可以从你的笔记本上收集。虽然笔记本是你整体投资组合的一小部分,但它们仍然很重要。幸运的是,我写了一篇关于这些主题的文章,你可以在这里更新你的笔记本:

[](/the-data-scientists-guide-to-reproducible-research-ea1a512be3e5) [## 数据科学家可重复研究指南

### 你的假设还是假设!

towardsdatascience.com](/the-data-scientists-guide-to-reproducible-research-ea1a512be3e5) 

# 一个隐喻

我们可以对笔记本电脑做一个很好的比较,那就是终端会话。让我们假设我们是开发运营工程师,我们的工作是部署全栈 web 服务。我的开发-运营组合的最大部分当然不会是我的终端会话的输出,尽管它们可能很重要。虽然运行后端的配置文件和代码肯定是开发-运营工程师组合的一大部分,但最重要的事情是返回产品。产品是公司所追求的。如果你能够运输一个产品,那么你很可能拥有重复这项工作所需的所有技能。

类似地,我们可以把它比作一个全栈的 web 开发人员。没有一个招聘经理会花时间去检查你的存储库,下载你所有的文件来研究你的代码。当然,可能会出现一些文件的峰值,以查看您在笔记本或应用程序中执行了多少冗余操作,但重要的是要记住,最重要的是提供一些实用且实际可用的东西:

> 一个产品。

# 黑仔投资组合

我回顾了如此多的作品集,甚至有同事的作品集都是以 Jupyter-Notebook 为中心的。虽然这些肯定是数据科学家投资组合的一大部分,但最重要的是交付一个真实的结果。问题是许多数据科学家不愿意使用 BASH,这是一个很大的问题,因为它经常成为这项工作的主要内容。

制作一个模型是很棒的,但是如果你不知道如何部署它或者获取它的数据,那么这个模型本质上是没有用的。如果它不能被查询并产生适当的回报,那么这个模型将永远不会有任何真正的用途。尽管幕后发生的事情可能比观众所相信的要高级一些,但是如果产品做得很好,那么你就有可能得到这份工作。

# 结论

虽然 Jupyter 笔记本电脑是现代科学计算的主要产品,也是一个适当的数据科学家的投资组合所必需的,但缺乏与工作的许多主要操作相关的内容通常会被排除在投资组合的这些部分之外。Jupyter 是一个很好的工具,可以让代码变得清晰、可复制,但是在某些情况下,它确实有点不太好用。

我想我可能会触及这个主题,因为有许多数据科学家对笔记本有点着迷。虽然笔记本电脑在任何科学计算工作中都是非常重要的一部分,但笔记本电脑不太可能成为 Github 帐户的主要产品,我认为科学家不仅仅是 Jupyter,这一点非常重要。笔记本修改起来也相对简单,所以润色一下可能是个好主意!

# Jupyter 笔记本到 PDF 的几行

> 原文:<https://towardsdatascience.com/jupyter-notebook-to-pdf-in-a-few-lines-3c48d68a7a63?source=collection_archive---------0----------------------->

## 轻松将您的 Jupyter 笔记本转换为 PDF 文件

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/600ab99068765bc7fd04f98aa1e495df.png)

作者创建的图像

在我们的 Jupyter 笔记本上工作时,有时我们希望以可读的形式共享我们处理过的数据集,包括创建的图和我们已经创建的降价解释。有一种简单的方法可以将我们的 Jupyer 笔记本转换成 PDF 文件。只需一个简单的设置,您就可以访问 PDF 格式的笔记本。

例如,我会使用我在文章[这里](/breaking-down-the-agglomerative-clustering-process-1c367f74c7c2)中提供的笔记本来转换成 PDF 表单。下面是我的 Jupyter 笔记本。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/836cb34bbe87920f11f3c6d8a31d5b2b.png)

下面是 PDF 格式的笔记本。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/73a67a235f20743c42c407c2b365e261.png)

如你所见,它显示了所有的代码和你的解释。有多花哨?

现在让我告诉你怎么做。

# Jupyter 到 PDF

我们需要做的第一件事是安装必要的软件包。在这里,我们将使用名为 notebook-as-pdf 的软件包来帮助我们将 Jupyter 笔记本转换为 pdf 文件。您需要在命令提示符下运行以下代码。

pip install -U notebook-as-pdf


我们还需要一个额外的铬设置。它用于执行 HTML 到 PDF 的转换。只需在代码提示符下运行以下代码。

pyppeteer-install


就这样,我们已经做好了准备。现在,让我们打开您打算转换为 PDF 的笔记本。在您的笔记本中,单击文件菜单栏,然后选择下载为,然后选择 PDF via HTML 来转换笔记本。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/08981d3f9a9871771edcbc8a6e3fd149.png)

就这样,你已经有了一个 PDF 格式的笔记本。如果您喜欢使用命令提示符来转换笔记本,您可以使用下面的代码来完成。

jupyter-nbconvert --to PDFviaHTML example.ipynb


结果将被称为 example.ipynb,因为我们的 Jupyter 笔记本被称为 example.ipynb

# **结论**

这里我向你展示了一个将你的 Jupyter 笔记本转换成 PDF 文件的技巧。这可能很简单,但从长远来看是有用的。

如果你想了解更多关于这个包的信息,你可以访问网站[这里](https://pypi.org/project/notebook-as-pdf/)。

在我的 [**社交媒体**](https://bio.link/cornelli) **上访问我。**

> 如果您没有订阅为中等会员,请考虑通过[我的推荐](https://cornelliusyudhawijaya.medium.com/membership)订阅。

# Jupyter 笔记本调整使 python 项目对非技术人员可读

> 原文:<https://towardsdatascience.com/jupyter-notebook-tweaks-to-make-python-projects-readable-for-non-technicals-86000e9aff01?source=collection_archive---------30----------------------->

## 让数据科学项目更具可读性和可展示性

“这看起来像希腊语!”,我的妻子说,每次她看着我的 Jupyter 笔记本或很少命令行,当我试图 git bash,pool 和其他一切数据科学家和用户这样的工具,如 Jupyter 笔记本,命令行,python,然后一切。嗯,实际上有相当多的希腊人,尤其是在这个严重依赖大量统计和数学的行业。我自己一直很难接受大量的新术语提醒,Josh 解释道,他管理着我的一个了解希腊语的 youtube 账户,Josh 的 Statsquest。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/53fe2937115ca54438bbcbfe3866f775.png)

来自 giphy.com 的史蒂文·A 对 T2 的数据和数学着迷

虽然她确实了解数据科学的一些基础知识,包括收集、处理、设计、建模和可视化发现。事实是,我有时希望能够以最简单易懂的方式解释我们所做的一些项目的过程和最终产品。虽然侧边演示文稿是开始这种简单的数据科学项目总结的绝佳场所,但 Jupyter 笔记本仍然可以让那些愿意进一步探索这一过程的人更容易阅读。

下面我列出了一些你可以在笔记本上做的基本事情,让它看起来更像样,最重要的是更容易理解。

1.  **总结你的优秀工作-** 清晰的问题定义,包括流程和方法的总结以及发现和后续步骤。
2.  **目录** -包括一个清晰的目录,包括标题和副标题。让您的技术笔记本易于浏览。检查目录扩展的[n 扩展](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/install.html)。下面的例子展示了我和我的同事 Muoyo Okome 最近完成的一个项目的目录。[该项目的目标是尝试发现数据是否可以帮助芝加哥市的拼车司机赚更多的钱](https://github.com/muoyo/chicago-ridesharing)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b4eebe11716c3ff590fda0d1244badf3.png)

[芝加哥 rideshare 项目目录](https://github.com/muoyo/chicago-ridesharing)

3.**使代码折叠和标题可折叠-** 除了目录之外,您希望允许查看您代码的人能够只选择他们感兴趣的主题,由于某种原因,您的技术笔记本仍然包含复杂的代码或太多的代码单元,您可以使用扩展折叠部分代码。您也可以使用隐藏所有输入。再次[nbextensions](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/install.html)是这方面的一个关键。

4.**简洁的可视化效果**——包括易于理解且外观简洁的可视化效果,可以很容易地给出正在发生的事情的清晰画面,并突出一些关键的发现。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/aa2602ec9f3d4b955890ecde94c2eda1.png)

[显示芝加哥优步拼车高峰票价时间的图表](https://github.com/muoyo/chicago-ridesharing)

总之,让你的非技术性笔记本干净、整洁、易于浏览是很重要的。这将帮助大多数人容易理解我们作为数据科学家所做的一些工作。我真的找到了[nbextensions](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/install.html)工具,它拥有上面大部分突出显示的扩展以及更多。正确安装后,您可以通过 jupyter 笔记本电脑的以下界面启用这些功能:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cf5dbe58facfb9f42af66301e461c5f9.png)

[n 扩展](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/install.html)接口

要安装 NBextentions,请使用下面的代码

> !pip 安装 jupyter _ contrib _ nb extensions
> !pip 安装[https://github . com/ipython-contrib/jupyter _ contrib _ nb extensions/tarball/master](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/tarball/master)
> !jupyter contrib nbextension 安装—用户

希望这将有助于您向技术人员和非技术人员发布和分享您的辛勤工作成果。

# IDE 中的 Jupyter 笔记本

> 原文:<https://towardsdatascience.com/jupyter-notebooks-in-the-ide-visual-studio-code-versus-pycharm-5e72218eb3e8?source=collection_archive---------0----------------------->

## Visual Studio 代码与 PyCharm

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d243bd26004e4cbe21c06e9485116afe.png)

我每天都用 Jupyter 笔记本工作。每天我都在使用和编辑 Python 库。两者都是我作品中的关键元素。笔记本是记录和解释你的发现的好方法。从长远来看,库是一项安全的投资,因为它们使您的代码可重用。现在,你有没有想过……除了用 Jupyter 做笔记本,用 ide 做图书馆,我们还能做别的吗?

如果你知道我是 Jupytext 的作者,你就已经知道我认为能够在你最喜欢的 IDE 中编辑你的 Jupyter 笔记本有很多附加价值。

如果你没有听说过 Jupytext,那么让我提一下 Jupytext 是 Jupyter 的一个插件,它可以让你将传统的笔记本与一个或多个文本文件配对。配对的文本文件,例如 Python 脚本,可以*编辑*(使用任何文本编辑器或 IDE),然后当您重新加载笔记本时,您可以在 Jupyter 中获得更改。

Jupytext 提供了一种从 IDE 访问笔记本的方法。但这不是唯一的方法。Spyder 在为脚本提供双百分比单元格标记的交互模式方面有着悠久的历史。Hydrogen 是 Atom 编辑器的一个插件,可以让你交互式地运行这些脚本。而我最常用的两个编辑器,PyCharm 和 Visual Studio Code,现在让你直接在 IDE 里打开你的`.ipynb`笔记本!

我很好奇,想看看这有多有效。那些 ide 的笔记本使用体验比 Jupyter 好吗?我会掉包吗?在本文中,我描述了我目前使用笔记本的工作流程,然后将它与 PyCharm 和 Visual Studio 代码现在可能实现的工作流程进行了比较。

# 我的 Jupytext 工作流程

我将以典型的一天工作为例。今天,我要回答一个关于我们的数据和算法的新问题。原来我以前已经回答过类似的问题了。所以,首先,我*搜索*我现有的笔记本中哪一个最接近今天问题的答案。

由于我使用 Jupytext,我所有的`.ipynb`笔记本都有配对的`.py`表示。所以我打开 PyCharm,使用*在路径中查找*搜索窗口,在我收集的`.py`笔记本中找出能够让我开始今天问题的:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a9e28ee60b844affd6237fad3cb05747.png)

让我补充一下

*   当您将搜索限制在`*.py`文件,并将`.ipynb_checkpoints`添加到 PyCharm 设置/编辑器/文件类型中的*忽略文件和文件夹*时,搜索体验会大大改善
*   并且,如果您想将当前目录中的所有笔记本与`percent`脚本配对,您可以简单地运行`jupytext --set-formats ipynb,py:percent *.ipynb`。

现在我打开现有的笔记本,它将作为*模板*。我将它的内容摘录——我想开始的部分——复制到一个新的`.py`文件中。我负责包含 YAML 头,因为它是定义 Jupytext 配对信息和笔记本内核的地方。然后我把新的`.py`笔记本调到今天的问题。在一个减价单元格中(用`# %% [markdown]`分隔),我写下一些我今天想做的事情。然后我调整代码以更好地解决当前的问题。在 IDE 中这样做比在笔记本中更舒服。它也更加安全和快速,因为我受益于 IDE 语法检查和突出显示。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/45aaf856e18937b41c8b96b8cfee838f.png)

当我的草稿足够好的时候,我在 Jupyter *中打开`.py`文件作为笔记本*(在 Jupyter 笔记本中单击;在 JupyterLab 中,右击该文件,并选择*用/Notebook* 编辑。在这个阶段,它没有输出,所以我运行它。当然,新笔记本在第一次运行时可能不会很好,所以我继续在 Jupyter 中编辑笔记本,直到它正常运行。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f24e54527b9982652aceb1d601167233.png)

当我在 Jupyter 中保存笔记本时,`.py`文件会更新以匹配最新的内容。此外,还创建了一个包含输出的`.ipynb`文件,因为 Jupytext 头在这一行有`ipynb`:`formats:ipynb,py:percent`。如果我忘记复制标题,我可以使用 Jupyter 中的 Jupytext 菜单,选择:*将笔记本与。ipynb 文档*激活与`.ipynb`笔记本的配对。

现在我完成了。通常,我会共享`.ipynb`文件(例如,使用 Jupyter nbviewer),并对`.py`文件进行版本控制。

我最喜欢这个工作流程的什么?

*   在笔记本中搜索非常容易——它们只是文本文件。
*   起草一个新的笔记本太舒服了。我以前从未能够如此轻松地从不同的笔记本中复制粘贴多个单元格。
*   当我在 PyCharm 中编辑`.py`笔记本时,我受益于 IDE 的高级功能:语法检查、补全、重新格式化、文档提示...
*   我也可以在 Jupyter 中自由编辑笔记本。
*   Jupytext 解决了版本控制的问题。通常,我不想将笔记本输出保存在`git`中,所以我只对`.py`文件进行版本化,它有一个干净的差异历史。

注意,这里我使用 PyCharm Professional,但这只是因为它是我最喜欢的 IDE。您可以使用任何其他编辑器,工作流程将是相同的。

我不太喜欢的是:

*   每个笔记本都有一个双重表示(`.ipynb` / `.py`)。这可能会让不止一个用户感到惊讶。
*   在两个编辑器(这里是 PyCharm 和 Jupyter)中同时处理同一个文档需要格外小心。在切换到另一个编辑器之前,我必须注意在当前编辑器中保存文档(并且可能会禁用自动保存)。我需要在我切换到的编辑器中*刷新*笔记本。
*   PyCharm 可以执行和调试我的脚本,但是,输出在终端中显示为文本,所以实际上,我更喜欢在 Jupyter 中执行笔记本。

# PyCharm 的 Jupyter 笔记本

PyCharm 是我最喜欢的代码编辑器。请不要问我为什么,因为我不确定有一个单一的原因…但是我可以肯定的是,在那里编辑脚本和库是非常棒的!此外,我喜欢 PyCharm 的测试和调试工具套件(看看附录,了解如何配置 PyCharm)。并且版本控制被很好地集成…

PyCharm 有两个版本:社区版和专业版。你已经可以用社区版做很多事情了。然而,Jupyter 笔记本只有专业版。

我准备了一个测试笔记本

*   减价牢房
*   一个代码单元,输出一个熊猫数据帧
*   Matplotlib 图
*   Jupyter 小部件
*   和一个阴谋。

现在我在 PyCharm Professional 2019.3.1 中打开笔记本,我得到了这个:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e4d5d0cbd013c13fdd6da7ca06b96f21.png)

这是超级令人印象深刻的,不是吗?

我最喜欢什么?

*   笔记本里的所有输出都工作!甚至是小部件,或者 Plotly 图。干得好,皮查姆!
*   我可以把笔记本编辑成 Python 脚本。就像用 Jupytext 一样,复制粘贴多个单元格是超级容易的!仅用`#%%`创建一个新的代码单元。使用`#%% md`创建降价单元格。
*   执行单元格的快捷键与 Jupyter 中的相同(Ctrl+Enter,Shift+Enter 执行并将光标移动到下一个单元格)。并且预览窗口与输入窗口很好地同步。当您单击一个输入单元格时,视图窗格会自动滚动到相应的输出,反之亦然。
*   当您键入或检查代码时,您可以利用 PyCharm(例如,ctrl+click 将您带到函数或对象的定义)。代码补全、文档提示等都可以在笔记本上找到。
*   您可以在笔记本或底层库上设置*断点*。
*   记事本变量出现在变量资源管理器中:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/61f331c518e30fde59bb959c6e025929.png)

如果有我不喜欢的东西,也许这就是笔记本的展示方式。它与 Jupyter 明显不同,因为输出显示在预览窗格中。我不习惯那样。这也减少了我的地块或表格的可用空间。我想我更喜欢输出在输入之下,比如 Code、Hydrogen 甚至 RStudio。此外,在工作中,我可能会写很长的笔记本,对于这种笔记本,*目录*扩展非常有用,因为它让我可以轻松地在笔记本的不同部分之间导航——我可能会错过 PyCharm 的笔记本编辑器中的这一功能。

如果你是 PyCharm 开发团队的一员,让我告诉你,作为一个笔记本用户,我很高兴看到你在这方面的工作!你做了令人印象深刻的工作!现在我有一些额外的观察给你:

*   你会考虑在代码单元后显示输入吗?你能做到这一点并让我们轻松地选择/复制/粘贴多个单元格吗?
*   减价单元格标记不标准。按照 Spyder 的约定,`# %% md`是一个标题为 `md`的单元格。你可以用`# %% [md]`或`# %% [markdown]`来代替吗,比如 Code,Hydrogen 或 Jupytext?
*   搜索窗口(*在路径*中查找)不能很好地用于笔记本——它显示他们的 JSON 内容的摘录。展示他们的`.py`形象本可以更加用户友好。
*   在笔记本的上下文中,重新格式化代码(Ctrl+Alt+L)是无效的。
*   执行笔记本增加了一些单元格元数据(`{"pycharm": {"is_executing": false}}`)。
*   最后,也许`.py`格式并不适合所有的笔记本。我的一些教程包含大量文本,对于这些,我更喜欢使用 Jupytext 的 Markdown 格式。PyCharm 可以很好地处理 Markdown 文件,但是它不允许我在那里运行代码...在 IDE 中把这些文档渲染成笔记本,你会怎么想?

干得好,皮查姆!现在让我们看看 VS 代码提供了什么。

# Visual Studio 代码中的 Jupyter 笔记本

Visual Studio Code 是由微软开发和维护的免费开源编辑器。它不是专门针对 Python 的,并且有许多语言的插件。在这里,我们将测试 1.41.1 版本的代码,由微软于 2020 年 1 月 13 日发布的最新 [Python 扩展。](https://marketplace.visualstudio.com/items?itemName=ms-python.python)

每当我想编辑 Markdown 文件,或者用 Python 之外的任何语言编写的脚本,比如 Javascript 或 Typescript,我都会使用代码。但是直到最近,我都不怎么使用 Python 代码。回想起来,我认为原因是我不知道如何设置代码来与我的 conda 环境一起工作。这个问题现在已经解决了,并记录在附录中,我要感谢来自 [Python Visual Studio 代码](https://twitter.com/pythonvscode)团队的[露丝安娜](https://twitter.com/luumelo14)帮助我解决了这个问题。

现在让我用代码打开我们刚刚在 PyCharm 中打开的同一笔记本。结果是这样的:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6fff754b216845c5829c1b21acb78f49.png)

我喜欢什么?

*   有用!所有的输出都显示得很好(小部件还不被支持,但是我被告知它们会在下一个版本中被支持)。
*   在这里,执行一个单元格的快捷键与 Jupyter 中的相同(Ctrl+Enter,Shift+Enter 执行并将光标移动到下一个单元格,Esc-A 创建上面的单元格,等等)。
*   我喜欢把输出放在 Jupyter 代码下面。
*   由于自动完成,输入代码很舒服。
*   我们可以在变量资源管理器中检查笔记本变量。

但也许我想要更多。我想一次选择/复制/粘贴多个单元格。我想导航到一个函数的定义,就像我们在脚本中用 ctrl-click 一样。为什么我们没有和`.py`脚本一样的上下文菜单?我想在我的笔记本上设置断点...但是我已经说过了,我希望有一个*目录*来帮助我在长笔记本中找到方向。

我的故事结束了吗……没有!还有最后一件事我想试试。在 Code 的文档中:[在 Visual Studio Code 中使用 Jupyter 笔记本](https://code.visualstudio.com/docs/python/jupyter-support)据说一旦*将笔记本转换成 Python 脚本*就可以设置断点!让我们试试那个。

# Visual Studio 代码中的交互式脚本

现在我们点击*将笔记本转换成 Python 脚本*。我们得到一个看起来像皮查姆的笔记本的脚本:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f6b58459b77b18ce40ecf55f56cac080.png)

我喜欢这里的什么?

*   我可以利用 Code 的高级功能来编辑文件。Ctrl+click 起作用,让我导航到定义。我可以轻松地一次选择/复制/粘贴多个单元格。
*   表格、图和交互式图在交互式预览中工作。
*   我可以在终端中键入和执行 Python 代码,而不必创建新的单元。这太棒了!有多少次,我创建了一个新的单元格,只是因为我需要检查一个变量,然后我忘了从笔记本上删除那个单元格…
*   该脚本使用与 Jupytext 相同的单元格标记。这意味着我可以依靠 Jupytext 在笔记本和脚本之间进行转换和同步。在 Jupyter 中,我会使用 percent 脚本访问 Jupytext/Pair,并保存/重新加载笔记本以更新两个文件。在终端中,我会使用`jupytext notebook.ipynb --set-formats ipynb,py:percent`然后使用`jupytext notebook.ipynb --sync`来保持两个文件同步。

我更喜欢的是*断点*。在脚本上放一个断点,就可以*调试单元格*看变量了!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c03e331c82b7ae8c5d5e5c56baa82cde.png)

我很喜欢那种互动模式!此时,在编辑器中编辑笔记本是我最喜欢的方式之一。

现在我有几个问题要问 Visual Studio 代码 Python 扩展的开发人员:

*   我知道我可以将 VS 代码连接到本地或远程 Jupyter 内核。现在,我可以在 Jupyter 和 Code 之间共享同一个会话吗,比如使用`%connect_info`魔法命令?这将使我能够在 Jupyter 中执行我的笔记本的大部分内容,并且只调试代码中的特定单元,而不必重新运行笔记本的全部代码。
*   Jupytext 允许我将笔记本编辑成脚本或减价文件。我发现 Markdown 格式更适合包含文本多于代码的笔记本,比如教程或文档。你想为笔记本提供降价模式,还是相反,让降价文件以笔记本的形式在代码中交互执行?

# 结论

Visual Studio 代码和 PyCharm 是两个很棒的代码编辑器。它们使得设计、编辑或重构 Python 代码变得如此容易。所以我真的很欣赏能够在这些 ide 中打开笔记本的想法。

笔记本在 IDE 中应该如何表现?我喜欢 PyCharm 的类似脚本的笔记本模式和代码的交互式脚本模式,因为它们允许在笔记本上以与使用脚本完全相同的方式工作(复制/粘贴、在代码中导航、设置断点……)。

我会将笔记本电脑切换到 IDE 吗?我想我会继续在 IDE 和 Jupyter 之间切换,当我想在我的笔记本中搜索,起草新的笔记本,重构现有的笔记本,或者设置断点时,当我想使用目录在笔记本中导航,分析情节,评论我的发现,或者展示笔记本时。

# 感谢

我要感谢 [Python Tools for VS](https://twitter.com/PT4VS) 、 [Python Visual Studio Code](https://twitter.com/pythonvscode) 和 [JetBrains PyCharm](https://twitter.com/pycharm) 开发人员所做的工作。根据经验,我知道在 IDE 中处理笔记本有很大的潜力,但这并不是一个简单的挑战。所以我喜欢看到更多的人致力于此。

让我也感谢帮助我改进这篇文章的早期读者:[弗朗索瓦·沃茨](https://github.com/fwouts),以及 [CFM](https://www.cfm.fr) 、[埃里克·奥·莱比戈](https://github.com/lebigot)、[弗洛伦特·扎拉](https://github.com/flzara)和[文森特·阮](https://www.linkedin.com/in/vincent-nguyen-31533672/)。

# 附录——如何重现该研究

在这一部分,我分享了我关于如何正确安装 Python 以及配置 PyCharm 和代码的笔记。我的笔记是针对 Windows 10 的,但我希望它们适用于任何平台。

## 获取示例文件

请从我的 [GitHub 仓库](https://github.com/mwouts/notebooks_in_vscode_and_pycharm_jan_2020)中克隆环境和示例文件:

git clone https://github.com/mwouts/notebooks_in_vscode_and_pycharm_jan_2020.git


## 用 conda 创建 Python 环境

请安装一个[迷你巨蟒](https://docs.conda.io/en/latest/miniconda.html)或[巨蟒](https://www.anaconda.com/distribution/)。如果不知道区别,就拿 Miniconda,比较轻。

然后进入开始菜单,键入 *Miniconda* 然后点击 *Anaconda Powershell 提示符(Miniconda3)* 。在终端中,将目录更改为此项目,然后创建示例 Python 环境,例如

cd Documents\Github\notebooks_in_vscode_and_pycharm_jan_2020 conda env create --file environment.yml


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d98fb7bb824bf2482bd5424504745c34.png)

现在,我们用以下方式激活环境

conda activate notebooks_in_vscode_and_pycharm_jan_2020


## 发射 Jupyter

我们刚刚创建的环境包括 Jupyter 和 Jupytext。用...发射 Jupyter

cd Documents\Github\notebooks_in_vscode_and_pycharm_jan_2020
conda env create --file environment.yml


您将能够探索我们的示例脚本和笔记本,并了解 Jupytext 是如何工作的。

## 配置 PyCharm

假设您已经安装了 PyCharm Community 或 PyCharm Professional,并且已经在 PyCharm 中打开了我们的`notebooks_in_vscode_and_pycharm_jan_2020`项目。

下一步是告诉 PyCharm 我们想要使用哪种 Python。为此,在使用`conda activate notebooks_in_vscode_and_pycharm_jan_2020`激活环境后,我们在 Windows 上执行`where.exe python`,或者在 Linux 或 Mac OSX 上执行`which python`:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9cbbe7179334cf7a5da6f1d6761053bf.png)

现在我们转到 File\Settings,搜索*项目解释器*,点击 gear/Add,选择*现有环境*,粘贴 Python 解释器的完整路径——在我的例子中是:`C:\Users\Marc\Miniconda3\envs\notebooks_in_vscode_and_pycharm_jan_2020\python.exe`。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/062b9e89392733389d967018a3abb528.png)

## 配置 Visual Studio 代码

Visual Studio 代码的[文档](https://code.visualstudio.com/docs/python/environments)详细解释了如何用虚拟 Python 环境配置 Visual Studio 代码。

如果您想使用 conda,您必须从 Conda 中的*启动代码。所以我们进入 *Anaconda PowerShell 提示符*,通过键入`code`启动 VS 代码:*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f36491f3a52feed6804bdcfe96fbe2cf.png)

现在你可以关闭外壳了。作为从 conda 环境继承的代码,您将能够从该环境中使用 Python 和 Jupyter。

让我强调一下,如果您不在 conda 中启动 Visual Studio 代码*,您将会得到各种类型的错误,包括:*

1.  `conda is not recognized as internal or external command.`
2.  我知道,你把康达加到了你的道路上...但这还不够)
3.  或者甚至,`"Import Error: Unable to import required dependencies: numpy:"`。

# JupyterLab 2.0

> 原文:<https://towardsdatascience.com/jupyterlab-2-0-edd4155ab897?source=collection_archive---------6----------------------->

## 让我们来一窥 Jupyter 笔记本编辑的未来。像编码辅助和更多☀️这样的特性让未来看起来很光明

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2e7eb14da37b50e8e3c0d701e2c2880c.png)

照片由[德鲁·比默](https://unsplash.com/@drew_beamer?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄

前几天,我写了一个故事[你还在用 JupyterLab 吗?我得到了惊人的回应。读者向我推荐了各种为数据科学开发的新 ide,但其中有一个非常突出。](/are-you-still-using-jupyterlab-ce1a4339c0a9)

Michal Krassowski 给我留了一张纸条,上面写着他和其他贡献者正在做的一个项目。JupyterLab-LSP 是 JupyterLab 的一个语言服务器协议集成。简而言之,它为 JupyterLab 增加了新的超能力,比如代码导航、悬停建议、linters、自动完成和重命名。我真的很兴奋,因为它解决了大多数问题,PyCharm 优于 JupyterLab。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3c6046a1b6a4217025577fbc19aa363b.png)

米哈尔·克拉索夫斯基的笔记

> 让我们试驾一下吧

**这里有几个你可能会感兴趣的链接:**


*上面的一些链接是附属链接,如果你通过它们购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。*

# 编码林挺和吸尘建议

安装 JupyterLab-LSP 后,您会在状态栏中看到“完全初始化”图标。这意味着 JupyterLab-LSP 正在工作。

代码林挺工作很好。在下面的示例中,它显示“由未使用的导入”警告。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/329e612c33c8a3400a6e6fd16259da20.png)

用 JupyterLab-LSP 在 JupyterLab 中编码林挺

# 代码完成

这是我最期待的功能之一。我们来测试一下。

从下面的视频中可以看出,代码完成(CC)对 pandas 或 numpy 不起作用。我还用 pandas DataFrame 中的列尝试了 CC,但没有任何不同。CC 在系统库和我定义的类上工作得很好。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/991a0c8c0e5b4e6b5b7345c860057daa.png)

使用 JupyterLab-LSP 在 JupyterLab 中完成代码

# 功能签名建议

一些熊猫函数有很多参数,其中一些我很少使用。每次我使用这样的功能时,我都必须去谷歌搜索文档来更新我的记忆。

JupyterLab-LSP 增加了函数签名建议(FSS),效果很好。你得到一个漂亮的弹出窗口——不太打扰,刚刚好。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4f46624cf954bc9c482e0222365a6332.png)

JupyterLab 中的函数签名建议

FSS 可以通过突出你正在编辑的当前论点来进一步改进,就像 NeoVim 中的[deo complete-Jedi](https://github.com/deoplete-plugins/deoplete-jedi)插件。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/086e84eb5e267a746e876c096e220696.png)

在 NeoVim 与 deo complete-Jedi 的功能签名建议

> 函数签名建议非常有效,但仍有改进的空间

# 诊断面板

JupyterLab-LSP 还有一个漂亮的诊断面板,列出了所有的警告和错误。这非常有用,因为红色下划线可能会被忽略。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/79f553580173cfcbf27592385eb50f07.png)

带有 JupyterLab-LSP 的 JupyterLab 中的诊断面板

# 重命名变量

我对这个有点失望,因为我以为它会进行重构,但它是一个关键字替换。我试图重构一个变量名,但它也重命名了一个字符串,如下面的视频所示。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4c47e1fec8425ce9dbcf330b5f5271a7.png)

使用 JupyterLab-LSP 重命名 JupyterLab 中的变量

# **其他特色**

JupyterLab-LSP 包含了许多有用的功能,比如“转到定义”——你想看看熊猫数据帧在幕后是如何工作的吗——只需使用“转到定义”。

代码格式化在某些时候也会成为 LSP 扩展的一部分!

> W 你想看看熊猫数据框架是如何在幕后工作的吗——只要使用 Go to Definition

# 你自己试试

确保您安装了最新的 JupyterLab 在撰写本文时是 2.1.0。您还需要在 JupyterLab 中启用扩展管理器。

pip install -U jupyterlab


安装 LSP 服务器扩展:

pip install jupyter-lsp


安装节点(该命令适用于 macOS):

brew install nodejs


安装前端扩展:

jupyter labextension install @krassowski/jupyterlab-lsp


为编程语言安装 LSP 服务器:

pip install 'python-language-server[all]'


启动 jupyterlab,您应该会在状态栏中看到“完全初始化”图标。

# 判决

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3bc052ef00ab3e0c7c2c3ab72abeeed7.png)

比尔·牛津在 [Unsplash](https://unsplash.com/s/photos/verdict?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片

根据我所做的正面评论,你可能会认为我会每天使用 JuypterLab 2.0 和 LSP。你会惊讶地发现,在我写完这篇文章后,我已经安装了旧版本。这是为什么呢?

虽然新功能运行良好,但我使用的其他扩展还不支持 JupyterLab 2.0。这些是用于 Vi 键绑定的 [jupyterlab-vim](https://github.com/jwkvam/jupyterlab-vim) 和用于代码格式化的[jupyterlab _ code _ formatter](https://github.com/ryantam626/jupyterlab_code_formatter)。这两个扩展目前对我来说比 LSP 支持更重要。也许我们可以两全其美,因为 JupyterLab-LSP 似乎也支持 JupyterLab 1.x,但我还没有试过。

for JupyterLab 1.x

jupyter labextension install @krassowski/jupyterlab-lsp@0.8.0


> 简而言之,JupyterLab-LSP 是一个巨大的改进,我可以说我将来肯定会使用它

# 在你走之前

在 [Twitter](https://twitter.com/romanorac) 上关注我,在那里我定期[发布关于数据科学和机器学习的](https://twitter.com/romanorac/status/1328952374447267843)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b5d426b68cc5a21b1a35d0a157ebc4f8.png)

由[考特尼·海杰](https://unsplash.com/@cmhedger?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com/?utm_source=medium&utm_medium=referral) 拍摄的照片

# 保持冷静和堆叠—使用 mlxtend 在 Python 中实现堆叠回归

> 原文:<https://towardsdatascience.com/just-keep-stacking-implement-stacking-regression-in-python-using-mlxtend-3250ff327ee5?source=collection_archive---------28----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/5c63a64a009d5676e1bc5e08e35155be.png)

[王占山](https://unsplash.com/@jdubs?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍照

如果你曾经在一些 Kaggle 比赛中结合多个 ML 模型来提高你在排行榜上的分数,你知道这是怎么回事。事实上,这些 Kaggle 竞赛的许多获胜解决方案使用集合模型,而不仅仅是单一的微调模型。

集成模型背后的直觉非常简单:有效地组合不同的 ML 算法可以降低不幸选择一个差模型的风险。

在这篇文章中,我将讨论**堆叠**,一种流行的集成方法,以及如何使用 *mlxtend* 库在 Python 中实现一个简单的 2 层堆叠回归模型。我选择的示例任务是 Airbnb 价格预测。

# 古玩目录

1.  [什么是堆叠,它是如何工作的?](#ce45)
2.  [与基本型号相比,堆叠型号的性能如何?](#7224)
3.  [堆叠有哪些注意事项?](#16b4)
4.  [接下来我们能做什么?](#8ac8)

# 概观

堆叠,或堆叠泛化,是一种元学习算法,它学习如何以最佳方式组合每个基础算法的预测[1]。

简单来说,这就是如何建立一个两层堆叠模型。第一层,有些人称之为基础层,包括基础模型。在分类的上下文中,您可以将基本模型视为任何可用于进行预测的分类器,如神经网络、SVM、决策树等。类似的逻辑也适用于回归。在我们使用训练集训练这些模型之后,第二层通过从这些模型中获取预测以及对**样本外**数据的预期输出来构建元模型。你可以想到这种元模型的最简单的情况是平均出基础模型的预测。

避免过度拟合的常见方法是在这些基础模型上执行[交叉验证](https://machinelearningmastery.com/k-fold-cross-validation/),然后使用折叠外预测和输出来构建元模型。

查看大卫·沃尔菲特的论文,了解更多关于堆叠工作原理的技术细节。

我选择了 Kaggle ( [link](https://www.kaggle.com/c/digit-recognizer) )的 Airbnb 价格预测任务作为这里的示例,因为它是一个相对简单的数据集,具有较小的样本大小和一组功能。任务是根据卧室数量、租赁类型(整个公寓或私人房间或合租房间)等信息预测 Airbnb 上的公寓租赁挂牌价格。

要查看完整的 Python 代码,请查看我的 [Kaggle 内核](https://www.kaggle.com/dehaozhang/stacking-ensemble)。

事不宜迟,让我们进入细节!

# 探测

出于本文的目的,我不会讨论预处理步骤,但请参考 Kaggle 内核了解全部细节。

在高层次上,我检查了每个特性的分布,删除了异常值,为分类“room_type”创建了虚拟变量(因为只有三个类别),并对特性进行了标准化。

**训练/测试分割**

我将数据集的 70%设置为训练集,剩下的 30%将用作测试集。

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


**基本型号**

让我们首先建立一些基础模型。这里我选择了 **Xgboost** 、**套索回归**和 **KNN** 作为三个基础模型。原则上,当模型在不同的范围内,并且它们的预测误差尽可能不相关时,叠加效果最好,这样单个模型的弱点和偏差可以被其他模型的优点抵消[2]。

**绩效指标**

在评估模型的性能度量方面,我选择使用**平均绝对误差(MAE)** ,它衡量预测值与测量值的差距。

**基本型号的性能**

让我们快速检查三个基本模型的性能(所有默认超参数):

Model: XGBRegressor, MAE: 35.80629559761084
Model: Lasso, MAE: 35.0691542225316
Model: KNeighborsRegressor, MAE: 38.35917874396135


MAEs 在 35-38 之间,这意味着预测价格平均与真实价格相差 35-38 美元。

**使用 mlxtend** 构建堆叠模型

现在,我们可以为元学习者建立基础模型。或者,我们可以使用 *mlxtend* 库([文档](http://rasbt.github.io/mlxtend/user_guide/regressor/StackingCVRegressor/#api))中的‘StackingCVRegressor’来创建快捷方式:

from mlxtend.regressor import StackingCVRegressorstack = StackingCVRegressor(regressors=(XGBRegressor(),
Lasso(), KNeighborsRegressor()),
meta_regressor=Lasso(), cv=10,
use_features_in_secondary=True,
store_train_meta_features=True,
shuffle=False,
random_state=1)


使用相同的三个基础模型,对于元学习者,我选择使用 Lasso。我们也可以尝试其他回归模型作为元学习者,然后在上面构建另一个元学习者(三层堆叠!)注意,在这种配置中,我还选择使用原始训练数据作为元模型的输入,因为它可以为元模型提供更多的上下文。

现在,让我们将训练数据放入模型中,并在测试集上检查性能:

stack.fit(X_train, y_train)
X_test.columns = ['f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11'] # Xgboost internally renames the features
pred = stack.predict(X_test)
score = mean_absolute_error(y_test, pred)
print('Model: {0}, MAE: {1}'.format(type(stack).name, score))

Model: StackingCVRegressor, MAE: 34.01755981865483


我们看到新的 MAE 大约是 34,与最佳基础模型 Lasso 的结果相比减少了 1。

虽然这种差异看起来微不足道,但像这样的小收获实际上可以在排行榜上产生巨大的差异。

如果你想研究集成神经网络,看看这篇论文。

# 警告

尽管有堆叠功能,但还是要记住以下几点:

1.  有效地使用堆栈有时需要一些尝试和错误,并且不能保证堆栈在所有情况下都会提高性能。
2.  堆叠在计算上可能是昂贵的,尤其是当堆叠层数很高时。
3.  随着叠加层数的增加,模型的可解释性降低。对于 Kaggle 竞争来说,这不是一个大问题,但是对于商业案例来说,理解特性的重要性及其对结果变量的增量影响可能更重要。

# 后续步骤

以下是我们接下来可以尝试的几件事:

1.  超参数调整—我们可以在选定的模型中调整一些超参数,以进一步优化性能。在这个过程中,“GridSearchCV”可能是一个有用的工具。
2.  继续堆叠—尝试构建额外的堆叠层,并绘制性能指标与层数的关系图,以检查边际回报递减是否成立(应该成立!).

# 摘要

让我们快速回顾一下。

我们使用 *mlxtend* 库在 Python 中实现了一个简单的两层堆叠回归模型,将其测试 MAE 与三个基本模型的测试 MAE 进行了比较,并观察到了改进。

我希望你喜欢这篇博文,并请分享你的想法:)

查看我的另一篇关于使用 t-SNE 降维的文章:

[](/dimensionality-reduction-using-t-distributed-stochastic-neighbor-embedding-t-sne-on-the-mnist-9d36a3dd4521) [## 在 MNIST 上使用 t-分布随机邻居嵌入(t-SNE)进行降维…

### t-SNE vs PCA vs PCA & t-SNE

towardsdatascience.com](/dimensionality-reduction-using-t-distributed-stochastic-neighbor-embedding-t-sne-on-the-mnist-9d36a3dd4521) 

# 参考

[1][https://machinelementmastery . com/stacking-ensemble-machine-learning-with-python/](https://machinelearningmastery.com/stacking-ensemble-machine-learning-with-python/)
[http://support . SAS . com/resources/papers/proceedings 17/SAS 0437-2017 . pdf](http://support.sas.com/resources/papers/proceedings17/SAS0437-2017.pdf)

# 数据科学家制作网站指南

> 原文:<https://towardsdatascience.com/just-make-a-website-7c57f8f021c?source=collection_archive---------27----------------------->

## 一个全面的指南来学习 HTML/CSS

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e70957877403b6a65d153183f1a6440d.png)

对 HTML 的恐惧是心灵上的——黑仔

除了建模,数据科学家还花大量时间写作。他们写作来交流见解,他们写博客,他们发微博。数据科学领域的主题数量极其庞大。从自然语言处理到面部识别,从预测客户流失到检测罕见的深空事件,关注的范围是无限的。然而,大多数数据科学经验涉及 Python 和数据收集:数据科学家很少处理 HTML、CSS 和 JavaScript,即所谓的 *web dev* 语言*。*具有讽刺意味的是,这种设计经验的缺乏限制了数据科学家的影响力,否则他们可能会在漂亮的作品集或博客中展示他们的项目。实际上,创建自己的数据科学网站或博客是非常容易的,尽管前期对 CSS 和 HTML 有所畏惧,以至于你可以在几天内学会制作一个漂亮的个人网站所需的一切。

无论是个人还是公司使用,制作自己网站的资源多得令人困惑,还有更多关于如何制作的教程,这是其中之一!

我希望这篇文章能为**提供一个干净、最新、最简单的指南,让你对 HTML、CSS 或 JavaScript 一无所知。**

web 开发中最令人困惑的部分甚至不是 HTML 或 CSS。有了 Google 和 Stack Overflow,修改网页外观的技巧和工具就相对简单了。相反,困难来自于理解技术如何交织在一起,以及什么样的抽象构成了一个“网站”

这篇文章将介绍网站的三个主要抽象概念:

1.  **HTML、CSS 和 JavaScript** ,以及你不应该担心它们的原因。
2.  **主持**。你的页面内容实际上在哪里?
3.  **域名**。“你如何通过传统顾客到达那个页面”。com 的名称?

# 步骤 1: HTML、CSS 和 JavaScript

这里有一个他们工作的快速概述,只是为了一个基本的理解或复习。

**HTML…**

是“超文本标记语言”,它只是用于**在最基本的层次**布局网页的构建模块。所有你看到的像`<p>code stuff</p>`一样的*标签*都是 HTML,甚至右击你正在阅读的这个页面,点击‘检查’就会打开你浏览器的编辑器,向你展示这个页面的直接主干布局。HTML 主要关注矩形网页的大块内容。HTML 与样式、颜色或交互性无关。它的代码不是真正的功能性的,或者严格来说不是编程。更确切地说,HTML 是颜料下面的砖块。你不能对它进行样式化或者与之交互,但是你可以对它进行绘画(CSS)并且在之后添加门和窗(JavaScript)。

**CSS…**

是“级联样式表”,它与外观和样式有关。它涉及不同的字体系列、不同的字体大小、颜色、不透明度、分层和形状变化。这看起来是设计中最表面的层面,但是 CSS 实际上为用户体验做了相当多的工作。如果没有由聪明的 CSS 应用驱动的直观感受,即使最好的幕后设计和功能(由 JavaScript 驱动)也是无用的。每当你将光标悬停在社交媒体上的“竖起大拇指”图标上,它就会改变颜色或大小,这就是 CSS 驱动光滑和令人满意的用户体验的无意识力量。

**JavaScript…**

是三人组真正的“编程语言”。由于互连抽象的上下文,编程语言通常是为功能性和交互性保留的名称,而 JavaScript 在网站下以功能和数据流的形式处理这些抽象。每当用户点击按钮、填写表格或搜索栏,或者点击另一个页面的链接时,必须运行不可见的脚本来处理预期的效果。这些以基本函数、类和对象的形式出现。

## 所有这三样东西…

是你不应该为建立自己的网站而担心的事情!除非你是一个网络开发高手,或者是为了迎接挑战而从零开始建立一个网站,否则你可以随时学习 HTML、CSS 和 JavaScript 的基础知识,因为有了模板,这是可能的。

## **什么是模板?**

它是 HTML、CSS 和 JavaScript 的预开发代码库,有足够简单的主干,可以直观地更改。许多入门程序员一开始可能会认为这是*欺骗*,因为这不像是你在建立自己的品牌或者在努力。但这对学习过程至关重要,因为 HTML 和 CSS 最好是自上而下学习**。教程只是不提供学习所必需的个人投资。**

**正式的教程提供了结构化的知识,但是建立你自己的品牌是一个非常混乱和特殊的过程,学习 HTML 标签和 CSS 规则的基础知识通过使用一个漂亮的模板,并在进行中做一些小的修改会更好。首先改变<title>和<p>标签,看看有什么变化,你会很快获得一个个性化的,虽然风格上没有创意的网站。开始改变一些 CSS 规则,看看颜色和字体是如何变化的,很快你就会开发出自己风格化的网站。学习永远是一个<strong class="kx ir">互联体验的过程,使用模板是最快的学习方式。</strong></p></title>**

**使用谷歌查找“免费 html5 模板”或“免费响应 html 模板 2020”等。有无穷无尽的选择,所以只需选择一个看起来漂亮简单的。我使用了 HTML5 UP,这是一个 Creative Commons 免费模板库,但它们中的任何一个都或多或少是一样的。Github pages 还与另一个免费模板源 [Jekyll themes](https://jekyllrb.com/) 集成在一起,因为 Github Pages 上的托管(见步骤 2)是免费的,Jekyll 是构建快速博客或个人网站的一个很好的选择。**

**一旦你下载了一个模板或主题,在你喜欢的代码编辑器中打开文件库作为一个新的项目,它可能是 Visual Studio 代码,然后开始修改!`index.html`文件包含 HTML,您可以在其中修改文本和结构的构建块,而`main.css`文件包含 CSS 规则。只是玩一玩,很快你就会发现没有任何教程你能做多少。打开`index.html`文件(默认情况下应该在浏览器中打开)进行预览,然后通过几个小时的反复试验进行小的修改,观察哪些代码变化产生了哪些视觉变化。然后,**只有当你足够了解你困惑的背景,判断一个教程是否值得时,才使用教程或指南。大多数时候,你真正需要学习的是一长串快速的 Google/Stack-overflow 解决方案。****

# **第二步:托管**

**这是一个相对简单的步骤。建立一个网站背后的大部分努力都是为了让网页看起来更好,其中很大一部分就是 CSS。一旦完成,你只需要找到一个地方让代码“在野外”生存。如果你希望你的网站可以随时随地被访问,那么你应该利用网络上任何主要的免费托管服务。标准的免费托管位置是 [Github Pages](https://guides.github.com/features/pages/) 用于较小的网站,如博客和个人网站,设置它的过程很简单。它很大程度上涉及到用你电脑上的代码在 Github 上创建或初始化一个存储库(例如,在你在 Visual Studio 代码中使用的项目目录中),将它公开,并在“设置”中设置 Github 页面。在“设置”中,向下滚动到“源”,并选择“主分支”,以使该存储库中的 HTML 代码在以下位置可见:your _ username . github . io/your _ project _ repository _ name**

**例如,如果我的 Github 配置文件名为`bluepanda`,我的网站库名为`bamboo`,Github Pages 以上述方式启用,那么在短暂的延迟之后,URL `bluepanda.github.io/bamboo`应该会显示您的网站!这里有一个很好的 Github 页面指南,尽管文档[对于最新的指南总是很有帮助。](https://docs.github.com/en/github/working-with-github-pages/about-github-pages)**

# **第三步:域名**

**你如何最终让你的网站建立在一个自定义域名上,比如`bamboo.com`,而不是略显尴尬的`bluepanda.github.io/bamboo`?这一步很快也很容易,但是由于配置 DNS 设置的复杂性,有点奇怪和吓人。首先,你需要寻找一个域名提供商!这要花钱,但通常是每年 8-12 美元。这就像在你选择的提供商上搜索你定制的想要的域名一样简单,比如`bamboo.com`(快速搜索‘域名提供商’应该足以提供主要的大域名,但它们基本上都是一样的),然后付费!**

**然后是 DNS 设置,这是最棘手的部分。重要的是要知道这很容易做到,你可以担心以后理解不理解。同时,一步一步地跟随[文档](https://docs.github.com/en/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site)绝对值得。这些步骤仅仅包括通过在 Github Pages 设置中添加您的自定义域名(如`bamboo.com`)将一个`CNAME`文件添加到存储库中,以及通过您的 DNS 提供商设置一个`A`记录。如果你遇到困惑,在这里搜索一下可能会有用,但是 Github 关于设置域名的文档非常好。**

**就是这样!使用一个 **1) HTML 模板,2)在 Github 页面上托管它,3)用自定义域名**注册这个库,这些都是创建你自己的网站的步骤!即使您已经对本指南中的一些步骤非常有经验,我希望看到所有步骤是如何连接的会有所帮助,因为我发现本指南中的步骤 1-3 很少集成在一个教程中。**

**感谢阅读!**

# 刚刚发布:BigQuery 用户友好的 SQL 函数

> 原文:<https://towardsdatascience.com/just-released-bigquery-user-friendly-sql-functions-979fca9cd007?source=collection_archive---------14----------------------->

## 从 BigQuery 截断表到动态 SQL 支持;我们涵盖了 Google Cloud 发布的 12 个用户友好的 BigQuery 函数。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/eb9ad3974709f6339f2e1a229c5ccf6e.png)

授权给作者的图像

随着 **12 个新的 BigQuery SQL 特性**的发布,我们很兴奋地看到 [BigQuery](https://www.ancoris.com/google-bigquery) 的能力得到了进一步的提升。谷歌云将这些描述为“*用户友好的 SQL 功能*”。那么,让我们来看看现在有什么可能。

# 1.通过 DDL 添加表列

BigQuery 的新特性是能够通过 ALTER TABLE DDL 语句添加新列。这是具有传统本地数据库平台背景的数据专业人员所期望的标准,所以很高兴看到 Google Cloud 已经承认了这一点。

alter table mydataset.mytable
add column a string,
add column if not exists b geography,
add column c array,
add column d date options(description="my description")


我们喜欢这样的语法:如果一个列还不存在,就只添加一个,这对于幂等部署来说很方便。也完全支持记录。从 [*BigQuery 文档中了解更多信息。*](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_table_add_column_statement)

# 2.截断表格

现在支持 TRUNCATE TABLE,这将满足那些来自本地后台的用户。与 BigQuery 中会产生扫描成本的 DELETE DML 语句不同,TRUNCATE 属于不断增长的 [BigQuery 自由操作](https://cloud.google.com/bigquery/pricing#free)列表。我们肯定会经常用到这个。

truncate table [project_name.] dataset_name.] table_name


*为了降低查询扫描成本,我们建议在需要删除表的全部内容时使用 TRUNCATE 而不是 delete。*

# 3.Unicode 表命名

BigQuery 现在支持 Unicode 表命名。由于支持多语言,表名不再仅限于字母、数字和下划线。

*小心表格命名,确保表格一致、易读,并遵循组织内的命名惯例。*

# 4.BigQuery 联邦表变得(甚至)更好了

在 Ancoris,我们喜欢 BigQuery 中的联邦(外部)表;它们作为一种强大的零数据工程方法,可以轻松地从 Google 云存储中摄取文件,包括常见的格式,如 JSON 和 CSV。

*很高兴看到您现在可以使用 DDL 语句创建外部表了。*

下面的示例创建了一个从两个不同的存储 URIs 读取 CSV 的表:

create external table dataset.CsvTable options(
format = 'CSV',
uris = ['gs://bucket/path1.csv', 'gs://bucket/path2.csv']);


要了解更多信息,请参见这些创建联邦表的例子。我们计划在接下来的几周内做一个技术指导来展示什么是可能的。

# 5.使用 SQL 将数据从 BigQuery 导出到 Google 云存储

这在发行说明中被掩盖了一点,但是在我们看来这是一个非常强大的特性。您现在可以使用新的 EXPORT DATA SQL 命令将 BigQuery 查询的结果导出到 Google 云存储中;支持所有 [Bigquery 支持的数据格式和压缩类型](https://cloud.google.com/bigquery/docs/exporting-data)。

这里有一个取自 [BigQuery 导出数据文档](https://cloud.google.com/bigquery/docs/reference/standard-sql/other-statements#export_data_statement)的例子。

export data options(
uri='gs://bucket/folder/*.csv',
format='CSV',
overwrite=true,
header=true,
field_delimiter=';') as
select field1, field2
from table1
order by field1 limit 10


*很高兴看到没有外出费用;您只需为任何扫描的 BigQuery 数据和存储在 GCS 中的数据付费。*

这似乎加强了谷歌云减少复杂数据工程需求的愿望,这是我们(和我们的许多客户)所共有的。如果将它与从目标 GCS bucket 触发的云函数结合起来,就可以提供一种简单的机制,将数据传递到 BigQuery 之外的数据管道中。

# 6.立即执行(动态 SQL)

BigQuery 现在支持动态 SQL 的执行。语法非常熟悉,特别是对于那些有 MS SQL 背景的人来说。

-- create a temporary table called Books.
execute immediate
‘create temp table books (title string, publish_date int64)’;-- add a row for Hamlet
execute immediate
‘insert into books (title, publish_date) values('Hamlet', 1599)’;


更多例子见 [BigQuery 动态 SQL 支持](https://cloud.google.com/bigquery/docs/reference/standard-sql/scripting#execute_immediate)。

*一般来说,我们非常谨慎地使用动态 SQL,并尽可能避免使用它(主要是因为 SQL 注入的风险,它会使代码更难阅读和调试)。*

# 7.授权的用户定义函数(UDF)

对于那些不熟悉[BigQuery UDF](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions#temporary-udf-syntax)的人来说,这些是 big query 中的标量函数,允许您使用 SQL 或 Javascript(以及相关的 Javascript 库)对数据进行操作。

BigQuery 现在支持授权的 UDF,这允许授权的使用者(通过 IAM)查询数据集中的表,即使调用 UDF 的用户无权访问这些表。你们中有 MS SQL 背景的人,这类似于 SQL Server 中的表值函数的许可;这些通常用作(锁定的)表的安全层,并加强行/列级别的安全性。

# 8.查询结果中有重复的列名

BigQuery 现在允许您在一个查询中多次选择同一个(未分类的)列,方法是附加一个后缀 _n,其中 n 是观察到的重复次数。

# 9.新的 BigQuery 最后一天日期函数

BigQuery 已经很好地支持了使用 SQL 的日期操作。看起来在这个版本中,谷歌云已经认识到了一个常见的商业主导用例;查找给定期间的最后一天,例如一个月的最后一天或一周的最后一天。

新的 LAST_DAY 函数具有直观的语法,易于阅读:

select last_day(’2020-10-23’, week) as last_day_of_week
2020-10-24


*注意默认情况下,这将返回下一个星期六,因为在 BigQuery 中一周从星期日开始。*

要强制一周从星期一开始:

-- the last day of the week
-- (week starting monday)select last_day(’2020-10-23’,
week(monday)) as last_day_of_week
2020-10-25


# 10.BigQuery 中的日期算法

我们习惯于使用 data_add 和 date_sub 函数进行日期运算,但是现在您可以使用+和-操作符来完成这项工作。

-- you can now do this
select ’2020-10-23’ + 2
2020-10-25-- instead of this
select date_add(’2020-10-23’, interval 2 day)
2020-10-25


# 11.新的 BigQuery 字符串函数

许多(总共 14 个)新的用于操作字符串的 [BigQuery SQL 函数](https://cloud.google.com/bigquery/docs/reference/standard-sql/string_functions)。以下是我们特别喜欢的几个:

# 大查询串联运算符“||”

作为一个团队,我们认为这种连接字符串的方法比 concat 函数更容易阅读。

-- the new way
select ’The ’||‘quick ’||‘brown ’||‘fox’ as quip-- the old way
select concat(’The ’,‘quick ’,‘brown ’,‘fox’) as quip


# BigQuery 指令

这将返回字符串中搜索值的索引。注意,字符串中的第一个字符索引为 1,如果没有找到该字符串,则返回 0。

第三个参数是**位置**,表示从哪里开始搜索。默认值为 1。如果提供了负数,这表示从字符串末尾开始-n 个字符。

最后一个参数是**的出现次数**,如果提供了该参数,则指定要搜索的字符串的出现次数,例如 2 表示查找搜索值的第二个出现次数的索引。

select instr(’banana’,‘an’)
2
select instr(’banana’,‘an’,3)
4
select instr(’banana’,‘an’,1, 2)
4
select instr(’banana’,‘an’,1, 3)
0


# BigQuery Soundex

这在我们的列表中,因为我们都认为它非常简洁。这个函数返回一个单词的拼音,表示为 soundex 代码(alpha 后跟 3 个数字)。该算法于 1918 年首次获得专利,可用于模糊逻辑匹配,例如检测人名的拼写错误:

select soundex(’Brian’)
B650
select soundex(’Bryan’)
B650
select soundex(’Briann’)
B650
select soundex(’Brrian’)
B650
select soundex(’Brenda’)
B653


# 12.扩展信息模式

ANSI SQL 标准中指定的 INFORMATION_SCHEMA 允许用户查询包含或引用数据的各种对象或实体的元数据,如表、视图、存储过程和用户定义的函数。下面是 [BigQuery INFORMATION_SCHEMA 文档](https://cloud.google.com/bigquery/docs/information-schema-intro)。

BigQuery 引入了许多新的对象,包括表、视图、例程(存储过程、UDF)和数据集,使得这一点变得更加容易。

select table_name
from mydataset.INFORMATION_SCHEMA.TABLES
where table_name like 'scenario%'


*注意表格是大写的(BigQuery 区分大小写)。*

# 意见

总之,这是对 BigQuery SQL 库的一个很好的补充,我们肯定会在客户端项目中使用它。我们将在即将发布的数据操作系列中讨论其中的一些主题。

# 后续步骤

1.阅读[谷歌云 Bigquery 发布说明](https://cloud.google.com/blog/topics/developers-practitioners/smile-new-user-friendly-sql-capabilities-bigquery)

2.了解更多关于 [Ancoris 数据,分析& AI](https://www.ancoris.com/solutions/data_analytics_ai)

3.与[作者](https://www.linkedin.com/in/google-cloud-platform/)连线

# 刚刚在我的锻炼中使用了机器学习!

> 原文:<https://towardsdatascience.com/just-used-machine-learning-in-my-workout-ff079b8e1939?source=collection_archive---------10----------------------->

## 计算机视觉在健身中的应用演示

我是体重法的忠实粉丝,通常也是锻炼的忠实粉丝,但我不太喜欢去健身房。

此外,在这个由于冠状病毒而被迫封锁的时期,尝试不同的方式来进行健身和训练可能是有用的。

于是我问自己:有没有办法把机器学习用在这方面?我能把两种激情结合起来做点有用的东西吗?

一个主要的问题是有一种方法来验证一个练习的正确性,所以我做了一些实验并尝试了一种方法,发现…

好了,不想剧透什么,就继续看下去了解一下吧!

# 框定问题

和往常一样,让我们从框定问题开始。我们想要实现的是使用视频作为输入,有一种方法来评估练习的正确性。

最佳方案应该是使用实时流,但是现在让我们简单地使用一个文件,因为毕竟我们想在构建之前验证一种方法。

因此,第一步应该是有一个(希望)正确执行的视频,因为它可以用作比较其他视频的基线。

这是第一个视频,在我的地下疲劳室拍摄的:)

基线 ok 执行

我的第一个想法是使用 CNN 来建立一个分类器,但是,除了所需的例子数量之外,我不确定图像序列像素是否有助于训练一个关于练习执行中什么是错什么是对的模型。

所以,我做了一些研究,看看是否有可能使用视频作为输入来获得不同的特征,并找到了一个很棒的库, [OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose) ,一个“用于身体、面部、手和脚估计的实时多人关键点检测库”。

看到演示视频,我明白这可能非常有用,所以我试图将它应用到我的问题中,并有了这个…

使用 OpenPose

(我将在后面的附录中写下所有必要的设置步骤)

正如你在视频中看到的,该库可以很好地跟踪不同的身体部位(使用带有 18 个关键点的 COCO 配置)

很酷的一点是,也可以输出一个 json 文件,一帧一帧地显示所有的位置,所以应该可以用数字来表示一个练习。

因此,做一些辅助功能,并使用 Plotly,这是这个练习看起来如何考虑 y 轴移动-跳过 x 轴,因为给定相机位置不太有用。

姑且称之为**“ok1”**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f13ecf317129b3ea3325c9889175c856.png)

好习题 ok1 的分解分析

很好,下一步是找到一种方法来比较两个不同的执行,看看是否有显著的差异。

让我们首先基于这些指标进行一个视觉比较,我们称这个执行为**“失败 1”**

故障 1

让我们比较一下运动的图表

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/da6c6e451c1049dac93f95560cd8652c.png)

ok1 和 fail1 的比较

存在明显的差异。

让我们尝试另一个失败的表现(**“fail 2”**)

故障 2

让我们与基线正确执行 ok1 进行比较

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bce03fd5a9f9156d5a113e20c4474475.png)

ok1 和 fail2 之间的比较

现在让我们来比较两个好的表现(让我们称之为第二个**“ok 2”**)

ok2

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/dca22a46bde4155cfa6d9817324cd058.png)

ok1 和 ok2 的比较

曲线看起来非常相似,所以我们根据经验测试了这种方法。

现在的问题是:考虑到可能有不同的时间尺度,有没有办法评估这些单变量时间序列曲线之间的相似性?

原来有一种叫做**动态时间扭曲**的东西可以用来“测量两个时间序列之间的相似性”。更多[此处](https://en.wikipedia.org/wiki/Dynamic_time_warping)

Python 中有实现吗?当然,使用 *tslearn.metrics*

所以让我们分析一些数字

首先比较“ok1”和它自己

dtw_value for feature nose_y is 0.0
dtw_value for feature right_shoulder_y is 0.0
dtw_value for feature right_elbow_y is 0.0
dtw_value for feature right_wrist_y is 0.0
dtw_value for feature left_shoulder_y is 0.0
dtw_value for feature left_elbow_y is 0.0
dtw_value for feature left_wrist_y is 0.0
dtw_value for feature right_hip_y is 0.0
dtw_value for feature right_knee_y is 0.0
dtw_value for feature right_ankle_y is 0.0
dtw_value for feature left_hip_y is 0.0
dtw_value for feature left_knee_y is 0.0
dtw_value for feature left_ankle_y is 0.0
dtw_value for feature right_eye_y is 0.0
dtw_value for feature left_eye_y is 0.0
dtw_value for feature right_ear_y is 0.0
dtw_value for feature left_ear_y is 0.0
dtw_value for feature background_y is 0.0


所以 0 值是最大相似度,分数越低表示相似度越高

让我们现在尝试测量 ok1 和 fail1

dtw_value for feature nose_y is 188.00378744123748
dtw_value for feature right_shoulder_y is 155.97642562435527
dtw_value for feature right_elbow_y is 156.39925059973916
dtw_value for feature right_wrist_y is 17.982641407757672
dtw_value for feature left_shoulder_y is 13.5329438534267
dtw_value for feature left_elbow_y is 158.0005797757085
dtw_value for feature left_wrist_y is 27.544745106825722
dtw_value for feature right_hip_y is 12.151614599714703
dtw_value for feature right_knee_y is 191.94638493339747
dtw_value for feature right_ankle_y is 223.23781654997444
dtw_value for feature left_hip_y is 263.0165952996121
dtw_value for feature left_knee_y is 195.8379463587177
dtw_value for feature left_ankle_y is 227.95958454954243
dtw_value for feature right_eye_y is 288.64055642788685
dtw_value for feature left_eye_y is 192.9321060365538
dtw_value for feature right_ear_y is 192.15753964939807
dtw_value for feature left_ear_y is 190.20149442225735
dtw_value for feature background_y is 189.09276308989186


我发现采用一个整体值来获得更简洁的信息很有用,比如中位值

dtw_median : 189.6471287560746


ok1 和 fail2 之间的比较

dtw_value for feature nose_y is 65.28319682858675
dtw_value for feature right_shoulder_y is 38.87442004120449
dtw_value for feature right_elbow_y is 37.75683113715981
dtw_value for feature right_wrist_y is 18.907807197028447
dtw_value for feature left_shoulder_y is 19.50736795264806
dtw_value for feature left_elbow_y is 45.031636992674414
dtw_value for feature left_wrist_y is 36.101698713495466
dtw_value for feature right_hip_y is 13.248353503737741
dtw_value for feature right_knee_y is 39.45295418596681
dtw_value for feature right_ankle_y is 49.27277845829276
dtw_value for feature left_hip_y is 65.78598402395453
dtw_value for feature left_knee_y is 38.59586190254078
dtw_value for feature left_ankle_y is 44.54850474482842
dtw_value for feature right_eye_y is 64.17832564035923
dtw_value for feature left_eye_y is 50.02819053653649
dtw_value for feature right_ear_y is 50.233695101993064
dtw_value for feature left_ear_y is 45.21480605000976
dtw_value for feature background_y is 42.15576012017812dtw_median : 43.35213243250327


ok1 和 ok2 的比较

dtw_value for feature nose_y is 16.023831603583467
dtw_value for feature right_shoulder_y is 11.24889546622242
dtw_value for feature right_elbow_y is 11.94796246520719
dtw_value for feature right_wrist_y is 20.509653605070962
dtw_value for feature left_shoulder_y is 19.65007578484111
dtw_value for feature left_elbow_y is 14.486468134089847
dtw_value for feature left_wrist_y is 7.208783392501132
dtw_value for feature right_hip_y is 14.17544715061928
dtw_value for feature right_knee_y is 25.759515076957445
dtw_value for feature right_ankle_y is 43.123581089700735
dtw_value for feature left_hip_y is 83.91171946754521
dtw_value for feature left_knee_y is 23.860467116131673
dtw_value for feature left_ankle_y is 44.80603683656928
dtw_value for feature right_eye_y is 91.27560108813313
dtw_value for feature left_eye_y is 31.263050533657154
dtw_value for feature right_ear_y is 25.735729785455852
dtw_value for feature left_ear_y is 12.39151408383979
dtw_value for feature background_y is 11.887661376402017dtw_median : 20.079864694956036


因此,该值似乎可以用作一个指标,根据要找到的阈值来比较两次执行的正确性。

作为一个经验性的反检验,让我们从这个值开始尝试其他例子

ok1 和 check1 ->中位值 82。46860 . 66666666666

ok2 和 check 2-->中位值 19660 . 666666666616

确定并检查 3 ->中位值 25。48860 . 88888888861

似乎低于 30 的中位值可能是起始阈值

让我们在视频上看到他们

不允许跳跃!

不完全的

好的。

# 结论

这只是这个实验的开始:假设这是正确的方法,有很多开放点,例如:

*   不同身高的人怎么样?他们也需要一个个人基线,或者可以概括?
*   不同的相机位置怎么样?
*   如何推断阈值?
*   如何对执行中的错误给出更详细的建议?
*   如何在连续视频流中处理练习的相关部分?
*   可以跟踪使用哑铃等工具进行的练习吗?(提示:是的,但是也有特定的对象检测库)

我有一些想法要检查,我会在未来做,即使因为可能性是美妙的。

更新:我从这开始增加了其他功能。在这里[查看](/used-again-machine-learning-in-my-workout-this-time-building-a-personal-trainer-3dfae9730c2b)

想象一个带有摄像头的工作站

*   当您用面部识别输入时,识别您
*   加载您的“wod”(当天锻炼)
*   检查给出提示的练习的正确性
*   向在场或可能与几十人一起参加远程课程的培训师发出执行不当的信号,允许他/她采取纠正措施。

甚至培训也可以根据之前的课程和个人的整体情况进行定制。

一如既往,我对这些技术可能实现的目标和想象感到惊讶,使用它们非常有趣。

同时,祝你锻炼愉快,注意安全。

# 附录

## Docker+OpenPose

我没有直接安装 OpenPose 和所有必要的依赖项,而是选择了 Docker 方法。你可以在这里找到图片:[https://hub.docker.com/r/garyfeng/docker-openpose/](https://hub.docker.com/r/garyfeng/docker-openpose/)

请记住,对于实时方法来说,使用容器可能不是正确的解决方案,因为有很多延迟,但我没有尝试过其他解决方案,所以我不能肯定地说。

但是在运行之前,需要使用 GPU 运行容器,否则 OpenPose 不会启动。这里是所有做这件事的指令(用 Invidia GPU):【https://github.com/NVIDIA/nvidia-docker

您将在命令中看到“privileged”和-e DISPLAY = $ DISPLAY-v/tmp/. X11-UNIX:/tmp/. X11-UNIX 部分,如果需要的话,它们用于访问容器内的摄像机。

在启动 docker 命令之前,请确保执行:

xhost +


所以容器可以连接。

然后,就发射

docker run --privileged --gpus all -v 😕data -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -it garyfeng/docker-openpose:latest


过一会儿,您将进入容器内的 bash shell

如果你查看 [OpenPose 文档](https://github.com/CMU-Perceptual-Computing-Lab/openpose),有很多参数,但是让我们看几个例子

build/examples/openpose/openpose.bin --face


它应该打开相机,并开始检测你脸上的关键点。

我之前用来创建数据的命令是:

build/examples/openpose/openpose.bin --video /data/ --write_video /data/ --no_display --write_keypoint_json /data/


注意启动容器时挂载的“data”文件夹。如果您更改了它,请确保根据命令进行相应的调整。

## Python 代码

现在让我们看一些 Python 代码来处理本文中使用的数据

import pandas as pd
import os
import numpy as npdef read_pose_values(path, file_name):
try:
path, dirs, files = next(os.walk(path))
df_output = pd.DataFrame()
for i in range(len(files)):
if i <=9:
pose_sample = pd.read_json(path_or_buf=path+'/' + file_name + '_00000000000' + str(i) + '_keypoints.json', typ='series')
elif i <= 99:
pose_sample = pd.read_json(path_or_buf=path+'/' + file_name + '_0000000000' + str(i) + '_keypoints.json', typ='series')
else:
pose_sample = pd.read_json(path_or_buf=path+'/' + file_name + '_000000000' + str(i) + '_keypoints.json', typ='series')
df_output = df_output.append(pose_sample, ignore_index = True)
return df_output
except Exception as e:
print(e)


这用于返回一个 DataFrame,其中包含在 OpenPose json 输出路径中找到的所有 json(注意,如果有 1000 个以上的文件,它会中断——肯定要修复:)

'''
Nose – 0, Neck – 1, Right Shoulder – 2, Right Elbow – 3, Right Wrist – 4,
Left Shoulder – 5, Left Elbow – 6, Left Wrist – 7, Right Hip – 8,
Right Knee – 9, Right Ankle – 10, Left Hip – 11, Left Knee – 12,
LAnkle – 13, Right Eye – 14, Left Eye – 15, Right Ear – 16,
Left Ear – 17, Background – 18
'''
from sklearn.preprocessing import MinMaxScalerdef transform_and_transpose(pose_data, label):
output = pd.DataFrame()
for i in range(pose_data.shape[0] -1):
if len(pose_data.people[i]) > 0:
output = output.append(pd.DataFrame(pose_data.people[i][0]['pose_keypoints']).T)# drop confidence detection
for y in range(2,output.shape[1] ,3):
output.drop(columns=[y], inplace=True# rename columns
output.columns = ['nose_x', 'nose_y', 'right_shoulder_x', 'right_shoulder_y', 'right_elbow_x', 'right_elbow_y',
'right_wrist_x', 'right_wrist_y', 'left_shoulder_x', 'left_shoulder_y', 'left_elbow_x', 'left_elbow_y',
'left_wrist_x', 'left_wrist_y', 'right_hip_x', 'right_hip_y', 'right_knee_x', 'right_knee_y',
'right_ankle_x', 'right_ankle_y', 'left_hip_x', 'left_hip_y', 'left_knee_x', 'left_knee_y',
'left_ankle_x', 'left_ankle_y', 'right_eye_x', 'right_eye_y', 'left_eye_x', 'left_eye_y',
'right_ear_x', 'right_ear_y', 'left_ear_x','left_ear_y','background_x', 'background_y']

# interpolate 0 values
output.replace(0, np.nan, inplace=True)
output.interpolate(method ='linear', limit_direction ='forward', inplace=True)return output

这里,我们基于 COCO 设置和基本插值对列进行重命名,如果值为 0(例如,当鼻子在引体向上栏后面时):

def model_exercise(json,name,label):
df_raw = read_pose_values(json,name)
return transform_and_transpose(df_raw,label)df_exercise_1 = model_exercise('','<file_name>','


将所有这些放在一起,使用函数得到最终的数据帧。

现在让我们看一些图表:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
def plot_y_features(df):
fig = make_subplots(rows=3, cols=6, start_cell="top-left")
r = 1
c = 1
X = pd.Series(range(df.shape[0]))
for feature in df.columns:
if '_y' in feature:
fig.add_trace(go.Scatter(x=X, y=df[feature], name=feature),
row=r, col=c)
fig.update_xaxes(title_text=feature, row=r, col=c)
if c < 6:
c = c + 1
else:
c = 1
r = r + 1
fig.update_layout(title_text="Exercise y-axis movements breakdown", width=2000, height=1000)
fig.show()plot_y_features(df_exercise_1)


画出所有位置的支线剧情。

现在比较两个练习:

def plot_comparison_y_features(df1,df2):
fig = make_subplots(rows=3, cols=6, start_cell="top-left")
r = 1
c = 1
X1 = pd.Series(range(df1.shape[0]))
X2 = pd.Series(range(df2.shape[0]))
for feature in df1.columns:
if '_y' in feature:
fig.add_trace(go.Scatter(x=X1, y=df1[feature], name=feature + '_ok'),row=r, col=c)
fig.add_trace(go.Scatter(x=X2, y=df2[feature], name=feature + '_fail'),row=r, col=c)
fig.update_xaxes(title_text=feature, row=r, col=c)
if c < 6:
c = c + 1
else:
c = 1
r = r + 1
fig.update_layout(title_text="Exercise y-axis movements breakdown comparison", width=2000, height=1000)
fig.show()plot_comparison_y_features(df_exercise_1, df_ok2)


最后是动态时间弯曲部分:

def evaluate_dtw(df1,df2,feature, plot=False):
x1 = range(df1.shape[0])
y1 = df1[feature].values x2 = range(df2.shape[0])
y2 = df2[feature].values

dtw_value = evaluate_dtw(df1[feature],df2[feature])
  print("dtw_value for feature {} is {}".format(feature,     dtw_value))
return dtw_valuedef evaluate_dtw_values(df1,df2,plot = False):
dtw_values = []
for feature in df1.columns:
    if '_y' in feature:
        dtw_values.append(dtw(df1,df2,feature,plot))
return pd.DataFrame(dtw_values)

仅此而已!谢谢你。

# 库存预测的合理性

> 原文:<https://towardsdatascience.com/justification-of-stock-market-projections-a954caf49b80?source=collection_archive---------37----------------------->

## 机器学习算法能证明有效市场假说是错误的吗?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2f80b4e189e1c9cb5031b82498fa2d7c.png)

*Github 资源库:*[](https://github.com/waiyannaing/MSFT-Equity-Projection)

****来自《走向数据科学》编辑的提示:*** *虽然我们允许独立作者根据我们的* [*规则和指南*](/questions-96667b06af5) *发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的* [*读者术语*](/readers-terms-b5d780a700a4) *。**

# *简介(预测的有效性)*

*根据美国经济学家、畅销书《华尔街随想》的作者伯顿·戈登·马尔基尔的说法:“在科学的审视下,图表阅读必须与炼金术共享一个基座。”马尔基尔和学术界的许多其他人都认为,根据有效市场假说的条款,股票市场是一个股票价格波动非常大的地方,其结果无法根据过去的数据合理预测。话说回来,是不是经常这样?*

*有效市场假说认为:证券在交易所总是以公允价值交易,股票价格应该代表所有相关信息,即阿尔法的产生是不可实现的。简单地说,该假设断言,在一段时间内的任何给定时间,市场都有能力适应新信息,因此不可能超越它。换句话说,基本面分析比技术分析更有优势。一个人的猜测和另一个人的一样好,或者如马尔基尔的名言所说:“你的猜测和猿的一样好。”*

*现在应该更清楚为什么作为现代金融理论基石的有效市场假说的支持者认为股票市场的预测是无效的。然而,这并不能解释金融服务领域的绝大多数机构,如交易公司、共同基金和对冲基金,它们采用定量交易算法和图表数据,通过技术分析每年产生数十亿美元的利润。行为金融学还表明,股票市场的投资者远非理性,这意味着未来的价格事实上可以在“一定程度上”基于对历史趋势的分析来预测。这意味着股票市场预测的概念肯定有一些优点。*

# *摘要*

*本报告旨在探讨预测证券价格的有效性。更具体地说,它解决了一个研究问题:**根据历史股票数据训练的机器学习模型能否准确预测未来数据,以及预测到什么程度?***

*因此,它的特点是使用一种称为 LSTM(长短期记忆)的深度学习类的机器学习算法进行单变量时间序列分析。微软公司(MSFT)的历史股票数据用于数据探索、预处理、后处理、可视化以及模型拟合和评估。从最近的日期开始的十五个营业日的股票市场预测也在接近结束时进行。此外,均方误差、均方根误差和 R 平方作为评估模型总体性能的主要估计量。*

*与实际价格相比,该模型生成的结果值相当准确。因此,可以得出结论,机器学习确实可以是在很大程度上预测股票数据的有效方法。*

*包含整个程序的 GitHub 库可以在[这里](https://github.com/waiyannaing/MSFT-Equity-Projection)访问。*

# *方法学*

## *数据采集-*

*MSFT 的数据集是通过名为 *Tinngo* 的金融市场 API(应用程序编程接口)获得的,并使用 pandas_datareader 包进行访问。为了了解正在处理的数据,下面是将其转换为数据框后的原始形式。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a6f00cbc7580be7061cc939f6c8b8034.png)*

*数据集由 14 个要素组成,如列所示。*

## *数据预处理-*

*在最初的清理/格式化阶段实施了一些简单的过程,以便为将来使用数据集做准备。*

*   *所有列标题的第一个字母都大写。*
*   *日期列中的值被转换为日期时间对象。*
*   *从日期列的值中删除了时间值,因为它不涉及 MSFT 价格的日常时间序列模式。*
*   *创建了一个循环来检查任何缺少的值;对于所有列中的所有行,它都返回 false,这表明没有丢失值。*

*生成的新数据框如下所示:*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b969af63522c480decfbf74a3c18a3c2.png)*

## *初步数据可视化-*

*深入了解 MSFT 价格运动的复杂本质非常重要,因为这有助于在未来决定最有效的机器学习模型。由于“收盘”功能涵盖了每个交易日结束时股票的现金价值,因此执行了仅与“收盘”相关的某些可视化方法。*

*绘制了一个箱线图和一个补充描述图,作为数据可视化这一阶段的第一步。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fd6d15415fb719cadfea2b22ace37944.png)**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/79d47ca2003aec8b9722c75a7889fb03.png)*

*从箱线图可以很容易地看出,似乎没有超出分布数据的最小和最大范围的极端异常值。*

*图表中的高标准差确实揭示了过去五年 MSFT 价格的波动性。更准确地说,在 96.44 美元的平均值周围有 41.91 美元的离差。此外,这个值必须有所保留,因为标准差的项可能与基础证券的价格有关。这意味着标准差的值可以反映股票价格而不是波动性。因此,使用变异系数来评估波动的真实程度,变异系数代表标准差与平均值的比率。这有助于理解样本中数据相对于总体均值的可变性程度。*

*由此得出的变异系数为:41.91 ÷ 96.44 = 0.4346。由于该值远低于 1,因此可以有把握地假设 MSFT 总体上不像之前假设的那样高度不稳定。此外,考虑到微软公司基于其资产负债表的强大财务健康,预计与其股权相关的风险应处于较低水平。*

*为了更好地显示 MSFT 证券的过去趋势,绘制了一个折线图。图表的主要亮点是 2020 年 3 月至 6 月证券价值的大幅下降和快速恢复。这种极端的波动性可以解释为由于最近的 2020 年新冠肺炎疫情对整个股票市场的忧虑态度。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/62f1b414cc3ec0820ea3c31bd9de72d7.png)*

## *型号选择-*

*如前所述,选择了单变量时间序列分析,该分析用单个时间相关变量检查一个序列。这是在初步数据可视化阶段之后完成的;在做出这个决定之前,我们考虑了一些因素:*

*   *报告的目的不是要找出多个系列之间的相关关系。更确切地说,它是分析单个价格序列如何在其自身的历史视角上发展的行为。*
*   *数据集中的许多其他特征已被证明对收盘价影响很小甚至没有影响。股息是一个例外;然而,API 并不提供关于它的数据。*
*   *虽然特征高,低,开放和他们的调整后的对应物可能对收盘价有一个小的影响,这可能只是通过引入噪音使模型过于复杂。*

*考虑到这些因素,建立了长短期记忆(LSTM)神经网络作为执行单变量时间序列预测的最佳选择。这些推理属于 LSTM 的架构,它在时间序列的每一步存储信息的能力,以及研究问题的性质。*

*为了理解 LSTM 网络的结构,首先必须理解人工神经网络和递归神经网络(RNNs)的概念。人工神经网络基于互连的数据处理组件的网络,这些组件被称为组织成层的节点。一层中的给定节点通过权重与前面层中的所有其他节点相连,权重影响信号的强度和网络的输出。有三种类型的节点:1)收集数据的输入节点,2)生成值的输出节点,3)修改数据的隐藏节点。*

*RNN 是一种人工神经网络,它以前馈方式工作,允许信息从一个步骤按顺序传播到另一个步骤。然而,与基本前馈神经网络不同,RNNs 在层之间具有递归关系。这意味着他们利用反馈回路,即所谓的时间反向传播,将细节传回网络,这样来自先前输入的信息就可以持续。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ce9ed6a2d5d360bb512d44d26069f785.png)*

*展开的 RNN |来源:https://colah.github.io/posts/2015–08-Understanding-LSTMs/*

*然而,RNNs 也处理消失梯度问题,即在时间段的大间隙之间逐渐丢失信息。当更新神经网络中的权重的梯度由于时间上的反向传播而收缩时,就会发生这种情况。长期短期记忆网络通过实施内部机制(细胞状态和门)来调节信息流,从而改善了这一缺点。细胞状态在整个序列处理过程中传输相关信息,而门是不同的神经网络,它选择哪些信息可以在细胞状态中持续存在。有三种门:1)遗忘门,它选择相关信息来存储和传递,2)输入门,它更新单元状态,3)输出门,它确定随后的隐藏状态。这些操作使得 LSTM 模型善于学习长期依赖关系。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cace770db820b756504598221c2c97d0.png)*

*https://colah.github.io/posts/2015–08-Understanding-LSTMs/ LSTM 网络中的复读模块|来源*

*因此,LSTM 网络被确定为处理报告时间序列问题的最佳选择。有关 rnn 和 LSTMs 的更多信息可在此处查看。*

## *数据-后处理-*

*在本节中,来自预处理阶段的数据被进一步讨论,目的是为 LSTM 模型做准备。形成了一个新的数据帧,该数据帧仅由“Close”组成,并以“Date”作为索引值。由于日终现金价值最能代表某一特定日的证券市场价格,因此重点是“收盘”。*

*LSTM 模型对比例很敏感;因此,来自新数据帧的数据通过从 0 到 1 的缩放进行标准化。这将提高网络收敛的速度。*

#Scaling Datamms = MinMaxScaler(feature_range = (0,1))scaled_close = mms.fit_transform(df_close).reshape(-1,1)


*新的数据集然后被分成两个部分:80%的训练和 20%的测试。这将允许在最初 80%的数据(训练集)上训练模型,然后在剩余部分(测试集)上重新评估其性能。*

#Splitting Train/Test Datatrain_ratio = 0.80rolling = 60train_data = np.array(scaled_close[:int(len(df_close)train_ratio)])test_data = np.array(scaled_close[int(len(train_data))-rolling:])*


*“滚动”变量代表时间步长,即模型分析产生输出的天数。考虑下面的例子:*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/38c14c3f1d6f170d41ee4b45fadefbfd.png)*

*有一个用于训练机器学习模型的值序列。在每一行中,序列的四个值作为输入,随后的第五个值作为输出;随着行的前进,输入和输出组在序列中向下移动一个值。变量“滚动”代表用于产生输出的输入数量。这个概念进一步应用于将训练集和测试集分成输入集和输出集。*

#Separating x/y Training Setsx_train = []y_train = []for i in range(rolling, len(train_data)): x_train.append(train_data[i-rolling:i,0]) y_train.append(train_data[i,0])#Separating x/y Testing Sets*x_test = []y_test = df_close[int(len(train_data)):]for i in range(rolling, len(test_data)): x_test.append(test_data[i-rolling:i])*


*LSTM 网络需要三维数组数据作为输入。第一个维度表示批量大小,第二个维度描述时间步长,最后一个维度描述特征。因此,输入被整形以符合这些要求。*

#Reshaping x/y Setsx_train, y_train = np.array(x_train), np.array(y_train)x_train_shape = x_train.shape[0]x_train = np.reshape(x_train, (x_train_shape, rolling, 1))x_test, y_test = np.array(x_test), np.array(y_test)x_test_shape = x_test.shape[0]x_test = np.reshape(x_test, (x_test_shape, rolling, 1))


## *模型制作-*

*为了构建 LSTM 模型,从 Keras 库中导入了某些模块。*

from keras.models import Sequentialfrom keras.layers import LSTMfrom keras.layers import Densefrom keras.layers import Dropout


*1)顺序将被用作初始化神经网络的构造器,2) LSTM 将协助添加长短期记忆层,3)密集将添加密集连接的神经网络层 4)丢弃将添加丢弃层以防止模型过度拟合。*

*生成的模型如下所示:*

#LSTM Modellstm = Sequential()lstm.add(LSTM(rolling, return_sequences = True, input_shape =(rolling, 1)))lstm.add(Dropout(0.2))lstm.add(LSTM(rolling, return_sequences = True))lstm.add(Dropout(0.2))lstm.add(LSTM(rolling))lstm.add(Dropout(0.2))lstm.add(Dense(1)) lstm.compile(optimizer = 'adam', loss = 'mse', metrics = ['mean_squared_error'])


*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ca67b4a05577aa2c755814a30ddb6a1e.png)*

*LSTM 模型是用以下参数创建的:*

*   *60 个单位作为 LSTM 层中输出空间(时间步长)的维度。*
*   *Return_sequences = True,返回每个输入时间步长和堆叠的隐藏状态输出*
*   *LSTM 层。(以便随后的 LSTM 层具有三维序列)*
*   *0.2 作为丢弃层的输入,丢弃 20%的层,以防止模型过度拟合。*
*   *密集层中的输入 1 指定一个单位的输出。*
*   *Adam optimizer 是一种更新网络权重的优化算法,用于编译模型。*
*   *均方误差被设置为损失优化器。*

*然后用来自数据训练部分的输入和输出集来拟合该模型。然后用某些特征对其进行训练,例如 epochs,其指示学习算法将在整个数据集中工作的次数,设置为 60,分配给 x_train.shape[0]的批量大小,以及给定测试集的验证集。*

#LSTM Model Fittinglstm.fit(x_train, y_train, validation_data=(x_test, y_test),epochs = 60, batch_size = 50, verbose = 1)


## *模型评估指标-*

*被选择用来评估 LSTM 模型性能的三个估计量是均方误差(MSE)、均方根误差(RMSE)和 R 平方。MSE 应评估误差平方和返回误差方差的平均值。RMSE 是 MSE 的平方根版本,它将计算残差(预测误差)的标准偏差。最后,R 平方度量将展示回归线与实际数据点的拟合,因为它测量模型所解释的响应变量变化的百分比。*

# *结果*

*使用 Sequential 的 predict()和 MinMaxScaler 的 inverse_transform()函数,从拟合的模型生成预测,并从 0 到 1 的范围内重新缩放。这导致了两套价格预测;一个用于训练部分,一个用于测试部分。*

*模型在训练集上的性能由三个模型评估度量来评估。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/47d821f1937fe1093b57161220a7e6fa.png)*

*这些 MSE 和 RMSE 值立即表明在实际历史数据点周围没有太多误差,因为两者都接近于 0。R 平方的值表明 MSFT 99.53%的价格可以用模型解释。虽然这些结果最初可能说明了预测的惊人准确性,但存在严重的过度拟合问题,因为它可能无法很好地转化为看不见的数据。*

*通过绘制实际训练数据集及其预测值,可以更好地可视化这些指标。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4c72e6d555357431b20caea55a116241.png)*

*该模型在测试集上的性能由相同的三个评估指标进一步评估。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a9b6e5f0f6121b018d8005ebadb08ef0.png)*

*与训练集相比,MSE 和 RMSE 更高,R 平方更低。然而,这些 MSE 和 RMSE 仍然被认为非常低。这证明了模型集与实际值相差不大。R 平方值表明 94.2%的 MSFT 价格可以用模型解释。*

*再次,这是可视化的图形实际训练数据集和预测值。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2f80b4e189e1c9cb5031b82498fa2d7c.png)*

*实际值与预测值的图表:*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7805cf8dccd7ac2e8a6f3b261441d722.png)*

# *讨论*

*可以有一定把握地说,LSTM 模型在预测股票价格方面证明是成功的。与真实数据点相比,特别是测试部分的预测值相当准确;0.17 的 MSE 和 0.41 的 RMSE 接近于 0 并且非常低,因此表明平均误差偏差很小。这一印象被 0.942 的 R 平方进一步证实,因为该模型能够解释测试集中 94.2%的 MSFT 股票价格。*

*虽然最初有人担心该模型在训练集上过度拟合,因为它在所有三个指标上都非常接近完美,但实际上它最终很好地转变为预测测试集上的未知数据。然而,仍然有一个问题值得关注,即为什么模型表现得如此之好,它涉及单步和多步时间序列预测之间的差异。迄今为止建立的模型是单步时间序列预测模型,因为它使用几个输入来生成一个输出。但是,请考虑已定型的模型是否是多步时间序列投影,在这种情况下,也将接受多个输入并生成多个输出。毫无疑问会有不同的结果。*

*创建多步时间序列投影的一种常用方法是通过递归方法,这种方法包括制作单个投影并将其附加到下一组输入中,以预测后续的时间步。*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cf5cf310bf9674c1e178de2a50200fbf.png)*

*然而,它也引入了将早期误差传播到未来预测中的问题;来自时段 t 和 t+1 的预测误差将延续到后续时段。因此,如果单个预测在某种程度上不准确,则下一个值链很有可能变得越来越错误,因为错误的值将被用作未来的输入。因此,由于误差传播,多步时间序列预测模型有可能在更长的预测时间内退化。*

*在本报告中使用的单步模型的情况下,即使一个预测完全偏离实际值,后续的预测也很有可能被实际值带回正轨。*

*话又说回来,这个关注点不应该完全抹黑模型的准确性。如前所述,该模型在捕获 60 个数据点作为输入以生成一个输出方面表现良好,这平均只会在训练数据上偏离 0.19 美元,在未看到的数据上偏离 0.41 美元。因此,即使在递归多步时间序列预测的情况下,基于该模型的预测在未来的某个时期也应该是相当准确的,很可能小于 60 点。*

# *结论*

*预测股市还是有一些好处的,尤其是通过像机器学习这样强大的方法。该报告的研究结果表明,在单步时间序列预测问题的情况下,使用 LSTM 网络可以产生具有良好准确性的结果,更具体地说是 94.2%。对此的解释可能是,尽管有效市场假说可能在很长一段时间内成立,但它并不能完全解释证券价格的短期行为。如前所述,行为金融学展示了这样一个事实:股票市场在很大程度上是由非理性投资者决策和经济趋势驱动的;一个恰当的例子是,2020 年 MSFT 股票价格的大幅下跌是由新冠肺炎引起的。因此,在很大程度上,理解股票市场的行为可以被视为一个序列问题。*

*话说回来,报告的调查结果也有些局限。它只真正调查了一个序列的行为,因此,它不能建立各种其他因素和证券价格之间的关系。因此,如果该模型在未来继续被使用,在面对不可预见的事件时,可能会有许多实例产生完全有缺陷的预测。此外,基于单步时间序列预测模型的研究结果也存在问题。看看多步系列预测模型会产生什么样的结果,以及它将如何回答本报告的研究问题,这将是很有趣的。如果将来要进行任何改进,这两个考虑因素是改进的主要候选因素。*

# *十五天预测(方法到结果)*

*为了全面总结本报告,从最近的交易日期开始,使用递归多步时间序列预测方法对 MSFT 价格进行十五天预测。选定数字 15 是因为它小于“滚动”(时间步长)值的一半。因此,之前构建的 LSTM 模型使用 MSFT 的所有历史数据进行了重新训练,没有拆分。*

#Creating Inputs/ Outputs Using Whole Test Datadf_final = np.array(scaled_close)x = [] y = []train_amt = 60for i in range(train_amt, len(df_final)): x.append(df_final[i-train_amt:i,0]) y.append(df_final[i,0])x, y = np.array(x), np.array(y)x_shape = x.shape[0]x = np.reshape(x, (x_shape, train_amt, 1))y = np.reshape(y, (-1,1))


*训练完模型后,将创建一个循环,以接受新的单个输出作为未来的输入,并生成后续输出。*

#Projection Setsteps = 15df_final = pd.DataFrame(scaled_close)for x in range (0,steps): data = np.array(df_final[len(df_final)-train_amt + x:]) x_project = np.array(data) x_project_shape = x_project.shape[0] x_project = np.reshape(x_project, (1, -1, 1)) projected_data = pd.DataFrame(lstm_final.predict(x_project)) df_final = df_final.append(projected_data)#Rescaling the Dataset*df_final = mms.inverse_transform(df_final)*


*构造了一个新的函数,增加“n”个新的营业日来预测“n”个价格。*

*#Creating a Function For Adding Business Daysimport datetimedef add_bdays(from_date, add_days): bdays_add = add_days curr_date = from_date while bdays_add > 0: curr_date += datetime.timedelta(days=1) weekday = curr_date.weekday() if weekday >= 5:

        continue bdays_add -= 1return curr_date*

*在创建新的远期指数后,将构建一个仅用于价格预测的新数据框架。*

#Creating Date Index With 15 Days Forwarddf_date = df[['Date']]start_date = str(df_date['Date'][0])end_date = df_date[‘Date'].iloc[-1]proj_dates = []for x in range(1,steps+1): proj_dates.append(add_bdays(end_date,x))df_proj_dates = pd.DataFrame(proj_dates)df_append_date = df_date['Date'].append(df_proj_dates)date_array = np.array(df_append_date)#Creating New DataFrame For Forward Dates*df_new = pd.DataFrame(df_final, columns=['Projected Close'])df_new['Date'] = date_arraydf_new.set_index('Date', inplace = True)projected_df = df_new.tail(steps)projected_df*


*由此得出的价格预测是:*

*![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9946ee5d08fa186fd845002a83f0ce8d.png)**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c0fa7c48ee1db03df721eab01d56410d.png)**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0e54fe298b7b985cab3f093deababde1.png)*

# *资源*

*[http://colah.github.io/posts/2015-08-Understanding-](http://colah.github.io/posts/2015-08-Understanding-LSTMs/)*

*[LSTMs/](http://colah.github.io/posts/2015-08-Understanding-LSTMs/)[https://machine learning mastery . com/gentle-introduction-long-short-term-memory-networks-experts/](https://machinelearningmastery.com/gentle-introduction-long-short-term-memory-networks-experts/)*

*【http://vision.stanford.edu/pdf/KarpathyICLR2016.pdf *

*[https://machine learning mastery . com/multi-step-time-series-forecasting-with-machine-learning-models-for-household-consumption-electricity-consumption/](https://machinelearningmastery.com/multi-step-time-series-forecasting-with-machine-learning-models-for-household-electricity-consumption/)*

*[https://www . research gate . net/publication/262450459 _ Methods _ for _ Multi-Step _ Time _ Series _ Forecasting _ with _ Neural _ Networks](https://www.researchgate.net/publication/262450459_Methods_for_Multi-Step_Time_Series_Forecasting_with_Neural_Networks)*

# Chrome 上的 GitHub 面向专业人士的 Git 设置!

> 原文:<https://towardsdatascience.com/jvisions-top-5-chrome-extensions-for-github-a356c7800069?source=collection_archive---------41----------------------->

## Github 的 5 个 Chrome 扩展可以提高您的工作效率!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/53b5598c75f22e914f3dc8eead6f7455.png)

图片通过 [Pixabay](https://pixabay.com/vectors/processor-bar-machine-strong-41295/)

对于那些尚未探索 [Chrome 扩展](https://support.google.com/chrome_webstore/answer/2664769?hl=en)(根据 [Chrome 网上商店](https://chrome.google.com/webstore/category/extensions))的人来说,如今有大量的扩展可以添加——每一个都旨在增强界面、进步的潜力(即生产力),以及各种意图的可用功能。最近,我正在建立一个系统,作为我研究的一部分——应用机器学习,通常以图像作为输入/输出信号。因此,让我分享一下我觉得有用的 Chrome 专用设置。换句话说,让我分享一下我在准备 SW 开发和使用 Git、Github 和 Google 的 Chrome 的版本控制源代码时设置浏览器的方式。

不管您的具体关注点是什么,以下扩展都与任何使用 Github 的人相关。现在,除了本地设置之外,对于 mac 用户来说,可以通过关注我以前的媒体博客像专业人士一样进行 git 设置,我们可以通过添加基于 Github 的扩展来扩展我们的功能。

其余部分的组织如下。前面的五个子部分涵盖了五个扩展(即每个部分一个)。注意,顺序是不明确的(即前者不一定比后者评级高,反之亦然)。接下来,我们得出结论,其中包括一个列表,列出了所有相关项目的*荣誉提名*和*参考文献*。这里列出了包括的扩展:

1.  增强型 Github
2.  Github 代码折叠
3.  Github 黑暗主题
4.  精制 Github
5.  八叉树

每个扩展的呈现是相同的:子部分以 Chrome 网络商店中列出的扩展的名称、URL、视图(即,预告图像)开始。此外,还显示了描述每个扩展在使用时的截图——通常快照跨越了前的*和*后的*视图。*

当然,首先必须安装基于 Chromium 的浏览器。几个选项是[谷歌的 Chrome](https://www.google.com/chrome/?brand=CHBF&ds_kid=43700052784036214&utm_source=bing&utm_medium=cpc&utm_campaign=1008138%20%7C%20Chrome%20Win10%20%7C%20DR%20%7C%20ESS01%20%7C%20NA%20%7C%20US%20%7C%20en%20%7C%20Desk%20%7C%20BING%20SEM%20%7C%20BKWS%20~%20Top%20KWDS%20-%20Exact%20-%20NEW&utm_term=google%20chrome&utm_content=Desk%20%7C%20BING%20SEM%20%7C%20BKWS%20%7C%20Exact%20~%20Google%20Chrome%20~%20Top%20KWDS&gclid=COLug8C94uoCFcnwswod5tsEbA&gclsrc=ds) 、 [Mozilla Firefox](https://www.mozilla.org/en-US/exp/firefox/new/) 和[微软 Edge](https://www.microsoft.com/en-us/edge) (2020 年或更晚)——这些,以及其他几个基于 Chrome 的浏览器,允许安装 Chrome 扩展。

注意,对于谷歌以外的浏览器,允许安装 Chrome 扩展的选项必须是设置中上的*(例如,这里是 Edge [ [link](https://www.onmsft.com/how-to/how-to-install-extensions-from-the-chrome-store-on-edge-insider#:~:text=Here%20are%20the%20steps%20required%20to%20add%20extensions,ability%20to%20allow%20extensions%20from%20other%20stores.%20) ]的步骤)。*

## 增强型 Github

chrome://extensions/?id = anlikcnbgdeidpacdbdljnabclhahhmd

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d5c2c13ff4e242c7b1812903e014df7d.png)

**图 1。预告图像。**增强版 Github,如 Chrome 网上商店所见。

如预告图(图 1)中所述,列出了每个文件的文件大小,并允许从文件查看器下载单个文件(即,通常必须打开单个文件才能下载专有内容)。尽管可能很简单,但这个扩展经常会派上用场。图 2 和图 3 分别示出了前视图和后视图。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7ab3ca0b206f0206c2fb15766589299c.png)

**图二。在*增强 Github 之前。*** *注意视图是默认的 Github 界面。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1619ef3f1052c6eeb03860075a85f479.png)

**图 3。激活*后增强 Github。*** *红色边界框显示差异(即图 2)。注意文件大小,以及下载单个文件的图标(绿色边框)。*

## Github 代码折叠

chrome://extensions/?id = lefcpjbffalgdcdgidjnmabfenecjdf

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b2da999c4dbc0aecad692aff6e6d74b2.png)

**图 4。预告图像。** Github 代码折叠,在 Chrome 网上商店看到的。

顾名思义(图 4),这个扩展支持直接在浏览器中进行代码折叠!图 5 中描绘的是与 Python 源代码一起激活和使用的扩展。然而,该工具是复杂的,因为它根据软件语言自动适应(即,自动设置),用于通用样式指南和文档语法(例如, [docstring](https://www.pythonforbeginners.com/basics/python-docstrings/) , [Pep 8](https://pep8.org/) , [Doxygen](https://www.doxygen.nl/index.html) )。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ffc7ae847d832ee0f4986d6888d8b719.png)

**图 5。通过 Chrome 扩展进行代码折叠。**注意代码折叠设置为 on(顶部)的函数定义的放大视图。此外,靠近底部折叠的代码显示了条件体也可以是可折叠的。切换按钮是箭头形状的,可以在左边看到(即,通过行号)。

## Github 黑暗主题

chrome://extensions/?id = odkdlljoangmamjilkamahebpkpgpeacp

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2155a7e4fdf77f99ae6f767589e890ea.png)

**图 8。预告图像。** Github 黑暗主题,如 Chrome 网上商店所见。

简而言之,通过使背景颜色变暗来减轻视图——将 Github 的主题设置为暗色(图 8 和图 9)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/5644dc7ec4bf540ca74aae371524d67f.png)

**图 9。Github 黑暗主题扩展。** Github 的外观和感觉现在是黑暗模式——一种许多人更喜欢的模式。

## 精制 GitHub

chrome://extensions/?id = hlepfoohegkhhmjioechaddaejaokhf

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/733081659a7ab74bfb0fb66e06d7d1af.png)

**图 8。预告图像。**精制的 GitHub,如 Chrome 网上商店所见。

这个扩展带来了一系列功能增强(图 8)!项目报告([链接](https://github.com/sindresorhus/refined-github/blob/master/readme.md))中包含的自述文件中有一个详尽的列表,该列表列出了功能的目标级别(即,存储库、文件管理、基于代码、评论(管理和审阅)、对话、PR 和提交(查看和编辑)、配置文件、新闻订阅等)。此外,还允许定制(例如,基于 Javascript 的定制 CSS)。图 9 是示出所包括的几个特征的多个视图的 GIF 图像。尽管如此,还是有将近一百个特性。此外,该扩展集成的简单性使其成为一个重要的工具(即,没有学习曲线,如果不喜欢某个特性,就不要使用它,因为该扩展对界面的整体外观影响很小)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ef55fa76dcb159dcb92438de63408c7c.png)

**图 9。插图显示了作为改进的 Github 扩展的一部分的特性。Github 的外观和感觉现在是黑暗模式——一种许多人更喜欢的模式。(图片来自项目的 Github,[https://github.com/sindresorhus/refined-github](https://github.com/sindresorhus/refined-github))。)**

## 八叉树

chrome://extensions/?id = bkhaagjahfmjljalopjnoealnfndnagc

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e9ec51c6a9cf1f7fbc2447c89f7f40a5.png)

**图 10。预告图像。** Octotree,见于 Chrome 网上商店。

Octotree(图 10)是通过 GitHub 浏览项目时增强文件可访问性的一种简单方法。正如许多人可能同意的那样,传统的文件查看器对于观察项目的整体结构或快速打开嵌套在本地目录中的文件是最佳的(图 11)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3464493d4334120213eaba9ddfda8299.png)

**图 11。八棵树的景色。**该扩展允许快速浏览文件。

图 12 示出了增强型观察器的剪辑。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bf89770aa58d01996601a180a7225378.png)

**图 12。八叉树的增强视图。**可以快速查看和打开文件。

# 结论

因此,它总结了五个对 GitHub 有用的 Chrome 扩展。新的扩展会定期出现;仅 GitHub 就有几十个扩展可以通过 Chrome 网上商店下载。除此之外,还有许多扩展 to 和 [themes](https://chrome.google.com/webstore/category/themes) 来增强最流行的网站(例如 [Medium Code Highlighter](https://chrome.google.com/webstore/detail/medium-code-highlighter/apdaagmhepellbjjbnaljaocodjjjjfd) ,这对于我过去的许多帖子来说是必不可少的)。如果你还没有去过的话,肯定值得去逛逛这家商店!

最后,这里是荣誉提名和相关参考。

## 荣誉提名

以下是其他基于 Github 的扩展,可能会有用。

*   [Git 历史浏览器扩展](https://chrome.google.com/webstore/detail/git-history-browser-exten/laghnmifffncfonaoffcndocllegejnf)
*   [GitHub 的头像](https://chrome.google.com/webstore/detail/avatars-for-github/pgjmdbklnfklcjfbonjfkdhaonlfogbb)
*   [Git Cheatsheet](https://chrome.google.com/webstore/detail/git-cheat-sheet/mjdmgoiobnbkfcfjcceaodlcodhpokgn)
*   [GitHub 等距投稿](https://chrome.google.com/webstore/detail/github-isometric-contribu/mjoedlfflcchnleknnceiplgaeoegien)
*   GitHub Hovercard
*   [GitHub 强大的自动完成功能](https://chrome.google.com/webstore/detail/awesome-autocomplete-for/djkfdjpoelphhdclfjhnffmnlnoknfnd)
*   [GitHub 存储库大小](https://chrome.google.com/webstore/detail/github-repository-size/apnjnioapinblneaedefcnopcjepgkci)
*   [ZenHub for GitHub](https://chrome.google.com/webstore/detail/zenhub-for-github/ogcgkffhplmphkaahpmffcafajaocjbd)
*   [还有更多](https://chrome.google.com/webstore/search/github?_category=extensions)

如果你有最喜欢的扩展,不管是不是这个博客的一部分,请在下面评论中分享。

## 相关参考文献

像现在的大多数话题一样,网上有大量的资源,大体上涵盖了 Chrome 扩展。这里有一些精选的。

*   [Alexander Isora 为极客设计的 14 款热铬扩展](https://medium.com/hackernoon/14-hot-chrome-extensions-for-geeks-c815a3883f9e)🦄
*   [25 个扩展、应用程序、&让您的工作效率提高两倍](https://medium.com/hackernoon/25-chrome-extensions-apps-and-hacks-to-2x-your-productivity-dd4b13e95443),作者 [Brian Tan](https://medium.com/u/51d08cbd58a1?source=post_page-----a356c7800069--------------------------------)
*   [杰克·普林斯](https://medium.com/better-programming/how-to-create-and-publish-a-chrome-extension-in-20-minutes-6dc8395d7153)在 20 分钟内创建并发布 Chrome 扩展
*   [想要 GitHub 通知。所以我做了一个 Chrome 扩展](https://medium.com/free-code-camp/i-wanted-real-time-github-push-notifications-so-i-built-a-chrome-extension-7e6be0611e4),作者是 [Stacy Goh](https://medium.com/u/51819d0a98cc?source=post_page-----a356c7800069--------------------------------)
*   同样,还有更多!

评论是其他读者和我最喜欢的资源!

这篇文章是我的非正式博客系列*Git Like Pro*、*、*的第二篇。另一篇涵盖了在 Mac 计算机上正确设置 Git 的步骤!检查一下, [Git 像专业人士一样设置](https://medium.com/better-programming/git-setup-like-a-pro-67bc3fe86fd1)!

现在,我不知道你,但我准备写一些代码!:) :) :)

# k-意味着比 Scikit-learn 的 25 行代码快 8 倍,错误低 27 倍

> 原文:<https://towardsdatascience.com/k-means-8x-faster-27x-lower-error-than-scikit-learns-in-25-lines-eaedc7a3a0c8?source=collection_archive---------8----------------------->

## 脸书·费斯图书馆又罢工了

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/68e8b2771b55a98cab1478fdb9446e69.png)

k-均值迭代([来源](https://en.wikipedia.org/wiki/K-means_clustering#/media/File:K-means_convergence.gif))

## 介绍

在我上一篇关于 faiss 库的文章[中,我用 20 行代码展示了如何使用](/make-knn-300-times-faster-than-scikit-learns-in-20-lines-5e29d74e76bb)[脸书的 faiss 库](https://github.com/facebookresearch/faiss)让 kNN 比 Scikit-learn 快 300 倍。但是我们可以用它做更多的事情,包括更快更准确的 K-Means 聚类,只用了 25 行代码!

K-Means 是一种迭代算法,它将数据点聚类成 k 个聚类,每个聚类用一个均值/中心点(质心)表示。训练从一些最初的猜测开始,然后在两个步骤之间交替:分配和更新。

在分配阶段,我们将每个点分配给最近的聚类(使用点和质心之间的欧几里德距离),在更新步骤中,我们重新计算每个质心,从当前步骤中分配给该聚类的所有点计算平均点。

聚类的最终质量被计算为聚类内距离的总和,其中对于每个聚类,我们计算该聚类中的点与其质心之间的欧几里德距离的总和。这也叫惯性。

对于预测,我们在新点和质心之间执行 1 最近邻搜索(k=1 的 kNN)。

**Scikit-learn vs faiss**

在这两个库中,我们必须指定算法超参数:聚类数、重启次数(每次都从其他初始猜测开始)和最大迭代次数。

正如我们从例子中看到的,算法的核心是搜索最近的邻居,特别是最近的质心,用于训练和预测。这就是 faiss 比 Scikit 快几个数量级的地方——学习!它利用了优秀的 C++实现、尽可能的并发性,甚至 GPU,如果你愿意的话。

**用 faiss 实现 K-Means 聚类**

下面的 Github 要点也可以在我的定期 Github(链接)上找到。

faiss 的一个很大的特点是它既有安装和构建说明(安装文档),又有一个优秀的文档和示例(入门文档)。安装完成后,我们可以编写实际的集群。代码非常简单,因为我们只是模仿了 Scikit-learn API。

重要元素:

*   faiss 专门为这个任务内置了`Kmeans`类,但是它的参数名称与 Scikit-learn 中的不同(参见[文档](https://github.com/facebookresearch/faiss/wiki/Faiss-building-blocks:-clustering,-PCA,-quantization)
*   我们必须确保使用`np.float32`类型,因为 faiss 只使用这种类型
*   `kmeans.obj`通过训练返回错误列表,为了得到像 Scikit-learn 中那样的最终错误,我们使用`[-1]`索引
*   使用`Index`数据结构进行预测,这是 faiss 的基本构建块,用于所有最近邻搜索
*   在预测中,我们使用 k = 1 执行 kNN 搜索,从`self.cluster_centers_`返回最近质心的索引(索引`[1]`,因为`index.search()`返回距离和索引)

## 时间和准确度比较

我选择了 Scikit-learn 中的一些流行数据集进行比较。比较列车时刻和预测时刻。为了便于阅读,我明确地写了基于 faiss 的集群比 Scikit-learn 的集群快多少倍。为了进行误差比较,我刚刚写了基于 faiss 的聚类实现了多少倍的低误差(因为数字很大并且不太能提供信息)。

所有这些时间都是用`time.process_time()`函数测量的,该函数测量进程时间而不是挂钟时间,以获得更准确的结果。结果是 100 次运行的平均值,除了 MNIST,在那里 Scikit-learn 花费了太长时间,我不得不运行 5 次。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b49f487d827cc08675386bdd05f07f8a.png)

火车时间(图片由作者提供)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4702376d8a639b2b44cdb3fd556c351a.png)

预测时间(图片由作者提供)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e3be8178fe5077517df1580cd21593f1.png)

训练错误(图片由作者提供)

正如我们所看到的,对于小数据集(前 4 个数据集)的 K-Means 聚类,基于 faiss 的版本对于训练来说更慢,并且具有更大的误差。对于预测来说,它的工作速度普遍更快。

对于更大的 MNIST 数据集,faiss 显然是赢家。训练速度提高 20.5 倍是巨大的,特别是因为它将时间从几乎 3 分钟减少到不到 8 秒钟!1.5 倍的预测速度也不错。然而,真正的成就是误差降低了惊人的 27.5 倍。这意味着对于更大的真实世界数据集,基于 faiss 的版本要精确得多。而这只需要 25 行代码!

因此,基于这一点:如果你有大型(至少几千个样本)真实世界数据集,基于 faiss 的版本显然更好。对于小型玩具数据集,Scikit-learn 是更好的选择;然而,如果你有一个 GPU,GPU 加速的 faiss 版本可能会更快(我没有检查它以进行公平的 CPU 比较)。

## 摘要

通过 25 行代码,我们可以利用 faiss 库为合理规模的数据集进行 K-Means 聚类,从而获得巨大的速度和准确性提升。如果你需要,你可以通过 GPU、多个 GPU 等获得更好的性能,这在 faiss 文档中有很好的解释。

# K-means 和 PCA 在图像聚类中的可视化分析

> 原文:<https://towardsdatascience.com/k-means-and-pca-for-image-clustering-a-visual-analysis-8e10d4abba40?source=collection_archive---------9----------------------->

## 我们可以使用 K-means 和主成分分析(PCA)对时尚 MNIST 数据集上的图像进行聚类。我们还将使用 [matplotlib](https://matplotlib.org/) 和 [plotly](https://plotly.com/) 对结果进行可视化分析。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/436a215b63a7a15e3c47bd2429246865.png)

时尚 MNIST 数据集。图片来自 researchgate.net

我们在这里要做的是在 f-MNIST 数据上训练一个 K-means 聚类模型,以便它能够相对准确地对数据集的图像进行聚类,并且这些聚类具有一些我们可以理解和解释的逻辑。然后,我们将参考实际标签(y)使用 matplotlib 和 plotly 直观地分析聚类的结果,并得出关于 k-means 聚类如何在图像数据集上执行的粗略结论。最后的代码可以在最后的链接中找到。

在本文中,*功能*和*组件*可互换使用。

[***直奔 Github 上的代码。***](https://github.com/sunman91/Data-Science-stuff/blob/master/k-means-and-pca-on-f-mnist-dataset.ipynb)

# 介绍

**聚类**是一种无监督的机器学习算法,它识别没有特定标签的模式,并根据特征对数据进行聚类。在我们的例子中,我们将看到一个聚类算法(k-means)是否可以在没有标签(y)的情况下在 f-MNIST 中找到不同服装图像之间的模式。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/31929f92a50da839ef38449ca7072c89.png)

说明 K-means 如何工作的 gif。每个红点是一个质心,每种不同的颜色代表一个不同的集群。每一帧都是质心被重新定位的迭代。(来源: [gyfcat](https://gfycat.com/softenragedhypsilophodon) )

**K-means** 聚类的工作原理是根据给定的聚类数分配多个质心。每个数据点被分配给质心最接近它的聚类。该算法旨在最小化观测值与其所属聚类质心之间的平方欧氏距离。

**主成分分析或 PCA** 是一种减少给定数据集的维度,同时仍然保留其大部分方差的方法。维基百科将其定义为,“ *PCA 被定义为一种正交线性变换,它将数据变换到一个新的坐标系,使得数据的一些标量投影的最大方差位于第一个坐标上(称为第一主分量),第二个最大方差位于第二个坐标上,以此类推。”*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ea81306d3cd9a904a92c387ab7e7e0b1.png)

PCA 可视化。最好的 PC(黑色移动线)是那些红线的总长度最小的时候。它将被用来代替水平和垂直分量(来源: [giphy](https://giphy.com/gifs/pca-Lyejb62QjQepG)

基本上,PCA 降低了数据集的维度,同时保留了大部分信息。例如,如果一个数据集有 500 个特征,根据保留的特定方差量,它会减少到 200 个特征。保留的方差越大,保存的信息就越多,但是得到的维数也就越多。

维度越少,训练和测试模型的时间就越少。在某些情况下,使用数据集和 PCA 的模型比原始数据集表现更好。PCA 的概念以及它通过改变保留方差而在图像上引起的变化在这里[处](/pca-using-python-scikit-learn-e653f8989e60)得到了很好的展示。

# 这个计划

因此,计划是在数据集上执行 k-means,但只是在对其应用 PCA 之后。

1.  从 keras 加载数据集
2.  预处理数据,展平数据(从 60000 x 28 x 28 数组到 60000 x 784 数组)
3.  对其应用 PCA 以减少维度(使用 0.98 方差从 784 到 420)
4.  在 PC 数据集上应用 K 均值聚类(10 个聚类)
5.  使用 matplotlib 和 plotly 观察和分析结果

# 数据集

与 MNIST 数字数据集相比,f-MNIST 数据集是一个稍微高级的数据集,它由不同种类服装的 28 x 28 像素图像组成,数字代表以下服装类型。

Loading required libraries **import keras

from keras.datasets import fashion_mnist
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans** #Loading the dataset
(X_train,y_train), (X_test,y_test) = fashion_mnist.load_data()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/436a215b63a7a15e3c47bd2429246865.png)

时尚 MNIST 数据集

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d7c17234ddf42bdde76e111c720fba39.png)

每张图片都是 28×28 像素,上面有各种各样的衣服、鞋子和包包

# **数据预处理**

我们通过将特征展平成一维来将数据从 3D 阵列重新成形为 2D 阵列。28×28 阵列的每个图像现在是 784 个特征的单个阵列。所以我们的数据集从之前的 60000,28,28 变成了 60000,784 数组。

Reshaping X to a 2D array for PCA and then k-means

X = X_train.reshape(-1,X_train.shape[1]*X_train.shape[2]) #We will only be using X for clustering. No need of y.print ("The shape of X is " + str(X.shape))
print ("The shape of y is " + str(y.shape))
#We will be using y only to check our clustering Output:
The shape of X is (60000, 784)
The shape of y is (60000,)


# 主成分分析

我们现在将在数据集上使用 PCA 来降低维数。我们将选择保留方差 0.98(通过反复试验选择的值),并将其用于我们的数据集。

from sklearn.decomposition import PCA

Make an instance of the Modelvariance = 0.98 #The higher the explained variance the more accurate the model will remain, but more dimensions will be presentpca = PCA(variance)

pca.fit(Clus_dataSet) #fit the data according to our PCA instanceprint("Number of components before PCA = " + str(X.shape[1]))
print("Number of components after PCA 0.98 = " + str(pca.n_components_))

dimension reduced from 784Output:

Number of components before PCA = 784
Number of components after PCA 0.98 = 420


我们现在根据 PCA 实例转换数据

Clus_dataSet = pca.transform(Clus_dataSet)print(“Dimension of our data after PCA = “ + str(Clus_dataSet.shape))Output:
Dimension of our data after PCA = (60000, 420)


我们还可以对数据进行逆变换,以查看数据因 PCA 而发生的变化。

approximation = pca.inverse_transform(Clus_dataSet)#image reconstruction using the less dimensioned data
plt.figure(figsize=(8,4));n = 500 #index value, change to view different data# Original Image
plt.subplot(1, 2, 1);
plt.imshow(X[n].reshape(X_train.shape[1], X_train.shape[2]),
cmap = plt.cm.gray,);
plt.xlabel(str(X.shape[1])+’ components’, fontsize = 14)
plt.title(‘Original Image’, fontsize = 20);
# 196 principal components
plt.subplot(1, 2, 2);
plt.imshow(approximation[n].reshape(X_train.shape[1], X_train.shape[2]),
cmap = plt.cm.gray,);
plt.xlabel(str(Clus_dataSet.shape[1]) +’ components’, fontsize = 14)
plt.title(str(variance * 100) + ‘% of Variance Retained’, fontsize = 20);


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/32a10947d9c0b4ca411eb606527cd105.png)

左边的数据是原始数据(784 个分量),右边的数据是从 PCA 逆变换而来的(420 个分量)。两者都有 28 x 28 的尺寸。

# k 均值聚类

构建 k 均值模型时,我们需要以下参数的值。

**init** :质心的初始化方法。值将为:“k-means++”。k-means++以一种智能的方式为 k-mean 聚类选择初始聚类中心,以加速收敛。

**n_clusters** :要形成的簇的数量以及要生成的质心的数量。值将是:10(根据索引,我们有 10 个类,可能不是最好的,但对我们的上下文足够好)

**n_init** :使用不同质心种子运行 k-means 算法的次数。就惯性而言,最终结果将是 n_init 次连续运行的最佳输出。基于我们的惯性结果,值将是:35(可能不是最好的,但对我们的环境来说足够好了)

现在我们有了自己的模型,并使它适合我们的数据集。首先尝试使用提到的参数来检查本文的结果。您可以稍后更改它们,并看到不同的结果。

k_means = KMeans(init = “k-means++”, n_clusters = 10, n_init = 35)
k_means.fit(Clus_dataSet)


现在,该模型已经适合我们的图像数据集,我们已经执行了主成分分析。数据现在被分成 10 个簇。现在,我们必须检查哪种类型的图像出现在每个集群中,并查看是否有任何模式。请记住,分布是相似的,但是在执行此操作时,集群的数量(标签)可能会有所不同。

# 可视化和分析

拟合之后,我们使用下面的代码来可视化我们的集群。

G = len(np.unique(k_means_labels)) #Number of labels#2D matrix for an array of indexes of the given label
cluster_index= [[] for i in range(G)]
for i, label in enumerate(k_means_labels,0):
for n in range(G):
if label == n:
cluster_index[n].append(i)
else:
continue
#Visualisation for clusters = clustplt.figure(figsize=(20,20));
clust = 3 #
enter label number to visualise num = 100 #num of data to visualize from the cluster for i in range(1,num):
plt.subplot(10, 10, i);
#(Number of rows, Number of column per row, item number) **plt.imshow(X[cluster_index[clust][i+500]].reshape(X_train.shape[1], X_train.shape[2]), cmap = plt.cm.binary);

plt.show()**


正如你在下面看到的,这个特殊的集群(在我的例子中是 3 个)在集群踝靴方面做得很好。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/02ffe663603e859ff180c52d201c3320.png)

第三组似乎有短靴(略短)、运动鞋和一些凉鞋

下面的条形图可视化代码可以在最后的链接中找到。这使用来自数据集的 *y_train* 的类别标签,并检查给定聚类中某个类别的数量。该图将是相同的(如果您使用相同的参数),而当您执行它时,集群的数量(标签)可能会有所不同。*例如,在我的示例中,标记为 0 的聚类似乎是凉鞋聚类,而在你的示例中,该聚类可能标记为 4。*

*注:簇名为条形图上方****。***

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b1f3ccdaac4e72fdafcf5d5371d358f0.png)**

**簇 0~ 3 的条形图**

****集群 0** 好像以凉鞋居多。**

****集群 1** 看似随机但大多只有上身衣服。 *(T 恤、套头衫、连衣裙、外套和衬衫)***

****集群 2** 也有上身衣服但是种类较少。*(套头衫、衬衫和外套)***

**集群 3 似乎大多是短靴,很少有运动鞋和凉鞋。基本上都是鞋子。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/293394a0fef54da0f120ce2088ea6d94.png)**

**簇 4 ~ 7 的条形图。集群 6 和 7 似乎都有包。**

**同样,我们可以观察到星团 4 ~7。在群集 6 和 7(在我的情况下)中,似乎有大多数的包。但是在使用上述集群的可视化(如下所示)时,我们看到了一个合理的模式。一个集群的提手被提起(以及其他),另一个没有。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d410687d5204a795f822d038de9bac6d.png)**

**第六组似乎有提手的袋子。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2ffef899f479845729dcbbe315fff219.png)**

**第 7 组似乎有把手朝下的包。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f90c47773782a1f90ebe5156aa0189ee.png)**

**看起来有鞋子的分类 8 和分类 9 的条形图。**

**下面显示的群集 8 和 9 似乎是鞋。聚类 8 有一些凉鞋,大部分是运动鞋,聚类 9 似乎有一些凉鞋,大部分是短靴。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0919e2a2ac2f65fdb778753f569595ba.png)**

**第八组好像有运动鞋和凉鞋。两个都是鞋。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bd09170c16d60ab313ec41bd1a62acec.png)**

**集群 9 似乎主要是踝靴和几双凉鞋。两个都是鞋。**

# **集群的 3D 可视化**

**我们将使用 [plotly 在 3D 中可视化星团。](https://plotly.com/) Plotly 是 python 的高级可视化库。使用以下代码获得聚类数据的 3D 散点图。我们将仅使用数据集中 420 个要素中的 3 个要素。这种可视化有助于了解集群的形成情况,以及单个集群扩散到其他集群的程度。**

install these if you haven’t

!pip install chart_studio
!pip install plotly****import plotly as py
import plotly.graph_objs as go
import plotly.express as px
#3D Plotly Visualization of Clusters using golayout = go.Layout(
title='Cluster Visualisation',
yaxis=dict(
title='Y'
),
xaxis=dict(
title='X'
)
)****colors = ['red','green' ,'blue','purple','magenta','yellow','cyan','maroon','teal','black']
trace = [ go.Scatter3d() for _ in range(11)]
for i in range(0,10):
my_members = (k_means_labels == i)
index = [h for h, g in enumerate(my_members) if g]
trace[i] = go.Scatter3d(
x=Clus_dataSet[my_members, 0],
# 0 is a component among the 420 components. Feel free to change it y=Clus_dataSet[my_members, 1],# 1 is a component among the 420 components. Feel free to change it z=Clus_dataSet[my_members, 2],# 2 is a component among the 420 components. Feel free to change it **mode='markers',
marker = dict(size = 2,color = colors[i]),
hovertext=index,
name='Cluster'+str(i),

        )****fig = go.Figure(data=[trace[0],trace[1],trace[2],trace[3],trace[4],trace[5],trace[6],trace[7],trace[8],trace[9]], layout=layout)

py.offline.iplot(fig)**


*****输出:*****

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/92a4fc4247e32c443c77a727dd6b01ab.png)**

**使用 PCA 对 k 均值聚类的 f-MNIST 数据集进行 3D plotly 散点图可视化。每种颜色代表一个不同的集群。**

**由于数据集(具有 PCA)实际上具有 420 个维度,因此该可视化仅在散点图中显示了这些特征中的 3 个。要绘制的组件可以在代码中更改,以了解不同组件的情况。**

***(可进行进一步的主成分分析,将所有 784 个分量减少到 3 个分量,以在 3D 图中完全表示,但这样做会丢失大量信息)***

# ****结论****

**聚类似乎将相似的项目分组在一起。一个集群或者包含上身衣服 *(T 恤/上衣、套衫、连衣裙、外套、衬衫)*或者鞋子*(凉鞋/运动鞋/短靴)*或者包。然而,该聚类在裤子上表现不佳,并且似乎将其与连衣裙归为一组。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8a5a5c9cb9cd9398545e55935e3c61a1.png)**

**一群穿着裤子和裙子的人**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/59417f82a37382b25f6aedc9d734005d.png)**

**前述集群中的服装和裤子的数据可视化**

**但它很好地区分了这两种包。这种模式可以由我们来解释。一组是提手凸起的包,另一组是提手未凸起的包。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cc483cd456f1571f7377db4e8b4cd061.png)**

**两个集群都有包。但是该算法能够区分手柄被提起和未被提起**

**类似地,在下面显示的两个集群中,两个集群都以短靴为主。但是短靴看起来大小不一,小一点的看起来和同一组的运动鞋很相似。**

**![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7d58132db7bc43426cb4ddc40b49d68a.png)**

**两个集群都有最大的踝靴。左边的比右边的短**

**观察上面的结果,我们可以看到 k -means 算法基于一个合理的模式来区分它的聚类。因此,我们可以得出一个粗略的结论,K-means 聚类方法在进行主成分分析后可以得到一个不错的分类结果。**

**[***点击此处链接到***](https://github.com/sunman91/Data-Science-stuff/blob/master/k-means-and-pca-on-f-mnist-dataset.ipynb)**

***参考文献***

**[1] A. Ng,斯坦福大学的机器学习。(未注明)。从 https://www.coursera.org/learn/machine-learning[取回](https://www.coursera.org/learn/machine-learning)**

**[2] [S Joel Franklin](https://medium.com/@joel_34096?source=post_page-----a648f28bdc47----------------------) , [K-Means 聚类用于图像分类](https://medium.com/@joel_34096/k-means-clustering-for-image-classification-a648f28bdc47) (2020),[中](https://medium.com)**

**[3] [迈克尔·加拉内克](https://github.com/mGalarnyk), [PCA + Logistic 回归(MNIST)](https://github.com/mGalarnyk/Python_Tutorials/blob/master/Sklearn/PCA/PCA_Image_Reconstruction_and_such.ipynb)(2018)[github](https://github.com)**

# k-均值聚类算法

> 原文:<https://towardsdatascience.com/k-means-clustering-algorithm-e845e2b25784?source=collection_archive---------32----------------------->

## 在 k-means 的引擎盖下,以便一个 7 年级学生能够理解

我选择为这个项目实现的算法是 *K 均值聚类*。生成的数据试图根据每个点离拟定水井的距离来模拟配水场景。本质上,该算法对于客户细分场景是理想的,这种场景基于客户的位置和井的数量将客户聚集在特定的水井周围。

在这个假想的场景中,几个地方自治市多年来一直在与老化的水利基础设施作斗争。水的供应、储存和从一个地方到另一个地方的运输是一个挑战。一位数据科学家被请来建立一些关于客户将如何受到影响的模型,并为改善供水提供一些启示。

目标是理解算法;然而,当变量有真正的意义时,它有助于我们深入了解它是如何工作的,以及背后的数学原理。

***例题:*** 客户将如何根据他们的位置进行聚类?创建一个放置 3 口和 7 口水井的可视化模型,每口井作为质心。

客户的位置是固定的等距点,使用内置的范围函数生成。一共 1392 分。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8f64728efb8b79419a3a6e1c3fdb3b59.png)

作者图片

在绘制了每个客户的固定位置后,我找到了我认为是数据集地理中心的地方。我认为这是第一口水井的理想地点。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b625341e81a067e7edd311ce9b54c788.png)

作者图片

对于以每口井为质心的 3 口水井的布局,客户将被分为以下几类。用于预测新井位置的特征是每个点距质心的距离。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e0a6826d56c5410f7405a2a91e13949c.png)

作者图片

对于 7 个水井的位置,每个水井都有一个质心,客户将按以下方式聚集。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/892c4d78fbc485e863f8de37eec60db6.png)

作者图片

假设所有单个点的距离彼此等距,则在这种情况下应用 k-means 聚类算法是有意义的。应用距离公式计算每个点和所选质心之间的欧几里德距离。

接下来,我决定给这个问题添加一些上下文,并包含一些特征工程,以查看当应用 k-means 算法时,客户将如何聚类。

我添加了一些随机点,每个点代表一个特定的负责分配水的供水公司。显然,在这个假想的数据集上做了一些假设,但总体目标是看到 k-means 聚类算法在运行。

假设每个自来水公司都有一个单独的定价结构,根据水从每口井流出的距离来生产和向客户分配水,我想看看在考虑其他特征时,k-means 聚类算法将如何运行。

在这个场景中,根据一家供水公司的定价结构和水到达每个客户的距离创建了四个分类。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1a70b294edf18118381f55ad91cff2de.png)

作者图片

k-means 聚类算法用于计算如何根据利润率(生产价格和销售价格之间的差额)对客户进行细分。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3177b6e31f4aa94b98a8f2729d818256.png)

作者图片

我对这个虚拟数据集应用的 k-means 聚类算法的最后一个应用程序将客户分为 3 个部分。它使用了一种称为线附加费的功能,这是一种基于距离应用于数据集的功能。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bddcc0bbdc9592b92b3d5c784e43ff9f.png)

作者图片

我花了大约两周的时间尝试了解 k-means 聚类算法。当应用于现实生活的概念场景时,理解算法如何工作是最好的证明。

虽然这目前超出了 k-means 聚类算法的范围,但逻辑上的下一步将包括探索每个自来水公司的一些分类算法模型以及对该场景的更多假设,例如:

想象一下,在公共供水公司突然被私有化为七家公司后,每个客户被随机分配到一口井,而不考虑距离。每个公司根据水的运输距离有不同的线路附加费,根据客户的选择有不同的送货时间表和用水量。创建一个应用程序,准确地将各自的资金分配给每个自来水公司,并创建一个模型,以便有效和高效地将水分配给所有客户。

# k-均值聚类和间隙统计

> 原文:<https://towardsdatascience.com/k-means-clustering-and-the-gap-statistics-4c5d414acd29?source=collection_archive---------0----------------------->

## 用差距统计弥合知识差距

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/656f5b5e0c1ea81da2b02dcf61a74495.png)

照片由[suser ll just me](https://www.freeimages.com/photographer/Suserl-44212)在 [Freeimages](https://www.freeimages.com/) 上拍摄并由我编辑

> 在引擎盖下有许多代码在运行。这就是为什么我在这篇文章的最后提供了我的 Github 库,并且我只展示了 K-Means 的一小段代码。

# 介绍

聚类是模式分析中识别数据中不同组的一种重要技术。由于数据大多是三维以上的,所以在应用聚类技术之前,我们执行像 PCA 或拉普拉斯特征映射这样的降维方法。然后,这些数据可以在 2D 或 3D 中使用,这使得我们可以很好地将发现的星团可视化。
尽管这是一个基本的工作流程,但情况并非总是如此。

数据通常也是无标签的。这意味着你没有明确的定义你想在这些数据中找到什么。这就是为什么聚类也是一种很好的数据探索技术,而不需要事先降维。

常见的聚类算法是 K-Means 和 Meanshift 算法。在这篇文章中,我将重点介绍 K-Means 算法,因为这是最简单和最直接的聚类技术。此外,我们将假设数据要么直接提供有两个特征(因此 2D),要么有人对数据执行 2D 降维,然后将其提供给我们。因此,我们直接深入应用 K-Means。

K-Means 算法需要一个超参数,即你想要寻找的聚类数 **K** 。但是,如果我们想找到集群,我们怎么知道我们需要多少集群?

> **示例**:如果我们想要在数据中为我们的营销团队找到人物角色,我们可以假设我们想要找到三到四类人。

在这种情况下,K 的数量是固定的。但是如果**不是**呢?

超参数的选择称为模型选择。在
K-Means 的情况下,这只是我已经说过的 **K、**的数量。在这篇博文中,我将重点讲述我们如何通过对 K-Means 执行 Tibshirani 的 Gap-Statistics,从统计上找出 K 的最佳值。

> Gap-Statistics 是由 Robert Tibshirani 于 2000 年在斯坦福引入的。

# 目标

我想用这个帖子来回答这三个问题:

*   1)如何在 K-Means 中找到 K 的最佳值?
*   2)我们如何衡量差距统计的性能?
*   3)在什么条件下差距统计可能会失败?

# **K-Means——非常简短的介绍**

K-Means 执行三个步骤。但是首先你需要预先定义 k 的数量。这些聚类点通常被称为**质心**。

*   1)通过计算所有点到所有质心之间的欧几里德距离,将每个数据点(重新)分配到其最近的质心。
*   2)基于所有相应的数据点计算每个质心的平均值,并将质心移动到所有指定数据点的中间。
*   3)转到 1)直到满足收敛标准。在我的例子中,我计算所有点到重新分配的质心平均值之间的类内距离。在新的迭代之后,如果所有的质心一起移动小于 0.01,那么基本上不再发生什么,执行收敛标准。

代码 1)K-表示由我从头开始编写

在上面的代码 1 中可以看到,第 9 行使用列表理解为每个数据点计算到每个中心点的欧几里德距离(第 3 行中 K = 3)。Numpy.argmin 然后为每个点选择最近的距离,并将其分配给该质心。第 13 行计算第三步,并对总的簇内距离求和。如果小于 0.01,则 while 循环中断。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/339d2542577a034f28d1bb765226d2f2.png)

图 1) K=3 gif |我做的

我们可以看到在循环中每个*点的分配是如何变化的。总共需要五次循环直到收敛。*

> 通知:质心的初始化对 K-Means 的执行有很大的影响。想象两个质心从最左边和最低的位置开始。每个数据点将被分配给质心一号,聚类是无用的。
> 
> **注意** : K-Means 只是局部最优,并不能保证全局最小

## 进一步的调查

图 1 显示了 300 个数据点的 3 个质心。我还没有展示数据的代码,它只是从带有 *make_blobs* 的 *sklearn* 中生成的。

当然,在有三个全局最优质心的情况下,这种簇内距离不会进一步减小。但是当我们给 K 加上越来越多的值时会发生什么呢?簇内距离将几乎单调地缩小。想象一下,如果我们用一个额外的质心将图 1 的三个集群中的一个分成两个。簇内距离会缩小,因为所有点现在都更靠近另一个质心,即使这显然是一个错误的**簇分裂。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e3ceebb84fdd7300643458b766dafe29.png)

图 2) K=300 |我做的

当我们选择 K 的数量等于质心的数量时,总的簇内距离将是 0。从最小化问题的角度来看,这是理想的,但对我们来说不是。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1d03c77509a760cd8d4f3aa35cd48855.png)

图 3) K=11 |我做的

当我们选择 K 的数目等于 11 时,我们可以看到,我们将永远不会达到小于 3 的总簇内距离。

> 由于图 2 和图 3 中的起点为 1,所以图 2 的实际簇内距离为零,而图 3 的实际簇内距离为二。

那么我们如何防止 K 被选择为等于数据点的数量呢?

## 我们如何通过初始化来强制我们的集群拥有 K 个非空组件?

*   1)在样本点的位置初始化每个聚类中心
*   2)针对局部最小值制定对策

# 1)如何在 K-Means 中找到 K 的最优值?

答案当然是**缺口统计**,但它是什么呢?

它是由罗伯特·提布拉尼在 20 年前发明的。基本的最小化问题如下所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9a1e0e0588f40b6e8b110e39339c7c46.png)

公式 1)估计 K*的形式规则由 **HTF** 统计学习的要素第 **519 页** | 14.3.11 实际问题

看起来怪怪的?没问题!K*是我们想要找到的 K 的最优值。我们需要定义不同的数据矩阵 W_data 和 W_uniform。其中 W_data 是上图 1 中的 300 个数据点,W_uniform 基本上是群集内距离的模拟平均分布,如**进一步调查**部分所述。W_uniform 基本看起来像图 3。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/85b2cb53071eaeb804e78cef21827129.png)

公式 2)缩减差距统计公式

我们在 ***中可以看到,其中*** 上面的*,*表示 S’(S 素数)等于前面的 S 乘以一个小值(1.024695)。这意味着它在每个时间步长不断变大。

第一个时间步长的初始 S 等于所有均匀绘制的数据点的标准偏差,例如 20 次运行。可能更多,但是 Tibshirani 写道 20 次模拟已经足够了。

## 这是什么意思呢?

好吧。正如我们已经指出的,我们需要一种方法,使得 K 的最佳数目不被选为数据点的数目。为此,引入模拟平均值**W _ uniform from**和标准差 S’(K+1)。

通过检查公式 1 中每个时间步长的图中的最小化问题,我们取 K 的数目,这通过引入新的质心而使最大跳跃进入减少的总簇内距离。

如果你仔细观察图 3,你会发现距离减少的跳跃对于前几个质心来说特别大。这具有直观的意义,因为如果你回头看一下图 1,很明显你引入的质心越多,簇内距离的变化就越小。

因此,差距统计的基本思想是根据均匀抽取的样本的总体行为,选择 K 的数量,即类内距离发生最大跳跃的地方。可能的情况是簇内距离仅发生非常轻微的减小。出于这个原因,S'(K+1)充当阈值,以挑选出太微小的变化,并从数据中去除采样噪声。只有当变化大到阈值 S′(K+1)不再起作用时,才会选择 K 的最佳值。

让我为你想象一下:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/27111645d3daeb7bd08e5f4450eb6106.png)

图 4)差距统计|我做的

> **注意**:类内距离曲线的值已经被最大类间距离归一化。

我故意选择了图 4 左上角的数据,下面的两个簇非常接近。K-means 几乎不可能分辨出这些是不同的聚类。

在左下方的图像中,我们可以看到差距统计数据。选择 K=3 的最佳值,因为我们在值再次收缩之前选择第一个峰值点。红线的计算方法是从右下图的 W_data(蓝色)中减去 W_uniform(绿色)。

> **退一步**:右下图像显示 W_data(蓝色)和 W_uniform(绿色)分布。通过查看 G(K)上的公式 2,我们看到需要用 W_data to 的对数减去 W_uniform 的对数。

对于 W_data 和模拟的 W_uniform,总的簇内距离如预期的那样收缩。但是在 K=4 时,间隙统计检测到 W_data 的总距离的变化不像模拟的那样。这意味着它没有像预期的那样减少。

即使当从 W_uniform 中减去标准偏差 S’(K+1)时,间隙统计也将选择 K 的最佳值作为 **3** 。

> **注意**:如果我们假设 K=4 处的间隙不存在,则低于其前一个点的下一个点在 K=6 处。但由于我将标准偏差标记为垂直的粗红线,我们看到,减去标准偏差后,距离的变化太小,因此 K 将被选择为 K=6。将被选择的下一个 K 是 K=7,因为在 K=8 时出现下一个大间隙。

# 2)我们如何衡量差距统计的性能?

正如我已经提到的,质心的初始化高度影响 K 均值的优化。我们需要考虑不同的数据分布。在计算 K-Means 算法的第二步时,我们需要记住两种基本情况:

*   1)总体聚类距离**大** - >我们取平均值
*   2)总体聚类距离**小** - >我们取最小值

如果我们在计算差距统计之前考虑这两种差异,那么差距统计将更加稳健。

对于我的例子,总的聚类距离很小,所以我计算了平均值,如代码 1 的第 12 行所示,这里我使用 Numpy.mean。

# 3)在什么条件下差距统计可能会失败?

可能会出现三种情况:

*   低估集群
*   高估集群
*   通常

## 低估

如果两个或三个集群非常接近,而其他集群相距甚远,它往往会低估。这正是我之前向您展示的示例中所发生的情况。其中两个星系团靠得太近,所以间隙统计低估了 K*。

## 高估

如果所有的星团都很接近,那就高估了而不是低估了。我真的不能解释为什么,但这是我计算了几次后发生的事情。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/284f82dda6504ffabec7bb29585814b2.png)

图 5)差距统计高估|我做的

## 通常

低估和高估都主要取决于随机初始化的质心。当它们中的一些由于随机的不顺利而被忽略时,类内距离的中断迫使间隙统计更早地产生最佳的类。

# 结论

即使间隙统计是找到合适的 K 的好方法,它仍然不是完美的。例如,我们需要引入一个新的超参数,即模拟 W_uniform 的 K 的个数。我们不能确定这个的理想值是多少。此外,质心的随机初始化会导致高估或低估 K*。

但是通过了解差距统计的所有方面,最好的方法是应用它,然后运行几次差距统计图。取差距统计的平均值可以是一个增加的评估标准。

希望你喜欢这篇文章,它给了你一些差距统计的见解。

# 密码

你可以在我的 Github 页面 [**这里**](https://github.com/Mavengence/Pattern_Analysis_SS20_FAU/blob/master/Exercise_6.ipynb) 找到这个项目的完整代码。如果您对代码有任何疑问,可以给我发电子邮件。你可以在我的[网站](https://timloehr.me/)上找到我的邮箱地址。

# 参考

[1] Trevor Hastie,Robert Tibshirani 和 Jerome Friedman,[统计学习的要素:数据挖掘、推理和预测](https://web.stanford.edu/~hastie/ElemStatLearn/) (2009),Springer
[2] Trevor Hastie,Robert Tibshirani 和 Guenther Walther,[通过差距统计估计数据集中的聚类数](https://statweb.stanford.edu/~gwalther/gap) (2000)

这篇博文基于从弗里德里希·亚历山大大学埃尔兰根-纽伦堡的课程模式分析中获得的知识。我使用了 Christian Riess 博士演讲的部分内容来说明这篇文章的例子。所以所有权利归克里斯汀·里斯博士所有。

# k-均值聚类—已解释

> 原文:<https://towardsdatascience.com/k-means-clustering-explained-4528df86a120?source=collection_archive---------3----------------------->

## 详细的理论解释和 scikit-learn 实现

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/38946ce451cdce190f1fe08d3c102c53.png)

[图源](https://aeroleads.com/blog/10-best-practices-customer-segmentation/)

假设我们开始做生意,向人们出售一些服务。业务进展顺利,几个月内我们的数据库中就有了大约一万名客户。我们希望留住我们的客户,同时增加每位客户的收入。所以我们计划向数据库中的客户提供一笔交易。我们有两个选择:

*   向所有客户提供相同的交易
*   准备客户特定的交易

第一种选择很简单。“所有服务打九折”的交易就可以了。然而,与针对客户的交易相比,这种方式效率较低,利润也较低。此外,针对客户的交易可能对客户更有吸引力。一些顾客喜欢某一件商品打折,而另一些顾客喜欢买一送一的交易。一些客户在周末购买服务 A,而另一些客户在周一上午购买。根据企业规模和客户数量,我们可以列出更多不同的选项。

我们决定准备客户特定的交易。下一步是决定提供什么样的交易。我们不能只为每个客户创建不同的交易。这根本无法管理。一个明智的选择可能是发现具有相似兴趣或购买行为的客户,并将他们分组。分组的标准可以是客户偏好、品味、兴趣、客户服务组合等等。假设客户数据库中有每个客户的以下信息:

*   客户年龄、地址
*   平均采购金额
*   平均购买数量
*   购买频率
*   购买的时间和类型

这个列表很容易扩展。手动对客户进行分组极其困难。然后我们向**机器学习**寻求帮助。将相似客户分组的任务称为**聚类**。维基百科上更正式的定义:

> **聚类分析**或**聚类**是对一组对象进行分组的任务,使同一组中的对象(称为**聚类**)比其他组(聚类)中的对象彼此更相似(在某种意义上)。

在我们的例子中,对象是客户。

聚类是无监督的,这意味着没有样本(或数据点)的标签。聚类在很多行业都有应用。以下是集群的一些示例:

*   客户细分
*   图象分割法
*   图像/颜色压缩
*   检测异常或异常值

有许多不同的聚类算法。在这篇文章中,我将介绍一种最常见的聚类算法: **K-Means 聚类。**

# **聚类 vs 分类**

在开始讨论 k-means 聚类之前,我想指出聚类和分类之间的区别。

*   分类任务中的样本有标签。每个数据点根据一些测量结果进行分类。分类算法试图对样本的测量值(特征)和它们的指定类别之间的关系进行建模。然后模型预测新样本的类别。
*   聚类分析中的样本没有标签。我们希望该模型能够在数据集中找到结构,以便相似的样本能够被分组到聚类中。我们基本上是让模特给样品贴标签。

# **K-均值聚类**

k-均值聚类旨在将数据划分为 k 个聚类,使得同一聚类中的数据点相似,而不同聚类中的数据点相距较远。

> 两点的相似性由它们之间的距离决定。

测量距离的方法有很多。[欧氏距离](https://en.wikipedia.org/wiki/Euclidean_distance)(p = 2 的闵可夫斯基距离)是最常用的距离度量之一。下图显示了如何计算二维空间中两点之间的欧几里德距离。它是使用点的 x 和 y 坐标之差的平方来计算的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b0f391d25bc42025dc1b4ed0a9abced3.png)

在上面的例子中,欧几里德距离是(16 + 9)的平方根,也就是 5。二维中的欧几里得距离让我们想起了著名的[勾股定理](https://en.wikipedia.org/wiki/Pythagorean_theorem)。

还有其他方法来衡量距离如余弦相似度,平均距离等等。相似性度量是 k-means 聚类的核心。最佳方法取决于问题的类型。因此,为了选择最佳的测量类型,拥有良好的领域知识是很重要的。

> K-means 聚类试图最小化一个类内的距离,最大化不同类之间的距离。

让我们从一个简单的例子开始理解这个概念。像往常一样,我们首先导入依赖项:

Importing necessary libraries

import numpy as np
import pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import make_blobs
from sklearn.cluster import KMeans


> Scikit-learn 提供了许多有用的功能来创建合成数据集,这对练习机器学习算法非常有帮助。我将使用 **make_blobs** 函数。

X, y = make_blobs(n_samples = 200, centers=4, cluster_std = 0.5, random_state = 0)plt.scatter(X[:, 0], X[:, 1], s=50)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/595e2cb6f58330cfbc9637fdc17f7957.png)

然后我们创建一个 KMeans 对象并拟合数据:

kmeans = KMeans(n_clusters = 4)
kmeans.fit(X)


现在,我们可以将数据集划分为多个集群:

y_pred = kmeans.predict(X)
plt.scatter(X[:, 0], X[:, 1], c = y_pred, s=50)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3f4a0db991b5d9a2af433d3fb5ff3c00.png)

现实生活中的数据集要复杂得多,其中的聚类没有明显的区分。但是,算法的工作方式是一样的。

> K-means 算法不能确定聚类数。我们需要在创建 KMeans 对象时定义它,这可能是一项具有挑战性的任务。

K-means 是一个迭代过程。它基于[期望最大化](https://en.wikipedia.org/wiki/Expectation%E2%80%93maximization_algorithm)算法。确定集群数量后,它通过执行以下步骤来工作:

1.  为每个簇随机选择质心(簇的中心)。
2.  计算所有数据点到质心的距离。
3.  将数据点分配给最近的聚类。
4.  通过取聚类中所有数据点的平均值,找到每个聚类的新质心。
5.  重复步骤 2、3 和 4,直到所有点收敛并且聚类中心停止移动。

> **注意**:初始质心是随机选择的,这可能会导致最终的聚类有些不同。为了克服这个问题,scikit learn 提供了 **n_init** 参数。k-means 算法以不同的初始质心运行“n_init”次,并且最终结果将根据 n_init 次连续运行来确定。

你可以使用 Naftali Harris 在他的博客上准备的这个工具来可视化每个步骤。我从这个互动工具中截取了截图,这样上面的步骤就更容易理解了。我强烈建议花点时间使用这个工具。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e3b3299b99d2e1c4036aa4906dbed427.png)

随机选择质心

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b14805832be36cccb0f76cb39ccefbfa.png)

计算所有数据点到质心的距离,并将数据点分配给最近的聚类

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9c011b200f7965c6f8a6ab83ef970368.png)

通过取平均值来计算每个聚类的新质心

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/26870ab18a0480d31c8ed47201c69f08.png)

将数据点重新分配到最近的聚类中心

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ad655f9174499ee652b3ff4874a44290.png)

当聚类中心(质心)不再移动时,模型收敛

# **利弊**

**优点:**

*   容易理解
*   相对较快
*   可扩展用于大型数据集
*   能够以一种聪明的方式选择初始质心的位置,从而加速收敛
*   保证收敛

**缺点:**

*   集群的数量必须预先确定。K-means 算法无法猜测数据中存在多少个聚类。确定集群的数量可能是一项具有挑战性的任务。
*   只能画线性边界。如果数据中存在非线性结构来分隔组,k-means 将不是一个好的选择。
*   随着样本数量的增加而变慢,因为在每一步,k-means 算法都会访问所有数据点并计算距离。另一种方法是使用数据点的子集来更新质心的位置(即 sk learn . cluster . minibatchkmeans)
*   对异常值敏感

感谢您的阅读。如果您有任何反馈,请告诉我。

# 我关于机器学习算法的其他帖子

*   [朴素贝叶斯分类器—解释](/naive-bayes-classifier-explained-50f9723571ed)
*   [逻辑回归—已解释](/logistic-regression-explained-593e9ddb7c6c)
*   [K-最近邻(kNN)-解释](/k-nearest-neighbors-knn-explained-cbc31849a7e3)
*   [支持向量机—解释](/support-vector-machine-explained-8d75fe8738fd)
*   [决策树和随机森林——解释](/decision-tree-and-random-forest-explained-8d20ddabc9dd)
*   [梯度增强决策树—解释](/gradient-boosted-decision-trees-explained-9259bd8205af)
*   [主成分分析—已解释](/principal-component-analysis-explained-d404c34d76e7)
*   [用机器学习预测二手车价格](/predicting-used-car-prices-with-machine-learning-fea53811b1ab)

# K-Means 聚类讲解:算法和 Sklearn 实现

> 原文:<https://towardsdatascience.com/k-means-clustering-explained-algorithm-and-sklearn-implementation-1fe8e104e822?source=collection_archive---------57----------------------->

## *聚类和 k-means 聚类简介。详细概述和 sklearn 实现。*

**K-Means** 聚类是数据科学和机器学习领域中最强大的聚类算法之一。它非常简单,但却能产生非常好的效果。因为聚类是理解数据集的一个非常重要的步骤,所以在本文中,我们将讨论什么是聚类,我们为什么需要它,以及 k-means 聚类在数据科学中对我们有什么帮助。

# 文章概述:

*   什么是集群
*   什么是无监督机器学习
*   集群应用
*   k-均值聚类解释
*   k-均值聚类算法
*   使用 Scikit-Learn 和 Python 实现 K-Means 聚类

# 什么是集群

**聚类**的任务是根据数据的属性,更确切地说是根据数据中或多或少明显的某些模式,将数据分组为两个或多个组。我们的目标是找到数据中的那些模式,帮助我们确定,给定数据集中的某个项目,我们将能够正确地将该项目放在正确的组中,以便它与该组中的其他项目相似,但与其他组中的项目不同。

这意味着聚类实际上由两部分组成:一部分是识别组,另一部分是尽可能将每个项目放在正确的组中。

聚类分析算法的理想结果是同一组中的两个项目尽可能相似,而不同组中的两个项目尽可能不同。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/49afb7bd7c70170618d29a1dbf4fcd56.png)

聚类示例—来源:[维基百科](https://en.wikipedia.org/wiki/Cluster_analysis)

一个真实的例子是**客户细分**。作为一家销售各种产品/服务的企业,很难为每个客户找到完美的商业策略。但我们可以明智地将我们的客户分成几个小组,了解这些客户的共同点,并针对每个小组调整我们的业务策略。向客户提出错误的商业策略可能意味着失去该客户,因此我们实现了良好的市场聚类非常重要。

# 什么是无监督机器学习

无监督机器学习是一种机器学习算法,它试图在没有任何先验知识的情况下推断数据中的模式。与之相反的是监督机器学习,我们有一个训练集,算法将通过将输入与预定义的输出进行匹配来试图找到数据中的模式。

我写这个的原因是因为**聚类一个无监督的机器学习任务**。当应用聚类算法时,我们事先不知道类别(尽管我们可以设置想要被识别的类别的数量)。

分类将从分析数据的算法中产生。正因为如此,我们可以称聚类为探索性的机器学习任务,因为我们只知道类别的数量,而不知道它们的属性。然后,我们可以尝试使用不同数量的类别,看看我们的数据是否有更好的聚类。

然后,我们必须了解我们的集群,这实际上可能是最不同的任务。让我们重新使用客户细分的例子。假设我们运行了一个聚类算法,将我们的客户分为 3 组。但是那些群体是什么呢?为什么算法决定这些客户适合这个组,而那些客户适合那个组?这是你需要非常熟练的数据科学家以及非常了解你的业务的人的部分。他们会查看数据,尝试分析每个类别中的一些项目,并尝试猜测一些标准。一旦他们找到一个有效的模式,他们就会从那里进行推断。

当我们得到一个新客户时会发生什么?我们必须将该客户放入我们已经拥有的一个聚类中,这样我们就可以通过我们的算法运行关于该客户的数据,并且该算法将使我们的客户适合我们的一个聚类。此外,在未来,在我们获得大量新客户后,我们可能需要重建我们的集群——可能新的集群会出现,也可能旧的集群会消失。

# 集群应用

**有哪些常见的集群应用?**在我们爱上聚类算法之前,我们需要了解什么时候可以使用它们,什么时候不可以。

最常见的用例是我们已经讨论过的:**客户/市场细分**。公司无时无刻不在进行这种类型的分析,以便了解他们的客户和市场,并调整他们的商业策略、服务和产品,使之更适合他们。

另一个常见的用例由**信息提取任务**表示。在信息抽取任务中,我们经常需要发现实体、单词、文档等之间的关系。现在,如果你的直觉告诉你,我们有更大的机会找到彼此更相似的项目之间的关系,那么你是对的,因为对我们的数据点进行聚类可能会帮助我们找出在哪里寻找关系。(注:如果想了解更多关于信息抽取的内容,也可以试试这篇文章: [Python NLP 教程:信息抽取和知识图](https://programmerbackpack.com/python-nlp-tutorial-information-extraction-and-knowledge-graphs/))。

另一个非常流行的用例是使用聚类进行**图像分割**。图像分割是观察图像并试图识别图像中不同项目的任务。我们可以使用聚类来分析图像的像素,并识别图像中的哪个项目包含哪个像素。

# k-均值聚类解释

**K-Means 聚类算法**是一种迭代聚类算法,它试图将数据点准确地分配到我们预定义的 *K* 个聚类中的一个聚类。

与任何其他聚类算法一样,它试图使一个聚类中的项目尽可能相似,同时也使这些聚类尽可能互不相同。这是通过确保一个聚类中的数据点与该聚类的**质心**之间的平方距离之和最小来实现的。聚类的质心是聚类中所有值的平均值**。你也可以从这一段了解到**K-的意思是**的来源。**

**用更专业的术语来说,我们试图将数据放入一个尽可能*同质*的集群,同时尽可能*异质*的集群。K 数是我们试图获得的集群数。我们可以摆弄 K,直到我们对结果满意为止。**

# **k-均值聚类算法**

**K-Means 聚类算法只需要几个简单的步骤。**

1.  **分配 *K* 组数**
2.  **混洗数据并将每个数据点随机分配到 *K* 个簇中的一个,并分配初始随机质心。**
3.  **计算每个数据点和所有质心之间的平方和。**
4.  **根据步骤 3 的计算,将每个数据点重新分配到最近的质心。**
5.  **通过计算每个聚类的平均值来重新分配质心**
6.  **重复步骤 3、4、5,直到我们不再需要更改集群中的任何内容**

**运行 K 均值聚类算法所需的时间取决于数据集的大小、我们定义的 K 数以及数据中的模式。**

# **使用 Scikit-Learn 和 Python 实现 K-Means 聚类**

**我们将使用 **Sckikit-Learn Python** 库在一个小数据集上运行 K-Means 聚类算法。**

# **K 均值聚类算法的数据集**

**该数据由关于伦敦、巴黎和柏林的 3 个文本组成。我们将提取维基百科中关于这三个城市的文章的摘要部分,并通过我们的聚类算法来运行它们。**

**然后,我们将提供 3 个我们自己的新句子,并检查它们是否被正确地分配到各个组。如果发生这种情况,我们就知道我们的聚类算法起作用了。**

# **k-均值聚类实现**

**首先让我们安装我们的依赖项。**

Sklearn library for our cluster

pip3 install scikit-learn

We will use nltk(Natural Language Toolkit) to remove stopwords from the text

pip3 install nltk

We will use the wikipedia library to download our texts from the Wikipedia pages

pip3 install wikipedia


**现在让我们定义一个小类来帮助我们从维基百科页面收集文本。我们将文本存储到本地的 3 个文件中,这样我们就不会在每次运行算法时再次下载文本。第一次运行算法时使用 class,第二次运行时可以注释第 8-12 行,取消第 13-15 行的注释。**

import wikipedia

class TextFetcher:

def __init__(self, title):
    self.title = title
    page = wikipedia.page(title) # 8
    f = open(title + ".txt", "w") # 9
    f.write(page.summary) # 10
    f.close() # 11
    self.text = page.summary # 12
    #f = open(title + ".txt", "r")
    #self.text = f.read()
    #f.close()

def getText(self):
    return self.text 

**现在让我们构建数据集。我们将获取关于每个城市的文本,并删除**停用词**。停用词是我们通常在每次文本处理任务之前过滤掉的词。它们是英语中非常常见的单词,不会给文本带来任何价值和意义。因为它们中的大多数在任何地方都被使用,它们将阻止我们正确地对我们的文本进行聚类。**

from text_fetcher import TextFetcher
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
import nltk

def preprocessor(text):
nltk.download('stopwords')
tokens = word_tokenize(text)
return (" ").join([word for word in tokens if word not in stopwords.words()])

if name == "main":
textFetcher = TextFetcher("London")
text1 = preprocessor(textFetcher.getText())
textFetcher = TextFetcher("Paris")
text2 = preprocessor(textFetcher.getText())
textFetcher = TextFetcher("Berlin")
text3 = preprocessor(textFetcher.getText())

docs = [text1, text2, text3]

# **单词矢量化技术**

**众所周知,计算机非常不擅长理解文本,但它们在处理数字方面表现得更好。因为我们的数据集是由单词组成的,所以我们需要将单词转换成数字。**

****单词嵌入或单词矢量化**代表一组用于将单词分配给实数向量的技术,这些技术可由机器学习用于某些目的,其中之一是文本聚类。**

**Scikit-Learn 库包含一些单词矢量器,但是对于本文,我们将选择*tfidfvector。***

tfidf_vectorizer = TfidfVectorizer()
tfidf = tfidf_vectorizer.fit_transform(docs)


**现在是时候应用我们的 K 均值聚类算法了。幸运的是,Scikit-Learn 有一个非常好的 K-Means 算法实现,我们将使用它。因为我们知道要将文本分为 3 类(每个城市一类),所以我们将定义 K 值为 3。**

kmeans = KMeans(n_clusters=3).fit(tfidf)
print (kmeans)

Output: [0 1 2]


**我知道,就这么简单!现在我们的产量意味着什么?简单地说,这 3 个值就是我们的 3 个集群。**

**为了测试它们,我们现在可以提供 3 个文本,我们确定它们应该在不同的簇中,看看它们是否被正确分配。我们必须确保不要忘记对这 3 个文本进行矢量化,以便我们的算法能够理解它们。**

test = ["This is one is about London.", "London is a beautiful city", "I love London"]
results = kmeans.predict(tfidf_vectorizer.transform(test))
print (results)

# Prints [0, 0, 0]

test = ["This is one is about Paris.", "Paris is a beautiful city", "I love Paris"]
results = kmeans.predict(tfidf_vectorizer.transform(test))
print (results)

# Prints [2, 2, 2]

test = ["This is one is about Berlin.", "Berlin is a beautiful city", "I love Berlin"]
results = kmeans.predict(tfidf_vectorizer.transform(test))
print(results)

# Prints [1, 1, 1]

test = ["This is about London", "This is about Paris", "This is about Vienna"]
results = kmeans.predict(tfidf_vectorizer.transform(test))
print (results)

# Prints [0, 2, 1]

**看起来我们的集群成功了!现在让我们假设我们会得到另一个我们一无所知的文本。我们可以将该文本通过我们的分类器,看看它属于哪个类别。我认为这是一个非常好和有效的文本分类器。**

# **结论**

**今天我们讨论了 K 均值聚类算法。我们首先对聚类算法和无监督机器学习技术进行了概述,然后讨论了 K-Means 算法,并使用 Scikit-Learn Python 库实现了它。**

***本文原载于* [*程序员背包博客*](https://programmerbackpack.com/k-means-clustering-explained/) *。如果你想阅读更多这类的故事,一定要访问这个博客。***

**非常感谢你阅读这篇文章!对更多这样的故事感兴趣?在 Twitter 上关注我,在[*@ b _ dmarius*](https://twitter.com/b_dmarius)*我会在那里发布每一篇新文章。***

# k 均值聚类

> 原文:<https://towardsdatascience.com/k-means-clustering-fa4df5990fff?source=collection_archive---------22----------------------->

## **概述**

今天机器学习的大多数应用都是基于监督学习的。然而,大部分数据是没有标签的:我们有输入 **X** ,但没有标签**y**计算机科学家扬·勒库恩的名言

> 如果智能是一块蛋糕,无监督学习就是蛋糕,有监督学习就是糖衣,强化学习就是上面的樱桃。

换句话说,无监督学习有巨大的潜力。

无监督学习的一种形式是将相似的实例分组到*簇中。*聚类是数据分析、客户细分、推荐系统、搜索引擎、半监督学习、降维等等的一个很好的工具。

如果你每天在一个公园里散步,你可能会无意中发现一棵你从未见过的树。如果你环顾四周,注意到更多的一些,它们并不完全相同,但看起来非常相似,你知道它们属于同一个属。你可能需要一个树木学家来告诉你这是哪一个物种,但是你不需要专家来给你的树分类。这就是*集群*的本质:识别相似实例,并将它们分配到*集群*或相似实例组中的任务。

# k 均值

最常用的聚类技术之一是 K-means。K-means 算法是由 Stuart Lloyd 和 Bell Labs 在 1957 年作为一种脉冲编码调制技术提出的,但直到 1982 年才在公司外部发表。Edward Forgy 在 1965 年发表了几乎相同的算法,因此它被称为 Lloyd-Forgy。以下内容生成了我们将进行聚类的数据:

from sklearn.datasets import make_blobsblob_centers = np.array([[ 0.2, 2.3],[-1.5 , 2.3],[-2.8, 1.8],[-2.8, 2.8],[-2.8, 1.3]])blob_std = np.array([0.4, 0.3, 0.1, 0.1, 0.1])X, y = make_blobs(n_samples=2000, centers=blob_centers,
cluster_std=blob_std, random_state=7)plt.figure(figsize=(8, 4))
plot_clusters(X)
save_fig("blobs_plot")
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e8b26ed79709d96b3be48ffff2acabdb.png)

未标记的数据集

K-Means 在聚类上面的数据时非常有效,通常只需要很少的迭代。它将试图找到每个集群的中心,并将每个实例分配给最近的集群。让我们训练一个 K 均值聚类器:

from sklearn.cluster import KMeans
k = 5
kmeans = KMeans(n_clusters = k)
y_pred = kmeans.fit_predict(X)


每个实例被分配到五个集群中的一个。它接收一个标签*作为它被分配到的集群的索引。*

我们可以看到这些标签:

y_pred
array([4, 0, 1, ..., 2, 1, 0], dtype=int32)y_pred is kmeans.labels_
True


我们还可以看到算法找到的五个质心(聚类中心):

kmeans.cluster_centers_
array([[ 0.20876306, 2.25551336],
[-2.80580621, 1.80056812],
[-1.46046922, 2.30278886],
[-2.79290307, 2.79641063],
[-1.99213367, 1.3131094 ]])


对于新数据,我们也可以很容易地做到这一点,通过查看任何新数据点最接近哪个质心。我们也可以可视化决策边界,每个质心用 x 表示。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e4282601343ca4612b94009c1c8112b1.png)

k 意味着判定边界和质心

最初,随机放置质心,标记实例,并更新质心。这个过程反复进行,直到质心停止移动,并且已经定义了聚类。

# 加速 K-均值算法

加速 K-Means 是 Sklearn 的默认设置。它通过跟踪实例和质心之间的距离的下限和上限,大大加速了该算法。你可以强迫 Sklearn 使用原来的算法,尽管不太可能需要。

# 小批量 K 均值

代替在每次迭代中使用完整的数据集,该算法能够使用小批量,在每次迭代中稍微移动质心。这通常会将算法速度提高 3 到 4 倍。尤其重要的是,它使得对不适合内存的大型数据集进行聚类成为可能。一个限制是它的惯性通常稍差,尤其是当集群增加时,但是对于许多集群,使用小批量的速度要快得多。

# 寻找最佳的聚类数

在这个数据集中,我们可以清楚地看到有 5 个我们想要彼此分割的聚类。然而,情况并不总是如此,我们的数据通常没有像这样明显地分段。如果我们不采取预防措施来计算最佳集群数量,我们的结果可能会很差:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/885da5cae8ba44fd73aa2e8bb8bed146.png)

K 值过低

第一个想法是选择最小化惯性的 k,但是我们不能这样做,因为惯性总是随着 k 的增大而减小。事实上,集群越多,每个实例越接近其最近的质心,因此惯性越低。正如我们在 k=8 的情况下所看到的,我们正在毫无理由地分割集群。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f40f73df01747e624eb10626a52df46e.png)

惯性作为 k 的函数

惯性很快下降到 5,但之后下降很慢。任何低于 5 的 k 值,增益都是巨大的,任何高于 5 的 k 值,我们都不会得到更多的信息。这是一种相当粗糙的,主观的分配 k 的方法,但是它通常工作得很好。这样做时,我们也可以考虑业务问题的特定需求。

然而,在这种情况下,我们可以看到有 5 个集群我们想要细分。4 个集群可能足够了,但是我们应该研究 k=4 和 k=5 之间的差异

# 剪影分数

另一种更精确的方法是对每个实例使用轮廓分数,并对不同数量的聚类绘制它们,然而这种方法计算量更大,它将给出更清晰的最佳 k:

from sklearn.metrics import silhouette_scoresilhouette_score(X, kmeans.labels_)silhouette_scores = [silhouette_score(X, model.labels_) for model in kmeans_per_k[1:]]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/621fac35a5005266f2cd4f803df9504c.png)

聚类数和轮廓分数

正如我们所看到的,使用 k 的每个级别的轮廓分数,哪一个 k 是最优的就更加明显了。

更有用的是绘制每个实例的轮廓系数,按它们所在的聚类和系数的值排序。这是一张剪影图。形状的高度表示聚类包含的实例数量,其宽度表示聚类中实例的排序轮廓系数(越宽越好)。虚线表示平均轮廓系数。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/edb45221302efeeb2fd9ce43264fdea7.png)

分析各种 K 的轮廓图

垂直虚线表示每个聚类数的轮廓分数。如果许多实例在虚线的短边(左边)停止,那么这个集群就相当糟糕,因为这意味着这些实例彼此靠得太近。在 k=3 和 k=6 时,我们得到的是坏簇,但在 k=4 和 k=5 时,它们相当好。大多数情况下会超出虚线。然而,当 k=4 时,橙色集群相当大,而在 k=5 时,它们都是相似的大小,所以看起来应该使用 5 来获得相似大小的集群。

执行这一过程显示了肘方法的明显局限性,定期执行它可以增强您选择 k 的稳健性。

# **K-意味着限制**

作为一名优秀的数据科学家,了解你所使用的方法背后的假设是很重要的,这样你才能对它们的优缺点有所了解。这将帮助您决定何时以及在什么情况下使用每种方法:

*   我们经常会得到次优解和局部极小值(由于质心的随机初始化),因此需要多次运行算法来避免这种情况。
*   除此之外,我们还需要指定 k,这可能是主观的,有时相当麻烦,取决于数据集。
*   最大的问题是,当聚类具有不同的大小、密度或非球形形状时,K-Means 的性能不是特别好。根据数据的不同,另一种聚类算法可能会更好。(通常,在执行 K-Means 之前缩放输入要素会有所帮助,但这并不能保证所有聚类都是完美的球形)
*   K-Means 也给予较大的聚类比较小的聚类更多的权重。换句话说,较小聚类中的数据点可以远离质心,以便更多地集中在较大的聚类上。这可能仅仅因为不平衡的数据而导致较小的集群分配不当。
*   最后,因为 K-Means 将每个实例分配到一个非重叠的聚类中,所以对于位于边界线附近的点没有不确定性的度量

在本文中,我讨论了最著名的聚类算法之一——K-Means。我们研究了在使用 K-Means 时可能面临的挑战。

我们实现了 k-means 并查看了肘形曲线,这有助于在 K-Means 算法中找到最佳的聚类数,同时也展示了它的局限性。

如果你有任何疑问或反馈,欢迎在下面的评论区分享

**参考文献**

Aurelien Geron (2019) *用 Scikit-Learn、Keras 和 TensorFlow 进行动手机器学习:构建智能系统的概念、工具和技术图书*,第 2 版。,:奥赖利。

所有可视化的代码都可以在我的 GitHub [这里](https://github.com/Carterbouley/kmeans)找到

# 适用于初学者的 k-均值聚类

> 原文:<https://towardsdatascience.com/k-means-clustering-for-beginners-ea2256154109?source=collection_archive---------16----------------------->

## 一个学生用 Python 对这个有趣而有用的机器学习算法进行了深入的解释和逐步的指导

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f55426d89c96f344c5eeac057015a29e.png)

Python K-Means 聚类(所有照片按作者分类)

# 介绍

K-意思是聚类是我在进入机器学习时学习的第一批算法之一,就在线性和多项式回归之后。

但是 K-Means 从根本上背离了后两者。回归分析是一种*监督的* ML 算法,而 K-Means 是*非监督的。*

**这是什么意思?**

监督学习和非监督学习是机器学习算法的两大类别:

## 监督学习

你输入标有数据的程序。换句话说,你在提供正确答案的数据上训练算法,然后将学习到的规则应用于新数据,以预测它们的答案。

这对回归和分类很有用。

## 无监督学习

您不需要为数据提供标签,而是由程序来发现它们。

这对于聚类和发现数据中的隐藏模式非常有用。

# 重要提示:

如果你是初学者,我建议你先阅读这些关于线性和多项式回归的文章,我在下面链接了这些文章。在其中,我涵盖了一些基本的机器学习知识和术语,我将在整篇文章中以此为基础。

[](/linear-regression-the-actually-complete-introduction-67152323fcf2) [## 线性回归:(实际上)完全介绍

### 一位同学用 Python 对这个简单的机器学习算法进行了全面、深入的解释

towardsdatascience.com](/linear-regression-the-actually-complete-introduction-67152323fcf2) [](/polynomial-regression-the-only-introduction-youll-need-49a6fb2b86de) [## 多项式回归:你需要的唯一介绍

### 一名学生对 Python 中机器学习算法背后的理论和应用的深入探究

towardsdatascience.com](/polynomial-regression-the-only-introduction-youll-need-49a6fb2b86de) 

# 该算法

我想象一个有大量数据点的数据集。我们的目标是将每个点分配给一个集群或组。要做到这一点,我们需要找出集群在哪里,以及哪些点应该属于每一个。在我们的例子中,我们将有两个变量:不同国家的出生率和预期寿命。我们可以创建这个数据的散点图来可视化我们的组。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/66936bcf4a3cc8d66fb6f04c022b178a.png)

K-均值聚类的一个例子

*为什么我们要对这些数据执行 K-Means 聚类?*

这里有一个实际的例子:假设联合国希望根据这两个指标将国家分为三类,这样它们就可以根据各自的需求提供相应的援助。

除了目测,我们可以使用 K-Means 来自动化这个过程(其中 *K* 表示我们想要创建的集群的数量,而 *Mean* 表示平均值)。

**K 均值背后有两个关键假设:**

1.  每个聚类的中心是属于该聚类的所有数据点的平均值。
2.  每个数据点属于具有最近中心点的聚类。

这两个简单的假设描述了整个算法。我们的程序所做的就是迭代几个步骤,每个步骤都试图满足上述条件。

## 距离

在继续之前,我们必须讨论距离的概念。我们可以在 ML 中使用许多距离度量,例如*曼哈顿*和*切比雪夫*,但今天我们将坚持使用更熟悉的*欧几里德、*,你可能会记得高中数学中的这些。

在二维空间中,两点之间的欧几里德距离是

√((xⱼ — xᵢ)² + (yⱼ — yᵢ)²)


## 步伐

这是算法的概要:

1.  通过从数据集中随机选取点并使用这些点作为平均值的初始值,初始化每个聚类的平均值。
2.  将每个点分配给最近的聚类。
3.  计算每个聚类的平均值,作为属于它的所有点的平均值。
4.  重复 2 和 3 预定的次数,或者直到收敛。

# 这个例子

像往常一样,我们从进口开始:

1.  matplotlib(py plot & RC params)——创建我们的数据可视化
2.  sci kit-Learn(pairwise _ distances _ arg min)-执行机器学习
3.  NumPy——做科学计算
4.  csv —读取 csv 文件
5.  集合(计数器和默认值)—用于计数

import matplotlib.pyplot as plt
import numpy as np
import csv
from sklearn.metrics import pairwise_distances_argmin
from collections import Counter, defaultdict


我有一个 csv 文件,其中包含如下所示的数据:

Countries,BirthRate(Per1000 - 2008),LifeExpectancy(2008)
Afghanistan,46.613,47.532
Albania,14.69,76.492
Algeria,20.804,72.44
...


为了处理这些数据,我们需要一些变量来保存我们的 *x 值、y 值、标签*和*国家名称,在这个 csv 文件中是*。我们可以用一个函数从文件中提取所有这些信息:

x, y, x_label, y_label, countries = read_csv()


我对 *read_csv()* 函数的定义如下。当然,您应该调整它以适合您的 csv 文件。

def read_csv():
x = []
y = []
countries = []
x_label = ""
y_label = ""
with open('dataBoth.csv') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
lines = 0
for row in reader:
if lines >= 1:
print(', '.join(row))
x.append(float(row[1]))
y.append(float(row[2]))
countries.append(row[0])
lines += 1
else:
x_label = row[1]
y_label = row[2]
print(', '.join(row))
lines += 1
return x, y, x_label, y_label, countries


现在我们已经处理了数据,我们需要将 x 和 y 组合成(x,y)对的 2D 列表,我们可以这样做:

X = np.vstack((x, y)).T


现在我们有了一个 2D 列表(实际上是一个 numpy 数组),如下所示:

[[46.613, 47.532]
[14.69, 76.492]
[20.804, 72.44]
...]


让我们绘制这些数据点的散点图,看看我们在这里处理的是什么:

plt.xlabel(x_label)
plt.ylabel(y_label)
plt.scatter(x, y, color='#76c2b4')
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a16c9177d1bef301a6774f2f1c6395b2.png)

(出生率、预期寿命)对列表的散点图

正如你所看到的,出生率和预期寿命之间的负相关是显而易见的。然而,3 个不同的组不会立即出现。这就是 K-Means 的用武之地。

接下来,我们将编写迭代创建集群的函数。该函数的逐行解释作为注释包含在下面的代码片段中,但是我也将在这里提供一些说明。

我们可以使用*NP . random . random state(rseed)*选择随机中心,调用*。在那上面排列*找到一个 *i* ,然后选择 X 的第个元素*,这就是我们的 *(x,y)* 对的 2D 列表,记住。我们有一个循环,其中我们使用*pairwise _ distance _ arg min*来计算点和中心之间的距离,然后从这些点的平均值中找到新的中心,然后检查聚类是否已经收敛(如果不能选择新的中心,则平均值变小)。当群集收敛时,此循环终止:*

def find_clusters(X, n_clusters, rseed=2):
# 1. Randomly choose clusters
rng = np.random.RandomState(rseed)
i = rng.permutation(X.shape[0])[:n_clusters]
centers = X[i]

# The main loop
# This loop continues until convergence.
# You could make it run a set number of times by changing
# it to say while x > 5, for example, and removing the break
print("\nConverging centres:")
while True:
    # 2a. Assign labels based on closest center
    # I am using the pairwise_distances_argmin method to
    # calculate distances between points to centres
    labels = pairwise_distances_argmin(X, centers)

    # 2b. Find new centers from means of points
    new_centers = np.array([X[labels == i].mean(0) for i in
    range(n_clusters)])

    # 2c. Check for convergence
    if np.all(centers == new_centers):
        break
    centers = new_centers

    # Print converging centres
    print(centers)
    print()

return centers, labels

让我们将集群的数量设置为 3:

clust_num = 3


剩下要做的就是将我们的 K-Means 算法应用于数据的结果可视化:

centers, labels = find_clusters(X, clust_num)
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.title('K-Means clustering of countries by birth rate vs life expectancy')
plt.xlabel(x_label)
plt.ylabel(y_label)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/eef0506d207cc597b74b364beb3980cf.png)

数据被分成 3 组

那就是成功实现的算法!

但是如果我们想要更多的信息呢?

毕竟,联合国希望看到每个集群中的国家名称。

我们可以提取所有这些信息,并将其打印到终端:

print("\nNumber of countries in each cluster:")
print(Counter(labels))

Get cluster indices

clusters_indices = defaultdict(list)
for index, c in enumerate(labels):
clusters_indices[c].append(index)

Print countries in each cluster and means

x = 0
while x < clust_num:
print("\nCluster " + str(x + 1))
print("----------")
for i in clusters_indices[x]:
print(countries[i])
print("----------")
print("Mean birth rate:")
print(centers[x][0])
print("Mean life expectancy:")
print(centers[x][1])
x+=1


这将打印每个集群中的国家以及该集群的平均出生率和预期寿命。

# 结论

至少应该清楚,K-Means 聚类是一种非常有用的算法,有许多实际应用。希望您已经学到了足够的知识,可以对一些有趣的数据执行自己的实现,并发现一些隐藏的聚类。

**内容概述:**

1.  监督与非监督机器学习的简单比较。
2.  该技术应用的一个例子。
3.  算法的概要。
4.  实现的例子。

如果您觉得这篇文章有帮助,我很乐意与您合作!在 Instagram 上关注我,了解更多机器学习和软件工程内容。

编码快乐!

[**订阅**](https://medium.com/subscribe/@adenhaus) 📚为了不错过我的一篇新文章,如果你还不是中等会员,请加入[](https://medium.com/@adenhaus/membership)**🚀去读我所有的,还有成千上万的其他故事!**

# **资源**

****ski kit Learn***sk Learn . cluster . k means*[https://sci kit-Learn . org/stable/modules/generated/sk Learn . cluster . k means . html](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html)**

****Python 文档** *收藏*[https://docs.python.org/2/library/collections.html](https://docs.python.org/2/library/collections.html)**

****SciPy***numpy . random . random state*https://docs . SciPy . org/doc/numpy-1 . 15 . 0/reference/generated/numpy . random . random state . html**

****sci kit Learn***sk Learn . metrics . pairwise _ distance _ arg min*[https://sci kit-Learn . org/stable/modules/generated/sk Learn . metrics . pairwise _ distance _ arg min . html](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise_distances_argmin.html)**

****Numpy.org**numpy . v stackhttps://numpy . org/doc/stable/reference/generated/numpy . v stack . html**

# k-均值聚类从零开始

> 原文:<https://towardsdatascience.com/k-means-clustering-from-scratch-6a9d19cafc25?source=collection_archive---------7----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0f68587fe0374263f76a4f778937d7f8.png)

梅尔·普尔在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

## 我们学习 K-Means 聚类是如何工作的,并一点一点地对它进行编码

K -means 聚类(本文简称 k-means)是一种流行的无监督机器学习算法(无监督是指不需要目标变量,也就是 Y 变量来训练算法)。当我们面对数据时,尤其是具有大量特征的数据,将它们分类是很有帮助的。通过将相似的观察结果分类到一个桶中(也称为集群),我们可以比较和对比这些桶。理解驱动跨存储桶差异的特征为我们提供了关键的线索,让我们知道在创建分析或构建模型时应该关注什么特征(我们甚至可能希望将我们的分类直接用作模型特征)。

简而言之,这就是集群。现在让我们看看 k-means 是如何将我们的观察结果分成有意义的聚类的。

# 入门指南

如果你想看完整的代码,你可以从 GitHub 这里下载。

我已经为之前的帖子下载了它,所以我们今天将再次使用泰坦尼克号数据集:

import numpy as np
import pandas as pd
import numpy.matlib
import matplotlib.pyplot as plt
import seaborn as snstitanic = pd.read_csv('train.csv')


由于我们的主要重点是构建 k-means 并探索它是如何工作的,所以我们将只处理数据集中的两列:票价(为机票支付的价格)和乘客的年龄。我们也将删除空值。我先按票价然后按年龄对数据进行分类,因为我最终会选择前 k 个观察值作为聚类中心(质心)。排序确保了我将挑选 k 个彼此非常相似的观测值作为我的初始质心。这样,起始质心将是次优的,我们可以更清楚地看到算法如何能够收敛到更好的质心(和聚类)。

cluster_data = titanic[['Fare','Age']].copy(deep=True)
cluster_data.dropna(axis=0, inplace=True)
cluster_data.sort_values(by=['Fare','Age'], inplace=True)
cluster_array = np.array(cluster_data)


我们将要聚类的数据存储在数组 **cluster_array** 中。它看起来如下(第一列是票价,第二列是年龄):

Fare Age

[[ 0. 19. ]
[ 0. 25. ]
[ 0. 36. ]
[ 0. 38. ]
[ 0. 39. ]
[ 0. 40. ]
[ 0. 49. ]
[ 4.0125 20. ]
[ 5. 33. ]
[ 6.2375 61. ]]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ce6aa0eaac8514acd818e468b5c7d553.png)

罗斯·斯奈登在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

# K-均值算法

在我们编写代码之前,让我们先从概念上理解 k-means 算法是如何工作的。K-means 把每个星团想象成一个太阳系。**星团中的一切(所有观测)围绕的恒星被称为星团的质心。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0d403fdc5519687ebfb9aef19d5d4ef0.png)

簇及其质心

所以给定一组质心和它们的坐标(其中 X 坐标是 fare,Y 坐标是 age),我们可以通过计算每个观察值最接近哪个质心(根据欧几里德距离)来轻松地计算出每个观察值属于哪个簇。

但是我们如何决定质心在哪里呢?这就是 k 均值算法的用武之地。首先,我们选择一个 k 值,即质心的数量(这是一个我们必须调整的超参数)。假设我们选择 k 为 4。然后我们可以随机选择 4 个点,并将它们指定为我们的起始质心。使用我们随机选择的起始质心,我们可以创建 4 个集群。听起来有点傻,对吧?选择随机质心并创建随机簇有什么意义?

这里有一个窍门:**我们聚类的平均值成为我们新的质心**(对于每个聚类,我们计算平均费用和平均年龄,这是我们新质心的坐标)。只要我们开始随机挑选的质心彼此稍有不同,新的质心(聚类平均值)将比我们最初的聚类更优;其中**最优性被定义为最大化集群内的相似性和集群间的差异**。

一旦我们有了新的质心,我们就可以根据它最接近的新质心来重新分配每个观测值的聚类。由于质心变得更加优化,我们的聚类也应该改进(在聚类内的同质性和跨聚类的方差方面)。现在,我们可以根据重新分配的簇的坐标的平均值,再次计算新的质心。这些质心将再次改进它们的前身,我们可以不断清洗和重复这个过程,直到算法收敛。收敛被定义为当我们不再能够减少所有聚类的偏离质心的平方和(也称为聚类平均值)时。与平均值的方差之和是一种衡量聚类成员之间相似程度的方法,该值越低,越相似越好。

一个例子可能会帮助你更好地理解这个算法的工作原理。想象一个房间里挤满了不同身高的人(下图)。我们想根据唯一可观察的参数,高度,将它们分成两类。所以我们随机选择两个人(穿灰色衣服的),并告诉其他人站在他们身高最接近的人旁边(抛硬币以打破平局)。一旦他们这样做了,这个组的平均值(或者身高等于平均值的人)就成为新的质心(绿色)。注意这是如何将质心推开的——绿色质心比灰色质心离得更远。这种推开所有质心(实际上我们会有不止 1 个特征和 2 个质心)是我们重复取平均值和重新聚类(假设我们没有取最大值和彼此相反的极值点作为初始质心)时往往会发生的情况。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d53f63971328467bf5dfdadb3fe24040.png)

新聚类的均值如何变得更优的示例

# 编码 K-均值-辅助函数

在我们开始编写代码之前,让我们回顾一下步骤:

1.  随机分配质心来启动事物。
2.  基于这些质心(以及一个观测到质心的距离),将每个观测分配给一个簇。
3.  计算每个簇的平均坐标;这些是我们新的质心。
4.  基于新的质心重新分配簇。
5.  不断重复步骤 3 和 4,直到收敛。

为了让生活更简单,让我们定义几个助手函数。首先让我们写一个来计算两点之间的欧几里德距离(又名两点之间的直线距离):

def calc_distance(X1, X2):
return (sum((X1 - X2)2))0.5


接下来,我们需要一个给定一组质心的函数,它可以告诉我们每个观察值属于哪个簇。下面的函数使用嵌套的 for 循环(我知道效率不高)来计算每个观察值和每个质心之间的距离(使用我们的 **calc_distance** 函数)。然后,它根据最接近的质心将观察值分配给一个聚类。输出是每个观察的分类标签的列表。

Assign cluster clusters based on closest centroid

def assign_clusters(centroids, cluster_array):
clusters = []
for i in range(cluster_array.shape[0]):
distances = []
for centroid in centroids:
distances.append(calc_distance(centroid,
cluster_array[i]))
cluster = [z for z, val in enumerate(distances) if val==min(distances)]
clusters.append(cluster[0])
return clusters


现在我们需要一个更新步骤的函数,在这里我们分配新的质心。以下函数将数据(每次观察的费用和年龄)、 **cluster_array** 及其所属的当前聚类、 **clusters** 连接在一起,形成一个数据帧、 **cluster_df** 。然后,我们可以按簇过滤 **cluster_df** ,以获得属于特定簇的观察值,并计算这些观察值的平均值。这些计算的平均值就是我们新的质心。

Calculate new centroids based on each cluster's mean

def calc_centroids(clusters, cluster_array):
new_centroids = []
cluster_df = pd.concat([pd.DataFrame(cluster_array),
pd.DataFrame(clusters,
columns=['cluster'])],
axis=1)
for c in set(cluster_df['cluster']):
current_cluster = cluster_df[cluster_df['cluster']
==c][cluster_df.columns[:-1]]
cluster_mean = current_cluster.mean(axis=0)
new_centroids.append(cluster_mean)
return new_centroids


**calc_centroids** 的返回值是一个数组,其中第一列是每个分类的平均费用,第二列是每个分类的平均年龄:

Example Output of calc_centroids # Mean Mean

# Fare       Age
        0          1

0 34.835711 18.394295
1 13.119311 32.090217
2 285.381483 31.166667
3 96.662211 36.114023


我们需要的最后一个助手函数更多的是用于报告目的。我们想知道聚类内的方差是多少,或者换句话说,一个聚类内的观测值彼此之间有多相似或不相似。因此,让我们构建一个函数来计算每个聚类相对于质心的偏差平方和。该函数按聚类过滤 **cluster_df** ,计算平均值,然后从聚类内的每个观察值中减去聚类平均值。函数 **repmat** 获取一个给定的数组并复制它——在我们的例子中,我们希望复制我们观察到的所有次数的平均值,这样我们就可以直接减去这两个数组。

Calculate variance within each cluster

def calc_centroid_variance(clusters, cluster_array):
sum_squares = []
cluster_df = pd.concat([pd.DataFrame(cluster_array),
pd.DataFrame(clusters,
columns=['cluster'])],
axis=1)
for c in set(cluster_df['cluster']):
current_cluster = cluster_df[cluster_df['cluster']
==c][cluster_df.columns[:-1]]
cluster_mean = current_cluster.mean(axis=0)
mean_repmat = np.matlib.repmat(cluster_mean,
current_cluster.shape[0],1)
sum_squares.append(np.sum(np.sum((current_cluster - mean_repmat)**2)))
return sum_squares


酷,我们现在准备运行 k-means。

# 运行 K 均值

让我们仍然使用 4 个集群(k=4)。就像我之前所说的,我们将有目的地选择糟糕的起始质心,这样我们就可以看到算法所做的改进(我使用观察 2、3、4 和 5,因为它们产生了非常糟糕的起始簇)——*实际上,我们不想这样做,因为它会减慢速度*。然后,我们使用我们的助手函数 **assign_clusters** ,根据最接近的质心将每个观察值分配给一个集群。

接下来,我们运行 for 循环 20 次(在这种情况下,20 次就足够收敛了),其中我们重复计算新的质心(使用 **calc_centroids** )和新的聚类(使用 **assign_clusters** ),以便我们可以获得最佳的聚类。回想一下,通过重复计算聚类平均值(也称为新质心)和基于这些新质心分配新聚类的过程,该算法如何收敛到最终的聚类。

k = 4
cluster_vars = []centroids = [cluster_array[i+2] for i in range(k)]
clusters = assign_clusters(centroids, cluster_array)
initial_clusters = clusters
print(0, round(np.mean(calc_centroid_variance(clusters, cluster_array))))for i in range(20):
centroids = calc_centroids(clusters, cluster_array)
clusters = assign_clusters(centroids, cluster_array)
cluster_var = np.mean(calc_centroid_variance(clusters,
cluster_array))
cluster_vars.append(cluster_var)
print(i+1, round(cluster_var))


对于我的循环中的每一次迭代,我都在列表 **cluster_vars** 中存储了聚类与其质心的偏差平方和的平均值。此平均值是每个分类(对于所有分类)内方差水平的近似度量。因为我们希望集群成员尽可能相似,所以我们希望这个平均值尽可能低。让我们看看这个平均值是如何随着我们的迭代而演变的。开始时急剧下降,然后趋于平稳。到我们循环的第六次迭代时,它差不多收敛了。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/662eb498926b0cb971c4de203771e6a8.png)

所有聚类的平均方差和与循环迭代次数的关系

让我们看看我们的集群是否变得更好了。回想一下,我们从任意选择的质心开始。以下是基于这些初始质心的聚类(每种颜色都是一个聚类)。看起来我们很幸运有一些基于年龄的分离,但仅此而已。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d214191ecd908d6b120862172aab7f1b.png)

初始聚类

这是聚合集群。这些集群的区分似乎更有意义:

1.  有年纪较大的低价位乘客(绿色)。
2.  年轻的低票价人群(深红色)。
3.  买得起高价票的人(蓝色)。
4.  还有那些买得起超贵门票的(讽刺的是黄金)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f4a7e40cc0fe48bc38248280dfc1273a.png)

聚合集群

另一种检验我们做得如何的方法是通过观察我们的集群的生存概率是否不同。记住 k-means 聚类是无监督的;因此,我们没有明确地训练模型来预测乘客是否幸存。相反,我们希望通过产生有意义的差异化集群,我们可以发现在我们关心的事情(在这种情况下是生存)方面也恰好表现不同的群体。相对于我们最初的集群,我们的聚合集群似乎在预测存活率方面做得更好。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ed50a77fe6ade53b22d37904674a8f92.png)

该算法找到了具有更高生存概率的聚类

# 结论

显然,我们还可以做更多的事情,包括添加更多的功能(而不是只有 2 个),调整 k(集群的数量),并尝试更好地理解每个集群的身份和关键特征。但那是以后的事了。我希望通过阅读这篇文章,你对聚类是如何工作的,以及 k-means 是如何使用一个非常简单的算法来产生一些非常酷的结果有了一些了解。干杯,大家注意安全!

# K-Means 聚类:工作原理&在数据中寻找最优的聚类数

> 原文:<https://towardsdatascience.com/k-means-clustering-how-it-works-finding-the-optimum-number-of-clusters-in-the-data-13d18739255c?source=collection_archive---------8----------------------->

## 数学公式,寻找最佳聚类数和 Python 中的工作示例

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cea6dbd3066c87f2a98aedd5c8565ae7.png)

作者创造的形象

# 介绍

> K-means 是应用最广泛的无监督聚类方法之一。

**K-means** 算法通过尝试将样本分成等方差的 **K** 组来对手头的数据进行聚类,从而最小化被称为 ***惯性*** 或**组内平方和**的标准。**该算法要求指定聚类数**。它适用于大量样品,并已在许多不同领域的大范围应用中使用。

k-means 算法将一组 **N** 个样本(存储在数据矩阵 **X** 中)分成 **K** 个不相交的聚类 **C** ,每个聚类由聚类中样本的均值 ***μj*** 来描述。这个星团通常被称为“T28 质心”。

**K-means** 算法属于**无监督**机器 学习算法/方法的家族。对于这一系列模型,研究需要手头有一个带有一些观察值的数据集**,而不需要观察值的**标签** / **类别**。无监督学习研究系统如何从未标记的数据中推断出描述隐藏结构的函数。**

现在让我们来发现算法的数学基础。

# 数学公式

给定一组观察值( **x** 1、 **x** 2、…、 **x** *n* ),其中每个观察值是一个*d*-维实向量,*k*-意味着聚类旨在将 *n* 个观察值划分为 *k* (≤ *n* )个集合**形式上,目标定义如下:**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d5cf771fd13e0b65aeea3b0be201129a.png)

作者创作的乳胶图像。

其中***μ***I 是组/簇 *Si* 中的点的平均值。

如果你想在交互式路线图和活跃的学习社区的支持下自学数据科学,看看这个资源:[https://aigents.co/learn](https://aigents.co/learn)

# 理解背后的算法

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4aa93fe2c4722c912f02e69600e8d231.png)

部分 Voronoi 图示例(来源:[https://sci kit-learn . org/stable/auto _ examples/cluster/plot _ k means _ digits . html # sphx-glr-auto-examples-cluster-plot-k means-digits-py](https://scikit-learn.org/stable/auto_examples/cluster/plot_kmeans_digits.html#sphx-glr-auto-examples-cluster-plot-kmeans-digits-py))。

该算法也可以通过 Voronoi 图的概念来理解。

首先,使用当前质心计算点的 Voronoi 图。最初,质心是随机选择的*通常是*,但这取决于底层使用的包/库/软件。

Voronoi 图中的每个线段成为一个单独的簇。

其次,质心被更新到每个线段的平均值。然后,该算法重复这一过程,直到满足停止标准。

当迭代之间**目标** **函数**中的相对**减少**小于给定的**容差** (ε)值**或**质心** **移动**(在空间中)**小于**容差**时**算法**停止**。**

# 寻找最佳聚类数

如介绍中所述,**K-Means 算法需要预先指定聚类的数量。如果没有关于数据中潜在聚类数的有效假设,这项任务可能很难完成。**

幸运的是,有一些方法可以估计我们数据中的最佳聚类数,如**轮廓系数或肘方法。**如果地面真实标签未知,必须使用模型本身进行评估。在本文中,我们将只使用**轮廓系数**,而不是简单得多的肘法。简而言之,[肘方法](https://en.wikipedia.org/wiki/Elbow_method_(clustering))将方差百分比解释为聚类数的函数:应该选择多个聚类,以便添加另一个聚类不会提供更好的数据建模。

**较高的轮廓系数分数与具有更好定义的聚类的模型相关**。轮廓系数是为每个样本定义的,由两个分数组成:

*   **a** :一个样本到同一类中所有其他点的平均距离。
*   **b** :样本与下一个最近簇*中所有其他点之间的平均距离*。

单个样本的轮廓系数 ***s*** **定义为:**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7d684f1f618b60ada237faef6d62d3d0.png)

作者创作的乳胶图像。

**最后,一组*样本的总轮廓系数*作为每个样本轮廓系数的平均值给出。**

> 最好的值是 1,最差的值是-1。接近 0 的值表示重叠的簇。负值通常表示样本被分配到错误的聚类,因为不同的聚类更相似。

# Python 工作示例

对于本例,我们将创建人工数据,即人工聚类。这样**我们将提前**知道**地** **到**即**我们数据集**中簇的确切数目。

让我们从导入所需的 python 库开始:

from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples, silhouette_score

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np


接下来,让我们创建一些包含 **500 个样本**、 **2 个特征/变量**和 **K=4 个聚类**的人工数据。

Generating the data

This particular setting has one distinct cluster and 3 clusters placed close together.

X, y = make_blobs(n_samples=500,
n_features=2,
centers=4,
cluster_std=1,
center_box=(-10.0, 10.0),
shuffle=True,
random_state=1)


我们知道数据中有 K=4 个聚类,但是,为了了解剪影评分如何工作**,我们将使用一系列不同数量的聚类来拟合模型。**

每一次,我们将估计**轮廓分数**,并且也用最终(**收敛** ) **质心**绘制数据。所有这些都是由下面的代码完成的:

range_n_clusters = [3, 4, 5]for n_clusters in range_n_clusters:
# Create a subplot with 1 row and 2 columns
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.set_size_inches(18, 7)

# The 1st subplot is the silhouette plot
# The silhouette coefficient can range from -1, 1 but in this example all
# lie within [-0.1, 1]
ax1.set_xlim([-0.1, 1])
# The (n_clusters+1)*10 is for inserting blank space between silhouette
# plots of individual clusters, to demarcate them clearly.
ax1.set_ylim([0, len(X) + (n_clusters + 1) * 10])

# Initialize the clusterer with n_clusters value and a random generator
# seed of 10 for reproducibility.
clusterer = [KMeans](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans)(n_clusters=n_clusters, random_state=10)
cluster_labels = clusterer.fit_predict(X)

# The silhouette_score gives the average value for all the samples.
# This gives a perspective into the density and separation of the formed
# clusters
silhouette_avg = [silhouette_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_score.html#sklearn.metrics.silhouette_score)(X, cluster_labels)
print("For n_clusters =", n_clusters,
      "The average silhouette_score is :", silhouette_avg)

# Compute the silhouette scores for each sample
sample_silhouette_values = [silhouette_samples](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_samples.html#sklearn.metrics.silhouette_samples)(X, cluster_labels)

y_lower = 10
for i in range(n_clusters):
    # Aggregate the silhouette scores for samples belonging to
    # cluster i, and sort them
    ith_cluster_silhouette_values = \
        sample_silhouette_values[cluster_labels == i]

    ith_cluster_silhouette_values.sort()

    size_cluster_i = ith_cluster_silhouette_values.shape[0]
    y_upper = y_lower + size_cluster_i

    color = cm.nipy_spectral(float(i) / n_clusters)
    ax1.fill_betweenx([np.arange](https://numpy.org/doc/stable/reference/generated/numpy.arange.html#numpy.arange)(y_lower, y_upper),
                      0, ith_cluster_silhouette_values,
                      facecolor=color, edgecolor=color, alpha=0.7)

    # Label the silhouette plots with their cluster numbers at the middle
    ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))

    # Compute the new y_lower for next plot
    y_lower = y_upper + 10  # 10 for the 0 samples

ax1.set_title("The silhouette plot for the various clusters.")
ax1.set_xlabel("The silhouette coefficient values")
ax1.set_ylabel("Cluster label")

# The vertical line for average silhouette score of all the values
ax1.axvline(x=silhouette_avg, color="red", linestyle="--")

ax1.set_yticks([])  # Clear the yaxis labels / ticks
ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

# 2nd Plot showing the actual clusters formed
colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
ax2.scatter(X[:, 0], X[:, 1], marker='.', s=30, lw=0, alpha=0.7,
            c=colors, edgecolor='k')

# Labeling the clusters
centers = clusterer.cluster_centers_
# Draw white circles at cluster centers
ax2.scatter(centers[:, 0], centers[:, 1], marker='o',
            c="white", alpha=1, s=200, edgecolor='k')

for i, c in enumerate(centers):
    ax2.scatter(c[0], c[1], marker='$%d$' % i, alpha=1,
                s=50, edgecolor='k')

ax2.set_title("The visualization of the clustered data.")
ax2.set_xlabel("Feature space for the 1st feature")
ax2.set_ylabel("Feature space for the 2nd feature")

[plt.suptitle](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.suptitle.html#matplotlib.pyplot.suptitle)(("Silhouette analysis for KMeans clustering on sample data "
              "with n_clusters = %d" % n_clusters),
             fontsize=14, fontweight='bold')

plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1bd242d02eb3d6bfea3efffcf5ed2463.png)

控制台中的代码输出(图片由作者创建)

> 我们观察到,在 K=4 个聚类的情况下,平均/均值**轮廓得分最高。**

**这验证了轮廓分数是 K-均值拟合优度的良好度量。**

我们还制作了这些图:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cea6dbd3066c87f2a98aedd5c8565ae7.png)

剪影分数&最终(**收敛** ) **质心**的数据(图片由作者创建)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6216eaab829c312db69e175d98ffb59a.png)

剪影分数&最终(**收敛** ) **质心**的数据(图片由作者创建)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9974c12b7dd9300bbc358f9d57cc2040.png)

剪影分数&最终(**收敛** ) **质心**的数据(图片由作者创建)

**垂直线是所有值的平均轮廓得分。**

**同样,我们还可以直观地验证轮廓得分是特定示例的 K 均值拟合优度的良好度量。**

# **结论**

**K-means** 是应用最广泛的无监督聚类方法之一。该算法通过尝试将样本分成等方差的 **K** 组来对手头的数据进行聚类,从而最小化被称为惯性或类内平方和的标准。该算法要求指定聚类数。

但是,如果地面实况标签未知,则必须使用模型本身进行评估。

在本文中,我们使用了**轮廓系数。从工作示例中,我们可以验证轮廓分数是 K-means 拟合优度的良好度量。**

仅此而已!希望您喜欢这篇新文章——更多内容即将发布!

# 参考

[1]彼得·j·鲁瑟夫(1987 年)。“轮廓:聚类分析的解释和验证的图形辅助”。计算与应用数学 20:53–65。[doi:10.1016/0377–0427(87)90125–7](https://doi.org/10.1016/0377-0427(87)90125-7)。

[2][https://en . Wikipedia . org/wiki/Silhouette _(集群)](https://en.wikipedia.org/wiki/Silhouette_(clustering))

## 您可能还喜欢:

[](/lstm-time-series-forecasting-predicting-stock-prices-using-an-lstm-model-6223e9644a2f) [## LSTM 时间序列预测:使用 LSTM 模型预测股票价格

### 在这篇文章中,我将向你展示如何使用预测 LSTM 模型来预测股票价格

towardsdatascience.com](/lstm-time-series-forecasting-predicting-stock-prices-using-an-lstm-model-6223e9644a2f) [](/time-series-forecasting-predicting-stock-prices-using-an-arima-model-2e3b3080bd70) [## 时间序列预测:使用 ARIMA 模型预测股票价格

### 在这篇文章中,我将向你展示如何使用预测 ARIMA 模型来预测特斯拉的股票价格

towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-an-arima-model-2e3b3080bd70) 

# 敬请关注并支持这一努力

如果你喜欢这篇文章并觉得它有用,请关注我,这样你就可以看到我所有的新帖子。

有问题吗?把它们作为评论贴出来,我会尽快回复。

# 最新帖子

[](https://medium.com/@seralouk/the-best-free-data-science-resources-free-books-online-courses-9c4a2df194e5) [## 最佳免费数据科学资源:免费书籍和在线课程

### 最有用的免费书籍和在线课程,适合想了解更多数据科学知识的人。

medium.com](https://medium.com/@seralouk/the-best-free-data-science-resources-free-books-online-courses-9c4a2df194e5) [](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [## 用新冠肺炎假设的例子解释 ROC 曲线:二分类和多分类…

### 在这篇文章中,我清楚地解释了什么是 ROC 曲线以及如何阅读它。我用一个新冠肺炎的例子来说明我的观点,我…

towardsdatascience.com](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [## 支持向量机(SVM)解释清楚:分类问题的 python 教程…

### 在这篇文章中,我解释了支持向量机的核心,为什么以及如何使用它们。此外,我还展示了如何绘制支持…

towardsdatascience.com](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [## PCA 清楚地解释了——如何、何时、为什么使用它以及特性的重要性:Python 指南

### 在这篇文章中,我解释了什么是 PCA,何时以及为什么使用它,以及如何使用 scikit-learn 在 Python 中实现它。还有…

towardsdatascience.com](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [## 关于 Python 中的最小-最大规范化,您需要知道的一切

### 在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它

towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [](/how-and-why-to-standardize-your-data-996926c2c832) [## Scikit-Learn 的标准定标器如何工作

### 在这篇文章中,我将解释为什么以及如何使用 scikit-learn 应用标准化

towardsdatascience.com](/how-and-why-to-standardize-your-data-996926c2c832) 

# 和我联系

*   **LinkedIn**:【https://www.linkedin.com/in/serafeim-loukas/ 
*   https://www.researchgate.net/profile/Serafeim_Loukas**研究之门**:[](https://www.researchgate.net/profile/Serafeim_Loukas)

# k-均值聚类:识别有利可图的酒店客户

> 原文:<https://towardsdatascience.com/k-means-clustering-identifying-profitable-hotel-customers-87a1ed8630c9?source=collection_archive---------40----------------------->

## K-Means 聚类算法允许我们对接近平均值的观察值进行分组。这使我们能够更高效地将数据分类到特定的部分。

在本例中,K-Means 用于分析葡萄牙一家酒店的市场细分聚类。

该分析基于下面参考文献部分引用的由 **Antonio、Almeida 和 Nunes** 进行的原始研究。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/354bc873abd91cb7c322d2a309a0b449.png)

来源:Jupyter 笔记本输出

给定**提前期**(从客户预订到他们实际入住酒店的时间),以及 **ADR** (每位客户的平均每日房价),k-means 聚类算法用于直观地识别哪些细分市场对酒店最有利可图。

具有高 ADR 和低交付周期的客户是理想的,因为这意味着 1)客户支付高每日价格,这意味着酒店的利润率更高,而低交付周期意味着客户更快支付预订费用,这增加了酒店的现金流。

# 数据操作

加载数据并随机选择 100 个样本:

df = pd.read_csv('H1full.csv')
df = df.sample(n = 100)


间隔(或连续随机变量)为**提前期**和 **ADR** 定义如下:

leadtime = df['LeadTime']
adr = df['ADR']


使用'''分类代码' ' '定义具有分类成分的变量,在本例中为**细分市场**。

marketsegmentcat=df.MarketSegment.astype("category").cat.codes
marketsegmentcat=pd.Series(marketsegmentcat)


这样做的目的是为每个细分市场分配分类代码。例如,以下是数据集中一些市场细分条目的片段:

10871 Online TA
7752 Online TA
35566 Offline TA/TO
1353 Online TA
17532 Online TA
...
1312 Online TA
10364 Groups
16113 Direct
23633 Online TA
23406 Direct


应用`cat.codes`后,这里有相应的类别。

10871 4
7752 4
35566 3
1353 4
17532 4
..
1312 4
10364 2
16113 1
23633 4
23406 1


细分市场标签如下:

*   0 =公司
*   1 =直接
*   **2** =组
*   **3** =离线 TA/TO
*   **4** =在线 TA

使用 sklearn 对提前期和 ADR 特性进行缩放:

from sklearn.preprocessing import scale
X = scale(x1)


下面是 X 的一个例子:

array([[ 1.07577693, -1.01441847],
[-0.75329711, 2.25432473],
[-0.60321924, -0.80994917],
[-0.20926483, 0.26328418],
[ 0.53174465, -0.40967609],
[-0.82833604, 0.40156369],
[-0.89399511, -1.01810593],
[ 0.59740372, 1.40823851],
[-0.89399511, -1.16560407],


# k 均值聚类

当谈到选择集群数量时,一个可能的解决方案是使用所谓的**肘方法**。以下是肘部曲线的一个示例:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c7d9ba8d361e648d1f37a7236cb1f8cd.png)

来源:Jupyter 笔记本输出

这是一种计算每个分类的分类内方差的技术,方差越低,分类越紧密。

在这方面,随着分数开始变平,这意味着随着我们增加聚类的数量,方差的减少越来越少,这允许我们确定 **k** 的理想值。

但是,这种技术不一定适合较小的集群。此外,我们已经知道我们想要定义的集群的数量(k=5 ),因为我们已经知道我们想要分析的细分市场的数量。

此外,虽然 k-means 聚类方法也可以使用 PCA(或主降维)来减少特征的数量,但这在这种情况下是不合适的,因为使用的唯一两个特征(除了细分市场)是 **ADR** 和**提前期**。

因此,k-means 算法定义如下:

km = KMeans(n_clusters = 5, n_jobs = None, random_state = None)
km.fit(X)KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
n_clusters=5, n_init=10, n_jobs=None, precompute_distances='auto',
random_state=None, tol=0.0001, verbose=0)


为每个细分市场标签定义颜色主题:

Market Segment Labels: 0 (Complementary) = firebrick, 1 (Corporate) = dodgerblue, 2 (Direct) = forestgreen, 3 (Groups) = goldenrod, 4 (Offline TA/TO) = rebeccapurplecolor_theme = np.array(['firebrick', 'dodgerblue', 'forestgreen', 'goldenrod', 'rebeccapurple'])


以下是实际标签的图表:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/de7426cde7ab3814f0b5421a09394b81.png)

来源:Jupyter 笔记本输出

下面是 k-means 算法生成的聚类图:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c91545b6f26ea0f8f1f4638b74778233.png)

来源:Jupyter 笔记本输出

如前所述,具有最短交付时间和最高 ADR 的客户被视为利润最高。

但是,好像有问题!许多细分市场类别都被贴错了标签。

这是使用 k-means 聚类时的一个常见问题,并不一定表示应该抛弃该模型!相反,它只是建议我们需要以不同的方式思考我们的数据。

例如,我们已经知道哪些客户属于哪个细分市场。在这点上,生成 k-means 聚类算法来再次预测这一点并没有多大用处。相反,运行这种算法的目的是快速了解哪种类型的客户最有利可图。

此外,我们只考虑了提前期和 ADR 这两个特征。可能还有我们没有考虑到的其他特征,这些特征可以更好地表明客户可能属于哪个细分市场,并且从我们目前看到的情况来看,没有直观的证据表明某些细分市场比其他细分市场更有利可图。

对此,我们稍微简化一下分析。如果我们使用三个集群呢?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/354bc873abd91cb7c322d2a309a0b449.png)

来源:Jupyter 笔记本输出

我们看到,蓝色类别具有最高的 ADR 和最低的提前期(利润最高),而绿色类别显示最低的 ADR 和最高的提前期(利润最低)。

从这个角度来看,k-means 聚类算法提供了一种快速对酒店最赚钱的客户进行分类的有效方法,并且可以进行进一步的分析,以分析每组客户共有的某些属性。

当谈到无监督学习时——重要的是要记住这在很大程度上是一种**探索性**分析方法——目标不一定是预测,而是揭示以前可能没有考虑过的关于数据的见解。例如,为什么某些客户的交付周期比其他客户短?来自某些国家的客户更有可能符合这一特征吗?不同的客户类型呢?

这些都是 k-means 聚类算法可能无法直接回答我们的问题——但是将数据减少到单独的聚类中为能够提出这样的问题提供了一个强大的基线。

# 结论

在本例中,我们看到:

*   如何使用 Python 进行 k-means 聚类
*   k-均值聚类在按盈利能力细分酒店客户中的应用
*   有效使用 k 均值模型的数据配置

非常感谢您的参与,这个例子的相关 GitHub 库可以在[这里](https://github.com/MGCodesandStats/hotel-modelling)找到。

*免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。*

# 参考

*   [Antonio、Almeida 和 Nunes:使用数据科学预测酒店预订取消](https://www.researchgate.net/publication/309379684_Using_Data_Science_to_Predict_Hotel_Booking_Cancellations)
*   [OpenClassrooms:执行 K-Means 聚类](https://openclassrooms.com/en/courses/5869986-perform-an-exploratory-data-analysis/6177851-carry-out-a-k-means-clustering)
*   [中:用 PYTHON 中的 K-MEANS 聚类预测鸢尾花的种类](https://medium.com/@belen.sanchez27/predicting-iris-flower-species-with-k-means-clustering-in-python-f6e46806aaee)
*   [走向数据科学:当集群没有意义的时候](/when-clustering-doesnt-make-sense-c6ed9a89e9e6)
*   [方差解释:K 均值聚类不是免费的午餐](http://varianceexplained.org/r/kmeans-free-lunch/)

# Python 中的 K-Means 聚类

> 原文:<https://towardsdatascience.com/k-means-clustering-in-python-4061510145cc?source=collection_archive---------8----------------------->

## 用 K-Means 直观地介绍数据科学

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7c231ba939c65186ba9e3124c7fc1dad.png)

照片由 [NASA](https://unsplash.com/@nasa?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄

意味着聚类是一种无监督的最大似然算法,我们可以用它来将我们的数据集分成逻辑分组——称为聚类。因为它是无监督的,所以我们不需要依赖已标记的数据来进行训练。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ec2920411b338c5df7624960d7f084d2.png)

用 K-均值识别的五个聚类。

这些分类是通过将数据分成明显不同的组来创建的,其中组成每个组的值是相似的,而不同组之间的值是不同的。

K-means 中的 ***K*** 是指聚类的个数。聚类机制本身的工作方式是将数据集中的每个数据点标记为一个随机的聚类。然后,我们循环执行以下过程:

1.  取每个聚类中所有数据点的平均值
2.  将该平均值设置为新的聚类中心(质心)
3.  将每个数据点重新标记到其最近的聚类质心。

我们继续这个过程,直到质心停止移动,这意味着我们已经成功地对数据集进行了聚类!

这种算法的应用范围很广,一些最常见也最有趣的应用包括:

*   文档聚类(例如,政策、法规、技术规范)
*   市场分割
*   欺诈检测[1]
*   识别犯罪热点[2]

在本文中,我们将使用一个简单的数据集。然而,K-Means 可以有效地用于极其丰富多样的数据集-有些数据集有几十个特征和数百万个样本。

# 实现算法

我们将使用 Sci-kit Learn 实现 K-means。但在此之前,我们需要数据。这里我们可以使用 Sci-kit Learn 的`make_blobs`函数来生成给定数量的人工生成的集群:

from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=500, n_features=3, centers=5,
cluster_std=2)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7bd69b7b41f13a0556e144ff39ca382e.png)

在这个玩具示例中,我们可以分辨出我们的聚类——然而,当处理数百万个数据点和数十个特征/维度时,就变得困难多了。

这样,在变量`X`中,我们现在有了包含`500`数据点的人工数据,每个数据点由`3`特征/尺寸组成,并且每个数据点属于`5`斑点中的一个。变量`y`告诉我们每个数据点属于哪个集群——通常,我们不知道这一点。

## k 均值

现在我们有了数据。我们可以运行 K-Means 对其进行聚类!我们再次使用 sci-kit learn:

from sklearn.cluster import KMeans
model = KMeans(n_clusters=5)


这里我们已经用`5`聚类质心初始化了 K 均值模型。然后,我们可以使用`fit`方法用我们的数据`X`运行我们的模型:

model.fit(X)


现在我们可以分别使用`labels_`和`cluster_centers_`方法访问我们的数据分类和质心坐标。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/15dc28a7af1ad9ed875d735c277860a7.png)

我们分别用 **model.cluster_centers_** 和 **model.labels_** 访问 **X** 数据聚类中心和标签。

当绘制质心和标记的数据点时,我们可以看到该算法已经识别了五个聚类:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/78f8a6ecada24218a69c044509dce67a.png)

# 用肘法选择 K

我们对 K-Means 的理解中缺少的一部分是如何选择 K?

到目前为止,最流行的方法是*肘法*。幸运的是,这也非常简单。

首先,我们需要用 K 的某个值运行我们的算法—一旦完成,我们可以从`intertia_`属性中提取 X 值的误差平方和(SSE ):

sse = model.inertia_


SSE 计算为每个数据点与其分配的聚类质心之间的平方距离之和。如果所有数据点都紧紧聚集在分配给它们的质心周围,那么 SSE 将会很低,否则就会很高。

重要的是,我们要有足够的聚类来匹配我们数据集中的聚类,但不要有太多的聚类,通过简单地为每个数据点分配它自己的聚类,SSE 就会最小化。

sse = []for K in range(1, 10):
model = KMeans(n_clusters=K)
model.fit(X)
sse.append(model.inertia_)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2f01c81584ba0a6414ea55adb26787d1.png)

我们需要找到一个神奇的地方,在那里我们可以正确地确定最合理的集群数量。可以通过计算 K 值范围的 SSE 并识别上图中的“弯头”来识别该点。

这就是对 K-Means 算法聚类的介绍!我们涵盖了:

*   K 的意思是
*   用在哪里
*   我们如何使用它
*   用肘法选择 K

我希望你喜欢这篇文章——如果你有任何问题或想法,请通过 [Twitter](https://twitter.com/jamescalam) 或在下面的评论中告诉我。

感谢阅读!

# 参考

[1] A. Ghorbani,S. Farzai,[使用基于数据挖掘方法的汽车保险欺诈检测](http://www.aeuso.org/includes/files/articles/Vol8_Iss27_3764-3771_Fraud_Detection_in_Automobile_Insur.pdf) (2018),IJMEC

[2] M. Zulfadhilah 等人,[使用日志分析和 K-Means 聚类的网络分析](https://thesai.org/Downloads/Volume7No7/Paper_59-Cyber_Profiling_Using_Log_Analysis_And_K_Means_Clustering.pdf) (2016),IJACSA

**除非另有说明,所有图片均出自作者之手*

# 大学数据的 k-均值聚类

> 原文:<https://towardsdatascience.com/k-means-clustering-of-university-data-9e8491068778?source=collection_archive---------29----------------------->

## 我们能仅仅根据大学的特点把它们分为公立和私立吗?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7c50e37237126c774571c9e7ea726b30.png)

瓦迪姆·谢尔巴科夫在 [Unsplash](https://unsplash.com/photos/d6ebY-faOO0) 拍摄的照片。

大家好!对于这个项目,我想介绍一下 **K 均值聚类**,这是机器学习中最常见的聚类算法之一。在此过程中,我们将进行一些探索性的数据分析,以了解更多关于大学的数据集。

# 背景

对于那些可能是机器学习新手的人来说,**聚类**是**无监督学习模型**的一个例子,当我们将未分类的训练数据输入模型,并让我们的模型尝试根据数据的特征以某种方式对数据进行分类。

另一种方法是**监督学习模型**,我们预先为我们的训练数据分配标签,指示每个数据点属于哪个类别,该模型试图预测新数据点属于哪个类别。

我在中国从事教育工作近 4 年,我的工作涉及使用数据分析来估计学生被他们学校名单上的大学录取的可能性。为了好玩,我将用 Python 创建一个模型,使用 K-means 聚类将大学分为两组:私立和公立。事实上,一个在大学网站上至少做了粗略研究的学生可以在不到一分钟的时间内找到一所学校是私立还是公立的,但我们将看看一个模型是否能够根据似乎非常相关的特征(州外学费、毕业率)和似乎完全不相关的特征(捐赠校友的百分比)正确地对学校进行分类。

**注意:我们实际上有这个数据集的标签,但是我们不会将它们用于 K-means 聚类算法,因为这是一个无监督的学习算法。最后,我将比较 K-means 和监督学习算法,以比较这两种模型的性能。**

# 数据

以下是[该数据集](https://github.com/ChrisWoodard43/KMeans-Universities)中的特征—随意浏览它们,并思考它们预测一所学校是公立还是私立的好坏程度:

*   **申请**:收到的申请数量
*   **受理**:受理的申请数量
*   **招生**:招生人数
*   前 10%的学生:来自高中班级前 10%的新生的百分比
*   高中班级排名前 25%的新生比例
*   **F .本科生**:全日制本科生人数
*   **P .本科生**:非全日制本科生人数
*   **州外**:州外学费
*   **房间。食宿**:食宿费用
*   **图书**:预计图书成本
*   **个人**:预计个人支出
*   博士:拥有博士学位的教师比例
*   **终端**:拥有终端学位(博士/法学博士/医学博士/工商管理硕士等)的教师比例
*   **学生/教师比率**:学生/教师比率
*   **校友百分比**:捐赠的校友百分比
*   **expense**:每个学生的教学支出
*   毕业生。比率:毕业率

# 探索性数据分析

开始任何分析的一个好方法是使用熊猫。DataFrame.describe()来获得关于数据的一些基本统计信息。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snscolleges = pd.read_csv(‘College_Data’,index_col=0)
colleges.describe()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1d15d82580913121c8325f26f6e382fa.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a89bf9f362eed12c26fcd747433f2437.png)

DataFrame.describe()的输出,关于数据集特征的一些基本统计数据。图片作者。

仅通过查看这些列的最大值,就可以发现一些问题:

1.  众所周知,顶级私立学校每年收费高达 6 万美元,但这里的州外学费最高只有 21,700 美元,所以我们可以假设这笔学费是按学期而不是按年列出的。
2.  有一所学校 100%以上的教师都是博士!这似乎有些可疑,但这或许可以用一小撮成绩优异的教师来解释,他们可能有一个被重复计算的双博士学位。
3.  同样,我们也有一所毕业率为 118%的学校!我们稍后会探讨这种异常现象…

请随意查看平均值、中间值和其他统计数据,看看有什么让你印象深刻!这就是*探索性*数据分析的原因。

让我们来看看哪所大学的申请人数最多。

colleges.loc[colleges[‘Apps’]==np.max(colleges[‘Apps’])]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/752a59fcd7c6aa27f07d3ef83bf5f333.png)

输出。图片作者。

结果是罗格斯大学的申请人数和录取人数最多,但注册人数却不是最多的。高中和大学的另一个值得夸耀的地方是他们的师生比:越低越好。

colleges.loc[colleges[‘S.F.Ratio’]==np.min(colleges[‘S.F.Ratio’])]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d5cb1fd4914340709ddb0751541acd20.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4f7b78a5e663531e87eb249f5f9cfef8.png)

输出。图片作者。

这里的赢家是查尔斯顿大学,其 ***非常低*** 的比率为 2.5,这实际上是一个与家庭学校或私人辅导一样亲密的教学环境。考虑到学生与教师比率的第 25 百分位是 11.5,C 的 U 是一个主要的异常值。

现在来说说钱:哪个大学的校友捐赠率最高?

colleges.loc[colleges[‘perc.alumni’]==np.max(colleges[‘perc.alumni’])]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/76057694c563931e66bc49f1b4bb707f.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2947f07bb6d00eca642979661fdc53c0.png)

输出。图片作者。

威廉姆斯获奖不足为奇,因为这是一所小型文理学院(总共约 2000 名学生),主要面向拥有强大人脉的富裕家庭。之前打电话告诉我们,捐款比例的中位数只有区区 21%,因此作为学生打电话者,校园里有大量的工作机会。

现在有趣的事情来了:让我们通过观察学校在每个学生身上的支出与州外学费的比率,来看看谁真正从大学教育中获得了他们的美元价值。

colleges[‘expense ratio’] = colleges[‘Expend’]/(colleges[‘Outstate’])colleges.describe()[‘expense ratio’]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c7a1f1c236fec4aa34a074357089f7e8.png)

输出。图片作者。

WOAH!平均值小于 1 的事实告诉我,当把学费作为唯一的收入来源时,普通学校在学生身上是赔钱的。事实上, **~69%** 的大学在学生身上的投资超过了他们收取的费用,这对大多数大学的未来来说不是一个好兆头。比例最高的学校大概是一些常春藤盟校吧?

colleges.loc[colleges[‘expense ratio’]==np.max(colleges[‘expense ratio’])]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/95610d6ca0bf01d637eaf978ef702e2f.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/982fab5c0fed673a7eb5a1ed2e6683cf.png)

输出。图片作者。

不对!最佳“物有所值”奖授予…****鼓乐****…伯明翰阿拉巴马大学,费用比率为 **3.68** !然而,一种更愤世嫉俗的观点是,如果 UAB 在每个学生身上的花费是州外学费的近 4 倍,那么它可能不会在商业上持续太久…所以如果你是 2021 年的 HS 班,在他们还在运营的时候就进去,但要握紧你的钱包,因为那些打电话的学生会加班加点地抢你的捐款!

对于任何想知道的人来说,最大的小偷(费用比率最低的大学)是林登伍德学院,比率为 **0.378。哎呀!**

# 形象化

是时候创建一些数据可视化了!

让我们调查一下学费是如何随着学生人数以及学校是公立还是私立而变化的。我怀疑私立学校的学费更高,因为它们不像公立学校那样接受政府资助。全日制学生的数量可能会对这两种情况产生不利影响,因为更多的学生意味着更多的员工和更多的建筑,但一所大学可能会从针对如此大量学生的建筑项目的规模经济中受益。

plt.figure(figsize=(8,6))
sns.scatterplot(data=colleges,x='Outstate',y='F.Undergrad',hue='Private')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ab20d75aa759afdff948c80a013ce2cb.png)

全日制本科生与州外学费的数量,按私立/公立区分。图片作者。

嗯… ***非常*** 有趣的是,这所学校的本科生人数几乎完全与学费无关,这就引出了一个问题:这些钱去了哪里?让我们放大一下州外学费,看看毕业率。

sns.set_style('darkgrid')
g = sns.FacetGrid(colleges,hue='Private',palette='coolwarm',height=6,aspect=1.5)
g = g.map(plt.hist,'Outstate',bins=20,alpha=0.7)
plt.legend(labels=['Private','Public'])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9f968d6ffd422eb9152b76884e383b11.png)

私立和公立学校的州外学费。图片作者。

grid = sns.FacetGrid(colleges,hue='Private',palette='coolwarm',height=6,aspect=1.5)
grid = grid.map(plt.hist,'Grad.Rate',bins=20,alpha=0.7)
plt.legend(labels=['Private','Public'])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/715457ecc45341bd858ae28b407d5a32.png)

私立和公立学校的毕业率。图片作者。

不出所料,**私立学校的州外学费更高,毕业率也更高**——也许是因为如果一个学生在教育上投入那么多钱,他们的父母会想,“你最好完成学业…否则!”

现在回到那个毕业率高于 100%的学校……原来罪魁祸首是**卡泽诺维亚学院。**也许这个学校作弊,把双专业算作两次毕业?现实中这是没有意义的,所以**我准备把这个毕业率改成 100%。**

现在到了你们期待已久的时刻:**K-均值聚类!**

# k-均值聚类创建

首先,我们将从 Scikit-learn 导入 **KMeans** ,Scikit-learn 是 Python 中最流行的机器学习包。K-means 的工作方式如下:

1.  **选择集群的数量**。选择 2、4 还是 10 取决于具体问题的领域。在本例中,我们对公立和私立学校进行分类,因此我们将选择聚类数为 2。如果你正在分析一个群体中的基因变异,并且事先知道有 7 个已知的变异,那么你会选择 7 个。
2.  **将每个数据点随机分配到一个类别。**
3.  **取每个类别中数据点的质心**。对于那些认为质心是某种听起来很酷的小行星的人来说,它是多变量微积分——代表“每个星团中所有数据的平均值”对于 1-D 数据,您已经直观地理解了这一点:食品杂货的平均价格得到一个像 52 美元这样的数字。如果您计算杂货项目的平均价格和平均数量(二维),您将得到两个数字,如$52 和 2 个项目。在该数据集中,我们有 18 个要素,因此每个质心对应一组 18 维坐标。不,我们不会尝试去想象这个。
4.  **将每个数据点重新分配到最近质心对应的类别。**
5.  **重复第 3 步和第 4 步,直到类别不再发生变化。**

这里有一个很好的图片来帮助说明:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/827d36133a58c92e43e6e8c1d3e97632.png)

逐步 K-均值聚类,大点代表每个彩色聚类的质心。资料来源:第 389 页,[《统计学习简介](http://faculty.marshall.usc.edu/gareth-james/ISL/index.html),作者:James,Witten,Hastie 和 Tibshirani。

用 Python 编写 K-means 模型非常简单,如下所示,模型生成的聚类可以用`km.labels_`引用(不要忘了末尾的下划线!).

from sklearn.cluster import KMeans
km = KMeans(n_clusters=2)
km.fit(colleges.drop(‘Private’,axis=1))


# **评估**

如果没有标签,就没有评估聚类的完美方法。然而,在这种情况下,学院数据集告诉我们每个学校是公立还是私立,因此我们可以使用这些标签交叉验证我们的 K-means 模型,以**比较监督和非监督模型的总体性能**。

评估机器学习模型性能的两个快速方法是查看一个 [**混淆矩阵**](https://en.wikipedia.org/wiki/Confusion_matrix) 和一个 [**分类报告**](https://muthu.co/understanding-the-classification-report-in-sklearn/) 。

def convertToCluster(cluster):
if cluster=='Yes':
return 1
else:
return 0
colleges['Cluster'] = colleges['Private'].apply(convertToCluster)from sklearn.metrics import classification_report,confusion_matrixprint(confusion_matrix(colleges['Cluster'],km.labels_))
print(classification_report(colleges['Cluster'],km.labels_))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/73bf1674136640adbdabea341a50eee2.png)

来自 Scikit-learn 的无监督 K-means 模型的混淆矩阵和分类报告。图片作者。

如果你习惯于监督学习算法,你可能会看着这些结果想,“ ***22%的准确率?!*** 这款就是垃圾!无监督模型到底有什么用?”但是请记住**无监督**的定义:该模型旨在从我们给它的混乱的 18 个特征中找出意义,没有标签。这并不是一件容易的事情,所以让我们把功劳归于 K-means 该归功的地方。

# ~奖金部分~比较无监督和有监督学习算法

让我们实际上比较我们刚刚得到的结果和监督学习模型的结果,以评估它们的性能(或者至少,将我们的期望设置为无监督学习的适当低水平😉).让我们来做一个经典的逻辑回归。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegressionunis = colleges
X = unis.drop('Cluster',axis=1)
y = unis['Cluster']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)logmodel = LogisticRegression()
logmodel.fit(X_train,y_train)preds = logmodel.predict(X_test)print("Using K means clustering (unsupervised):\n")
print(confusion_matrix(colleges['Cluster'],km.labels_))
print(classification_report(colleges['Cluster'],km.labels_))print("Using logistic regression (supervised):\n")
print(confusion_matrix(y_test,preds))
print(classification_report(y_test,preds))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/08059d6db8f9b2eb00a281a6ccfab4ae.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/33bd686163fde8d57298d881abc20678.png)

比较无监督和有监督学习模型的性能(在这种情况下是逻辑回归)。作者图片。

伙计们,看看标签的力量。使用一个简单的逻辑回归,一个监督学习模型,准确率从 **22%飙升到 91%** ,这可能可以通过选择另一个模型来提高。

希望你能开始明白 K 的意思是如何从混乱的数据中理出头绪的!使用探索性数据分析随意探索其他领域,看看您会发现什么!

# 有序数据的 k-均值聚类

> 原文:<https://towardsdatascience.com/k-means-clustering-on-ordinal-data-7222b5ee1693?source=collection_archive---------37----------------------->

## 使用映射来揭示数据中类似数字的行为

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/224232a71923498b39177025855e95cb.png)

图片由来自 [Pixabay](https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=259458) 的 [Reimund Bertrams](https://pixabay.com/users/8385-8385/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=259458) 拍摄

K——意思是聚类。这是无监督学习的圣杯。老实说。我明白为什么…当然,决定你应该计算的集群的数量*有一点艺术形式,但是总的来说,坐下来让算法做它的事情是不可思议的。尽管如此,有一个非常重要的警告: **k-means 聚类只对数值数据有效** … *对吗?!**

# 嗯…也许吧

一般来说,试图扩大 k-means 到分类应用是不稳定的。k-means 聚类最重要的部分是寻找它们之间具有最小*距离*的点。我们如何定义分类变量之间的距离?苹果离橘子有多远?那些更接近蓝莓还是西瓜?在无序的上下文中,问这些问题是没有意义的。

## 但是如果我的分类数据是有序的呢?

哇,我很高兴你问了。正如你敏锐地指出的,在某些情况下,似乎应该有一种方法来回答这些问题。

最近,我在看一些来自 KFF 的数据,这些数据是关于美国为应对新冠肺炎病毒而实施的全州范围的社会距离指令。经过一番争论,下面是最初几行的样子:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3d04f00e4f3f792aee98ee69d2b2a863.png)

(注:如果想看我扯皮分析这个数据集的全过程,可以在 [Github](https://github.com/ariel-j-w/social-distancing-effectiveness) 上查看我的 R 代码。)

例如,考虑留在家中订单属性。此属性描述了一个州是否有留在家中的命令,以及该命令会影响哪些人群。显然,没有秩序不同于全州秩序,全州秩序不同于仅适用于高风险人群的秩序。这里是重要的部分:*一个全州范围的命令似乎“更接近”一个只影响高风险人群的命令,而不是根本没有命令*。

似乎我们**应该**能够回答 k-means 聚类所需的问题。我们数据的自然排序有助于进一步分析。当然,它实际上不是数字数据,但它以一种大致数字的方式表现,那么是什么阻碍了我们将它视为数字数据呢?用 Hannah Montana 无处不在的话说,生活是由你创造的,所以让我们对有序数据执行 k-means 聚类成为可能!(没有?那不是她的原话吗?开枪吧。)

要点如下:为了使 k-means 在有序数据集上成为可能,我们将定义一个从有序数据到数值的映射。本质上,我们为每个因素级别分配权重,并使用这些权重来执行我们的分析。

(提醒:如果你的分类数据没有自然排序,这是一个坏主意。我们基本上是在*创造*数量级和数量级的概念,并把它们强加给我们的数据集。如果这对您的数据没有意义,您可能会对 [k-modes 集群](https://www.youtube.com/watch?v=b39_vipRkUo)感兴趣。)

对于我的数据,我有 3 个想要转换的属性。为了确保属性在聚类过程中同等重要,我确保每个属性的可能权重范围从 0 到 10。0 和 10 的精确选择并不像**确保所有属性具有相似数量级的想法那么重要。在定义映射时,这可能是需要记住的最重要的事情。**

> 为所有属性创建相似量级的标度是转换 k-means 分析的有序数据时要考虑的最重要的方面。

最后,我将我的映射定义如下:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9fb161c9f7edcebe11a866643de60078.png)

将有序社会距离变量映射为数值

一旦定义了映射,我就对现在的数字变量进行了完整的 k-means 聚类分析。下面是我转换后的数据的一瞥:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b1f8688f6c9c24f4fdaa5eefa4c7a0e7.png)

转换后的序数数据,以及由 k-means 识别的聚类

这看起来效果很好:我的聚类均值彼此截然不同,三个变量的每个组合的散点图恰当地说明了聚类之间的界限。(查看 [Github](https://github.com/ariel-j-w/social-distancing-effectiveness) 上的代码了解全部细节。)说了这么多,做了这么多,我最终得到了以下的集群标识。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b6b295a867ff67dfa1c398948e4cd1d7.png)

通过有序数据的 k-均值聚类确定的全州社会距离任务的分类

# 这是一种艺术形式,不是科学。

定义从序号到数值的映射是一个非常主观的过程。这在很大程度上取决于数据的细节,我认为除了关于如何选择映射的一般建议之外,不可能给出任何其他的建议。

在某些数据集中,有序数据的简单排序可能是最合适的。在其他情况下,比如我们的案例研究,可能需要一个更灵活的尺度。这种方法没有放之四海而皆准的方法,但我仍然相信它有潜力产生非常有价值的见解。

# K-Means 聚类——一个将它们全部分组的规则

> 原文:<https://towardsdatascience.com/k-means-clustering-one-rule-to-group-them-all-f47e00720ee7?source=collection_archive---------13----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9b684c2c8c3cb64ca06b9e9400583ac7.png)

*图片由* [Ellen Qin](https://unsplash.com/@ellenqin?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) *上* [Unsplash](https://unsplash.com/s/photos/balls?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

**本文将尝试:**

*   用图形解释 K-Means 聚类的基础,这是一种无监督的机器学习算法
*   讨论寻找 **K** 的最佳值和团簇质心位置的方法

**你应该已经知道的:**

基础数学和欧几里德几何

在机器学习中,经常遇到的问题之一是将相似的数据分组在一起。你知道人们的收入水平,现在你想把收入水平相似的人分组在一起。你想知道谁是低收入人群,谁是高收入或非常高收入人群,你认为这有助于设计一个完美的营销策略。您有客户的购物数据,现在您想要将具有相似购物偏好的客户分组在一起,或者您是生物专业的学生,想要根据您手头的细胞数据了解哪些细胞具有相似的属性。

所有上述问题都属于称为聚类的无监督机器学习方法的范畴。虽然有许多聚类算法,但当谈到最简单的一个,奖项将授予 K-Means 聚类。为了理解该算法,让我们假设我们有以下数据:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7a5b804408810132342b2f094ffa4a34.png)

我们有十个数据点,给出了它们的 **x** 和 **y** 坐标。这里我们有表示为 **x** 和 **y** 的变量,但在实际情况中,它们可以是不同的,比如在市场细分情况下的**月收入**或**日支出**。让我们从两个集群开始,首先将上述数据可视化,以便对其有所了解:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a46dc6974f92e0847b842584d190472e.png)

上图显示了我们手头的数据(图 1)和我们可以从中得出的两个可能的聚类(图 2)。请注意,在任何数据中查找集群数量(本例中为 2)的决定完全是任意的&基于随机猜测。稍后,您将发现这种随机猜测最初是如何引导我们找到数据中可能的最佳聚类数的。现在的问题是如何计算和分析找出这两个集群。

**方法背后的逻辑**

1.  首先,假设数据附近的任意两个随机点&将它们视为两个集群的中心(质心)
2.  找出每个数据点到两个中心的距离
3.  将每个数据点分配到离其最近的质心,从而形成两个聚类
4.  计算形成的两个簇的中心,并在那里移动质心。
5.  转到步骤 1,重复该过程,直到形成的簇没有变化。

让我们将上述逻辑应用于给定的数据。我们知道在笛卡尔坐标系中,两点(x1,y1)和(x2,y2)之间的距离由下式给出:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b0a0ef28bf1c48e03b8b22a7a18f4725.png)

使用上面的公式,我们可以计算每个点与假设中心之间的距离。让我们假设我们的质心在 C1 = (4,1)和 C2 = (6,1),从图形上来说,如下图所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0fd3778d78911b7e237e8c23071ab903.png)

如果我们计算每个点到两个质心的距离,结果如下表所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d8c828a37334dde62ba13fa8436716b9.png)

基于上述距离值,每个点将被分配到其距离最小或最近的质心,例如考虑第一个数据点,其距离 **C1** 为 3.6,距离 **C2** 为 5.4。由于它更靠近 C1,它将被分配到这个特定的质心。对每个点做同样的操作,分配如下所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2852567649e9780fc0349eacce1621c1.png)

从上表可以看出,每个点都根据其与假定质心的距离被分配给一个质心。分配后,通过计算分配给每个簇的点的中心来计算质心的新位置,如表中所示,计算每个坐标的平均距离。因此,质心的新位置将是 C1 = (2.6,3.8)和 C2 = (7.6,3.4),如下图所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/36143df25a40da7f9bf504bee9d57db3.png)

上图显示了单个计算循环是如何使两个质心更接近数据的。如果您运行另一个计算循环,您可以看到质心不再移动,并且没有数据点将其质心从 C1 改变到 C2,反之亦然。这是计算循环或递归停止的地方。

将数据分配给质心以使其成为聚类的上述过程被称为 K 均值聚类,并且 **K** 的值是所形成的聚类的数量,例如在当前情况下 **K** 的值将是 2。

最后两个集群如下所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/390356873d5a6aa7f906a0a71d5e1b84.png)

**如何决定 K 的值?**

我们从 K=2 的随机坐标开始,也就是说,我们给质心的数量和位置都分配了随机值。虽然我们最终找到了计算质心最终位置的方法,但仍然存在的问题是以最佳方式拟合给定数据的 **K** 的值是多少。我们也试图找到这个问题的答案,但首先让我们了解什么是成本函数。

**成本函数**

它是一个函数,给出了相对于每一个 **K** 值的模型缺陷的度量。理想情况下,聚类中的每个点应该尽可能靠近其质心,或者特定聚类中的每个点与其质心之间的距离应该为零。我们将计算这个距离&,将距离的平方和视为缺陷的成本或度量。我们将对每个集群重复同样的操作&将找到使该成本最小化的 **K** 的值。

参考表-1 和表-2,我们将每个点分类到一个簇中,并将这些点与它们各自质心的距离总结如下:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e2429a5b61f7211ba576c110d0a3ada3.png)

每个距离的平方相加,两个聚类的总和为 15.72 + 10.76 = 26.84。这个数字是我们设 K = 2 时模型的成本。同样,可以针对不同的 **K** 值计算成本,当成本值相对于 **K** 值绘制时,我们将得到如下所示的图表:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/edbce58956742a347ae4344bac8b55cc.png)

根据上图, **K** 的最佳值将是显示最大偏差(用红色标记)或成本曲线形成弯头的值。虽然较高的 K 值进一步降低了成本,但会导致过拟合。这种找出最佳值 **K** 的方法称为肘法。

到目前为止,我们所做的任何事情的 Python 代码如下所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f615ceed29f307d0839e3d1442ead6ee.png)

这都是关于 K-均值聚类&如何找出 K 的最佳值和质心的位置。希望你喜欢。请发表您的评论

**延伸阅读:**

*   [主成分分析](https://en.wikipedia.org/wiki/Principal_component_analysis)
*   DBSCAN

谢谢,

过得愉快😊

如果你对这篇文章有任何疑问,你可以通过 LinkedIn 联系我

*原载于 2020 年 4 月 10 日 https://wildregressor.com*[](https://www.wildregressor.com/2020/04/k-means-clustering-one-rule-to-group.html)**。**

# 使用 Spotify 歌曲特征的 K-means 聚类

> 原文:<https://towardsdatascience.com/k-means-clustering-using-spotify-song-features-9eb7d53d105c?source=collection_archive---------16----------------------->

## *使用高维数据聚类自动创建播放列表*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fc54920ec3f9a23e781caefd8dd310ef.png)

由[马尔特·温根](https://unsplash.com/@maltewingen?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/music?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片

spotify API 允许我们创建一个简单的服务器端应用程序,从 spotify 应用程序中访问用户相关数据。它还可以让你获得应用程序上没有的信息,如艺术家受欢迎程度、歌曲指标、专辑封面图片等。它允许你创建、删除和修改用户帐户中的现有播放列表。

> 这个项目的目标是使用聚类算法将一个大的播放列表分解成更小的播放列表。为此,使用了歌曲度量标准,如“可跳性”、“效价”、“速度”、“活跃度”、“语速”。

## 在这篇文章中,你会发现:

*   使用 Spotify API 收集数据
*   寻找理想的集群数量
*   肘方法和轮廓分析
*   特征选择
*   聚类算法
*   播放列表创建和性能分析

如果您还不是会员,请在此获得您的中级会员资格[!](https://medium.com/@alejandra.vlerick/membership)

# 数据收集

import spotipy
from spotipy.oauth2 import SpotifyOAuth
from spotipy.oauth2 import SpotifyClientCredentials


连接 spotify API 非常简单,内容也有很好的文档记录。这个[链接](https://spotipy.readthedocs.io/en/latest/)将为您提供连接所需的所有信息,而[这个](https://developer.spotify.com/documentation/web-api/)将为您提供 python 示例代码。

前往[https://developer.spotify.com/dashboard/](https://developer.spotify.com/dashboard/),点击**创建客户端 ID** 或**创建 App** ,获取您的“*客户端 ID* ”和“*客户端密码*”。之后,重定向 URI 必须被更改到你在 Spotify 应用程序的设置中决定的任何页面。

scope = "user-library-read playlist-modify-private"
OAuth = SpotifyOAuth(
scope=scope,
redirect_uri='http://localhost:8888/callback',
client_id = 'client_id',
client_secret = 'client_secret',
username= 'username')


变量“sp”将作为 spotify 数据的访问键,并允许我们使用所有功能来获取和发布 Spotify 的请求。

sp = spotipy.Spotify(auth_manager=OAuth)


# 保存的曲目数据收集

下一步是从我的“ ***喜欢的歌曲*** ”播放列表中收集数据。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b6446656633e6e2378a7d7416f6ec033.png)

API 一次只能提取 50 首歌曲,因此我们运行一个 while 循环,以 50 首为一组遍历整个播放列表。用来访问我个人喜欢的歌曲的函数是***current _ user _ saved _ tracks()。***

offset = 0songs = []
items = []
ids = []
while True:
content = sp.current_user_saved_tracks(limit=50, offset=offset)
songs += content['items']
if content['next'] is not None:
offset += 100 else:
break


下面的步骤是使用 ***audio_features()*** 函数提取每首歌曲的音频特征:

for i in songs:
ids.append(i['track']['id'])while index < len(ids):
audio_features += sp.audio_features(ids[index:index + 50])
index += 50features_list = []
for features in audio_features:
features_list.append([features['energy'], features['liveness'], features['tempo'],features['speechiness'],
...
features['mode'], features['type'], features['uri']])

df = pd.DataFrame(features_list, columns=['energy', 'liveness', 'tempo', 'speechiness', ...'mode', 'type','uri'])


结果是一个 pandas 数据帧,它收集了行上的歌曲和列上它们各自的特征。每首歌曲都由它唯一的 ***uri*** 来标识。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b93c2b1b9c17dacd76faa272a9524a1a.png)

数据框的右侧

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/88320d4f6651ee16e3834e48e7105814.png)

数据框的左侧

只是为了好玩,我决定查看播放列表中所有歌曲的特征值分布情况:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4980d8b05ba7601ad654e5c3edd7dd0d.png)

歌曲特征(标准化后):

我很快得出结论,这些指标之间没有很强的相关性。歌曲并没有根据它们的类型遵循固定的模式。当尝试基于所有 12 个特征执行聚类时,结果并不理想…为此,我决定使用较少数量的指标,并测试所有可能产生最佳聚类的特征组合。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1a0e24104c0efc7c3ee7ad092be38468.png)

不同指标之间没有真正的相关性…

# 寻找理想的集群数量

在对所有 12 个特征尝试聚类算法之前,我决定精选几个特征进行聚类,希望它能产生更好的聚类质量。

第一步是归一化所有的值,使它们位于[0;1].

from sklearn import preprocessingx = df.values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df = pd.DataFrame(x_scaled)


接下来的步骤是基于一些特征的选择找到一个聚类质量度量。我做的第一件事是创建一个包含所有歌曲指标的列表,然后使用 **permutations()** 函数创建一组当时使用三个歌曲特征的所有可能组合。

columns = ["energy", "speechiness", "acousticness", "instrumentalness", "loudness","tempo","danceability",'valence' , "liveness", "time_signature", "key"]

perm = permutations(columns, 3)
output = set(map(lambda x: tuple(sorted(x)),perm))


对于每个排列,我使用**肘方法计算了一个聚类分数。**

> **肘法** *是一种启发式方法,用于确定数据集中的聚类数。* ***方法*** *包括绘制所解释的变异作为聚类数的函数,并拾取曲线的* ***【肘形】*** *作为聚类数来使用。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a94fec27d55b566d587ae384052854e5.png)

x 轴为肘值,y 轴为分数。每条线对应不同的排列。

对于每个排列,我提取了一个肘分数和一个肘值。**分数**告诉我该排列的聚类有多好,**肘值**告诉我该排列的理想聚类数。

model = KMeans(random_state=0)
visualizer = KElbowVisualizer(model, k=(2,12), metric='silhouette', timings=False)
visualizer.fit(x_scaled)
score = visualizer.elbow_score_
value = visualizer.elbow_value_


结果是一个熊猫数据帧的特征排列和他们相应的理想数量的集群和质量评分这些集群。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3454966143e837fd7f0788e774be67f4.png)

一旦计算出每个排列的分数,我决定选择大于 0.4 的排列,并将它们保存在一个单独的数据框中。

if score>0.4:
idx = df.columns
mylist = idx.tolist()
dict = {
"features": mylist, "score": score, "elbow": value
}
df2 = df2.append(dict, ignore_index=True)


# 集群和播放列表创建

有许多排列产生了很好的结果,得分甚至超过 0.5。

排列**[‘工具性’,‘语音性’,‘化合价’]**建议创建 4 个集群,得分为 0.504。这是我在创建播放列表时选择的一个。

我缩放了一个只包含这三个指标的数据帧,然后使用 **KMeans()** 函数执行了聚类。

from sklearn.cluster import KMeanskmeans = KMeans(init="k-means++", n_clusters=4, random_state=15, max_iter = 500).fit(x_scaled)
df1['kmeans'] = kmeans.labels_
df1.columns = ['energy', 'instrumentalness', 'loudness','kmeans' ]


结果是数据帧包含每行一首歌曲,标签[0,1,2,3]对应于特定歌曲被分配到的每个簇。**特征分布清楚地表明,能量和响度在所有集群中分布不同。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9952a38955bbea196f2ca09fb447074c.png)

3D 散点图给出了不同的视角,显示了较高的乐器度值被分类到相同的群中,而能量和响度区分了其余三个群。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d1a25573fadd33016a51984a34db2188.png)

聚类的三维散点图

# 非常感谢你的阅读!

更多类似的文章,请点击在 Medium [上找到我!](https://towardsdatascience.com/medium.com/@alejandra.vlerick)

如果您有任何关于如何改进的**问题**、**建议**或**想法**,请在下面留下评论或通过 LinkedIn [这里](https://www.linkedin.com/in/alejandra-g-283595b8)取得联系。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b9e69c51ca7e3ad1b00168b67c9c0a51.png)

照片由[威廉·冈克尔](https://unsplash.com/@wilhelmgunkel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/thank-you?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄

# Github 知识库

所有的代码都可以在 Github [这里](https://github.com/alejandra-gutierrez/SpotifyAPI)找到。排列脚本可以在 *analysis_v2.py* 中找到,聚类可以在 *feature_analysis.py* 中找到。

# k 表示使用 Python 进行集群

> 原文:<https://towardsdatascience.com/k-means-clustering-with-python-66288925e5f6?source=collection_archive---------30----------------------->

## 在本文中,我们将了解 K 均值聚类的基础知识,并使用著名的机器学习库 Scikit-learn 在 Python 中实现它

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a980ba702b8abb0012f0685c5207f829.png)

尼克尼斯在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

# 什么是 K 均值聚类?

**K 均值聚类**是一种**无监督机器学习算法**。它接收**混合数据**并且**基于**数据**中的**模式**将**数据分成小的**组/簇**。

# K 均值算法的目标

[**奥德里布**](https://www.education-ecosystem.com/andreybu/REaxr-machine-learning-model-python-sklearn-kera/oPGdP-machine-learning-model-python-sklearn-kera/) 曾经说过:

> K-means 的目标很简单:将相似的数据点组合在一起,发现潜在的模式。为了实现这个目标,K-means 在数据集中寻找固定数量的聚类( *k* )。

# K 均值聚类的工作原理

为了解释 **K 均值算法**的工作原理,让我们假设我们有一些使用**散点图**绘制出来的数据。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fef97787622f949c59f4724da94e2dd3.png)

数据绘制在散点图上,照片由作者提供

现在在**稍微分析**数据之后,我们可以看到我们的数据可以分成两个独立的**组/簇**。现在, **K 表示**将要做的是,它还会**将**数据**划分为**两个簇**,并为每个**簇标记一些**边界**。**因此,每当一些新的**数据**被馈送到**模型**时,它将检查这个**数据点**落入了什么**边界**,并在最后告诉我们**集群的名称**或**编号。****

# k 均值聚类算法讲解

首先我们会选择**簇数(k)** (本例中 **k=2** )。这意味着现在我们将随机假设 **2 个点**,它们将作为我们的**簇质心**。(**簇形心**是**簇**的**中心点**)。

**K 均值聚类**有两个主要步骤:

*   **聚类分配步骤**:在该步骤中,靠近质心的数据点将分别落在那些质心聚类中。
*   **移动质心步骤**:在这一步中,我们将计算一个聚类中所有数据点的平均值,并将该聚类的质心移动到该平均值位置。

一旦后的**条件之一**为真:**,我们将**重复上述**两步******

1.  我们的质心停止改变位置。
2.  达到最大迭代次数。

我们的**数据**现在被安排到**簇中。**

# 选择 K 的值

为了选择最适合我们数据的**簇数**,我们可以使用著名的**肘法**。这种**肘方法**背后的基本思想是,它用**变化的集群数量(k)** 来绘制**成本(误差)**的各种值。随着**组数(k)** **增加**,每个组的**数据点数** **减少**。因此**平均失真减少**。**小于**一个**簇**中的**个数的数据点**,这些**数据点**离它们的**质心**越近**。所以 **k** 处**畸变下降**最大的值称为**拐点。****

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b55a918bc03dc7f8bcee30c863db540d.png)

选择合适的 **k** 值,作者照片

有时我们图的**斜率**是**相当平滑**所以**很难**选择 **k** 的值,因为没有明确的**拐点。**在这种情况下,我们利用我们的**行业经验**和**连续实验**来确定 k 的**值。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ba4d486b15b97d2ed87b9043392ced27.png)

没有清晰的**肘点**,作者照片

# 用 Python 实现

现在我们已经很好地理解了 **K 意味着聚类算法**是如何工作的。所以现在我们将在一个数据集**上实现 **K Means** 以获得关于它的更清晰的**直觉**。为此,我们将使用 **Python 的**著名的**机器学习库**、 **Scikit-learn。****

# 什么是 Scikit-learn?

**Scikit-learn** (又名 **sklearn** )是一个针对 Python 的机器学习库。它包括各种**分类**、**回归、**和**聚类算法**以及**支持向量机(SVM)** 、**随机森林**、**梯度提升**、**、 *k* -means** 和 **DBSCAN** ,并且被设计为与像 **NumPy** 、**这样的 Python 库一起工作**

# k 表示使用 Scikit-learn 进行聚类

**K 表示聚类**是一种非常直接且易于使用的**算法**。特别是在这个 **Scikit learn** 库的帮助下,它的实现和使用变得相当容易。现在,我们开始使用 **Sklearn** 。

***在 Python 中导入重要库***

import seaborn as sns
import matplotlib.pyplot as plt


***创建人工数据***

from sklearn.datasets import make_blobs
data = make_blobs(n_samples=200, n_features=2,centers=4, cluster_std=1.8,random_state=101)


***可视化我们的数据***

plt.scatter(data[0][:,0],data[0][:,1],c=data[1],cmap='rainbow')


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/fef97787622f949c59f4724da94e2dd3.png)

可视化我们的数据,作者照片

***创建集群***

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=4)
kmeans.fit(data[0])


现在,在从`sklearn.cluster`导入了`KMeans` 之后,我们创建了一个`KMeans`类的对象`kmeans`。在这里,你可能会发现**奇怪**的一点是我们指定了`n_clusters=4`。这是因为在创建**数据**时,我们指定了`centers=4`,所以我们知道该数据应该有 **4 个簇**。所以我们手动指定了它。但是如果我们不知道这些中心,那么我们将不得不使用**肘方法**来确定正确的星团数量。

好了,现在继续向前,我们的代码**的这`kmeans.fit(data[0])`段分析数据**,**使集群、**甚至**将每个**集群**的质心**匹配到它们的**适当位置**。

现在为了检查我们的**质心**的**位置**,我们可以使用下面的代码。

print(kmeans.cluster_centers_)


它会打印出一个 **(4,2)** **数组**,分别显示每个**簇**的**质心**的位置。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/295dc2e8dc1ad2300c56a6dd8cb8979d.png)

每个聚类的质心值,照片由作者提供

***应用 K 后对比原始数据集 VS 表示***

f, (ax1, ax2) = plt.subplots(1, 2, sharey=True,figsize=(10,6))
ax1.set_title('K Means')
ax1.scatter(data[0][:,0],data[0][:,1],c=kmeans.labels_,cmap='rainbow')
ax2.set_title("Original")
ax2.scatter(data[0][:,0],data[0][:,1])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c73cbfcf9b412681bca97d93ae201f9d.png)

*对比* ***原始数据集*** *VS 应用* ***K 表示*** *,作者照片*

**恭喜恭喜!**我们已经在我们的**数据集**上成功实现了 **K 均值聚类**。

# **学习成果**

到目前为止,我们已经了解了什么是 **K 均值聚类算法**,它的**工作**,以及**如何选择 K 的值**。另外,我们已经使用 **Python 的**著名的**机器学习库**,即 **Scikit-learn,在**数据集**上实现了 **K Means** 。**

# k 表示用 python 代码解释的集群

> 原文:<https://towardsdatascience.com/k-means-clustering-with-python-code-explained-5a792bd19548?source=collection_archive---------3----------------------->

## *一种解决聚类问题的简化无监督学习算法*

k 均值聚类是机器学习中的另一种简化算法。它被归类为无监督学习,因为这里我们还不知道结果(不知道将形成哪个聚类)。该算法用于数据的*矢量量化*,取自信号处理方法。这里数据被分成几组,每组中的数据点都有相似的特征。这些聚类通过计算数据点之间的距离来决定。这个距离是众多无人认领的数据点之间关系的度量。

k 表示不应与 [**KNN 算法**](https://medium.com/@yogeshchauhan09/simplified-knn-algorithm-using-python-with-coding-explanation-ab597391b4c3) 混淆,因为二者使用相同的距离测量技术。这两种流行的机器学习算法有一个基本的区别。K means 处理数据,并将其分成不同的聚类/组,而 KNN 处理新的数据点,并通过计算最近邻方法将它们放入组中。数据点将移动到具有最大数量邻居的簇。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/beffc0da6b9920c16bd850cb942ac8f4.png)

随机点数据集

**K 表示聚类算法步骤**

1.  在数据中选择随机数量的质心。即 k=3。
2.  在 2D 画布上选择与质心数量相同的随机点。
3.  计算每个数据点到质心的距离。
4.  将数据点分配到距质心距离最小的聚类中。
5.  重新计算新的质心。
6.  重新计算每个数据点到新质心的距离。
7.  重复从第 3 点开始的步骤,直到没有数据点改变其聚类。

k 表示将数据分成不同的簇,簇的数量等于 k 的值,即如果 k=3,则数据将被分成 3 个簇。k 的每个值都是质心,数据点将围绕质心聚集。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/75229a0ffc3113ee17406484078a8d0c.png)

取自 rosalind.info 的欧氏距离图像

距离计算可以通过四种方法中的任何一种来完成,即欧几里得、曼哈顿、相关和艾森。这里,我们使用欧几里德方法进行距离测量,即两点(x1,y1)和(x2,y2)之间的距离为

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0cc213f25071271f723d0fb901267889.png)

以下是在机器学习中使用 k 均值聚类算法的一些优点和缺点

**优点:**

1.  一种相对简单的算法
2.  灵活,能够很好地处理大量数据
3.  保证了收敛

**缺点:**

1.  我们必须手动定义质心的数量
2.  无法避免离群值
3.  取决于所选质心的初始值

现在,我们将尝试用 python 语言创建一个算法。在这里,我们将调用一些基本的和重要的库来工作。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans


sklearn 是机器学习中最重要的包之一,它提供了最大数量的函数和算法。要使用 k 意味着聚类我们需要从 sklearn 包中调用它。

为了获得一个样本数据集,我们可以使用 numpy 生成一个随机序列

x1=10*np.random.rand(100,2)


通过上面的代码行,我们得到了一个包含 100 个点的随机代码,它们组成了一个形状为(100,2)的数组,我们可以使用这个命令来检查它

x1.shape


现在,我们将通过处理所有数据来训练我们的算法。这里,簇的数量将是 3。这个数字是我们任意给定的。我们可以选择任何数字来定义集群的数量

kmean=KMeans(n_clusters=3)
kmean.fit(x1)


使用下面的命令,我们可以看到我们的三个中心

kmean.cluster_centers_


要检查创建的标签,我们可以使用下面的命令。它给出了为我们的数据创建的标签

kmean.labels_


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b391a9adbb4238d72ef615fcca4bf0ea.png)

通过 k 均值聚类输出 3 个聚类

我们可以看到,由于手动选择质心的数量,我们的集群没有很大的分离。一个集群有一组相似的信息,我们的目标是使集群尽可能的独特。它有助于从给定的数据集中提取更多的信息。因此,我们可以绘制一条肘形曲线,它可以清楚地描述质心数量和信息增益之间的平衡。

wcss = []
for i in range(1,20):
kmeans = KMeans(n_clusters=i,init=’k-means++’,max_iter=300,n_init=10,random_state=0)
kmeans.fit(x1)
wcss.append(kmeans.inertia_)
print(“Cluster”, i, “Inertia”, kmeans.inertia_)
plt.plot(range(1,20),wcss)
plt.title(‘The Elbow Curve’)
plt.xlabel(‘Number of clusters’)
plt.ylabel(‘WCSS’) ##WCSS stands for total within-cluster sum of square
plt.show()


你可以看到有 **K-means++作为方法比传统的 K-means。前一种方法克服了人工选择时容易出现的质心选择错误的缺点。有时选择的质心离点太远,以至于在它们的簇中没有任何数据点。**

输出图可以帮助我们确定为更好的聚类选择的质心的数量。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7822eb1f7df8af9f223bf3e2eb61cb6c.png)

确定质心实际数量的曲线

该曲线清楚地表明,如果我们选择质心的数量为 7、8、9 或 10,那么我们有更好的机会进行精细聚类。数据非常分散,我们甚至可以选择 14 作为质心的数量。这条曲线有助于在计算开销和从数据集获取知识之间做出决定。现在,让我们选择质心为 10,这样我们有 10 个独立的集群。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4d7d8d46f7d69d3d2b479f56c5ba88d1.png)

10 个由 K 均值聚类创建的聚类

**结论:**

我们已经成功地从随机数据集中创建了三个集群。所有数据分类以不同的颜色显示。我们可以使用相同的代码对其他数据进行聚类,甚至可以改变算法中聚类的数量。然后通过使用肘方法,我们预测更多的质心可以改善聚类。因此,在选择更多的聚类之后,我们得到了具有改进的信息增益的更好的聚类。

# K-means、DBSCAN、GMM、凝聚聚类——掌握细分问题中的流行模型

> 原文:<https://towardsdatascience.com/k-means-dbscan-gmm-agglomerative-clustering-mastering-the-popular-models-in-a-segmentation-c891a3818e29?source=collection_archive---------2----------------------->

## 为无监督聚类实现 python 中最广泛使用的模型的一站式商店

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/c456a41f0e2e62ea11f2701da4b18deb.png)

梅尔·普尔在 [Unsplash](https://unsplash.com/?utm_source=medium&utm_medium=referral) 上的照片

在当今时代,大量客户/产品的粒度数据的可用性以及高效处理数 Pb 数据的技术能力正在快速增长。正因为如此,现在有可能提出非常有战略意义和有意义的集群来进行有效的定位。并且识别目标分段需要稳健的分段练习。在这篇博客中,我们将讨论最流行的无监督聚类算法,以及如何用 python 实现它们。

在这篇博客中,我们将使用一家为孕妇提供服装的在线商店的点击流[数据](https://archive.ics.uci.edu/ml/datasets/clickstream+data+for+online+shopping)。它包括产品类别、照片在网页上的位置、IP 地址的来源国以及产品的美元价格等变量。它有 2008 年 4 月到 2008 年 8 月的数据。

*第一步是为分割准备数据。我建议您在继续下一步之前,查看下面的文章,以深入了解为分段准备数据的不同步骤:*

[*One Hot 编码、标准化、PCA:python 中分割的数据准备*](/one-hot-encoding-standardization-pca-data-preparation-steps-for-segmentation-in-python-24d07671cf0b)

*选择最佳聚类数是处理分割问题时需要注意的另一个关键概念。如果您阅读下面的文章,将有助于您理解选择集群的流行指标的完整列表:*

[*Python 中选择最佳聚类数的 7 种方法实现清单*](/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad)

我们将在本博客中讨论 4 类模型:

1.  k 均值
2.  凝聚聚类
3.  基于密度的空间聚类
4.  高斯混合模型(GMM)

**K-表示**

K 均值算法是一个迭代过程,有三个关键阶段:

1.  **选择初始聚类质心**

该算法从选取初始的 k 个聚类中心开始,这些聚类中心被称为质心。确定最佳聚类数(即 k)以及正确选择初始聚类对于模型的性能极其重要。聚类的数量应该总是取决于数据集的性质,而初始聚类的不良选择会导致局部收敛的问题。幸运的是,我们对这两者都有解决方案。

有关选择最佳集群数量的更多详细信息,请参考这篇详细的[博客](/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad)。对于初始聚类的选择,我们可以运行具有各种初始化的模型的多次迭代来挑选最稳定的一个,或者使用具有以下步骤的“k-means++”算法:

1.  *从数据集中随机选择第一个质心*
2.  *计算数据集中所有点与所选质心的距离*
3.  *选择一个点作为新的质心,该点具有与该距离成比例的最大概率*
4.  *重复步骤 2 和 3,直到 k 个质心被采样*

该算法将质心初始化为彼此远离,从而产生比随机初始化更稳定的结果。

2.**集群分配**

K-means 然后根据点和所有质心之间的欧几里德距离将数据点分配给最近的聚类质心。

**3。移动质心**

该模型最后计算聚类中所有点的平均值,并将质心移动到该平均位置。

重复步骤 2 和 3,直到聚类中没有变化或者可能满足一些其他停止条件(例如最大迭代次数)。

为了在 python 中实现模型,我们需要首先指定集群的数量。我们使用了肘方法、间隙统计、轮廓评分、Calinski Harabasz 评分和 Davies Bouldin 评分。对于这些方法中的每一种,最佳聚类数如下:

1.  肘法:8
2.  差距统计:29
3.  剪影评分:4
4.  卡林斯基·哈拉巴斯得分:2
5.  戴维斯·波尔丁得分:4

如上所述,5 种方法中有 2 种建议我们应该使用 4 个集群。如果每个模型建议不同数量的聚类,我们可以取平均值或中值。找到最佳 k 数的代码可以在[这里](https://github.com/IDB-FOR-DATASCIENCE/Segmentation-Modelling.git)找到,关于每种方法的更多细节可以在[博客](/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad)中找到。

一旦我们有了最佳数量的聚类,我们就可以拟合模型,并使用 Silhouette 评分、Calinski Harabasz 评分和 Davies Bouldin 评分来获得模型的性能。

K meansfrom sklearn.cluster import KMeans

from sklearn.metrics import silhouette_score
from sklearn.metrics import calinski_harabasz_score
from sklearn.metrics import davies_bouldin_score# Fit K-Means
kmeans_1 = KMeans(n_clusters=4,random_state= 10)# Use fit_predict to cluster the dataset
predictions = kmeans_1.fit_predict(cluster_df)# Calculate cluster validation metricsscore_kemans_s = silhouette_score(cluster_df, kmeans_1.labels_, metric='euclidean')score_kemans_c = calinski_harabasz_score(cluster_df, kmeans_1.labels_)score_kemans_d = davies_bouldin_score(cluster_df, predictions)print('Silhouette Score: %.4f' % score_kemans_s)
print('Calinski Harabasz Score: %.4f' % score_kemans_c)
print('Davies Bouldin Score: %.4f' % score_kemans_d)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/380ad09760f682920344c050581e885c.png)

图 1:K-Means 的聚类验证指标(作者图片)

我们还可以使用簇间距离图来检查簇的相对大小和分布。

Inter cluster distance map

from yellowbrick.cluster import InterclusterDistance# Instantiate the clustering model and visualizervisualizer = InterclusterDistance(kmeans_1)visualizer.fit(cluster_df) # Fit the data to the visualizer
visualizer.show() # Finalize and render the figure


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3da017b6a38e644298f5c4a1728ffca9.png)

图 2:聚类间距离图:K 均值(图片由作者提供)

如上图所示,两个集群相对于其他集群来说相当大,并且它们之间似乎有适当的间隔。然而,如果两个聚类在 2D 空间重叠,这并不意味着它们在原始特征空间重叠。关于这款车型的更多细节可以在[这里](https://projecteuclid.org/euclid.bsmsp/1200512992)找到。最后,K-means 的其他变体,如小批量 K-Means,K-Medoids 将在单独的博客中讨论。

# 凝聚聚类

凝聚聚类是一类通用的聚类算法,它通过连续合并数据点来构建嵌套聚类。这种聚类层次结构可以表示为一个树形图,称为树状图。树的顶部是包含所有数据点的单个聚类,而底部包含各个点。以连续方式链接数据点有多种选择:

*   **单连锁:**它**最小化成对聚类的最近观测值之间的距离**
*   **完全或最大关联:**试图最小化成对聚类的观测值之间的最大距离
*   **平均关联:**最小化所有聚类对之间的平均距离
*   **Ward:** 类似于 k-means,因为它最小化了所有聚类内的平方差之和,但采用了分层方法。我们将在练习中使用该选项。

通过基于聚类验证指标(Silhouette 评分、Calinski Harabasz 评分和 Davies Bouldin 评分)检查哪种连锁方法表现最佳,可以挑选出理想的选项。与 K-means 相似,我们必须指定该模型中的聚类数,树状图可以帮助我们做到这一点。

Dendrogram for Hierarchical Clustering

import scipy.cluster.hierarchy as shc
from matplotlib import pyplot
pyplot.figure(figsize=(10, 7))
pyplot.title("Dendrograms")
dend = shc.dendrogram(shc.linkage(cluster_df, method='ward'))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6ac332642e9ffb917bf9cf5b2cef075e.png)

图 3:树状图(图片由作者提供)

从图 3 中,我们可以看到我们可以选择 4 或 8 个集群。我们还使用肘方法、剪影得分和 Calinski Harabasz 得分来寻找最佳聚类数,并得到以下结果:

1.  肘法:10
2.  戴维斯·波尔丁得分:8
3.  剪影评分:3
4.  卡林斯基·哈拉巴斯得分:2

我们将按照戴维斯·波尔丁评分和树状图的建议进行 8 分。如果指标给出了不同的集群数量,我们可以继续使用树状图建议的数量(因为它是基于这个特定的模型),或者取所有指标的平均值/中值。寻找最佳集群数量的代码可以在这里[找到](https://github.com/IDB-FOR-DATASCIENCE/Segmentation-Modelling.git),关于每种方法的更多细节可以在这个[博客](/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad)中找到。

与 K-means 类似,我们可以用最佳的集群数量和链接类型来拟合模型,并使用 K-means 中使用的三个指标来测试其性能。

Agglomerative clustering

from numpy import unique
from numpy import where
from sklearn.cluster import AgglomerativeClustering
from matplotlib import pyplot# define the model
model = AgglomerativeClustering(n_clusters=4)

fit model and predict clusters

yhat = model.fit(cluster_df)
yhat_2 = model.fit_predict(cluster_df)

retrieve unique clusters

clusters = unique(yhat)# Calculate cluster validation metricsscore_AGclustering_s = silhouette_score(cluster_df, yhat.labels_, metric='euclidean')score_AGclustering_c = calinski_harabasz_score(cluster_df, yhat.labels_)score_AGclustering_d = davies_bouldin_score(cluster_df, yhat_2)print('Silhouette Score: %.4f' % score_AGclustering_s)
print('Calinski Harabasz Score: %.4f' % score_AGclustering_c)
print('Davies Bouldin Score: %.4f' % score_AGclustering_d)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2dd0ccd6ebfff21efd6d3efc6e0bea05.png)

图 4:聚类验证指标:聚集聚类(作者图片)

比较图 1 和图 4,我们可以看到,基于所有的聚类验证指标,K-means 优于凝聚聚类。

# 基于密度的空间聚类

DBSCAN 将紧密聚集在一起的点组合在一起,同时将其他点标记为孤立在低密度区域中的异常值。定义“密度”需要模型中的两个关键参数:形成密集区域所需的最小点数`min_samples`和定义邻域的距离`eps`。更高的`min_samples`或更低的`eps`需要更大的密度来形成集群。

基于这些参数,DBSCAN 从任意点 x 开始,根据`eps`识别 x 邻域内的点,并将 x 分类为以下类型之一:

1.  **核心点**:如果邻域内的点数至少等于`min_samples`参数,则称之为核心点,并在 x 周围形成一个聚类。
2.  **边界点**:如果 x 是具有不同核心点的聚类的一部分,但其邻域内的点数小于`min_samples`参数,则 x 被视为边界点。直观上,这些点位于星团的边缘。

3.**异常值或噪声**:如果 x 不是核心点,且与任何核心样本的距离至少等于或大于`eps`,则认为是异常值或噪声。

为了调整模型的参数,我们首先通过找到一个点的相邻点之间的距离并绘制最小距离来确定最佳的`eps`值。这给了我们找到数据点密度的肘形曲线,并且可以在拐点找到最佳的`eps`值。我们使用`NearestNeighbours`函数来获得最小距离,使用`KneeLocator`函数来识别拐点。

parameter tuning for eps

from sklearn.neighbors import NearestNeighbors
nearest_neighbors = NearestNeighbors(n_neighbors=11)
neighbors = nearest_neighbors.fit(cluster_df)
distances, indices = neighbors.kneighbors(cluster_df)
distances = np.sort(distances[:,10], axis=0)from kneed import KneeLocator
i = np.arange(len(distances))
knee = KneeLocator(i, distances, S=1, curve='convex', direction='increasing', interp_method='polynomial')
fig = plt.figure(figsize=(5, 5))
knee.plot_knee()
plt.xlabel("Points")
plt.ylabel("Distance")print(distances[knee.knee])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/87c3683219a13e096d77ec36a2425065.png)

图 5:每股收益的最佳值(图片由作者提供)

如上所示,`eps`的最佳值是 1.9335816413107338。我们将该值用于参数向前发展,并尝试根据剪影得分、Calinski Harabasz 得分和 Davies Bouldin 得分找到`min_samples`参数的最佳值。对于这些方法中的每一种,最佳聚类数如下:

1.  剪影得分:18
2.  卡林斯基·哈拉巴斯得分:29
3.  戴维斯·波尔丁得分:2

找到最佳数量`min_samples`的代码可以在[这里找到](https://github.com/IDB-FOR-DATASCIENCE/Segmentation-Modelling.git),关于每种方法的更多细节可以在这个[博客](/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad)中找到。我们继续采用建议的中间值,即侧影得分为 18。如果我们没有时间对这些指标进行网格搜索,一个快速的经验法则是将`min_samples`参数设置为特性数量的两倍。

dbscan clustering

from numpy import unique
from numpy import where
from sklearn.cluster import DBSCAN
from matplotlib import pyplot

define dataset

define the model

model = DBSCAN(eps=1.9335816413107338, min_samples= 18)# rule of thumb for min_samples: 2*len(cluster_df.columns)# fit model and predict clusters
yhat = model.fit_predict(cluster_df)

retrieve unique clusters

clusters = unique(yhat)# Calculate cluster validation metricsscore_dbsacn_s = silhouette_score(cluster_df, yhat, metric='euclidean')score_dbsacn_c = calinski_harabasz_score(cluster_df, yhat)score_dbsacn_d = davies_bouldin_score(cluster_df, yhat)print('Silhouette Score: %.4f' % score_dbsacn_s)
print('Calinski Harabasz Score: %.4f' % score_dbsacn_c)
print('Davies Bouldin Score: %.4f' % score_dbsacn_d)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/464b40a2b7c65537aa96ce74fc256179.png)

图 6:集群验证指标:DBSCAN(作者图片)

比较图 1 和图 6,我们可以看到 DBSCAN 在轮廓得分上比 K-means 表现得更好。该模型在论文中描述为:

*   [一种基于密度的算法,用于在带有噪声的大型空间数据库中发现聚类](https://www.osti.gov/biblio/421283),1996。

在另一篇博客中,我们将讨论更高级版本的 DBSCAN,称为基于层次密度的空间聚类(HDBSCAN)。

# 高斯混合模型(GMM)

高斯混合模型是一种基于距离的概率模型,它假设所有数据点都是由具有未知参数的多元高斯分布的线性组合生成的。像 K-均值一样,它考虑了潜在高斯分布的中心,但与 K-均值不同,它还考虑了分布的协方差结构。该算法实现了期望最大化(EM)算法,以迭代方式查找使模型质量度量(称为对数似然)最大化的分布参数。该模型中执行的关键步骤是:

1.  初始化 k 个高斯分布
2.  计算每个点与每个分布关联的概率
3.  根据与分布相关的每个点的概率重新计算分布参数
4.  重复该过程,直到对数似然最大化

在 GMM,有 4 种计算协方差的方法:

1.  **完整:**每个分布都有自己的一般协方差矩阵
2.  **并列:**所有分布共享一般协方差矩阵
3.  **Diag:** 每个分布都有自己的对角协方差矩阵
4.  **球形:**每个分布都有自己的单方差

除了选择协方差类型,我们还需要选择模型中的最佳聚类数。我们使用 BIC 评分、剪影评分、Calinski Harabasz 评分和 Davies Bouldin 评分来使用网格搜索选择两个参数。对于这些方法中的每一种,最佳聚类数如下:

1.  BIC 分数:协方差-“满”和聚类数- 26
2.  轮廓得分:协方差-“并列”和聚类数- 2
3.  Calinski Harabasz 得分:协方差-“球形”和聚类数- 4
4.  戴维斯·波尔丁得分:协方差-“满”和聚类数- 8

寻找最佳参数值的代码可以在[这里](https://github.com/IDB-FOR-DATASCIENCE/Segmentation-Modelling.git)找到,关于每种方法的更多细节可以在这个[博客](/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad)中找到。我们选择协方差为“完全”,基于 BIC 评分的聚类数为 26,因为它是基于这个特定的模型。如果我们有来自多个指标的相似配置,我们可以取所有指标的平均值/中值/众数。我们现在可以拟合模型并检查模型性能。

gaussian mixture clustering

from numpy import unique
from numpy import where
from sklearn.mixture import GaussianMixture
from matplotlib import pyplot

define the model

model = GaussianMixture(n_components= 26,covariance_type= "full", random_state = 10)

fit the model

model.fit(cluster_df)

assign a cluster to each example

yhat = model.predict(cluster_df)

retrieve unique clusters

clusters = unique(yhat)# Calculate cluster validation scorescore_dbsacn_s = silhouette_score(cluster_df, yhat, metric='euclidean')score_dbsacn_c = calinski_harabasz_score(cluster_df, yhat)score_dbsacn_d = davies_bouldin_score(cluster_df, yhat)print('Silhouette Score: %.4f' % score_dbsacn_s)
print('Calinski Harabasz Score: %.4f' % score_dbsacn_c)
print('Davies Bouldin Score: %.4f' % score_dbsacn_d)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7dcd08d1137260e6237bb6313cc972e6.png)

图 7:集群验证指标:GMM(图片由作者提供)

比较图 1 和图 7,我们可以看到 K-means 在所有集群验证指标上都优于 GMM。在另一篇博客中,我们将讨论 GMM 的更高级版本,称为变分贝叶斯高斯混合。

# 结论

这篇博客的目的是帮助读者理解 4 种流行的聚类模型是如何工作的,以及它们在 python 中的具体实现。如下所示,每种模式都有其优缺点:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2773d773b2f3049c0daa1da314dbcd9a.png)

图 8:聚类算法的利与弊(图片由作者提供)

最后,重要的是要理解这些模型只是一种手段,用于找到合理的、易于理解的、可以有效定位的客户/产品细分市场。因此,在大多数实际情况下,我们将最终尝试多种模型,并从每次迭代中创建客户/产品档案,直到我们找到最具商业意义的细分市场。因此,分段既是一门艺术也是一门科学。

你对这个博客有什么问题或建议吗?请随时留言。

# 感谢您的阅读!

如果你和我一样,对人工智能、数据科学或经济学充满热情,请随时添加/关注我的 [LinkedIn](http://www.linkedin.com/in/indraneel-dutta-baruah-ds) 、 [Github](https://github.com/IDB-FOR-DATASCIENCE) 和 [Medium](https://medium.com/@indraneeldb1993ds) 。

# 参考

1.  Ester,M .,Kriegel,H . P .,Sander,J .,,Xu .*一种基于密度的算法,用于在带有噪声的大型空间数据库中发现聚类*。美国:不扩散条约,1996 年。网络。
2.  多变量观察的分类和分析的一些方法。第五届伯克利数理统计和概率研讨会会议录,第 1 卷:统计,281–297,加州大学出版社,伯克利,加利福尼亚州,1967 年。[https://projecteuclid.org/euclid.bsmsp/1200512992](https://projecteuclid.org/euclid.bsmsp/1200512992)
3.  [sci kit-learn:Python 中的机器学习](http://jmlr.csail.mit.edu/papers/v12/pedregosa11a.html),Pedregosa *等人*,JMLR 12,第 2825–2830 页,2011 年。

# k-意味着用 NumPy 从头开始

> 原文:<https://towardsdatascience.com/k-means-from-scratch-with-numpy-74f79d2b1694?source=collection_archive---------18----------------------->

## 使用这种快速简单的聚类算法回归基础

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/379b796a7859ff207b2f414996d9e833.png)

图片来自 [unsplash](https://unsplash.com/photos/0vV4SEdf4gI)

K-means 是最简单的聚类算法。它很容易理解和实现,当试图理解无监督学习的世界时,这是一个很好的起点。

无监督学习指的是机器学习的整个子领域,其中数据没有标签。我们不是训练一个模型来预测标签,而是希望揭示数据中的某种潜在结构,否则这些结构可能不明显。

## 它是如何工作的?

K-means 从假设数据可以分成 K 个不同的簇开始。每个聚类的特征在于与该聚类相关的点的平均值(因此得名… K-means)。

识别 K 个不同装置位置的程序如下:

1.  **随机分配**数据中的每个点到一个簇中
2.  **计算分配给特定聚类的每个点的平均值**
3.  对于每个点,**根据最接近该点的平均值更新分配的平均值**。
4.  重复步骤 2 和 3,直到平均值收敛到恒定值。

## 来实施吧!

为了便于跟踪不同的点以及它们之间的关联,让我们构建一个小类(注意,同样的事情可以通过命名元组或字典轻松实现)。

import numpy as npK = 3class point():
def init(self, data):
self.data = data
self.k = np.random.randint(0,K)

def __repr__(self):
    return str({"data":self.data, "k":self.k})

也不需要`__repr__`函数,但它有助于查看引擎内部发生了什么。

现在我们需要一些模拟数据来玩:

N = 200
data1 = np.random.randn(N//3,2) + np.array([5,6])
data2 = np.random.randn(N//3,2) + np.array([-5,-6])
data3 = np.random.randn(N//3,2) + np.array([-10,3])
data = np.concatenate((data1, data2, data3))


绘制如下图:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1c56e23a331fd21215326501d256f5c5.png)

用 3 个集群模拟数据

## 第一步:随机分配

当我们为每个数据点实例化类时,我们的类通过随机选择一个指定的平均值来处理这个问题。

points = [point(d) for d in data]


## 第二步:计算平均值

为了完成这一步,我们需要构建两个函数。一个创建分配给每个分类的点的列表,另一个计算每个分类的平均值。我们可以使用如下的`collections.defaultdict`实现第一个:

from collections inport defaultdictdef make_k_mapping(points):
point_dict = defaultdict(list)
for p in points:
point_dict[p.k] = point_dict[p.k] + [p.data]
return point_dict


然后是第二个功能:

def calc_k_means(point_dict):
means = [np.mean(point_dict[k],axis=0) for k in range(K)]
return means


## 步骤 3:更新点群分配

现在我们需要计算距离,并根据最接近的聚类平均值更新关联的聚类。

def update_k(points,means):
for p in points:
dists = [np.linalg.norm(means[k]-p.data) for k in range(K)]
p.k = np.argmin(dists)


## 训练循环

现在,我们只需要将这些函数组合在一个循环中,为我们的新聚类算法创建一个训练函数。

def fit(points, epochs=10):
for e in range(epochs):
point_dict = make_k_mapping(points)
means = calc_k_means(point_dict)
update_k(points, means)
return means, pointsnew_means, new_points = fit(points)


如果我们把新的方法和原始点一起画出来,我们会得到这样的结果:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7e0d5fd573cfdf292bc785b4e0deb40f.png)

聚类和原始数据

## 参数调谐

对于你们当中目光敏锐的人来说,你们会意识到我们从一开始就选择了正确的集群数量。如果我们选择 K 大于或小于 3,我们会有一个较差的数据拟合。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a90561efc1e6b85dc8107208583d25dc.png)

K = 2

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/dad13028b8ae24947f8eb65602d46c53.png)

K = 4

这就引出了一个问题,我们如何更好地量化模型的拟合度?一个自然的选择是计算一个点与其聚类平均值的平均距离。考虑到点被分配给具有欧几里德距离的簇,使用这个作为性能的度量看起来是一个合理的选择。

def evaluate(points):
point_dict = make_k_mapping(points)
means = calc_k_means(point_dict)
dists = [np.linalg.norm(means[p.k]-p.data) for p in points]
return np.mean(dists)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4237def55a155c28369d14d5e9f56098.png)

作为 K 的函数的平均距离

表面上看起来是可行的,但仍然有一个问题,K = 4 的平均距离小于 K = 3。仔细想想,这很有意义,每个数据点都有一个聚类,平均距离为 0。然而,这显然是一个过度拟合数据的模型。

对此的一个解决方案被称为 Akaike 信息标准(AIC)。该度量以模型参数的数量来惩罚模型的可能性。

对于 K-means,AIC 是点与其分配的均值之间的平方距离之和,由训练参数的数量决定。这来自于假设每个聚类是具有单位协方差的高斯分布。K 均值模型的训练参数的数量是`K * d`,其中`d`是维度的数量。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2ed3e5a02aec2872b5a07722705de163.png)

K 均值的 AIC

这个图有一个明确的最小值 3,这正是我们想要的!

## 我们学到了什么?

所以在这里,我们已经了解了 K-means 如何工作,如何用 NumPy 构建模型,以及如何训练它。我们还研究了一些评估模型性能的潜在方法,以及如何使用模型参数的数量来惩罚评估指标。

K-means 是一种轻量级但功能强大的算法,可用于解决许多不同的聚类问题。现在您知道它是如何工作的,以及如何自己构建它了!

# 营销分析中的 K-Means:聚类 210 个美国 DMA

> 原文:<https://towardsdatascience.com/k-means-in-marketing-analysis-clustering-210-us-dmas-deb9e60e3fe5?source=collection_archive---------30----------------------->

## 从头到尾的 K-Means 聚类分析

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bd793975f07b9ec4202b0cf1acf220b6.png)

佩德罗·拉斯特拉在 [Unsplash](https://unsplash.com/s/photos/chicago?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片

当我可以将机器学习技术应用于日常营销问题时,这让我非常兴奋。给你一些背景,我在一家大型广告公司工作,我的一些客户是美国的顶级广告商,他们的产品和服务覆盖整个国家,他们有很多营销预算要花(每年大约 9 位数!).所以我们的工作就是帮助他们聪明高效地花钱!

挑战之一是为所有当地市场制定战略,即 DMA(**DMA**代表“**指定市场区域**”,也可能被称为媒体市场)。美国有 210 个 DMA,你当然可以按地区划分,或者简单地按西部、东部和中部划分。然而,考虑到大区域内的人口统计和经济差异,我们可能希望使用一些更数据驱动的方式来查看所有这些 DMA。因此,今天我将使用聚类来获得几个市场聚类,每个聚类中具有最大的相似性。

在深入细节之前,我想给你看一下我在探索机器学习时最喜欢的图表。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/50f5fdd0402d4e7ac2200d739c419b21.png)

聚类属于**无监督学习**的分支,该分支在没有预先存在标签的数据集中寻找以前未检测到的模式。聚类背后的主要思想是,您希望以一种方式将对象分组到相似的类中,即同一组的成员之间的相似性高,而不同组的相似性低。

最流行和最广泛使用的算法是 **K-Means 聚类算法。**k-means 聚类算法是一种迭代算法,在未标记的数据集中达到预定数量的聚类,基本工作方式如下:

1.  选择𝑘初始种子
2.  将每个观察值分配给具有最近平均值(最小平方欧几里得距离)的聚类
3.  为分配给每个聚类的观测值重新计算聚类质心
4.  继续迭代,直到质心没有变化

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b3fa8308a4fab01285cbe6f1bb773325.png)

k 表示聚类示例(k = 7)

对于 k-means 聚类算法来说,两个假设非常重要:

1.  要计算“聚类中心”,需要计算属于该聚类的所有点的(算术)平均值。在每次新的迭代开始时,重新计算每个聚类中心
2.  在重新计算聚类中心之后,如果给定点现在比其当前聚类的中心更靠近不同的聚类中心,则该点被重新分配给最近的中心

我将用一个营销支出数据集来演示它在 Python 中是如何工作的,这个数据集是我从一家研究公司 Kantar 收集的,它是过去两年中排名前 30 位的科技公司的数据。

market.head(5)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a419fc094d77eb6b68748df94ad10719.png)

**数据字典**

*   市场:指定市场区域(DMA)是指人们可以接收相同电视和广播电台节目的区域,也可能包括其他类型的媒体,包括报纸和互联网内容
*   媒体:10 种常见媒体类型,包括电视、广播、户外、数字等。
*   观众人口:12 岁以上的电视/广播观众人口
*   公司/品牌:在该市场做广告的公司/品牌数量
*   IsTop31:电信行业对市场重要性的主观分类。0 表示不是前 31 名市场,1 表示前 31 名市场
*   Spend_K:以千美元计的媒体支出(000)

**预处理分类值**

Change MARKETS to categorical

market['DMA_Code']=market['DMA_Code'].astype('category')#One Hot Encoding for Media and Industryfrom sklearn.preprocessing import LabelBinarizerdef labelcoder(data, column):
onehot = data.copy()
lb=LabelBinarizer()
lb_results = lb.fit_transform(onehot[column])
lb_results_df = pd.DataFrame(lb_results, columns=lb.classes_)
return lb_results_dfmedia_features = labelcoder(market, 'MEDIA')
industry_features = labelcoder(market, 'INDUSTRY')
division_features = labelcoder(market, 'Division_Name')#Put them all together
market_df = pd.concat([market['DMA_Code'],scaled_features, media_features, industry_features, division_features], axis=1)


**标准化数字特征**

num_features = market[['Audience Population','BRAND','Company','IsTop31','Spend_K']]from sklearn.preprocessing import MinMaxScaler

Scale the numerical features

scaler = MinMaxScaler()
scaled = scaler.fit_transform(num_features)
scaled_features = pd.DataFrame(scaled, columns = num_features.columns)


## **设置 K-Means**

**用肘法求最优 K**

这一步非常重要,因为我们不仅想要任意数量的聚类,还想要找到尽可能多地分隔数据点而不引入整体复杂性的 K 的数量。常用的度量是**惯性——样本到其最近聚类中心的平方距离之和**

import matplotlib.pyplot as plt
from sklearn.cluster import KMeanssum_of_squared_distances = []K = range(1,20)
for k in K:
km = KMeans(n_clusters=k)
km = km.fit(market_df)
sum_of_squared_distances.append(km.inertia_) plt.plot(K, sum_of_squared_distances, 'bx-')
plt.xlabel('k')
plt.ylabel('Sum of Squared Distances to the Nearest Cluster')
plt.title('Elbow Method For Optimal k')
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/14eb183d3caecac2c0ce03e307b6d2ce.png)

如上图所示,收益递减达到 k = 3。在 k =3 之后,度量以慢得多的速度变得更好。

Fit the model with k = 3

k_means = KMeans(n_clusters=3, random_state=0).fit(market_df)
cluster_preds = k_means.predict(market_df)
k_means.get_params


**使用 Calinski Harabasz 评分(方差比)评估聚类适合度**

from sklearn.metrics.cluster import calinski_harabasz_score calinski_harabasz_score(market_df, cluster_preds)39451.77110587817


## 解释

理解 k-means 聚类结果不像解释监督学习结果那样容易,因为我们本质上是在寻找数据的“底层”模式,并且经常需要领域知识。

但是,我们可以查看描述性统计数据来了解这些分类。

n_clusters = 3
k_means_cluster_stats = pd.DataFrame()for i in range(n_clusters):
k_means_cluster_stats['Cluster ' + str(i+1)] = market_df[k_means.labels_ == i].mean(axis=0)

k_means_cluster_stats = k_means_cluster_stats.T


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3933daa23e9bb57ac6fc4a1581a40cf5.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/755821fef602f2adccb54e4dfc963458.png)

我们可以看出,集群 2 拥有最大的平均受众群体和最高的平均支出水平,这可能表明这一组市场是排名前 30 位的科技公司的主要关注点或领域。

*   集群 0 和集群 2 混合了不同的部门,而集群 1 只有西部市场
*   集群 0 的本地支出中值最高,数字支出的百分比也很高
*   第 1 组主要是户外活动,数字消费相对较低
*   群组 2 的广告电视支出最高

感谢您的关注,希望这对您的集群项目有所帮助!

完整的代码可以在我的 github [这里](https://github.com/bonniema/Competitive_Spend_Classifier)找到。

# K-Means 与 DBSCAN 聚类—适用于初学者

> 原文:<https://towardsdatascience.com/k-means-vs-dbscan-clustering-49f8e627de27?source=collection_archive---------3----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d0bb6a6b58c9cefed235b3a9fca2e35e.png)

图片来源——un splash

# 聚类——一种无监督的机器学习技术

聚类是将未标记的数据点以这样的方式分组:
***同一组内的数据点彼此相似,
不同组内的数据点彼此不相似。***
目标是创建具有高的类内相似性和低的类间相似性的类。

# k 均值聚类

*K-Means 聚类是最常用的无监督机器学习聚类技术之一。这是一种基于质心的聚类技术,需要您决定聚类(质心)的数量,并随机放置聚类质心来开始聚类过程。目标是重复地将 N 个观察值分成 K 个簇,直到不能形成更多的组。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b9ee6297374b9e021f99298d837eca47.png)

## K 均值的优势

*   易于理解和实施。
*   能很好的处理大型数据集。

## K 均值的缺点

*   对选择的簇/质心的数量敏感。即使使用了像 Elbow 方法这样的技术,有时也很难生成好的集群。
*   不适用于异常值。质心可能会被离群值拖住,导致聚类偏斜。
*   在高维空间中变得困难,因为点之间的距离增加,欧几里德距离发散(收敛到恒定值)。
*   随着维数的增加而变慢。

# k-均值算法

1.决定集群的数量。这个数叫做 K,聚类数等于质心数。基于 K 的值,生成 K 个随机质心的坐标。

2.对于每个点,计算该点和每个质心之间的欧几里德距离。

3.将该点指定给其最近的质心。分配给同一个质心的点形成一个簇。

4.一旦聚类形成,通过取聚类平均值来计算每个聚类的新质心。聚类平均值是属于该聚类的所有点的 x 和 y 坐标的平均值。

5.重复步骤 2、3 和 4,直到质心不能再移动。换句话说,重复这些步骤直到收敛。

# 使用 Scikit Learn 的虹膜数据集的 k 均值

import pandas as pd
from sklearn import metrics
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt# reading the classic iris dataset into a df
iris_df = pd.read_csv(“iris_dataset.csv”)# Setting the independent features (input)
X = iris_df.drop(“species”, axis=1).values# Creating the KMeans object and fitting it to the Iris data
iris_kmeans = KMeans(n_clusters=3)iris_kmeans.fit(X)# Predicting the cluster labels
labels = iris_kmeans.predict(X)
print(labels)# Finding the final centroids
centroids = iris_kmeans.cluster_centers_# Evaluating the quality of clusters
s = metrics.silhouette_score(X, labels, metric=’euclidean’)
print(f”Silhouette Coefficient for the Iris Dataset Clusters: {s:.2f}”)# plotting the clusters using sepal_length and sepal_width
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap=”rainbow”)
plt.show()


## 输出

标签值代表聚类数。

[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2 0 0 0 0 2 0 0 0 0
0 0 2 2 0 0 0 0 2 0 2 0 2 0 0 2 2 0 0 0 0 0 2 0 0 0 0 2 0 0 0 2 0 0 0 2 0
0 2]Silhouette Coefficient for the Iris Dataset Clusters: 0.55


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3c8f17eb085a4b3069bfbff709fc63cb.png)

三个 K 均值聚类

# 寻找 K-Means 的最佳聚类数(肘方法)

使用 K-Means 形成的聚类的质量很大程度上取决于 K 的选定值。K 的错误选择会导致较差的聚类。那么如何挑选 K 呢?我们来看看常用的手法叫做“**肘法**”。目标是选择形成弯头的 K 点。

**步骤:**

1.对于不同的 K 值,执行以下步骤:

2.对于每个聚类,计算每个点到其质心的距离的平方和。

3.将每个聚类的距离平方和相加,得到 k 值的距离平方和。

4.不断将每个 K 的距离平方和添加到列表中。

5.绘制距离平方和(使用上一步创建的列表)及其 K 值。

6.选择发生急剧变化的 K(看起来像曲线的弯头)。

Arbitrarily selecting a range of values for K

K = range(1,10)sum_of_squared_distances = []# Using Scikit Learn’s KMeans Algorithm to find sum of squared distancesfor k in K:
model = KMeans(n_clusters=k).fit(X)
sum_of_squared_distances.append(model.inertia_)plt.plot(K, sum_of_squared_distances, “bx-”)
plt.xlabel(“K values”)
plt.ylabel(“Sum of Squared Distances”)
plt.title(“Elbow Method”)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4c314c3479313f63a2241bb3d67fa863.png)

查看该图,我们可以看到 K=3 处的拐点,因此这是该数据集的最佳聚类数。

有时,我们可能会以多个值显示一个肘形结束。在这种情况下,为了找到最佳 K,可以使用像轮廓系数这样的评估度量。应该选择将返回轮廓系数的最高正值的 K。

# 基于密度的含噪声应用空间聚类(DBSCAN)

*DBSCAN 是一种基于密度的聚类算法,它形成数据点密集区域的聚类,忽略低密度区域(将其视为噪声)。*

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/52eb3f047e8a4211f21d4e72d65397ac.png)

维基百科图片

## DBSCAN 的优势

*   适用于噪声数据集。
*   可以轻松识别异常值。
*   聚类可以采取任何不规则的形状,不像 K-Means 中的聚类或多或少是球形的。

## DBSCAN 的缺点

*   不适用于稀疏数据集或密度变化的数据集。
*   对 eps 和 minPts 参数敏感。
*   对于多处理器系统不可分区。

# DBSCAN 参数

DBSCAN 使用以下两个用户定义的参数进行聚类:

**ε(EPS)**:定义为被认为是相邻点(属于同一个聚类)的两点之间的最大距离。

**最小点(min_samples 或 minPts)** :这定义了一个给定点需要被视为核心数据点的相邻点的最小数量。这包括点本身。例如,如果最小点数设置为 4,则给定点需要有 3 个或更多的相邻数据点才能被视为核心数据点。

如果最小数量的点满足ε距离要求,则它们被视为一个聚类。

# **DBS can 中的重要术语**

Core Point: A data point is considered to be a core point if it has minimum number of neighboring data points (min_samples) at an epsilon distance from it. This minimum number of data points includes the original data point.Border Point: A data point that has less than minimum number of data points needed but has at least one core point in the neighborhood.Noise: A data point that is not a core point or a border point is considered noise or an outlier.


# **DBSCAN 算法**

**1** 。决定 eps 和 minPts 的值。

**2** 。对于每个点:

*   计算它与所有其他点的距离。如果距离小于或等于 eps,则将该点标记为 x 的邻居。
*   如果该点的相邻点计数大于或等于 minPts,则将其标记为核心点或已访问点。

**3** 。对于每个核心点,如果它还没有被分配给一个集群,则创建一个新的集群。递归地找到它的所有邻近点,并把它们分配到与核心点相同的簇中。

**4** 。继续这些步骤,直到覆盖所有未访问的点。

# **使用 Scikit Learn 对虹膜数据集进行 DBSCAN 聚类**

import pandas as pd
from sklearn import metrics
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt# reading the classic iris dataset into a df
iris_df = pd.read_csv(“iris_dataset.csv”)X = iris_df.drop(“species”, axis=1).valuesiris_dbscan = DBSCAN(eps=0.5, min_samples=5)
iris_dbscan.fit(X)labels = iris_dbscan.labels_# label=-1 means the point is an outlier. Rest of the values represent the label/cluster number starting from 0
print(labels)# Creating a numpy array with all values set to false by default
core_samples_mask = np.zeros_like(labels, dtype=bool)# Setting core and border points (all points that are not -1) to True
core_samples_mask[iris_dbscan.core_sample_indices_] = True# Finding the number of clusters in labels (ignoring noise if present)
n_clusters_ = len(set(labels)) — (1 if -1 in labels else 0)
n_noise_ = list(labels).count(-1)# Printing the number of clusters and number of noise points (outliers)
print(“Estimated number of clusters: %d” % n_clusters_)
print(“Estimated number of noise points: %d” % n_noise_)# Evaluating the quality of clusters
s = metrics.silhouette_score(X, iris_dbscan.labels_)
print(f”Silhouette Coefficient for the Iris Dataset Clusters: {s:.2f}”)


## 输出

Label = -1 表示它是一个噪声点(异常值)。
Label = 0 或以上,表示集群编号。

[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 -1 1 1 -1 1 1 1 1 1 1 1 -1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1
1 1 -1 1 1 1 1 1 1 -1 -1 1 -1 -1 1 1 1 1 1 1 1 -1 -1 1
1 1 -1 1 1 1 1 1 1 1 1 -1 1 1 -1 -1 1 1 1 1 1 1 1 1
1 1 1 1 1 1]Estimated number of clusters: 2Estimated number of noise points: 17Silhouette Coefficient for the Iris Dataset Clusters: 0.49


## 绘制聚类图

unique_labels = set(labels)colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))for k, col in zip(unique_labels, colors):
if k == -1:
# Black used for noise
col = “k”

class_member_mask = (labels == k)
xy = X[class_member_mask & core_samples_mask]
plt.plot(xy[:, 0], xy[:, 1], “o”, markerfacecolor=col,
markeredgecolor=”k”, markersize=10) xy = X[class_member_mask & ~core_samples_mask]
plt.plot(xy[:, 0], xy[:, 1], “o”, markerfacecolor=col,
markeredgecolor=”k”, markersize=5)plt.title(“Estimated number of clusters: %d” % n_clusters_)

plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/16ca416e712b37ad26088a8f04b94238.png)

黑色代表异常值,彩色点代表两个 DBSCAN 集群

# 寻找每股收益的最佳值(拐点法)

DBSCAN 聚类算法对我们选择的 eps 值很敏感。那么如何才能知道我们选择了最优的 eps 值呢?这里有一个常用的手法叫做“**膝法**”。目标是找出每个点到其 K 个最近邻点的平均距离,并选择曲率最大或发生急剧变化的距离。K 的值被设置为等于 minPoints。

以下是一个使用 Scikit Learn 的 NearestNeighbors 模块显示最佳 eps 值选择的示例。

from sklearn.neighbors import NearestNeighbors
nearest_neighbors = NearestNeighbors(n_neighbors=5)nearest_neighbors.fit(X)
distances, indices = nearest_neighbors.kneighbors(X)
distances = np.sort(distances, axis=0)[:, 1]
print(distances)plt.plot(distances)
plt.show()


## 输出

[0. 0. 0. 0. 0. 0.1
0.1 0.1 0.1 0.1 0.1 0.1
0.1 0.14142136 0.14142136 0.14142136 0.14142136 0.14142136
0.14142136 0.14142136 0.14142136 0.14142136 0.14142136 0.14142136
0.14142136 0.14142136 0.14142136 0.14142136 0.14142136 0.14142136
0.14142136 0.14142136 0.14142136 0.14142136 0.14142136 0.14142136
0.14142136 0.14142136 0.14142136 0.14142136 0.14142136 0.14142136
0.14142136 0.14142136 0.14142136 0.14142136 0.14142136 0.14142136
0.17320508 0.17320508 0.17320508 0.17320508 0.17320508 0.17320508
0.17320508 0.2 0.2 0.2 0.2 0.2
0.2 0.2 0.2 0.2 0.2 0.2
0.2236068 0.2236068 0.2236068 0.2236068 0.2236068 0.2236068
0.2236068 0.2236068 0.2236068 0.2236068 0.24494897 0.24494897
0.24494897 0.24494897 0.24494897 0.24494897 0.24494897 0.24494897
0.24494897 0.24494897 0.24494897 0.24494897 0.26457513 0.26457513
0.26457513 0.26457513 0.26457513 0.26457513 0.26457513 0.26457513
0.26457513 0.26457513 0.26457513 0.26457513 0.28284271 0.28284271
0.28284271 0.28284271 0.3 0.3 0.3 0.3
0.3 0.3 0.3 0.31622777 0.31622777 0.31622777
0.33166248 0.33166248 0.33166248 0.33166248 0.33166248 0.34641016
0.34641016 0.34641016 0.34641016 0.34641016 0.34641016 0.34641016
0.36055513 0.36055513 0.36055513 0.36055513 0.37416574 0.38729833
0.38729833 0.38729833 0.41231056 0.41231056 0.41231056 0.41231056
0.42426407 0.42426407 0.43588989 0.45825757 0.48989795 0.48989795
0.53851648 0.53851648 0.55677644 0.6244998 0.63245553 0.73484692]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/79afbba483943c8e742ebc5a836f2d46.png)

最佳值应该是我们看到最大曲率的值,在这种情况下,该值似乎接近 0.5。

有时,我们可能会以多个值显示急剧变化而告终。在这种情况下,为了找到最佳 K,可以使用像轮廓系数这样的评估度量。应该选择将返回轮廓系数的最高正值的 K。

*何时使用这两种聚类技术中的哪一种,取决于问题。尽管 K-Means 是最流行的聚类技术,但也有使用 DBSCAN 得到更好的聚类的用例。*

# k 表示没有库的集群

> 原文:<https://towardsdatascience.com/k-means-without-libraries-python-feb3572e2eef?source=collection_archive---------4----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6d5247ed27e7a46127e599d5d0bfcd72.png)

Billy Huynh 在 [Unsplash](https://unsplash.com/s/photos/cluster?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片

## ***—使用 Python***

*Kmeans 是一种广泛使用的聚类工具,用于分析和分类数据。然而,我怀疑,人们往往并不完全了解幕后发生了什么。如果你理解最终产品传达了什么,这不一定是一件坏事,但是通过从头开始构建算法来了解发生了什么肯定会导致对其背后的推理的更深入的理解。*

我 **想先强调一下**互联网是程序员和工程师的绝佳去处。答案和资源随处可得,只需谷歌搜索即可。假装这一切都是我自己想出来的是愚蠢的。我很乐意承认,有时需要通读其他人在算法方面的工作,才能理解如何更好地接近它。代码的美妙之处在于它可以用许多不同的方式编写,每种方式强调的质量都略有不同。在你的学习中利用这一点。

既然我已经谈到了那一点,让我们开始吧!

**K 表示聚类**最简单的形式是一种算法,它在数据簇中找到密切的关系,并将它们分组以便于分类。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4dec8573fee40abc8b00e7b5375dd295.png)

你在这里看到的是一种算法,根据特定的质量将不同的数据点分类成组或段…接近(或接近)一个中心点。

最常见的是 Scikit-Learn 的 KMeans 算法,看起来像这样:

from sklearn.cluster import KMeanskm = KMeans(
n_clusters=3, init='random',
n_init=10, max_iter=300,
random_state=42
)y_km = km.fit_predict(X)


您可能不太理解这些部分,但它的方法相当简单。它主要做的是,它说我们需要 3 个集群,从 10 次迭代开始(或运行,每次细化集群和位置),3 个中心点的初始化是随机的,最大迭代次数是 300,随机状态只是指每次运行它,它都是相同的。然后我们运行预测。更多信息可在此处[阅读](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html)关于可使用的不同参数。

那么,我们如何从头开始创建这些代码呢……尤其是在我们不确定发生了什么的情况下?我们来想办法吧!

第一步是思考并描述正在发生的事情。首先,[这篇文章](/how-does-k-means-clustering-in-machine-learning-work-fdaaaf5acfa0)很好地描述了每一步。总之,我们在散点图上绘制出 *k* 数量的点(也称为*质心)*,通常是随机的,并找到最接近这些点的数据。然后,我们不断地重新计算从数据到质心的平均距离和质心位置,直到每个 *k* 质心周围都有清晰的数据组。

我失去你了吗?希望不会。让我们浏览一下每个流程,看看发生了什么:

*   第一步是我们需要决定要将数据分成多少个簇。这有一个方法,但是为了简单起见,我们说我们将使用 3 个集群,或者, *k =* 3。代码看起来像这样:

k = 3
clusters = {}for i in range(k):
clusters[i] = []


你在上面看到的只是创建了 3 个空的集群。看起来是这样的…

{0: [], 1: [], 2: []}


很简单,对吧?

然后,我们以类似的方式设置质心,但这次我们使用我们正在使用的数据。在我的例子中,我使用的是[波士顿住房数据集](https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.data)。 *X,在本例中,*是我从数据集中选择的两个数据点的数组。

for i in range(k):
centroids[i] = X[i]


接下来,我们需要找到每个数据点到质心的距离。这个概念很简单,但是下一个块一开始看起来有点混乱。我建议搜索和阅读这篇文章的不同部分,以便更好地了解正在发生的事情。*例如,如果你在谷歌上搜索“np.linalg.norm ”,你会发现* [*这个页面*](https://numpy.org/doc/stable/reference/generated/numpy.linalg.norm.html) *描述了它是什么以及它的作用。*

for data in X:
euc_dist = []
for j in range(k):
euc_dist.append(np.linalg.norm(data - centroids[j]))
clusters[euc_dist.index(min(euc_dist))].append(data)


初始化质心和聚类后,我们要重新计算这两个值!为什么?因为它们在某种程度上是随机初始化的,所以我们需要慢慢地将它们移向数据自然分段的最理想方式(如果有的话,*,但那是另一个讨论*)。

我写了两个函数来实现这个功能。让我们来看看:

def recalculate_clusters(X, centroids, k):
""" Recalculates the clusters """
# Initiate empty clusters
clusters = {}
# Set the range for value of k (number of centroids)
for i in range(k):
clusters[i] = []
for data in X:
euc_dist = []
for j in range(k):
euc_dist.append(np.linalg.norm(data - centroids[j]))
# Append the cluster of data to the dictionary
clusters[euc_dist.index(min(euc_dist))].append(data)
return clustersdef recalculate_centroids(centroids, clusters, k):
""" Recalculates the centroid position based on the plot """
for i in range(k):
centroids[i] = np.average(clusters[i], axis=0)
return centroids


我希望您能在这两个函数中识别出一些相同的代码。请密切注意不同的零件和部件。学习的最好方法之一是剖析内在发生的事情。再一次,我要求你用谷歌搜索这段代码的个别部分。这就像把收音机拆开,然后再组装起来。把那个内在的工程师拿出来!

从那里,我们将把一个绘图函数放在一起,绘制每个集群,并为其分配不同的颜色。这就像将数据输入分拣机,分拣机根据数据的去向对不同的数据进行颜色编码。出来的东西看起来像这样:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/90239a08f681ad583097de4193b2f8e4.png)

我们可以看到数据被清晰地分割成不同的部分,尽管它们分布得不是很好。这是因为这仅仅是数据的第一次迭代!我还应该提到,这种形状并不完全适合于聚类,这本身就是一个关于算法的优点和缺点的教训。

那么,当我们希望在集群之间有更好的分布时,我们该怎么做呢?…重新计算,重新计算,重新计算!在这种情况下,如果我们运行它,比如说,10 次,它将如下所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/09e5423f3dc506ff0af5f1f1d1a39839.png)

现在有一个稍微好一点的分配,不是吗?我们看到的是数据中 3 种不同的非监督分类。算法告诉我们,这三种颜色可能意味着数据中至少值得研究的东西。请注意,这并不意味着它实际上很重要。这就是数据的有趣之处。计算机努力增强我们在数据中寻找关系的能力,但最终还是要由我们来决定这些关系(如果有的话)意味着什么。你的数据科学工作可能会持续一段时间。唷!

更有趣的旁注之一…当决定运行多少次迭代时(或者换句话说,你想要重新计算多少次),你可以把通常所说的“肘图”放在一起,看看迭代真正开始失去区分能力的地方。我的看起来像这样:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8e8046130439e7a84824a5a3ed8f7c87.png)

您可以看到,大约 3 到 4 次重复后,它开始失去每次迭代在调整这些簇和质心时产生的动量。这是一个很好的检查有多少计算你真的想运行。毕竟这对于一个公司来说,时间就是金钱,资源一般都是有限的!当然,这是非常低级的东西,所以没什么大不了的,但它总是值得你和/或团队就项目和分析进行一次对话。

要查看整个(*进行中*)笔记本,请导航到我的 GitHub 库,这里是[T5!你将会看到我如何选择数据集以及最初探索数据集的一些细节。](https://github.com/lechemrc/CS-Build-Week)

我希望你喜欢 K 均值聚类的概述!请注意,我对数据科学的世界还相当陌生,所以我绝对愿意接受本文中详述的观点和方法的修正。毕竟,我觉得学习是持续的,我一点也不介意提高我解释和利用这些方法的能力。我们都从错误中学习!如果您觉得有任何错误或需要澄清的地方,请联系我们。谢谢大家!

# k-最近邻

> 原文:<https://towardsdatascience.com/k-nearest-neighbor-85bd50ea3e4d?source=collection_archive---------30----------------------->

## 邻居很重要!!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b1c4140a374750e42c469d52b05a16f7.png)

照片由 [Pexels](https://www.pexels.com/photo/variety-of-food-2952869/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) 的 [Engin Akyurt](https://www.pexels.com/@enginakyurt?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) 拍摄

## 介绍

KNN 或 k-最近邻是一种监督学习算法。它可以应用于回归和分类问题的解决。KNN 是一种基于其最近样本来识别样本空间中任何特定点的类别或类标签的技术。KNN 中的字母 k 表示我们将在邻域中考虑多少样本,以预测我们在样本空间中关注点的类别标签。

KNN 也被称为基于实例的学习算法**。在基于实例的学习中,当我们获得训练样本时,我们不会处理它们并学习模型,而是存储训练样本,当我们需要对实例进行分类时,我们会对测试样本进行训练和类标签关联。所以基于实例的学习算法也被称为**懒惰算法**。**

## 分类中的 KNN

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ff31648013d5d0a2d556400ab4dbb462.png)

作者图片

我们被给予不同的样本点(x₁,y₁),(x₂,y₂),(x₃,y₃),…..,(xₙ,yₙ).所有这些点都被归入类标签 1 或类标签 2。我们引入一个点(xₜ,yₜ)and 想预测它的类标签。因此,我们使用 KNN 方法,并遵循以下步骤。

**第一步:选择 k 的值**

我们可以决定 k 的值,它将决定我们需要考虑的预测测试 sample(xₜ,yₜ).值的最近样本的总数在我们的例子中,我们考虑 k=5。

**第二步:计算距离**

使用欧几里得距离公式确定 5 个最接近的样品 w.r.t 测试样品。对于任意两个给定点,欧几里德距离使用以下公式计算

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/23378b61cc32e532353ef1f2c4254908.png)

作者图片

**步骤 3:根据类别对最近的点进行分类**

从图中可以观察到,在 5 个最近的点中,它们中的 3 个属于类别 label-2,它们中的两个属于类别 label-1。因此,根据大多数情况,可以得出结论,点(xₜ,yₜ)属于类 label-2。

## **回归中的 KNN**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/dd1535743dbae9321c19c8e4c9f25a7f.png)

作者图片

在 KNN 回归的情况下,我们将使用与分类几乎相同的方法。只有第 3 步有所不同,在这一步中,我们不会为测试样本取多数类别标签。相反,我们将取所有类标签的平均值,并将该值设置为测试样本的类标签。例如,在上图中,我们考虑 k=5 来确定测试样本的类别标签。通过使用距离公式,我们识别 5 个最近的训练样本点,并识别它们的类别标签。因为这是一个回归问题,所以所有 5 个训练样本的类别标签是相似的。因此,取所有测试样本的类别标签的平均值,就得到测试样本的类别标签。

## 属性和权重

我们看到每个样本点都有自己的 x 和 y 坐标。但是除了坐标之外,还有代表样本空间中的点的特征或属性。这些属性也非常有助于将点分成各种类别标签。因此,在寻找最近的 k 点时,也必须从所有这些属性计算欧几里德距离。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2c12e051282ee911f06f555ebed49cee.png)

作者图片

现在我们知道我们考虑回归 KNN 问题的类别标签的平均值。当我们考虑 k 的大值时,那么在分类过程中有必要取类别标签的平均值,而不是多数考虑。以下是一些原因:

1.  属性中的噪声——由于噪声的存在,距离测试样本最近的样本点可能无法捕捉到测试样本的所有特征,而稍远的点可能能够捕捉到。
2.  类别标签中的噪声——由于类别标签中存在噪声,测试样本的错误分类几率很高
3.  部分重叠的类别标签-类别标签的重叠导致算法无法分配样本测试点的正确类别标签。

你有没有想过为什么我们不考虑属性的权重?如果认为所有属性的权重相等,则以下关于样本空间的假设将成立:

1.  所有属性都具有相同的比例。拥有相同的尺度意味着所有的属性都使用相同的单位来测量,也就是说,用厘米和英尺来测量学生的身高是不相关的。
2.  所有属性的范围必须相同。例如,所有属性的值必须从 0 到 100 变化,而不是从 0 到 1000。

## **限制**

**不平衡**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8dcf676a9bf059a687ad9a41ae2c4572.png)

作者图片

考虑样本空间中的一种情况,其中大约有 1000 个点被分类为 A 类或 b 类。假设 1000 个点中有 800 个点属于 A 类,这表明数据集高度不平衡。这会影响新测试样本的分类吗?是的,肯定的!!考虑我们想要在样本空间中找到点 X 的类标签。如果我们认为 k 值非常大,比如大约 150,那么不平衡的数据集将迫使点 X 落入 A 类,这可能导致错误分类。

**异常值**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8878e84c3f5726c9a93e2870f440e690.png)

作者图片

考虑上面的图像具有属于类别 1 的异常值。假设我们想要预测 1 类标记异常值和 2 类标记训练点之间的点。测试点可能属于类别 2 标签,但由于类别 1 异常值的存在,这些点可能会被错误地分类到类别 1 中。

因此,KNN 的局限性在于,由于不平衡或异常数据集的存在,它可能会对点进行错误分类。

## 如何选择 K 的最佳值?

k 的最佳值是提供最小误差和最大精度的值。我们集中于为 k 取一组随机的值,并且在训练和测试模型时验证我们获得最小错误率的 k 值。

## 编码和学习

我们现在来看看 Kaggle 著名的 Pima Indian 糖尿病数据集任务,以便更好地理解 KNN 分类。这里,在给定的数据集中,我们有各种独立的特征,例如葡萄糖、血压、皮肤厚度、胰岛素、身体质量指数等,这些特征决定了该人是否患有糖尿病的结果。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/0e66acb6cc82f1f9fe0ee144ab6f3d0d.png)

作者图片

因此,最初我们做一些探索性的分析,以发现独立特性之间的相互依赖性和相关性。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/4dc33d5ed4ab518b940ea1fa65dd0887.png)

作者图片

## 拆分测试和训练数据

## 调用 KNN 分类器对 k=1 的数据进行训练和测试

## 使用混淆矩阵和分类报告检查准确性

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e1b88672399fee5a28fa43433645f22b.png)

作者图片

## 基于从 1 到 50 的 k 值对数据进行训练和测试。

## 检查并绘制从 1 到 50 的所有 k 值的误差率。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/515333a79222f44517bdbd16b1c0edb1.png)

作者图片

## k=13 时误差最小。训练和测试数据,同时检查准确性

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/bf28d68b3dc19fbac040b197af6930e7.png)

作者图片

感谢您阅读文章!!

# k 近邻(KNN)算法

> 原文:<https://towardsdatascience.com/k-nearest-neighbor-knn-algorithm-3d16dc5c45ef?source=collection_archive---------38----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9010982bd212b8bb09dfb8569b1ba7f9.png)

妮娜·斯特雷尔在 [Unsplash](https://unsplash.com/s/photos/neighbor?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄的照片

## 使用简单的东西在泰坦尼克号比赛中获得高分

数据科学很热门,似乎每个人都在从事某种涉及最新艺术(SOTA)算法的项目。当然有充分的理由,因为在许多情况下,我们可以使用数据来给出非常合理的预测,几乎在任何领域。虽然最近有很多人关注 SOTA 算法,但更简单的方法有时会被遗忘。

> 想入门 Python?[从这里开始](/master-python-in-10-minutes-a-day-ac32996b5ded)!

最近,我玩了一个 k 近邻(KNN)算法,我惊讶于它的强大。这项技术本身也用于许多其他领域。例如,我用它来识别我在博士期间的一个研究项目的高速记录的连续帧中的相同粒子。粒子的坐标是已知的,我们在下一帧中寻找该位置周围最近的粒子。当然,当有多个粒子非常接近时,你就有麻烦了。为此,您可以利用来自多个帧的高阶信息,如速度或加速度向量。对于机器学习中的 KNN,我们通常没有时态数据,因此,我们只使用它的一阶,这是最简单的形式。

当我们想用 KNN 对新数据进行分类,即进行预测时,我们使用已知数据(或标记数据)作为一种查找表。我们选择与我们想要预测的新数据相似的数据,并从该选择中选择最突出的类。所以我们将一个未知的例子和一个已知的数据集进行比较。没有训练,没有层次,没有重量。唯一的参数是 *k* ,它指定了预测类时要考虑的邻居数量。例如,为了对一种水果进行分类,我们可以从数据集中选择五个最相似的例子。现在我们说,那五个被选择的例子中最突出的类可能也是我们想要预测的类。如果我们发现了三个苹果和两个梨,我们也会预测一个苹果。

现在我们来看另一个问题:我们如何从特征列表中选择最相似的例子。当我们有一个单一的特征时,例如*高度*,这将是非常容易的。我们简单地计算差异并选择最接近的 *k* 个匹配。但是当我们也有*重量*和*宽度*的时候该怎么办呢?我们必须量化每个特性的差异,并将结果聚合成一个值。幸运的是,有很多方法可以做到这一点。其中最常见的是欧几里德距离,可以看作是两点之间最短的直线。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/41edb852fcc4c208071e00406714ec0a.png)

欧几里德距离:毕达哥拉斯引入的魔法!(我自己的图解技巧)

欧几里德距离适用于许多特征(或维度),但是有一个缺点适用于一般的 KNN。特征必须是数字,为了计算距离,数字必须代表意义。高度特征具有与数字相关的含义。数字越大,物体越大。数字越小,物体越小。这使得距离,即两个高度之间的差异有意义,因为它是高度的差异。现在我们以颜色为特征。颜色不是数字(至少我们使用名称,而不是波长),因此,我们需要将其转换为分类单位来创建数字。现在,绿色的值用 0 表示,红色用 1 表示,以此类推。虽然这些数字表示对象附带的颜色,但值本身没有实际意义。如果我们有一个颜色值为 100 的对象和另一个颜色值为 50 的对象,除了颜色不同之外,这些数字没有任何意义。因此,这些数字之间的差异(或距离)对 KNN 来说是没有意义和没有用的。

虽然真正的分类变量是不可用的,但并不是所有东西都丢失了。例如,我们可以使用诸如 is_green 的二进制指示器来指示一个对象是否是绿色的。尽管如此,如果我确信这些特性会增加预测,我还是会使用它们。

## 创建算法

我们将创建一个 KNN 算法,并将其用于著名的[泰坦尼克号数据集](https://www.kaggle.com/c/titanic/discussion/182810),预测谁在这场悲惨的灾难中幸存下来。因此,所有函数都将与该数据集有某种链接。要创建 KNN 预测算法,我们必须执行以下步骤:

1.计算未知点和已知数据集之间的距离。
2。从该数据集中选择 k 个最近邻。
3。做一个预测

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/60c7847e7ecb40e8bb18edd8aba75324.png)

简单的 GIF 展示了 KNN 是如何工作的

如上图所示,我们只需应用毕达哥拉斯来计算欧几里得距离:

接下来我们需要做一个循环来计算和比较数据集与我们想要预测的点的所有距离:

现在我们有了一个函数,它给出了 k 个最近邻的列表。最后一步是从列表中选择最突出的类,并将其用作预测。这很容易通过取平均值和四舍五入来解决。请随意检查这是不是真的。

## 准备数据集

在测试算法之前,我们需要准备数据。这是读入数据并以巧妙的方式填充缺失的值。我们不会使用登船和客舱功能,所以我们不必担心这些。有一个票价缺失,我们将使用该 Pclass 的中间值来填充。有相当多的年龄数据丢失。我们将使用标题对每个缺失的年龄做一个很好的猜测。

接下来,我们创建几个附加特征(特征)。我最近在 Kaggle 上看到的一个是家庭生存。它假设家庭成员互相帮助,如果你的家人幸存下来,你也很可能幸存下来。这个想法来自于[徐顺江/血浓于水](https://www.kaggle.com/shunjiangxu/blood-is-thicker-than-water-friendship-forever)我认为这是相当惊人的。此外,我们将增加家庭规模,将性别更改为二元指标,缩放所有变量并将其拆分回训练/测试。

## 做预测

算法准备好了,数据准备好了,我们准备做一些预测!

这需要很长时间,因为我们的算法相当慢。如果都是正确的,你应该得到一个 **83.5%** 的准确度。我们唯一可以调整的参数是要考虑的邻居数量。我玩了一下,10 似乎给出了最好的结果。现在让我们制作一个 Kaggle 提交数据集!

把这个提交给 [Kaggle](https://www.kaggle.com/c/titanic/discussion/182810) 会得到 **81.3%** 的分数。略低于训练集,但仍然相当高。我们只用一个简单的 KNN 算法就做到了。

## 一些最后的想法

我们创造的算法强大而有效。唯一的缺点是我们的实现非常慢。对于每个向量,我们需要计算距离并与完整的数据集进行比较。Sci-kit learn 提供了更智能的实现,使用基于树的方法来最小化所需的计算量,并使其速度大大加快。

这里我们使用 KNN 作为分类器,但是,它的工作方式也非常类似于回归。对于回归,结果是连续的,因此,例如,在进行预测时对最近邻进行平均是有意义的。

我希望你和我一样开心。如有任何问题,欢迎通过 [LinkedIn](https://www.linkedin.com/in/dennisbakhuis/) 联系我。

所有代码都可以在我的 [Github](https://github.com/dennisbakhuis/algorithms_from_scratch/tree/master/KNN) 和 [Kaggle](https://www.kaggle.com/dennisbakhuis/titanic-k-nearest-neighbor-knn-frmscratch-0-813) 上获得。

我将*非常感谢*对我的 Kaggle 笔记本的任何支持。

# k-最近邻

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-94395f445221?source=collection_archive---------5----------------------->

## 关于 KNN 你需要知道的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b83665cf69eaa078c238c9b5fb230ba5.png)

罗伯特·卡茨基在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

> "一个人因他交的朋友而出名。"

我必须说这是一个完美的开场白,用来展示 K 个最近的邻居。是的,这就是 KNN 背后的简单概念。它只是根据一个数据点最近的几个邻居对其进行分类。有多少邻居?这是我们的决定。

看起来你已经知道了很多关于这个简单模型的知识。让我们深入了解一下。

在继续之前,知道 KNN 可用于分类和回归问题是很重要的。我们将首先理解它是如何解决分类问题的,从而使可视化回归变得更容易。

## KNN 分类器

我们将要使用的数据是 [*乳腺癌威斯康星(诊断)数据集*](https://www.kaggle.com/uciml/breast-cancer-wisconsin-data?select=data.csv) *。*有 30 个属性对应于为考虑中的细胞核计算的实值特征。该数据中共有 569 个样本,其中 357 个被归类为*‘良性’*(无害),其余 212 个被归类为*‘恶性’*(有害)。

*诊断*栏分别包含恶性和良性癌症的“M”或“B”值。为了更好的分析,我将这些值分别改为 1 和 0。

此外,为了这篇文章,我将只使用数据中的两个属性→“平均半径”和“平均纹理”。这将有助于我们理解 KNN 划定的决策界限。下面是最终数据的样子(洗牌后):

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7affb5c44ad1cb4f52e2ee046ed2865b.png)

让我们给 KNN 编码:

Defining X and y

X = data.drop('diagnosis',axis=1)
y = data.diagnosis# Splitting data into train and test
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.25,random_state=42)# Importing and fitting KNN classifier for k=3
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train,y_train)# Predicting results using Test data set
pred = knn.predict(X_test)
from sklearn.metrics import accuracy_score
accuracy_score(pred,y_test)


上面的代码应该会给你一个稍微不同的输出。

0.8601398601398601


刚刚发生了什么?当我们在训练数据上训练 KNN 时,它对每个数据样本采取以下步骤:

1.  借助欧几里得方法计算数据样本和其他样本之间的距离。
2.  按升序排列这些距离值。
3.  从排序的距离中选择前 K 个值。
4.  根据上述 K 值中最常见的类别将类别分配给样本。

让我们想象一下 KNN 是如何在训练数据集上画出一个决策边界的,以及这个边界是如何被用来对测试数据集进行分类的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/53f0723706c6370e02e2ca365032d3c5.png)

K=3 时的 KNN 分类。图片由 [Sangeet Aggarwal](https://medium.com/u/db3258338f2f?source=post_page-----94395f445221--------------------------------)

训练准确率为 93%,测试准确率为 86%,我们的模型在这里可能显示出过度拟合。为什么这样

当 K 值或邻域数太低时,模型仅选取最接近数据样本的值,从而形成如上所示的非常复杂的决策边界。这种模型无法在测试数据集上很好地概括,从而显示出较差的结果。

这个问题可以通过调整参数 *n_neighbors* 的值来解决。*随着我们增加邻居的数量,模型开始很好地泛化,但是增加太多的值会再次降低性能。*

因此,找到 K 的最佳值很重要,这样模型就能够在测试数据集上很好地分类。让我们观察训练,并随着邻居数量的增加测试精确度。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/a34a6a9c09b49f761e107ae649fc1da4.png)

在 k=11 时观察到最佳结果

上面的结果可以通过下面的图得到最好的可视化。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/f30b1bee8bb3eca8ebd40ae66f7a63e2.png)

图片由 [Sangeet Aggarwal](https://medium.com/u/db3258338f2f?source=post_page-----94395f445221--------------------------------)

该图显示了测试精度在某一点上的总体上升趋势,之后精度再次开始下降。这是最近邻的最佳数量,在本例中为 11,测试准确率为 90%。

让我们再次画出 k=11 的决策边界,看看它是什么样子。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/6a4cce0032ed548f8acceea80a9bdb6e.png)

K=11 时的 KNN 分类。图片由 [Sangeet Aggarwal](https://medium.com/u/db3258338f2f?source=post_page-----94395f445221--------------------------------) 提供

我们通过微调邻居的数量来改善结果。此外,KNN 的决策边界现在平滑得多,能够很好地概括测试数据。

现在让我们来理解 KNN 是如何用于回归的。

## KNN 回归量

*KNN 分类器返回最近 K 个邻居的模式,而 KNN 回归器返回最近 K 个邻居的平均值。*

我们将用[广告数据](http://faculty.marshall.usc.edu/gareth-james/ISL/data.html)来理解 KNN 的回归。下面是电视预算和销量的前几排。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e3678ef90907e7340b2c6ee7b824709c.png)

Defining X and Y

X_ad = ad.TV.values.reshape(-1,1)
y_ad = ad.sales# Splitting data into train and test
train_x, test_x, train_y, test_y = train_test_split(X_ad, y_ad, test_size=0.25, random_state=42)# Running KNN for various values of n_neighbors and storing results
knn_r_acc = []for i in range(1,17,1):
knn = KNeighborsRegressor(n_neighbors=i)
knn.fit(train_x,train_y) test_score = knn.score(test_x,test_y)
train_score = knn.score(train_x,train_y) knn_r_acc.append((i, test_score ,train_score))df = pd.DataFrame(knn_r_acc, columns=['K','Test Score','Train Score'])
print(df)


上面的代码将针对不同的 K 值(从 1 到 16)运行 KNN,并将训练和测试分数存储在一个数据帧中。让我们看看当我们增加 *n_neighbors(或 K)* 的值时,这些分数是如何变化的。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/181afe80e57209daa20df81a858f1528.png)

K=4 时的最佳结果

在 K=1 时,KNN 倾向于紧密跟随训练数据,因此显示出高的训练分数。但相比较而言,测试分数相当低,从而说明过度拟合。

让我们想象一下 KNN 如何绘制不同 k 值的回归路径

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8c6851330c0a8211d0e272a2d7beb4ef.png)

**左:**用 KNN 回归器训练数据集**右:**用相同的 KNN 回归器测试数据集。图片由 [Sangeet Aggarwal](https://medium.com/u/db3258338f2f?source=post_page-----94395f445221--------------------------------) 提供

随着 K 的增加,KNN 将数据拟合为更平滑的曲线。这是因为 K 值越高,考虑的数据就越多,从而降低了模型的整体复杂性和灵活性。

正如我们之前看到的,增加 K 值会将分数提高到一定程度,之后分数会再次下降。这一点可以通过下面的情节更好的理解。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/241e2b30abce85e2fbfb9ed76b15a5db.png)

图片由 [Sangeet Aggarwal](https://medium.com/u/db3258338f2f?source=post_page-----94395f445221--------------------------------) 提供

正如我们在该图中看到的,该模型在 K=4 时产生最佳结果。我用 R 来评估这个模型,这是我们能得到的最好的结果。这是因为我们的数据集太小而且太分散。

关于 KNN,需要了解的其他几点很重要:

*   KNN 分类器没有任何专门的训练阶段,因为它使用所有的训练样本进行分类,并简单地将结果存储在内存中。
*   KNN 是一种非参数算法,因为它没有对训练数据做任何假设。这对于具有非线性数据的问题非常有用。
*   如果数据非常大,KNN 在时间和存储方面的计算都很昂贵,因为 KNN 必须存储训练数据才能工作。其他监督学习模型一般不会出现这种情况。
*   KNN 对数据的规模非常敏感,因为它依赖于计算距离。对于比例较高的要素,计算出的距离可能会很大,结果可能会很差。因此,建议在运行 KNN 之前缩放数据。

这个帖子到此为止。我希望你在学习 KNN 的时候过得愉快。欲知详情,敬请关注。

# 举例说明 Python 中的 k-最近邻算法

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-algorithm-in-python-by-example-79abc37a4443?source=collection_archive---------17----------------------->

## 通过代码示例介绍 K-最近邻

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/39999ce33da0f053efea33b515568973.png)

图片由李可莹通过 [Unsplash](https://unsplash.com/photos/o5GGlwHfff8) 提供

## k-最近邻(KNN)

KNN 是一种受监督的机器学习算法,可用于解决分类和回归问题。KNN 的原理是一个数据点的值或类别由该值周围的数据点决定。

要理解 KNN 分类算法,最好通过例子来说明。本教程将演示如何在 Python 中使用 KNN 来解决自己的分类问题。与这个例子相对应的 Jupyter 笔记本可以在[这里](https://github.com/StephenFordham/KNN/blob/master/KNN_practise.ipynb)找到,如果你想跟随的话。

预测算法计算从未知点 x 到数据中所有点的距离。然后,数据中的点按离 x 的距离递增进行排序。通过从“K”个最近点预测多数标注来进行预测。

选择一个 K 会影响一个新点将被分配到什么类。

在下面的示例中,选择 K 值 2 会将未知点(黑色圆圈)分配给类别 2。但是,如果 K 值为 7,未知点将被分配到类别 1。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/30f9f1288e5353ac19e2cbcd8c281c53.png)

作者个人制作,[斯蒂芬·福特汉姆](https://medium.com/@stephenfordham)

## 创建假数据集

首先,我们导入我们需要的库,然后使用 sklearn 的 makeblobs 函数创建一个假数据集。我们可以传入样本数量、数据集中的特征、数据将落入多少个中心或类中,以及最终这些聚类的标准偏差。为了这个 Jupyter 笔记本的多次运行之间的一致性,我将整数 101 赋给了 random_state 参数。

注意,首先,我们将有一个大的集群标准偏差。这将在分类中引入方差,我们可以通过专门选择最佳 K 值来对其进行改进。这可以通过肘法来实现。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2b3c28588de01b14ed63aba69394a09e.png)

sklearn 的 makeblobs 函数返回一个 2 元素元组。我们可以使用 pd 创建我们特征的数据框架。DataFrame,并传入对应于特征数据的第一个元组的索引。数据元组的第二个元素对应于特征的标签。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ef7c8afa1a024cbbb789c63b7f99e8a8.png)

我们现在可以通过从 Sklearn.preprocessing 导入 MinMaxScaler 来缩放数据。与其他机器学习算法不同,在执行我们的训练测试分割之前,我们在*上拟合和转换所有*训练数据。

## 预测算法和优化

为了在代码中实现预测,我们首先从 sklearn.neighbors 导入 KNeighborsClassifier,然后实例化 KNeighborsClassifier 的一个实例,将参数 1 传递给 n_neighbors,并将其赋给变量 knn。传递给 n_neighbors 的值表示 K 值。

然后,在进行预测之前,我们通过调用 KNeighborsClassifier 对象上的 predict 方法来拟合定型数据。

现在我们可以使用分类报告和混淆矩阵来评估预测的准确性。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/3d0a2567b79e5a66085417a2f64510f7.png)

这些指标表明准确性已经非常好了。这可能是因为我们用 makeblobs 制作了数据集,并特别要求了 2 个中心。然而,我们确实*故意*为集群标准偏差设置了一个大值,以引入方差。这导致了我们数据集中 4 个点的错误分类。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e1fe014f7a8f9d675cb2fbd05a21a943.png)

## 提高数据准确性

我们可以尝试通过修改邻居的数量来提高结果的准确性。这可以通过肘法来实现。

我们首先遍历 40 个邻居值,用这个数量的邻居实例化一个 KNeighborsClassifier 对象。然后,我们可以将训练数据拟合到此 KNN 模型,获得预测,并追加预测 pred_i 和正确值 y_test 之间的平均值。

如果 pred_i 和 y_test 在数组中不匹配,则返回值为 1 的真值。这个数字越高,分类就越不准确。

错误率的较低值将对应于性能更好的模型。

这些结果可以用 x 轴上的 I 值范围对 y 轴上的误差率来绘制。

现在我们可以选择返回的 K 的最低值,最低的错误率。在这里,我们可以选择 5。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e39ed2668007db0adbd337d367795dc5.png)

现在,我们可以再次使用混淆矩阵和分类报告重新运行准确性评估,以查看我们是否能够更准确地对 4 个未对齐点进行分类。我们有所改进,从 4 个错误分类点减少到 2 个。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/640f7c648ba0ba8ca6656bcffba10b49.png)

## 针对新数据点的培训

我们现在可以使用原始数据创建一个数据点。首先,我们创建两个数据帧;一个包含要素,一个包含标注,将它们连接成单个数据帧,并选择第一行作为预测标注的数据点。我们必须记住*缩放*数据点,因为模型是根据缩放后的数据训练的。

预测表明,数据点 1 将给出标签 0,这与原始数据集点相匹配,通过调用 df.head(1)进行验证。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/86c5949bd03d54bd196547a7c26f1d4f.png)

## 摘要

KNN 很简单,训练也很简单,而且很容易添加更多的数据。此外,参数很少。在本教程中,我只在 KNeighborsClassifier 类的调用中包含了 K 参数(n_neighbors)。

然而,KNNs 也有缺点,包括高预测成本,这对于大型数据集来说更糟。KNN 对异常值也很敏感,因为异常值对最近的点有影响。此外,它们不适用于高维数据集,分类特征也不太适用。随着数据越来越多,KNN 算法变得越来越慢,因为模型需要存储所有这些数据点,以便确定它们之间的距离。

这个例子是人为设计的,主要是为了理解如何用 Python 编写 KNN。我特意使用 makeblobs 制作了数据集,以说明这个函数作为练习 KNNs 的工具是多么有用。如果你想得到我所有的 Jupyter 笔记本,可以在这里找到。

尝试将聚类标准差更改为更高的值,然后尝试使用错误率最低的 K 值来优化 KNN 分类。

此外,KNNs 可以与一起使用来对多个类进行分类。通过增加传递给中心的值,可以在 makeblobs 函数调用中进一步改变这一点。这些参数可以很容易地调整,将有助于理解 KNNs,所以我们可以有效地将它们纳入我们的分析。

快乐分类。

# k 手动最近邻:

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-by-hand-a-computer-science-exercise-for-the-data-scientist-72b5821c8941?source=collection_archive---------36----------------------->

## 打开“黑匣子”并理解其中的算法

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/9a964b0c994215a1b485e6c99491c0de.png)

数据科学家有时谈论数据科学的“黑盒”方法;也就是说,当你理解了不同机器学习算法的用例,以及如何在不理解算法在表面下如何工作的情况下插入数据。但是*算法*仅仅是——它们是“算法”——一组用于解决特定类型问题的指令。

在这篇博客文章中,我将向您展示如何手工构建一个简单的机器学习算法。我们将要构建的模型是 knarestneighborsclassifier(KNN classifier)。

## 什么是 KNNClassifier,它是如何工作的?

KNNClassifier 是我用过的第一个机器学习算法。它很简单,但是非常强大。该算法被认为是“懒惰”的,因为它本身并不*学习*;该算法只是记忆数据,而不是在训练过程中学习数据中的模式,并根据这些模式对新数据进行预测。然后,该模型将数据与其自身相关联,并找到每个数据点之间的“[欧几里德距离](https://en.wikipedia.org/wiki/Euclidean_geometry#:~:text=Euclidean%20geometry%20is%20a%20mathematical,propositions%20(theorems)%20from%20these.)”(本质上是直线距离)。当添加新数据时,算法会根据我们指定的“最近邻”数据点的数量来预测该数据的目标。

举个简单的例子,假设一个数据集有两三个特征。将这些数据映射到 2D 或 3D 图形上,并找到每个点之间的距离非常简单——只要沿着轴,在图形上找到适当的点时添加数据点。然后,当我们向模型中输入新数据时,该算法会找到与新数据最近的 k 个数据点,并预测该目标是邻居中最常出现的目标。

如果这仍然令人困惑,不要害怕!一旦我们将它应用到真实的数据集,它将变得有意义。

**泰坦尼克号数据集**

*如果您想了解这个示例,只需在这里* *下载数据* [*,并将 csv 文件添加到与 Python 笔记本相同的文件夹中。(参见源代码*](https://web.stanford.edu/class/archive/cs/cs109/cs109.1166/stuff/titanic.csv) [*此处*](https://github.com/AndrewSLowe/KNN_from_Scratch) *)*

由于 KNNClassifier 是一个分类模型,我们需要一个数据集来预测一些离散的目标(与回归模型相反,回归模型预测连续统上的值)。在这个练习中,我们将使用可能是学习分类模型最流行的数据集 Titanic 数据集。我们试图预测的是,根据我们对一个人的一些特征的了解,这个人是否能在泰坦尼克号沉没后幸存下来。

下面是我们需要的导入和加载数据的代码:

如果我们接着运行`df.head()`,我们可以观察前 5 行,并看到我们正在处理的特性:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/096d51fb9edeaeab6cd37fcd5a33be52.png)

如果您不熟悉数据集,请花点时间尝试并预测哪些特征与存活率最相关。

## **预处理和列车测试分割**

`survived`列——最左边的列——是我们试图预测的(也称为 y 变量或“目标”)。其余的特征是我们用来预测目标的。我们现在需要做一些预处理工作,以最好地建立我们的模型来预测。由于这篇文章的重点是机器学习算法,我们将尽可能简单地进行预处理。

我们将首先删除“姓名”和“费用”列,因为“姓名”并不能决定某人是否幸存,而“费用”与“等级”密切相关。然后我们将使用`pd.get_dummies()`将“性别”列一次性编码成两列,男性和女性。代码如下所示:

现在,我们的数据已经处理完毕,我们可以执行训练测试分割。这是监督机器学习模型的标准——其思想是,我们在训练数据上训练算法,并通过在我们的测试数据上评估它来测试模型的性能。幸运的是,scikit-learn 库有一个内置模块可以轻松地执行分割:

**带 Scikit 的 KNN classifier-Learn**

首先让我们看看如何使用 scikit-learn 来编码这个问题。由于所有的预处理和训练-测试-拆分都已完成,因此根据数据训练模型并做出预测只需三行代码。我们将首先制作一个模型对象,然后使用`.fit`方法根据数据训练模型,使用`.predict`方法根据模型从训练数据中学到的知识对测试集中的每个值进行预测:

输出显示了测试数据中表示的每个人的生存状态预测。“1”表示模型预测此人幸存,“0”表示模型预测此人未能幸存:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/74ece50420de97a8d855b7cd43f4de8b.png)

**手动 KNN 算法**

既然我们已经使用 sklearn 库对测试集进行了预测,并且对幕后发生的事情有了基本的了解,那么让我们构建自己的 KNNClassifier 自制版本。我们将使用面向对象的编程来构建模型。(如果您对类和 OOP 不熟悉,请务必关注我的一系列博客文章,在这些文章中,我们将学习 OOP 并使用类来构建一个基于文本的冒险游戏!)

我们首先需要的是辅助函数。这些函数存在于类的外部,我们在类内部调用它们来执行一些操作。下面是一个自制的平方根函数和欧几里德距离公式:

如上所述,欧几里德距离本质上是两条数据之间的直线。该函数只是简单地将两行之间的每一列的值之间的距离相加,然后求出该和的平方根。

接下来我们将编写 KNNHomebrew 函数。该类中的方法模拟了 scikit-learn knnclassifier 模型完成的操作。我们有一个`model_fit()`方法,一个`model_predict`方法,它对一个新的数据点进行预测,还有一个`model_predict_all`方法,它对一组新的数据进行预测。文本注释中解释了每行代码的具体功能。

现在是关键时刻了!让我们看看是否可以像调用 scikit-learn 模型一样调用我们的模型:

输出应该如下所示:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/2f5b7bf73c864e9214162411583e0047.png)

*如果你继续下去,你会注意到 hombrew 模型比 scikit-learn 模型慢得多——可怜可怜我吧,我只是个初级开发人员。我可能会写一篇后续的博客文章,在那里我优化了算法,并使时间低于 1 秒,但现在,让我们看看我们的模型与 scikit-learn 模型的性能相比如何。*

## **比较型号**

现在是时候对比一下车型的性能了。首先,我们需要找到基线。在运行任何机器学习模型之前,这是最佳实践。对于分类问题,问题是,如果我们猜测所有新数据的主要类别,我们猜对的频率是多少?

这是一个非常简单的计算,我们需要做的就是将训练集中多数类的出现次数除以数据集中的观察总数。多数类为 0 或“未存活”。假设我们的训练数据是一个真正的随机样本,在我们进行任何机器学习或预测分析之前,我们应该用任何新数据来预测这个类。由于我们的准确率是 61.24%,我们可以假设这个天真的预测有 61.24%是正确的。

现在让我们看看我们的模型和 scikit-learn 模型是如何比较的。下面是查找 Scikit-Learn 模型和我们的 KNNHomebrew 模型的准确性的代码:

1.  Scikit-learn: `model.score(X_test, y_test)`
2.  KNNHomebrew: `knnHB.model_accuracy(X_test, y_test)`

结果是:

1.  科学知识-学习:75.84%
2.  KNNHomebrew: 72.47%

因此,在其当前的形式下,似乎 scikit-learn 模型将比我们的 KNNHomebrew 模型多正确预测新数据的生存大约 3.5%…失败:(

开玩笑!这个练习的目的不是要打败 Python 中最流行的机器学习库之一,而是要了解其背后的东西。

## 敬请关注。

揭示机器学习算法的所谓“黑盒”中的魔力是有趣且极具教育意义的。我计划在其他预测模型上发表更多这样的博文,所以请保持警惕!

# k-最近邻分类从零开始

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-classification-from-scratch-6b31751bed9b?source=collection_archive---------58----------------------->

## 没有第三方库的 R 中的分步示例

这篇文章旨在探索一步一步的方法来创建一个**K-最近邻算法**而不需要任何第三方库的帮助。在实践中,这种算法应该足够有用,每当我们已经进行了分类(在这种情况下,颜色)时,我们就可以对我们的数据进行分类,这将作为查找邻居的起点。

在这篇文章中,我们将使用一个特定的数据集,它可以在这里下载[。它包含 539 个二维数据点,每个数据点都有特定的颜色分类。我们的目标是将他们分成两组(训练和测试),并根据我们的算法建议尝试猜测我们的测试样本颜色。](https://www.kaggle.com/tenaciousjay/knn-fromscratch?select=RGB.csv)

# 训练和测试样本生成

我们将创建两个不同的样品组:

*   **训练集:**这将包含我们 75%的工作数据,随机选择。这个集合将用于生成我们的模型。
*   **测试集:**我们剩余的 25%工作数据将用于测试我们模型的样本外准确性。一旦我们做出了 25%的预测,我们将通过比较预测值和实际值来检查“*正确分类的百分比*”。

# Load Data
library(readr)
RGB <- as.data.frame(read_csv("RGB.csv"))
RGB\(x <- **as.numeric**(RGB\)x)
RGB\(y <- **as.numeric**(RGB\)y)
print("Working data ready")# Training Dataset
smp_siz = floor(0.75nrow(RGB))
train_ind = sample(seq_len(nrow(RGB)),size = smp_siz)
train =RGB[train_ind,]
# Testting Dataset*
test=RGB[-train_ind,]
OriginalTest <- test
paste("Training and test sets done")


# 培训用数据

我们可以看到,我们的训练数据根据颜色分为 3 类。

# We plot test colored datapoints
library(ggplot2)
colsdot <- c("Blue" = "blue", "Red" = "darkred", "Green" = "darkgreen")
ggplot() +
geom_tile(data=train,mapping=aes(x, y), alpha=0) +
##Ad tiles according to probabilities
##add points
geom_point(data=train,mapping=aes(x,y, colour=Class),size=3 ) +
scale_color_manual(values=colsdot) +
#add the labels to the plots
xlab('X') + ylab('Y') + ggtitle('Train Data')+
#remove grey border from the tile
scale_x_continuous(expand=c(0,.05))+scale_y_continuous(expand=c(0,.05))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1f5811bda4017d0d36c227491604191f.png)

训练数据:我们可以观察 3 个类别(蓝色、绿色和红色)

# 测试数据

即使我们知道测试数据的原始颜色分类,我们也将尝试创建一个模型,该模型可以仅根据有根据的猜测来猜测它的颜色。为此,我们将删除它们的原始颜色,保存它们只是为了测试的目的;一旦我们的模型做出预测,我们将能够通过比较原始预测和我们的预测来计算我们的**模型精度**。

# We plot test colored datapoints
colsdot <- c("Blue" = "blue", "Red" = "darkred", "Green" = "darkgreen")
ggplot() +
geom_tile(data=test,mapping=aes(x, y), alpha=0) +
##Ad tiles according to probabilities
##add points
geom_point(data=test,mapping=aes(x,y),size=3 ) +
scale_color_manual(values=colsdot) +
#add the labels to the plots
xlab('X') + ylab('Y') + ggtitle('Test Data')+
#remove grey border from the tile
scale_x_continuous(expand=c(0,.05))+scale_y_continuous(expand=c(0,.05))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/1f51b7ad9a50d74b748217e32803b0d2.png)

测试数据:我们删除并故意忘记了它的分类颜色,以创建一个能够猜测它们的模型。

# k-最近邻算法

下面是实现该算法的分步示例。我们想要实现的是,对于上面每个选定的灰点(我们的测试值),据称我们不知道它们的实际颜色,从我们的训练值中找到最近的邻居或最近的彩色数据点,并分配与此相同的颜色。

**具体来说,我们需要:**

*   **归一化数据:**即使在这种情况下不需要,因为所有值都是相同的标度(0 到 1 之间的小数),建议归一化,以便有一个“标准距离度量”。
*   **定义我们如何度量距离:**我们可以将这个二维数据集中两点之间的距离定义为它们之间的欧氏距离。我们将计算 L1(绝对差之和)和 L2(平方差之和)距离,尽管最终结果将使用 L2 计算,因为它比 L1 更不宽容。
*   **计算距离:**我们需要计算每个测试数据点和训练数据集中每个值之间的距离。标准化在这里是至关重要的,因为在身体结构的情况下,体重(1 公斤)和身高(1 米)的距离是不可比的。我们可以预见到公斤比米的偏差更大,导致总距离不正确。
*   **排序距离:**一旦我们计算出每个测试点和训练点之间的距离,我们就需要按降序对它们进行排序。
*   **选择前 K 个最近的邻居:**我们将选择前 K 个最近的训练数据点,以检查它们属于哪个类别(颜色),以便将该类别分配给我们的测试点。由于我们可能使用多个邻居,我们可能会有多个类别,在这种情况下,我们应该计算一个概率。

# We define a function for prediction
KnnL2Prediction <- function(x,y,K) {

# Train data
Train <- train
# This matrix will contain all X,Y values that we want test.
Test <- data.frame(X=x,Y=y)

# Data normalization
Test\(X <- (Test\)X - min(Train\(x))/(**min**(Train\)x) - max(Train\(x)) Test\)Y <- (Test\(Y - **min**(Train\)y))/(min(Train\(y) - **max**(Train\)y))
Train\(x <- (Train\)x - min(Train\(x))/(**min**(Train\)x) - max(Train\(x)) Train\)y <- (Train\(y - **min**(Train\)y))/(min(Train\(y) - **max**(Train\)y)) # We will calculate L1 and L2 distances between Test and Train values.
VarNum <- ncol(Train)-1
L1 <- 0
L2 <- 0
for (i in 1:VarNum) {
L1 <- L1 + (Train[,i] - Test[,i])
L2 <- L2 + (Train[,i] - Test[,i])^2
}

# We will use L2 Distance
L2 <- sqrt(L2)

# We add labels to distances and sort
Result <- data.frame(Label=Train$Class,L1=L1,L2=L2)

# We sort data based on score
ResultL1 <-Result[order(Result\(L1),] ResultL2 <-Result[order(Result\)L2),]

# Return Table of Possible classifications
a <- prop.table(table(head(ResultL2\(Label,K))) b <- as.data.frame(a) **return**(**as.character**(b\)Var1[b\(Freq == **max**(b\)Freq)]))
}


# 使用交叉验证找到正确的 K 参数

为此,我们将使用一种叫做“交叉验证”的方法。这意味着,我们将在训练数据本身中进行预测,并针对数据的许多不同折叠或排列,对许多不同的 K 值进行迭代。一旦我们完成,我们将平均我们的结果,并为我们的“K-最近邻”算法获得最佳 K。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/24954c1fd3983d263182e3ad85d28b40.png)

# We will use 5 folds
FoldSize = floor(0.2nrow(train)) # Fold1
piece1 = sample(seq_len(nrow(train)),size = FoldSize )
Fold1 = train[piece1,]
rest = train[-piece1,] # Fold2
piece2 = sample(seq_len(nrow(rest)),size = FoldSize)
Fold2 = rest[piece2,]
rest = rest[-piece2,] # Fold3
piece3 = sample(seq_len(nrow(rest)),size = FoldSize)
Fold3 = rest[piece3,]
rest = rest[-piece3,] # Fold4
piece4 = sample(seq_len(nrow(rest)),size = FoldSize)
Fold4 = rest[piece4,]
rest = rest[-piece4,] # Fold5
Fold5 <- rest
# We make folds*
Split1_Test <- rbind(Fold1,Fold2,Fold3,Fold4)
Split1_Train <- Fold5Split2_Test <- rbind(Fold1,Fold2,Fold3,Fold5)
Split2_Train <- Fold4Split3_Test <- rbind(Fold1,Fold2,Fold4,Fold5)
Split3_Train <- Fold3Split4_Test <- rbind(Fold1,Fold3,Fold4,Fold5)
Split4_Train <- Fold2Split5_Test <- rbind(Fold2,Fold3,Fold4,Fold5)
Split5_Train <- Fold1# We select best K
OptimumK <- data.frame(K=NA,Accuracy=NA,Fold=NA)
results <- trainfor (i in 1:5) {
if(i == 1) {
train <- Split1_Train
test <- Split1_Test
} else if(i == 2) {
train <- Split2_Train
test <- Split2_Test
} else if(i == 3) {
train <- Split3_Train
test <- Split3_Test
} else if(i == 4) {
train <- Split4_Train
test <- Split4_Test
} else if(i == 5) {
train <- Split5_Train
test <- Split5_Test
}
for(j in 1:20) {
results\(Prediction <- mapply(KnnL2Prediction, results\)x, results\(y,j) *# We calculate accuracy* results\)Match <- ifelse(results\(Class == results\)Prediction, 1, 0)
Accuracy <- round(sum(results$Match)/nrow(results),4)
OptimumK <- rbind(OptimumK,data.frame(K=j,Accuracy=Accuracy,Fold=paste("Fold",i)))

}

}OptimumK <- OptimumK [-1,]
MeanK <- aggregate(Accuracy ~ K, OptimumK, mean)
ggplot() +
geom_point(data=OptimumK,mapping=aes(K,Accuracy, colour=Fold),size=3 ) +
geom_line(aes(K, Accuracy, colour="Moving Average"), linetype="twodash", MeanK) +
scale_x_continuous(breaks=seq(1, max(OptimumK$K), 1))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/d443713b90229d5f9c956420ff898698.png)

20 个不同 K 值的 5 倍

如上图所示,我们可以观察到,对于所有褶皱,我们算法的预测精度在 88%-95%的范围内,并且从 K=3 开始下降。我们可以在 K=1 (3 也是一个很好的选择)上观察到最高的一致精度结果。

# 基于前 1 个最近邻进行预测。

## 模型精度

# Predictions over our Test sample
test <- OriginalTest
K <- 1
test\(Prediction <- mapply(KnnL2Prediction, test\)x, test\(y,K) head(test,10)*# We calculate accuracy* test\)Match <- ifelse(test\(Class == test\)Prediction, 1, 0)
Accuracy <- round(sum(test$Match)/nrow(test),4)
print(paste("Accuracy of ",Accuracy*100,"%",sep=""))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/15fc38aa7a94d8552b264ad11b3c8169.png)

使用 K=1 的前 10 个预测

从上面的结果可以看出,我们有望在 93%的时间里“猜出正确的类别或颜色”。

## **原始颜色**

下面我们可以观察测试样本的原始颜色或类别。

ggplot() +
geom_tile(data=test,mapping=aes(x, y), alpha=0) +
geom_point(data=test,mapping=aes(x,y,colour=Class),size=3 ) +
scale_color_manual(values=colsdot) +
xlab('X') + ylab('Y') + ggtitle('Test Data')+
scale_x_continuous(expand=c(0,.05))+scale_y_continuous(expand=c(0,.05))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8dd8a17a02ba29e122c4b81a6dd7d8e8.png)

这是我们测试样品的原始颜色/等级

## **预测颜色**

使用我们的算法,我们为最初无色的样本数据集获得以下颜色。

ggplot() +
geom_tile(data=test,mapping=aes(x, y), alpha=0) +
geom_point(data=test,mapping=aes(x,y,colour=Prediction),size=3 ) +
scale_color_manual(values=colsdot) +
xlab('X') + ylab('Y') + ggtitle('Test Data')+
scale_x_continuous(expand=c(0,.05))+scale_y_continuous(expand=c(0,.05))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/e14c151383df093682dc6d4cd861bdef.png)

在红圈里,我们标出了不同或不正确的分类。

从上面的图中可以看出,尽管我们的算法对大多数数据点进行了正确的分类,但其中一些数据点还是失败了(用红色标记)。

## **决策限制**

最后,我们可以可视化我们在原始测试数据集上的“决策限制”。这为我们的模型如何对数据进行分类以及其分类空间的限制提供了一个极好的可视化近似值。

简而言之,我们将在原始数据集的范围内模拟 160,000 个数据点(400x400 矩阵),当稍后绘制时,将使用颜色填充大部分空白空间。这将帮助我们详细地表达我们的模型将如何在其学习的颜色类别中分类这个 2D 空间。我们生成的点数越多,我们的“分辨率”就越好,就像电视上的像素一样。

# We calculate background colors
x_coord = seq(min(train[,1]) - 0.02,max(train[,1]) + 0.02,length.out = 40)
y_coord = seq(min(train[,2]) - 0.02,max(train[,2]) + 0.02, length.out = 40)
coord = expand.grid(x = x_coord, y = y_coord)
coord[['prob']] = mapply(KnnL2Prediction, coord\(x, coord\)y,K)# We calculate predictions and plot decition area
colsdot <- c("Blue" = "blue", "Red" = "darkred", "Green" = "darkgreen")
colsfill <- c("Blue" = "#aaaaff", "Red" = "#ffaaaa", "Green" = "#aaffaa")
ggplot() +
geom_tile(data=coord,mapping=aes(x, y, fill=prob), alpha=0.8) +
geom_point(data=test,mapping=aes(x,y, colour=Class),size=3 ) +
scale_color_manual(values=colsdot) +
scale_fill_manual(values=colsfill) +
xlab('X') + ylab('Y') + ggtitle('Decision Limits')+
scale_x_continuous(expand=c(0,0))+scale_y_continuous(expand=c(0,0))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/7a5191532cb4fc7ce5fb39fe57a77a68.png)

如上所述,彩色区域代表我们的算法将定义为“彩色数据点”的区域。显而易见,为什么它未能对其中一些进行正确分类。

# 最后的想法

k-最近邻是一种简单的算法,似乎可以提供很好的结果。尽管在这里我们可以用肉眼对物品进行分类,但是这个模型也适用于我们不能仅仅用肉眼观察的高维情况。为了实现这一点,我们需要一个具有现有分类的训练数据集,我们稍后将使用它来对周围的数据进行分类,这意味着它是一个由 T2 监督的机器学习算法。

遗憾的是,这种方法在一些情况下存在困难,例如在存在无法用简单的直线距离表示的复杂模式的情况下,比如在放射状或嵌套式集群的情况下。它还存在性能问题,因为对于新数据点的每个分类,我们需要将其与训练数据集中的每个点进行比较,这是资源和时间密集型的,因为它需要复制和迭代整个集合。

# 用 NumPy 从零开始进行 k-最近邻分类

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-classification-from-scratch-with-numpy-cb222ecfeac1?source=collection_archive---------6----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/8e296977a24d25424160713982e3f1a6.png)

妮娜·斯特雷尔在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 拍摄的照片

W 欢迎来到另一个用 NumPy 从零开始实现机器学习算法的帖子。在这篇文章中,我将实现 K 近邻(KNN),这是一种机器学习算法,可用于分类和回归的目的。它属于监督学习算法的范畴,为看不见的观察预测目标值。换句话说,它对带标签的数据集进行操作,并预测测试数据的类(分类)或数值(回归)。

正如我在其他帖子中提到的,我不会使用已经实现的 k-nearest neighborhood 算法,我将只使用 NumPy 实现它,并将使用其他库进行数据可视化,并创建和使用数据集。

考虑到有很多有用的资源可以解释 KNN 的基本原理,我想马上进入编码部分。我们继续吧!

我们从导入将在整个实现中使用的库和函数开始:

*   ***numpy*** :显然,它将用于多维数组的数值计算,因为我们大量处理高维向量。
*   ***make _ class ification***:我们将使用它来创建我们自己的分类数据集。我们可以决定需要多少个类和特征,是否需要对样本进行聚类,等等。

在 KNN 算法中,我们需要一个函数来计算训练数据点和我们想要分类的数据之间的距离。这里,我选择了欧几里德距离,因为它是机器学习应用中广泛使用的距离。可以尝试使用其他距离度量,如曼哈顿距离、切比雪夫距离等。

当我们考虑 KNN 的实际情况时,我们会尝试找到邻居,即最接近我们想要分类的数据的数据点。数据点是否接近是由我们上面实现的欧几里德距离函数决定的。这里,数据点之间距离的实际值并不重要,相反,我们感兴趣的是这些距离的顺序。

在训练过程之前,我们挑选一个数字作为我们的超参数(k ),并挑选 k 个与我们想要在训练期间分类的数据点最近的邻居。因此,例如,当我们说 5 个最近的邻居时,我们指的是前 5 个最近的数据点。

在上面的 ***kneighbors*** 函数中,我们找到了测试数据集中每个点(我们要分类的数据点)与数据集其余部分(即训练数据)之间的距离。我们将这些距离存储在 ***point_dist*** 中,其中每一行对应于一个测试数据点和所有训练数据之间的距离列表。因此,我们检查每一行,对其进行计数,然后根据距离进行排序。我们枚举每一行的原因是因为我们不想丢失用来计算距离的训练数据点的索引,因为我们稍后将引用它们。

因此, ***sorted_neigh*** 保存了我们的测试数据点的前 k 个最近邻,并且根据它们的欧几里德距离对它们进行排序。然后,我们从 ***sorted_neigh*** 中提取索引和距离值,并返回它们。

在找到 k-最近邻后,我们尝试预测我们的测试数据点所属的类。这里,我们有 k 个邻居,每个邻居都有一票来决定类别标签。然而,投票机制可以根据所选择的标准而变化。这里,在上面的**预测**函数中,如果**权重**被选择为**统一**,这意味着每个邻居在决定类标签时具有相等的投票(权重),而与它们的距离无关。

假设我们的测试数据点有 5 个最近邻,其中 3 个属于 A 类,2 个属于 b 类。我们不考虑邻居的距离,并得出测试数据点属于 A 类的结论,因为大多数邻居都属于 A 类。但是,如果选择**权重**作为**距离**,那么这意味着邻居的距离确实很重要。因此,最接近测试数据点的邻居具有与其距离的倒数成比例的最大权重(投票)。因此,关于前述示例,如果属于类别 A 的那 2 个点比其他 3 个点更接近测试数据点,则仅这一事实就可以在决定数据点的类别标签中起很大作用。

在**预测**功能中,如果**权重**是**均匀的**,那么预测数据点的标签是相当容易的。首先,我们获得邻居的索引,然后使用这些索引从训练数据集中获得它们对应的类别标签。 **neighbors** 中的每一行对应于每个测试数据点所具有的一组邻居。然后,我们使用 nump **y 的** **bincount** 函数找到类标签的出现,并获得对应于预测的类标签的最大出现的索引。

如果我们选择**权重**作为**距离**,事情会变得有点混乱。在这种情况下,我们找到相邻距离的平均倒数,并计算每个测试数据点的分类概率。

我实现了 **score** 函数,作为一个在分类问题中广泛使用的非常简单的准确性度量。我们只是返回正确分类标签的百分比。这很简单!

现在,是时候创建数据集了,我们将在其上测试我们的 knn 算法。我们利用 **sklearn.dataset** 的 **make_classification** 函数来填充数据集。之后,我们通过减去平均值然后除以标准偏差来标准化每个数据点。

在创建数据集之后,我们为我们的训练阶段实现随机分割,从而获得我们的训练和测试集。

In[104]: kneighbors(X_test)Out[104]: array([[ 85, 405, 370, 63, 694],
[345, 64, 189, 136, 32],
[554, 216, 690, 672, 51],
...,
[560, 323, 99, 418, 295],
[214, 180, 534, 190, 133],
[ 20, 129, 564, 103, 679]])


是时候测试我们的 knn 实现代码了。我们得到了测试数据集的 k 个最近邻。请注意,每一行都与测试集中的每个数据点相关,并且每一行中的元素都对应于测试数据点的邻居的索引。

In[105]: predict(X_test)Out[105]: array([0, 1, 2, 1, 0, 2, 1, 1, 0, 0, 2, 1, 1, 0, 0, 1, 0, 0, 0, 1, 2, 2, ..., 2, 1, 0, 2, 1, 2, 1, 0, 0, 1, 1, 0, 0, 2, 0, 2, 1, 2, 0, 1, 2, 0])


如预期的那样,**预测**函数输出测试数据的预测类标签。

In [106]: score(X_test, y_test)Out[106]: 0.99


看起来我们的实现做得非常好,给出了很高的准确度分数。

# K-最近邻的类实现

在实现了所有必要的函数之后,创建 knn 的类实现就相当容易了。这里唯一新增加的函数是我们类的 **__init__** 函数。

# 将我们的实现与 Sklearn 的 KNeighborsClassifier 进行比较

Out[110]:
Our Implementation Sklearn's Implementation Accuracy 0.955556 0.955556


原来我们自己实现的精度和 **sklearn** 的实现看起来是一样的。这是好消息,对吗?我们在实现方面做得相当不错。

你也可以查看我的 [GitHub 简介](https://github.com/leventbass/k_nearest_neighbors)来沿着 *jupyter 笔记本*阅读代码或者简单地使用代码来实现。

将来,我一定会带来更多的实现。

编码快乐!

**疑问?评论?联系我在**[](http://leventbas92@gmail.com)****,通过**[**GitHub**](https://github.com/leventbass)**或**[**LinkedIn**](https://www.linkedin.com/in/levent-bas/)**。****

# k 近邻计算复杂度

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-computational-complexity-502d2c440d5?source=collection_archive---------7----------------------->

## 了解 kNN 算法的计算成本,并提供案例研究示例

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/26a00a1f0f811efc11f4e2d68757e562.png)

kNN 算法的可视化([来源](https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm#/media/File:KnnClassification.svg))

# **算法介绍**

kNN (k 最近邻)是最简单的最大似然算法之一,通常在入门课程中作为第一批算法之一讲授。它相对简单但非常强大,尽管很少有人花时间去理解它的计算复杂性和实际问题。它可以以相同的复杂度用于分类和回归,因此为了简单起见,我们将考虑 kNN 分类器。

kNN 是一种关联算法-在预测过程中,它会搜索最近的邻居,并将他们的多数投票作为样本的预测类别。训练阶段可能存在,也可能不存在,一般来说,我们有两种可能性:

1.  蛮力方法——计算从新点到训练数据矩阵 X 中每个点的距离,对距离进行排序并取 k 个最近的,然后进行多数投票。不需要单独训练,所以只考虑预测复杂度。
2.  使用数据结构-将 X 中的训练点组织到辅助数据结构中,以实现更快的最近邻查找。这种方法使用额外的空间和时间(用于在训练阶段创建数据结构)来进行更快的预测。

我们关注 Scikit-learn 中实现的方法,这是 Python 中最流行的 ML 库。它支持蛮力,k-d 树和球树数据结构。这些方法相对简单、高效,非常适合 kNN 算法。这些树的构造源于计算几何,而不是机器学习,与我们没有太大关系,所以我将在概念层面上更详细地介绍它。关于这方面的更多细节,请参见文章末尾的链接。

在下面的所有复杂性中,计算距离的时间被省略,因为与算法的其余部分相比,它们在大多数情况下是可以忽略的。此外,我们标记:

*   `n`:训练数据集中的点数
*   `d`:数据维度
*   `k`:我们考虑投票的邻居数量

# **暴力破解法**

**训练时间复杂度:**

**训练空间复杂度:** `O(1)`

**预测时间复杂度:** `O(k * n * d)`

**预测空间复杂度:** `O(1)`

训练阶段在技术上是不存在的,因为所有的计算都是在预测过程中完成的,所以我们在时间和空间上都有`O(1)`。

正如方法名所示,预测阶段是一个简单穷举搜索,在伪代码中是:

Loop through all points k times:
1. Compute the distance between currently classifier sample and
training points, remember the index of the element with the
smallest distance (ignore previously selected points)
2. Add the class at found index to the counterReturn the class with the most votes as a prediction


这是一个嵌套循环结构,其中外部循环执行`k`步,内部循环执行`n`步。第三点是`O(1)`,第四点是`O(# of classes)`,所以他们比较小。此外,我们必须考虑维度的数量`d`,更多的方向意味着更长的向量来计算距离。因此,我们有了`O(n * k * d)`时间复杂度。

至于空间复杂度,我们需要一个小向量来统计每个类的投票数。它几乎总是非常小并且是固定的,所以我们可以把它当作一个`O(1)`空间复杂度。

# **k-d 树方法**

**训练时间复杂度:** `O(d * n * log(n))`

**训练空间复杂度:** `O(d * n)`

**预测时间复杂度:** `O(k * log(n))`

**预测空间复杂度:** `O(1)`

在训练阶段,我们必须构建 k-d 树。这个数据结构拆分了 k 维空间(这里 k 是指空间的 k 维,不要把这个和 k 混淆为最近邻的个数!)并允许更快地搜索最近的点,因为我们“知道在那个空间中去哪里看”。你可能会认为它是 BST 在许多维度上的推广。它使用轴对齐的切割来“切割”空间,将点分成子节点中的组。

构建 k-d 树本身不是机器学习任务,因为它源于计算几何领域,所以我们不会详细讨论这一点,只在概念层面上讨论。时间复杂度通常是`O(d * n * log(n))`,因为插入是`O(log(n))`(类似于常规 BST)并且我们有来自训练数据集的`n`点,每个点有`d`个维度。我假设数据结构的有效实现,即它在`O(n)`中找到最佳分割点(维度中的中值),这对于中位数算法是可能的。空间复杂度是`O(d * n)` —注意,它取决于维度`d`,这是有意义的,因为更多的维度对应更多的空间划分和更大的树(除了同样原因的更大的时间复杂度)。

至于预测阶段,k-d 树结构自然支持“k 最近点邻居查询”操作,这正是我们对于 kNN 所需要的。简单的方法是只查询`k`次,删除每次找到的点——因为查询需要`O(log(n))`,所以总共是`O(k * log(n))`。但是由于 k-d 树已经在构造过程中减少了空间,所以在一次查询之后,我们大概知道在哪里寻找——我们可以搜索该点周围的“环境”。因此,k-d 树的实际实现支持一次查询整个`k`邻居,并且具有复杂度`O(sqrt(n) + k)`,这对于机器学习中非常常见的更大维度要好得多。

以上复杂度为**平均**复杂度,假设 k-d 树平衡。对于不平衡的树,上面假定的`O(log(n))`时间可能降低到`O(n)`,但是如果在树构造期间使用中间值,我们应该总是得到具有大约`O(log(n))`插入/删除/搜索复杂度的树。

# **球树法**

**训练时间复杂度:** `O(d * n * log(n))`

**训练空间复杂度:** `O(d * n)`

**预测时间复杂度:** `O(k * log(n))`

**预测空间复杂度:** `O(1)`

球树算法采用另一种方法来划分训练点所在的空间。与用中间值“切割”划分空间的 k-d 树相反,球树将点分组为组织成树结构的“球”。它们从最大的(根,有所有的点)到最小的(叶,只有几个甚至 1 个点)。它允许快速最近邻查找,因为附近的邻居在相同的或至少接近的“球”中。

在训练阶段,我们只需要构建球树。构造球树的算法有几种,但与 k-d 树(为此称为“k-d 构造算法”)最相似的是`O(d * n * log(n))`,与 k-d 树相同。

由于树构建的相似性,预测阶段的复杂性也与 k-d 树相同。

# **在实践中选择方法**

总结一下复杂度:蛮力是大 O 记法中最慢的,而 k-d 树和球树都有同样低的复杂度。那我们怎么知道用哪一个呢?

为了得到答案,我们必须同时考虑训练和预测时间,这就是为什么我提供了两者。蛮力算法只有一个复杂度,对于预测,`O(k * n)`。其他算法需要首先创建数据结构,因此对于训练和预测,它们得到`O(d * n * log(n) + k * log(n))`,没有考虑空间复杂性,这可能也是重要的。因此,在频繁构建树的情况下,训练阶段可能会超过其更快的最近邻查找的优势。

应该用 k-d 树还是球树?这取决于数据结构-相对均匀或“表现良好”的数据将更好地利用 k-d 树,因为空间的切割将很好地工作(在所有切割之后,近点将在树叶中接近)。对于更聚类的数据,来自球树的“球”将更好地反映结构,因此允许更快的最近邻搜索。幸运的是,Scikit-learn 支持“auto”选项,它会自动从数据中推断出最佳的数据结构。

让我们通过两个案例来看看这一点,这两个案例是我在学习和工作中遇到的。

# **案例研究 1:分类**

kNN 更“传统”的应用是数据分类。它通常有相当多的点,例如 MNIST 有 60k 的训练图像和 10k 的测试图像。分类是离线完成的,这意味着我们首先进行训练阶段,然后在预测过程中使用结果。因此,如果我们要构造数据结构,我们只需要这样做一次。对于 10k 测试图像,让我们比较蛮力(每次计算所有距离)和 3 个邻居的 k-d 树:

蛮力(`O(k * n)` ): `3 * 10,000 = 30,000`

k 线树(`O(k * log(n))` ): `3 * log(10,000) ~ 3 * 13 = 39`

对比:`39 / 30,000 = 0.0013`

如您所见,性能提升是巨大的!数据结构方法只使用了蛮力时间的很小一部分。对于大多数数据集,这种方法是一个明显的赢家。

# **案例研究 2:实时智能监控**

机器学习通常用于图像识别,通常使用神经网络。它对于实时应用非常有用,在实时应用中,它通常与摄像机、警报器等集成在一起。神经网络的问题是,它们经常检测同一个对象两次或更多次——即使是像 YOLO 这样最好的架构也有这个问题。实际上,我们可以通过最近邻搜索用一种简单的方法来解决这个问题:

1.  计算每个边界框(矩形)的中心
2.  对于每个矩形,搜索其最近的邻居(1NN)
3.  如果点比选定的阈值更近,则合并它们(它们检测到相同的对象)

关键部分是寻找另一个包围盒的最近中心(点 2)。这里应该使用哪种算法?通常我们只有几个运动物体在摄像机上,可能多达 30-40 个。对于这样一个小数字,使用数据结构进行快速查找所带来的加速可以忽略不计。每一帧都是一个独立的图像,所以如果我们想要构建一个 k-d 树,我们必须对每一帧都这样做,这可能意味着每秒 30 次——总的来说是一个巨大的成本。因此,对于这种情况,简单的强力方法工作最快,并且具有最小的空间需求(对于重型神经网络或对于相机中的嵌入式 CPU,这可能是重要的)。

# **总结**

kNN 算法是机器学习中一种流行、简单且有用的技术,我希望在阅读完这篇文章后,你能理解它的复杂性以及你可以在哪里以及如何使用这种方法的真实场景。

# 参考资料:

*   [https://stats . stack exchange . com/questions/219655/k-nn-computational-computational-complexity](https://stats.stackexchange.com/questions/219655/k-nn-computational-complexity)
*   [https://en.wikipedia.org/wiki/K-d_tree](https://en.wikipedia.org/wiki/K-d_tree)
*   [https://www.alglib.net/other/nearestneighbors.php#header0](https://www.alglib.net/other/nearestneighbors.php#header0)
*   [http://www.cs.utah.edu/~lifeifei/cis5930/kdtree.pdf](http://www.cs.utah.edu/~lifeifei/cis5930/kdtree.pdf)
*   [https://towards data science . com/tree-algorithms-explained-ball-tree-algorithm-vs-KD-tree-vs-brute-force-9746 debcd 940](/tree-algorithms-explained-ball-tree-algorithm-vs-kd-tree-vs-brute-force-9746debcd940)

# 6 步 k 近邻

> 原文:<https://towardsdatascience.com/k-nearest-neighbors-in-6-steps-efbcbebce54d?source=collection_archive---------15----------------------->

## 使用 scikit-学习 python

本书旨在成为一个应用指南,介绍如何利用 K 近邻(KNN)方法来解决 python 中的商业问题。KNN 最流行的用例是在分类中。有趣的是,它也适用于 KNN 回归。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/04e8e0d7ebf9d292a0dc6e00b0fd55fa.png)

[法比奥](https://unsplash.com/@fabioha?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

## 这个概念

从 KNN 分类器模型的基础开始。KNN 分类器模型在 3 个主要步骤中工作,以预测前所未有的特征值(不在训练数据中)的标签。

1.  它会记住整个训练测试集——特别是哪个特征产生了哪个 y 标签。
2.  它定义了 K 个最近的最相似实例,其中 K 是用户定义的整数。对于给定的数据点,它会查看最近的要素及其各自的标注。
3.  它根据最近邻居的标签来预测新标签。通常,这是多数票。

回到 KNN 回归:不同之处在于,KNN 回归模型从前所未有的特征值的连续分布中预测新值。从概念上讲,它如何获得预测值与 KNN 分类模型类似,只是它将采用其 K 个最近邻的平均值。

# k 近邻分类器

## 包裹

让我们首先导入所需的包:

1.  numpy 和*pandas*:python 中的数据和数组操作
2.  *来自 *matplotlib 库的 pyploy 模块*:*数据可视化
3.  *sklearn 模块*用于创建列车测试分割,并创建 KNN 对象。

Packages

%matplotlib notebook
import numpy as np
import pandas as pd
import matplotlib.pyplot as pltfrom sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import MinMaxScaler


## 数据

数据集有 59 行和 7 列,前 10 行如下所示。为了简单起见,我们不会使用所有的特性;我们的目的是使用*质量*和*宽度*来预测标签*水果 _ 标签*。

import data

fruits = pd.read_table('readonly/fruit_data_with_colors.txt')feature_names_fruits = ['height', 'width', 'mass', 'color_score'] #x variable names
X_fruits = fruits[feature_names_fruits] #setting the col names
y_fruits = fruits['fruit_label'] #setting the col names
target_names_fruits = ['apple', 'mandarin', 'orange', 'lemon'] #potential classesfruits.head(10)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/239629f7f0ce20253cb4d8bc3d8570ea.png)

水果.头(10)

## 1.特征工程

丢弃不需要的要素和标注。您将对数据集执行的要素工程的范围在很大程度上取决于您所操作的业务环境。

setting up the 2 dimensional array of height and width predictors. other x vars discarded

X_fruits_2d = fruits[['height', 'width']]
y_fruits_2d = fruits['fruit_label'] #labels


## 2.列车测试分离

现在,我们将使用 75/25 的训练测试拆分来拆分 59 个条目,其中 75%的数据用于训练 KNN 分类模型,剩余的 25%从模型中“隐藏”出来,用于验证结果。75/25 分割是由 *train_test_split 执行的默认分割。*

75 / 25 train test split

X_train, X_test, y_train, y_test = train_test_split(X_fruits, y_fruits, random_state=0)


## 3.特征最小-最大缩放

查看*质量*和*宽度*特征,我们注意到它们都在不同的尺度上:*质量*值的范围是两位数和三位数,而*宽度*值的范围通常是个位数。如果值的范围太大,目标函数可能无法正常工作,因为一些特征可能会无意中对预测产生更大的影响。

最小-最大缩放是一种相对简单的方法,类似于对分布应用 Z 分数归一化。相对于要素最小值和最大值,值被重新调整到-1 和 1 之间的范围内。

scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)

we must apply the scaling to the test set that we computed for the training set

X_test_scaled = scaler.transform(X_test)


## 4.创建适合的 KNN 对象

我们可以用第一行创建一个“空的”KNN 分类器模型。此外,*n _ neighbors*参数允许控制我们的‘K’值。接下来,模型将根据训练数据集中缩放后的 X 要素及其对应的 Y 标注进行拟合。

knn = KNeighborsClassifier(n_neighbors = 5) #setting up the KNN model to use 5NN
knn.fit(X_train_scaled, y_train) #fitting the KNN


## 5.评估绩效

类似于如何使用 *R 平方*度量来评估简单线性模型的拟合优度,我们可以使用 *F 值*来评估 KNN 分类器。 *F 值*衡量模型正确预测标签的准确性。我们可以观察到,该模型在 95%的训练数据时间和 100%的保留测试数据集时间上预测标签是正确的。

Checking performance on the training set

print('Accuracy of K-NN classifier on training set: {:.2f}'
.format(knn.score(X_train_scaled, y_train)))

Checking performance on the test set

print('Accuracy of K-NN classifier on test set: {:.2f}'
.format(knn.score(X_test_scaled, y_test)))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/5ac3cd323001d4770e639bb4225a8fd1.png)

## 6.做一个预测

最后,我们想用这个模型来做预测。给定一个*质量、宽度、高度和 color_score* 分别为 5.5、2.2、10 和 0.70 的水果,这是什么水果?在适当的最小-最大缩放之后,模型预测它是普通话。

example_fruit = [[5.5, 2.2, 10, 0.70]]
example_fruit_scaled = scaler.transform(example_fruit)

Making an prediction based on x values

print('Predicted fruit type for ', example_fruit, ' is ',
target_names_fruits[knn.predict(example_fruit_scaled)[0]-1])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/caa483707a43d383179a71cafabb5e11.png)

## 7.测绘

让我们看看如何使用 *matplotlib* 库可视化数据。我们还可以进一步检查数据集在不同 K 值下的表现。下面我绘制了 K = 1,5,11。

通常,我们可以观察到,K 值越低,训练数据的过度拟合程度越高。该模型尝试使用较低的 K 值更准确地预测每个点。结果,我们可以观察到分类区域之间的边界是锯齿状的,并且随着局部变化而剧烈变化。

查看 K = 11 的 KNN,我们可以看到分类区域之间的边界相对更平滑。这种 KNN 模型在捕捉全球趋势方面变得相对更好,并允许它更通用于一个持续的测试集。

from adspy_shared_utilities import plot_two_class_knnX_train, X_test, y_train, y_test = train_test_split(X_C2, y_C2,
random_state=0)plot_two_class_knn(X_train, y_train, 1, ‘uniform’, X_test, y_test)
plot_two_class_knn(X_train, y_train, 5, ‘uniform’, X_test, y_test)
plot_two_class_knn(X_train, y_train, 11, ‘uniform’, X_test, y_test)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/ad96c46840aec60865c9d5c6bb14ad40.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/cae6346e0f1634eaad8cef2f5bfda784.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2020/-/raw/master/docs/img/b1c106d933711f9643008ff9e7f701d2.png)

K = 1,5,11

# 尾注

我通过由 Coursera 主办的密歇根大学 MOOC“Python 中的应用机器学习”了解到了这一点。

如果你有问题或者想讨论后新冠肺炎世界,请随时联系我,LinkedIn !

我希望我能够以这样或那样的方式帮助您学习数据科学方法!

这是另一篇数据科学文章!

[](https://medium.com/python-in-plain-english/linear-regressions-with-scikitlearn-a5d54efe898f) [## 使用 scikit-learn 进行线性回归

### 本文应该足以涵盖如何在 python 中运行构造一个简单的线性回归;它还将包含…

medium.com](https://medium.com/python-in-plain-english/linear-regressions-with-scikitlearn-a5d54efe898f) 

*   [机器学习](https://medium.com/tag/machine-learning)
*   [数据分析](https://medium.com/tag/data-analysis)
*   [数据分析](https://medium.com/tag/data-analytics)
posted @ 2024-10-15 13:42  绝不原创的飞龙  阅读(152)  评论(0)    收藏  举报