TowardsDataScience-博客中文翻译-2016-2018-二十二-

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

TowardsDataScience 博客中文翻译 2016~2018(二十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

利用特征权重学习提高聚类性能

原文:https://towardsdatascience.com/improving-clustering-performance-using-feature-weight-learning-d65d4fec77cb?source=collection_archive---------11-----------------------

给无监督学习一个目标

聚类是一种无监督的机器学习方法,旨在将数据划分为不同的组或簇。有几种不同的形式,包括等级、密度和相似性。每一个都有一些不同的算法。任何机器学习算法中最难的部分之一是特征工程,这对于聚类来说尤其困难,因为没有简单的方法来找出最好的方法将数据分成独立但相似的组。

基于相似性的聚类的指导原则是相似的对象在同一聚类内,而不相似的对象在不同的聚类内。这与大多数传统聚类算法的目标没有什么不同。对于基于相似性的聚类,必须给出一个度量来确定两个对象有多相似。这种相似性度量是基于距离的,并且可以采用不同的距离度量,但是相似性度量通常产生[0,1]中的值,其中 0 没有相似性,1 是相同的。为了测量特征权重重要性,我们将不得不使用加权欧几里德距离函数。相似性度量定义如下:

β是我们实际上必须求解的一个值,(w)表示距离权重矩阵,d 表示所有对象之间的成对距离。为了求解β,我们必须假设,如果使用标准权重(全为 1),我们的相似性矩阵将在[0,1]之间均匀分布,导致平均值为. 5。为了找到β,我们求解方程:

如果使用加权欧几里德距离,则可以使用该相似性矩阵来识别哪些特征引入了更多噪声,以及哪些特征对于聚类是重要的。最终目标是最小化相似性矩阵的“模糊性”,试图将中间(即. 5)的所有内容移动到 1 或 0。为此,我们使用损失指标:

这里(1)表示基本权重(全为 1),而 ρ 表示得到的模糊划分矩阵,它是点 p 和 q 之间的欧几里德距离函数中使用的权重的乘积。

然后,我们可以尝试对这个损失函数使用梯度下降,以尝试相对于相似性矩阵最小化它。梯度下降是机器学习中最常见的优化算法之一,用于通过使用函数梯度(偏导数的组合)来寻找给定函数的最佳参数。通过采取与梯度的负值成比例的步骤,我们可以试图找到函数的局部最小值。我们将不断更新权重,直到达到我们的最大迭代次数,或者函数收敛。所以梯度下降是我们的损失函数,对重量有偏导数。我们将根据梯度和学习率在每次迭代中更新权重。

其中 n 是定义的学习率。n 是一个非常重要的参数,因为太小需要太多的计算,而太大,函数可能永远不会收敛。

如果你能从一个 3D 图形的角度来考虑它,它就像拉伸或收缩每个轴,以某种方式将我们的点放入更紧密的组中,这些组彼此之间距离更远。我们实际上并没有改变数据的位置,我们只是改变了衡量驱动相似性度量的距离的方式。

这是一个创建的示例,我在前两个变量上引入了 3 个具有独立质心的聚类,但引入了第三个噪声变量,这会使聚类更加困难。它们由创建数据时给出的实际分类标签来着色。当消除第三个噪声变量时,我们可以看到,识别聚类要容易得多。

尽管由于 3D 视角的原因,很难看出差异,但您可以看到聚类在学习到的特征权重下更加清晰。通过扩展可以轻松区分它们的主要特征,它能够更好地识别集群。

测量改进

其有效性的一个很好的代表是模糊 c-均值,一个常用的 k-均值算法的相对。它的工作方式与 k-means 非常相似,但是它会产生一种叫做模糊划分矩阵的东西,而不仅仅是一个聚类标签。

模糊划分矩阵是一组权重,用于测量单个点与给定聚类中心的相似程度,类似于我们之前使用的相似性矩阵。它也可以使用加权距离度量来计算,我们可以将它提供给我们新发现的最佳权重。这也将返回到更新集群中心。像 K-means 一样,这导致聚类中心随着每次迭代而移动,直到达到最大迭代次数或某个改进阈值。

在模糊 c 均值中,你会有一个和我们最初的损失函数非常相似的目标。您希望点变得不那么“模糊”,并且希望它们都尽可能靠近它们的聚类中心,而远离其他点。模糊聚类算法的一个很好的度量是 Dunn 的划分系数,它是模糊划分矩阵的所有分量的总和。

让我们尝试在有和没有我们学习的特征权重的情况下对虹膜数据集使用模糊 c 均值。这里模糊 c-的输出意味着比较所有变量,假设 3 个聚类(因为我们从数据集中知道)。

请注意,一些要素之间的界限不太明确,因为我们有多个同等权重的要素,所以界限可能会模糊。现在,当应用特征加权学习方法时,我们得到归一化的距离权重:

{'sepal length': 0.0, 'sepal width': 0.0, 'petal length': 1.0, 'petal width': 0.0258}

仍然存在模糊的边界,主要是在我们认为它们在距离权重中的值为 0 的特征上,但是该算法将主要焦点放在花瓣长度上。我们得到了相似的聚类,更强的边界(在一些特征上),并且总体上我们的模糊划分系数增加了大约 23%!

我们现在还知道,如果我们想要生成关于分类它们的规则,我们可以只关注 2 个特征而不是 4 个!

注意事项

仅仅因为使用模糊 c 均值最容易看到结果,并不意味着这种改进措施只能用于该算法。您可以在许多方面使用它,在聚类之前扩展或更好地理解您的数据。我最近在一个使用 OPTICS 算法的应用程序中使用了这种特征约简和重要性技术,并通过根据特征权重学习算法缩放我的特征看到了改进的结果。

如果你想亲自检查或使用它,我已经将这个功能权重学习构建到一个独立的存储库中。

[## Csinclair0/feature_learning

基于相似性聚类的特征权重学习

github.com](https://github.com/Csinclair0/feature_learning.git)

参考文献

王,,王,亚东,王。“基于特征权重学习改进模糊 c 均值聚类”。2004 年 Elsevier B .诉 doi 案:10.1016/j.patrec.2004.03.008

通过路线优化改善运营

原文:https://towardsdatascience.com/improving-operations-with-route-optimization-4b8a3701ca39?source=collection_archive---------1-----------------------

撰稿人:Feiko Lai,Michal Szczecinski,Winnie So,Miguel Fernandez

这个故事最初发表在 GOGOVAN 科技博客

请在这里找到我们关于主题 的学术论文。

每天,GOGOVAN 的司机都会抵达亚洲各地的仓库,提取我们的业务合作伙伴要求我们交付给他们客户的数千份订单。

这些订单可以是一系列的东西——从期待已久的新手机,到最后一刻订购的周年礼物。它们都有不同的大小、形状和重量。对于他们中的每一个人,都会有一个人在等待,希望这次快递公司能准时到达…

这就是为什么在 GOGOVAN,我们尽我们所能确保顺利和及时的交付,并提供令客户惊叹的服务质量。每一条送货路线都由我们的运营团队手工精心规划和反复检查,以确保我们不会失败。

手动?!

你刚才不是说你每天有几千个订单吗?!

是的,没错。

过去,运营团队通常需要在取货当天早上手动整理送货路线,并确保我们满足当天的所有送货时间要求。正如您可能想象的那样,这不是一个特别令人兴奋或容易的任务:)

一个人花了大约 1 个小时来创建 100 个路点的次优路线。对于更大的请求,这个时间会成倍增长。

我们立刻意识到这个过程只是在乞求一些自动化。

我们不仅为每天清晨不得不做如此平凡工作的运营团队感到难过,而且我们也知道,随着订单量的增长,这项任务将慢慢变成不可能完成的任务。我们认为这是一个开发尖端技术的机会,该技术将成为 GOGOVAN 数据科学堆栈的核心组件。

我们是怎么开始的?

我们非常以客户和司机为中心。因此,我们总是首先尝试从他们的角度分析问题,以了解我们的解决方案如何影响和惠及他们。经过大量的头脑风暴,我们得出了以下目标:

  • 所有订单都需要按时交付
  • 通过使用缓冲时间和实时距离确保驾驶员不会匆忙准时到达。
  • ****通过减少行驶距离来节省燃油
  • 尽量减少司机的空闲时间——没有人喜欢拿着装满包裹的行李箱等待。
  • ****提高车辆利用率
  • 完全自动化流程。****
  • 该算法需要能够与我们一起成长——支持不同类型的交付、车辆和国家。

确定了我们的主要目标后,我们决定探索学术界和开源的世界——重新发现轮子是没有意义的。我们意识到我们所面临的问题就是众所周知的车辆路径问题。

什么是车辆路径问题?

车辆路径问题【VRP】可以描述为从一个或多个车场到多个*客户约束创建一组最优路线*的问题。目标是向所有客户交付货物,同时最大限度地降低路线成本和车辆数量。**

这个问题是 NP-hard ,已经被伦斯特拉和 Rinnooy Kan 证明。然而,仍然有一些精确的解决方法,使用一个分支限界,或者动态规划,然而,正如上面的论文中所描述的,它们似乎只适用于最多 150 个航路点。

目前,最先进的解决方案是使用元启发式算法获得的:遗传算法 ⁴、禁忌搜索 ⁵和蚁群优化 ⁶.这些是目前该领域主要使用的方法。

对于该领域的深入回顾,我们推荐李晓燕的这篇精彩论文 ⁷。

我们的解决方案

随着 VRP 成为一个被广泛认可的问题,确实有很多公司似乎正在解决这个问题。

然而,不知何故,我们对他们的解决方案并不满意……

我们只知道,如果我们结合我们的运营知识、数据科学和研究专业知识、大量数据以及开源的最新贡献,我们就可以获得一个强大的内部解决方案,该解决方案:

  • 更先进,性能更好,有可定制的算法和迭代逻辑。
  • 更便宜、更高效、更具可扩展性。
  • 允许开发有形的知识产权资产并围绕它建立竞争优势。
  • 允许我们向客户保证,他们的交付数据不会超过 GOGOVAN。

考虑了很长时间后,我们决定,如果我们想成为这个领域的领导者,我们需要用我们自己的方式,而不是用一些黑箱解决方案。****

所以我们开始了…

第一算法

但是我们并没有马上开始研究学术论文!

首先,我们专注于提出自己的方法,并对其进行评估。这个过程让我们从一开始就对这个领域有了更好的了解,并亲身经历了一些常见的问题(我们没有想当然!).更重要的是,这在后来帮助了我们,因为我们可以很容易地看到学术论文中提出的不同方法的利弊,并想出将它们结合起来的策略。****

这样一个过程是理解这个出色的软件包— 谷歌优化工具如何工作的关键。我们知道谷歌的人节省了我们几个月的时间来编写我们想要测试的所有不同的算法。他们允许我们立即进入最有趣的部分!

我们花了很多时间来玩这个库,测试不同的场景,亲眼看看哪些策略在什么时候有效。

我们非常喜欢它,所以决定围绕它来开发我们的工具!

它拥有我们所需要的一切——透明度、实验能力、灵活性和支持。

第一个算法准备好了。我们部署了它。

Figure 1: Visualisation of one of our first Route Optimization assignments

快速增长—如何处理更多订单?

路由优化的第一个版本取得了巨大的成功。

提交给 Route Optimizer 的订单量迅速从每个仓库 500 件增加到 1000 多件。理论上,我们应该没事。

但是我们没有。

我们的算法运行时间和内存使用量惊人地快速增长——从 1 分钟 500 MB 增加到 10 分钟 5 GB。随着我们对越来越大的容量进行测试,我们最终达到了最大值— 对于 2000 个航路点,该模块使用了 25GB 的 RAM 内存。

这是不可接受的。

基本上,我们有两个选择:

  • ****建立一个全新的路由优化器,默认情况下能够支持如此大的容量
  • 创建一个新的算法,在当前实现的基础上运行——可能是一种将订单组合成更小批量的方法,然后提交给主优化算法****

由于我们务实(也喜欢在我们已经完成的伟大工作的基础上再接再厉),我们决定进行第二个选择。

我们如何创建更小的批量?

让我们从一个著名的聚类算法开始— DBSCAN ⁸.

我们拥有的是一种最先进的方法,将地理点组合在一起。然而,它也有不利的一面:每个星团都必须有相同的半径。

这不是我们想要的,原因很简单:尖沙咀 1 公里半径的一个集群可能包含 1000 个订单,而薄扶林和瀑布湾的其他 1 公里集群可能每个仅包含 3 个订单。

这些集群将会非常低效和不均衡……

在尖沙咀,集群规模会太大,一个集群中会有太多订单。但与此同时,在其他一些区域,这个半径可能不够,因为聚类太小,相对靠近的停靠点将位于单独的聚类中。

这就是为什么我们决定使用一种改进的方法——称为“递归-DBSCAN”。****

递归数据库扫描

它建立在 DBSCAN 的辉煌之上,但同时允许我们更深入地挖掘高航点密度区域,同时将远程订单分组在一起。

对于订单列表,我们的目标是找到平均路点数最大的半径(但聚类数将高于 min_no_clusters )。我们通过使用简单的二分搜索法算法来做到这一点。****

一旦我们找到最优解,我们“进入”太大的集群,并应用相同的逻辑,直到我们到达每个集群包含小于 max_len_cluster 的点。

然后,对于每个集群,我们使用谷歌优化工具运行我们开发的路线优化算法。希望这将更快地给我们一个相似的结果,并且使用更少的内存。

伪代码如下:

基准

我们非常好奇我们的方法将如何执行,但同时我们担心递归可能会运行很长时间,从而使我们的算法不比基线方法好。

这就是为什么我们首先决定看看运行时:

原来, recursive-dbscan 算法大大优于谷歌优化工具方法。同时,它与 dbscan 方法的运行时间没有太大的不同。

由于 RAM 内存使用问题,我们只能对最多 2000 个订单运行 dbscan 和对 1500 个订单运行 Google 优化工具:当所需内存超过 25 GB 时,这两种方法都会崩溃。

运行时间很重要,但我们感兴趣的是,与基线方法相比,我们的新算法在总距离和使用的车辆数量方面的表现如何。这两个图表显示:

****

正如我们所见,在距离和车辆数量方面,递归方法紧跟谷歌优化工具方法。同时,它优于 dbscan 方法。

这意味着我们的新算法比基线算法更快,而且找到的解的质量也一样好。此外,使用的最大 RAM“只有”1GB!

我们拿到了!

DBSCAN 与递归 DBSCAN

我们还想向您展示递归 dbscan 如何更好地用于远程航路点。

Figure 5: Comparison od DBSCAN and Recursive-DBSCAN routes. We are aware that they are still not perfect!

上图中,左侧是一张使用普通 DBSCAN 算法找到的分配图。我们可以看到许多司机只交付一个订单,因为这些订单是他们批次中唯一的订单。

在右侧,我们看到递归方法很好地处理了这个问题,通过对不同区域使用不同的半径,它设法找到了一个仅使用 3 辆车交付所有订单的解决方案!****

这是递归 dbscan 方法如何更适合我们的用例以及我们为什么选择使用它的完美可视化。

结论(又名 TL;博士)

在这篇文章中,我们提出了我们的方法来解决带有时间窗的有容量限制的车辆路径问题。通过使用递归 dbscan 方法,我们能够显著减少运行时间和内存使用,同时保持与基准 Google 优化工具方法类似的结果质量

这种算法对我们的运营团队有很大的帮助将几个小时的琐碎手工工作减少到几分钟的 CPU 时间(并由人工复核结果)。

今后

我们意识到我们的工具并不完美。

一个主要的问题是仍然是一个静态方法,一旦运行,如果有更好的路线可用,或者如果路况改变,它不会更新自己。在这种情况下,我们有几个选择,一个是实施地理哈希如 Lyft ,另一个来自我们的合作伙伴——香港理工大学大数据分析研究机构。

我们的目标是改善路线优化,以便持续监控司机,并且在司机有可能无法按时运送包裹时发出警报所有这些都是为了让我们的客户对我们的服务更加满意。****

希望这篇文章为您提供了一些关于我们在 GOGOVAN 解决的问题的深刻见解。如果您对此感兴趣,或者您只是想了解更多,请随时联系我们。

当然,未来还有很大的改进空间,但我们希望分享我们的一些方法,以便在优化按需物流运营这一迷人领域引发讨论和取得进展。

如果您想了解我们数据团队的更多信息,请点击查看我们数据主管的文章。

我们一直在寻找顶尖的应用运营和 ML 研究人才。有意者请联系!(现场和远程)

参考文献:

[1]j . k .伦斯特拉和 Kan a . h .(1981),车辆路线和调度问题的复杂性。网络,11:221–227。doi:10.1002/net . 3230110211

[2] Fukasawa,r .,Longo,h .,Lysgaard,j .等人。程序。(2006) 106: 491.

[3]巴尔达奇和明戈齐,数学。程序。(2009) 120: 347.https://doi.org/10.1007/s10107-008-0218-9

[4] Nagata Y. (2007)带容量限制的车辆路径问题的边缘装配交叉。参见:Cotta C .,van Hemert J .(编辑)组合优化中的进化计算。EvoCOP 2007。计算机科学讲义,第 4446 卷。施普林格,柏林,海德堡

[5]br ysy,o .和 Gendreau,M. Top (2002 年)10: 211。https://doi.org/10.1007/BF02579017

[6]谭鑫,卓鑫,张军(2006)带时间窗车辆路径优化问题的蚁群系统。在:黄 DS。、李 k、欧文 G.W .(编)计算智能与生物信息学。ICIC 2006。计算机科学讲义,第 4115 卷。施普林格,柏林,海德堡

[7]李晓燕(2015)带时间窗的有能力限制的车辆路径问题:非营利组织食品提货的案例研究

[8] M. Ester,H. Kriegel,J. Sander 和 X. Xu,“一种基于密度的算法,用于在带有噪声的大型空间数据库中发现聚类”,在 Proc .第二国际。糖膏剂知识发现和数据挖掘(KDD'96),1996 年,第 226-231 页。

利用数据科学和分析改善患者流量

原文:https://towardsdatascience.com/improving-patient-flows-with-data-science-and-analytics-faf29affaa60?source=collection_archive---------19-----------------------

通过改进流程降低成本

我们的团队最近被问到如何利用数据分析和数据科学来改善医院的瓶颈和患者流量。医疗保健提供商和医院可能会有非常复杂的患者流。许多步骤可能会相互交织,资源必须始终在任务之间转移,患者和新患者的严重程度决定了谁需要一直接受治疗。这使得在医院进行流程改进并不容易。这个问题是工艺问题。工业工程师和六西格玛从业者喜欢的东西。他们喜欢在有数千个标签和数千行数据的 Excel 表格中查看医疗保健流程问题。然而,现在我们不再局限于在 Excel 电子表格中对数千行数据进行分析和模型开发。我们现在可以访问更完整的数据集,根据我们的经验,这些数据集可以多达数十亿行,而且更强大的计算系统可以更准确有效地分析患者流量和瓶颈。

现在,有了 SQL、R 和 python 等工具,我们可以快速分析这些数据集。

这不仅仅是工具的问题。事实上,有了如此强大的工具,人们很容易尝试制作能够一次性解决所有问题的模型和算法。这种方法在研究医院的病人流量和瓶颈(或任何问题)时,最大的问题之一是它的视角太过宽泛。这使得评估一项分析何时完成变得非常困难,并且经常让数据科学家和分析师持续数周而得不到真正的答案。

这里的问题是查看所有内容的范围很难管理和确定问题。而不是试图攻击医院的所有流程和程序。更好的办法是将你认为可能存在瓶颈的程序/患者流程/过程分成几大类。这是因为医院有如此多不同的可能路径和流程(下面我将使用“流程”一词来描述患者流),以至于盲目寻找某种瓶颈将会花费很长时间(这就像在医疗保健中寻找欺诈一样,如果你试图做得太笼统,那么几乎不可能找到)。

第一步是找出问题所在。不知道你想瞄准什么,就很难知道解决方案是什么。在一个完美的世界里,你的医院有一个数据库,跟踪所有的过程和程序。这将使开发能够指出主要瓶颈的查询或 Jupyter 笔记本变得容易。这将进一步帮助您的团队减少不必要的工作量。一旦你的团队知道了问题在哪里,那么你的团队就可以用这些唾手可得的果实来寻找问题。

异常

异常,比如病人流动的时间不一致,无论是特定的医生还是一般情况下,都可能表明存在问题。找到这些特定的异常值可能非常简单。

例如,假设您寻找患者流程 x 的时间异常值,并且您假设一周中的特定日期或一天中的特定时间更有可能具有特定步骤的更长时间。然后,您取出这些步骤,并在时间粒度上分析时间,以单独标记每个流程。你可能会发现夏季的生产力下降,或者在 7 月 4 日你的 ERs 溢出,或者一些不太明显的数据点。

这里的一个关键点是,你首先提出一个理论。因为有了明确的问题和假设,寻找证据就容易多了。有了明确的问题,你就知道进一步分析的目标。您可以使用查询来清理数据,并将其分解到所需的粒度。这可能是在医院层面,医生层面,甚至可能下降到程序层面。

在此基础上,您可以应用一个擅长突出异常值的基本算法(如基本的 IQR 计算或更复杂的计算)。一旦发现异常值,就可以进一步分析为什么在特定流程中会有较长的时间或不一致的时间。有许多看似合理的原因,但现在你已经决定了一类程序,假设并发现了一个看似合理的弱点。有了这些基本步骤,前进就容易多了。

按照这些步骤,您可以重复类似的过程。从理论上解释为什么你会看到异常值,是什么导致了异常值,并进一步研究数据。这可能是由糟糕的流程造成的,在你需要更多人手的时候人手太少(想想排队论)。一旦你知道要关注哪些步骤,你就可以开始采取下一步措施,比如流程改进团队,他们现在已经找到了确切的问题,而不是简单地派出一个分析师团队跟随医生,猜测问题出在哪里。

瓶颈

除了异常,另一个常见的问题是一些进程可能需要相同的资源。现在,定位这些瓶颈的一种方法是基于第一个异常点。因为瓶颈可能是导致异常的问题之一。然而,瓶颈也可能隐藏在这样一个事实中,即所讨论的步骤总是运行很长,因此没有异常。相反,这种分析需要问一个简单的问题。患者流程中是否有重叠的步骤,并且似乎需要很长时间或至少比预期的时间长。某些步骤可能需要很长时间,例如某些实验室需要一段时间才能运行。还有其他人不应该。分析这些步骤可能会导致医院设置新的套房或雇用新的专家来处理某些领域的繁重负载。

结论

改善患者流量是降低患者成本和提高患者满意度的重要一步。通过减少他们在医院和医疗保健系统花费的时间,您可以减少员工照顾他们所需的时间。这应该有助于降低总成本。我们的团队总是把它看作是对患者的一种削减,尽管它也应该反过来降低医疗保健系统的成本。从我们的角度来看,医院、保险公司和顾问能够做的任何有助于降低我们当前系统中医疗保健成本的事情都需要去做。

改进 Python 中的随机森林第 1 部分

原文:https://towardsdatascience.com/improving-random-forest-in-python-part-1-893916666cd?source=collection_archive---------1-----------------------

收集更多数据和特征工程

在之前的帖子中,我们用 Python 实现了一个简单随机森林的端到端实现,解决了一个监督回归问题。虽然我们涵盖了机器学习过程的每个步骤,但我们只简要地触及了最关键的部分之一:改进我们最初的机器学习模型。我们完成的模型取得了不错的性能,超过了基线,但我们应该能够通过一些不同的方法来改进模型。本文是探索如何使用 Python 和 Scikit-Learn 库改进我们的随机森林机器学习模型的两篇文章中的第一篇。我建议在继续之前先看看这篇介绍性的文章,但是这里涉及的概念也可以独立存在。

如何改进机器学习模型

有三种改进现有机器学习模型的通用方法:

  1. 使用更多(高质量)数据和特征工程
  2. 调整算法的超参数
  3. 尝试不同的算法

这些是按照我平时尝试的顺序来呈现的。通常,为改进不良模型而提出的直接解决方案是使用更复杂的模型,通常是深度神经网络。然而,我发现这种方法不可避免地会导致沮丧。一个复杂的模型需要花费很多时间来构建,但是也不能交付,导致了另一个模型的产生,等等。相反,我的第一个问题总是:“我们能获得更多与问题相关的数据吗?”。正如 Geoff Hinton(深度神经网络之父)在一篇名为‘数据的不合理有效性’的文章中所指出的,对问题来说,有用数据的数量比模型的复杂性更重要。其他人附和了这个观点,即一个简单的模型和大量的数据将会击败一个数据有限的复杂模型。如果有更多的信息可以帮助解决我们没有使用的问题,从投入的时间和获得的性能来看,最好的回报就是获取这些数据。

这篇文章将介绍改进 ML 模型的第一种方法,第二种方法将出现在后续文章中。我还将编写几个算法的端到端实现,这些算法可能会也可能不会击败随机森林(如果对特定算法有任何要求,请在评论中告诉我)!这个例子的所有代码和数据都可以在项目 GitHub 页面找到。我在这篇文章中包含了大量代码,不是为了让不熟悉 Python 的人气馁,而是为了展示机器学习变得多么容易,并鼓励任何人开始实现这些有用的模型!

问题重述

简单提醒一下,我们正在处理一个温度预测问题:给定历史数据,我们想预测我们城市明天的最高温度。我正在使用华盛顿州的西雅图,但也可以随意使用 NOAA 气候数据在线工具来获取你所在城市的信息。这个任务是一个有监督的回归机器学习问题,因为我们有我们想要预测的标签(目标),并且这些标签是连续的值(与无监督学习相反,在无监督学习中,我们没有标签,或者在分类中,我们预测离散的类)。我们在简单模型中使用的原始数据是 2016 年以来某一年的最高温度测量值以及历史平均最高温度。这得到了我们“有气象倾向”的朋友的预测的补充,这是通过从历史平均值中随机加减 20 度计算出来的。

我们使用原始数据的最终性能的平均误差为 3.83 度,而基线误差为 5.03 度。这表示最终准确率为 93.99%。

获取更多数据

在第一篇文章中,我们使用了 2016 年的一年历史数据。多亏了美国国家大气和海洋管理局,我们可以获得 1891 年的数据。现在,让我们把自己限制在六年内(2011-2016),但可以随意使用额外的数据来看看是否有帮助。除了简单地获取更多年份的数据,我们还可以包含更多的特性。这意味着我们可以使用我们认为对预测最高温度有用的额外天气变量。我们可以使用我们的领域知识(或专家的建议),以及变量和目标之间的相关性来确定哪些特性是有帮助的。从 NOAA 提供的过多选项中(说真的,我不得不称赞这个组织的工作和他们的开放数据政策),我将平均风速、降水量和地面积雪深度添加到我们的变量列表中。请记住,因为我们预测的是明天的最高温度,所以我们实际上不能使用当天的测量值。我们必须将它转移到过去的某一天,这意味着我们使用今天的总降水量来预测明天的最高温度。这防止了我们通过今天拥有来自未来的信息来“欺骗”。

额外的数据直接来自源代码,状态相对较好,但是在将它读入 Python 之前,我确实需要做一些轻微的修改。我已经省略了“数据管理”的细节,将重点放在随机森林实现上,但是我将发布一个单独的帖子,展示如何清理数据。我在 munging 中使用了 R 统计语言,因为我喜欢它使数据操作具有交互性的方式,但这将在另一篇文章中讨论。现在,我们可以加载数据并检查前几行。

# Pandas is used for data manipulation
import pandas as pd# Read in data as a dataframe
features = pd.read_csv('data/temps_extended.csv')
features.head(5)

Expanded Data Subset

新的变量是:

ws_1 :前一天的平均风速(mph)

prcp_1 :前一天的降水量(in)

snwd_1 :前一天地面积雪深度(in)

在我们有 348 天的数据之前。现在来看看尺寸。

print('We have {} days of data with {} variables'.format(*features.shape))**We have 2191 days of data with 12 variables.**

现在有超过 2000 天的历史温度数据(约 6 年)。我们应该对数据进行汇总,以确保数字中没有突出的异常。

round(features.describe, 2)

Expanded Data Summary

从描述性统计数据来看,没有什么立即出现异常。我们可以快速绘制所有变量的图表来证实这一点。我省略了绘图代码,因为虽然 matplotlib 库非常有用,但代码不直观,很容易迷失在绘图的细节中。(所有代码都可以在 GitHub 上查看和修改)。

首先是四个温度图。

Expanded Data Temperature Plots

接下来,我们可以看看历史最高平均温度和三个新的变量。

Expanded Data Additional Variables

从数值和图形上看,我们的数据中没有明显的异常值。此外,我们可以检查这些图,看看哪些特性可能有用。我认为积雪深度是最没有帮助的,因为大部分时间积雪深度为零,同样,风速看起来也太嘈杂了,没有多大帮助。根据以往的经验,历史平均最高温度和以往最高温度可能是最重要的,但我们将不得不看到!

我们可以再画一个探索图,配对图,来形象化变量之间的关系。这在散点图中绘出了所有变量之间的相互关系,使我们能够检查特征之间的相关性。与上面的图表相比,这个令人印象深刻的情节的代码相当简单!

# Create columns of seasons for pair plotting colors
seasons = []for month in features['month']:
    if month in [1, 2, 12]:
        seasons.append('winter')
    elif month in [3, 4, 5]:
        seasons.append('spring')
    elif month in [6, 7, 8]:
        seasons.append('summer')
    elif month in [9, 10, 11]:
        seasons.append('fall')# Will only use six variables for plotting pairs
reduced_features = features[['temp_1', 'prcp_1', 'ws_1', 'average', 'friend', 'actual']]
reduced_features['season'] = seasons# Use seaborn for pair plots
import seaborn as sns
sns.set(style="ticks", color_codes=True);# Create a custom color palete
palette = sns.xkcd_palette(['dark blue', 'dark green', 'gold', 'orange'])# Make the pair plot with a some aesthetic changes
sns.pairplot(reduced_features, hue = 'season', diag_kind = 'kde', palette= palette, plot_kws=dict(alpha = 0.7),
                   diag_kws=dict(shade=True))

Pairplots

对角线图显示了每个变量的分布,因为每个变量相对于自身的图形将只是一条直线!这些颜色代表四季,如右边的图例所示。我们想要关注的是实际最高温度和其他变量之间的趋势。这些图在最下面一行,要查看与实际最大值的特定关系,请移至包含变量的行。例如,左下方的图显示了实际最高温度和前一天的最高温度(temp_1)之间的关系。这是一个强正相关,表明前一天的最高气温升高,第二天的最高气温也升高

数据准备

这些数据已经在数字和图形上得到验证,现在我们需要将它转换成机器学习算法可以理解的格式。我们将执行与简单实现中完全相同的数据格式化过程:

  1. 一键编码分类变量(星期几)
  2. 将数据分为要素(独立变量)和标签(目标)
  3. 将数据帧转换为 Numpy 数组
  4. 创建要素和标注的随机训练和测试集

我们可以用几行 Python 代码完成所有这些步骤。

# One Hot Encoding
features = pd.get_dummies(features)# Extract features and labels
labels = features['actual']
features = features.drop('actual', axis = 1)# List of features for later use
feature_list = list(features.columns)# Convert to numpy arrays
import numpy as npfeatures = np.array(features)
labels = np.array(labels)# Training and Testing Sets
from sklearn.model_selection import train_test_splittrain_features, test_features, train_labels, test_labels = train_test_split(features, labels,                                          test_size = 0.25, random_state = 42)

我们设置了一个随机的种子(当然它必须是 42 )来确保不同运行的结果一致。让我们快速检查一下每个数组的大小,以确认一切正常。

print('Training Features Shape:', train_features.shape)
print('Training Labels Shape:', train_labels.shape)
print('Testing Features Shape:', test_features.shape)
print('Testing Labels Shape:', test_labels.shape)**Training Features Shape: (1643, 17)
Training Labels Shape: (1643,)
Testing Features Shape: (548, 17)
Testing Labels Shape: (548,)**

可以走了!我们有大约 4.5 年的训练数据和 1.5 年的测试数据。然而,在我们开始建模的有趣部分之前,还有一个额外的步骤。

建立新的基线

在之前的帖子中,我们使用历史平均最高温度作为我们要击败的目标。也就是我们把明天的最高气温作为当天的历史平均最高气温来评估预测的准确性。我们已经知道,即使是根据一年的数据训练的模型也可以超过基线,所以我们需要提高我们的预期。对于新的基线,我们将使用根据原始数据训练的模型。为了进行公平的比较,我们需要用新的、扩展的测试集来测试它。然而,新的测试集有 17 个特征,而原始模型只训练了 14 个特征。我们首先必须从测试集中删除 3 个新特性,然后评估原始模型。原始随机森林已经根据原始数据进行了训练,下面的代码显示了准备测试功能和评估性能(参考笔记本进行模型训练)。

# Find the original feature indices 
original_feature_indices = [feature_list.index(feature) for feature in feature_list if feature not in ['ws_1', 'prcp_1', 'snwd_1']]# Create a test set of the original features
original_test_features = test_features[:, original_feature_indices]# Make predictions on test data using the model trained on original data
predictions = rf.predict(original_test_features)# Performance metrics
errors = abs(predictions - test_labels)print('Metrics for Random Forest Trained on Original Data')
print('Average absolute error:', round(np.mean(errors), 2), 'degrees.')# Calculate mean absolute percentage error (MAPE)
mape = 100 * (errors / test_labels)# Calculate and display accuracy
accuracy = 100 - np.mean(mape)
print('Accuracy:', round(accuracy, 2), '%.')**Metrics for Random Forest Trained on Original Data
Average absolute error: 4.3 degrees.
Accuracy: 92.49 %.**

在一年的数据上训练的随机森林能够实现 4.3 度的平均绝对误差,表示在扩展的测试集上 92.49%的准确度。如果我们用扩展的训练集训练的模型不能击败这些指标,那么我们需要重新思考我们的方法。

扩展数据的训练和评估

Scikit-Learn 的伟大之处在于,可以用几行代码创建和训练许多最先进的模型。随机森林就是一个例子:

# Instantiate random forest and train on new features
from sklearn.ensemble import RandomForestRegressorrf_exp = RandomForestRegressor(n_estimators= 1000, random_state=100)
rf_exp.fit(train_features, train_labels)

现在,我们可以进行预测,并与已知的测试集目标进行比较,以确认或否认我们扩展的训练数据集是一项不错的投资:

# Make predictions on test data
predictions = rf_exp.predict(test_features)# Performance metrics
errors = abs(predictions - test_labels)print('Metrics for Random Forest Trained on Expanded Data')
print('Average absolute error:', round(np.mean(errors), 2), 'degrees.')# Calculate mean absolute percentage error (MAPE)
mape = np.mean(100 * (errors / test_labels))# Compare to baseline
improvement_baseline = 100 * abs(mape - baseline_mape) / baseline_mape
print('Improvement over baseline:', round(improvement_baseline, 2), '%.')# Calculate and display accuracy
accuracy = 100 - mape
print('Accuracy:', round(accuracy, 2), '%.')**Metrics for Random Forest Trained on Expanded Data
Average absolute error: 3.7039 degrees.
Improvement over baseline: 16.67 %.
Accuracy: 93.74 %.**

嗯,我们没有浪费时间去获取更多的数据!基于六年的历史测量值和使用三个附加特征的训练已经使我们在基线模型上获得了 16.41%的改进。确切的指标将根据随机种子而变化,但我们可以确信新模型优于旧模型。

为什么一个模型会随着更多的数据而改进?回答这个问题的最好方法是从人类如何学习的角度来思考。我们通过经验来增加我们对世界的了解,我们练习一项技能的次数越多,我们就会学得越好。机器学习模型也“从经验中学习”,因为每次它查看另一个训练数据点时,它都会学习更多关于特征和标签之间关系的信息。假设数据中存在关系,为模型提供更多数据将使其更好地理解如何将一组要素映射到标注。对于我们的例子,随着模型看到更多天的天气测量,它更好地理解如何进行这些测量并预测第二天的最高温度。实践提高了人的能力和机器学习模型的性能。

特征约简

在某些情况下,我们可能走得太远,实际上使用了太多的数据或添加了太多的功能。一个适用的例子是我目前正在研究的涉及建筑能源的机器学习预测问题。问题是根据天气数据预测 15 分钟内的建筑能耗。对于每栋建筑,我都有 1-3 年的历史天气和电力使用数据。令人惊讶的是,我发现随着我包含更多的一些建筑的数据,预测的准确性下降了。经过询问,我确定一些建筑在数据收集过程中进行了改造以提高能源效率,因此,最近的用电量与改造前有很大不同。在预测电流消耗时,使用修改前的数据实际上降低了我的模型的性能。变更后的最新数据比旧数据更相关,对于几栋建筑,我最终减少了历史数据的数量以提高性能!

对于我们的问题,数据的长度不是一个问题,因为在六年的数据中没有影响最高温度的重大变化(气候变化正在增加温度,但时间跨度更长)。然而,有可能我们有太多的功能。我们之前看到一些特征,特别是我们朋友的预测,看起来更像是噪音,而不是最高温度的准确预测。额外的功能可能会降低性能,因为它们可能会通过向模型提供不相关的数据来“混淆”模型,从而阻止模型学习实际的关系。随机森林执行隐式特征选择,因为它在最重要的变量上分割节点,但其他机器学习模型不这样做。因此,改进其他模型的一种方法是使用随机森林特征重要性来减少问题中的变量数量。在我们的例子中,我们将使用特征重要性来减少随机森林模型的特征数量,因为除了潜在的提高性能之外,减少特征数量将会缩短模型的运行时间。本文不涉及更复杂的降维,如 PCA ( 主成分分析)或 ICA ( 独立成分分析)。这些在减少特征数量的同时不减少信息方面做得很好,但是它们转换了特征,使得它们不再代表我们测量的变量。我喜欢机器学习模型具有可解释性和准确性的混合,因此我通常坚持使用允许我理解模型如何进行预测的方法。

特征重要性

在 Scikit-Learn 中,查找随机森林的特征重要性很简单。重要性的实际计算超出了这篇博文的范围,但是这发生在后台,我们可以使用模型返回的相对百分比来对特性进行排序。

以下 Python 代码创建了一个由元组组成的列表,其中每个元组都是一对(要素名称,重要性)。这里的代码利用了 Python 语言中一些巧妙的技巧,即列表综合、压缩、排序,以及参数解包。如果你不完全理解这些,不要担心,但是如果你想熟练掌握 Python,这些是你应该有的工具!

# Get numerical feature importances
importances = list(rf_exp.feature_importances_)# List of tuples with variable and importance
feature_importances = [(feature, round(importance, 2)) for feature, importance in zip(feature_list, importances)]# Sort the feature importances by most important first
feature_importances = sorted(feature_importances, key = lambda x: x[1], reverse = True)# Print out the feature and importances 
[print('Variable: {:20} Importance: {}'.format(*pair)) for pair in feature_importances]Variable: temp_1               Importance: 0.83
Variable: average              Importance: 0.06
Variable: ws_1                 Importance: 0.02
Variable: temp_2               Importance: 0.02
Variable: friend               Importance: 0.02
Variable: year                 Importance: 0.01
Variable: month                Importance: 0.01
Variable: day                  Importance: 0.01
Variable: prcp_1               Importance: 0.01
Variable: snwd_1               Importance: 0.0
Variable: weekday_Fri          Importance: 0.0
Variable: weekday_Mon          Importance: 0.0
Variable: weekday_Sat          Importance: 0.0
Variable: weekday_Sun          Importance: 0.0
Variable: weekday_Thurs        Importance: 0.0
Variable: weekday_Tues         Importance: 0.0
Variable: weekday_Wed          Importance: 0.0

这些数据明确证明了一些变量比其他变量对我们的问题更重要!鉴于有如此多的变量的重要性为零(或由于舍入而接近零),似乎我们应该能够在不影响性能的情况下去掉其中一些变量。首先,让我们制作一个图表来表示特征重要性的相对差异。我留下了这个绘图代码,因为它更容易理解。

# list of x locations for plotting
x_values = list(range(len(importances)))# Make a bar chart
plt.bar(x_values, importances, orientation = 'vertical', color = 'r', edgecolor = 'k', linewidth = 1.2)# Tick labels for x axis
plt.xticks(x_values, feature_list, rotation='vertical')# Axis labels and title
plt.ylabel('Importance'); plt.xlabel('Variable'); plt.title('Variable Importances');

Expanded Model Variable Importances

我们还可以制作一个累积重要性图,显示每个额外变量对整体重要性的贡献。虚线表示 95%的总重要性。

# List of features sorted from most to least important
sorted_importances = [importance[1] for importance in feature_importances]
sorted_features = [importance[0] for importance in feature_importances]# Cumulative importances
cumulative_importances = np.cumsum(sorted_importances)# Make a line graph
plt.plot(x_values, cumulative_importances, 'g-')# Draw line at 95% of importance retained
plt.hlines(y = 0.95, xmin=0, xmax=len(sorted_importances), color = 'r', linestyles = 'dashed')# Format x ticks and labels
plt.xticks(x_values, sorted_features, rotation = 'vertical')# Axis labels and title
plt.xlabel('Variable'); plt.ylabel('Cumulative Importance'); plt.title('Cumulative Importances');

Cumulative Feature Importances

我们现在可以用它来删除不重要的特征。95%是一个任意的阈值,但是如果它导致明显的低性能,我们可以调整这个值。首先,我们需要找到超过 95%重要性的特征的确切数量:

# Find number of features for cumulative importance of 95%
# Add 1 because Python is zero-indexed
print('Number of features for 95% importance:', np.where(cumulative_importances > 0.95)[0][0] + 1)**Number of features for 95% importance: 6**

然后,我们可以创建一个新的训练和测试集,只保留 6 个最重要的特性。

# Extract the names of the most important features
important_feature_names = [feature[0] for feature in feature_importances[0:5]]
# Find the columns of the most important features
important_indices = [feature_list.index(feature) for feature in important_feature_names]# Create training and testing sets with only the important features
important_train_features = train_features[:, important_indices]
important_test_features = test_features[:, important_indices]# Sanity check on operations
print('Important train features shape:', important_train_features.shape)
print('Important test features shape:', important_test_features.shape)**Important train features shape: (1643, 6)
Important test features shape: (548, 6)**

我们将特性的数量从 17 个减少到 6 个(尽管公平地说,其中 7 个特性是从一周中的某一天的一次性编码中创建的,所以我们实际上只有 11 条唯一的信息)。希望这不会显著降低模型的准确性,并将大大减少训练时间。

重要特性的培训和评估

现在,我们进行与所有功能相同的训练和测试程序,并评估准确性。

# Train the expanded model on only the important features
rf_exp.fit(important_train_features, train_labels);# Make predictions on test data
predictions = rf_exp.predict(important_test_features)# Performance metrics
errors = abs(predictions - test_labels)print('Average absolute error:', round(np.mean(errors), 2), 'degrees.')# Calculate mean absolute percentage error (MAPE)
mape = 100 * (errors / test_labels)# Calculate and display accuracy
accuracy = 100 - np.mean(mape)
print('Accuracy:', round(accuracy, 2), '%.')**Average absolute error: 3.821 degrees.
Accuracy: 93.56 %.**

仅使用 6 个特征,性能遭受 0.12 度平均误差的微小增加。通常,随着功能的减少,性能会略有下降,这必须与运行时间的减少相权衡。机器学习是一个进行权衡的游戏,运行时间与性能通常是关键决策之一。我将很快做一些基准测试来比较这两个模型的相对运行时间(代码见 Jupyter Notebook)。

Model Tradeoffs

总体而言,缩减特征模型的相对精度降低了 0.131% ,相对运行时间降低了 35.1% 。在我们的例子中,运行时是无关紧要的,因为数据集很小,但是在生产环境中,这种权衡可能是值得的。

结论

我们没有开发更复杂的模型来改进我们的随机森林,而是采取了收集更多数据点和附加特征的明智步骤。这种方法得到了验证,因为与基于有限数据训练的模型相比,我们能够将的误差降低 16.7%。此外,通过将特征的数量从 17 个减少到 6 个,我们将运行时间减少了 35%,而准确性仅略有下降。总结这些改进的最好方法是用另一个图表。根据一年的训练数据训练的模型在左侧,使用六年的数据和所有特征的模型在中间,而右侧的模型使用六年的数据,但只是最重要特征的子集。

Model Comparisons

这个例子展示了增加数据量的有效性。虽然大多数人犯了立即转向更强大的模型的错误,但我们已经认识到,大多数问题可以通过收集更多相关数据点来改善。在本系列的后续部分中,我们将研究改进模型的其他方法,即超参数调整和使用不同的算法。然而,在这种情况下,获得更多的数据可能会在投入的时间和提高的性能方面获得最大的回报。下次你看到有人在第一个模型失败后急于实现复杂的深度学习模型,礼貌地问他们是否已经用尽了所有的数据来源。机会是,如果仍然有与他们的问题相关的数据,他们可以获得更好的性能并在这个过程中节省时间!

一如既往,我感谢任何意见和建设性的反馈。可以在 wjk68@case.edu 找到我

改进主题模型的解释

原文:https://towardsdatascience.com/improving-the-interpretation-of-topic-models-87fd2ee3847d?source=collection_archive---------0-----------------------

在我的上一篇博文中,我使用了在令人惊叹的 Scikit Learn 机器学习 Python 库中实现的非负矩阵分解(NMF)和潜在狄利克雷分配(LDA)算法,来在文档集合中查找主题。派生主题的输出包括给主题分配一个数字标签,并打印出主题中的热门单词。通常的做法是简单地打印出每个主题的热门词汇——很多主题模型浏览器、可视化工具和公开网站上的例子都是这样做的!然而,仅仅显示主题中的顶部单词可能不会帮助用户理解每个主题是关于什么的或者确定使用这些单词的上下文。仅显示顶部主题单词不能利用两种算法返回的所有数据。在这篇博文中,我将解释 NMF 和 LDA 返回的矩阵,包括打印出主题中顶部文档的代码,并讨论我改进派生主题解释的想法,特别是当数据集中包含冗长的文档时。

NMF 和 LDA 返回的矩阵

NMF 和 LDA 都采用一个单词包矩阵(没有文档没有单词)作为输入。在单词包矩阵中,文档表示为行,单词表示为列。这两种算法都需要主题的数量( k ),这些主题必须作为参数导出。主题建模算法产生的输出是 2 个矩阵:文档到主题矩阵(无文档 k 主题)和主题到单词矩阵( k 主题*无单词)。大多数主题模型输出仅使用主题到单词矩阵,并显示主题中权重最高的单词。通过显示主题中的热门文档,可以更好地理解主题,这对于 Scikit Learn 来说是相对简单的。

显示主题中的热门词汇和文档

让我们首先编写一个新的 display_topics()方法,它将单词到主题矩阵(H)和主题到文档矩阵(W)作为参数。除了单词(feature_names)和顶部单词数(no_top_words)作为参数显示之外,该方法还需要显示文档集合(documents)和顶部文档数(no_top_documents)。display_topics 方法打印出一个数字索引作为主题名,打印出主题中的热门单词,然后打印出主题中的热门文档。顶部的单词和顶部的文档在返回的矩阵中具有最高的权重。argsort()方法用于对矩阵的行或列进行排序,并按顺序返回权重最高的单元格的索引。

我们需要从 NMF 和 LDA 算法中获得单词到主题矩阵(H)和主题到文档矩阵(W)。词到主题矩阵(H)可以从模型的 component_ attribute 后得到。调用 fit()。将主题转换为文档矩阵有点棘手,但在阅读了 Scikit Learn api 文档后,每个算法都会变得有意义。在算法模型上调用 transform()方法会将主题返回到文档矩阵(W)。下面是从 NMF 和 LDA 获得 H 和 W 矩阵,然后调用 display_topics()方法的完整代码:

一个说明性的玩具例子

一个很小的,我是说非常小的数据集被用来说明一个主题中的热门单词和文档的打印。这个小小的数据集有两个主题,分别是关于用户界面和图形/树。有 9 个非常短的句子组成了这个数据集。下面的代码使用 NMF 和 LDA 查找 2 个主题,在一个主题中打印 4 个热门单词和 4 个热门文档:

来自 NMF 和 LDA 的主题显示如下。NMF 和 LDA 在寻找我们知道的主题方面做得很好。

NMF 话题
话题 0:
树图未成年人调查
-图未成年人 IV:树的宽度与准有序
-树中路径的交集图
-随机、二进制、无序树的生成
-图未成年人:调查

主题 1:
用户时间响应界面
用户对计算机系统响应时间的意见调查
用户感知的响应时间与误差测量的关系
EPS 用户界面管理系统
实验室 ABC 计算机应用的人机界面

LDA 主题:
主题 0:
用户响应时间计算机
-对计算机系统响应时间的用户意见调查
-用户感知的响应时间与误差测量的关系
-EPS 用户界面管理系统
-实验室 ABC 计算机应用的人机界面

主题 1:
树图人类未成年人
-图未成年人 IV:树的宽度和准排序
-图未成年人:调查
-树中路径的交集图
-实验室 ABC 计算机应用的人机界面

主题建模浏览器的构想

当文档很大时,打印主题时显示整个文档是不切实际的。该技术仅对短文档(例如,tweets)或单个段落文档直接有用。一种解决方案是只显示文档中包含任何热门单词的片段。在以后的博文中,我将发布一些 Python 代码来实现这个想法,并提供一个派生主题的上下文关键字视图。将这种想法与可视化工具如 LDAVis T1 结合起来,将会产生一个真正有用的主题模型浏览器,帮助用户解释和探索派生的主题。

改进香草梯度下降

原文:https://towardsdatascience.com/improving-vanilla-gradient-descent-f9d91031ab1d?source=collection_archive---------2-----------------------

应用于训练神经网络的性能改进

简介

当我们使用梯度下降来训练神经网络时,我们会冒着网络陷入局部最小值的风险,在这种情况下,网络会停止在误差曲面上的某个位置,而该位置不是整个曲面上的最低点。这是因为误差曲面不是固有凸的,所以曲面可能包含许多独立于全局最小值的独立局部最小值。此外,虽然网络可能达到全局最小值并收敛到训练数据的期望点,但是不能保证它将如何很好地概括它所学习的内容。这意味着它们容易在训练数据上过度拟合。

为了帮助减轻这些问题,我们可以使用一些东西,尽管没有办法明确地防止它们发生,因为这些网络的误差表面往往很难遍历,并且神经网络作为一个整体很难解释。

随机和小批量随机梯度下降

标准梯度下降算法的这些修改为算法的每次迭代使用训练数据的子集。SGD 将在每次权重更新时使用一个样本,小批量 SGD 将使用预定义的数量(通常比训练样本的总数小得多)。这使得训练进行得更快,因为它需要更少的计算,因为我们在每次迭代中不使用整个数据集。这也有望带来更好的性能,因为网络在训练期间的剧烈运动应该允许它更好地避免局部最小值,并且只使用数据集的一小部分应该有助于防止过度拟合。

正规化

一般而言,正则化是一种通过向表示模型复杂性的损失函数添加一项来惩罚模型复杂性的机制。在神经网络的情况下,它惩罚大的权重,这可能指示网络已经过度适应训练数据。

使用 L2 正则化,我们可以将损失函数重写如下,将网络的原始损失函数表示为 L(y,t) ,正则化常数表示为 λ :

正则化将网络中每个权重的平方和添加到损失函数中,惩罚模型对任何一个连接赋予过多的权重,并有望减少过度拟合。

动力

简单地说,动量将过去权重更新的一部分添加到当前权重更新中。这有助于防止模型陷入局部最小值,因为即使当前梯度为 0,过去的梯度很可能不是,所以它很容易陷入。通过使用动量,沿着误差表面的运动通常也更平滑,并且网络可以更快地穿过误差表面。

对于简单动量,我们可以将权重更新方程重写如下,将 α 表示为动量因子:

也有其他更高级的动量形式,比如 T2 内斯特罗夫方法 T3。

学习速率退火

我们可以调整学习速度,让它随着时间的推移而下降,而不是在整个训练过程中使用一个恒定的学习速度。

最常见的调度具有如下的 1/t 关系,其中 Tμ_0 被提供超参数,并且 μ 是当前学习率:

这通常被称为“搜索然后收敛”退火时间表,因为直到 t 到达 T ,网络处于“搜索”阶段,并且学习速率没有降低太多,之后,学习速率变慢,网络到达“收敛”阶段。这大致与开发探索之间的平衡有关。开始时,我们优先探索搜索空间并扩展我们对该空间的整体知识,随着时间的推移,我们过渡到利用我们已经发现的搜索空间中的好区域,并缩小到特定的最小值。

结论

这些是改进标准梯度下降算法的一些方法。当然,这些方法中的每一种都会向您的模型添加超参数,因此会增加调整网络所花费的时间。最近,更新的算法如亚当阿达格拉德、和阿达德尔塔如雨后春笋般涌现,它们使用了其中一些技术以及许多其他技术。他们倾向于在每个参数的基础上优化,而不是全局优化,因此他们可以根据个人情况微调学习速度。他们在实践中往往工作得更快更好;然而,要正确实施它们要困难得多。下图说明了同时工作的上述每个梯度下降变化。观察到更复杂的版本比简单的动量或 SGD 版本收敛得更快。

马尔可夫鼠

原文:https://towardsdatascience.com/in-5-mins-the-markov-mouse-a4f7a38289fb?source=collection_archive---------1-----------------------

什么是马尔可夫链?

马尔可夫链是一种描述一系列可能事件的模型,其中每个事件的概率仅取决于前一个事件达到的状态,即如果我们可以仅根据流程的当前状态对其未来进行预测,就像了解流程的完整历史一样,那么该流程被称为“马尔可夫流程”。让我们带着一个问题直接进入它。

问题:

让我们模拟一只老鼠在迷宫里走来走去。迷宫是一个包含九个房间的封闭空间,房间之间有门道相连。

THE MOUSE AND THE MAZE

Mouse snacking before entering the maze !

有通向相邻房间的门,即有门:

从 1 到 2 4

从 2 到 1 3 5

从 3 到 2 6

从 4 到 1 5 7

从 5 到 2 4 6 8

从 6 到 3 5 9

从 7 到 4 8

从 8 到 5 7 9

从 9 到 6.8

我们假设鼠标是“马尔可夫鼠标”,即鼠标随机地从一个房间移动到另一个房间,其中鼠标到达下一个房间的概率仅取决于它当前所在的房间,而不取决于它如何到达当前房间。

下面是我们可以用提供的信息创建的转移概率数据,称为转移矩阵:

Transition Matrix

它为我们提供了鼠标从源房间到目的房间的概率。例如,如果鼠标出现在房间 1,它可以以 1/2 的概率去房间 2,或者它可以以 1/2 的概率去房间 4。同样,如果老鼠在 2 号房间,它可以去 1 号、3 号或 5 号房间——每个房间都有 1/3 的概率。

符号:

转移矩阵用 P 表示。左上角的矩阵元素用 P(1,1)表示,而右下角的矩阵元素是 P(9,9)。示例:

P(1,1) =鼠标从房间 1 移动到房间 1 的概率= 0

P(1,2) =老鼠从房间 1 移动到房间 2 的概率= 1/2

P(3,6) =老鼠从房间 3 移动到房间 6 的概率= 1/2

重申马尔可夫性质,P(2,3)是假设鼠标从状态 2 开始,鼠标下一步到状态 3 的概率。马尔可夫性意味着概率不依赖于早期的历史。

现在我们已经对流程进行了建模,让我们来看看两个有趣的问题:

问题 1

鼠标从 1 号房间出发,经过两次跃迁到达 6 号房间的概率是多少?

解决方案 1

让我们从直觉开始这个问题——在第一次转换中,鼠标可以从状态 1 进入状态 2 或 4。

如果鼠标进入状态 2,那么在第二次转换中,它只能进入状态 3、4 或 5。

如果鼠标进入状态 4,那么在第二次转换中,它只能进入房间 4、5 或 7。

因此,鼠标不可能在两次转换中从房间 1 到达房间 6。老鼠从 1 号房间出发到达 6 号房间的概率为 0。

问题二

鼠标从 2 号房间出发,在两次转场中再次到达 2 号房间的概率是多少?

方案二

从房间 2 开始,鼠标可以通过以下方式再次到达房间 2:

一、 2 →1 → 2

→概率= P(2,1)*P(1,2) = 1/3 * 1/2 = 1/6

二。 2 → 3 → 2

→概率= P(2,3)*P(3,2) = 1/3 * 1/2 = 1/6

三。 2 →5 →2

→概率= P(2,5)*P(5,2) = 1/3 * 1/4 = 1/12

将所有的个体概率相加,我们得到 1/6 + 1/6 + 1/12 = 5/12。因此,如果鼠标从房间 2 开始,它可以以 5/12 = 0.4167 的概率在两次转换中再次到达状态 2。

解决上述两个问题的另一种方法是矩阵乘法。如果我们将转移矩阵提升到 2 的幂(P ),我们将得到转移矩阵或鼠标在两次转移中从任何其他房间到达任何房间的概率。下面是 P 矩阵。

P² Matrix

从上面的矩阵我们可以看到,在两个跃迁中 P(2,2) = 0.4167P(1,6) = 0 ,和我们上面计算的一样。

这是理解马尔可夫链的一个很好的起点,当我们更进一步时,我们可以回答更有趣的问题,例如:

如果从 1 号房间开始,老鼠会在每个房间呆多长时间(持续时间的百分比)?

如果有无限个跃迁,我们会达到稳态吗,它会是什么样子?

从一个特定的房间开始,在 100 次转换中,鼠标最有可能出现在哪里?

————****—————

在 LinkedIn 上连接

资料来源:http://www.columbia.edu/~ww2040/4701Sum07/MarkovMouse.pdf

在一场人工智能与内容营销者的对决中,谁将赢得未来?

原文:https://towardsdatascience.com/in-a-ai-vs-content-marketer-showdown-who-will-win-the-future-22b737213868?source=collection_archive---------11-----------------------

Photo by Pamela Saunders on Unsplash

2017 年 6 月底,1300 名行动号召会议与会者聚集在加拿大温哥华,与 Unbounce 的人工智能机器正面交锋,看谁能最好地预测登陆页面的性能。参与者将查看 Unbounce 的 204 个登录页面中的一个,分析该副本,并确定哪个将获得高于平均水平的转化率。与此同时,Unbounce 的算法也被设置为做同样的事情。

在 17,000 名参与者输入后,结果被记录下来。Unbounce 的人工智能(AI)算法在 80%的情况下正确预测了高于平均水平的转化率,而参与者的平均正确预测率为 50%。

问题是,在这些与会者中,有一些世界上最聪明的营销专家,他们来自顶级公司,如 Adobe、Mirum,甚至 Unbounce 自己的 Oli Gardner。CTA 会议发言人 Joel Klettke 的专长是转换文案,他获得了 57%的正确预测率(以人类标准衡量,这是一个令人印象深刻的成绩),远远低于算法的成功率。他们每个人都被耍了。Unbounce 的下一个前沿:使用机器视觉创建一个类似的算法来预测网站设计转化率。

尽管如此,其他品牌也在创造类似的算法来预测图像转换率。Visit Utah 的营销团队与 Cortex 合作,Cortex 是一种人工智能算法,可以对图像元素进行评级,以发现哪些元素可以在目标受众之前产生更大的参与度。当该品牌需要吸引寻求滑雪体验的游客时,该算法通过咨询犹他州的营销人员,告诉他们滑雪者更喜欢只有一个人的场景、干净的雪道、蓝天和松树,帮助将转化率提高了 23% 。

AI 算法比人更会营销吗?那么,这给创意内容营销者留下了什么?AI 能在多大程度上比创意营销人员更好地完成内容营销工作?虽然不总是在摊牌活动中,但 Unbounce 和 Cortex 并不是唯一一个让创意营销人员与人工智能算法对抗,看谁能更好地完成设计或文案工作的公司。让我们来看看其中的一些,以确定创意营销人员在人与机器的世界中所处的位置。

让我们看看文案如何对抗人工智能…… 在最近的一项研究中,焦点小组被要求给几份文案打分。参与者不知道的是,有些是由人工智能生成的,有些是由人类撰稿人生成的。最终,机器生成的内容在客观性和可信度方面表现良好,但在参与度方面表现不佳——易读、有趣、写得好、连贯和清晰。

尽管如此,Gartner 预计 2018 年总业务内容的 20%将由机器生成。然而,“商业内容”和“营销文案”之间的差异,为人工智能何时应该用于内容创作和机器生成内容的总体目的提供了关键的见解。

“人工智能驱动的内容生成可以为金融机构生成详细的报告,处理海量数据,并将其转化为逻辑清晰的文本。但是,如果你要求它写一个新鲜的、引人注目的故事,抓住读者的想象力,它将会悲惨地失败,“ Bill Zeintek SEO 专家,搜索引擎优化专家,以及拥有深厚足迹的数字营销策略师说。

用于报告目的的文本,例如业绩报告和股票交易摘要,其中“值得信赖”和“客观”等指标是关键,如果是机器制作的,会做得很好。自动化生产流程意味着文案人员消除或减少耗时的收集、编译、标准化、清理和汇总大数据的手动流程。

但是,旨在吸引受众的营销应该写得很好,清晰,有趣,易读——换句话说,它需要人性。

Photo by Headway on Unsplash

也许人工智能驱动的内容设计会更好…… 这是 Grid.io 的首个营销视频中的脚本:“你的网站应该反映你是谁。而且做起来应该很好看。当然,你可以自己造一个。但是设计、开发、拖放……如果你能做你关心的事情,让其他事情……发生,不是更好吗?网站直接自己做不是更好吗?这就是所谓的网格。”

该品牌声称,使用一个名为 Molly 的人工智能机器人,她可以创建个性化的高质量网站,而你则可以运营你的业务。只需选择调色板或上传品牌标志,Molly 就能为您的企业打造完美的数字家庭,既能反映您的产品,也能反映其团队。听起来好得难以置信?确实是。

最终,它的局限性让许多用户希望得到更多。测试用户认为它需要一个更加个性化的展示来区分它,从而吸引访问者,并且它作为一个作品集而不是一个品牌网站。用户开始设计论坛来展示他们的发现:“终于看到 grid.io 网站了。我认为你们的工作是安全的。”

尽管如此,人工智能在支持图形和网页设计师方面取得了长足的进步。Adobe Sensei 在 Adobe Summit 2017 上首次亮相了他们新的人工智能设计功能,并展示了其尖端的图形设计和网页设计功能的原型。

虽然它不能为你做所有的图形设计,但它做了一些令人印象深刻的工作,包括基于图像和图像组件识别的自动照片裁剪,基于设计师图像数据库的元素推荐;图像元素交换;消除难看的图像成分;以及设计建议,如布局、颜色和照片尺寸。

虽然它不会从头开始想象和创建界面或用户体验设计,但它将通过确定哪些照片和副本可能会吸引一小部分用户来支持内容个性化,并实时将它们替换为自定义演示。

结果:“人类增强设计”说 Cedric Huesler,Adobe 营销云的主管,他参与了原型的工作。

尽管最初有些不信任,但有创意的营销人员从人工智能那里获得一些帮助是安全的。
Jesus Ramirez,Adobe 制作杰作项目的参与者,解释了人工智能对创意营销人员的作用:“当相机被发明出来时,人们认为我们不再需要画家了。对于人工智能,我想有些人会有这样的印象,即计算机将完成所有的工作,但归根结底,它只是另一种工具。”

“只是另一个工具,”的确。像 Unbounce 和 Adobe 这样的案例研究表明,尽管有参与限制,创意内容营销人员仍然可以依靠人工智能来增强自己的优势。波长分析和数据分析师的创始人 Natalie Robb 认为,人工智能将最好地帮助内容营销者创造更好的内容,并更有效地使用这些内容。

她表示:“内容营销人员将不再面临一些手工劳动。”。手工劳动,如裁剪图像、交换元素、总结某个主题的主导思想、综合数据、预测副本的转换率;在内容颜色、布局或图像之间进行选择;还有更多。

那么,创意营销人员该何去何从?娜塔莉总结道:“内容营销者必须与技术一起发展,成为数据和通信的大师,但他们不会被取代。”需要人类的创造力来制作有趣的、精心制作的、连贯的、整体吸引人的内容,以供目标受众消费。

使用 YOLO 和 TensorFlow.js 的浏览器内对象检测

原文:https://towardsdatascience.com/in-browser-object-detection-using-yolo-and-tensorflow-js-d2a2b7429f7c?source=collection_archive---------3-----------------------

Original image

前一段时间,我花了几个晚上玩最先进的物体检测模型 YOLO,这对那些每天对机器学习感兴趣的人来说肯定是已知的。最初写于Darknet——开源神经网络框架——YOLO 在定位和识别图片上的物体的任务中表现非常好。由于我对 TensorFlow.js 感兴趣已经有几个星期了,我决定看看 YOLO 将如何处理浏览器内计算的局限性。完整的源代码以及我以前的 TF.js 项目可以在 GitHub 上找到。如果你想玩演示版,请访问“我学习机器学习”项目网站。

注:我还推荐阅读最近出现在《走向数据科学》上的一篇文章,这是我这个项目的起点。我将尽量不重复其中包含的信息,而是拓宽其中提出的主题,并希望用我的经验丰富它。

老枪暂时…

几个月前,《YOLO》第三版发布了。我有机会用 Python 测试它的功能,我非常希望能在我的小项目中使用它。在花了两天时间浏览了各种存储库、论坛和文档之后,结果发现现在还不可能这样做。如前所述,要在 TensorFlow.js 项目中使用原始 YOLO 模型,您必须首先进行两步转换。第一步将我们从 Darknet 带到 TensorFlow / Keras,第二步将我们的模型转换成 TensorFlow.js 可以理解的形式。不幸的是,由于 YOLOv3 在其架构中引入了新的层,并且像 Darkflow 或 YAD2K 这样最受欢迎的工具都不支持它们向 TensorFlow 的转换,我们现在必须坚持使用旧的工具。将来,我肯定会回来把 v2 换成新的型号。

让我们把手弄脏吧

将模型与我们的应用程序连接起来的过程是非常标准的,在本系列的第一篇文章中已经详细描述过了。然而这一次,有更多的脏活等着我们,主要涉及预测前后的数据处理。

F 首先,我们的模型必须要有一个适当维数的张量——确切地说是——【1,416,416,1】。通常情况下,这些值与训练图像的尺寸和批量大小有关。这种方形输入是有问题的,因为通常图片不会以这种方式裁剪。剪切图像以满足上述条件,会带来丢失有价值的数据的风险,这可能导致对图片中的对象的错误识别。为了限制这种不良影响,我们使用流行的 smartcrop 库,它通过选择最有趣的片段来框住照片。下图是上述机制的一个很好的例子,也是一个成功的预测,如果没有这个技巧可能会失败。最后,我们归一化每个像素的值,使它们在 0 和 1 之间。最后一点对我来说特别重要,因为我花了将近两个小时寻找导致我的模型性能如此糟糕的 bug。迟到总比不到好…

Original image

作为每次预测的结果,模型返回具有相当奇怪维度的张量[1,13,13,425]。这些谜一样的数字在这篇文章中被有效地揭露出来,这篇文章完美地解释了在 YOLO 的引擎盖下正在发生的事情。我把它推荐给任何想理解这个美丽算法的人。我们现在的任务是将这个张量转换成图片中物体周围整齐的矩形。这一步非常广泛,很容易成为另一篇文章的主题。在不涉及太多细节的情况下,我要说的是,我们将使用诸如交集超过并集和非最大值抑制之类的技术来去除不太可能的结果,并将剩余的具有高概率的矩形聚集到检测到的对象的边界框中。我建议查看包含这些计算的源代码。

Original image

不同设备之间的不一致性

在完成了 alpha 版本的工作后,我决定在我的朋友面前展示我的新玩具。通过这种方式,我非常意外地发现,该模型在不同的设备上可以表现得非常不同。检测到的对象的类别不会改变,但是它们的概率值可以改变几十个百分点。在下面显示的模型中,阈值被设置为 0.5。这意味着所有概率较低的对象都将被过滤掉。这就是左下方图片中斑马的命运,它的概率下降了 25%以上。TensorFlow.js 仍然是一个年轻的库,正在与某些问题作斗争——目前有几个问题与他们的 GitHub 上的不一致性有关。显然,在每台设备上进行完全相同的计算并不容易。我为 TensorFlow.js 团队祈祷,希望他们能解决所有这些问题。

Original image

速度杀人

F 最后,我想就 web 编程的一个重要方面(尽管经常被忽视)写几句话,那就是应用程序的速度。将 YOLO 转换成 TF.js 可以理解的形式后,创建了 20 多个文件,总共大约 45 MB。在缓慢的 3G 连接上加载如此大量的数据需要近乎神圣的耐心。如果我们决定在生产中使用这种类型的解决方案,这当然值得注意。

寥寥数语

TensorFlow.js 仍然非常年轻,但它给了我们开发人员和日期科学家惊人的可能性。你应该知道我提到的某些限制,但是给 TF.js 一个机会是值得的,因为在我看来,它的真正能力还没有被开发。

在我们信任的代码中

原文:https://towardsdatascience.com/in-code-we-trust-7620207f4dfe?source=collection_archive---------16-----------------------

在机器学习项目中试验软件开发管道——第二部分——管理您的代码。

正如我在我的第一篇文章中提到的,为了改变我们编写代码的方式,从某种自制的过程到更专业和一致的过程,为软件开发者提供适当的基础设施和工具是一件好事。

考虑一个安装和维护此类工具的集中环境会有所帮助。这就是我之前命名的“C.I .环境”——c . I .代表“持续集成”,这个术语强调以自动化的方式生产最终的集成应用程序[1]。这样的环境也可以被视为一种有组织的软件工厂——这里的术语从传统制造业获得灵感——一台完美的润滑机器,有助于提高个人生产率,减少每个人出错的机会。简而言之,帮助开发人员用最少的努力产生好的代码。

到目前为止还不错,但是…这在实践中意味着什么呢?

好的,正如你所知道的,我在这里的目标是回顾一下为我们的代码生产管道选择工具时的一些选择和选项。我将主要关注开源工具:尽管围绕[2有非常好的商业和专有解决方案,但我更喜欢向每个人免费提供选项(我来自意大利北部的一个小镇,那里的人以吝啬闻名[3;-) ).

回到我们的环境,以及我们需要在其中放置什么样的东西:在非常基本的层面上,事情实际上可以变得更复杂,我们需要工具来:(a)管理源代码,提供代码模板,处理源代码版本等,(b)管理构建过程,将源代码转换为二进制(可执行)工件,处理依赖关系,版本管理和存储生成的组件等。最后但同样重要的是,(c)为这些组件的最终配置部署提供仪器。

正如我们所看到的,当涉及到某种模型训练的 ML 项目时,实际上在(b)和(c)之间有一个进一步的步骤,这包括产生训练好的模型。即某种新的人工制品,它以某种紧凑的形式存储模型参数,以供以后使用。

但是让我们按顺序处理事情:第一点——源代码控制和版本控制——是非常重要的一点。在修改后保存代码版本是一个基本的习惯。它提供了一种在变更发生时监控这些变更的方法,它协调不同人的贡献并跟踪对代码所做变更的所有权,它提供了已完成工作的备份,并允许在某些变更引入错误或故障的情况下恢复工作版本。不错,不是吗?一般来说,某种形式的版本控制不仅应该应用于应用程序代码,还应该应用于二进制代码、ML 模型、文档、配置和脚本。

总之,版本 一切

当谈到对源代码的控制和版本控制时,首先想到的是 Git[4]。当然,还有其他选择,但是可以肯定地说,现在 Git 可以被认为是绝对的赢家。

众所周知,Git 是一个分布式版本控制系统:与 CVS 或 SVN 等其他工具不同,我们原则上不需要一个集中的存储库。不过,在实践中,出于协调和归档的目的,最好有一个中心位置,供开发人员推送他们的代码更改。一种选择是利用一些基于 Git 的在线公共存储库,如 GitHub 或 Bitbucket,但私营公司通常会在将源代码放在自己公司堡垒的安全墙之外时感到紧张。

您可能更喜欢在自己的本地服务器上托管源代码管理中央存储库。只是将 Git 项目的裸存储库放在一些共享文件夹中——通过 shell 命令访问——是一种选择,但是如果您想要一些不错的 UI 工具,可以尝试 Git lab[5];我过去用过它,它工作得很好。

这里的好消息是,对于基于机器学习的软件项目的具体情况,我没有找到任何改变版本控制工具或工作流的具体原因。代码就是代码,不管你的代码是用 Angular 实现漂亮的用户界面,还是用 Java REST 服务包装 JDBC 数据库查询,还是用 Tensorflow 定义深度神经网络架构的 Python 代码,Git 都能很好地工作。

那么,下一步呢,管理构建过程,将您的源代码转换成二进制(可执行)产品?对于这一点,唯一依赖你的 IDE 的项目配置和构建机制[6]通常不是一个好主意,最好使用一些特定的构建和依赖管理工具。与 ide 不同,构建工具通常是基于 shell 的,这意味着它们可以通过基于文本的脚本和配置文件来管理。然后你的整个构建过程可以被组织、存档、版本化等等… 版本化一切,记得吗?

构建和依赖管理工具将您的源代码编译成二进制代码,跟踪包的依赖关系,并自动统一地管理它们。企业规模的软件项目通常有大量的依赖项,手工管理它们通常会导致真正的噩梦。

构建工具的问题是,当选择一个工具时,您必须确保它适合您的技术堆栈。因为我的正常工作主要是基于 Java 的项目,所以我最常用的工具是 Maven[7]

当我开始使用 Tensorflow 和 Keras 代码时,我必须找到一种方法来使我的 Python 代码适应现有的构建工作流(或者反之亦然)。Python 有自己的构建和依赖管理工具,基于 distutils 和 setuptools,挑战是将这些与我们的 Maven 工作流集成。

Maven 是一个相当灵活的工具,允许通过基于插件的系统扩展其功能。我在网上搜索了一些与 Python 相关的插件:实际上有一些可用的插件,既有 Python 专用的插件,也有使用通用的 exec-maven-plugin 来启动 Python 子进程,调用 setup . py[8]——但最终,我决定采用一种不同的方法。

我面临的问题是一个更普遍的问题的实例,被称为多语言编程。也就是说,使用不同的编程语言来建模应用程序的不同部分,每种语言提供性能、可用的库或 API、表达能力等。最适合每个特定的功能或软件层。

所谓的微服务架构的最近趋势[9]使得这种编程非常流行:你可以在 Python 中有一个服务层来服务 ML 模型(想想 TensorflowServing),一个 Java 服务的业务逻辑层和一个提供用户界面功能的 typescript/Angular 应用层。根据应用程序的需要,您可以考虑添加任意多的语言。请记住,在任何完整的现实世界应用程序中,提供机器学习能力的功能可能只是许多交互部分中的一部分。

在这样一个混乱的环境中,我没有试图让一个像 Maven 这样的工具适合所有的技术,而是回归到为不同的项目使用不同的工具:Maven 用于 java 项目,setuptools 用于 python,Angular cli 用于 Angular 项目等等。然后,为了给操作提供统一的结构,一组 bash 脚本将通过为每种给定的技术开发适当的工具来实现每个开发阶段。一款打造。sh 脚本,一个 test.sh 脚本,一个用于主要开发生命周期阶段的 deploy.sh 脚本,以及像 setver.sh 这样的用于更改当前构建版本的支持脚本(例如,在 Maven 的情况下,这个脚本编辑 pom.xml 文件),等等。

用于生成和初始化项目代码的项目模板(如 Maven 原型或 Python cookiecutter 模板)将在主项目文件夹下包含一个./scripts 子文件夹,其中包含给定技术的脚本的正确版本,这样开发人员就不必担心调用了什么,只要。/scripts 文件夹包含在系统路径中。我不知道这种组织方式是否代表了当前多语言编程开发的最佳实践,但在我的案例中,它工作得相当好。

关于我在本文开头列出的清单——要放入 CI 环境的东西的清单——我们仍然需要讨论管理生成的二进制文件、配置和部署它们的工具。

在这里,我们也有这样的问题,不同的语言使用不同的工具会导致我们的应用程序组件产生异构的、不兼容的二进制格式。(我们可能有。java 组件的 jar 文件,Python 的 wheels 等等)。我只是预计,为了解决这个问题的一部分,我已经在一个叫做 docker 的漂亮的小工具中找到了宝贵的帮助,但是由于我已经写得比我计划的多,我将把它留到另一天。

像往常一样,我希望你觉得这篇文章有趣!

参考文献和注释

[1] 我们在这里可以使用的其他类似术语是连续部署,或连续交付(c . d .);或者是 DevOps 环境,在这种环境中,重点依次放在应用程序组件的部署及其向最终用户的持续供应上。我对这些术语的使用并不是非常精确或正式,我只是想表达一个一般概念,即某种计算环境是在公司层面上建立的,它提供了管理我们的软件生命周期所需的所有工具。

【2】 吉拉软件为例

https://www . quora . com/Why-do-Italians-say-the-Genovese-are-stiggy;-)

4】https://git-scm.com/

https://about.gitlab.com/

[6] 当然,也有例外。例如,尽管我已经有几年没有使用微软技术了,但我知道一般来说,构建过程与。网游世界

https://maven.apache.org/

[8] S ee 例如shining panda的解决方案,它使用通用的 maven exec 插件来包装对 Python 的 setuptools 的调用。

[9] 为了更好地解释微服务架构,你可以看看马丁·福勒的 文章——引自那里:

微服务架构这个术语是在过去几年中出现的,用来描述一种将软件应用程序设计成可独立部署的服务套件的特殊方式。虽然这种架构风格没有精确的定义,但围绕业务能力、自动化部署、端点智能以及语言和数据的分散控制,组织有一些共同的特征。”

或者查查山姆纽曼的书 建筑微服务

为廉价的数据科学辩护

原文:https://towardsdatascience.com/in-defense-of-cheap-data-science-f630f248d400?source=collection_archive---------3-----------------------

回到 2014 年,在我加入世界银行后不久,我带着“ Iamthecode ”去了塞内加尔。其中一个目标是举办数据科学研讨会和培训。尽管我很兴奋能参加最新最棒的遥感、数据管理、卫星图像的培训,但我没能意识到一个非常基本的关键。甚至想起来都很尴尬:我那花哨到爆的 MacBook Pro 笔记本电脑——价值他们三年的全部平均收入——。一半的人没有笔记本电脑(在他们的工作单位/大学只有台式机),而那些有笔记本电脑的人有几年前的旧电脑。

几个月后,我们的团队设法采购了三台游戏笔记本电脑(与 IT 部门的对话并不容易)。在我们合作的国家,它们同样超出了大多数人的承受能力,但游戏笔记本电脑具有最佳的性能/成本/重量。例如,我们用它们在科索沃或阿根廷农村进行无人机地图处理(由于连接速度的原因,云处理不适合),但我们也用它来训练神经网络和其他数据科学的东西。

Processing drone cadastral maps in Kosovo, pulling all available things with CPUs and GPUs.

数据科学对发展和发展中国家有着巨大的好处。开始时,分析通常是最基本的,而且是基于数量和质量都大大降低的可用数据。最重要的是,解决这一数字鸿沟挑战的紧迫性与数字红利的丧失相结合。事实上,“数字红利”是 2016 年发布的世界银行报告的标题(我记得和作者讨论过这个话题)。如果数据科学在发展中发挥作用,我们创新实验室的目标之一就是用发展数据在典型的发展基础设施中证明这一点。

许多数据科学工具都是免费的,可以在普通的笔记本电脑上使用。Linux、python、git、qgis、perl、bash……几乎在任何计算机上都可以做很多事情。然而,我看到越来越多的昂贵工具激增(不仅是许可成本,还包括最低性能或假设快速连接)。像 Hadoop、张量流、AWS 红移、ArcGIS 等工具……

廉价数据科学是优雅地退化到一台普通计算机和糟糕的连接的设计原则。如果花的时间比较多,或者需要捆绑上网需求,也是可以的。重要的是,你不要忽略那些没有 MacBook Pro 或互联网连接来构建强大的 AWS EC2 实例的人。

今年 1 月我离开银行的时候,原因之一就是尽可能地从“另一边”了解发展。我扔掉了我的 MacBook,我买了最便宜的笔记本电脑,我可以带着它旅行,并且可以完成大部分工作。一台不算太贵的 300 美元 Thinkpad。仍然大约是 MacBook 的 10 倍。此外,我还买了一个 40 美元的覆盆子酱,看看我能从中榨出多少。

300\(, 3000\), 100$ and 40$ computer. How much Data Science could you do with each?

从那以后,我用这台“廉价笔记本电脑”完成了我所有的个人和职业用途,包括编码咨询、去不丹培训和建立一个物流系统,或者在 T2 卫星公司处理巨大的卫星图像。有可能用非常少的资源、硬件和连接来交付惊人的专业级数据科学产品。这也迫使我求助于有用的技巧,提醒我当互联网又慢又贵的时候,事情是如何回来的。使用 USB 脱机安装,设置 intranet 和 torrent 服务。Git 到内部网机器上,而不是 github 上…

我认为,做廉价数据科学也越来越难了。一些轶事证据。回到不丹,我想与团队一起利用的大部分数据科学在线课程都使用花哨的多媒体视频和套接字来进行远程浏览器内代码执行。在我们的环境中,这是不可能的,因为带宽有限,而且在办公时间也很拥挤。我不得不求助于又老又长的 pdf 手册(通常是 LaTex)。了不起的人fast . ai特别乐于助人,关心帮助我解决这个问题。尽管如此,在我看来,许多最新的数据科学进展使用的框架无法在运行缓慢的计算机上运行。事实上,许多通用工具,如 nvm、npm、docker,都没有容易打包的命令来进行离线分发。如果有 4 个人安装相同的软件,那么您需要从远程资源为每台笔记本电脑下载每个小的子依赖项。

我担心数据科学的进步正在创造一个不必要的更高的准入门槛。通常的计算机设置变成了最小设置。我们可能遗漏了一部分潜在的数据科学家,他们的生活可能会发生最大的变化,他们的工作会改变最需要的人的生活。

讽刺的是,我用今天刚买的 MacBook 给你写信。虽然道德上让我很痛苦,但我也必须承认,这种设置可能让我损失了大约 30%的效率。其他人,尤其是那些和我有同样电脑的人,可能不同意这一点。如果我花更多的时间调整和维护它,我可能会有同样的效率。也许这就是我的观点。我想专注于交付价值,而不是维护系统,如果我能避免的话。我不知道。在数字红利框架中,我不能错过这 30%的效率。

我不知道这是否意味着我游说“廉价数据科学”的实验失败了。这无疑迫使我展现了我在塞内加尔或我们购买游戏笔记本电脑时才瞥见的意识。我真的希望阅读这篇文章至少能帮助你考虑你运行的软件,你构建的软件,是否会优雅地降级。

捍卫简单,数据可视化之旅

原文:https://towardsdatascience.com/in-defense-of-simplicity-a-data-visualization-journey-86676bd05c57?source=collection_archive---------2-----------------------

我职业生涯的最后 8-9 年一直专注于数据可视化,这给了我足够的时间来发展我在这个领域的一两个理念。我说两个,但我真正指的是大约六个半心烦意乱的职业危机产生时刻(持续几周或几个月),询问我想从这个领域中得到什么,我正在做的事情是否是“正确的事情”,以及我是否应该做其他事情。

鉴于 Elijah Meeks 关于为什么 数据可视化从业者正在离职的深思熟虑的文章,我认为分享我的道路可能是值得的,因为我所坚持的哲学(在这篇文章的标题中巧妙地掩饰为“简单”)是我多年来感觉最好的哲学。

觉醒

Always be learning (source)

首先认识到数据可视化是一个领域。这看起来很令人惊讶,但是我们并不是生来就有这种知识,也没有人在我没有问的情况下教给我这方面的知识。接下来的几年只是努力跟上。学习数学,学习不同类型的可视化等等。我没有自己的声音,我真的只是试图弄清楚什么是什么,如何建立它,如何做好工作。我做了很多坏事。很多原型都被扔掉了,我真的很伤心,因为我还不知道如何在这个领域评价“好”。这也是一段时间以前的事了,所以例子的基数要小得多。我选择阿曼达·考克斯作为我职业生涯中的英雄,并继续前进。

想成为数据艺术家的人

The struggle is real (source)

选择一群才华横溢的人作为我的榜样,既鼓舞人心,同时又令人沮丧。我刚刚了解了如何做这些事情,而这些人在提出表达数据的创造性方法方面比我强得多,比如 T2。我刚刚开始能够选择正确的方法并建立它们。我涉足了一些兼职项目,试图做出一些创造性的数据解释,从没有真正展示任何东西的数据中制作东西,只是总体上推动自己尝试将一点点艺术-东西-东西带到我的实践中。不过,我不认为这些努力是成功的,因为我似乎从未找到任何能引起我共鸣的东西。不知何故,这些东西都没有让我展示的人产生任何感觉。他们可能会喜欢,但仅此而已。我不满意,因为我仍然不知道为什么我在做这件事。

中场休息

BRB DataVis (source)

厌倦了我的缺乏进展和仍然缺乏发言权,我决定从数据可视化中休息一下,只是更好地在 web 应用程序上工作。他们当时风靡一时(还记得 Backbone.js 出来的时候吗!?)我很兴奋能在网络上制作有生命和表演性的东西。

helllooooooooo 数据新闻

I LUV DATA JOURNALISM (source)

我很幸运地与伦敦的《卫报》签订了合同,这是我在 Bocoup 的第一个项目之一。突然间,我和一组优秀的数据可视化工具一起研究一些真正有意义的故事。我们与全球发展办公室合作,他们既有有趣的故事要讲,也有一个伟大的使命,那就是揭示否则可能不会得到足够报道的重要故事。在我知道之前,我必须思考如何把我的视觉化编织在一起;胶水是什么。有一个更高的目的,那就是以一种有意义的方式将它们放在一起,并与广泛的人群(新闻消费者)交流。)这是一次令人谦卑的经历,也教会了我很多。它教会了我快速迭代设计,扔掉东西,制造可重用的组件,能够快速编码,这个故事是国王。我为我们做出的作品感到骄傲,但我有一种挥之不去的感觉,也许有些东西我们没有做到。数据中有一些很有说服力的妙语/趣闻,但是我们做的探索性交互需要一段时间才能达到,或者需要用户交互(嘿,还记得 steppers 吗?!)我们不确定用户在做什么。我担心我们采取的方法不是最好的,但我不知道什么是最好的(因为我不是记者)。

工具制造时代

Tools are important (source)

当我试图弄清楚我如何适应或不适应这个新闻世界时,我很快发现很多东西都不见了:紧迫的截止日期需要一些可重用性或妥协,我不喜欢这样做,不断增长的数据类型和规模允许进行更复杂的分析,而大多数新闻编辑室不一定具备这种技能。在 Bocoup,我通常是一个问题解决者,比起努力成为一名记者,我更容易投入到这个世界中,努力为我的新闻同行建立工具和资源。我还一边在远处佩服他们,一边想办法偷他们的招数。

在这一点上,我绝对是一个新闻迷。我正享受着由《纽约时报》等媒体催生的交互式图形的黄金时代,我正通过管道把它们传递给我同样投身于政治的父母。然而有趣的事情发生了——它们没有粘在一起。我父母没收到。现在,你可以把这个扔给我的父母,他们已经老了,但是我的妈妈是一个音乐老师,她花了一生的时间来阅读我甚至不能解析的乐谱,我的爸爸是一个机械师,他知道如何从 80 年代的示意图中修复不可思议的机器。然而,他们就是不喜欢这些互动,他们只是不停地问我“这是什么意思?”。在某个时候,我开始截图并发送长篇解释,然后跳过所有截图,只关注对话。那时我意识到,我不想做大多数人都做不到的东西。虽然我很爱他们,但我的同修并不是我的主要观众。

数据和设计颠覆了视觉效果

Data IS beautiful (source)

之前的经历让我很快意识到两件事:

  1. 如果人们想要一个故事,给他们一个故事。不要浪费他们的时间去得到它。
  2. 如果人们有他们想要解决的问题,尽你所能做最简单的事情来帮助他们解决问题。

这两个原则意味着一些事情。

  1. 首先,我必须更好地进行数据分析。大多数时候,显示单个数值计数、中位数和平均值实际上并不能解决任何人的问题。我在大学里上的那堂统计学课(完全通过 powerpoint 讲授,讲的是抛硬币)并没有起到什么作用。我钻研了现在被称为数据科学的世界,以了解我可以在数据中找到答案的所有方法。我仍在学习很多东西,我很幸运有吉姆·瓦兰丁汉姆在身边帮我学习。
  2. 对于我来说,要学习如何让用户使用和理解,我必须开始思考感知、心理学和人们在与我制作的任何东西交互时的用户体验。我学到的很多东西并不支持制作复杂的视觉效果的愿望。我们都知道制作一个毛团状的网络图通常是没有帮助的——好吧,到目前为止科学也同意这一点。

我开始从优秀的书籍中学到更多关于人类感知的知识,比如科林·威尔的信息可视化:设计感知。当时,我还遇到了莱恩·哈里森,他在数据可视化感知方面的工作已经改变了实践(这个星期我能引用这篇论文多少次?!).我也开始和 Bocoup 非常优秀的设计师一起工作,比如 Jess Klein ,他开始提醒我可用性和有用性是王道。制作大多数人无法理解或不知道如何使用的界面有什么意义?如果是小说又怎么样?如果对大多数人来说没有意义,那么我真的没有解决任何人的问题。

问题解决(又名当前哲学)

Bridge crossing at its best (source)

这些天来,我放松了对自己作品视觉效果的要求。当然,得到业内同行的认可确实很棒,但为小诊所从业者构建一个真正简单的工具来首次以数字方式跟踪他们的患者体验数据实际上更棒;向他们展示并解释一个方框图,然后突然看到他们利用它。方框图永远不会获奖,但一个制作精良、使用简单的工具会让某人的生活变得更好,或者至少更轻松一点。

有时这些工具使用简单的图表,有时我们会想出一些更复杂的东西。有时候,我们有太多的数据,我们需要将它们简化为可消费的东西,或者以某种可以通过交互过滤的方式来表示它们。不管是什么情况,我有一个巨大的工具包,我用它来制作对人们来说简单的东西。

不,我还需要做一些我父母能理解的事情。#人生目标。

深入总结艾的音乐翻译模式

原文:https://towardsdatascience.com/in-depth-summary-of-facebook-ais-music-translation-model-7516a0c3f2ce?source=collection_archive---------10-----------------------

这不是第一次,我们正在解决音乐翻译,其中你试图将钢琴轨道转换为吉他。有很多很多这样的尝试。但是,让脸书·艾最近的论文[1]与众不同的是,他们将它作为一种无监督的学习来对待,并实现了惊人的领域推广。因此,模型在训练时可能没有观察到一个长笛或口哨样本,但它仍然可以将长笛演奏转换为钢琴曲目。

现在,假设我们想要将管弦乐队演奏的莫扎特交响乐的音频转换为钢琴家演奏贝多芬的音频。我将演示 4 种不同的方法。

Level-0:新手如何接近

像我这样的新手会迫不及待地认为这是一个转录问题。我会简单地通过短时傅立叶变换找到音符和和弦,然后用新乐器演奏。传统的语音处理提供了许多方法,如基于 Eighen 乐器的乐器概括[6],多音转录[3]然后解码等。每个乐器在时域中都有独特的音符开始和瞬变。但难点在于,即使是单个乐器(频谱包络)在频域,也不遵循不同音高的峰值模式。我们怎么能忘记复调音乐中的次谐波,等等。所有这些因素使问题变得非常困难。

Level-1:深度学习科学家如何接近

如果我在音乐理论方面稍好,那么我可能会使用 CNN 学习音乐转录,它通过 midi 格式生成标签。Midi 是大多数合成器录制数字音乐的标准格式。在 Midi 中,每个按键的按下和释放都是一个事件。我们有像 MAPS[7]这样的数据集,可以用来解决复调钢琴的转录问题。

Level-2:一个 NLP 的家伙将如何接近

如果我是一个 NLP 的家伙,我可能会使用序列到序列模型[5],但我将需要匹配的行为和目标工具的轨道。

Level-3:学习直接翻译和领域泛化

如果你真的是优秀的音乐家,那么你会明白每种乐器的细微差别是 MIDI 无法捕捉到的。这也是本文的创新之处。

Noam 等人借用了 wavenet 的自回归架构,并利用它将问题转化为“下一个音符是什么?有点问题。这使得它无人监管。

可以在官网(https://deep mind . com/blog/wave net-generative-model-raw-audio/)了解 wavenets。但本质上,波网摇滚,因为随着学习门扩大卷积,导致感受野增加,因此更好的预测,更丰富的隐藏特征的潜在空间。这些特征是捕捉人类声音或音乐本质的特征,就像 CNN 中的特征地图(具有不同的架构)。

现在,如果你想学习一个自动回归模型来预测 piano 的下一个样本,那么你只需要学习 wavenet 编码器和解码器。这里,编码器将把先前的序列投影到潜在空间中。然后,解码器试图从潜在空间中的隐藏值中找出意义,以解码序列中的下一个值。

如果这个模型可以为钢琴编码,为其他乐器解码,那不是很好吗?一类条件自回归模型?

这就是脸书人工智能集团所做的。Noem 等人[1]在同一个编码器上训练多个乐器域,并为每个类别配备不同的解码器。你可能会想,这有什么用呢?

但是共享的编码器迫使它学习共同的特征。我们仍然需要告诉模型,这是一个钢琴轨道,而不是一个管弦乐队。为此,我们有一个域混淆网络,它可以理解匹配的类/域。该论文将此视为对手,因为公共潜在空间试图找出公共特征,失去唯一性,而混淆矩阵试图分离公共表示,并使它们更具类条件性。共性和特性之间的斗争。这也需要精心选择正则化系数,这样才能两全其美。

让我们来看看目标函数。我们从域 j 中选取一个样本 sj,然后进行随机音高移位,以避免模型对数据的无脑记忆。在论文中,他们提到,样本在 0.25 到 0.5 秒内完成-0.5 到+0.5 个半音的随机音高。这表示为 O(sj,r),其中 r 是随机种子。你可能会想,这有什么大不了的。但那些与谷歌品红或任何时间生成模型合作过的人,肯定知道模仿的诅咒。有时,模型开始像鹦鹉一样,做简单的顺序记忆(明显的过度拟合)。这就是为什么这个放大和扭曲的过程在这里非常重要。这就是为什么在多个域上训练编码器是重要的。

然后,我们让这个扩充的输入通过 wavenet 编码器的扩展卷积移动到潜在空间,然后通过特定域解码器 Dj 返回到原始空间,以获得下一个值的预测。我们将预测的下一组值与具有交叉熵损失的实际下一组值进行比较。作为对手或反目标,我们也有一个监督正则化项,它试图根据编码后获得的特征向量来预测域。他们称之为领域混乱网络。

这里的推论非常简单。我们只是根据我们的目标域 j 来调整解码器 dj。因此,如果你给它输入管弦乐曲目,它就会返回目标域 j 中的翻译(钢琴等)。但这是最酷的部分。如果你把一个看不见的乐器输入到模型中,并遵循自动编码过程,使用 j 乐器的解码器,那么它仍然可以近似地工作,这真是太棒了!!!这是因为,它表明编码器真正地概括了可见和不可见领域的潜在表征。这个概念是许多生成算法的核心,比如 GANs,变分自动编码器,我强烈推荐你阅读参考资料。

那是我所有的朋友。我已经做了一个超级棒的视频。一定要小心。 对博客表示支持 在媒体上鼓掌:)

订阅我的 youtube 频道 。我每周都发布关于 AI 近期话题的数学直觉的视频。链接如下:http://youtube.com/c/crazymuse

Youtube 视频(基于本博客):

有用链接

[1]主题深度讲解:https://www.youtube.com/watch?v=QL_joojCzvs

[2]https://www.youtube.com/watch?v=vdxCqNWTpUs 脸书团队演示:

[3] 谷歌洋红:https://magenta.tensorflow.org/

[4] 地图数据集:http://www . TSI . telecom-Paris tech . fr/AAO/en/2010/07/08/MAPS-database-a-piano-database-for-multi pitch-estimation-and-automatic-transcription-of-of-music/

*[5] NSynth 数据集:【https://magenta.tensorflow.org/nsynth *

【6】【https://github.com/vishnubob/python-midi】有用的博客 Midi-python:

参考文献

[1] Mor,n .,Wolf,l .,Polyak,a .,& Taigman,Y. (2018)。一个通用音乐翻译网络。arXiv 预印本 arXiv:1805.07848。

[2]范·登·奥尔德,a .、迪耶曼,s .、曾,h .、西蒙扬,k .、维尼亚尔斯,o .、格雷夫斯,a .、… &卡武克库奥卢,K. (2016)。Wavenet:原始音频的生成模型。arXiv 预印本 arXiv:1609.03499。

[3]西格蒂亚,s .,贝内托斯,e .,&迪克森,S. (2016)。用于复调钢琴曲改编的端到端神经网络。IEEE/ACM 音频、语音和语言处理汇刊(TASLP),24(5),927–939。

[4] Sutskever,I .,Vinyals,o .,& Le,Q. V. (2014 年)。用神经网络进行序列间学习。神经信息处理系统进展(第 3104-3112 页)。

[5]罗伯茨,a .,恩格尔,j .,拉弗尔,c .,霍桑,c .,&埃克,D. (2018)。学习音乐长期结构的层次潜向量模型。arXiv 预印本 arXiv:1803.05428。

[6]贝内托斯和迪克森(2013 年)。使用时间约束移位不变模型的多乐器复音音乐转录。美国声学学会杂志133 (3),1727–1741。

[7] V. Emiya,钢琴音乐的自动改编,博士论文,巴黎电信,法国,2008

赞美人为的愚蠢

原文:https://towardsdatascience.com/in-praise-of-artificial-stupidity-60c2cdb686cd?source=collection_archive---------18-----------------------

为什么今天的人工授精不是“真正”的人工授精,但对您来说可能没那么重要。

让人工智能再次变得伟大

“人工智能就是电。“a . Ng

"那些不学习历史的人注定要重复历史。"桑塔亚那

N 在阳光明媚的硅谷,一家新的人工智能公司以闪亮的新承诺和/或令人瞠目结舌的融资回合成为头条新闻。这种狂热并不局限于硅谷:一片概念有些重叠的云——大数据、数据科学、机器学习、人工智能、深度学习——近年来已经成为主流;严肃的商界人士甚至声称数据科学家是“21 世纪最性感的工作”,部分证明了我成为 NBA 超级巨星的失败尝试(为了一些清晰的照片证据,将这种生活与下面的生活进行比较)。

Still, not as sexy as the life of a data scientist.

对许多老(ish)从业者来说,世界似乎终于赶上了我们一直知道的事情:制造智能机器非常酷!另一方面,在人工授精的含义、人工授精的承诺和人工授精实际能实现的目标上,似乎存在一些可怕的混乱。

作为一名资深从业者和另一家拥有人工智能领域的旧金山初创公司“T14”的创始人,我发现自己完全沉浸在一个生态系统中,在这个生态系统中,乐观主义往往只与对人工智能历史中基本事实的真正无知相匹配:我不禁想知道,我们是处于一个时代的开始,还是处于一个时代的结束?

在接下来的文章中,我提交了我对人工智能非常主观的概述——昨天、今天、明天——并将犯下终极(呆子)罪:将科学炒作与商业价值脱钩。

免责声明:在接下来的内容中,我们不会从学术角度提出特别原创的主张;即使只是考虑非学术的东西,我们的一些考虑也是共用的 [这里](http://nautil.us/issue/67/reboot/why-robot-brains-need-symbols)这里这里 这里 。这篇文章的目的不是在学术上讨论一些支持或反对人工智能的有力论据,而是从“内部人士”的角度看待当前的炒作,并将其放在更广泛的背景下,特别是对受过教育的新领域读者来说。没有任何完整性和中立性的假设,你会在最后找到一个参考文献列表,相当令人印象深刻的人和进一步的评论。**

在人工智能之前做人工智能很酷

"你会看到,我们的艺术由一些数学和大量的想象力组成."达伦马特

为了提醒自己我多大了,并对今天的炒作有所了解,让我们跳回到我们都知道并热爱的 90 年代。我在下面学究式地转载了人工智能创始人约翰·麦卡锡在对彭罗斯的书的评论中的一些言论(你没想到彭罗斯会出现在 2018 年的人工智能博客上,是吧?):

人工智能的进步是由:

  1. 用逻辑公式或其他合适的方式表示更多种类的关于世界的一般事实。
  2. 识别智力机制,例如常识推理中涉及的逻辑推理之外的机制。
  3. 代表人们在常识推理中使用的近似概念。
  4. 设计更好的搜索可能性空间的算法,例如让计算机进行逻辑推理的更好方法。

像其他科学一样,人工智能产生数学问题,并提出新数学。到目前为止,最重要和典型的是非单调推理的形式化

Wow : 我们刚刚在 A.I .上浏览了一整段,没有遇到“深度学习”。抛开彭罗斯不谈(抱歉,我对的逻辑学家和的家伙捣乱情有独钟),文章中的参考文献与当前的辩论相去甚远,令人尴尬而着迷。

如果你对人工智能的热情始于九十年代的经典读物(如明斯基,1988,珀尔,2000,霍夫施塔特,1995,等。),麦卡锡关于人工智能进步的观点会在你心中产生共鸣,就像一首来自遥远而快乐的过去的歌曲。然而,如果你刚刚来到数据科学派对,这些话很可能听起来很空洞:虽然今天在“人工智能公司”的面试可能会涉及到,比如说,普通最小二乘法,但大多数候选人可能对 非单调推理 甚至的意思一无所知。“到底发生了什么?”这时你可能会问(“我们应该雇佣他们吗?”你也可能会问,但这是一个棘手的问题)。

在一个口号中,数据的不合理有效性发生了(作为一个概念,而不仅仅是开创性的哈勒维、诺维格和佩雷拉,2009 ,不出所料,佩雷拉是这一概念的一个非常标志性的代表)。

为了明白我的意思,是时候更深入地探究第一个人工智能的光辉岁月了:屏住呼吸。

冬天来了

“你可以给思想定价。有些花费很多,有些花费很少。一个人如何支付思想的费用?我认为答案是:有勇气。”维特根斯坦

众所周知,这门学科“诞生”于达特茅斯研讨会:约翰·麦卡锡是的麦卡锡创造了“人工智能”一词,以标志着对概念和任务的计算学习,这些概念和任务在以前只属于人类智能。如果我必须用一句话来总结那些辉煌的过去——有时被称为象征性的人工智能——大致如下:

一般(“常识”)智能行为的关键是以一种允许明确操作和组合概念的方式来表示概念:我们对这种“表示”的最佳猜测是形式逻辑,而我们对“操作”的最佳猜测是逻辑推理。

尽管开国元勋们很乐观,但事实证明,从原理中复制伯特兰·罗素的定理是“相当容易的”,但让自主代理像一个 2 岁的孩子一样走过一个房间“基本上是不可能的”。商业应用在规模上被证明是不成功的,“人工智能”变成了一件坏事:冬天确实来了,而且对我们所有人来说,几乎“埋葬”了这个领域——至少在主流文化和大规模商业活动的眼中是这样。

虽然不确定人工智能复兴的根本原因,但在我看来,谷歌的大规模增长发挥了很大作用,证明了一家建立在核心技术和算法(今天我们称之为“人工智能”)基础上的公司确实可能是“下一个大事件”。谷歌对待能够完成“以前只留给人类智能的任务”的产品的方式有什么不同?

让我们从一个非常熟悉的例子开始:Gmail awesome 垃圾邮件过滤器,这个例子直接取自我自己的收件箱。

A message flagged as “spam” by my Gmail account.

对于人类来说,有许多常识性的推理来决定一条消息是合法的还是垃圾邮件,例如:

  • 严肃的企业不会写信给人工智能创业者谈论石油合作伙伴关系;
  • “石油销售部门”的主管(不管是什么)不会有一个展望领域(谁会有一个展望领域呢?).

换句话说,你的推理会是:

a) 明确的 —即,如果被问到,你可以使用类似上述的概念来陈述为什么你认为该邮件是垃圾邮件(例如,你有“表述”,并且这些表述很容易通过语言共享);

b)在很大程度上基于大量重要的知识,从完全理解英语开始——也就是说,同样的信息在俄语中不会以同样的方式进行分析。

如果你认为向计算机教授所有这些听起来像一场噩梦,那么,你就明白了为什么古老的人工智能方法很快就被认为是非常不切实际的,甚至对于简单的“认知任务”也是如此。那么,谷歌的出路是什么?

事实证明,要将一封邮件可靠地归类为垃圾邮件,并不需要深厚的英语知识或常识信念。我们可以通过将挑战转化为一个简单的统计问题来回避语言意义的问题:在垃圾邮件和合法邮件中,“合作伙伴”和“石油”这两个词会同时出现多少次?如果你对电子邮件中的所有单词都问这个问题,你会有一个“全局概率”,即电子邮件本身是垃圾邮件还是合法邮件:你处理的包含这些单词的电子邮件越多,你的过滤就越准确。

如果你想一想,这是一个不可思议的工程技巧:我们从一个需要非平凡智能来解决的问题开始,我们承认我们不能完全理解/复制这种智能,我们意识到用平凡的算法和大量数据代替非平凡智能可以实现完全相同的目标:事实证明,解决本质上的意义问题更容易(这个人是在用文字欺骗我做什么吗?)通过完全忽略的意思并利用共现模式。

随着谷歌和大数据时代的兴起,一场完美风暴开始让“智能机器”再次变得酷起来:增强的计算能力、前所未有的可用数字信息和许多聪明的算法(如上文的垃圾邮件分类器)开始为各种商业上成功的产品提供动力。虽然细节有所不同,但大多数成功都有一个共同点:将表示复杂知识的漫长而艰苦的工作转化为某种优化问题;由于我们无法横向扩展智能,我们转而扩展了数据收集。

从某种意义上说,人工智能冬天过后,我们学到的大部分东西并不是如何建造更智能的机器:对我来说,最重要的信息确实是,我们认为需要智能的许多实际问题实际上可以通过愚蠢的算法和大量的数据点来解决。

“智能作为曲线拟合的产物是当今深度学习的炒作。

深度学习和浅薄的想法

“一个聪明人不值得花时间去争取多数。从定义上来说,已经有足够多的人可以做到这一点。”哈代

毫无疑问,深度学习在各种“人工智能任务”中取得了突破性的、可衡量的进步,并释放了人工智能技术实际应用的惊人潜力。如果有可能与我们的智能手机交谈,并从中获得除沮丧之外的东西,这在很大程度上要归功于语音识别方面与深度学习相关的改进;如果使用谷歌翻译作为理解外语歌曲的第一近似值是合理的,那么这在很大程度上是由于机器翻译中与深度学习相关的改进——这个列表还可以继续下去。

淡化神经网络的科学和工程成就是完全没有意义和完全愚蠢的。

虽然有但是。学习“模仿人脑”的神经元样结构的想法(是的,人们实际上大声说出来)确实是非常古老的:最近发生的变化是硬件和算法的改进使得(嗯,相当简化事情)在更多数据上训练更大的网络成为可能,并大幅提高各种任务的性能。“作为曲线拟合的智能”的一般思想仍然是一样的:给定足够的数据和聪明的计算技术,我们一次又一次地从“昂贵”和“难以捉摸”的知识到“便宜”和“可测量”的优化进行交易。

Real 2018 slide from a real A.I. unicorn: gotta love the human brain metaphor.

有趣的是,人类和机器之间的差异已经变得很明显,与其说是在他们得到了多少对/错的答案,不如说是在他们错得有多离谱。换句话说,即使人类和机器同意这幅图片的标题:

他们会基于非常不同的“思维过程”达成一致。作为证明,以下机器生成的标题(“冲浪板上的恐龙”)不仅是错误的:它实际上远远不是一个对整个游戏产生怀疑的“智能猜测”——一个物理系统怎么可能让理解图像如此错误?

嗯,事实上这是不可能的:当系统“碰巧”正确/错误时,没有理解,因为一般的教训仍然是一样的——为了在许多看似智能的任务上达到 90%的准确性,确实根本没有必要智能。

当手头的任务具有某种程度上抵制“曲线拟合”的深度(不是有意的双关语)结构时,事情通常会变得更糟:我一生都对语言感兴趣,所以很自然地会问深度学习到底揭示了人类语言多少。以一个非常酷的项目为例, deepmoji ,它使用深度学习来制作一个模型,这个模型“已经学会理解情绪和讽刺即使最初的论文非常有趣,我们也很容易意识到“理解讽刺”可能比宣传的更难以捉摸。考虑下面的一对句子:

Testing Deepmoji with negation (original video here).

  • 我的航班被延迟了..太神奇了。
  • 我的航班没有延误..太神奇了。

而在第一种情况下,DeepMoji 检测到讽刺,并建议适当的“愤怒”表情符号(真棒!),第二句话,只有三个字母(N-O-T)不同,完全被误解了:根本没有讽刺的意思。与之前的图像一样,这表明我们最初并没有真正“理解”讽刺,但我们“只是”能够训练神经网络来拾取统计特征,在特定条件下,这些特征被证明足够精确。

在结束之前,让我们强调最后两点:

  • 可解释性:人们经常注意到深度学习模型是“黑箱”,因为人类很难理解他们为什么做他们所做的事情。虽然大多数观察家强调这种特征的明显的伦理和实践后果,但我们对人工智能历史的小小探索(不一定证明但是)表明,某种程度的可解释性可能是“智能”的关键部分:拥有表征意味着某种“模块化”结构,这种结构比简单的权重矩阵更自然地导致回答“为什么问题”;**
  • 数据:大量的统计学习(不仅仅是深度学习)需要大量的数据才能工作。虽然吨级数据不是一个精确的数量,但重要的是要注意,无论您如何定义,它可能比其他更高效的物理系统需要的数据多得多:哪些系统?很有可能,你现在身边就有一个这样的人:他们被称为“孩子”,他们有时甚至会从一个简单的例子中学到复杂的概念。虽然我们当然可以想象是一个超级智能的外星种族,需要很长时间才能掌握新的任务,但通过考虑机器学习的缓慢和昂贵,我们很容易衡量我们离真正的智能还有多远。**

最终,尽管“曲线拟合”已经变得令人印象深刻,但越来越多的从业者认为,人工智能需要的是新想法,而不是更多的数据/GPU(深度学习的真正先驱 Geoffrey Hinton 最近表示,我们应该“抛弃这一切,重新开始)。我们将在最后提到一些我们喜欢的开创性发展,因为我们现在不得不问:我们应该如何处理所有这些新发现的人工愚蠢?

预测机器

“有时候,似乎人工智能的每一个新步骤,都没有产生大家都同意是真正智能的东西,而只是揭示了真正智能不是什么。”霍夫施塔特

Agrawal、Gans 和 Goldfarb,2018 是三位经济学家最近的书,通过经济理论的透镜分析了人工智能的复兴。他们的核心论点相当简单:人工智能意味着更低的预测成本,由于预测具有巨大而广泛的商业价值,随着人工智能渗透到我们个人和企业生活的方方面面,许多经济过程将在不久的将来被改变。

在这一点上,应该清楚的是,他们心目中的“人工智能”显然不是麦卡锡和他的朋友们在达特茅斯的那个夏天开始建立的;他们所想的是过多的小型、特定任务、精细优化的软件,这些软件将比现有系统更好地解决狭窄的业务问题——垃圾邮件过滤器、电子商务中的推荐书籍传送带、何时购买芝加哥机票的通知、针对天气、航空公司价格波动的优化等。

这,“仅仅”是这,当前的人工智能革命,通过更好地完成“愚蠢”的任务,正在席卷消费者和企业市场:虽然这些预测机器不会达到任何程度的智能或理解,但结合在一起,它们降低了成本,提高了许多过程的效率。

从这个角度来看,虽然技术不再是主要的参与者,但它显然是这种新商业生态系统的推动者:没有开源工程工具和库、教育资源、计算能力、纯粹的数据的繁荣,这些“T0”人工智能群对于 X 公司来说都是不可能的,而且许多情况仍然会相当不优化。随着预测被更好的库和服务抽象和封装,我们可以看到在不远的将来,人工智能组件在代码库中会像今天与数据库交互一样常见。虽然用经过适当优化的曲线拟合工具来交换理解智力的梦想对一些人来说肯定令人沮丧,但将人工智能从大学实验室带入疯狂的商业世界是恢复兴趣、增加资金和吸引人才的必要步骤。从商业角度来看,有数十亿美元的机会摆在那些只需要一点点科学和适量数据的人面前(麦肯锡估计人工智能可能每年创造超过 3.5 万亿美元的价值):对于“基于预测的人工智能”来说,春天,当然是而不是冬天,正在来临。

很明显,与“真正的”人工智能所能实现的相比,所有这些“愚蠢的”人工智能都是毫无价值的;不幸的是,人工智能作为一个领域多年来一直在做的一件事,就是与它自己的期望严重不符。在这方面,“预测机器”的出现虽然不如“思维机器”的未来出现那样令人兴奋和改变游戏规则,但却标志着该学科历史上一个前所未有的里程碑——即商业价值超过了象征性的“不归路”。

尽管炒作和乐观情绪会时好时坏,“曲线拟合”最终给了人工智能一个席位:的确,有时候明智胜过

一个遥远的未来

“霍夫斯塔德定律:它总是比你预期的要长,即使你考虑到了霍夫斯塔德定律。”D. R. Hofstadter

在过去的 60 年里,我们从“演绎机器”到“预测机器”——离“思考机器”还有多远?嗯,这个是一个非常难的预测:没有人知道目标有多远,更糟糕的是,没有人知道我们会走哪条路。如上所述,仅凭“自下而上的方法”或“符号推理”似乎是极不可能满足的:然而,如何有效地将两者完全结合起来仍然是一个谜。在更具“象征性”的部分,最近一波不可思议的想法、论文和工具在概率编程中承诺以一种前所未有的方式将逻辑和概率结合起来:如果你对我们自己的观点感到好奇,我们最近发表了一篇长的、固执己见的和认知友好的帖子,里面有可运行的代码样本。**

如果人工智能历史——我们对其进行了部分和主观回顾——能给我们一些启示,我有信心提出三点建议:****

  • 对于人工智能中的业务人员:不要恐慌。当然,人工智能市场可能很快会放缓,深度学习可能会开始停滞,媒体的所有乐观情绪可能会冻结一点。虽然确实有很多”。人工智能初创公司“只是”随波逐流”,近年来制造的许多预测机器将会留在这里,还有更多的机器有待发明。当然,我们可能想在某个时候重温整个“人工智能”标签,但这并不意味着我们要赶走婴儿。**
  • 对于人工智能的研究人员:回到基础。人工智能建立在理解认知的跨学科努力之上;有趣的是,大部分关于深度学习的原创想法来自心理学杂志(如辛顿 1985,罗森布拉特 1958 )。虽然现在很难确定路线图,也几乎不可能看到各个部分——计算机科学、心理学、语言学、神经科学、逻辑——是如何整合在一起的,但从不同角度解决一个非常困难的问题不会损害我们的机会。
  • 对于 A.I .的投资者来说:引领创新,不要只是跟随。资金一直在行业持续流动,尤其是深度学习初创公司。然而,所有这些对人工智能的狭隘看法的资金可能会让我们陷入“局部最小值”,而其他有前途的方法,离宣传更远,受到的关注更少。这不仅仅是对科学不利:如果你在那些幂回报定律中寻找好的异常值,随着“预测机器”市场变得拥挤,你对下一件大事的最佳押注可能完全来自一种新的方法。

那么人工智能初创公司的创始人呢(如果有人关心他们的话)?好吧,在为真正的机器智能提前规划的同时,我们可能应该继续在我们的日常追求中追求更卑微和平凡的里程碑。我们的灵感和指导不亚于艾伦·图灵本人:

“我们只能看到前面不远的地方,但我们可以看到那里有许多需要做的事情。”

让我们永远不要忘记,完成这件事取决于我们自己。

再见,太空牛仔

如果您有问题、反馈或评论,请与jacopo . taglia bue @ tooso . ai分享您的人工智能观点。

别忘了在 Linkedin 、 Twitter 和 Instagram 上获取 Tooso 的最新消息。

感谢

感谢整个 Tooso 团队,Stefano Pacifico 和 Davide Romano 对这篇文章之前的草稿的评论。

在我们之前关于学习概念的媒体报道中,以及在我们 11 月的人工智能讲座中,已经详细讨论了其中一些观点:我们要感谢人工智能未来会议的组织者和参与者,感谢他们对我们的观点做出的热情贡献和有益反馈。

杂项笔记和更多阅读材料

  • 显然,任何工业规模的垃圾邮件过滤器都会采用比上面解释的朴素贝叶斯分类更复杂的思想,但直到今天,它仍然是一种非常简单有效的基线算法,具有很大的教学价值。对于数据科学新手和不懒惰的读者来说,这里有一章非常不错。
  • 微软深度学习 Twitter 机器人可以在这里找到:我们在听 Josh Tenenbaum 的精彩演讲时了解到了它,其中涉及许多有趣的问题:学习、概率编程和基于模型的推理。
  • 在我们最近关于概念的帖子中,我们详细讨论了乔希·特南鲍姆在“贝叶斯学习”方面的最新作品。如果你想从某个地方开始, 认知的概率模型 是一本真正令人惊叹的书。
  • 在我们最近关于概念的帖子中,我们详细讨论了流体概念和道格拉斯·霍夫斯塔德。一些简短的文章暂且不提,感觉霍夫施塔特大部分都从幕后消失了:慈曼赤道格拉斯!
  • 我们在最后掩盖了与主题相关的大量学术材料:在没有任何完整性假设的情况下,你可以得到一堆经典材料(例如福多尔,皮里申,1988平克,普林斯,1988 )和下面参考文献中更近期的材料(例如达维奇,2017,马库斯,2018珀尔,2018 )。 Lake,Baroni,2017 是 NLP 最近的一个作品,我们很喜欢;对于如何将归纳偏见与深度学习结合起来的一些想法,Google Brain,Deep Mind 等公司的人有一篇很好的论文。(参见下面的参考文献)。虽然一些人最近一直在使用推特(Twitter)来讨论这些和类似的话题,但很多这样的争论确实可以追溯到几十年前(正如我们指出的,一些基本的事情还没有改变。】。
  • 图灵奖获得者朱迪亚·珀尔多年来一直是“偶然模型”的倡导者,即如果没有推理因果过程和做出反事实判断的能力,就无法实现真正的智能。认知科学家也提出了类似的想法(见 Lake,Ullman,Tenenbaum 和 Gershman,2016 的概述),特别强调了人类学习的“组合性方面”,即利用简单概念构建复杂概念的能力( Lake,Salakhutdinov 和 Tenenbaum,2015 )。基于模型的学习是我们关于概率编程的帖子的主要主题,其中包含注释代码示例和额外的参考资料,以进行更深入的探索。
  • 专家读者可能已经注意到,我们使用“表示”有点随意(草率?)在我们的讨论中;特别是,我们强调“外显表征”是类人智能的一个关键组成部分,但我们没有详细评论在深度学习经验成功中至关重要的表征。当涉及语言时,这两种类型之间的差异更明显(因为 1)人类使用语言在他们之间进行交流,2)非平凡的组成性是语言的本质),但这肯定是所有人工智能任务之间的真正差异。对于概念倾向的读者来说,福多尔,Pylyshyn,1988 是符号与神经架构中表征精神状态的一个里程碑式的讨论。

引用(惰性格式)

  • 预测机器:人工智能的简单经济学
  • 人类水平的智力还是类似动物的能力?
  • Google Brain People 等,2018,关系归纳偏差、深度学习与图形网络
  • 福多尔,皮利希恩,1988,连接主义与认知架构:批判性分析
  • Halevy,Norvig,Pereira,2009,数据的不合理有效性
  • 辛顿,1985,玻尔兹曼机的学习算法
  • Hofstadter,1995,流体概念和创造性类比:思维基本机制的计算机模型
  • Marcus,2018,深度学习:一种批判性评价
  • 麦卡锡,1990,评论:罗杰·彭罗斯,皇帝的新思想
  • 明斯基,1988,心灵的社会
  • Lake,Baroni,2017,没有系统性的泛化:论序列对序列递归网络的组合技巧
  • Lake,Salakhutdinov 和 Tenenbaum,2015 年,通过概率程序归纳进行人类水平的概念学习
  • 莱克、乌尔曼、特南鲍姆和格什曼,2016 年,建造像人一样学习和思考的机器
  • 珀尔,2000 年,因果关系:模型、推理和推论
  • Pearl,2018,因果革命的七个火花对机器学习的理论障碍
  • Pinker,Prince,1988,论语言与联结主义:语言习得的并行分布式处理模式分析
  • 罗森布拉特,1958 年,感知器:大脑中信息存储和组织的概率模型

编程(JHU 课程,课程 2)

原文:https://towardsdatascience.com/in-progress-review-course-2-r-programming-jhu-coursera-ad27086d8438?source=collection_archive---------0-----------------------

Histogram Showing Mortality Rates (Part of Week 4 Assignment)

数据科学专业的第二门课程“R 编程”是一门向用户教授 R 基础知识的入门课程。虽然我确实认为它很好地讲解了基础知识,但对于真正的 R 初学者来说,任务难度有点太大。因此,我决定将我的所有代码发布在我的 github 上。

我带着一点曲折完成了这门课程。我决定使用非常流行的 data.table 包,而不是纯粹使用 data.frame,data . frame 没有 data.table 广泛用于大型数据集。

第 1 周重点:删除和子集化数据是一项非常有用的技能。向量、列表、矩阵和因子的教学是极好的。并不太难。

R Programming JHU Quiz 1

第二周重点:词法范围是所有对象必须存储在内存中的原因。编程作业很有用。如下所示,我已经决定尽可能地对 data.table 语法进行专门化,因为它在行业中被广泛使用。

R Programming JHU Week 2 Quiz

第二周的恐惧:许多用户抱怨这周的项目难度增加了很多。这也是我决定将所有作品放在 github 上的部分原因。

R Programming JHU Assignment 1

第 3 周重点:在下面的测验中练习我的数据表技能(或缺乏技能)的机会。很高兴看到通用数据集的使用,因为它们易于操作。《T4》的任务还不错。

第 4 周亮点:测验还不错。R 剖面仪讲座。有一个很好的说明,当代码被设计、运行和理解时,优化是一个优先事项。通过排序、分组等方式找出各州最好的医院很有趣。在我看来,考虑到这是一个初学者的专业,这个作业有点多。这个缩略图是我在这个作业的早期生成的。

R Programming JHU Assignment 3

总的来说,这是一门对工业界非常有用的课程,因为它教会人们获取数据文件并对其进行操作。然而,对于初学者来说,它的期望太高太快了。如果你有任何问题,请留言告诉我!

另外,请看我的课程 3 获取和清理资料复习!

追求幸福(上)

原文:https://towardsdatascience.com/in-pursuit-of-happiness-4283c8c335c4?source=collection_archive---------2-----------------------

幸福的国家都是相似的;每个不幸的国家都有自己的不幸之处。

Global well-being

在一个增长往往等同于经济的世界,OCED 提出了福祉的重要性,这使国家层面的幸福成为人们关注的焦点。

今天我在看联合国委托的 2016 年世界幸福报告,该报告包含全球幸福指数和一系列社会经济因素,如经济、家庭、健康、自由、信任和慷慨。越来越多的国家将幸福作为衡量社会进步的标准。众所周知,不丹使用国民幸福总值(GNH)作为发展指标。鲜为人知的是,3 月 20 日被定为国际幸福日。

我注意到的第一件事是一个广泛的模式,在每个因素上排名越高的国家越幸福。因此,经过一些数据清理后,我研究了每个地区的国家在社会经济福祉方面的表现。

一些观察结果:

  • 慷慨、信任和自由都很低
  • 有些地区(如北美)比其他地区(如南美)更加 T4 化。
  • 地区有离群值:信任指数在东南亚相当低,新加坡除外;东非的毛里求斯经济指数特别高,也高于世界平均水平;与南亚国家相比,斯里兰卡和不丹的家庭指数要好得多。

这是可视化数据集的第一步。接下来,我打算研究社会经济福祉如何对国家层面的幸福做出贡献,以及这一趋势如何逐年变化。

我今天学到的是,为了循环图表,需要在 print()语句中包含 ggplot。这些图表只是极坐标上的柱状图投影。

你可以在这里阅读更多关于世界幸福报告的内容。

感谢阅读。这是我关于数据科学和视觉故事的# 100 天项目的# 12 天。

产品分类:Spotify

原文:https://towardsdatascience.com/in-this-article-i-provide-a-detailed-analysis-of-spotify-as-a-company-music-industry-direction-eeb945d7257c?source=collection_archive---------3-----------------------

在这篇文章中,我详细分析了 Spotify 作为一家 公司 (音乐产业方向、市场竞争、增长战略)和作为一款 产品 (特点分析、Spotify 的 ML 概述、UI 建议)。

尽管 Spotify 在计划公开募股之前正忙于清理其诉讼和债务,投资者对这家音乐流媒体巨头的估值为 160 亿美元。在全球 1.466 亿付费音乐用户中,Spotify 拥有 7000 万 T21 用户,在音乐流媒体市场中的份额不到 50%。

了解你的历史……并重复它。

那么是什么让 Spotify 走到了今天?有几个关键策略曾经奏效并将继续奏效:

社会特征:

  • 订阅你的朋友,看看他们在听什么。由于 Spotify 与脸书整合在一起,找到你的朋友变得很简单。看到你的朋友听什么会让你感觉联系更紧密,并为音乐发现增加额外的分数。
  • 通过直接连接到平台的简单链接,与任何人分享歌曲/播放列表。每一份股票都像一张请柬,促进增长。
  • 公共播放列表是 Spotify 上音乐发现的主要部分。Spotify 有 3000 万首歌曲,有 20 亿个播放列表。考虑到该平台的设计提倡制作播放列表并将其公之于众,如此巨大的数字并不令人惊讶。默认情况下,播放列表是公开的,制造摩擦来隐藏你的音乐品味。从头开始制作播放列表或添加到现有的播放列表,只需点击一下鼠标。

智能定价(定期订阅 10 美元/月):

  • 为学生提供 5 美元的折扣订阅,以抓住在线社交网络中最常见的细分市场,因此最有可能引起使用该服务的邀请。
  • 最多 6 人的家庭订阅费为 15 美元,激励整个家庭转向一个平台,减少竞争对手的市场份额。

锁定设计。随着用户保存的歌曲和定制的播放列表越来越多,他们越来越有可能继续使用 Spotify,因为没有将用户库导出到 Spotify 生态系统之外的功能。虽然这可能会对加入 Spotify 构成威慑,但这是一个明智的策略,因为它是新竞争对手的强大进入壁垒。除非竞争对手能提供完全不同的、更好的东西,否则大多数已经在 Spotify 上收藏了一个系列的用户不会换。为了弥补不能拥有自己音乐的不适,Spotify 含蓄地宣传了这样一种信念,即有一个巨大的音乐海洋应该是我们真正感兴趣的,而不仅仅是保留你已经拥有的音乐。

真实性。通过允许歌曲在音乐选择算法上“推广”来赚钱是很诱人的,但迄今为止 Spotify 担心失去听众的信任是正确的。通过将听众的兴趣放在心上,Spotify 很快让每个人都适应了它的音乐查找功能,如发现周刊和艺术家/歌曲电台。

数据驱动的文化:Spotify 几乎立即开始追求通过算法来了解音乐的目标,认为这是开发其功能的最佳方式。当 Apple Music 吹嘘其“手工管理的播放列表”时,Spotify 正忙着从该领域雇佣尽可能多的机器学习/数据科学专家。

Spotify——你进入音乐世界的向导。

最重要的是,Spotify 寻求表现得像一名导游,一名算法大师,在你的音乐启蒙之旅中握着你的手。这反映在 Spotify 的营销和用户界面上。

source

许多人对 Spotify 机智的活动(2016–2018)窃笑,这些活动经常与重要新闻(亲爱的 3749 名观看“这是我们所知的世界末日”的人,英国退出欧盟投票的那一天,坚持住),或者轻松地嘲笑社会规范(“比那些在跑步播放列表上写着‘慢手’的 46 个人更传统地锻炼。”)。除了机敏的喜剧之外,他们之间的共同主题是基于数据的 音乐知识,以及对用户的关注

UI 的设计方式使得每个元素都像一扇等待打开的门,一个等待探索的新领域。如果你喜欢这首歌,右击打开歌曲电台,寻找相似的音乐。寻找新的东西——查看你的每周发现或者点击你朋友的订阅。想要收听您最喜欢的音乐吗——选择一个您的每日混音播放列表。

更正式地说,Spotify 的 UI 仅仅是 Spotify 核心的机器学习冰山的表面。它有 3 个主要的数据来源:

  • 播放列表(关于什么音乐被视为相似的信息),
  • 个人收听历史(音乐播放顺序模式),
  • 喜欢/不喜欢/跳过电台(关于歌曲如何混合在一起的信息)。

所有这些都是与内容无关的数据,但通过使用神经网络预测仅来自音频信号的数据(即歌曲内容本身),Spotify 的算法也变得与内容相关

Spotify 正在使用一整套协作过滤方法(通过在数据中寻找模式来分解艺术家-用户、歌曲-用户矩阵,使其变得紧凑)【Spotify 的幻灯片,为其提供每个用户和每个艺术家/歌曲的潜在表示(数字向量)。这给了 Spotify 一个全面的音乐地图,相似的歌曲被放在一起,用户倾向于只在地图的特定区域听音乐。

t-SNE visualization of found latent space (i.e. map of music), [A. van den Oord, S. Dieleman, B. Schrauwen]

通过遍历该地图,Spotify 可以找到与您指定的偏好(例如,每周探索、向播放列表推荐歌曲)或给定查询(例如,播放列表的电台、歌曲、艺术家等)相关的相近但新颖的歌曲。).[ 详细解释

总而言之,Spotify 的大部分导航功能只是导航音乐地图的包装器,只去你感兴趣或可能感兴趣的区域。

高质量的音乐需要快乐的艺术家。

Spotify 并不是号称每流付费率最高的公司。每条流媒体的价格为 0.0038 美元,落后于 Google play(0.0059 美元)、Apple Music(0.0064 美元),但领先于 Pandora(0.0011 美元)和 YouTube(0.0006 美元)。[ 信息是美丽的 ]然而 Spotify 并不吝啬——它向该行业支付了大约 70%的收入,其中大部分是版税。原因在于市场历史和激进的艺人标签合同。

Economist article

早在 2008 年,Spotify 继承了处于衰落期的音乐行业,当时互联网正以免费下载的文化蚕食音乐利润。然而,即使在 1999 年音乐产业的巅峰时期,消费者在音乐上的平均花费也是 28 美元/年(41.46 美元,如果考虑通货膨胀因素的话)。今天,许多人愿意再次为音乐付费,甚至是每年 120 美元的订阅费。因此,当更多的消费者接受新的音乐模式时,Spotify 将使音乐行业的收入潜力增加两倍。

在此之前,Spotify 与旗下艺人保持良好关系至关重要。Spotify 很明智,它已经向艺术家们提供了免费数据,比如在哪里寻找他们的活跃粉丝来举办一场演唱会,有多少人在观看每首歌曲等等。它可以使用相同的数据来帮助艺术家的营销活动。了解每首歌的听众,艺术家可以根据地点定制他们的表演内容,并决定在哪里租广告位最好,以及以什么情绪为目标。

标签正在成为支付链中一个过时的中间人,从所有版税中拿走很大一部分。因此,从长远来看,Spotify 可以致力于成为自己的品牌。这将减少浪费的利润,并允许 Spotify 以更丰厚的版税份额吸引艺术家。它已经拥有所有必要的数据来维护艺术家的最佳音乐会日程,建议与相关艺术家合作,帮助将艺术家的作品交付给最有可能的观众,等等。这将引起标签行业的强烈反对。然而,考虑到 Spotify 已经面临压力要从 CRB 支付更多版税,而且它没有像苹果或亚马逊那样的替代收入可以依赖,Spotify 基本上被迫尽可能地减少中间商。

目前,Spotify 可以在粉丝和艺术家之间建立更明确的对话。粉丝们明确要求与他们最喜欢的艺术家保持一致,这一点从天才(已经集成在 Spotify 中)——歌词解释平台的流行以及以艺术家解释他们的创作过程为特色的播客(例如歌曲浏览器)中可以看出。围绕歌曲创作一个故事往往和创作歌曲本身一样重要。Spotify 可以创建有利于分享此类故事的平台功能(通过整合现有平台或从头开始设计功能):

  • 一个简单的基于向上/向下投票的 Q/A 标签可以充当艺术家回答粉丝最迫切问题的简单方式,为他们提供“被听到”的安慰感。(想想 reddit 上的 r/AMA。)
  • 艺术家在做什么,他们在哪里表演,以及他们的合作进展如何的专门信息。或许,与艺人的 Twitter 账户整合可以做到这一点,但它有与音乐无关的风险。
  • 根据有多少需求和最终的资源量,短记录会话更新(即长度为 15-45 秒的“snapchats ”)可以作为艺术家和他们的粉丝之间的短暂亲密时刻。Instagram 整合可能会减少艺术家在各种平台上的维护。

通过提供更明确的数据分析工具,并为艺术家提供与观众亲密接触的机会,Spotify 可以弥补其较低的报酬率,并与艺术家保持健康的关系,这最终应该会让艺术家们看到 Spotify 不仅是一个流媒体平台,而且是一个必要的一体化工具,可以真正帮助他们的职业生涯。

结束语。

statista

Spotify 距离完全巩固其市场地位还有很长的路要走。由于聪明的初始促销、社交定制设计、ML 焦点和对艺术家的免费数据服务,它领先于游戏。然而,其竞争对手正在积极投资音乐流媒体业务,愿意忍受支付更高的版税,并通过在硬件上预装他们的平台(如亚马逊、谷歌、苹果)甚至与软件集成(如苹果)来偷工减料。但如果 Spotify 能够通过提供不仅仅是一个流媒体平台来保持与艺术家的良好关系,并通过其真实的音乐发现设计来吸引更多的听众,它将有机会在未来进一步重塑音乐行业。

不相容性和可预测性——萨尔维尼 vs 迪迈奥:基于推特的分析

原文:https://towardsdatascience.com/incompatibility-and-predictability-salvini-vs-di-maio-a-twitter-based-analysis-131c15fced54?source=collection_archive---------23-----------------------

Luigi Di Maio (left) and Matteo Salvini (right). Image from liberoquotidiano.it

意大利最近的大选中诞生了所谓的“黄绿”混合联盟,五星运动(5SM)和北方联盟(LN)的议员在两院都占据了多数席位。然而,他们非常不同的政治背景和优先事项正在促成一种令人不安的共存,质疑这两个派别在这样一个独特的机构中的兼容性。然而,联合五星和北方联盟是最低阶层的共同关切,通常通过不可满足的承诺和无视其他政党和/或旧的国家和超国家机构,如欧盟来解决;一句话:民粹主义。

这足以保证意大利政府长期执政(理论上是 5 年)吗?要回答这个问题,我们需要以某种方式量化这两股力量之间的重叠——以他们的领导人路易吉·迪迈奥(5SM)和马泰奥·萨尔维尼(LN)为代表。我在这里要做的是使用 Python 对两位领导人最近的推文进行简单而有意义的分析。我们将看到重叠被量化为低至约 15% 。为了补充我的研究,从 3mi1y here 的帖子中获得灵感,我将衡量——或者更好地说,让你来衡量——两位领导人的可预测性。更准确地说,我将使用一个一阶马尔可夫模型来构建一个 Salvini-和/或 Di Maio-tweet 生成器。

显然,说意大利语的人在充分理解我的结果的真实性方面有优势。然而,这篇文章可能与愿意对 Twitter 数据进行类似分析的用户有关。

导入推文

要导入特定用户的推文,必须申请一个开发者 Twitter 账号,可以在这里做。然后,它足以创建一个个人应用程序(激励其使用等)。根据新法规)获得:

  • 消费者密钥
  • 消费者秘密
  • 访问令牌
  • 访问令牌秘密

完成后,我们就可以导入推文了。我使用了 tweepy 包,并遵循了这里报道的步骤

#fill below with your credentials
consumer_key = '......'
consumer_secret = '...yours...'
access_token = '...'
access_token_secret = '...' auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)collect_tweets_Salvini=[]
collect_tweets_DiMaio=[] for status in tweepy.Cursor(api.user_timeline, screen_name='[@matteosalvinimi](http://twitter.com/matteosalvinimi)').items():
    #Split and re-join to get rid of \n and similar charachters
    temp = status._json['text']    temp = ' '.join(temp.split())
    collect_tweets_Salvini.append(temp)

for status in tweepy.Cursor(api.user_timeline, screen_name='[@luigidimaio](http://twitter.com/luigidimaio)').items():
    temp = status._json['text']
    temp = ' '.join(temp.split())
    collect_tweets_DiMaio.append(temp)

这段代码返回两个列表collect_tweets_...,其中包含两位政治家的大量推文(每条约 3200 条)。有许多替代的方法可以得到这些,例如见这里。

第一部分:探索性数据分析和重叠测量

数据清理和功能定义

在执行任何类型的分析之前,我们需要清理我们的数据。有些类型的推文与我们无关,比如转发。还有,我们想去掉@、#、表情符号等。我定义了以下函数:

用函数clean_tweets() 清理一条推文的过程如下:首先用prune_tweet()修剪它,它检查推文中的所有单词,如果它们不满足某些要求(例如,如果它们以@)就丢弃或修改它们,这是用goodWord()实现的目标。然后,通过tweet_process(),删除意大利语中的标点符号和常用词(如冠词)。最后,我们还消除了重复的单词。这整个过程是通过运行以下命令实现的:

clean_Salvini = clean_tweets(tweets_Salvini)
clean_DiMaio = clean_tweets(tweets_DiMaio)

创建一个列表列表,其中每个元素都是一个不同的干净的 tweet。

一个非常有用的工具来检查每个政治家的推特语料库的组成,是词云。我们展平列表的列表,以生成两位政治家使用的所有单词的集合,并使用它们作为输入来创建单词云。

这是结果

Figure 1: Salvini Twitter wordcloud.

Figure 2: Di Maio Twitter wordcloud.

单词云显示了某种程度的相似性(“governo”、“oggi”、“diretta”的大小差不多)。最明显的区别涉及人名的出现:大量使用“Salvini”一词来称呼 LN 领导人,而使用“Renzi”(前总理和民主党领导人)来称呼 M5S 领导人。我让你在这里下结论,看看下面的单词出现次数会更容易些

Figure 3: Salvini Top 20 words.

Figure 4: Di Maio Top 20 words.

好吧,我真的希望不要在这里得出任何结论,尽可能少一些政治偏见,但事实上,“salvini”这个词的使用超过了两个列表中的所有其他词——大约一个数量级——值得一些评论。这主要是由于两个原因:第一个原因是,LN 领导人喜欢以#Salvini 标签开始他的推文。第二个是对沟通的受害者般的态度,因为许多帖子都报道了其他人对他的评论,萨尔维尼反过来能够以新的方式提出这些评论,以增加选民的支持。你可以通过浏览推文列表来明确检查这一点。

现在,如何衡量两者的重叠部分?自然语言处理中最常见的技术是对每条 tweet 进行矢量化,使其适合数字分析。这涉及到 tweets 的标记化和相关的东西(例如,见这里的)。后一种分析与分类问题特别相关,一个经典的例子是将电子邮件分类为垃圾邮件或不是垃圾邮件。试图将这种方法强加于我们的案例显然是行不通的:就推文相似性而言,Di Maio 被归类为 Salvini 的可能性非常低。最后,我们谈论的是两个不同的人…因此,我将使用的方法如下:

  • 以一位政治家为参照,得到他的前 20 个词(图 3,4);
  • 找到他的包含前 20 个列表中最大出现的单词的 5 条推文,通过产生其相对重要性的函数进行加权(前 5 个列表);
  • 将第二位政治家的一条推文t2与上面t1前五名中的一条推文进行比较。测量它们的重叠,作为出现在t1中的t2中的单词的分数
  • 将如此获得的 5 个重叠部分平均。

用实例来说明这个过程会更容易理解。让我们以萨尔维尼为参照政治家。他的前 20 个单词如图 3 所示。现在,通过扫描推文语料库并计算前 20 个词中的每一个出现的次数,获得了他的推文的相关前 5 名列表,我们首先根据它们在语料库中的出现进行加权。举个例子,最初的推文(被归类为最重要的,看起来有用……)

'#Salvini: dopo mesi di lavoro offro agli italiani, che mi pagano lo stipendio, non solo il decreto, ma anche un....'

这对应于删减的 tweet

'decreto lavoro offro solo dopo salvini pagano stipendio italiani pro mesi'

包含单词(及其相对权重,参见图 3): ('lavoro ',115),(' solo ',109),(' dopo ',98),(' Salvini ',864),(' italiani ',186)。因此,这条推文的部分“分数”是:score _ sum = 115+109+98+864+186 = 1372。我们需要考虑到较短的推文获得较高分数的概率较低。然后,我们将分数除以修剪后的 tweet 的长度,在上面的例子中,长度= 11。除此之外,为了执行有意义的分析,我们希望为修剪后的 tweet 的长度设置一个下限,比如 10。每条推文的得分为

分数=分数总和/长度* \Theta(长度-10)

其中\Theta (length)是 Heaviside 阶梯函数,正参数为 1,否则为 0。

代码:

现在我们有了前五名的名单,是时候将其中的每一个元素与 Di Maio 的推文进行比较了。对于 Di Maio t2的单个推文,五个重叠被量化为每个t1.中包含的t2中的字数,这产生了 Di Maio 的#总推文(= 3191) x 5 矩阵。我们取每列重叠的最大值,然后取它们的平均值。发现最大值量化为 15%,如介绍中所述(见下文)。好吧,如果你相信这个分析…

Figure 5: Statistical properties of the overlap matrix described above.

第二部分:马尔可夫链

最后,我们采用离散时间马尔可夫链来模拟推文中的领导者。(一阶)马尔可夫链是一个随机过程,其中事件 X_m 在时间 t_m 的可能性只取决于前一时间 t_(m-1),而没有关于时间 t_(m-2),t_(m-3)等的记忆。这意味着从 X_1 到 X_n 发生一系列事件的概率可以分解为

其中 p(X_m |X_{m-1})是 X_m 给定 X_{m-1}的条件概率。

为了在我们的 twitter 数据上训练马尔可夫链,我们做了以下事情:

  • 取语料库中所有单词的集合
  • 固定其中一个,统计其后每隔一个单词的出现次数。
  • 归一化以概率的形式转换出现的次数。
  • 迭代集合。

例如,在句子“你好,世界,你好,月亮:今天是星期六”中,我们会有一组独特的单词(你好,世界,月亮,今天,是,星期六)。然后,我们固定单词“hello ”,并统计它后面的每个单词在句子中的出现次数:

你好→[你好:0,世界:1,月亮:1,今天:0,是:0,星期六:0],

将每个计数除以总出现次数= 2,得出一个单词被另一个单词替代的频率(别名概率):

p(世界|你好)= p(月亮|你好)= 0.5,

p(你好|你好)= p(今天|你好)= p(是|你好)= p(星期六|你好)=0。

创建这种对象的 Python 方法是定义字典。我们通过以下函数在我们的 tweets 语料库上执行这个操作

注意这里我们想保留文章,标点符号等。在推特的语料库中。因此,我们只应用功能prune_tweet()而不是clean_tweets()。正如上面可以看到的,只要提取出任何 4 个标点符号,我就停止生成推文。我们跑

clean_Salvini_WP = list(map(prune_tweet,tweets_Salvini))
clean_DiMaio_WP = list(map(prune_tweet,tweets_DiMaio))dict_S = firstMarkov(clean_Salvini_WP)
Salvini = normalizeFirstMarkov(dict_S)dict_DM = firstMarkov(clean_DiMaio_WP)
DiMaio = normalizeFirstMarkov(dict_DM)

这是用这种方法生成的几个句子:

萨尔维尼:“意大利的帕索里尼·斯克里韦瓦反对萨尔维尼。7 mesi del centro di invalidità。意大利,rozzo。

迪马约:我是说,意大利是意大利最大的国家。再见,伦佐波利。

他们听起来像他们吗?哈哈哈。

很明显,这个简单的模型可以通过采用更高阶的马尔可夫链或用其他一些来加权概率函数以考虑语言中的常见模式(例如,添加 exra 权重来区分冠词和形容词等)来改进。).或者,人们可以通过任意混合引用两位领导人的话来改变输出。我将把它作为这个简单项目的后续工作。

欢迎建议!

谢谢

利用剑桥分析概念整合持续主动病毒式营销

原文:https://towardsdatascience.com/incorporating-continuous-active-viral-marketing-by-using-cambridge-analytica-concepts-75f1d845628c?source=collection_archive---------9-----------------------

Viral Marketing (image is taken from https://infinitymkt.com/viral-marketing/)

我们只是把信息输入互联网和 的血液中,然后看着它成长,时不时地推它一下,看着它成形所以这种东西渗透到网上社区,并不断扩大,但没有品牌——所以它是不可归属和不可追踪的

在这些话中, Cambridge Analytica 首席执行官 Alexander Nix 透露了 Cambridge Analytica 声称它如何运营特朗普总统的“所有”数字竞选活动的秘密,正如第四频道新闻在调查中发现的那样。

在我们的新论文(阿隆·塞拉、马頔·戈登伯格、伊拉德·本-加尔和埃雷兹·什穆利)、“主动病毒营销:将持续的主动播种努力纳入扩散模型”中,该模型最近被 专家系统接受并应用(ESWA) 。我们展示了这种方法如何在社交网络中实际工作。

正如论文中所述,现有的病毒式营销网络模型通常假设一个被动病毒过程,即社交网络中的用户在没有外部干预的情况下感染其他用户。然而,在现实世界中,公司和组织投入了大量的努力来推广他们的产品、服务或想法,这表明这些营销项目的采用很少是被动病毒传播的结果。

在这种观察下,我们提出了一种新的社交网络扩散模型,称为主动病毒营销,它更适合现实世界的营销场景,其中新想法的采用依赖于营销人员持续的主动推广努力。在提出的模型中,试图感染潜在(未受感染)用户的营销成功取决于该用户的采纳朋友(受感染邻居)的数量,假设用户更有可能采纳一种产品,如果他/她的更多朋友已经采纳了该产品,同时考虑到由于记忆丧失效应,社会影响会随着时间的推移而减弱。

这项研究提出了一套实用的方法来安排网络中的营销尝试在一段时间内的时间。这些方法背后的主要思想是在选择下一个种子节点时,除了静态社交网络拓扑之外,还利用关于邻居节点的动态采用状态的信息。一项广泛的实验证明,与主要依赖社交网络拓扑的现有最先进方法相比,所提出的播种启发式方法如何将产品采用率提高 30%-75%。

我们欢迎任何反馈!

用一个简单的 Python 机器人增加你的 Instagram 粉丝

原文:https://towardsdatascience.com/increase-your-instagram-followers-with-a-simple-python-bot-fde048dce20d?source=collection_archive---------0-----------------------

我在 4 天内有大约 500 名真正的追随者!

Picture taken by me — Ho Chi Minh City

培养观众是一项昂贵而痛苦的任务。如果你想建立一个与你相关并有共同兴趣的观众群,那就更难了。我总是看到 Instagram 有一个很好的方式来推广我的照片,但我从来没有超过 380 个粉丝...每隔一段时间,我决定再次在 Instagram 上发布我的照片,我设法定期发布一段时间,但从来不会持续超过几个月,我也没有多少粉丝让我保持动力和参与。

这个项目的目标是建立一个更大的观众群,并作为一个加号,可能会带动一些交通到我的网站,我卖我的照片!

一年前,在我最后一次运行 Instagram 时,我得到了一个可以让你追踪谁没有关注你的应用程序。我很好奇,因为有几次我的关注者数量莫名其妙地减少了。经过一番研究,我意识到一些用户基本上是如何抓取关注者的。他们评论、喜欢并关注他人——寻找追随者。只是为了在接下来的日子里不再关注他们。

我不能说这对我来说是一个惊喜,Instagram 中有机器人…这只是让我想自己建立一个!

这就是我们在这里的原因,让我们开始吧!我用 Python 开发了一个简单的机器人,当时我正在摆弄 Selenium,试图找出一些项目来使用它。简单地说,Selenium 就像一个浏览器,你可以在 Python 中非常容易地与之交互。

理想情况下,增加我的 Instagram 受众会让我有动力定期发布帖子。另外,我在我的个人简介中加入了我的网站,人们可以在那里购买一些照片。我认为这有点夸张,但是谁知道呢?!我的销售额到目前为止基本为零,所以跟踪那个转化应该很容易!

如果你想访问我的其他网络抓取文章——以及媒体上的几乎所有内容——你考虑过订阅吗?你会大力支持我的工作!

[## 阅读媒体上的每一个故事!

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@fneves/membership)

正是这个世界所需要的!又一个 Instagram 机器人…

在对这个项目进行了一番思考之后,我的目标是增加与我相关的人的数量。我想得到真正想关注我并看到我更多作品的追随者。在最常用的标签中很容易遇到奇怪的内容,所以我设计了这个机器人来查找特定的标签,并与那里的照片进行交互。通过这种方式,我可以非常具体地了解我希望我的观众有什么样的兴趣。例如,我真的很喜欢长时间曝光,所以我可以瞄准使用这个标签的人,并围绕这种内容建立一个观众群。简单高效!

我的画廊融合了不同的主题和风格,从街头摄影到空中摄影,还有一些旅行照片。因为这是我的家乡,我也有很多里斯本的照片。这些将是我在目标标签中使用的主要话题。

这不是一个“在 24 小时内获得 1000 名追随者”的机器人!

那么我们在谈论什么样的数字呢?

我在几个不同的标签中运行了几次这个机器人,比如“travelblogger”、“travelgram”、“lisbon”、“dronephotography”。三天之内,我的粉丝从 380 人增加到 800 人。大量的喜欢,评论,甚至一些有机增长(人们关注我,但没有被机器人关注)。

需要说明的是,我并不是在密集使用这个 bot,因为如果你运行得太快,Instagram 就会停止响应。它需要在动作之间有一些睡眠命令,因为在短时间内进行一些评论和跟随后,Instagram 会停止响应,机器人会崩溃。

你将登录到你的帐户,所以我几乎可以肯定,如果你加快这个过程,Instagram 可以知道你在做一些奇怪的事情。最重要的是,在做了十几个标签之后,在相同的标签中寻找新用户变得越来越困难。你需要几天时间来更新那里的用户群。

但是我不想在过程中跟着那么多人…

在 Instagram 中获得关注者的最有效方式(除了发布很棒的照片!)就是跟着人走。这个机器人对我来说真的很好,因为我不在乎我是否关注 2000 个人来获得 400 个关注者。

这个机器人保存了一个列表,里面有它运行时被跟踪的所有用户,所以有一天我可能真的会对这个列表做些什么。例如,我可以访问每个用户的个人资料,评估他们有多少关注者或帖子,并决定是否继续关注他们。或者,我可以从他们的图库中获取第一张图片,并检查其日期,看看他们是否是活跃用户。

如果我们从机器人中移除关注行为,我可以向你保证增长率将受到影响,因为人们不太倾向于根据单一的喜欢或评论进行关注。

你为什么要分享你的代码?!

这就是我和自己的辩论。即使我真的相信回报社会(我也从中学到了很多!),有几个付费平台做的和这个项目差不多。有些是黑幕,有些是名人用的。我自己启动一个类似平台的可能性还没有被排除,那么为什么要提供代码呢?

考虑到这一点,我决定给这个过程增加额外的难度,所以我将把代码作为图片发布在下面。我写了“曾经”,因为与此同时,我意识到我得到的图像是低质量的。这反过来让我重新考虑并张贴要点。我就是那么好!图像背后的想法是,如果你真的想使用它,你必须自己键入代码。这就是我限制这个工具的使用的方法,只限于那些真正经历了整个过程去创造它,甚至可能改进它的人。

当我自己键入代码,而不是复制/粘贴脚本时,我学到了更多。希望你也有同感!

这个剧本没有想象中那么复杂,我知道还有很大的改进空间。但是,嘿… 它起作用了!我有其他项目,我想添加到我的投资组合,所以我的时间来进一步发展它是相当有限的。尽管如此,如果我深入研究,我会尝试更新这篇文章。

这是最后一个字幕!

你需要 Python(我用的是 Python 3.7)、、Selenium 、一个浏览器(我用的是 Chrome)以及……显然,一个 Instagram 账户!关于机器人将做什么的快速概述:

  • 打开浏览器,使用您的凭据登录
  • 对于 hashtag 列表中的每一个 hashtag,它都会打开页面,点击第一张图片打开
  • 然后,它会喜欢,跟随,评论,并移动到下一张图片,在 200 次迭代循环(数量可以调整)
  • 保存您使用 bot 关注的所有用户的列表

如果你到了这一段,谢谢!你完全应该得到你的奖励!如果您发现这对您的个人资料/品牌有任何帮助,请在下面分享您的体验:)

为了配合 Selenium 使用 chrome,你需要安装 chromedriver 。这是一个相当简单的过程,我没有任何问题。只需安装和替换上面的路径。一旦你这样做了,我们的变量 webdriver 将成为我们的 Chrome 标签。

在 3 号单元格中,您应该用自己的用户名和相应的密码替换字符串。这是为了让机器人在显示的字段中键入它。你可能已经注意到,当运行 2 号单元格时,Chrome 打开了一个新标签。在密码之后,我将登录按钮定义为一个对象,在下面的行中,我单击它。

如果你想知道那些奇怪的弦是什么,不要害怕!在我的 文章 中,关于房地产网站的网页抓取,我也经历过类似的任务,包括检查网页以告诉机器人去哪里找。您可以非常容易地做到这一点,只需右键单击您想要映射的元素,并选择 Inspect。

一旦进入 inspect 模式,找到与您想要映射的内容相对应的 html 代码。右键单击它并将鼠标悬停在复制上。您将看到,对于如何复制它,您有一些选项。我在整个代码中混合使用了 XPath 和 css 选择器(在 find_element_ 方法中可以看到)。我花了一段时间让所有的参考顺利运行。有时,css 或 xpath 指示会失败,但是当我调整睡眠时间时,一切开始平稳运行。

在本例中,我选择了“复制选择器”并将其粘贴到一个 find_element_ 方法中(单元格编号 3)。它会给你找到的第一个结果。如果是 find_elements_ ,将检索所有元素,您可以指定要获取哪个元素。

一旦你做到了这一点,时间的循环。您可以在 hashtag_list 中添加更多的 hashtag。如果您第一次运行它,您仍然没有您所关注的用户的文件,因此您可以简单地创建 prev_user_list 作为空列表。

一旦你运行一次,它将保存一个带有时间戳的 csv 文件。该文件将在您第二次运行时用作 prev_user_list 。简单且容易跟踪机器人做了什么。

在接下来的运行中使用最新的时间戳进行更新,每次运行 bot 时,您都会得到一系列 csv 积压文件。

代码非常简单。如果你对 Python 有一些基本的概念,你可能会很快学会。我不是 Python 忍者,我能够创建它,所以我想如果你读到这里,你就可以开始了!

循环中的 print 语句是我发现能够有一个跟踪器的方式,它让我知道机器人一直处于哪个迭代。它将打印它所在的标签、迭代的编号以及为注释动作生成的随机数。我决定不在每一页都发表评论,所以我添加了三个不同的评论和一个 1 到 10 之间的随机数来定义是否有任何评论,或者是三个中的一个。循环结束后,我们将 new_followed 用户添加到先前用户的“数据库”中,并保存带有时间戳的新文件。你也应该得到一份小报告。

就是这样!

在几个小时没有检查电话之后,这些是我得到的号码。我绝对没有想到它会做得这么好!在我开始测试它的 4 天里,我有了大约 500 个新的追随者,这意味着我的观众在几天内翻了一番。我很好奇接下来几天我会失去多少新粉丝,看看这种增长是否可以持续。在我最新的照片中,我也有很多“赞”,但我猜这比后面的照片更令人期待。

I didn’t get the screenshot at the exact start of the bot, but you get the idea!

如果能让这个机器人在服务器上运行就好了,但是我还有其他项目要探索,配置服务器不在其中!欢迎在下面留言,我会尽力回答你的问题。

如果你想更认真地对待这个问题,我强烈推荐这些书:

  • 用 Python 进行网页抓取—https://amzn.to/3QRGzYt
  • 实用网页抓取—【https://amzn.to/3cyRVli

Picture taken by me — Azores

感谢阅读!如果你喜欢这篇文章,我邀请你看看我的其他故事。我主要感兴趣的是数据科学、Python、区块链和数字货币、技术,以及其他一些东西,如 摄影

如果你想取得联系,可以在这里联系我或者直接回复下面的文章。

声明:本文中的一些链接是附属链接。这意味着,对你来说零成本,如果你通过链接完成购买,我将赚取代销商佣金!

使用交互式代码在 Numpy 和 Tensorflow 中通过梯度上升进行独立分量分析

原文:https://towardsdatascience.com/independent-component-analysis-via-gradient-ascent-in-numpy-and-tensorflow-with-interactive-code-98b9a73e5d19?source=collection_archive---------4-----------------------

GIF from this website

我想了解更多关于独立分量分析的知识,我发现实际上有多种方法来计算这种运算。

请注意,这篇帖子是为了我对 ICA 更深入的了解。

计算独立分量分析的演进

首先,Bell 和 Sejnowski 使用 infomax 原理开发了原始 ICA。(于 1991 / 1994 年提出)。

Paper from this website

还有使用定点算法的 FastICA。(1997 年提交)

Paper from this website

还有从 Inria 出发的 FasterICA。(2017 年呈现)

Paper from this website

我对 ICA 如此着迷的原因之一是因为它的悠久传统。如上所述,从 1991 年到 2017 年,各种研究人员一直在研究这种方法。最后,我不太确定这个 pdf 是什么时候创建的,但是有一种方法可以通过 Andrew NG 的随机梯度下降来执行 ICA。

Paper from this website

带梯度上升的 ICA

Andrew Ng’s Gradient Ascent (left) Shireen Elhabian’s Gradient Ascent (Right) (source)

现在,当使用梯度上升执行 ICA 时,没有一个可靠的公式可以遵循。在我们不知道源密度的情况下,Ng 教授建议我们使用 Sigmoid 函数作为累积分布函数,但是 Elhabian 教授使用了 tanh 函数。(所以我想这真的取决于具体情况。).

我不会深入讨论梯度上升法的细节,因为我高度推荐论文本身,而是总结一下。

设 x = As 其中 x 是变换后的数据,A 是变换矩阵,s 是原始信号。我们要做的是估计 A,这样我们就可以恢复原始信号。当我们设置 A^-1 = W 时,我们可以很容易地看到 w 来自哪里。现在让我们来看看这种方法与 FastICA 相比如何。

使用 ICA 的 2D 数据分离

让我们首先从最简单的情况开始,如上所示,我们有两个真正独立的数据源作为散点图 2D。经过一些变换后,我们得到了如右图所示的散点图。我们已经可以看到,对于 PCA,新的基向量是相互正交的,它们指向数据中最大方差的位置。然而,对于 ICA 来说,新的基向量指向数据彼此最独立的方向。

在看结果之前,下面是我实现的代码的屏幕截图。我们将使用 FastICA、PCA、带 Sigmoid 的 ICA 和带 tanh 的 ICA。

如上所述,在最后阶段,我们可以观察到每种方法都(以自己的方式尝试)来恢复原始信号。注意,对于 epoch,我使用 10000 作为总迭代次数,学习率为 0.00003。

接下来,当我们绘制相关矩阵时,我们可以观察到类似上面的情况,我们可以安全地忽略除了前两行之外的所有内容。(让我们仔细看看它们)。

我们可以观察到 FastICA 在将数据分解成独立组件方面做得很好。(尽管变量发生了逆转,但这并不是一个大问题。)对于 PCA,我们可以看到不同变量之间仍然存在一些相关值。最后,使用双曲正切函数可以更好地分解数据。

当我们绘制每种方法的散点图时,我们可以清楚地看到 FastICA 和带双曲正切函数的 ICA 在分解方面做得最好。

使用 ICA 的波形数据分离

现在使用 sklean ICA 的例子,让我们看看梯度上升 ICA 如何处理波浪数据。同样,我们可以看到,对于这个例子,三个不同的信号通过某个随机变换矩阵 a 组合在一起。

如上所述,让我们首先使用 FastICA 和 PCA 来恢复原始信号。

为了让事情更有趣,让我们使用正常梯度更新规则,以及亚当优化器来更新权重 w。(并看看他们如何比较。)上述 ICA 梯度上升方法对 CDF 使用 sigmoid 函数。

最后,让我们使用双曲正切函数作为 cdf,看看哪个性能更好。此外,我还使用 tensorflow 实现了相同的技术。

如上所述,当所有的分解都完成时,我们可以观察到所有的方法都产生它们的恢复信号版本。

同样,我们可以画出相关矩阵,看看每种方法是如何执行的。

同样,我们只需看到前三行,显然 FastICA 在分解信号方面做得最好。对于 PCA,我们可以看到两个信号被恢复(部分),但是在不同信号之间仍然具有一些相关值。对于所有的梯度上升方法,我们可以看到 tanh 结合正常梯度更新规则产生了最好的结果。

当我们可视化结果信号时,我们可以看到 FastICA 做得最好。

互动码

对于谷歌实验室,你需要一个谷歌帐户来查看代码,你也不能在谷歌实验室运行只读脚本,所以在你的操场上做一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!

有关 2D 数据分离的代码,请点击此处。
有关波形数据分离的代码请点击此处。

遗言

研究 Andrew NG 和 Elhabian 教授的工作是一种荣誉,因为现在我们可以直接通过 back prop,我们可以大胆地做一些非常非常有趣的事情😉

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请在这里查看我的网站。

同时,在我的 twitter 这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。我也实现了广残网,请点击这里查看博文 pos t。

参考

  1. 熊猫,R. (2018)。重命名 pandas 中的列。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/11346283/rename-columns-in-pandas
  2. seaborn . heat map-seaborn 0 . 8 . 1 文档。(2018).Seaborn.pydata.org。检索于 2018 年 7 月 14 日,来自https://seaborn.pydata.org/generated/seaborn.heatmap.html
  3. matplotlib?,H. (2018)。如何改变用 matplotlib 绘制的图形的大小?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/332289/how-do-you-change-the-size-of-figures-drawn-with-matplotlib
  4. 标签,M. (2018)。Matplotlib 颜色根据类别标签。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/12487060/matplotlib-color-by-class-labels
  5. /ml/机器学习数据库/鲍鱼索引。(2018).Archive.ics.uci.edu。检索于 2018 年 7 月 14 日,来自http://archive . ics . UCI . edu/ml/machine-learning-databases/鲍鱼/
  6. 熊猫。data frame . plot . scatter—pandas 0 . 23 . 1 文档。(2018).Pandas.pydata.org。检索于 2018 年 7 月 14 日,来自https://pandas . py data . org/pandas-docs/version/0.23/generated/pandas。DataFrame.plot.scatter.html
  7. 法,一.(2018)。使用 pandas plot 方法设置图形大小时不一致。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/42215252/consistency-when-setting-figure-size-using-pandas-plot-method
  8. 熊猫。data frame . plot-pandas 0 . 23 . 1 文档。(2018).Pandas.pydata.org。检索于 2018 年 7 月 14 日,来自http://pandas . pydata . org/pandas-docs/version/0.23/generated/pandas。DataFrame.plot.html
  9. xaxis,P. (2018 年)。熊猫数据框线图显示 x 轴上的日期。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/44213781/pandas-data frame-line-plot-display-date-on-xaxis
  10. 带颜色散点图缺少 xticks 问题#10611 pandas-dev/pandas。(2018).GitHub。检索于 2018 年 7 月 14 日,来自https://github.com/pandas-dev/pandas/issues/10611
  11. numpy.linalg.inv — NumPy v1.14 手册。(2018).Docs.scipy.org。检索于 2018 年 7 月 14 日,来自https://docs . scipy . org/doc/numpy-1 . 14 . 0/reference/generated/numpy . Lina LG . inv . html
  12. NumPy . eye—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 7 月 14 日,来自https://docs . scipy . org/doc/numpy/reference/generated/numpy . eye . html
  13. 使用 FastICA 的盲源分离—sci kit—学习 0.19.1 文档。(2018).Scikit-learn.org。检索于 2018 年 7 月 14 日,来自http://sci kit-learn . org/stable/auto _ examples/decomposition/plot _ ICA _ blind _ source _ separation . html # sphx-glr-auto-examples-decomposition-plot-ICA-blind-source-separation-py
  14. 2D 点云上的 FastICA-sci kit-了解 0.19.1 文档。(2018).Scikit-learn.org。2018 年 7 月 14 日检索,来自http://sci kit-learn . org/stable/auto _ examples/decomposition/plot _ ICA _ vs _ PCA . html # sphx-glr-auto-examples-decomposition-plot-ICA-vs-PCA-py
  15. 梯度下降优化算法综述。(2016).塞巴斯蒂安·鲁德。检索于 2018 年 7 月 14 日,来自 http://ruder.io/optimizing-gradient-descent/index.html#adam
  16. 2D 点云上的 FastICA-sci kit-了解 0.19.1 文档。(2018).Scikit-learn.org。检索于 2018 年 7 月 14 日,来自http://sci kit-learn . org/stable/auto _ examples/decomposition/plot _ ICA _ vs _ PCA . html
  17. Python?,H. (2018)。如何用 Python 计算一个 logistic sigmoid 函数?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/3985619/how-to-calculate-a-logistic-sigmoid-function-in-python
  18. matplotlib?,H. (2018)。如何改变用 matplotlib 绘制的图形的大小?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/332289/how-do-you-change-the-size-of-figures-drawn-with-matplotlib
  19. NumPy . arctan—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 7 月 14 日,来自https://docs . scipy . org/doc/numpy/reference/generated/numpy . arctan . html
  20. NumPy . arctan—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 7 月 14 日,来自https://docs . scipy . org/doc/numpy/reference/generated/numpy . arctan . html
  21. 价值观?,h. (2018)。如何解释 numpy.correlate 和 numpy.corrcoef 值?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/13439718/how-to-interpret-numpy-correlate-and-numpy-corrcoef-values
  22. Python,C. (2018)。在 Python 中计算皮尔逊相关和重要性。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/3949226/calculating-Pearson-correlation-and-significance-in-python
  23. 相关系数:简单的定义,公式,简单的步骤。(2018).统计学如何?检索于 2018 年 7 月 14 日,来自http://www . statistics show to . com/probability-and-statistics/correlation-coefficient-formula/
  24. SciPy . stats . Pearson r—SciPy v 1 . 1 . 0 参考指南。(2018).Docs.scipy.org。检索于 2018 年 7 月 14 日,来自https://docs . scipy . org/doc/scipy/reference/generated/scipy . stats . Pearson r . html
  25. inria——数字世界的发明者。(2018).因里亚。检索于 2018 年 7 月 14 日,来自https://www.inria.fr/en/
  26. (2018).INF . fu-Berlin . de . 2018 年 7 月 14 日检索,来自http://www . INF . fu-Berlin . de/le hre/WS05/musterekennung/info max/info max . pdf
  27. 下载 FastICA。(2018).Research.ics.aalto.fi 于 2018 年 7 月 14 日检索,来自https://research.ics.aalto.fi/ica/fastica/code/dlcode.shtml
  28. (2018).Cs.helsinki.fi 于 2018 年 7 月 14 日检索,来自https://www.cs.helsinki.fi/u/ahyvarin/papers/NC97.pdf
  29. CS229:机器学习。(2018).Cs229.stanford.edu。检索于 2018 年 7 月 14 日,来自http://cs229.stanford.edu/syllabus.html
  30. (2018).Cs229.stanford.edu。检索于 2018 年 7 月 14 日,来自 http://cs229.stanford.edu/notes/cs229-notes11.pdf
  31. 数组?,H. (2018)。如何用几个 numpy 1d 数组创建熊猫数据帧?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/45399950/how-to-create-a-pandas-data frame-with-numpy-1d-arrays
  32. 剧情?,H. (2018)。如何更改 seaborn 图的图形大小?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/31594549/how-do-I-change-the-figure-size-for-a-seaborn-plot
  33. matplotlib?,H. (2018)。如何改变用 matplotlib 绘制的图形的大小?。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/332289/how-do-you-change-the-size-of-figures-drawn-with-matplotlib
  34. 热图标注字体大小问题#430 mwaskom/seaborn。(2018).GitHub。检索于 2018 年 7 月 14 日,来自https://github.com/mwaskom/seaborn/issues/430
  35. 热图,L. (2018)。在 seaborn heatmap 中分隔组的线条。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/39352932/lines-to-separate-groups-in-seaborn-heat map
  36. tf.eye |张量流。(2018).张量流。检索于 2018 年 7 月 14 日,来自https://www.tensorflow.org/api_docs/python/tf/eye
  37. TF . global _ variables _ initializer | tensor flow。(2018).张量流。检索于 2018 年 7 月 14 日,来自https://www . tensor flow . org/API _ docs/python/TF/global _ variables _ initializer
  38. 重新启动,R. (2018)。无需重启即可重置 IPython 内核。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/35492914/reset-an-ipython-kernel-without-restart
  39. 人们。(2018).Sci.utah.edu。检索于 2018 年 7 月 14 日,来自 https://www.sci.utah.edu/people/shireen.html
  40. (2018).Sci.utah.edu。检索于 2018 年 7 月 14 日,来自http://www . sci . Utah . edu/~ shire en/pdf/tutorials/El habian _ ICA 09 . pdf
  41. matplotlib,M. (2018)。在 matplotlib 中将 x 轴移动到绘图顶部。堆栈溢出。检索于 2018 年 7 月 14 日,来自https://stack overflow . com/questions/14406214/moving-x-axis-to-the-top-of-a-plot-in-matplotlib

奥运会上的印度

原文:https://towardsdatascience.com/india-at-the-olympics-d3b1c4e1468d?source=collection_archive---------12-----------------------

对青年事务和体育部的建议

在亚运会上,印度共获得 671 枚奖牌,排名第六。在英联邦运动会上,印度共获得 504 枚奖牌,排名第四。然而,在奥运会上,印度只获得了 28 枚奖牌,排名第 67 位。数据分析可用于为青年事务和体育部(GOI)提供建议,以提高印度在奥运会上的表现。分析流程图如下所示

分析的每个阶段的主要结果如下所示。

层次聚类

通过对参加过奥运会的国家进行聚类(基于每个国家在过去 120 年中获得的奖牌数量),我们发现有三个主要的聚类——一个是美国单独的聚类(红色聚类),第二个是 19 个国家的聚类(黄色聚类),第三个(蓝色)是世界其他国家(包括印度)的聚类。印度在蓝色集群中,下一步将进入第二集群(黄色集群),在一届夏季奥运会上赢得至少 53 枚奖牌。

解释集群

上述分组可以用各国在人口、人均国内生产总值、平均人类发展指数、公共卫生支出占国内生产总值的百分比、预期寿命以及平均教育指数方面的巨大差异来解释。

在所有这些变量中,选择其中四个用于下一阶段,即。人口、人均 GDP、预期寿命和公共卫生支出的回归分析。

多元线性回归

所选变量的散点图显示,人口和人均国内生产总值具有指数模式,如果进行转换,效果会更好。

“顺序替换”方法用于选择多元线性回归的最佳子集,即获得的奖牌数回归到公共卫生支出、预期寿命、log(人均 GDP)和 log(人口)上。

在进行删除诊断之后,回归模型在独立变量中具有显著的 F 统计量以及显著的β系数;也满足多元线性回归的假设。

然而,该模型的调整后 R 平方较低,仅为 22%。该模型的可视化显示,它在预测奖牌数量方面做得不太好。

因此,考虑使用逻辑回归模型。

逻辑回归

各国获得的奖牌数转化为一个二元变量,1 代表“53 块奖牌及以上”,0 代表“53 块奖牌以下”。“穷尽”模型选择方法为逻辑回归提供了相同的变量子集,即公共卫生支出、预期寿命、log(国内生产总值/人均)和 log(人口),具有最低 AIC 值。

负截距意味着当所有自变量都为 0 时,印度获得 53 枚以上奖牌的几率不到 50%。公共卫生支出每增加 1%,获得 53 枚以上奖牌的几率就会增加 0.50916,即增加 66%。同样,预期寿命增加 1 岁,赢得 53 枚以上奖牌的概率对数可能增加 0.42712,即增加 53%。此外,人均 GDP 每增加 k 倍,k^1.42818 时报获得超过 53 枚奖牌的几率就会降低;人口每增加 k 倍,k^0.815 时报获得超过 53 枚奖牌的几率就会增加。

回归诊断表明,logit 与数据拟合得很好,没有自相关,并且伪 R 平方度量更好(比线性模型更好)。然而,VIF 值高于多元线性回归,表明可能存在自相关。删除诊断揭示了要删除的 9 个观察值,并且逻辑回归模型被重新拟合到训练数据。构建混淆矩阵以基于二进制结果的值对数据进行分类,优化的截止值为 0.60。

预测分析

下一步是预测至少两届奥运会的变量,即直到 2026 年。不同的预测模型适用于 4 个变量(公共卫生支出、预期寿命、人均国内生产总值和人口)。这些方法包括移动平均、霍尔茨温特(乘法和加法)、指数和双指数方法,使用水平、趋势和季节性(α、β和γ)的默认参数值以及优化值。将每个模型的预测值与实际值进行对比,以确定最适合每个变量的模型。

基于训练和验证数据集的结果平均百分比误差(MAPE)来选择模型。然后对印度的变量进行预测,直到 2026 年。

研究发现,在未来 12 年,印度可能达到 72 岁的预期寿命,15.6 亿以上的人口和 3000 美元的人均国内生产总值(目前 2016 年)。

结果分类

逻辑回归模型用于对印度获得超过 53 枚奖牌的几率进行分类。基于对这 4 个变量的预测,尽管概率随着时间的推移而增加,但这种增加不足以得出印度将在 2020 年或 2024 年奥运会上进入第 2 组(黄色组)的结论。

将印度的增长与其他两个集群(即美国和竞争对手)的当前水平进行比较,以得出政策建议。

推荐

印度正以指数速度增长,但公共卫生支出却没有增长。国民的整体健康水平需要提高。此外,印度经济似乎不是为培养世界级运动员而设计的。印度落后于其他两个集群,为了提高印度在奥运会上的机会,政府干预是必要的。政府。印度政府需要将公共卫生支出增加一倍(占 GDP 的百分比)。青年事务和体育部需要为鼓励体育运动提供更多支持。这可以采取与第二组国家建立体育合作的形式(即“竞争者”),鼓励运动员在第二组国家(即“竞争者”),在城镇和乡村发展世界级的体育训练设施,并向现有的体育团体等提供财政援助。

面临的挑战

互联网上关于奥运会的数据集相互矛盾。我假设奖牌数是由参加比赛的“运动员”来计算的。国家一级的体育和运动员数据不容易获得。决定运动员在奥运会上表现的因素需要更多的研究。

使用的工具

Google Chrome 用于背景研究和下载基础数据;用于数据预处理和初步清理的电子表格软件;r 用于处理数据和得出统计见解;用于可视化结果的表格;苹果 QuickTime,用于演示代码工作流程;iMovie 用于编辑影片剪辑,YouTube 用于托管视频

参考文献

弗里皮克(2018)“弗里皮克的图标”,www.flaticon.com,2018 年 9 月 20 日访问。

奥运会(2018)“结果”,https://www.olympic.org/olympic-results,2018 年 9 月 12 日访问。

数据中的世界(2018)“健康”,https://ourworldindata.org/health-meta,2018 年 9 月 11 日访问

联合国数据(2018)"雇员",http://data.un.org/Data.aspx?q=sport&d = UNIDO&f = table code % 3a 04% 3 bisic code % 3a 3693,于 2018 年 9 月 12 日获取。

维基百科(2018)“教育指数”,https://en.wikipedia.org/wiki/Education_Index,2018 年 8 月 20 日访问。

维基百科(2018)《按人口统计的国家列表(联合国)》,https://en . Wikipedia . org/wiki/List _ of _ countries _ by _ population _(联合国),2018-8-20 访问。

维基百科(2108),“亚运会上的印度”,【https://en.wikipedia.org/wiki/India_at_the_Asian_Games ,于 2018 年 9 月 17 日访问

维基百科(2108),“英联邦运动会上的印度”,https://en . Wikipedia . org/wiki/India _ at _ the _ Commonwealth _ Games,2018 年 9 月 17 日访问

维基百科(2108),“奥运会上的印度”,https://en.wikipedia.org/wiki/India_at_the_Olympics,于 2018 年 9 月 17 日访问

世界银行集团(2018)“国内生产总值(现值美元)”,https://data.worldbank.org/indicator/NY.GDP.MKTP.CD,2018 年 8 月 12 日获取。

印度人类住区研究所-实习旅程至今。

原文:https://towardsdatascience.com/indian-institute-for-human-settlements-internship-journey-so-far-7ffbb9d521d0?source=collection_archive---------2-----------------------

到我在 NIT Surat计算机工程第五学期结束时,所有的同学要么在寻找实习机会,要么已经在校园里找到了。我是那群寻找好实习机会的人中的一员,尤其是研究实习。我之前在初创公司实习过几次,也有过自己的初创公司,所以这次我想去做一个研究实习,这将非常适合我未来的努力。我犯的第一个错误是把我的 CGPAs 记在心里,我没有申请任何外国大学实习项目,以为我会在筛选过程中被直接从名单中剔除,但情况并非总是如此。

在 11 月至 12 月期间,我开始记下一份来自世界各地在数据科学和机器学习领域工作的教授的名单,并在 12 月底之前开始给名单上的教授发电子邮件。这是我的第二个错误,因为那时全球各地都是圣诞假期和冬季假期。在那段时间里,我发出了大约 50-60 封电子邮件,为每一位教授策划一个特定的内容。我开始收到自动生成的回复,提到“度假”、“旅行”、“不在办公室”等等。学长们总是说要获得一个研究实习机会,你所需要的就是耐心,这也是我一直坚持的。到了三月,我知道现在是时候了。

今年 3 月,我申请了几个研究所的实习项目和几个在我感兴趣的领域工作的初创公司。三月对我来说基本上是最难熬的一个月,因为我要在 3 月 30 日写 GRE,还得去实习研究。同时协调两者是困难的。我每天的时间表是早上和晚上阅读 GRE 考试,下午与教授和初创公司进行面试。在我的 GRE 考试之后,在下周的一个周一下午,我和一个朋友坐在一起寻找项目结果,在那里我得到了我的第一份研究实习,师从来自 IIIT 德里计算生物学中心的 Ganesh Bagler 教授 (1 次面试),项目是使用机器学习进行食物配对分析(分子水平)。周三,我又收到了来自班加罗尔your story(1 次面试)和班加罗尔 (2 次面试)印度人类住区研究所(IIHS)的两份工作邀请。在 Yourstory,项目是创建一个机器学习工具,它根据给定的面试数据,使用自然语言处理自动生成文章和故事。在 IIHS,该项目旨在使 Landsat 8 和 Sentinel 2 波段图像的土地覆盖分类自动化。现在的问题是选择去哪里

我听从了自己的心声,决定接受 IIHS 的邀请。

印度人类住区研究所(IIHS)是一个国家教育机构,致力于公平、可持续和有效地改造印度住区。

他们就是这么说自己的。这里最棒的事情是,我必须在多位教授和导师的指导下工作,他们都拥有国外知名大学的学位。我在他们的招待所住了一周。2017 年 5 月 10 日,我开始了在班加罗尔 IIHS 的实习。第一天我很早就到了,坐在接待处,这时一位来自人民职能部门的女士走过来,向我打招呼“欢迎来到 IIHS”,并带我一起去,我做了所有的手续和材料。那天,作为城市校园之旅的一部分,我见到了在 IIHS 工作的每一个人。有趣的是,我穿着正装去那里,那里的人穿着便装和 kurtas。我第一天学到的一件事是,在职业世界里,没有人使用“先生”、“女士”、“T2”和“T3”。我应该直呼我的教授和导师的名字。我非常惊讶地看到这里的人们经过多年的研究后为各国政府撰写住房政策,有些人设计排水系统,有些人研究世界各地的各种城市居住计划。我在地理空间实验室有一些很棒的同伴,他们叫洛克什、查鲁和尼勒克什,他们带我学习地理信息系统的基础知识。我过去常常问他们一些非常愚蠢的问题,他们总是积极地帮助我。他们是实验室里的地理空间忍者,让工作环境变得愉快。

The IIHS City Campus building

第一周—城市信息实验室

我被分配的第一个项目是由普林斯顿大学的城市统计学家 Shriya Anand 负责的。在她的房价分析项目中,数据生成是一个大问题,我在那里帮助他们。我必须创建一个工具,从所有流行的住房平台获取价格、纬度、经度、位置、平方英尺面积、新/转售等数据。当时我知道如何用 Python 抓取数据,并认为这是一个简单的第一个任务,直到我遇到了魔术砖的无限滚动平台。每当你滚动到最后,它生成新的数据,页面高度增加。像 beautifulsoup 这样的普通库在这里没有用,必须使用 selenium 的浏览器自动化。我必须解决无限滚动的问题,让数据保持原样。最后,我将一些 javascript 代码注入到我的 python 脚本的 selenium 模块中,该模块为我完成了这项工作,此处提供。到那个周末,我已经准备好了 PyQt 应用程序,它为你完成了所有的浏览器自动化和抓取工作。

Caffeine Love

第 2 周—地理空间实验室

我对地理空间情报这个热门词汇感到兴奋,更兴奋的是对它进行研究。主题是“机器学习如何应用于地理空间数据,以及我们如何自动生成分析?”。这个项目是我这次实习的主要项目,我必须在荷兰特温特大学研究员 Teja Malladi 和加州大学伯克利分校研究员兼城市规划师Krishna chandran Balakrishnan的指导下工作。最初,我和他们开了几次会,以了解项目的整体情况。简而言之,我可以告诉你的是,从卫星图像中,他们想直接找到建筑物的高度,居住在这些定居点的人的阶级,一个地区种植的作物类型,预测城市的城市发展以及你能想到的所有疯狂的事情。根据我们的谈话,我必须做研究和建立智能系统,可以从卫星图像进行这种分类。所以,在我的第二周,我浏览了很多关于 OpenCV(计算机视觉)的资料,它是如何工作的,我能从中得到什么。

Geospatial Lab, IIHS

第 3 周—地理空间实验室

现在,我已经准备好利用我现有的所有技能,包括数据科学、机器学习、计算机视觉和地理信息系统。我从实验室的同伴那里得到了一些 Landsat 8 波段的图像。Landsat 8 有 11 幅波段图像组合成一幅单幅卫星图像。我们都听说过 jpg、png、gif、tiff 等图像格式,这些波段图像是 Geotiff 格式的。Geotiff 图像的特殊之处在于,这里的每个像素都有一些 RGB 值以及附加到该像素的经度和纬度。这是我无法想象的事情…嘣!你把这个图像加载到一个软件中,它就直接适合所有地理空间分析的世界地图。OpenCV 可以接受所有格式的图像,但是 Geotiff 狗屎!通过四处搜索,我发现 OpenCV 在这里不能为我做任何事情。我遇到了另一个令人惊奇的东西,叫做GDAL——地理空间数据抽象库,它用于读取地理标签和它拥有的所有地理空间数据。OpenCV 可以单独从 geotiffs 中读取 RGB 值(实际上是 BGR,因为 OpenCV 实际上遵循它)。然后,我开始从波段中提取 RGB 数据,探索机器学习算法,如神经网络、SVM 和决策树等,并将它们应用于数据以检查结果(准确性)。我有一个算法的训练数据池,但以训练集格式获取数据是一项艰巨的工作。

SF042

除了工作,迄今为止,IIHS 的文化融合了学术界和工业界。我花了 5000 美元在班加罗尔呆了 4 天,找到了一个不错的单人合租 PG 住。当你有大学朋友在城里时,周末总是很有趣。夜生活很棒,因为每隔一条街你都能找到很棒的酒吧。我去了一趟南迪山,那是一块坚固的花岗岩,也是班加罗尔附近(60 公里外)风景最好的小山站。到目前为止,我唯一不喜欢的是这里的交通:)

A view from Nandi Hills

总之,当你将计算机科学的知识运用到地理信息学、城市规划和人类住区发展等其他跨学科领域时,总会感觉很神奇。为了实现我暑期实习的最终结果,还有很多东西需要探索,更多的特征需要从地球资源卫星数据中提取。希望一切顺利!

个人利益与公共利益:人工智能玩家的公地悲剧

原文:https://towardsdatascience.com/individual-gain-vs-the-common-good-tragedy-of-the-commons-with-ai-players-77ffb40f0c6a?source=collection_archive---------18-----------------------

Panorama photo I took at Lake Cochabamba on a trip to Bolivia in 2017

对于社会科学专业的学生来说,公地悲剧将是一个熟悉的例子,说明理性的个人行为如何对整个社会产生负面影响。公地悲剧的最初例子发生在 1833 年,当时英国经济学家威廉·福雷斯特·劳埃德讨论了在公共土地上放牧的问题。从那以后,个人过度利用公共土地/物品的想法被应用到不同的主题中。另一个经典的例子是新英格兰鳕鱼渔场的过度捕捞。

New England Cod fishing

公地悲剧的基本前提是,以理性方式行事的个人会耗尽公共资源,因为他们最大化了自己的效用,即使可以说保留这些公共资源供未来使用符合他们的最佳利益。这是因为未来是不确定的,个人有动机最大化自己的个人效用。在没有任何外部监管/行动的情况下,这意味着他们应该利用现有资源,而不是为了不确定的未来而抑制消费。

社会科学提出的避免这种公地悲剧的解决方案是制定法规或措施来帮助抑制即期消费,这将有助于所讨论的资源在未来生存。这方面的一些例子是将资源放在私人手中,对其使用附加费用/许可,或者对其施加法律/法规以供政府/社会执行。

这一切都很好,但我是一名数据科学家,喜欢构建人工智能。那这和这里有什么关系?我认为数据科学和深度学习通常是朝着某个目标优化的过程。这个目标可以是最大化胜率或准确率,这是很好的,也是非常令人满意的。然而,随着人工智能越来越多地融入我们的社会,我们选择优化的目标将会产生越来越多的社会后果。为了说明选择优化什么是重要的,这篇文章将讲述我如何建立一个环境,让强化学习机器人的训练上演公地悲剧,以及调整它们的奖励如何改变游戏的社会影响。

Another Lake Cochabamba photo, glad I am getting mileage out of this part of my photo portfolio

教机器人钓鱼

第一步是建立一个游戏环境来模拟公地悲剧。我的例子是基于我在网上为经济学课程找到的一个版本。

游戏由两个玩家和渔场中的一些起始数量的鱼初始化,当渔场数量下降到某个阈值以下时,游戏结束,该阈值代表由于过度捕捞导致的种群崩溃。最后吃到最多鱼的人获胜。每个回合玩家同时宣布他们将捕获多少鱼,如果总捕获量没有迫使种群低于阈值,每个玩家获得他们的捕获量,并且剩余的鱼都有一个后代,最大数量永远不会超过最初的鱼数量。在最后一个回合,剩下的鱼根据玩家在该回合宣称要拿多少鱼来分配。因此,如果我声明 10 条鱼,你声明 8 条鱼,剩下 9 条,我将得到 5 条,你将得到 4 条。

游戏本身是一个循环,只有当渔业人口崩溃(低于 8 的阈值)或游戏达到 100 回合时才会打破。我添加了 100 转的限制,以避免循环无限运行。

在游戏中,鱼的起始数量是 20 条,我有两个玩家,一个是“电脑玩家”,它会根据当前的渔业水平随机选择鱼的价值,还有一个 Keras 强化学习机器人。这个 Keras 机器人将是这篇文章的重点,通过测试调整其奖励结构如何影响游戏的结果。

作为上下文输入到神经网络中的游戏状态是 5 节点输入的当前计算机得分、机器人得分、总渔业计数、过去计算机得分、过去机器人得分。网络的输出层是 20 个节点,代表在给定的回合中要申报的不同数量的鱼,1-20 条鱼。为了更好地了解机器人的训练周期,我认为有必要回顾一下强化学习,特别是深度 q 学习。

游戏详情见悲剧. py 。TOC 类包含游戏函数和其他一些运行游戏和报告结果的实用函数。

网络位于 netlearner.py 文件中

快速深度 Q-学习回顾

这一部分是为了展示机器人是如何被训练的,以及它们是如何学习它们所展示的特定游戏行为的。从高层次上来说,机器人的条件是基于它们对结果的奖励和惩罚。为一个神经网络机械地做这件事显然和为一个生物做这件事不太一样,所以最好把它展示出来。基本流程如下:

  1. 代理(在这种情况下是网络)被告知游戏的当前状态。这可能是 atari pong 游戏的像素,也可能是你选择的任何表示。这是当前鱼的数量,玩家和电脑的分数,玩家和电脑最近的拍摄。我的想法是,这是一个人类玩家在玩游戏时会有的环境类型。
  2. 代理从动作空间中选择一个动作。在 Pong 的例子中,Andrej Karpathy 把它作为上升的概率。在本例中,这意味着选择 20 个输出节点中的一个,对应于声明捕获 1-20 条鱼。这里需要注意的一点是,这里有探索与开发的概念。本质上是说,有时应该随机选择一个动作,而不是简单地做代理认为最好的事情。这有助于代理探索和发现额外的奖励,否则如果它只是利用它知道的奖励,它将不会发现。
  3. 行动被归入环境,任何奖励被收集,环境进入下一个状态、框架或回合。机械地,我这样做是通过将奖励添加到网络输出的卡槽组合中。对于正的奖励,该类别在输出数组中的值增加,并且网络将再次看到给定该输入,该特定类别是有益的。
  4. 代理根据其收到的奖励进行更新。在奖励被用于修改输出阵列之后,网络以修改后的输出阵列为目标在初始输入状态上被训练。这有助于巩固好的选择,同时也考虑到坏的选择。
  5. 冲洗并重复。

参见前面提到的 netlearner.py 和harvest . py文件之间的交互

Photo from Tsukiji bluefin tuna auction in Tokyo from a 2014 trip. Seems appropriate for a tragedy of the commons writeup

以公共利益为代价的胜利

我发现奖励的标准配置创造了非常“贪婪”的机器人。通过标准配置,我的意思是我把奖励放在赢的时候,负奖励放在输的时候,没有奖励放在两者之间。通常这样做是为了让机器人能够了解什么行为导致他们获胜,并允许他们最大限度地提高胜率。这种行为在像 Atari Pong、Cartpole 或其他以胜利为目标的游戏中很有用。但这种获胜的最大化并不一定意味着它有良好的社会后果。

我甚至尝试根据回合数来调整输赢奖励(我在一些测试中使用了回合数的 sqrt ),以激励在较长的游戏中获胜,但结果仍然相同,机器人玩的是非常贪婪的游戏风格。

那么我说的“贪心打法”是什么意思呢?…基本上,当我用这些奖励训练机器人时,机器人赢得了大约 99%的时间,这很酷!基本上,机器人已经想出了如何最大化他们对我编写的小电脑玩家的胜率。然而,他们平均在一个回合中达到 99%的胜率。

机器人陷入的策略是宣布在第一轮捕获更多数量的鱼,这导致渔场的数量立即崩溃。然后,因为在最后一轮的条件下,种群是根据每个玩家申报的鱼的数量来划分的,如果机器人申报的鱼多,它会自动击败对手。即使机器人可以通过玩更长时间来获得额外的奖励,即使它设置为在 10%或 20%的回合中探索,它仍然落入相同的策略,并且不学习玩更长时间的游戏。

这很有趣,因为这种类型的机器人具有共同的回报结构和最大化获胜的行为几乎与经典公地悲剧中的代理人完全相同。机器人可以通过在更长的时间内保持资源来获得更大的回报,但相反,它决定现在消耗资源以最大化其短期收益,因为它可能会也可能不会在未来获胜。因此,虽然这个机器人已经学会了如何赢,并且赢得很好,但它也过度消耗并破坏了有问题的资源。

现在让我们用一行代码来捣乱…

2017 photo from Valencia, Spain. I liked the futuristic look of this part of the city.

一个提高公共效用的机器人

所以我在上一节中列出了机器人的奖励结构,现在如果我调整奖励结构的一部分会怎么样。把胜利和失败的奖励留在原地,我进行了多次测试,其中对继续转弯的奖励在 1.5、5 和 10 之间的正值之间变化。我发现它创造了“利他”的机器人,可以玩更长时间的游戏,但机器人的胜率因此受到影响。

从技术角度来看,我正在测试这个想法,即设置 1.5 的奖励意味着机器人会发现学习玩长度大于 2 的游戏对自己有益(因为奖励是获胜回合数的 sqrt)。我对机器人如何玩 1000 多个游戏窗口进行了基准测试,发现根据迭代,机器人的胜率在 85-91%之间,平均游戏持续 2-4 轮。

在奖励为 5 的情况下,机器人以相当低的 36%的胜率和 7 的回合数开始,但是以 59%的胜率和 11 的游戏长度结束了它的训练,并且来自训练的最后部分的一些测试游戏是长度为 100 的游戏,机器人以 406 到 401 的分数获胜。

在奖励为 10 的情况下,机器人的胜率不会超过 30-40%,但它们的游戏会进行到 100 轮。所以他们学习对游戏继续有用的行为。但不一定会赢。由于机器人会非常专注于简单地让游戏继续,很多时候他们遵循的策略是每回合简单地拿走 4-5 条鱼。因此,如果我试图优化这些机器人来获胜,这是一个非常糟糕的训练它们的方式。

然而,我们不只是想让机器人获胜,所以让我们退后一步,想想机器人的行为!

Shibuya X photo from a trip to Tokyo, I had my family sit in a second story of a Starbucks for an hour so I could take short timelapse photos of the crossing… Things like this are why it is hard to travel with photographers I think.

确定的胜利或为共同利益而优化

在一个未受监管的公地悲剧版本中,作为理性代理人的参与者应该试图最大化他们的短期收益,而不是希望一个不确定的未来。“贪婪”的机器人反映了这种行为,它们采取接近 100%胜率的策略,在第一个回合就获胜。

然而,如果我们考虑资源的消耗。立即烧掉所有的资源很少是我们的目标,相反,资源的继续存在对每个人都有好处。因此,如果我们能够建立激励机制,允许可持续的捕捞,这将导致比一轮捕捞更多的鱼。

从机械/游戏理论的角度来看,玩这个游戏的可持续方式是让两个玩家每个回合拿 5 条鱼,总共拿 10 条。这使得渔业数量从 20 下降到 10。因为渔业数量不低于 8,所以人口翻倍,从 10 到 20。这意味着渔业可以无限期地维持下去。

这种平衡在实际操作中很难保持,因为参与者之间没有交流,并且需要参与者放弃短期收益(一定的胜利)而不是让所有参与者收集更多的鱼(增加集体效用)。在现实世界中,这可能会随着监管/监控/文化规范/私有化之类的事情而发生。

因此,当“贪婪的”机器人为快速获胜而优化时,那些因继续游戏而获得更多奖励的“利他的”机器人开始为行为而不是简单的获胜而优化。事实上,机器人开始表现得非常类似于我上面提出的这种更可持续的最佳游戏。

在奖励为 10 的情况下,机器人玩这种保守游戏的更安全版本,并且每回合只玩 4-5 条鱼,基本上放弃任何获胜的机会。至于平衡胜率和平均回合数,奖励 5 机器人保持更具竞争力的姿态,每回合吃 4-6 条鱼。这种额外的竞争力反映在他们更高的胜率,同时仍然试图不耗尽渔业。

所有更无私的机器人都被优化来尝试并赢得比赛,但是是在更长的比赛中。这种多部分优化意味着有一些权衡,在这种情况下,这意味着他们赢得了更低的百分比的时间,但如果在更大的背景下,你可能会认为这是没问题的。

在玩更长时间的游戏时,机器人有时会赢,但有时也会落后很多,例如一些 100 回合的游戏以 350-400 到 600+的分数结束。虽然就胜利或失败而言,这是一个相当惊人的损失,但如果你考虑到鱼类的继续存在为整个社区带来了额外的效用,那么即使机器人没有为自己赢得那么多,这仍然是一个非常有利的结果。

通过比较一个模拟生成的鱼的总数,这个惊人的损失可能是一个好的结果。“贪婪”机器人的胜利使双方玩家总共收获了 20 条鱼。机器人赢了,资源没了。“利他”机器人玩 100 场游戏,可能会输,但双方玩家会收集 800-1000 条鱼。

Photo from back home on Maui, Hawaii

最后的想法

作为一名经济学家/社会科学家,这篇文章直截了当地展示了如何使用深度学习/强化学习对偏好的修改进行建模,以说明达到更高水平的整体社会效用的方法。

作为一名数据科学家,这篇文章是我拐弯抹角的评论,随着人工智能与社会的融合程度越来越高,我们选择如何优化人工智能以及我们在构建人工智能时所做的权衡将会产生更多后果。

我可能会改进我在这篇文章中应用的 RL 方法,并尝试让机器人学习更强的策略来增加他们的胜率,无论回合数是多少。截至目前,连续回合奖励较高的机器人牺牲了胜利,陷入了非常弱的整体策略。通过更多的实验,机器人可能会学会如何维持鱼的数量,但也会采取行动缩小它们与对手之间的差距,或增加对对手的领先优势。这可以是另一个时间的项目。

感谢阅读!

Github 回购此处

One last picture taken on the way to Honolua Bay on Maui, Hawaii

用机器学习和动手 Python 对网站进行行业分类

原文:https://towardsdatascience.com/industrial-classification-of-websites-by-machine-learning-with-hands-on-python-3761b1b530f1?source=collection_archive---------2-----------------------

嘿伙计们,欢迎来到我的第一个技术教程。在本教程中,我想解释提取,清理和分类网站到不同的类别。我会用 python 环境运行我的代码进行数据抓取,用神经网络对网站进行分类。

Text classification

文本分类是在数据科学的许多不同领域中广泛使用的自然语言处理任务之一。一个有效的文本分类器可以使用 NLP 算法有效地自动将数据分类。

文本分类是监督机器学习任务的一个例子,因为包含文本文档及其标签的标记数据集用于训练分类器。

一些常见的文本分类技术有:

  1. 朴素贝叶斯分类器
  2. 线性分类器
  3. 支持向量机
  4. 装袋模型
  5. 增压车型
  6. 深度神经网络

网页抓取网页抓取网页数据提取是用于从网站中提取数据的数据抓取。一般来说,这是通过模拟人类网上冲浪的软件从不同的网站收集特定的信息来完成的。

可用于网页抓取的一些技术有:

  1. 人类复制粘贴
  2. 文本模式匹配
  3. HTTP 编程
  4. HTML 解析
  5. DOM 解析
  6. 垂直聚集
  7. 语义标注识别
  8. 计算机视觉网页分析

在本教程中,我们将尝试将完整的模型实现为三个不同的模块:

  1. 数据抓取
  2. 用于创建训练数据集的基于关键字的分类
  3. 将神经网络应用于实际测试模型

模块 1:数据搜集

在本模块中,我将使用 Python 3.5 环境来实现我的脚本。因此,请跟随以获取完整的参考资料。

步骤 1:从网站请求数据

为了提取 web 数据,可以使用许多不同的包,但是在本教程中,我将使用 请求

**import** **requests
url='**https://medium.com/**'
try:** page = requests.get(url)        #to extract page from website
    html_code = page.content        #to extract html code from page
except **Exception** **as** e:
    print(e)

在上面的代码中,requests.get()方法将使用 https 协议从网站请求页面,并将页面加载到对象“ page”中。下一行代码将把 HTML 代码移动到字符串 html_code 中。因此,到目前为止,我们已经从网站上提取了数据,但它仍然是 HTML 格式,与实际文本相差甚远。

步骤 2:从 HTML 页面中提取文本

为了从 HTML 页面中提取完整的文本数据,我们有两个非常受欢迎的包,beautiful souphtml2text 。使用上一步找到的 html_code 字符串,我们可以应用下面两种方法中的任何一种。

**from** **bs4** **import** BeautifulSoup
try:
    soup = BeautifulSoup(html_code, 'html.parser')  #Parse html code
    texts = soup.findAll(text=**True**)                 #find all text
    text_from_html = ' '.join(texts)                   #join all text
except **Exception** **as** e:
    print(e)

在上面的代码片段中, BeautifulSoup 包将解析 HTML 代码并将数据分配给 soup 对象。findall () 函数从代码中找到所有可见的文本,并返回一个字符串列表,我们将它存储在文本中。最后,我们使用 join() 函数将所有单独的文本连接成一个公共字符串。

**import** **html2text** h = html2text.HTML2Text()                 #Initializing object
h.ignore_links = **True** #Giving attributes **try:** text = h.handle(html_code)            #handling the HTML code 
    text_from_html=text.replace("**\n**"," ") #replacing next line char
except **Exception** **as** e:
    print(e)

在这个替换块中,我们使用 package html2text 来解析字符串,并直接从 html 代码中获取文本。我们还需要用空格替换空行,最后找到 text_from_html。

类似地,我们可以在大约 1000 多个 URL 上使用循环,并从这些站点提取数据,并将它们存储为 csv(逗号分隔文件)格式,我们可以在分类模块中进一步使用该格式。

模块 2:基于关键字的分类

对于任何机器学习算法,我们都需要一些训练集和测试集来训练模型和测试模型的准确性。因此,为了创建模型的数据集,我们已经有了来自不同网站的文本,我们将根据关键字对它们进行分类,然后在下一个模块中应用结果。

在本教程中,我们将把网站分为三类,即:

  1. 技术、办公和教育产品网站(Class_1)
  2. 消费品网站(Class_2)
  3. 工业工具和五金产品网站(Class_3)

这里的方法是,我们将拥有属于特定类别的某些关键字,我们将这些关键字与文本进行匹配,并找到具有最大 Matching_value 的类别。

Matching_value =(与一个行业匹配的关键字数)/(匹配的关键字总数)

因此,相应地,我们有一个单独类别的关键字列表,如下所示:

Class_1_keywords = ['Office', 'School', 'phone', 'Technology', 'Electronics', 'Cell', 'Business', 'Education', 'Classroom']Class_1_keywords = ['Restaurant', 'Hospitality', 'Tub', 'Drain', 'Pool', 'Filtration', 'Floor', 'Restroom', 'Consumer', 'Care', 'Bags', 'Disposables']Class_3_keywords = ['Pull', 'Lifts', 'Pneumatic', 'Emergency', 'Finishing', 'Hydraulic', 'Lockout', 'Towers', 'Drywall', 'Tools', 'Packaging', 'Measure', 'Tag ']keywords=Class_1_keywords + Class_2_keywords + Class_3_keywords

现在,我们将使用 关键字处理器 来查找从 URL 接收的文本中的关键字。

关键字处理器 在 pypi 上的 flashtext 包中有。

**from** **flashtext.keyword** **import** KeywordProcessor
kp0=KeywordProcessor()
**for** word **in** keywords:
    kp0.add_keyword(word)kp1=KeywordProcessor()
**for** word **in** Class_1_keywords:
    kp1.add_keyword(word)kp2=KeywordProcessor()
**for** word **in** Class_2_keywords:
    kp2.add_keyword(word)kp3=KeywordProcessor()
**for** word **in** Class_3_keywords:
    kp3.add_keyword(word)

在上面的代码中,我们将使用关键字加载 KeywordProcessor 对象,我们将进一步使用这些关键字来查找匹配的关键字。

为了找到匹配值的百分比值,我们定义一个函数百分比如下:

**def** percentage1(dum0,dumx):
    **try**:
        ans=float(dumx)/float(dum0)
        ans=ans*100
    **except**:
        **return** 0
    **else**:
        **return** ans

我们现在将使用 extract_keywords(string)方法来查找文本中出现的关键字。我们将查找该列表的长度,以找到文本中匹配关键字的数量。以下函数将查找百分比,并选择百分比最大的类。

def find_class:
    x=str(text_from_html)
    y0 = len(kp0.extract_keywords(x))
    y1 = len(kp1.extract_keywords(x))
    y2 = len(kp2.extract_keywords(x))
    y3 = len(kp3.extract_keywords(x))
    Total_matches=y0   
    per1 = float(percentage1(y0,y1))
    per2 = float(percentage1(y0,y2))
    per3 = float(percentage1(y0,y3))
    **if** y0==0:
        Category='None'
    **else**:
        **if** per1>=per2 **and** per1>=per3:
            Category='Class_1'
        **elif** per2>=per3 **and** per2>=per1:
            Category='Class_2'
        **elif** per3>=per1 **and** per3>=per2:
            Category='Class_3'
    return Category

在上面的函数中使用一个循环,我们可以根据关键字找到所有网站的类别。我们将分类数据保存到文件 Data.csv 中,我们将进一步使用该文件。因此,现在我们已经为应用神经网络进行分类准备好了数据集。

模块 3:应用神经网络

Classification of websites

在下面的实现中,我们将从头开始创建一个神经网络,并将使用 NLTK 单词标记化器进行预处理。首先,我们需要导入从上述步骤中获得的数据集,并将其加载到一个列表中。

**import** **pandas** **as** **pd** data=pd.read_csv('Data.csv')
data = data[pd.notnull(data['tokenized_source'])]
data=data[data.Category != 'None']

上面的代码将加载和清理分类数据。空值将被删除。

下面的代码将根据它的类创建一个数据字典。

**for** index,row **in** data.iterrows():
    train_data.append({"class":row["Category"], "sentence":row["text"]})

为了应用神经网络,我们需要将语言文字转换成数学符号,用于计算。我们将列出所有字符串中的所有单词。

words = []
classes = []
documents = []
ignore_words = ['?']
*# loop through each sentence in our training data*
**for** pattern **in** training_data:
    *# tokenize each word in the sentence*
    w = nltk.word_tokenize(pattern['sentence'])
    *# add to our words list*
    words.extend(w)
    *# add to documents in our corpus*
    documents.append((w, pattern['class']))
    *# add to our classes list*
    **if** pattern['class'] **not** **in** classes:
        classes.append(pattern['class'])

*# stem and lower each word and remove duplicates*
words = [stemmer.stem(w.lower()) **for** w **in** words **if** w **not** **in** ignore_words]
words = list(set(words))

*# remove duplicates*
classes = list(set(classes))

print (len(documents), "documents")
print (len(classes), "classes", classes)
*print (len(words), "unique stemmed words", words)*

例如,输出将是:

1594 个文档
3 个类['Class_1 ',' Class_3 ',' Class_2']
唯一词干 40000 个

现在,我们将为该模式创建一个单词列表,并使用 NLTK Lancaster 斯特梅尔创建一个单词包。

**from** **nltk.stem.lancaster** **import** LancasterStemmerstemmer = LancasterStemmer()
*# create our training data*
training = []
output = []
*# create an empty array for our output*
output_empty = [0] * len(classes)

*# training set, bag of words for each sentence*
**for** doc **in** documents:
    *# initialize our bag of words*
    bag = []
    *# list of tokenized words for the pattern*
    pattern_words = doc[0]
    *# stem each word*
    pattern_words = [stemmer.stem(word.lower()) **for** word **in** pattern_words]
    *# create our bag of words array*
    **for** w **in** words:
        bag.append(1) **if** w **in** pattern_words **else** bag.append(0)

    training.append(bag)
    *# output is a '0' for each tag and '1' for current tag*
    output_row = list(output_empty)
    output_row[classes.index(doc[1])] = 1
    output.append(output_row)

print ("# words", len(words))
print ("# classes", len(classes))

输出:

word 41468

class 3

现在,我们对数据进行最后的预处理,并创建一些函数。

乙状结肠功能

**def** sigmoid(x):
    output = 1/(1+np.exp(-x))
    **return** output

*# convert output of sigmoid function to its derivative*
**def** sigmoid_output_to_derivative(output):
    **return** output*(1-output)

清洁功能

**def** clean_up_sentence(sentence):
    *# tokenize the pattern*
    sentence_words = nltk.word_tokenize(sentence)
    *# stem each word*
    sentence_words = [stemmer.stem(word.lower()) **for** word **in** sentence_words]
    **return** sentence_words

包话功能

**def** bow(sentence, words, show_details=**False**):
    *# tokenize the pattern*
    sentence_words = clean_up_sentence(sentence)
    *# bag of words*
    bag = [0]*len(words)  
    **for** s **in** sentence_words:
        **for** i,w **in** enumerate(words):
            **if** w == s: 
                bag[i] = 1
                **if** show_details:
                    print ("found in bag: **%s**" % w)

    **return**(np.array(bag))

最终将用于神经网络的函数:思考函数

**def** think(sentence, show_details=**False**):
    x = bow(sentence.lower(), words, show_details)
    **if** show_details:
        print ("sentence:", sentence, "**\n** bow:", x)
    *# input layer is our bag of words*
    l0 = x
    *# matrix multiplication of input and hidden layer*
    l1 = sigmoid(np.dot(l0, synapse_0))
    *# output layer*
    l2 = sigmoid(np.dot(l1, synapse_1))
    **return** l2

现在我们已经准备好训练我们的神经网络模型。我们将通过 scratch 实现它,并将对每个神经元使用逻辑回归。只有一层,但有 50000 个历元,我们将训练我们的模型。完整的训练示例将在 CPU 上运行。

**def** train(X, y, hidden_neurons=10, alpha=1, epochs=50000, dropout=**False**, dropout_percent=0.5):

    print ("Training with **%s** neurons, alpha:**%s**, dropout:**%s** **%s**" % (hidden_neurons, str(alpha), dropout, dropout_percent **if** dropout **else** '') )
    print ("Input matrix: **%s**x**%s**    Output matrix: **%s**x**%s**" % (len(X),len(X[0]),1, len(classes)) )
    np.random.seed(1)

    last_mean_error = 1
    *# randomly initialize our weights with mean 0*
    synapse_0 = 2*np.random.random((len(X[0]), hidden_neurons)) - 1
    synapse_1 = 2*np.random.random((hidden_neurons, len(classes))) - 1

    prev_synapse_0_weight_update = np.zeros_like(synapse_0)
    prev_synapse_1_weight_update = np.zeros_like(synapse_1)

    synapse_0_direction_count = np.zeros_like(synapse_0)
    synapse_1_direction_count = np.zeros_like(synapse_1)

    **for** j **in** iter(range(epochs+1)):

        *# Feed forward through layers 0, 1, and 2*
        layer_0 = X
        layer_1 = sigmoid(np.dot(layer_0, synapse_0))

        **if**(dropout):
            layer_1 *= np.random.binomial([np.ones((len(X),hidden_neurons))],1-dropout_percent)[0] * (1.0/(1-dropout_percent))

        layer_2 = sigmoid(np.dot(layer_1, synapse_1))

        *# how much did we miss the target value?*
        layer_2_error = y - layer_2

        **if** (j% 10000) == 0 **and** j > 5000:
            *# if this 10k iteration's error is greater than the last iteration, break out*
            **if** np.mean(np.abs(layer_2_error)) < last_mean_error:
                print ("delta after "+str(j)+" iterations:" + str(np.mean(np.abs(layer_2_error))) )
                last_mean_error = np.mean(np.abs(layer_2_error))
            **else**:
                print ("break:", np.mean(np.abs(layer_2_error)), ">", last_mean_error )
                **break**

        *# in what direction is the target value?*
        *# were we really sure? if so, don't change too much.*
        layer_2_delta = layer_2_error * sigmoid_output_to_derivative(layer_2)

        *# how much did each l1 value contribute to the l2 error (according to the weights)?*
        layer_1_error = layer_2_delta.dot(synapse_1.T)

        *# in what direction is the target l1?*
        *# were we really sure? if so, don't change too much.*
        layer_1_delta = layer_1_error * sigmoid_output_to_derivative(layer_1)

        synapse_1_weight_update = (layer_1.T.dot(layer_2_delta))
        synapse_0_weight_update = (layer_0.T.dot(layer_1_delta))

        **if**(j > 0):
            synapse_0_direction_count += np.abs(((synapse_0_weight_update > 0)+0) - ((prev_synapse_0_weight_update > 0) + 0))
            synapse_1_direction_count += np.abs(((synapse_1_weight_update > 0)+0) - ((prev_synapse_1_weight_update > 0) + 0))        

        synapse_1 += alpha * synapse_1_weight_update
        synapse_0 += alpha * synapse_0_weight_update

        prev_synapse_0_weight_update = synapse_0_weight_update
        prev_synapse_1_weight_update = synapse_1_weight_update

    now = datetime.datetime.now()

    *# persist synapses*
    synapse = {'synapse0': synapse_0.tolist(), 'synapse1': synapse_1.tolist(),
               'datetime': now.strftime("%Y-%m-**%d** %H:%M"),
               'words': words,
               'classes': classes
              }
    synapse_file = "synapses.json"

    **with** open(folder_path+synapse_file, 'w') **as** outfile:
        json.dump(synapse, outfile, indent=4, sort_keys=**True**)
    print ("saved synapses to:", synapse_file)

最后,我们将训练模型:

import time
X = np.array(training)
y = np.array(output)

start_time = time.time()

train(X, y, hidden_neurons=10, alpha=0.1, epochs=50000, dropout=**False**, dropout_percent=0.2)

elapsed_time = time.time() - start_time
print ("processing time:", elapsed_time, "seconds")

输出:

用 10 个神经元训练,alpha:0.1,dropout:False
输入矩阵:1594x41468 输出矩阵:1 x3
10000 次迭代后的 delta:0.0665105275385
20000 次迭代后的 delta:0.0610711168863
30000 次迭代后的 delta:0.0561908365355
40000 次迭代后的 delta

正如我们所看到的,训练这个模型花了将近 11 个小时。在如此密集的计算之后,我们准备测试数据。

测试数据的函数:

*# probability threshold*
ERROR_THRESHOLD = 0.2
*# load our calculated synapse values*
synapse_file = 'synapses.json' 
**with** open(synapse_file) **as** data_file: 
    synapse = json.load(data_file) 
    synapse_0 = np.asarray(synapse['synapse0']) 
    synapse_1 = np.asarray(synapse['synapse1'])

**def** classify(sentence, show_details=**False**):
    results = think(sentence, show_details)

    results = [[i,r] **for** i,r **in** enumerate(results) **if** r>ERROR_THRESHOLD ] 
    results.sort(key=**lambda** x: x[1], reverse=**True**) 
    return_results =[[classes[r[0]],r[1]] **for** r **in** results]
    *#print ("\n classification: %s" % ( return_results))*
    **return** return_results

让我们测试模型的准确性:

classify("Switchboards Help KA36200 About Us JavaScript seems to be disabled in your browser You must have JavaScript enabled in your browser to utilize the functionality of this website Help Shopping Cart 0 00 You have no items in your shopping cart My Account My Wishlist My Cart My Quote Log In BD Electrical Worldwide Supply Remanufacturing the past SUSTAINING THE FUTURE Hours and Location Michigan Howell")

输出:

[['Class_3 ',0.9766343788614435]]

classify("  New Website Testimonial Policies Parts Catalog Contact Support Forum Documentation Themes WordPress Blog Products Spindle Parts Latest News Kennard Parts Suggest Ideas Legal/Disclaimers WordPress Planet News About CDT Home Latest News Testimonial Products Parts Catalog About CDT History Staff Policies Centrum Legal Disclaimers Contact About CDT Custom Drilling Technologies established in 1990 has been providing superior customer service to the printed circuit board industry for almost 20 years We specialize in Excellon Drilling and Routing Equipment Parts and Service Our staff has over sixty years of combined experience in the design building troubleshooting operation programming")

输出:

[['Class_1 ',0.96297535870017]]

如你所见,我们在这些测试中获得了相当高的准确度。我在不同的数据上尝试了这个模型,发现它有相当高的准确性。

在这种只有一层的模型中,大约 95%以上的精度被认为是非常准确的。对于不同模型的进一步分类,我们可以使用 Keras 或 Tensorflow。为了减少训练模型的时间,我们可以使用 NVIDIA GPU。

现在,借助反向传播的深度神经网络,我们可以很容易地收集数据并对其进行分类。

在后续教程中,我将尝试解释 Keras 和 Tensorflow 的工作和实践。

请在下面的评论区或通过我的 LinkedIn 页面分享您对本教程的反馈:https://www.linkedin.com/in/ridhamdave/。也分享一下你对这个教程的疑惑。

关于机器学习的行业故事

原文:https://towardsdatascience.com/industry-stories-about-machine-learning-bb5652455fe2?source=collection_archive---------9-----------------------

伦敦 PAPIs.io 2018 大会笔记

上周我去参加了 PAPIs.io Europe 2018 大会,在伦敦金丝雀码头大厦举行。

该会议将自己描述为“一系列致力于现实世界机器学习应用以及推动这些应用的创新、技术和工具的国际会议”(据我所知,名称 papis 来自“预测 API”)。

我在周四去了那里,那一天是专门讨论“工业和创业”的,我对我所看到的做了一些笔记。下面快速总结一下!

The view from the 39th floor of Canary Wharf Tower.

采用 Kubernetes、Dask 和 Jupyter 的 ML 基础设施

上午的主题演讲由 Olivier Grisel 主讲,他可能因对 scikit-learn 的巨大贡献而闻名——因此任何用 Python 进行机器学习的人都应该感谢他!他的幻灯片在网上这里。

在这个大约 23 分钟开始的视频中,他展示了如何使用三个主要的开源组件来建立自己的机器学习基础设施: Kubernetes (一个基于容器的集群编排系统) Dask (一个并行化 python 作业的工具,它与现有的 python 库如 pandas/numpy 深度集成)和 Jupyter Notebooks (著名的交互式开发 web 应用)。

具体来说,他使用 minikube 在本地运行 kubernetes,使用 jupyter hub 在一台 jupyter 服务器上管理多个用户。他展示的第一个例子有些琐碎(例如,增加一个计数器),但这使他能够深入地描述计算是如何分布和执行的。第二个例子展示了如何运行网格搜索来为支持向量机找到最佳参数,使用 dask-joblib 在集群上运行。

问答中我最喜欢的一句话是一个关于开发 ML 系统的即兴评论:“你不应该在 Jupyter 笔记本上做所有的事情”(因为这对维护来说不是很好)。

使用自动气象站进行边缘预测

第二个演讲人是来自亚马逊的人工智能/人工智能传播者朱利安·西蒙(他在这里写博客)。从这个视频的第 59 分钟开始,他的演讲集中在运行数据中心之外的机器学习预测(“在边缘”——在摄像机、传感器等方面)。).实现这一点需要,也许并不奇怪,经历一场机器学习系统可用的各种 AWS 服务的旋风之旅。其中包括:

  • 用胶子和 MXNet 定义和操纵模型;
  • 用 SageMaker 建立和训练模型;
  • 使用λ编写按需预测函数;
  • 使用 Greengrass 将代码部署到边缘设备。

他的演讲以最近推出的“世界上第一款面向开发者的深度学习摄像机”DeepLens 的演示结束,展示了实时物体检测的作用。

管理工程师和数据科学家角色之间的差距

其中一个涉及非常有趣话题的演讲是由来自数据驱动广告公司 dataxu 的 Beth Logan 主持的。她描述了他们如何着手开发和自动部署机器学习管道(因此标题为“驾驶时更换轮胎”这个演讲是在线的这里是)以支持广告领域的各种应用。

离开 ML 本身,有一些有趣的观点是关于如何管理“数据科学家”和“工程师”的工作,以使每个角色发挥他们的优势。实际上,这是让数据科学家开发和迭代模型,同时将生产和扩展模型的所有工作留给工程师,工程师还必须证明生产实现的性能符合预期。

数据科学和工程的交叉是一个我可能会写一整篇博文的主题;可以说,我们在最后讨论了这样的划分是否是“正确”的方式,以及在合作时每个学科如何超越另一个学科。

机器学习中的流水线丛林

下一个发言人是来自另一家处理数字广告的公司 Appnexus 的 Moussa Taifi。他讨论了为点击预测建立各种管道,这是在线广告的一项常见任务。

穆萨在研究和生产之间来回穿梭时,谈到了开发管道的一些实际问题。这些问题包括:一旦管道过于复杂(“丛林”),就很难再现结果;为实验进行模型版本控制;避免时间旅行等常见问题(对测试集中的数据之后创建的数据进行培训);以及不管手头的任务如何,采用即时数据转换和特征提取的系统与根据预先计算的固定特征集构建模型相比,哪一种更好。

建立机器学习的文化

Lars Trieloff 发表了一篇关于在 Adobe 内部培育人工智能文化的高级演讲——特别关注 Adobe Sensei 。他的演讲跨越了三个广泛的领域:品牌、愿景和技术,以及这三者需要如何结合才能在组织内培养机器学习的文化。有趣的是,他还谈到了责任——以及在开发新的机器学习工具时,公司的所有员工需要如何经历培训和批准过程。

机器学习的可行性与投资回报

来自 BigML 的 Poul Petersen 发表了一篇关于该公司如何预测 2018 年奥斯卡获奖者中的 6 位的演讲——见这篇博文有一些类似的内容。除了奥斯卡奖,他还提出了一个有趣的观察,即如何根据对机器学习项目的可行性和预计投资回报的比较,对这些项目进行优先排序。如果两者都很低,这显然是一个禁区;如果两者都很高,这是一个显而易见的,你应该已经在努力了。剩下的两个类别是“可推迟”(低投资回报率,高度可行)和“脑力劳动者”(高投资回报率,目前不可行)。

他给出了一个类似的类比,根据特定系统的发展阶段,哪些算法是他的目标:早期阶段,需要快速原型(逻辑回归),中期阶段,你有一个经过验证的应用程序(随机森林),最后是后期阶段,调整性能变得至关重要(神经网络)。

创业推介和小组讨论——欧洲人工智能景观

创业推介分散在一天当中。我在这里看到的:

  • 逻辑时钟:他们有一个名为 Hops 的企业机器学习平台,旨在提高数据科学家的生产力。
  • Antiverse :旨在利用人工智能在一天内发现抗体药物。
  • Tensorflight :通过使用机器学习分析卫星和航空数据,实现财产检查自动化。
  • 为企业客户提供单一联系点,自动化他们与你联系的各种方式。

这些创业公司中的一些在一天结束时参加了一场创业大战,这是由一个 AI 判断的。当我第一次听说这件事时,我有些怀疑,但它实际上非常有趣。每个初创公司都被 Alexa 轮流提问,问题涉及团队的规模、经验和结构,并根据各种因素进行评分。获胜者赢得了 10 万英镑!

相反,创业小组采取了回顾的视角——回顾 Twizoo(在我离开前不久,被 Skyscanner 收购)、 prediction.io (在伦敦成立后被 Salesforce 收购)和 Seedcamp 。反复出现的主题是关注客户而不是机器学习的重要性:技术是解决客户痛苦的使能器,与客户的需求相比,需要在过程中解决的抽象机器学习问题几乎是多余的。

这一天有许多不同的外卖。一个突出的现象是,机器学习领域的欧洲创业公司仍然在蓬勃发展。事实上,Juno AI项目的 Libby 宣布他们正在开始新一轮的地形测绘——这个项目绝对值得一试并为之做出贡献。

英超联赛中的不平等

原文:https://towardsdatascience.com/inequality-in-the-premier-league-a3a9a7294d96?source=collection_archive---------3-----------------------

Pixabay

由于许多学者所做的出色研究,我们现代社会中日益扩大的收入和财富不平等已经开始引起媒体和决策者的注意。在本文中,为了让读者熟悉不平等研究中的一个关键概念——基尼系数,我将展示我的一个附带项目的结果:英格兰超级联赛中的足球运动员价值不平等。

衡量一个国家收入(或财富)不平等程度最常用的方法是基尼系数。科拉多·基尼在 1962 年发明了这个系数,用来衡量收入的分配情况。想象一个 100 人的村庄,他们一起生产和销售价值 10 万美元的商品。如果每个村民每月都有 1000 美元的收入,那么基尼系数将会是 0,因为收入是平均分配的。另一方面,如果村里只有 1 个人获得全部销售收入,10 万美元;而其他村民什么也得不到,基尼系数将升至最大值 1。这 10 万美元在这 100 名村民中的任何其他可能分配都会得到 0 到 1 之间的基尼系数。

在当今世界,收入不平等程度最低的国家往往是前苏联或斯堪的纳维亚国家,基尼系数通常低于 0.30(或 30%)。在另一个极端,我们看到了基尼系数超过 0.60 的南非。非洲和拉丁美洲的收入不平等程度很高,而欧洲国家的收入不平等程度与世界其他地区相比相对较低。当然,值得注意的是,许多盛产石油的中东国家不存在不平等数据,那里的不平等水平可能是世界上最高的。

好吧,既然我们现在知道基尼系数是如何工作的,我们可以用它来衡量其他经济概念的分布。你可能已经听说了,欧洲足球联赛的冬季转会窗口最近关闭了。英格兰俱乐部出手阔绰,总共花费了 4 . 3 亿英镑,他们实际上已经打破了转会截止日的记录。这个数字是巨大的,但是仔细想想,这些钱大部分都花在了少数球员的转会上,这个窗口最贵的转会是 7500 万,超过了整个金额的 1/6。

当一个俱乐部花费塞尔维亚每天的 GDP(国内生产总值)仅仅是为了转会一名球员,球队内部的平衡和平等会发生什么?

让我们看看英超的球队到底有多不平等。首先,在这个问题的理想研究中,我们应该有每个参与者收入的完美信息。不幸的是,据我所知,没有这样的信息来源。然而,感谢 Transfermarkt 网站,我们知道了球员的估计市场价值。当然,这些都是主观的价值,它们不一定反映实际的市场价值,但是,如果我们假设在转会市场上更有价值的球员比那些价值较低的球员赚得更多,它们可以很好地代表球员的收入。

一旦我们有了每个球员的估计市场价值,我们就可以计算基尼系数来衡量足球运动员在英超球队中的价值分布。你可以在上图中找到 2005 年以来英超各队的基尼系数。我们看到,2005 年至 2013 年间,平均不平等从 0.48 左右降至 0.44,但此后又开始上升。2005 年的阿森纳阵容是我们样本中最不平等的一个,基尼系数超过 0.60,而 2013 年的斯托克城基尼系数最低,为 0.27。

就目前的情况来看,价值不平等和英超联赛的成功之间有着很强的正相关关系。在我们的样本中,拥有更多不平等阵容的球队赢得了更多的分数。当然,相关性并不意味着因果关系。不平等的球队也可能是拥有最好(或更贵)球员的球队,上图正好反映了这一点。事实上,当我们观察五巨头——阿森纳、切尔西、利物浦、曼城和曼联时,我们会发现它们的不平等水平在大多数赛季中一直高于英超联赛的平均水平,尽管不平等水平有下降趋势(见下图)。

显然,当我们检查总市值和成功之间的联系时,我们看到了明显的正相关,但这次是二次关系(下图)。挥金如土的球队也比其他英超球队更成功,但这并不令人惊讶。

如果你想研究英超联赛中每支球队的不平等程度是如何变化的,我还创建了一个信息丰富且易于使用的 Tableau 仪表盘——如下图所示。不幸的是,这些仪表板不能嵌入到媒体中,所以如果你想检查一下,请随时访问www.baymul.com/en/data-viz-epl.html并亲自处理数据。

The full, interactive version of this visual above can be found at http://www.baymul.com/en/data-viz-epl.html

推断统计学基础

原文:https://towardsdatascience.com/inferential-statistics-basics-294512909a33?source=collection_archive---------6-----------------------

简介:

统计是数据科学家需要的最重要的技能之一。统计学涉及大量的数学知识,很难掌握。因此,在本教程中,我们将浏览一些统计学的概念,以学习和理解推断统计学并掌握它。

为什么我们需要推断统计学?

考虑这样一种情况,你对孩子们每天看电视的平均时间感兴趣。现在你知道你所在地区的儿童平均每天看 1 小时电视。你如何为所有的孩子找到这个?

有两种方法可以用来计算结果:

  1. 收集每个孩子的数据。
  2. 使用我们掌握的数据来计算总体平均值。

第一种方法是极其困难和令人生畏的任务。完成这项任务所需的努力和资源将是巨大的。

第二种方法简单得多,也更容易实现。但是有一个问题。你不能把从有限的数据集中得到的平均值等同于整个人口。考虑这样一种情况,你所在地区的儿童对体育运动更感兴趣,因此他们花在电视上的时间明显少于总人口。我们如何着手寻找人口平均数?这就是推理统计学帮助我们的地方。

推理统计:

推理统计学帮助我们回答以下问题:

  • 从样本中对总体进行推断
  • 推断样本是否与总体显著不同。让我们看看前面的例子,我指出样本与总体不同,因为孩子们对体育更感兴趣,而不是看电视。
  • 从模型中添加或删除一个特征是否有助于改进它。
  • 如果一个模型明显不同于另一个。
  • 假设检验。

这向我们展示了为什么推断统计学是重要的,以及为什么值得投入时间和精力来学习这些概念。

正态分布和 z 统计量:

正态分布也称为钟形曲线,具有以下特性:

  1. 均值=中位数=众数。
  2. 曲线是对称的,一半的值在左边,一半的值在右边。
  3. 曲线下的面积是 1。

Image credit: University of Virginia

在正态分布中:

  • 68%的数据在平均值的一个标准偏差范围内
  • 95%的数据落在平均值的两个标准偏差内
  • 99.7 %的数据落在平均值的三个标准偏差内。

为了计算事件发生的概率,我们需要 z 统计量。计算 z-统计量的公式为

其中 x 是要计算 z 值的值。μ和σ分别是总体均值和标准差。基本上,我们在这里做的是通过将平均值移动到 0 并将标准偏差转换为 1 来标准化正态曲线。z-统计量实际上是以标准差形式计算的值与平均值的距离。因此,z 值 1.67 意味着该值在正方向上偏离平均值 1.67 个标准偏差。然后,我们通过从 z 表中查找相应的 z 值来找到概率。

中心极限定理;

正态分布的主要重要性来自中心极限定理。中心极限定理表明,无论总体分布的形状如何,随着样本量的增加,样本均值的抽样分布都接近正态分布。让我们通过一个例子来看这个问题。考虑这样一种情况,我们查看一个人一周内的推文数量(随机生成的数据在 0 到 200 之间)。数据的频率分布如下所示:

这与我们所知的任何一种分布都不相似。

现在,让我们从这些数据中随机抽取 1000 个大小为 50 的样本,并计算每个样本的平均值。当我们绘制这些平均值时,我们得到一个正态分布曲线,也称为采样曲线采样分布

平均值= 98.78(人口平均值= 98.87)

中心极限定理有一些重要的性质:

  1. 总体的平均值大约等于抽样分布的平均值。我们可以在上面的例子中看到这一点,其中总体平均值(98.87)大约等于抽样分布的平均值(98.78)。
  2. 抽样分布的标准偏差也称为标准误差,等于总体标准偏差除以样本大小的平方根。因此,样本量越大,标准偏差越低,从总体平均值确定样本平均值的准确度越高。

  1. 不管总体分布的形状如何,样本均值的分布都是正态分布。这意味着,即使我们的原始分布是偏态或双峰分布或其他分布,样本均值始终是正态分布。这就是中心极限定理如此强大的原因。

为了使中心极限定理成立,样本量应该足够大(一般大于 30)

置信区间:

就像我之前说过的,我们找到了样本平均值,并且想要估计总体平均值。样本统计对潜在人口的估计有多准确一直是个问题。置信区间解决了这个问题,因为它提供了可能包含总体参数的一系列值。

image credit: Luis Fok, Oregon State University

有单侧或双侧置信区间。在双侧置信区间中,如果我们选择 95%的置信区间,我们在尾部的每一侧选择 2.5%,然后计算范围。在单侧置信区间中,我们通过在分布的左边或右边取整个 5%来计算置信区间。上图显示了一个双侧置信区间。我们用来计算置信区间的公式是:

这些符号代表什么

Sample Mean

Z value for the desired confidence level

confidence level

the standard deviation of the population

置信区间概念中的另一个重要术语是误差幅度。它是置信区间的一半。它被称为抽样误差,这意味着如果样本平均值在误差范围内,那么它的实际值就是总体平均值,差异只是偶然出现的。否则,结果被认为具有统计学意义。我们将在后面的教程中再次讨论这个概念。

当我们取 95%的置信区间时,并不意味着总体均值在我们以 95%的概率得出的范围内。置信区间表示包含未知总体参数真值的可能置信区间的频率(即比例)。因此,如果我们取无限多的样本,并找出每个样本的置信区间范围,那么包含总体参数的区间数就等于置信区间。如果我们取 95%的置信区间,那么这意味着总体参数存在于所有可能的置信区间范围的 95%中。

这些是继续前进所需的一些基本概念。

激进化对社交媒体的影响模型

原文:https://towardsdatascience.com/influence-models-of-radicalization-on-social-media-a762fbc35c36?source=collection_archive---------9-----------------------

数据科学在工作中发现 ISIS 极端分子和恐怖主义在网上传播

Photo by Tom Roberts on Unsplash

考虑到当前激进思维和激进主义的趋势,理解激进主义如何在在线社交网络上发挥作用至关重要。

一个数据科学项目基于取自社会科学模型的“激进化的根源”模型,研究了 激进化影响 的问题。这项工作围绕着被认为具有影响力的三个层面:

  • 微观影响:内部的、个人的影响,由该人在 Twitter 上发布的帖子来表示。
  • 中观影响力:小群体影响力,以他人帖子为代表,分享。
  • 宏观影响:全球影响,以公共网站为代表(这部分未被涵盖,因为大多数网站实际上都被执法机构屏蔽了)。

通过分析部首语音风格 (n-gram 模型)研究了部首化,并通过语言的余弦相似性将人与部首化进行了比较。

Kaggle 上有一个数据集,包含 112 名普通(非激进)用户和 112 名亲 ISIS 的激进用户。

进行了两项主要分析。

1.我能理解一个用户是否真的激进了吗?

第一个分析是关于激进和非激进用户的分类,基于个人和社会(中观层次)。结果表明,这两个方面密切相关:

因此,即使使用非常简单的分类器,用户也可以很容易地被分为两类。朴素贝叶斯分类已经达到 90%的精度。

2.我能预测用户是否会受到影响从而变得激进吗?

第二项分析着眼于对激进化的预测。为了做到这一点,用户的时间表被分成两个依赖于时间的集合,帖子的前 80%用于培训,最新的 20%用于测试。因此,对于激进化预测,中性用户组的精度更高,亲 ISIS 激进组的召回率更高。在这两种情况下,准确率和召回率都不是很高。这可能是因为在激进化的时间窗口中应该考虑到可能的灵活性。因此,可以应用进一步的研究来改进这种现象的检测。

这项关于 激进化影响 的研究已经由 Miriam Fernandez 、Moizzah Asif、Harith Alani(英国 KMI 开放大学)在阿姆斯特达姆网络科学大会 2018 上发表。

关于这项研究的全文可在线获取。

这篇论文在 WebSci2018 上获得了最佳论文奖

信息根——生成性对抗网络第三部分

原文:https://towardsdatascience.com/infogan-generative-adversarial-networks-part-iii-380c0c6712cd?source=collection_archive---------1-----------------------

结账我的 YouTube 上甘斯的视频 。本文原载于

在第一部分中,提交了原始 GAN 文件。第二部分对 DCGAN 进行了概述,它极大地提高了 GANs 的性能和稳定性。在这最后一部分,将探讨 InfoGAN 的贡献,它应用信息论中的概念将一些噪声项转换成对结果有系统、可预测影响的潜在代码。

动机

正如在第二部分的例子中所看到的,当对发生器的噪声矢量进行算术运算时,可以做一些有趣且令人印象深刻的事情。在下面来自 DCGAN 论文的例子中,戴眼镜的男人的输入噪声向量被操纵以给出导致戴太阳镜的女人一旦被馈送到生成器中的向量。这表明在噪声向量中有结构对发电机输出具有有意义且一致的影响。

然而,没有系统的方法找到这些结构。这个过程是非常手动的:1)生成一堆图像,2)找到具有你想要的特征的图像,3)将它们的噪声向量平均在一起,并希望它捕捉到感兴趣的结构。

改变发电机输出的唯一“旋钮”是噪声输入。因为它是噪音,所以没有关于如何修改它以获得想要的效果的直觉。问题是:“如果你想要一个戴眼镜的男人的图像——你如何改变噪声?”这是一个问题,因为你的表象是纠缠。InfoGAN 试图解决这个问题,并提供了一个清晰的表示

这个想法是提供一个潜在代码,它对输出有意义和一致的影响。例如,假设您正在处理 MNIST 手写数字数据集。你知道有 10 个数字,所以如果你能通过把部分输入赋给一个 10 态离散变量来使用这个结构就好了。希望是,如果你保持代码不变,随机改变噪声,你会得到相同数字的变体。

Entangled vs Disentangled

InfoGAN

InfoGAN 解决这个问题的方法是将生成器输入分成两部分:传统的噪声向量和新的“潜在代码”向量。然后,通过最大化代码和发电机输出之间的互信息,使代码变得有意义。

理论

该框架仅通过将正则化项(红框)添加到原始 GAN 的目标函数来实现。

λ是正则化常数,通常设置为 1。我(c;G(z,c))* 项是潜在码 c 和发电机输出 G(z,c) 之间的互信息。*

显式计算互信息是不实际的,因此使用标准的变分论点来近似下限。这包括引入一个“辅助”分布 Q(c|x) ,该分布由一个参数化的神经网络建模,并且旨在逼近真实的 P(c|x)P(c|x) 表示在给定生成的输入 x 的情况下,码 c 的可能性。然后,他们使用一种重新参数化的技巧,使您可以只从用户指定的先验(即均匀分布)中采样,而不是未知的后验。

**

上面的正则项转化为以下过程:从你选择的先验中为潜在代码 c 采样一个值;从您选择的先验中采样噪声值z;生成 x = G(c,z);计算 Q(c|x=G(c,z))

然后,目标函数的最终形式由互信息的下限近似给出:

体系结构

如上所述,现在有了生成器的第二个输入:潜在代码。理论部分介绍的辅助分布由另一个神经网络模拟,它实际上只是一个完全连接的层,附加在鉴别器的最后一个表示层上。Q 网络本质上是试图预测代码是什么(见下面的细微差别)。这只在输入假输入时使用,因为这是唯一知道代码的时候。

InfoGAN architecture. New components outlined in red.

这里有一个很难理解的细微差别。为了计算正则项,您不需要估计代码本身,而是需要估计对于给定的生成输入,看到该代码的可能性。因此, Q 的输出不是代码值本身,而是您选择用来对代码建模的分布的统计数据。一旦知道了概率分布的充分统计量,就可以计算可能性了。

例如,如果您使用连续值代码(即在-1 和+1 之间),您可以将 Q(c|x) 建模为正态/高斯分布。在这种情况下, Q 将为这部分代码输出两个值:平均值和标准差。一旦你知道了平均值和标准差,你就可以计算出可能性 Q(c|x),,这就是你需要的正则项。

结果

在 MNIST 手写数字数据集上的训练报告了初步结果。作者指定了一个 10 态离散码(希望它能映射到手写的数字值),以及两个介于-1 到+1 之间的连续码。为了进行比较,他们训练了一个具有相同结构的常规 GAN,但没有使用最大化互信息的正则化项。

下图显示了一个过程,其中特定的噪声矢量保持不变(每行),但潜在代码发生了变化(每列)。在部分 a 中,您可以看到离散代码不断改变数字。部分 b 显示常规 GAN 基本上没有显著或一致的变化。

零件 cd 显示了 InfoGAN 的连续代码变化。这显然会影响手指的倾斜度和宽度。有趣的是,它们实际上从-2 变化到+2,即使训练只使用从-1 到+1 的值,这表明这些代码有意义地推断。

Comparing InfoGAN to regular GAN when changing code values. From InfoGAN paper.

这是一些面部图像的结果。请参见论文了解更多结果和解释。

Results on 3D face model dataset

Results on CelebA dataset

结论

值得强调的是,从来没有预先指定倾斜或手指粗细将有助于分离为代码。InfoGAN 训练程序自己发现了这些属性,即在无人监督的情况下。这项研究做的唯一事情就是确定潜在代码的结构。

我们已经看到,通过简单地添加一个项,最大化部分生成器输入与其输出之间的互信息,学习过程将数据中有意义的属性解开,并将它们分配给这个强加的潜在代码结构。

你做吧

我发现原始回购很难运行,因为它的依赖关系非常陈旧。我已经更新了代码,这样你就可以用现代 Tensorflow APIs(版本 1.3.0)运行了。

继续挖

在这个由 3 部分组成的系列中,我们已经介绍了一些主要的贡献,并看到了 GANs 所做的惊人的事情。尽管如此,这仅仅触及了表面。有多个 github repos,其中包含大量且不断增长的研究论文。这里有一个,这里有另一个。这是一个令人兴奋的研究领域,其成熟度和有效性都在不断提高。如果你在这里发现了你想评论的某篇论文,请在评论中留言。

信息图营销:10 件小事可以带来巨大变化

原文:https://towardsdatascience.com/infographic-marketing-10-small-things-that-can-make-a-big-difference-92f18951f54a?source=collection_archive---------10-----------------------

人类是视觉生物。这或许可以解释为什么猜图法已经成为最近数字营销人员使用的最有效的病毒式营销技术之一。

那么,什么是猜图? Backlinko 的 Brian Dean 将访客画像定义为三种强大的数字营销策略的结合:信息图、访客发帖和链接建设。他甚至称之为他有史以来“最喜欢的”SEO 策略之一。

作为一种搜索引擎优化策略,使用猜测图包括在权威网站上重新利用和重新发布你的信息图作为客座博文——因此有了术语“猜测图”通过简单地编写独特的介绍来配合你的访客照片,你可以毫不费力地将这些图片发布在多个网站上。

需要一些灵感和技巧来开展你自己的猜图活动吗?这里有五个正确使用猜图法的案例研究。

你可以在下面查看这篇文章的视觉摘要或者 点击这里 阅读每一个推广猜谜技巧的详细解释。

在你的网站上嵌入:

<script src="//my.visme.co/visme.js"></script><div class="visme_d" data-url="pv0go3jo-10-small-things-that-can-make-a-big-difference" data-w="800" data-h="4615" data-domain="my"></div><p style="font-family: Arial; font-size: 10px; color: #333333" >Created with <a href="http://www.visme.co/make-infographics" target="_blank" style="color: #30a0ea"><strong>Visme</strong></a></p>

5 家成功推出 Guestographics 的公司

1.如何将“无聊”的小众生活化

你可以想象为像害虫控制这样无聊的话题制造轰动是多么具有挑战性。但是 SEO 战略家 Mike Bonadio 通过巧妙策划的猜测活动做到了这一点,他不太可能的成功是如此有趣,以至于它被发表在 Backlinko 上。

以下是他的竞选结果:

  • 超过 1000 份社交分享
  • 在《班戈每日新闻》和《地球母亲新闻》等高权威出版物上发表
  • 有机交通增长 15.5%

以下是他使用的猜测照片的部分截图:

Image Source

下面是迈克是如何做到的简要概述:

  • 由于“害虫控制”是一个相当无聊的话题,迈克研究了更有趣的“肩膀壁龛”,他可以用它来启动他的活动。这些话题与他的主题密切相关,同时也是他的目标受众感兴趣和关心的事情。
  • 迈克围绕“害虫控制”创建了一张思维导图,其中他确定了理想的“壁龛”,他的主题“害虫控制”可以借用这些壁龛,例如园艺、家庭装修、自己动手等等。
  • 一旦他有了“肩膀龛”的列表,他就运行搜索与这些次要话题相关的热门或趋势帖子。在“园艺”这个案例中,Mike 发现大多数著名的园艺博客都非常关心(并且写了)如何消灭花园害虫。答对了。

  • 在 Mike 发现他的主要主题和肩膀小生之间的完美重叠后,他开始创作关于“园丁的自然害虫控制”的内容,并以此作为他的猜测摄影的基础。然后他创造了另一个思维导图来帮助他的设计师将他的想法充实到一个完成的信息图中。
  • 到了推广他的信息图的时候,迈克用谷歌搜索、内容研究工具 Buzzsumo 和博客目录 Alltop 列出了 40 个顶级园艺博客和博客作者。然后,他确定了这些网站背后的合适人选,并向多达 97 名潜在客户发送了推广信息。

其他提示

提示 1:分为两部分的软销售推广比直接的更有效。

当 Mike 启动他的猜图推广时,他测试了两种类型的推广。一种是软推销的“试探性”接触,在发送信息图之前,他先判断接收者的兴趣。

另一种是更直接的推销,他立即与接收者分享他的信息图。

“试探”邮件的回复率为 40%,而直接推销邮件的回复率仅为 16%,因此了解这一点对未来的营销活动很有帮助。

提示 2:主动为你的信息图写一个定制的介绍。

对于那些反应良好的潜在客户,Mike 发送了一封电子邮件,其中包含了一个嘉宾照片的链接,并提供了一份定制的介绍。

提示 3:确保定制的介绍必须有一个包含品牌或描述性锚文本的单一反向链接。

下面是 Mike 如何在他的 guestographics 简介中使用品牌锚文本:

提示 4:如果你的猜测图出现在显著的网站上,在你的推广邮件中提到这一点,作为你的信息图可信度的社会证明。

从那以后,迈克的信息图像病毒一样传播开来,并在 Flipboard 和 Pinterest 等网站上分享。不用说,他的害虫控制公司客户肯定得到了他们急需的流量提升,而这一切都来自于一个经过深思熟虑的猜图策略!

2.如何使用猜图法与更权威的网站竞争

当 HerePup 的 Perrin Carrell 决定推出一个宠物博客时,他知道自己进入了一个已经被 PetMD.com 等博客主宰的利基市场。尽管如此,他还是坚持了下来。

Perrin 开展了一项猜测活动,取得了显著优势,并取得了以下成果:

  • 仅在 6 周内流量增加了 963%
  • 超过 1k 的推荐访问者
  • 《赫芬顿邮报》的一篇特写

以下是信息图的部分截图:

以下是 Perrin 如何使用猜图法超越竞争对手的:

  • 首先,Perrin 选择了一个高需求的话题,同时也是他的目标读者关心的话题。因此,他在谷歌上搜索“狗和人类健康”,偶然发现了 WebMD 的一篇文章,“宠物如何改善你的健康”,这篇文章获得了 228 个推荐域名。他看到它有相当大的流量,但仍然缺乏,他肯定能写出更好的东西。他找到了他的摩天大楼技术机会。
  • 在此之后,佩兰做了更多关于“宠物如何改善人类健康”这一主题的研究,整理了他能找到的关于这一主题的最佳资料。
  • 最后,他让一名自由设计师捕捉他收集的所有数据,并将其转化为引人注目的信息图。

其他提示

提示 1:改进现有媒体,你可能会超越你的竞争对手。

在 Perrin 的案例中,他发现顶级内容可以通过更多的研究和设计来改善,所以他开始创造比他从更有影响力的来源找到的内容更好的内容。

由于以视觉震撼的信息图形式添加了更多引人入胜的媒体,并将其推广到相关网站,Perrin 得以突破,并从更成熟的竞争对手中脱颖而出。

3.如何用病毒猜测恢复旧内容

争议可能是很好的宣传。以 Ahrefs 博客上的这个猜测性的案例研究为例。

这个名为的信息图“喝完一罐可乐一小时后会发生什么”最初发表在《叛离的药剂师》上。它是基于韦德·梅雷迪思 11 年前的一篇文章,关于可乐如何在饮用后一小时内对你的系统造成严重破坏。

下面是信息图的截图:

以下是这张信息图的表现:

  • 收到差不多 1K 的反向链接。
  • 在赫芬顿邮报、Reddit、雅虎、电讯报、Buzzfeed、Examiner、Indiatimes 等网站上发表。,这带来了更多的反向链接和评论。
  • 增加了数百个关键字的 DA 和排名
  • 仅在脸书就收到了超过 4.4 万股股票

那么,他们是怎么做到的呢?

显然,根据 Ahrefs 的说法,这张信息图完美地结合了以下成分,这导致了它的广泛传播:

  • 伟大的设计
  • 在正确的地方推广
  • 令人激动的话题
  • 一点争议
  • 讨论了一个引起大品牌愤怒的话题

以下是每个属性与其他属性相结合对结果的影响:

  • 这位叛逆的药剂师选择了一个他们擅长的话题,引发了情感上的回应。在他们的案例中,他们的信息图表谈到了可乐对健康的危害,这引发了读者的焦虑。
  • 它打击了世界上最强大的饮料制造商之一可口可乐,这在很大程度上导致了它在网上产生的轰动和争议。
  • 他们的信息图表首先在在线论坛 Reddit 上获得了势头。它的受欢迎程度像滚雪球一样越来越大,最终到达了权威网站,这些网站不失时机地链接回该信息图。即使 Reddit 上的原始帖子最终被删除,该信息图的受欢迎程度也已经飙升,来自权威网站的更新链接仍然存在。

Wordstream 已经成功推出了几个信息图表,如“谷歌最大的失败和失败”,以及他们最近的信息图表,题为“谷歌在哪里赚钱:谷歌 Adwords 广告中最昂贵的 20 个关键词”

Wordstream 写了一个案例研究,概述了他们是如何通过信息图取得成功的。值得注意的是,这是在 2010 年制作的,但你可以从中学到很多东西。以下是他们猜测活动的惊人结果:

  • 美国有线电视新闻网,这无疑是最权威的网站之一,导致了大量的反向链接
  • 转载于《财富》、Techcrunch(美国和日本)、维基百科、赫芬顿邮报、Epic.org 和 Privacy.org
  • 登上 Digg、Reddit 和 StumbleUpon 的首页,获得大量曝光
  • 在脸书产生了 2K 个赞和 1.2K 条推文
  • 赢得了 3500 个链接

尽管 Wordstream 承认信息图没有 2010 年那样的病毒效应,但快速搜索他们最新的博客帖子,包含“谷歌在哪里赚钱”的猜测图,仍然显示出这些令人惊叹的结果:

  • 产生的社交分享:1 204 条推文、187 条脸书分享、13 条 Google+分享和 107 条 Instagram 分享

4.如何复活被低估的信息图

当知名的在线营销人员鼓吹搜索引擎优化策略时,你可以打赌它在大多数时候是有效的。

在一个案例研究中,尼尔在他的博客上发布了一张信息图,起初,几乎没有引起任何关注。

下面是该图的截图:

根据 Neil 的说法,他的信息图表在他的博客上首次发布时并没有获得太多的流量。

但是当他把它投给《企业家》杂志时,奇迹发生了。他的猜测最终产生了超过 12K 股!

尼尔从恢复他被低估的猜测摄影中学到了什么:

  • 如果你创建的信息图没有吸引你的读者和追随者,不要放弃。而是推广到其他网站。
  • 将你的信息图表发布在权威网站上,尤其是你的目标受众经常光顾的网站。因为他已经是《企业家》的定期撰稿人,所以很容易就能在网站上发布他的信息图。
  • 正如尼尔·帕特尔所说,数据驱动的博客帖子非常成功。当你做一个猜测图时,确保添加百分比、统计数据、案例研究和其他相关数据。在你的信息图中利用可信网站发布的数据、研究或调查。

结论

现在你知道了:四个伟大的案例研究证明了猜图学的力量。

正如你所看到的,猜图是给你的网站带来急需的提升的最佳策略之一!

急于赶上潮流,但没有资源?然后,我推荐你试试 Visme ,它能让你在几分钟内制作信息图,而且不需要任何设计技巧。很好,对吧?

缺乏灵感?然后继续检查这个关于 19 个不同主题的 101 个最佳信息图表示例的庞大列表。

那么,猜图学是如何帮助你的博客成长的呢?请在下面的评论中告诉我!

本帖 原版 最早出现在 Visme 的 视觉学习中心

信息图表 2.0:如何在信息图表疲劳的时代脱颖而出

原文:https://towardsdatascience.com/infographics-2-0-how-to-make-yours-stand-out-in-the-age-of-infographic-fatigue-48d7163493dc?source=collection_archive---------12-----------------------

信息图是当今最有效的视觉交流形式之一。教育家们用它们来进行课堂教学和研究项目。项目经理和业务主管使用它们来创建可视化报告。营销人员和记者正利用它们更有效地与受众沟通。

为什么在过去的十年里受欢迎程度激增?因为有文字的图片几乎总是会比只有文字的图片更容易让人记住。事实上,这项研究得出的结论是,那些按照包含插图的说明去做的人比那些按照纯文字说明去做的人要好 323%。

然而,问题是:当互联网上充斥着成百上千的信息图(有些设计得并不那么有效)时,你怎么能让这些信息图为你和你的品牌服务呢?

让我们来看看信息图设计中一些最有创意的趋势,并向您展示如何将它们应用到您自己的视觉营销内容中,使其在视觉噪音的海洋中脱颖而出。我们还将看看信息图的未来,以及如何利用这些信息来改善信息图的内容。

什么是信息图疲劳?

信息图表已经存在了很长时间,远在数字时代之前。但是,一般来说,当我们谈论信息图时,我们指的是那些遍布 Pinterest 并出现在博客帖子中的长垂直图形。自从 Visme 和 Piktochart 等简单的在线图形创建工具问世以来,信息图在网络世界变得非常流行。

几年前,社交媒体专家说,随着在线读者开始厌倦在互联网上看到信息图表,信息图表已经达到了顶峰。事实是,每个人都厌倦了看到糟糕的信息图,而不一定是一般的信息图。普通人只需要 8 秒钟就能对他们不感兴趣的内容失去兴趣。考虑到 93%的 Pinterest 用户利用该平台来研究和计划未来的购买,难以处理的信息图表将永远不会被第二次看到。

当信息图表疲劳开始出现时,品牌必须找到更多创新的方式来创建不会让读者厌烦的内容。信息图表开始包括互动元素,如动画、视频和 gif,以及引人注目的自定义视觉效果,如插图和照片。与此同时,设计师开始脱离通常的模板,创造新的和创新的设计。

信息图表仍然相关吗?

信息图表疲劳仍然存在,尽管我们应该称之为“糟糕的信息图表超载”。糟糕的信息图可以快速滚动,不会给浏览者留下任何印象。做得好、有创意的信息图仍然非常有意义,而且在未来许多年里都会如此。

你应该继续创建信息图表用于你的内容营销吗?

是的,只要你这样做是为了给你的内容增加独特的价值,而不仅仅是为了创建一个好看的信息图。确保信息准确,视觉效果不会令人不快,并且易于理解。你知道吗,在你的博客文章中包含一个精心设计的信息图表会使它的可分享性至少增加 12%?

为了避免“信息图失败”,你的视觉需要有一定的质量。随着在线信息图创作者和 DIY 编辑多年来的发展,可以完成的事情的可能性也在发展。

例如,许多信息图已经偏离了一般的垂直构成,以满足某些社交媒体渠道的大小要求。我们看到越来越多的方形和矩形信息图、微型信息图、动画和互动信息图等等。与此同时,一些信息图被制作得看起来像网站,而一些网站被设计成模仿滚动信息图。

以下是我们在过去一年中观察到的一些最值得注意的很酷的信息图表趋势:

微型信息图表

信息图并不总是充满信息的纵向作品。有时候,一个微型信息图就是你以视觉方式呈现一条信息所需要的全部。此外,方形或矩形的微型信息图更容易在社交媒体上分享。为了获得更惊人的效果,添加动画效果并将信息图保存为视频或 GIF。

信息图表风格的网站/滚动信息图表

Image Source

随着信息图变得越来越具有交互性,它们也逐渐进入了网页设计的领域。因此,我们开始看到网络和应用程序开发工具被用来创建信息图表。(点击阅读更多关于用户界面设计(UID)、用户体验设计(UXD)和信息图表之间的关系。

在下面的例子中,有两种变体:以完整的网站格式呈现的信息图和看起来像信息图的网站。有些情况下,你甚至分不清!

如果您的企业有重要的信息需要可视化地解释,尝试这种格式是一个好主意(并且您也有额外的时间和资源来投资开发类似网站的信息图)。这种类型的可视内容通常具有交互式按钮和指向其他页面或信息图部分的超链接,以创建更好的用户体验。

滚动和交互式信息图

Image Source

这些是可以在滚动网页格式中欣赏的信息图表:

  • 咖啡来自哪里?
  • 天伦之乐
  • 信息图设计流程

受信息图表启发的网站

Image Source

这些网站被设计成类似信息图表:

  • 步入成年的千禧一代
  • 保证书:驾驶执照
  • 棋子种类

方形信息图

分享信息图的首选社交媒体渠道一直是 Pinterest,因为它的垂直特性。然而最近,越来越多的信息图被放到了 Instagram 上,并从那里被放到了脸书和 Twitter 上。这是一个非常新的趋势,我们认为它将在 2018 年起飞。由于这种趋势只涉及信息图的大小,所有其他趋势都可以应用于它。例如,3D 设计和动画可以用来创建非常创新的方形信息图。

方形信息图对于提供快速解释和促进快速社交媒体分享非常有用。公司和创业公司可以真正从这种信息图表趋势中受益,因为它更容易分享!

以上是我们目前在网上最喜欢的一些正方形信息图。如果你关注 Instagram 上的标签#信息图,你会看到一些非常惊人的例子,而且每天都有更多。

动画信息图

现在你在网上找到的一些很酷的信息图可以包含所有类型的动画效果。动画可以是一个焦点,也可以是设计的补充。制作信息图动画的最佳策略是知道何时使用它。

问问你自己:动画会促进信息的传递还是会分散读者的注意力?

我们上面展示的滚动信息图充满了动画和元素的进出效果,它们随着你的滚动而移动。但是这些并不是唯一可以添加到信息图中的动画。您可以制作图表和文本动画。

当信息图包含动画时,需要以向查看者显示动画的格式保存。其中包括可以在任何浏览器上查看的. html5。可以在任何设备上查看的 gif 和视频格式的. mp4。这实际上取决于您应用于信息图的动画类型,从而知道您需要哪种文件格式。

以上是保存在中的动画信息图示例。gif 格式。

互动信息图表

Image Source

交互式信息图是用户可以与之交互的信息图。这可以通过点击、悬停甚至数据输入来实现。主要思想是,根据用户在信息图上的操作,信息会自我修改。

这些信息图可以是任何形状:正方形、长方形或长而垂直。它们的一个共同点是,它们需要是. html5 格式才能工作。这种风格的信息图还不能在社交媒体上分享。它们特殊的可点击特性最好在浏览器中体验。

以下是一些例子:

  • 大脑的基本功能
  • 学会像保卫城堡一样保卫自己的家园
  • 来自外太空的火球

多媒体信息图表

Image Source

当在线信息图制作者们整合了嵌入视频和 gif 的可能性时,他们向前迈出了一大步。只需一个 iframe 代码片段,任何视频或 GIF 都可以包含在信息图中。

这些交互式信息图表需要嵌入到网站或电子邮件中,以. html5 或。gif 文件格式。如果下载为. jpeg 或。png 文件,视频和 gif 显示为静态照片。因此,包含视频或 gif 的信息图不能发布在 Pinterest 上。

这些听起来像是挫折,但它们真的不是。这些很酷的信息图表可能不会在社交媒体上疯传,但它们肯定会让你的内容在竞争中胜出。它们也可以用作会议上的演示文稿或创新的数字简历。

信息图设计的可能性已经发展到如此的高度,信息图甚至可以被认为是多媒体设计的一个例子。例如,您可以使用 Visme 等在线信息图表制作工具将所有类型的互动和动画内容嵌入到您的视觉效果中,包括视频、音频、gif 和实时内容。

例如,有些信息图有不同部分的背景音乐和音频解释。点击可以产生声音效果并激活叙述。动画可以用来显示社交媒体渠道或电子商务网站在线销售柜台上的实时活动。

集成的第三方内容和实时信息

随着信息图变得越来越数字化,第三方内容的整合变得越来越普遍。第三方内容到底是什么?视频和 gif 是第三方内容,但来自 Twitter 和脸书的表格、地图和实时社交媒体反馈也是第三方内容。通过嵌入第三方内容,您的信息图表可以达到一个全新的水平。显示的信息可以有许多不同的表达渠道。

这里有一个例子:

Image Source

插图人物

我们看到的另一个有趣的趋势是使用插图人物。在信息图中,字符被用作解说员或演示者,而不是单独显示数据。使用插图人物的另一种方法是将他们作为视觉形象的一部分。字符可以赋予信息图额外的个性和亲切感,而不是依赖图表、箭头和流程图。

Image Source

3D 插图/等距信息图

Image Source

我们观察到的另一个趋势是 3D 插图的使用。使用 3D 元素的信息图被称为等轴信息图,具有真正不同的感觉。三维插图通常用于在等距信息图中创建一个完整的场景,模糊了我们习惯的经典部分的线条。这种风格的信息图将在 2018 年继续流行,但只有时间才能证明它是否会成为永恒。

手绘风格

Image Source

手绘风格不仅仅是信息图设计中的一种趋势——我们在设计的各个方面都可以看到它。自从手绘刻字和脚本字体热潮以来,我们在内容营销的各个环节看到了越来越多的手绘风格设计。当在信息图表中使用时,这种样式赋予信息一种真正特殊的感觉。如果使用得当,手绘风格可以让你的酷信息图在浩瀚的互联网视觉海洋中更快地被看到和识别。

摄影

Image Source

在信息图中包含摄影一点都不新鲜,但是它的使用方式确实令人印象深刻。许多很酷的信息图混合了手绘风格的设计和摄影,创造出一些非常有创意的视觉效果。

你如何利用这些趋势让你的信息图脱颖而出?

没有必要用你自己的内容去尝试这些趋势中的每一个。挑选一些符合你品牌风格的,看看你是否喜欢它们,它们是否能给你带来效果。在我们提到的趋势中,有些集中在数字风格的信息图表上,比如使用动画和第三方内容。其他人更倾向于艺术方面,比如静态信息图。

你对内容数字化的选择很大程度上取决于你的品牌和产品。如果你的服务是面向连接、网络、响应设计和数字营销,那么数字风格趋势可能是一个更好的选择。如果你是设计烹饪书的艺术家或者打印材料的教育者,更有创造性和艺术性的趋势可能更适合你的视觉内容。

当然,两种不同的趋势可以在同一个信息图中一起使用。一个动画微型信息图在。gif 格式可以在 Twitter 和 Instagram 上产生很大的影响(转换成. mp4 格式时)。就像我们在上面看到的,手绘设计和摄影真的很好地结合在一起,所以想象一个视频嵌入在同一信息图中的电视或手持设备的绘图中。可能性是无限的。

UXD 和 UID 如何帮助你制作更好的信息图?

当我们观察上述趋势时,我们提到了一些信息图是如何被视为网站的,以及一些网站是如何受到信息图的启发的。这种趋势的出现是因为网站和应用开发者使用的工具启发了信息图表的制作方式,反之亦然。

这些工具被称为用户体验设计(UXD)用户界面设计(UID) 。网站和应用程序设计人员和开发人员遵循 UXD 和 UID 规则来构建他们的项目。这两种实践是网站和应用程序运行的基础。

UXD 和 UID 到底是什么?

UXD

来自 Beaker 的 Ben Ralph 说:“用户体验设计是研究用户行为和理解用户动机,目的是设计更好的数字体验。”UXD 适用于网站和应用程序对用户点击和操作做出反应的方方面面。这完全是关于用户对数字平台的体验。

UID

用户界面设计更多的是关于一个网站或应用程序如何符合 UXD。它遵循平台功能的视觉图形方面。

UXD 和 UID 一起工作,确保一个网站或应用程序不仅看起来不错,而且运行良好。随着信息图越来越数字化,了解 UXD 和 UID 的工作方式将有助于您创建更好的信息图,并从您的设计中获得更好的结果。

这里有一些关于如何应用 UXD 和 UID 来创建很酷的信息图的提示

创建信息图时,首先要考虑的是将会看到它并与之交互的人:

  • 他们是谁?
  • 你想用你的信息为他们解决什么问题?
  • 你的信息图的目的是什么?是销售线索磁铁还是视觉支持?

一旦你决定了你是为谁设计,就该计划信息流了。

  • 在文案和视觉效果方面,到底需要包含哪些信息?
  • 你如何在信息呈现的方式上变得有创造性?
  • 评估信息图的导航:什么应该是交互式内容?
  • 使用讲故事的技巧来增强信息图的体验和可用性。

在解决了 UXD 方面的问题之后,是时候构建信息图了。这是用户界面设计。

UID 的首要规则是忠于你的品牌。采取必要的步骤遵循你的 UXD 大纲,同时在颜色、字体、形状和视觉策略方面保持品牌。

  • 使用对齐、间距和大小调整等设计工具构建信息图。
  • 整合支持信息流的动画,而不是分散信息的注意力。
  • 评估您可以包含第三方内容的地方,并确保它在视觉上非常合适。

当您完成信息图的构建后,请考虑在发布或发布前对其进行测试。请你的同事测试信息图,并询问他们对信息图的看法。评估结果并调整你的设计。

为什么你的信息图应该是移动友好的?

信息图表也应该是移动友好的,这并不奇怪,特别是因为人们平均在手机上花费 69%的媒体时间。他们很可能会先在智能手机上看到你的信息图,然后再在笔记本上看到。这就是为什么你的信息图在手机和桌面上都应该表现良好。它应该看起来不错,功能良好,易于滚动,可读,易于在所有设备上使用。UID 和 UXD 在这个意义上也可以帮助你的信息图。

让信息图在桌面和移动设备上都好看的最好方法是不要用过多的形状、颜色和字体。注意它在小屏幕上的大小。如果观众需要放大才能看到一条信息,那么这条信息就太小了。适合手机屏幕的信息图的理想宽度是 630 像素,比普通信息图的 800 像素略小。

结论:信息图表的未来是什么?

正如我们所见,信息图表的未来很大程度上取决于用户和观众。信息图比以往任何时候都更需要功能性和美观性。他们需要走得更远,探索比所呈现的信息更深远的可能性。

信息图表的未来在于数字和互动领域,用户将享受这一旅程,并记住它。

这就是为什么可以有把握地说,在 2018 年及以后,信息图表将更加数字化。随着时间的推移,多媒体信息图将变得越来越普遍。更多信息图表将保存为. html5,.gif 和. mp4 格式来维护动画和嵌入的第三方内容。我们甚至可能会看到虚拟现实中使用的信息图表,在虚拟现实中,用户可以用一种全新的方式与信息互动。

由于“糟糕的信息图表疲劳”的出现,静态信息图表的未来更加不确定我们相信,随着等距设计和品牌插图的使用,这种风格的信息图将会出现创造力和创新的激增。即使没有交互性,信息图也需要流畅并对用户产生影响。

将来你的信息图和其他的相比如何?这完全取决于你想在设计中承担的风险。

本帖 原版 最早出现在 Visme 的 视觉学习中心

信息规划和朴素贝叶斯

原文:https://towardsdatascience.com/information-planning-and-naive-bayes-380ee1feedc7?source=collection_archive---------1-----------------------

用更少的例子学得更好

信息规划包括基于信息度量做出决策。信息规划与主动学习[1]和最优实验设计[2]密切相关,其中标记数据的获得是昂贵的。

主动学习背后的关键思想是,如果仔细选择训练样本以最大化特定任务的信息增益,那么模型可以用更少的标记样本学习得更好。换句话说,给定大量未标记的数据,我们希望根据它们在学习模型参数中的有用性对未标记的例子进行排序。前 K 个信息量最大的训练样本由专家标注器标注,并添加到训练集中。

这里,我们将考虑使用朴素贝叶斯图形模型的文本分类任务。我们将着眼于两种信息度量[3]:熵和互信息,它们将被用于为信息规划对未标记的文档集进行排序。

x_ij 为伯努利随机变量,指示{1,…,D}中的单词 j 对于{1,…,n}中的文档 i 的存在( x_ij = 1 )或不存在( x_ij=0 ),由θ_ JC 参数化(单词 j 出现在类 c 中的概率)

另外,设 pi 是代表类别标签上的先验的狄利克雷分布。因此,可学习参数的总数是|theta| + |pi| = O(DC) + O(C) = O(DC),其中 D 是字典大小, C 是类别数。由于参数数量少,朴素贝叶斯模型不会过度拟合。

伯努利朴素贝叶斯公式的选择很重要,因为它导致了基于单词的信息规划。通过将字典中的每个单词与一个二进制随机变量相关联,我们能够计算单个单词对类别标签分布的影响。

我们可以将类条件密度写为:

我们可以通过最大化对数似然来推导朴素贝叶斯推理算法。考虑单个文档中的单词x _ II:

使用朴素贝叶斯假设,我们可以计算对数似然目标:

通过将 log p(D|theta)相对于模型参数 pi_c 和 theta_jc 的梯度设置为零,我们获得以下 MLE 更新:pi_c = N_c/N 和 theta_jc = N_jc / N_c 其中 N_c = sum(1[y_i = c])。

请注意,为伯努利随机变量添加β先验和为类密度添加 Dirichlet 先验以平滑 MLE 计数是很简单的:

在测试期间,给定训练数据 D 和学习的模型参数,我们想要预测类别标签 y 。应用贝叶斯规则:

将分布代入 p(y=c|D)p(x_ij|y=c,D) 并取对数,我们得到:

伯努利朴素贝叶斯的贝叶斯公式在 scikit-learn [5]中使用上述步骤实现。虽然从零开始(用更快的语言,如 C++)派生和实现 ML 算法是一个很好的实践,但我们将使用 scikit-learn 实现,并专注于信息规划。下面的 ipython 笔记本中有全部代码。

我们将在20 个新闻组数据集的子集上训练我们的模型。特别是,我们将自己限制在 4 类:空间,图形,汽车和曲棍球。我们将使用计数矢量器来生成每个文档的字数矢量,同时过滤停用词和低频词。

熵规划

熵衡量随机变量中的不确定性。在基于熵的规划中,我们希望根据类别标签的熵对测试文档进行排序。这个想法是,通过注释对其类标签具有最高不确定性的文档,将能够用更少的注释示例更好地训练我们的模型。在类分布的情况下,熵可以以封闭形式计算:

*#rank test documents according to entropy of their class label*
top_K = 20
X_test_class_logp = nb_clf.predict_log_proba(X_test_vec)
X_test_class_entropy = -np.sum(np.exp(X_test_class_logp) * X_test_class_logp, axis=1)
planning_entropy_idx = np.argsort(X_test_class_entropy)[-top_K:]

相互信息规划

在交互信息的情况下,我们需要选择我们想要用于规划的随机变量。既然我们对文档分类感兴趣,选择 y_i (文档 i 的类标签)作为变量之一是有意义的。我们对第二个变量的选择取决于感兴趣的数量。我们可以选择一个全局变量 theta_jc(单词 j 出现在类 c 中的概率)或者 pi_c(类 c 的概率)。在这个例子中,我们考虑估计 MI(y _ I;theta),即我们感兴趣的是在给定测试文档的类别标签 y_i 的情况下,测量关于单词分布 theta 的信息增益。因为两个变量都是离散的,所以可以以封闭形式估计互信息:

我们可以使用全概率法则计算p(θ):

此外,我们计算 MI(x _ j;pi)来衡量每个单词 x_j 对全局标签分布 pi 的信息量。

*#rank test documents according to mutual information (MI) between class labels and theta*
log_pi = nb_clf.class_log_prior_              *#log pi(c) global*
log_py = nb_clf.predict_log_proba(X_test_vec) *#log py(c) per doc*
log_pxy = nb_clf.feature_log_prob_            *#log pxy(c,j) = log p(x_ij = 1 | y = c)*

[C,D] = log_pxy.shape
log_pi_tile = np.tile(log_pi.reshape(-1,1), log_pxy.shape[1])
*#log px(j) = log [\sum_c p(x_ij = 1 | y = c) x p(y = c)]*
*#          = log [\sum_c exp{log_pxy(c,j) + log_pi(c)}]*
log_px = logsumexp(log_pxy + log_pi_tile, axis=0)

*#MI between x_j and pi*
X_test_word_MI = np.zeros(D)
**for** class_idx **in** range(C):
    X_test_word_MI = X_test_word_MI + \
    np.exp(log_pi[class_idx]) * np.exp(log_pxy[class_idx,:]) * np.log(np.exp(log_pxy[class_idx,:])/np.exp(log_px)) + \
    np.exp(log_pi[class_idx]) * (1-np.exp(log_pxy[class_idx,:])) * np.log((1-np.exp(log_pxy[class_idx,:]))/(1-np.exp(log_px)))    
*#end for*

*#MI between y_j and theta*
logp_theta = logsumexp(log_pxy + log_pi_tile, axis=0)
X_test_docs_MI = np.zeros(X_test_vec.shape[0])
**for** doc_idx **in** range(X_test_vec.shape[0]):
    doc_MI = 0
    **for** class_idx **in** range(C):
        doc_MI += np.sum(np.exp(log_pxy[class_idx,:] +    
                  log_py[doc_idx, class_idx]) * \
                  (log_pxy[class_idx,:] - logp_theta), axis=-1)
    *#end for*
    X_test_docs_MI[doc_idx] = doc_MI
*#end for*

planning_MI_idx = np.argsort(X_test_docs_MI)[-top_K:]

让我们来看看每门课学习的单词概率:

我们可以显示上面与每个类别相关的前 10 个(最高概率)单词:

课堂十大单词:0
get 请像任何人一样使用感谢图形会知道

课堂十大词汇:1
想想也知道汽车变得像一辆汽车

班级十大单词:2
赛季年第一次打曲棍球

课堂十大单词:3
美国国家航空和宇宙航行局可能知道得更多,就像太空一样

让我们来看看前 20 个(MI 最高的)信息词汇:

前 20 名 MI 单词:
球队计划联赛月球季后赛轨道球员地球游戏 nasa nhl 玩汽车赛季图形曲棍球队游戏汽车空间

还不错!考虑到地面真相标签是:

地面实况标签:
科学.空间.计算机.图形.记录.汽车.记录.运动.曲棍球

我们可以看到,最高 MI 的单词很好地反映了地面真相标签。

最后,让我们可视化基于熵和互信息的测试文档排序:

特别地,我们对离群值感兴趣,即具有最高熵和互信息的文档。从上面的 violin 图中,我们可以看到与高熵文档相比,高 MI 测试文档的密度更大,这表明 MI 可以更好地区分哪些文档最适合信息规划。

在离散 X 和 Y 的情况下,为了最大化信息增益 I(X;Y),我们想要最大化 H(X)(关于 X 的不确定性)和最小化 H(X|Y)(即我们想要 Y 关于 X 的信息性)。

为了可视化熵和基于 MI 的计划之间的差异,我们可以根据熵对文档进行排序,并使用相同的索引对 MI 进行排序。

在上图中,具有高熵但低 MI 的文档是不确定的,但不是信息丰富的。因此,管理信息为信息规划提供了更好的手段。

密码

下面的 ipython 笔记本中有全部代码。

结论

我们研究了两种用于选择训练样本的信息度量:简单朴素贝叶斯设置中的熵和互信息。虽然熵根据文档的不确定性对文档进行排序,但是 MI 也考虑了计划变量的信息量。通过主动选择训练样本,我们可以用更少的标记样本获得更高的准确率。信息规划可以在减少我们对大量训练数据的依赖方面发挥作用,尤其是在标签获取成本高昂的情况下。

参考

[1] B. Settles,“主动学习文献调查”,技术报告,2010 年
[2] K. Chaloner 和 I. Verdinelli,“贝叶斯实验设计:综述”,统计科学,1995 年
[3] T. Cover 和 J. Thomas,“信息理论的要素”,Wiley,2006 年
[4] K. Murphy,“机器学习:一种概率观点”,麻省理工学院出版社,2012 年
[5] F. Pedregosa 等人,“Scikit-learn:Python 中的机器学习:【T4

神经网络信息论

原文:https://towardsdatascience.com/information-theory-of-neural-networks-ad4053f8e177?source=collection_archive---------3-----------------------

打开黑盒…稍微

"信息:概率的负倒数值."—克劳德·香农

这个博客的目的不是理解神经网络背后的数学概念,而是从信息处理的角度来看神经网络。

编码器-解码器

在我们开始之前:

编码器-解码器不是两个 CNN/rnn 组合在一起!事实上也不一定是神经网络!

本来,信息论的一个概念。编码器只是简单地压缩信息,而解码器扩展编码后的信息。

在机器学习的情况下,编码和解码都是完全丢失的过程,即一些信息总是丢失。

编码器的编码输出被称为上下文向量,这是解码器的输入。

有两种方法可以设置编码器-解码器设置:

  1. 编码器反函数中的解码器。这样,解码器试图再现原始信息。这是用来消除数据噪声的。这个设置有一个特殊的名字,叫做自动编码器。
  2. 编码器是压缩算法,解码器是生成算法。这有助于将上下文从一种格式转换为另一种格式。

示例应用:

自动编码器:把英文文本压缩成矢量的编码器。解码器从向量生成原始英文文本。

编码器-解码器:将英文文本压缩成向量的编码器。解码器从向量生成原文的法语翻译。

编码器-解码器:将英文文本压缩成向量的编码器。从文本内容生成图像的解码器。

信息论

现在,如果我说每个神经网络,本身,是一个编码器-解码器设置;对大多数人来说,这听起来很荒谬。

让我们重新想象一下神经网络。

假设输入层是 X,它们的真实标签/类(存在于训练集中)是 y。现在我们已经知道神经网络找到了 X 和 y 之间的潜在函数。

所以 X 可以看成是 Y 的高熵分布,高熵是因为 X 包含了 Y 的信息,但它也包含了很多其他信息。

示例:

“这小子不错。”包含足够的信息来告诉我们它的“积极”情绪。

它还包含以下内容:

1.是一个特定的男孩

2.只是一个男孩

3.句子的时态是现在时

这句话的非熵版本应该是“正的”。是的,这也是输出。我们过一会儿再回到这个话题。

现在想象每一个隐藏的层作为一个单一的变量 H(因此层将被命名为 H0,H1 …..H(n-1))

现在每一层都变成了变量,神经网络变成了马尔可夫链。因为每个变量只依赖于前一层。

所以本质上每一层都形成了一个信息的党派。

下面是一个神经网络的可视化马尔可夫链。

最后一层 Y_ 应该产生最小熵输出(相对于原始标签/类“Y”)。

这个获取 Y_ 的过程就是在 X 层的信息流经 H 层的时候对其进行挤压,只保留与 Y 最相关的信息,这就是信息瓶颈。

交互信息

I(X,Y) = H(X) — H(X|Y)

H ->熵

h(X)-> X 的熵

H(X|Y) ->给定 Y 的 X 的条件熵

换句话说,H(X|Y)表示如果 Y 已知,从 X 中去除了多少不确定性。

互信息的性质

  1. 当你沿着马尔可夫链移动时,互信息只会减少
  2. 互信息对于重新参数化是不变的,即在图层中混排值不会改变输出

重温瓶颈

在神经网络的马尔可夫表示中,每一层都成为信息的一个分区。

在信息论中,这些划分被称为相关信息的连续细化。你不必担心细节。

另一种方式是将输入编码和解码成输出。

因此,对于足够的隐藏层:

  1. 深度神经网络的样本复杂度由最后一个隐层的编码互信息决定
  2. 精度由解码的最后一个隐藏层的互信息决定

样本复杂度是一个人需要获得一定准确度的样本的数量和种类。

培训阶段的相互信息

我们计算相互之间的信息

  1. 层和输入
  2. 层和输出

Initial Conditions

最初,权重是随机初始化的。因此,关于正确的输出几乎一无所知。对于连续层,关于输入的互信息减少,并且隐藏层中关于输出的信息也很少。

Compression Phase

当我们训练神经网络时,图开始向上移动,表示关于输出的信息的获得。

图也开始向右侧移动,表示后面层中关于输入的信息增加。

这是他最长的阶段。这里,图的密度最大,图集中在右上方。这意味着与输出相关的输入信息的压缩。

这被称为压缩阶段。

Expansion Phase

在压缩阶段之后,曲线开始向顶部移动,但也向左侧移动。

这意味着,在连续的层中,关于输入的信息会丢失,而在最后一层中保留的是关于输出的最低熵信息

虚拟化

神经网络的马尔可夫链版本突出了一点,学习是从一层到另一层发生的。图层拥有预测输出所需的所有信息(外加一些噪声)。

所以我们用每一层来预测输出。这有助于我们窥视所谓黑盒的分层知识。

这给了我们一个视角,需要多少层才能对输出做出足够准确的预测。如果在较早的层达到饱和,则该层之后的层可以被修剪/丢弃。

这些层通常有数百或数千维。我们的进化不允许我们想象任何超越三维的事物。所以我们使用降维技术。

有各种方法来执行降维。克里斯托夫·奥拉有一个精彩的博客解释这些方法。我不会深入 t-SNE 的细节,你可以查看这个博客了解详情。

为了保持简洁,SNE 霸王龙试图降低维数,将高维空间的邻居保留在低维空间。因此,这导致了相当准确的 2D 和三维绘图。

以下是具有两层的语言模型的层图。

关于情节:

  1. 精选 16 个单词
  2. 使用最终的语言模型找到上述 16 个单词的 N 个同义词(2D 的 N=200,3D 的 N=50)
  3. 在每一层找到每个单词的表示向量
  4. 使用 t-SNE 找出以上所选单词及其同义词的 2D 和三维简化表示
  5. 绘制简化的表示

2D plots of Layer 1 and Layer 2

3D plots of Layer 1 and Layer 2

摘要

  1. 几乎每个深度神经网络都像一个编码器-解码器
  2. 大部分训练时间花在压缩阶段
  3. 层是自下而上学习的
  4. 在压缩阶段之后,神经网络对输入的遗忘越多,它就越准确(消除输入中不相关的部分)。

我已经把数学排除在这个博客之外了。如果你对信息论、博弈论、学习理论等数学足够熟悉,那么请观看 Mastero Naftali Tishby视频

谢谢(-_- )/

InOut——从为期两天的黑客马拉松中学到的东西

原文:https://towardsdatascience.com/inout-learnings-from-2-day-hackathon-6d1196410298?source=collection_archive---------12-----------------------

Pic Credit

班加罗尔频繁举办科技活动,有时同一天还会有不止一个好活动。谷歌的班加罗尔开发者大会原定于 10 月 13 日举行,而同一天也没有发布。我必须选择参加哪一个,因为我有参加两个的确认。由于我的朋友说,“你应该参加 InOut,这真的很好”,我花了 2 天的周末,与其他许多热情的开发者和创造者一起,与一个我以前不认识的人合作,建立了一个人脸识别的 web 应用程序,日夜进行对话和讨论。InOut 是一个社区黑客马拉松,已经举办了几年。今年,它收到了来自世界各地不同国家的 4000 多份申请,我很高兴我参加了这次黑客马拉松,因为我有一些很棒的收获。

黑客马拉松于周六早上开始(前一天晚上有一些技术讲座),我可以看到到处都是兴奋的面孔——这要感谢 InOut 的欢迎包。虽然它对每个人都开放,但大多数参与者都是大学生,很高兴看到他们提出一些非常好和有趣的想法。虽然黑客马拉松有一些感兴趣的话题,如区块链、人工智能、物联网、健康等,但参与者可以自由地构建和处理他们的任何想法。周六早上开始的几个小时有着复杂的场景。当一些参与者分组讨论他们的想法和构建方法时,一些人已经开始工作(或者编码!).

Pic Credit

我和我的队友 Utkarsh(我在参加黑客马拉松之前并不认识他)讨论了一些我们想要尝试和构建的东西。大约一个小时后,我们最终决定建立一个自动化商店的工作模型,该模型使用人脸识别、物体检测和使用深度学习的支付自动化。他负责 UI 部分,而我负责使用 TensorFlow 进行人脸检测和识别的模型构建。从想法讨论开始,在接下来的 30 个小时的许多其他对话中,我们在一些事情上相互同意和不同意,所有这些都导致了更好的决策和改进的代码。这就是黑客马拉松所做的,他们提供平台和环境来提出想法,并在建立想法的过程中通过讨论和协议与团队相处。

由于我们每个人都在应用程序的两个不同部分工作,我们必须不时地整合这些变化。在协作时,版本控制是必须的。我把初始化我作为 Git 存储库工作的任何文件夹/工作区作为个人习惯,这样即使我不想把代码推到任何代码存储库中,我也可以用它来跟踪变化。使用代码时,许多事情都可能出错。运行良好的代码可能会突然崩溃。你可能会花时间试图解决一些不是实际问题的东西。出于所有这些原因,每当一个特性/功能工作时,进行一次提交,以便有一个工作状态作为备份!如果你正在开发的应用程序在你需要演示之前一个小时就中断了(这种情况就发生在我们身上),这就有很大的不同了!

Swags & Stickers — Pic Credit

周六午夜左右,我们和黑客马拉松组织者开了一个社区会议。我是为数不多的出席者之一。虽然我认为这只是一个讨论会议,但几分钟后我意识到这不是。InOut 现已成为印度最大的社区黑客马拉松之一,它是几年前从一个大学活动开始的。组织者,也是 InOut 的创始人,分享了他们开始一个大学水平的活动,然后发展成为像这样大的黑客马拉松的经历。大多数参与讨论的人都是大学生,他们也在组织大学级别的技术活动。他们分享了考虑到所涉及的成本以及缺乏大学的适当支持,他们组织一次社区活动有多困难。的确,组织一次社区活动需要付出很多努力!

由于我们在午夜后试图修复一个代码问题,我们认为最好睡一会儿。在我睡觉之前,我想再试一次来解决这个问题。代码错误很棘手。他们不断告诉你,他们可以在不超过 5-10 分钟内修复,然后你花了几个小时,修复错误,然后感觉鼓励你继续工作。差不多同样的事情也发生在我身上。当我彻夜未眠,让应用程序变得更好更实用时,第二天早上,黑夜进行了报复,它让我像僵尸一样走来走去!在这整个过程中,时间过得飞快..

Pic Credit

组织者确保我们在会场度过的两天不仅仅是编码。不时会有食物、能量饮料、竞赛、赠品,还有纳什·维尔,他在整个黑客马拉松中登台表演,让环境充满活力。在黑客马拉松快结束的时候,我们在其他参与者的帮助下验证了我们构建的自动签入和签出应用程序是如何工作的。而且效果相当不错!!获奖者呢?有一些非常有趣的提交,但得到大多数评委投票和参与者最大掌声的是 SAD,它代表悲伤的分布。随着计算设备在我们周围的出现,设备的空闲时间可以用于分布式计算。SAD 就是建立在这个理念上的。恭喜👏 👏

Pic Credit

黑客马拉松让我们能够提出想法,并提供一个强化和推动我们实现目标的环境。非常感谢 InOut 组织了如此精彩的活动!!

TL;博士:

黑客马拉松是将你的想法转化为解决方案的绝佳机会

注册,组建团队,集思广益,开始编码(看这很简单)

仅仅保存代码是不够的。提交代码,提交,提交!!!

你不一定要成为极客/忍者/黑客才能参加黑客马拉松👍

走进这样一个黑客马拉松,你会得到代码(不管它是否有效😉),新朋友和美好的经历👏 👏

还有赃物👌

下面是我们在黑客马拉松期间构建的 web 应用程序的演示。我继续对它进行研究,并将其转化为一个身份管理系统,该系统通过将人口统计信息与人脸结合起来注册身份,并使用深度学习模型进行人脸检测和验证。这项工作仍在进行中,还有更多的功能需要添加:

你觉得这篇文章有用吗?欢迎留下任何反馈/意见。感谢阅读!!😃

连接:LinkedInTwitter和我的* 博客 *

在伯顿,在你的衣服上喷洒隐形数据

原文:https://towardsdatascience.com/inperton-spraying-invisible-data-on-your-clothes-28ec76e64f35?source=collection_archive---------8-----------------------

在读完阿尔多斯·赫胥黎的《勇敢新世界》后,我醒来时对世界有了这种反乌托邦的看法,在那里,的数据将以人眼看不见的方式写在物体上。例如,在你的 t 恤上。想象一下,你的衣服被一波看不见的二进制数据写入,在这些数据中,没有人能看到、感觉到、闻到和破译。像喷雾一样,这种技术可以用于,例如,如果你进入一家商店,机构想在你的衣服上写一个“cookie”来跟踪你的访问。使用传感器,他们可以跟踪,例如,你什么时候进入商店,你在哪里,你在一个特定的产品前花了多少时间。我给它起了个名字:‘in perton’——不可见的持久原子数据。

我们消费的数据很大一部分是我们能看到的数据。自从有了印刷机,书面语言现在无处不在:在这篇文章中,街道上的标志,衣服标签,杂志,瓶子标签,说明书。也就是说,我们不使用任何解码设备就可以看到和理解的数据。另一方面,大量的数据以二进制格式存储在我们电脑的硬盘中。虽然我们无法读取这些数据,但我们知道设备一个数据容器。我们知道数据就在那里。硬件的唯一目的是存储数据,因此,如果我们破坏存储卡或 DVD,数据就消失了。

在 19 世纪早期,一种新的数据格式被引入。电磁波的发现为“看不见的数据”创造了机会。模拟和数字数据就像空气中弥漫的烟雾一样在我们周围流动。电台、Wi-Fi 网络、电视信号就在我们面前,只是我们看不见而已。这个故事的好处在于这些看不见的数据是不稳定的。使用它或者失去它。我们只能使用现在正在产生的电波,但我们无法恢复昨天由我们的电台产生的电波。基本上,它不会“粘”在任何地方。然而,不可见的数据已经可以通过其他方式存储和检索。

IBM 的研究人员去年成功地在单个原子上存储了数据。这对于减小硬盘的物理尺寸是一个巨大的成就,但这并不意味着这些原子可以被“喷射”到物体中,并以有序的方式被取回。DNA 储存也已经成为可能。研究人员能够存储数百万数据,包括从莎士比亚的十四行诗到马丁·路德·金的演讲。这种 DNA 储存可以持续数千年。分子可以被插入物体中以获得永久数据。然而,DNA 数据存储的排序和检索是复杂的。

在一个不太危险的用途上,该技术与区块链结合,可用于强制私有财产。就像序列号一样,每个产品都可以在它的分子上包含唯一的 id。举例来说,如果你买了一辆车,它的底盘上不会有 VIN 号码,它会出现在车的每个部分。所有的部件、轮胎、车轮和保险杠都会包含这个数字,不销毁它就无法删除。

如果研究人员能够找到一种更简单的方法来重新排列衣服的纤维、物质的原子或植入易于写入或检索的 DNA,这将是下一个技术突破。类似于核能的发现,会带来很多伦理上的担忧。数据变得越来越有价值,许多机构正在研究存储、检索和分析数据的替代方法。

看不见的数据很难被发现,先进的加密算法几乎无法破解。和其他任何技术一样,储存在粒子上的隐形持久数据可以用于好的方面或坏的方面。看看你现在的衬衫,问问自己:上面有看不见的数据吗?吓人?是的…但也许这就是我们勇敢的新世界。

磷的内幕:见见 Roman Shraga,数据科学家!

原文:https://towardsdatascience.com/inside-phosphorus-meet-roman-shraga-data-scientist-73b594de295d?source=collection_archive---------9-----------------------

嘿,罗曼,给我们介绍一下你自己吧!

我两岁的时候,我们全家从乌兹别克斯坦移民到布鲁克林,我在纽约这里长大。我在布朗大学主修计算机科学,我大学毕业后的第一份工作是在微软,在那里我所在的团队专注于构建机器学习模型,以增强在微软搜索引擎 Bing 上的体验。之后,我在一家名为 PlaceIQ 的公司工作了两年,在那里我建立了分析管道来处理和分析万亿字节的数据。现在,我正与遗传学家、分子生物学家和工程师合作,利用我的数据科学技能释放基因组学的全部力量。

你在磷公司的头衔是什么?你为公司做什么?

我的头衔是数据科学家,我的职责包括使用机器学习和统计学从数据中获取价值。作为一家基因组公司,我们有许多数据来源:来自我们实验室的原始基因信息、我们的研究合作伙伴与我们共享的临床数据,以及来自我们应用程序的各种使用和物流数据。我的工作就是利用这些数据回答问题,改进我们的产品。

你最喜欢你工作的什么?

我喜欢我们所做的工作对人们的生活产生切实的影响。无论我们开发一种新的分析方法,改进我们的流程,还是拓展研究的范围,我们的工作都会有所作为。这种环境促进学习,鼓励协作,让每个人都想超额完成任务。每天和一群分享这些价值观的人一起工作真的是一种特权。

在磷公司工作,你学到了什么?

我学到了这么多,很难保持这个答案简短!我已经了解了人类生物学的复杂性和美丽,了解了医疗保健生态系统,了解了运行临床实验室需要什么,了解了生物信息学和基因组学数据,了解了现代软件改善复杂过程功能的能力。

到目前为止,你最喜欢的项目是什么?

我最喜欢的项目是使用下一代测序数据构建检测拷贝数变异的工具。拷贝数变异是基因结构变异的一种重要类型,已知在某些情况下会导致疾病。准确检测这些是临床遗传学的一项重要能力,但由于各种原因,这样做具有挑战性。我一直致力于开发标准化技术和算法来揭示这些变体。

你有个人的口头禅吗?

就数据建模而言,我认为复杂性是必须赢得的。也就是说,我认为您应该选择尽可能简单的模型,并证明您引入的任何额外的复杂性在性能方面都有可衡量的好处。在我的领域中,人们经常会对使用一个闪亮的新工具感到兴奋,即使它对一个更简单、更容易理解、更容易维护的解决方案没有任何好处。

告诉我们一些大多数人不知道的你的事。

我是烹饪和家居装修节目的狂热观众。顶级厨师和房屋猎人是我的最爱。

明年空闲时间你最期待的一件事是什么?

十二月初,我要养一只小狗了!

你有什么爱好吗?

我喜欢发现新的有趣的地方。我喜欢住在纽约的一个原因是,总有一家新餐馆可以尝试,一个有趣的活动可以参加,或者一个未被发现的街区可以逛逛。我尽可能经常尝试新事物。

哪种口味的冰淇淋最适合你?

薄荷巧克力片。

在 Tensorflow(直方图、激活、内部/整体梯度)中具有交互式代码的神经网络的思维内部[带 TF 的手动背部道具]

原文:https://towardsdatascience.com/inside-the-mind-of-a-neural-network-with-interactive-code-in-tensorflow-histogram-activation-a4dff0963103?source=collection_archive---------6-----------------------

GIF from this website

很长时间以来,我一直想了解我的模型的内部运作。从今天开始,我希望了解与这个主题相关的话题。在这篇文章中,我想涵盖三个主题,权重直方图,可视化神经元的激活,内部/积分梯度。

请注意,这篇文章是为了我未来的自己来回顾这些材料。

上阅读之前

Original Video from TechTalksTV (https://vimeo.com/user72337760) If any problem arises I will delete the video asap. Original video Link here: https://vimeo.com/238242575

这个视频超出了本文的范围,但它确实帮助我理解了内部和积分梯度,以及如何理解神经网络内部工作的概述。

数据集/网络架构/精确度/类别号

Image from this website

红色矩形 →输入图像(32323)
黑色矩形 →与 ELU 卷积()有/无平均池
橙色矩形 → Softmax 进行分类

像往常一样,我们将使用 CIFAR 10 数据集来训练我们的全卷积网络,并尝试了解为什么网络会将某些图像预测到它的类别中。

有一点需要注意,因为这篇文章更多的是关于了解网络的内部运作。我将只使用测试集中的 50 张图片来衡量准确性。

左图像 →测试图像(50 张图像)的精度/时间成本
右图像 →训练图像(50000 张图像)的精度/时间成本

如上所述,该模型在第 7 个时期的最终精度为 81%。(如果您希望访问完整的培训日志,请点击此处。)最后,让我们看看每个类的每个数字代表什么。

Image from this website

权重直方图(训练前/后)

Histogram of weighs before training

上图是每一层的权重直方图,为了便于可视化,我将每一层直方图分为三层。在最左侧,我们可以观察到权重的平均值通常为 0,标准偏差(stddev)值在 0.04 到 0.06 之间。这是意料之中的,因为我们用不同的 stddev 值声明了每个层。此外,一些曲线比其他曲线小的原因是由于每层的权重数不同。(例如,层 0 仅具有 3 * 3 * 128 的权重,而层 2 具有 3 * 128 * 128 的权重。)

Different stddev values

Histogram of weighs after training

马上,我们可以观察到一个明显的差异。尤其是前三层。分布的范围从-5 增加到 5。然而,看起来大部分权重存在于-1 和 1 之间(或者接近于零。)对于第 4 层到第 6 层,看起来平均值和最后三层一样发生了偏移。

可视化某些层的激活值

Test Input for the network

使用由约辛斯基和他的同事完成的技术,让我们想象上面的图像是如何在第 3、6 和 9 层之后被修改的。(请注意,我最初在这篇博文中发现了亚瑟·朱利安尼使用的方法。)

Activation after layer 3

绿框 →捕捉绿色值的通道
蓝框 →捕捉蓝色值的通道

现在有 128 个频道,所以我就不一一列举了。相反,我会想象前 27 个通道,如上所示。我们可以看到,在第 3 层之后,某些颜色值在网络中被捕获。

Activation for layer 6

红色框 →捕捉红色的通道

然而,在第六层之后,似乎某些过滤器能够比绿色或蓝色更好地捕捉红色。

Activation after layer 9

最后,在第九层之后(就在全局平均汇集之前),我们可以可视化深度为 1 的每个通道(因此它看起来像灰度图像)。然而(至少对我来说),它似乎不是人类可以理解的。所有的图片都可以在这里找到并且我创建了一个 GIF 来累积所有的变化。

GIF 的顺序 →输入图像,第 3 层后激活,第 6 层后激活,第 9 层后激活

内部渐变/正负属性

alpha value of 1.0

现在让我们使用内部渐变,阿尔法值为…
0.01,0.01,0.03,0.04,0.1,0.5,0.6,0.7,0.8,1.0(与原始输入相同),来形象化的表现网络的内部运作。

上面的所有图像都代表了相对于具有不同 alpha 值的输入的梯度。我们可以观察到,随着 alpha 值的增加,由于网络中的饱和度,梯度变得更接近 0(黑色)。当我们以 gif 格式查看所有图像时,我们可以清楚地看到渐变是如何变化的。

然而,我能够做出一个有趣的观察,随着 alpha 值变小,我的网络无法做出正确的预测。如下所示,当 alpha 值很小(0.01)时,网络通常预测 3 或 4。(猫/鹿)

红框 →车型预测

但是随着 alpha 值的增加,最终达到 1.0,我们可以观察到模型的准确性增加了。最后,让我们看看每个 alpha 值的渐变的正负属性。

蓝色像素→ 正属性覆盖原始图像
红色像素→ 负属性覆盖原始图像

同样,如果我们用这些图像创建一个 gif,会更容易看到变化。

积分梯度/正负属性

左图 →步长为 3000 的积分梯度黎曼近似
右图 →蓝色表示正属性,红色表示负属性

最后,当我们使用积分梯度来可视化梯度时,我们可以观察到类似上面的东西。我发现的一个非常有趣的事实是,网络是如何预测马(7)、狗(5)和鹿(4)的。

让我们先看看原始图像,如左上图所示,中间的图像是马,右边的图像是羊。

当我们可视化积分梯度时,我们可以看到一些有趣的东西。如中间的图片所示,网络认为马的头部是最重要的。但是,只拍头部的时候,网络以为是狗的形象。(它看起来有点像一只狗)。类似的故事对于右图,当网络只考虑到只有一只羊的头时,它预测为看到一只狗。

然而,如最左边的图像所示,当网络获得一匹马的整体形状(包括人类的某个部分)时,它会正确地将图像识别为一匹马。太神奇了!

互动码

对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上复制一份。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!同样为了透明,我在 github 上上传了所有的训练日志。

要访问这篇文章的代码,请点击这里,培训日志点击这里。

最后的话

由于这个领域仍在成长和发展,将会有新的方法和发现。(我希望我也能为这些发现做出贡献。).最后,如果你想访问来自论文原作者的代码"请点击这里。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请在这里查看我的网站。

同时,在我的推特这里关注我,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 pos t。

参考

  1. http://公理/定义/定理/证明。(2018).YouTube。检索于 2018 年 6 月 14 日,来自https://www.youtube.com/watch?v=OeC5WuZbNMI
  2. 公理—字典定义。(2018).Vocabulary.com。检索于 2018 年 6 月 14 日,来自https://www.vocabulary.com/dictionary/axiom
  3. 深度网络的公理化属性--穆昆德.孙达拉扬,安库尔.塔利,严琦琦。(2017).Vimeo。检索于 2018 年 6 月 14 日,来自https://vimeo.com/238242575
  4. STL-10 数据集。(2018).Cs.stanford.edu。检索于 2018 年 6 月 15 日,来自 https://cs.stanford.edu/~acoates/stl10/
  5. 贝嫩森河(2018)。分类数据集结果。rodrigob . github . io . 2018 年 6 月 15 日检索,来自http://rodrigob . github . io/are _ we _ there _ yet/build/classification _ datasets _ results . html # 53544 C2 d 3130
  6. [复本],H. (2018)。如何在 Matplotlib (python)中隐藏轴和网格线?堆栈溢出。检索于 2018 年 6 月 16 日,来自https://stack overflow . com/questions/45148704/how-to-hide-axes-and-gridlines-in-matplotlib-python
  7. VanderPlas,J. (2018)。多重支线剧情| Python 数据科学手册。jakevdp . github . io . 2018 年 6 月 16 日检索,来自https://jakevdp . github . io/python datascience handbook/04.08-multiple-subplots . html
  8. Matplotlib . py plot . subplot-Matplotlib 2 . 2 . 2 文档。(2018).Matplotlib.org。检索于 2018 年 6 月 16 日,来自https://matplotlib . org/API/_ as _ gen/matplotlib . py plot . subplot . html
  9. matplotlib,m. (2018)。matplotlib 中超过 9 个支线剧情。堆栈溢出。检索于 2018 年 6 月 16 日,来自https://stack overflow . com/questions/4158367/more-than-9-subplots-in-matplotlib
  10. pylab_examples 示例代码:subplots _ demo . py—Matplotlib 2 . 0 . 0 文档。(2018).Matplotlib.org。检索于 2018 年 6 月 16 日,来自https://matplotlib . org/2 . 0 . 0/examples/pylab _ examples/subplots _ demo . html
  11. Matplotlib . py plot . hist-Matplotlib 2 . 2 . 2 文档。(2018).Matplotlib.org。检索于 2018 年 6 月 16 日,来自https://matplotlib . org/API/_ as _ gen/matplotlib . py plot . hist . html
  12. Python?,I. (2018)。在 Python 中有没有一个干净的生成折线图的方法?。堆栈溢出。检索于 2018 年 6 月 16 日,来自https://stack overflow . com/questions/27872723/is-there-a-clean-way-to-generate-a-line-histogram-chart-in-python
  13. Pyplot 文本— Matplotlib 2.2.2 文档。(2018).Matplotlib.org。检索于 2018 年 6 月 16 日,来自https://matplotlib . org/gallery/py plots/py plot _ text . html # sphx-glr-gallery-py plots-py plot-text-py
  14. 【谷歌/ ICLR 2017 /论文摘要】反事实的梯度。(2018).走向数据科学。检索于 2018 年 6 月 16 日,来自https://towards data science . com/Google-iclr-2017-paper-summary-gradients-of-counter factuals-6306510935 F2
  15. NumPy . transpose—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 6 月 16 日,来自https://docs . scipy . org/doc/numpy-1 . 14 . 0/reference/generated/numpy . transpose . html
  16. 命令,G. (2018)。Git 在一个命令中添加和提交。堆栈溢出。检索于 2018 年 6 月 16 日,来自https://stack overflow . com/questions/4298960/git-add-and-commit-in-one-command
  17. 如何将图像切片为红色,g. (2018)。如何使用 misc.imread. Stack 溢出将图像分割为红色、绿色和蓝色通道。检索于 2018 年 6 月 16 日,来自https://stack overflow . com/questions/37431599/how-to-slice-a image-into-red-green-and-blue-channels-with-misc-imread
  18. 如何在 Windows 10 上安装 Bash shell 命令行工具?(2016).Windows 中央。检索于 2018 年 6 月 16 日,来自https://www . windows central . com/how-install-bash-shell-command-line-windows-10
  19. Google Colab 免费 GPU 教程—深度学习火鸡—中等。(2018).中等。检索于 2018 年 6 月 16 日,来自https://medium . com/deep-learning-turkey/Google-colab-free-GPU-tutorial-e 113627 b9f5d
  20. 安装— imgaug 0.2.5 文档。(2018).img aug . readthe docs . io . 2018 年 6 月 16 日检索,来自http://img aug . readthe docs . io/en/latest/source/installation . html
  21. NumPy . absolute—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 6 月 16 日,来自https://docs . scipy . org/doc/numpy-1 . 14 . 0/reference/generated/numpy . absolute . html
  22. NumPy . clip—NumPy 1.10 版手册。(2018).Docs.scipy.org。检索于 2018 年 6 月 16 日,来自https://docs . scipy . org/doc/numpy-1 . 10 . 0/reference/generated/numpy . clip . html
  23. NumPy . percentile—NumPy 1.14 版手册。(2018).Docs.scipy.org。检索于 2018 年 6 月 16 日,来自https://docs . scipy . org/doc/numpy/reference/generated/numpy . percentile . html
  24. CIFAR-10 和 CIFAR-100 数据集。(2018).Cs.toronto.edu。检索于 2018 年 6 月 16 日,来自https://www.cs.toronto.edu/~kriz/cifar.html
  25. [ ICLR 2015 ]追求简单:具有交互码的全卷积网。(2018).走向数据科学。检索于 2018 年 6 月 16 日,来自https://towards data science . com/iclr-2015-forwards-for-simplicity-the-all-convolutional-net-with-interactive-code-manual-b 4976 e 206760
  26. EN10/CIFAR。(2018).GitHub。检索于 2018 年 6 月 16 日,来自https://github.com/EN10/CIFAR
  27. 深度网络的公理化属性--穆昆德.孙达拉扬,安库尔.塔利,严琦琦。(2017).Vimeo。检索于 2018 年 6 月 16 日,来自https://vimeo.com/238242575
  28. (2018).Arxiv.org。检索于 2018 年 6 月 16 日,来自https://arxiv.org/pdf/1506.06579.pdf
  29. 黎曼和。(2018).En.wikipedia.org。检索于 2018 年 6 月 16 日,来自https://en.wikipedia.org/wiki/Riemann_sum

洞察路线——有效志愿者数据科学项目的七个步骤

原文:https://towardsdatascience.com/insight-lane-seven-steps-to-an-effective-volunteer-data-science-project-781a00f40d1e?source=collection_archive---------27-----------------------

Photo by Kevin Ku from Pexels

Insight Lane 背后的团队:D4D 碰撞模型最近发布了他们项目的版本 1.2 ,这是一个重大的升级,解决了项目技术堆栈中的许多基础问题,将允许未来更快更好的开发。

虽然我们都对我们在这个版本中取得的具体成就感到非常自豪和兴奋,但我最喜欢的方面是看到团队使用结构良好的计划和有效的项目管理技术富有成效地协作。规划和项目管理有时被视为在数据科学中完成“实际工作”的不便或阻碍,但我们的经验表明,它们是项目成功和团队快乐的基础。

志愿技术项目往往遵循一条既定的弧线:个人或团体从一个令人信服的想法开始。首先是巨大的热情——聊天渠道建立起来了,源源不断的好想法和有趣的文章被分享。代码库被创建,并且有一系列的初始提交。当然,对于项目将如何发展并最终达到目标,还没有投入太多的思考,但是嘿,我们有热情,我们正在建设!

Photo by Startup Stock Photos from Pexels

然而,随着时间的推移,这种热情开始消退。很快,每日代码提交变成了每周,然后是每月。困难的决策被推迟,因为它们涉及太多的工作,并且影响项目的太多领域,这通常会进一步减慢进度。现有团队成员开始渐行渐远,新成员也没有成功加入,因为他们不知道从哪里开始,也不知道如何跟上进度。

Insight Lane 团队已经活跃了一年多,在此期间,项目的性质发生了重大变化。最初只是与美国的一个城市合作,现在已经发展成为一种工具,可以帮助世界上任何一个城市实现更安全的道路。这种方向上的变化带来了在更广泛的背景下考虑每个问题的需要——城市以多种不同的方式记录和存储数据,一些数据源的覆盖范围不一致,项目的总体复杂性急剧增加。我们的最终目标是让所有参与城市在推进道路安全事业中相互分享他们的见解,利用集体智慧的力量,而不是在孤立的孤岛中运作。

为了解决这种新方法的挑战,同时保持专注和高效,团队实施了许多不同的项目管理技术,这些技术可能对希望启动自己的项目的新团队有用。它们中的每一个都有促进有效沟通和朝着明确定义的目标不断前进的想法。

1。定期会议

Insight Lane 团队每周三东部时间下午 6 点通过 Google Hangouts 召开一个小时的会议。这个时间很方便,因为它允许来自不同时区的成员参加。我们有一个轮流主持会议的时间表,这让每个人都有机会确保他们的想法被听到和讨论。这种格式可以适应那一周需要解决的任何问题,但总是包括重要的日程安排,如审查正在进行的任务和更新与外部小组的讨论。

2。任务跟踪

一个项目最终是其各个部分的总和,而在一个数据科学项目中,必然会有很多移动的部分!如果某件事情值得讨论,那么通常就值得采取行动,试图在没有结构化流程的情况下组织任务会很快变得难以管理。任务跟踪对于了解当前正在进行的工作、谁在做以及还有什么需要做是非常重要的。我们的团队已经选择使用 GitHub Issues,它与我们的项目代码库和其他 GitHub 功能(如拉请求)很好地集成在一起。任务存储在逻辑列表中(待办事项、进行中、已完成和等待),每个任务的完整通信历史都很容易看到。

3。项目里程碑

将我们的项目组织成具有清晰范围的发布里程碑,对于确保我们总是致力于增加价值的事情来说是一个巨大的胜利。在这个过程中,我们再次选择了 GitHub,使用它的“项目”特性。通常,当我们接近一个发布的工作范围的末尾时,我们会设定一个完成的时间表,这可以真正地帮助激励团队完成他们的任务,而不是延迟发布。

4。自由交流

虽然项目面临的大部分重大问题都是在例会上通过使用我们的任务跟踪软件来讨论的,但通过使用实时聊天服务,从事同一任务的团队成员之间往往可以在短时间内取得很大进展。还可以分享新的想法,以激发关于项目下一步可能走向的进一步讨论。我们通过 DataForDemocracy 的 Slack 环境有一个专门的项目通道,我们用它来深入研究技术问题、发送测试文件和一般的项目聊天。这也是在团队中培养团队精神的一个重要方法,这对于保持参与和投入是至关重要的。

5。新用户入职流程

每个团队都可以从新成员的到来中受益,他们带来了新的想法和观点以及额外的能力。不幸的是,一旦一个项目达到一定的复杂程度,新成员如果不花大量的时间让他们熟悉情况,就很难参与进来,这通常会导致很高的退出率。为了缓解这种情况,Insight Lane 团队邀请每一位加入我们渠道的新成员使用我们在版本 1.1 中开发的既定管道流程登上一座新城市。这使得新成员阅读我们的文档并为自己运行代码,通常是根据他们自己城市的数据,这提供了一个有趣且相关的起点。它还帮助我们发现我们假设中的未知边缘情况,因为每个城市都是不同的,并确定我们的文档不像我们认为的那样清晰的区域。

6。代码管理&评审

数据科学团队由个人组成,每个人都有自己的经验和对所用技术的熟悉程度。对于什么样的工作标准是可接受的,会有不同的期望,因此使用一些行业实践和工具有助于建立项目基线。我们的团队有一个惯例,在没有首先被审查之前不合并代码,并且使用 Travis 持续集成来确保现有的功能不会受到负面影响。此外,我们最近开始使用 Codecov,这是一个工具,旨在提供一个简单的度量,来衡量我们的代码有多少被自动化测试所覆盖。通过将新功能与新测试相匹配,我们试图确保这个数字不会因为添加代码而减少。

7。使用适当的技术

数据科学团队需要了解有哪些新工具可用,以确保他们以最佳方式实现目标。但是如今技术领域变化很快,有很多很酷的语言、应用和服务可供使用,这意味着很容易陷入兔子洞,而这不一定会推动项目向前发展。广泛使用并有良好记录的技术和语言是很好的选择,那些允许重用现有模块的技术和语言也是如此。鉴于我们项目的数据驱动性质,Python 是一个很好的选择,有许多机器学习和数据分析模块可以提供帮助。团队成员的计算机和设置很可能是各种标准的混合,因此找到在不同环境中一致工作的方法也是一个好主意。Docker 容器在这方面帮了我们大忙。

七个步骤,一个目标

Photo by Kaique Rocha from Pexels

乍一看,这些技术都集中在提高项目的效率上,但是在更重要的层面上,它们致力于提升团队成员的 T2 乐趣。志愿者项目可能是艰苦的工作。现代世界不断吸引着你的注意力,在常规工作或学习之外找时间免费工作是很困难的。拥有一种进步感、成就感和团队精神可以让一个项目变得令人愉快,我相信这是 Insight Lane 长期保持稳定和高效的重要原因。最终,任何项目都取决于它的员工,当员工参与其中并感受到价值时,他们处于最佳状态。

原载于 2018 年 8 月 21 日medium.com

来自纽约市 DATAx 会议 7 场会议的见解(2018 年 12 月)

原文:https://towardsdatascience.com/insights-from-7-sessions-of-the-datax-conference-in-nyc-dec-2018-d6265702dbbd?source=collection_archive---------20-----------------------

纽约 DATAx 大会(创新企业峰会)于 2018 年 12 月 12 日和 13 日举行。该活动分为五个平行的赛道会议,侧重于不同的领域,并允许参与者从一个赛道流向另一个赛道。虽然我不能参加每一次会议,但这里有一些我听过的精彩演讲。

让数据变得有用

凯西·科兹尔科夫,谷歌首席决策科学家

Cassie Kozyrkov 提供了一些可行的建议,让数据科学家在产生业务影响方面更加有用。本次演讲的几个要点包括:

激励你的全体员工查看信息是很重要的;使其易于访问并打破孤岛。

严谨应该从决策者开始。她讨论了学术界如何教授使用最复杂工具的技能,这在多年的实践后成为一个难以打破的习惯,所以当这些人被商业企业聘用时,他们不会神奇地改变他们的思维模式(他们还不知道什么对商业价值来说是重要的)。这意味着他们可能会在错误的项目上投入精力。她建议先对数据进行粗略的扫描,只有当决策者认为这项工作有价值时,才进行更深入的挖掘。

按正确的顺序做事。(你可以在她的文章中读到更多信息:“人工智能的第一步可能会让你吃惊”)

处理应用项目的正确方法是颠倒算法-输入-输出的顺序,就像这样:考虑输出,然后输入,然后算法/模型。确保每个项目的正确阶段都有正确的领导参与。如果他们是独立的个体(在许多组织中,一个人拥有几个或所有这些角色),那么您将按如下方式传递接力棒:

  • 决策者(关注产出)
  • 首席分析师(关注输入)
  • 首席机器学习工程师(专注于算法/模型)
  • 首席统计师(关注绩效)

在她的演讲中听到的另一个关键信息是“拆分你该死的数据”——凯西称之为最佳生活理念,所以她希望这些话会成为她的墓碑

Airbnb 动态定价的定制回归模型

徐航军,高级机器学习软件工程师,Airbnb

杭军描述了 Airbnb 部署的定价策略模型,这是一个分享家居和体验的在线市场。价格优化的目标是帮助在 Airbnb 上分享房屋的房东为他们的房源设定最佳价格。

与定价策略适用于大量相同产品的传统定价问题相比,Airbnb 上没有“相同”的产品,因为他们平台上的每个列表都为他们的客人提供独特的价值和体验。Airbnb 房源的独特性质使得人们很难估算出一条准确的需求曲线,而这条曲线是应用传统的收入最大化定价策略所必需的。

他们使用监督回归模型,以最优价格为标签。如果一个列表没有以 140 美元被预订,他们不应该以更高的价格(比如 160 美元)列出它。另一方面,如果列表的预定价格是 120 美元,那么他们不应该以低于这个价格(比如 110 美元)的价格列出它。这就创造了一个他们试图平衡的最低和最高预订范围。

该公司面临的一些挑战包括处理非常独特的列表和稀疏的数据。

数据驱动的产品管理:如何在亚马逊时代建立成功的客户体验

丽贝卡·格林,Handy 首席产品官

在今天的零售环境中,两天发货、点击订购和轻松退货已经成为赌注。为了在亚马逊时代保持竞争力,公司必须适应并超越对即时、无缝和端到端客户体验的期望。

Rebecca 谈到了公司如何通过数据驱动的产品管理来满足不断增长的客户期望。她还分享了在当今的商业环境中,构建成功产品的一些设计决策和客户考虑因素。

我从她的演讲中得到的主要启示是“便利是王道”——让你的买家更容易,也会让你更容易!她提供了一些让顾客生活更轻松的公司的例子:Lowes 的虚拟现实可以让你更快地找到商店里的东西。另一个例子是 Sephora 的调查、配色等。当然,亚马逊提高了免费退货和 2 天送货的风险。

她的公司 Handy 让顾客的生活变得更轻松的一种方式是将其服务与其他公司(如销售家具的 Wayfair)无缝集成。Handy 提供家庭服务(其中一项是组装家具)。通过合作,他们简化了流程,并在一个屏幕上提供家具和组装工作(无需单独结账),并且无需额外的安排,因为 Handy 正好在送货卡车经过的同一天过来。

他们也使用大量的 A/B 测试来看什么对他们的客户有效。例如,他们试图通过使用 2 分钟的视频宣传 Handy 的工作原理,并通过使用 FAQ 文本部分来揭示在购买时刻,购买者更喜欢阅读 FAQ 而不是观看视频。

深度学习闪电入门

麦格劳-希尔教育公司分析和 R&D 副总裁 Alfred Essa

深度学习是机器学习中发展最快的领域。在他的演讲中,阿尔弗雷德谈到了什么是深度学习?为什么重要?与其他 ML 技术相比,它是如何工作的?然后,他通过构建一个简单的营销深度学习模型得出结论。

阿尔弗雷德从讨论“极端”的含义开始,他提供了一些例子,如跑马拉松(我完全可以理解)——然后他继续谈论深度学习是机器学习的一个极端情况。

我们讨论了深度学习的各个方面,包括:神经元、层、前向传播、损失和成本函数以及反向传播。最终目标是创建一组实现最低损失或误差的网络参数(权重和偏差)。

从金融服务部门的人工智能计划中吸取的 10 条经验教训

Andy Price,金融服务主管,纯存储

数据驱动的用例正在为商业领域的人工智能(AI)等下一代工作流铺平道路,金融服务业也不例外。为了大规模交付人工智能,组织必须考虑几个主要的依赖因素和挑战,这要求他们对人工智能项目对组织内基础设施的技术要求有高层次的理解。Andy 分享了从金融服务领域的人工智能计划中学到的 10 条经验。

  1. 不要低估信息安全挑战—访问您需要的内部数据很困难,其他挑战包括将数据放入公共云中。数据来源计划花费的时间比任何人预计的都要长 2-3 倍
  2. 工具和框架正在快速发展——不要对工具过于虔诚。你不想 6 个月正确而永远错误。这里遵循的原则是建立在开放标准的基础上,避免供应商锁定——这样您就可以根据需要换入/换出工具
  3. 你的计划是战略性的还是战术性的——提前与客户和利益相关者讨论,因为这可能会推动不同的思维过程。想想必须对解决方案进行全面重新设计的含义。如果你不提前考虑战略方向,技术投资可能会被扔掉。如果是战略性的,就这样对待它,并在允许您无中断扩展的基础上进行构建
  4. 人工智能通常对概念验证具有挑战性——测试难的东西——尝试打破它——不要在容易的东西上浪费时间。尽可能进行真实世界的测试;了解你的投资能让你走多远(避免意外)。玩具数据集产生玩具结果
  5. 记录您的关键能力—您希望为解决方案设计的实际规模水平是多少;多少个 GPU 等等。你可能想对未来进行再投资,但提前记录这一点是值得的
  6. 基础架构关键优先级—让 GPU 保持忙碌,让数据科学家忙于数据科学。避免让数据科学家进行系统集成和系统优化/调整。确保基础设施有能力处理混乱因素;针对一切进行了调整,并且能够同时提供不同的数据类型
  7. 认识到数据科学的成本-你不希望数据科学家没有生产力。在纽约,一名数据科学家的平均成本是每年 15 万美元。不要吝啬基础设施投资。如果我们相信软件正在吞噬世界,数据是世界上最有价值的资源,人工智能是第四次工业革命,那么让我们相应地行动和投资。
  8. 人工智能是一个管道——不仅仅是培训。60-80%的人工智能工作是数据准备,只有 20-40%是训练。大多数组织都专注于培训部分;但所有早期阶段都包括从组织中各个领域的数据科学家的笔记本电脑中收集各种数据集。需要整合,在端到端平台上保持高效和有效
  9. 很少有人了解端到端的解决方案。数据科学家了解工具和框架。基础设施必须能够应对挑战。很少有数据科学家懂基础设施,很少有基础设施人不懂数据科学;需要弥合这一差距
  10. 在大型组织中,这变得越来越具有挑战性——需要密切协作;公司在各自为政中工作。AIRI 人工智能就绪基础设施—产品闪存刀片—一旦您的 GPU 数量增加,传统存储将无法跟上

从金融领域的机器学习(ML)教学中获得的 5 个经验教训

Meninder (Mike) Purewal,纽约大学主任、数据科学家兼兼职教授

迈克讲述了他从教授 ML 金融课程中学到的五条经验。

  1. 教金融领域的 ML 很难——找到理解金融、数学和计算机科学的独角兽几乎是不可能的。最好的办法是找到覆盖几个领域的人,把他们和覆盖其他专业领域的人组成团队。教育供给刚刚开始满足需求
  2. 在金融领域教授 ML 很容易——借助谷歌搜索的便利,你可以快速找到代码,并将其复制粘贴到你的控制台上,然后说你是一名数据科学家。这很有吸引力,也很危险,因为大多数人并不完全了解这种东西是如何工作的
  3. 期望与现实——在现实中,工作是艰难的,细节是一种折磨。市场上活跃的产品主要是编码规则 vs. AI。让这些东西运转起来是一件苦差事。对高层领导的期望与现实不符
  4. 没有太多好的例子可以教——金融文化倾向于保密(信息囤积)。教科书非常缺乏,所以他建议人们使用博客/ LinkedIn 帖子来学习。他被迫使用 Iris 数据集,因为金融数据很少。这导致人们在实际工作之前无法学习
  5. 深度&少 vs .浅层&多——在机器学习中,人们可以选择两个方向。他们可以成为专注于研究的专家(深度&少数),或者进入咨询/管理角色(浅层&人)。两者都有价值,但它们走的是不同的道路。你需要适当地宣传自己,适当地设定学习目标和期望

通过负责任的人工智能加速创新

普华永道董事兼兼职教授 Jay Chakraborty

我真的很期待这次会议,因为人工智能和数据科学背景下的“伦理”真的是我最关心的问题

对我来说。Jay 在强调一些例子方面做得很好,这些例子说明了为什么在处理机器/数据时我们需要人的因素。他提供的例子包括 Stanislav Petrov——他承认显示俄罗斯受到攻击的数据中存在问题(他意识到美国不会只派 5 枚导弹来攻击俄罗斯;因为这还不够)——他基本上发现了一个系统故障;点击阅读更多关于的内容。

另一个例子是对选美冠军的预测(其中包含主要选择白人女性作为潜在获胜者的偏见)。此外,他提到了一个例子,我计划将这个例子纳入我正在开发的数据科学伦理课程中——这是一个决定警察应该巡逻哪些街区的算法——这通常会导致他们巡逻更贫困的街区,并仅仅因为有机会在那个街区发现更多的“犯罪”。

为了释放人工智能的全部潜力来转变您的业务,需要深入了解客户,将社会和道德影响嵌入人工智能设计和模型开发的结构化方法中。他介绍了负责任的人工智能的伟大模型;它代表着治理、可靠、道德、负责和透明。

Jay 还强调了一个事实,即我们需要摆脱使用“黑盒”的借口,开始打开它并记录进入这些模型/算法的一切。

结论

总之,DATAx 大会给我提供了几次学习的机会,让我认识了一些真正有趣的人!

从原始 NBA 投篮记录数据和探索热手现象的见解

原文:https://towardsdatascience.com/insights-from-raw-nba-shot-log-data-and-an-exploration-of-the-hot-hand-phenomenon-1f1c6c63685a?source=collection_archive---------12-----------------------

作者:迈克尔·阿瑟、凯勒·约翰逊、艾蒙·汗、尼迈·库马尔、里德·怀德

Photo by Ramiro Pianarosa on Unsplash

概述

数据科学和篮球比赛每年都变得越来越交织在一起。休斯顿火箭队的强力三分中锋进攻使他们一跃成为 NBA 的精英球队之一。他们的总经理达里尔·莫雷十多年来一直是高级分析的公开支持者,在过去的几年里,很明显莫雷球(被 NBA 书呆子亲切地称为 T5)正在被整个联盟的总经理模仿。费城 76 人队现在正在收获前通用汽车和数据大师 Sam Hinkie 的好处,他的非正统团队建设战略引起了整个联盟的两极分化辩论,并最终导致他在 2016 年下台。虽然他可能丢掉了工作,但他数据驱动的工作成果是不可否认的。76 人队现在是联盟中最强的球队之一,主要由欣奇选中的年轻球员提供动力。

我们小组认为在篮球分析方面仍有大量有趣的工作要做,我们想探索一个原始数据集并做一些我们自己的分析。具体来说,我们小组希望获取原始 NBA 投篮日志数据,从中提取有意义的信息,并创建引人注目的图形来展示我们的发现。此外,我们想探索“热手”现象的统计学意义。换句话说,我们想发现,事先知道一个球员连续投篮几次,是否会改变我们对他下一次投篮是否会进的预期。

数据

数据收集

除了 NBA 网站之外,像我们使用的数据这样的原始空间拍摄数据很难在任何地方找到。不幸的是,NBA 在几年前就停止公开其 API 了。我们需要刮他们的网站,以获取当前的数据。我们对项目的分析和可视化方面比对抓取更感兴趣,所以我们使用了 2014-2015 赛季的数据集,该数据集是在公共 API 仍然可用时获得的。当新数据可用时,我们的分析可以很容易地扩展到新数据。数据集的示例如下所示。

A snippet of the raw NBA shot log dataset

数据清理

正如对 NBA 官方数据集的预期,这些数据得到了合理的维护;然而,有一些令人惊讶的差异需要清理。许多名字在数据中被拼错了,这在我们的分析中造成了异常值。此外,CLOSEST_DEFENDER 和 player_id 要素中的名称需要采用相同的格式,以便于我们的分析。一旦我们有了相同格式和正确拼写的名字,我们就可以做一些预处理和特征提取,并做一些分析。

特征抽出

由于炮测井数据提供的直接信息很少,我们需要为我们所做的每一种不同类型的分析进行大量的特征提取。我们不会在这一节中用很少的上下文来解释我们所有的预处理工作,我们将回顾一下在洞察和分析一节的每个不同小节中什么样的预处理是必要的。

见解和分析

最佳双向球员

我们希望从 2014-2015 年 NBA 最佳双向球员的简单评估开始我们的分析。一个好的双向球员是进攻和防守都有效的球员。我们决定通过创建一个包含三个特征的数据帧来做到这一点:{player_id,pts_scored,pts_allowed}。通过对 SHOT_RESULTS 列中每个“制造”篮筐的所有 PTS_TYPE 特征求和来计算每个球员的得分。所允许的点数是通过对给定球员在 CLOSEST_DEFENDER 功能中列出的每个投篮进行求和来计算的。新数据框架的示例如下:

一旦我们有了这个数据框架,我们创建了一个散点图(如下)来更好地可视化数据。

Points given up vs Points scored

正如所料,一些最优秀的双向球员,如德怀恩·韦德,拉塞尔·维斯特布鲁克和勒布朗·詹姆斯,被列在图表的右下部分,因为他们得到了很多分,但在许多篮下没有被列为最接近的防守者。其他球员如克莱·汤普森、斯蒂芬·库里和詹姆斯·哈登也榜上有名。虽然这些球员的防守并不出色(根据这一分析),但他们的得分能力使他们和其他人一样属于精英类别。

关于这个图表的一个奇怪的事情是贾马尔·克劳福德出现在精英双向球员中。贾马尔·克劳福德被普遍认为是一个糟糕的防守者。他意外出现在图表的这个区域可以用他在团队中的角色来解释。克劳福德的角色是替补能力较弱的球员,并在球队最好的球员休息时承担进攻负担。这个角色导致克劳福德比图表上显示的其他球员少打了 30%的比赛,这也导致他比其他人打了更多的比赛。换句话说,这种特定类型的分析确实有利于像贾马尔·克劳福德这样的球员,显然不是一个完全描述球员价值的指标。事实上,任何先进的体育指标都将固有地偏爱某些类型的球员,这取决于该指标优先考虑比赛的哪些方面。

球员得分效率

为了评估单个球员的表现,我们希望收集更多关于他们投篮的背景信息。这位球员的投篮一般都很好,还是效率不高?在深入研究之前,我们首先必须使用特征提取来开发数据,这些数据详细说明了球员的平均投篮距离,他们在每个区域的投篮百分比,以及他们在每个不同区域能够投篮的次数。这些信息给了我们一个球员在比赛中投篮类型的更完整的图像。然后,我们创建了一个模块,该模块接受输入玩家姓名,并将他们的击球距离、击球时间和击球结果数据输出到一个新的数据帧中。我们工具的屏幕截图如下所示:

一旦我们有了新的数据帧,所有的镜头都由 DIST 镜头和时钟镜头组织成 144 个独特的箱。投篮距离被分割成 6 个距离范围的<5 ft, 5–10 ft, 10–15 ft, 15–20 ft, 20–25 ft, and 25–30 ft. Clock times were segmented into 24 bins of 1 second each, from 0–24 sec. Each bin was then mapped to the amount of shots taken in that bin, and the amount of shots made.

We then made 2D heatmaps of this data, with distance on the Y-axis and clock time on the X-axis.

Using this 数据,我们计算了球场上每个区域的联盟平均投篮命中率(投篮次数/总投篮次数)。然后我们创建了一个二元热图,它显示了一个球员在球场的那个区域是高于还是低于联盟平均水平。棕色区域表示高于联盟平均水平,黑色区域表示低于联盟平均水平。扬尼斯·阿德托昆博的二元热图如下所示:

虽然热图很有用,但它们并不十分美观。我们想要更好的东西。使用 matplotlib 中的 plot_trisurf(),我们绘制了# shots made、shots taken 和 binary 图。这些是热图的 3D 视图:

Giannis Antetokounmpo Shot Breakdown

解释

使用这些图形,我们可以确定哪些球员知道他们在场上的哪些区域效率很高,哪些球员在他们缺乏持续转换技能的区域持续投篮。在扬尼斯·阿德托昆博(希腊怪胎)的例子中,我们可以看到他的大部分投篮都是在离篮筐更近的地方完成的,大部分时间仍然在投篮时间表上。詹尼斯是一个有效率的球员,这张图表显示他的大部分投篮都靠近篮筐,他是一个强有力的射手。

布莱恩·罗伯茨是一个很大程度上在三分球范围内投篮的球员,尽管他不是一个特别好的三分球手。请注意,在第三张图中,当投篮时间低于 3 分范围时,他低于联盟平均水平:

Brian Roberts Shot Breakdown

玩家互动

使聚集

除了之前提取的数据集特性之外,我们还必须设计一种方法来将一些高级防御指标融入到我们的数据中。我们可以通过在每个球员的数据帧末尾添加防守框加减栏来做到这一点。这个指标让我们可以看到一个球员在球场上的个人防守对整个球队的防守表现有多大贡献。在提取了关于玩家倾向和综合统计数据的有用特征之后,我们想要比较不同玩家如何倾向于相互得分,以及我们是否可以在这些玩家关系中找到任何趋势。

为此,我们考虑了两种聚类算法:K-Means 和 Mean-Shift。我们最终选择使用 K-Means,因为均值漂移在处理不密集且有很多异常值的数据时表现不佳。鉴于我们数据集中合格的 NBA 球员数量相对较少,并且两个球员投篮命中率非常相似的可能性很小,我们决定 K-Means 是我们数据集的一个更好的聚类工具。

使用 K-Means 时最大的挑战是决定聚类的数量。我们发现 4 到 5 个聚类对于这个数据集是最佳的,因为有更多的聚类会创建一些参与者很少的小类,而有更少的聚类会导致类过于一般化。使用 k=5 会产生两类高容量得分玩家,一类中容量玩家和两类低容量玩家。

可视化集群

下一步,我们想要可视化这些职业如何影响玩家的得分和防守。我们用于这个可视化的工具是 D3.js ,因为它在创建不同类型的可视化方面非常灵活。受我们在研究数据驱动文档时发现的一个例子的启发,我们选择创建一个力导向图。创建这个图表需要在 Jupyter Notebook 中进行大量的数据预处理,以构建一个 JSON 文件,该文件的格式易于从 JavaScript 操作。

首先,我们必须从击球日志数据中创建一个查找矩阵,以记录每个球员在其他球员身上的得分。然后,这个矩阵 attack_defense_matrix.csv 与 players_kmeans.csv 一起被迭代,以构建节点和边的列表。每个节点包含一个玩家的信息,包括一个唯一的标识符,他们的总得分,k-means 定义的类别标签,以及玩家的[防守框加/减(DBPM)](http://Defensive Box Plus/Minus (DBPM)) 。每条边反映了给定玩家相对于其他玩家的得分。这些数据随后被存储为 JSON 文件中的邻接表,JavaScript 文件解析该文件以填充图形。

我们从这些经过处理的数据中创建了两个交互式的力导向图:一个可视化玩家的进攻能力和一个突出他们的防守限制。在 mouseover 上,进攻图形显示每个球员从我们的得分效率工具生成的 3D 热图。防守图形显示每个球员调整后的 DBPM。

Force-Directed Graph of NBA Players by Offensive Cluster

图表的解释

攻击图

进攻图中节点的大小表明了球员得分的多少。我们选择在 mouseover 上展示一个球员的投篮分布,来探究不同类型球员的进攻能力有何不同。节点的平均大小因类而异。节点的颜色代表 k-means 聚类生成的不同组。红色和蓝色节点往往都是高得分者,但他们通常在球场上的不同区域投篮。紫色节点是次要得分手,投篮分布更均匀,绿色和橙色节点往往是更低输出的球员。我们发现这些 k-Means 定义的类是一种合理有趣的球员分组方式,作为传统篮球位置的替代。

蓝色节点代表在篮筐附近得分最多的球员。虽然这一组主要由大个子组成,但一些凶悍的后卫如凯里·欧文和詹姆斯·哈登也属于这一类。大多数大个子的蓝色节点都是高度连接的,这意味着大个子通常会在其他中锋和大前锋身上得分。这是有道理的,因为这些球员经常互相防守,并且在大多数防守中都倾向于靠近篮筐。

红色节点代表射手,主要是后卫,他们的大部分得分来自三分球范围,如斯蒂芬库里和达米恩·利拉德。这些球员中的一小部分通常会在其他后卫身上得分,这是有道理的,因为后卫是最经常防守远射的球员。其他 K 均值聚类包含对游戏影响较小的玩家。

防御图

防守图中节点的大小代表了一个球员允许在其上得分的投篮次数。乍一看,似乎较大的节点代表较差的防守者,因为他们得分最多,但这是误导性的,因为球员上场时间越长,节点越大。此外,中锋和大前锋更有可能在我们的数据中被列为最接近的防守者,因为他们经常在篮下投篮。由于这些原因,我们的防守图不公平地惩罚了‘大个子’。

当鼠标悬停在一个节点上时,我们图表的用户可以看到玩家的防守框正/负(DBPM)评级。这一评级是最广泛用于衡量球员对防守的整体影响的,它是我们的分析偏离球员普遍观点程度的晴雨表。例如,图中保罗·米尔萨普节点的大小暗示他是一个糟糕的防守者,但他的 DBPM 评分是 26——联盟中最强的之一。

滚烫的手

一些球员(咳咳克莱·汤普森)怎么可能“走火入魔”,或者换句话说,怎么可能有看似不可阻挡的高效发挥?我们想知道,“热度”,或者一个球员在最后 N 次投篮中的投篮次数,对投篮命中率或者得分有影响吗?

为了研究这一点,我们开发了一个击球条件和球员热度的模型,并研究这些因素如何影响击球精度。

作者感谢的分析,因为它解决了“热手”问题。所有的编码都是由这篇文章的作者独立完成的。

难度条件分为四类:

  • 游戏条件(主场/客场、游戏时间、总游戏时间、积分优势)
  • 射门条件(到球网的距离,英尺对 2 对 3 指针,射门时钟)
  • 防守条件(最近的防守者距离、防守者技能(DBPM)、身高劣势)
  • 球员固定效果(球员真实投篮百分比)

我们做多重回归来找出每个条件类别中特征的重要性。然后,我们对所有条件类别进行回归,找出每个条件类别的相对重要性:

难度条件分析

在游戏条件图中,我们看到主场和客场的区别比积分分布和周期占主导地位。经过的游戏时间看起来基本没有影响。我们应该小心不要过早地解释这一点,因为与其他三种难度条件相比,游戏条件显得无关紧要。

投篮条件和防守条件(分别以距离和防守者技能为特征)对投篮难度的贡献相对相等,球员固定效应(真实投篮百分比)的贡献约为投篮条件和防守条件的 75%。

热分析

我们必须根据先前的多次发射来定义热。N 热被定义为在最后 N 次尝试中进行的 K 次射击的 K/N。我们比较了 N 次热身赛得分和一次投篮得分:

虽然这个模型可能暗示了不同热度之间的显著影响差异,但是我们在线性模型截距的上下文中解释了相对较低的量级分数:0.988402331。

这意味着热量对这些点的影响相对来说是微不足道的。

热,在上下文中

为了进一步研究热量的影响,我们做了另一个回归,这次控制困难条件:

在这个最终回归中,我们看到球员固定效应,即球员的真实投篮命中率,是平均热效应的 8 倍以上,并且是得分的最重要的决定因素。这并不奇怪,因为真实的投篮命中率是一个球员整个赛季的总和,也是他们得分多少的决定性指标。防御条件也是一个相当大的贡献。射击条件本质上是由结构决定的射击距离。我们看到主场优势实际上没有热火重要。

“热手”存在吗?这很难说,但与环境和球员统计相比,这在 NBA 人口中似乎可以忽略不计。要做的进一步工作包括对单个玩家进行分析,看是否只有一些玩家表现出热手牌。可以探索玩家信心指标和更深入的投篮难度分析。

结论

在这个项目的过程中,我们清理了一个原始的 NBA 投篮日志数据集,执行了特征提取技术,并创建了有用的分析工具,为球员如何得分提供了有用的视觉效果和洞察力。虽然我们的工具目前只提供了初步的见解,但只需对我们的源代码进行微小的更改,就可以实现更高级的概念,并且可以相对容易地收集和分析更近的炮测井数据。

此外,我们发现热手现象没有统计学意义。虽然有一些我们没有探究的热手问题的变体(例如一些特定的玩家是否有能力变热),但我们发现,一般来说,连续投篮并不会对未来的投篮产生有意义的影响。

我们希望您喜欢阅读我们的工作。如果你有兴趣,看看我们的 Github 库。

洞察流失预测的复杂性

原文:https://towardsdatascience.com/insights-on-churn-prediction-complexity-30b32d466660?source=collection_archive---------5-----------------------

Photo by Gabriel Crismariu on Unsplash

如果仅仅进行客户流失预测就像参加一场纸牌游戏比赛。

你已经有了一个数据集,一个很好的基础设施,一个衡量你的预测成功与否的标准,你的目标和特性也已经定义好了。你只需要做一些功能工程和测试一些算法,瞧,你得到了一些东西。我希望有这么简单。

实际上,这很复杂。我在移动游戏行业研究客户流失已经有一段时间了,这篇文章将揭示与这种预测相关的一些复杂性。让我们想一想在进行客户流失预测之前我们必须回答的一些问题。

  1. 你打算如何利用你的结果来产生投资回报?这一点极其重要,但却常常被忽视。如果某个用户成为高流失率用户,你打算如何行动?基础设施和/或组织结构是否能够发挥作用?运送无法采取行动的复杂物品是没有意义的。
  2. 预测的目标是什么?是了解还是预测有可能流失的用户?这通常会导致您使用两套不同的算法。
  3. 在你的行业中,有没有你应该知道的基准或最佳实践?这肯定会对你试图解释和/或预测的客户流失产生影响。
  4. 你如何衡量你的预测是否成功?如果你把用户流失看作是一个二元分类问题,不流失的用户可能非常少。您可能会尝试使用 ROC 曲线下的部分面积(PAUC ),而不是 AUC 或自定义加权指标(得分=敏感性 0.3 +特异性* 0.7)。*
  5. 你怎么知道什么时候停止改进你的预测,什么时候发布你的第一个版本?一旦您建立了评分标准,您必须建立一个阈值。阈值将通知您何时发货。
  6. 您是否与利益相关方就模型的成功衡量达成一致?
  7. 你想预测你的所有用户还是只预测一个细分市场?例如,如果你想预测新用户或老用户,你可能不会使用相同的功能。
  8. 目标是什么?这很有趣,但你可以将流失预测视为一个经典的二元问题(1:流失用户,0:不流失),但你也可以将 Y 视为播放的会话数。
  9. 你有什么特点?您打算使用时间相关功能吗?根据你的行业知识,预测客户流失最重要的特征是什么?基于您当前的数据库,它们容易计算吗?你考虑过 RFM 的著名特征吗?
  10. 你如何获得数据?您是否需要进行批量 SQL 调用来收集所需的数据形状,或者您是否需要从流式数据开始,或者您是否打算在发布更好的版本时从批量数据发展到流式数据?
  11. 你打算如何清理你的数据?你如何处理丢失的、异常的和极端的值,这些值会破坏你的模型。
  12. 当你编码时,你应该测试什么?谷歌发表了一篇很棒的文章,它提供了一套可操作的测试来帮助你开始。
  13. 你如何在生产中推动你的工作?您需要将您的预测结果放入数据库中,还是需要将您的模型作为 REST API 提供?你如何与软件工程师合作?
  14. 您将如何监控生产中预测的质量?您打算创建一个仪表板吗?您会在数据库中创建一个包含日志的表吗?你会监控什么?根据您预测质量的某些 KPI,您打算如何行动?
  15. 你的车型保养流程是怎样的?您是否打算每个月、每个季度对您的模型进行一次更改?你计划改变什么?改变的历史是什么?
  16. 你的交付成果是什么?随着时间的推移,您打算如何改进您的模型?
  17. 你要用哪个工具?在必要的情况下,你将使用 R、Python 或 park。当你真的有大数据(1000 万行要预测)的时候,推荐 Spark。注意,与顶级 Python 库(tensorflow、sk learn……)相比,Spark ML 库是有限的
  18. 您将使用哪些软件包进行预测?有这么多包有(sklearn,H2O,TPOT,TensorFlow,Theano…等等)
  19. 你如何处理再次聘用用户的问题?如果你决定预测用户将在未来 30 天内流失会怎样?如果他们 30 天后回来呢?在你的分析中,你如何看待这种偏见?
  20. 你打算用哪种算法?可能是随机森林、SVM、线性回归、神经网络或其他。你也可以使用自动机器学习来找到你的第一个模型。无论你决定选择什么,你都需要知道每个算法的数据假设。

这是最好的部分,你甚至还没有开始编码…

伟大文章的链接

  • 作为回归问题的流失: delta dna 文章
  • 新用户流失: gamasutra 文章
  • 老用户流失: gamasutra 文章
  • 流失预测生存分析:硅工作室
  • 考虑再次参与的流失预测的高级示例:[点击](http://Seems like an approach that address all problem related to churn https://ragulpr.github.io/2016/12/22/WTTE-RNN-Hackless-churn-modeling/)

值得分享?

请按下💚就在你的正下方。它帮助更多的人找到它。

Instagram #LifeInScience 系列。

原文:https://towardsdatascience.com/instagram-lifeinscience-series-657e4749e589?source=collection_archive---------11-----------------------

与更多的观众分享你的故事和激情。

我们#life in science系列的目标是更好的了解你。你为什么对自己的工作如此有激情,你是如何开始的,你目前在做什么?

举例 : 那华,卢多,艾迪。

您可以通过给我们发送电子邮件来投稿:

  1. 你的名字(如你所愿)。
  2. 您的 Instagram 用户名(可选)。
  3. 这些问题中的一个或两个问题的答案(总计2200 个字符):
  • 你是如何对你的科学领域充满热情的?
  • 你目前在做什么?
  • 你最喜欢的,你认为应该让更多人知道的科学概念是什么?
  • 最新的科学发现是什么让你有一种“哇”的感觉?

5.最后,为你的故事选择至少十个精确的标签(这个列表并不详尽):#生命科学#科学#科学故事#科学#科学理论#实验#实验室#认知科学#神经科学#大脑#心理学#生物学#进化#哲学#人类学#语言学#健康#太空#未来#技术#科技#生活#创新#艺术#灵感#女性科技#地球#自然#计算机科学#数据科学#机器学习#数据可视化#数据驱动#统计#设计#分析

把你的短信发给 publication@towardsdatascience.com T21,不要忘记一张或多张你的照片。最好的帖子将会发布在我们的insta gram 脸书 页面上。

非常感谢,

TDS 团队。

Snoopreport 服务为深度分析提供 Instagram 用户活动数据

原文:https://towardsdatascience.com/instagram-user-activity-data-provided-for-in-depth-analytics-by-snoopreport-service-c9c2007f1bf6?source=collection_archive---------7-----------------------

Snoopreport 是一个监控平台,监控 Instagram 上的用户活动,如喜欢、评论和关注。

该服务有一个用户友好的仪表盘,你可以添加无限数量的 Instagram 账户进行监控。用户操作在每周和每月的 PDF 报告中提供。要了解 PDF 报告的更多信息,请点击此处。

您还可以按时间顺序下载所有用户操作和 CSV 格式的附加帖子数据,以便进行深入分析。

CSV 报告示例:

CSV 报告中提供的数据

该报告提供您监控的用户的赞、评论和关注,以及获得赞和评论的帖子的相关数据(帖子描述、帖子 URL、地理标签和一些其他指标)。

CSV 报告中显示的数据:

  1. 日期—受监控用户执行操作的日期和时间。你可以确定用户在 Instagram 上最活跃的时间间隔
  2. 类型—操作的类型:喜欢、评论或关注
  3. 用户名—获得赞、评论或关注的用户的用户名
  4. 全名—通常是获得赞、评论或关注的用户的名和姓

5.帖子 URL —链接到 Instagram 帖子,带有赞或评论

6.媒体 URL —指向媒体文件的链接。通过这个链接,你只能得到图片(视频也是以图片形式打开的)

7.直接媒体 url —指向您可以直接下载的媒体文件(照片或视频)的直接链接。该数据可用于图像识别,以自动方式确定介质上的物体或人

8.标题——对罐子的描述,包括文字、标签和用户名。使用此字段确定标记的用户或品牌。例如,如果您想知道用户喜欢的品牌,解析该字段以自动获得品牌列表。字幕也可以通过自然语言处理进行分析,以识别作为文本提及的情感、品牌、地理位置和事件。

9.位置名称-文本格式的地理标记。如果用户没有添加位置,则该字段为空

10.位置地址-地址格式的地理标记

11.位置 URL——在谷歌地图上将地理标记为坐标

12.Likeback —显示用户是否在他喜欢的帖子上被标记的指标。用它从简单提到用户的内容中突出用户真正的兴趣。

首先,营销人员和分析师会对 CSV 报告感兴趣。要了解 Snoopreport professional 用于分析的更多信息,请阅读我们的文章。

为了获得更有价值的用户洞察,如果您监控多个用户,我们还提供群组报告。您可以在单个 CSV 报告中下载添加到仪表板中的任意数量用户的活动数据,并分析这组用户的行为。组报告看起来像单个用户的报告,但是添加了 Username_Monitored 列。它有执行某个动作的 Instagram 用户。

我们将在未来的报告中添加新的指标,如品牌、博客或个人用户标志等。关注更新https://snoopreport.com!

在 Ubuntu 16.04 上逐步安装 Hadoop 3.1.0 多节点集群

原文:https://towardsdatascience.com/installing-hadoop-3-1-0-multi-node-cluster-on-ubuntu-16-04-step-by-step-8d1954b31505?source=collection_archive---------2-----------------------

Image Source: www.mapr.com/products/apache-hadoop/

网上有很多关于安装 Hadoop 3 的链接。他们中的许多人工作不好或需要改进。这篇文章摘自官方文件和其他文章以及 Stackoverflow.com 的许多回答

1.先决条件

注意:所有先决条件必须应用于名称节点和数据节点

1.1.安装 JAVA、SSH 和其他软件实用程序

首先,我们需要为 Java 8 安装 SSH 和一些软件安装实用程序:

sudo apt install \openssh-server \software-properties-common \python-software-properties

然后我们需要安装 Oracle 的 Java 8 发行版,并更新当前的 OS。

sudo add-apt-repository ppa:webupd8team/javasudo apt updatesudo apt install oracle-java8-installer

要验证 java 版本,您可以使用以下命令:

java -version

1.2.为 Hadoop 创建专门的用户和组

我们将使用专用的 Hadoop 用户帐户来运行 Hadoop 应用程序。虽然这不是必需的,但建议这样做,因为它有助于将 Hadoop 安装与同一台机器上运行的其他软件应用程序和用户帐户(安全、权限、备份等)分开。

sudo addgroup hadoopgroupsudo adduser --ingroup hadoopgroup hadoopusersudo adduser hadoopuser sudo

您可以使用以下命令检查组和用户:

compgen -gcompgen -u

1.3.SSH 配置

Hadoop 需要 SSH 访问来管理其不同的节点,即远程机器加上您的本地机器。

首先,您需要以 Hadoopuser 的身份登录

sudo su -- hadoopuser

以下命令用于使用 SSH 生成一个键值对

ssh-keygen -t rsa -P “” -f ~/.ssh/id_rsa

将 id_rsa.pub 中的公钥复制到 authorized_keys 中。

cat ~/.ssh/id_rsa.pub>> ~/.ssh/authorized_keyschmod 0600 ~/.ssh/authorized_keys

确保 hadoopuser 可以 ssh 到自己的帐户,无需密码。从 hadoopuser 帐户 ssh 到 localhost,以确保它工作正常。

ssh localhost

注意:如果你得到错误:ssh:连接到主机本地主机端口 22:连接被拒绝,那么,请尝试使用下面的命令安装 ssh-server。

sudo apt-get install ssh

2.下载并配置 Hadoop

在本文中,我们将在三台机器上安装 Hadoop:

第一台机器将充当名称节点(主节点)和数据节点(从节点),其他机器是数据节点(从节点)

在每台机器上,我们必须使用以下命令编辑/etc/hosts 文件

sudo gedit /etc/hosts

每个文件必须包含这些行:

127.0.0.1 localhost10.0.1.1 hadoop-namenode10.0.1.2 hadoop-datanode-210.0.1.3 hadoop-datadnode-3

注意:如果/etc/hosts 文件包含下面一行

127.0.1.1 <Hostname>

然后你要删除这一行。

2.1.下载 Hadoop

我们将把所有软件安装在/opt 目录下,并将 HDFS 的底层数据也存储在那里。下面我们将用一个命令创建文件夹。

sudo mkdir -p /opt/{hadoop/{logs},hdfs/{datanode,namenode},yarn/{logs}

文件夹的布局将如下所示

/opt/├── hadoop│ ├── logs├── hdfs│ ├── datanode│ └── namenode├── yarn│ ├── logs

您可以使用以下命令下载 hadoop-3.1.0.tar.gz:

wget -c -O hadoop.tar.gz [http://www-eu.apache.org/dist/hadoop/common/hadoop-3.1.0/hadoop-3.1.0.tar.gz](http://www-eu.apache.org/dist/hadoop/common/hadoop-3.1.0/hadoop-3.1.0.tar.gz)

要解压缩 Hadoop 包,您可以使用以下命令:

sudo tar -xvf hadoop.tar.gz \ --directory=/opt/hadoop \--strip 1

Hadoop 3 的二进制版本压缩了 293 MB。它的解压缩大小为 733 MB,其中有 400 MB 的小文档文件,解压缩可能需要很长时间。您可以通过在上面的命令中添加以下行来跳过这些文件:

--exclude=hadoop-3.1.0/share/doc

2.2.Hadoop 常见配置

注意:这些步骤必须在名称节点和数据节点上完成。

有一些环境设置将被 Hadoop、Hive 和 Spark 使用,并由 root 和普通用户帐户共享。为了集中这些设置,我将它们存储在/etc/profile 中,并从/root/创建了一个符号链接。bashrc 到这个文件。这样,所有用户都将拥有集中管理的设置。

sudo gedit /etc/profile

/etc/profile 必须类似于:

if [ “$PS1” ]; thenif [ “$BASH” ] && [ “$BASH” != “/bin/sh” ]; then# The file bash.bashrc already sets the default PS1.# PS1=’\h:\w\$ ‘if [ -f /etc/bash.bashrc ]; then. /etc/bash.bashrcfielseif [ “`id -u`” -eq 0 ]; thenPS1=’# ‘elsePS1=’$ ‘fififiif [ -d /etc/profile.d ]; thenfor i in /etc/profile.d/*.sh; doif [ -r $i ]; then. $ifidoneunset ifiexport HADOOP_HOME=/opt/hadoopexport PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbinexport HADOOP_CONF_DIR=/opt/hadoop/etc/hadoopexport HDFS_NAMENODE_USER=rootexport HDFS_DATANODE_USER=rootexport HDFS_SECONDARYNAMENODE_USER=rootexport JAVA_HOME=/usr/lib/jvm/java-8-oracleexport HADOOP_MAPRED_HOME=/opt/hadoopexport HADOOP_COMMON_HOME=/opt/hadoopexport HADOOP_HDFS_HOME=/opt/hadoopexport YARN_HOME=/opt/hadoop

以下命令将在~/之间创建一个符号链接。bashrc 和/etc/profile,并应用对/etc/profile 所做的更改

sudo ln -sf /etc/profile /root/.bashrcsource /etc/profile

更新/opt/HADOOP/etc/HADOOP/HADOOP-env . sh 文件并设置 JAVA_HOME 变量和 HADOOP_HOME、HADOOP _ CONF _ 目录和 HADOOP _ LOG _ 目录变量

export JAVA_HOME=/usr/lib/jvm/java-8-oracleexport HADOOP_HOME=/opt/hadoopexport HADOOP_CONF_DIR=/opt/hadoop /etc/hadoopexport HADOOP_LOG_DIR=/opt/hadoop/logs

注销并重新登录到您的 hadoopuser 帐户,并使用以下命令检查 Hadoop 安装。

hadoop -version

2.3.主节点配置

首先,我们必须更新位于/opt/Hadoop/etc/Hadoop/的 hdfs-site.xml 文件,以定义这台机器上的名称节点和数据节点,并定义复制因子和其他设置:

sudo gedit /opt/hadoop/etc/hadoop/hdfs-site.xml

该文件必须类似于:

<configuration><property><name>dfs.namenode.name.dir</name><value>file:///opt/hdfs/namenode</value><description>NameNode directory for namespace and transaction logs storage.</description></property><property><name>dfs.datanode.data.dir</name><value>file:///opt/hdfs/datanode</value><description>DataNode directory</description></property><property><name>dfs.replication</name><value>3</value></property><property><name>dfs.permissions</name><value>false</value></property><property><name>dfs.datanode.use.datanode.hostname</name><value>false</value></property><property><name>dfs.namenode.datanode.registration.ip-hostname-check</name><value>false</value></property></configuration>

然后,我们必须更新位于/opt/hadoop/etc/hadoop 的 core-site.xml 文件,并让 hadoop 发行版知道名称节点的位置:

sudo gedit /opt/hadoop/etc/hadoop/core-site.xml

该文件必须类似于:

<configuration><property><name>fs.defaultFS</name><value>hdfs://hadoop-namenode:9820/</value><description>NameNode URI</description></property><property><name>io.file.buffer.size</name><value>131072</value><description>Buffer size</description></property></configuration>

然后我们必须更新位于/opt/hadoop/etc/hadoop/的 yarn-site.xml 文件

sudo gedit /opt/hadoop/etc/hadoop/yarn-site.xml

该文件必须类似于:

<configuration><property><name>yarn.nodemanager.aux-services</name><value>mapreduce_shuffle</value><description>Yarn Node Manager Aux Service</description></property><property><name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name><value>org.apache.hadoop.mapred.ShuffleHandler</value></property><property><name>yarn.nodemanager.local-dirs</name><value>file:///opt/yarn/local</value></property><property><name>yarn.nodemanager.log-dirs</name><value>file:///opt/yarn/logs</value></property></configuration>

然后我们必须更新位于/opt/hadoop/etc/hadoop/的 mapred-site.xml 文件

<configuration><property><name>mapreduce.framework.name</name><value>yarn</value><description>MapReduce framework name</description></property><property><name>mapreduce.jobhistory.address</name><value>hadoop-namenode:10020</value><description>Default port is 10020.</description></property><property><name>mapreduce.jobhistory.webapp.address</name><value> hadoop-namenode:19888</value><description>Default port is 19888.</description></property><property><name>mapreduce.jobhistory.intermediate-done-dir</name><value>/mr-history/tmp</value><description>Directory where history files are written by MapReduce jobs.</description></property><property><name>mapreduce.jobhistory.done-dir</name><value>/mr-history/done</value><description>Directory where history files are managed by the MR JobHistory Server.</description></property></configuration>

现在我们必须格式化名称节点

hdfs namenode –format

最后,我们必须将您的数据节点(Slaves)添加到位于/opt/hadoop/etc/hadoop 的 workers 文件中

10.0.1.110.0.1.210.0.1.3

配置数据节点后,您必须确保名称节点可以无密码访问它们:

ssh-copy-id -i /home/hadoopuser/.ssh/id_rsa.pub hadoopuser@10.0.1.2ssh-copy-id -i /home/hadoopuser/.ssh/id_rsa.pub hadoopuser@10.0.1.3

2.4.配置数据节点

注意:您可以将 Hadoop.tar.gz 文件从名称节点复制到数据节点并提取,而不是下载 Hadoop。你可以使用下面的命令:

scp hadoop.tar.gz hadoop-datanode-2:/home/hadoopuserscp hadoop.tar.gz hadoop-datanode-3:/home/hadoopuser

在每个数据节点上,您必须执行以下步骤:

我们必须更新位于/opt/hadoop/etc/hadoop 目录下的 hdfs-site.xml、core-site.xml、yarn-site.xml 和 mapred-site.xml,如下所示:

hdfs-site.xml

<configuration><property><name>dfs.datanode.data.dir</name><value>file:///opt/hdfs/datanode</value><description>DataNode directory</description></property><property><name>dfs.replication</name><value>3</value></property><property><name>dfs.permissions</name><value>false</value></property><property><name>dfs.datanode.use.datanode.hostname</name><value>false</value></property></configuration>

core-site.xml

<configuration><property><name>fs.defaultFS</name><value>hdfs://hadoop-namenode:9820/</value><description>NameNode URI</description></property></configuration>

yarn-site.xml

<configuration><property><name>yarn.nodemanager.aux-services</name><value>mapreduce_shuffle</value><description>Yarn Node Manager Aux Service</description></property></configuration>

mapred-site.xml

<configuration><property><name>mapreduce.framework.name</name><value>yarn</value><description>MapReduce framework name</description></property></configuration>

2.5.启动 Hadoop

完成上述步骤后,我们必须从名称节点执行以下命令来启动名称节点、数据节点和辅助名称节点:

start-dfs.sh

它将给出以下输出:

Starting namenodes on [hadoop-namenode]Starting datanodesStarting secondary namenodes [hadoop-namenode]

此外,要启动资源管理器和节点管理器,我们必须执行以下命令:

start-yarn.sh

它将给出以下输出:

Starting resourcemanagerStarting nodemanagers

之后,为了确保 Hadoop 成功启动,我们必须在 name node 上运行 jps 命令,data nodes 必须给出以下输出:

在名称节点上(忽略进程 id):

16488 NameNode16622 DataNode17215 NodeManager17087 ResourceManager17530 Jps16829 SecondaryNameNode

在数据节点上(忽略进程 id):

2306 DataNode2479 NodeManager2581 Jps

如果您得到类似的输出,那么所有的 Hadoop 守护进程都会成功启动。

注意:您可以通过运行 hdfs dfsadmin -report 命令(它必须返回 Live datanodes (3)) ,在/opt/hadoop/logs 下检查日志并检查是否一切正常。

2.6.在浏览器上访问 Hadoop

Namenode

访问以下网址:https://Hadoop-NameNode:9870/

资源经理

访问以下 URL:https://Hadoop-NameNode:8088/

3.参考

  • [1] F. Houbart,“如何安装和设置 hadoop 集群”,Linode,2017 年 10 月 16 日。【在线】。可用:https://www . Li node . com/docs/databases/Hadoop/how-to-install-and-set-up-Hadoop-cluster。【2018 年 7 月 20 日获取】。
  • [2]“栈溢出问答”,栈溢出,[在线]。可用:https://www.Stackoverflow.com。
  • [3]“Apache Hadoop 文档”,Apache,[在线]。可用:https://www.hadoop.apache.org。【访问时间 2018 年 01 月 07 日】。
  • [4] G. Bansal,“在 Ubuntu 上安装 Hadoop 3.0.0 多节点集群”,2017 年 8 月 31 日。【在线】。可用:http://www . gaur av 3 ansal . blogspot . com/2017/08/installing-Hadoop-300-alpha-4-multi . html【访问时间 16 07 2018】。
  • [5] M. Litwintschik,“Hadoop 3 单节点安装指南”,2018 年 3 月 19 日。【在线】。可用:http://www . tech . marksblogg . com/Hadoop-3-single-node-install-guide . html【2018 年 10 月 06 日访问】。

在 Windows 10 中安装基于 Python 的机器学习环境

原文:https://towardsdatascience.com/installing-keras-tensorflow-using-anaconda-for-machine-learning-44ab28ff39cb?source=collection_archive---------0-----------------------

机器学习入门指南

Photo by Ahmad Dirini on Unsplash

目的:为机器学习安装一个基于 Python 的环境。

The following set of instructions were compiled from across the web and written for a Windows 10 OS. Last tested on 02/09/2019.

概观

当我第一次进入机器学习领域时,我花了几个小时来思考如何正确设置我的 Python 环境。出于沮丧,我决定写这篇文章来帮助任何经历这个过程的人。我们将从安装 Anaconda Navigator 开始,这将允许我们创建独立的环境,这将非常方便。此外,使用 Anaconda,我们可以用非常简单的命令轻松安装兼容的 Python 模块。最后,我们可以使用 Anaconda 获得 Spyder——一个科学的 Python 开发环境。如果您按照下面显示的步骤操作,您将很快安装好 Tensorflow、Keras 和 Scikit-learn。

得到蟒蛇

为了开始用 Python 构建您的机器学习(ML)模型,我们将从安装 Anaconda Navigator 开始。Anaconda 提供了一种在您的机器上安装 Python 模块的高效而简单的方法。所以让我们开始吧。

  1. 下载并为你的操作系统安装最新版本的 Anaconda Navigator。

2.继续安装向导,但是跳过需要下载和安装 VS 的步骤,我们将在后面完成。此外,确保为单个用户安装 Anaconda Navigator 为所有用户安装 Anaconda 可能会导致问题。例如,您将无法安装任何模块,因为 Anaconda 没有必要的特权。

Make sure you install Anaconda to the current user else you might face problems down the road.

Skip this step. We will get it done in a bit.

3.启动 Anaconda Navigator 并选择 Home 选项卡,它应该是默认选中的。找到 VS 代码面板,点击安装按钮。这需要一两分钟。

After you install VS Code, you will be able to see a Launch button under the VS Code panel.

安装 Keras 和 Tensorflow

现在我们已经安装了 Anaconda,让我们在机器中安装 Keras 和 Tensorflow。

4.关闭 Anaconda Navigator 并启动 Anaconda 提示符。通过在 windows 搜索栏中搜索来启动 Anaconda 提示符。下面的终端应该打开。注意,这将在 base Anaconda 环境中打开。

5.将 Python 降级为Keras&tensor flow兼容版本。Anaconda 将开始寻找 Python 3.6 的所有兼容模块。这可能需要几分钟时间。要降级到 Python 3.6,请使用以下命令:

conda install python=3.6

After the environment is resolved, Anaconda will show you all the packages that will be downloaded. Currently, Tensorflow offers compatiblity with Python 3.5–3.8.

6.创建一个新的 conda 环境,我们将在其中安装我们的模块,以使用 GPU 构建我们的模型。为此,请执行以下命令:

conda create --name PythonGPU

注意:确保你有一个 NVIDIA 显卡。如果没有,安装 Keras 的 CPU 版本。

如果您想使用您的 CPU,请执行以下命令:

conda create --name PythonCPU

按照终端上显示的说明进行操作。Conda 环境允许用户自由安装非常特殊的独立模块。我个人创造了两个环境。一个是我可以使用 CPU 构建我的模型,另一个是我可以使用 GPU 构建我的模型。关于康达环境的更多信息,我建议你看一下官方文档。

7.要激活刚刚创建的 conda 环境,请使用:

activate PythonGPUactivate PythonCPU

要停用环境,请使用:

conda deactivate

不要停用环境,我们将安装所有好的东西。

8.要安装 Keras & Tensorflow GPU 版本,即使用我们的 GPU 创建模型所必需的模块,请执行以下命令:

conda install -c anaconda keras-gpu

如果您想使用您的 CPU 来构建模型,请改为执行以下命令:

conda install -c anaconda keras

许多计算机的东西将开始发生。一旦疯狂停止,我们可以继续前进。先不要关闭任何东西。

为机器学习/深度学习获取 Spyder 和其他 Python 包

现在,您可能需要一些软件来编写和执行您的 Python 脚本。您可以随时使用 Vim 来编写和编辑您的 Python 脚本,并打开另一个终端来执行它们。然而,你将错过 Spyder 提供的所有酷功能。

9.安装 Spyder。

conda install spyder

10.安装熊猫。Pandas 是一个非常强大的库,允许您轻松地读取、操作和可视化数据。

conda install -c anaconda pandas

如果您想用 Pandas 读取 Excel 文件,请执行以下命令:

conda install -c anaconda xlrd

conda install -c anaconda xlwt

11.安装 Seaborn 库。Seaborn 是一个令人惊叹的库,可以让您轻松地可视化您的数据。

conda install -c anaconda seaborn

12.安装 scikit-learn。

conda install -c anaconda scikit-learn

13.安装枕头来处理图像

conda install pillow

添加缺少的模块

现在,您应该对使用 conda 命令安装模块感到满意了。如果你需要一个特定的模块,只需在谷歌上搜索如下内容:

Anaconda LibraryNameYouWant Install

如果你遇到任何问题,搜索网页。很可能你不是第一个遇到给定错误的人。

启动 Spyder 并检查所有模块是否安装正确

要启动 Spyder,首先激活您想要的 conda 环境(PythonCPU 或 PythonGPU)并执行以下命令:

spyder

为了确保一切安装正确,在 python 控制台上执行以下代码行:

import numpy as np # For numerical fast numerical calculations
import matplotlib.pyplot as plt # For making plots
import pandas as pd # Deals with data
import seaborn as sns # Makes beautiful plots
from sklearn.preprocessing import StandardScaler # Testing sklearn
import tensorflow # Imports tensorflow
import keras # Imports keras

如果您没有看到 ModuleImport 错误,您现在可以开始使用 Keras、Tensorflow 和 Scikit-Learn 构建基于机器学习的模型了。

你可以在 LinkedIn 找到我,或者访问我的个人博客。

[## 弗兰克·塞瓦洛斯

图表

www.frank-ceballos.com](https://www.frank-ceballos.com/) [## Frank Ceballos -威斯康星医学院博士后| LinkedIn

我是威斯康星医学院的博士后研究员,在那里我分析高维复杂的临床数据…

www.linkedin.com](https://www.linkedin.com/in/frank-ceballos/)

在树莓 Pi 3 模型 B+上安装 OpenCV 3.4.3

原文:https://towardsdatascience.com/installing-opencv-3-4-3-on-raspberry-pi-3-model-b-e9af08a9f1d9?source=collection_archive---------7-----------------------

我之前写了一个分步指南,展示如何让 OpenCV 3.4.1 在一个 Raspberry Pi 3 B 上运行。从那时起,我已经完成了一些安装,所以这里有一个新的、简化的过程来获得 OpenCV 3.4.1(最新版本!)在您的 Raspberry Pi 3 B plus 上运行。

为什么是 3.4.1?它提供了一个改进的 DNN 模块和许多其他改进和错误修复。总的来说,自从 OpenCV 3.4.0 以来,已经集成了大约 250 个补丁,关闭了 200 多个问题。

警告:编译 OpenCV 是一项 CPU 密集型任务——所有 4 个内核都将因 1 个内核而达到极限..两个小时。为了避免过热,确保你的树莓派有散热器和风扇(或者在旁边放一个强大的外部风扇)。不,它不会因过热而死亡,但它会抑制其 CPU 性能,潜在地将构建时间从 2 小时增加到 6 小时,您可能不希望这样。

这是新的流程:

第一步:确保你的操作系统是最新的。(<5 分钟)

当前 OS 版本为Raspbian Stretch(2018 年 4 月)。您可以从 SD 进行全新安装(遵循此处列出的说明),或者升级您现有的版本。

要升级,请在您最喜欢的编辑器中打开(以 sudo 身份)文件 /etc/apt/sources.list/etc/apt/sources . list . d/raspi . list,并将当前发行版名称(如“jessie”)的所有出现处更改为“stretch”。然后,打开终端并运行更新:

sudo apt-get update 
sudo apt-get -y dist-upgrade

如果您已经在运行 Stretch,只需在继续之前更新所有软件包:

sudo apt-get update 
sudo apt-get upgrade

第二步:配置 SSH 和实用程序(<2 分钟)

确保 SSH 已启用。也更改默认密码!

我在 Linux 上最喜欢的一些实用程序是 screen (如果您的终端会话丢失,保持进程运行)和 htop (性能监控)——这些可能已经预装了:

sudo apt-get install screen 
sudo apt-get install htop

第三步:放弃 Wolfram 和 Libreoffice,释放 1GB+(2 分钟)

您的计算机视觉系统不太可能需要这两个软件包,因此:

sudo apt-get purge wolfram-engine 
sudo apt-get purge libreoffice* 
sudo apt-get clean 
sudo apt-get autoremove

第四步:安装依赖关系(<10 分钟)

sudo apt-get install build-essential cmake pkg-config sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt-get install libxvidcore-dev libx264-dev sudo apt-get install libgtk2.0-dev libgtk-3-dev sudo apt-get install libatlas-base-dev gfortran

第五步:安装 Python 3(<2 分钟)

为了在 Open CV 中启用 Python 绑定,我们需要这样做:

在 OpenCV 中,所有算法都是用 C++实现的。但是这些算法可以在不同的语言中使用,如 Python、Java 等。这是由绑定生成器实现的。这些生成器在 C++和 Python 之间架起了一座桥梁,使用户能够从 Python 中调用 C++函数。要全面了解后台发生的事情,需要对 Python/C API 有很好的了解。关于将 C++函数扩展到 Python 的一个简单例子可以在官方 Python 文档中找到[1]。因此,通过手动编写包装函数将 OpenCV 中的所有函数扩展到 Python 是一项耗时的任务。所以 OpenCV 以一种更智能的方式来做这件事。OpenCV 使用位于 modules/python/src2 中的一些 Python 脚本从 C++头文件自动生成这些包装函数

sudo apt-get install python3-dev

第六步:安装 pip 3(<2 分钟)

sudo apt-get install python3-pip

第七步:获取最新的(3.4.3) OpenCV 源代码 ( < 5min)

我使用的是 OpenCV 的 3.4.3 版本。你可以查看官方网站(或 Github)的版本部分,看看当前的版本是什么。如果您想要的版本不同,请相应地更新下面的命令和路径。

下载并解压 OpenCV 3.4.3 及其实验模块(存储在 opencv_contrib 库):

wget -O opencv.zip [https://github.com/opencv/opencv/archive/3.4.3.zip](https://github.com/opencv/opencv/archive/3.4.3.zip) wget -O opencv_contrib.zip [https://github.com/opencv/opencv_contrib/archive/3.4.3.zip](https://github.com/opencv/opencv_contrib/archive/3.4.3.zip) unzip opencv.zip unzip opencv_contrib.zip

步骤 8:安装 Numpy,Scipy(❤️ 分钟)

sudo pip3 install numpy scipy

第九步:编译 OpenCV(<10 分钟)

注意:这一步需要很长时间。在我的设备上花了将近 2 个小时。此外,如果没有适当的冷却,您的覆盆子酱会过热。

同样,我使用的是 OpenCV 的 3.4.3 版本。如果不是,请相应地更新您的路径:

cd ~/opencv-3.4.3/ 
mkdir build 
cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ 
    -D CMAKE_INSTALL_PREFIX=/usr/local \ 
    -D INSTALL_PYTHON_EXAMPLES=ON \ 
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.4.3/modules \ 
    -D BUILD_EXAMPLES=ON ..

请确保 cmake 完成时没有错误。

第十步:构建 OpenCV(90-120 分钟)

如果您使用全部四个 CPU 核心,这将运行得更快:

make -j4

一旦 OpenCV 构建成功,继续安装:

sudo make install 
sudo ldconfig 
sudo apt-get update

…然后重新启动系统,您就可以开始了!

sudo reboot

步骤 11:测试你的 OpenCV 安装(<1 分钟)

$ python3 Python 3.5.3 (default, September 5 2018, 14:11:04) 
[GCC 6.3.0 20170124] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import cv2 
>>> cv2.__version__ 
'3.4.3' 
>>>

欢迎评论和建议!

原载于 2018 年 9 月 5 日www.alatortsev.com

在树莓 Pi 3 B 上安装 OpenCV

原文:https://towardsdatascience.com/installing-opencv-on-raspberry-pi-3-b-46ab17a9fc5a?source=collection_archive---------6-----------------------

我用的是 B 版本,在亚马逊购买,规格如下:

  • 1.2GHz 64 位四核 ARMv8 CPU,1 GB 内存
  • 802.11n 无线局域网,10/100Mbps 局域网速度
  • 蓝牙 4.1,蓝牙低能耗
  • 4 个 USB 端口、40 个 GPIO 引脚、全 HDMI 端口、组合 3.5 毫米音频插孔和复合视频
  • 相机接口(CSI)、显示器接口(DSI)、Micro SD 卡插槽(现在是推拉式而不是推推式)、VideoCore IV 3D 图形核心

现在有一个的更新版本(“b+”),它应该以同样的方式工作,但一些步骤(如编译 OpenCV,在我的设备上花了近 2 个小时)应该更快。

此外,正如所料,编译 OpenCV 使无风扇 CPU 过热 30 分钟——所以我不得不在它旁边放置一个强大的风扇,直到我收到一个有适当冷却的案例。

第一步:确保你有最新版本的操作系统

当前 OS 版本为Raspbian Stretch(2018 年 4 月)。您可以从 SD 进行全新安装(遵循此处列出的说明),或者升级您现有的版本。

要升级,请在您最喜欢的编辑器中打开(以 sudo 身份)文件 /etc/apt/sources.list/etc/apt/sources . list . d/raspi . list,并将当前发行版名称(如“jessie”)的所有出现处更改为“stretch”。然后,打开终端并运行更新:

sudo apt-get update 
sudo apt-get -y dist-upgrade

步骤 2:配置 SSH 和实用程序

确保 SSH 已启用。也更改默认密码!

我在 Linux 上最喜欢的一些实用程序是 screen (如果你的终端会话丢失,保持进程运行)和 htop (性能监控)——这些可能已经预装了:

sudo apt-get install screen 
sudo apt-get install htop

第三步:放弃 Wolfram 和 Libreoffice,释放 1GB+

您的计算机视觉系统不太可能需要这两个软件包,因此:

sudo apt-get purge wolfram-engine 
sudo apt-get purge libreoffice* 
sudo apt-get clean sudo apt-get autoremove

第四步:安装依赖关系

sudo apt-get install build-essential cmake pkg-config sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt-get install libxvidcore-dev libx264-dev sudo apt-get install libgtk2.0-dev libgtk-3-dev sudo apt-get install libatlas-base-dev gfortran

第五步:安装 Python 2.7 & 3

为了在 Open CV 中启用 Python 绑定,我们需要这样做:

在 OpenCV 中,所有算法都是用 C++实现的。但是这些算法可以在不同的语言中使用,如 Python、Java 等。这是由绑定生成器实现的。这些生成器在 C++和 Python 之间架起了一座桥梁,使用户能够从 Python 中调用 C++函数。要全面了解后台发生的事情,需要对 Python/C API 有很好的了解。关于将 C++函数扩展到 Python 的一个简单例子可以在官方 Python 文档中找到[1]。因此,通过手动编写包装函数将 OpenCV 中的所有函数扩展到 Python 是一项耗时的任务。所以 OpenCV 以一种更智能的方式来做这件事。OpenCV 使用位于 modules/python/src2 中的一些 Python 脚本从 C++头文件自动生成这些包装函数

sudo apt-get install python2.7-dev 
sudo apt-get install python3-dev

第六步:获取最新的 OpenCV 源代码

我使用的是 OpenCV 的 3.4.1 版本。你可以查看官方网站(或者 Github)的版本部分,看看当前的版本是什么。如果您想要的版本不同,请相应地更新下面的命令和路径。

下载并解压 OpenCV 3.4.1 及其实验模块(存储在 opencv_contrib 库):

wget -O opencv.zip [https://github.com/opencv/opencv/archive/3.4.1.zip](https://github.com/opencv/opencv/archive/3.4.1.zip) wget -O opencv_contrib.zip [https://github.com/opencv/opencv_contrib/archive/3.4.1.zip](https://github.com/opencv/opencv_contrib/archive/3.4.1.zip) unzip opencv.zip unzip opencv_contrib.zip

第七步:安装 pip 和 virtualenv

这些是管理 Python 包的最底层工具。

首先获取 pip:

wget -O get-pip.py [https://bootstrap.pypa.io/get-pip.py](https://bootstrap.pypa.io/get-pip.py) 
sudo python get-pip.py 
sudo python3 get-pip.py

来源:https://pip.pypa.io/en/stable/installing/

然后,安装虚拟环境:

sudo pip install virtualenv virtualenvwrapper

修改你的 ~/。配置文件包括以下行:

导出 WORKONHOME=$HOME/。virtualenvs 导出 VIRTUALENVWRAPPERPYTHON =/usr/bin/python 3

source/usr/local/bin/virtualenvwrapper . sh

这是我的文件的样子:

# ~/.profile: executed by the command interpreter for login shells. # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login # exists. 
# see /usr/share/doc/bash/examples/startup-files for examples. 
# the files are located in the bash-doc package. # the default umask is set in /etc/profile; for setting the umask 
# for ssh logins, install and configure the libpam-umask package. #umask 022 # if running bash 
if [ -n "$BASH_VERSION" ]; then 
    # include .bashrc if it exists 
    if [ -f "$HOME/.bashrc" ]; then 
        . "$HOME/.bashrc" 
    fi 
fi # set PATH so it includes user's private bin if it exists 
if [ -d "$HOME/bin" ] ; then 
     PATH="$HOME/bin:$PATH" 
fi # virtualenv and virtualenvwrapper settings 
export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 source /usr/local/bin/virtualenvwrapper.sh

…激活更改:

source ~/.profile

第八步:创建一个虚拟环境

mkvirtualenv cv -p python3

…或者,如果您想使用 Python 2.7 而不是 Python 3:

mkvirtualenv cv -p python2

以下是使用 virtualenvwarapper 的基本命令:

mkvirtualenv virtualenv_name # create virtualenv workon virtualenv_name # activate/switch to a virtualenv deactivate virtualenv_name # deactivate virtualenv

在我们的例子中,我们可以激活一个名为“cv”的 virtualenv:

pi@raspberrypi:~ $ workon cv 
(cv) pi@raspberrypi:~ $

第九步:安装 Numpy,Scipy

现在您已经进入了虚拟环境(如终端窗口中的“(cv)”前缀所示),让我们安装一些用于数据分析的附加包— numpyscipy :

sudo pip install numpy scipy

第十步:最后,安装 OpenCV

注意:这将需要很长、很长、很长的时间。在我的设备上花了将近 2 个小时。此外,如果没有适当的冷却,您的覆盆子酱会过热。

同样,我使用的是 OpenCV 的 3.4.1 版本。如果不是,请相应地更新您的路径:

cd ~/opencv-3.4.1/ mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D INSTALL_PYTHON_EXAMPLES=ON \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.4.1/modules \ -D BUILD_EXAMPLES=ON ..

请确保 cmake 完成时没有错误。

现在,给自己拿杯啤酒,准备最后一步——编译。为了加快速度,暂时增加您的 /etc/dphys-swapfile 中的交换文件大小,将 CONF _ 交换大小从 100 改为 1024:

# set size to absolute value, leaving empty (default) then uses computed value 
# you most likely don't want this, unless you have an special disk situation 
#CONF_SWAPSIZE=100 
CONF_SWAPSIZE=1024

要避免重新启动以使这些更改生效,只需重新启动交换服务:

sudo /etc/init.d/dphys-swapfile restart

这里有一个关于如何用包编译 OpenCV 的详细指南:

https://github.com/opencv/opencv_contrib

我所做的(使用所有 4 个 CPU 内核):

make -j4

OpenCV 编译成功后,继续安装:

sudo make install 
sudo ldconfig 
sudo apt-get update

…然后重新启动系统,您就可以开始了!

还有一件事:

测试安装:

$ python3 
Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170124] on linux Type "help", "copyright", "credits" or "license" for more information. 
>>> import cv2 
>>> cv2.__version__ '3.4.1' 
>>>

如果出现错误(ImportError:没有名为“cv2”的模块),则库的命名可能不正确:

(cv) pi@raspberrypi:$ ls -l /usr/local/lib/python3.5/site-packages/ total 4500 -rw-r--r-- 1 root staff 4604912 Apr 27 14:41 cv2.cpython-35m-arm-linux-gnueabihf.so

通过将库文件重命名为“cv2.so”来修复它:

cd /usr/local/lib/python3.5/site-packages/ sudo mv cv2.cpython-35m-arm-linux-gnueabihf.so cv2.so

原载于 2018 年 4 月 27 日www.alatortsev.com

在 OSX 上安装 XGBoost

原文:https://towardsdatascience.com/installing-xgboost-on-osx-e17e77c00635?source=collection_archive---------1-----------------------

我们本周的项目是研究一个古老的卡格尔竞赛(https://www.kaggle.com/c/predict-west-nile-virus)。XGBoost 在过去的 kaggle 比赛中被许多获胜者使用,所以我们非常希望它能提高我们的成绩。虽然这并没有提高我们的成绩,但我确实在这个过程中学到了很多。

我找到的下载 XGBoost for Mac 的最好的文章是通过 IBM 网站(讽刺的是,不是?).甚至这篇文章也有很多地方需要进行故障诊断,所以我想介绍一下我遇到错误的地方,但这绝对是一个好的起点。如果 IBM 的文章对您有用,就不需要继续读下去了,但是如果没有,我希望我能回答您的一些问题。

[## 在 Mac OSX 上安装 XGBoost(最好保密的是优化)

OSX 比 Windows 好得多,不是吗?这是一个普遍的智慧,当我…

www.ibm.com](https://www.ibm.com/developerworks/community/blogs/jfp/entry/Installing_XGBoost_on_Mac_OSX?lang=en)

  1. 在你的终端上,如果你还没有安装家酿软件的话。"/usr/bin/ruby-e " $(curl-fsSLhttps://raw . githubusercontent . com/home brew/install/master/install)" "如果在这一步遇到错误,请参考本网站"https://computers . tuts plus . com/tutorials/home brew-demystified-OS-xs-ultimate-package-manager-MAC-44884"。
  2. 同样在终端中,您应该“brew install gcc—without-multi lib”,without multilib 应该有助于解决我们稍后可能会遇到的多线程错误。这可能需要一些时间,但是如果这不起作用,请尝试“sudo apt-get install gcc
    sudo apt-get install g++”
  3. cd 到你想放目录的任何地方,我简单地把我的放在我的根目录,但是确保这不是在另一个目录里!(我们不需要任何怀孕的回复)
  4. 使用这一行“git clone-recursivehttps://github.com/dmlc/xgboost”将存储库克隆到您希望您的目录所在的任何位置
  5. cd 放到名为 xgboost 的新目录中
  6. 打开 make/config.mk。如果您的计算机已正确格式化,只需键入“打开 make/config.mk”就可以了。如果没有,您可以使用 GUI 在您喜欢的文本编辑器或其他命令中打开它。取消对这两行代码的注释:“export CC = gcc
    export CXX = g++”。根据您安装的 gcc 版本,您可能需要将它们更改为“export CC = gcc-6
    export CXX = g++-6”。请确保保存此内容,然后继续下一步。
  7. cd 进入 xgboost(如果您还没有在那里),然后“cp make/config.mk。
    make -j4
  8. 最后一步:“CD python-package;sudo python setup.py 安装

要检查这是否成功,您可以打开一个 jupyter 笔记本或者在您的终端中键入“pip freeze ”,并确保 xgboost 有一个版本。如果你想在 jupyter 笔记本中使用它,你应该打开一个新的终端窗口,并启动一个新的内核。你可以通过“import xgboost”来检查这个过程是否成功,只要它不抛出错误,你就可以使用它。

如果这些步骤不起作用,请尝试“brew install gcc5”,然后将步骤 6 更改为“export CC = gcc-5
export CXX = g++-5”

如果最后一步不起作用,就用这三个代替:“sudo。/build . sh
CD python-package
sudo/home/username/anaconda/bin/python setup . py install "

令人沮丧的答案是,如果这不起作用,卸载并再次尝试稍微改变步骤,并尝试准确地遵循 IBM 的文章。

[## pip 安装失败问题#463 dmlc/xgboost

xgboost -可扩展、可移植和分布式梯度增强(GBDT、GBRT 或 GBM)库,用于 Python、R、Java、Scala…

github.com](https://github.com/dmlc/xgboost/issues/463#issuecomment-147365960)

实例嵌入:没有建议的分段

原文:https://towardsdatascience.com/instance-embedding-instance-segmentation-without-proposals-31946a7c53e1?source=collection_archive---------3-----------------------

在这篇文章中,我将回顾实例分割领域的 3 篇论文。它们不同于主流的基于提议的基于 fast-RCNN 的方法,如 Mask-RCNN 或 MaskLab 和最新的 PANet ,在多个数据集上实现了最先进的结果( CityScapes 、 COCO 、 MVD )。参见此处的 Mask-RCNN 教程。

在基于提议的实例分段架构中有三个基本缺陷。首先,两个对象可能共享同一个边界框,或者非常相似的框。在这种情况下,遮罩头部无法判断要在盒子中选取哪个对象。对于其边界框中填充率较低的线状对象(如自行车和椅子),这是一个严重的问题。其次,架构中没有任何东西阻止两个实例共享一个像素。第三,实例的数量受限于网络处理的提案数量(通常为数百)。

architecture for Mask-RCNN, https://www.slideshare.net/IldooKim/deep-object-detectors-1-20166

此外,该架构非常复杂,很难调整和“调试”。在目标检测中,这个问题的前兆,已经成功地使用了更简单的单级架构,例如 RetinaNet 。

使用实例嵌入,每个对象都被分配一个 n 维空间中的“颜色”。网络处理图像并产生与输入图像相同大小的密集输出。网络输出中的每个像素是嵌入空间中的一个点。属于同一对象的像素在嵌入空间中是靠近的,而属于不同对象的像素在嵌入空间中是远离的。解析图像嵌入空间涉及某种聚类算法。

论文 1:具有区别损失函数的语义实例分割

伯特·德·布拉班德雷,戴维·内文,吕克·范古尔https://arxiv.org/abs/1708.02551
https://github.com/DavyNeven/fastSceneUnderstanding

visualizing the contrastive loss.

损失。本文使用由三部分组成的对比损失函数:

(1)拉力。惩罚相同实例的所有元素与其平均值的距离。也就是说,获取一个实例的所有像素并计算它们的平均值。拉力会将同一实例的所有像素嵌入吸引到同一点。简而言之,减少每个实例嵌入的差异。

(2)一个推力。取所有的中心点(在嵌入空间中,而不是空间中心)并将它们推得更远。

(3)正规化。中心不应该离原点太远。

α和β的值为 1,γ设置为 0.001。两个增量都是拉力和推力的阈值。

解析。在获得语义分割图(汽车、狗、计算机……)之后,我们将每个类别掩码细分为实例。这是通过在语义掩码中选取一个随机未分配的点,并迭代应用均值漂移算法来找到实例的均值点来实现的。

均值的第一个假设是最初选取的随机像素的嵌入。然后,围绕该点(在嵌入空间中)扩展一组点,然后再次计算它们的平均值,并且重复该过程,直到平均值的变化不显著。根据我的经验,算法收敛不超过 10 次迭代。大多数时候 3-4 次迭代就足够了。

用于在嵌入空间中扩展实例遮罩的半径与拉取阈值相同。理论上,如果测试误差为 0,并且中心之间的最小距离至少是方差分量的拉阈值的两倍,则我们可以使用这些阈值来解析图像。距离不大于拉动阈值的所有点应属于同一个实例。因为测试误差几乎从不为 0,所以使用均值漂移算法来寻找嵌入的高密度部分的中心。

a nice visualization of this tracking process in a two dimensional embedding space where the mode of the set, the peak of the density, is finally found.

错误来源

这些结果显示了 Cityscapes 数据集上大多数错误的来源。如果语义分段没有被断定,而是使用了基础事实,则 AP50 结果从 40.2 跳到 58.5。如果也使用实际的中心,而不是使用均值漂移来估计,则得分几乎增加了 20 分,达到 77.8 分。使用面板(参见仪表板)在 COCO 上不进行预训练的当前技术水平结果是 57.1。与使用语义分段基本原理相同。我们了解到嵌入本身可能非常好。

嵌入示例

下面是一个由一个训练有素的网络嵌入生成的实例。它用于解决目前正在 Kaggle 上运行的数据科学碗 2018 提出的问题。目的是在医学图像中找到细胞核。

左上角的图像是原始图像。中上部图像是语义分割(这里只有两类,背景和前景)。其余的图像是 64 个嵌入空间的前 7 个通道。从嵌入可以明显看出,网络学习了在空间上区分细胞核的通道。对角线或水平编码的例子。一些编码从图像中心的距离。但是,在实例内部,颜色是同质的。这让我们对网络如何学习分割实例有了一些了解。

论文 2:通过深度度量学习的语义实例分割

阿里雷扎·法蒂,兹比格涅夫·沃伊纳,维韦克·拉特霍德,王鹏,玄武铉,塞尔吉奥·瓜达拉马,凯文·p·墨菲
【https://arxiv.org/abs/1703.10277

Network architecture proposed in Semantic Instance Segmentation via Deep Metric Learning

本文的主要贡献是为每个像素学习种子分数。分数告诉我们该像素是否是扩展遮罩的良好候选。在之前的论文中,种子是随机选择的,然后使用均值漂移算法来细化中心。这里只做了一次扩展。

seedeness score per pixel. taken as the maximum over all classes and bandwidths.

该论文提出为每个像素学习几个可能种子。我们为每个半径(在嵌入空间中)和类学习一个种子。因此,如果我们有 C 类,我们学习 T 带宽(半径),我们有 CxT 种子“建议”每像素。对于每个像素,只考虑得分最高的建议。

嵌入损失。本文对像素对的嵌入进行惩罚。我们考虑具有相同实例的对和来自不同实例的对。

a logistic distance function in embedding space

本文使用一种改进的逻辑函数,将嵌入空间中的欧氏距离变换到[0,1]域。嵌入空间中接近的对将被函数赋予接近 1 的值,而距离远的对将接近 0。

自然地,logloss 被用作损失函数。实例大小可能会有所不同,因此,为了减轻这种不平衡问题,根据实例的大小对它们进行加权。

logloss over logistic distance between pairs of pixels

落英。对于每个像素,模型学习几个种子性分数。带宽(嵌入空间的半径)和类别的每个组合得一分。由于种子分数接近但不同于语义分割,因此每次评估嵌入时都要确定每一个的基础事实。围绕像素的嵌入扩展掩码,并且如果具有基本事实实例的 IoU 超过某个阈值,则该像素被认为是该实例的类的种子。这个损失将会惩罚这个职业的低种子分数。

seediness loss

每批图像中只有 10 个左右的种子被评估,随机挑选。学习几个这样的模型,一个用于一个带宽。带宽越宽,物体越大。在某种程度上,获得最高分数的带宽是模型传达其对实例大小的估计的方式(相对于嵌入空间中的距离)。

训练程序。本文使用在 COCO 数据集上预处理的 ResNet-101 主干。训练从没有分类/种子预测开始,即λ=0,并且随着嵌入更加稳定而进展到 0.2。

以不同的比例(0.25,0.5,1,2)评估主链,并将连接的结果输入种子和包埋头。

解析。这个过程非常简单,因为种子学会了。提出了一种为图像选择最佳种子集的方法。它一方面优化了高种子分数,另一方面优化了嵌入空间的多样性。

迭代地选择种子,每个新的种子被选择为在嵌入空间中远离先前选择的种子。选择的第一个种子是图像中种子性得分最高的像素。第二个将是一方面具有高种子性分数,另一方面在嵌入空间中不接近的种子。使用参数α来控制这两个要求之间的平衡。α是一个需要调整的参数,该参数的测试范围在 0.1 到 0.6 之间。与 NMS 不同,嵌入空间的多样性受到鼓励,而不是空间多样性。

some results from Semantic Instance Segmentation via Deep Metric Learning

论文 3:用于实例分组的递归像素嵌入

舒孔,查尔斯·福尔克斯
https://arxiv.org/abs/1712.08273
https://github . com/aimerykong/Recurrent-Pixel-Embedding-for-Instance-Grouping

本文提出在 n-球面上进行嵌入,并使用余弦距离来测量像素的邻近性。然而,本文的主要贡献是基于高斯模糊均值漂移(GBMS)算法的改进版本的递归分组模型。

GBMS 是一种迭代算法,类似于第一篇论文中用于查找实例中心的简单均值漂移算法。在这个版本中,所有的像素都被认为是潜在的种子。所有像素在每次迭代时都相对于它们周围的密度进行更新。朝着一个“重心”移动,好像图像的嵌入空间是一个产生行星的星云。点与点之间的距离越远,它们之间的相互影响就越小。从下面的算法可以清楚地看出,距离是由高斯的带宽控制的,这是它的标准偏差。

对于 GBMS 来说,有三次收敛保证,所以在应用几次变换后,我们最终应该得到非常密集的,几乎像点一样的簇。想了解更多关于 GBMS 的信息,请看这里。

为了将该算法结合到网络中,已经使用矩阵上的运算来表示该算法。

简单地应用上述算法是没有意义的,因为嵌入是在球体上,并且它们的接近度是使用余弦变换来测量的。描述所有点之间距离的相似性矩阵使用以下变换来计算:

测量球体上的距离,而不是使用 L2 规范。此外,在应用 GBMS 步骤后,需要对生成的嵌入进行归一化,以便它们位于单位球面上。

训练。使用成对像素损失,类似于之前的论文,对不同对所需的距离设置阈值(alpha)。使用范围为[0,1]而不是[-1,-1]的校准余弦距离来评估每一对。

calibrated cosine distance

损失通过递归分组模型的每个应用反向传播。应用的后期阶段只会出现非常困难的情况。例如,作者将这一特性与在 fast-RCNN 训练中使用的硬负挖掘进行了比较。

loss used in Recurrent Pixel Embedding for Instance Grouping

作者在论文中使用 0.5 作为α值。请注意,实例的大小用于重新平衡大小实例之间的损失。

解析。在分组模块的几次应用之后,簇应该非常密集,随机选取值应该产生足够好的种子。

出于实际目的,在 GBMS 步骤中仅使用一些像素是有意义的,因为计算相似性矩阵可能被证明是极其昂贵的。所取的像素数量是速度/精度的折衷考虑。

其他方法

实例嵌入不是基于建议的网络的唯一替代方案。以下是一些使用其他方法解决实例分割问题的论文

  • 【https://arxiv.org/abs/1605.09410】端到端实例分割与递归关注

  • 深分水岭变换为例分割
    https://arxiv.org/abs/1611.08303

  • 关联嵌入:用于联合检测和分组的端到端学习
    http://ttic . uchicago . edu/~ mmaire/papers/pdf/affinity _ CNN _ cvpr 2016 . pdf

  • 序贯分组网络实例分割
    https://www . cs . Toronto . edu/~ urta sun/publications/Liu _ et al _ iccv 17 . pdf

摘要

与基于建议书的解决方案相比,这些论文的结果没有竞争力。我们已经回顾了 3 篇论文,它们对丢失和解析提出了不同的解决方法。

(1) 使用区别损失函数的语义实例分割
使用了非成对损失函数。使用图像中的所有像素产生丰富得多的渐变。

(2) 通过深度度量学习的语义实例分割
引入了种子模型,帮助我们分类并同时挑选最佳种子,优化速度。

(3) 循环像素嵌入例如分组
GBMS,均值偏移的一种变体,在训练和解析中被用于网络内部。产生非常密集的集群。

这些方法可能被结合和改进以产生更好的结果。它们比基于提议的方法更简单,可能更快,同时避免了本文介绍中提到的基本缺陷。

联系人:me@barvinograd.com

幻灯片:https://goo.gl/iTC9aS

results from “Semantic Instance Segmentation with a Discriminative Loss Function” on the CityScapes dataset

实例分割:自动细胞核检测。

原文:https://towardsdatascience.com/instance-segmentation-automatic-nucleus-detection-a169b3a99477?source=collection_archive---------5-----------------------

实例分割成为医学图像处理的热门话题并非偶然。

识别细胞核是大多数分析的起点,因为人体的 30 万亿个细胞中,大多数都含有一个充满 DNA 的细胞核,DNA 是为每个细胞编程的遗传密码。识别细胞核使研究人员能够识别样本中的每个细胞,通过测量细胞对各种处理的反应,研究人员可以了解潜在的生物过程。

每年的数据科学杯比赛都会提出有趣的挑战,以获得洞察力、现有解决方案的增强和对问题的新观点,从而对医学发展产生前所未有的影响。
今年数据科学杯的任务是创建一个模型,可以识别各种条件下的一系列原子核。换句话说,这是一个实例分割任务,以检测不同类型的扫描细胞核。班级数量— 1。主持人提供了地面真相图片和面具。所有关于数据和指标的信息都可以在竞赛页面上找到。

下面我想简要描述两种最流行的解决这类竞争的策略和一些准确性增强实验。

屏蔽 RCNN

想到实例分割首先想到的是,当然是 Mask RCNN。

因此,一个基本的方法是使用掩模 RCNN 框架进行对象实例分割,它开箱即用,效果很好。之所以做出这样的选择,是因为模型给出了相当不错的现成结果,而且两阶段 RCNN 比一阶段解决方案更好。RCNN 有助于过滤 RPN 的错误结果。

但是,当然“相当好”并不是我们竞争所需要的,并且很难实现模型的进一步增强。

尽管如此,还是做了一些实验和修改来提高模型的准确性

  • 对模型进行大量的扩充
  • 不同类型的内部模型集合,例如具有不同尺寸参数的不同掩模头,以处理重叠情况,或者具有多个区域建议网络和多个 RCNN 的多个掩模头
  • 当然适当的外部数据
  • 不同的主干网 ResNet-50、SEResnext-50、ResNet-101
  • TTA 扩增
  • 具有进一步 NMS 系综的基于 IOU 的聚类结果
  • 使用后处理改进掩模边界
  • 伪标记
  • 在后处理阶段扩张然后腐蚀掩膜

一些合奏技巧看起来像

其中来自不同阶段的结果可以用 NMS 和联合集来集合。

改进:

  • resnet 152 主干,用于提高精确度和处理复杂图像
  • 显著更多的增强来提高泛化能力

带分水岭后处理的 UNet

另一种解决问题的方法是使用带有 ResNet 编码器的编码器-解码器 Unet 风格架构。模型的掩模检测超过了 MaskRcnn 检测部分的结果。剩下未解决的问题是分离粘在一起的细胞核。

第一个想法是使用形态学后处理(基于标记的分水岭)来分离掩模。

在这里可以找到一个很好的分水岭工作原理的解释——分水岭变换。

基本上,它看起来像:

  1. 预测两个通道,一个是二元掩模,另一个是原子核的质心。
  2. 使用预测质心作为分水岭函数中的标记。

另一个想法是通过预测从最近的边界像素指向的中间单位矢量场,使用深分水岭变换来预测分水岭能量水平(被不同偏移侵蚀的掩模)。能级图与像素和最近边界之间的距离有关。它可以通过使用相同的 Unet 模型来完成,而不需要训练新的模型,只需在多个通道中输入。

可以用来改进 pipeline 的改进与 Mask Rcnn 的相同。至于后处理-腐蚀操作分离掩模是有益的。还使用了来自多个检查站和 TTA 的集合结果。更深的编码器和更大数量的增强。

结果:

最终想法

Mask Rcnn 是最适合此类问题的模型,并且易于使用。整个比赛表明,Unet 风格的建筑更轻,更灵活,最重要的是,它显示了核心探测任务的艺术成果。

链接

  • 第一名解-https://www . ka ggle . com/c/data-science-bowl-2018/discussion/54741
  • 比赛页面-https://www.kaggle.com/c/data-science-bowl-2018
  • 竞赛中的文档化 DWT 解决方案和许多其他有用信息-https://spark-in.me/post/playing-with-dwt-and-ds-bowl-2018
  • https://github.com/matterport/Mask_RCNN
  • 马斯克 cnn 论文-https://arxiv.org/abs/1703.06870
  • TernausNet - Unet 用于实例分割【https://github.com/ternaus/TernausNet T2
  • Unet 论文-【https://arxiv.org/abs/1505.04597
  • 分水岭变换-http://cmm.ensmp.fr/~beucher/wtshed.html
  • 深分水岭变换-https://arxiv.org/pdf/1611.08303.pdf
  • 用于图像识别的深度残差学习-https://arxiv.org/pdf/1512.03385.pdf

即时可视化什么是不同的

原文:https://towardsdatascience.com/instantly-visualizing-whats-different-c842ccf44056?source=collection_archive---------8-----------------------

这是一篇关于我们期待已久的 VLDB 2016 论文 的简短博文,标题为“SeeDB:支持可视化分析的高效数据驱动可视化建议”,这是我们 SeeDB 系统上继 2013 愿景论文 和 2014 演示论文 之后的巅峰之作。合著者: 玛纳斯·瓦尔塔克 ,这位首席博士生完成了大部分工作。论文上的合著者包括绝世的 山姆·马登 和才华横溢的 阿尔基斯·多佐蒂斯

A Tired Data Scientist

数据可视化通常是数据科学家探索新数据集的第一道“攻击线”。作为他们探索的一部分,数据科学家一个接一个地重复生成可视化,并检查每一个,以找到那些显示有趣或不寻常行为的可视化。根据数据集有多少属性,这种 基于试错的探索可能需要很长时间

示例时间!假设一名数据科学家对研究“悬浮滑板”产品感兴趣,该产品最近表现不佳。他们想将悬浮滑板与一直热销的产品“融合先生”相提并论。那么他们会怎么做呢?嗯,他们会生成一些可视化效果,并检查这些可视化效果对于悬浮滑板和 Fusion 先生是否不同。这样的可视化之一可能是各州的销售分布——也许悬浮滑板的分布与 Fusion 先生非常不同。另一个可视化可能是广告随着时间的推移——可能悬浮滑板的广告保持不变,而 Fusion 先生的广告随着时间的推移而增加。这两个都是“有趣”的可视化,突出了两个数据子集之间的差异——悬浮滑板数据和 Mr 融合数据。

目标和挑战

SeeDB 的目标是 自动搜索有趣的可视化 。我们现在描述用户使用 SeeDB 浏览数据集的体验。

SeeDB Frontend

用户选择他们想要比较的两个数据子集(窗格 A),并立即获得推荐的可视化(窗格 D),显示这两个数据子集在哪些可视化上最不同。可选地,用户也可以明确地选择他们想要创建可视化的属性(窗格 B),然后接收生成的可视化(窗格 C)。

那么 SeeDB 是如何做到这一点的呢?构建 SeeDB 有两个挑战(即从窗格 A 到窗格 D):

  1. 我们如何判断 某件事是否有趣
  2. 我们如何遍历候选可视化的大空间来找到那些感兴趣的?

挑战 1:评估兴趣度

对于 1,我们使用分布差异作为效用度量。有许多方法可以评估分布差异,包括 K-L 散度、运土机距离(我们的特定选择)和欧几里德距离;关于评估这些指标的更多信息,请稍后讨论。

挑战 2:提高性能

对于 2,我们发现有两个主要原因导致我们浪费时间探索这个可视化的空间:

  1. 我们对数据进行重复处理,以生成和评估每个候选可视化。
  2. 我们在低效的可视化上浪费了大量时间。

对于 1,我们开发了许多基于共享的优化,对于 2,我们开发了许多基于剪枝的优化。**

Architecture Diagram

这些优化以中间件层的形式实现,位于可视化客户端界面和常规关系数据库之间,如我们的架构图所示。

这种共享+修剪的组合允许我们将合理的大型数据集 上的可视化推荐从几十分钟缩短到几秒钟。

用户反应

除了全面的性能评估之外,我们还进行了一项用户研究,以了解用户对可视化建议的总体反应,以及对基于我们的效用指标的可视化建议,特别是的反应。总的来说,从定量的角度来看,SeeDB 在帮助视觉数据探索方面非常有效。从定性的角度来看,以下是一些有说服力的引用:

".。。快速确定相关的相关性”

".。。帮我【分析】。。。快速创建新数据集”

".。。为数据集提出一组初始查询的绝佳工具”

".。。潜在的负面影响可能是,它让我变得懒惰,所以我不会过多地考虑我真正可以学习或感兴趣的东西。”

因此,尽管 SeeDB 在帮助勘探方面很棒,但也有一个警告,即这种帮助可能会让分析师产生一种错误的自满感——然而,我们认为这种收益非常值得冒险。

当前工作

SeeDB 在 2015 年初被接受出版,因此我们已经转向其他项目。一个这样的项目是一个成熟的“毫不费力”的视觉探索引擎, ZenVisage ,推广了 SeeDB 的工作;我们还有一篇关于可视化推荐系统的远景论文正在审阅中。

承认

一个疲惫的数据科学家的形象来自 https://outkasty.wordpress.com/的。非常感谢美国国家科学基金会、英特尔和国家卫生研究院对这项工作的资助。

Python 中的整数编程

原文:https://towardsdatascience.com/integer-programming-in-python-1cbdfa240df2?source=collection_archive---------0-----------------------

We’ll use integer programming to make optimal decisions. Photo from Unsplash

整数规划(IP)问题是优化问题,其中所有变量都被约束为整数。知识产权问题是如何最好地分配资源的有用的数学模型。假设您正在为一位政治候选人组织一场营销活动,您正在决定向哪些选民发送营销材料。你可以给每个选民发一张醒目的传单、一本解释你议程的详细小册子,或者一张保险杠贴纸(或者三者结合)。如果你有办法根据人们收到的营销材料来衡量他们投票给你的候选人的可能性,你会如何决定发送哪些材料,同时注意不要超出你的供应量?

传统的优化算法假设变量可以采用浮点值,但在我们的情况下,给某人送半个保险杠贴纸或四分之三的小册子是不合理的。我们将使用一个名为 cvxpy 的特殊 python 包来解决我们的问题,这样解决方案才有意义。

我将向您展示如何使用 cvxpy 来解决政治候选人问题,但是我将首先从一个称为背包问题的简单问题开始,向您展示 cvxpy 语法是如何工作的。

背包问题

让我们假设你要去远足,你正在计划你可以带哪些物品。每个物体都有重量,单位是磅 w_i,会给你 u_i 单位的效用。你想把它们都带走,但是你的背包只能装 P 磅。假设你要么拿一个对象,要么不拿。你的目标是在不超过包的重量限制的情况下最大化你的效用。

cvxpy 问题有三个部分:

  1. 创建变量:我们将用一个由 1 和 0 组成的向量来表示我们的选择。1 表示我们选择了那个对象,0 表示我们把它留在了家里。我们用 cvxpy 构造了一个只能取 1 和 0 的变量。布尔对象。
  2. 指定约束:我们只需要确保我们的对象的总和不超过重量限制 p。我们可以使用选择向量和权重向量的点积来计算我们的对象的总重量。请注意,cvxpy 重载了*运算符来执行矩阵乘法。
  3. 公式化目标函数:我们想要找到最大化我们效用的选择。任何给定选择的效用是选择向量和效用向量的点积。

Complete cvxpy code for the Knapsack problem

一旦我们有了一个成本函数和约束,我们就把它们传递给一个 cvxpy 问题对象。在这种情况下,我们已经告诉 cvxpy,我们试图用 cvxpy.Maximize 最大化效用。之后,我们可以通过查看选择向量的值属性来检查它的最优值。

print(selection.value)matrix([[1.],
        [1.],
        [1.],
        [1.],
        [0.],
        [1.],
        [0.],
        [0.],
        [0.],
        [0.]])

我们选择了前四项和第六项。这是有道理的,因为这些有很高的实用重量比,而不会太重。

营销问题

现在我们已经介绍了基本的 cvxpy 语法,我们可以为我们的政治候选人解决营销优化问题。比方说,我们有一个模型,它接受一个选民的属性,并预测他们为我们发送给他们的营销材料的每个组合投票给我们的候选人的概率。我在这里使用了假数据,但让我们假设模型输出以下概率:

print(test_probs[0:5])array([[0.0001, 0.0001, 0.3   , 0.0001, 0.2   , 0.0001, 0.2   , 0.3   ],
       [0.1   , 0.1   , 0.1   , 0.2   , 0.2   , 0.2   , 0.1   , 0.0001],
       [0.1   , 0.0001, 0.2   , 0.0001, 0.1   , 0.2   , 0.0001, 0.4   ],
       [0.3   , 0.0001, 0.0001, 0.2   , 0.1   , 0.2   , 0.2   , 0.0001],
       [0.2   , 0.3   , 0.1   , 0.0001, 0.2   , 0.1   , 0.1   , 0.0001]])

每个成分有八个总概率,因为我们可以发送给个人的材料总共有八种组合。以下是每个 1 x 8 向量的条目所代表的内容:

【1 张传单,1 张小册子,1 张保险杠贴纸,传单和小册子,传单和保险杠贴纸,小册子和保险杠贴纸,三个都有,无】。

例如,如果第一个选民收到传单或小册子,他有 0.0001 的概率投票给我们的候选人,但如果我们给他寄去保险杠贴纸,他有 0.3 的概率投票给我们的候选人。

在我们进入 cvxpy 代码之前,我们将通过取负对数把这些概率转化为成本。这使得数学结果更好,它有一个很好的解释:如果概率接近 1,负对数将接近 0。这意味着向选民发送特定组合的材料几乎没有成本,因为我们确信这将引导他们投票给我们的候选人。如果概率接近于 0,反之亦然。

#clipping so that we don't take log of 0 or 1
test_probs = np.clip(test_probs, 0.0001, 0.9999)#turning into costs
model_costs = -np.log10(test_probs)

最后,假设我们不能发送超过 150 份传单、80 份小册子和 25 张保险杠贴纸。

supply = np.atleast_2d([150, 80, 25])

现在我们已经完成了所有的设置,我们可以开始有趣的部分了:

  1. 创建变量:我们将使用 cvxpy。因为我们在这里只能做二进制选择。我们将指定它必须与我们的概率矩阵形状相同:
selection = cvxpy.Bool(*test_probs.shape)

2.指定约束:我们的选择变量将只告诉我们为每个组成部分做了 8 个选择中的哪一个,但它不会告诉我们决定给他们发送多少个材料。我们需要一种方法将我们的 1 x 8 选择向量转换成 1 x 3 向量。我们可以通过将选择向量乘以以下矩阵来实现:

TRANSFORMER = np.array([[1,0,0],
                        [0,1,0],
                        [0,0,1],
                        [1,1,0],
                        [1,0,1],
                        [0,1,1],
                        [1,1,1],
                        [0,0,0]])

如果这一部分有一点混乱,请解出下面的例子:

print(np.dot(np.array([0,0,0,1,0,0,0,0]), TRANSFORMER))array([1, 1, 0])

我们的决策向量的第四个条目表示向选民发送传单和小册子,乘以 TRANSFORMER 告诉我们的就是这一点!所以我们会告诉 cvxpy,我们的选择矩阵乘以 transformer 不能超过我们的电源:

supply_constraint = cvxpy.sum_entries(selection * TRANSFORMER, axis=0) <= supply

我用 cvxpy.sum_entries 对这些行求和,以合计我们发送给所有委托人的材料总数。

我们还需要确保每个成分只做一次选择,否则求解器可以通过不向任何人发送任何东西来实现零成本。

# We must make our choice per constituent
# remember that the last column is for "no materials"feasibility_constraint = cvxpy.sum_entries(selection, axis=1) == 1constraints = [supply_constraint, feasibility_constraint]

3.公式化目标函数:我们任务的总成本将是我们为每个组成部分所发生的成本的总和。我们将使用 cvxpy.mul_elemwise 函数将我们的选择矩阵乘以我们的成本矩阵,这将为每个成分选择成本,cvxpy.sum_elemwise 函数将通过将各个成本相加来计算总成本。

cost = cvxpy.sum_entries(cvxpy.mul_elemwise(model_costs, selection))

最后一步是创建 cvxpy。问题并解决它。

# Solving the problemproblem = cvxpy.Problem(cvxpy.Minimize(cost), constraints=constraints)problem.solve(solver=cvxpy.GLPK_MI)

就是这样!下面是我们期末作业的快照。我们决定不给第一个选民寄任何材料。这是有道理的,因为无论我们给他们寄去保险杠贴纸还是什么都不寄,他们投票给我们候选人的概率都是 0.3。

事实证明,最佳作业耗尽了我们的小册子和保险杠贴纸,但只用了总共 150 张传单中的 83 张。我们应该告诉我们的候选人,她的传单没有她想象的那么有说服力。

print(hard_assignments.value[0:5])matrix([[0., 0., 0., 0., 0., 0., 0., 1.],
        [0., 0., 0., 1., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 1.],
        [1., 0., 0., 0., 0., 0., 0., 0.],
        [1., 0., 0., 0., 0., 0., 0., 0.]])print(np.dot(hard_assignments.value, TRANSFORMER).sum(axis=0))matrix([[83., 80., 25.]])

以下是打包在一起的所有代码:

结束语

我希望您喜欢学习整数编程问题以及如何用 Python 解决这些问题。信不信由你,我们已经涵盖了你解决自己的优化问题所需的大约 80%的 cvxpy 知识。我鼓励你阅读官方的文档来了解剩下的 20%。CVXPY 能解决的不仅仅是 IP 问题,看看他们的教程页面,看看 cvxpy 还能解决什么问题。

要安装 cvxpy,请遵循他们网站上的说明。我还会安装 cvxopt 来确保 cvxpy 附带的所有解算器都能在你的机器上工作

我们已经指定 cvxpy 应该在求解方法中使用 GLPK _ 米求解器。这是一个专门为 IP 问题设计的求解器。在你解决你自己的问题之前,参考这个表来看看哪个预先打包的 cvpxy 解算器最适合你的问题。

快乐优化!

将 TensorFlow 分布式图像服务与 TensorFlow 对象检测 API 集成

原文:https://towardsdatascience.com/integrating-tensorflow-distributed-image-serving-with-the-tensorflow-object-detection-api-5f62d80bce4c?source=collection_archive---------11-----------------------

通过网络为您的 TensorFlow 对象检测模型服务

这款笔记本是使用 TensorFlow-Serving 的 RESTful API 服务基于图像的深度学习模型的续集。请务必阅读该文章,以了解 TensorFlow 服务和 TensorFlow 分布式图像服务(Tendies)库的基础知识。强烈推荐克隆Tendies 库来跟随本教程,因为我将关注重要的代码摘录而不是整个文件。如果你想在笔记本上查看这篇文章,点击这里。

在这里,我们将扩展基本 Tendies 类的功能,以集成一个更快的 R-CNN 深度神经网络,它使用 TensorFlow 对象检测 API 。这将允许我们为符合 REST 的远程推理提供更快的 R-CNN,就像上一篇文章中的 CycleGAN 一样。

CycleGAN 相当简单,因为它接受图像并输出图像;然而,更快的 R-CNN 接受一个图像并输出张量的字典。此外,对象检测 API 迫使我们从 pipeline.config 构建我们的模型,并且重新定义推理函数,使得服务更快的 R-CNN 成为更困难的任务。整合新模型和趋势的步骤如下:

  1. 在 LayerInjector 中定义预处理和后处理功能。
  2. 在 ServerBuilder 中创建或导入模型推理函数。
  3. 创建或导入客户端。

虽然我将使用更快的 R-CNN 进行演示,但是这些步骤对于任何任意模型都是相同的,所以请按照您的特定用例随意操作。

分层注射

每个预处理函数必须将图像位串、图像大小和args(其中args 可用于表示任意数量的自定义位置参数)作为参数,然后将模型输入作为张量返回。相反,每个后处理函数必须将模型输出和*args 作为参数,然后返回输出节点名称列表以及输出是否应该作为图像传输。这些输出将在导出模型时在 ServerBuilder 中使用。

首先,我们将定义我们的预处理函数,它将把图像位串转换成适合推理的 uint8 张量。

import tensorflow as tf
def bitstring_to_uint8_tensor(self, input_bytes, image_size, *args):
    input_bytes = tf.reshape(input_bytes, [])# Transforms bitstring to uint8 tensor
    input_tensor = tf.image.decode_png(input_bytes, channels=3)# Ensures tensor has correct shape
    input_tensor = tf.reshape(input_tensor, [image_size, image_size, 3])# Expands the single tensor into a batch of 1
    input_tensor = tf.expand_dims(input_tensor, 0)
    return input_tensor

符合对象检测 API 的模型返回有用张量的字典,比如 num_detections、detection _ boxes 等等。在我们的后处理函数中,我们将遍历这些张量并给它们分配名称,这样我们就可以在 ServerBuilder 中提取它们。我们还必须考虑检测类张量的 1-索引。最后,我们返回一个输出节点名称列表,并将 output_as_image 设置为 False,因为我们将通过 JSON 将输出张量(不是可视化的图像)发送回客户机。

def object_detection_dict_to_tensor_dict(self, object_detection_tensor_dict, *args):
    # Sets output to a non-image
    OUTPUT_AS_IMAGE = False
    # Class labels are 1-indexed
    LABEL_ID_OFFSET = 1 # Assigns names to tensors and adds them to output list
    output_node_names = []
    for name, tensor in object_detection_tensor_dict.items():
        if name == "detection_classes":
            tensor += LABEL_ID_OFFSET
        tensor = tf.identity(tensor, name)
        output_node_names.append(name) # Returns output list and image boolean
    return output_node_names, OUTPUT_AS_IMAGE

如果您遵循您自己的模型,可以随意使用*args 来接受您需要的任意多个参数进行处理。Tendies 对张量的形状和类型相当挑剔,所以要确保你的预处理器的输出和后处理器的输入分别等价于你的模型的输入和输出。

推理功能

接下来,我们必须从 pipeline.config 构建更快的 R-CNN,并定义我们的推理函数。其代码在 example_usage()下的 ServerBuilder.py 中,这是我们的模型导出的地方。通过将配置文件读入对象检测 API model_builder,我们可以实例化一个更快的 R-CNN,而无需实际查看模型代码。接下来的几个单元格被认为在 example_usage()的范围内。

from object_detection.protos import pipeline_pb2
from object_detection.builders import model_builder
from google.protobuf import text_format# Builds object detection model from config file
pipeline_config = pipeline_pb2.TrainEvalPipelineConfig()
with tf.gfile.GFile(config_file_path, 'r') as config:
    text_format.Merge(config.read(), pipeline_config)detection_model = model_builder.build(pipeline_config.model, is_training=False)

由于 export_graph 期望单个推理函数,但是对象检测 API 有自己的前后处理要做,所以我们必须自己将它们组合起来。这是使用闭包的好地方,因为当我们传递推理函数时,我们希望保留实例化更快的 R-CNN 的范围。闭包是最好的。

# Creates inference function, encapsulating object detection requirements
def object_detection_inference(input_tensors):
    # Converts uint8 inputs to float tensors
    inputs = tf.to_float(input_tensors) # Object detection preprocessing
    preprocessed_inputs, true_image_shapes = detection_model.preprocess(inputs)
    # Object detection inference
    output_tensors = detection_model.predict(preprocessed_inputs, true_image_shapes)
    # Object detection postprocessing
    postprocessed_tensors = detection_model.postprocess(output_tensors, true_image_shapes)
    return postprocessed_tensors

最后,我们将实例化一个 ServerBuilder 和 LayerInjector,然后导出模型。注意,我们将推理函数、预处理器和后处理器传递给 export_graph()。

# Instantiates a ServerBuilder
server_builder = ServerBuilder()# Instantiates a LayerInjector
layer_injector = LayerInjector()# Exports model
print("Exporting model to ProtoBuf...")
output_node_names, output_as_image = server_builder.export_graph(
                            object_detection_inference,
                            layer_injector.bitstring_to_uint8_tensor,
                            layer_injector.object_detection_dict_to_tensor_dict,
                            FLAGS.model_name,
                            FLAGS.model_version,
                            FLAGS.checkpoint_dir,
                            FLAGS.protobuf_dir,
                            FLAGS.image_size)
print("Wrapping ProtoBuf in SavedModel...")
server_builder.build_saved_model(output_node_names,
                                 output_as_image,
                                 FLAGS.model_name,
                                 FLAGS.model_version,
                                 FLAGS.protobuf_dir,
                                 FLAGS.serve_dir)
print("Exported successfully!")

客户

创建定制趋势客户端的最佳方式是从客户端继承,这为远程推理提供了一个框架。在这样的子类中,只需创建 visualize()和相关的 helper 函数,然后调用 client.inference()开始评估过程。

我们将需要几个这样的帮助函数;第一个函数与我们的预处理函数几乎完全相同,只是没有添加批处理。

def bitstring_to_uint8_tensor(self, input_bytes):
    input_bytes = tf.reshape(input_bytes, []) # Transforms bitstring to uint8 tensor
    input_tensor = tf.image.decode_jpeg(input_bytes, channels=3) # Ensures tensor has correct shape
    input_tensor = tf.reshape(input_tensor, [self.image_size, self.image_size, 3])
    return input_tensor

我们的第二个助手函数将用于从提供的标签映射中的对象检测 API 创建我们的类别索引字典;这个更快的 R-CNN 的具体实现只有一个类,所以很简单:

from object_detection.utils import label_map_util
def get_category_index(self):
    # Loads label map
    label_map = label_map_util.load_labelmap(self.label_path)

    # Builds category index from label map
    categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=1, use_display_name=True)
    category_index = label_map_util.create_category_index(categories)
    return category_index

借助我们的助手,我们的可视化功能还不算太差。我们将解码 JSON 数据并将其转换为边界框,然后在对象检测 API visualization_utils 的帮助下将它们覆盖在输入图像上。请注意,我们将输入图像转换为张量,因此我们必须。在可视化之前对其进行 eval()。

from object_detection.utils import visualization_utils
def visualize(self, input_image, response, i):
    # Processes response for visualization
    detection_boxes = response["detection_boxes"]
    detection_classes = response["detection_classes"]
    detection_scores = response["detection_scores"]
    image = self.bitstring_to_uint8_tensor(input_image)
    with tf.Session() as sess:
        image = image.eval() # Overlays bounding boxes and labels on image
    visualization_utils.visualize_boxes_and_labels_on_image_array(
        image,
        np.asarray(detection_boxes, dtype=np.float32),
        np.asarray(detection_classes, dtype=np.uint8),
        scores=np.asarray(detection_scores, dtype=np.float32),
        category_index=self.get_category_index(),
        instance_masks=None,
        use_normalized_coordinates=True,
        line_thickness=2) # Saves image
    output_file = self.output_dir + "/images/" + self.output_filename + str(i) + self.output_extension
    visualization_utils.save_image_array_as_png(image, output_file)

使用服务器

既然我们已经完成了集成更快的 R-CNN 和 Tendies,让我们运行服务器。首先,我们必须导出我们的模型:

python serverbuilder.py --checkpoint_dir $(path) --image_size 512

截至 2018 年 7 月,Python 3 不支持 TensorFlow 服务,但有人提出了解决方案。安装 Python 3 TensorFlow 服务 API,包括:

pip install tensorflow-serving-api-python3

现在,我们可以用下面的命令从 bash 运行这个 TensorFlow 模型服务器:

tensorflow_model_server --rest_api_port=8501 --model_name=saved_model --model_base_path=$(path)

其中$(path)是服务器目录的路径。在我的例子中,它是/mnt/c/Users/Tyler/Desktop/tendies/full _ functional/serve。

最后,我们可以通过在输入图像的文件夹上调用我们的客户端来运行远程推理:

python objectdetectionclient.py

结论

感谢跟随本教程;希望对你有帮助!这个笔记本是用我的 TensorFlow 分布式图像服务库构建的,你可以在这里下载。更多关于我的博文和信息,请访问我的网站。

计算机器中的智能:探索、方法和未来

原文:https://towardsdatascience.com/intelligence-in-computing-machinery-quest-approach-and-the-future-deab2ce89f55?source=collection_archive---------14-----------------------

智能科学与工程整体发展的必要性

Photo by Alexandre Debiève on Unsplash

出于某种原因,我们倾向于让我们的生活变得更好。科学和工程分别努力理解事物和建造它们,互相帮助进行下一次迭代。经过多次反复之后,我们变得更加明智,对我们的生活和我们自己的内心有了更多的控制,最终使我们变得更加文明。下一个迭代是智能的科学和工程。

智力的这个问题,无论是智力的科学还是工程,都被 认为是 所有科学中最大的问题,可能是科学和工程本身的最后一次迭代。如果要解决智能问题,机器智能是必要的或迫在眉睫的。

智能机器,如果成为可能,可能是许多问题的答案。制造甚至设计的完全自动化,个人辅助和护理,增强的人类智能,以及科学发现本身。这是未来的路。我们甚至不知道这是否可能。但是,这正是激起人类好奇心的原因。

在这里,我们看到了在计算机器中对智能的追求,以及几种构建智能机器的独立方法。我们推断出智力问题的严格跨学科性质和该领域研究者的明显利益不一致。一直以来,我们呼吁智能科学和工程的整体发展,这可以帮助我们克服如此多的障碍,为通往智能机器的道路提供一个清晰的视野。

1.探索

将智能设计到机器中的想法可以追溯到数学家、第一个计算机程序员阿达·洛芙莱斯,他说“除了思考,机器可以做任何事情”。在一定程度上反对这种反对意见和其他意见,关于机器智能的最重要的早期工作是艾伦·图灵(Alan Turing)的开创性论文《计算机器与智能》(Computing Machinery and Intelligence),他在论文中还谈到我们应该如何阐述“机器会思考吗?”这个问题。我们可以推断,他把“思考”的问题简化为对人类对话的模仿,这可能涉及推理、解决问题、常识和对世界的理解。他预言,大约 50 年后,我们将拥有一台相当大的思维机器,但 70 年后的今天,我们仍然没有一台我们都认为智能的机器。

对激动人心的冒险的乐观

后来,人工智能领域在达特茅斯的夏季研究项目中崭露头角,参与者有约翰·麦卡锡、马文·明斯基、克劳德·香农等。整个领域都非常乐观,他们的项目将逻辑、常识、一般问题解决能力整合到一台机器中,我们现在意识到这是一个遥不可及的目标。

马文·明斯基在他的论文“迈向人工智能的步骤”(出版, pdf )中,带着我们不再敢拥有的对人工智能的断言和希望,总结如下——(这篇论文是计算智能科学的一个伟大而简单的例子)。

启发式编程的问题——让计算机解决真正困难的问题——分为五个主要领域:搜索、模式识别、学习、规划和归纳。在适当的地方,讨论由文献的广泛引用和一些迄今为止最成功的启发式(解决问题)程序的描述来支持。

研究者们想出了不同的模型,主要是通过对事物及其变化的符号解释,这些模型只能达到探索他们所追求的问题的重要性的程度,但没有一个成功。然后,基于商业规则的专家系统出现了,但并没有给科学发现带来飞跃。即便如此,由于问题的艰巨性和整体性,还是有太多的方法是合理的。直到问题的严重性使人气馁之后,不可挽回的损失才发生。

连接主义(与符号方法相反,具有对象的分布式表示和从数据中进行统计学习的能力——例如,神经网络)方法开始发挥作用了。然后,大多数研究人员停止了智能机器科学的研究,转而专注于他们狭隘智能的小项目。语音识别、对象检测和所有类型的模式识别任务都受益匪浅。这并不是说它没有带来任何好处(许多应用为我们提供了很好的服务),而是智能机器的科学没有前进一步。

一个被低估的问题

智力的问题总是被低估,也许是因为它的新颖性、艰巨性和整体性。许多研究人员,如图灵、马文·明斯基,大概还有所有从事人工智能工作的人,都预测智能机器会比现在更早出现,但事实上,我们离他们建造智能机器的目标并不遥远。

2.方法

这个问题吸引了许多制造智能机器的方法。在这个领域的开端,象征主义和联结主义的方法。然后,人工智能模型是否需要更多的天赋才能变得智能,直到根据正在解决的狭隘问题寻求混合方法,而不参考智能机器的科学。

从事象征主义和联结主义研究的研究者预见到了建造智能机器的成功,但对另一种方法持怀疑态度。前者的研究者,因为问题的复杂性,如常识和一般问题的解决,而后者的研究者,因为他们的方法具有更好的模式识别能力。参见这个关于智能机器的理论,‘符号主义者对联结主义者’,它谈论将智能设计到机器中,并使辩论成为暂时的,而不是需要关注的主要问题。

“……智能系统需要这两个组成部分,所以符号连接主义的对立不是一个有效的技术问题,而只是当代科学政治中的一个短暂问题。”

现在,竞争的范式是非常不同的类型,比如是否在模型中使用更多的先天机制。先天机制是模型中独立的(先验的)结构,无法从数据中学习。在大多数情况下,它支持并推动学习。举一个熟悉的先天类型的例子,卷积神经网络中的卷积或权重分配可以被视为驱动特定学习的先天机制。

现在,从哲学到语言学,围绕智能机器的天赋有很多讨论,Gary Marcus 和阎乐存之间的这场辩论(视频)题为‘人工智能需要更多的先天机器吗’将是相当全面和当代的。

以及是否从神经科学中寻找灵感或者从零开始建造智能机器。强化学习是最终的答案。神经网络是。现在,像计算机视觉,自然语言处理,机器人,生成模型等子领域。,提供了从智能机器科学的困难问题中解脱出来的方法,这是唯一有助于每个子领域在更大的时间范围内向前飞跃的东西。

面对所有科学中最大的问题,我们再次低估了这个问题,但现在,由于缺乏对智能科学整体发展的关注,在深度学习短暂成功的启发下,我们转向了不同的方法或子领域。一门具体的智能科学将会成功地辨别在模糊不清的时代什么是正确的方法,以及什么是正确的方法组合来推进每个子领域。没有智能科学,我们就无法成功地将智能设计成一台机器

3.今后

智能科学和工程的理论有必要引导相关领域(可能涉及人类智能或人工智能,如计算机科学、神经科学、认知科学、哲学、心理学……)的研究者走上正确的道路,或者至少为不同的研究提供占位符,并能够在下一次迭代中建立这些占位符。

David Marr,一位杰出的视觉研究者,表达了他的观点,即探索物体表征的不同类型的内在结构的研究将对计算机视觉产生影响。从视觉智能的角度查看分类调查的综述- “人工智能-个人观点”

“……Marr 和 Nishihara 的 3D 表示理论断言,深层结构本质上是简笔画的结构,这种表示在图像分析过程中受到操纵……”

以便在下一次迭代中解决不同的认知任务,如推理、常识和问题解决。这来自心灵哲学的方法,即有一个先验的结构来实现无法学习的感知。比起从一个数据集求解到另一个数据集,这是一个更好的研究方法。一个完整的智力理论将鼓励这种研究,并通过这种研究得以实现。

深度学习领域的研究人员表示(在关于模型所需先天的争论中),他们正在将先验结构(先天)的所有方面整合到模型的架构中,以便它可以从数据中学习一切。在科学迭代中,这将成为一个可信的调查,但只有通过讨论他们的调查的重要性和立场,更多地关注这些方面,参考智能科学,而不是仅仅在辩论中为他们辩护。(关于先天的争论如上所述)

我们不能只猜测我们的调查将是解决问题的第一步,甚至不考虑完全了解我们正在解决的问题。我们必须将我们的研究作为原始数据呈现给下一代,这些原始数据将在下一次迭代中被研究。我们必须以超出应用科学范围的更科学的严谨态度来处理智力问题。

该领域目前的调查能力

主要研究在著名的机器学习会议上提出,如 NIPS、ICML、ICLR 等。,是关于神经网络的新结构和算法,神经网络模型的理论理解,改进最优化,正则化等的新方法。,以及一些受神经科学和认知科学启发的实现。

不是出于对智能能力的关注,而是该领域目前的研究实际上对智能机器的科学和工程没有多大贡献。大部分工作都被认为是对机器智能的贡献,说“这是迈向机器智能的第一步,也是必不可少的一步”,而没有考虑它在智能机器完整理论中的作用。如果从任何角度来看,这些研究似乎在智能机器科学中发挥了作用,那么,我们可以很容易地看到,它只是在几个方面,而不是全面的,这使得即使那些微小的贡献也不具有建设性。应用机器学习的多功能性和价值可能会随着一些政治和文化影响对该领域产生影响。

我们可以在一定程度上看到智能机器科学的贡献。对于一个简单的衡量标准,让我们看看

  • 如何在该领域的调查中利用马文·明斯基提出的智能机器的五个组成部分(搜索、模式识别、学习、规划和归纳,来自上述论文“迈向人工智能的步骤”)、它们的关系以及它们的组合集成。
  • 柏拉图、亚里士多德和康德等许多心灵哲学家提出的感知和理解的先验结构(先天结构)如何被证明/集成到为机器感知和理解而设计的神经网络模型中。
  • 机器学习社区接受输入(要实现的理论、设计模型的见解、模型的验证等)的频率和认真程度如何。,)从几十年甚至几个世纪以来一直在研究人类智力和大脑的领域,像心灵哲学、数理逻辑、神经生理学、认知科学、心理学、神经科学等等。

显然,这些方法不是主流。也许是因为存在更多有益于智力的途径(通过应用科学),而这些途径不一定对科学有贡献。这些途径的问题在于,它们很少能成功实现我们让机器变得智能的目标。

对该领域先驱的影响

该领域的大多数研究人员都会同意,人工智能作为一个领域正处于起步阶段。在所有的科学中,一个新兴科学领域的研究者们会专注于他们正在解决的问题的根源。这是智力的问题,根源是心灵哲学、认知和行为科学、心理学、语言学等等。

这一领域的先驱们很清楚这一点。马文·明斯基是人工智能的先驱之一,他深受心理学家西格蒙·弗洛依德和许多在他之前的哲学家的影响。他职业生涯的大部分时间都在研究智能机器的理论。他最重要的工作可能是‘心智社会’,这是一个大脑的计算模型。它建立在计算理论、数理逻辑、神经解剖学、哲学、认知和行为心理学的基础上,以解释智力的不同方面。

约翰·麦卡锡广泛致力于将逻辑集成到机器中,致力于哲学和人工智能的交叉。为了熟悉他从哲学中借用的思想,请参见这篇有见地的论文,‘人工智能的哲学和人工智能的哲学’。

甚至该领域的一些杰出研究者也欣赏人工智能的跨学科性质。Deepmind 的联合创始人戴密斯·哈萨比斯为神经科学启发的人工智能提供了一个案例,支持神经科学的灵感帮助人工智能的例子,并描述了这种方法在机器中设计智能的潜力和必要性。

一位年轻的实地调查员

让我们假设在不久的将来,一些新的领域的调查者想要一台机器来理解世界上的事情,并通过阅读文本输入来推理抽象的想法。然后,他可能不会单独使用人工智能/深度学习的工具成功建立那个模型。他需要从语言学、逻辑学、常识推理、认识论的研究中获得灵感,还需要从神经科学、认知科学等方面了解大脑实际上是如何理解的..,

如果一个人打算从事智能科学和工程方面的工作,他/她必须超越这一新生领域的研究者的工作,看到先驱者本身的影响。如果我们对正在解决的问题不全面,那么我们最终会“重新发明轮子”,或者可能根本解决不了问题。

与智能相关的问题,信息技术的科学和工程,应该是所有人工智能研究的基础,但在目前的情况下,它们最终只是总结整个领域的流行谈话中的一个哲学上的一线希望。

参考

[1]艾伦·m·图灵。计算机械与智能 ( pdf ),Mind 1950。

[2]马文·明斯基。迈向人工智能 ( pdf ),IRE 会议录,1961 年。

[3]马文·明斯基。符号主义者 vs 联结主义者,麻省理工学院人工智能,拓展前沿,帕特里克·h·温斯顿(编。),第一卷,麻省理工学院出版社,1990 年。

4 大卫·马尔。人工智能——个人观点,AIM 355,1976 年 3 月。

[5]马文·明斯基。心理学会,西蒙&舒斯特公司,纽约,纽约州,美国 1986 年,ISBN:0–671–60740–5

[6]约翰·麦卡锡。人工智能的哲学和哲学的人工智能,斯坦福大学计算机科学系,2006 年。

[7]加里·马库斯。天赋、AlphaZero 和人工智能, arXiv:1801.05667, 2018。

[8]戴密斯·哈萨比斯、达尔山·库马兰、克里斯托弗·萨默菲尔德、马修·博特文尼克。神经科学启发的人工智能,神经元,2017。

这是' 探知' 举报的奠基篇。即将发表的文章详细讨论了哲学和语言学中提出的不同的先验结构(先天机器),以及它们如何在机器感知和语言理解的当代研究中实现。

智能环境:从汽车到国家

原文:https://towardsdatascience.com/intelligent-environment-from-cars-to-countries-2e74d1bc82c1?source=collection_archive---------9-----------------------

物联网正在改变我们周围的世界。我们从电脑、平板电脑和智能手机的普及开始。现在我们可以制造小而低成本的芯片,将它们嵌入电器、灯、门、窗甚至马桶中。让我们看看这项技术将如何在不同的尺度上改变我们的环境。

无人驾驶汽车

研究人员在 20 多年前推出了第一辆自动驾驶汽车,它们包含一套 100 多公斤的计算机。如今,一块 6 英尺大小的智能手机配一对摄像头就可以做同样的工作,价格不到 1000 美元。同样,软件驾驶比普通司机安全得多,尽管在特殊情况下会有一些问题。

MobilEye 是该领域的领先公司之一(最近被英特尔以 150 亿美元收购)。他们为沃尔沃、宝马、奥迪和许多其他公司提供技术。埃隆·马斯克创造的特斯拉将在今年年底实现完全自动化。数十家其他创业公司正在崛起,你可以在网上学习如何开发自动驾驶技术。

智能家居

知道哪些产品丢失或变质的冰箱。咖啡机,等待信号从你的智能手机,你醒了,开始做一杯。了解您的偏好并找到您可能喜欢的节目的电视。这种门可以识别你的指纹或声音,不用任何钥匙就能打开。根据您的需求不断调节的气候控制和照明。监控你健康和饮食的马桶。

你家的每一部分都可以适应创造你喜欢的环境。

自动化商店、诊所和学校

亚马逊将带着他们的新项目 Amazon Go 走向现实世界。一般都是没有排队和结账的店。进来吧,带上你需要的东西,然后出去。周围的智能传感器系统会识别你拿了什么东西。在你离开商店后,它会自动从你的信用卡上扣钱。不再等待,24/7 简单购物。

在医院门口用一滴血诊断成千上万种疾病怎么样?或者,例如,MRI 扫描仪在没有任何服务人员的情况下检测肿瘤并将结果发送给医生?

对于学生,我们可以提供个性化和互动的教育。此外,我们可以自动记录孩子的出勤和进步情况。

适应性城市

每个大城市都有交通基础设施的问题。传感器可以提供关于交通、免费停车场和事故的信息。此外,结合自动驾驶汽车,这个网络将能够大大减少交通堵塞。

旧金山和洛杉矶电灯公司正在升级他们的室外照明。一项技术根据周围人的数量来控制亮度,而第二项技术可以检测并向警察部门报告枪声。结合起来,他们可能会减少犯罪和电费。

超过 100 个城市已经实施了智能垃圾箱,以减少容器数量和降低回收费用。

智能国家

今天可用的自然语言处理工具能够处理数百万个文档。机器人可以处理公共咨询服务。用于识别身份的智能应用程序可以简化投票过程,促进民主。Civiciti 正在开发一种类似的产品。看一看:

同时,人工智能技术可能被用于有问题的项目。中国政府正在开发一个系统,该系统将分析公民的公共和私人信息,并给他们打分。它可以用来作为信用评分,就业,禁止出境,抵制欺诈和许多其他目的。

我认为收集关于公民的数据是有用的,但是这样的项目应该完全透明。

智能物流

原文:https://towardsdatascience.com/intelligent-logistics-e85de07c3570?source=collection_archive---------6-----------------------

【戴上我的公司分析师帽子……】

物流领导者开始利用他们的信息物理系统产生的大量数据。通过人工智能,他们发现了更高的效率、更高的性能、更复杂的网络协调和更准确的需求预测。

物流是一个庞大的行业,已经在全球范围内形成了一个复杂的网络。收入估计为 8 万亿美元,预计到 2024 年将增长到 15.5 万亿美元。与此同时,IDC 预测,到 2020 年,全球人工智能支出将增长至 470 亿美元,相当于 55%的 CAGR。随着人工智能与工业物联网的融合,物流公司现在看到了人工智能的价值。

像供应链的许多部分一样,物流正在经历数字化转型。连接物流价值链会产生更多的数据、更好的互操作性和更强的控制力。现在,它正在被学习系统(深度学习算法的集合)放大,这些系统筛选数据,建立和管理高分辨率模型,微调运营绩效,并预测整个价值链的变化。对于物流运营商来说,这些变化可以实现持续的感知和学习,以及在不断加速的世界中保持敏捷和适应性的能力。

德国物流公司 DHL 认为这是一个 1.9 万亿美元的机会。援引来自能源、安全和技术的压力,他们的物流趋势雷达宣称,“数据驱动和自主供应链的影响为制造、物流、仓储和最后一英里交付方面以前难以想象的优化水平提供了机会,这可能在不到五年的时间内成为现实。”物流正在进入第四次工业革命。

…围绕不同的地理需求,协调他们的动态供应网络。

供给&需求

从库存到交付,该行业一直在持续数字化和自动化。亚马逊现在在其仓库中部署了超过 45,000 台机器人拣货员。学习系统直观地检查新包装,监控货架,为每件商品分配包装,并协调库存从仓库到运输车辆的移动。这种数据、机器人和机器智能的融合已经成为信息物理系统的模板。“我们喜欢将它视为软件、机器学习、计算机算法和人的交响乐,”亚马逊发言人凯利·齐斯曼说。

管理供应和需求可能非常复杂,失误可能意味着错过机会和浪费商品,尤其是易腐商品。Shelf Engine 使用学习系统根据历史需求模式预测订购多少食物。他们帮助零售商 Molly's 增加了 9%的利润。跨国杂货商 Tesco 通过将天气数据输入其预测分析引擎来预测对天气相关食品(如冰淇淋)的需求,节省了 1.4 亿美元。他们使用这些数据来调整每个商店的库存和订单,围绕不同的地理需求来协调他们的动态供应网络。

从库存到编排

物流公司必须协调大型供应商、合作伙伴、分包商和车辆网络。这些存在于更大的背景下,如地区需求、全球经济、地缘政治和气候。随着学习系统构建更强大的模型并整合来自世界的信息,它们充当网络指挥者的能力正在增强。ClearMetal 利用预测物流来管理集装箱,解决了这一复杂性。为了降低供应和需求之间的风险,他们跟踪集装箱,评估承运人,并整合关于天气、经济和港口条件的第三方信号,用机器学习对所有这些进行建模。

引擎盖下

随着越来越多的组件被连接和感知,越来越多的数据可以输入到学习系统中。罗尔斯·罗伊斯的特伦特·XWB 喷气发动机有数千个传感器,在长途飞行中产生万亿字节的数据。使用微软的 Azure Stream Analytics 和机器智能库,他们可以优化燃油效率并预测维护,从而节省成本并最大限度地减少停机时间。通用运输公司对其机车也采取了同样的做法,同时试图为每天运送 500 万吨货物的美国铁路系统提供仪器。戴姆勒和纳威司达各自在相连的车队中试验了自动驾驶长途卡车——百威英博自动运送了一卡车啤酒(在优步 Otto 无人驾驶设备的帮助下)。百威英博表示,自动卡车运输每年可以在美国节省 5000 万美元。孟买的 ABB 船舶管理展示了许多重工业的路线图。他们正在他们的船上和船之间建立网络,以及连接和自动化操作的服务。这将让他们使用远程控制,然后启动完全自主的系统。ABB 展示了如何利用物理资产获取高分辨率数据,从而为深度分析、预测模型和自我管理奠定基础。

这说明了也许是最有价值的机会:降低能源和水的使用,污染和排放,以及工业化的临近。

含义

在其关于第四次工业革命的工作中,世界经济论坛宣称“我们正站在一场技术革命的边缘,这场革命将从根本上改变我们的生活、工作和人际交往方式。”物流领域的领导者一直在稳步奠定这一基础,现在正在构建学习系统来理解所有数据。初创公司正试图分拆物流,让大型运营商拥有一些灵活性和撤资的机会,同时也威胁到他们的控制权。这推动了更多的竞争和并购。

自动化、预测和协调复杂、动态的生态系统以提高性能和效率的能力将继续吸引 R&D 并保证季度收益。谷歌已经表明,其 DeepMind 学习系统可以将数据中心的能源成本降低 15%。他们不仅在其数据中心部署了这一解决方案,而且现在他们正在与英国国家电网合作,看看相同的解决方案是否可以降低英国能源足迹的总体负荷。这说明了也许是最有价值的机会:降低能源和水的使用,污染和排放,以及工业化的临近。

路障

物流转型面临诸多挑战。人工智能很难,物流是一个庞大而分散的行业,协调着数万家企业。存在相当大的数据和互操作性挑战,但人工智能可以被训练在它们之间进行翻译。该行业厌恶风险,采用速度缓慢,尤其是当网络暴露出安全和漏洞问题时。此外,随着自主系统继续对人类劳动力施加压力,监管反应将会很强烈。在美国,350 万工人驾驶运输车辆。随着物流车队变得自主,劳工危机将会发展,并推动监管机构施加限制。

还有许多挑战有待解决,但人工智能提供的能力太强大了,不容忽视。这是影响所有行业的下一波数字化转型。

智能支付路由

原文:https://towardsdatascience.com/intelligent-payment-routing-d6c4097720e?source=collection_archive---------12-----------------------

使用多臂 Bandit 算法优化支付性能

Multi-Armed Bandits a.k.a. Slot Machines

如果你有一个电子商务网站,你很可能会花无数的时间来寻找正确的产品组合,内容,按钮,颜色和其他变量,可以提高你的转化率,平均交易价值,最终你的收入。大多数商家止步于支付。

多年来,支付行业让我们相信,在优化结账流程的性能方面,我们几乎无能为力。大多数美国企业只要求能够接受信用卡,从标准的万事达卡和维萨卡,到增加美国运通、 JCB 、 Diners/Discover 或银联。但纵观全球,本地支付方式已经能够捕捉到很大一部分交易,尤其是在线交易。荷兰有 iDeal,德国有 Sofort,法国有 Cart Bancaire,中国有支付宝,日本有 Konbini。全球现在有超过 250 种可供选择的支付方式,这使得商家更难决定他们应该提供什么样的支付方式,更不用说优化了。

The global brand general purpose cards — Visa, UnionPay, Mastercard, JCB, Diners Club/Discover, and American Express — generated 295.65 billion purchase transactions for goods and services in 2017, up 18.0%.

实验

在金融服务行业工作超过 14 年后,我一直使用数据来帮助自己和他人做出更好的决策。通过描述性分析(发生了什么)、诊断性分析(为什么会发生)、预测性分析(可能会发生什么)或规定性分析(采取什么行动)。

作为一名数据科学家,我最喜欢最后阶段,因为那是我进行实验的地方。第一阶段对于弄清楚发生了什么,甚至为什么会发生什么是必要的,但是能够使用数学和算法来预测将要发生的事情,并开发技术来自动化需要采取的行动,这才是真正让我兴奋的。

因此,当我在 2015 年为一家大型全渠道零售商做项目时,他们很难决定使用哪种支付方式组合。在六个月的时间里,我研究了他们的业务、新的和已有的支付方式,以及客户从登陆网站到付款或决定不付款的行为。我创建了实验来测试不同的场景,并进行优化,直到我得到最佳的支付组合。事后看来,实验非常成功,我们将结账转化率(购物者点击支付按钮并实际输入和成功支付交易的转化率)从 91%提高到 95%。额外的收益是额外的 100 万欧元的收入,预计在接下来的 12 个月中会有 400 万欧元的收入。我没有留在公司,而是从处理商户交易的 PSP(他们是项目的发起人)那里得到了一个提议,用我的方法帮助其他更大的商户获得相同类型的结果。

加入一家注重结果而非完美执行的超高增长公司后,我能够在近两年的时间内运行超过 100 种不同的分析和实验,并得出描述性、诊断性、预测性和规范性的分析结果。从计算授权率,提高收单性能,弄清楚支付领域的哪些变量导致被授权的可能性更高。但在所有这些项目中,帮助商家找到最佳支付组合是最突出的。

考虑到这个问题和许多其他问题,运行多个实验是获得答案的唯一途径,我无意中发现了多臂强盗算法。

多臂强盗实验

多臂强盗是一种实验类型,其中:

  • 目标是找到最佳或最有利可图的行动
  • 随机化分布可以随着实验的进行而更新

“多臂强盗”这个名字描述了一个假设的实验,在这个实验中,你面对几个吃角子老丨虎丨机(“单臂强盗”),它们具有潜在的不同预期支付。你想找到具有最佳支付率的吃角子老丨虎丨机,但你也想最大化你的奖金。根本的矛盾在于“利用”过去表现良好的武器和“探索”新的或看似较差的武器,以防它们表现更好。

被谷歌用来运行内容实验,我开始思考支付服务提供商和更具体的收单连接是如何相似的。与大多数人可能认为的不同,PSP 或收购方可能对正在处理的交易的性能有很大影响。根据地区、声誉和数据质量等变量,信用卡交易平均有 80%的几率被批准。他们拒绝的原因可以从资金不足,交易不允许持卡人或广泛覆盖不兑现。通过拥有多个 PSP 或获取连接,多臂 Bandit 实验可以在没有人工干预的情况下产生最佳性能。

盗匪如何运作

本质上,多臂 Bandit 算法从多个变量开始,基于输入产生输出。根据性能,每个变量的流量比例将自动调整。性能优于其他变体的变体将被分配更大部分的流量,而性能不佳的变体将看到流量减少。每次调整都基于一个统计公式,该公式同时使用样本大小和绩效指标,以确保变化是真实的绩效差异,而不仅仅是随机的。根据时间和流量,一个或多个变体将成为赢家,我们将奖励所有流量或决定运行一个新的实验。与传统的 A/B 实验不同,Multi-Armed Bandit 实验是在进行实验的同时获得并利用结果,而不是等到有了结果再决定哪种变化是最好的。

应用于商户支付

与任何算法一样,将它应用于现实生活场景给了我们机会去了解结果是否可以改进。向旅游业中一家拥有多个 PSP 连接的大型商家提出这个想法,我们能够测试这个想法。

第一个实验侧重于授权率,这是支付行业内提供 PSP 性能反馈的一个指标。我们知道,在差异较小的地区,获得具有统计显著性的结果将具有挑战性,因此我们决定将重点放在授权率在 60%至 70%之间的国家和其他 PSP(未连接)上,他们表示能够获得 80%左右的授权率。现有的两个集成扩展为三个。开发了在每个 PSP 连接之间切换所需的逻辑以及跟踪性能的能力。

在我们测试该解决方案时,我们进行了不同的调整,以确保流量仅在结果具有统计学意义时才重新分配。在一个月的时间里,我们处理了超过 10 万笔交易,三个 PSP 的授权率分别为 74%、66%和 59%,其中本地 PSP 的性能最高。

尝试多臂强盗实验的其他场景

除了将交易路由到多个 PSP 之外,当然还有许多其他方式来使用多臂 Bandit 算法。在支付领域,将交易路由到不同的收单机构是次佳选择,但也是测试不同的欺诈保护工具。支付之外的选择是无穷无尽的,从测试你的网站或电子邮件中的内容。每当你想比较两个以上的变量,等到最后再做决定代价太大,多臂土匪实验肯定应该考虑。

感谢阅读;),如果你喜欢它,请点击下面的掌声按钮,这对我意义重大,也有助于其他人了解这个故事。通过在推特或 Linkedin 上联系让我知道你的想法。或者关注我,阅读我关于数据科学、支付和产品管理的每周帖子。

机器人过程自动化中的智能过程挖掘

原文:https://towardsdatascience.com/intelligent-process-mining-in-robotic-process-automation-f684dd4c7de5?source=collection_archive---------7-----------------------

智能流程挖掘为什么以及如何改善 RPA 结果

Image source: Envato Elements

了解您的“现状”流程状态

许多组织正在将机器人流程自动化(RPA)作为其数字化转型工作的一个关键方面。RPA 为公司提供了一种“数字工人”战略,这种战略可以对使用最佳实践来规划和执行自动化项目的团队产生显著的可量化影响,这些最佳实践有助于清楚地识别自动化友好的流程,同时避免自动化设计不佳或不完善的流程。评估“原样”状态流程的能力有助于明确设定投资回报预期,确保敏捷的服务交付,或实现改善的客户旅程的好处。

RPA 为更好的服务、更高的过程精度和巨大的成本效益提供了巨大的希望——这无疑是以服务为重点的行业纷纷采用它的原因。

如果您的组织使用手动方法来理解端到端的流程执行,那么您正在进行大量的时间和金钱的前期投资,并且只能获得一小部分。负责执行操作和后台事务的软件会生成大量与流程相关的数据。能够提取这些数据并进行汇总和分析,为您提供了对“现状”流程的切实可行的见解。这一概念听起来简单易行,但对大多数组织来说却是一个巨大的挑战。这有什么难的?一个重要的原因是,当多个系统执行任何流程的不同方面时,几乎不可能使用旧的方法重新创建一个单一的、可用的流程视图。另一个原因是,用于生成关键指标的分析工具及时提供快照,而不是在时间背景下查看流程执行情况。

流程智能为 RPA 增值

而当前的大多数 RPA 计划侧重于在没有人工干预的情况下自动执行涉及结构化数据的大量相对简单的流程。在处理非结构化数据的过程中,以及在人类参与其中的更复杂的环境中,或者在可能需要采用一些认知推理的情况下,越来越多地考虑使用机器人。日益增加的复杂性和复杂性推高了部署成本,进而对 RPA ROI 合理性提出了挑战。在数字工人环境中,访问可操作流程智能的能力与涉及人类工人时一样重要。它允许您:

  • 找出你可能没有意识到的冗余过程。
  • 确定可以解放数字员工周期的机器人流程优化,从而让效率最高的数字员工变得更有效率。
  • 发现低效的人机交互,反之亦然
  • 按流程提供有关数字工作者财务影响的可量化数据。
  • 从成本、准确性、效率和持续时间方面比较人工劳动和数字劳动。

流程智能平台为您的机器人操作模型实例化相应的风险和合规性框架,该框架定期监控和评估自动化流程性能:

  • 为流程治理建立数据驱动的基础,并清晰地记录和自动化风险缓解步骤。
  • 创建 RPA 卓越中心,该中心可以捕获流程、将流程导出到剔除的 RPA 流程中,或者根据多个数据标准对流程的感知价值评分进行排名。
  • 通过识别流程异常和自动启动补救来扩大 RPA 范围。
  • 对数字和人工流程及其交互执行更广泛的生命周期管理。

瞄准正确的 RPA 机会

许多不同的行业使用流程挖掘来自动建模和呈现流程流。类似于最初用于制造环境的数字双胞胎,它基于真实数据,在实际发生时揭示任何业务流程的内部工作方式。详细的过程数字孪生是智能过程挖掘的核心。直观的 BI 风格分析使发现、分析和自动监控接近实时的流程变得更加容易和快速,从而揭示自动化机遇和挑战的真正深度和广度。

以下是智能流程挖掘解决方案可以应对的四个常见 RPA 挑战——改善实施和大规模可持续性:

瞄准自动化潜力最大的流程,同时缩短实现价值的时间

  • 提供跨多个业务应用程序的实际流程执行的单一全面的端到端视图,以发现主要的自动化机会以及潜在的副作用。
  • 基于显示所有流程变化以及时间和成本影响的实际流程执行数据,轻松识别高价值的自动化候选项目。
  • 基于交易数量,实现可量化、数据驱动的投资回报计算;流程步骤的数量;AHT/TAT 流程(持续时间);每笔交易的成本。
  • 消除了费力、昂贵且通常主观的手动流程评估。

智能流程挖掘提供 100%的流程可见性。找到你意想不到的高风险或高成本的模式。

瞄准高价值 RPA 机会

避免中断或执行不良流程的自动化

  • 100%的“已执行”流程可见性允许团队识别、分析和纠正流程执行问题,如瓶颈、法规遵从性风险或 RPA 前的错误执行顺序
  • 避免或修复会增加 RPA 开发成本并延长价值实现时间的中断流程
  • 确定流程执行中可能会扩大 RPA 投资范围和价值的潜在变化

维护受影响流程的 RPA 后可见性

  • 确保您的自动化投资在部署后按预期运行
  • 监控自动化对上游和下游的影响,确保持续的协议合规性
  • 混合模式场景中的自动化流程执行监控(机器人包含人工协助)保障了投资回报承诺
  • 轻松指定在正确的时间向正确的人触发实时警报的详细场景或条件。
  • 每天自动监控清晰、可量化的实施后成本影响,为未来的自动化计划提供数据支持

在企业规模执行 RPA

  • 使用流程智能作为空中交通控制塔,通过近乎实时地监控企业范围的业务流程,建立合规性和风险治理框架
  • 从几十个扩展到几百个,甚至几百个到几千个机器人需要大量的命令和控制,以确保自动化在它涉及的每个流程和业务系统中保持同步。
  • 使用警报功能实时监控启用 bot 的流程执行情况,以生成自动化补救流程。

构建您自己的过程数字双胞胎

交互式流程模型也称为流程数字双胞胎,它不仅可以 100%地显示 RPA 机器人或 IT 系统执行的任何流程,还可以了解导致意外或不良行为的复杂动态。您可能已经有了大量的 IT 平台投资和各种部门系统,以确保获得关于每个支持事件或分配任务的每条有意义的信息。

智能流程挖掘通过自动发现流程,提供复杂的工具来分析流程行为,帮助您优化生产力、客户满意度和服务质量,从而释放更多价值。然后,近乎实时地监控流程执行,以保持最佳性能。

无论用于存储数据的系统数量有多少,流程智能平台都可以帮助您从端到端改善 RPA 流程的各个方面。将来自任意数量 IT 系统的流程数据转换为可操作的洞察,可以更快、更低成本地做出更准确的自动化决策。智能流程挖掘为做出数据驱动的决策提供了信心,这些决策对服务交付的任何方面都有可持续的影响。简而言之,利用智能流程挖掘技术,您可以确保您的流程在更短的时间内以更低的成本以最高的效率运行。

增加可见性——加速变化

评分者间协议

原文:https://towardsdatascience.com/inter-rater-agreement-kappas-69cd8b91ff75?source=collection_archive---------0-----------------------

又名评分者之间的可靠性或一致性

在统计学中,评分者之间的可靠性、评分者之间的一致性或一致性是评分者之间的一致程度。它给出了评委给出的评分中同质性或一致性的程度。

这里涵盖的 Kappas 最适合于【名义】数据。这些方法忽略了数据中的自然排序(如果有的话)。如果您要使用这些指标,请确保您了解限制。

科恩的卡帕

这有两个部分:

  1. 计算观察到的一致
  2. 偶然计算一致

假设我们正在处理“是”和“否”的答案以及 2 名评定者。以下是收视率:

rater1 = ['yes', 'no', 'yes', 'yes', 'yes', 'yes', 'no', 'yes', 'yes']
rater2 = ['yes', 'no', 'no', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes']

将这些评级转化为混乱矩阵:

Observed agreement = (6 + 1) / 10 = 0.7
Chance agreement   = probability of randomly saying yes (P_yes) + probability of randomly saying no (P_no)
P_yes              = (6 + 1) / 10 * (6 + 1) / 10 = 0.49
P_no               = (1 + 1) / 10 * (1 + 1) / 10 = 0.04
Chance agreement   = 0.49 + 0.04 = 0.53

因为观察一致大于偶然一致,我们会得到一个正的 Kappa。

kappa = 1 - (1 - 0.7) / (1 - 0.53) = 0.36

或者直接用sklearn的实现

**from** **sklearn.metrics** **import** cohen_kappa_scorecohen_kappa_score(rater1, rater2)

它返回 0.35714。

卡巴的解释

特殊情况

小于机会协议

rater1 = ['no', 'no', 'no', 'no', 'no', 'yes', 'no', 'no', 'no', 'no']
rater2 = ['yes', 'no', 'no', 'yes', 'yes', 'no', 'yes', 'yes', 'yes', 'yes']
cohen_kappa_score(rater1, rater2)
-0.2121

如果所有的评级都是相同和相反的

这种情况可靠地产生 0 的kappa

rater1 = ['yes'] * 10
rater2 = ['no'] * 10
cohen_kappa_score(rater1, rater2)
0.0

随机评级

对于随机评分,Kappa遵循平均值约为零的正态分布。

随着评级数量的增加,Kappa 值在分布中的可变性更小。

10 random ratings for each rater (random sample of 1,000 inter-rater Kappa calculations)

100 random ratings for each rater (random sample of 1,000 inter-rater Kappa calculations)

您可以在此找到更多详情

请注意,Cohen 的 Kappa 仅适用于对完全相同的项目进行评分的 2 名评分者。

弗莱斯

将 Cohen 的 Kappa 扩展到 2 名以上的评定者。

解释

它可以被解释为表达评价人之间观察到的一致程度超过了所有评价人完全随机进行评价时的预期程度。

评分者可以对不同的项目进行评分,而对于 Cohen,他们需要对完全相同的项目进行评分

Fleiss’kappa 特别允许,尽管有固定数量的评定者(例如,三个),不同的项目可以由不同的个人进行评定

例如,假设我们有 10 名评定者,每人对 5 个项目进行“是”或“否”评定:

例如,假设我们有 10 名评定者,每人对 5 个项目进行“是”或“否”评定:

例如第一行(P_1):

P_1 = (10 ** 2 + 0 ** 2 - 10) / (10 * 9) = 1

第一列(p_1):

p_1 = 34 / (5 * 10) = 0.68

如果不清楚的话,在这里看一下这个例子。

现在你可以计算 Kappa:

P_bar = (1 / 5) * (1 + 0.64 + 0.8 + 1 + 0.53) = 0.794
P_bar_e = 0.68 ** 2 + 0.32 ** 2 = 0.5648

在这一点上,我们已经得到了我们需要的一切,而kappa的计算就像我们计算科恩的:

kappa = (0.794 - 0.5648) / (1 - 0.5648) = 0.53

你可以在这里找到这篇文章附带的 Jupyter 笔记本。

参考文献

  • 【https://www.wikiwand.com/en/Inter-rater_reliability
  • https://www.wikiwand.com/en/Fleiss%27_kappa

使用 Jupyter 笔记本的交互式数据科学

原文:https://towardsdatascience.com/interactive-data-science-with-jupyter-notebooks-457ab4928b08?source=collection_archive---------3-----------------------

在我的视频中,你已经看到我在屏幕上实时运行 Python 代码并显示结果。今天,我想和你分享我是如何做到这一点的,并告诉你如何利用它!

我在屏幕上实时运行 python 代码的方式是使用一个名为 Jupyter 的 Python 包。Jupyter 构建于 IPython 项目之上,允许在浏览器中运行交互式 Python。但远不止如此。从 bash 命令到特殊的“魔法”和插件,Jupyter 极大地增强了 Python 编码体验。

如果你已经在使用 Jupyter,我希望我能改进你的工作流程,并向你展示一些新的技巧。如果您还没有使用 Jupyter,那么让我们开始吧。

安装和启动

安装 Jupyter 最简单的方法是运行pip install jupyter,尽管如果您使用打包的 python 发行版,比如 Anaconda,您可能已经安装了它。确保首先激活您的 Python 环境。让我们开始吧。

在本地运行 Jupyter 时,您将通过浏览器连接到本地运行的 web 服务器,通常是在端口 8888 上。在你的工作目录中运行jupyter notebook来启动你的笔记本。通常 Jupyter 启动后会自动打开,但如果没有,请将你的浏览器指向localhost:8888

如果您还没有想要打开的笔记本,您可以通过单击“新建”并选择 Python 2 或 3 来创建一个,具体取决于您环境中运行的 Python 版本。Jupyter 非常灵活,实际上可以处理许多语言和文件类型,尽管我们现在只坚持使用 Python。

在 Jupyter 笔记本中运行代码

一旦你有一个新的笔记本在运行,你可以在空的单元格中写一些 python 代码,然后按 ctrl+enter 来运行它。我们可以在这里运行所有典型的 Python 代码,就像您可能用 Python 脚本编写一样。不同的是,我们可以运行它,并立即看到结果!

注意当我们用 ctrl+enter 运行一个单元格时会发生什么。当单元正在运行或排队等待运行时,单元左侧的括号中会显示一个星号,然后在运行完成后会显示一个数字,代表单元在给定会话中的运行顺序,从“1”开始。

代码单元格最后一行的结果将作为该单元格的输出打印出来,但前提是该值没有存储到变量中。例如,如果我导入 tensorflow,然后用一个字符串连接它,输出如下所示,即使我没有使用 print 命令。

当然,我也可以使用 print()。这对于修补和观察事物的行为非常有用。

Shift-Tab

Jupyter 笔记本的另一个奇妙的特性是能够通过按shift-tab显示你正在调用的函数的文档字符串。这允许您使用正确的参数调用函数,而不需要每次都查阅完整的文档。

这个特性也可以和你自己的本地自定义函数一起工作,所以如果你写了好的 docstrings,你会得到回报的!

输出

当您有大量输出时,您可以通过单击输出的左侧面板来减少它占用的空间,这将使它变成一个滚动窗口。如果双击,输出将完全折叠。

更多细胞!

一个细胞是有用的,但实际上我们希望有许多细胞。要添加单元格,请单击工具栏上的“加号”图标。还有一些单元执行命令可以创建新的单元。

如果您按下shift+enter,它将运行当前单元格,然后高亮显示下一个单元格。如果没有新单元,则创建一个新单元。另一方面,如果您想在给定的单元格之后立即创建一个新的单元格,您可以使用alt-enter来执行该单元格,然后在它之后直接插入一个新的单元格。

有人说降价了吗?

也许到目前为止,我遗漏的最大特性是降价支持。我对 Jupyter 笔记本的第一印象是它能够提供一种很好的方式来编写代码和描述我正在编写的代码。markdown 丰富的语义允许研究人员和教育工作者简单明了地交流思想和观点。

也许最重要的是,它允许过去的你告诉未来的你一个给定的代码单元应该做什么,以一种比使用注释块更有表现力的方式!

朱庇特魔术

有时我只想快速检查一下一个培训或评估周期需要多长时间。一个简单的方法来计时你的代码,用%%time 开始一个单元,一旦这个单元完成执行,它将打印出运行这个单元花了多长时间。这不是精确的原子计时,但这是一个很好的方式,可以用最小的努力获得一些可靠的第一印象。

如果要在笔记本中运行命令行命令,最简单的方法就是在命令前面加一个感叹号。这对于一次性命令非常有用。

如果您想运行一组命令,用“%%bash”开始一个单元,使整个单元被解释为一个 bash 脚本。

这个的一个很大的用途是启动张量板。通常,运行 TensorBoard 可能需要启动一个新的终端窗口,并在命令行上运行它,如果您想运行一段时间,我们通常会这么做。但是,如果你只是想旋转它,看一眼,然后关闭它,把它放在 Jupyter 笔记本电池里也不是一个坏主意。

此外,您将永远不会忘记运行它,因为它嵌入到您的笔记本电脑单元的工作流程中!请注意,它将占用您的笔记本。因此,在 Tensorboard 运行时,您将无法运行任何其他内容。要停止它,点击中断内核,星号会消失,你会得到控制流。

这就是我最喜欢的 Jupyter 特性和功能。这当然不是对 Jupyter 特性的全面讨论。我刚刚在这里介绍了一些我最喜欢和最常用的。还有很多很多等着你去探索。

感谢阅读这一集的云人工智能冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注媒体上的我或订阅 YouTube 频道以观看未来的剧集。更多剧集即将推出!

附:如果你还在读:这篇文章的 gif 怎么样?他们有帮助吗?分散注意力?俏皮?迷惑?让我知道!

用 D3.js 实现交互式数据可视化

原文:https://towardsdatascience.com/interactive-data-visualization-with-d3-js-43fc3428a27e?source=collection_archive---------2-----------------------

开启数据驱动的可视化之路

本文内容由 昆西·史密斯 供稿,昆西·史密斯是 跳板 在线培训公司营销团队的一员,该公司致力于弥合世界各领域的技能差距。他们开设以行业为重点、由导师指导的课程,如数据科学训练营和网络安全职业跟踪。

Credit: https://d3js.org/

交互式可视化可以给平淡乏味的数据集增添令人印象深刻的魅力。交互数据的主要特征在于它本身作为一个应用程序使用。它允许用户选择特定的数据点,以他们选择的方式将故事可视化。实现这一点的最强大的方法之一是通过 JavaScript ,或者更具体地说,D3.js 框架。

由 Mike Bostock 开发的 D3 (data-driven documents)是一个开源的 JavaScript 库,它利用 SVG、HTML 和 CSS 来创建强大的数据可视化表示,从而赋予数据以生命。让我们看一个由 D3.js 支持的有趣的交互式可视化的例子!

Tech Company IPOs vs. Company Value

在上述示例中,将鼠标悬停在特定数据点上会弹出一个弹出窗口,显示关于该特定数据的更多信息。图表本身可以进一步动画化,创建一个令人兴奋的用户数据视图。请看它在 这里的

[## 脸书产品:如何比较

在 2400 次科技、互联网和电信的首次公开募股之后发生了什么

archive.nytimes.com](https://archive.nytimes.com/www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html)

D3 . js 的主要特性

  1. 它使用预先存在的约定: D3.js 使用 web 标准,比如前面提到的 SVG、HTML 和 CSS。就其本身而言,这一特殊特征可能并不显著。然而,这允许跨平台的脚本的容易实现,而不需要除了浏览器之外的其他技术或插件。它还允许数据可视化与其他脚本和 JS 框架统一应用,如 Angular.js、Ember.js 或 React.js。换句话说,它可以顺利地放入您的网站中,而不会干扰其余的代码。最好的部分:D3 是轻量级的。它适用于任何网络标准,因此速度很快,不管你的数据集有多大。
  2. 数据驱动: D3 完全由数据驱动,通过输入静态数据或从远程服务器获取数据。这可以通过多种格式实现,从数组和对象到 CSV、JSON 和 XML 等等。通过这个专门的工具,可以很容易地创建不同类型的图表。D3 大量使用数据驱动元素也增强了您的数据,允许动态生成不同的元素和图表样式,无论是表格、图形还是任何其他类型的元素分组。
  3. 它是动态的:凭借其灵活性,D3 可以成为一个非常强大的工具,因为它为几乎所有的功能提供了最大的动态属性。然后,您输入到脚本中的数据可以很容易地形成特定数据集可视化所需的样式和属性类型。

点击这个咖啡风味转盘上的任何地方,它就会以一种流畅、动态的动作缩放。查看 这里

[## 咖啡调味轮

咖啡味道的形象化。

www.jasondavies.com](https://www.jasondavies.com/coffee-wheel/)

如果您真的想深入了解技术细节,这是一个使用[d3.layout.partition](http://github.com/mbostock/d3/wiki/Partition-Layout)布局从分层数据生成可缩放旭日树的例子。旭日树是一种特殊的放射状空间填充可视化,类似于冰柱树。

总而言之,D3 允许用户创建基本上任何类型的可视化,纯粹基于数据,而不是来自个人对数据的理解。无论是表格还是饼图、图形还是条形图,D3 都通过简化数据可视化过程来避免人为错误,同时为用户提供了进行调整和控制可视化功能的所有机会。

不仅如此,D3 通过像**duration()****delay()****ease()**这样的功能为交互和动画提供了足够的空间,这些功能允许用户制作数据动画,就像在你的网站上添加视频一样——除了在 D3 的情况下,它被简化并直接在你的网站上实现。这些动画也很快,对用户交互反应灵敏,使它们更有吸引力。

如何入门?

D3.js 实现起来非常简单,只要你已经掌握了一些 JavaScript 的基础知识。这里有一个简化的分步指南,帮助您开始交互式数据之旅。

步骤 1:设置

D3 的第一步是建立 D3 库,它作为 D3 代码的信息和指令的存储库。它构成了数据可视化的基础,所以把这一步做好很重要。

有两种方法可以做到这一点:

  1. 将 D3 库引入您的项目文件夹:由于 D3 是开源的,源代码可以在 D3 网站上下载。你要做的就是解压下载的文件夹,寻找**d3.min.js**,直接复制到你项目的根文件夹。然后,使用**<script src =…>****d3.min.js**文件包含在 HTML 页面中。有了这个,你的 HTML 网页现在可以访问 D3 库中的代码和 DOM 元素。
  2. 介绍来自内容交付网络(CDN)的 D3 库: CDN 是一个由不同服务器组成的网络,这些服务器托管根据用户的地理位置交付给他们的文件。使用 CDN,您甚至不需要源代码(就像使用第一种方法一样)。只需使用**<script src=…>**包含 CDN URL

第二步:DOM 元素

有了开源代码库,就可以根据样式和操作其他 DOM 元素来设置网页本身了。使用**d3.select** (css-selector)或**d3.selectAll** (css-selector)获取 DOM 元素的引用是很重要的。之后,应用众所周知的 HTML 和 CSS 约定,并且可以相应地实现这些元素。

DOM 元素也可以由一系列方法操作,比如**text(“content”)****remove()**。这些与现有的约定非常相似,因此从编码的角度来看很容易使用。您可以使用不同的脚本以类似的方式添加动画和其他功能,这些脚本可以在官方网站的 API 参考中找到。

开发这段代码的关键点在于“链语法”,如果您使用过 JQuery,可能会对它很熟悉。D3 的链接技术是通过使用句点将方法放在一起实现的。这样,第一个方法的输出作为输入传递给下一个方法,从而简化了代码。

Standard Candlestick Chart for Stock Prices

凭借其数据驱动的焦点,D3 可以轻松创建烛台图,如this

[## D3 蜡烛图

绘制股票数据的一个微妙之处是市场只在工作日开放:如果你…

beta.observablehq.com](https://beta.observablehq.com/@mbostock/d3-candlestick-chart)

第三步:加载您的数据

下一步是加载数据集并将它们绑定到 DOM 元素。D3 可以处理不同类型的文件,本地的和外部的。数据的上传类似于 HTML 和 CSS 的传统数据加载,通过**.csv**文件的**d3.csv()****.json**文件的**d3.json()**等方法。

第四步:可视化数据

数据成功加载到 D3 后,用户可以创建数据可视化最重要的部分:可视化本身。

这可以以 SVG 的形式出现,它允许您的图表显示不同的形状,从线条到圆形到椭圆形,并允许您完全控制以实现数据的理想可视化。本质上,SVG 值的操作与 DOM 元素的操作非常相似。

通过采取这些步骤,用户可以轻松地创建图像和形状,帮助构建完整的图表和图形。然而,这实际上并没有形成真正的数据可视化。相反,需要通过 D3 对几何图形和样式进行操作,以获得想要的结果。这也包括从图表的刻度到它的轴到图表的动画。

然而,一旦掌握了 D3.js 技术,从移动饼图到响应条形图,制作任何东西都很容易。

US Trade Deficit

上图显示了一段时间以来美国的贸易逆差。第一次打开时,图表会根据时间线从 2001 年移动到 2013 年。单击时间线的任何部分都会导致图表相应移动,显示特定时间段的贸易逆差。仔细看看这里的

* [## 美国贸易赤字-亮点

美国在贸易逆差下运作,这意味着美国从国外购买的商品多于其销售的商品。这个…

www.brightpointinc.com](http://www.brightpointinc.com/united-states-trade-deficit/)

简单地说

总的来说,D3.js 是一个极其强大和通用的工具。

它包含大量的功能,让数据科学家(有经验的&新)完全控制图表或图形的外观和感觉,使其成为任何希望掌握数据可视化的人最有影响力的工具之一。*

感谢 昆西史密斯跳板 为迈向数据科学贡献此贴。**

** [## 昆西·史密斯-营销-跳板| LinkedIn

查看昆西·史密斯在全球最大的职业社区 LinkedIn 上的个人资料。昆西有 9 份工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/qlsmith/)

如果你对我的文章或数据科学有任何反馈、评论或有趣的见解要分享,请随时通过我的 LinkedIn 社交媒体频道联系我。

[## Dipanjan Sarkar -数据科学家-英特尔公司| LinkedIn

查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 6 份工作列在…

www.linkedin.com](https://www.linkedin.com/in/dipanzan/)**

交互式机器学习:让 Python 再次“活跃”

原文:https://towardsdatascience.com/interactive-machine-learning-make-python-lively-again-a96aec7e1627?source=collection_archive---------3-----------------------

当使用交互式小工具时,笔记本变得活跃起来。用户可以可视化和控制数据和模型的变化。学习变成了一种身临其境的、有趣的体验。

你已经用 Jupyter 编写了代码,Jupyter 是一个无处不在的笔记本平台,用于用几乎所有主流编程语言编写和测试很酷的想法。你喜欢它,你经常使用它。

但是你想要更多的控制,你想要通过简单的点击鼠标来改变变量,而不是通过编写 for 循环。你该怎么办?您可以使用 IPython 小部件。请继续阅读…

什么是 Python Widget?

Project Jupyter 诞生于 2014 年的 IPython 项目,并迅速发展到支持跨所有主要编程语言的交互式数据科学和科学计算。毫无疑问,它对数据科学家如何快速测试和原型化他/她的想法并向同行和开源社区展示工作产生了最大程度的影响。

然而,当用户可以交互地控制模型的参数并(几乎)实时地看到效果时,学习和实验数据就变得真正身临其境了。Jupyter 中大多数常见的渲染都是静态的。不过有一个很大的努力,引入了名为 ipywidgets 的元素,在 Jupyter 笔记本上渲染出有趣的交互控件。

小部件是多事件的 python 对象,在浏览器中有一个表示,通常是像滑块、文本框等控件。,通过前端(HTML/Javascript)呈现通道。

在之前的一篇文章中,我使用基本的小部件控件演示了一个简单的曲线拟合练习。请阅读那篇文章,了解关于安装这个小部件包的说明。在本文中,这在交互式机器学习技术领域得到了进一步的扩展。

交互式线性回归

我们使用交互控制元素演示单变量的简单线性回归。注意,该思想可以容易地扩展到复杂的多变量、非线性、基于核的回归。然而,为了简化可视化,我们在这个演示中坚持使用单变量的情况。

我的 Github 库 中有锅炉板块代码 。我们分两个阶段展示交互性。首先,我们将数据生成过程显示为输入变量和相关噪声统计属性的函数。这是一个视频,展示了用户使用简单的滑动条控件动态生成和绘制非线性函数的过程。

这里,生成函数(又名“地面真相”)是四次多项式,噪声来自高斯分布。接下来,我们使用 scikit-learn 的 多项式特征生成流水线方法 编写一个线性回归函数。此处 给出了这样一个机器学习流水线过程的详细 分步指南。在这里,我们将整个功能封装在另一个交互式控件中,以便能够动态地改变线性模型的各种参数。

我们为以下超参数引入交互控制。

  • 模型复杂性(多项式的次数)
  • 规则化类型— 套索或山脊
  • 测试集的大小(测试中使用的总样本数据的一部分)

以下视频显示了用户与线性回归模型的交互。请注意,测试和训练分数也是如何随着模型复杂性的变化而动态更新,以显示过度拟合或欠拟合的趋势。可以返回到数据生成控制,增加或减少噪声幅度,以查看其对拟合质量和偏差/方差权衡的影响。

摘要

我们简要介绍了一个 Jupyter 笔记本,它具有嵌入式交互控制对象,允许用户/程序员动态地处理数据集的生成和建模。当前演示允许用户引入噪声,改变模型复杂性,并检查正则化的影响,所有这些都在运行中,并立即看到最终的模型和预测。但整个想法在笔记本中以一步一步的方式进行了解释,这应该有助于感兴趣的读者试验这些小部件,并提出生动、交互式的机器学习或统计建模项目。

如果您有任何问题或想法要分享,请通过tirthajyoti【AT】Gmail[DOT]com联系作者。你可以查看作者的 GitHub 资源库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。此外,如果你像我一样对机器学习/数据科学/半导体充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

交互式(自然)语言学习

原文:https://towardsdatascience.com/interactive-natural-language-learning-199b2c6bfa46?source=collection_archive---------7-----------------------

设置和模型/算法核心

设置

游戏中的两个玩家:人类电脑

游戏:通过固定数量的关卡进行。

对于人机之间的每一个层次:在 Y 中,人类和计算机都有一个起始状态 s ,但在 Y 中,只有人类知道目标状态 t

  • 人类给计算机说话 x
  • 计算机在 Z 中构造动作 z 的排序列表,然后对于给定当前状态 sz 中的每个,它计算排序后的后继状态 yi 并返回给人类。
  • 然后,人类根据他/她的发言 x 选择后继状态(如果 i ==1,则计算机是正确的)
  • 状态更新为 s = yi
  • 如果 s==t,则该级别结束

玩家进入下一关

模型和算法核心

语义分析

逻辑形式(动作)上的对数线性模型 z 给定话语 x

其中φ(x,z) ∈ R^d 是特征向量,θ ∈ R^d 是要学习的参数向量。

特征

n-grams(包括跳格)在逻辑形式方面与树-gram 连接

  • 话语方:(' stack red on orange ')、一元语法(' stack '、∑、∑)、二元语法(' red '、' on '、∑)、三元语法(' red '、' on '、' orange ')和跳过三元语法(' stack '、∑、' on ')。
  • 逻辑形式方面:特性对应于逻辑形式中的谓词及其参数。

  • 特性对应于逻辑形式中的谓词及其参数。

生成/解析

在生成逻辑形式中使用波束搜索:对于每个大小 n = 1,.。。,8,通过根据语法规则组合较小大小的逻辑形式,构造一组大小为 n 的逻辑形式(正好有 n 个谓词)。

对于每个 n,保留 100 个逻辑形式 z 具有最高得分θ^Tφ(x,z)。

但是, Z 不保证包含获得观察状态 y 的逻辑形式。所以在训练中使用一个课程,这样在初级阶段只需要简单的动作,给人类一个机会,在移动到更大的复合动作之前,先教计算机一些基本的术语,比如颜色

学问

使用 AdaGrad 和以下损失函数进行单一梯度更新:

建模语用学

通过对上述语义解析模型的初步体验,他们发现它能够很好地学习,但缺乏人类学习者所具有的推理能力

想法

把语言游戏当成说话者(人)和听话者(计算机)之间的合作游戏。

形式上,让 S(x | z)是说话者的策略,L(z | x)是听话者的策略。说话者考虑字面语义分析模型 pθ (z | x)以及话语上的先验 p(x ),而听者考虑说话者 S(x | z)和先验 p(z ):

然后,计算机将使用 L(z | x)而不是 pθ对候选人进行排名

务实的倾听者将说话者塑造成一个合作的代理人,他以一种的方式最大限度地成功交际。

在线学习

使用了两种近似技巧:

  1. 近似所有话语 x 上的难以处理的和,我们仅使用看到的例子来计算归一化常数

  1. 为了避免使用每个新示例存储的当前参数再次解析所有以前的示例

关于在线学习算法的详细解释,请参考论文中的语用在线学习

相关研究

  1. 透过互动学习让程式语言自然化。(2017).来自同一组
  2. 项目链接在这里。
  3. 一个视频链接
  4. 本文从一种核心编程语言开始,允许用户通过定义替代的、更自然的语法和越来越复杂的概念来逐渐“适应”核心语言。
  5. 高迪尔,乔恩和伊戈尔·莫达奇。"情境和目标驱动的语言学习模式."更正 abs/1610.03585 (2016 年):n. pag。
  6. 本文提出了一种通用的情境语言学习范式,旨在产生能够与人类有效合作的健壮的语言主体。这种对话模式是建立在语言理解的功利主义定义之上的。功利主义的定义是由最近强化学习方法的成功所激发的。在强化学习环境中,代理最大化现实世界任务的成功度量,而不需要直接监督语言行为。
  7. 李,纪伟等,《在对话互动中学习》更正 abs/1612.04936 (2016 年):n. pag。代码
  8. 本文通过设计一个模拟器和一组电影领域的综合任务来探索(一般)学习,这些任务允许学习者和教师之间进行互动
  9. 他们认为一个好的对话代理应该有能力通过回答问题和提问与用户互动,重要的是从两种互动中学习。

参考

  1. 王,司大一等:“在互动中学习语言游戏”更正 abs/1606.02447 (2016): n. pag。
  2. shrdurn web 演示、日历应用演示
  3. shrd 返回代码,数据,并在 CodaLab 上进行实验,shrd 返回客户端代码
  4. 王,四大一等,“通过交互学习自然化程序设计语言”(2017).
  5. 高捷、乔恩和伊戈尔·莫尔达奇。"情境和目标驱动的语言学习模式."更正 abs/1610.03585 (2016 年):n. pag。
  6. 李,纪伟等.“在对话互动中学习”更正 abs/1612.04936 (2016 年):n. pag。

使用 Tableau 的交互式简历

原文:https://towardsdatascience.com/interactive-resume-tableau-a1a1bbf86c85?source=collection_archive---------7-----------------------

Static version of my Tableau Resume

对于 2018 年春季学期,我参加了由教授 Rahul Basole 讲授的 MGT CS 8803 数据可视化原理和应用课程,在那里我了解了#datavisualization (#dataviz)的方方面面。

几个课程目标是:-

  • 了解人类感知和认知能力,以设计有效的数据可视化。
  • 根据最终用户的目标和目的,评论不同的可视化技术
  • 了解如何使用商业和开源软件工具设计和实现数据可视化。

作为作业的一部分,我们被要求将专业简历转换成数据可视化。因此,在这里我开始思考如何用素描来完成它,这对于其他人来说可能更容易,但对我来说要复杂得多。有时,灵活性会成为障碍。

Tableau 作为一种数据可视化工具,在演示文稿、仪表盘、统计(定量和定性分析)中经常使用。但是在我看来,把它用于交互式简历是一种严重利用不足的应用。做完这个练习后,如果有人问我你更喜欢哪份简历,我会左右为难。不是因为我做了这两项,而是因为可视化有效地将观点传达给了用户(在这种情况下是读者)。

数据

这种可视化的数据既不容易在网上获得,简历也不能以其原始形式使用。Tableau 足够健壮,可以接受来自各种数据源(JSON、PDF、MySQL、Excel 等)的数据,但它需要大量的数据管理才能使其可用。对于这个任务,我专注于使用数据来揭示我的技能和项目贡献。虽然我的 LinkedIn 和 Github 个人资料上有这些内容,但 Tableau 不一定能马上导入和使用这些内容(至少我还没有找到一种方法来导入网站链接并即时使用这些信息)。

形象化

1.项目捐款

目的是更好地可视化 Github 的贡献。我使用了简单的文本表格,但是以 Github 的方式。不同于通常在一个轴上分配时间,在另一个轴上分配数量特征,我在两个轴上都使用了时间(日期)。工作日在行,季度为列。Github 将其进一步细化到每月,给出全年的概况。由于空间的限制,我不得不满足于四分之一。人们可以看到我对 Github 的贡献并与 Tableau 进行比较。

2。技能时间表

我希望它是一个垂直的时间线(像传统的简历),但 Tableau 不允许垂直的时间线(到目前为止)。我将技能时间线显示为多年来技能水平总和的趋势。颜色显示技能的细节。该视图根据技能进行筛选,保留 10 个成员中的 9 个。组织和工作等附加信息已被编码为标签。

Tableau 仪表板

Tableau 上的仪表板帮助用户将不同的工作表缝合在一起。它有助于统一所有数据,并利用链接特性来触发跨多个工作表的交互。此外,Tableau Public 允许用户在他们的平台上发布他们的 Tableau 仪表盘,以便轻松分享他们的工作。这是一个非常方便的工具,可以让你的可视化快速启动和运行。

这是我的期末成绩,可以和我在网站上找到的简历相比较。

用 Jupyter 窗口小部件实现决策树的交互式可视化

原文:https://towardsdatascience.com/interactive-visualization-of-decision-trees-with-jupyter-widgets-ca15dd312084?source=collection_archive---------2-----------------------

Photo by Aaron Burden on Unsplash

决策树是广泛用于分类和回归任务的监督模型。在本文中,我们将讨论决策树分类器,以及如何动态地可视化它们。这些分类器在训练数据上建立一系列简单的 if/else 规则,通过它们来预测目标值。决策树很容易解释,因为它们的结构和我们可视化建模树的能力。

使用 sk learnexport _ graphviz函数,我们可以在 Jupyter 笔记本中显示该树。在这个演示中,我们将使用 sklearn 葡萄酒数据集。

from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn import tree
from sklearn.datasets import load_wine
from IPython.display import SVG
from graphviz import Source
from IPython.display import display# load dataset
data = load_wine()

# feature matrix
X = data.data

# target vector
y = data.target

# class labels
labels = data.feature_names

# print dataset description
print(data.DESCR)estimator = DecisionTreeClassifier()
estimator.fit(X, y)

graph = Source(tree.export_graphviz(estimator, out_file=None
   , feature_names=labels, class_names=['0', '1', '2'] 
   , filled = True))display(SVG(graph.pipe(format='svg')))

Decision Tree with default parameters

在树形图中,每个节点都包含分割数据的条件(if/else 规则),以及该节点的一系列其他指标。Gini 指的是 Gini 杂质,节点杂质的度量,即节点内样本的同质程度。当一个节点的所有样本都属于同一个类时,我们说这个节点是纯的。在这种情况下,没有必要进一步分裂,这个节点被称为叶。Samples 是节点中实例的数量,而 value 数组显示每个类中这些实例的分布。在底部,我们可以看到节点的多数类。当 export_graphviz 的 filled 选项设置为 True 时,每个节点根据多数类进行着色。

虽然很容易理解,但决策树往往会通过构建复杂的模型来过度拟合数据。过度拟合的模型很可能不能很好地概括“看不见的”数据。防止过拟合的两种主要方法是预修剪和后修剪。预修剪是指在创建树之前限制树的深度,而后修剪是指在构建树之后移除无信息的节点。

Sklearn 学习决策树分类器只实现预剪枝。预修剪可以通过几个参数来控制,例如树的最大深度、节点保持分裂所需的最小样本数以及叶子所需的最小实例数。下面,我们在相同的数据上绘制一个决策树,这次设置 max_depth = 3。

Decision Tree with max_depth = 3

这个模型没有我们最初训练和绘制的模型那么深入,因此也没有那么复杂。

除了预修剪参数,决策树还有一系列其他参数,我们在构建分类模型时会尝试优化这些参数。我们通常通过查看准确性度量来评估这些参数的效果。为了掌握参数的变化如何影响树的结构,我们可以再次在每个阶段可视化树。我们可以利用Jupyter Widgets(ipywidgets)来构建我们的树的交互式绘图,而不是每次做出改变时都绘制一个树。

Jupyter 小部件是交互式元素,允许我们在笔记本中呈现控件。安装 ipywidgets 有两个选项,通过 pip 和 conda。

和皮普一起

pip install ipywidgets
jupyter nbextension enable --py widgetsnbextension

与康达

conda install -c conda-forge ipywidgets 

对于这个应用程序,我们将使用交互功能。首先,我们定义一个训练和绘制决策树的函数。然后,我们将这个函数以及每个感兴趣的参数的一组值传递给交互函数。后者返回一个我们用 display 显示的小部件实例。

from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn import tree
from sklearn.datasets import load_wine
from IPython.display import SVG
from graphviz import Source
from IPython.display import display                               
from ipywidgets import interactive# load dataset
data = load_wine()# feature matrix
X = data.data# target vector
y = data.target# class labels
labels = data.feature_names
def plot_tree(crit, split, depth, min_split, min_leaf=0.2):estimator = DecisionTreeClassifier(random_state = 0 
      , criterion = crit
      , splitter = split
      , max_depth = depth
      , min_samples_split=min_split
      , min_samples_leaf=min_leaf)
    estimator.fit(X, y)graph = Source(tree.export_graphviz(estimator
      , out_file=None
      , feature_names=labels
      , class_names=['0', '1', '2']
      , filled = True))

    display(SVG(graph.pipe(format='svg')))return estimatorinter=interactive(plot_tree 
   , crit = ["gini", "entropy"]
   , split = ["best", "random"]
   , depth=[1,2,3,4]
   , min_split=(0.1,1)
   , min_leaf=(0.1,0.5))display(inter)

Initial view of widget

在本例中,我们公开了以下参数:

  • 标准:节点处分割质量的度量
  • 拆分器:每个节点的拆分策略
  • max_depth:树的最大深度
  • min_samples_split:节点中所需的最小实例数
  • min_samples_leaf:一个叶节点所需的最小实例数

最后两个参数可以设置为整数或浮点数。浮动被解释为实例总数的百分比。关于参数的更多细节,你可以阅读 sklearn 类文档。

Widget demonstration

这个交互式小部件允许我们修改树参数,并动态地查看图形变化。通过这种相互作用,我们能够通过揭示每一步产生的变化来掌握每个参数的影响。

虽然这不是模型性能评估或参数调整的工具,但它有几个好处。通过检查深度、节点数量和叶子的纯度,它可以作为评估模型复杂性的一种手段。另一方面,它可以给我们关于数据的有用见解,因为我们可以看到树使用了多少和哪些特性。此外,我们也许能够发现清楚地将我们的样品区分到不同类别的条件。

总之,我发现这种交互式可视化是一种有趣的工具,可以更深入地理解构建决策树的抽象过程,脱离特定的数据集,这将为我们下次为我们的一个项目构建决策树提供一个良好的开端!

Jupyter 笔记本中的交互式可视化

原文:https://towardsdatascience.com/interactive-visualizations-in-jupyter-notebook-3be02ab2b8cd?source=collection_archive---------0-----------------------

这篇文章并不详尽地介绍了如何直接从 Jupyter 笔记本上创建交互式内容。内容主要是指数据可视化工件,但我们将看到我们可以轻松地扩展到通常的图表之外,为各种场景提供有价值的交互位,从数据探索到动画。

我将从简单介绍数据可视化开始,并更好地定义本文中的交互性的范围和含义。
然后我将提供一个相关工具的快速概述(Plotly 和 ipywidgets)以及一些关于 Jupyter 生态系统的一般性建议。
最后,我将展示一些具体的例子,大部分是指我的个人项目,以及我依靠这些互动片段获得的改进。这最后一部分正是为了在 Jupyter 这样一个令人印象深刻的框架上展示这些工具的能力。这一切都是为了推动你尝试自己的项目,并传播这个词。

介绍

数据可视化是成为一名优秀的数据科学家所需的核心技能之一——或者任何其他与数据相关的角色。它既能让您(或团队中的其他人)更好地理解数据集的本质,又能向外部受众(技术和非技术)传达正确的信息。

当搜索“数据可视化”时,最常见的建议编程库之一是 D3.js,但是一些断言,当你搜索非常个性化/定制化的方法和随之而来的结果时,它是值得深入这样的工具的。如果您的目标是更直接和“标准”的可视化,那么您选择的语言中已经可用的包可能是更好的方法。

对于 Python 生态系统来说,不可避免地从 Matplotlib 的基础块开始,然后可能扩展到更高级别的替代(例如 Seaborn 、 Bokeh )。一个额外的越来越有保障的选择——特别是对于数据科学数字——是使用 Jupyter 笔记本。我相信 Jupyter 崛起背后的主要力量和原因之一是它如何将不同的媒体打包在一个简单的解决方案中:你编码,你写作,你可视化。它不仅能让你在工作时变得流畅愉快,还能极大地简化这类工作的分享,无论是出于教育还是协作目的。

就个人而言,结合 Jupyter 的支持,我发现 Matplotlib+Seaborn 组合非常适合我的可视化需求,甚至比 Pandas 的额外嵌入式绘图功能更好。当需要动画功能时,Matplotlib 1.1 版中的简单动画框架在可用性和结果之间提供了很好的折衷。

但在某一点上,人们觉得需要更多的东西。并不是完全转向新工具,只是在必要时依赖它们。在这方面,我个人认为有两种类型的互动:

  • 互动图:关于当前探索的特定点或区域的实时信息,加上高亮/隐藏特定内容的可能性。
  • 用于内容交互的窗口小部件:这超越了图形情节,扩展到其他类型的媒体和内容,通常需要一个或多个复杂的 UI 元素来收集外部输入。

对于前者,我现在在使用plottly中找到了极大的满足感。对于后者,我专门搜索了可以轻松嵌入 Jupyter 的解决方案,这样我几乎可以将我的任何笔记本变成交互式仪表盘。为此,我们将研究 ipywidgets。

工具

在讨论之前提到的工具的细节之前,这里有一些我认为值得分享的关于 Python 和 Jupyter 生态系统的个人建议。

第一个建议:使用 Anaconda (一个 Python 发行版等等)。
第二个建议:使用虚拟环境(相当于 Anaconda)。是关于管理多个独立的 Python 环境。
第三个建议:参见 nb_conda_kernels 从你的 Jupyter 笔记本管理多个环境/内核。
第四条建议:用 Jupyter 扩展定制你的 Jupyter 的****

Plotly

Plotly 让创建和分享互动情节变得非常容易。这个库的一个伟大之处在于它为你的图形提供了无缝的网络托管能力。通常情况下,你可以获得一个免费账户,但代价是你托管的一切都将是公开的。但与一些人所说的相反,如果需要的话你绝对可以完全离线使用 Plotly,直接在笔记本上渲染互动情节,并能够将它们导出为(仍然互动的)HTML 文件。

如果这还不够的话,还有两个特征让这个包更有吸引力:plot_mpl和袖扣。
前一种方法执行从纯 matplotlib 图形到交互式 Plotly 图形的直接转换(这种操作还不完美,但正在迅速变得越来越好)。

相反,袖扣是熊猫数据框和图案之间的自动绑定。这种绑定再次保证,只需一次调用,您就可以获得 dataframe 内容的高质量数据可视化,具有自动解析和格式化日期时间值以及推断的色调和列标签管理等优点。

开始使用 Plotly(在一般情况下)就像跑步一样简单

pip install plotly
pip install cufflinks

然后,您必须为您的每台笔记本电脑选择在线或离线绘图。同时记住.iplot()是显示 Jupyter 内部内容的神奇语法。

ipywidgets

ipywidgets 是关于在你的笔记本中易于构建的交互式图形用户界面。这又是一个在灵活性和可用性之间做出巨大妥协的工具。

在安装步骤之后,真正要做的就是发挥创造力,了解如何在项目中最好地利用新功能。这个想法是让小部件作为你的内容的交互界面,例如滑块、复选框、按钮、文本框等。

当您开始使用时,最令人印象深刻的是交互功能,,它根据传递的参数自动生成您的小部件(可能有多个组件)。例如,传递带有布尔值的参数会自动生成相应的复选框;取而代之的是,一个值列表被转换成一个下拉小部件。
所有的机制都非常简单,并且在官方文档中有详细的解释,所以让我们转到展示部分。

显示优点的东西

现在,为了演示到目前为止所解释的内容,加上一点无耻的自我宣传,这里有一个来自个人项目的例子列表。

包含不同的更复杂的项目的事实实际上是为什么我没有简单地为这个条目写一个笔记本,而是选择了一个老式的文章。然而,你可以在我的 Github repo 中找到所有的项目,一些简单到自包含和可复制的笔记本

示例 1: Fitbit 仪表板

这个例子可能会让我的一些量化自拍伙伴特别感兴趣,或者总的来说,对于那些为了探索和获得洞察力而想要轻松显示个人数据的人来说,不需要太多精细的工作(构建一个完整的仪表板应用程序),但仍然保证拥有灵活性——可能是变化无常的——需求(是的,这意味着编码)。

我的 Fitbit 睡眠数据就是一个例子,其中我在可能的不同粒度级别(例如,一天、工作日、一年)有不同的统计数据要可视化(例如,睡眠效率、睡眠值计数、入睡的第一分钟)。一种选择是使用 Seaborn factorplot 并一次可视化目标统计数据的子集。

Static Seaborn Factorplot for summary stats

这对于简单的情况有效,但是当内容变得更加混乱时,情节就失去了有效性。例如,转到按月显示工作日统计数据,我们可以得到如下结果

Static weekday stat by month

已经有太多的信息了,如果你不像我一样擅长颜色,就不容易找到数据。如果这是一个打印的情节,它肯定不符合良好的沟通和情节指南。转移到 Plotly 为这种情况提供了一个解决方案,可以通过三种方式进行:

  • 将 matplotlib 图形直接传递给iplot_mpl方法
  • 使用 Plotly 语法从头开始创建您的绘图
  • 使用袖扣,直接从你的熊猫数据框中绘图

在这种情况下,最后一个选项是最直接和最精确的,因为原始数据格式只是将工作日转换为目标 stat 的行、月和列,这里是我按月列出的工作日睡眠效率。

综合所有这些,我最终得到了一个我认为相当不错的睡眠数据仪表板。

Demo of Jupyer as dashboard for Fitbit sleep data

示例 2:营养数据库

您可能希望有一个快速的界面来访问一些结构化的内容。例如,我在研究营养数据时就这么做了。特别是,我转述了美国农业部国家营养数据库。这是一个非常丰富和相对复杂的数据集,但可以很容易地用 Python 和 Pandas 解决。

有人可能会争辩说,这只是数据库范围内的事情,一个合适的 SQL 工具将证明更适合这种情况。这可能是真的,但是我仍然想展示通过 ipywidgets 在 Jupyter 中实现这一点是多么容易,以及对于某些人来说,这最终会成为比单独的数据库系统更好的临时选择,尤其是在数据探索期间。

Interacting with Nutrient Database

在这里,您可以看到我再次简单地依赖于interact函数,传递我的原始 Python 函数(参数化的),加上将自动映射到小部件的参数:

  • food: 空列表,转换为文本框
  • 营养素:数据库中存在的独特营养素的列表,它被转换成一个下拉小部件

示例 3:动画

如前所述,一旦你手头有了好的工具,交互性对于各种场景都是很方便的,动画肯定是其中之一。

一个简单的 intslider(由interact在传递一个(min,max,step)元组时自动生成),可以极大地帮助探索不同分辨率或复杂性的动画,正如这个模拟康威的生命游戏所示。

Conway’s Game of Life simulation

此外,您可以构建自定义界面来快速浏览您的数据和相关分析结果,就像在这个示例中,我可视化了 CNN 在猫狗数据集上训练的内部图层输出。

CNN Layer Output Heatmap Demo

有许多可视化的框架和工具可用,特别是对于机器学习任务,但有时像上面这样快速而肮脏的解决方案可以节省大量时间,同时提供所有实际需要的信息和功能。

结论

所有展示都是使用所列工具提供的非常基本的功能获得的。例如,考虑所有与 ipywidgets 相关的例子都简单地使用了interact并对生成的小部件进行类型推断。正如官方文档中的很好地解释的那样,通过自定义小部件定义和组合可以获得更多。

通过这个条目,我想准确地传播这个词,并迅速显示这些工具在简单性和定制化方面的巨大价值。同时,我也对关于数据可视化工具的一般反馈感兴趣,特别是关于可能包含更多边缘领域(如 3D 建模和动画)的框架。

作为最后的赠品,我想强烈推荐这个库,它提供了可选的 Jupyter 主题和额外的视觉定制。

使用 Spark 交互式分析 100 GB JSON 数据

原文:https://towardsdatascience.com/interactively-analyse-100gb-of-json-data-with-spark-e018f9436e76?source=collection_archive---------2-----------------------

你知道有史以来印刷的最重的书是什么吗?让我们通过使用 Python 中的 Spark 探索开放库数据集来找出答案。

本教程的目的是教育,最初由Valentin Dali bard 博士Raoul-Gabriel Urma 博士:https://Cambridge Spark . com/content/tutorials/interactive-analyze-100 GB-of-JSON-data-with-Spark/index . html

您将初步了解 Spark 中的一些可用操作,以及如何使用这些操作来交互式地探索在 Excel 等简单工具中不方便使用(由于大小和结构)的数据集。您还将看到如何在 Spark 中轻松表达 MapReduce 操作。注意,我们使用 Spark 以一种方便的方式运行一个特别的分析。还有其他方法可以分析这个数据集,比如使用 Impala 。

在本教程中,您将学习:

  • 如何开始使用 Spark,
  • 如何使用mapflatMapfilterreduce模式,以及
  • 如何使用groupByKeyreduceByKey功能。

数据集

开放图书馆是一项旨在为“每本已出版的书创建一个网页”的倡议您可以在终端中使用以下命令下载他们的数据集,该数据集大约有 20GB 的压缩数据。--continue标志让您可以分几次下载数据。

wget --continue [http://openlibrary.org/data/ol_cdump_latest.txt.gz](http://openlibrary.org/data/ol_cdump_latest.txt.gz)

然后,您可以使用以下命令提取数据—您需要大约 100GB 的可用空间:

gunzip -k ol_cdump_latest.txt.gz | cut -f 5 > ol_cdump.json

要使用 EC2 上的数据集,请将其上传到亚马逊 S3。使用以下命令,使用您的 S3 存储段名称,将数据上传到 S3。像前三步一样,这一步需要时间来完成。

aws s3 cp ol_cdump.json s3://my_bucket

或者,如果你想处理更小的数据集以节省时间,你可以从 https://s3-eu-west-1.amazonaws.com/csparkdata/ol_cdump.json 的下载一个数据样本。下面的技术是可行的,但是结果会有所不同。

如果你想在本地分析数据,你可以在你自己的机器上安装 PySpark,忽略 Amazon 的设置,直接跳到数据分析。

启动亚马逊 EMR

如果您想在集群上开始使用 Spark,一个简单的选项是Amazon Elastic MapReduce(EMR)。它为您提供了一个包含几台预配置了 Spark 的机器的集群。如果您需要快速处理存储在 S3 上的大型文件,这将非常有用。

这里有一个 youtube 视频向你展示如何开始:

开始一本齐柏林飞船笔记本

亚马逊 EMR Spark 实例与 Zeppelin 笔记本一起提供:jupyter 笔记本的替代品,直接运行在 Spark 之上。点击亚马逊 EMR 上的 Zeppelin 链接,打开 Zeppelin 笔记本。

Zeppelin 允许在同一个笔记本中使用多种语言。使用单元格顶部的%pyspark来运行 Python 命令。

%pyspark
print("Hello")

或者,您可以执行 shell 指令:

%sh
echo "World !"

导入数据集

第一步是在一个 Spark RDD 中加载数据集:一个抽象数据处理方式的数据结构——在分布式模式下,数据在机器之间分割——并允许您应用不同的数据处理模式,如过滤、映射和简化。要了解更多关于 rdd 以及本教程其余主题的信息,请查看我们的大数据训练营。

您可以读取文件,并使用操作textFile将每一行转换成 RDD 的一个元素。

path = "s3://my_bucket/ol_cdump.json"
raw_data = sc.textFile(path)

请注意,如果您正在使用文件的本地副本,您可以将一个标准文件路径(例如,ol_cdump.json)传递给该函数。

RDD 中的每个元素都是代表一个 json 值的单个字符串。因此,第二步是在 Python 字典中转化这些元素,以便更容易地分析它们。json.loads函数将一个 JSON 值解析成一个 Python 字典。方法.map(f)返回一个新的 RDD,其中f已经应用于原始 RDD 中的每个元素。将两者结合起来解析 RDD 的所有行。

import json
dataset = raw_data.map(json.loads)
dataset.persist()

注意,代码还调用了方法.persist()来缓存内存中的 RDD,以便以后可以直接重用。

RDD 数据集中的每个元素现在都是一个将键映射到值的字典。

探索性数据分析

您可以从找出条目的数量开始:

dataset.count()

这将返回 126,107,177 。还不错,书挺多的!

您可以使用first操作偷偷查看数据,返回第一个元素。或者,take(k)返回第一个k元素的列表

dataset.take(10)

输出相当长。但是你会看到返回的条目包含了number_of_pagestitleweightisbn_10等书籍属性。

为了理解您所拥有的数据的形状,您可以提取字典中所有可用的不同键。你可能想再次使用map操作,但是你必须使用flatMap来代替。实际上,对于每一个字典,您提取一个键列表,所以map将产生一个键列表的 RDD。使用flatMap,所有的键都被折叠成一个单一的平面 RDD。考虑flatMap的一种方式是,它允许您对每个元素应用一对多的转换,而不是像map那样一对一。

在这个 RDD 键上,您可以使用distinct删除重复的键。最后,使用collect操作将惟一键的 RDD 提取到一个 Python 列表中。

keys = dataset.flatMap(**lambda** d: d.keys()).distinct().collect()
len(keys)

504 唯一键!一本书有很多不同的属性。

实际上,并不是所有的 JSON 对象都有相同的属性:经常会缺少属性。例如,数据库可能提到一本书的页数,但不一定提到它的印刷尺寸。这就是你从真实世界的数据中得到的。在开放图书馆数据集中,你会发现很多多样性!为了探索这种多样性,您可以使用groupByKey对每个元素的属性数量进行分组:

groups = dataset.map(**lambda** e: (len(e.keys()), e)).groupByKey()

但是坚持住!这实际上根本不是好的做法!您可以拥有一个最常见的键数,其中包含大量与该键相关联的数据,比如 20GB。在这种情况下,您将创建一个 20GB 的 Python 列表,这会使您的机器崩溃或导致交换。

计算相同结果的更好方法是使用reduceByKey:

count_per_key = (
    dataset
    .map(**lambda** e: (len(e.keys()), 1))
    .reduceByKey(**lambda** x, y: x + y)
    .collect()
  )

reduceByKey操作将为每个键生成的1相加,最终返回每个属性的计数。Zeppelin 在这里非常有用,因为它让您可以通过其界面直接可视化结果:

print("%table")
**for** e in count_per_key:
  print("%d\t%d" % (e[0], e[1]))

告诉我重量

你设法获得了一些关于数据的见解。不如来点更有趣的东西,你可以在高级晚宴上提出来?你很幸运。JSON 的一个属性是每本书的重量。你好奇想知道最重的书是什么吗?让我们希望这至少是一本有趣的书。当您浏览数据集时,您会注意到weight属性有不同的单位:kg、g、盎司、磅等。一切都很乱!你将需要一个函数,可以正常化的重量,所以你可以比较每本书:

**def** sanitizedWeight(weight_str):
  w = convertToKilograms(weight_str)
  **if** w > 1e6:  *#books above 1e6 kg are errors*
    **return** 0.0
  **else**:
    **return** w**def** convertToKilograms(weight_str):
  result = weight_str.split()
  **if**(len(result)) != 2:
    **return** 0
  **try**:
    number = float(result[0])
  **except** ValueError:
    **return** 0
  **if**(result[1] == 'pounds' or result[1] == 'lb' or result[1] == 'lbs'):
    **return** number * 453.592 * 1e-3
  **elif**(result[1] == 'ounces' or result[1] == 'oz' or result[1] == 'oz.'):
    **return** number * 28.35 * 1e-3
  **elif**(result[1] == 'grams' or result[1] == 'gms' or result[1] == 'g'):
    **return** number * 1e-3
  **elif**(result[1] == 'kilograms' or result[1] == 'kilo' or result[1] == 'kg'):
    **return** number
  **else**:
    **return** 0

注意,仍有少数带有权重属性的书籍被该函数忽略。有些重量的数字和单位之间没有空格,有些是不寻常的大写字母(GM,KGms),有些是错别字(ounds),有些是其他奇怪的符号。让我们把重点放在分析数据集上——但是如果您愿意,可以随意改进这个解析器。

要找到最重的书,你只需要迭代数据并减少它,每次选择最重的书。

heaviest_book = (
    dataset
    .filter(**lambda** e: "weight" in e and "title" in e)
    .map(**lambda** e: (e, sanitizedWeight(e["weight"])))
    .reduce(**lambda** x, y: x **if** x[1]>y[1] **else** y)
  )

那么答案是什么呢?不幸的是,这是一个有点失望,输出是一本书的 200,000 磅(刚刚超过 90 公吨)与扼杀标题!

({… u'weight': u'200000 pounds', …,  u'title': u'u fool,stupid', …}, 90718.40000000001)

显然有人在数据库中插入了一个虚拟条目!这有点令人失望。

想象一下书是什么时候出版的怎么样?您可以使用所学的操作生成以下查询:

booksWithDate = (
    dataset
    .filter(**lambda** e: "publish_date" in e)
    .map(**lambda** e: (e["publish_date"], 1))
    .reduceByKey(**lambda** x, y: x + y)
    .collect()
  )**def** is_int(s):
  **try**:
    t = int(s)
    **return** True
  **except** ValueError:
    **return** FalsebooksWithDate = (
    dataset
    .filter(**lambda** e: "publish_date" in e)
    .filter(**lambda** e: len(e["publish_date"]) >=4)
    .filter(**lambda** e: is_int(e["publish_date"][-4:]))
    .map(**lambda** e: (int(e["publish_date"][-4:]), 1))
    .reduceByKey(**lambda** x, y: x+y)
    .collect()
  )

同样,在处理真实年份之前,您需要处理和清理数据。您现在可以使用 Zeppelin 中的可视化功能来获得一个不错的分布:

print("%table")
**for** r in d:
  print("%d\t%d" % (r[0], r[1]))

如果您对 Spark 和大数据系统更感兴趣,请查看我们即将举办的网络研讨会系列:

[## 数据科学网络研讨会系列

在世界各地加入我们,了解数据科学、大数据分析和在以下领域使用的先进技术…

cambridgespark.com](https://cambridgespark.com/webinar)

与此同时,你可以测试你的星火技能,尝试找到这些问题的答案:

  • 数据集里哪个作者写的或者合著的书最多?
  • 数据集中哪一类书最受欢迎?

Kaggle.com 有趣的数据集

原文:https://towardsdatascience.com/interesting-datasets-on-kaggle-com-3a4a250b0b85?source=collection_archive---------6-----------------------

Kaggle.com 是数据科学家和机器学习工程师中最受欢迎的网站之一。虽然 Kaggle 还没有 GitHub 受欢迎,但它是一个正在崛起的社交教育平台。

这是一个数据科学家寻找有趣数据集的好地方,他们已经做了一些预处理。你可以找到图像数据集,CSV,金融时间序列,电影评论等。此外,所有这些数据集都可以从 kaggle.com 完全免费下载。

55,000 首歌词— CSV

这个数据集是一个矩阵,由每首歌曲的快速描述和文本挖掘中的整首歌组成。需要做一些预处理,将这个数据集导入字符级递归神经网络。然而,对于这项任务来说,这是一个非常大的数据集,使用 RNN 来学习生成歌词的结果非常令人印象深刻。如果在本地笔记本电脑上运行,预计这个模型需要一点时间来训练,训练这个模型是开始在 Jupyter 笔记本电脑中使用 EC2 实例进行数据科学项目的一个很好的练习。

获取数据集

辛普森一家人物数据-图像

对于神经网络风格转换算法来说,这是一个非常有趣的数据集。这些算法可能很难构建,但尝试将真实人脸映射到辛普森一家角色的风格将是一个非常有趣的项目。这项技术可能会为电视节目的动画软件带来重大变革,如《瑞克和莫蒂》、《一家人》、《F 代表家庭》、《杰克骑士》等。

获取数据集

SF 工资— csv

开始使用 RNN/序列模型的绝佳数据集。

水果 360 数据集—图像

难以置信的图像数据集,轻量级文件,(只有 386 MB 的图像数据集)。非常适合对不同类型的水果进行分层,这些水果有可能被用于改善工业化农业。这也是一个有趣的数据集,可以用来玩生成对立网络,生成独特的水果设计。

获取数据集

通过声音识别性别—带音频统计的 csv

我希望看到这个数据集作为原始音频文件,但是,仍然有可能建立一个神经网络分类器,将能够把语音数据分为男性和女性。这些模型有一些有趣的应用程序,如 Siri 和 Alexa。

获取数据集

南方公园对话—包含对话句子的文本 csv

对于单词级递归神经网络来说,这可能是一个非常有趣的测试。想象神经网络算法在《南方公园》等喜剧节目中写笑话或台词,是一件很迷人的事情。这个软件对于许多不同媒介的小说作者来说非常有用。

获取数据集

TED 演讲— csv

非常有趣的文本挖掘数据集。使用诸如 TED 演讲的描述、持续时间、时间和地点作为 TED 演讲视频在线评论数量的预测指标。

获取数据集

各国幸福报告— csv

参与社会科学研究的人将他们的快乐程度从 0 到 10 分不等。这些参与者按照他们的国家和地区进行地理排序。对于 Google Maps API 或 D3.js 可视化库来说,这是一个很大的地图可视化问题。

关于使用谷歌地图的更多信息,请查看他们的 API 文档页面:

【https://developers.google.com/maps/documentation/

当我完成上传我的 Keras 项目,在耐克和阿迪达斯篮球鞋上建立一个图像识别分类器时。创建我自己的数据集帮助我更加欣赏 Python 中的 web 管理数据集和 web 抓取 html 解析工具。如果您对使用这些数据集之一构建图像识别模型感兴趣,请查看该项目。

[## 如何构建卷积网络分类器:耐克 vs 阿迪达斯鞋

我为#100DaysOfMLCode 做的一个实验是建立一个图像分类器,它可以区分 Nike…

blog.usejournal.com](https://blog.usejournal.com/how-to-build-a-convolutional-network-classifier-81eef880715e)

CShorten

Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对数据科学、深度学习和软件工程感兴趣。主要用 Python,JavaScript,C++编码。请关注更多关于这些主题的文章。

来自 R/Pharma 的有趣包装

原文:https://towardsdatascience.com/interesting-packages-taken-from-r-pharma-e89639788180?source=collection_archive---------12-----------------------

几个月前,我参加了马萨诸塞州剑桥的 R/Pharma 会议。

作为一个收获,我想到了我的项目,以及如何利用别人提供的解决方案进行改进。 R 中的解决方案主要是 R 包。我是一名在监管环境下的优秀程序员,所以我列出的解决方案主要是为了帮助你,如果你提供 a)优秀的应用程序 b)统计软件包 c)经过验证的解决方案。让我们来看看哪些 R 包我以前不知道,现在发现确实有用:

个人信息管理程序

我的大多数同事制作的是报告。实际上是大量的统计报告。由于我们在受监管的环境中工作,所有报告都要经过双重检查。意思是你给它编程,别人也给它编程。你不想浪费时间,因为有一个数学包的更新导致了数字的差异。有一个非常好的解决方案。

Packrat 允许您存储在某个会话/项目中使用的所有包。packrat 的主要指南可以在描述 it 的 RStudio 博客中找到。

Packrat 不仅会存储所有的包,还会存储所有的项目文件。它集成在 RStudio 的用户界面中。它让你可以很快地与不同的同事分享项目。

我认为主要的不足是需要一个服务器,在那里你存储所有这些包。这个应该可以用 RStudio 新的包管理器解决。另一个缺点是与一些软件包不兼容。我注意到我不能用 packrat 使用 R-3.4.2 下的 BH 包,必须找到一个解决办法。

Diffdf

我必须告诉你,我浪费了将近 30%的时间来比较数据。这是测试统计结果或用你编写的统计应用程序进行计算的一项重要任务。在制药和诊断应用中,最相关的方面之一是数据的有效性。确保我们在临床研究、质量保证或日常工作中使用的数据来自同事。对我来说,这个任务不仅很难,而且更难记录。

基兰·马丁的 diffdf 包真正解决了这个任务。它不仅为你提供了一个整洁的界面,还提供了精心安排的结果。

基本的 diffdf 示例如下所示:

library(diffdf)
iris2 <- iris
for (i in 1:3) iris2[i,i] <- i^2
iris2$new_var <- "hello"
class(iris2$Species) <- "some class"
diffdf(iris, iris2)

您可以看到,基本上新引入了一个列,在 3 个不同的数字列中更改了三个值,并且更改了一个列的类型。所有这三个变化都显示在单独的输出中。此外,还提到了没有变化的内容,如果您没有检查正在比较的数据帧是否完全相等,这可能会非常有帮助。

Differences found between the objects!

A summary is given below.

There are columns in BASE and COMPARE with different classes !!
All rows are shown in table below

  ==================================
   VARIABLE  CLASS.BASE  CLASS.COMP 
  ----------------------------------
   Species     factor    some class 
  ----------------------------------

There are columns in COMPARE that are not in BASE !!
All rows are shown in table below

  =========
   COLUMNS 
  ---------
   new_var 
  ---------

Not all Values Compared Equal
All rows are shown in table below

  =================================
     Variable    No of Differences 
  ---------------------------------
   Sepal.Length          1         
   Sepal.Width           1         
   Petal.Length          1         
  ---------------------------------

All rows are shown in table below

  ============================================
     VARIABLE    ..ROWNUMBER..  BASE  COMPARE 
  --------------------------------------------
   Sepal.Length        1        5.1      1    
  --------------------------------------------

All rows are shown in table below

  ===========================================
    VARIABLE    ..ROWNUMBER..  BASE  COMPARE 
  -------------------------------------------
   Sepal.Width        2         3       4    
  -------------------------------------------

All rows are shown in table below

  ============================================
     VARIABLE    ..ROWNUMBER..  BASE  COMPARE 
  --------------------------------------------
   Petal.Length        3        1.3      9    
  --------------------------------------------

输出易于阅读,并且包含了完成预期任务所需的所有信息:比较两个数据帧。我真正喜欢的是关于观察到多少差异的快速反馈。如果您有很多不同之处,除了您给列的每个值加了+1,您可以立即在摘要中看到这一点。

此外,详细信息不仅给出了值的差异,还给出值在表中的位置,这是一个巨大的优势。有时,分析大型患者群组,可以揭示测量值 99,880 的差异,并且您不希望在找到这一差异之前滚动“匹配”表。因此,这个详细视图相对于其他包来说是一个巨大的优势。

档案保管员

旨在改进数据分析结果管理的 R 包。该软件包的主要功能包括:

(I)管理包含 R 对象及其元数据(对象的属性和它们之间的关系)的本地和远程储存库;

㈡将 R 对象存档到储存库;

(iii)通过其独特的挂钩共享和检索对象(及其谱系);

㈣搜索具有特定属性或与其他对象有关系的对象;

㈤核实物品的身份及其创造背景。

这在可再生数据分析中非常重要。在药理学项目中,你经常需要在很长时间后重现病例。档案包允许在文件中存储模型、数据集和整个 R 对象,这些对象也可以是函数或表达式。现在,您可以将文件存储在长期数据存储器中,甚至在 10 年后,使用 packrat + archivist,您将能够重现您的研究。

任务(ii)示例—恢复模型

此示例给出了存储在包中的模型列表

library(archivist)
models <- asearch("pbiecek/graphGallery", patterns = "class:lm")
modelsBIC <- sapply(models, BIC)sort(modelsBIC)

任务(I)示例—本地存储对象

我在 https://github.com/zappingseb/RPharma2018packages的文件夹里有一个 data.frame。您的任务是创建一个新的 data.frame,将其存储在arepo_new文件夹中,并将其添加到恢复的 data.frame 中。如果一切顺利,data.frames 的总和显示为位置(1,1)的 2。

library(archivist)repo <- "arepo_new"
createLocalRepo(repoDir = repo, default = TRUE)df <- data.frame(x=c(1,2),y=c(2,3))
saveToRepo(df)setLocalRepo("arepo")
df2 <- loadFromLocalRepo("4a7369a8c51cb1e7efda0b46dad8195e",value = TRUE)df_test <- df + df2print(df_test[1,1]==2)

在此任务中,您可以看到,我的旧 data.frame 不仅存储为 data.frame,而且还具有独特的可复制 md5 哈希。这使得在几年后再次找到东西并展示它正是你所需要的东西变得非常容易。

logR

logR 包可以用来记录你的分析步骤。如果您在分析中有很多步骤,并且需要知道这些步骤需要多长时间,状态是什么(错误、警告)以及确切的调用是什么,那么您可以使用 logR 来存储所做的一切。因此,logR 连接到 PostGres 数据库,并在那里记录您分析的所有步骤。我强烈推荐使用 logR,以防您不确定您的分析是否会再次运行它。logR 将检查你的每一个步骤,因此任何失败都会被存储。如果您的下一步运行只是因为设置了任何环境变量,您肯定会看到这一点。下面是来自作者的 logR 的基本示例:

library(logR)

# setup connection, default to env vars: `POSTGRES_DB`, etc.
# if you have docker then: docker run --rm -p 127.0.0.1:5432:5432 -e POSTGRES_PASSWORD=postgres --name pg-logr postgres:9.5
logR_connect()
# [1] TRUE

# create logr table
logR_schema()

# make some logging and calls

logR(1+2) # OK
#[1] 3
logR(log(-1)) # warning
#[1] NaN
f = function() stop("an error")
logR(r <- f()) # stop
#NULL
g = function(n) data.frame(a=sample(letters, n, TRUE))
logR(df <- g(4)) # out rows
#  a
#1 u
#2 c
#3 w
#4 p

# try CTRL+C / 'stop' button to interrupt
logR(Sys.sleep(15))

# wrapper to: dbReadTable(conn = getOption("logR.conn"), name = "logr")
logR_dump()
#   logr_id              logr_start          expr    status alert                logr_end      timing in_rows out_rows  mail message cond_call  cond_message
#1:       1 2016-02-08 16:35:00.148         1 + 2   success FALSE 2016-02-08 16:35:00.157 0.000049163      NA       NA FALSE      NA        NA            NA
#2:       2 2016-02-08 16:35:00.164       log(-1)   warning  TRUE 2016-02-08 16:35:00.171 0.000170801      NA       NA FALSE      NA   log(-1) NaNs produced
#3:       3 2016-02-08 16:35:00.180      r <- f()     error  TRUE 2016-02-08 16:35:00.187 0.000136896      NA       NA FALSE      NA       f()      an error
#4:       4 2016-02-08 16:35:00.197    df <- g(4)   success FALSE 2016-02-08 16:35:00.213 0.000696145      NA        4 FALSE      NA        NA            NA
#5:       5 2016-02-08 16:35:00.223 Sys.sleep(15) interrupt  TRUE 2016-02-08 16:35:05.434 5.202319000      NA       NA FALSE      NA        NA            NA

RInno——像 Windows 应用程序一样闪亮的应用程序

我们经常构建闪亮的应用程序,需要本地 PC 设置才能运行良好。例如,我们是否构建了一个闪亮的应用程序,通过用户的活动目录登录来访问 MySQL 数据库。为了在没有登录窗口的情况下获取 Active Directory 凭证,我们只需在本地运行这个闪亮的应用程序。由于部门中并非所有用户都知道如何运行 R + runApp(),RInno 对我来说听起来是一个很好的解决方案。

RInno 将你闪亮的应用打包成一个.exe文件,你的用户可以直接在他们的 PC 上运行。这也将允许他们在本地存储的 Excel 文件上使用奇特的 ggplot 功能。这在数据受到安全保护而无法上传到服务器的情况下非常重要。开发者给出的教程可以帮助你很好的理解这个问题以及如何解决。

码尺

Photo by patricia serna on Unsplash

包含评估统计模型预测能力所需的所有度量的软件包。我在第一次治疗中看到了这个包裹。每当我们想到一种恰当的方法来衡量我们的模型和数据之间的差异时,我们会讨论很多不同的方法。当然写sqrt(sum((x-y)**2))很简单,但是用标尺two_class_example %>% rmse(x, y)看起来更好。在码尺中,你知道你的数据来自哪里,你可以很容易地交换函数rmse,而在我展示的例子中,你需要重新编码整个功能。码尺以后会省去我们团队很多讨论。很高兴它出来了。

有趣的概率问题:自我修正随机漫步

原文:https://towardsdatascience.com/interesting-probability-problem-self-correcting-random-walks-30acc15ec2c6?source=collection_archive---------7-----------------------

这是另一个与众不同的问题,一个你在教科书上找不到的问题。你可以用数据科学的方法来解决它(我的方法),但是有一些空闲时间的数学家可以找到一个优雅的解决方案。与你的同事或你的学生分享,看看他们对数学有多精通。虽然我还没有找到最终的解决方案(也许你会找到),但我能够在单独使用 Excel 的 1-2 个小时的工作中取得实质性的进展。)我的包含所有计算的 Excel 电子表格可以从本文中获得。你不需要很深的统计学背景就能很快发现一些有趣的结果。从初学者到老手的计算机科学家、软件工程师、quants、BI 和分析专家也将能够享受它!

问题

我们正在处理一个随机过程,它比随机漫步复杂不了多少。随机漫步也被称为醉酒漫步,因为它们代表了一个喝醉的家伙看似随机地左右移动,并随着时间的推移而迷失的路径。这里的过程是一个自校正随机行走,也称为受控随机行走,在这个意义上,与随机行走相比,醉酒程度较低的行走者能够越来越多地校正任何偏离直线路径的情况,随着时间的推移,在每一步都略微过度或不足校正。其中一个模型参数(正参数 a )代表步行者的醉酒程度,其中 a = 0 为最差。除非 a = 0,否则校正的幅度会随着时间的推移而减小,直到最终(在许多步之后)行走者几乎直线行走并到达其目的地。该模型代表了许多物理过程,例如,在某种程度上由政府控制以避免泡沫和内爆的股票市场的行为,其定义如下:

先从 X (1) = 0 开始,递归定义 X ( k )如下,对于 k > 1:

要阅读全文和初步解决方案,请点击此处。

物联网蓬勃发展 15 万亿市场

原文:https://towardsdatascience.com/internet-of-things-booming-15-trillion-market-88fde1da2113?source=collection_archive---------12-----------------------

物联网、人工智能和区块链等智能技术具有颠覆性的前景。这对市场意味着什么?

物联网是区块链、人工智能和智能技术中蓬勃发展的技术之一。新的令人兴奋的解决方案正以越来越快的速度出现,旨在解决我们这个时代的问题,如气候变化,以及缓解地球上的日常生活。

在开始讨论物联网之前,我们先来看看区块链、加密货币和人工智能市场。技术的结合带来了颠覆性的希望。颠覆三重奏。

T2 的加密货币 T3 市场去年蓬勃发展。在今年的下跌趋势之前,它已经接近 1 万亿美元,这导致加密货币市场下降到 2000 亿美元。尽管大幅下跌超过 70%,加密货币市场仍比去年的最低水平高出 5 倍。

随着首次发行硬币,区块链行业的规模不断增长,ICO 从市场上筹集了数百万美元的资金。与去年的 60 亿美元相比,今年总共筹集了 200 亿美元。

世界经济论坛估计,到 2027 年,全球 GDB 100 万亿美元中,将有 10 万亿美元来自与区块链相关的技术。

人工智能 AI 正在让机器像人类一样工作,这最终将把人们从日常工作中解放出来,从事更具生产力和创造性的工作。通过提供答案和完成简单的操作,AI 已经在让我们的日常生活变得更加简单。你需要记住,机器仍然会保持逻辑,这使得它们如此令人敬畏。人类也将在未来完成创造性的任务。它需要我们训练创造力和想象力。

人工智能市场

人工智能即将创造超过 1000 亿美元的收入。

此外,麦肯锡预测,到 2025 年,人工智能将在 19 个行业的 9 项业务职能中每年创造 3.5 至 5.8 万亿美元的收入。

物联网

凯文·阿什顿(Kevin Ashton)有一句名言,他将物联网概念化,被许多人誉为物联网之父:

“如果我们有知道所有事情的计算机——在没有我们任何帮助的情况下使用它们收集的数据——我们将能够跟踪和计算所有事情,并大大减少浪费、损失和成本。我们会知道什么时候东西需要更换、修理或召回,它们是新鲜的还是已经过了最佳状态。我们需要让计算机拥有自己收集信息的手段,这样它们就可以自己看到、听到和闻到这个世界的所有随机荣耀。RFID 和传感器技术使计算机能够观察、识别和理解世界,而不受人类输入数据的限制。”—物联网之父凯文·阿什顿

我们每天都离阿什顿的梦想越来越近。物联网设备的数量正以前所未有的速度增长。汽车、衣服、手表等等都与互联网相连。据统计数据显示,到 2025 年,物联网设备将超过 700 亿台。(下图)

我们可以看到来自 IBM、微软、英特尔、甲骨文等大公司的物联网解决方案的不断发展……新的创新解决方案正在获得宣传,并已经解决了我们在日常生活中面临的实际问题。物联网与其他智能技术相结合,将在拯救我们的星球和建设地球可持续性方面发挥重要作用。因此,物联网市场正在经历高速增长,并吸引了大量投资。每年有近 1000 亿美元流向物联网市场,预计到 2020 年,物联网公司的年收入将超过 4500 亿美元(贝恩

以下是贝恩公司对不同行业年收入的划分:

幸运的是,当我们看到物联网的市场潜力时,这些投资有望带来一些高回报。

根据麦肯锡的报告,到 2025 年,通过连接物理世界和数字世界,每年可以产生 11.1 万亿美元的收入。与全球 100 万亿美元的 GDP 相比,这是一个相当大的数字。此外,根据商业内幕情报报告物联网 2018 ,到 2025 年可能会有近 15 万亿的物联网总投资。

物联网支出也在增长。这份名为 的半年度全球物联网支出指南 的报告估计,到 2021 年,支出将每年增长 1 万亿美元。

令人印象深刻的数字,但我们已经看到来自大公司和新创业公司的创新。解决现实生活问题并为所有人提供舒适生活的解决方案。

孟买的实习:事实与数据

原文:https://towardsdatascience.com/internships-in-mumbai-facts-and-figures-34064ac7d1c7?source=collection_archive---------1-----------------------

在过去的几个月里,我已经养成了通过各种方式获取数据的习惯,并试图从中找出规律或任何有用的见解。我的一次恶作剧是寻找实习数据,在一个风雨交加的圣诞节,我把这些数据拆开,试图找到可能对我或任何涉足企业界的用户有用的信息。

先说数据集。该数据集包含孟买市的 894 个实习机会,范围从全职职位到几周的短期工作。该数据集包含以下特征:

1.标题

2.组织

3.持续时间

4.定期津贴

5.组织详细信息

6.实习详情

至于是怎么获得的。我只能说它包括一个相当漂亮的图书馆。

调查结果:

我试图回答的第一个问题是找出支付给实习生的平均工资。这是一个小问题,因为它涉及到将每周和每件产品的销售额转换为每月付款。但是一旦这样做了,就很容易发现平均实习月薪是 卢比。6655

有趣的是,实习工资最高是 卢比。联邦快递的一个网络开发职位 3 万英镑。数据科学在薪酬方面排名第四,薪酬为 11 卢比。25000在想分析。

除了薪水,我也很好奇什么职位有最大的机会。这个结果并不令人惊讶。业务发展(又称销售)的机会最多,为 192 个。紧随其后的是社交媒体营销,81。平面设计、内容写作和人力资源也相当受欢迎。尽管 Web 开发比移动应用程序开发有更多的机会。数据录入的机会最少。

数据集包含 694 个唯一的雇主 。在 694 个机会中,计划我的健康机会最多(9)。他们的机会涵盖了相当广泛的范围,从营养师/营养学家到法律/法律职位。紧随他们之后的是股权风险金融公司,他们也有很多机会,包括网络开发、商业联盟和其他职位,如内容写作。有趣的是,一般来说,机会最多的地方都是初创企业。

撇开薪水、角色和公司类型不谈,实习求职者脑海中闪现的下一个问题是承诺。数据集中的大多数机会寻求 2-3 个月的最低承诺。

实习期限

我还试图找出组织喜欢使用的“流行语”。因此,在对每个实习描述进行分词和词干化之后,我开始根据 tf-idf 分数提取关键词。现在这种方法并不完美,在每次机会提取的 20 多个关键词中有一些噪音,但它确实非常接近。此外,由于输入源的标准化语言的性质,结果也偏向某些单词。

Internship Buzzwords

这篇文章仅仅是一些探索性的数据分析,可以帮助一些大学生更好地规划他们的实习和获得高价值技能的方法。当我想到新的问题来询问数据或者当我得到新的数据时,我打算更新这篇文章。请随意分享这篇文章,这样更多的人可以了解这些趋势,并可能从他们的实习经历中获得更多。此外,如果你有任何问题,请在评论中留下,我会尽我所能用我掌握的数据来回答。

解释机器学习模型

原文:https://towardsdatascience.com/interpretability-in-machine-learning-70c30694a05f?source=collection_archive---------2-----------------------

不管您的数据科学解决方案的最终目标是什么,最终用户总是更喜欢可解释和可理解的解决方案。此外,作为一名数据科学家,您将始终受益于模型的可解释性,以验证和改进您的工作。在这篇博文中,我试图解释可解释性在机器学习中的重要性,并讨论一些简单的动作和框架,你可以自己进行实验。

xkcd on Machine Learning

为什么机器学习中的可解释性很重要?

在传统统计学中,我们通过调查大量数据来构建和验证假设。我们建立模型来构建规则,这些规则可以整合到我们的心理过程模型中。例如,一家营销公司可以建立一个将营销活动数据与财务数据相关联的模型,以确定什么构成了有效的营销活动。这是一种自上而下的数据科学方法,可解释性是关键,因为它是所定义的规则和流程的基石。因为相关性通常不等于因果性,所以在做出决策和解释决策时,需要对模型有充分的理解。

在自下而上的数据科学方法中,我们将部分业务流程委托给机器学习模型。此外,机器学习使全新的商业理念成为可能。自下而上的数据科学通常对应于手工和费力任务的自动化。例如,制造企业可以在机器上安装传感器,并进行预测性维护。因此,维护工程师可以更高效地工作,并且不需要执行昂贵的定期检查。模型的可解释性对于验证模型所做的事情是否符合您的期望是必要的,它允许与用户建立信任,并简化从手工到自动化过程的转换。

In a top-down process, you iteratively construct and validate a set of hypotheses. In a bottom-up approach, you attempt to automate a process by solving a problem from the bottom-up.

作为一名数据科学家,您通常关心微调模型以获得最佳性能。数据科学通常被框定为:“给定带有标签 y 的数据 X,找出误差最小的模型”。虽然训练性能模型的能力对于数据科学家来说是一项关键技能,但能够放眼全局也很重要。数据和机器学习模型的可解释性是数据科学管道实际“有用性”的关键方面之一,它确保模型与您想要解决的问题保持一致。虽然在构建模型时很容易迷失自己,但能够正确解释您的发现是数据科学过程中必不可少的一部分。

Interpreting models is necessary to verify the usefulness of the model predictions.

为什么对你的模型进行深入分析是必要的?

作为一名数据科学家,关注模型可解释性有几个原因。尽管这两者之间有重叠,但它们抓住了可解释性的不同动机:

识别并减少偏见。

任何数据集中都可能存在偏差,这取决于数据科学家如何识别并尝试解决它。数据集的大小有限,可能无法代表全部人口,或者数据采集过程可能没有考虑潜在的偏差。偏差通常只有在彻底的数据分析之后或者当模型预测和模型输入之间的关系被分析时才变得明显。如果你想了解更多不同类型的偏见,我强烈推荐下面的视频。请注意,解决偏见没有单一的解决方案,但意识到潜在的偏见是实现可解释性的关键一步。

偏见的其他例子如下:

例如,word2vec 向量包含性别偏见,这是由于它们被训练的语料库中存在固有偏见。当你用这些单词嵌入来训练一个模型时,搜索“技术简介”的招聘人员会把女性简历放在最下面。

例如,当您在小型手动创建的数据集上训练对象检测模型时,通常情况是图像的宽度太有限。需要不同环境、不同闪电条件和不同角度下的各种物体图像,以避免模型只适合数据中的噪声和不重要的元素。

说明问题的背景。

在大多数问题中,您使用的数据集只是您试图解决的问题的粗略表示,而机器学习模型通常无法捕捉真实任务的全部复杂性。可解释的模型有助于您理解和考虑模型中包含(不包含)的因素,并在根据模型预测采取措施时考虑问题的背景。

提高通用性和性能。

高的可解释性通常会导致模型更好地概括。可解释性不是理解模型中所有数据点的每一个细节。扎实的数据、模型和对问题的理解的结合对于拥有一个表现更好的解决方案是必要的。

道德和法律原因。

在金融和医疗保健等行业,审计决策过程并确保其没有歧视或违反任何法律是至关重要的。随着 GDPR 等数据和隐私保护法规的兴起,可解释性变得更加重要。此外,在医疗应用或无人驾驶汽车中,一个不正确的预测就会产生重大影响,因此能够“验证”该模型至关重要。因此,系统应该能够解释它是如何得出给定建议的。

解读你的模型

关于模型可解释性的一个常见说法是,随着模型复杂性的增加,模型可解释性下降的速度至少也一样快。特征重要性是解释模型的一个基本(通常是免费的)方法。即使对于深度学习等黑盒模型,也存在提高可解释性的技术。最后,将讨论作为模型分析工具箱的 LIME 框架。

特征重要性

  • 广义线性模型

广义线性模型( GLM 的)都基于以下原则:
如果你将你的特征 x 与模型权重 w 进行线性组合,并通过挤压函数 f 输入结果,你就可以用它来预测各种各样的反应变量。GLM 最常见的应用是回归(线性回归)、分类(逻辑回归)或泊松过程建模(泊松回归)。训练后获得的权重是特征重要性的直接代表,并且它们提供了模型内部的非常具体的解释。

例如,在构建文本分类器时,您可以绘制最重要的特征,并验证模型是否过度拟合噪声。如果最重要的词不符合您的直觉(例如,名称或停用词),这可能意味着模型适合数据集中的噪声,并且它不会在新数据上表现良好。

An example of a neat visualisation for text interpretability purposes from TidyTextMining.

  • 兰登森林和 SVM 的

甚至诸如基于树的模型(例如随机森林)的非线性模型也允许获得关于特征重要性的信息。在随机森林中,在训练模型时,特征重要性是免费的,因此这是验证初始假设和识别模型正在学习“什么”的一种很好的方式。基于核的方法中的权重,例如 SVM 的,通常不是特征重要性的很好的代理。核方法的优势在于,您可以通过将特征投影到核空间来捕捉变量之间的非线性关系。另一方面,仅仅把权重看做特征重要性并不能公正地对待特征交互。

By looking at the feature importance, you can identify what the model is learning. As a lot of importance in this model is put into time of the day, it might be worthwhile to incorporate additional time-based features. (Kaggle)

  • 深度学习

由于参数的剪切数量以及提取和组合特征的复杂方法,深度学习模型因其不可解释性而臭名昭著。由于这类模型能够在许多任务中获得最先进的性能,许多研究都集中在将模型预测与输入联系起来。

The amount of research on interpretable machine learning is growing rapidly (MIT).

特别是当转向处理文本和图像数据的更复杂的系统时,很难解释模型实际上在学习什么。目前研究的主要焦点主要是将输出或预测与输入数据联系和关联起来。虽然这在线性模型的背景下相当容易,但对于深度学习网络来说,这仍然是一个未解决的问题。两种主要的方法是基于梯度或基于注意力。

-在基于梯度的方法中,在反向过程中计算的目标概念的梯度被用于产生一个映射,该映射突出了用于预测目标概念的输入中的重要区域。这通常应用于计算机视觉的环境中。

Grad-CAM, a gradient-based method is used in visual caption generation. Based on the output caption, the method determines which regions in the input image were important.

-基于注意力的方法通常用于顺序数据(如文本数据)。除了网络的正常权重,注意力权重被训练为“输入门”。这些注意力权重决定了每个不同元素在最终网络输出中的比重。除了可解释性之外,在例如基于文本的问答环境中的注意力也导致更好的结果,因为网络能够“聚焦”它的注意力。

In question answering with attention, it is possible to indicate which words in the text are most important to determine the answer on a question.

石灰

Lime 是一个更通用的框架,旨在使“任何”机器学习模型的预测更具可解释性。

为了保持与模型无关,LIME 通过局部修改模型的输入来工作。因此,不是试图同时理解整个模型,而是修改特定的输入实例,并监控对预测的影响。在文本分类的上下文中,这意味着一些单词例如被替换,以确定输入的哪些元素影响预测。

如果你对机器学习的可解释性有任何问题,我很乐意在评论中阅读。如果你想收到我博客的更新,请在 Medium 或 Twitter 上关注我!

使用 XGBoost 的可解释机器学习

原文:https://towardsdatascience.com/interpretable-machine-learning-with-xgboost-9ec80d148d27?source=collection_archive---------0-----------------------

模型可解释性

这是一个关于错误解释你的机器学习模型的危险,以及正确解释它的价值的故事。如果您发现集合树模型(如梯度推进机器或随机森林)的稳健准确性很有吸引力,但也需要解释它们,那么我希望您会发现这是有益的。

假设我们的任务是为一家银行预测一个人的财务状况。我们的模型越准确,银行赚的钱就越多,但是由于这种预测用于贷款申请,我们也需要在法律上对为什么做出预测做出解释。在对几种模型类型进行实验后,我们发现 XGBoost 中实现的梯度提升树具有最好的准确性。不幸的是,解释 XGBoost 为什么做出预测似乎很难,所以我们只能选择退回到线性模型,或者弄清楚如何解释我们的 XGBoost 模型。没有数据科学家愿意放弃准确性…所以我们决定尝试后者,并解释复杂的 XGBoost 模型(恰好有 1,247 棵深度为 6 的树)。

经典的全球特征重要性度量

第一个显而易见的选择是在 Python XGBoost 接口中使用 plot_importance()方法。它给出了一个非常简单的条形图,代表了我们数据集中每个特性的重要性:(复制这篇文章的代码在 Jupyter 笔记本中)

Results of running xgboost.plot_importance(model) for a model trained to predict if people will report over $50k of income from the classic “adult” census dataset (using a logistic loss).

如果我们查看 XGBoost 返回的特征重要性,我们会发现年龄支配着其他特征,显然是收入的最重要预测因素。我们可以在这里停下来,向我们的经理报告直观上令人满意的答案:年龄是最重要的特征,其次是每周工作时间和受教育程度。但是作为优秀的数据科学家……我们看了一下文档,发现在 XGBoost 中有三个度量特性重要性的选项:

  1. 体重。一个特征被用于跨所有树分割数据的次数。
  2. 封面。使用某个特征在所有树之间分割数据的次数,这些树由经过这些分割的训练数据点的数量加权。
  3. 增益。使用特征进行分割时获得的平均训练损失减少量。

这些是我们可能在任何基于树的建模包中找到的典型的重要性度量。重量是默认选项,因此我们决定尝试其他两种方法,看看它们是否有所不同:

Results of running xgboost.plot_importance with both importance_type=”cover” and importance_type=”gain”.

令我们沮丧的是,我们发现 XGBoost 提供的三个选项中的每一个的特性重要性排序都非常不同!对于覆盖法来说,资本收益特征似乎是最能预测收入的,而对于收益法来说,关系状态特征支配了所有其他特征。这应该会让我们在不知道哪种方法是最好的情况下,依赖这些方法来报告特性重要性时感到非常不舒服。

是什么决定了特性重要性的好坏?

如何比较一种特征归属方法和另一种特征归属方法并不明显。我们可以测量每种方法在数据清理、偏差检测等任务上的最终用户性能。但是这些任务只是对特征归属方法质量的间接测量。这里,我们将定义两个我们认为任何好的特征归属方法都应该遵循的属性:

  1. 一致性。每当我们改变一个模型,使它更加依赖于一个特性,那么这个特性的重要性就不会降低。
  2. 准确度。所有特征重要性的总和应等于模型的总重要性。(例如,如果重要性是通过 R 值来衡量的,那么每个特征的属性总和应该是整个模型的 R 值)

如果一致性不成立,那么我们不能比较任何两个模型之间的属性特征重要性,因为然后 具有更高的分配属性并不意味着模型实际上更依赖于那个特征

如果准确性不成立,那么我们不知道每个特征的属性如何组合来表示整个模型的输出。我们不能在方法完成后就规范化属性,因为这可能会破坏方法的一致性。

当前的归因方法是否一致和准确?

回到我们作为银行数据科学家的工作…我们意识到一致性和准确性对我们很重要。事实上,如果一个方法不一致,我们不能保证具有最高属性的特性实际上是最重要的。因此,我们决定使用两个非常简单的树模型来检查每种方法的一致性,这两个树模型与我们在银行的任务无关:

Simple tree models over two features. Cough is clearly more important in model B than model A.

模型的输出是基于个人症状的风险评分。模型 A 只是二元特征发烧咳嗽的简单“与”函数。模型 B 具有相同的功能,但是每当咳嗽为是时,具有+10。为了检查一致性,我们必须定义“重要性”。这里我们将从两个方面定义重要性:1)当我们删除一组特征时,模型的预期精度T21 的变化。2)当我们移除一组特征时,模型的预期输出的变化。

重要性的第一个定义度量了特征对模型的全局影响。而第二个定义测量特征对单个预测的个性化影响。在我们的简单树模型中,咳嗽特征在模型 B 中显然更重要,当发烧咳嗽都为是时,对于全球重要性和个体预测的重要性都是如此。

上面的权重覆盖增益方法都是全局特征归属方法。但是,当我们在银行部署我们的模型时,我们还需要为每个客户提供个性化的解释。为了检查一致性,我们在简单的树模型上运行了五种不同的特征归属方法:

  1. 树 SHAP。我们提出了一种新的个性化方法。
  2. 萨巴斯。一种个性化启发式特征归因方法。
  3. 意思是(|树 SHAP|)。基于个体化树 SHAP 属性平均大小的全局属性方法。
  4. 增益。与上述 XGBoost 中使用的方法相同,也等同于 scikit-learn 树模型中使用的基尼系数。
  5. 拆分计数。表示 XGBoost 中密切相关的“权重”和“覆盖”方法,但使用“权重”方法进行计算。
  6. 排列。当单个特征在测试数据集中被随机置换时,模型精度的下降。

Feature attributions for model A and model B using six different methods. As far we can tell, these methods represent all the tree-specific feature attribution methods in the literature.

之前除了特征置换的方法都不一致!这是因为与模型 a 相比,它们在模型 B 中对咳嗽的重视程度较低。不一致的方法无法正确地对最有影响的特征给予更多的重视。敏锐的读者会注意到,这种不一致性早在我们研究的经典特征归因方法在同一模型上相互矛盾时就已经出现了。精度属性呢?事实证明,树 SHAP、Sabaas 和 Gain 都与前面定义的一样准确,而特征置换和分裂计数则不准确。

或许令人惊讶的是,像 gain(基尼系数)这样广泛使用的方法会导致如此明显的不一致结果。为了更好地理解为什么会发生这种情况,我们来看看模型 A 和模型 b 的增益是如何计算的。为了简单起见,我们假设数据集的 25%落在每个叶中,并且每个模型的数据集都有与模型输出完全匹配的标签。

如果我们将均方误差(MSE)视为我们的损失函数,那么在模型 a 中进行任何分割之前,我们从 1200 的 MSE 开始,这是来自 20 的恒定均值预测的误差。在模型 A 中拆分了发烧之后,MSE 下降到 800,因此 gain 方法将这 400 的下降归因于发烧特性。在咳嗽特征上再次分裂导致 MSE 为 0,增益方法将这 800 的下降归因于咳嗽特征。在模型 B 中,同样的过程导致发烧特征的重要性为 800,咳嗽特征的重要性为 625:

Computation of the gain (aka. Gini importance) scores for model A and model B.

通常,我们认为靠近树根的特征比靠近树叶的特征更重要(因为树是贪婪地构建的)。然而,增益方法偏向于将更多的重要性归于较低的分裂。这种偏见导致了不一致,当咳嗽变得更重要时(因此它在根上分裂了),它的归属重要性实际上下降了。个性化的 Saabas 方法(由 treeinterpreter 包使用)在我们沿着树向下时计算预测的差异,因此它也遭受了同样的偏向于树中较低位置的分裂。随着树木越来越深,这种偏见只会越来越大。相比之下,树 SHAP 方法在数学上等同于对所有可能的特征排序的预测差异进行平均,而不仅仅是由它们在树中的位置指定的排序。

这不是一个巧合,只有树 SHAP 是一致和准确的。假设我们想要一个既一致又准确的方法,那么只有一种方法来分配特性的重要性。详细内容在我们最近的 NIPS 论文中,但总结是,来自博弈论的关于利润公平分配的证明导致了机器学习中特征归属方法的唯一性结果。这些独特的值被称为 Shapley 值,以 Lloyd Shapley 在 20 世纪 50 年代得出的值命名。我们这里使用的 SHAP 值是与 Shapley 值相关的几种个性化模型解释方法的统一。树 SHAP 是一种快速算法,可以在多项式时间内准确计算树的 SHAP 值,而不是传统的指数运行时间(见 arXiv )。

自信地诠释我们的模型

坚实的理论证明和快速实用的算法相结合,使 SHAP 价值观成为一个强有力的工具,自信地解释树木模型,如 XGBoost 的梯度推进机。有了这个新方法,我们回到解释我们的银行 XGBoost 模型的任务:

The global mean(|Tree SHAP|) method applied to the income prediction model. The x-axis is essentially the average magnitude change in model output when a feature is “hidden” from the model (for this model the output has log-odds units). See papers for details, but “hidden” means integrating the variable out of the model. Since the impact of hiding a feature changes depending on what other features are also hidden, Shapley values are used to enforce consistency and accuracy.

我们可以看到,关系特征实际上是最重要的,其次是年龄特征。由于 SHAP 值保证了一致性,我们不需要担心在使用增益或分割计数方法之前发现的矛盾。然而,由于我们现在对每个人都有个性化的解释,我们可以做的不仅仅是做一个条形图。我们可以为数据集中的每个客户绘制特征重要性图。 shap Python 包让这变得简单。我们先叫 shap。TreeExplainer(模型)。shap_values(X)来解释每个预测,然后调用 shap.summary_plot(shap_values,X)来绘制这些解释:

Every customer has one dot on each row. The x position of the dot is the impact of that feature on the model’s prediction for the customer, and the color of the dot represents the value of that feature for the customer. Dots that don’t fit on the row pile up to show density (there are 32,561 customers in this example). Since the XGBoost model has a logistic loss the x-axis has units of log-odds (Tree SHAP explains the change in the margin output of the model).

这些特征按平均值(| SHAP 树|)排序,因此我们再次将关系特征视为年收入超过 5 万美元的最强预测因素。通过绘制特征对每个样本的影响,我们还可以看到重要的异常影响。例如,虽然资本收益在全球范围内并不是最重要的特征,但对一部分客户来说却是最重要的特征。按特征值着色向我们展示了一些模式,比如年轻会降低你挣 5 万美元以上的机会,而高等教育会增加你挣 5 万美元以上的机会。

我们可以在这里停下来向我们的老板展示这个图,但是让我们更深入地挖掘其中的一些特性。对于年龄特征,我们可以通过绘制年龄 SHAP 值(对数几率的变化)与年龄特征值的关系来实现:

The y-axis is how much the age feature changes the log odds of making over $50K annually. The x-axis is the age of the customer. Each dot represents a single customer from the data set.

在这里,我们看到了年龄对收入潜力的明显影响,正如 XGBoost 模型所捕捉到的那样。请注意,与传统的部分相关图(显示更改特征值时的平均模型输出)不同,这些 SHAP 相关图显示了交互影响。尽管数据集中的许多人都是 20 岁,但是他们的年龄对他们预测的影响程度是不同的,正如 20 岁时点的垂直分布所示。这意味着其他特征正在影响年龄的重要性。为了了解这种影响的部分特征,我们用受教育的年数来给这些点着色,结果发现,在 20 多岁时,高教育水平会降低年龄的影响,但在 30 多岁时会提高这种影响:

The y-axis is how much the age feature changes the log odds of making over $50K annually. The x-axis is the age of the customer. Education-Num is the number of years of education the customer has completed.

如果我们绘制另一张每周工作小时数的依赖关系图,我们会看到,每周工作 50 小时左右会有更多的好处,如果你已婚,额外工作不太可能意味着高收入:

Hours worked per week vs. the impact of the number of hours worked on earning potential.

解释你自己的模型

这个简单的演练旨在反映您在设计和部署自己的模型时可能会经历的过程。 shap 包很容易通过 pip 安装,我们希望它能帮助你满怀信心地探索你的模型。它包含了比本文更多的内容,包括 SHAP 相互作用值,模型不可知的 SHAP 值估计,以及其他可视化。笔记本可以在各种有趣的数据集上展示所有这些特征。例如,你可以在一个解释 XGBoost 死亡率模型的笔记本中,根据你的健康检查,找出你将死的主要原因。对于 Python 以外的语言,树 SHAP 也被直接合并到核心的 XGBoost 和 LightGBM 包中。

具有附加模型的可解释 ML

原文:https://towardsdatascience.com/interpretable-ml-with-additive-models-a3a4100643cc?source=collection_archive---------6-----------------------

今年早些时候,我去听了微软研究院 Rich Caruana 的精彩演讲,他讲述了如何为医学应用构建可解释的 ML 模型。作为可解释 ML 的支持者,Rich Caruana 去年在 NIPS 与 Yann LeCun 在进行了一场激烈的辩论。这里我总结一下他的想法,并给出自己的解读。

主要的想法是,我们可以建立一个人类可解释的 ML 模型,通过使它与明确指定的交互相加。那么什么是加法模型呢?想想好的旧回归模型。在简单的回归模型中,一个变量的影响不依赖于其他变量,它们的影响加起来就是总的影响。如果我们能够单独理解每个变量或者稍微理解一下,我们就能够解释整个模型。然而,在存在相互作用的情况下,这将不再是真实的。

两个变量之间的相互作用是指两个变量的影响相互依赖。交互会使模型更难解释。即使我们理解了每个变量是如何改变模型预测的,当几个变量发生变化时,我们仍然无法计算出模型预测。就像有几种有益的药物,结合起来就变成了毒药。当有许多变量和许多相互作用时,就不可能解开变量的影响。

这正是大多数 ML 车型的问题所在。在决策树中,我们可以先用一个变量分裂分支,然后再用另一个变量分裂;这实质上是创造互动。我们可以通过跟随分裂来解释一个小的决策树,但是当树变得更大或者形成一个随机的森林时,这很容易变成一个痛苦。在多层神经网络中,由于每个隐藏单元是输入的非线性组合,因此当通过隐藏层传播时,会隐式地创建交互。

我们可以通过允许每个变量具有更灵活但仍有附加效应来使简单的回归模型更强大。我们不会假设每个变量都有线性效应,而是用任意函数 f 来建模变量的边际效应,为了保持模型的可解释性,我们将显式地添加交互作用;同样,每个交互都可能产生任意效果。

这不是一个全新的想法,因为它显然类似于广义加法模型。然而,在 GAMs 中,平滑样条通常用于 f 。在论文中,里奇·卡鲁阿纳增加了一个更 ML 的转折;函数 f 用随机森林建模(针对每个变量)。我认为高斯过程可能同样有效,如果不是更好的话;尽管实际上随机森林更方便。

我们可以通过查看每个变量的边际效应来解释模型。代替读取回归模型系数,模型预测如何作为感兴趣变量的函数而变化的图明确地讲述了一个相当完整的故事。正如我们在上面看到的,呼吸率似乎在 30 到 60 之间有很强的正效应,这种效应在 30 之前不会出现,在 60 以上就会减弱。如果我们有一个简单的回归模型,估计的影响在整个范围内会是适度的正的和线性的。通过更好地模拟每个变量的边际效应,我们可以得到一个更准确的模型。其实这个模型和其他黑箱 ML 模型一样好。

最后一部分是我对此的看法。为了更好地模拟边际效应,另一种方法是变量转换或“特征工程”,这是本书中最古老的技巧。根据我的经验,当处理偏斜变量时,标准的预处理方法通常不会很好地工作;而用他们训练出来的 ML 模型会很差。百分点转换可以解决这一问题,因为它强制每个变量不偏不倚,并且在同一尺度上。为了解释这个模型,我们可以像 Rich Caruana 一样进行反向转换(反向百分位数)并绘制边际效应。

****

例如,感兴趣的变量是谷歌对本地企业的评级,这在整体上是高度倾斜的,并且在不同的企业类型之间是不同的。直接使用原始评级不会产生好的模型。在执行百分位数转换后,我们可以更好地捕捉在谷歌搜索中被推荐的概率的边际效应。当评分较低时(0 到 3),几乎没有任何影响。但当评分高于 3 时,随着评分的增加,这种影响实际上会稍大一些。这个结果是有道理的,因为谷歌可能永远不会推荐二星级的企业;在评级较高的企业中,0.1 的增长将产生平局打破效应。

归根结底,所有的模型都是错的。很难说变量应该总是有累加效应。但是实践中的大多数 ML 模型都是由人类使用或为人类使用的。重要的是我们能够理解 ML 模型。假设可加性和更好地模拟边际效应肯定会给我们更多可解释的模型。

可解释神经网络

原文:https://towardsdatascience.com/interpretable-neural-networks-45ac8aa91411?source=collection_archive---------3-----------------------

解释黑盒模型是机器学习中的一个重大挑战,可以显著减少采用该技术的障碍。

在之前的一篇文章中,我讨论了使用形状值解释复杂的机器学习模型。总而言之,对于特定的特征,当模型可以看到该特征时和当它不能看到该特征时,会比较模型对于特定数据点的预测,这种差异的大小告诉我们该特征对于模型的预测有多重要。

在下面的例子中,我们建立了一个模型来预测某人是否想要冰淇淋,它由三个特征组成:他们是否喜欢冷食,他们现在所处的季节以及他们是否喜欢甜食。Shap 值允许我们解释单个数据点的模型输出—在本例中,对于 Bob:

Inspired by the diagrams in the shap values paper

这个冰淇淋模型有两点需要注意:首先,当模型看不到特征时,特征的效果与模型预测的基线进行比较。其次,特征重要性的总和(红色和蓝色箭头)是该基线和 Bob 的模型实际预测之间的差异。

不幸的是,虽然某些机器学习算法(如 XGBoost)可以处理空特征值(即看不到某个特征),但神经网络不能,因此需要一种略有不同的方法来解释它们。迄今为止,最常见的方法是考虑输入相对于预测的梯度。

在这篇文章中,我将讲述使用这些渐变背后的直觉,以及由此产生的两种具体技术:集成渐变和深度提升。

使用梯度解释神经网络

可能最难解释的模型——也是我们将用作灵感的模型——是回归。在一个回归中,每个特征 x 被分配一个权重 w ,这直接告诉我该特征对模型的重要性。

具体来说,对于特定数据点的第 i 个特征,该特征对模型输出的贡献为

这个重量 w 代表什么?因为回归是

然后

换句话说,分配给第 i 个特征的权重告诉我们该特征相对于模型预测的梯度:模型的预测如何随着特征的改变而改变。

方便的是,这个梯度对于神经网络来说很容易计算。因此,与回归一样,一个特性的贡献是

,也许梯度可以用来解释神经网络的输出。

在尝试使用这种方法时,我们会遇到两个问题:

首先,特性的重要性是相对的。对于梯度增强决策树,特征的 shap 值告诉我,相对于没有看到该特征的模型,特征如何改变模型的预测。由于神经网络不能处理空输入特征,我们需要重新定义一个特征相对于其他东西的影响。

为了克服这一点,我们将定义一个新的基线:我的输入与什么进行比较?一个例子是 MNIST 数字数据集。因为所有的数字都是白色的,背景是黑色的,所以一个合理的背景应该是全黑的图像,因为这不代表关于数字的任何信息。

Some MNIST digit examples, and a reasonable baseline for them

为其他数据集选择背景要简单得多——例如, ImageNet 数据集的背景应该是什么?我们稍后将讨论这个问题的解决方案,但是现在让我们假设我们可以为每个数据集找到一个基线。

第二个问题是,使用输出相对于输入的梯度对于线性模型(如回归)很有效,但对于非线性模型则很快失效。为了了解原因,让我们考虑一个仅由一个 ReLU 激活组成的“神经网络”,其基线输入为 x=2

现在,让我们考虑第二个数据点,在 x = -2

ReLU(x=2) = 2 ,而 ReLU(x=-2) = 0 ,所以我的输入特征 x = -2 相对于基线改变了我的模型的输出 2。我的模型输出的这种变化必须归因于 x 的变化,因为它是这个模型的唯一输入特征,但是 ReLU(x)在点 x = -2 的梯度是 0!这告诉我 x 对产出的贡献是 0,这显然是一个矛盾。

出现这种情况有两个原因:首先,我们关心函数中的一个有限差(当 x = 2 时的函数和当 x = -2 时的函数之差),但是梯度计算的是无穷小的差。其次,ReLU 函数可能会饱和——一旦 x 小于 0,它变小多少都无关紧要,因为该函数只会输出 0。正如我们在上面看到的,这导致了不一致的模型解释,其中输出相对于基线发生了变化,但是没有特征被标记为引起了这种变化。

这些不一致正是 Integrated Gradients 和 DeepLIFT 试图解决的问题。他们都认识到,最终,我们关心的不是点 x 的梯度。我们关心当输入从基线改变时,输出如何从基线改变

集成渐变

积分梯度所采用的方法是提出以下问题:我可以计算什么,它类似于也承认基线存在的梯度?

部分问题在于基线处的梯度(相对于输入的输出)将不同于我测量的输出处的梯度;理想情况下,我会考虑两点的梯度。但是这还不够:考虑一个 sigmoid 函数,其中我的基线输出接近 0,我的目标输出接近 1:

这里,我的基线和数据点的梯度都接近于 0。事实上,所有有趣的——也是信息丰富的——梯度都在两个数据点之间,所以理想情况下,我们也会找到一种方法来捕捉所有这些信息。

这正是积分梯度所做的,通过计算基线和感兴趣点之间的梯度积分。实际上,计算梯度的积分是很难的,因此,相反,它们是使用赖曼和来近似的:梯度是在基线和感兴趣的点之间的许多小步长上获得的。

这非常容易实现——事实上,Integrated Gradients 的作者在他们的 ICML 演讲中演示了一个七行代码的实现:

然而,缺点是,由于我们是在近似一个积分,我们的解释也将是一个近似。此外,这种方法非常耗时;理想情况下,我们的 Reimann 和中的步长较小,因此我们可以非常接近积分,但每一步都需要网络的反向传递。

深层提升

采用的方法 DeepLIFT 在概念上非常简单,但实现起来很棘手。DeepLIFT 认识到我们关心的不是梯度,它描述了在点xT15 处 y 如何随着 x 改变而改变,而是斜率,它描述了 y 如何随着 x 与基线不同而改变。

事实上,如果我们考虑斜率而不是梯度,那么我们可以将特征的重要性重新定义为

这是很好的动机,因为我们关心与基线相关的一切。将此应用于我们的网络:

这个方法告诉我们,输入 x 的重要性值为-2。或者,换句话说:“与基线相比,输入 x = -2 改变了模型的输出-2”。既然事实如此,这种方法就很有意义。

现在,对于每一层,我将计算斜率而不是梯度,其中

Note that the inputs and outputs here are of a certain operation — so here, y and x are the outputs and inputs of (for instance) a certain layer in the network.

DeepLIFT 将这个斜率称为“乘数”,并将其象征性地表示为 m 。既然我们已经将梯度重新定义为一个乘数,正常的链式法则(因此也是反向传播法则)就适用了,但是一切都是相对于基线进行的。

Chain rule with multipliers works the same as chain rule with gradients

因此,您现在可以沿着这些乘数反向传播,以找到输入相对于模型输出的斜率,从而轻松定义要素的重要性。

Note that I am calculating the ‘partial slope’ of Y, similar to calculating the partial derivative.

DeepLIFT 对模型互操作性的方法的问题在于,它重新定义了梯度的计算方式,这意味着你需要非常深入地挖掘大多数深度学习框架的内部来实现它。

其优点是速度快(只需要模型的一次反向传递来计算特征重要性值)且精确(因为与积分梯度不同,没有发生近似)。

选择基线

正如所承诺的,我们现在将回到挑选基线。除了一些非常明显的例子(例如上面的 MNIST 例子),决定基线输入是非常重要的,可能需要领域的专业知识。

手动选取基线的替代方法是考虑已训练模型的先验分布。这可以让我们很好地了解模型在完全没有信息的情况下在想什么。

例如,如果我在 ImageNet 上训练了一个模型,它之前的假设是什么,它看到的一张新照片是一只猫鼬吗?如果 ImageNet 数据集中有 2%的照片是猫鼬,那么模型会认为它看到的新照片有 2%的机会是猫鼬。当它真正看到照片时,它会相应地调整它的预测。衡量输入相对于先前假设的影响是有意义的。

那么,我如何选择一个 2%猫鼬的基线呢?好吧,一个好的方法可能是取数据集的平均值,简单地将数据集中的图像平均在一起。这是在 shap 库的集成渐变和深度提升实现中使用的方法。方便的是,它消除了作为领域专家为被解释的模型选择合适基线的需要。

结论

模型可解释性仍然是机器学习中一个有趣的挑战。最大的问题是,没有一种定量的方法来衡量一种解释是否优于另一种解释;我们所能做的最好的事情就是定义我们希望我们的解释具有什么样的属性(比如特征重要性的总和等于预测与基线的差异)。

希望这篇文章直观地展示了两种强大的解释技术以及它们之间的区别,但是还有很多内容我没有涉及(比如 Integrated Gradients 和 DeepLIFT 的作者在开发他们各自的技术时优化了哪些属性),所以我鼓励大家看看这些论文。

最后,如果你想试验这些方法, shap 库有两者的多框架实现。

来源/延伸阅读

综合梯度 : 穆昆德·孙达拉拉詹,安库尔·塔利,奇奇颜,深度网络公理化归属,2017

DeepLIFT : 两代情·什里库马尔,佩顿·格林塞德,安舒尔·昆达耶,通过传播激活差异学习重要特征,2017

SHAP 价值观 : Scott M. Lundberg,Su-In Lee, 解释模型预测的统一方法,2017

解释随机森林和其他黑盒模型,如 XGBoost

原文:https://towardsdatascience.com/interpreting-random-forest-and-other-black-box-models-like-xgboost-80f9cc4a3c38?source=collection_archive---------1-----------------------

在机器学习中,在表现解释之间有一个反复出现的困境。通常,模型越好,越复杂,越难理解。

一般来说,有两种方式来解释一个模型:

  1. 总体解读:确定哪些变量(或变量组合)最有预测力,哪些最没有预测力
  2. 局部解释:对于一个给定的数据点和相关的预测,确定哪些变量(或变量组合)可以解释这个特定的预测

根据您使用的模型类型,可能会有特定的方式来解释您的模型。例如,决策树模型可以简单地通过绘制树并观察分裂是如何进行的以及叶子的组成来解释。

然而,RandomForest 或 XGBoost 没有具体的方法来做到这一点,它们通常更擅长进行预测。

整体解读

在 Python 的大多数模型中,整体解释已经开箱即用,具有“feature_importances_”属性。下面的例子:

Example of feature importances for a given model, what I call “feature importances table” in this article (sorted by feature importance in descending order)

解释这个输出非常简单:根据模型,变量越重要,就越相关。这是一个很好的方式

  1. 确定具有最佳预测能力的变量
  2. 提出问题/纠正错误:相对于其他变量来说太重要的变量。
    示例:在之前的项目中,我们处理有偏差的数据:类 1 的数据在变量中有许多缺失值,而类 0 的数据没有。我们直到看了特性重要性表才意识到这一点。该模型了解到,如果数据丢失,则它属于类别 1。我们通过从类 0 的数据中抽取缺失值来解决这个问题
  3. 用新变量更新您的模型。要查看新变量是否与您的模型相关,计算之前的模型(无新变量)和之后的模型(有新变量)的特征重要性。分析新变量在要素重要性表中产生的变化。
    举例:在进行特征工程时,你可以提出一个更相关的特征,但是在你的数据中引入它可能会降低与新特征直接相关的特征的重要性。
  4. 比较不同的模型:通过比较变量的重要性来比较两个不同模型(例如 RandomForest 和 XGBoost)的特性重要性。它有助于了解模型是否掌握了变量的预测能力。
    例:比较不同深度的 XGBoost 模型,可以帮助你理解当你使用特定深度时,特定变量变得有用。

到目前为止,对模型的整体理解还不错。

现在你如何解释一个给定数据点的预测?

本地解释

在这里,我将定义什么是本地解释,并提出一个解决方法来处理您拥有的任何模型。

如何定义地方解读?

这里启发我的是我从数据机器人那里得到的一个演示,他们想预测贷款违约。在他们的演示中,对于每个单独的预测,他们还输出了增加违约概率最多的前 3 个变量,以及减少违约概率最多的前 3 个变量。

让我们保留这个例子(用模拟数据),为了更好的可读性,让我们仅用 3 个变量来表示局部解释,如下所示:

Illustration of local interpretation: for each data point, we identify the 3 variables with the most impact on the prediction of default. Variable Var_1 increases the probability of default in the first 2 predictions (resp. +34% and +25%), but decreases it in the 3rd (-12%)

从这个解释中最有趣的收获是

解释每个单独的预测可用于:

  1. 理解个别情况下预测的原因。
    例如:两个人有很高的违约概率,但原因完全不同(即变量不同)
  2. 了解被过滤人群最常见的预测原因。这和特性重要性是不一样的!
    举例:考虑一个欺诈检测用例。这是一个典型的多数类问题(0.1%的 1 类数据 vs 99.9%的 0 类数据),特征重要性偏向 0 类。因此,查看第 1 类的每个单独预测,并对最能解释第 1 类的前 3 个变量进行分组,将非常有助于了解哪些特征会导致最大的风险。

For all predictions of defaults (probability > 50%), we rank the variables that are the most frequent in the top 3 variables, to understand which variables explain the most the default. Variable Var_1 is in 43 cases the most contributing variable for the prediction of default, in 15 cases the second, in 12 cases the 3rd

用 Python 实现

Python 中的tree interpreter库允许我们精确地计算每个特性对随机森林模型的影响。我让好奇的读者查看了包作者的两篇惊艳文章( 1 和 2 )。

对于其他模型,我们将做一个快速的解决方案:运行一个随机森林模型,并在您的模型和随机森林模型之间的预测匹配时进行局部解释(当它们同时预测违约或非违约时)。这是我在一个客户项目中选择的解决方案,在这个项目中我有一个 XGBoost 模型。在这种情况下,Random Forest 的本地解释很有意义,但是没有专门针对 XGBoost 的框架仍然是一个令人沮丧的解决方法。

由于计算需要一些时间(取决于随机森林模型中的树的数量),我建议在本练习中使用您的预测的子集。例如,根据模型,最有可能违约的 10 个人。

For each individual prediction, we compute the individual contribution of each variable in the prediction with the treeinterpreter package

注意,treeinterpreter 既有可变贡献,也有整体偏差。更深入的了解,推荐原创博文。

有一点要记住

假设您有一个变量“年龄”,它的贡献足够高,可以位于前 3 个变量中,从而有助于特定的预测。你可能会对年龄感兴趣,因为你(或专家)会对 18 岁或 35 岁有不同的解释。因此,查看变量的贡献及其值是一个好习惯(就像上面的代码,其中有两列“value_variable”和“contribution_variable”)

超越 treeinterpreter

解释黑盒模型一直是许多研究论文的主题,目前也是,特别是当涉及到深度学习解释时。试验并采用了不同的方法:石灰、偏相关图、 defragTrees …

对于 treeinterpreter,如果有其他基于树的模型,比如 XGBoost、LightGBM、CatBoost 或其他梯度提升方法,那就太好了。

最近偶然发现一篇很棒的关于随机森林模型解读的文章:https://medium . com/usf-MSDS/intuitive-interpretation-of-random-forest-2238687 CAE 45,有瀑布图和部分依赖图。

感谢阅读,如果你觉得这篇文章有用,请考虑给它至少 50 个掌声:)

解读 SHAP 的深度学习模型

原文:https://towardsdatascience.com/interpreting-your-deep-learning-model-by-shap-e69be2b47893?source=collection_archive---------0-----------------------

Photo by JESHOOTS.COM on Unsplash

前面的篇提到过,模型解释非常重要。这篇文章继续这个话题,但分享另一个著名的库是夏普利附加解释(SHAP)[1]。Lundberg 等人提出了解释模型预测的统一方法。

看完这篇文章,你会明白:

  • 什么是沙普利值
  • 沙普利添加剂解释(SHAP)
  • 用例
  • 外卖食品

沙普利值

在介绍 SHAP 之前,我们先来看看合作博弈理论中的解概念——沙普利值。

让我们以一个开发团队为例。我们的目标是交付一个深度学习模型,它需要完成 100 行代码,而我们有 3 个数据科学家(L,M,N)。他们中的 3 个人必须一起工作来完成这个项目。鉴于:

Contribution among coalition

Marginal Contribution by different orders

我们有 3 名球员,所以总组合是 3!也就是 6。上表显示了不同联盟顺序的贡献。

根据 Sherley 值公式,我们有上表。虽然 M 的能力比 N 大 6 倍(30 比 5),但是 M 应该得到 41.7%的奖励,而 N 应该得到 24.17%的奖励。

沙普利添加剂解释(SHAP)

这个想法是用博弈论来解释目标模型。所有特征都是“贡献者”,并试图预测“游戏”任务,而“回报”是实际预测减去解释模型的结果。

在 SHAP,特征重要性被分配给每个特征,其等同于所提到的贡献。让我们以汽车贷款(车贷)为例。我们有“新司机”、“有孩子”、“4 门”、“年龄”。

理论上,组合数是 2^n,其中 n 是特征数。鉴于我们想知道“年龄”的 Shapley 值。我们将预测以下所有带有和不带有“年龄”特征的组合。提到了一些优化

All possible combinations

通过使用沙普利公式,SHAP 将计算所有上述情况,并返回平均贡献和。换句话说,当特定功能错过了时,没有谈论差异。

用例

SHAP 为不同类型的模型提供了多种解释者。

  • TreeExplainer:支持 XGBoost、LightGBM、CatBoost 和 scikit-learn 模型,由 Tree SHAP 开发。
  • DeepExplainer(深度 SHAP):通过使用 DeepLIFT 和 Shapley 值支持 TensorFlow 和 Keras 模型。
  • GradientExplainer:支持 TensorFlow 和 Keras 模型。
  • KernelExplainer(内核 SHAP):通过使用 LIME 和 Shapley 值应用于任何模型。

下面的示例代码将展示我们如何使用 DeepExplainer 和 KernelExplainer 来解释文本分类问题。

深度解说

explainer = shap.DeepExplainer(pipeline.model, encoded_x_train[:10])
shap_values = explainer.shap_values(encoded_x_test[:1])x_test_words = prepare_explanation_words(pipeline, encoded_x_test)
y_pred = pipeline.predict(x_test[:1])
print('Actual Category: %s, Predict Category: %s' % (y_test[0], y_pred[0]))shap.force_plot(explainer.expected_value[0], shap_values[0][0], x_test_words[0])

内核解释器

kernel_explainer = shap.KernelExplainer(pipeline.model.predict, encoded_x_train[:10])
kernel_shap_values = kernel_explainer.shap_values(encoded_x_test[:1])x_test_words = prepare_explanation_words(pipeline, encoded_x_test)
y_pred = pipeline.predict(x_test[:1])
print('Actual Category: %s, Predict Category: %s' % (y_test[0], y_pred[0]))shap.force_plot(kernel_explainer.expected_value[0], kernel_shap_values[0][0], x_test_words[0])

外卖食品

要访问所有代码,你可以访问我的 github repo。

  • 当你阅读 Christoph 的博客 时,你可以参考上面代码的 Shapley 值解释部分。
  • Shapley 值是在不同情况下预测的特征的平均贡献。换句话说,当特定功能错过了时,这就是没有谈论差异。
  • SHAP 包括多种算法。你可以查看关于石灰、深度提升、夏普利值计算的更多细节。
  • 有可能 DeepExplainer 和 KernelExplainer 引入了不同的结果

延伸阅读

  • SHAP 值的高级用途

关于我

我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体或者 Github 联系到我。

参考

[1]伦德伯格 S. M .,李素英。解释模型预测的统一方法。2017.http://papers . nips . cc/paper/7062-a-unified-approach-to-interpretation-model-predictions . pdf

[2] Lundberg S. M .,Erion G. G .,Lee Su-In .树集成的一致个性化特征属性。2017.https://arxiv.org/pdf/1802.03888.pdf

进入黑暗的文本中心

原文:https://towardsdatascience.com/into-a-textual-heart-of-darkness-39b3895ce21e?source=collection_archive---------5-----------------------

通过仇恨言论分类在 NLP 中从零到不太英雄

Image courtesy of Peggy and Marco Lachmann-Anke, CC0 license.

互联网是一个丛林。在这里,丰富的多样性和奇妙的色彩结合起来,创造了一个独特的生态系统,使新的技术和通信方法。但是在这个明亮的树冠下是不受控制的互联网的黑暗下层——在这个地方,匿名的安全性模糊了公民话语的界限。

在这里,你会发现侮辱和侮辱,辱骂和嘲笑。在这个勇敢的新世界里,人仅仅是一个抽象概念,与他或她所说的事情无关。在这里,整批的人被妖魔化和诋毁,而不是因为他们自己的过错。值得庆幸的是,其中一些是网络钓鱼者的结果——精心构建的评论假装无知并激起愤怒。

一些。但是,不是全部。

其中一些评论是真正的偏见和恶意的产物。我想看看我是否能找到一种方法来构建一个模型,能够检测和分类这些评论,并将它们从其他评论中分离出来。作为一个对自然语言处理技术知之甚少的人,我很想看看自己在两周内能走多远。

“太恐怖了!恐怖!”

为了限制我的调查范围,我想专注于令人反感的评论的一个特定类别——仇恨言论。虽然这个词越来越多地被使用,但它也越来越多地被误解。Alito 法官在他对 Matal 诉 Tam 案的书面意见中对仇恨言论以及我们与仇恨言论的关系做了如下定义:

基于种族、民族、性别、宗教、年龄、残疾或任何其他类似理由贬低他人的言论是令人憎恶的;但我们言论自由法理最值得骄傲的是,我们保护表达“我们讨厌的思想”的自由。

令人惊讶的是,在美国,仇恨言论在联邦一级不受管制,并一直受到第一修正案的保护。然而,像大学这样的机构经常定义行为和礼仪规范,对言论加以限制,但效果有限。

随着互联网提供的匿名性,以及它提供的与后果的隔离,仇恨言论肯定在增加,并且越来越受到寻求保持文明的社区和平台的关注。

数据

首先,我需要一些仇恨言论。快速的网络搜索让我找到了一个由人类标注的推文集合。这些数据构成了论文“自动化仇恨言论检测和攻击性语言问题”的基础。对数据的粗略浏览揭示了我所面临的问题:

A sample tweet from the data, classified as offensive, but not hateful.

数字列从左至右对应于:

  • tweet 的索引或条目编号
  • 查看该推文的人类读者数量
  • 认为推特上有仇恨言论的人类读者数量
  • 认为这条推文令人不快的读者人数
  • 认为推文不属于以上两种情况的读者人数
  • 最终分类,即多数意见

每条推文至少有三名读者阅读,对于更模糊的陈述,阅读人数会增加一倍。

由于我的挑战是只根据推文的文本对推文进行分类,所以除了最终的分类决定,我忽略了所有的数字列。

倒垃圾

推文本来就乱;互联网交流是非正式的,不固定的——重复的强调字母、非常规的缩写和不断演变的俚语只是其中的一些东西,它们既给平台带来了活力,也让文本变得更加难以处理。为了对我的数据中的单词进行任何形式的准确阅读,我需要标准化和规范化。

为了做到这一点,我从一些关于古腾堡项目的书籍中生成了一个单词列表。不幸的是(也是可以理解的),互联网上的许多脏话和行话不是这些经典文学作品的一部分,需要手动添加。这是一个非常不完美的系统,因为对我来说不可能解释所有的事情,但是它保留了我需要的脏话,并规范了我的大部分文本。

An example from my normalization workflow. Note the repeated ‘yyy’ in ‘crazy’ is corrected, though ‘bahaha’ is interpreted as an unrelated word.

我希望大多数遗漏的内容至少会以一致的方式被错误地规范化,从而限制潜在的影响。

分解它

有了(大部分)修改过的文字,我就可以把我的推文转换成机器可读的东西了。处理文本的一种常见方法是将文本分成单个单词或单词组,称为

Partial n-grams for a normalized tweet, with corresponding part-of-speech tags (discussed later).

这些 n-gram 然后被转换成机器可读的数字向量,数字对应于每个 n-gram 的 tf-idf 权重。

术语频率-逆文档频率( tf-idf )可以被认为是一个单词对于一类文档的独特性或独特性的度量。确定一个单词有多重要的一种方法是简单地计算它出现的次数(术语频率)。

不过,我们有个问题。有些词只是在所有文档中更频繁地出现,例如“and”、“the”或“a”。如果不删除这些词,简单的术语频率将被这些不可区分的词所支配,从而隐藏真正的信息。

tf-idf 的构想是通过惩罚出现在多个文档中的单词来纠正这一点。虽然“the”可能有很高的术语频率,因为它出现在几乎每个文档中,但它的 tf-idf 得分将受到影响,从而使真正独特的描述性单词浮出水面。

在我的例子中,“冒犯”和“憎恨”类共享了很多词汇,比如骂人的话。我的希望是,tf-idf 将允许独特的诋毁,使仇恨言论是什么出现。

保持优雅

我执行了两个主要的分类步骤——词性标注,以及最终的分类,即仇恨、冒犯或两者都不是。

最高级,不定式和分词,天啊!

现在我坦率地承认我不是语法迷。直到五分钟前,我才知道什么是“语义最高级形容词”。但是词性可能会帮助我从现有的数据中收集一些额外的信息,所以我开始认真准备一些核心的语言学指导。

现在,更聪明的人已经在之前走过这条路,并且优秀的代码已经存在以最小的努力标记文本。但是以学习的名义,我决定自己造一个低劣的模型来做同样的工作。以一个预先标记的语料库为例,我使用了一个简单快速的算法,一个朴素贝叶斯分类器来完成这项工作。

The result of my part-of-speech classifier.

正如“天真”可能暗示的那样,这种类型的分类器头脑简单,做出假设,用准确性换取简单性和速度。简单而迅速;在几行代码中,我启动并运行了我的 tagger,准确率为 85%。当然还有改进的空间,但已经足够了:我渴望进入问题的核心——检测仇恨言论本身。

回顾:现在,我已经清理了我的原始推文,附加了词性标签,将我的文本分解成小块的单词,并将它们转换成一大堆数字。我已经准备好迎接重头戏了。

Off-平衡

我第一次浏览数据时,针对我的六种类型的特征中的每一种,我训练了五种不同类型的模型:一个、两个或三个单词的组块及其相应的词性标签。

Average F1-Score. Each number corresponds to a distinctly trained model.

第一遍看起来不错,对吧?我的最高 F1 分已经在 80 多分,通过优化,我有信心可以推得更高。

不幸的是,我的数据没有这么好。当我试图构建一个仇恨言论分类器时,我最感兴趣的指标是针对仇恨言论的 F1 分数;只显示数据描绘了一幅完全不同的画面。

F1-Score for “hate speech” classification of tweets.

这是怎么回事?可悲的是,在我的兴奋和匆忙中,我没有勤奋地执行我的探索性数据分析。如果我做得更彻底,我可能会注意到我的数据有些不太对劲。

Class 0: hate speech. Class 1: offensive speech. Class 2: neither offensive nor hateful.

我的班级比例严重失衡。第 0 类,仇恨言论——我最感兴趣的一类——只占我总数据的 7%多一点。由于“仇恨”和“冒犯”类在语言上的相似性,我的模型很难看出仇恨和冒犯的界限在哪里。

团队里没有“我”

我最好的模型只有 25%左右的表现,显然我的方法不起作用。因为我的独立模型不能胜任这项任务,所以我考虑结合我最好的——一个穷人的随机森林。

The five models I selected for my ensemble approach.

我最终选择的五个模型都是决策树或其变种。对于每一条推文,我把多数决定作为我的分类;如果三个模型预测为 0 级,这将是我对该推文的分类决定。这种方法让我的 0 级 F1 分数达到了 21%。这比我以前所取得的成就要少。

时间不多了,我开始担心。即使是多数决定,我的模型也不能得出正确的结论。但是这给了我第二个想法——如果我的大多数模型都把仇恨言论分类错了,也许他们一直都错了。如果有某种模式的话,我可以把这五个决定输入到一个新的分类器中,这个分类器能够理解这一切。

我的策略得到了回报:将我的模型输入输入到一个新的朴素贝叶斯分类器中,做出最终决策,这让我的 F1 分数达到了 31% ,当然,这不是一个非常显著的改进,但仍然是一个改进。

结束语

虽然我对仇恨言论的成功分类并不令人印象深刻,但它提供了一个良好的开端。虽然这可能有些老生常谈,但比我的准确性或精确性更重要的是,我对良好的代码和数据分析的理解增加了,这只能来自于犯错误和拥有愚蠢的代码架构。

至于模型本身,我当然可以做得更多,尤其是以我现在所知道的。从优雅地处理类不平衡到探索更高级的算法或单词嵌入,唯一可走的路就是 up。

为大家介绍数据分析;第三部分!

原文:https://towardsdatascience.com/intro-to-data-analysis-for-everyone-part-3-d8f02690fba0?source=collection_archive---------7-----------------------

我们希望你已经喜欢这个数据分析和数据科学介绍的前两部分(第一部分、第二部分)。

在接下来的几节中,我们将查看不同的数据集,提出问题并提出可能的停止点,您可以尝试思考您可能会从数据和可视化等中做些什么或得出什么结论。

我们一直忙于最近的一些项目,所以我们有点落后于这个职位!

在第一部分。我们将使用来自 Kaggle.com 的这个人力资源数据集。它已经聚合并且干净…

任何一个数据工程师或数据科学家都知道数据不会整齐地打包。相反,通常会有无数的问题,如丢失数据、重复数据、垃圾数据等。

获得一个干净的数据源并不容易。它需要主题专家和数据团队一起工作,以确保每个人都使用同一种语言。

有大量的标准化、测试和记录来确保项目启动时数据馈送保持一致。

清理数据仍然是数据专业人员工作的一大部分。下面的图 1 汇总了我们团队成员在过去工作中的几天。有新的工具使这些工作的某些部分变得更容易。然而,有些是不可避免的。

典型的数据科学家工作日

figure 1 A Data Scientists Average Day

聊够了,回到数据分析

如果你还记得我们之前的部分。我们展示了满意度和员工离职之间已经存在某种关联。这是影响员工离职的唯一因素吗?

人力资源数据集的相关矩阵

figure 2 Correlation Matrix Of HR Data Data Set

如果这就是分析的结束,那么数据分析师可以去找他们的老板,简单地说:“满意度在你的员工离职中起着重要作用!你应该去鼓舞士气。那会解决你所有的问题!

现在给我升职?

也许…但这并不能真正告诉数据分析师的老板为什么员工要离开。

好的数据科学家要多提问!而且很多时候,那些问题不会横向移动。参见下面的图 3。

问为什么!

figure 3 A Data Scientists Daily Struggle

标准化数据

首先,我们获取所有数值数据点,并对它们进行归一化。这是获取一系列数字并在数据集中的最小值和最大值之间创建线性关系的过程。

我们是什么意思?图像有一组介于 1–1000 之间的数据和另一组介于 0–10 之间的数据。现在,这些数字之间的贬低可能会混淆算法。因此,我们将它们规范化。

而不是 1–1000 和 1–10。我们希望将范围限制在 0-1。这意味着您将使最大值=1,最小值= 0,然后在两者之间创建一条线,其中每个数字都适合。因此,对于 1-10,5 大约是 0.5,对于 1-1000,500 大约是 0.5。这样可以减少噪音。

你如何使数据正常化?

这里有一个快捷的函数,它将在 python 中规范化您的数据

normalized = (x-min(x))/(max(x)-min(x))

从数学上讲,它看起来像下面这样:

加载数据分析库

当使用 python 执行数据分析时,这些是您将需要的典型 python 库。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

标记离开的员工

我们决定根据谁走谁留来寻找聚类。下面是我们使用其中两个字段输出的数字之一。在图 4 中,红色代表离开的员工,蓝色代表留下的员工。

你看到了什么?似乎有 3 个集群,对吗?

有一群员工满意度很高,平均每月工作时间也很长。这可能是高绩效者,但他们为什么离开?如果不是他们离开。大多数离开的员工都是那些满意度低的人。这很有道理。

这也将使早先简单地提高士气的结论变得正确。

figure 4 Red = Employees That Have Left ; Blue = Employees That Haven’t Left

用颜色创建基本散点图

X = hr_data_s[['average_monthly_hours','satisfaction_level']]  # we only take the first two features.
y = hr_data_s.left
plt.scatter(X['average_monthly_hours'], X['satisfaction_level'], c=y, cmap=plt.cm.coolwarm)
plt.xlabel('Average Monthly Hours')
plt.ylabel('Satisfaction Levels')
plt.title('Average Monthly Hours by Satisfaction Levels')
plt.legend()
plt.show()

作为这家公司的一部分,分析师还应该问,留住每一类员工的投资回报率是多少。

我们没有足够的信息来判断哪些离职的员工是最有价值的。然而,常识告诉我们,图 4 右上角的组可能是。纯粹从我们目前所关注的指标来看,他们似乎是非常有价值的员工。

那是真的吗?

在本文中,我们将敦促您回头看看图 3。记住“问为什么”这个数字!

单从这个数据来看,很难说哪个群体最有价值。看起来有很高价值的群体可能是那些被要求完成适量工作从而表现出色的员工。他们也可能是工资最低、替换成本最低的员工。

这就是为什么,重要的是在分析中,继续问为什么!为什么有 3 个独立的组?他们每个人都不一样吗?怎么做,为什么?

figure 5 figure 4 Red = Employees That Have Left ; Blue = Employees That Haven’t Left

看一下图 5,似乎也很少有高薪员工离职。图中离职的员工都是中低薪员工。这个,更有道理一点。

员工为什么会离职?

下一节将分析上面列出的各组之间的一些差异。

让我们从计算“已经离开的员工”组中的员工总数开始。

14999 名员工中离职的总人数为 3571 人。

从这里开始,我们将在下表中检查每个组的大小。我们已经根据迄今为止所看到的特征对每个组进行了标记。

下面的组只是我们个人的假设,为什么我们会看到这些不同的组。简单地将它们标记为组 1、2、3 等以避免确认偏差可能不是一个坏主意。

因此,评估分数高、工作时间长的那一组人就是“高绩效者”

小时数低、评价分数低的那一组是“低绩效者”

小时数高、评价分数低的群体“过劳”

然后,有一个离群组,针对的是没有完全融入这些集群的每个人。

离职员工明细

figure 6 Breaking down the employees that have left

细分下来,各组加起来就是 3571。这太棒了!

任何类型的数据专家。这应该是一个目标,在这个过程中创建这样的检查,以确保您的数字继续增加。数据总是有可能突然消失或增长。尤其是在 SQL 中。

数据分析 讲的是为什么

请记住,这不仅是数据科学,也是数据分析。我们可以很容易地将这个数据集放入算法中,让计算机替我们思考。python 和 R 中有很多库会很乐意为你做这些。

重要的是培养对数据的直觉,不要完全依赖预先制定的算法。

因此,让我们只看看那些离开的人,并尝试看看我们是否可以创造一个故事来告诉经理。

我们接下来的几个数字将是项目数量、平均每月小时数和评估分数的分布。

这很好,因为不像平均可以隐藏实际的传播,我们将能够可视化的雇员。

项目分布数量

figure 7 Distribution Of Number Of Projects Per Group

创建分布图

sns.distplot(hr_data_s[‘last_evaluation’][hr_data_s.clutser == ‘Poor Performers’], label=’Poor Performers’);
sns.distplot(hr_data_s[‘last_evaluation’][hr_data_s.clutser == ‘High Performers’], label=’High Performers’);
sns.distplot(hr_data_s[‘last_evaluation’][hr_data_s.clutser == ‘Overworked’], label=’Overworked’);
plt.title(‘Last Evaluation Distribution’)
plt.legend()
plt.show()

请看图 7,我们看到超负荷工作的员工承担了大量的项目。这很奇怪吗?为什么工作过度、满意度较低的员工会得到更多的项目?那没有意义…是吗?

上次评估分布

figure 8 Last Evaluation Distribution

然后我们看一下图 8,可以看到有很大一部分高绩效者有着惊人的评价。如果我们找到曲线下的区域(积分…哦,不),从那里,表现较好的人的最终峰值开始于 0.9 左右,结束于 1,我确信大约有 20%的人比“过度工作”的人得分更高。

当然,在这一点上表现不佳的人既不能在评估中得分,也不能得到很多项目。

平均月小时分布

figure 9 Distribution Of Monthly Hours

现在,为了使其完整,我们在图 9 中再次引入了小时。根据图 1,我们已经知道平均每月工作时间和项目是正相关的。所以图 9 不应该是一个惊喜

这仍然是很好的检查,因为也许“高绩效者”和“过度工作者”仍然具有与图 9 中相同的分布,但是转换了图 7 中的分布。

然后,人们可能会假设“过度工作”的那一组之所以慢,是因为他们每小时做的项目比“高绩效者”少。

事实并非如此!

组和职务类型分解透视

figure 10 Pivot Table Breakdown Of Groups to Job Type

最后,对于这一部分,我们有图 10。这并不优雅,但目的是展示每种工作类型在每组中是如何分解的。

这很奇怪,如果你真的看薪水的话。“高绩效者”的平均工资比“低绩效者”和“过度工作者”都低。

此外,现在我们已经找出了所有这些组,我们可以看到每个组的满意度有多低。

“过度工作”通常接近 0.01(正常)…这与“表现不佳”的人相比非常不同

怎么回事!

小学亲爱的沃森

基于这些信息,现在。到目前为止,你的结论是什么?

到目前为止,你已经注意到了哪些事实?

假设你是夏洛克·福尔摩斯。看目前的线索?

  • 我们看到三个不同的群体
  • 每一组都有不同的工作时间
  • 两组好像满意度都很低?
  • 一个评估分数比高绩效者低的群体也有高项目量?他们为什么被信任?
  • 你还注意到了什么其他特征

作为一名分析师或数据科学家。得出结论是你的工作!和可操作的步骤!

同样,我们希望你想出一个结论。请在下面随意回答你现在的想法。继续之前。您的结论应该能够为经理或您的团队创建可操作的步骤。这是关键。

你越深入问题,你就越能找到根本原因。你就越有可能想出一个清晰的解决方案,并向经理解释为什么你会看到你所看到的趋势。

为什么不直接把这个扔进算法里呢?

如果你把这个数据集扔进一个像决策树这样的算法里。它实际上会给你一个相当精确的输出。然而,现在向你的经理解释一下?

我们认为,告诉一位经理“算法”证明了这一点,从来都不太管用。

做一个讲故事的人

作为一名分析师,能够讲述数据的故事是很重要的。上面的一些数字可以开始讲述这个故事!然后你可以把它和决策树或者逻辑回归算法结合起来。

那就不仅仅是一堆你甚至不理解的抽象数学了…

我们在第 1 部分中讨论过这个问题。你必须是一个好的沟通者,一个“数据故事讲述者”。不要隐瞒为什么!

一些机构让人们觉得,你需要做的只是通过算法运行数据,然后把结果当作福音来宣扬。

我们相信为了让真正的经理们接受。需要一份可靠的报告,让他们了解你是如何得出最终结论的。单纯的从数据探索到结论并不能证明你的观点,也不科学。

科学领域的理论需要多份研究论文一遍又一遍地证明同一个结论!

数据分析师也应该有证据证明他们超越了某种算法。这样,当你的经理问他们如何知道原因时,他们就可以回答了!

为了进一步阅读数据科学和分析,这里有一些很棒的文章

人人数据分析简介第 1 部分

使用 Kafka 流分析预测预算

如何将数据科学应用于实际业务问题

数据科学家的统计回顾

伦理机器学习

为什么使用数据科学

数据科学简介

原文:https://towardsdatascience.com/intro-to-data-science-part-1-numpy-and-pandas-49d98740661b?source=collection_archive---------7-----------------------

第一部分:熊猫和熊猫

  • 第二部分:数据争论
  • 第三部分:数据分析

Photo by geralt on Pixabay

作为一名科学家,数据在我的日常生活中无处不在。但是分析数据的方法本身就是一门艺术。在“数据科学导论”中,我综合了来自 Udacity 的一门课程,在那里你会发现一个有抱负的数据科学家应该知道的所有基础知识。

在第 1 部分中,我们将看到如何使用 Numpy 创建和操作数组,以及使用 Pandas 创建和操作系列数据帧。最后,您将能够:

  • 创建、索引、切片、操作 numpy 数组
  • 创建一个带有 2D 数字阵列的矩阵
  • 对 numpy 数组应用算法
  • 对 numpy 数组应用数学函数(平均值和点积)
  • 创建、索引、切片、操作熊猫系列
  • 创建熊猫数据框
  • 通过切片、单独索引(iloc 或 loc)、布尔索引选择数据框行

数据科学中常用的工具:Numpy 和 Pandas

Numpy

Numpy 因增加了对多维数组和矩阵的支持而广受欢迎。它还增加了许多基础 python 所缺乏的数学函数。这些函数对于统计分析非常有用(一个数组的平均值、中值、标准差……)。array object 类是 Numpy 的基础,Numpy 数组就像 Python 中的列表,只是数组中的所有内容都必须是同一类型,比如 int 或 float。

>>> [1\. 4\. 5\. 8.]  
>>>[[1\. 2\. 3.]
    [4\. 5\. 6.]]

可以对 Numpy 数组进行索引、切片和操作,就像处理 Python 列表一样。

>>> [1\. 4\. 5\. 8.]  
>>> 4.0
>>> [1\. 4.] 
>>> 5.0

矩阵索引和切片的作用。

>>> [[1\. 2\. 3.]  
     [4\. 5\. 6.]]  
>>> 5.0  
>>> [4\. 5\. 6.]  
>>> [3\. 6.]

下面是一些可以用 Numpy 数组做的算术运算。

>>> [6\. 4\. 9.]  
>>> [-4\.  0\. -3.]  
>>> [ 5\.  4\. 18.]

同样的算术运算,但这次用的是矩阵。

>>> [[ 6\.  8.]  [10\. 12.]]  
>>> [[-4\. -4.]  [-4\. -4.]]  
>>> [[ 5\. 12.]  [21\. 32.]]

除了标准的算术运算,Numpy 还有一系列的
其他数学运算可以应用于 Numpy 数组,比如
均值和点积。

>>> 2.0 
>>> 7.0  
>>> [44.]

熊猫

另一方面,Pandas 允许以适合数据分析的方式构建和操作我们的数据。Pandas 还从 R 中吸取了很多最好的元素,并用 Python 实现了它们。我们将关注熊猫、系列和数据框的主要概念。

您可以将序列视为一维对象,类似于数据库中的数组、列表或列。默认情况下,它将为系列中的每个项目分配一个从 0 到 N 的
索引标签,其中 N 是
系列中项目的数量减 1。

0           Dave 
1      Cheng-Han 
2        Udacity 
3             42 
4    -1789710578


创建系列时,您也可以手动为系列中的项目分配索引,并使用索引从系列中选择特定项目。

>>>
Instructor               Dave 
Curriculum Manager    Cheng-Han 
Course Number               359 
Power Level                9001>>> Dave>>>
Instructor                 Dave 
Curriculum Manager    Cheng-Han 
Course Number               359

您也可以使用布尔运算符从系列中选择特定的项目

>>>
Cockroach    1 
Fish         2 
Mini Pig     3 
Puppy        4 
Kitten       5 >>>
Cockroach    False 
Fish         False 
Mini Pig     False 
Puppy         True 
Kitten        True >>>
Puppy     4 
Kitten    5 

通常,Pandas 中的数据包含在一个称为数据帧的结构中。数据框是具有列的 2D 标签数据结构,如果需要,列可以是不同的类型(字符串、整数、浮点或布尔)。例如:

要创建一个 dataframe,您可以将一个列表字典传递给 Dataframe
构造函数:
1)字典的键将是列名
2)关联列表将是该列中的值。

>>>
   losses     team  wins  year 
0       5    Bears    11  2010 
1       8    Bears     8  2011 
2       6    Bears    10  2012 
3       1  Packers    15  2011 
4       5  Packers    11  2012 
5      10    Lions     6  2010 
6       6    Lions    10  2011 
7      12    Lions     4  2012

Pandas 还有各种功能,可以帮助您了解有关数据框的一些基本
信息。代码中提到的这些函数有:

  1. dtypes:获取每列的数据类型
  2. describe:用于查看数据帧的数字

    的基本统计数据 3) head:显示数据集的前五行
  3. tail:显示数据集的后五行
>>>
losses     int64 
team      object 
wins       int64 
year       int64 
dtype: object>>>
          losses       wins         year 
count   8.000000   8.000000     8.000000 
mean    6.625000   9.375000  2011.125000 
std     3.377975   3.377975     0.834523 
min     1.000000   4.000000  2010.000000 
25%     5.000000   7.500000  2010.750000 
50%     6.000000  10.000000  2011.000000 
75%     8.500000  11.000000  2012.000000 
max    12.000000  15.000000  2012.000000>>> losses     team  wins  year 
0       5    Bears    11  2010 
1       8    Bears     8  2011 
2       6    Bears    10  2012 
3       1  Packers    15  2011 
4       5  Packers    11  2012>>> losses     team  wins  year 
3       1  Packers    15  2011 
4       5  Packers    11  2012 
5      10    Lions     6  2010 
6       6    Lions    10  2011 
7      12    Lions     4  2012

注意:
1)从数据帧中选择单个列将返回一个序列
2)从数据帧中选择多个列将返回一个数据帧

>>>
0    2010 
1    2011 
2    2012 
3    2011 
4    2012 
5    2010 
6    2011 
7    2012 
Name: year, dtype: int64 >>> ... Same as above
>>> year  wins  losses 
0  2010    11       5 
1  2011     8       8 
2  2012    10       6 
3  2011    15       1 
4  2012    11       5 
5  2010     6      10 
6  2011    10       6 
7  2012     4      12

行选择可以通过多种方式完成。一些基本和常用的方法有:
1)切片
2)单个索引(通过函数 iloc 或 loc)
3)布尔索引

您还可以通过布尔
操作符,如& (and)或| (or)来组合多个选择需求

>>>
   losses   team  wins  year 
0       5  Bears    11  2010     
>>>
   losses   team  wins  year 
0       5  Bears    11  2010     
>>>
   losses     team  wins  year 
3       1  Packers    15  2011 
4       5  Packers    11  2012>>>
   losses     team  wins  year 
0       5    Bears    11  2010 
3       1  Packers    15  2011 
4       5  Packers    11  2012>>>
   losses     team  wins  year 
3       1  Packers    15  2011 
4       5  Packers    11  2012

接下来的课程将是关于数据争论。

数据科学简介

原文:https://towardsdatascience.com/intro-to-data-science-part-2-data-wrangling-75835b9129b4?source=collection_archive---------6-----------------------

第 2 部分:数据争论

  • 第一部分:熊猫和熊猫
  • 第三部分:数据分析

Photo by Markus Spiske on Unsplash

真实世界的数据通常是杂乱无章的。数据科学家应该具备的最重要的技能之一是提取和清理数据的能力。这通常被称为数据争论或数据咀嚼。

我们获取数据的三个最常见的来源是文件、数据库或通过 web APIs 从网站获取数据。

如果我们想要处理和分析我们的数据,理解数据本身的结构是至关重要的。

在第 2 部分中,我们将学习:

  • 我们可以在线获取的数据格式及其结构(csv、xml、json)
  • 如何将 csv 文件加载到熊猫数据框中(pd.csv_read())
  • 为什么关系数据库有用?(复杂查询、可伸缩性、模式)
  • 如何制定简单和复杂的查询(SELECT、FROM、LIMIT、WHERE、GROUP BY、聚合函数、pandasql.sqldf())
  • 什么是 API 以及如何从 API 获取数据(request.get()、json.loads())
  • 健全性检查数据(描述()、部分删除、插补、fillna())

获取数据

网上的很多数据都存储在文本文件中,尤其是在政府网站上,往往只是从网站上下载文件的问题。例如,让我们得到所有美国职业棒球大联盟统计数据的数据库,我们可以在这里找到。在页面上,我们可以看到数据有多种格式。三种最常见的格式是 csv、xml 和 json。

我下载了名为“ 2016 —逗号分隔版本—2017 年 2 月 26 日更新”的 csv 格式的数据。查看 AllstarFull.csv 文件时,前两行是:

playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,,1

在 csv 格式中,我们通常有一系列的行,每行对应一个条目。条目由逗号分隔。文件顶部的标题行对应于标识符,如球员 ID,yearID…如果我们查看第一个球员的条目,我们可以看到相同顺序的相应数据。如果一个数据丢失了,我们会看到两个逗号连在一起,中间没有空格。

在 xml 文档的情况下,我们最终会得到与 html 非常相似的东西。我们可以有一个打开的文档元素,也可以有一系列打开的表格。该表有许多对应于上述值的子表。如果数据丢失,字段以斜杠结尾打开(例如:)

<Document Element>
  <Table>
    <playerID>gomezle01</playerID>
    <yearID>1933</yearID>
    <gameNum>0</gameNum>
    <gameID>ALS193307060</gameID>
    <teamID>NYA</teamID>
    <lgID>AL</lgID>
    <GP/>
    <startingPos>1</startingPos>

在 json 文档中,我们有许多用花括号表示的 json 对象。json 文档很像 python 字典。我们有键,对应于 csv 文件中的标题行,后跟值。在缺少值的情况下,我们只需打开和关闭引号

{ "playerID":"gomezle01"
  "yearID":1933
  "gameNum":0
  "gameID":"ALS193307060"
  "teamID":"NYA"
  "lgID":"AL"
  "GP":""
  "startingPos":1
}

xml 和 json 的好处是它们支持 csv 文档所不能支持的嵌套结构,尽管 csv 仍然是一种非常流行的存储数据的方式。

CSV 数据

将 csv 数据加载到 Pandas 数据框中只需一行代码。每一列都可以通过提及它们的名称来检索。我们还可以通过以矢量化的方式操作列,在数据框上创建新列。例如,如果我们想要一个新的列,它是每个球员的身高和体重的总和,我们可以编写 to 列的算法,如下所示。

也可以将数据写入一个新的 csv 文件,该文件包含我们刚刚用 to_csv()函数添加的新列。

>>>
    playerID  birthYear  birthMonth  birthDay birthCountry ...
0  aardsda01     1981.0        12.0      27.0          USA ...    
1  aaronha01     1934.0         2.0       5.0          USA ...      
2  aaronto01     1939.0         8.0       5.0          USA ...      
3   aasedo01     1954.0         9.0       8.0          USA ...      
4   abadan01     1972.0         8.0      25.0          USA ...     
>>>
0    290.0
1    252.0
2    265.0
3    265.0
4    257.0

关系数据库

我们现在知道如何从 csv 这样的平面文件中加载数据。现在让我们看看如何处理存储在关系数据库中的数据。关系数据库类似于电子表格的集合。在每个电子表格中,都有列和行。列指定一个值及其类型,如 playerID。每一行包含每一列的值,我们称每一组行和列为表格,而不是电子表格,这些表格通常以某种方式相互关联。

关系数据库非常有用,主要有三个原因:

  • 用复杂的查询提取数据很简单。
  • 它伸缩性很好
  • 它确保所有数据的格式一致

事实上,与平面文件相比,使用数据库选择年龄大于 50 岁、体重小于 50、城市等于孟买的人的所有记录很容易。

拥有数十万或数百万条目的数据库并不少见。由于所有信息都理想地存储在一个位置,所以很容易以可伸缩的方式更新、删除和向数据库添加新数据。

最后,关系数据库总是有一个模式。模式是告诉数据库我们计划如何存储数据的蓝图。例如,人的年龄不能是字符串,而其他人的年龄是整数。此外,模式规定对于给定的表,每一行或每一项都有对应于相同值的完全相同数量的列,并且每一列的值都以相同的方式格式化。

问题

我们如何从关系数据库中获取数据?通常使用结构查询语言(SQL)从关系数据库中检索数据。如果我们想要选择所有(*)的数据,查询应该是:

SELECT * FROM database_name;

我们可以通过在 SQL 命令的末尾添加 limit 20 来限制行数。

SELECT * FROM database_name LIMIT 20;

我们也可以只要求特定的列,如姓名和年龄。

SELECT name, age FROM database_name LIMIT 20;

让我们将这个查询编写在一个 python 文件中,并将数据存储在“database_solution”中。

我们还可以执行更复杂的查询。以下查询选择与国家冰岛对应的所有数据。

SELECT * FROM database_name WHERE country = "Iceland";

SQL 中存在一些函数,如 group by 和 aggregate。聚合函数接受一组值,通常是数字,并对它们执行数学运算。例如,sum()是一个聚合函数。

每个地区 50 岁以上的人登记在数据库中的总人数是多少?以下查询首先选择每个地区有多少男性和女性注册。因为我们使用的是聚合函数,所以我们需要包含一个分组依据和非聚合字段,在本例中是地区和性别。最后,我们希望将此限制在 50 岁以上的男性和女性。因此,我们在表名后包含 where 子句,其中 age > 50。

SELECT gender, district, sum(database_generated) 
FROM database_name
WHERE age > 50
GROUP BY gender, district

应用程序编程接口

我们现在知道如何从文件或数据库中获取数据,但是像 Twitter 这样的网站上的数据呢?通过搜索或抓取网站来获取所有数据可能会变得复杂。幸运的是,许多公司允许用户和开发人员通过 API 以简单的、机器可读的格式直接访问数据。有几种不同类型的 API,但最常见的一种,也是 Twitter 使用的一种,是表示状态转移或 REST API。

让我们以 last.fm API 为例,看看我们如何与之交互。正如您在左侧看到的,有几个不同的 last.fm API 方法,我们可以与之对话并从中检索信息。例如,让我们检查一下图像中紫色方块中的 Album.getInfo 方法。

last.fm API

当点击 Album.getInfo 链接时,我们会看到一个页面,描述 API 方法将返回的数据类型,如艺术家姓名、专辑名称等

正如你所看到的,这个页面告诉我们 API 方法将返回的数据类型,如艺术家姓名、专辑名称和一系列其他信息,如语言或专辑中的音乐大脑 ID。

但是我们如何从 API 中获取数据呢?

  1. 获得一个 API 账号。然后,您将收到一个 API 密钥。
  2. 返回到 Album.getInfo 页面并点击其中一个示例 URL(在紫色方块中)
  3. 您应该会看到一条错误消息,提示您需要一个 API 密钥。

4.复制您的 API 密钥并将其粘贴到 url 中,而不是您的 _API_KEY 中。现在你应该看到数据了。

注意这个 URL 有一些有趣的地方。

http://ws.audioscrobbler.com/2.0/?method=album.getinfo&API _ KEY = YOUR _ API _ KEY&艺人=雪儿&专辑=相信

API 参数定义在问号之后,如 method、api_key、artist 和 album。例如,如果我们想让蕾哈娜大声说出专辑中的信息,我们可以简单地写:

http://ws.audioscrobbler.com/2.0/?method=album.getinfo&API _ KEY = YOUR _ API _ KEY&艺人=蕾哈娜&专辑= 大声

现在让我们在一个简单的 python 程序中实现它,该程序使用 json 和请求库。

首先,我们像前面看到的那样指定一个 URL。函数 requests.get()将从. txt 中的 url 获取数据。查看 json 对象,我们会看到一个很难处理的字符串格式,但是由于 json.load()函数,json 库允许与 json 数据进行非常简单的交互。现在,json 数据被转换成 Python 字典。

健全性检查数据

既然我们已经获得了数据,无论是非正式的平面文件 sequel(如关系数据库)还是 API,我们都需要在进行任何分析之前对数据进行完整性检查。健全检查允许我们确定数据是否有意义。我们不会深入讨论细节,但是为了进行最基本的健全性检查,Pandas DataFrames 有一个非常有用的方法叫做 describe()。

为了说明 Panda 的 describe 函数是如何工作的,我们将使用上面的 baseball_data。

>>>birthYear  birthMonth  birthDay  deathYear  deathMonth
count  18973        18803     18656       9441        9440   
mean    1931            6        15       1964           6   
std       41            3         8         31           3   
min     1820            1         1       1872           1   
25%     1895            4         8       1942           3   
50%     1937            7        16       1967           6   
75%     1969           10        23       1990          10   
max     1996           12        31       2017          12 deathDay        weight    height  
count   9439         18251    18320  
mean      15           186       72  
std        8            21        2  
min        1            65       43  
25%        8           170       71  
50%       15           185       72  
75%       23           200       74  
max       31           320       83

函数 describe()返回一个数据帧。对于每个数字列,我们可以看到计数、平均值、标准偏差、平均值。我们可以做一些快速检查,以确保有些数据通常是有意义的,例如月份包含在 1 到 12 之间,日期包含在 1 到 3 之间。有没有异常值?查看最小值和最大值是否远大于第 25 或 75 百分位对应的值…

您可能会注意到,每一列的计数都不同。这说明我们可能有一堆缺失值。值可能丢失的原因有很多,例如收集数据失败、数据丢失、无响应值。缺失值会使您的发现无效,因此设计数据收集方法非常重要。可以使用不同的方法来减轻这些缺失值对我们分析的影响。

存在两种方法,部分删除插补。部分删除就像它听起来的那样,将我们用于分析的数据集限制在我们可用的数据范围内。我们可以使用的一种方法叫做列表式删除。在我们执行列表删除的情况下,我们将从所有分析中排除特定的数据点,即使存在一些有用的值。

当我们没有太多数据时,或者移除缺失值会损害样本的代表性时,我们会使用插补。仅仅因为缺少值就丢弃一堆条目可能会严重影响我们试图执行的任何分析的统计能力。在这种情况下,对我们的数据中缺失的值进行智能猜测(如近似值)可能是有意义的。例如,我们可以用所有其他值的平均值替换所有缺失值,或者使用线性回归来估计缺失值。然而,插补给数据集带来了偏差和不准确性。这是一个非常困难的问题,新技术也在不断发展。存在更复杂和健壮的方法。

在下面的代码中,我们计算“weight”数组的平均值,并通过将“weight”列中的任何缺失值设置为平均权重来估算它们。

在下一篇文章中,我们将深入实际数据分析!

数据科学简介

原文:https://towardsdatascience.com/intro-to-data-science-part-3-data-analysis-71a566c3a8c3?source=collection_archive---------3-----------------------

第 3 部分:数据分析

  • 第一部分:熊猫和熊猫
  • 第二部分:数据争论

Photo by Markus Spiske on Unsplash

我们将看到统计学和机器学习中分析数据的基本方法。统计使我们能够确保我们正在从数据中进行合理的推断,并检查统计意义,了解置信区间…它们为比较和评估数据提供了一个正式的框架,并使我们能够评估我们的数据集中的感知效果是否反映了整个人群的差异。

在这一部分,我们将看到:

  • 正态分布的 t 检验(韦尔奇检验)
  • 如何处理非正态数据(夏皮罗-维尔克检验),非参数检验(曼-惠特尼 U 检验)
  • 线性回归
  • 如何在 Python 中实现渐变下降

统计检验

您可能用来分析数据的许多统计测试都假设了数据将遵循的概率分布。有许多不同的概率分布,但最常见的是正态分布,它有时也被称为高斯分布或钟形曲线。

Normal distribution

正态分布有两个相关参数。平均值(μ)和标准偏差(σ)。这两个参数插入到概率密度函数中,该函数描述了高斯分布。正态分布关于它的平均值是对称的。了解正态分布将有助于理解我们接下来将看到的参数测试。

T 型测试

我们可能用来比较两组数据的最常见的参数检验之一是 t 检验。t 检验允许检查两组数据之间是否有显著差异。这就是描述统计学和推断统计学的区别。使用描述性统计数据,如平均值,您只能描述我们拥有的样本,但除此之外我们无法进行概括(例如,如果我掷硬币 10 次,得到 7 个正面,而一个朋友得到 5 个正面,这并不意味着我更有可能得到正面,我们也不能说我将总是得到更多正面)。像 t 检验一样,推断统计不仅仅描述我们拥有的样本,还告诉我们可以从我们没有的样本中得到什么。它允许我们超越正在测试的样本进行归纳。t 检验只是测量组间的差异,并将其与组内的差异进行比较。t 值越小,各组越相似,反之,t 值越大,各组越不同。当我们想要比较两个不同的样本检验时,我们进行两个样本的 t 检验。我们将讨论这种称为韦尔奇 t 检验的变体,它不假设相等的样本大小或相等的方差。在 Welch 的 t 检验中,我们使用以下等式计算 t 统计量。

我们还想用下面的等式估计自由度的数量(ν)。

一旦我们有了这两个值,我们就可以估计 p 值。p 值是获得至少与实际观察到的一样极端的检验统计的概率。如果 p 值=0.05,这意味着 t 值大于或等于的概率为 5%。t 检验的目标是接受或拒绝一个零假设。无效假设是我们试图通过测试来否定的陈述。在进行统计检验时,我们通常设置一个 p-临界值。如果 p 值<是 p 临界的,那么我们将拒绝零假设。

计算 p 值可能很繁琐,幸好在 Python 中有一种简单的方法。让我们把这个应用到一个例子中。我们想确定右手和左手击球手的表现是否有差异。无效假设是“惯用右手和惯用左手的击球手之间没有区别”。

首先,我们需要将棒球数据集加载到熊猫数据帧中

 name handedness height weight    avg   HR
0  Brandon Hyde          R     75    210  0.000    0
1   Carey Selph          R     69    175  0.277    0
2  Philip Nastu          L     74    180  0.040    0
3    Kent Hrbek          L     76    200  0.282  293
4   Bill Risley          R     74    215  0.000    0

然后我们分割数据来比较我们的两个子集(右手和左手)

 name handedness height weight    avg  HR
0     Brandon Hyde          R     75    210  0.000   0
1      Carey Selph          R     69    175  0.277   0
4      Bill Risley          R     74    215  0.000   0
6  Steve Gajkowski          R     74    200  0.000   0
7        Rick Schu          R     72    170  0.246  41 name handedness height weight    avg   HR
2      Philip Nastu          L     74    180  0.040    0
3        Kent Hrbek          L     76    200  0.282  293
9      Tom Browning          L     73    190  0.153    2
13        Tom Brown          L     70    168  0.265   64
15  Floyd Bannister          L     73    190  0.175    0

我们使用 ttest_ind()函数执行 t-test。当指定 equal_var = False 时,我们指出我们是否认为两个样本的方差相等。这个 equal_var=false 参数使得 t-test 的这个特定调用等于 Welch 的 t-test。这个函数将返回一个元组。第一个值是数据的 t 值。第二个值是双尾检验的相应 p 值。该函数返回的值假设我们正在执行双边 t 检验,我们只检验两个样本的均值是否不同。

我们选择 p-critical = 0.05,这意味着如果 p-value < 0.05 we would reject the null hypothesis and we could say that there is no significant difference between right-handed and left-handed batters.

Ttest_indResult(statistic=-9.935702226242094, pvalue=3.810274225888738e-23)There is a significant differenceFalse

Non-Normal Data

When performing a t-test, we assume that our data is normal. But we can also encounter probability distribution that are not normal. In this case, we have to use other statistical tests. If we are uncertain, we first need to determine whether or not our data is normal. The shapiro-wilk 检验测量样本取自正态分布总体的可能性。shapiro()函数返回两个值。第一个是夏皮罗-维尔克检验统计量。第二个值是我们的 p 值,我们应该用解释 t 检验的 p 值的方式来解释它。也就是说,给定该数据来自正态分布的零假设,我们观察到夏皮罗-威尔克检验统计值至少与我们看到的一样极端的可能性有多大?

非参数检验

假设我们刚刚确定我们的数据是非正态的,仍然有一些非参数检验,我们可以用来比较两个样本。非参数检验是一种统计检验,它不假设我们的数据来自任何特定的潜在概率分布。一种这样的测试是曼-惠特尼 U 测试,它有时也被称为曼-惠特尼威尔科克森测试。这是对两个群体相同的零假设的检验。mannwhitneyu()函数返回两个值,即 Mann-Whitney 检验统计量和该检验的单侧 p 值。

这些只是我们在对数据进行统计测试时可以使用的一些方法。正如您所想象的,有许多其他的方法来处理来自不同概率分布的数据或者看起来不像来自任何概率分布的数据。数据科学家可以执行许多统计程序。但是理解数据集的底层结构是至关重要的,因此,在给定数据的情况下,哪些统计测试是合适的。

既然我们知道分析现有数据,我们就可以看看是否有办法对数据进行预测。

机器学习

机器学习是人工智能的一个分支,专注于从大量数据中学习来进行预测的系统的构建。但是统计学和机器学习有什么区别呢?

总之答案是不多。这两个领域越来越多地融合在一起,它们共享许多相同的方法。然而,这两个主题之间有一些重要的哲学差异。一般来说,统计学专注于分析现有数据,得出有效的结论,而机器学习专注于做出预测。这意味着:在统计学中,我们非常关心我们的数据是如何收集的,并使用概率模型得出关于现有数据的结论。例如,我们可能试图回答这样一个问题:从统计学上来说,左撇子击球手比右撇子更好吗?在机器学习的情况下,我们更专注于做出准确的预测,如果有更准确的方法根本不使用概率模型,我们就不太愿意使用概率模型。只要我们的机器学习方法持续做出准确的预测,例如,一个球员会打多少个本垒打,我们就不会太担心模型做出什么假设。

机器学习问题有许多不同的类型,但两个常见的是监督学习非监督学习。机器学习通常涉及到针对我们试图解决的问题生成某种类型的模型。我们将把数据输入这个模型,然后试着做出预测。在监督学习中,有标记的输入,我们在其上训练我们的模型。训练我们的模型韦尔奇的测试简单地说就是告诉模型答案是什么样的。监督学习的一个例子是估计一栋新房子的成本,假设我们有许多例子,我们知道一些特征,如平方英尺、房间数量或位置。我们也知道那栋房子卖了多少钱。假设我们知道所有相同的参数,我们可以训练一个模型,然后预测未来的房子会卖多少钱。这是一个回归的例子。

当执行无监督学习时,我们没有任何这样的训练示例。相反,我们有一堆未标记的数据点,我们试图了解数据的结构,通常是通过将相似的数据点聚集在一起。例如,如果我们给一个无监督学习算法提供一堆照片,它可能会将这些照片分成不同的组,比如人的照片、马的照片、建筑物的照片,而不需要事先知道这些组应该是什么。它可能不知道这些群体是人、马还是建筑,但它可以知道这些不同的群体存在。

线性回归

回到我们的棒球数据集,我们想要创建一个模型来预测一个不在我们的数据集中的球员一生中的本垒打数。我们可能能够解决这个问题的一个方法是使用线性回归,机器学习的一个基本实现是通过使用梯度下降来执行线性回归。

当进行线性回归时,我们通常有许多数据点(下面的图中从 1 到 m)。每个数据点都有一个输出变量(Y)和一些输入变量(X1 到 Xn)。在我们的棒球例子中,Y 代表一生中本垒打的次数,X1 到 Xn 代表他们的身高和体重。

目标是通过将输入变量乘以某组系数(θ1 至θn)来构建一个模型,该模型可预测每个数据点的输出变量的值。我们称每个θ为模型的一个参数或权重。它表明了某个输入变量 X 对于输出变量 y 的预测有多重要。该模型的建立方式是,我们将每个 X 乘以相应的θ,并将它们相加,得到 y。从等式中可以看出,θ越小,θ和 X 的乘积越小,反之亦然。计算θ时,对于在预测 Y 时不太重要的输入 X,θ较小,而对于贡献较大的输入 X,θ较大。最佳等式是最小化我们预测的 Y 和我们观察到的 Y 之间所有数据点的差异的等式。我们需要做的是找到产生最佳预测的θ,这是由于梯度下降而最小化这种差异。

为了进行梯度下降,我们首先需要定义以下成本函数 J(θ)。

成本函数旨在衡量我们当前的θ集在数据建模方面的表现。所以我们想最小化成本函数的值。正如我们在上图中看到的,成本函数只是误差平方和的一半。请注意,x 上标 I 代表我们的整个 x 的集合。所以预测的 Y 等于我们在上面看到的两个图中 x 和θ的乘积之和。

那么,我们如何找到θ的正确值来最小化我们的成本函数 J(θ)?梯度下降是一种算法,它对θ进行一些初始猜测,并迭代地改变θ;使得 J(θ)不断变得越来越小,直到它收敛到某个最小值。

实现梯度下降算法

现在,让我们实现梯度下降算法的基本功能,以在一个小数据集中找到边界。首先,我们将从 plot_line()函数开始,它将帮助我们绘制和可视化数据。注意 gradient_descent()函数将 alpha 作为参数。Alpha 被称为学习率,它基本上设置了每次迭代的步骤。在更新权重方面迈出大步会让你超越权利等式。另一方面,小步前进会增加达到收敛所需的迭代次数。它通常涉及一个微调过程,以找到正确的平衡。

数据集应该是这样的:

我用蓝色标出了初始化线。这条线通常是随机设置的

每 10 次迭代,我就打印一次成本。请记住,成本应该一直降低,直到达到可能的最低点(收敛)。

('\n========== Epoch', 0, '==========')
Cost:  16.004954
('\n========== Epoch', 10, '==========')
Cost:  7.52057727374
('\n========== Epoch', 20, '==========')
Cost:  3.71424722592
('\n========== Epoch', 30, '==========')
Cost:  2.0064263714
('\n========== Epoch', 40, '==========')
Cost:  1.23996949709
('\n========== Epoch', 50, '==========')
Cost:  0.895797093343
('\n========== Epoch', 60, '==========')
Cost:  0.741057191151
('\n========== Epoch', 70, '==========')
Cost:  0.671295578372
('\n========== Epoch', 80, '==========')
Cost:  0.639655519089
('\n========== Epoch', 90, '==========')
Cost:  0.625117716849

在这里,我们可以看到不同的步骤,在这些步骤中,直线朝着更好的回归方向更新。您可以随意使用这段代码并调整不同的参数。你可以改变时代,学习率(阿尔法),改变数据集…

初学者的深度学习

原文:https://towardsdatascience.com/intro-to-deep-learning-d5caceedcf85?source=collection_archive---------0-----------------------

如果你在技术领域工作,或者对技术领域感兴趣,你可能会经常听到“深度学习”这个词。计算机科学的新兴领域正在彻底改变人工智能,使我们能够建造未来的机器和系统。虽然深度学习让我们的生活变得更容易,但理解它的工作原理可能很难。我花了相当多的时间探索深度学习的世界,主要是计算机视觉应用,我学到了一两件关于它的事情,因此我在这里分享我学到的东西。

首先,在你理解深度学习之前,知道什么是机器学习很重要。很简单,机器学习是人工智能(AI)的一个领域,允许计算机“学习”。传统上,我们总是通过向计算机提供一组严格的指令(也称为计算机程序)来让它做事情。机器学习使用一种非常不同的方法。我们不是给计算机一套如何做某事的指令,而是给它如何学习做某事的指令。我们通过给它数据和编程,让它使用各种数学和统计模型来理解数据,并学习根据数据做出决策。例如:想象一个系统,可以将动物的图片分类为‘猫’、‘狗’、‘老虎’、‘狮子’或者‘大象’。你可以给计算机编程,让它接受这些动物的图像,并自己找出不同动物图像之间的视觉模式和差异,而不是手动从这些动物的图像中找到独特的视觉特征和模式,然后对其进行编码。这可以通过一系列不同的算法来实现。这里的想法是,计算机可以自己“学习”,而不是被专门编程来完成某项任务(在这种情况下,对不同动物的图像进行分类)。教计算机的过程(即给它学习的数据)被称为训练

深度学习,顾名思义,是机器学习的一个分支。深度学习主要涉及使用深度人工神经网络(算法/计算模型,大致受人脑启发)来解决机器学习问题。回到我之前举的例子,今天最先进的图像分类解决方案使用深度学习。注意:有时,使用决策树和/或其他机器学习算法也可以称为深度学习,但在大多数情况下,深度学习涉及到神经网络的使用。

那么,什么是神经网络?这里有一个类比:把神经网络想象成一系列一个接一个的门,把你自己想象成神经网络的“输入”。每次你打开一扇门,你就变成了一个不同的人(也就是说,你在某些方面发生了变化)。当你打开最后一扇门的时候,你已经变成了一个完全不同的人。当你从最后一扇门出去时,你就成了神经网络的“输出”。在这种情况下,每扇门代表一个。因此,神经网络是以某种方式转换输入以产生输出的层的集合。神经网络中的每一层都由“权重”和“偏差”组成——这些只是增加输入的数字。神经网络的总体思想是,它接受一些输入(通常是代表某些东西的数字的集合,例如图像中像素的红-绿-蓝值),使用其层中的权重和偏差对输入应用一些数学变换,并最终输出。如果你以前上过线性代数课,你可以把输入、输出和权重看成矩阵。输入矩阵通过一系列矩阵(即各层的权重和偏差矩阵)进行转换,成为输出。当然,这是一个关于神经网络如何工作的非常简单的描述,但是你已经明白了(我希望)。

一个深度神经网络只是一个有许多层的神经网络(当你在另一层上堆叠层时,神经网络不断变得“更深”)。多少才算多?嗯,有一个由 16 层组成的 VGG16 神经网络架构(用于图像分类),还有一个由 152 层组成的 ResNet 架构(也用于图像分类)——因此,范围相当广。深度学习的基本思想是使用多层神经网络。

现在,问题是:一个神经网络如何学习?反向传播!正如我之前所说,神经网络由层组成,这些层由权重和偏差组成(这些只是数字的集合)。在训练阶段,神经网络试图找到导致最准确输出的正确权重/偏差。它使用一种叫做反向传播的方法来实现。在训练神经网络之前,随机地或者根据先前训练的模型初始化权重/偏差。无论哪种方式,当训练发生时,神经网络根据它“学习”的内容改变这些权重和偏差。当我们建立一个神经网络时,我们必须决定(即选择或设计)一个叫做成本函数的东西。成本函数基本上只是一个数学函数,它接受来自神经网络的输出(对于给定的输入)和基本事实数据(即对于给定的输入,来自神经网络的预期输出),并计算来自神经网络的结果有多差。使用像梯度下降这样的优化技术,计算机计算如何改变权重和偏差,以使成本函数最小化(如果你以前学过微积分,这将对你更有意义——还记得优化/最小化/最大化函数吗?).随着它对越来越多的数据进行训练,它会一直这样做(从神经网络获得输出,计算成本并反向传播以改变权重)。随着时间的推移,权重和偏差会随着数据进行调整,(希望)您最终会得到一个具有高输出精度的神经网络。请记住,神经网络的实际有效性或准确性在很大程度上取决于用于训练它的数据;因此,构建或选择合适的数据集非常重要。没有好的数据(和大量的数据),很难训练出精确的神经网络。

PS:代价函数基本上衡量的是神经网络的不精确程度;当我们通过改变权重/偏差来最小化成本函数时,我们本质上是试图使神经网络在数学上更精确(如成本函数所定义的)。然而,这种准确性取决于它接受训练的数据;因此,低成本并不一定意味着神经网络得到了充分的训练。**

至此,你应该对什么是机器学习、深度学习、神经网络有了基本的了解。这就是我想通过这篇文章分享的全部内容。我知道网上的许多资源可能看起来非常技术性或吓人,所以我尽量保持简单。当然,我写的很多东西都是过度简化的,旨在帮助任何人获得深度学习的基本概念。如果你想知道更多,你应该考虑在这个领域做更多的研究——这对我来说是一次非常有益的经历!

最后,这是给那些想了解更多深度学习的人的。如果你以前从未研究过机器学习,你可以考虑参加 Udacity 上的机器学习入门课程。我认为这是一个非常好的开始,尤其是如果你完全没有机器学习的经验或知识。进入深度学习将需要你熟悉微积分和线性代数,至少在基本水平上理解正在发生的事情。如果你了解这一点,我会推荐你参加斯坦福大学的 CS231N 课程(可在此链接免费在线获得),但这只是因为我在深度学习方面的大部分经验都是在计算机视觉方面,这也是该课程的重点。斯坦福大学还提供了另一门名为 CS224N 的课程,专注于深度学习的自然语言处理。这两者都应该是一个很好的起点。然而,在一天结束时,大多数学习都是在你试图自己构建东西时发生的,所以如果你想更深入地进行深度学习,请整理好基础知识,并开始尝试神经网络。此外,寻找关于神经网络的研究论文(架构、应用等。)并阅读它们!我自己也在学习,所以如果你遇到任何有趣的学习材料,请一定和我分享。

期待由人工智能和深度学习驱动的激动人心的未来!

描述统计学简介

原文:https://towardsdatascience.com/intro-to-descriptive-statistics-252e9c464ac9?source=collection_archive---------0-----------------------

描述性统计分析帮助你理解你的数据,是机器学习非常重要的一部分。这是因为机器学习就是做预测。另一方面,统计学就是从数据中得出结论,这是必要的第一步。在本帖中,你将了解最重要的描述性统计概念。它们将帮助你更好地理解你的数据试图告诉你什么,这将导致整体更好的机器学习模型和理解。

目录:

  • 介绍
  • 正态分布
  • 集中趋势(平均值、众数、中位数)
  • 可变性的度量(范围,四分位范围)
  • 方差和标准差
  • 形式
  • 歪斜
  • 峭度
  • 摘要

介绍

对数据集进行描述性统计分析绝对至关重要。许多人跳过了这一部分,因此失去了许多关于他们数据的有价值的见解,这往往会导致错误的结论。慢慢来,仔细运行描述性统计,确保数据满足进一步分析的要求。

但是首先,我们应该回顾一下统计学到底是什么:

统计学是数学的一个分支,处理数据的收集、解释、组织和解释。

在统计学中,有两个主要类别:

1。描述性统计:在描述性统计中,你通过数字计算或图表来描述、展示、总结和组织你的数据(总体)。

2。推断统计:推断统计是由更复杂的数学计算产生的,它允许我们根据对样本的研究来推断趋势,并对总体做出假设和预测。

正态分布

正态分布是统计学中最重要的概念之一,因为几乎所有的统计检验都需要正态分布的数据。它基本上描述了大样本数据在绘制时的样子。它有时被称为“钟形曲线”或“高斯曲线”。

推理统计和概率计算要求给出正态分布。这基本上意味着,如果你的数据不是正态分布的,你需要非常小心你应用的统计测试,因为它们可能会导致错误的结论。

如果您的数据是对称的、钟形的、居中的和单峰的,则给出正态分布。

在完美的正态分布中,每一边都是另一边的精确镜像。它应该看起来像下图中的分布:

你可以在图片上看到,分布是钟形的,这仅仅意味着它没有严重见顶。单峰意味着只有一个峰值。

集中趋势

在统计学中,我们必须处理均值、众数和中位数。这些也被称为“集中趋势”。这只是三种不同的“平均值”,当然也是最受欢迎的一种。

平均值是简单的平均值,被认为是对单个样本的总体趋势做出假设的最可靠的度量。集中趋势确定数据值围绕其平均值、众数或中位数聚集的趋势。平均值由所有值的总和除以值的个数计算得出。

众数是数据中最常出现的值或类别。因此,如果没有重复的数字或没有相同的类别,数据集就没有模式。一个数据集可能有多种模式,但我将在下面的“模态”一节中介绍这一点。
该模式也是可用于分类变量的集中趋势的唯一衡量标准,因为您无法计算变量“性别”的平均值。您只需将分类变量报告为数字和百分比。

中位数是数据的“中间”值或中点,也称为“第 50 百分位”。请注意,中位数比平均值受异常值和偏差数据的影响要小得多。我将通过一个例子来解释这一点:假设您有一个房屋奖励数据集,大部分奖励从 10 万美元到 30 万美元不等,但包含一些价值超过 300 万美元的房屋。这些昂贵的房子会严重影响价值,因为它是所有价值的总和,除以价值的数量。中位数不会受到这些异常值的严重影响,因为它只是所有数据点的“中间”值。因此,中位数是一个更适合用来报告数据的统计数字。

在正态分布中,这些度量都落在同一中线点。这意味着平均值、众数和中位数都是相等的。

差异量数

最受欢迎的变异性度量是极差、四分位差(IQR)、方差和标准差。这些用于测量数据中的分布或变化量。

范围描述数据中最大和最小点之间的差异。

四分位数间距(IQR)是上四分位数(第 75 个)和下四分位数(第 25 个)之间的统计离差的度量。

范围衡量的是数据点的开始和结束位置,而四分位数范围衡量的是大多数值的位置。

对于初学者来说,标准差和方差之间的区别往往有点难以理解,但我会在下面详细解释。

方差和标准差

像范围和 IQR 一样,标准差和方差也衡量我们的数据有多分散(例如离差)。因此,它们都是由平均值派生出来的。

方差的计算方法是找出每个数据点与平均值之间的差值,将它们平方,求和,然后取这些数字的平均值。

在计算过程中使用正方形,因为它们比接近平均值的点更重视异常值。这可以防止平均值以上的差异抵消平均值以下的差异。

方差的问题在于,由于平方,它与原始数据的度量单位不同。

**假设您正在处理一个包含厘米值的数据集。你的方差是平方厘米,因此不是最好的测量。

这就是为什么标准差用的比较多,因为它是在原单位。它只是方差的平方根,正因为如此,它被返回到原始的度量单位。**

让我们看一个说明方差和标准差之间区别的例子:

假设一个数据集包含 1 到 15 之间的厘米值,其平均值为 8。对每个数据点和平均值之间的差求平方,并对平方求平均,得到 18.67(平方厘米)的方差,而标准偏差是 4.3 厘米。

当标准偏差较低时,您的数据点往往接近平均值。高标准偏差意味着您的数据点分布在很大的范围内。

当数据为单峰时,最好使用标准差。在正态分布中,大约 34%的数据点位于平均值和高于或低于平均值的一个标准差之间。由于正态分布是对称的,68%的数据点落在平均值以上一个标准差和平均值以下一个标准差之间。大约 95%落在低于平均值的两个标准偏差和高于平均值的两个标准偏差之间。并且大约 99.7%落在平均值以上三个标准偏差和平均值以下三个标准偏差之间。

下图完美地说明了这一点。

通过所谓的“Z 得分”,您可以检查特定数据点有多少标准差低于(或高于)平均值。对于熊猫,您只需使用“STD()”功能。为了更好地理解正态分布的概念,我们现在将讨论模态、对称性和峰值的概念。

形式

****一个分布的模态是由它包含的峰的数量决定的。大多数分布只有一个峰值,但也有可能遇到有两个或更多峰值的分布。

下图显示了三种形态的视觉示例:

单峰意味着分布只有一个峰值,这意味着它只有一个频繁出现的分数,聚集在顶部。双峰分布有两个频繁出现的值(两个峰值),多峰分布有两个或几个频繁出现的值。

歪斜

偏斜度是对分布对称性的一种度量。

因此,它描述了一个分布与正态分布有多大的不同,或者向左,或者向右。偏斜值可以是正数、负数或零。请注意,完美的正态分布的偏斜度为零,因为平均值等于中位数。

下面你可以看到不同类型的偏斜度:

****如果数据堆积在左边,使得尾部指向右边,我们称之为正偏斜。

****如果数据堆积到右边,会出现负偏斜,使得尾部指向左边。注意,正偏斜比负偏斜更频繁。

对分布的偏斜度的一个很好的度量是皮尔逊偏斜系数,它提供了对分布对称性的快速估计。要计算熊猫的偏斜度,你只需使用“skew()”函数。

峭度

峰度测量数据集与正态分布相比是重尾还是轻尾。峰度高的数据集尾部重,离群值多,峰度低的数据集尾部轻,离群值少。请注意,直方图是显示数据集的偏斜度和峰度的有效方法,因为您可以很容易地发现数据是否有问题。概率图也是一个很好的工具,因为正态分布是沿着直线的。

在下图中,您可以看到正倾斜数据集的两种情况:

用数学方法测量分布的峰度的一个好方法是 fishers 峰度测量法。

现在我们将讨论三种最常见的峰度。

正态分布称为中峰度,峰度为零或接近零。与正态分布相比,宽峰分布具有负峰度,并且尾部非常细。尖峰分布的峰度大于 3,厚尾意味着该分布产生更多的极值,并且具有相对较小的标准偏差。

如果你已经认识到一个分布是偏斜的,你不需要计算它的峰度,因为这个分布已经不正常了。在 pandas 中,您可以简单地通过调用“Kurt osis()”函数来查看峰度。

摘要

这篇文章给了你一个正确的描述统计学的介绍。您学习了正态分布的样子以及它的重要性。此外,您还了解了三种不同的平均值(平均值、众数和中位数),也称为集中趋势。之后,您学习了极差、四分位差、方差和标准差。然后我们讨论了三种类型的模态,你可以用偏斜度来描述一个分布和一个正态分布有多大的不同。最后,你学习了薄黑洞、中黑洞和宽黑洞的分布。

这篇文章最初发表在我的博客上(【https://machinelearning-blog.com】T2)。

数据科学的描述统计和概率介绍

原文:https://towardsdatascience.com/intro-to-descriptive-statistics-and-probability-for-data-science-8effec826488?source=collection_archive---------2-----------------------

目录:

  • 介绍
  • 集中趋势的度量(平均值、众数、中位数)
  • 可变性测量(范围、IQR、方差、标准差)
  • 概率(伯努利试验,正态分布)
  • 中心极限定理
  • z 分数

简介:

在描述统计学中,你通过数字计算、图表或表格来描述、展示、总结和组织你的数据。在描述性统计中,一些常用的度量是集中趋势,另一些是数据集的可变性。

描述性统计分析帮助我们理解我们的数据,并且是机器学习的非常重要的部分。对我们的数据集进行描述性统计分析绝对至关重要。许多人跳过了这一部分,因此失去了许多关于他们数据的有价值的洞察力,这常常导致错误的结论。

集中趋势的测量:

它用代表其分布中心的单个值来描述一整套数据。有三种主要的集中趋势测量方法:

  1. 均值:是观察值之和除以样本量。这不是一个稳健的统计数据,因为它受到极值的影响。因此,非常大或非常低的值(即异常值)会扭曲答案。
  2. 中位数:数据的中间值。它将数据分成两半,也称为第 50 百分位。与平均值相比,它受异常值和偏差数据的影响要小得多。如果数据集中的元素数量是奇数,则最中间的元素是中值。如果数据集中的元素数量是偶数,则中位数将是两个中心元素的平均值。
  3. 模式:数据集中出现频率较高的值。因此,一个数据集没有模式,如果没有类别是相同的,也可能一个数据集有一个以上的模式。这是唯一可以用于分类变量的集中趋势的量度。

可变性测量

可变性的度量也称为数据的分布,描述了一组观察值的相似性或差异性。最受欢迎的变异性度量是极差、四分位差(IQR)、方差和标准差。

  1. 范围:范围描述数据中最大和最小点之间的差异。范围越大,数据越分散。
  2. IQR :四分位数间距(IQR)是对上四分位数(第 75 个)即第三季度和下四分位数(第 25 个)即 Q1 之间的统计离差的衡量。你可以通过下面的例子理解这一点。

虽然范围衡量的是数据点的开始和结束位置,但四分位数范围衡量的是大多数值所在的位置。

3.方差:是均值的均方差。方差的计算方法是找出每个数据点与平均值之间的差值,将它们平方,求和,然后取这些数字的平均值。

方差的问题在于,由于平方,它与原始数据的度量单位不同。

4.标准差:标准差因为是原单位,所以用的比较多。它只是方差的平方根,正因为如此,它被返回到原始的度量单位。

当标准偏差较低时,您的数据点往往接近平均值。高标准偏差意味着您的数据点分布在很大的范围内。

当数据为单峰时,最好使用标准差。在正态分布中,大约 34%的数据点位于平均值和高于或低于平均值的一个标准差之间。由于正态分布是对称的,68%的数据点落在平均值以上一个标准差和平均值以下一个标准差之间。大约 95%落在低于平均值的两个标准偏差和高于平均值的两个标准偏差之间。并且大约 99.7%落在平均值以上三个标准偏差和平均值以下三个标准偏差之间。

下图完美地说明了这一点。

通过所谓的“Z 得分”,您可以检查特定数据点有多少标准差低于(或高于)平均值。

可能性

我将简单介绍一下概率。在给出概率的实际定义之前,让我们先看看一些术语。

  • 实验:实验可能类似于——德里每天是否下雨。
  • 结果:结果是单次试验的结果。如果今天下雨,今天的审判结果就是“下雨了”。
  • 事件:事件是实验的一个或多个结果。对于德里每天是否下雨的实验,事件可能是“下雨了”或“没下雨”。
  • 概率:简单来说就是事件发生的可能性。所以如果今天有 60%的可能性下雨,那么下雨的概率是 0.6。

伯努利 试验

像掷硬币一样有两种结果的实验叫做伯努利试验。

n 次伯努利试验中成功次数的概率分布称为二项式分布

二项式分布的公式如下。

Binomial distribution Formula

具有不同成功概率和 100 个随机变量的二项分布的概率质量函数

Probability Mass Function

连续随机变量(变量可以取两点之间的任何可能值)的概率分布称为概率密度函数。在连续随机变量的情况下,将有无限个试验。

概率密度函数下的面积给出了随机变量在该范围内的概率。

如果我有一个总体数据,我从数据中随机抽取相同大小的样本,样本均值大致呈正态分布。

正态分布

它基本上描述了大样本数据在绘制时的样子。它有时被称为“钟形曲线”或“高斯曲线”。

推理统计和概率计算要求给出正态分布。这基本上意味着,如果你的数据不是正态分布的,你需要非常小心你应用的统计测试,因为它们可能会导致错误的结论。

在完美的正态分布中,每一边都是另一边的精确镜像。它应该看起来像下图中的分布:

Normal Distribution

在正态分布中,均值、众数和中位数都相等,并且落在同一中线点。

Normal Distribution Function

均值为 0,标准差为 1 的正态分布称为标准正态分布。标准正态分布曲线下的面积为 1。

中心极限定理

  • 如果我们从一个分布中取随机样本的平均值,并画出平均值,当我们取了足够多的这种样本时,图表就接近正态分布。
  • 该定理还指出,均值将近似等于样本均值,即总体均值。

标准偏差较高的正态分布更平坦,即与标准偏差较低的正态分布相比,分布范围更广。

z 分数

以标准偏差数表示的距离,即观察值远离平均值的距离,是标准分数或 Z 分数。

正 Z 值表示观察值高于平均值 Z 个标准差。Z 分数为负表示该值低于平均值。

观察值= +zσ [是平均值,σ是标准偏差]

从上图来看,平均值 2 附近的标准偏差为 0.95,这意味着数据位于该范围内的概率为 0.95。

对于特定的 Z 得分,我们可以查看 Z 表,找出值小于该特定 Z 值的概率。

所以,我希望这篇文章给了你一个正确的描述统计学的介绍。

Excel 超级用户熊猫简介

原文:https://towardsdatascience.com/intro-to-pandas-for-excel-super-users-dac1b38f12b0?source=collection_archive---------2-----------------------

我和微软 Excel 认真交往多年。它伴随着我度过了大学时光和两份分析师工作。我非常了解 Excel 它所有的曲线和边缘,它的捷径和不完美。虽然它不是最有效的工具,但它完成了工作,不需要我学习如何编码。

然后,大概八个月前,我开始读研,被介绍认识了 Python。我们成了即时的朋友。随着 Python 的出现,出现了一种叫做熊猫的东西。一开始我不确定我对熊猫的感觉。老实说,感觉有点像这样:

在 Excel 中花了我 10 秒钟的分析将需要 10 多分钟的谷歌搜索和反复试验。然而,随着时间的推移,我越来越喜欢熊猫了。它能做 Excel 能做的一切,甚至更多,只是更快、更灵活、完全可复制。我每天都在学习一些关于熊猫的新知识,但是还没有达到我和 Excel 之间的亲密程度。

与此同时,我想通过分享一些常用的 Excel 函数/工具来传播这种爱,这些函数/工具可以在熊猫身上进行分析。在下面的例子中,我们将探索来自芝加哥公立学校 2016-2017 学年的学校进度报告数据。数据包含学校级别的详细信息,每行一所学校。

表示数据

Excel :数据在 Excel 表格中用列、行、单元格表示。对于不同的数据集,我们可以有不同的工作表。

Pandas :数据的“表格”存储在数据帧中。我们可以从头开始创建数据框架,或者更常见的是,从 csv 文件导入数据:

import pandas as pd

sy1617 = pd.read_csv('CPS-Progress-Reports_SY1617.csv', index_col='School_ID')

列将被标记为它们在 csv 中的样子。行也标有唯一标识符,称为“索引”我们选择了 School_ID 列作为索引,因为每个学校 ID 唯一地标识一个学校行。如果我们在加载 csv 时没有明确地指定一个列作为索引,Pandas 将自动生成一个索引,标记从 0 开始的行。

要快速查看数据框的顶部:

sy1617.head()

访问数据

Excel:Excel 的一个好处就是数据随时都在我们眼前。我们使用基本点和点击命令或键盘快捷键来选择数据。

Pandas :有几种不同的方法来访问特定的行、列和单元格。

若要访问单个列,请使用方括号。输出是一个 Series 对象,它是一个一维数组:

sy1617['School_Type']

若要访问多个列,请指定列名列表。输出现在是一个数据帧:

sy1617[['School_Type', 'Primary_Category']]

我们可以通过索引标签来访问一行:

sy1617.loc[400062]

我们也可以改为指定行号:

sy1617.iloc[0]

要访问单个单元格,只需按行和列划分子集:

sy1617.loc[400062]['School_Type']

基本汇总统计

Excel :应用计数、平均值、中位数、百分位数等。跨所需列或行的函数。

熊猫:描述方法可以显示所选列的汇总统计数据。输出的统计类型将取决于列的数据类型。

文本列将输出计数、唯一、最常见和最常见的频率:

sy1617[['School_Type', 'Primary_Category']].describe()

数字列将输出计数、平均值、标准差、最小值、最大值以及下限、50%和上限百分点:

sy1617[['School_Survey_Student_Response_Rate_Pct', 'Suspensions_Per_100_Students_Year_1_Pct']].describe()

过滤

Excel :通过特定值或某些条件将过滤器应用到子集数据的列。

熊猫:子集 a 数据帧按某种条件。首先,我们将一个条件语句应用于一个列,并获得一系列真/假布尔。然后,我们将这些结果放入方括号中,以便只为满足条件(即 True)的行划分数据帧的子集。

例如,筛选“特许”类型学校的数据框架:

is_charter = sy1617['School_Type'] == 'Charter'
sy1617[is_charter]

我们可以使用 isin 方法在一列中查找多个值,例如“特许”和“磁铁”学校:

charter_magnet = sy1617['School_Type'].isin(['Charter','Magnet'])
sy1617[charter_magnet]

筛选学生调查回复率至少为 80%的学校:

gt80 = sy1617['School_Survey_Student_Response_Rate_Pct'] >= 80
sy1617[gt80]

我们可以用&和|组合多个条件:

sy1617[is_charter & gt80]

整理

Excel :按某一列或一组列对数据进行排序。

Pandas :使用 sort_values 方法对数据进行排序。例如,按小学/初中/高中和学校名称的字母顺序排序:

sy1617.sort_values(by=['Primary_Category', 'Short_Name'])

数据透视表

Excel:数据透视表是我在 Excel 中的首选。拖放功能使得以任何方式聚集和过滤数据变得容易。下面是一个数据透视表示例,它在行中按学校类型分组,在列中按小学类别分组,并计算表中学校调查学生响应率百分比的平均值。

熊猫:我们可以使用 pivot_table 函数在熊猫中生成同一个表。得到的数据帧并不漂亮,但是它完成了任务!

pd.pivot_table(sy1617, values='School_Survey_Student_Response_Rate_Pct', index='School_Type', columns=['Primary_Category'], aggfunc=np.mean)

视频库

Excel: VLOOKUP s 是我在 Excel 中的首选。简而言之,VLOOKUP 函数在一系列单元格中搜索一个特定的值,然后返回一个与该值位于同一行的值。

我过去非常依赖 VLOOKUPs 将一个数据集的相关列与另一个数据集连接起来。例如,假设我们有芝加哥公立学校前一年的学校进度报告,在一个标题为“SY1516”的表中。我们想知道 SY1617 数据集中每所学校的 sy 1516 Student _ achievement _ Rating,以便我们可以分析两年间评级的变化。

我们可以通过创建一列 VLOOKUPs 来引入这些数据,使用 School_ID 作为查找值:

如果我们想从 SY1516 表中引入任何其他列,我们需要为每个列添加一个额外的 VLOOKUP 列。

Pandas: 在 Pandas 中,连接两个数据集要简单得多。我们可以用数据帧做很多事情,你可以在这里找到一些很好的合并、连接和连接的例子。

现在,让我们使用 Pandas 来复制上面的 VLOOKUP 示例。 merge 函数允许我们使用它们的索引(School_ID)作为一种“查找值”来组合两个数据集。

# read in the csv for prior year's data
sy1516 = pd.read_csv('Chicago_Public_Schools_-_School_Progress_Reports_SY1516.csv', index_col='School_ID')sy1617_short = sy1617[['Student_Attainment_Rating', 'Long_Name']]
sy1516_short = sy1516[['Student_Attainment_Rating']]
pd.merge(sy1516_short, sy1617_short, how='right', left_index=True, right_index=True, suffixes=('_1516','_1617'))

注意:how='right '确保我们从第二个/right (SY1617)数据帧中捕获所有学校 id;这类似于 SQL 中的右外连接。

或者,由于 School_ID 是两个数据帧的索引,我们可以使用 join 方法来获得相同的结果:

sy1617_short.join(sy1516_short, how='left', lsuffix='_1617', rsuffix='_1516')

使用合并和连接,我们可以根据需要轻松地从上一年的数据中提取尽可能多的列。

这些只是熊猫可以执行 Excel 功能的许多方法中的一些,还有更多。我希望这能激励你考虑离开 Excel,给熊猫一个机会!

介绍 PCFGs,最左边的推导,乔姆斯基 NF,CKY 算法和许多其他可怕的单词变得简单

原文:https://towardsdatascience.com/intro-to-pcfgs-left-most-derivations-chomsky-nf-cky-algorithm-and-many-other-scary-words-80114e896369?source=collection_archive---------3-----------------------

写这篇文章的想法是非常自发的,只要我现在工作的主要领域是命名实体识别和从原始多语言文本中提取高级数据;概率上下文无关文法绝对不是我感兴趣的类型(二叉树结构一点也不吸引我),我也不是用 PCFGs 开发一些应用程序的专家。然而,了解这样一个概念对每个自然语言处理科学家来说都是一个很好的实践,所以我为什么不应该花一些时间来研究 PCFG 的基本思想和细节呢?

请不要期望这篇文章是对上下文无关语法世界的“深度探索”,并解释先进的方法论;这只是对想知道它如何工作以及我们在哪里使用它的人的介绍。

上下文无关文法的定义

基本上,我们可以将 CFG 视为元组,由 4 个元素组成: G = (N,E,R,S) ,其中

  • N 是所有非终端符号的集合(在我们的例子中是 POS 标签);
  • E 是所有终端符号(单词)的集合;
  • R 是以下形式的规则集:

  • S 是卓越的开始符号。

如果规则由 2 个元素组成(非终结来自 N 和终结或非终结来自 NE 的并集),那么它是一元规则。如果规则由左边的非终结符和任意长度的终结符和非终结符的序列组成,那么它是一个混合规则。

解析树的定义(最左边的派生)

如果给我们一个上下文无关的语法,那么最左边的派生是来自 E* (由来自 E 的字符串组成的所有可能序列的集合)的一个字符串序列,它形成一个句子。我们正在为索引为 i 的每个 s 检索该字符串,方法是获取索引为 i-1s ,并挑选 N 中最左边的非终结符 X ,并用一些 β 更新它,其中我们在 R 中有一个规则 X → β。

解析树不是一个复杂的概念,但是它们有不同的重要术语,值得解释和讨论。

  • 每个最左边的派生总是以从 E*开始的索引为 n 的字符串 s 结束;
  • s 用指数 n 表示导数的产率;
  • 如果至少有一个 yield 为 s,则来自 E的字符串 s 在语言中。*

概率解析树的定义(概率上下文无关文法)

这个概念解释起来也很简单,但是它背后有很多符号背景。让我们假设,我们的上下文无关文法是不明确的:给定一个上下文无关文法,我们可以有许多产出。对于给定的语法,我们如何考虑什么产量是最好的?正确的答案总是一个——概率。

  • 索引为 G 的 T 是文法 G 下所有可能的最左导子的集合;
  • 对于从 T 到索引为 G 的任何导子 T,我们写 yield(t)来表示来自 E的字符串 s,这是 T(T 中的单词序列)的 yield;*
  • 对于来自 E的给定句子 s,我们用 T(s)来指代集合:*

  • 如果句子 s 至少有一棵解析树,我们说它是语法的。

我们的主要想法是扩展我们的定义,给出可能导数的概率分布。

求导的概率大于零的条件要满足(我们不能有求导是很符合逻辑的,这是完全不可能的):

而且全概率的条件也要满足(概率的和法则;不同的派生是不同的事件,它们一起形成一个结果):

现在,有了这 2 个公式,我们可以将概率上下文无关文法定义为 G = (N,E,R,S) + set(q (α→β))。

这个集合中的每一个元素都是在一个最左边的推导中选择规则α→β的条件概率 q (α→β),假设被展开的非终结点是 α。

现在,我们可以用新的符号以这种方式重新制定全概率规则(现在,我们将 α 视为我们可以拥有的任何最左侧推导的根):

关于导数大于零的概率的想法也保持不变,只是替换了相同的概念:

给定规则集 q (α→β)的整个解析树的概率由联合概率规则定义:

从语料库中导出 PCFG 为了从预定义的语料库中生成先前的概率上下文无关语法,我们需要规则 q (α→β)上的一些概率分布。为了得到它们,我们可以使用最大似然估计,公式如下:

这基本上是条件概率估计的简单定义。我们可以使用拉普拉斯平滑和其他技术来更好地计算我们的概率,这取决于我们正在处理的任务和语料库。

乔姆斯基范式
这种范式背后的思想是,我们的 PCFGs 中使用的每个规则都应该采用以下形式之一:

它只意味着这样一个事实:如果一个节点都不是来自 N 的终端,那么它可以有两片叶子;如果它是来自 E 的终端(单词),那么它可以有一片叶子。

CKY 算法

我认为这个概念是光子晶体光纤光栅理论中最复杂的部分;然而,它的输入是解析树,它显示了我们试图从给定语法的句子中找到的句法依赖。

CKY 算法的目标是找到给定句子和 PCFG 的最可能的分析树;它通过逐步选择最可能的树结构来解决这个问题。

我觉得前面的伪代码不是很好理解,所以我尽量在上面做些小说明。

该算法可以非正式地分为两步:初始化和优化。

初始化部分意味着从语法上给我们正在处理的句子中的每个非终结符赋值;如果有一个以上的终端导致当前的非终端,那么我们要记住他们两个。因此,想象中的“三角形表”的底部填充了起始终端正上方的非终端。

优化部分是 3 个嵌套 for 循环的结构:对于我们正在处理的每个跨度,对于句子的每个开始和结束(结束被定义为开始+跨度)我们正在寻找非结束,这是最可能的树的根,它支配从开始到结束的范围内的子元素(在前面的循环中计算)。使用从+ 1 开始到-1 结束范围的分割点递归地找到最大非终结符(以找到所有可能的单词组合)。

CKY 有不同的变体,可能定义选择非终结点是选择拆分点之前的前一步,以及相反的情况;作者可能会声称我们只是在寻找一个解析树的结构,但是使用 CKY,我们也可以找到最可能的 PCFG 的概率。

结论

我希望这篇文章对不熟悉创建解析树的读者有用,以便理解它的语法结构并能够估计它的概率;我不认为这篇文章对有经验的数据科学家和 NLP 专家有帮助。

说到我的个人经验(我没有很多年的经验),我可以说我从来没有见过真正的解析树在真实数据上运行;人们应该始终明白,这个概念作为理论基础是重要的,但在实践中很少使用。

我见过的解析树的最佳实现来自 NLTK 它的所有工作都做得很好(老实说,这是一个科学软件包应该做的)。

感谢任何形式的反馈,为新的帖子和像这样的小笔记提供了很多灵感。

推荐系统简介

原文:https://towardsdatascience.com/intro-to-recommender-system-collaborative-filtering-64a238194a26?source=collection_archive---------1-----------------------

协同过滤方法:最近邻和矩阵分解

“我们正在离开信息时代,进入推荐时代。”

像许多机器学习技术一样,推荐系统基于用户的历史行为进行预测。具体来说,它是基于过去的经验来预测用户对一组项目的偏好。为了建立推荐系统,最流行的两种方法是基于内容和协同过滤。

基于内容的方法需要项目自身特征的大量信息,而不是使用用户的交互和反馈。例如,它可以是电影属性,如类型、年份、导演、演员等。或者可以通过应用自然语言处理提取的文章的文本内容。协同过滤,另一方面,除了用户对一组项目的历史偏好之外,不需要其他任何东西。因为它是基于历史数据的,所以这里的核心假设是,过去同意的用户将来也会同意。就用户偏好而言,它通常由两类来表达。显式评分,是用户给一个项目的评分,如泰坦尼克号的 5 颗星。这是来自用户的最直接的反馈,表明他们有多喜欢一个项目。隐性评分,间接暗示用户偏好,如页面浏览量、点击量、购买记录、是否听某首音乐曲目等等。在这篇文章中,我将仔细研究一下协同过滤,它是推荐系统的一个传统而强大的工具。

最近邻域

协同过滤的标准方法被称为最近邻算法。有基于用户的 CF 和基于物品的 CF,我们先来看基于用户的 CF 。我们有一个 n × m 的收视率矩阵,用户 uᵢ,i = 1,...n 和项目 pⱼ,j=1,…m。现在,如果目标用户 I 没有观看/评价项目 j,我们想要预测评价 rᵢⱼ。该过程是计算目标用户 I 和所有其他用户之间的相似性,选择前 x 个相似用户,并且取这些具有相似性的 x 个用户的评价的加权平均值作为权重。

Source: https://dzone.com/articles/recommendation-engine-models

虽然不同的人在给予评级时可能有不同的基线,但有些人倾向于给予高分,有些人即使对项目满意也非常严格。为了避免这种偏差,我们可以在计算加权平均值时减去每个用户对所有项目的平均评分,并将其添加回目标用户,如下所示。

计算相似度的两种方法是皮尔逊相关余弦相似

基本上,这个想法是找到与你的目标用户最相似的用户(最近的邻居),并对他们对某个项目的评分进行加权,作为目标用户对该项目评分的预测。

在对项目和用户本身一无所知的情况下,当两个用户给同一个项目相似的评价时,我们认为他们是相似的。类似地,对于基于项目的 CF ,当两个项目从同一个用户收到相似的评级时,我们说它们是相似的。然后,我们将通过计算目标用户对大多数 X 个相似项目的评分的加权平均值来对该用户的项目进行预测。基于项目的 CF 的一个关键优势是稳定性,即给定项目的评分不会随着时间的推移而发生显著变化,这与人类的口味不同。

Source: https://medium.com/tiket-com-dev-team/build-recommendation-engine-using-graph-cbd6d8732e46

这种方法有相当多的局限性。当邻居中没有人评价你试图为目标用户预测的项目时,它不能很好地处理稀疏性。此外,随着用户和产品数量的增长,计算效率也不高。

矩阵分解

由于稀疏性和可扩展性是标准 CF 方法面临的两个最大挑战,因此出现了一种更先进的方法,将原始稀疏矩阵分解为具有潜在因子/特征和较少稀疏性的低维矩阵。那就是矩阵分解。

除了解决稀疏性和可伸缩性的问题,还有一个直观的解释为什么我们需要低维矩阵来表示用户的偏好。一位用户给电影《阿凡达》、《地心引力》和《盗梦空间》打了高分。它们不一定是 3 个独立的意见,而是表明该用户可能喜欢科幻电影,并且可能有更多该用户喜欢的科幻电影。与特定电影不同,潜在特征是由更高层次的属性来表达的,在这种情况下,科幻类别是潜在特征之一。矩阵分解最终给我们的是,一个用户与一组潜在特征有多大程度的契合,一部电影与这组潜在特征有多大程度的契合。与标准的最近邻相比,它的优势在于,即使两个用户没有对任何相同的电影进行评级,如果他们分享相似的潜在品味,仍然有可能找到他们之间的相似性,这也是潜在的特征。

要了解一个矩阵如何分解,首先要了解的是奇异值分解(SVD) 。基于线性代数,任何实矩阵 R 都可以分解为 3 个矩阵 U、σ和 V。继续使用电影示例,U 是 n × r 用户潜在特征矩阵,V 是 m × r 电影潜在特征矩阵。σ是包含原始矩阵的奇异值的 r × r 对角矩阵,简单地表示特定特征对于预测用户偏好有多重要。

要通过降低绝对值对σ值进行排序,并将矩阵σ截断到前 k 维(k 个奇异值),我们可以将矩阵重构为矩阵 A。k 的选择应确保 A 能够捕捉原始矩阵 R 内的大部分方差,因此 A 是 R 的近似值,A≈R。A 和 R 之间的差异是期望最小化的误差。这正是主成分分析的思想。

当矩阵 R 稠密时,U 和 V 可以很容易地解析分解。然而,一个电影评级矩阵是超级稀疏的。尽管有一些填补缺失值的插补方法,但我们将求助于一种编程方法来处理这些缺失值,并找到因子矩阵 U 和 V。我们不是通过 SVD 对 R 进行因子分解,而是尝试直接找到 U 和 V,目的是当 U 和 V 相乘时,输出矩阵 R’是 R 的最接近的近似值,而不再是稀疏矩阵。对于推荐系统,这种数值近似通常通过非负矩阵分解来实现,因为评级中没有负值。

参见下面的公式。查看特定用户和项目的预测评级,项目 I 被记为向量 qᵢ,而用户 u 被记为向量 pᵤ,使得这两个向量的点积是用户 u 对项目 I 的预测评级

我们如何找到最优的 qᵢ和 pᵤ?像大多数机器学习任务一样,损失函数被定义为最小化错误成本。

rᵤᵢ是来自原始用户项目矩阵的真实评级。优化过程是寻找由向量 pᵤ组成的最优矩阵 p 和由向量 qᵢ组成的最优矩阵 q,以最小化预测收视率 rᵤᵢ'和真实收视率 rᵤᵢ.之间的平方和误差此外,L2 正则化已被添加,以防止用户和项目向量的过度拟合。添加偏差项也很常见,它通常有 3 个主要部分:所有项目的平均评级μ,项目 I 的平均评级减去μ(记为 bᵤ),用户给出的平均评级 u 减去 u(记为 bᵢ).

优化

一些优化算法已被广泛用于解决非负因式分解。备选最小二乘法就是其中之一。由于在这种情况下损失函数是非凸的,所以没有办法达到全局最小值,但它仍然可以通过找到局部最小值来达到很好的近似。替代的最小二乘法是保持用户因子矩阵不变,通过对损失函数求导并将其设置为 0 来调整项目因子矩阵,然后在调整用户因子矩阵的同时设置项目因子矩阵不变。通过来回切换和调整矩阵来重复该过程,直到收敛。如果您应用 Scikit-learn NMF 模型,您将看到 ALS 是默认的求解器,也称为坐标下降。Pyspark 还提供了非常简洁的分解包,为 ALS 本身提供了更多的调整灵活性。

一些想法

协同过滤为推荐系统提供了强大的预测能力,同时需要最少的信息。然而,它在某些特定情况下有一些限制。

首先,潜在特征所表达的潜在品味实际上是不可解释的,因为元数据没有与内容相关的属性。以电影为例,在我的例子中,它不一定是像科幻那样的类型。可以是配乐有多励志,剧情有多好等等。协同过滤缺乏透明度和这一级别的信息的可解释性。

另一方面,协同过滤面临冷启动。当一个新的项目出现时,直到它必须被大量的用户评级,该模型才能够做出任何个性化的推荐。类似地,对于尾部没有获得太多数据的项目,模型倾向于给它们较少的权重,并通过推荐更受欢迎的项目来产生受欢迎程度的偏差。

使用集成算法来构建更全面的机器学习模型通常是一个好主意,例如通过添加一些可解释的关键词维度来组合基于内容的过滤,但我们应该始终考虑模型/计算复杂性和性能改善有效性之间的权衡。

统计测试介绍——谁想成为一名程序员?

原文:https://towardsdatascience.com/intro-to-statistical-tests-who-wants-to-be-a-coder-c5e04c3ea7ce?source=collection_archive---------5-----------------------

在 kaggle 闲逛时,我遇到了 2016 年新编码器调查数据集。这是一项针对学习编码的人的调查。

该调查包括一个问题,询问参与者他们感兴趣的工作角色是什么。我很好奇,想知道一个新程序员的年龄和他梦想的工作角色之间是否有联系。

在这篇文章中,我将尝试回答这个问题。这篇文章将是一篇技术文章,我将带你浏览数据探索,如何处理我们的研究问题,以及为了找到答案可以使用哪些统计测试。

首先,让我们导入一些东西:

import numpy as np
import pandas as pd
import scipy.stats
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlinedata = pd.read_csv('2016-FCC-New-Coders-Survey-Data.csv')

对于我们的研究问题,没有说明年龄的受访者对我们来说没有价值。然而,那些指定了年龄但没有指定工作角色的受访者确实给了我们关于新程序员年龄的一般信息。

data = data[data['Age'].notnull()]
data['JobRoleInterest'] = data['JobRoleInterest'].fillna('unspecified').map(lambda job: job.strip())

让我们来考察一下受访者的大致年龄:

data['Age'].plot.hist(title='ages (N=%d, mean=%.2f, median=%.2f)' % (len(data), data['Age'].mean(), data['Age'].median()),
                     bins=100)

我们可以看到数据看起来几乎正常。平均值大于中位数,根据非参数偏度定义,这意味着分布具有右偏度。这意味着学习编程的老年人比年轻人多(平均年龄约为 29 岁)。

有趣的是,当我写这篇文章的时候,我的妻子也在学习编码;她 29 岁,是平均年龄。我想这会帮助我记起…

向下钻取

让我们探讨一下受访者群体的平均年龄,每个群体都是由感兴趣的工作角色定义的。

average_ages = pd.DataFrame([{
            'job': group,
            'N': len(data.loc[rows]),
            'average age': data.loc[rows]['Age'].mean()
        } for group, rows in data.groupby('JobRoleInterest').groups.items()]).sort_values(by='average age')
sns.barplot(data=average_ages, x='average age', y='job', hue='N', palette='Blues_d')

每个组都有一个长度等于该组平均年龄的条形。组越大,条形的颜色越浅。

我选择关注质量保证工程师团队。他们的平均年龄比其他群体大,大约 32 岁。理解这种影响是否是由于偶然,或者也许成为 QA 工程师的愿望更有可能与平均年龄较大的人联系在一起是很有趣的。

我来解释一下“由于偶然”是什么意思。请记住,我们的数据有限。它只讲述了一小部分新编码者的故事。具体来说,我们只有 91 个 QA 工程师的数据。事实上,有更多的新程序员想成为 QA 工程师:有些人没有参与调查,有些未来的新程序员甚至还没有开始学习编码。32 年是新的编码员 QA 工程师样本的意思是。我们很想知道新程序员 QA 的人口平均数是否大于其他新程序员的人口平均数。我们没有全部人口的数据,所以我们能做的最好的事情就是估计他们的平均值。我们通过使用样本均值来实现这一点。样本均值是一个随机变量;这取决于我们得到的样品。我们可以得到一些 QA 工程师的其他样本,样本均值会有所不同。另一方面,总体均值是分布的一个非随机参数。

给定我们拥有的新编码样本,有两种互补的可能性:

  1. QA 群体的平均年龄等于一般新编码者群体的平均年龄。
  2. 他们是不同的。

样本支持第二个选项,但这可能是偶然的(尤其是因为 QA 样本量很小)。接下来,我们将使用统计测试来量化观察到这种偶然差异的可能性。

统计框架

对于外行读者来说,许多统计测试的工作方式如下:首先陈述一个零假设,这是可以描述这个世界的默认选项。在我们的例子中,无效假设是 QA 工程师的平均年龄和其他新程序员的平均年龄没有区别。然后,提出另一个假设。在我们的情况下,另一种选择是差异确实存在。然后,计算检验统计量(数据的函数)。假设零假设为真,检验统计量的分布是已知的,并且可以计算观察检验统计量的现有值的概率。这个概率叫做 p 值。如果 p 值小于我们在进行实验之前决定的显著性水平(例如 0.01),则零假设被拒绝,取而代之的是替代假设。

z 检验

假设年龄呈正态分布,我们可以使用 Z 检验。请注意,即使它们不是正态分布,我们也可以利用中心极限定理,并利用平均年龄近似正态分布的事实。

如果我们知道平均年龄的标准偏差,我们可以通过以下方式归一化平均年龄:

x̄是观察到的平均年龄。μ是假设零假设为真时的预期平均年龄。在我们的例子中,我们选择一般新编码者样本的平均年龄 29.18 为μ。注意,有更好的估计μ的方法,也有更合适的统计检验,例如双样本 T 检验,为了简单起见,我选择不在本文中描述。为了简单起见,我将坚持 29.18。因为我有很多数据,我认为这是一个足够好的估计。

Z 是一个标准的正态随机变量:Z∞N(0,1)。因此,给定 x̄的观测值,我们可以计算它的概率,看看它是否低于一个合理的阈值。如果是的话——我们将拒绝无效假设。

z 检验假设我们知道σ。我们不知道。不要绝望,测试救援!

t 检验

t 检验和 Z 检验一样,区别是不知道σ。它的工作原理如下:

s 是年龄的样本标准差。s/√N 为平均年龄的样本标准差(其中 N 为样本数)。你可以在这里阅读它是如何产生的。

您可以看到该统计数据与在 Z 测试中计算的数据非常相似…T 统计数据根据 T 分布进行分布。每当一个正态分布的随机变量的方差未知时,就会出现 t 分布。

它有一个参数叫做自由度。我不会对此进行详细说明,但直观地说,它捕捉了用于估计参数的数据量。在我们的例子中,σ是被估计的参数,自由度是 n1。

随着自由度接近无穷大,t 分布接近正态分布。

我们将使用scipy来计算这个概率:

qa = average_ages[average_ages['job'] == 'Quality Assurance Engineer'].iloc[0]
t_score = float(qa['average age'] - data['Age'].mean()) / (data['Age'].std() / np.sqrt(qa['N']))
degrees_of_freedom = qa['N'] - 1
p_value = 1 - scipy.stats.t(df=degrees_of_freedom).cdf(t_score)
print 'The p-value is', p_value>>> The p-value is 0.000551459304572

这个数字相当小。这意味着 QA 工程师平均年龄与总人口平均年龄的偏差不到百分之十的概率是由于偶然。如果我们选择 0.01 的显著性水平——这是一个常见的选择,我们会拒绝零假设。

让事情变得复杂一点,你应该注意到我刚才做的叫做单侧检验:我们计算了观察到大于或等于观察值的 T 值的概率。我们实际上关心两个方向上的差异:如果 QA 工程师的平均年龄明显小于预期值(零假设),这也将是有趣的。在 T 检验中,通过将计算出的 p 值乘以 2(由于分布的对称性)来检验两个方向上的显著差异,从而得出

print "The two sided test's p-value is", p_value * 2>>> The two sided test's p-value is 0.00110291860914

仍然重要…

模拟

统计学家喜欢统计测试。它们功能强大,但有两大缺点:

  1. 他们对数据进行假设。在我们的例子中,样本平均年龄并不正常。近似正态,所以 T 检验结果是近似值。不过还是很不错的一个…
  2. 有时他们会让你测试一些类似的东西,但不完全是你想要的。在我们的例子中,这不是真的:我们感兴趣的是平均差异,而这正是 T 检验所提供的。如果我们想测试一些更复杂的东西,而没有对用例进行经典的统计测试,我们会有麻烦。

为了解决这两个问题,我们可以使用模拟。我们首先计算观察数据的一些统计数据——就像以前做的那样。我们没有计算观察统计值的概率,而是模拟了许多假设零假设为真的实验。我们计算实验中产生一个统计量的部分,这个统计量至少和我们以前计算的统计量一样极端。

让我解释一下为什么模拟有效:如果一个人选择使用假设得到满足的统计检验,计算出的 p 值就是观察到一个统计数据的真实概率,该统计数据至少与从实际数据计算出的统计数据一样极端,假设零假设为真。我们可以把它当作伯努利试验,其中 p 值是成功的概率。执行模拟就像多次运行伯努利试验。运行模拟的目标是估计成功的概率,即 p 值。使用 MLE 方法,我们简单地估计这个概率是成功的分数。随着模拟次数接近无穷大,该估计量接近真实 p 值。

让我们在我们的例子中尝试这种方法:零假设表明 QA 工程师的平均年龄和普通新编码员的平均年龄没有区别。这意味着 QA 工程师小组观察到的平均年龄也可以被新编码员的任何随机小组观察到。所以这正是我们要做的:我们将随机抽取一个与 QA 工程师小组规模相同的小组,并计算他们的平均年龄与一般新编码员平均年龄之间的差异:

observed_diff = abs(qa['average age'] - data['Age'].mean())
num_of_simulations = 100000
num_of_extreme_values = sum(abs(data.sample(n=qa['N'])['Age'].mean() - data['Age'].mean()) >= observed_diff
                            for _ in range(num_of_simulations))
p_value = float(num_of_extreme_values) / num_of_simulations
print 'The p-value is', p_value>>> The p-value is 0.0007

我们得到了相似的结果,但是有点不同。请注意,我们运行的模拟越多,结果就越精确(它将趋向于真实的 p 值)。

为什么它不同于 T 检验方法?因为 T 检验假设数据是正态的,而它只是近似正态的。

在过去,计算机速度很慢,计算能力很昂贵,所以运行模拟没有太大意义。然而,如今它确实有意义——至少在某些情况下。这是一个很好的方法,应该在需要的时候使用。这里的是一篇很棒的帖子,它进一步讨论了模拟方法。

多重测试问题

你们中的一些人可能已经注意到我的分析是有问题的:它引发了多重测试问题。只有在检查数据后,我才注意到 QA 工程师的平均年龄高于其他组的平均年龄。然后我做了一个统计测试,看看这是否是由于偶然。问题是,因为我们有多个组,我们检查的组越多,一个组在平均年龄上有显著差异的可能性就越大。有很多方法可以解释这个问题。一种选择是在不同于提出假设的数据集上测试假设。其他选项包括相应地调整显著性水平。

含义

这个分析有什么含义吗?首先要区分统计意义和实际意义。这可能有统计学意义:观察到的数据不仅仅是偶然的结果,差异确实存在。

实际意义意味着我们观察到的差异具有实际意义:人们可以据此采取行动。实际意义取决于手头的问题。

在我们的案例中,我认为与观察到的平均年龄差异没有太大关系……如果一般新程序员的平均年龄是 20 岁,而 QA 是 40 岁,我们可以建议新程序员的学校应该改变 QA 轨道的时间表,因为 QA 学生可能有孩子在家里等着他们。

【www.anotherdatum.com】这个帖子最初是我在 发的。

为 UCI 机器学习库引入简单直观的 Python API

原文:https://towardsdatascience.com/introducing-a-simple-and-intuitive-python-api-for-uci-machine-learning-repository-fd2ce8eb6cd4?source=collection_archive---------4-----------------------

为 UCI 机器学习门户引入简单直观的 API,用户可以在其中轻松查找数据集描述,搜索他们感兴趣的特定数据集,甚至下载按大小或机器学习任务分类的数据集。

介绍

UCI 机器学习数据集库是机器学习教育学领域的一个传奇。对于初学者和高级学习者来说,这都是一个‘逛商店’。它是数据库、领域理论和数据生成器的集合,由机器学习社区用于机器学习算法的经验分析。这个档案是 1987 年由加州大学欧文分校的大卫·阿哈和其他研究生创建的 ftp 档案。从那时起,它就被世界各地的学生、教育工作者和研究人员广泛用作机器学习数据集的主要来源。作为档案影响的一个标志,它被引用了 1000 多次,使其成为所有计算机科学中被引用次数最多的 100 篇“论文”之一。

也就是说,导航门户可能会有点令人沮丧和耗时,因为对于您感兴趣的数据集,没有简单直观的 API 或下载链接。您必须跳过多个页面才能进入您正在寻找的原始数据集页面。此外,如果您对特定类型的 ML 任务(例如回归或分类)感兴趣,并希望下载与该任务对应的所有数据集,则没有简单的命令来完成此任务。

我很高兴为 UCI ML 门户网站推出一个简单直观的 API,用户可以在这里轻松查找数据集描述,搜索他们感兴趣的特定数据集,甚至下载按大小或机器学习任务分类的数据集。

从这里下载/克隆

这是一个麻省理工学院许可的开源 Python 3.6 代码库,它提供了允许用户以交互方式使用 UCI ML 数据集的函数和方法。从我的 Github 页面这里 下载/克隆/分叉代码库。

必需的包/依赖项

运行这段代码只需要三个广泛使用的 Python 包。为了便于安装这些支持包,我的 repo 中包含了 setup.bash 和 setup.bat 文件。只要在您的 Linux/Windows shell 中执行它们,您就准备好了!

  • 熊猫
  • 美丽组 4
  • 请求

怎么跑?

确保你连接到互联网:-)然后,只需下载/克隆 Gitgub 回购,确保有支持包安装。

**git clone https://github.com/tirthajyoti/UCI-ML-API.git {your_local_directory}**

然后转到您克隆 Git 的your_local_directory,在您的终端上运行下面的命令。

**python Main.py**

将打开一个菜单,允许您执行各种任务。这是菜单的截图,

当前支持的特性和功能

目前实施了以下功能…

  • 通过搜索整个门户,构建包含数据集的名称、描述和 URL 的本地数据库
  • 通过爬取整个门户来构建数据集的名称、大小、机器学习任务的本地数据库
  • 搜索并下载特定数据集
  • 下载前几个数据集
  • 打印所有数据集的名称
  • 打印所有数据集的简短描述
  • 搜索数据集的单行描述和网页链接(了解更多信息)
  • 根据数据集的大小下载数据集
  • 基于与数据集相关联的机器学习任务下载数据集

示例(搜索和下载特定数据集)

例如,如果您想下载著名的数据集 Iris,只需从菜单中选择选项 3,输入存储的本地数据库的名称(以加快搜索速度),瞧!您将下载 Iris 数据集并将其存储在目录中名为“Iris”的文件夹中!

示例(使用特定关键字搜索数据集)

如果您通过选择选项 7 使用关键字进行搜索,那么您将得到所有数据集的简短的一行摘要,这些数据集的名称与您的搜索字符串匹配(甚至部分匹配)。您还将获得这些结果的相关网页链接,这样,如果您愿意,您就可以进一步探索它们。下面的屏幕截图显示了使用术语Cancer进行搜索的示例。

如果想绕过简单的 API,使用低级功能

如果您想绕过简单的用户 API,使用底层功能,欢迎您这样做。这是它们的概要。首先,导入必要的包,

from UCI_ML_Functions import *
import pandas as pd

read_dataset_table():从 URL“https://archive . ics . UCI . edu/ml/datasets . html”中读取数据集的表格,并对其进行进一步处理,以进行清理和分类。

clean_dataset_table():接受原始数据集表格(DataFrame 对象)并返回一个清除了未知数量样本和属性的条目的清理版本。还使指示与数据集相关联的主要机器学习任务的“默认任务”类别列合理化。

build_local_table(filename=None,msg_flag=True):读取 UCI ML 门户并构建一个包含名称、大小、ML 任务、数据类型等信息的本地表。

  • filename:用户可以选择的可选文件名。如果未选择,程序将选择一个默认名称(“UCI 表. csv”)。
  • msg_flag:控制详细程度。

build_dataset_list():浏览 UCI ML 数据集页面,建立所有数据集的列表。

build_dataset_dictionary():浏览 UCI ML 数据集页面,建立一个包含所有数据集名称和描述的字典。还存储对应于数据集的唯一标识符。下载器功能需要该标识符字符串来下载数据文件。通用名称不起作用。

build_full_dataframe():构建包含所有信息的数据框架,包括下载数据的 url 链接。

build_local_database(filename=None,msg_flag=True):读取 UCI ML 门户网站,并建立一个本地数据库,其中包含名称、摘要、数据页面 URL 等信息。

  • filename:用户可以选择的可选文件名。如果未选择,程序将选择一个默认名称(“UCI 数据库. csv”)。
  • msg_flag:控制详细程度。

return_abstract(name,local_database=None,msg_flag=False):通过搜索给定的name,返回特定数据集的一行描述(以及获取更多信息的网页链接)。

  • local_database:本地存储(即在同一目录下)的数据库(CSV 文件)的名称,其中包含有关 UCI ML repo 的所有数据集的信息。
  • msg_flag:控制详细程度。

describe_all_dataset(msg_flag=False):调用build_dataset_dictionary函数并打印所有数据集的描述。

print_all_datasets_names(msg_flag=False):调用build_dataset_dictionary函数并从中打印所有数据集的名称。

extract_url_dataset(dataset,msg_flag=False):给定数据集标识符,此函数提取实际原始数据所在页面的 URL。

download_dataset_url(url,directory,msg_flag=False,download_flag=True):从给定 url 中的链接下载所有文件。

  • msg_flag:控制详细程度。
  • download_flag:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。

download_datasets(num=10,local_database=None,msg_flag=True,download_flag=True):下载数据集,放在以数据集命名的本地目录下。默认情况下,仅下载前 10 个数据集。用户可以选择要下载的数据集数量。

  • msg_flag:控制详细程度。
  • download_flag:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。

download_dataset_name(name,local_database=None,msg_flag=True,download_flag=True):通过搜索给定的名称下载特定的数据集。

  • local_database:本地存储(即在同一目录下)的数据库(CSV 文件)的名称,其中包含有关 UCI ML repo 的所有数据集的信息。
  • msg_flag:控制详细程度。
  • download_flag:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。

download_datasets_size(size='Small',local_database=None,local_table=None,msg_flag=False,download_flag=True):下载满足“大小”标准的所有数据集。

  • size:用户想要下载的数据集的大小。可能是以下任何一种:“小号”、“中号”、“大号”、“超大号”。
  • local_database:本地存储的数据库(CSV 文件)的名称,即存储在同一目录中,其中包含 UCI ML repo 上所有数据集的名称和 URL 信息。
  • local_table:本地存储的数据库(CSV 文件)的名称,即存储在同一目录中,其中包含 UCI ML repo 上所有数据集的特征信息,即样本数量、对数据集执行的机器学习任务的类型。
  • msg_flag:控制详细程度。
  • download_flag:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。

download_datasets_task(task='Classification',local_database=None,local_table=None,msg_flag=False,download_flag=True):下载符合用户输入的 ML 任务标准的所有数据集。

  • task:用户想要下载数据集的机器学习任务。可能是以下任何一种:
  • “分类”、“推荐系统”、“回归”、“其他/未知”、“聚类”、“因果发现”。
  • local_database:本地存储的数据库(CSV 文件)的名称,即在同一目录中,包含 UCI ML repo 上所有数据集的名称和 URL 信息。
  • local_table:本地存储的数据库(CSV 文件)的名称,即存储在同一目录中,其中包含 UCI ML repo 上所有数据集的特征信息,即样本数量、要对数据集执行的机器学习任务的类型。
  • msg_flag:控制详细程度。
  • download_flag:默认为真。如果设置为 False,则仅创建目录,但不启动下载(出于测试目的)。

如果您有任何问题或想法要分享,请通过tirthajyoti【AT】Gmail . com联系作者。你也可以查看作者的 GitHub 资源库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

引入自定义分类器—构建您自己的文本分类模型,无需任何训练数据

原文:https://towardsdatascience.com/introducing-custom-classifier-build-your-own-text-classification-model-without-any-training-data-40254d37e13d?source=collection_archive---------6-----------------------

介绍

机器学习最成功的范例之一是监督学习,它让你通过从大量训练样本中学习来建立一个泛化模型。监督学习广泛用于自然语言处理中,以构建多类或多标签文本分类器,用于解决各种用例,如垃圾邮件检测、情感分析、情感分析、客户意图分析等..任何熟悉构建文本分类模型的过程的人都知道它包括下面列出的三个步骤:

准备训练数据:训练数据,也称为标记数据,是特定领域案例的语料库,这些案例用分类器期望分类的标签进行人工注释。

训练文本分类模型:然后选择合适的机器学习算法,在标注数据集上训练模型。我们已经在之前的博客中介绍了一些建立情感分析模型的技术。

测试和验证:标记数据集的一部分被留出,用于测试和验证训练好的模型,以评估其泛化能力。

当我们没有足够的标记数据来完成任务训练一个可靠的模型时,传统的监督学习范式就会崩溃。现实世界中的文本分类项目经常面临最大的障碍,即访问大量数据并手动注释它们。因此,大多数现实世界的项目都陷入了第一步。那些跨越了第一个障碍的人通常会发现他们的数据要么不充分,要么偏向某些类别,导致最终的人工智能模型中出现偏差

什么是自定义分类器?

深度学习中的许多研究都是针对从更少的数据中学习更好的表示,其中一个令人兴奋的领域是零射击学习。引用 Ian Goodfellow 在他的 Quora 回答中的话——“零射击学习是指尽管没有收到任何关于任务的训练样本,却能够解决一项任务。”换句话说,想象一下预测一条推文的情绪,而不提供任何带有该情绪标签的推文的训练示例。
ParallelDots 的内部研究团队提出了他们自己的文本分类零镜头学习范式,并发布了一篇题为“一次训练,随处测试:文本分类零镜头学习”的研究论文。你可以在这里看论文。

此外,为了兑现我们让人工智能触手可及的承诺,我们决定将这项令人兴奋的研究成果转化为商业应用,因此推出了一个新的 API,让您可以利用零触发学习的全部功能来进行文本分类用例。我们称之为自定义分类器,因为它可以让你建立自己的文本分类器的定义,自定义类别。这是我们在开发前沿人工智能解决方案的过程中迈出的革命性一步,让用户在不需要建立任何训练数据的情况下开发和集成自定义文本分类模型。

通过示例学习—构建样本文本分类模型

由于不需要训练数据,这也降低了建立文本分类模型的成本和时间。有了所有的背景知识,让我们试着看看自定义分类器的运行情况。
在下面的截图中,我们从我们网站上的自定义分类器演示页面中截取了一个体育标题,并定义了五个类别,我们希望将这个标题分为世界政治、体育、宗教、娱乐和商业。

正如您从结果中看到的,体育类别在所有类别中具有最高的概率得分,因此是我们输入文本中最有可能的类别。请注意,我们在测试时定义了类别,底层的人工智能模型并没有在这些类别上进行明确的训练。
接下来,我们尝试将运动类别进一步细分为不同的类别,如足球、高尔夫等。看看我们的分类器能否理解它们。

我们再次看到,分类器准确地识别了体育类别,而没有对它们进行明确的训练。我希望现在您已经开始了解这项技术的潜力。
最后一步,让我们试着将我们的足球类别进一步细分为全球不同类型的联赛,看看我们的分类器是否能正确预测。

确实神奇!我们的分类器也正确地选择了联盟。

总之,自定义分类器让您对文本分类的未来有所了解,在这种情况下,将一段文本可靠地分类到自定义类别中只需要很少或不需要训练示例。这种能力将开启无限的可能性,并赋予众多休眠的文本分析项目新的生命,这些项目由于缺乏训练数据或训练资源而永远不会看到光明的一天。

设置自定义分类器

设置自定义分类器非常简单,可以通过下面提到的三个简单步骤来完成:

  1. 注册免费的 ParallelDots API 账户,登录到你的仪表盘。
  2. 导航到仪表板中的自定义分类器部分,提供一个示例文本并定义一些类别来分析您的文本。默认情况下,你将处于测试模式,让你调整你的类别列表多次,你想免费。
  3. 一旦您对分类准确性感到满意,单击 Publish 部署您的分类器以供生产使用,并获取分类器 id。一旦发布,您将能够通过 API 端点访问您的自定义分类器。

自定义分类器的 API 文档可以在这里获得。一个 Excel 加载项功能将很快可用,以便从 MS Excel 中使用它。

在这篇博文中,我们介绍了一种新的文本分类模式,我们希望我们的用户能够从中受益匪浅。我们已经看到一些令人兴奋的用例被我们的用户通过自定义分类器解决,比如对招聘信息进行分类、对新闻文章进行分类、处理开放式调查反馈等。通常,分析原始数据的第一步是将它分类到您关心的类别中,并监控一段时间内的趋势,以获得可操作的见解。

自定义分类相对于标准文本分类的优势

在分析客户之声等非结构化数据时,情感分析等标准文本分类模型并不总是足以获得整体视图。另一方面,自定义分类器可以让您将这些数据分类到我们关心的更细微的类别中。例如,使用自定义分类器,快餐连锁店老板可以将通过社交媒体从客户那里收到的反馈分类为价格、氛围、员工行为、食品质量等类别。更好地了解她需要改进业务的哪些方面。使用简单的情绪分析,她可能知道她的业务总体情况如何,但可能会错过一些关键趋势,如员工行为和客流量之间的关系。自定义分类器的潜力是对文本进行分类,而不仅仅是情绪标签(正面、负面或中性),这样你不仅可以知道你的产品得到了多少负面反馈,还可以知道用户在这些负面陈述中谈论了什么。

我们相信定制分类器可以使没有数据科学背景的用户能够构建和部署他们自己的分类器,并获得相对于竞争对手的优势。它还将帮助企业从根本上转变为数据驱动的组织,并将最终加速人工智能和机器学习的产业化。你也可以在这里探索更多文本分类博客。

parallel dots AI API,是由 ParallelDots Inc 提供的深度学习支持的 web 服务,可以理解大量的非结构化文本和视觉内容,为您的产品提供支持。你可以查看我们的一些文本分析应用程序接口(API )( T7 ),在这里填写表格(T8 )( T9)或者给我们 apis@paralleldots.com 写信。

简介:数据好奇,时事通讯

原文:https://towardsdatascience.com/introducing-data-curious-the-newsletter-cf16ff57770c?source=collection_archive---------11-----------------------

经过长时间的中断,我的最佳数据资源的每周综述以一种新的形式回来了。

TL;博士:我正在把综述移到每周电子邮件时事通讯上。订阅 这里 如果你很投入的话。如果你有疑问,或者想了解新版本的更多信息,请继续阅读。

去年,我开始在 Medium 上发布我最喜欢的数据故事、数据集和数据可视化的每周综述(阅读旧版本此处了解一下味道)。在这个过程中,我收集了大量的灵感。但是现在,我想尝试一些不同的东西。

这是独家新闻

新的“数据好奇”将更加关注策展。

更少的数量,只有最好的。足够容易理解,比如说,一封电子邮件。

它还将优先考虑科学领域的数据发展。

当你专注于你感兴趣的东西时,数据项目总是更有趣。对我来说,是科学、环境和技术。因此,期待大量的酷的东西,但少一点政治(尽管在那个领域也有大量伟大的数据工作)。

我将寻找与环境、空间、教育、健康、技术和自动化相关的数据驱动内容。这些天我也少做新闻,多做数据项目开发:所以自然就少了新闻性。

出于学习目的,我正在添加更多的内容。

关于数据处理,我最喜欢的一点是社区有多开放。我花了无数的时间受益于其他人的教程和演练。因此,作为一种向前推进的方式,我将包括一些我自己的教程,以及我在其他地方找到的与数据科学和数据可视化相关的有用的学习资源。

关于《新方向》的最后一点:最重要的是,我希望这篇时事通讯能激发一些好奇心。最好的发现是通过问大量的问题发现的。最好的数据项目是从提出正确的问题开始的。

因此,与之前的三部分文章格式不同,每封邮件都将涉及几个主要部分:

阅读

我的 top 在一个与数据相关的主题上挑选了一些有趣的想法。

探索

最好的数据可视化不只是讲述一个故事,而是讲述多个故事。这一部分将包括一周的数据,这些数据提供了重要的洞察力/影响力。

分析

当我想学习一项新的数据相关技能时,手头有实践数据集总是很方便的。在这里,我将每周分享一个有趣的数据集,供您参考。

学习

在过去的一年里,我花了更多的时间来发展我在 Python 和数据科学方面的技能。我可能会分享与这两者相关的文章,但偶尔他们会更关注数据可视化(如 d3.js 和 bokeh)。

这将是一次疯狂的旅程。所以我需要你的反馈!您可以随时在这里提交(也会在每封邮件的页脚)。如果有足够的需求,我会尽最大努力改编和改变每份简讯的内容。

在这里注册每周数据灵感

DAX 简介—数据分析表达式

原文:https://towardsdatascience.com/introducing-dax-data-analysis-expressions-dca49cb68501?source=collection_archive---------6-----------------------

DATAAanalysis Expression 是一个函数的集合,可以用来执行一个任务并返回一个或多个值。虽然这听起来与任何其他编程语言都非常相似,但 DAX 只是一种公式或查询语言。DAX 是微软在 2009 年左右开发的,用于微软的 PowerPivot,当时是作为 Excel (2010)插件提供的。它现在非常受欢迎,因为它现在是 Power BI 的首选语言,并且也受到表格 SSAS 的支持。由于 DAX 在 Power BI 中被广泛使用,所以在本文中,我将重点放在 DAX for Power BI 上,但是它也可以应用于其他适用的工具。

Power BI logo

Power BI 是一种商业智能工具,它可以从数百个数据源中获取数据,准备数据,并生成漂亮的交互式报告和仪表盘,提供令人信服的见解。它提供了一套服务来引入数据,构建仪表板或报告,并与所需人员共享。虽然 Power BI 相对较新,但它的核心在某种程度上已经酝酿了很长时间。它基于 SSAS (SQL Server Analysis Services)、Power Pivot、Power View 和 Power Query,其中一些是免费的 Excel 插件。

DAX usability in Power BI Desktop

在 Power BI 的整个套件中,DAX 主要用于转换导入 Power BI 的数据模型和/或为可视化添加新的度量。这些函数用于创建计算列或度量,以帮助进行报告。

DAX 还通过在数据模型级别提供行级安全性(RLS)来保护发布的报告和仪表板。

计算列

计算列在数据模型中创建,在列级别逐行计算,存储在数据模型中,成为其所在表的一部分。计算列也会消耗更多内存。计算列通常表示为 Table[Column]。

措施

顾名思义,度量是聚合,DAX 有助于根据数据模型创建额外的度量,以帮助进行报告/可视化。这些 DAX 函数动态运行,也称为动态聚合,因此不与数据模型一起存储。由于度量是在查询时计算的,因此会消耗额外的 CPU。一个测度简单的表示为【测度】。

语法

Syntax of a DAX function

聚合函数

DAX 聚合函数聚合表中行上的列或表达式,用于度量中。DAX 提供了很多内置的聚合函数,这里有一个引用列表。

举例:

Customer Table

平均销售额=平均(客户[销售额])

平均销售额现在将返回 500。

‘X’聚合函数

X 聚合函数对表中的行进行迭代和聚合,与聚合函数相同,唯一的区别是 X 版本的聚合函数对表达式而不是表中的列进行聚合。

举例:

Customer Table

平均销售额=AVERAGEX(客户,[销售额]*[数量])

平均销售额现在将返回 1433.34。

VAR 函数

命名变量存储表达式的结果,该结果可以作为参数传递给其他表达式。变量减少了代码中的冗余,并通过避免创建新的计算列来提高性能。

举例:

An example of variable in DAX

时间智能功能

时间智能函数在商业智能中非常有用,并且在简单函数中执行复杂计算时可以节省时间。这些函数处理日期和时间字段,根据不同级别的时间段产生各种计算。这里有一个时间智能功能的列表。

文本功能

文本函数对表中的列进行操作,以连接、搜索或操作字符串,并返回整个或部分字符串。这里有一个文本函数的列表。

表格功能

表函数返回完整的表而不是值。它们通常与其他函数结合使用,以迭代返回的结果表中的每一行。

假设您有一组相关的表,并且需要基于两个或更多的表执行计算。在这种情况下,一些表函数非常有用。这里有一个表函数列表。

函数 FILTER 根据提供的表达式返回当前表的子集,并返回一个表作为结果。

举例:

Orders Tables

SuperStore = FILTER (Orders,Orders[产品名称] = "Newell 317 ")

这将创建一个名为 SuperStore 的新表,其中只包含 Newell 317 产品,如下所示。

SuperStore Table

函数 RELATEDTABLE 返回表格中与当前表格相关的所有行。

举例:

Customer Table

订单计数= COUNTROWS(RELATEDTABLE('超市'))

Outro

虽然这只是对 DAX 的简单介绍,但 DAX 中还有许多其他有用的功能,它们将使分析师或开发人员的工作变得更加轻松。

这里有一些学习 DAX 的优秀资源

  • 在 SQLBI 的 DAX 培训视频
  • DAX on 教程点
  • 立方体中的家伙

介绍深度学习和神经网络——新手的深度学习(1)

原文:https://towardsdatascience.com/introducing-deep-learning-and-neural-networks-deep-learning-for-rookies-1-bd68f9cf5883?source=collection_archive---------0-----------------------

Source: Allison Linn, Microsoft

关注我的 推特 了解更多关于深度学习创业公司的生活。

欢迎来到我的系列菜鸟深度学习的第一篇帖子,作者是我,一个菜鸟。我是作为强化学习策略来写的,以便更好地处理和消化知识。但是如果你是深度学习的新手,那么这也适合你,因为我们可以像新手一样一起学习!

(你也可以在我的网站 上阅读 这篇帖子,该网站支持 LaTeX with MathJax

Source: deepinstinct.com

深度学习可能是目前最热门的技术话题之一。大公司和年轻的创业公司都在这个奇特的领域淘金。如果你认为大数据很重要,那么你应该关心深度学习。经济学家说数据是 21 世纪的新石油。如果数据是原油,数据库和数据仓库是在互联网上挖掘和抽取数据的钻机,那么就把深度学习想象成炼油厂,最终把原油变成所有有用和有洞察力的最终产品。地下可能隐藏着许多“化石燃料”,市场上有许多钻机和泵,但是没有合适的提炼工具,你将得不到任何有价值的东西。这就是为什么深度学习很重要。这是数据驱动的大图景的一部分。

好消息是,我们不会用完数据,我们的“精炼机”越来越好。今天,在网上做任何事情都会产生数据。因此,与石油不同,数据是“可持续的”,并且在“爆炸式”增长。与此同时,只要数据不是垃圾,深度学习就不会有垃圾。因此,数据越多越好。(查看 Trent McConaghy 在区块链上的帖子,为 AI 提供解决方案,让数据拥有声誉!).

此外,这个“炼油厂”正在改善软件和硬件。深度学习算法在过去几十年中得到了改善,世界各地的开发人员为开源框架做出了贡献,如 TensorFlow、Theano、Keras 和 Torch,所有这些都使人们可以轻松地构建深度学习算法,就像玩乐高积木一样。由于世界各地游戏玩家的需求,GPU(图形处理单元)使我们能够利用深度学习算法以省时的方式构建和训练模型,并取得令人印象深刻的结果!所以,对于所有不喜欢你的孩子玩游戏的父母来说:游戏也有好的一面…

深度学习:秘方

你可能已经读过新闻,知道深度学习是许多令人兴奋的发展背后的秘方,并使我们许多最疯狂的梦想甚至噩梦成真。谁会想到 DeepMind 的 AlphaGo 可以在最深的棋盘游戏中击败最好的围棋选手之一 Lee Sedol,这种游戏号称比整个宇宙中的原子还多。很多人,包括我,都没想到会这样。这似乎是不可能的。但它现在就在这里。深度学习正在最具挑战性的棋盘游戏中击败我们。AI 什么时候觉醒?有些人认为这很快就会发生。

Lee Sedol vs. AlphaGo in 2016, Source: The New Yorker

我们还没有谈到由深度学习驱动的其他令人印象深刻的应用程序,如谷歌翻译和 Mobileye 的自动驾驶。你说吧。我是不是忘了提到深度学习在诊断癌症方面也打败了医生?深度学习擅长许多错误率低于人类的任务!不仅仅是自动化那些无聊的东西,还有有趣的东西。唉,我们凡人…

亲爱的总统先生,不是外国人。是自动化。

以下是深度学习在真实情况下可以执行的一般任务的简短列表:

  1. 识别人脸(或更一般的图像分类)
  2. 阅读手写数字和文本
  3. 识别语音(不再需要自己抄写采访)
  4. 翻译语言
  5. 玩电脑游戏
  6. 控制自动驾驶汽车(和其他类型的机器人)

还有更多。暂停一下,想象一下深度学习可以实现的所有事情。这是惊人的,也许有点可怕!

区别:人工智能、机器学习和深度学习

好吧,等一下。你可能已经在你的社交媒体新闻中看到过像人工智能( AI )、机器学习( ML )和深度学习( DL )这样的术语满天飞。都有什么区别?他们指的是同一件事还是什么?问得好。在我们深入到深度学习之前,重要的是逐步建立这些术语的概念框架。

粗略地说,下图展示了这三个概念之间的关系。深度学习是机器学习的一个子领域,机器学习是人工智能的一个子领域。奥菲尔·萨姆森和 T2 都写过关于他们的好故事。检查这里的和这里的和。

Source: Nvidia

先来讨论一下包罗万象的 AI。你可能已经知道了图灵测试。如果一个人在向计算机提出一些书面问题后,不能分辨出这些书面回答是来自另一个人还是计算机,那么计算机就通过了图灵测试。根据人工智能:现代方法,Peter Norvig 和 Stuart Russell 定义了计算机为了通过图灵测试必须具备的 4 种能力:

  • 自然语言处理:用英语成功交流
  • 知识表示:存储计算机读取的内容
  • 自动推理:利用存储的知识回答问题并得出新的结论
  • 机器学习:适应新环境,识别新模式

啊,有个术语叫“机器学习”!ML 是关于用数据集训练学习算法,如线性回归、KNN、K-Means、决策树、随机森林和 SVM,以便算法可以学习适应新的情况,并找到可能有趣和重要的模式。同样,ML 是数据驱动的。学习算法有很多奇怪的术语?别担心,我也不全认识。所以以后我们一起学习。

对于训练 ML,数据集可以被标记,例如,它带有一个“答题卡”,告诉计算机什么是正确的答案,比如哪些电子邮件是垃圾邮件,哪些不是。这被称为监督学习,并且像线性回归和 KNN 这样的算法被用于这样的监督回归分类。其他数据集可能没有被标记,您实际上是在告诉算法(如 K-Means)将它在没有任何答案的情况下找到的或聚类模式与相关联。这叫做无监督学习。这里有一个关于栈溢出的监督与非监督学习的很好的答案,这里也有一个来自 Olivia Klose 博客的关于监督与非监督的帖子。

Source: http://oliviaklose.com/

Norvig 和 Russell 还提到了另一项名为总图灵测试的测试,该测试通过物理模拟进一步检验了计算机的感知能力。要通过这一关,计算机需要:

  • 计算机视觉:感知周围的物体
  • 机器人学:操纵物体并四处移动

那么 DL 现在怎么样了?还记得上一节深度学习擅长的一般任务吗?像人脸或手写文本识别这样的事情与计算机视觉有关,因为你要将图形输入计算机进行分析。其他任务如语言翻译或语音识别与自然语言处理(NLP)有关。因此,DL 是 ML 的一个分支,因为它也有一套学习算法,可以对数据进行训练和学习,更具体地说 DL 由神经网络驱动。此外,DL 可以在机器学习领域之外执行,并帮助其他领域,如计算机视觉和 NLP,以便有希望人工智能有一天可以通过图灵测试和总图灵测试!

但是神经网络到底是什么?它是在模仿真实神经元细胞的行为吗?还是某种神奇的黑盒子?对于你们中的一些人来说,到目前为止提供的信息可能有点太多了,所以让我们休息一下,查看一些免费的在线资源,看看哪些适合你:)之后,我们将直接进入神经网络。

中途奖金:宝贵的资源

神经网络和 DL 往往隐藏在一层神秘的面纱后面。所有与该主题相关的技术术语可能会让初学者感到非常困惑。由于 DL 将在未来自动化许多任务并取代许多工人,我个人认为我们都保持开放的心态和好奇心来学习新技术是很重要的。DL 可以代替从事手工重复性工作的工人。但是 DL 不能代替科学家或工程师构建和维护 DL 应用程序。

目前,互联网上已经有许多关于这个主题的很棒的课程、教程和书籍,例如(不详尽或按特定顺序):

  1. 迈克尔·尼尔森的神经网络和深度学习
  2. 杰弗里·辛顿的用于机器学习的神经网络
  3. 古德费勒、本吉奥、库维尔的深度学习
  4. 伊恩·特拉斯克的摸索深度学习,
  5. Francois Chollet 的用 Python 进行深度学习
  6. Udacity 的深度学习纳米学位(不免费但高质量)
  7. Udemy 的深度学习 A-Z($ 10-$ 15)
  8. 斯坦福的 CS231n 和 CS224n
  9. Siraj Raval 的 YouTube 频道

这个清单还在继续。大卫·文丘里为自由代码营写了一篇文章,列出了更多的资源。点击查看。

在自我教育的时代,我们真的很幸运。顺便问一下,你听说过那个来自芝加哥的高中生阿布·卡德吗?这个孩子自学了机器学习和深度学习框架 Tensorflow,并帮助将乳腺癌的诊断提高到 93%-99%的实时准确率!他登上了谷歌 I/O 2017。下面是一个来自谷歌的关于他的故事的鼓舞人心的视频。

Source: Google

感知机:数字逻辑的前奏

好吧,我希望阿布·卡迪尔的故事让你对学习感到兴奋!让我们进入这篇文章的第二个主题:神经网络介绍。中国古代哲学家老子曾经说过:

“千里之行,始于足下。”

所以我们将用一个非常简单的神经网络来开始和结束这篇文章。听起来很酷?神奇吧。

尽管有了新的名声,神经网络领域一点也不新鲜。1958 年,美国心理学家弗兰克·罗森布拉特(Frank Rosenblatt)试图建造一台“像人脑一样感知、识别、记忆和反应的机器”,并将这台机器称为“感知机”。但是罗森布拉特并没有凭空发明感知机。实际上,他站在巨人的肩膀上,从沃伦麦卡洛克和沃尔特皮茨在 20 世纪 40 年代的作品中获得了灵感。天哪,这使得神经网络,或者更具体地说,感知器,成为这个快速变化的技术世界中的恐龙。

Rosenblatt and Perceptron, Source: The New Yorker

所以我们来看看什么是感知机。首先,看看下面的神经元细胞:树突是神经细胞的延伸(在图的左下角)。它们接收信号,然后将信号传输到细胞体,细胞体处理刺激并决定是否向其他神经元细胞触发信号。如果这个细胞决定触发信号,细胞体上称为轴突的延伸将触发轴突末端向其他细胞的化学传输。在这里你不需要记住任何东西。我们不是在研究神经科学,所以对它如何工作有一个模糊的印象就足够了。

Original Source: thinglink.com

A Single Perceptron

现在,上图是一个感知器的样子。很像上面的神经细胞图,对吧?确实如此。感知器和其他神经网络的灵感来自我们大脑中的真实神经元。请注意,它只是受到的启发,并不完全像真正的神经元一样工作。感知器处理数据的过程如下:

  1. 在左侧,你有带下标 1,2,…,mx 的神经元(小圆圈)携带数据输入。
  2. 我们将每个输入乘以一个权重 w,也标有下标 1,2,…,m,沿着箭头(也称为突触)到中间的大圆圈。于是 w1 * x1w2 * x2w3 * x3 等等。
  3. 一旦所有的输入都乘以一个权重,我们将所有的输入相加,并加上另一个预先确定的数字,称为偏差。
  4. 然后,我们将结果进一步向右推。现在,我们在矩形中有了这个阶跃函数。它的意思是,如果步骤 3 的结果是等于或大于 0 的任何数字,那么我们得到 1 作为输出,否则,如果结果小于 0,我们得到 0 作为输出。
  5. 输出为 1 或 0。

请注意,或者,如果您将 bias 移动到激活函数中等式的右侧,如 sum(wx) ≥ -b ,则此 -b 称为阈值。因此,如果输入和权重之和大于或等于阈值,则激活触发 1。否则,激活结果为 0。选择有助于你更好理解的,因为这两种表达方式是可以互换的。

Illustration of using Threshold Value instead of Bias

我在下面添加了另一个感知器图,这次每一步都用了颜色。完全理解它并记住每一步发生的事情非常重要,因为当我们谈论更复杂的神经网络结构时,我们将忽略未来图表中的中间步骤:

Procedures of a Perceptron labeled in colors

  1. 输入被输入感知器
  2. 权重乘以每个输入
  3. 求和然后加上偏置
  4. 激活功能被应用。注意,这里我们使用阶跃函数,但是还有其他更复杂的激活函数,如 sigmoid、双曲正切( tanh )、整流器( relu )和更多的。不要担心,我们将在未来涵盖其中的许多内容!
  5. 输出要么触发为 1,要么不触发为 0。注意我们用 y 帽 来标注我们的感知器模型产生的输出

将来,我们有时可能会简化我们的感知器如下,而不提及步骤 3 和 4。我们刚刚谈到的这种感知器也是一种单层感知器,因为我们直接将输入处理成输出,中间没有任何多层神经元:

Simplified Representation of Perceptron

感知器:直觉

好吧,你现在知道感知器是怎么工作的了。这只是一些机械的乘法,接着是求和,然后是一些激活……瞧,你得到了一个输出。是啊,这怎么会接近人类大脑中的神经元呢?

为了理解感知机,让我们看一个不一定真实的简单例子。假设你看了我的帖子后很有动力你需要决定是否学习 DL。有 3 个因素会影响你的决定:

  1. 如果掌握 DL 后你会赚更多的钱(是:1,否:0)
  2. 相关的数学和编程容易吗(是:1,否:0)
  3. 您可以立即在 DL 上工作,而不需要昂贵的 GPU(是:1,否:0)

我们使用 x1、x2、x3 作为每个因素的输入变量,并为每个因素分配一个二进制值(1 或 0 ),因为答案只是简单的“是”或“否”。假设到目前为止你真的很喜欢 DL,并且你愿意克服你一生对数学和编程的恐惧。你也有一些储蓄,现在投资一个昂贵的 Nvidia GPU 来训练你的 DL 模型。假设这两个因素同等不重要,因为你可以在它们之间做出妥协。但是,你花了那么多时间和精力学 DL,真的是想赚更多的钱。所以有了高预期的投资回报,如果事后赚不到更多的$$$就不会把宝贵的时间浪费在 DL 上。

在了解了你的决策偏好后,让我们假设你在学习 DL 后有 100%的概率赚更多的钱,因为市场上有很多需求,但供应却很少。所以 x1 = 1 。假设数学和编程超级难。所以 x2 = 0 。最后,假设你必须有 Titan X 这样强大的 GPU,那么 x3 = 0 。好了,我们已经准备好输入,也可以初始化权重。我们选 w1 = 6,w2 = 2,w3 = 2权重越大,对应的输入越有影响力。所以既然你决定学 DL 最看重钱, w1 > w2w1 > w3

我们将假设阈值 threshold = 5,这相当于说偏置项 bias = -5 。我们把它们加起来,加上偏差项。关于使用感知器来确定你是否会学习 DL 的过程,请检查以下内容。

注意阈值为 5,我们只有赚更多的钱才会学习深度学习。就算数学既轻松( x2 = 1 )又不需要花钱买 GPU ( x3 = 1 ),以后赚不到更多的钱还是不会去学 DL。请参见下图:

现在你知道偏差/阈值的诀窍了。这个 5 的高阈值意味着感知器必须满足你的主导因素才能触发 1 的输出。否则,输出将为 0。

有趣的是:改变权重和阈值/偏差将导致不同的可能决策模型。例如,如果我们将阈值从 threshold = 5 降低到 threshold = 3,那么输出为 1 的可能性更大。现在,对于输出= 1最低要求为:

  1. 你以后会赚更多的钱,所以 x1 = 1 保证你学习 DL的决定,而不管到 x2x3 的值
  2. 或者说,数学很容易,不需要买 GPU,所以 x2 = x3 = 1 也保证了你决定学习 DL 而不管值到 x1

为什么你可能已经知道了;)以下是解释:

没错。现在门槛降低了,所以其他两个因素可以激励你学习 DL,即使你赚更多钱的前景已经消失。现在,我鼓励你玩玩权重 w1、w2 和 w3 ,看看你学习 DL 的决定会如何相应地改变!

感知机:在行动中学习

为什么要在这个例子中摆弄砝码呢?因为这有助于你理解感知器是如何学习的。现在,我们将使用这个例子以及输入和权重来说明单层感知器,并看看尽管它有局限性,但它能实现什么。

在一个真实的 DL 模型中,我们被给予输入数据,我们不能改变它。同时,在你训练你的神经网络模型之前,偏置项被初始化。假设我们假设偏差是 7。现在,让我们假设以下输入数据,以便(1)。你会赚更多的钱。DL 的数学和编程会很难,还有(3)。是的,你必须花 1400 美元买一个 GPU 来处理 DL,而且最重要的是, 我们假设你实际上想要学习深度学习, 我们将其命名为 期望输出 以了解感知机应该如何正确预测或确定:

让我们进一步假设我们的权重初始化如下:

因此,对于输入数据、偏置和输出标签(所需输出):

好的,我们知道你的神经网络的实际输出与你想要研究 DL 的真实决定不同。那么,考虑到实际输出和期望输出之间的差异,神经网络应该做些什么来帮助自己学习和改进呢?是的,我们不能改变输入数据,我们现在已经初始化了我们的偏差。所以我们唯一能做的就是告诉感知器调整权重!如果我们告诉感知器将 w1 增加到 7,而不改变 w2w3 ,那么:

调整权重是我们感知机学习过程的关键。并且具有阶跃函数的单层感知器可以利用下面列出的学习算法在处理每组输入数据之后调整权重。尝试用这个算法自己更新权重:)这差不多就是单层感知器的学习方式。

顺便说一下,现在我们已经完成了这个不太现实的例子,我可以告诉你,你不需要买一个 GPU。如果你作为初学者训练较小的数据集,你很可能不需要 GPU。然而,当你开始用大量图像文件训练更大的数据集时,你可以使用云服务,如 AWS 、 Floyd ,可能还有谷歌 TPU 。

此外,DL 的数学并不简单,但也不是不可逾越的。大多数情况下,我们只会遇到一些矩阵运算和基本的微积分。但是记住,没有什么能让你脱颖而出的东西是容易学的。这里有一段引自的话:

“做我们知道如何做好的事情是令人愉快的,这与刻意练习的要求正好相反。我们应该坚持寻找我们不擅长的,而不是做我们擅长的。然后,我们确定那些会让我们变得更好的痛苦、困难的活动,并一遍又一遍地做这些事情。如果导致伟大的活动既容易又有趣,那么每个人都会去做,他们不会区分最好的和其他的。”

所以对于那些像我一样害怕数学和编程的人,我希望这句话能给你一些勇气,让你继续学习和实践:)

感知器:局限性

尽管公众早期有一些感觉,但由于其局限性,感知器的受欢迎程度悄悄地消失了。1969 年,马文·明斯基和西蒙·派珀特讨论了这些限制,包括感知器无法学习 XOR(异或)门(因此基本上一个具有阶跃函数的 单层感知器无法理解天气必须要么热要么冷,但不能同时热和冷的逻辑)。这些逻辑门,比如 And、OR、NOT、XOR,都是非常重要的概念,为你的计算机提供动力;)TutorialsPoint 有一个逻辑门列表,如果你想了解更多。在这里勾选。

当然,后来人们意识到 多层感知器能够学习异或门的逻辑,但它们需要一种叫做 反向传播 的东西,以便网络从试验和错误中学习。毕竟,记住深度学习神经网络是数据驱动的。如果我们有一个模型,而它的实际输出与期望输出不同,我们需要一种方法,沿着神经网络反向传播误差信息,告诉权重调整并以某个值修正它们自己,以便在一轮又一轮的测试后,模型的实际输出逐渐接近期望输出。

事实证明,对于涉及不能从输入的线性组合中产生的输出的更复杂的任务(因此输出是非线性的或不可线性分离的),阶跃函数将不起作用,因为它不支持反向传播,这要求所选择的激活函数具有有意义的导数。

Source: mathnotes.org

某微积分讲:阶跃函数是一个线性激活函数,其导数对于除零点以外的所有输入点都为零。在零点,导数是未定义的,因为函数在零点是不连续的。所以虽然这是一个非常简单和容易的激活功能,但它不能处理更复杂的任务。继续阅读,你会发现更多。

线性与非线性

什么!?那么什么是线性组合?还有为什么感知器学不会异或门?这越来越令人困惑了。没问题,这里有一个解释:

想一想我们之前的例子。用 3 个二进制输入来表示你在学习 DL 后是否赚了更多的钱,如果涉及的数学和编程容易与否,如果你可以在不投资昂贵的硬件的情况下学习 DL,我们总共有 2 = 8 组可能的输入和输出。利用权重( w1 = 6,w2 = 2,w3 = 2),bias = -5,我们得到了下面的一组( x1,x2,x3 ):

  1. (1,0,0)-> sum+bias = 6–5 = 1,期望输出= 1
  2. (1,1,0)-> sum+bias = 8–5 = 3,所需输出= 1
  3. (1,1,1) ->总和+偏差= 10–5 = 5,期望输出= 1
  4. (1,0,1)-> sum+bias = 8–5 = 3,所需输出= 1
  5. (0,1,1)-> sum+bias = 4–5 =-1,期望输出= 0
  6. (0,1,0)-> sum+bias = 2–5 =-3,期望输出= 0
  7. (0,0,1)-> sum+bias = 2–5 =-3,期望输出= 0
  8. (0,0,0)-> sum+bias = 0–5 =-5,期望输出= 0

因此,从字面上看,如果我们从随机权重开始,而不是从( w1 = 6,w2 = 2,w3 = 2 )的随机权重开始,我们的感知机将尝试学习调整并找到理想的权重( w1 = 6,w2 = 2,w3 = 2 ),这将正确地将每组( x1,x2,x3 )的实际输出匹配到期望的输出。其实我们可以在一个 3D 空间里用一个平面把这 8 个可能的集合分开,比如 x1 = 0.5 的平面。这种类型的分类问题,你可以画一个平面来分隔不同的输出(或在 2D 为输出画一条线),这是我们的单层感知器可以解决的问题。

A plane separating the 4 sets to the left from the 4 to the right

A Plane separating the 4 sets to the left from the 4 to the right

希望你能想象一下上面 8 组输入分开的平面。由于( x1,x2,x3 )的集合涉及一个三维空间,这可能有点挑战性。但一般来说,具有线性激活函数的单层感知器可以学习分离一个数据集,就像下图中的图表 A,可以用一条 y = ax + b 的线来分离。但是,如果数据集只能像图表 B 那样被一个圆非线性地分开,我们的感知机将会表现得很糟糕。

Source: Sebastian Raschka

为什么会这样呢?我从栈溢出为你复制粘贴一个报价。你也可以在这里查看答案和。

激活函数不可能是线性的,因为具有线性激活函数的神经网络仅在一层深度有效,不管它们的结构有多复杂。网络输入通常是线性变换(输入*权重),但是现实世界和问题是非线性的。为了使输入数据非线性,我们使用称为激活函数的非线性映射。激活函数是决定特定神经特征存在的决策函数。它映射在 0 和 1 之间,其中 0 表示该特征不存在,而 1 表示该特征存在。不幸的是,权重中发生的小变化不能反映在激活值中,因为它只能取 0 或 1。因此,非线性函数在这个范围内必须是连续的和可微的。神经网络必须能够接受从-无穷大到+无穷大的任何输入,但在某些情况下,它应该能够将其映射到范围在{0,1}或{-1,1}之间的输出,因此需要激活函数。激活函数中需要非线性,因为它在神经网络中的目的是通过权重和输入的非线性组合产生非线性决策边界。”-用户 7479

那么为什么具有阶跃函数的单层感知器不能学习异或门呢?看看下面的图表。左边是 XOR 逻辑图,右边是来自 XOR 门的 2 个不同结果(1 和 0)的笛卡尔表示。

Source: https://stackoverflow.com/a/35919708/6297414

事实上,我们不可能用一条直线来区分白点和黑点。我们需要更强大的东西来让神经网络学习 XOR 门逻辑。我很快会写更多关于这个话题的文章。

概述

深度学习是一个令人兴奋的领域,它正在迅速改变我们的社会。我们应该关心深度学习,至少了解它的基础知识是很有趣的。我们还介绍了一个非常基本的神经网络,称为(单层)感知器,并了解了感知器的决策模型是如何工作的。

我们的单层感知器加上一个阶跃函数对于简单的线性可分二分类工作良好。但仅此而已…因为它对涉及非线性输出的更复杂的问题不太适用。我知道这听起来有点令人失望,但我们接下来将详细介绍它们!

接下来将是一个关于神经网络的新帖子和隐藏层(听起来很棒吧?)和一个名为s 形函数的新激活函数。如果空间允许,我们将触及梯度下降反向传播,这是智能神经网络要学习的关键概念。敬请关注(这里是第二个帖子的链接) 😃

现在,祝贺你跟帖到目前为止,你已经学到了很多!保持动力,我希望你在深度学习中获得乐趣!如果你迫不及待地想看我的文章,请查看以下免费资源,了解更多信息:

[## 神经网络和深度学习

我们专注于手写识别,因为这是学习神经系统的一个极好的原型问题…

neuralnetworksanddeeplearning.com](http://neuralnetworksanddeeplearning.com/chap1.html) [## 用于视觉识别的 CS231n 卷积神经网络

斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。

cs231n.github.io](http://cs231n.github.io/)

享受学习!

你喜欢这次阅读吗?别忘了关注我的 推特

Jupytext 简介

原文:https://towardsdatascience.com/introducing-jupytext-9234fdff6c57?source=collection_archive---------4-----------------------

Jupyter 笔记本是包含代码、叙述和情节的交互式文档。它们是试验代码和数据的绝佳场所。笔记本很容易分享,GitHub 上的 2.6M 笔记本正好说明笔记本有多受欢迎!

Jupyter 笔记本很棒,但是它们通常是巨大的文件,具有非常特殊的 JSON 文件格式。让我们来介绍一下 Jupytext ,这是一个 Jupyter 插件,它以纯文本文件的形式读写笔记本:Julia、Python、R scripts、Markdown 或 R Markdown 文档。

Jupyter 笔记本作为文本文件

我们编写了 Jupytext 来处理 Jupyter 笔记本,就像我们处理文本文件一样。使用 Jupytext

  • 在您最喜欢的文本编辑器或 IDE 中重构笔记本(例如用普通的 Python 脚本来表示)成为了一个真正的选择,
  • 将笔记本直接写成脚本或降价是另一种选择
  • 使用 Git 在 Jupyter 笔记本上进行协作变得非常简单。

笔记本的文本表示集中在我们实际书写的部分:单元格输入。我们重视投入甚于产出。通常,它们是笔记本中唯一我们想要版本控制的部分。输入比输出轻得多(通常是千字节比兆字节)。

我们也重视产出。使用配对笔记本可以保存输出。在该配置中,除了脚本或 Markdown 文档之外,Jupyter 还将笔记本保存为传统的.ipynb文件。文本表示可以在 Jupyter 之外编辑。在 Jupyter 中重新加载笔记本时,单元格输入来自文本文件,匹配的输出来自.ipynb文件。

作为脚本编辑的 Jupyter 笔记本

在第一个动画中,我们展示了如何使用您最喜欢的文本编辑器或 IDE 来编辑您的 Jupyter 笔记本。在浏览代码、编辑和执行单元或单元片段以及调试方面,ide 比 Jupyter 更方便。

动画脚本:

  • 我们从 Jupyter 笔记本开始。
  • 笔记本包括一幅世界人口图。剧情图例没有按照人口递减的顺序排列,我们会解决这个问题。
  • 我们希望将笔记本保存为一个.ipynb和一个.py文件:我们向笔记本元数据添加一个"jupytext_formats": "ipynb,py",条目。
  • Python 脚本可以用 PyCharm 打开:
  • 在代码和文档中导航比在 Jupyter 中更容易。
  • 控制台便于快速测试。我们不需要为此创建细胞。
  • 我们发现数据帧的列顺序不正确。我们更新相应的单元格,并得到正确的绘图。
  • Jupyter 笔记本在浏览器中刷新。从 Python 脚本加载修改后的输入。输出和变量被保留。我们最终重新运行代码并得到正确的图形。

脚本和降价作为 Jupyter 笔记本

有了 Jupytext ,每一个 Julia、Python 或者 R script、R Markdown 或者 Markdown 文档都变成了一个潜在的 Jupyter 笔记本。把你的笔记本写成文本,需要的时候在 Jupyter 中呈现出来。

在下面的动画中,

  • Jupyter notebook(不是 lab,敬请关注)将我们的普通 Python 脚本作为 Jupyter notebook 打开。
  • 从 Jupyter 中保存会给其他未更改的文件添加一个 YAML 头。
  • 向笔记本添加一个单元格会带来一个非常简单的区别。
  • 刷新笔记本会保留变量,但不会保留输出。输出不存储在文本文件中。
  • 我们通过向笔记本元数据添加一个"jupytext_formats": "ipynb,py",条目,将脚本与传统的 Jupyter 笔记本配对。当我们保存时,会创建一个新的ipynb文件。
  • 由于有了ipynb文件,当笔记本刷新或重新加载时,输出会保留下来。

Jupyter 笔记本协作

你试过合并 Jupyter 笔记本吗?您应该使用 nbdime,或者准备好面对不可读的笔记本:NotJSONError 如果合并的 JSON 中缺少逗号或括号!

有了 Jupytext ,在笔记本上协作就像在脚本上协作一样简单。

只签入文本版本。享受简单的合并和有意义的差异!

安装 Jupytext

Jupytext 在 pypi 上有售。安装 python 包并将 Jupyter 配置为使用 Jupytext 的内容管理器:

# Get Jupytext from pip
pip install jupytext --upgrade# Append this to .jupyter/jupyter_notebook_config.py c.NotebookApp.contents_manager_class="jupytext.TextFileContentsManager"# And restart your notebook server
jupyter notebook 

通过在笔记本元数据中添加"jupytext_formats": "ipynb,py",(用您喜欢的扩展名替换py),将 Python 脚本与您的 Jupyter 笔记本相关联,或者将ipynb文件与您的 Python 脚本相关联(为了方便保存单元格输出)。如果您计划在 Jupyter 之外编辑文本文件时保持 Jupyter 打开,请通过在单元格中运行%autosave 0来关闭 Jupyter 的自动保存。

参考

将 Jupyter 笔记本作为文本使用的想法并不新鲜。Python 中实现的可选转换器包括:

  • 笔记 : Jupyter 笔记本作为减价文件,
  • ipymd : Jupyter 笔记本作为 Markdown 文档,Python 脚本,OpenDocument 文件,
  • ipymd 的一个分支增加了对 R Markdown 和 R HTML 笔记本的支持,
  • pynb :作为 Python 脚本的 Jupyter 笔记本。

我们怀着极大的兴趣关注着 Atom 的 Hydrogen 插件,以及 Visual Studio 代码的 Jupyter 扩展。这些扩展将脚本(带有明确的单元格标记,我们希望在 Jupytext 中在某个点支持这些标记)转化为类似于笔记本的交互式环境。

感谢

Jupytext 是我第一个重要的开源贡献。从事开源项目是一次很棒的经历。我问了很多问题,非常感谢这些有帮助的回答、建议和合作。

特别是,我要感谢 Gregor Sturm 提出了一个伟大的想法,让我们可以将 T21 的笔记本和传统的 Jupyter 笔记本配对,并感谢他对这个项目的反馈。Eric Lebigot 和 Franç ois Wouts 关于如何推进和沟通项目的建议非常有帮助。最后,我要感谢早期的测试人员花时间在 Jupyter 笔记本和 Jupytext 上尝试新的协作方式。

反馈

Jupytext 很大程度上归功于用户的反馈。欢迎提出建议和问题:请在我们的 GitHub 项目中使用问题跟踪器,以便对程序或文档提出改进建议。那里见!

介绍 K-FAC

原文:https://towardsdatascience.com/introducing-k-fac-and-its-application-for-large-scale-deep-learning-4e3f9b443414?source=collection_archive---------9-----------------------

大规模深度学习的二阶优化方法

Photo by Nareeta Martin on Unsplash

在本文中,我总结了 Kronecker-factored 近似曲率(K-FAC) (James Martens et al .,2015),深度学习最高效的二阶优化方法之一。

概观

曲率的繁重计算限制了二阶优化方法在深度学习中的应用数量。Kronecker-factored approximated Curvature(K-FAC)是由多伦多大学的 James Martens 和 Roger Grosse 在 ICML2015 中提出的一种深度学习的二阶优化方法,通过 Kronecker 因子分解来逼近曲率,降低了参数更新的计算复杂度。得益于包括 K-FAC 在内的高效二阶方法,ML 研究人员现在开始重新审视二阶方法快速收敛对于减少深度学习训练时间的好处。

自然梯度下降

自然梯度下降(NGD) 是由甘利顺一(Shun-Ichi Amari)在 1998 年提出的一种基于信息几何的优化方法。NGD 通过使用费希尔信息矩阵(FIM) 作为损失函数的曲率,正确地获得损失情况,并且在“迭代”方面比简单的一阶方法(例如随机梯度下降)收敛得更快。因此,人们可以把 NGD 看作二阶优化的有效实现。

给定 x ,输出条件概率为 y 的概率模型的 FIM 定义如下:

Fisher information matrix (Empirical Fisher)

这个取数据期望值的定义叫做 经验费希尔 (当你使用小批量时,你计算其中数据的平均值来得到 FIM)。在图像分类任务中,由于人们经常使用负对数似然的平均值作为损失函数,因此可以将 FIM 视为损失函数的曲率的近似。下面的等式显示了 FIM 和负对数似然损失 E(θ)的 Hessian 之间的关系:

The loss function

The Hessian of the loss function and the relationship between the FIM

NGD 的更新规则是:

The update rule of Natural Gradient Descent (NGD)

这里,FIM 的逆过程应用于损失梯度,FIM 预处理的梯度称为自然梯度。对于 N 的参数,FIM 的大小是 N×N,深度学习中使用的神经网络往往具有大量的参数(例如,用于 ImageNet 分类的 AlexNet 中的 6000 万个参数),因此 FIM 的逆是难以处理的,并且它限制了 NGD 在深度学习中的应用数量。

自然梯度近似方法

近年来,一些作品提出了近似(或避免)反演 FIM 的方法,深度学习研究者重温了 NGD 的“快速收敛”。

粗略地说,有三种近似方法(我引用了这篇文章进行这种分类。)

  1. 近似 Fisher 信息矩阵(以便逆矩阵易于计算)
  2. 重新参数化,使 FIM 更接近单位矩阵。
  3. 直接逼近自然梯度。

The three approaches for approximating NGD

使用克罗内克因子分解(K-FAC)的近似

Approximation of (inverse of) FIM by K-FAC

可以将 K-FAC 视为自然梯度近似方法之一,其对应于“1。近似 Fisher 信息矩阵(这样逆矩阵容易计算)”。特别地,与其他自然梯度近似方法相比,它是基于数学原理的最有效的近似方法。

首先,K-FAC 块对角化 FIM,其中每个对角块对应于神经网络每层的参数。例如,K-FAC 将三层网络的 FIM 近似为具有三个块的块对角矩阵。

接下来,K-FAC 用两个矩阵的 Kronecker 积来近似每个块(称为 Kronecker 因式分解)。

Kronecker product of two matrices

最后,K-FAC 使用矩阵的 Kronecker 积的临界性质:

The inverse of Kronecker product = Kronecker product of the inverse matrices

简而言之,K-FAC 将 FIM 的逆近似为块对角矩阵,其中每个对角块是微小克罗内克因子的逆(与 FIM 相比)。

为了阐明克罗内克因子的大小(你可以降低多少求逆的复杂度),我解释一下克罗内克因子分解的机制。以一个全连接层为例,你可以看到如何因式分解 FIM 的一个对角块(为方便起见,称为 Fisher 块)对应于这个层。第 I 层中的 Fisher 块表示为

The Fisher block of i-th layer (i-th diagonal block of the FIM)

(期望值的符号被简化。)其中∇i 是第 I 层参数的梯度。通过使用反向传播方法,这是一种在深度神经网络中计算梯度的有效方法,对数似然的梯度(对于每个样本)被表示为两个向量的克罗内克乘积:

利用这种关系,费希尔区块可以转化为“克罗内克乘积的期望值”的形式:

K-FAC 将“克罗内克积的期望值”近似为“期望值的克罗内克积”(克罗内克因式分解)。

Kronecker factorization of a Fisher block by K-FAC

如上所述,Kronecker 因式分解显著降低了 Fisher 块逆运算的计算复杂度。以图像分类领域经常使用的架构 AlexNet 为例,可以更清晰地看到这种效果。下图显示了 Alex net for ImageNet(1000 类分类)的所有层和最后一层(全连通层)的矩阵大小的比较结果。

AlexNet for Imagenet (1,000 classification)

总结到目前为止,可以说 K-FAC 是一种自然梯度近似方法,它执行以下三个过程。

  1. 通过费希尔信息矩阵的块对角化(每个对角块对应于每一层),忽略“跨层参数”的相关性。
    • 还有一种使用分块三对角的方法(考虑相邻层参数的相关性)。
  2. 通过对每个对角块(Fisher 块)的 Kronecker 分解,忽略每层中“输入”和“输出梯度”之间的相关性。
  3. 通过 1,2 的近似,有效地计算费希尔信息矩阵的逆矩阵,以产生自然梯度。

在这里,我为全连接层引入了 K-FAC,但是在卷积层的 K-FAC 中,除了 2 之外,还应用了更多的近似。(参考论文。)

最后,以图像数据集 CIFAR-10 的分类任务(10 类分类)为例,说明了 K-FAC 的有效性。下图显示了随机梯度下降法(SGD)、无任何近似的自然梯度下降法(NGD)和 K-FAC 的训练曲线的比较。

The comparison of training of ConvNet for CIFAR-10 dataset. Solid line: train, dashed line: validation

你可以看到 NGD 在“迭代次数”上比 SGD 收敛得快,但是在 NGD,每次迭代的计算时间很长,所以你也可以看到“经过的时间”比 SGD 晚。另一方面,K-FAC 在“迭代次数”方面很好地再现了 NGD 的训练曲线,并且在“经过的时间”方面也比“SGD”快

这种快速收敛促使引入了 K-FAC 等自然梯度近似方法,但 K-FAC 在 ImageNet 等大规模深度学习中的应用受到限制,之前没有人针对 SGD 验证过有效性。

K-FAC 的应用

  • 递归神经网络(RNN)

    詹姆斯·马滕斯,吉米·巴,
    ICLR2018。
  • 强化学习
    基于克罗内克因子自然梯度的最近策略优化实证分析,
    宋家明,吴,
    arXiv:1801.05566【cs .AI],2018 年 1 月。
  • 贝叶斯深度学习
    噪声自然梯度作为变分推理,
    张国栋,孙升阳,大卫·杜文瑙,罗杰·格罗斯,
    arXiv:1712.02390【cs .LG],2018 年 12 月。

K-FAC 的实现

  • 张量流
    https://github.com/tensorflow/kfac
  • py torch
    https://github.com/yaroslavvb/kfac_pytorchT21【在本帖中介绍)
  • 链轮
    https://github.com/tyohei/chainerkfac

结论

在本文中,我解释了自然梯度法的近似方法之一 K-FAC 的概要。我牺牲了数学的严谨性,致力于直观的理解。

pydbgen 简介:一个随机数据帧/数据库表生成器

原文:https://towardsdatascience.com/introducing-pydbgen-a-random-dataframe-database-table-generator-b5c7bdc84be5?source=collection_archive---------3-----------------------

通常,SQL 或数据科学的初学者都很难轻松访问大型样本数据库文件()。DB。sqlite )用于练习 SQL 命令。如果有一个简单的工具或库来生成一个包含多个表的大型数据库,并用自己选择的数据填充,岂不是很棒?

当你开始学习和实践数据科学时,通常最大的担忧不是算法或技术,而是原始数据的可用性。幸运的是,网上有许多高质量的真实数据集可供尝试很酷的机器学习技术。但是,从我个人的经验来看,我发现在学习 SQL 的时候,情况并非如此。现在,对于数据科学来说——对 SQL 有一个基本的熟悉几乎和知道如何用 Python 或 r 编写代码一样重要,但是访问一个足够大的包含真实数据(比如姓名、年龄、信用卡、SSN、地址、生日等)的数据库。)远不如访问 Kaggle 上专门为机器学习任务设计或管理的玩具数据集常见。

如果有一个简单的工具或库来生成一个包含多个表的大型数据库,并用自己选择的数据填充,岂不是很棒?

除了数据科学的初学者之外,即使是经验丰富的软件测试人员也会发现拥有一个简单的工具是很有用的,在这个工具中,他们只需要几行代码就可以生成任意大的数据集,其中包含随机的(伪造的)但有意义的条目。

我很高兴介绍一个轻量级的 Python 库,叫做 pydbgen 。你可以在这里阅读关于套餐的详细信息。我将在这篇短文中讨论类似的细节。

pydbgen 到底是什么?

这是一个轻量级的纯 python 库,可以生成任意有用的条目(例如,姓名、地址、信用卡号、日期、时间、公司名称、职位、车牌号码等)。)并将它们保存在 Pandas dataframe 对象中,或者作为数据库文件中的 SQLite 表,或者保存在 MS Excel 文件中。

怎么安装?

它(当前版本 1.0.5)托管在 PyPI (Python 包索引库)上。记住你需要安装 Faker 来完成这项工作。所以,只要输入,

pip install pydbgen 

注意,它目前只在 Python 3.6 上测试过。它在 Python 2 安装上不起作用。

怎么用?

你必须启动一个pydb对象来开始使用它。

import pydbgen
from pydbgen import pydbgen
myDB=pydbgen.pydb()

之后,您可以访问由**pydb**对象公开的各种内部函数。例如打印随机美国城市,

**myDB.city_real()**
>> 'Otterville'for _ in range(10):
    print(**myDB.license_plate()**)
>> 8NVX937
   6YZH485
   XBY-564
   SCG-2185
   XMR-158
   6OZZ231
   CJN-850
   SBL-4272
   TPY-658
   SZL-0934

如果你只是说'城市'而不是'城市 _ 真实',你会得到虚构的城市名称:)

print(myDB.gen_data_series(num=8,data_type='city'))
>>
New Michelle
Robinborough
Leebury
Kaylatown
Hamiltonfort
Lake Christopher
Hannahstad
West Adamborough

如何用随机条目生成熊猫数据帧?

您可以选择要生成多少数据和什么数据类型。注意,所有内容都以字符串/文本的形式返回。

testdf=**myDB.gen_dataframe**(5,['name','city','phone','date'])
testdf

产生的数据帧如下所示:

如何生成数据库表?

您可以选择要生成多少数据和什么数据类型。注意,数据库的所有内容都以 text/VARCHAR 数据类型返回。您可以指定数据库文件名和表名。

**myDB.gen_table**(db_file='Testdb.DB',table_name='People',
fields=['name','city','street_address','email'])

这将生成一个. DB 文件,可用于 MySQL 或 SQLite 数据库服务器。生成的数据库表在 DB Browser for SQLite 中打开,如下所示:

如何生成 Excel 文件?

与上面类似,只需使用下面的代码生成一个带有随机数据的 Excel 文件。注意,“simple_phone”设置为 False,从而生成复杂的长格式电话号码。这对于试验更复杂的数据提取代码来说很方便!

myDB.gen_excel(num=20,fields=['name','phone','time','country'],
***phone_simple=False***,filename='TestExcel.xlsx')

结果文件看起来像…

一个很酷的方式来生成随机电子邮件 id 的废料使用?

pydbgen 中的一个内置方法是realistic_email,它从种子名称生成随机的电子邮件 id。你能想到这种方法在网络上的任何用途吗?你不想给出你真实的电子邮件 ID,而是一些相近的东西。

for _ in range(10):
    print(myDB.realistic_email('Tirtha Sarkar'))
>>
Tirtha_Sarkar@gmail.com
Sarkar.Tirtha@outlook.com
Tirtha_S48@verizon.com
Tirtha_Sarkar62@yahoo.com
Tirtha.S46@yandex.com
Tirtha.S@att.com
Sarkar.Tirtha60@gmail.com
TirthaSarkar@zoho.com
Sarkar.Tirtha@protonmail.com
Tirtha.S@comcast.net

未来改进和用户贡献

当前版本是 1.0.5,可能包含许多 bug。如果你注意到任何和你的程序在执行过程中崩溃(除了你的错误输入),请让我知道。此外,如果你有很酷的想法来贡献源代码,那么 Github repo 全部为你开放。一些问题很容易浮现在脑海中,

  • 我们能否将一些机器学习/统计建模与这个随机数据生成器集成在一起?
  • 生成器是否应该增加可视化功能?

可能性无穷无尽,令人兴奋……

如果您有任何问题或想法要分享,请联系作者在tirthajyoti【AT】Gmail . com。你也可以查看作者的 GitHub 资源库 中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

介绍 ReviewNB:Jupyter 笔记本的代码审查

原文:https://towardsdatascience.com/introducing-reviewnb-visual-diff-for-jupyter-notebooks-6797e6dfa20c?source=collection_archive---------12-----------------------

我们很高兴地宣布 ReviewNB ,这是一款帮助您对 Jupyter 笔记本进行版本控制&的工具。

问题

Jupyter 非常适合数据探索,但是很难超越这个范围&使用它进行协作。将 Jupyter 笔记本电脑与现代版本控制系统(如 Git)配合使用存在以下挑战:

  • 笔记本差难读。因此我们不能在 GitHub 上做代码审查
  • 由于笔记本文件的 JSON 格式,合并远程更改很困难。ipynb)
  • 没有简单的方法来分享反馈&围绕笔记本电脑进行讨论
  • 重现笔记本结果并不容易
  • 测试笔记本代码单元并不容易

解决办法

ReviewNB 旨在从差异、代码审查和协作入手解决这些问题

  • 我们为笔记本电脑打造了一流的视觉差异。更多例子在我们的主页上。

Visual Diff for Jupyter Notebooks

  • 您可以在 repo 中浏览 GitHub 提交、拉取请求或打开笔记本文件&在笔记本单元格上写评论以提出改进建议、寻求澄清,或者只是为您同事的工作鼓掌!

Conversation Threads to Track All Ongoing Discussions

它是如何工作的?

  • ReviewNB 是 GitHub marketplace 上提供的 GitHub 应用(我们的应用通过 GitHub 的验证)
  • ReviewNB 与 GitHub APIs 通信,以获取在提交或拉取请求中所做的笔记本更改。我们以并排差异的格式向用户展示这些变化。所有笔记本内容(降价、代码、图像、公式)都以 Jupyter UI 中的方式呈现。这种视觉差异比笔记本常见的混乱 JSON 差异更具可读性。
  • 您还可以在 pull 请求中的笔记本单元格上,甚至在独立的笔记本文件上写注释。您的队友将会收到评论的电子邮件通知&任何人都可以表达他们的想法。

工作流程

ReviewNB 使用起来超级简单。它不需要任何本地安装或配置。人们可以在不到一分钟的时间内在他们的 GitHub 库上开始使用它。

  • 任何人都可以通过 GitHub 登录并选择 ReviewNB 有权访问的存储库(需要大约 30 秒)。
  • 登录后,您可以在存储库上浏览提交或拉取请求。

Browse notebooks, commits & pull requests on ReviewNB

  • 就是这样!您可以开始看到任何提交或拉请求的可视差异,并开始与您的同事进行讨论!

为我们的路线图做出贡献

我们在露天建造。你可以查看即将推出的新功能,为它们投票,甚至申请一个新功能。

暂时就这样吧!在我们的网站上有更多的信息,还有一个精心制作的常见问题解答部分供你询问其他问题。我们还为有兴趣自行运行 ReviewNB 的公司提供自托管选项。如果你有任何问题,我可以在 amit@reviewnb.com 找到你。试试 ReviewNB,让我知道你对它的看法!

查看 Amit Rathi 的所有帖子

原载于 2018 年 10 月 24 日blog.amirathi.com

与 tsalib 图书馆的 Tensors 成为朋友

原文:https://towardsdatascience.com/introducing-tensor-shape-annotation-library-tsalib-963b5b13c35b?source=collection_archive---------7-----------------------

tldr: [tsalib](https://github.com/ofnote/tsalib)是为张量定义维度名称和命名形状表达式的库。允许变量上的形状标签、形状断言和使用名称的直观形状转换。使用任意张量库。显式形状注释加速了深度学习程序的调试,并提高了开发人员的生产率和代码可读性。

源代码可在 github 资源库 获得。

更新(2019 年 11 月):检查我们的库 tsanley 到注释动态检查命名的形状。使用 tsanley,您可以避免编写显式的形状断言,并自动注释您想要重用的第三方深度学习代码。

编写操纵张量的深度学习程序(例如,使用numpypytorchtensorflowkeras..)要求你仔细记录张量变量的形状。当你编写更复杂的程序时,在你的头脑中思考这些图形变得越来越困难。例如,当创建一个新的RNN细胞或设计一种新的attention机制或试图做一个非平凡的预训练架构的手术(resnet101densenet)。不幸的是,没有在代码中跟踪形状的原则性方法——大多数开发人员求助于编写嵌入代码中的特别注释来跟踪张量形状。

例如,考虑一下最近流行的来自 Google 的 BERT 模型实现的片段。注意每条语句是如何被其inputoutput形状标记的。没有这种明确的形状跟踪,实际上不可能编写和调试复杂的张量程序。

Code from BERT implementation from Google.

同样,考虑 tensorflow 教程中的这个 CNN 模型。注意每个语句是如何用其inputoutput形状来标记的,以帮助开发人员。因为形状可能是动态的,所以这些注释同时包含了参数 (batch_size)和常量 (28)。

随着网络架构变得复杂,这些注释对于保持开发人员的理智以及其他人理解和扩展代码变得非常重要。不幸的是,没有对这些注释的本地支持,工程师们继续编写特别注释来填补空白。事实上,从业者一直在向 T21 寻求更好的支持。

张量形状注释

美国运输安全管理局图书馆 ( tsalib)来帮你了。

  • 该库允许您定义自定义维度变量( B =Batch, C =Channels,…)以及它们的张量形状表达式。
  • tsalib不触及代码所依赖的张量库的内部——适用于任何张量库(numpytensorflow,pytorch等等)。
  • 直接在代码中用其形状表达式标注张量变量,作为一级类型标注。
  • 您可以使用 TSA 直接构建(清晰的)形状变换(reshapepermuteaxis索引)和简洁的矩阵/张量运算——稍后将详细介绍。

这里是使用 TSAs 的简单张量程序(代码在这里可用)。注意变量abc是如何用它们的形状标注的。形状标注,例如(2,B,D)既可以包含常量,也可以包含命名的尺寸变量 ( BD)。请注意代码是如何立即变得更具可读性的——您可以简单地浏览一下形状注释,发现由numpy函数执行的形状转换(即使您不熟悉 API)。

尺寸变量,形状表达式

该库背后的核心思想是维度变量及其表达式。

  • [tsalib](https://github.com/ofnote/tsalib)允许你为你的架构声明自定义维度变量,在形状注释中使用它们,并像普通 Python 变量一样对它们执行算术运算。
  • 声明包括可选的大小默认值和简写名称。用 dim 变量(BD)替换您的配置参数(batch_sizeembed_dim)。在代码的所有部分只使用 dim 变量。

TSA 在很多方面都很有用。

  • 当编写新的转换或修改现有模块时,它们帮助我们快速地交叉检查调试变量形状。
  • TSA 作为有用的文档来指导其他人理解或扩展你的模块。
  • 周围有明确的形状是有益的,原因有几个(见下文)。
  • TSA 不会以任何方式影响程序的性能或正确性。您可以根据需要或多或少地添加注释。

示例:带 TSAs 的 Resnet

这里有一个更复杂的例子,一个来自pytorch torchvision库的resnet模块。这个模块是多个resnet 实现的基础:resnet{18,34,50,101,152}。现在,通过查看__init___make_layer模块很难获得对架构的任何洞察,即使你直觉地非常了解架构。因此,你也不能理解forward函数。

Resnet Implementation (Pytorch)

现在,让我们看看带注释的forward函数。无需了解各组件层的细节,TSA 允许您发现模块的预期输入(图像)的形状x以及它如何被每一层转换。如果您正在重用该模块,例如在SSD中用于对象检测,或在U-Net中用于分割,您可以一目了然地读出所有中间层的形状。

请注意在命名维度上编写算术表达式的能力是多么有帮助。配置变量(num_classes)可以直接在形状中使用。同样,很明显,架构是通过块扩展变量Ex 来参数化的(在较小的 resnetss 中为 1,在较大的 resnet 中为 4)。

基于注意力的架构,例如 Transformer,也深受不透明问题的困扰。参见TSA lib/examples/open ai _ transformer . py(注释从 AllenNLP 的实现开始)了解 TSA 如何显著影响代码的可读性。同样,通过浏览前进模块,我们可以快速了解架构。解剖一个多头注意力架构现在是小菜一碟!

形状变换,速记符号

一旦代码中有了维度变量,我们就可以利用它们来进一步提高代码的生产率和清晰度。我们可以使用维度变量直接指定视图和置换转换。例如,这就是从 AllenNLP 库中在原始openai_transformer.py中实现merge_heads的方式。

现在,我们可以使用tsalib简洁地编写它。所有形状都是显式的,不再需要代码操作。通过使用它们的速记string表示代替元组,形状注释可以变得更加简洁,例如用'bcd'代替(B,C,D)tsalib允许使用快捷键来指定转换。在这里阅读更多。

在所有张量库(numpy,pytorch,tensorflow)中拥有类似 TSA 的原生支持将对从业者极为有益。然而,这可能涉及到严重的 重新设计。相比之下,TSA 是独立于库的、轻量级的和即插即用的。你可以从今天开始在你的深度学习项目中使用它们!

一定要给[tsalib](https://github.com/ofnote/tsalib)一次机会,并给我发送反馈——通过 twitter 联系我,或者直接给我发电子邮件。

库内部

类型注释(或类型提示)是 Python 3 中一个受支持的可选特性。随着 Python 3 的改进和被广泛采用,对注释和类型检查的支持也在改进。例如, AllenNLP 的人在他们的代码中使用类型和形状注释,并且推荐作为最佳实践。

tsalib内部使用一个奇妙的符号表达式库[sympy](https://www.sympy.org/)来构建和转换表达式。sympy是它唯一的依赖。

关于我:我是一名独立的计算机科学研究员、工程师和演讲者,喜欢提炼复杂的技术并将其转化为可消费的产品。我在学术界、工业界和初创公司都工作过。我帮助公司理解和应对复杂、不断发展的人工智能空间,并构建基于深度学习的解决方案,以最大化投资回报。如果你喜欢这篇文章,请鼓掌并发表你的评论。你可以关注我,在这里阅读我的其他文章,在 linkedin 上找到我,或者直接发邮件给我。

TFServe 简介:用于 tensorflow 模型推理的简单易用的 HTTP 服务器

原文:https://towardsdatascience.com/introducing-tfserve-simple-and-easy-http-server-for-tensorflow-model-inference-582ea1b07da8?source=collection_archive---------12-----------------------

机器学习最有趣(也是最有趣)的部分是利用你花时间训练的模型。虽然有很多关于如何训练模型的资源,但我们经常发现很难弄清楚如何部署一个使用训练好的模型进行推理(即进行预测)的系统。TFServe 是一个框架,旨在通过 HTTP 服务器以简单和容易的方式为 tensorflow 模型提供服务。

TFServe 是构建在 apistar 之上的微框架。要安装它,只需运行:

$ pip install tfserve

如何使用 TFServe?

让我们从这个常见的场景开始。你已经发现了一个惊人的 Tensorflow Inception CNN 模型,该模型由 Google 在 ImageNet 上训练。 希望构建一个使用该模型进行推理的 HTTP 服务。

从描述中可以看出,该模型接收 224x224 的标准化 RGB 图像,并返回最可能的类(从 ImageNet 中的 1000 个类中)。你下载模型,得到一个frozen_graph.pb(或者类似的)文件。

现在怎么办?关于如何让它运行的说明涉及到关于模型架构(你对此一无所知)、TF 服务或其他工具的知识。运行 HTTP 服务器进行推理有多难?这里是 **tfserve** 发挥作用的地方:

你需要 5 个零件:

  1. 模型文件:可以是.pb文件,也可以是包含ckpt文件的模型目录。
  2. 输入张量名称:图形输入张量的名称。
  3. 输出张量名称:图形的输出张量名称。
  4. encode : python 函数,接收请求体数据并输出一个dict映射输入张量名称到输入 numpy 值。
  5. decode : python 函数,接收一个dict映射输出张量名称到输出 numpy 值并返回 HTTP 响应。

输入和输出张量名称?

您可能知道,每个张量流图张量都有一个唯一的名称。这个名称是在创建图形时声明的。你需要向tfserve指定输入张量的名称。输出张量也是如此。

但是我已经从一些 Tensorflow repo 下载了这个模型,我不知道输入/输出张量的名称!

不要惊慌。只需使用 tfserve.helper.estimate_io_tensors函数了解可能的 i/o 张量供您选择。

举个例子,

> import tfserve import helper
> helper.estimate_io_tensors("frozen_model.pb")Possible INPUT tensors:
        import/img:0

Possible OUTPUT tensors:
        pred/out:0
        pred/softmax_out:0

太好了!我将需要import/img:0作为我的输入张量,需要pred/softmax_out:0作为我的输出张量(这将是一个多类概率分布)。

编码功能

实现一个函数,该函数接收 HTTP 请求主体数据并输出一个将输入张量名称映射到输入numpy值的dict

在图像分类示例之后,encode函数将接收 HTTP 请求主体中提供的二进制数据,并应输出一个映射“import/img:0”到 224x224 标准化 RGB numpy图像的dict:

def encode(request_data):
    with tempfile.NamedTemporaryFile(mode="wb", suffix=".jpg") as f:
        f.write(request_data)
        img = PIL.Image.open(f.name).resize((224, 224)) 
        img = np.asarray(img) / 255.

    return {"import/img:0": img}

解码功能

实现一个函数,该函数接收将输出张量名称映射到输出值并返回 HTTP 响应。

在图像分类示例之后,decode函数将接收到一个将“pred/softmax_out:0”映射到一个 1000 大小的数组的dict映射,该数组具有分类概率。我希望返回一个 JSON 对象,如下所示:

{
    class: "german shepard",
    prob: 0.98,
}

它包含关于最可能的类的信息。

然后,decode功能将会是:

def decode(outputs):
    p = outputs["pred/softmax_out:0"]
    index = np.argmax(p)
    return {
               "class": index_to_class_name(index),
               "prob": float(p[index])
           }

运行服务器

您现在可以运行提供上述所有 5 个部分的服务器(模型路径、输入张量、输出张量、 *encode* *decode* 函数):

from tfserve import TFServeAppapp = TFServeApp("frozen_graph.pb", ["import/img:0"],
                 ["pred/softmax_out:0"], encode, decode)app.run('127.0.0.1', 5000, debug=True)

如何向模型发送实际图像?

服务器将在127.0.0.1:5000启动并运行。为了运行模型,您应该向/发送一个**POST**请求,并将二进制图像作为请求体。您应该得到在decode函数中实现的 JSON 响应。

Using the server through Postman

您可以在请求正文中提供任何类型的数据。你只需要在encode函数中正确处理它,就可以得到图形的输入张量。

此外,您可以在 HTTP 响应中返回任何类型的数据(例如,除了 JSON 对象之外,它还可以包含带有分段信息的二进制图像)。您只需要在decode函数中构建响应。

结论

有了tfserve,运行一个 tensorflow 训练好的模型真的简单又容易。只需提供模型路径、输入/输出张量名称、将请求数据转换成输入张量的encode函数和将输出张量转换成响应的decode函数。就是这样!tfserve会处理剩下的。

有关更多信息,请访问项目网站!

[## iitzco/tfserve

将 TF 模型作为 HTTP API 简单方便地提供。通过在…上创建帐户,为 iitzco/tfserve 的发展做出贡献

github.com](https://github.com/iitzco/tfserve)

喜欢这个项目吗?在 github 回购上留个⭐!

引入人工智能定义的基础设施

原文:https://towardsdatascience.com/introducing-the-ai-defined-infrastructure-aidi-because-its-not-just-about-software-anymore-ab04f27e413f?source=collection_archive---------7-----------------------

(AiDI)——因为这不再仅仅是关于软件

软件定义的基础设施(SDI)是数据中心和云环境中最流行和持续的趋势之一,它通过基于脚本和源代码开发基础设施来提高基础设施的灵活性。然而,SDI 越来越成为达到目的的一种手段,因为自动化、复杂的算法以及智能系统正在导致人工智能定义的基础设施(AI 定义的基础设施——AiDI)。

空间数据基础设施并没有消亡,它只是达到目的的一种手段

SDI 从硬件层抽象出软件。因此,智能不再在硬件组件中实现,而是被移到软件堆栈中。SDI 以软件和高度自动化为基础,旨在无需人工干预的情况下构建和控制基础设施。

典型的 SDI 环境,例如云基础设施,是通过开发脚本或源代码来构建的。该软件包括配置整个基础设施环境所需的所有命令,包括运行在基础设施上的应用程序和服务。基于 SDI 的基础设施独立于特定的硬件环境工作。因此,一个完整的基础设施可以通过软件进行交换,而不考虑底层的硬件组件。SDI 是当今云基础设施环境的基础的一个原因。

然而,SDI 一点也不聪明!它基于静态源代码,包括用于自动采取某些动作的硬编码命令。

了解人工智能定义的基础设施(AIDI)

软件定义的基础架构是构建和运行动态 IT 环境的一个重要概念。然而,SDI 仅限于静态源代码以及负责为环境编写脚本/代码的开发人员和管理员的技能。此外,SDI 仅在一定程度上是动态的,因为它不能理解或了解它正在运行的自身环境。

人工智能定义的基础设施(AI-defined infra structure-AiDI)通过必要的复杂算法、机器学习和人工智能来增强 SDI,从而为 SDI 提供智能。AiDI 允许 SDI 建立和运行自我学习和自我修复的基础设施环境。因此,在没有人工交互的情况下,人工智能定义的 IT 基础设施环境能够

  • 根据工作负载要求部署必要的资源,并在不再需要时取消资源分配。
  • 不断分析每一个基础设施组件不断变化的行为和状态,从而了解自身。
  • 通过自主采取行动,根据单个基础架构组件的状态做出反应或主动采取行动,从而使整个基础架构进入无错误状态。

人工智能定义的基础设施无法与经典的自动化软件相比,后者通常使用预定义的脚本。人工智能定义的基础设施利用公司的现有知识,自动独立地执行它。然而,像每一个新生的有机体一样,人工智能定义的基础设施需要训练,但之后可以自主工作。因此,基于学到的知识,可以解决干扰——甚至通过连接过去的适当事件来主动解决未预期的事件。因此,人工智能定义的基础设施实时监控和分析所有响应组件,以基于其现有知识识别和解决问题。解决的事件越多,基础架构知识就越丰富。人工智能定义的基础设施的核心是一个基于知识的架构,可以分析事件和变化,并自主制定策略来解决问题。

此外,人工智能定义的基础设施包含社区以

  • 吸收外部专家的知识,变得更加聪明。
  • 与其他人工智能定义的基础设施环境连接,以链接、组合和共享他们的知识库。
  • 不断扩大知识池。
  • 优化知识。

总而言之,人工智能定义的基础设施是一个智能系统,它最初由外部知识驱动,可以在没有人类交互的情况下自主学习和决策。

AIDI 只是整个人工智能定义的企业堆栈的一部分

人工智能定义的基础设施是当今 IT 运营的重要组成部分,为人工智能支持的企业奠定了基础。然而,最重要的是,它使 it 部门能够将基础架构行为从今天的半动态环境转变为真正的实时 IT 环境。

这种规划、构建、运行和维护整个基础架构的自主方式让 IT 运营和开发人员能够以最高效的方式部署 IT 资源,如服务器、存储、网络、数据库和其他现成的服务——利用不止一位专家而是整个 IT 运营团队的知识。此外,IT 运营正从纯粹的资源消费者转变为完全自动化和智能化 IT 体系的协调者和管理者。端到端人工智能就绪企业的基础。

原载于www . reasoning . world

Weacast 简介

原文:https://towardsdatascience.com/introducing-weacast-e6e98487b2a8?source=collection_archive---------2-----------------------

Weacast 是一个新的开源平台,用于收集、展示和利用天气预报数据。

为什么选择 Weacast?

现在每天都可以从主要的气象机构获得天气预报数据。当前的天气观测结果通过一个被称为数据同化的过程被输入到数字计算机模型中,以产生对未来天气状况的预测。这些模型从海洋向大气顶部输出数百种其他气象要素,如温度、降水、结冰条件等。例如,下面的动画图像代表了来自 NOAA 的 GFS 天气预报模型的典型输出。

WeacastWeacast(WeacastWeaforecast的快捷方式)旨在提供 web 服务和可视化工具,以简单的方式和格式收集、展示和利用天气预报数据。事实上,尽管公开可用的天气预报数据来自许多不同的来源,采用许多不同的专用协议/格式(例如 WCS 、 GeoTIFF 、 GRIB 等)。),使得在 web 应用程序中消费变得不那么容易,尤其是在客户端。此外,预报数据通常覆盖大片大陆地区,包含数百个要素,如温度、风等。但是一些通常是特定业务用例所需要的。最后但并非最不重要的一点是,预测数据本质上是动态的,因此用最近可用的数据更新您的应用程序始终是一项乏味的任务。

广播哲学

Weacast 是天气预报模型不可知的,也就是说,它主要公开了一个极简框架,可以按需添加预报数据源,以插件式架构扩展其功能。然后,这些数据可以通过简单的 REST/Websocket 服务以 JSON 格式在 Weacast 中获得,并可以使用内置的 web 应用程序进行可视化。

当前支持的插件如下:

  • 来自 Meteo France 的 ARPEGE 型号
  • 来自法国气象局的阿罗梅模型
  • GFS 型号来自 NOAA

Weacast 的目标不仅仅是提供粗略的预测数据,它还包括一些工具,通过以下方式获取您自己的业务数据:

  • 探查预测数据,提取或分析您感兴趣的地点的相关数据(如机场、城市、商店等。)
  • 查询您探测到的数据,找出哪些位置符合特定的天气条件
  • 在特定地点满足某些天气条件时发出警报。

怎么品尝?

首先,您可以根据我们的 Weacast web app 模板来看看我们的展示区,更具体地说:

  • 可视化预测数据

This short video demonstrates how Weacast can be used to gather forecast data from different models to visualize and predict wind in different locations.

  • 探索预测数据

This short video demonstrates how Weacast can be used to explore forecast data and future wind prediction using a timeline widget.

  • 探测预测数据

This short video demonstrates how Weacast can be used to probe your own business data to find locations matching target weather conditions. Using runways data, first are found airports with a target wind direction, then runways with a target wind direction relative to their own orientation.

This short video demonstrates how Weacast can be used to probe your own business data or any location in the world to obtain time series of any forecast elements.

然后你可以试着安装你自己的演示。要全面了解它是如何工作的,请阅读我们的在线文档并开始开发您自己的基于 Weacast 的应用程序!

生产准备好了吗?

Weacast 已经足够可靠,可以在现实世界的应用中使用,因为它主要依赖于一小组经过良好测试的模块: weacast-core 、wea cast-ar page、 weacast-arome 、 weacast-gfs 、 weacast-probe 。虽然这个社区还很新但是为一个大的行业玩家开发的应用已经在生产了。

里面是什么?

Weacast 是可行的,主要由以下堆栈提供支持:

  • 后端的羽毛
  • 前端侧的类星体
  • 用于映射的传单和插件
  • 叶片速度用于风力可视化
  • 传单-时间维度用于时间管理
  • 用于彩色地图可视化的传单-canvaslayer-field
  • 小叶风钩为风钩

熊猫基础数据分析介绍(慕尼黑私人住宅市场数据集)

原文:https://towardsdatascience.com/introduction-to-basic-data-analysis-with-pandas-private-munich-housemarket-data-set-4da58720172e?source=collection_archive---------21-----------------------

这篇文章是上一篇文章(此处链接到媒体)的延续,在那篇文章中,我解释了我为了买房而确定慕尼黑房产市场价值的目标。

因为我得到了数据,在慕尼黑买房子是不可能的,我没有(可能永远也不会)赚到足够的钱来真正意识到这一点,但这些数据仍然很有趣,以便快速浏览熊猫的数据分析。

第一篇文章真正关注的是清理数据,因为为了实现正确的数据分析,您需要干净的数据。否则,在运行代码时,您会遇到很多问题。此外,我真的很喜欢这句话:“垃圾进来,垃圾出去”

如果你不清理你的数据,那么你可能会分析错误的数据点,给你错误的结果。

在这篇文章中,我们将深入探讨熊猫图书馆在数据集分析和一些可视化方面能为你做些什么。我喜欢习语的【一图胜千言】。我也非常直观,所以它真的有助于描绘你在数据集中看到的东西。

Pandas 方法概述

在最开始的时候,通过导入数据集的最新版本(你已经清理或从我的 github 帐户中获取的),你可以通过一些方法开始,这些方法会给你一些信息。

import pandas as pd
df = pd.read_csv('data_immo.clean.csv', delimiter='\t')
df.head(1).T ## I like the transpose function as it gives you a better view

using the transpose on one line allows you to see easily type of data and column name

df.describe() ## Always worth checking

你可能已经注意到了,我们对每一列都有相同的计数。多亏了我们的清理,所有剩下的数据都可供我们找到一些有趣的信息。

现在您可能已经意识到,这个数据集是一个时间序列,这意味着有一个类似时间戳的列,这将使您能够看到数据集随时间的演变。这对我们的分析很有用,可以看出是否有进化。

为了设置时间序列,我们需要使用某种方法来确定哪一列包含此信息,以及如何将其转换为 pandas 数据帧。

您可能希望(但不是必须)导入 datetime 库并转换 date_year_month 列。
如果我们想从我们将从这个翻译创建的日期时间列中实际做其他事情,我们导入日期时间。

import datetime
df['date'] = pd.to_datetime(df['date_year_month'],format= '%Y%m') ## This will create a new column that contains your datetime element
##Let's not stop here and analyze the different element identified in that column 
df['date'].value_counts() ##Unique values and number of occurences

我们看到 2016 年 4 月、2017 年 5 月和 12 月
的数值较低。

我们需要记住这一点,以免在那一个月得出结论。没有足够的数据来做出任何假设。

从对你的数据集有一个想法开始,你可以实现一些简单的可视化,以便分析你的数据集或只是一个系列。
如果我们想看到价格的分布,我们可以实现这种盒子绘图

ax = df['price'].plot(kind='box', title='box plot visualization - price') #return an object from matplotlib
ax.set_ylabel('price')
ax.set_xlabel('data set')

oh oh… what are those data points near 0 ?

在这里,您可以看到大多数值(25–75%)在 210 k 和 500 K€范围内。
但你也可以看到一些额外的点,更重要的是,似乎有数据点要清理。我们有它的价格,但它是 0,这是不可能的,即使我真的很喜欢这个。

df[df['price'] == df['price'].min()] ## look for the data that match the minimum.
## In case you want to have some margin against the minimum, you can do something like this 

df[df['price'] < df['price'].min()*1.1] ## Will take everything below 10% more than the minimum.
## it doesn't work in our case as our minimum is 0 but we can set a hardcap nothing below 50K. 

df[df['price'] < 50000]

让我们暂时保存它们,我们以后可以使用这些数据。
我们只是将它们从主要分析中移除,并将它们保存在一个单独的数据框架中。

df_0_price = df[df['price'] < 50000].copy()
df_0_price.reset_index(inplace=True,drop=True) ## let's reset their index
df = df[df['price'] > 50000]
df.reset_index(inplace=True,drop=True) ## let's reset their index
df['price'].plot(kind='box')

This is a lot better

我认为这部分是你在实际工作中所做的一个很好的例子。即使您已经花了一些时间清理您的数据集,当您意识到分析时,您总是会发现一些要清理的东西。这是你真正挖掘数据的时候,你会经常遇到这种情况。重新清理数据。

回到分析,熊猫的一个有趣的方法是看两个变量之间是否有相关性。
为了做到这一点,您可以在 2 个系列之间使用 corr()。

df[['date_year_month','price']].corr()
## returns 0.42 : So positive correlation, price are increasing with time
## note that we are taking the 'date_year_month' data that are a number such as 201801 so it increased over time. 
df[['rooms','price']].corr()
## returns 0.093 : No correlation between price and number of rooms. 
## But this can be biased by the few number of different room number. 

df['rooms'].value_counts()
## returns 3 values 2 (821), 3 (24), 4 (8). 
## The over representation of 2 rooms will bias the correlation here.

对您的数据做的一件有趣的事情是通过按分类数据对元素进行分组来反转视图。如果你懂一点 SQL,你会直接对“分组”这个词挠痒痒。是的,熊猫有 groupby 功能,而且很容易使用。

我们可以做的一个有趣的分析是查看每个邮政编码的平均价格。为了有真正的比较,我们将采取每平方米的价格(价格 _ 表面)。

这将返回一个 groupby 对象,最好将它存储在一个变量中。

df_groupby_zip = df.groupby('zip')['price_surface'].mean() ## The good thing is that you can do a groupby on multiple elements. 

df_groupby_zip_room =  df.groupby(['zip','rooms'])['price'].mean()

这个方法其实很厉害。在这种状态下,它提供了更清晰的视图和查看数据的新方法。你也可能会说“这很好,它摆脱了复杂性,但我想知道实际上发生了什么”
如果我告诉你,你可以使用这种方法来查看发生了什么(聚合了多少数据点),但在一个命令中添加了更多的计算,会怎么样?

df_groupby_zip_agg = df.groupby('zip').agg({'price_surface' : ['mean','count','max']})

什么???在一条线上?
是的,很容易获得每个邮政编码的每平方米平均价格、数据点的数量以及每个群体聚集的最大值。的。agg 绝对是你需要记住的。

正如您可能已经猜到的那样,它只要求我们在字典中添加另一个列名,以便实际考虑另一个列(使用您想要应用于它的适当计算)。

问题出现在这里,因为 price_surface 列将有一个多重索引,这不容易处理。
我用来从 price_surface 数据类型中只选择一列的方法是使用。loc[]选择。

df_groupby_zip_agg.loc[:,('price_surface','mean')]

熊猫可视化

Pandas 集成了 matplotlib 以实现一些简单的可视化。
您已经看到了箱线图,这是一个非常有趣的数据集分布视图。在本文的下一部分,我们将看到如何创建这样的可视化来查看您的数据集。

为了看到可视化效果,您需要编写这行代码:

%matplotlib inline #will generate the graph in your console

正如我之前解释的,我们的数据集很酷的一点是它是一个时间序列。
要真正获得这类数据,您需要将 datetime 列放在索引中。
一旦你这样做了,所有的情节将以时间序列的方式生成。

ddf = df.set_index('date')
ddf_gby_mean = ddf.groupby('date').mean()
ddf_gby_mean[['price_room','price']].plot()

simple visualization

这是一个非常基本的绘图。
你可以改变类型,使用种类属性,但是你可以使用更多的属性。对我来说最有用的是:

  • 种类:决定情节的类型,我最喜欢的是 barh 或 bar。
  • figsize:使用一个元组来调整图形的大小
  • 标题:给你的图表起一个标题
  • cmap:使用不同的颜色地图,链接到一些文档
ddf_gby_mean[['price_room','price']].plot(kind='area',title='price per room & price overtime',figsize=(10,7),cmap='tab20')

How better is it ?

你可以清楚地看到从 2016 年 11 月开始的数据集的演变。
我们得到了一个更高的平均价格,这可能是因为最高价格已经提高了。我可以告诉你这是事实,但让我们看看数据来证实这一点。

graph = pd.DataFrame(df.groupby('date').agg({'price':['max','count']})) ##setting a new view with groupby
ax = graph.loc[:,('price','max')].plot(kind='line',title='Maximum price per month',figsize=(13,6))

您可以清楚地看到,我提高了我期望的最高价格。这是因为慕尼黑的物价太高,没有其他选择。

熊猫图形表示非常有用,将帮助您更好地理解您的数据。但是,您也可以使用具有一些高级可视化表示其他绘图库。这个主题本身值得再写一篇博文,但是让我们看看另一篇,它非常容易使用,并且对于额外的图形可视化非常强大:seaborn

import seaborn as sns
sns.relplot(x="construction_year", y="price", hue='rooms',sizes=(20, 400), alpha=.7, height=10, data=df)

很容易通过建筑年份和房间数量来显示价格吗?我们可以看到,市场上的大多数报价(在我的价格范围内)都在 1960 英镑到 1990 英镑之间。甚至有一些建筑预计建造时间会持续到 2020 年。

总的来说,绘图函数的使用通常来自 matplotlib 的包装。因此,您应该真正开始了解这个库是关于什么的,这样您就可以更好地整合它提供的可能性。

我希望这篇文章有助于了解如何使用 pandas 进行基本的数据分析。我计划涵盖更多的主题和可视化,但这已经变得很长了。我会回来的;)

贝叶斯线性回归简介

原文:https://towardsdatascience.com/introduction-to-bayesian-linear-regression-e66e60791ea7?source=collection_archive---------0-----------------------

解释线性建模的贝叶斯方法

贝叶斯与频率主义者的辩论是我觉得观看比参与更有趣的学术辩论之一。我认为学习两种统计推断的方法并在适当的时候应用它们会更有成效,而不是狂热地跳到某一方。按照这种思路,最近,我一直在努力学习和应用贝叶斯推理方法,以补充我的研究生课程中涵盖的频率统计。

在应用贝叶斯推理中,我首先关注的领域之一是贝叶斯线性建模。学习过程中最重要的部分可能只是向他人解释一个想法,这篇文章是我试图介绍贝叶斯线性回归的概念。我们将简要回顾线性回归的 frequentist 方法,介绍贝叶斯解释,并查看应用于简单数据集的一些结果。我在这篇文章中没有提到代码,但是它可以在 Jupyter 笔记本的 GitHub 上找到。

频率线性回归概述

线性回归的 frequentist 观点可能是您在学校中熟悉的观点:该模型假设响应变量(y)是权重乘以一组预测变量(x)的线性组合。完整的公式还包括一个误差项,以说明随机采样噪声。例如,如果我们有两个预测值,等式是:

y 是响应变量(也称为因变量),β是权重(称为模型参数),x 是预测变量的值,ε是一个误差项,表示随机采样噪声或模型中未包含的变量的影响。

线性回归是一个简单的模型,使其易于解释:β_0 是截距项,其他权重β显示了增加预测变量对响应的影响。例如,如果β_1 为 1.2,那么 x_1 每增加一个单位,响应将增加 1.2。

我们可以使用矩阵方程将线性模型推广到任意数量的预测值。将常数项 1 添加到预测值矩阵以说明截距,我们可以将矩阵公式写成:

从训练数据学习线性模型的目标是找到最好地解释数据的系数β。在 frequentist 线性回归中,最好的解释是指最小化残差平方和(RSS)的系数β。RSS 是已知值(y)和预测模型输出(ŷ,发音为 y-hat,表示估计值)之间的总平方差。残差平方和是模型参数的函数:

对训练集中的 N 个数据点求和。我们在此不再赘述细节(查看此参考文献了解推导过程),但该方程具有模型参数β的封闭形式解,可将误差降至最低。这被称为β的最大似然估计,因为在给定输入 X 和输出 y 的情况下,这是最有可能的值。以矩阵形式表示的封闭解为:

(同样,我们必须将“帽子”放在β上,因为它表示模型参数的估计值。)不要让矩阵数学把你吓跑了!感谢像 Python 中的Scikit-learn这样的库,我们通常不必手工计算(尽管编写线性回归代码是一个好的实践)。这种通过最小化 RSS 来拟合模型参数的方法被称为普通最小二乘法 (OLS)。

我们从 frequentist 线性回归中获得的是仅基于训练数据的模型参数的单一估计。我们的模型完全由数据提供信息:在这个视图中,我们需要知道的模型的一切都编码在我们可用的训练数据中。

一旦有了β-hat,我们就可以通过应用我们的模型方程来估计任何新数据点的输出值:

以 OLS 为例,我们可以对 15000 次锻炼观察的持续时间和消耗的卡路里的真实世界数据进行线性回归。下面是通过求解模型参数的上述矩阵方程获得的数据和 OLS 模型:

有了 OLS,我们得到了模型参数的一个单个估计,在这种情况下,就是线的截距和斜率。我们可以写出 OLS 提出的方程:

calories = -21.83 + 7.17 * duration

根据斜率,我们可以说,每增加一分钟的锻炼,就会多消耗 7.17 卡路里。这种情况下的截距并没有那么有帮助,因为它告诉我们,如果我们运动 0 分钟,我们将燃烧-21.86 卡路里!这只是 OLS 拟合过程的一个产物,该过程找到最小化训练数据上的误差的线,而不管它在物理上是否有意义。

如果我们有一个新的数据点,比如说锻炼持续时间为 15.5 分钟,我们可以将它代入等式,得到燃烧卡路里的点估计值:

calories = -21.83 + 7.17 * 15.5 = 89.2

普通最小二乘法为我们提供了输出的单点估计,我们可以将其解释为给定数据的最有可能的估计。然而,如果我们有一个小的数据集,我们可能希望将我们的估计表示为可能值的分布。这就是贝叶斯线性回归的用武之地。

贝叶斯线性回归

在贝叶斯观点中,我们使用概率分布而不是点估计来制定线性回归。响应 y 不是作为单个值来估计的,而是假设从概率分布中提取的。响应从正态分布取样的贝叶斯线性回归模型为:

输出 y 由以平均值和方差为特征的正态(高斯)分布产生。线性回归的平均值是权重矩阵的转置乘以预测矩阵。方差是标准差σ的平方(乘以单位矩阵,因为这是模型的多维公式)。

贝叶斯线性回归的目的不是找到模型参数的单个“最佳”值,而是确定模型参数的后验分布。不仅响应是由概率分布生成的,而且模型参数也被假定来自一个分布。模型参数的后验概率取决于训练输入和输出:

这里,P(β|y,X)是给定输入和输出的模型参数的后验概率分布。这等于数据的似然性 P(y|β,X)乘以参数的先验概率并除以归一化常数。这是贝叶斯定理的一个简单表达式,贝叶斯推理的基础:

让我们停下来想想这意味着什么。与 OLS 相反,我们有一个模型参数的后验分布,它与数据的可能性乘以参数的先验概率成正比。在这里,我们可以观察到贝叶斯线性回归的两个主要好处。

  1. 先验:如果我们有领域知识,或者对模型参数应该是什么的猜测,我们可以将它们包括在我们的模型中,不像 frequentist 方法那样假设关于参数的所有知识都来自数据。如果我们事先没有任何估计,我们可以使用无信息先验来获得正态分布等参数。
  2. 后验:执行贝叶斯线性回归的结果是基于数据和先验的可能模型参数的分布。这使我们能够量化我们对模型的不确定性:如果我们有更少的数据点,后验分布将更加分散。

随着数据点数量的增加,似然性会冲掉先验,在无限数据的情况下,参数的输出会收敛到从 OLS 获得的值。

将模型参数公式化为分布概括了贝叶斯世界观:我们从最初的估计开始,我们的先验,随着我们收集更多的证据,我们的模型变得不那么错误。贝叶斯推理是我们直觉的自然延伸。通常,我们有一个初始假设,当我们收集支持或反对我们想法的数据时,我们改变了我们的世界模型(理想情况下,这是我们推理的方式)!

实现贝叶斯线性回归

在实践中,对于连续变量,评估模型参数的后验分布是困难的,因此我们使用抽样方法从后验中抽取样本,以近似后验。从分布中抽取随机样本来近似分布的技术是蒙特卡罗方法的一个应用。蒙特卡洛采样有多种算法,最常见的是马尔可夫链蒙特卡洛的变体(关于 Python 中的应用,参见本文)。

贝叶斯线性建模应用

我将跳过这篇文章的代码(有关 PyMC3 中的实现,请参见笔记本),但实现贝叶斯线性回归的基本过程是:指定模型参数的先验(在本例中我使用了正态分布),创建一个将训练输入映射到训练输出的模型,然后让马尔可夫链蒙特卡罗(MCMC)算法从模型参数的后验分布中抽取样本。最终结果将是参数的后验分布。我们可以检查这些分布来了解发生了什么。

第一个图显示了模型参数的后验分布的近似值。这些是 1000 步 MCMC 的结果,意味着该算法从后验分布中提取了 1000 步。

如果我们将斜率和截距的平均值与 OLS 的进行比较(OLS 的截距为-21.83,斜率为 7.17),我们会发现它们非常相似。然而,虽然我们可以使用平均值作为单点估计,但我们也有模型参数的一系列可能值。随着数据点数量的增加,该范围将缩小并收敛到一个单一值,该值代表模型参数的更大置信度。(在贝叶斯推理中,变量的范围被称为可信区间,它的解释与频率推理中的置信区间略有不同)。

当我们想要显示贝叶斯模型的线性拟合,而不是只显示估计值时,我们可以绘制一系列线,每条线代表模型参数的不同估计值。随着数据点数量的增加,线条开始重叠,因为模型参数中的不确定性减少了。

为了演示模型中数据点数量的影响,我使用了两个模型,第一个模型使用了 500 个数据点,左边显示了结果拟合,右边的模型使用了 15000 个数据点。每个图显示了从模型参数后验中提取的 100 个可能的模型。

Bayesian Linear Regression Model Results with 500 (left) and 15000 observations (right)

当使用较少的数据点时,拟合中有更多的变化,这代表了模型中更大的不确定性。对于所有的数据点,OLS 和贝叶斯拟合几乎是相同的,因为先验被数据的可能性冲掉了。

当使用我们的贝叶斯线性模型预测单个数据点的输出时,我们也得不到单个值,而是一个分布。下面是运动 15.5 分钟消耗卡路里数的概率密度图。红色垂直线表示来自 OLS 的点估计。

Posterior Probability Density of Calories Burned from Bayesian Model

我们看到,燃烧卡路里数的概率峰值在 89.3 左右,但完整的估计是一个可能值的范围。

结论

不要在贝叶斯与频率主义的辩论(或任何争论)中偏袒任何一方,学习这两种方法更有建设性。这样,我们可以在正确的情况下应用它们。

在我们只有有限的数据或有一些先验知识要在我们的模型中使用的问题中,贝叶斯线性回归方法既可以包含先验信息,又可以显示我们的不确定性。贝叶斯线性回归反映了贝叶斯框架:我们形成一个初始估计,并在收集更多数据时改进我们的估计。贝叶斯观点是一种直观的看待世界的方式,贝叶斯推理是一种有用的替代方式。数据科学不是站在哪一边,而是找出工作的最佳工具,掌握更多技术只会让你更有效率!

一如既往,我欢迎反馈和建设性的批评。可以通过推特 @koehrsen_will 联系到我。

来源

  1. https://www . quant start . com/articles/Bayesian-Linear-Regression-Models-with-pymc 3
  2. http://twiecki.github.io/blog/2013/08/12/bayesian-glms-1/
  3. https://wise odd . github . io/tech blog/2017/01/05/Bayesian-regression/
  4. PyMC3 简介

贝叶斯网络简介

原文:https://towardsdatascience.com/introduction-to-bayesian-networks-81031eeed94e?source=collection_archive---------1-----------------------

贝叶斯网络是一种概率图形模型,使用贝叶斯推理进行概率计算。贝叶斯网络旨在通过用有向图中的边来表示条件依赖,从而对条件依赖以及因果关系进行建模。通过这些关系,人们可以通过使用因子有效地对图中的随机变量进行推断。

可能性

在深入到底什么是贝叶斯网络之前,首先回顾一下概率论是很有用的。

先记住随机变量 A_0,A_1,…,A_n 的联合概率分布,记为 P(A_0,A_1,…,A_n),由概率的链式法则,等于 P(A_1 | A_2,…,A_n) * P(A_2 | A_3,…,A_n) * … * P(A_n)。我们可以认为这是分布的分解表示,因为它是局部概率的 N 个因子的乘积。

接下来回想一下两个随机变量 A 和 B 之间的条件独立给定另一个随机变量 C,等价于满足以下性质:P(A,B|C) = P(A|C) * P(B|C)。换句话说,只要 C 的值已知且固定,A 和 B 就是独立的。另一种表述方式是 P(A|B,C) = P(A|C ),我们稍后会用到。

贝叶斯网络

使用我们的贝叶斯网络指定的关系,我们可以通过利用条件独立性来获得联合概率分布的紧凑、分解的表示。

贝叶斯网络是一个有向无环图,其中每条边对应一个条件依赖,每个节点对应一个唯一的随机变量。形式上,如果连接随机变量 A 和 B 的图中存在一条边(A,B ),则意味着 P(B|A)是联合概率分布中的一个因子,所以我们必须知道 B 和 A 的所有值的 P(B|A ),才能进行推断。在上面的示例中,由于 Rain 具有进入 WetGrass 的边,这意味着 P(WetGrass|Rain)将是一个因子,其概率值在条件概率表中 WetGrass 节点的旁边指定。

贝叶斯网络满足局部马尔可夫性质,该性质声明给定其父节点,节点有条件地独立于其非后代。在上面的例子中,这意味着 P(洒水喷头|多云,雨)= P(洒水喷头|多云),因为洒水喷头有条件地独立于它的非后代,雨,给定多云。这一性质使我们能够将上一节中使用链式法则得到的联合分布简化为更小的形式。简化后,贝叶斯网络的联合分布等于所有节点的 P(node|parents(node))的乘积,如下所示:

在较大的网络中,这一特性使我们能够大大减少所需的计算量,因为一般来说,相对于网络的整体规模,大多数节点的父节点很少。

推理

贝叶斯网络上的推理有两种形式。

第一种是简单地评估网络中每个变量(或子集)的特定赋值的联合概率。为此,我们已经有了联合分布的分解形式,所以我们简单地使用提供的条件概率来评估该产品。如果我们只关心变量的子集,我们将需要边缘化那些我们不感兴趣的变量。在许多情况下,这可能导致下溢,因此通常取该乘积的对数,这相当于将乘积中每一项的单独对数相加。

第二,更有趣的推理任务,是找到 P(x|e),或者,在给定其他变量赋值的情况下,找到变量子集(x)的某个赋值的概率(我们的证据,e)。在上面的示例中,可以找到 P(sprayer,WetGrass | Cloudy ),其中{ Sprinkler,WetGrass}是我们的 x,而{Cloudy}是我们的 e。为了计算这一点,我们使用了 P(x|e) = P(x,e) / P(e) = αP(x,e)这一事实,其中α是归一化常数,我们将在最后计算该常数,使得 P(x|e) + P( x | e) = 1。为了计算 P(x,e ),我们必须将没有出现在 x 或 e 中的变量的联合概率分布边缘化,我们将它们表示为 y。

对于给定的示例,我们可以如下计算 P(洒水喷头,湿草|多云):

我们将以同样的方式计算 P( x | e ),只是将 x 中变量的值设置为 false 而不是 true。一旦 P( x | e)和 P(x | e)都计算出来,我们就可以解出α,它等于 1 / (P(x | e) + P( x | e))。

请注意,在较大的网络中,Y 很可能相当大,因为大多数推理任务将只直接使用变量的一个小子集。在这种情况下,如上所示的精确推理计算量非常大,因此必须使用一些方法来减少计算量。一种更有效的精确推断方法是通过变量消除,它利用了每个因素只涉及少量变量的事实。这意味着求和可以重新排列,以便在该变量的边缘化中只使用涉及给定变量的因子。或者,许多网络甚至对于这种方法来说都太大了,所以使用近似推理方法,例如MCMC;这些提供的概率估计比精确推断方法需要更少的计算。

熊猫清洗数据介绍(私人慕尼黑 Housemarket 数据集)

原文:https://towardsdatascience.com/introduction-to-cleaning-data-with-pandas-private-munich-housemarket-data-set-be5fc558c9e3?source=collection_archive---------4-----------------------

一开始我就开始用 python 做数据分析之外的其他事情。我是一名技术 SEO 顾问,想要使用一个爬虫(或构建一个),但不知道任何编程语言,python 看起来是开始的完美语言…
现在,我更喜欢 python,因为它的多功能性可以做我刚才提到的事情,还可以轻松实现数据分析。

如果我们能把这两个世界融合在一起会怎么样?当我手腕受伤时,我创作了我的第一个爬虫,它并不漂亮,它是用一只手写的,但是很有效。
现在我正在看数据,我想这将是一个很好的简单的例子,说明如何使用 python(主要是 Pandas)来使用您收集的数据,或者您可以使用的数据。

慕尼黑的房产市场

我现在住在慕尼黑,我真的很喜欢这个城市,在我职业生涯的初期,我去过很多地方(纽约/旧金山/台湾/巴黎),我很快想到我需要一些数据来帮助寻找我的家。如果我想在某个地方购买,你需要支付的不是一个小数目,很可能是一大笔钱,所以你需要用一些确凿的数据来支撑你的愿望。

我用我的小爬虫独自收集慕尼黑周围房产市场的数据。它仍然是一个手动程序,因为当我创建它时,我不知道也没有时间让它成为一个全天候运行的云原生应用程序。

我可能会尝试改进它,使它成为云原生的,这样我就可以监控它。如果我成功了,这将是一篇博文。我在上的博客数据分析。
与此同时,我一次又一次地运行这个爬虫,有些人可能会说是以一种随机的方式;) .

慕尼黑的房市贵,不是一点点,是真的贵。
所以我在做我的爬虫,以便找到一个符合我预算的家。大部分是公寓(因为房子不在我的预算之内),位于慕尼黑地区。

所以从这个分析的偏见开始,这里有一些:

  • 我寻找“最多 4 个房间的公寓”
  • 我寻找“高达 60 万€”的公寓(大约 69 万美元)
  • 我找的是“离慕尼黑中心最多 20 公里”。
  • 我看了公寓是在一楼还是在楼上,但我没有看具体的楼层。

我将我的数据保存为 csv 格式,你可以在我的 github 账户上找到:https://github.com/pitchmuc/munich_housemarket.git

了解熊猫的数据

当我有数据集要查看时,我首先做两件事:

  1. 我观察数据集的大小。
  2. 我看数据集的类型。

对我来说,数据集不是很大(150 kb),所以我的电脑处理起来没有问题。如果它再大一点,我会把它分割成最大 100MB 的块,这样我就可以轻松地播放和测试我的脚本了。然后我会生成一个健壮的脚本来处理您的所有数据。
当您对您的完整数据集(即:5GB)执行分析时,您希望在花费数小时运行您的分析并发现它没有达到您想要的效果之前,确保这是可行的。

您必须处理的数据类型可以是:

  • clean:你只需要导入它
  • 半干净:您必须导入它,并处理一些丢失的数据。
  • 一点也不干净:你必须清理一下,导入它并处理掉丢失的数据。

在我们的例子中,我已经设法获得了相当干净到半干净的数据,但是仍然需要进行一些清理。
在下面的步骤中,你将看到如何用 python 熊猫实现基本的清洁:

导入您想要使用的库。在我们的例子中,你想要熊猫和熊猫。

import pandas as pd #naming convention 
import numpy as np #naming convention

在您的环境中导入数据集。
在我的例子中,我使用的是 ipython(或者叫做 jupyter notebook)。我真的很喜欢这种探索的环境。当事情变得严重时,我通常会去找 Spyder。

df = pd.read_csv('data_immoscout.csv',delimiter='\t') # df is going to be our dataframe. (place where we store all the data). I used tab as delimiter.

看看你掌握的数据。使用。head()函数将给出你的数据的预览。

df.head() ## use df.head(20) to get 20 lines

在 df.head()之上,您还可以尝试查看数据被处理的确切类型。
为了做到这一点,你可以使用

df.dtypes ##it will give you something like this : 
index0 int64 
terrace object 
bedrooms object 
construction_year object 
date_month int64 
date_year int64 
date_year_month object 
floor object 
rooms object 
price_room object 
price_surface object 
price object 
surface object 
zip int64 
dtype: object

查看您拥有的列的类型非常重要,因为这通常会让您了解数据存储的类型。或者应该存储数据的类型。

df.columns # will give you something like : Index(['index0', 'terrace', 'bedrooms', 'construction_year', 'date_month', 'date_year', 'date_year_month', 'floor', 'rooms', 'price_room', 'price_surface', 'price', 'scout_id', 'surface'], dtype='object')

由此我可以给你一些关于这些数据的解释,但是通过 dtypes 和 head()来看这些数据实际上应该已经给了你这样的想法:

  • index0:这是表格的索引
  • 露台:有没有露台
  • 卧室:有多少间卧室
  • 建造年份:什么时候建造的
  • date_month:一年中实现爬网的月份
  • date_year:实现爬网的年份
  • date_year_month:实现爬网的月份和年份
  • 地板:到底是不是底楼?
  • 房间:房间数量
  • 价格 _ 房间数:公寓价格除以房间数
  • 价格 _ 表面:公寓价格除以表面
  • 价格:公寓的价格
  • 表面:平面的表面
  • zip:公寓的邮政编码

当你开始处理这些数据时,你要做的第一件事是确保它们在系统中被正确识别。
什么叫“正确的方式”?
正确的做法是:数字看成数字,字符串看成字符串,日期看成日期,NaN 看成 NaN。

什么是南?
南代表“不是一个数”。了解这一点非常重要,因为这是我们在最终处理它们之前想要清理的数据类型。

正如你可能已经看到的,有几行实际上写的是 NAN。是公认的南吗?为了查看你有多少 NaN,你可以使用这个非常有用的函数:

df.isna().sum() ## The result will look like this :index0               0
terrace              0
bedrooms             0
construction_year    0
date_month           0
date_year            0
date_year_month      0
floor                0
rooms                0
price_room           0
price_surface        0
price                0
surface              0
zip                  0
dtype: int64

这意味着在您当前的数据集(或数据帧)中没有可识别的 NaN。
‘NAN’只是我实际运行爬虫时设置的一个字符串。

然后,您将用 NaN 的正确定义替换“NAN”字符串。为了做到这一点,我们将使用 numpy 库,您只需要这样使用它:

df.replace('NAN',np.NaN,inplace=True)When we have done that, we will then see different result on the previous method : df.isna().sum() ## The result will look like this :index0                 0
terrace                0
bedrooms             319
construction_year     49
date_month             0
date_year              0
date_year_month        0
floor                113
rooms                 34
price_room            35
price_surface        212
price                  1
surface              211
zip                    0
dtype: int64

在这里,我们开始了解这些数据的实际情况。
你看,我们缺少很多卧室信息的数据。
在接下来的步骤中,我们的任务是尽可能减少 NaN。
我们将尝试假设一些不同的策略来填充这里的 NaN。

如果你想看到你的数据集的整体质量,你实际上可以使用一些计算。
像这样:

(df.isnull().sum() / len(df))*100 ## result will look like this :index0                0.000000
terrace               0.000000
bedrooms             36.708861
construction_year     5.638665
date_month            0.000000
date_year             0.000000
date_year_month       0.000000
floor                13.003452
rooms                 3.912543
price_room            4.027618
price_surface        24.395857
price                 0.115075
surface              24.280783
zip                   0.000000
dtype: float64

所以我提供的数据并不完美,但你可能会看到很多比这更糟糕的数据。
了解数据:36.7%的行没有卧室信息。

真正令人不安的是,我们遗漏了一个特定数据点的价格信息。
价格真的很难预测,但让我们看看是什么数据,我们可能会有所发现:

df[df['price'].isna()].T ##the result will look like this :367index0 4terrace yesbedrooms NaNconstruction_year 2016 date_month 8date_year 2016date_year_month 2016_08floor NaNrooms 5price_room NaNprice_surface NaNprice NaNsurface 209zip 81479

你会发现我们遗漏了价格和卧室数量。
我们有两种选择:

  • 用我们掌握的信息预估价格(5 室,209 平米,建造年份:2016 年)
  • 从数据集中移除此线

在我们的案例中,2016 年建造的 200 平方米可能会超出我的数据集限制(<600 K€). I will then remove the line from the data set.

From my extract, I saw that the index of that line is 367.
我可以通过以下简单操作删除该线:

df.drop(df.index[367],inplace=True)

但是如果你有不止一个索引,你怎么管理呢?

你只需要大声说出你的病情指数:

df.drop(df[df['price'].isna()].index,inplace = True)

由于我们正在删除无用的信息,我们可以借此机会删除 index0 列,因为您可能已经看到 pandas 会自动为您的数据帧生成一个索引。
为了完全删除一列,你需要实现这个动作:

df.drop(['index0'],axis=1,inplace=True) #axis = 1 make sure that you are deleting column

现在我们想让熊猫识别正确的数据类型。
拥有正确的数据类型将允许我们实现对数值类型(int 或 float)的数值运算。
如果我们有正确的数据类型集,我们将能够以更好的方式处理 NaN。

我建议总是将数值设置为 int。
为什么 int ?因为它更容易处理和解释,但你可以试着让一切都浮动起来。
浮点数可以表示整数(2.0 == 2)但整数不能表示某些浮点数(2.1!= 2)

一个简单的循环可能是这样的:

for col in list(df.columns): # for each column
   try:
       df[col] = df[col].astype(int) #try to set it as int
   except:
       df[col] = df[col].astype(str) # if not sucessful try to set it as string

当您实现这个操作时,您可以看到并不是所有的列都被更改为数字。
这主要是因为某些列不是整数而是浮点数。(所以一个小数)

你可以实现另一个循环:

for col in list(df.columns):
    if df[col].dtypes == object:
        try:
            df[col] = df[col].astype(float)
        except:
            df[col] = df[col].astype(str)Then by doing a simple overview, your data start to look like something you can work :df.dtypes # it will show something like this :

Out[32]:

terrace               object
bedrooms             float64
construction_year    float64
date_month             int32
date_year              int32
date_year_month        int32
floor                 object
rooms                float64
price_room           float64
price_surface        float64
price                  int32
surface              float64
zip                    int32
dtype: object

填充 NaN

现在我们已经准备好处理不同类型的数据,我们将使用我们的大脑来处理不同的数据类型并填充 NaN 值。
如前所述,在进行任何分析之前,您可能想要感觉缺失值的最大值,以便计算最大值。

填写楼层栏你应该还记得,这一栏告诉我们这是不是底层。
通过这个简单的方法,你可以看到不同的值和它们出现的次数。

df['floor'].value_counts() ### Should show something like this :up floor 687 
nan 112 
ground floor 69 
Name: floor, dtype: int64

您需要做的是计算楼上和楼下之间的分布,并将该分布应用于其余数据。你可以很容易地计算出底层公寓的数量约占本栏的 10%。
因此,我们需要用“底层”值替换 na 的 1/10。

我们可以通过简单地创建一个函数来实现:

def fill10pct(): 
    if np.random.random_integers(0,9) == 0: 
        return 'ground floor' 
    else: 
        return 'up floor'

然后,您需要将它应用到您的行:

for index, value in df.iterrows(): 
    if df.loc[index,'floor']=='nan': 
        df.loc[index,'floor'] = fill10pct()

您可以运行 df['floor']。value_counts()来检查是否保持了分布。

填充房间现在我们将尝试填充房间。
我们将在这里尝试一种不同的技术。我们有一些信息可以帮助我们确定总共有多少个房间。
有卧室信息,所以在德国的邮政公寓中,卧室是唯一从房间数中分开统计的房间。
也就是:三室是指两个卧室,一个大房间,一个厨房和一个卫生间。
所以我们可以说房间的数量是卧室的数量+1,但是如果我们没有卧室的数量呢?那么,为了简单起见,我们可以说房间的数量是 2。这是我能拿到的最低工资。为此我们将创造我们的 2 个条件(有或没有若干卧室)

conditions = [ (df['rooms'].isnull()) & (df['bedrooms'].isnull()), (df['rooms'].isnull()) & (df['bedrooms'].notnull())] 
choices = [2,df['bedrooms']+1]
df['rooms'] = np.select(conditions, choices, default=2)

我们将使用 numpy select 函数来决定应用哪个选项

df['rooms'] = np.select(conditions, choices, default=2)

当你知道怎么做时,这很容易。:)它太简单了,所以我们将把它做得更健壮一点,并在其中集成曲面。我们会说,如果表面大于 75 平方米,我们将设置房间数为 3。

conditions =[ 
(df['rooms'].isnull()) & (df['bedrooms'].isnull()) & (df['surface'].isnull()), 
(df['rooms'].isnull()) & (df['bedrooms'].isnull()) & (df['surface']>75), 
(df['rooms'].isnull()) & (df['bedrooms'].notnull()), ] choices = [2,3,df['bedrooms']+1] 
df['rooms'] = np.select(conditions,choices,default=2)

填充卧室
填充卧室其实是相反的逻辑。如果你有房间的数量,你实际上可以猜出卧室的数量。
这一次,我们将使用从 numpy 中选择的方法:

df['bedrooms'] = np.where(df['bedrooms'].isnull(), df['rooms']-1, df['bedrooms'])

填充表面
对于表面,我们缺少 211 个数据点。我们可以有相同的策略,而不是房间的数量。外推现有公寓的表面以填充表面的缺失值。如果我们能得到 2、3 和 4 房间公寓的平均面积,我们就能给这些房间分配平均值。为了实现这一点,我们将使用熊猫最重要的功能之一。组由组成。

df.groupby(['rooms'])['surface'].mean() ##it should give you something like :
2.0 89.988924 
3.0 91.100000 
4.0 100.40000

有趣的是,你的 2 室和 3 室公寓的平均面积没有太大差别。很可能我们的数据没有那么干净,一些三室公寓被当成了两室公寓。

conditions = [
(df['rooms']==2 & df['surface'].isnull()), 
(df['rooms']==3 & df['surface'].isnull()), 
(df['rooms']==4 & df['surface'].isnull()) ] 
choices = [90,91.1,100] 
df['surface'] = np.select(conditions,choices,default=90.5)#default in between 2 and 3 rooms

填写建造年份
在这个例子中,这是相当困难的,因为建造年份可能是随机的。你无法根据之前的数据猜测建造年份。
在这种情况下,为了不虚报数据,我会选择用这个维度的含义来填补空白。
这是另一种你可以在熊猫身上快速使用的方法:

df['construction_year'].fillna(df['construction_year'].mean(),inplace=True)

填充剩余的…
正如你在做 df.isnull()时可能注意到的。sum()其他一些列有 NaN,但它们实际上是其他列的计算结果。所以你只需要用你的主列重新计算,所有的 NaN 就会消失。

如果您正在使用 Python 和 Pandas 进行数据分析,我希望这篇关于如何清理数据的教程能够对您有所帮助。
这是处理数据的一个非常重要的部分,如果您计划进行机器学习,清理数据并从 NaN 数据点中创造价值是机器学习最重要的方面之一。

如标题所示,我们将有第二篇文章,在那里我们实际分析数据,我们可能会尝试做一些可视化。

不要犹豫,评论并给出你的提示来分析这个数据集。
如上所述,数据集(干净的和不干净的)和 Jupyter 笔记本都在我的 Github 账户上:https://github.com/pitchmuc/munich_housemarket

临床自然语言处理导论:用出院总结预测医院再入院

原文:https://towardsdatascience.com/introduction-to-clinical-natural-language-processing-predicting-hospital-readmission-with-1736d52bc709?source=collection_archive---------1-----------------------

医生总是写下关于他们病人的临床记录——最初,这些记录写在纸上,锁在柜子里。对数据科学家来说幸运的是,医生现在可以在电子病历中输入他们的笔记。这些笔记代表了大量的知识和见解,可用于使用自然语言处理(NLP)的预测模型,以改善患者护理和医院工作流程。作为一个例子,我将向您展示如何通过出院总结来预测再次入院。

本文面向对医疗数据科学感兴趣的人。完成本教程后,您将学习

  • 如何为机器学习项目准备数据
  • 如何使用词袋方法预处理非结构化笔记
  • 如何建立一个简单的预测模型
  • 如何评估你的模型的质量
  • 如何决定改进模型的下一步

我最近读了 Rajkomar 等人的伟大论文“电子健康记录的可扩展和精确的深度学习”(论文发表于https://arxiv.org/abs/1801.07860)。作者利用医院数据建立了许多最先进的深度学习模型,以预测住院死亡率(AUC = 0.93-0.94)、30 天计划外再入院(AUC = 0.75-76)、延长住院时间(AUC = 0.85-0.86)和出院诊断(AUC = 0.90)。AUC 是一个数据科学性能指标(下面将详细介绍),越接近 1 越好。很明显,预测再入院是最困难的任务,因为它的 AUC 较低。我很好奇,如果将流量自由文本摘要与简单的预测模型结合使用,我们可以得到多好的模型。

如果你想在 Jupyter 笔记本上跟随 Python 代码,请随意从我的 github 下载代码。

模型定义

这篇博文将概述如何建立一个分类模型,利用自由文本的出院总结来预测哪些患者有 30 天无计划再入院的风险。

数据集

我们将利用 MIMIC-III(重症监护医疗信息集市 III)数据库。这个令人惊叹的免费医院数据库包含了 2001 年至 2012 年马萨诸塞州波士顿贝丝以色列女执事医疗中心收治的超过 50,000 名患者的去身份数据。为了访问该项目的数据,您需要通过此链接请求访问权限(【https://mimic.physionet.org/gettingstarted/access/】T4)。

在本项目中,我们将利用以下 MIMIC III 表格

  • 入院—包含入院和出院日期的表格(每个入院都有一个唯一的标识符 HADM_ID)
  • NOTEEVENTS —包含每次住院的所有注释(与 HADM_ID 的链接)

为了保持匿名,每个患者的所有日期都被转移到很远的将来,但是患者的两个连续事件之间的时间被保存在数据库中。这一点很重要,因为它保持了特定患者两次住院之间的时间。

由于这是一个受限制的数据集,我不能公开分享原始患者数据。因此,我将只向您展示人为的单个患者数据或汇总描述。

步骤 1:为机器学习项目准备数据

我们将按照以下步骤为我们的机器学习项目准备来自录取和 NOTEEVENTS 模拟表的数据。

首先,我们使用 pandas 数据帧加载录取表:

# set up notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt# read the admissions table
df_adm = pd.read_csv('ADMISSIONS.csv')

该表中感兴趣的主要列有:

  • SUBJECT_ID:每个主题的唯一标识符
  • HADM_ID:每次住院的唯一标识符
  • 入院时间:入院日期,格式为 YYYY-MM-DD hh:mm:ss
  • 出院时间:相同格式的出院日期
  • 死亡时间:相同格式的死亡时间(如果存在)
  • 入院类型:包括择期、急诊、新生儿、急症

下一步是将日期从字符串格式转换成日期时间。我们使用errors = ‘coerce’标志来考虑缺失的日期。

# convert to dates
df_adm.ADMITTIME = pd.to_datetime(df_adm.ADMITTIME, format = '%Y-%m-%d %H:%M:%S', errors = 'coerce')
df_adm.DISCHTIME = pd.to_datetime(df_adm.DISCHTIME, format = '%Y-%m-%d %H:%M:%S', errors = 'coerce')
df_adm.DEATHTIME = pd.to_datetime(df_adm.DEATHTIME, format = '%Y-%m-%d %H:%M:%S', errors = 'coerce')

下一步是获取下一个计划外入院日期(如果存在)。这将遵循几个步骤,我将向您展示一个人造病人会发生什么。首先,我们将按照入院日期对数据帧进行排序

# sort by subject_ID and admission date
df_adm = df_adm.sort_values(['SUBJECT_ID','ADMITTIME'])
df_adm = df_adm.reset_index(drop = True)

对于单个患者,数据帧可能是这样的:

我们可以使用 groupby shift 操作符来获取每个 SUBJECT_ID 的下一个许可(如果存在的话)

# add the next admission date and type for each subject using groupby
# you have to use groupby otherwise the dates will be from different subjects
df_adm['NEXT_ADMITTIME'] = df_adm.groupby('SUBJECT_ID').ADMITTIME.shift(-1)# get the next admission type
df_adm['NEXT_ADMISSION_TYPE'] = df_adm.groupby('SUBJECT_ID').ADMISSION_TYPE.shift(-1)

注意上一次录取没有下一次录取。

但是,我们要预测计划外的再次录取,所以我们应该过滤掉选修的下一次录取。

# get rows where next admission is elective and replace with naT or nan
rows = df_adm.NEXT_ADMISSION_TYPE == 'ELECTIVE'
df_adm.loc[rows,'NEXT_ADMITTIME'] = pd.NaT
df_adm.loc[rows,'NEXT_ADMISSION_TYPE'] = np.NaN

然后回填我们移除的值

# sort by subject_ID and admission date
# it is safer to sort right before the fill in case something changed the order above
df_adm = df_adm.sort_values(['SUBJECT_ID','ADMITTIME'])# back fill (this will take a little while)
df_adm[['NEXT_ADMITTIME','NEXT_ADMISSION_TYPE']] = df_adm.groupby(['SUBJECT_ID'])[['NEXT_ADMITTIME','NEXT_ADMISSION_TYPE']].fillna(method = 'bfill')

然后我们可以计算下一次入院的天数

df_adm['DAYS_NEXT_ADMIT']=  (df_adm.NEXT_ADMITTIME - df_adm.DISCHTIME).dt.total_seconds()/(24*60*60)

在我们 58976 例住院患者的数据集中,有 11399 例再次入院。对于那些再次入院的患者,我们可以绘制入院间隔天数的直方图。

现在我们已经准备好处理 NOTEEVENTS.csv 了

df_notes = pd.read_csv("NOTEEVENTS.csv")

感兴趣的主要列有:

  • 主题 ID
  • HADM_ID
  • 类别:包括“出院总结”、“回波”、“心电图”、“护理”、“医生”、“康复服务”、“病例管理”、“呼吸”、“营养”、“常规”、“社会工作”、“药房”、“咨询”、“放射科”、“T1”、“护理/其他”
  • 正文:我们的临床笔记专栏

由于我不能显示单个音符,我将在这里描述它们。数据集有 2,083,180 行,表明每次住院都有多个记录。在注释中,为了保密,日期和 PHI(姓名、医生、地点)已被转换。还有特殊字符,如\n(换行符)、数字和标点符号。

由于每次住院都有多张票据,我们需要选择使用哪种票据。为了简单起见,让我们使用放电摘要,但是如果我们愿意,我们可以通过连接它们来使用所有的注释。

# filter to discharge summary
df_notes_dis_sum = df_notes.loc[df_notes.CATEGORY == 'Discharge summary']

由于下一步是合并入院表上的记录,我们可能会假设每次入院都有一个出院总结,但我们可能应该检查一下。我们可以用一个 assert 语句来检查这一点,结果失败了。

在这一点上,您可能想要研究为什么有多个摘要,但是为了简单起见,让我们只使用最后一个

df_notes_dis_sum_last = (df_notes_dis_sum.groupby(['SUBJECT_ID','HADM_ID']).nth(-1)).reset_index()
assert df_notes_dis_sum_last.duplicated(['HADM_ID']).sum() == 0, 'Multiple discharge summaries per admission'

现在我们准备合并录取和注释表。我使用左合并来解决音符丢失的问题。在很多情况下,合并后会得到多行(尽管我们在上面已经处理过了),所以我喜欢在合并后添加 assert 语句

df_adm_notes = pd.merge(df_adm[['SUBJECT_ID','HADM_ID','ADMITTIME','DISCHTIME','DAYS_NEXT_ADMIT','NEXT_ADMITTIME','ADMISSION_TYPE','DEATHTIME']],
                        df_notes_dis_sum_last[['SUBJECT_ID','HADM_ID','TEXT']], 
                        on = ['SUBJECT_ID','HADM_ID'],
                        how = 'left')
assert len(df_adm) == len(df_adm_notes), 'Number of rows increased'

10.6 %的录取通知书丢失了(df_adm_notes.TEXT.isnull().sum() / len(df_adm_notes)),所以我进一步调查了一下

df_adm_notes.groupby('ADMISSION_TYPE').apply(lambda g: g.TEXT.isnull().sum())/df_adm_notes.groupby('ADMISSION_TYPE').size()

并发现 53%的新生儿入院缺少出院小结,而其他新生儿的这一比例为 4%。在这一点上,我决定取消新生入学。最有可能的是,这些失踪的新生儿入院记录的出院总结存储在模拟数据集之外。

对于这个问题,我们要对未来 30 天内是否会收治一个病人进行分类。因此,我们需要创建一个带有输出标签的变量(1 =重新接纳,0 =不重新接纳)

df_adm_notes_clean['OUTPUT_LABEL'] = (df_adm_notes_clean.DAYS_NEXT_ADMIT < 30).astype('int')

快速计数阳性和阴性结果为 3004 个阳性样本,48109 个阴性样本。这表明我们有一个不平衡的数据集,这在医疗保健数据科学中是常见的。

准备数据的最后一步是将数据分成训练集、验证集和测试集。为了获得可重复的结果,我让 random_state 始终为 42。

# shuffle the samples
df_adm_notes_clean = df_adm_notes_clean.sample(n = len(df_adm_notes_clean), random_state = 42)
df_adm_notes_clean = df_adm_notes_clean.reset_index(drop = True)# Save 30% of the data as validation and test data 
df_valid_test=df_adm_notes_clean.sample(frac=0.30,random_state=42)df_test = df_valid_test.sample(frac = 0.5, random_state = 42)
df_valid = df_valid_test.drop(df_test.index)# use the rest of the data as training data
df_train_all=df_adm_notes_clean.drop(df_valid_test.index)

由于患病率如此之低,我们希望防止模型总是预测为阴性(非再入院)。为此,我们有几个选项来平衡训练数据

  • 对底片进行子采样
  • 过度采样阳性
  • 创建合成数据(如 SMOTE)

由于我没有对您计算机的 RAM 大小做出任何限制,我们将对负面数据进行子采样,但我鼓励您尝试其他技术,如果您的计算机或服务器可以处理它,看看您是否可以获得改进。(如果你尝试这样做,请在下面发表评论!)

# split the training data into positive and negative
rows_pos = df_train_all.OUTPUT_LABEL == 1
df_train_pos = df_train_all.loc[rows_pos]
df_train_neg = df_train_all.loc[~rows_pos]# merge the balanced data
df_train = pd.concat([df_train_pos, df_train_neg.sample(n = len(df_train_pos), random_state = 42)],axis = 0)# shuffle the order of training samples 
df_train = df_train.sample(n = len(df_train), random_state = 42).reset_index(drop = True)

步骤 2:使用词袋方法对非结构化笔记进行预处理

现在,我们已经创建了具有标签和注释的数据集,我们需要预处理我们的文本数据,以将其转换为对机器学习模型有用的东西(例如数字)。我们将使用单词袋(BOW)方法。

BOW 基本上将笔记分解成单个单词,并计算每个单词出现的次数。你的数字数据就变成了一些单词的计数,如下所示。BOW 是做 NLP 分类最简单的方法。在我读过的大多数博客文章中,对于 NLP 分类任务,更高级的技术很难胜过 BOW。

在这个过程中,需要做出的选择很少

  • 如何对单词进行预处理
  • 如何统计单词
  • 使用哪些单词

没有适合所有 NLP 项目的最佳选择,所以我建议在构建自己的模型时尝试一些选项。

您可以用两种方式进行预处理

  • 修改原始数据帧文本列
  • 作为管道的一部分进行预处理,这样就不会编辑原始数据

我将向您展示如何做到这两个,但我更喜欢第二个,因为它需要大量的工作才能达到这一点。

让我们定义一个函数,通过用空格填充缺失的注释并删除换行符和回车符来修改原始数据帧

def preprocess_text(df):
    # This function preprocesses the text by filling not a number and replacing new lines ('\n') and carriage returns ('\r')
    df.TEXT = df.TEXT.fillna(' ')
    df.TEXT = df.TEXT.str.replace('\n',' ')
    df.TEXT = df.TEXT.str.replace('\r',' ')
    return df# preprocess the text to deal with known issues
df_train = preprocess_text(df_train)
df_valid = preprocess_text(df_valid)
df_test = preprocess_text(df_test)

另一种选择是作为管道的一部分进行预处理。这个过程包括使用一个标记器和一个矢量器。记号赋予器将单个音符分解成单词列表,矢量器获取单词列表并对单词进行计数。

我们将使用nltk包中的word_tokenize作为默认的记号赋予器,它基本上基于空格和一些标点符号来分解注释。下面显示了一个示例:

import nltk
from nltk import word_tokenize
word_tokenize('This should be tokenized. 02/02/2018 sentence has stars**')

带输出:

[‘This’, ‘should’, ‘be’, ‘tokenized’, ‘.’, ‘02/02/2018’, ‘sentence’,
 ‘has’, ‘stars**’]

默认情况下,一些标点符号被分开,数字留在句子中。我们将编写自己的记号赋予器函数来

  • 用空格替换标点符号
  • 用空格替换数字
  • 小写所有单词
import string
def tokenizer_better(text):
    # tokenize the text by replacing punctuation and numbers with spaces and lowercase all words

    punc_list = string.punctuation+'0123456789'
    t = str.maketrans(dict.fromkeys(punc_list, " "))
    text = text.lower().translate(t)
    tokens = word_tokenize(text)
    return tokens

有了这个标记符,我们就可以从原来的句子中得到

['this', 'should', 'be', 'tokenized', 'sentence', 'has', 'stars']

你可以做的另外的事情将会是词汇化或词干化,但是那是更高级的,所以我将跳过它。

既然我们有了将自由文本转换成令牌的方法,我们就需要一种方法来计算每个流量摘要的令牌数。我们将使用 scikit-learn 包中内置的CountVectorizer 。这个矢量器只是计算每个单词在笔记中出现的次数。还有一个TfidfVectorizer ,它考虑了单词在所有笔记中的使用频率,但对于这个项目,让我们使用更简单的一个(我在第二个项目中也得到了类似的结果)。

例如,假设我们有 3 个音符

sample_text = ['Data science is about the data', 'The science is amazing', 'Predictive modeling is part of data science']

本质上,您可以使用 CountVectorizer 来学习数据中的单词,并转换数据以创建每个单词的计数。

from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(tokenizer = tokenizer_better)
vect.fit(sample_text)# matrix is stored as a sparse matrix (since you have a lot of zeros)
X = vect.transform(sample_text)

矩阵 X 将是一个稀疏矩阵,但是如果你把它转换成一个数组(X.toarray(),你会看到这个

array([[1, 0, 2, 1, 0, 0, 0, 0, 1, 1],
       [0, 1, 0, 1, 0, 0, 0, 0, 1, 1],
       [0, 0, 1, 1, 1, 1, 1, 1, 1, 0]], dtype=int64)

其中有 3 行(因为我们有 3 个音符)和每个单词的计数。您可以看到带有vect.get_feature_names()的列名

['about', 'amazing', 'data', 'is', 'modeling', 'of', 'part', 'predictive', 'science', 'the']

我们现在可以在临床笔记上安装 CountVectorizer。只使用训练数据是很重要的,因为您不希望包含在验证和测试集中出现的任何新单词。有一个名为 max_features 的超参数,您可以设置它来限制矢量器中包含的单词数量。这将使用前 N 个最常用的单词。在第 5 步中,我们将对此进行调整以查看其效果。

# fit our vectorizer. This will take a while depending on your computer. from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(max_features = 3000, tokenizer = tokenizer_better)# this could take a while
vect.fit(df_train.TEXT.values)

我们可以看看最常用的词,我们会发现这些词中的许多可能不会为我们的模型增加任何价值。这些词被称为停用词,我们可以用 CountVectorizer 轻松地(如果我们想的话)删除它们。不同的自然语言处理语料库都有常用的停用词列表,但是我们将根据下面的图片来创建自己的停用词列表。

my_stop_words = ['the','and','to','of','was','with','a','on','in','for','name',                 'is','patient','s','he','at','as','or','one','she','his','her','am',                 'were','you','pt','pm','by','be','had','your','this','date',                'from','there','an','that','p','are','have','has','h','but','o',                'namepattern','which','every','also']

如果您愿意,可以随意添加自己的停用词。

from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(max_features = 3000, 
                       tokenizer = tokenizer_better, 
                       stop_words = my_stop_words)
# this could take a while
vect.fit(df_train.TEXT.values)

现在我们可以把笔记转换成数字矩阵。在这一点上,我将只使用训练和验证数据,所以我还不想看它如何在测试数据上工作。

X_train_tf = vect.transform(df_train.TEXT.values)
X_valid_tf = vect.transform(df_valid.TEXT.values)

我们还需要我们的输出标签作为单独的变量

y_train = df_train.OUTPUT_LABEL
y_valid = df_valid.OUTPUT_LABEL

从滚动条的位置可以看出……和往常一样,为预测模型准备数据需要花费 80%的时间。

第三步:建立一个简单的预测模型

我们现在可以建立一个简单的预测模型,该模型利用我们的词汇输入,预测患者是否会在 30 天内再次入院(是= 1,否= 0)。

这里我们将使用逻辑回归模型。逻辑回归是 NLP 任务的一个很好的基线模型,因为它可以很好地处理稀疏矩阵并且是可解释的。我们有一些额外的选择(称为超参数),包括 C 和 penalty,C 是正则化系数,penalty 告诉我们如何测量正则化。正则化本质上是一种试图最小化过度拟合的技术。

# logistic regression
from sklearn.linear_model import LogisticRegression
clf=LogisticRegression(C = 0.0001, penalty = 'l2', random_state = 42)
clf.fit(X_train_tf, y_train)

我们可以用拟合的模型计算每个样本的再入院概率

model = clf
y_train_preds = model.predict_proba(X_train_tf)[:,1]
y_valid_preds = model.predict_proba(X_valid_tf)[:,1]

步骤 4:评估模型的质量

在这一点上,我们需要衡量我们的模型表现如何。有几种不同的数据科学性能指标。如果你感兴趣,我写了另一篇博文详细解释了这些。由于这篇文章很长,我将开始展示结果和数据。您可以查看 github 帐户中生成这些数字的代码。

对于预测为阳性的阈值 0.5,我们得到以下性能

对于当前选择的超参数,我们确实有一些过度拟合。需要指出的一点是,两组数据的精度之间的主要差异是由于我们平衡了训练集,而验证集是原始分布。目前,如果我们列出一份预计会再次入院的患者名单,我们会发现他们是我们随机选择患者的两倍(精确度与患病率)。

上面没有显示的另一个性能指标是 AUC 或 ROC 曲线下面积。我们当前模型的 ROC 曲线如下所示。实际上,ROC 曲线允许您在改变您定义的预测阳性与预测阴性的阈值时,看到真阳性率和假阳性率之间的权衡。

步骤 5:改进模型的后续步骤

此时,您可能想在测试集上计算性能,看看自己做得如何。但是等等!我们做了许多选择(下面是几个),我们可以改变这些选择,看看是否有改进:

  • 我们应该花时间获取更多数据吗?
  • 如何标记—我们应该使用词干吗?
  • 如何向量化—我们应该改变字数吗?
  • 如何正则化逻辑回归——我们应该改变 C 还是惩罚?
  • 用哪个型号?

当我试图改进我的模型时,我阅读了许多其他博客帖子和文章,以了解人们如何解决类似的问题。当你这样做的时候,你开始看到可视化数据的有趣方式,我强烈推荐你在自己的项目中坚持使用这些技术。

对于使用 BOW+逻辑回归的 NLP 项目,我们可以绘制最重要的单词,看看我们是否可以获得任何洞察力。对于这一步,我借用了洞察数据科学的篇不错的 NLP 文章中的代码。当你看最重要的单词时,我看到两件直接的事情:

  • 哎呀!我忘了排除那些因为‘过期’出现在负面清单中而死亡的病人。目前,我将忽略这一点,并在下面修复它。
  • 还有一些我们可能应该删除的其他停用词('应该','如果','它','一直','谁','期间',' x ')

当我们想要改进模型时,我们希望以数据驱动的方式进行。你可以花很多时间在“预感”上,那不会以失败告终。要做到这一点,建议选择一个用于决策单一性能指标。对于这个项目,我将选择 AUC。

对于上面的第一个问题,我们可以绘制一条学习曲线来了解添加更多数据的影响。吴恩达有一套很棒的 Coursera 课程,讨论高偏差和高方差模型。

first learning curve with C = 0.0001

我们可以看到,我们有一些过度拟合,但添加更多的数据可能不会大幅改变验证集的 AUC。知道这一点很好,因为这意味着我们不应该花几个月的时间来获取更多的数据。

我们可以做的一些简单的事情是尝试看看我们的一些超参数(max_featuresC)的影响。我们可以运行网格搜索,但是因为我们这里只有两个参数,我们可以分别查看它们,看看效果。

Effect of C

Effect of max_features

我们可以看到,增加 C 和 max_features 会导致模型很快过度拟合。我选择 C = 0.0001,max_features = 3000,此时验证集开始趋于平稳。

在这一点上,你可以尝试一些其他的事情

  • 将子采样改为过采样
  • 向记号赋予器添加词干或词汇化
  • 测试几种不同的 sci-kit 学习模型
  • 连接所有的注释,而不是最后的出院小结
  • 尝试 LSTMs 等深度学习方法
  • 查看您认为错误的出院总结

步骤 6:完成你的模型并测试它

我们现在将使用超参数选择来拟合我们的最终模型。我们也将排除死于再平衡的患者。

rows_not_death = df_adm_notes_clean.DEATHTIME.isnull()df_adm_notes_not_death = df_adm_notes_clean.loc[rows_not_death].copy()
df_adm_notes_not_death = df_adm_notes_not_death.sample(n = len(df_adm_notes_not_death), random_state = 42)
df_adm_notes_not_death = df_adm_notes_not_death.reset_index(drop = True)# Save 30% of the data as validation and test data 
df_valid_test=df_adm_notes_not_death.sample(frac=0.30,random_state=42)df_test = df_valid_test.sample(frac = 0.5, random_state = 42)
df_valid = df_valid_test.drop(df_test.index)# use the rest of the data as training data
df_train_all=df_adm_notes_not_death.drop(df_valid_test.index)assert len(df_adm_notes_not_death) == (len(df_test)+len(df_valid)+len(df_train_all)),'math didnt work'# split the training data into positive and negative
rows_pos = df_train_all.OUTPUT_LABEL == 1
df_train_pos = df_train_all.loc[rows_pos]
df_train_neg = df_train_all.loc[~rows_pos]# merge the balanced data
df_train = pd.concat([df_train_pos, df_train_neg.sample(n = len(df_train_pos), random_state = 42)],axis = 0)# shuffle the order of training samples 
df_train = df_train.sample(n = len(df_train), random_state = 42).reset_index(drop = True)# preprocess the text to deal with known issues
df_train = preprocess_text(df_train)
df_valid = preprocess_text(df_valid)
df_test = preprocess_text(df_test)
my_new_stop_words = ['the','and','to','of','was','with','a','on','in','for','name',              'is','patient','s','he','at','as','or','one','she','his','her','am',                 'were','you','pt','pm','by','be','had','your','this','date',                'from','there','an','that','p','are','have','has','h','but','o',                'namepattern','which','every','also','should','if','it','been','who','during', 'x']from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer(lowercase = True, max_features = 3000, 
                       tokenizer = tokenizer_better,
                      stop_words = my_new_stop_words)# fit the vectorizer
vect.fit(df_train.TEXT.values)X_train_tf = vect.transform(df_train.TEXT.values)
X_valid_tf = vect.transform(df_valid.TEXT.values)
X_test_tf = vect.transform(df_test.TEXT.values)y_train = df_train.OUTPUT_LABEL
y_valid = df_valid.OUTPUT_LABEL
y_test = df_test.OUTPUT_LABELfrom sklearn.linear_model import LogisticRegressionclf=LogisticRegression(C = 0.0001, penalty = 'l2', random_state = 42)
clf.fit(X_train_tf, y_train)model = clf
y_train_preds = model.predict_proba(X_train_tf)[:,1]
y_valid_preds = model.predict_proba(X_valid_tf)[:,1]
y_test_preds = model.predict_proba(X_test_tf)[:,1]

这会产生以下结果和 ROC 曲线。

结论

恭喜你!你建立了一个简单的 NLP 模型(AUC = 0.70)来预测基于医院出院总结的再入院,这个模型仅比使用所有医院数据的最先进的深度学习方法(AUC = 0.75)稍差。如果你有任何反馈,请在下面留下。

如果你对医疗保健领域的深度学习 NLP 感兴趣,我推荐阅读 https://arxiv.org/abs/1711.10663的 Erin Craig 的文章

参考

利用电子健康记录进行可扩展和精确的深度学习。拉杰科马尔 A,柳文欢 E,陈 K,等数字医学(2018)。DOI:10.1038/s 41746–018–0029–1。地点:【https://www.nature.com/articles/s41746-018-0029-1

MIMIC-III,一个免费的重症监护数据库。Johnson AEW,Pollard TJ,Shen L,Lehman L,Feng M,Ghassemi M,Moody B,Szolovits P,LA 和 Mark RG。科学数据(2016)。DOI: 10.1038/sdata.2016.35 可在:http://www.nature.com/articles/sdata201635获得

机器学习中的数据预处理导论

原文:https://towardsdatascience.com/introduction-to-data-preprocessing-in-machine-learning-a9fa83a5dc9d?source=collection_archive---------0-----------------------

数据预处理初学者指南

Photo by Markus Spiske on Unsplash

数据预处理是机器学习中不可或缺的一步,因为数据的质量和从中获得的有用信息会直接影响模型的学习能力;因此,在将数据输入模型之前,对数据进行预处理是非常重要的。

我将在本文中介绍的概念是-

  1. 处理空值
  2. 标准化
  3. 处理分类变量
  4. 一键编码
  5. 多重共线性

您可以获得完整的代码(。ipynb) 这里

处理空值—

在任何真实世界的数据集中,总是很少有空值。无论是回归、分类还是任何其他类型的问题,都没有关系,没有模型能够独自处理这些 NULL 或 NaN 值,因此我们需要干预。

在 python 中,NULL 用 NaN 表示。所以不要混淆这两者,它们可以互换使用。

首先,我们需要检查我们的数据集中是否有空值。我们可以使用 isnull()方法来实现。

df.isnull()      
# Returns a boolean matrix, if the value is NaN then True otherwise Falsedf.isnull().sum() 
# Returns the column names along with the number of NaN values in that particular column

我们有各种方法来处理这个问题。解决这个问题最简单的方法是删除包含空值的行或列。

df.dropna()

dropna()接受各种参数,比如—

  1. axis —如果要删除行,我们可以指定 axis = 0;如果要删除列,我们可以指定 axis=1。
  2. how —如果我们指定 how = 'all ',那么只有当所有值都是 NaN 时,才会删除行和列。默认情况下,how 设置为“any”。
  3. thresh——它确定阈值,因此如果我们指定 thresh=5,那么具有少于 5 个实数值的行将被丢弃。
  4. subset-如果我们有 4 列 A、B、C 和 D,那么如果我们指定 subset=['C'],那么只有 C 值为 NaN 的行将被删除。
  5. 就地-默认情况下,不会对数据框进行任何更改。因此,如果您希望这些更改反映到您的数据帧中,那么您需要使用 inplace = True。

但是,从数据集中删除行和列并不是最佳选择,因为这会导致大量信息丢失。如果您有 300,000 个数据点,那么删除 2-3 行不会对您的数据集产生太大影响,但是如果您只有 100 个数据点,并且其中 20 个数据点对于特定字段具有 NaN 值,那么您不能简单地删除这些行。在现实世界的数据集中,某个特定字段有大量 NaN 值的情况经常发生。

例如,假设我们从调查中收集数据,那么可能会有一个可选字段,假设 20%的人留为空白。因此,当我们获得数据集时,我们需要了解剩余的 80%的数据仍然是有用的,因此,与其丢弃这些值,我们需要以某种方式替换缺失的 20%的值。我们可以在插补的帮助下做到这一点。

插补—

插补就是简单地替换我们数据集缺失值的过程。我们可以通过定义我们自己的定制函数来实现这一点,或者我们可以通过使用 sklearn 提供的simple imputr类来简单地执行插补。

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
imputer = imputer.fit(df[['Weight']])
df['Weight'] = imputer.transform(df[['Weight']])

。这里使用的值返回数据帧的 numpy 表示。
仅返回数据框中的值,轴标签将被移除。

标准化—

这是另一个完整的预处理步骤。在标准化中,我们转换我们的值,使平均值为 0,标准差为 1。

Image by author

考虑上面的数据帧,这里我们有 2 个数值:年龄体重。因为年龄是以年为单位,体重是以公斤为单位,所以它们不在一个等级上,因为体重更有可能大于年龄;因此,我们的模型将赋予权重更多的权重,这不是理想的情况,因为年龄也是一个不可或缺的因素。为了避免这个问题,我们执行标准化。

Image by author

简单来说,我们只需计算这些值的平均值和标准差,然后对于每个数据点,我们只需减去平均值,然后除以标准差。

示例—

考虑数据帧 1 中的列年龄。为了标准化该列,我们需要计算平均值和标准偏差,然后我们将使用上述公式转换每个年龄值。

我们不需要手动完成这个过程,因为 sklearn 提供了一个名为 StandardScaler 的函数。

from sklearn.preprocessing import StandardScaler
std = StandardScaler()
X = std.fit_transform(df[['Age','Weight']])

这里需要注意的重要一点是,我们需要标准化训练和测试数据。

  • fit_transform 相当于先使用 fit,再使用 transform。
  • fit 函数计算平均值和标准差,transform 函数实际上标准化数据集,我们可以使用 fit_transform 函数在一行代码中完成此过程。

这里要注意的另一件重要的事情是,当处理测试数据时,我们将只使用 transform 方法。

处理分类变量—

处理分类变量是机器学习的另一个重要方面。分类变量基本上是离散而非连续的变量。例如,商品的颜色是一个离散变量,而价格是一个连续变量。

分类变量进一步分为两种类型—

  • 有序分类变量 —这些变量可以排序。ex——T 恤衫的尺寸。我们可以说 M < L < XL。
  • 名义分类变量 —这些变量不能排序。前——t 恤的颜色。我们不能说蓝色是绿色,因为比较这两种颜色没有任何意义,因为它们没有任何关系。

这里需要注意的重要一点是,我们需要不同地预处理序数和名词性分类变量。

处理有序分类变量—

首先,我们需要创建一个数据框架。

df_cat = pd.DataFrame(data = 
                     [['green','M',10.1,'class1'],
                      ['blue','L',20.1,'class2'],
                      ['white','M',30.1,'class1']])
df_cat.columns = ['color','size','price','classlabel']

这里,列“size”和“classlabel”是顺序分类变量,而“color”是名义分类变量。

有两个非常简单和整洁的技术来转换顺序 cv。

  1. 使用 map()函数—
size_mapping = {'M':1,'L':2}
df_cat['size'] = df_cat['size'].map(size_mapping)

这里 M 将用 1 代替,L 用 2 代替。

2.使用标签编码器—

from sklearn.preprocessing import LabelEncoder
class_le = LabelEncoder()
df_cat['classlabel'] =
class_le.fit_transform(df_cat['classlabel'].values)

这里,class1 用 0 表示,class2 用 1 表示。

处理名词性分类变量的方式不正确—

大多数人犯的最大错误是他们无法区分序数型和名义型简历。因此,如果您对名义变量使用相同的 map()函数或 LabelEncoder,那么模型将认为名义变量之间存在某种关系。

所以如果我们使用 map()来映射颜色,就像-

col_mapping = {'Blue':1,'Green':2}

然后根据模型,绿色>蓝色,这是一个毫无意义的假设,模型会给出考虑这种关系的结果。所以,虽然你会用这种方法得到结果,但它们不会是最佳的。

处理名义分类变量的正确方法—

处理名义 cv 的正确方法是使用一键编码。使用独热编码最简单的方法是使用 get_dummies()函数。

df_cat = pd.get_dummies(df_cat[['color','size','price']])

在这里,我们传递了“size”和“price”以及“color ”,但是 get_dummies()函数非常聪明,它将只考虑字符串变量。所以它只是转换“颜色”变量。

现在,你一定想知道这到底是什么一次性编码。所以让我们试着去理解它。

一键编码—

因此,在一键编码中,我们主要做的是创建“n”列,其中 n 是名义变量可以接受的唯一值的数量。

例如,在这里,如果颜色可以是蓝色、绿色和白色,那么我们将只创建三个新列,即颜色 _ 蓝色、颜色 _ 绿色和颜色 _ 白色,如果颜色是绿色,那么颜色 _ 蓝色和颜色 _ 白色列的值将是 0,颜色 _ 绿色列的值将是 1。

因此,在 n 列中,只有一列的值为 1,其余的列的值都为 0。

一键编码是一个非常酷和简洁的技术,但是只有一个问题与之相关,那就是多重共线性。因为你们一定都认为这是一个相当沉重的词,所以一定很难理解,所以让我来验证一下你们新形成的信念。多重共线性确实是一个有点棘手但极其重要的统计学概念。这里的好处是,我们不需要真正理解多重共线性的所有本质细节,我们只需要关注它将如何影响我们的模型。因此,让我们深入了解多重共线性的概念,以及它将如何影响我们的模型。

多重共线性及其影响—

当我们的数据集中存在彼此高度依赖的要素时,就会出现多重共线性。在这种情况下,我们有一些特征-

color_blue,color_green 和 color_white,这些都是相互依赖的,并且会影响我们的模型。

如果数据集存在多重共线性,则无法使用权重向量来计算特征重要性。

多重共线性会影响我们模型的可解释性。

我认为,在机器学习的背景下,这些信息已经足够了。但是,如果您仍然不相信,您可以访问下面的链接,了解与多重共线性相关的数学和逻辑。

[## 12.1 -什么是多重共线性?| STAT 501

如课程概述中所述,只要回归模型中有两个或多个预测因子,就存在多重共线性…

newonlinecourses.science.psu.edu](https://newonlinecourses.science.psu.edu/stat501/node/344/)

现在,我们已经了解了多重共线性的含义,接下来让我们尝试了解如何识别它。

  • 识别多重共线性的最简单方法是绘制一对图,您可以观察不同要素之间的关系。如果两个要素之间存在线性关系,则它们之间存在强相关性,并且数据集中存在多重共线性。

Image by author

此处(体重,BP)与(BSA,BP)密切相关。您也可以使用相关矩阵来检查特征的紧密相关性。

Image by author

我们可以观察到,体重与 BP、BSA 与 BP 之间存在很强的协整关系(0.950)(0.875)。

避免多重共线性的简单技巧-

我们可以使用 drop_first=True 来避免多重共线性问题。

df_cat = pd.get_dummies(df_cat[['color','size','price']],drop_first=True)

这里 drop_first 将删除第一列颜色。所以这里蓝色将被去掉,我们只有绿色和白色。

这里需要注意的重要一点是,我们不会丢失任何信息,因为如果 color_green 和 color_white 都是 0,那么这意味着颜色一定是蓝色的。因此,我们只能借助这两栏来推断全部信息,因此这三栏之间的强相关性被打破了。

说完这些,我们就到了本文的结尾。非常感谢你阅读它。

您可以获得完整的代码()。ipynb) 此处为

如果你愿意,你可以鼓掌。这是免费的。

我的 LinkedIn 、 Twitter 和 Github
你可以登陆我的网站了解更多关于我和我的工作。

德鲁伊介绍,你的大规模互动分析

原文:https://towardsdatascience.com/introduction-to-druid-4bf285b92b5a?source=collection_archive---------3-----------------------

我大约在 2 年前发现了德鲁伊( http://druid.io )。

当时我在 SuperAwesome 工作,我们需要一个解决方案来替换我们现有的基于 Mongo 的报告系统,该系统已经显示出了它的疲态。由于数据基数大,我们的 MongoDB 实现没有很好地扩展,存储成本使我们认为它不是这项工作的最佳工具。

当时,我们每天处理大约 1 亿个事件,我们的一些报告需要 30 秒才能生成。我们目前每天处理数十亿个 事件,大部分时间报告花费不到 1 秒

我们在 MongoDB 中的数据被迁移了。存储在 MongoDB 中的数据使用了大约 60GB 的磁盘空间,当在 Druid 中进行索引时,相同的数据仅代表 600MB 。没错。存储容量减少 100 倍

这篇文章将解释什么是 Druid,为什么你应该关心它,一个关于它如何工作的高级概述,以及一些关于如何开始和实现不到 1 秒的查询时间的信息!

德鲁伊?那是电子游戏吗?

不。但这并不能说明它是 WoW 中的一个类;这使得有时很难找到资源。

为了描述德鲁伊,我只是引用他们的网站:

Apache Druid(孵化)是一个用于事件驱动数据的高性能分析数据存储。德鲁伊的核心设计结合了来自【OLAP】/分析数据库时间系列数据库搜索系统 的思想,创建一个统一的运营分析系统。**

Druid according to their website

如果要我用自己的话来描述:

Druid 是一个关于类固醇的实时柱状时间序列数据库,伸缩性非常好。

显然还有其他可用的数据库来存储时间序列数据,但这不是本文的目的。我只想向你介绍这一个,因为我有这方面的经验,不像其他的。(我当时很快尝试了一下,但我肯定不习惯比较或讨论它们。)

谁在用德鲁伊?我还是第一次听说这件事。

德鲁伊正在被科技市场的一些大玩家使用。druid 网站维护着一份在其架构中使用 Druid 的公司列表。

以下是部分清单:

  • ****元市场:他们创造了德鲁伊来驱动他们的程序报告。
  • ****网飞:监控他们的基础设施。它们每小时摄取大约 2TB。
  • AirBNB :快速获得用户的互动信息。
  • Optimizely : Druid 为优化个性化的结果仪表板提供动力。
  • ****沃尔玛:他们发表了一篇关于他们事件分析流的好文章。
  • 很多其他人…

什么时候应该考虑用德鲁伊?

如果你有以下问题,你应该使用德鲁伊:

  • 要存储的时间序列数据
  • 数据具有较高的基数
  • 您需要能够快速查询这些数据
  • 您想要支持流数据

几个好的用例示例:

  • 数字营销(广告数据)
  • 产品中的用户分析和行为
  • 应用性能管理
  • OLAP 和商业智能)
  • 物联网和设备指标

关于数据存储方式的快速说明

您的数据存储在中。段是不可变的。一旦创建,就不能更新。(您可以创建一个新版本的段,但这意味着要为该期间的所有数据重新编制索引)

Roll-up explained simply

您可以配置如何创建这些段(每天一个,每小时一个,每月一个等等)。您还可以定义段内数据的粒度。如果您知道每小时需要的数据,您可以配置您的段来自动累计数据。

在段内,数据按时间戳、维度和指标存储。

  • ****时间戳:时间戳(是否汇总)
  • 维度**:维度用于拼接或过滤数据。常见维度的几个例子有城市、州、国家、设备 Id、活动 Id、…
  • 指标**:指标是完成的计数器/聚合。sof 指标的几个例子可以是点击量、浏览量、响应时间、…

A druid segment: http://druid.io/docs/latest/design/segments.html

德鲁伊默认支持多种可能的聚合,比如 first、last、doubleSum、longMax、… 也有自定义/实验聚合可用,比如 近似直方图DataSketch ,或者你自己的!您可以轻松地将自己的聚合实现为 Druid 的插件。

你可以在德鲁伊文档中读到更多关于数据如何存储在段内的信息:http://druid.io/docs/latest/design/segments.html

它是如何在引擎盖下工作的?

每个 Druid 安装都是一个集群,需要运行多个组件。Druid 集群可以运行在一台机器上(非常适合开发),或者完全分布在几台到几百台机器上。

Druid Architecture from http://druid.io/docs/latest/design/

让我们首先从 Druid 所需的外部依赖性开始:

  • ****元数据存储:SQL 驱动的数据库,如 PostgreSQL 或 MySQL。它用于存储关于段的信息、一些加载规则,以及保存一些任务信息。Derby 可以用于开发。
  • 动物园管理员:动物园管理员需要在德鲁伊建筑的不同组件之间进行交流。某些类型的节点使用它来向其他节点传输它们的状态和其他信息。
  • ****深度存储:深度存储用于保存所有的分段文件,以便长期保存。支持多种存储,例如 S3、HDFS、本地挂载……其中一些是本地可用的,而另一些则需要安装扩展。

现在让我们来看看在一个 Druid 集群中运行的不同节点类型:

  • ****历史:它们正在加载集群中可用的部分或全部段。然后,他们负责响应对这些段的任何查询。他们不接受任何书写。
  • 中层经理:他们负责索引你的数据,不管是流式的还是批量摄取的。当一个段被索引时,它们还能够响应对这些段的任何查询,直到切换到一个历史节点。
  • ****经纪人:这是查询界面。它处理来自客户端的查询,并将它们分派到托管相关段的相关历史和中间管理器节点。最后,在发送给客户端之前,它会将结果合并回来。
  • ****协调者:协调者在这里管理集群的状态。当需要通过 zookeeper 加载段时,它们会通知历史节点,或者在集群中重新平衡段。
  • 霸主**:负责管理所有的索引任务。他们协调中层管理人员,并确保数据的发布。注意:现在有一种方法可以在与协调器相同的进程中运行霸王。
  • ****路由器(可选):霸王、经纪人、协调人前面的某种 API 网关。正如你可以直接询问这些,我真的不认为有任何必要。

中层管理人员的实时指数化通常与 Kafka 一起运行,但也可以使用其他 fire hose(rabbit MQ,RocketMQ,..)作为扩展。

运行查询时会发生什么?

现在让我们看看当一个查询被发送到代理时会发生什么。

该查询将包含关于间隔(时间段)、维度和所需指标的信息。

1)查询命中代理。代理知道所请求间隔的相关段在哪里(即,需要来自历史节点 A 的 2 个段,来自历史节点 B的 2 个段,并且它还需要来自在中间管理器 A 中发布的当前索引段的数据)。**

2)查询被发送到所有需要的节点(在我们的例子中是历史 A历史 B中间管理者 A )。

3)这些节点中的每一个都将执行请求的聚合,并根据查询拼接数据,然后将结果发送回代理。

4)然后,根据查询,在代理中合并数据,并将其返回给客户端。

由于经纪人中层经理、历史节点的查询接口是一样的(如果你愿意,可以直接向历史节点发送查询。你可能得不到你所期望的所有数据。),调试你的段,或者测试单个历史节点,真的很容易。代理只是发送相同的查询,但是简单地改变请求间隔以从每个其他节点只获得它需要的数据。

限制

即使最好的数据库也有局限性。这就是生活。

其中一些是我在过去两年和德鲁伊一起工作时发现的:

  • 窗口功能,如滚动平均。您必须在自己的 API 中实现它。
  • 不可能连接数据。但是如果你真的有这个用例,你可能做错了。
  • 你可能需要在它前面有某种 API,只是为了将你的 id 重新映射到用户可读的信息。由于数据库主要是附加的,我不会保存某个东西的值,而只是一个引用(活动 id 而不是活动名称,除非您的数据在您的数据库中也是只读的)。有可能直接在德鲁伊里做这个的方法,但是我还没试过。

关于性能和基础设施管理的说明

说实话,德鲁伊是“相当野兽”。根据您拥有的数据量,可能需要一个相当大的基础设施来维持亚秒级的查询时间。

一旦有了更多的数据,您还需要使用进程的配置(堆、CPU、缓存、线程……)。

在我看来,这也是德鲁伊的不足之处。他们还没有任何简单的工具来配置和维护不同的服务器(他们的云产品中有https://imply.io/product,但我还没有尝试过)。你可能需要用 Chef、Ansible、Puppet、Kubernetes 等工具设置自己的工具来实现自动化。

在 SuperAwesome,我们决定使用Kubernetes结合 掌舵 来尽可能自动化我们的德鲁伊部署。如果你喜欢解决那类问题,SuperAwesome正在招聘 全栈工程师 DevOps 工程师 **

我在哪里可以试着学习德鲁伊?

我目前正在编写和编辑一个关于德鲁伊的视频课程。这里有和。确保查看计划并注册,以便在计划上线时得到通知!

你也可以在我的博客上订阅我未来的帖子,因为我可能会谈论更多关于德鲁伊的事情,还会发布关于德鲁伊职业的更新。

与此同时,还有一些其他有趣的链接可供参考:

  • 德鲁伊快速入门:【http://druid.io/docs/latest/tutorials/index.html】T2
  • **关于德鲁伊的演讲/论文列表:【http://druid.io/docs/latest/misc/papers-and-talks.html **
  • 德鲁伊的暗示分布:https://docs.imply.io/on-prem/quickstart

来源

  • http://druid.io/technology
  • http://druid.io/docs/latest/design/

进化算法简介

原文:https://towardsdatascience.com/introduction-to-evolutionary-algorithms-a8594b484ac?source=collection_archive---------0-----------------------

自然选择最优化

Photo by Daniele Levis Pelusi on Unsplash

进化算法是一种基于启发式的方法,用于解决多项式时间内无法轻松解决的问题,例如经典的 NP 难问题,以及其他任何需要太长时间才能彻底处理的问题。当单独使用时,它们通常应用于组合问题;然而,遗传算法经常与其他方法一起使用,作为一种快速的方法,为另一种算法找到某种程度上最佳的开始位置。

假设你熟悉自然选择的过程,那么进化算法(进一步称为 EA )的前提非常简单。一个进化算法包含四个步骤:初始化、选择、遗传算子和终止。这些步骤大致对应于自然选择的一个特定方面,并提供了简单的方法来模块化这种算法类别的实现。简而言之,在进化过程中,更适合的成员会生存和繁殖,而不适合的成员会死去,不会为下一代的基因库做出贡献,就像自然选择一样。

语境

在本文的范围内,我们通常将问题定义为:我们希望找到使某个适应度函数最大化的元素的最佳组合,并且一旦我们已经运行了某个最大迭代次数的算法,或者我们已经达到了某个适应度阈值,我们将接受最终的解决方案。这种场景显然不是使用 EA 的唯一方式,但是它确实包含了离散情况下的许多常见应用程序。

初始化

为了开始我们的算法,我们必须首先创建解的初始群体。群体将包含问题的任意数量的可能解决方案,通常称为成员。它通常是随机创建的(在问题的约束范围内),或者,如果任务的一些先验知识是已知的,大致围绕被认为是理想的东西。群体包含广泛的解决方案是很重要的,因为它本质上代表一个基因库;因此,如果我们希望在算法的过程中探索许多不同的可能性,我们应该致力于让许多不同的基因存在。

选择

一旦群体被创建,群体的成员现在必须根据适应度函数被评估。适应度函数是一种函数,它接受成员的特征,并输出解决方案可行性的数字表示。创建适应度函数通常非常困难,找到一个准确表示数据的好函数非常重要;这是非常具体的问题。现在,我们计算所有成员的适应度,并选择一部分得分最高的成员。

多目标函数

EAs 还可以扩展到使用多种健身功能。这使过程有些复杂,因为当使用多个适应度函数时,我们不是能够识别单个最佳点,而是以一组最佳点结束。最优解的集合被称为帕累托边界,并且包含同样最优的元素,在这个意义上,没有一个解优于边界中的任何其他解。一个决策器随后被用于根据问题的上下文或其他一些度量来缩小单一解决方案的范围。

遗传算子

这一步真的包括两个子步骤:交叉和变异。选择顶级成员(通常是前 2 名,但这个数字可以变化)后,这些成员现在用于在算法中创建下一代。使用被选择的父母的特征,新的孩子被创造出来,它是父母的品质的混合物。根据数据的类型,这样做通常很困难,但通常在组合问题中,可以混合组合并从这些输入中输出有效的组合。现在,我们必须将新的遗传物质引入这一代。如果我们不做这关键的一步,我们将很快陷入局部极值,无法获得最佳结果。这一步是突变,而我们做到这一点,非常简单,通过改变一小部分孩子,使他们不再完美地反映父母的基因子集。突变通常是随机发生的,因为儿童接受突变的机会以及突变的严重程度是由概率分布决定的。

结束

最终,算法必须结束。这通常发生在两种情况下:或者算法已经达到某个最大运行时间,或者算法已经达到某个性能阈值。此时,选择并返回最终解决方案。

例子

现在,为了说明这一过程的结果,我将展示一个 EA 运行的例子。下面的 gif 展示了几代恐龙通过优化身体结构和施加肌肉力量来学习行走。从左到右,世代增加,因此越靠右,行走过程越优化。尽管早期的恐龙不能行走,但 EA 能随时间通过突变和交叉将恐龙进化成能行走的形态。

博弈论导论(第一部分)

原文:https://towardsdatascience.com/introduction-to-game-theory-part-1-1a812d898e84?source=collection_archive---------3-----------------------

两人序贯博弈——优势策略、纳什均衡、合作与背叛

Source

博弈论一般是指对描述逻辑决策者行为的数学模型的研究。它被广泛应用于经济学、政治学、政治学、计算机科学等多个领域,可以用来对很多现实世界的场景进行建模。一般来说,一个游戏指的是这样一种情况,一组玩家中的每一个都有一组可能的选择,其中任何一个玩家的结果部分取决于其他玩家的选择。

同步游戏

博弈论中的一种主要游戏类型是同时游戏,在这种游戏中,两个玩家同时行动(或者如果他们不这样做,后一个玩家不知道前一个玩家的行动,使其有效地成为同时)。连续博弈通常用范式来表示,对于一个有两个玩家并且每个玩家有 N 种可能移动的博弈,它由一个 N x N 矩阵组成,其中每个条目是一个二元组,包含每个玩家的收益。

为了说明这一点,考虑下面的例子。这是一种叫做囚徒困境的顺序游戏,每个囚犯都可以选择要么背叛另一个囚犯以减轻处罚(坦白),要么为另一个囚犯掩饰并希望另一个囚犯也这样做(撒谎)。在矩阵的每个单元中,元组的第一个元素表示囚犯 1 的收益,第二个元素表示囚犯 2 的收益。人们通过首先识别每个玩家将做出的选择(坦白或撒谎)来阅读这个收益矩阵,然后定位对应于该行和列的矩阵条目。例如,如果囚犯 1 选择坦白,囚犯 2 选择撒谎,你可以读取第一行第二列的矩阵条目,给囚犯 1 的收益是 0,给囚犯 2 的收益是-10。

在同时进行的游戏中,每个玩家都必须根据他对另一个玩家会做什么的假设来做决定。请记住,在博弈论中,我们假设玩家是理性的决策者,他们希望自己的收益最大化。预测游戏结果的一种方法是为每个玩家确定优势策略。优势策略是对给定参与人来说最好的策略,不管其他参与人的选择如何,所以不管囚犯 2 做什么,囚犯 1 的优势策略就是囚犯 1 的最优策略。

在囚徒困境博弈中,我们可以观察到双方的优势策略都是坦白。首先,注意这个收益矩阵是对称的,所以每个参与人的每个选择都有相同的收益。这意味着当确定优势策略时,我们只需要考虑一个玩家的优势策略,因为它也将是另一个玩家的优势策略。现在,为了找出一号囚犯(和二号囚犯)的优势策略,我们需要找出一号囚犯在二号囚犯可能的选择中的最佳选择。如果 2 号囚犯选择坦白,1 号囚犯坦白的收益是-8,撒谎的收益是-10,所以他会选择坦白。如果 2 号囚犯选择撒谎,1 号囚犯坦白后收益为 0,撒谎后收益为-1,所以他会再次选择坦白。因此,一号囚犯有一个优势策略,就是总是坦白,因为不管二号囚犯怎么选择,坦白是一号囚犯的最佳选择。同样的分析也适用于囚犯 2 的优势策略。所以在囚徒困境博弈中,两个囚徒最终都会选择坦白。

因此,(坦白,坦白)选项是一个 T2 纳什均衡。纳什均衡是一组选择,在这些选择中,没有人会因为只改变自己的选择而有所收获。既然我们已经知道坦白是两个囚犯的优势策略,我们就已经知道交换对双方都没有好处。因此,由于每个参与人都在使用他的优势策略,那套选择就是纳什均衡。

囚徒困境博弈是一个例子,在这个例子中,两个理性的决策者会选择而不是 合作 ( 缺陷),尽管合作(双方都选择谎言)会给双方带来更好的收益((-8,-8)对(-1,-1))。在这样一个不合作的博弈中,通过选择他们自己的个体优势策略,两个囚犯无法做出实际上是最优的选择。个人的理性策略与社会或全球的最优策略相冲突。一般来说,像囚徒困境这样的同时博弈为我们提供了研究冲突与合作的形式化方法。这种导致缺乏合作的特殊情况出现在几个领域,如政治、经济和生物学。这些例子说明,虽然在许多现实世界的情况下“最好”的选择可能是合作,但作为个体思考的理性参与者会选择不相互合作,因为他们无法信任另一个参与者会合作。

遗传算法简介—包括示例代码

原文:https://towardsdatascience.com/introduction-to-genetic-algorithms-including-example-code-e396e98d8bf3?source=collection_archive---------0-----------------------

遗传算法是一种受查尔斯·达尔文的自然进化理论启发的启发式搜索。这种算法反映了自然选择的过程,即选择最适合的个体进行繁殖,以产生下一代的后代。

自然选择的概念

自然选择的过程始于从群体中选择最适合的个体。他们产生的后代继承了父母的特征,并将被添加到下一代。如果父母有更好的健康状况,他们的后代会比父母更好,有更好的生存机会。这一过程不断迭代,最终会找到具有最适合个体的一代。

这个概念可以应用于搜索问题。我们考虑一个问题的一组解决方案,并从中选择最佳方案。

遗传算法中考虑了五个阶段。

  1. 原始群体
  2. 适应度函数
  3. 选择
  4. 交叉
  5. 变化

原始群体

这个过程从一组被称为群体的个体开始。每个个体都是你想要解决的问题的解决方案。

一个个体由一组被称为基因的参数(变量)来表征。基因连成一串形成染色体(解)。

在遗传算法中,一个个体的基因组用一串字母来表示。通常,使用二进制值(1 和 0 的字符串)。我们说我们在染色体中编码基因。

Population, Chromosomes and Genes

适应度函数

适应度函数决定个体的适应度(个体与其他个体竞争的能力)。它给每个人一个健康分数。一个个体被选择繁殖的概率是基于它的适合度分数。

选择

选择阶段的思路是选择最适的个体,让他们把自己的基因传递给下一代。

两对个体(父母)基于他们的适应性分数被选择。高适合度的个体有更多的机会被选择繁殖。

交叉

交叉是遗传算法中最重要的阶段。对于每对要交配的亲本,从基因中随机选择一个交叉点

例如,假设交叉点为 3,如下所示。

Crossover point

后代是通过在他们之间交换父母的基因来创造的,直到到达交叉点。

Exchanging genes among parents

新的后代被添加到种群中。

New offspring

变化

在某些新形成的后代中,他们的一些基因可能以低随机概率发生突变。这意味着位串中的一些位可以翻转。

Mutation: Before and After

变异的发生是为了保持群体的多样性,防止过早收敛。

结束

如果群体已经收敛(不产生与上一代明显不同的后代),则算法终止。然后说遗传算法为我们的问题提供了一套解决方案。

评论

人口数量是固定的。随着新一代的形成,最不适应的个体死亡,为新的后代提供空间。

这些阶段的顺序被重复,以在每一代中产生比上一代更好的个体。

伪代码

START
Generate the initial population
Compute fitness
REPEAT
    Selection
    Crossover
    Mutation
    Compute fitness
UNTIL population has converged
STOP

Java 实现示例

下面给出了一个遗传算法在 Java 中的实现示例。请随意摆弄代码。

给定一组 5 个基因,每个基因可以保存二进制值 0 和 1 中的一个。

适应值计算为基因组中存在的 1 的数量。如果有五个 1,那么它是最适合的。如果没有 1,那么它有最小的适合度。

这种遗传算法试图最大化适应度函数,以提供由最适合的个体组成的群体,即具有五个 1 的个体。

注意:在这个例子中,在交叉和变异之后,最不适合的个体从新的最适合的后代中被替换。

Sample output where the fittest solution is found in the 32nd generation

编辑

在 mem ento 的【https://github.com/memento/GeneticAlgorithm】查看这一令人敬畏的遗传算法实现,以及每一代基因库的可视化。

非常感谢 mem ento 与我分享这份报告,并让我添加文章的链接。

图像处理简介:构建一个简单的数字识别器

原文:https://towardsdatascience.com/introduction-to-image-processing-building-a-simple-digit-recognizer-b0c74d70d85d?source=collection_archive---------11-----------------------

Photo by Toa Heftiba on Unsplash

它必须从某个地方开始

数字识别并不是什么困难或高级的事情。有点像“你好,世界!”程序——不是很酷,但是你可以从这里开始。所以我决定分享我的工作,同时更新知识——这是我很久以前玩的图像。

数据导入和探索

我们从导入所有必需的包开始。

import pandas as pd
import random
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm%matplotlib inline

包含 2 万个手写数字的 MNIST 数据集是这项任务的“Hello World”数据集,它已经预加载在 Colaboratory(基于云的 Python 笔记本,奇妙的东西 BTW)中,所以我们将使用它。这里不需要发明轮子。

# load data
df = pd.read_csv('sample_data/mnist_train_small.csv', header=None)df.head()Out[7]: 
   0    1    2    3    4    5    6   ...   778  779  780  781  782  
0    6    0    0    0    0    0    0 ...     0    0    0    0    0    
1    5    0    0    0    0    0    0 ...     0    0    0    0    0    
2    7    0    0    0    0    0    0 ...     0    0    0    0    0    
3    9    0    0    0    0    0    0 ...     0    0    0    0    0    
4    5    0    0    0    0    0    0 ...     0    0    0    0    0 
len(df)
Out[9]: 20000

正如我们从 head()方法中看到的,数据集中的第一列包含标签和图像的其余像素 28×28——这就是为什么我们多了 784 列。每次修改后检查数据集的长度也是有用的,以确保我们做的一切都是正确的。

接下来,让我们可视化我们的像素,并观看我们的图像。每次运行下面的代码时,我们都使用 randint()来选择随机图像。此外,我们必须将我们的像素转换为 numpy 数组(现在它的类型是 Series ),并将其调整为 28×28 的大小,以便能够绘制它们。

ix = random.randint(0, len(df)-1)
label, pixels = df.loc[ix][0], df.loc[ix][1:]
img = np.array(pixels).reshape((28,28))
print('label: ' + str(label))
plt.imshow(img)label: 9
<matplotlib.image.AxesImage at 0x7ff9ac6fda20>

数据预处理

现在,为了让我们的生活稍微轻松一点,我们将把我们的数据帧转换成只有两列——标签和图像,其中图像是一个像素的 numpy 数组。此外,我们将减少数据帧的大小,以加快计算速度(首先,我们要确保一切正常,然后我们开始玩模型)

# transforming df for easier manipulation
labels, imgs = [], []
for index, row in df.iterrows():
    label, pixels = row[0], row[1:]
    img = np.array(pixels)
    labels.append(label)
    imgs.append(img)

df2 = pd.DataFrame({'label': labels, 'img': imgs})
df2 = df2[:1000] # checking images using new df structure
ix = random.randint(0, len(df2)-1)
img = df2.loc[ix].img.reshape((28,28))
label = df2.loc[ix].label
print('label: ' + str(label))
plt.imshow(img)label: 9
<matplotlib.image.AxesImage at 0x7ff9a9b997f0>

当我们准备好数据后,我们想把它分成两个数据集:一个用来训练我们的模型,另一个用来测试它的性能。最好的方法是使用 sklearn 。我们设置了一个 test_size=0.2 ,这是该操作的标准值(通常对于测试,我们会留下 20–30%的数据),这意味着对于训练,仍然是 80%。设置 shuffle=True 也是一个很好的做法,因为一些数据集可能有有序的数据,所以模型将学习识别 0 和 1,但不会知道例如 8 的存在。

from sklearn.model_selection import train_test_split
train_df, test_df = train_test_split(df2, test_size=0.2, shuffle=True)print(len(train_df), len(test_df))
800 200train_df.head()Out[12]: 
     label                                                img
296      9  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
488      2  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
124      7  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
862      7  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
421      9  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...

建立模型

我们检查了数据集的长度和头部——都很好,我们可以开始构建我们的模型了。为此,我们需要安装 pytorch 。如果我们转到“代码片段”并开始在那里键入“pyt”,它将显示“安装[pytorch]”,因此我们可以将其插入到我们的笔记本中。如果有人已经安装了 pytorch ,可以跳过这一步。

# http://pytorch.org/
from os.path import exists
from wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag
platform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag())
cuda_output = !ldconfig -p|grep cudart.so|sed -e 's/.*\.\([0-9]*\)\.\([0-9]*\)$/cu\1\2/'
accelerator = cuda_output[0] if exists('/dev/nvidia0') else 'cpu'

!pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.1-{platform}-linux_x86_64.whl torchvision# importing torch and setting up the device
import torch
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")print(device)

接下来,我们必须将数据转换成 pytorch 数据集。torch.utils.data.Dataset是表示数据集的抽象类。自定义数据集应继承数据集并重写以下方法:

  • __len__以便len(dataset)返回数据集的大小。
  • __getitem__支持索引,以便dataset[i]可用于获取其样本
# create torch dataset
from torch.utils.data import Dataset

class MNISTDataset(Dataset):
    def __init__(self, imgs, labels):
        super(MNISTDataset, self).__init__()
        self.imgs = imgs
        self.labels = labels

    def __len__(self):
        return len(self.imgs)

    def __getitem__(self, ix):
        img = self.imgs[ix]
        label = self.labels[ix]
        return torch.from_numpy(img).float(), labeldataset = {
    'train': MNISTDataset(train_df.img.values, train_df.label.values),
    'test': MNISTDataset(test_df.img.values, test_df.label.values)
} 

len(dataset['train'])
800# again checking image, now based on torch dataset
ix = random.randint(0, len(dataset['train'])-1)
img, label = dataset['train'][ix]
print(img.shape, img.dtype)
print(label)
plt.imshow(img.reshape((28,28)))torch.Size([784]) torch.float32
6
<matplotlib.image.AxesImage at 0x7ff99eeeed30>

pytorch 的美妙之处在于它定义模型的简单性。我们用输入和输出定义我们的层,我们添加一些批量标准化来改进我们的模型(这是一种向神经网络中的任何层提供零均值/单位方差输入的技术)和激活函数,在这种情况下 ReLU。

对于第一个输入,我们有 784 个神经元(每个像素一个神经元)和 512 个输出(这个几乎是随机的——我尝试了几个不同的值,这个表现得很好,所以我离开了)。下一层将有 512 个输入(input _ layer[n+1]= = output _ layer[n])和 256 个输出,接下来有 256 个输入和 128 个输出,最后一层有 128 个输入和 10 个输出(每个神经元代表 10 个数字中的一个)

# create model
import torch.nn as nn

def block(in_f, out_f):
  return nn.Sequential(
      nn.Linear(in_f, out_f),
      nn.BatchNorm1d(out_f),
      nn.ReLU(inplace=True),
      #nn.Dropout(),
  )

model = nn.Sequential(
  block(784,512),
  block(512,256),
  block(256,128),
  nn.Linear(128, 10)
)

model.to(device)

现在我们需要为我们的模型创建一些额外的参数:

  • 标准—计算损失函数,在我们的例子中是 CrossEntropyLoss
  • 优化器—设置学习率
  • 调度器——如果模型没有随时间改进,更新学习率(非常强大的技术,允许我们随时调整系统)
  • data loader——py torch 的类,为数据集提供单进程或多进程迭代器
from torch.utils.data import DataLoader
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.1)
scheduler = ReduceLROnPlateau(optimizer, 'max', factor=0.1, patience=3, min_lr=0.0001, verbose=True)

dataloader = {
    'train': DataLoader(dataset['train'], batch_size=32, shuffle=True, num_workers=4),
    'test': DataLoader(dataset['test'], batch_size=32, shuffle=False, num_workers=4),
}

训练和评估模型

有了这些,我们就可以开始训练和评估我们的模型了。虽然我们定义了 100 个时期,但是如果模型没有随着时间的推移而改进,那么停止循环也是有用的。这里我们已经设置了early_stop = 10,所以如果模型连续 10 个纪元没有改变,我们将停止训练过程。

训练过程:我们通过将每个图像和标签分配给先前定义的设备来迭代我们的训练数据,我们给我们的模型一个图像,它试图找到正确的类(preds),我们清除所有梯度(zero_grad())并计算损失函数和梯度(loss),执行优化步骤并将新值附加到total_loss数组。

测试过程:我们迭代测试数据,进行预测,计算模型的损失和准确性。在torch.max()中,我们寻找最大值的索引,因为它将代表一个数字的类别,在我们的例子中,它将匹配标签。然后,通过比较标签和预测,我们计算我们的模型的准确性。

每当我们找到最佳模型时,我们就保存它,如果我们点击early_stop,我们就退出并报告结果。通常它不需要所有的 100 个纪元。

# train
best_acc, stop, early_stop = 0, 0, 10
for e in range(100):

    model.train()
    total_loss = []
    for imgs, labels in tqdm(dataloader['train']):
        imgs, labels = imgs.to(device), labels.to(device)
        preds = model(imgs)
        optimizer.zero_grad()
        loss = criterion(preds, labels)
        loss.backward()
        optimizer.step()
        total_loss.append(loss.data)

    model.eval()
    val_loss, acc = [], 0.
    with torch.no_grad():
        for imgs, labels in tqdm(dataloader['test']):
            imgs, labels = imgs.to(device), labels.to(device)
            preds = model(imgs)
            loss = criterion(preds, labels)
            val_loss.append(loss.data)
            _, preds = torch.max(preds, 1)
            acc += (preds == labels).sum().item()

    acc /= len(dataset['test'])
    if acc > best_acc:
        print('\n Best model ! saved.')
        torch.save(model.state_dict(), 'best_model.pt')
        best_acc = acc
        stop = -1

    stop += 1
    if stop >= early_stop:
        break

    scheduler.step(acc)

    print('\n Epoch {}, Training loss: {:4f}, Val loss: {:4f}, Val acc: {:4f}'.format(
        e + 1, np.array(total_loss).mean(), np.array(val_loss).mean(), acc))

print('\n Best model with acc: {}'.format(best_acc)) Out[n]:
Epoch 30, Training loss: 0.015759, Val loss: 0.397337, Val acc: 0.910000
100%|██████████| 25/25 [00:01<00:00, 22.10it/s]
100%|██████████| 7/7 [00:00<00:00, 73.41it/s]Best model with acc: 0.91

当我们找到我们的最佳模型并保存它时,我们可以通过向它输入新数据来玩它,并观察它的表现。

# test
model.load_state_dict(torch.load('best_model.pt'))
model.to(device)
model.eval()

ix = random.randint(0, len(dataset['test'])-1)
img, label = dataset['test'][ix]
pred = model(img.unsqueeze(0).to(device)).cpu()
pred_label = torch.argmax(pred)
print('Ground Truth: {}, Prediction: {}'.format(label, pred_label))
plt.imshow(img.reshape((28,28)))Ground Truth: 5, Prediction: 5
<matplotlib.image.AxesImage at 0x7ff9a9ced748>

就像一开始说的,这是一个图像识别的“Hello World ”,我们没有使用卷积神经网络,它通常用于这样的任务,只是入门级别的理解流程。我通常不处理图像,所以如果有错误,请告诉我。对我来说,这是一次很好的复习,希望对其他人也有帮助。

你可以在 GitHub 上找到 Python 笔记本的代码

原载于 2018 年 11 月 14 日【sergilehkyi.com】

Python 中使用 Plotly 的交互式时间序列可视化简介

原文:https://towardsdatascience.com/introduction-to-interactive-time-series-visualizations-with-plotly-in-python-d3219eb7a7af?source=collection_archive---------3-----------------------

(Source)

使用强大的 plotly 可视化库启动和运行

总有一天,即使是最喜爱的工具,也有必要放弃。Matplotlib 实现了快速创建简单图表的目的,但我对定制图表或做一些看似简单的事情(如让 x 轴正确显示日期)所需的代码量感到沮丧。

有一段时间,我一直在寻找一个替代方案——不是完全的替代方案,因为 Matplotlib 对探索仍然有用——理想情况下,一个具有交互元素的库,让我专注于我想展示的内容,而不是陷入如何展示它的细节中。进入 plotly ,一个声明式可视化工具,带有一个易于使用的 Python 库用于交互式图形。

在本文中,我们将通过创建基本的时间序列可视化来介绍 plotly 库。这些图表虽然很容易制作,但将是完全交互式的图表,随时可供展示。在这个过程中,我们将学习该库的基本思想,这将使我们能够快速构建令人惊叹的可视化效果。如果你一直在寻找 matplotlib 的替代品,那么正如我们将看到的,plotly 是一个有效的选择。

Interactive Visualization made with a few lines of Plotly code

本文的完整代码在 GitHub 上有。您还可以在 nbviewer 上查看带有交互元素的笔记本。本文中使用的数据是我在 Cortex Building Intelligence 工作时获得的匿名建筑能源时间序列数据。如果你想用你的网络开发技能来帮助建筑节能,那么联系我们,因为我们正在招聘!

Plotly 简介

Plotly 是一家制作可视化工具的公司,包括一个 Python API 库。(Plotly 还制作了 Dash ,一个用 Python 代码构建交互式网络应用的框架)。对于本文,我们将坚持在 Jupyter 笔记本中使用plotly Python 库,并在在线 plotly 编辑器中润色图像。当我们制作一个 plotly 图形时,默认情况下会在网上发布,这使得分享可视化变得容易。

你需要创建一个免费的 plotly 帐户,给你 25 个公共图表和 1 个私人图表。一旦达到配额,您必须删除一些旧图表来制作新图表(或者您可以在离线模式下运行,图像只出现在笔记本中)。安装 plotly ( pip install plotly)并运行以下命令来验证库,替换用户名和 API 密钥:

import plotly# Authenticate with your account
plotly.tools.set_credentials_file(username='########',                                              
                                  api_key='******')

标准 plotly 导入以及离线运行的设置如下:

import plotly.plotly as py
import plotly.graph_objs as go# Offline mode
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)

当我们在离线模式下制作图时,我们会在图像的右下角获得一个链接,以导出到 plotly 在线编辑器进行润色和共享。

Example of image in the notebook with link to edit in plotly.

Plotly 的优势

plotly(Python 库)使用声明式编程,这意味着我们编写代码描述我们想要做什么而不是如何做。我们提供基本框架和最终目标,并让 plotly 指出实现细节。在实践中,这意味着构建一个形象花费的精力更少,使我们能够专注于呈现什么以及如何解释它。

如果你不相信这种方法的好处,那么去看看几十个例子,比如下面的用 50 行代码做的。

US City Populations (Source)

时间序列数据

对于这个项目,我们将使用来自我在Cortex Building Intelligence工作的真实世界建筑数据(数据已经匿名)。由于季节性、每日和每周模式以及天气条件的剧烈影响,建筑能源数据对时间序列分析提出了有趣的挑战。有效地可视化这些数据可以帮助我们了解建筑的反应以及哪里有节能的机会。

(注意,我交替使用术语“功率”和“能量”,尽管能量是做功的能力,而功率是能量消耗的比率。从技术上讲,功率以千瓦(KW)为单位,电能以千瓦时(KWh)为单位。你知道的越多!)

我们的数据在数据帧中,在列上有一个多索引,用于跟踪传感器类型和传感器编号。该索引是一个日期时间:

Time Series Building Data

使用多索引数据框架是完全不同的另一篇文章(这里有文档),但是我们不会做任何太复杂的事情。要访问单个列并绘制它,我们可以执行以下操作。

import pandas as pd # Read in data with two headers
df = pd.read_csv('building_one.csv', header=[0,1], index_col=0)# Extract energy series from multi-index
energy_series = df.loc[:, ('Energy', '3')]# Plot
energy_series.plot()

默认绘图(由 matplotlib 提供)如下所示:

这并不可怕,尤其是对于一行代码来说。但是,没有交互性,视觉上也不够吸引人。是时候进入剧情了。

基本时间序列图

就像散景一样,制作一个基本的情节需要在 plotly 中做更多的工作,但作为回报,我们得到了更多,比如内置的交互性。

我们从一个数据对象开始构建一个图。即使我们想要一个折线图,我们也使用go.Scatter()。Plotly 足够聪明,如果我们超过 20 个点,它会自动给我们一个线图!对于最基本的图形,我们只需要 x 和 y 值:

energy_data = go.Scatter(x=energy_series.index,
                         y=energy_series.values)

然后,我们使用默认设置和一些标题创建一个布局:

layout = go.Layout(title='Energy Plot', xaxis=dict(title='Date'),
                   yaxis=dict(title='(kWh)'))

(我们使用与{'x': 'value'}相同的dict(x = 'value')语法)。

最后,我们可以创建我们的图形,并在笔记本中交互显示它:

fig = go.Figure(data=[energy_data], layout=layout)
py.iplot(fig, sharing='public')

Basic time series plot in plotly

马上,我们有了一个完全交互式的图表。我们可以探索模式,检查单个点,并将绘图下载为图像。请注意,我们甚至不需要指定轴的类型或范围,plotly 为我们做了完全正确的事情。我们甚至不需要额外的工作就可以得到格式良好的悬停消息。

此外,该图会自动导出到 plotly,这意味着我们可以与任何人共享该图表。我们还可以单击“编辑图表”,在在线编辑器中打开它,在一个易于使用的界面中进行我们想要的任何更改:

Online editor interface

如果您在在线编辑器中编辑图表,那么您可以为您创建的精确图表和样式自动生成 Python 代码!

改善情节

即使是 Plotly 中一个基本的时间序列图也令人印象深刻,但我们可以用多几行代码来改进它。例如,假设我们想要比较建筑物的蒸汽使用量和能源。这两个量有非常不同的单位,所以如果我们把它们放在同样的尺度上,就不会有结果。在这种情况下,我们必须使用第二个 y 轴。在 matplotlib 中,这需要大量的格式化工作,但是在 Plotly 中我们可以很容易地做到。

第一步是添加另一个数据源,但是这次指定yaxis='y2'

# Get the steam data
steam_series = df.loc[:, ("Steam", "4")]# Create the steam data object
steam_data = go.Scatter(x=steam_series.index,
                        y=steam_series.values,
                        # Specify axis
                        yaxis='y2')

(我们还添加了一些其他参数来改进样式,这可以在笔记本中看到)。

然后,当我们创建布局时,我们需要添加第二个 y 轴。

layout = go.Layout(height=600, width=800,
                   title='Energy and Steam Plot',
                   # Same x and first y
                   xaxis=dict(title='Date'),
                   yaxis=dict(title='Energy', color='red'),
                   # Add a second yaxis to the right of the plot
                   yaxis2=dict(title='Steam', color='blue',
                               overlaying='y', side='right')
                   )fig = go.Figure(data=[energy_data, steam_data], layout=layout)
py.iplot(fig, sharing='public')

当我们显示图表时,我们在同一张图表上得到蒸汽和能量,轴的比例适当。

通过一点在线编辑,我们得到了一个成品:

Finished plot of energy and steam.

绘图注释

绘图注释用于调出可视化的各个方面以引起注意。例如,我们可以在查看一周的数据时,突出显示每天的高蒸汽消耗量。首先,我们将蒸汽传感器划分为一周(称为steam_series_four)并创建一个格式化的数据对象:

# Data object
steam_data_four = go.Scatter(
                     x=steam_series_four.index,
                     y=steam_series_four.values,
                     line=dict(color='blue', width=1.1),
                     opacity=0.8,
                     name='Steam: Sensor 4',
                     hoverinfo = 'text',
                     text = [f'Sensor 4: {x:.1f} Mlbs/hr' for x in
                             steam_series_four.values])

然后,我们将找到该传感器的每日最大值(代码见笔记本):

为了构建注释,我们将使用 list comprehension 为每个日最大值添加一个注释(four_highs就是上面的系列)。每个注释需要一个位置(xytext):

# Create a list of annotations
four_annotations = [dict(x = date, y = value, 
           xref = 'x', yref = 'y', 
           font=dict(color = 'blue'),
           text = f'{format_date(date)}<br> {value[0]:.1f} Mlbs/hr')
                    for date, value in zip(four_highs.index, 
                                           four_highs.values)]four_annotations[:1]**{'x': Timestamp('2018-02-05 06:30:00'),
  'y': 17.98865890412107,
  'xref': 'x',
  'yref': 'y',
  'font': {'color': 'blue'},
  'text': 'Mon <br> 06:30 AM<br> 18.0 Mlbs/hr'}}**

(文本中的<br>为 html,由 plotly 读取并显示)。

我们可以修改注释的其他参数,但是我们会让 plotly 处理细节。向绘图添加注释就像将它们传递给layout一样简单:

layout = go.Layout(height=800, width=1000, 
                   title='Steam Sensor with Daily High Annotations',
                   annotations=four_annotations)

在在线编辑器中稍作后期处理后,我们最终的剧情是:

Final plot with steam sensor annotations

额外的注释可以通过显示蒸汽使用的每日峰值出现的时间,让我们深入了解我们的数据。反过来,这将允许我们向建筑工程师提出蒸汽启动时间建议。

关于 plotly 最好的部分是,我们可以快速获得一个基本的绘图,并通过多一点代码来扩展功能。当我们想要添加更多的功能时,对基本情节的前期投资是有回报的。

结论

我们只是触及了我们在《T4》中能做的事情的表面。我将在以后的文章中探索其中的一些功能,而参考笔记本了解如何添加更多的交互性,比如选择菜单。最终,我们可以用 Python 代码在 Dash 中构建可部署的 web 应用程序。目前,我们知道如何在 plotly 中创建基本但有效的时间序列可视化。

这些图表为我们的小代码投资提供了很多,通过修改和在线分享这些图表,我们可以构建一个完整的、像样的产品。

尽管我并不是要放弃 matplotlib——单线条形图和折线图很难被击败——但很明显,将 matplotlib 用于自定义图表并不是一个好的时间投资。相反,我们可以使用其他库,包括 plotly,来有效地构建全功能的交互式可视化。在图表中查看数据是数据科学的乐趣之一,但编写代码通常是痛苦的。幸运的是,使用 plotly,Python 中的可视化非常直观,甚至可以愉快地创建和实现图形的目标:直观地理解我们的数据。

一如既往,我欢迎反馈和建设性的批评。可以通过 Twitter @koehrsen_will 或者通过我的个人网站 willk.online 找到我。

机器学习中的 Python 迭代器介绍

原文:https://towardsdatascience.com/introduction-to-iterators-and-generators-in-python-for-data-science-and-machine-learning-bce75e136360?source=collection_archive---------8-----------------------

Ricardo Gomez Angel on Unsplash

从事机器学习和人工智能的人非常依赖 Python 中的迭代器(和生成器)。它们是语言的核心概念,在机器学习包中使用很多,如 scikit-learnKeras 。理解它们是如何工作的以及为什么 Pythonistas 们使用它们会给你带来两个好处:

  1. 你可以更有效地使用它们。
  2. 你可以更快地理解与他们相关的问题。这种理解将为您节省大量的代码编写和调试时间。

我将分两步给你必要的背景知识。首先,我向您介绍一些基本概念,包括一些简单的例子。其次,我将向您介绍来自 scikit-learn 的两个示例性实现。在这一步中,我将向您展示源代码的简化版本。这种方法将让您了解开发人员如何将这些抽象概念转化为现实生活中的工具。

迭代器的一般概念

什么是迭代器?

迭代器是 Python 对象,一次返回一个元素。每次你向迭代器请求下一个项时,它都会调用它的__next__方法。如果有另一个值可用,迭代器将返回它。如果没有,它会引发一个StopIteration异常。

这种行为(只在被要求时返回下一个元素)有两个主要优点:

  1. 迭代器需要更少的内存空间。他们记住了上一个值和到达下一个值的规则,而不是记住一个(可能很长的)序列的每一个元素。
  2. 迭代器不检查它们产生的序列有多长。例如,他们不需要知道一个文件有多少行或者一个文件夹中有多少个文件来遍历它们。

重要的一点是:不要混淆迭代器和可迭代对象。Iterables 是可以通过使用它们的__iter__方法创建迭代器的对象。这就是 Python 在 for-loops 中做的事情:

for classifier in ["XGBoost", "Logistic Regression", "SVM"]:
    if classifier == "XGBoost":
        print(f"{classifier} is the best! Maybe.")
    else:
        print(f"{classifier} is fun. Somehow.")

在内部,Python 调用在in之后提交的任何东西的__iter__方法。然后在 while 循环中对创建的迭代器使用next,直到引发StopIteration异常。你可以在这里找到完整的解释和这里。在 Python 中可以构建多种类型的 for 循环的原因是它们有一个实现的__iter__方法。

Iterables 很方便,但是它们没有“纯”迭代器的优点。例如,你转换成迭代器的链表已经占用了内存。如果可以的话,尽量直接使用迭代器而不是可迭代的。

什么是发电机?

生成器是构建迭代器的一种简化方式。不是实现迭代协议,生成器是用yield语句返回值的函数。yieldreturn的区别在于,生成器会跟踪它们的局部变量。每次生成器到达yield时,都会返回值。然后,它会记住函数中变量的当前状态,并等待下一次调用。

机器学习包中的生成器

我想向您展示两个例子在 scikit-learn 中的实现。不过在 Keras 或者 Tensorflow 中也有例子。如果你想加深理解,我鼓励你去寻找它们。

示例 1: KFold

机器学习的主要挑战之一是避免过度拟合。许多算法都有超参数或修改来解决这个问题,但最重要的概念是交叉验证。对于一个很好的概述,我推荐这篇文章:

[## 在 Python 中训练/测试分割和交叉验证

大家好!在我上一篇关于 Python 中线性回归的文章之后,我认为写一篇文章是很自然的…

towardsdatascience.com](/train-test-split-and-cross-validation-in-python-80b61beca4b6)

在这里,我们正在寻找 K 倍交叉验证。其想法是将数据集分割成多个折叠,并使用每个折叠一次来测试在剩余折叠上训练的模型。例如,如果您使用三个折叠,模型将在其中两个上训练,并使用一个进行测试。

这里使用生成器的原因是,您不必一开始就记住所有的索引组合。知道在相应的回合中测试哪些指数就足够了。其余的将用于培训。

让我们看一下scikit-learn 的KFold 的源代码(第 357 到 434 行)来看看生成器是如何实现的:

class KFold(...):
    def __init__(...):
        ...
    def _iter_test_indices(...):
        ...
        current = 0
        for fold_size in fold_sizes:
            start, stop = current, current + fold_size
            yield indices[start:stop]
            current = stop

靠近类定义的末尾有一个yield语句,表示一个生成器函数。方法的名称_iter_test_indices 表明生成器只产生测试文件夹的索引。正如我之前所写的,训练将在所有其他指数上进行,因此没有必要显式计算它们。

第一次调用生成器时,它从索引 0 ( current=0)开始,加上折叠的大小,得到这个折叠的最后一个索引。然后产生这些指数。下一次,在运行另一轮 for 循环之前,它查找它的局部变量并将current设置为来自上一次迭代的stop的值。

示例 2:梯度增强分类器

梯度提升背后的基本思想是组合足够多的弱学习者来获得强模型。与并行训练许多学习者的 bagging 方法(如 random forest)相反,boosting 以迭代方式工作。它训练一个弱学习者,评估它的主要弱点,并试图在下一轮中弥补它们。

这种算法的迭代特性迫切需要生成器。让我们检查一下GradientBoostingClassifier的源代码,更具体地说是第 1693 到 2156 行。为了简单起见,我们只关注GradientBoostingClassfier类中的一个特定生成器(第 2151 行):

def staged_predict_proba(...):
    ...
    for score in self._staged_decision_function(X):
          yield self.loss_._score_to_proba(score)

我在这里省略了很多代码,但基本思想保持不变。梯度增强阶段是迭代过程中的一个步骤。这个生成器在每一步都监视测试集上的错误。这里使用生成器的原因是,您不必定义该模型的特定实例中有多少个阶段。

摘要

当然,迭代器、可迭代对象和生成器还有很多。我最喜欢的关于迭代器和其他 Python 对象之间关系的博文是 Datacamp 的这篇:

[## Python 迭代器教程

迭代器是 Python 无处不在的灵魂。它们无处不在,你一定在某个节目中见过它们…

www.datacamp.com](https://www.datacamp.com/community/tutorials/python-iterator-tutorial)

我希望这篇博文能帮助你掌握基本思想。我还希望源代码示例能够缩小基本概念和实际实现之间的差距。

感谢阅读!如果你喜欢这篇文章,留下一些吧👏🏻并分享一下!让我知道你在评论和 推特 上的想法。我也很乐意连接上LinkedIn。再次感谢,继续学习!

k 近邻介绍

原文:https://towardsdatascience.com/introduction-to-k-nearest-neighbors-3b534bb11d26?source=collection_archive---------3-----------------------

什么是 k 近邻(kNN),一些有用的应用,以及它是如何工作的

k-最近邻(kNN) 分类方法是机器学习中最简单的方法之一,也是向你介绍机器学习和分类的一个很好的方式。在最基本的层面上,本质上是通过在训练数据中找到最相似的数据点进行分类,并基于它们的分类做出有根据的猜测。虽然理解和实现起来非常简单,但这种方法已经在许多领域得到了广泛的应用,例如在推荐系统语义搜索异常检测中。

正如我们在任何机器学习问题中需要的那样,我们必须首先找到一种方法将数据点表示为特征向量。特征向量是我们对数据的数学表示,并且由于我们数据的期望特征可能不是固有的数值,因此可能需要预处理和特征工程来创建这些向量。给定具有 N 个独特特征的数据,特征向量将是长度为 N 的向量,其中向量的条目 I 表示特征 I 的数据点的值。因此,每个特征向量可以被认为是 R^N 中的一个点。

现在,与大多数其他分类方法不同,kNN 属于懒惰学习,这意味着在分类之前没有明确的训练阶段。相反,任何概括或抽象数据的尝试都是在分类的基础上进行的。虽然这确实意味着一旦我们有了数据,我们就可以立即开始分类,但这种类型的算法存在一些固有的问题。我们必须能够将整个训练集保存在内存中,除非我们对数据集应用某种类型的约简,并且执行分类在计算上可能是昂贵的,因为算法解析每个分类的所有数据点。由于这些原因,kNN 倾向于在没有很多特征的较小数据集上工作得最好。****

一旦我们形成了我们的训练数据集,它被表示为一个 M x N 矩阵,其中 M 是数据点的数量, N 是特征的数量,我们现在可以开始分类了。对于每个分类查询,kNN 方法的要点是:

**1.** Compute a distance value between the item to be classified and every item in the training data-set**2.** Pick the k closest data points (the items with the k lowest distances)**3.** Conduct a **“majority vote”** among those data points — the dominating classification in that pool is decided as the final classification

在进行分类之前,必须做出两个重要的决定。一个是将要使用的 k 的值;这可以任意决定,或者您可以尝试交叉验证来找到一个最佳值。接下来,也是最复杂的,是将要使用的距离度量

有许多不同的方法来计算距离,因为它是一个相当模糊的概念,并且要使用的适当度量总是由数据集和分类任务来确定。然而,两个流行的是欧几里德距离余弦相似度

欧几里德距离大概是你最熟悉的一个;它本质上是通过从要分类的点中减去训练数据点而获得的向量的幅度。

General formula for Euclidean distance

另一个常见的度量是余弦相似性。余弦相似度不是计算大小,而是使用两个向量之间的方向差异。

General formula for Cosine similarity

选择一个度量标准通常很棘手,最好使用交叉验证来决定,除非您事先有一些明确的见解,可以导致使用一个而不是另一个。例如,对于像单词向量这样的东西,您可能希望使用余弦相似度,因为单词的方向比分量值的大小更有意义。通常,这两种方法会在大致相同的时间内运行,并且会受到高维数据的影响。

在完成上述所有工作并决定一个度量标准后,kNN 算法的结果是一个将 R^N 划分为多个部分的决策边界。每一个部分(下面有明显的颜色)代表分类问题中的一个类别。边界不需要用实际的训练示例来形成,而是使用距离度量和可用的训练点来计算。通过将 R^N 分成(小)块,我们可以计算该区域中假设数据点的最可能类别,因此我们将该块着色为在该类别的区域中。

这些信息是开始实现算法所需要的全部,这样做应该相对简单。当然,有许多方法可以改进这个基本算法。常见的修改包括加权和特定的预处理,以减少计算和减少噪声,例如用于特征提取和维数减少的各种算法。此外,kNN 方法也被用于回归任务,尽管不太常用,其操作方式与通过平均的分类器非常相似。

Kaggle 内核简介

原文:https://towardsdatascience.com/introduction-to-kaggle-kernels-2ad754ebf77?source=collection_archive---------1-----------------------

在《人工智能历险记》的这一集里,你会发现什么是 Kaggle 内核,以及如何开始使用它们。虽然这一集没有爆米花,但我可以保证 Kaggle 内核正在爆开!

Kaggle 是一个进行和分享数据科学的平台。你可能听说过他们的一些比赛,经常有现金奖励。这也是实践数据科学和向社区学习的好地方。

什么是 Kaggle 内核?

Kaggle 内核本质上是浏览器中的 Jupyter 笔记本,可以在你眼前运行,全部免费!让我再说一遍,以防你错过,因为这太神奇了:

Kaggle Kernels 是一个在浏览器中运行 Jupyter 笔记本的免费平台!

这意味着您可以省去设置本地环境的麻烦,并且在世界上任何有互联网连接的地方,您的浏览器中都有一个 Jupyter 笔记本环境。

不仅如此,笔记本电脑的处理能力来自云中的服务器,而不是您的本地机器,因此您可以进行大量的数据科学和机器学习而不会耗尽笔记本电脑的电池!

http://blog.kaggle.com/2017/09/21/product-launch-amped-up-kernels-resources-code-tips-hidden-cells/

Kaggle 最近升级了所有的内核,以拥有更强的计算能力和内存,并将运行一个进程的时间延长到 60 分钟!

好了,我已经滔滔不绝地说了够了。让我们看看它实际上是什么样子。

运行中的内核

一旦我们在kaggle.com创建了一个账户,我们就可以选择一个数据集来玩,并且只需点击几下鼠标就可以运行一个新的内核或笔记本。

我们在中开始的数据集是预加载在该内核的环境中的,因此不需要将数据集推送到机器中,并等待大型数据集通过网络进行复制。

当然,如果您愿意,您仍然可以将额外的文件(最多 1GB)加载到内核中。

在我们的例子中,我们将继续使用fashion-mnist数据集。这是一个包含 10 类服装和配饰的数据集,比如裤子、包、高跟鞋、衬衫等等。有 50k 训练样本,10k 评估样本。让我们探索一下我们的 Kaggle 内核中的数据集。

查看数据集,它以 csv 文件的形式在 Kaggle 上提供。原始数据是 28x28 像素的灰度图像,它们在 csv 文件中被展平为 784 个不同的列。该文件还包含一个表示时尚项目的索引(从 0 到 9)的列。

数据加载

由于数据集已经在环境中,并且 pandas 已经加载,让我们用它来读取这些。csv 文件转换成pandas数据帧,一个用于训练,一个用于预测。

Notice that the data is stored in the ‘input’ directory, one level up.

如果你想跟随,我的 Kaggle 内核在这里:https://www.kaggle.com/yufengg/fashion-mnist/

[## 时尚-MNIST

Kaggle 内核使用来自时尚 MNIST 的数据

www.kaggle.com](https://www.kaggle.com/yufengg/fashion-mnist/)

数据探索

既然我们已经将数据加载到 DataFrame 中,我们就可以利用它带来的所有特性,这些特性我们在前面的章节中已经介绍过了。我们将使用head()显示前 5 行,并运行describe()来了解数据集结构的更多信息。

Looks like the dataset is shuffled already

数据可视化

此外,最好将这些图像可视化,这样它们对我们来说就不仅仅是一排排的数字了。让我们用matplotlib来看看这些图片是什么样子的。

这里我们将使用matplotlib.pyplot库,通常导入为plt,将像素值数组显示为图像。

我们可以看到,这些图像虽然模糊,但仍然可以识别出它们所声称的服装和配饰。

Kaggle Kernels 允许我们在一个完全交互式的笔记本环境中工作,几乎不需要任何设置,我想强调的是,我们不需要进行任何 python 环境配置或安装库,这真的很酷!

你可以在这里看到完整的内核:https://www.kaggle.com/yufengg/fashion-mnist/

[## 时尚-MNIST

Kaggle 内核使用来自时尚 MNIST 的数据

www.kaggle.com](https://www.kaggle.com/yufengg/fashion-mnist/)

你已经使用 Kaggle 内核了吗?你最喜欢的功能、技巧和诀窍是什么?

感谢阅读本集云 AI 冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注 Medium 上的me或订阅 YouTube 频道来观看未来的剧集。更多剧集即将推出!

Python 中的线性回归简介

原文:https://towardsdatascience.com/introduction-to-linear-regression-in-python-c12a072bedf0?source=collection_archive---------0-----------------------

如何用 Python statsmodels & scikit-learn libraries.实现线性回归的快速教程

Example linear regression model using simulated data

线性回归是一种基本的预测分析技术,使用历史数据来预测输出变量。它在预测建模中很受欢迎,因为它容易理解,可以用简单的英语解释。

线性回归模型在一系列行业中有许多实际应用,例如经济学(例如预测增长)、商业(例如预测产品销售、员工绩效)、社会科学(例如从性别或种族预测政治倾向)、医疗保健(例如从体重预测血压水平、从生物因素预测疾病发作)等等。

了解如何实现线性回归模型可以挖掘数据中的故事来解决重要问题。我们将使用 Python,因为它是处理和建模数据的强大工具。它有一系列用于线性回归建模的软件包。

基本的想法是,如果我们可以用一个线性回归模型来拟合观察到的数据,那么我们就可以用这个模型来预测任何未来的值。例如,假设我们从历史数据中发现,房子的价格( P )与房子的大小( S )呈线性相关——事实上,我们发现房子的价格正好是其大小的 90 倍。该等式将如下所示:

P = 90S*

有了这个模型,我们就可以预测任何房子的价格。如果我们有一栋 1500 平方英尺的房子,我们可以计算出它的价格:

P = 90 * 1500 = 135000 美元

在这篇博文中,我们涵盖了:

  1. 模型背后的基本概念和数学
  2. 如何使用模拟数据从头实现线性回归
  3. 如何用statsmodels实现线性回归
  4. 如何使用scikit-learn实现线性回归

这篇简短的教程改编自下一期 XYZPython 线性回归课程,其中包括浏览器内沙盒环境、要完成的任务以及使用公共数据集的项目。

基本概念和数学

线性回归模型中有两种变量:

  • 输入预测变量是帮助预测输出变量值的变量。就是俗称的 X
  • 输出变量是我们想要预测的变量。俗称 Y

为了使用线性回归估计 Y ,我们假设等式:

Yₑ = α + β X

其中 Y ₑ是基于我们的线性方程的 Y 的估计值或预测值。

我们的目标是找到使 YY ₑ.之间的差异最小化的参数 αβ 的统计显著值

如果我们能够确定这两个参数的最佳值,那么我们将有最佳拟合的线,我们可以用它来预测 Y 的值,给定 X 的值。

那么,我们如何估算 αβ ?我们可以用一种叫做 普通最小二乘法 的方法。

普通最小二乘法

Green lines show the difference between actual values Y and estimate values Y

最小二乘法的目的是找到使 YY ₑ.之间的平方差之和最小的 αβ 的值这里我们不进行推导,但是使用微积分我们可以表明未知参数的值如下:

其中 X 值的平均值,而ȳY 值的平均值。

如果你熟悉统计学,你可能会把 β 简单地理解为
Cov(X,Y) / Var(X)。

从头开始线性回归

在本文中,我们将使用两个 Python 模块:

  • [statsmodels](https://www.statsmodels.org/stable/index.html) —一个模块,为许多不同的统计模型的估计,以及进行统计测试和统计数据探索提供类和函数。
  • [scikit-learn](http://scikit-learn.org/stable/) —为数据挖掘和数据分析提供简单高效工具的模块。

在我们开始之前,了解如何从头开始实现这个模型是很有用的。了解包在幕后是如何工作的是很重要的,所以你不能只是盲目地实现模型。

首先,让我们模拟一些数据,看看预测值( Y ₑ)与实际值( Y )有何不同:

如果运行上述代码(例如,在 Jupyter 笔记本中),将会输出如下内容:

为了使用 OLS 方法估计 y ,我们需要计算xmeanymeanXy ( xycov)的协方差以及 X ( xvar)的方差,然后才能确定alphabeta的值。

**Out:**
alpha = 2.0031670124623426
beta = 0.32293968670927636

太好了,我们现在有了对alphabeta的估计!我们的模型可以写成 Yₑ = 2.003 + 0.323 X,我们可以做出预测:

**Out:**
array([3.91178282, 2.81064315, 3.27775989, 4.29675991, 3.99534802,
       1.69857201, 3.25462968, 2.36537842, 2.40424288, 2.81907292,
       ...
       2.16207195, 3.47451661, 2.65572718, 3.2760653 , 2.77528867,
       3.05802784, 2.49605373, 3.92939769, 2.59003892, 2.81212234])

让我们对照y的实际值绘制我们的预测ypred,以便更好地直观理解我们的模型。

蓝线是我们的最佳拟合线, Yₑ = 2.003 + 0.323 X. 从这个图中我们可以看出, Xy 之间存在正的线性关系。使用我们的模型,我们可以从 X 的任何值预测 y

例如,如果我们有一个值 X = 10 ,我们可以预测:
yₑ= 2.003+0.323(10)= 5.233。

statsmodels进行线性回归

既然我们已经从头开始学习了如何实现线性回归模型,我们将讨论如何使用statsmodels库中的ols方法。

为了演示这种方法,我们将使用一个非常受欢迎的advertising数据集,该数据集是关于不同媒体的广告费用以及特定产品的销售额。你可以在这里下载这个数据集。

在本例中,我们将只关注TV变量——我们将探究电视广告支出是否能预测产品的销售数量。让我们从使用read_csv()将这个 csv 文件作为pandas数据帧导入开始:

首先,我们使用statsmodels ' ols函数初始化我们的简单线性回归模型。这采用公式y ~ X,其中X是预测变量(TV广告成本)y是输出变量(Sales)。然后,我们通过调用 OLS 对象的fit()方法来拟合模型。

我们不再需要自己计算alphabeta,因为这种方法会自动为我们计算!调用model.params会显示模型的参数:

**Out:**
Intercept    7.032594
TV           0.047537
dtype: float64

在我们一直使用的符号中, α 是截距, β 是斜率,即 α = 7.032, β = 0.047。

因此,模型的等式将是: *销售= 7.032+0.047 电视

简单地说,这意味着平均来说,如果我们在电视广告上花了 100 美元,我们应该可以卖出 11.73 台。

现在我们已经拟合了一个简单的回归模型,我们可以尝试使用.predict方法根据我们刚刚推导出的公式来预测销售额。

我们还可以通过绘制sales_pred与电视广告成本的对比图来可视化我们的回归模型,以找到最佳拟合线:

我们可以看到,电视广告成本和销售额之间存在正线性关系——换句话说,在电视广告上花费更多预测了更高的销售额!

有了这个模型,我们可以从电视广告的任何花费中预测销售额。例如,如果我们将电视广告费用增加到 400 美元,我们可以预测销售量将增加到 26 台:

**Out:**
0    26.04725
dtype: float64

scikit-learn进行线性回归

我们已经学会了使用statsmodels实现线性回归模型…现在让我们学习使用scikit-learn来实现它!

对于这个模型,我们将继续使用advertising数据集,但这次我们将使用两个预测变量来创建一个多元线性回归模型。这是一个简单的线性回归模型,有一个以上的预测值,建模如下:

Yₑ = α + β₁X₁ + β₂X₂ + … + βₚXₚ, 其中 p 为预测数。

在我们的例子中,我们将使用变量TVRadio预测Sales,即我们的模型可以写成:

销售额= α + β₁TV + β₂Radio.

首先,我们初始化我们的线性回归模型,然后将模型拟合到我们的预测值和输出变量:

同样,我们不需要自己计算alphabetas的值——我们只需要为alpha调用.intercept_,为带有系数beta1beta2的数组调用.coef_:

**Out:**
alpha = 2.921099912405138
betas = [0.04575482 0.18799423]

因此,我们的模型可以写成:

*销量= 2.921+0.046 *电视+0.1880 收音机。

我们可以通过简单地使用.predict()来预测值:

**Out:**
array([20.555464, 12.345362, 12.337017, 17.617115, 13.223908,
       12.512084, 11.718212, 12.105515,  3.709379, 12.551696,
       ...
       12.454977,  8.405926,  4.478859, 18.448760, 16.4631902,
        5.364512,  8.152375, 12.768048, 23.792922, 15.15754285])

既然我们已经将多元线性回归模型拟合到我们的数据中,我们就可以根据电视和广播广告成本的任何组合来预测销售额了!例如,如果我们想知道,如果我们在电视广告上投资 300 美元,在广播广告上投资 200 美元,我们会取得多少销售额……我们所要做的就是输入这些数值!

**Out:**
[54.24638977]

这意味着,如果我们在电视广告上花 300 美元,在广播广告上花 200 美元,我们预计平均会卖出 54 台。

我希望你喜欢这个关于线性回归基础的简短教程!

我们讲述了如何在 Python 中使用statsmodelsscikit-learn来实现线性回归。在实践中,您必须知道如何验证您的模型和测量功效,如何为您的模型选择重要变量,如何处理分类变量,以及何时以及如何执行非线性转换。

我们有涵盖所有这些主题的完整课程(甚至更多!)这里在下一届 XYZ,如果你有兴趣学习更多关于 Python 线性回归的知识!

机器学习算法简介:线性回归

原文:https://towardsdatascience.com/introduction-to-machine-learning-algorithms-linear-regression-14c4e325882a?source=collection_archive---------0-----------------------

从头开始构建您自己的模型

人工智能最近变得流行起来。不同学科的人都在尝试应用人工智能来简化他们的任务。例如,经济学家正在使用人工智能预测未来的市场价格以获取利润,医生使用人工智能对肿瘤进行分类,气象学家使用人工智能预测天气,人力资源招聘人员使用人工智能检查申请人的简历以验证申请人是否符合工作的最低标准,等等。人工智能这种无处不在的使用背后的推动力是机器学习算法。对于任何想学习最大似然算法但还没有涉足的人来说,你来对地方了。每个机器学习爱好者开始使用的基本算法是线性回归算法。因此,我们将做同样的事情,因为它为我们建立和学习其他 ML 算法提供了一个基础。

什么是线性回归??

在了解什么是线性回归之前,让我们习惯于回归。回归是一种基于独立预测值对目标值建模的方法。这种方法主要用于预测和找出变量之间的因果关系。回归技术的主要区别在于自变量的数量以及自变量和因变量之间的关系类型。

Linear Regression

简单线性回归是一种回归分析,其中自变量的数量为 1,自变量(x)和因变量(y)之间存在线性关系。上图中的红线被称为最佳拟合直线。根据给定的数据点,我们试图绘制一条线,最好地模拟这些点。该线可以基于如下所示的线性方程进行建模。

y = a_0 + a_1 * x      ## Linear Equation

线性回归算法的目的是找到 A0 和 a1 的最佳值。在继续讨论算法之前,让我们先来看看两个重要的概念,为了更好地理解线性回归,你必须知道这两个概念。

价值函数

成本函数帮助我们计算出 a_0 和 a_1 的最佳可能值,这将为数据点提供最佳拟合线。因为我们想要 a_0 和 a_1 的最佳值,所以我们将这个搜索问题转化为最小化问题,我们希望最小化预测值和实际值之间的误差。

Minimization and Cost Function

我们选择上面的函数来最小化。预测值和地面真实值之间的差异测量误差差。我们对所有数据点的误差差求平方并求和,然后将该值除以数据点的总数。这提供了所有数据点的平均平方误差。因此,该成本函数也被称为均方误差(MSE)函数。现在,使用这个 MSE 函数,我们将改变 a_0 和 a_1 的值,使 MSE 值稳定在最小值。

梯度下降

理解线性回归需要的下一个重要概念是梯度下降。梯度下降是一种更新 A0 和 a1 以降低成本函数(MSE)的方法。想法是我们从 A0 和 a1 的一些值开始,然后我们迭代地改变这些值以降低成本。梯度下降帮助我们了解如何改变这些值。

Gradient Descent

打个比方,想象一个 U 形的坑,你站在坑的最高点,你的目标是到达坑的底部。有一个难题,你只能走不连续的几步才能到达底部。如果你决定一次迈出一步,你最终会到达深渊的底部,但这需要更长的时间。如果你每次选择走更长的步,你会更快到达,但是,有可能你会越过坑的底部,而不是正好在底部。在梯度下降算法中,你走的步数就是学习率。这决定了算法多快收敛到最小值。

Convex vs Non-convex function

有时,成本函数可以是非凸函数,在这种情况下,您可能会陷入局部最小值,但对于线性回归,它始终是凸函数。

你可能想知道如何使用梯度下降来更新 a_0 和 a_1。为了更新 a_0 和 a_1,我们从成本函数中取梯度。为了找到这些梯度,我们对 a_0 和 a_1 求偏导数。现在,为了理解下面的偏导数是如何得到的,你需要一些微积分,但是如果你不需要,也没关系。你可以照原样接受。

偏导数是梯度,它们用于更新 A0 和 a1 的值。Alpha 是学习率,它是一个必须指定的超参数。较小的学习率可以让你更接近最小值,但需要更多的时间来达到最小值,较大的学习率收敛更快,但有可能超过最小值。

密码

让我们来看看代码。我们有两个选择,我们可以使用 scikit learn 库导入线性回归模型并直接使用它,或者我们可以根据上面的等式编写自己的回归模型。与其两个选一个,不如两个都做:)

在线上有许多数据集可用于线性回归。我用的是这个链接里的那个。让我们将训练和测试数据可视化。

Training(left) and Testing(right) data

让我们从两种方法中最简单的开始,即使用 scikit learn 库来构建我们的线性回归模型。

我们使用熊猫图书馆来读取训练和测试文件。我们检索自变量(x)和因变量(y ),由于我们只有一个特征(x ),我们对它们进行整形,以便可以将它们输入到线性回归模型中。

我们使用 scikit learn 导入线性回归模型。我们根据训练数据拟合模型,并预测测试数据的值。我们使用 R2 分数来衡量我们模型的准确性。

R2 score on testing data

现在,让我们从上面的等式建立我们自己的线性回归模型。我们将只使用 numpy 库进行计算,使用 R2 分数进行度量。

我们为 a_0 和 a_1 初始化值 0.0。对于 1000 个时期,我们计算成本,并使用成本计算梯度,并使用梯度更新 a_0 和 a_1 的值。经过 1000 个历元后,我们会得到 A0 和 a1 的最佳值,因此,我们可以用公式表示最佳拟合直线。

测试集包含 300 个样本,因此我们必须将 A0 和 a1 从 700 x1300 x1 整形。现在,我们可以使用该方程来预测测试集中的值,并获得 R2 分数。

R2 score on testing data

我们可以观察到与前面方法相同的 R2 分数。我们还绘制了回归线以及测试数据点,以更好地直观了解我们的算法有多好。

Regression line — Test data

结论

线性回归是每个机器学习爱好者都必须知道的算法,也是想学习机器学习的人的正确起点。这确实是一个简单但有用的算法。我希望这篇文章对你有帮助。

马尔可夫链简介

原文:https://towardsdatascience.com/introduction-to-markov-chains-50da3645a50d?source=collection_archive---------0-----------------------

什么是马尔可夫链,什么时候使用,它们是如何工作的

(Generated from http://setosa.io/ev/markov-chains/)

马尔可夫链是统计建模随机过程的一种相当常见且相对简单的方法。它们已经被用于许多不同的领域,从文本生成到金融建模。一个流行的例子是 r/SubredditSimulator ,它使用马尔可夫链来自动创建整个 subreddit 的内容。总的来说,马尔可夫链在概念上非常直观,并且非常容易理解,因为它们可以在不使用任何高级统计或数学概念的情况下实现。它们是开始学习概率建模和数据科学技术的好方法。

方案

首先,我将用一个非常常见的例子来描述它们:

Imagine that there were two possible states for weather: sunny or cloudy. **You can always directly observe the current weather state, and it is guaranteed to always be one of the two aforementioned states.**Now, you decide you want to be able to predict what the weather will be like tomorrow. Intuitively, you assume that there is an inherent ***transition*** in this process, in that the current weather has some bearing on what the next day’s weather will be. So, being the dedicated person that you are, you collect weather data over several years, and calculate that the chance of a sunny day occurring after a cloudy day is 0.25\. You also note that, by extension, the chance of a cloudy day occurring after a cloudy day must be 0.75, since there are only two possible states.You can now use this ***distribution*** to predict weather for days to come, based on what the current weather state is at the time.

这个例子说明了马尔可夫链的许多关键概念。马尔可夫链本质上由一组满足 马尔可夫性质 的转移所组成,这些转移由某种概率分布决定。

观察在这个例子中,概率分布是如何仅通过观察从当天到第二天的转变而获得的。这说明了马尔科夫属性,马尔科夫过程的独特特征,使得它们 无记忆 。这通常使他们无法成功地产生序列,其中一些潜在的趋势预计会发生。例如,虽然马尔可夫链可能能够基于词频模仿作者的写作风格,但是它将不能产生包含深层含义或主题意义的文本,因为这些是在长得多的文本序列上开发的。由于它们不能考虑先前状态的完整链,因此它们缺乏产生依赖于上下文的内容的能力。

A visualization of the weather example

模型

形式上,马尔可夫链是一个概率自动机。状态转移的概率分布通常表示为马尔可夫链的 转移矩阵 如果马尔可夫链有 N 个可能状态,那么矩阵将是一个N×N矩阵,这样条目 (I,J) 就是从状态 I 转移到状态 J 的概率。此外,转移矩阵必须是一个随机矩阵,该矩阵的每一行的元素相加必须正好为 1。这完全有意义,因为每一行代表它自己的概率分布。

General view of a sample Markov chain, with states as circles, and edges as transitions

Sample transition matrix with 3 possible states

此外,马尔可夫链还有一个 初始状态向量 ,表示为一个N×1矩阵(一个向量),它描述了在 N 个可能状态中的每一个状态开始的概率分布。向量的条目 I 描述了链从状态 I 开始的概率。

Initial State Vector with 4 possible states

这两个实体通常是表示马尔可夫链所需的全部。

我们现在知道了如何获得从一个状态转换到另一个状态的机会,但是如何找到在多个步骤中发生转换的机会呢?为了形式化这一点,我们现在想要确定在 M 个步骤上从状态 I 移动到状态 J 的概率。事实证明,这其实很容易发现。给定一个转移矩阵 P ,这可以通过计算通过将 P 提升到 M 的幂而获得的矩阵的条目 (I,J) 的值来确定。对于小数值的 M(T25),这可以通过手动重复乘法很容易地完成。但是对于 M 的大值,如果你熟悉简单的线性代数,一个更高效的矩阵的幂次提升方法是先对角化矩阵。

结论

既然您已经了解了马尔可夫链的基础知识,现在您应该能够轻松地用自己选择的语言实现它们。如果编码不是你的专长,还有许多更高级的马尔可夫链和马尔可夫过程的特性可以研究。在我看来,沿着理论路线的自然进展将是走向隐马尔可夫过程或 MCMC。简单的马尔可夫链是其他更复杂的建模技术的构建模块,因此有了这些知识,您现在可以转移到诸如信念建模和抽样等主题中的各种技术。

ML⁵.简介射流研究…

原文:https://towardsdatascience.com/introduction-to-ml5-js-3fe51d6a4661?source=collection_archive---------6-----------------------

Photo by Christopher Robin Ebbinghaus on Unsplash

初学者友好的网络机器学习。

本文是关于 ML⁵.的第一部分 js 学习系列,完整系列将在媒体上以文本可读形式提供,并在 YouTube 上的我的频道上以视频解释形式提供。正在更新完整的视图播放列表。

ML⁵.js 该库由纽约大学开发,于 2018 年 7 月公开发布。该库在浏览器中提供对机器学习算法、任务和模型的访问,构建在[TensorFlow.js](https://js.tensorflow.org/)之上,没有其他外部依赖性。所以,可以和 Keras 比。ML⁵.js

ML⁵.js 我们可以把这个比作 Keras 。Keras 背后的动机是让 python 中的 ML/DL 简单到初学者也能使用。ML⁵.的情况也类似射流研究…..

这可以通过对 Tensorflow.js 库进行包装并在后端使用所有功能来实现。所以直观来说,对于 TensorFlow.js 来说是一个很好用的 API。

ML⁵.入门 js

我们可以用ml⁵.js 通过引用我们项目中它的最新版本,通过在 HTML 文件中使用如下脚本标签:

 <html>
    <head>
      <title>Getting Started</title>
      **<script src="https://unpkg.com/ml5@0.1.1/dist/ml5.min.js"></script>**
    </head> <body>
      <script> // Your code will go here </script>
    </body>
  </html>

仅此而已!💥

你已经准备好了..

请考虑在 ML5.js 上观看这个视频的详细解释:-

Source

承诺和回访

ML⁵.js 支持错误优先回调和所有方法中的承诺。

使用回调

ML⁵.js 使用一种被称为错误优先回调的模式:

例如——如果你使用的是imageClassifier()方法,你将需要以如下方式构建它:

错误优先回调是许多 JavaScript 库共有的约定,在 ML⁵.中实现 js 。JavaScript 语言本身并不强制这种模式。在实施之前,我们最需要了解的是 ML⁵.js 方法和函数是异步的(因为机器学习模型可能会花费大量的时间来处理输入和生成输出!).

利用承诺

ML⁵.js也支持承诺。如果没有向任何异步函数提供回调,则返回一个承诺。

有了承诺,图像分类示例可以按以下方式使用:

使用 ML⁵.进行图像分类 js

图像分类器()

ML⁵.js 可以用神经网络来识别图像的内容。ml5.imageClassifier()是创建对象的默认方法,使用预先训练的模型(如 MobileNet 等)对图像进行分类。

ML⁵.js 库从云中访问这些模型。

让我们构建一个具体的例子:-

我们将使用 p5 库和 ML⁵.js. p5 是一个强大而简单的 Javascript 库。你可以在这里找到更多细节。你可以随时用 ML⁵.js. 使用普通的 JavaScript 或者你选择的其他框架作品

在开始 Javascript 部分之前,我们需要使用 NodeJS 托管一个本地服务器。

下面是代码:-

本地服务器成功启动并运行后,我们可以开始编写 HTML 和 JS 文件。

Index.html

Index.html

main.js

好了..我们已经使用 ML⁵.js. 成功实现了一个图像分类器

可以去http://localhost:8081/index . html查看结果。截图如下:-

Screenshot of the App.

下面是上面代码的 Github Repo

** [## ADLsourceCode/ml5

GitHub 是人们构建软件的地方。超过 2800 万人使用 GitHub 来发现、分享和贡献超过…

github.com](https://github.com/ADLsourceCode/ml5)

注意:这个教程不是集中在用户界面上,而是集中在获得 ML⁵.的基础上 js 清零。UI 可以改进,UI 没有限制。

使用 ML⁵.js 对于图像分类来说很简单,在我的下一篇文章中,我们将关注网络摄像头视频分类&其他使用 ML⁵.js. 的 NLP 工作

请考虑观看此视频,了解使用 ML⁵.进行图像分类的详细说明 js :-

Source

我对 ML⁵.的看法射流研究…

这对熟悉 JavaScript 和 HTML 并试图在 ML/DL 世界中找到出路的程序员来说是极好的!

对于没有 ML/DL 背景,但希望了解这个领域的人来说,这让事情变得简单多了。它使得机器学习对于艺术家、创意编码者和学生等广大受众来说变得触手可及。

这方面的用例很多,我个人认为这是我们目前需要的。

如果你觉得我的文章有用,你也会觉得我在 AI 上的 You Tube 频道有用而且有趣。请考虑订阅我的频道

享受 AI。😉**

如果你喜欢我的文章,请点击👏下面的跟我上中的和&:

如果你有任何问题,请在下面的评论里或者 推特 告诉我。订阅我的 YouTube 频道获取更多科技视频: ADL

从头开始介绍模型树

原文:https://towardsdatascience.com/introduction-to-model-trees-6e396259379a?source=collection_archive---------4-----------------------

决策树是机器学习中一种强大的监督学习工具,用于递归地(通过特征分割)将数据分割成单独的“孤岛”,以减少您对训练集的拟合的整体加权损失。决策树分类中常用的是基尼指数损失的模态分类器,以及决策树回归的 L2 损失均值回归。然而应该另外观察的是,在树分裂过程中,决策树原则上可以采用任何 模型,即 线性回归、逻辑回归、神经网络。本文的目的是向您介绍这种更一般化的方法,名为模型树,它将允许您从您选择的任何模型中构建决策树(而不是依赖于标准的 CART 方法)!**

Fig 1) A schematic of using a linear regression model tree to fit a 1D training set to find segments of the training set that are well fit by a straight line.

在深入探讨为什么模型树有用和重要之前,我们在我的 Github 上提供了一个从头开始的模型树 Python 代码实现:

https://github . com/ankonzoid/learning x/tree/master/advanced _ ML/model _ tree

关于机器学习、深度学习和强化学习的更多博客、教程和项目,请查看我的 和我的 Github

模型树的目的是什么?

假设你有一些复杂的训练数据,你天真地想到了一个简单的模型来拟合这个训练集(比如线性回归或者逻辑回归)。尤其是如果您猜测的简单模型的复杂性如此之低,那么您的模型本身很有可能会不足以满足您的训练数据。然而,希望并没有在这一点上失去!模型树的目的是在你的简单模型之外建立一个决策树层次结构,试图适应你的训练集(通过特征切片创建)的几个较小部分,这样整个模型树确实很好地适应完整的训练集。

为了明确演示在常规决策树上构建模型树的有用性,考虑 4 阶一维多项式以及训练低深度线性回归模型树回归器(图 2.a)和默认 scikit-learn 默认决策树回归器(图 2.b)之间的差异。您将会注意到,在这个例子中,模型树轻松胜过 scikit-learn 决策树回归器。

在下面的图 2.a 中,我们绘制了线性回归模型树与数据的拟合度,并增加了树的深度,以找到深度为 5 的拟合度良好的数据。正如你所看到的,即使拟合在极低的树深度(即 0,1,2)下并不出色,但拟合具有直观的意义,因为它们都贪婪地试图通过覆盖多项式的大部分来减少损失,从远处看就像直线。当我们到达深度 4 和 5 时,模型树将已经很好地捕捉到数据的 x 相关性,正如从 4 阶多项式所预期的。

Fig 2.a) Linear regression model tree fit on a 4th-order polynomial

另一方面,在下面的图 2.b 中,我们绘制了 scikit-learn 的默认决策树回归器的拟合度,发现即使在较高的树深度,拟合度仍然很差,这主要是因为它不能有效地捕捉数据的 x 相关性,因为 scikit-learn 的决策树使用均值回归(不考虑 x 变量,只关心 y 值)!因此,解决方案(不使用集合方法)将是迫使树更深以更接近近似值。希望这是一个强有力的视觉提醒,无论何时你有一点点奢侈去理解你的训练数据的本质,模型树都可以极大地改善你的结果。

Fig 2.b) Decision tree regressor (scikit-learn default implementation) fit on a 4th-order polynomial

最后一点,请记住,模型树在概念上的构建方式与常规决策树相同,这意味着模型树也可能遭受与决策树相同的缺陷,这通常涉及容易过度拟合的问题,尤其是当您使用复杂的模型时。

朴素贝叶斯分类简介

原文:https://towardsdatascience.com/introduction-to-naive-bayes-classification-4cffabb1ae54?source=collection_archive---------1-----------------------

朴素贝叶斯是一个简单、有效且常用的机器学习分类器。它是一种概率分类器,在贝叶斯设置中使用最大后验决策规则进行分类。也可以用一个非常简单的贝叶斯网络来表示。朴素贝叶斯分类器在文本分类中特别受欢迎,是垃圾邮件检测等问题的传统解决方案。

模型

任何概率分类器的目标是,利用特征 x_0 到 x_n 和类 c_0 到 c_k,确定特征在每个类中出现的概率,并返回最可能的类。因此,对于每一类,我们希望能够计算 P(c_i | x_0,…,x_n)。

为了做到这一点,我们使用贝叶斯规则。回想一下贝叶斯规则如下:

在分类的上下文中,您可以用一个类 c_i 替换 A,用我们的一组特征 x_0 到 x_n 替换 B。由于 P(B)用作归一化,并且我们通常无法计算 P(x_0,…,x_n),我们可以简单地忽略该术语,而是只陈述 P(c_i | x_0,…,x_n) ∝ P(x_0,…,x_n | c_i) * P(c_i),其中∝表示“与成比例”。P(c_i)计算简单;P(x_0,…,x_n | c_i)更难计算。为了简化其计算,我们假设 x_0 到 x_n 是条件独立给定 c_i,这就允许我们说 P(x_0,…,x _ n | c _ I)= P(x _ 0 | c _ I)* P(x _ 1 | c _ I) P(x _ n | c _ I)。这个假设很可能是不正确的——因此命名为朴素贝叶斯分类器,但是该分类器在大多数情况下仍然表现良好。因此,我们对类概率的最终表示如下:

计算各个 P(x_j | c_i)项将取决于您的要素所遵循的分布。在文本分类的背景下,其中特征可以是字数,特征可以遵循多项式分布。在其他情况下,特征是连续的,它们可能遵循高斯分布

请注意,与其他常见的分类方法相比,朴素贝叶斯中的显式训练非常少。在预测之前必须做的唯一工作是找到特征的个体概率分布的参数,这通常可以快速且确定地完成。这意味着朴素贝叶斯分类器甚至可以在高维数据点和/或大量数据点的情况下表现良好。

分类

既然我们有了一种方法来估计给定数据点落入某个类别的概率,我们需要能够使用它来产生分类。朴素贝叶斯以非常简单的方式处理这个问题;根据数据点的特征,简单地选择具有最大概率的 c_i。

这被称为最大后验概率决策规则。这是因为,回头参考我们的贝叶斯规则公式,我们只使用 P(B|A)和 P(A)项,它们分别是似然项和先验项。如果我们只使用 P(B|A)的可能性,我们将使用一个最大可能性决策规则。

文本自然语言处理导论

原文:https://towardsdatascience.com/introduction-to-natural-language-processing-for-text-df845750fb63?source=collection_archive---------0-----------------------

Icons source: https://iconfinder.com

看完这篇博文,你会知道一些从一些文本提取特征的基本技术,所以你可以把这些特征作为机器学习模型输入

什么是 NLP(自然语言处理)?

NLP 是计算机科学和人工智能的一个子领域,涉及计算机和人类(自然)语言之间的交互。用于将机器学习算法应用于文本语音

例如,我们可以使用 NLP 创建类似于语音识别文档摘要机器翻译垃圾邮件检测命名实体识别问题回答、自动完成、预测打字等系统。

如今,我们大多数人的智能手机都有语音识别功能。这些智能手机使用 NLP 来理解所说的内容。此外,许多人使用操作系统内置语音识别的笔记本电脑。

一些例子

Cortana

Source: https://blogs.technet.microsoft.com/microsoft_presse/auf-diesen-4-saeulen-basiert-cortanas-persoenlichkeit/

微软 OS 有一个名为 Cortana 的虚拟助手,可以识别一个自然语音。你可以用它来设置提醒、打开应用程序、发送电子邮件、玩游戏、跟踪航班和包裹、查看天气等等。

你可以从这里阅读更多关于 Cortana 命令的内容。

Siri

Source: https://www.analyticsindiamag.com/behind-hello-siri-how-apples-ai-powered-personal-assistant-uses-dnn/

Siri 是苹果公司 iOS、watchOS、macOS、HomePod 和 tvOS 操作系统的虚拟助手。同样,你可以用语音 命令做很多事情:开始通话、给某人发短信、发送电子邮件、设置定时器、拍照、打开应用程序、设置闹钟、使用导航等等。

这里的是所有 Siri 命令的完整列表。

Gmail

Source: https://i.gifer.com/Ou1t.gif

谷歌开发的著名电子邮件服务 Gmail 正在使用垃圾邮件检测过滤掉一些垃圾邮件。

Python 的 NLTK 库简介

NLTK ( 自然语言工具包)是一个领先的平台,用于构建 Python 程序来处理人类语言数据。它为众多的 语料库词汇资源提供了易用的接口。此外,它还包含一套文本处理库,用于分类、标记化、词干化、标记、解析和语义推理。最棒的是,NLTK 是一个免费、开源、社区驱动的项目。

我们将使用这个工具包来展示自然语言处理领域的一些基础知识。对于下面的例子,我假设我们已经导入了 NLTK 工具包。我们可以这样做:import nltk

文本的自然语言处理基础

在本文中,我们将讨论以下主题:

  1. 句子标记化
  2. 单词标记化
  3. 文本词汇化和词干化
  4. 停止言语
  5. 正则表达式
  6. 词汇袋
  7. TF-IDF

1.句子标记化

句子标记化(也叫句子切分就是把书面语的一串分割成其成分句子的问题。这里的想法看起来很简单。在英语和其他一些语言中,每当我们看到标点符号时,我们就可以把句子分开。

然而,即使在英语中,由于缩写使用句号字符,这个问题也不是微不足道的。当处理纯文本时,包含句点的缩写表可以帮助我们防止错误分配句子边界。在很多情况下,我们使用库来完成这项工作,所以现在不要太担心细节。

例子:

让我们来看一段关于一个著名的棋盘游戏叫做双陆棋的课文。

双陆棋是已知最古老的棋盘游戏之一。它的历史可以追溯到近 5000 年前中东的考古发现。这是一个两人游戏,每个人有 15 个跳棋,根据两个骰子的滚动在 24 个点之间移动。

要用 NLTK 应用句子标记化,我们可以使用nltk.sent_tokenize函数。

作为输出,我们分别得到 3 个组成句子。

Backgammon is one of the oldest known board games.

Its history can be traced back nearly 5,000 years to archeological discoveries in the Middle East.

It is a two player game where each player has fifteen checkers which move between twenty-four points according to the roll of two dice.

2.单词标记化

分词(也叫分词)就是把书面语的一串分割成它的成分的问题。在英语和许多其他使用某种形式拉丁字母的语言中,空格是单词分隔符的一个很好的近似。

然而,如果我们仅仅通过空间分割来实现想要的结果,我们仍然会有问题。一些英语复合名词有不同的写法,有时它们包含一个空格。在大多数情况下,我们使用一个库来实现想要的结果,所以不要太担心细节。

举例:

让我们使用上一步中的句子,看看如何对它们应用单词标记化。我们可以使用nltk.word_tokenize函数。

输出:

['Backgammon', 'is', 'one', 'of', 'the', 'oldest', 'known', 'board', 'games', '.']

['Its', 'history', 'can', 'be', 'traced', 'back', 'nearly', '5,000', 'years', 'to', 'archeological', 'discoveries', 'in', 'the', 'Middle', 'East', '.']

['It', 'is', 'a', 'two', 'player', 'game', 'where', 'each', 'player', 'has', 'fifteen', 'checkers', 'which', 'move', 'between', 'twenty-four', 'points', 'according', 'to', 'the', 'roll', 'of', 'two', 'dice', '.']

文本词汇化和词干化

出于语法原因,文档可以包含单词的不同形式,例如驱动驱动驱动。还有,有时候我们会用相关的词来表达类似的意思,比如民族国家民族

词干化词汇化的目的都是为了 屈折 形式以及有时将单词的衍生相关形式缩减为****公共基础形式

来源:https://NLP . Stanford . edu/IR-book/html/html edition/stemming-and-lemma tization-1 . html

例句:

  • 是,是,是=>
  • 狗,狗,狗的,狗的=>

应用于文本的这种映射的结果将如下所示:

  • 男孩的狗大小不同

词干化和词汇化是规范化的特例。然而,它们彼此不同。

词干通常指的是一种粗糙的 启发式 过程,它砍掉单词的词尾,希望在大多数时候都能正确实现这一目标,通常还包括去除派生词缀。

词汇化通常是指使用词汇单词的形态分析正确地做事情,通常旨在只去除屈折词尾并返回单词的基本或词典形式,这就是所谓的引理

来源:https://NLP . Stanford . edu/IR-book/html/html edition/stemming-and-lemma tization-1 . html

不同之处在于词干分析器在不了解上下文的情况下操作,因此无法理解根据词性而具有不同含义的单词之间的差异。但是词干分析器也有一些优点,它们更容易实现,通常 T21 运行得更快。此外,降低的“精度”对于某些应用来说可能无关紧要。

例子:

  1. “更好”这个词的引理是“好”。这一环节被词干遗漏了,因为它需要查字典。
  2. 单词“play”是单词“playing”的基本形式,因此它在词干和词汇化上都是匹配的。
  3. 单词“meeting”可以是名词的基本形式,也可以是动词的形式(“to meet”),这取决于上下文;例如,“在我们最后一次见面时”或“我们明天还会见面”。与词干提取不同,词汇化试图根据上下文选择正确的词汇。

在我们知道区别之后,让我们看一些使用 NLTK 工具的例子。

输出:

Stemmer: seen
Lemmatizer: see

Stemmer: drove
Lemmatizer: drive

停止言语

Source: http://www.nepalinlp.com/detail/stop-words-removal_nepali/

停用词是在文本处理之前或之后从中过滤掉的词。在对文本应用机器学习时,这些词可以添加很多噪音。这就是为什么我们要去掉这些无关词

停用词通常是指中最常见的词如“”、”,但在一种语言中没有没有单一的停用词通用列表。停用字词的列表可以根据您的应用而改变。

NLTK 工具有一个预定义的停用词列表,它引用最常用的词。如果是第一次使用,需要使用这个代码下载停用词:nltk.download(“stopwords”)。一旦我们完成了下载,我们就可以从nltk.corpus加载stopwords包,并用它来加载停用词。

输出:

['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]

让我们看看如何从句子中去掉停用词。

输出:

['Backgammon', 'one', 'oldest', 'known', 'board', 'games', '.']

如果你不熟悉 Python 中的 列表理解。这里有另一种方法可以达到同样的效果。

然而,请记住列表理解更快,因为它们已经过优化,以便 Python 解释器在循环过程中发现可预测的模式。

你可能想知道为什么我们把我们的列表转换成一个 集合 。Set 是一种抽象数据类型,可以存储唯一的值,没有任何特定的顺序。集合中的搜索操作 比列表中的搜索操作快得多。对于少量的单词,没有太大的区别,但是如果你有大量的单词,强烈建议使用 set 类型。

如果你想了解更多关于不同数据结构的不同操作之间的时间消耗,你可以看看这个很棒的备忘单。

正则表达式

Source: https://digitalfortress.tech/tricks/top-15-commonly-used-regex/

****正则表达式regexregexp 是定义搜索模式的字符序列。让我们看看一些基本的。

  • . -匹配除换行符之外的任意字符
  • \w -匹配
  • \d -匹配数字
  • \s -匹配空格
  • \W——配不字
  • \D -匹配而非数字
  • \S -匹配而不是空白
  • [abc] -匹配 a、b 或 c 中的任意一个
  • [**^**abc] - 匹配 a、b 或 c
  • [a**-**g] -在和& g 之间匹配一个字符

正则表达式使用反斜杠字符 ( '\')来表示特殊形式,或者允许使用特殊字符而不调用它们的特殊含义。这个与 Python 在字符串文字中出于相同目的使用相同字符的用法相冲突;例如,要匹配一个文字反斜杠,可能必须将'\\\\'写成模式字符串,因为正则表达式必须是\\,并且每个反斜杠必须在一个常规 Python 字符串文字中表示为\\****

解决方案是将 Python 的原始字符串符号用于正则表达式模式;以 **'r'**为前缀的字符串文字中的反斜杠没有任何特殊的处理方式。所以r"\n"是包含'\''n'的双字符字符串,而"\n"是包含换行符的单字符字符串。通常,模式将使用这种原始字符串符号在 Python 代码中表示。

来源:https://docs.python.org/3/library/re.html?highlight=regex

我们可以使用正则表达式将附加过滤应用到我们的文本中。例如,我们可以删除所有非单词字符。在许多情况下,我们不需要标点符号,用正则表达式很容易删除它们。

在 Python 中,**re**模块提供了类似于 Perl 中的正则表达式匹配操作。我们可以使用**re.sub**函数用替换字符串替换模式的匹配。让我们看一个用空格字符替换所有非单词的例子。

输出:

**'The development of snowboarding was inspired by skateboarding  sledding  surfing and skiing '**

正则表达式是一个强大的工具,我们可以创建更复杂的模式。如果你想了解更多关于 regex 的知识,我可以推荐你试试这两个 web 应用: regex r, regex101 。

词汇袋

Source: https://www.iconfinder.com/icons/299088/bag_icon

机器学习算法不能直接处理原始文本,我们需要将文本转换成数字向量。这叫做 特征提取

词袋模型是一种流行的简单的 特征提取技术在我们处理文本时使用。它描述了文档中每个单词的出现。****

要使用该模型,我们需要:

  1. 设计一个已知单词的词汇表(也叫记号)
  2. 选择已知单词存在的度量

任何关于单词的顺序结构的信息都被丢弃。这就是为什么它被称为单词的。该模型试图理解一个已知单词是否出现在文档中,但不知道该单词在文档中的位置。

直觉是相似文档相似内容。同样,从一个内容中,我们可以了解一些关于文档的含义。

例子

我们来看看创建词袋模型有哪些步骤。在这个例子中,我们将用四个句子来看看这个模型是如何工作的。在现实世界的问题中,您将处理大量的数据。

1。加载数据

Source: https://www.iconfinder.com/icons/315166/note_text_icon

假设这是我们的数据,我们想把它作为一个数组加载。

要做到这一点,我们可以简单地读取文件,并按行分割。

输出:

**["I like this movie, it's funny.", 'I hate this movie.', 'This was awesome! I like it.', 'Nice one. I love it.']**

2。 设计词汇

Source: https://www.iconfinder.com/icons/2109153/book_contact_dairy_google_service_icon

让我们从四个加载的句子中获取所有独特的单词,忽略大小写、标点和单字符标记。这些单词将成为我们的词汇(已知单词)。

我们可以使用 sklearn 库中的 计数矢量器 类来设计我们的词汇表。我们也将在阅读下一步后看看如何使用它。

3。创建文档向量

Source: https://www.iconfinder.com/icons/1574/binary_icon

接下来,我们需要对每个文档中的单词进行评分。这里的任务是将每个原始文本转换成一个数字向量。之后,我们可以使用这些向量作为机器学习模型的输入。最简单的评分方法是用 1 代表存在,0 代表不存在来标记单词的存在。

现在,让我们看看如何使用上面提到的 CountVectorizer 类创建一个单词袋模型。

输出:

这是我们的句子。现在我们可以看到单词袋模型是如何工作的。

关于单词袋模型的补充说明

Source: https://www.iconfinder.com/icons/1118207/clipboard_notes_pen_pencil_icon

单词袋模型的复杂性来自于决定如何设计已知单词(记号)的词汇表以及如何对已知单词的存在进行评分。

设计词汇
当词汇
大小增加
时,文档的向量表示也增加。在上面的例子中,文档向量的长度等于已知单词的数量。****

在某些情况下,我们可能有大量的数据,在这种情况下,表示文档的向量的长度可能是数千或数百万个元素。此外,每个文档可能只包含词汇表中的几个已知单词。

因此,矢量表示将有个零。这些有很多零的向量被称为稀疏向量。它们需要更多的内存和计算资源。

当使用单词袋模型来减少所需的内存和计算资源时,我们可以减少已知单词的数量。在创建我们的单词袋模型之前,我们可以使用我们已经在本文中看到的文本清理技术:

  • 忽略大小写的字样
  • 忽略标点符号
  • 从我们的文档中删除停用词****
  • 将单词简化为基本形式(文本词条化和词干化)
  • 修复拼错的单词

另一种更复杂的创建词汇表的方法是使用分组单词。这改变了词汇表的范围,并允许单词袋模型获得关于文档的更多细节。这种方法被称为 n-grams

一个 n-gram 是一个由若干(单词、字母、数字、数位等)组成的序列。).在 文本语料库 的上下文中,n-grams 一般是指一个单词序列。一个一元词是一个词,一个二元词是两个词的序列,一个三元词是三个词的序列,等等。“n-gram”中的“n”是指分组单词的数量。仅对语料库中出现的 n 元文法进行建模,而不是所有可能的 n 元文法。

例句
让我们看看下面这个句子的所有二元模型:
The office building is open today

所有的二元模型是:

  • 办公室
  • 办公楼
  • 建筑是
  • 已打开
  • 今天开门

****二元模型袋比词汇袋方法更强大。

给单词打分 一旦我们创建了已知单词的词汇表,我们就需要给这些单词在我们的数据中的出现次数打分。我们看到了一种非常简单的方法——二元方法(1 代表存在,0 代表不存在)。

一些额外的评分方法是:

  • ****伯爵。计算每个单词在文档中出现的次数。
  • ****频率。计算文档中所有单词中每个单词出现的频率。

TF-IDF

****评分词频的一个问题是,文档中最频繁出现的词开始有最高的分数。与一些更罕见和特定领域的单词相比,这些频繁出现的单词可能不包含太多的"信息增益"。解决这个问题的一个方法是惩罚在所有文档频繁出现的单词。这种方法被称为 TF-IDF。

TF-IDF,简称词频-逆文档频数是一种统计量,用于评估一个词在集合或语料库中对一个文档的重要性。

TF-IDF 得分值与单词在文档中出现的次数成比例地增加,但是它被语料库中包含该单词的文档的数量所抵消。

让我们看看用于计算文档 y 中给定术语 x 的 TF-IDF 得分的公式。

TF-IDF Formula. Source: http://filotechnologia.blogspot.com/2014/01/a-simple-java-class-for-tfidf-scoring.html

现在,让我们把这个公式拆分一下,看看公式的不同部分是如何工作的。

  • 词频(TF) :该词在当前文档中出现频率的得分。

Term Frequency Formula

  • 逆词频(ITF) :对单词在文档中的稀有程度进行评分。

Inverse Document Frequency Formula

  • 最后,我们可以使用前面的公式来计算给定术语的 TF-IDF 得分,如下所示:

TF-IDF Formula

示例 在 Python 中,我们可以使用 sklearn 库中的tfidf 矢量器类来计算给定文档的 TF-IDF 分数。让我们使用和单词袋例子中相同的句子。

输出:

同样,我将在这里添加句子,以便于比较和更好地理解这种方法是如何工作的。

摘要

在这篇博文中,您将学习文本的 NLP 基础知识。更具体地说,您已经学习了以下概念以及其他详细信息:

  • NLP 用于将机器学习算法应用于文本语音
  • NLTK ( 自然语言工具包)是一个领先的平台,用于构建 Python 程序来处理人类语言数据****
  • ****句子标记化就是把书面语的一串分割成它的成分句子的问题
  • ****分词就是将书面语中的一串拆分成其成分单词的问题
  • 词干化词汇化的目的都是为了 屈折 形式以及有时将**单词的衍生相关形式缩减为**公共基础形式
  • ****停用词是在文本处理之前或之后过滤掉的词。他们通常指的是语言中最常见的单词
  • ****正则表达式是定义搜索模式的一系列字符。
  • 词袋模型是一种流行的简单的 特征提取技术在我们处理文本时使用。它描述了文档中每个单词的出现。
  • TF-IDF 是一个统计量,用于评估一个单词对集合中的一个文档或者语料库的重要性。

厉害!现在我们知道了如何从文本中提取特征的基本知识。然后,我们可以使用这些特征作为机器学习算法的输入。

要不要看所有用在的概念再来一个大例子**?

  • 给您!如果你在手机上阅读,请向下滚动到最后,点击“桌面版”链接。**

资源

  • https://en.wikipedia.org/wiki/Natural_language_processing
  • http://www.nltk.org/
  • **【https://en.wikipedia.org/wiki/Text_segmentation **
  • https://en.wikipedia.org/wiki/Lemmatisation
  • https://en.wikipedia.org/wiki/Stemming
  • https://NLP . Stanford . edu/IR-book/html/html edition/stemming-and-lemma tization-1 . html
  • https://en.wikipedia.org/wiki/Stop_words
  • https://en.wikipedia.org/wiki/Regular_expression
  • https://docs.python.org/3/library/re.html?highlight=regex
  • https://machine learning mastery . com/gentle-introduction-bag-words-model/
  • https://chrisalbon . com/machine _ learning/preprocessing _ text/bag _ of _ words/
  • https://en.wikipedia.org/wiki/Tf%E2%80%93idf

互动版

这里的是在 Deepnote (云托管 Jupyter 笔记本平台)上传的这篇文章的交互版本。请随意查看并使用示例。

我的其他博客文章

你也可以看看我以前的博文。

  • Jupyter 笔记本快捷键
  • 数据科学的 Python 基础知识
  • Python 数据科学:Matplotlib 数据可视化简介
  • Python 数据科学:pandas 加载、子集化和过滤数据简介

时事通讯

如果你想在我发表新的博客文章时得到通知,你可以订阅我的最新时事通讯。

商务化人际关系网

这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。

最后的话

谢谢你的阅读。我希望你喜欢这篇文章。如果你喜欢,请按住拍手键,分享给你的朋友。我很高兴听到你的反馈。如果你有什么问题,尽管问。😉

自然语言处理导论

原文:https://towardsdatascience.com/introduction-to-natural-language-processing-part-1-777f972cc7b3?source=collection_archive---------6-----------------------

用数学破译语言

Photo by Franki Chamaki on Unsplash

自然语言处理(NLP)是人工智能领域,涉及人类语言的处理和理解。自 20 世纪 50 年代问世以来,机器对语言的理解已经在翻译、主题建模、文档索引、信息检索和实体抽取中发挥了关键作用。

如今,它被用来驱动搜索引擎,过滤垃圾邮件,并以快速和可扩展的方式获得分析。随着计算效率和机器学习的新发展,这些系统的性能呈指数增长。今天的几个 NLP 系统甚至可以夸耀接近人类水平的对等性。

有了专门用于 NLP 的剩余工具和技术,现在是所以很容易开始。我的目标是涵盖自然语言处理的基本理论,并向您展示如何构建简单的工具来展示它们的魔力。查看这些后续文章,获取更多 NLP 阅读资料。

  • 垃圾邮件还是火腿——一个简单的文本分类问题
  • 探索单词嵌入的神经网络

顺便提一下:这篇文章以及后续的文章主要关注文本处理环境中的 NLP。

我们到底是如何对语言建模的?

语言是流动的。语言充满了抽象和歧义。成年后学习第二语言很难,那么机器到底是怎么做到的呢?

事实是,大多数自然语言理解系统都是非常结构化的。他们将文本数据转换成数字表示,并使用复杂的数学模型来学习每个单词、短语和文档之间的依赖关系。最终用户所看到的对语言的智能理解实际上是一个大型语料库中的数百万个参数。

把文字变成数字的过程俗称矢量化或者嵌入。这些技术是将单词映射到实数向量的函数。向量形成了向量空间,这是一个代数模型,其中应用了向量加法的所有规则和相似性度量。

Using the word embedding technique word2vec, researchers at Google are able to quantify word relationships in an algebraic model

向量空间中两个单词之间的距离度量了它们之间的某种相似性。还可以使用向量加法来量化单词关系。上图展示了国王和王后的关系就像男人和女人的关系一样。理论上,这将意味着King Vector — Queen Vector = Man Vector - Woman Vector

每个向量的粒度不限于单词,我们也可以将字符、短语或文档映射到向量

“文档”是指与问题相关的完整的文本实体。例如,垃圾邮件分类系统会将每封邮件视为一个文档。

文档可以映射到向量的向量,其中每个向量对应一个单词。在这种情况下,向量的向量被算法摄取,其中单词关系和单个向量的连接被用于导出含义。或者,可以将整个文档映射到一个向量。这创建了对语言的更简化的理解,但是更少依赖于数据量和计算资源。

文档级嵌入通常通过检查每个单词的频率来创建。这些嵌入技术依赖于分布假设,假设:

分布假设:在相同语境中使用和出现的词倾向于表达相似的意思

让我们来看看最简单的嵌入技术之一——单词包,它用于将每个文档映射到它自己的向量上。

一袋单词

由于语言过于简单,这种技术在实践中并不常用。它的使用案例主要是作为一种教育工具,旨在使 NLP 的学生轻松地进入该主题。

让我们考虑以下文件。如果有帮助的话,你可以想象它们是朋友之间分享的荒谬简单的短信。

文件一:击掌

文件二:我老了。

文件 3:她五岁了。

我们从这组文档中获得的词汇是(高,五,我,我,老,她,是)。我们现在将忽略标点符号,尽管根据我们的使用情况,将它们纳入我们的词汇表也很有意义。

我们可以创建一个矩阵来表示词汇表中的每个术语和文档之间的关系。矩阵中的每个元素表示该术语在特定文档中出现的次数。

使用这个矩阵,我们可以获得每个单词以及文档的向量。我们可以将“五”矢量化为[1,0,1],将“文档 2”矢量化为[0,0,1,1,1,0,0]。

单词袋并不能很好地代表语言,尤其是当你的词汇量很小的时候。它忽略了词序和词的关系,产生了稀疏向量,其中大部分是零。从这个小例子中我们还可以看到,单词“我”、“am”、“old”被映射到同一个向量。这暗示这几个字差不多,其实没什么意义。

这里有一些关于 NLP 阅读的文章。 Spam 或 Ham 引入了一种新的文档嵌入类型,它考虑了每个术语的相对重要性。探索单词嵌入的神经网络介绍了使用神经网络创建的嵌入,这两种方法都是单词袋的更实用的替代方法。

  • 垃圾邮件还是火腿—一个简单的文本分类问题
  • 探索单词嵌入的神经网络

在我矢量化/嵌入我的文本后,现在该怎么办?

数字表示允许我们使用数学模型来分析我们的文本。下一步是将这些嵌入作为分类问题中的特征。

By one hot encoding the classes, we can plug this data into any type of classifier

文本数据丰富且维数高,这使得更复杂的分类器(如神经网络)成为 NLP 的理想选择。

感谢您的阅读!

如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。通过 Medium 关注我的最新更新。😃

作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。

如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。

再次感谢您的阅读!📕

神经网络导论

原文:https://towardsdatascience.com/introduction-to-neural-networks-ead8ec1dc4dd?source=collection_archive---------2-----------------------

神经网络基础

什么是神经网络

神经网络,通常称为人工神经网络(ANN ),是机器学习(ML)问题中对人脑功能的模拟。人工神经网络不能解决所有出现的问题,但可以和其他技术一起为各种 ML 任务提供更好的结果。人工神经网络最常见的用途是聚类和分类,它们也可用于回归任务,但在这方面还有更好的方法。

人工神经网络的构建模块和功能

神经元

这是神经网络的构建单元,它模仿人类神经元的功能。典型的神经网络使用 sigmoid 函数,如下所示。使用这个函数主要是因为它能够根据 f(x) 本身写出导数,这在最小化误差时很方便。

sigmoid function

Neuron

*z* =  ∑ *w*×*x
y = sigmoid(z)**w* = weights
*x* = inputs

神经元按层连接,因此一层可以与其他层通信,形成神经网络。除了输入和输出层之外的内层称为隐藏层。一层的输出被馈送到另一层的输入。

调整重量

人工神经网络的学习任务是调整权重以最小化误差。这是通过误差反向传播实现的。对于使用 Sigmoid 函数作为激活函数的简单神经元,误差可以如下所示。让我们考虑一种一般情况,其中权重称为向量 W,输入称为向量 x。

Error calculation and weight adjustment

从上面的等式中,我们可以概括出权重调整,令人惊讶的是,您会注意到这仅需要相邻神经元级别的细节。因此,这是一种稳健的学习机制,称为反向传播算法。从输出节点开始反向传播,更新前一个神经元的权重。

带有简单 javascript 库的演示应用程序

让我们编写一个简单的应用程序,它将使用两个图像进行训练,并对给定的图像应用过滤器。以下是训练过程的源图像和目标图像。

Source image(left) and target image(right)

我使用了一个人工神经网络,它使用反向传播来调整误差。训练的意图是找到一个函数 f(红、绿、蓝、阿尔法)来匹配目标颜色变换。使用源图像的几种颜色调整来制作目标图像。让我们看看代码。

Package.json

Index.ts

$ npm install
$ npm start

源图像应为input_image_train.jpg,目标图像名称应为output_image_train.jpg。要应用滤镜的图像文件应该是test.jpg,新的图像文件将保存为out.jpg。以下是我用训练好的模型过滤的一些示例图像。

样本输出

Input images (left) and output images(right)

酷吧?训练需要几秒钟,但过滤是即时的。如果需要,您可以保存模型以供将来使用。这在现实世界的应用中是非常智能的。

用于数据分析的 Numpy 简介

原文:https://towardsdatascience.com/introduction-to-numpy-for-data-analysis-3aaded0d0996?source=collection_archive---------3-----------------------

查看更新的 DevOps 课程。

课程注册链接:

[## 创建一个帐户

编辑描述

www.101daysofdevops.com](https://www.101daysofdevops.com/register/)

课程链接:

[## 101 天的开发周期

http://100daysofdevops.com/day-100-100-days-of-devops/好消息是从话题开始包括(请让我知道…

www.101daysofdevops.com](https://www.101daysofdevops.com/courses/101-days-of-devops/)

YouTube 链接:

[## 普拉尚·拉赫拉

主要想法是通过视频分享我的 Linux 知识。我的 Linkedin 个人资料…

www.youtube.com](https://www.youtube.com/user/laprashant/videos)

NumPy 是 Python 的线性代数库,这也是 PyData 生态系统中所有库都依赖 NumPy 作为主要构建模块的重要原因。

安装 Numpy

*# pip2 install numpy**Collecting numpy**Using cached numpy-1.12.1-cp27-cp27mu-manylinux1_x86_64.whl**Installing collected packages: numpy**Successfully installed numpy-1.12.1*

强烈建议使用 Anaconda 发行版安装 Python,以确保所有底层依赖项( 如线性代数库 )都与 conda 安装同步。

如果你有康达安装【https://www.continuum.io/downloads】T21

*conda install numpy*

Numpy 数组是我们使用 Numpy 的主要原因,它们有两种类型

  • 向量(一维数组)
  • 矩阵(二维数组)
*# 1-D Array**>>> test = [1,2,3]**>>> import numpy as np**# We got the array
>>> np.array(test)**array([1, 2, 3])**>>> arr = np.array(test)*

我们来看看 二维数组

*>>> test1 = [[1,2,3],[4,5,6],[7,8,9]]**>>> test1**[[1, 2, 3], [4, 5, 6], [7, 8, 9]]**>>> np.array(test1)**array([[1, 2, 3],**[4, 5, 6],**[7, 8, 9]])*

但是生成 NumPy 数组最常见的方法是使用range函数(类似于 Python 中的 range)

*#Similar to range(start,stop,step),stop not included and indexing start with zero 
>>> np.arange(0,10)**array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])*

但是如果我们在寻找特定类型的数组

*>>> np.zeros(3)**array([ 0., 0., 0.])**#We are passing Tuple where* ***first value represent row*** *and* ***second represent column****>>> np.zeros((3,2))**array([[ 0., 0.],**[ 0., 0.],**[ 0., 0.]])*

类似的还有那些

*>>> np.ones(2)**array([ 1., 1.])**>>> np.ones((2,2))**array([[ 1., 1.],**[ 1., 1.]])*

现在我们来看看linspace

*#It will give 9 evenly spaced point between 0 and 3(It return 1D vector)
>>> np.linspace(0,3,9)**array([ 0\. , 0.375, 0.75 , 1.125, 1.5 , 1.875, 2.25 , 2.625, 3\. ])**>>> np.linspace(0,10,3)**array([  0.,   5.,  10.])*

让我们创建 单位矩阵 (二维方阵,其中行数等于列数,对角线为 1)

创建数组 随机数

*#1-D, it create random sample uniformly distributed between 0 to 1
>>> np.random.rand(3)**array([ 0.87169008, 0.51446765, 0.65027072])**#2-D
>>> np.random.rand(3,3)**array([[ 0.4217015 , 0.86314141, 0.14976093],**[ 0.4348433 , 0.68860693, 0.88575823],**[ 0.56613179, 0.56030069, 0.51783999]])*

现在如果我想要 随机整数

*#This will give random integer between 1 and 50
>>> np.random.randint(1,50)**27**#In case if we need 10 random integer
>>> np.random.randint(1,50,10)**array([39, 34, 30, 21, 18, 30,  3,  6, 37, 11])*

我们可以 重塑 我们现有的阵列

*>>> np.arange(25)**array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,**17, 18, 19, 20, 21, 22, 23, 24])**>>> arr = np.arange(25)**>>> arr**array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,**17, 18, 19, 20, 21, 22, 23, 24])**>>> arr.reshape(5,5)**array([[ 0, 1, 2, 3, 4],**[ 5, 6, 7, 8, 9],**[10, 11, 12, 13, 14],**[15, 16, 17, 18, 19],**[20, 21, 22, 23, 24]])*

让我们来看看其他一些方法

*>>> np.random.randint(0,50,10)**array([10, 40, 18, 30, 6, 40, 49, 23, 3, 18])**>>> ranint = np.random.randint(0,50,10)**>>> ranint**array([18, 49, 6, 28, 30, 10, 46, 11, 40, 16])**#It will return* ***max value*** *of the array
>>> ranint.max()**49****#Minimum value*** *>>> ranint.min()**6**>>> ranint**array([18, 49,  6, 28, 30, 10, 46, 11, 40, 16])**#To find out the position
>>> ranint.argmin()**2**>>> ranint.argmax()**1*

找出一个数组的形状

*>>> arr.shape**(25,)**>>> arr.reshape(5,5)**array([[ 0, 1, 2, 3, 4],**[ 5, 6, 7, 8, 9],**[10, 11, 12, 13, 14],**[15, 16, 17, 18, 19],**[20, 21, 22, 23, 24]])**>>> arr = arr.reshape(5,5)**>>> arr.shape**(5, 5)*

找出 的数据类型

*>>> arr.dtype**dtype(‘int64’)*

NumPy 情况下的分度

*>>> import numpy as np**>>> arr =np.arange(0,11)**>>> arr**array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])**>>> arr[0]**0**>>> arr[0:4]**array([0, 1, 2, 3])*

Numpy 数组与 Python 列表的不同之处在于它们的广播能力

*>>> arr[:] = 20**>>> arr**array([20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20])**# Now let's try to slice this array**>>> arr1 = arr[0:5]**>>> arr1**array([0, 1, 2, 3, 4])**>>> arr1[:] = 50**>>> arr1**array([50, 50, 50, 50, 50])**#But as you can see the side effect it change the original array too(i.e data is not copied it's just the view of original array)* ***>>> arr******array([50, 50, 50, 50, 50,  5,  6,  7,  8,  9, 10])****#If we want to avoid this feature, we can copy the array and then perform broadcast on the top of it**>>> arr2 = arr.copy()**>>> arr2**array([50, 50, 50, 50, 50,  5,  6,  7,  8,  9, 10])**>>> arr2[6:10] = 100**>>> arr2**array([ 50,  50,  50,  50,  50,   5, 100, 100, 100, 100,  10])**>>> arr**array([50, 50, 50, 50, 50,  5,  6,  7,  8,  9, 10])*

索引 二维数组(矩阵)

*>>> arr = ([1,2,3],[4,5,6],[7,8,9])
>>> arr**([1, 2, 3], [4, 5, 6], [7, 8, 9])**>>> arr1 = np.array(arr)**>>> arr1**array([[1, 2, 3],**[4, 5, 6],**[7, 8, 9]])**>>> arr[1]**[4, 5, 6]**# To grab 5(Indexing Start with zero)**>>> arr1[1][1]**5**#Much shortcut method
>>> arr1[1,1]**5*

从二维数组中抓取元素

*>>> arr**array([[1, 2, 3],**[4, 5, 6],**[7, 8, 9]])**#This will grab everything from Row 1 except last element(2) and staring from element 1 upto the end from Row 2* *>>> arr[:2,1:]**array([[2, 3],**[5, 6]])*

条件选择 :这样会返回布尔值

*>>> arr**array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])**>>> arr > 5**array([False, False, False, False, False, True, True, True, True, True], dtype=bool)**# We can save this value to an array and perform boolean selection**>>> my_arr = arr > 5**>>> my_arr**array([False, False, False, False, False,  True,  True,  True,  True,  True], dtype=bool)**>>> arr[my_arr]**array([ 6,  7,  8,  9, 10])****#OR much easier way****>>> arr[arr > 5]**array([ 6,  7,  8,  9, 10])**>>> arr[arr < 5]**array([1, 2, 3, 4])*

操作

*# It's the same operation as we are doing with Normal Python**>>> arr = np.arange(0,10)**>>> arr**array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])**>>> arr**array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])****#Addition*** *>>> arr + arr**array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])****#Substraction*** *>>> arr — arr**array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])****#Multiplication*** *>>> arr * arr**array([ 0, 1, 4, 9, 16, 25, 36, 49, 64, 81])****#Broadcast(It add's/substract/multiply 100 to each element)*** *>>> arr + 100**array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109])**>>> arr - 100**array([-100,  -99,  -98,  -97,  -96,  -95,  -94,  -93,  -92,  -91])**>>> arr * 100**array([  0, 100, 200, 300, 400, 500, 600, 700, 800, 900])*

在 Python 的情况下,如果我们试图用零除一,我们将得到被零除的异常

*>>> 0/0**Traceback (most recent call last):**File "<stdin>", line 1, in <module>**ZeroDivisionError: division by zero****OR****>>> 1/0**Traceback (most recent call last):**File “<stdin>”, line 1, in <module>**ZeroDivisionError: division by zero*

在 Numpy 的情况下,如果我们试图除以零,我们不会得到任何异常,但它会返回nan(不是一个数字)

*#Not giving you 
>>> arr/arr**__main__:1: RuntimeWarning: invalid value encountered in true_divide**array([* ***nan****, 1., 1., 1., 1., 1., 1., 1., 1., 1.])*

如果被零除,它将返回 无穷大

*>>> 1/arr**array([* ***inf****, 1\. , 0.5 , 0.33333333, 0.25 ,**0.2 , 0.16666667, 0.14285714, 0.125 , 0.11111111])*

万能数组功能

*#Square root
>>> np.sqrt(arr)**array([ 0\. , 1\. , 1.41421356, 1.73205081, 2\. ,**2.23606798, 2.44948974, 2.64575131, 2.82842712, 3\. ])**#Exponential
>>> np.exp(arr)**array([ 1.00000000e+00, 2.71828183e+00, 7.38905610e+00,**2.00855369e+01, 5.45981500e+01, 1.48413159e+02,**4.03428793e+02, 1.09663316e+03, 2.98095799e+03,**8.10308393e+03])**#Maximum
>>> np.max(arr)**9**#Minimum
>>> np.min(arr)**0**#Logarithmic
>>> np.log(arr)**__main__:1: RuntimeWarning: divide by zero encountered in log**array([       -inf,  0\.        ,  0.69314718,  1.09861229,  1.38629436,**1.60943791,  1.79175947,  1.94591015,  2.07944154,  2.19722458])*

遗传算法优化导论

原文:https://towardsdatascience.com/introduction-to-optimization-with-genetic-algorithm-2f5001d9964b?source=collection_archive---------1-----------------------

为机器学习任务选择最佳参数是具有挑战性的。一些结果可能不是因为数据有噪声或者所使用的学习算法弱,而是因为参数值的错误选择。本文简要介绍了进化算法,并描述了一种最简单的基于随机的进化算法&遗传算法。

From Pixabay by qimono

简介

假设一位数据科学家将一个图像数据集划分为多个类别,并且要创建一个图像分类器。在数据科学家研究了数据集之后,K-最近邻(KNN)似乎是一个不错的选择。为了使用 KNN 算法,有一个要使用的重要参数是 k。假设选择了初始值 3。科学家从选定的 K=3 开始 KNN 算法的学习过程。生成的训练模型达到了 85%的分类准确率。这个百分比可以接受吗?换句话说,我们能得到比目前更好的分类精度吗?在进行不同的实验之前,我们不能说 85%是最佳精度。但是要做另一个实验,我们必须改变实验中的一些东西,比如改变 KNN 算法中使用的 K 值。我们不能肯定地说 3 是在这个实验中使用的最佳值,除非尝试对 K 应用不同的值并注意分类准确度如何变化。问题是“如何找到使分类性能最大化的 K 的最佳值?”这就是所谓的优化。

在最优化中,我们从实验中使用的变量的某种初始值开始。因为这些值可能不是最好的,所以我们应该改变它们,直到得到最好的值。在某些情况下,这些值是由复杂的函数生成的,我们无法轻松地手动求解。但是进行优化是非常重要的,因为分类器可能产生差的分类精度,这不是因为例如数据有噪声或者所使用的学习算法弱,而是由于学习参数初始值的差的选择。因此,运筹学(OR)研究人员提出了不同的优化技术来完成这种优化工作。根据[1],优化技术分为四个主要类别:

  1. 约束优化
  2. 多模态优化
  3. 多目标优化
  4. 组合最优化

观察各种自然物种,我们可以注意到它们是如何进化和适应环境的。我们可以从这种已经存在的自然系统及其自然进化中受益,来创造我们的人工系统做同样的工作。这叫仿生学。例如,飞机是基于鸟类如何飞行,雷达来自蝙蝠,潜艇是基于鱼类发明的,等等。因此,一些优化算法的原理来自自然。比如遗传算法(GA),其核心思想来自查尔斯·达尔文的自然进化论“适者生存”。

在进入遗传算法工作的细节之前,我们可以对进化算法有一个总体的了解。

进化算法

我们可以说,优化是使用进化算法(EAs)执行的。传统算法和进化算法的区别在于进化算法不是静态的,而是动态的,因为它们可以随着时间的推移而进化。

进化算法有三个主要特征:

  1. 基于群体的:进化算法是优化一个过程,在这个过程中,当前的解决方案是不好的,以产生新的更好的解决方案。从中产生新解的当前解的集合称为群体。
  2. 健身导向:如果有几个方案,怎么说一个方案比另一个方案好?从适应度函数计算出的每个单独的解决方案都有一个相关的适应度值。这样的适应值反映了解决方案有多好。
  3. 变异驱动:如果根据每个个体计算出的适应度函数,在当前种群中没有可接受的解,我们就要做出一些东西来生成新的更好的解。因此,单个解决方案将经历许多变化以生成新的解决方案。

我们将转到正式发布并应用这些条款。

遗传算法

遗传算法是一种基于随机的经典进化算法。这里的随机是指为了使用 GA 找到一个解决方案,对当前解决方案进行随机更改以生成新的解决方案。请注意,遗传算法可以被称为简单遗传算法(SGA),因为它比其他进化算法简单。

遗传算法是基于达尔文的进化论。这是一个缓慢渐进的过程,通过做出微小而缓慢的改变来实现。此外,遗传算法缓慢地对其解进行细微的改变,直到得到最佳解。

下面是遗传算法工作原理的描述:

GA 处理由一些解组成的群体,其中群体大小(popsize)是解的数量。每个解决方案都被称为个体。每个溶液都有一条染色体。染色体被表示为定义个体的一组参数(特征)。每条染色体都有一组基因。每个基因都以某种方式表示,比如表示为一串 0 和 1,如图 1 所示。

Figure 1. Chromosome and gene.

而且,每个个体都有一个适合度值。为了选择最佳个体,使用适应度函数。适应度函数的结果是代表解的质量的适应度值。适应值越高,解决方案的质量越高。基于质量的最佳个体的选择被用于产生所谓的交配池,其中质量较高的个体在交配池中被选择的概率较高。

交配池中的个体被称为父母。从交配池中选出的每两个父母将产生两个后代(孩子)。仅仅通过优质个体的交配,就有望获得比其父母更优质的后代。这将杀死不良个体,防止产生更多的不良个体。通过不断选择和交配高质量的个体,将有更高的机会只保留个体的良好特性,而忽略不好的特性。最后,这将以期望的最优或可接受的解决方案结束。

但是目前使用所选择的父母产生的后代仅仅具有其父母的特征,而没有更多变化。没有新的东西加入其中,因此它的双亲中的同样的缺点实际上会存在于新的后代中。为了克服这样的问题,一些变化将被应用于每个后代以产生新的个体。所有新生成的个体的集合将是替换先前使用的旧群体的新群体。每创造一个群体称为一代。新人口取代旧人口的过程称为更替。图 2 总结了 GA 的步骤。

Figure 2. Genetic algorithm steps.

要全面了解 GA,需要回答两个问题:

  1. 两个后代是如何从双亲中产生的?
  2. 每一个后代是如何稍微改变成为一个个体的?

这些问题我们以后再来回答。

染色体表示和评估

染色体有不同的表示法,选择正确的表示法要视具体问题而定。好的表示使搜索空间更小,从而更容易搜索。

可用于染色体的表示包括:

二进制:每个染色体被表示为一串 0 和 1。

排列:适用于排序问题,如旅行商问题。

:实际值按原样编码。

例如,如果我们用二进制编码数字 7,它可能如图 3 所示。

Figure 3. Binary encoding example.

上述染色体的每一部分被称为基因。每个基因都有两种特性。第一个是它的值(等位基因),第二个是在染色体内的位置(基因座),它是高于它的值的数字。

每条染色体有两种表现形式。

  1. 基因型:代表染色体的一组基因。
  2. 表现型:染色体的实际物理表现。

在上面的例子中,0111 的二进制是基因型,7 是表型表示。

在用正确的方式表示每个染色体后,用来搜索空间,接下来是计算每个个体的适应值。假设我们示例中使用的适应度函数为:

f(x)=2x+2

其中 x 是染色体值

那么前一个染色体的适应值是:

f(7)=2(7)+2=16

计算染色体适应值的过程称为评估。

初始化

在获得如何表示每个个体之后,下一步是通过在群体中选择适当数量的个体来初始化群体。

选择

下一步是从交配池的种群中选择一些个体。基于先前计算的适应值,基于阈值的最佳个体被选择。在这一步之后,我们将结束选择交配池中种群的子集。

变异算子

基于交配池中选择的个体,选择亲本进行交配。每两个亲本的选择可以通过依次选择亲本(1-2、3-4 等)来进行。另一种方法是随机选择父母。

对于每两个选定的父代,都有许多变异运算符要应用,例如:

  1. 交叉(重组)
  2. 变化

图 4 给出了这些操作符的一个例子。

Figure 4. Crossover and mutation.

交叉

遗传算法中的交叉与自然变异一样产生新的一代。通过改变老一代父母,新一代的后代携带父母双方的基因。每个父母携带的基因数量是随机的。记住 GA 是基于随机的 EA。有时后代从父母一方获得一半基因,从另一方获得另一半基因,有时这种百分比会发生变化。对于每两个亲本,通过选择染色体中的随机点并交换亲本该点前后的基因来进行交叉。产生的染色体就是后代。因此算子被称为单点交叉。

请注意,交叉很重要,没有它,后代将与其父代相同。

突变

下一个变异算子是变异。对于每个后代,选择一些基因并改变其值。突变因染色体表现形式而异,但如何应用突变取决于您。如果编码是二进制的(即每个基因的值空间只有两个值 0 和 1),则翻转一个或多个基因的位值。

但如果基因值来自 1、2、3、4、5 等两个以上值的空间,那么二元突变就不适用,我们应该另寻他法。一种方法是从如图 5 所示的一组值中选择一个随机值。

Figure 5. Mutation by randomly updating some genes.

请注意,如果没有突变,后代将具有其父母的所有特性。为了给这样的后代增加新的特征,基因发生了突变。但是因为突变是随机发生的,所以不建议增加应用于突变的基因数量。

突变后的个体称为突变体。

参考

[1]艾本、阿戈斯顿和詹姆斯·史密斯。进化计算导论。第 53 卷。海德堡:施普林格,2003 年。

原文在 LinkedIn 可在此链接:https://www . LinkedIn . com/pulse/introduction-optimization-genetic-algorithm-Ahmed-gad

在 KDnuggets 上也分享到了这个链接:https://www . kdnugges . com/2018/03/introduction-optimization-with-genetic-algorithm . html

联系作者:

领英:【https://linkedin.com/in/ahmedfgad

电子邮件:ahmed.f.gad@gmail.com

介绍我们的放射学/人工智能系列

原文:https://towardsdatascience.com/introduction-to-our-radiology-ai-series-51d0e54cd3b9?source=collection_archive---------17-----------------------

Photo by rawpixel on Unsplash

放射科医生的机器学习介绍— 10 部分系列

第一部

作者: 达尼洛泰·瓦雄

编辑: 迈克尔博士

在 2017 年,Kaggle 数据科学碗旨在使用机器学习和人工智能来抗击美国男性和女性癌症死亡的主要原因。参赛者被要求使用成千上万张高分辨率肺部 CT 图像的数据集来创建新的肺癌检测算法。这些算法是为了提高诊断和减少假阳性率。

在 394 个参赛队中,哪个队获得了头奖?一个由中国清华大学医学和计算机科学系成员组成的团队。

诸如此类的比赛是将国际人才与全球问题结合起来的好方法。这种团队合作的风格仅仅是通过医学专业人员和计算机科学之间的互动,在我们的领域内的无限发展潜力的皮毛。

在放射学培训中,我们了解到一个 3 厘米长、呈毛刺状、软组织变薄的肺部肿块很有可能是癌症。同样,一个 5 毫米的光滑钙化结节患癌的概率也很低。

然而,我们也知道许多肺结节介于我们准确预测恶性肿瘤的能力之间。弗莱舍纳协会非常努力地在 2017 年更新了后续标准,提供了一个解决方案,其中包括大小和密度的变化。然而,我们仍然不能看着一个 8 毫米的边缘稍微不规则的结节就说它有多大可能是癌症。

为了使 Kaggle 竞赛更进一步,Fleischner 标准(或其替代标准)非常有可能是非常可定制的,肺结节跟踪将得到改善。我们将在第 2 篇文章中对此进行更深入的探讨。

这些团队在脸书的面部识别背后使用了类似的技术。你有没有想过他们怎么能确定你照片里的人是谁?这项技术被称为深度学习,是机器学习的子集,也是人工智能的子集,我们也会在第 3、5、6 篇文章中更深入地探讨这些话题。

这些努力证明了开源社区,以及人们如何决心通过合作和共享数据来找到重要问题的新颖解决方案。

让我们采取相反的观点,机器学习和人工智能可能预示着放射学专业的过时。我想起了杰弗里·辛顿教授。

杰弗里·辛顿是个非常聪明的家伙,但他缺乏关于放射学专业的细微差别的医学训练,如图像引导活检、肿瘤板和与我们外科同事的讨论等。,也许让他对我们的职业只有一个肤浅的看法。放射科医生的工作将随着新工具的出现而改变,但只要我们继续帮助我们的临床同事,他们的工作就会一直存在。

Kaggle 竞赛的结果也得益于时间和可用资源。由于巨大的视频游戏市场,我们第一次有了经济高效的高性能计算,称为图形处理单元(GPU)。详见第三条。另一个我们可能想当然的领域是语音识别。虽然我们可能看到也可能看不到每天的改善,但在过去的十年里,情况确实有所改善。详见第 4 条。

这个难题的另一个非常重要的部分是数据。大量数据。大量数据被正确标记。美国放射学院(ACR)和斯坦福大学目前正在进行这方面的研究。详见第五条。(或者 7)。

计算机科学家和医学专家的合作团队在开发改变领域的算法方面有着惊人的潜力。但是,当我们谈论将这些技术融入我们的日常工作流程,或者在隐私或数据管理的背景下,请注意。详见第八条。

在我们继续之前,我们想正式介绍一下我们自己。

泰·瓦雄

这是旨在指导我的同事的 10 篇系列文章中的第一篇。自 2012 年以来,我一直在跟踪人工智能和医疗应用的发展,并追随德雷耶博士和米哈尔斯基博士等伟大的导师。信息学,尤其是医学图像的利用,是我背景的很大一部分。在海军陆战队担任飞行外科医生后,我在美国海军接受了放射学培训。我的最后一次海军之旅是在冲绳,包括一次放射科主任之旅,之后我完成了我的海军使命,并作为天使投资人、企业家、信息学顾问和咨询顾问返回圣地亚哥。在撰写本文时,我还没有关于这个系列的相关财务披露。”

达尼洛·佩纳

“我有化学工程背景,做过两年工程师。在工作期间,我意识到我需要对社会产生更大的影响,我也想学习编码。因此,我申请了学校,被录取了,然后辞去了工作。我目前是休斯顿德克萨斯大学健康科学中心的生物医学信息学硕士生,也是艾伯特-史怀哲研究员。我总是在学习,我很高兴能帮助别人学习我所知道的。我希望通过这一系列文章,从医疗领域到机器学习领域的人们,乃至普通人,都可以利用这些信息来了解放射学的当前格局及其与人工智能技术进步的关系。”

我们相信,通过我们不同但互补的技能组合,我们可以在这个令人兴奋的领域教育他人。

既然你对我们有所了解,你可能会问为什么你要花时间在我们的系列节目上。

在本系列中,我们将从慢开始,回顾关键术语。我们还将讨论足够多的近期历史进展,以提供背景和应对新趋势。如果你更高级一点,请在评论中提供来自个人经历的清晰想法。当然,如果你注意到任何错误的文字,我们也会虚心审查这些评论。

本系列并不打算面面俱到,但这些文章旨在为放射学和人工智能提供公平的竞争环境。这个领域变化很快,有很多移动的部分。我们正在尽自己的一份力量通过这一过程进行教育和学习。

加入我们一组有趣的文章,这些文章由一位经验丰富的放射科医生策划,他专注于技术,是一名对理解 ML 和 AI 将如何影响下一代医疗保健感兴趣的学生。

第二部分——放射学和人工智能将如何走到一起

语法演变的 PonyGE2 介绍

原文:https://towardsdatascience.com/introduction-to-ponyge2-for-grammatical-evolution-d51c29f2315a?source=collection_archive---------1-----------------------

语法进化是算法优化的一种强有力的方法。给定一个目标函数和一个搜索空间(语法),有可能使用进化计算方法来进化一个算法,以最优地(或至少有效地)最大化目标函数。

PonyGE2 是 Python3 的一个实现,它让 GE 变得简单。本演练讨论了 GE 的优点和缺点,并提供了一个如何用 GE 改进您自己的算法的示例。一篇全面描述 PonyGE2 运作的论文可以在这里找到。

不幸的是,在当前计算机上用 PonyGE2 进行语法进化还不够快,不能在合理的时间内从大量语法中进化出函数,但这种技术肯定是未来需要关注的。

语法演变

这种方法最初是由的迈克尔·奥尼尔(付费墙)博士在 2001 年提出的,作为一种将进化计算方法应用于具有正式语法结构的问题的方式,比如算法。

一个正式的语法可以被认为是定义一种语言的一套规则,或者仅仅是一种规定什么样的单词组合有意义的官方方式。在英语中,我们在学说话时从父母那里学到这些,在学校里也是如此。学习第二语言时,通常可以分为两个步骤:

  1. 学习词汇
  2. 学习语法

编程并没有太大的不同,编程语言之间的主要区别不是你试图实现什么,而是你如何告诉计算机去做。

那么我们如何向计算机教授语法呢?那么这些词是如何用于进化优化的呢?

这个过程大概是这样的:

  1. 定义语法的巴克斯诺尔形式(BNF)表示;
  2. 随机生成线性染色体来编码信息;
  3. 通过将语法映射到染色体并对照适应度函数进行测试来评估染色体的适应度;
  4. 使用交叉、变异、繁殖等遗传算子生成下一代染色体;
  5. 重复第 3 步和第 4 步一定数量的世代。

巴克斯诺尔形式

BNF 语法是一种编写计算机可以理解的语法的方式(上下文无关)。在 Python 中,它由包含 4 个集合的元组表示:

  • t:终端设备
  • n:非终结集
  • 生产规则集
  • s:开始符号(是 N 的成员)。

这可能不能澄清事实,但是记住这一点是有好处的。让我们看一个例子:

T = {+, -, /, *, x, y}

所以终端集是你想在程序中使用的所有操作符和变量的集合。

N = {<e>, <o>, <v>}

非终结集是程序可以承担的所有生产活动的集合。在这种情况下,<e>是一个表达式,<o>是一个运算符,<v>是一个变量。

P接下来是生产规则的设定:

<e> ::= <e><o><e> | <v>
<o> ::= + | - | / | *
<v> ::= x | y

注意,P中的所有条目都是TN的条目。管道操作符|代表or。因此,当在染色体中遇到<e>时,它要么被替换为<e><o><e>,要么被替换为<v>,对于<o><v>也是如此。

最后,开始符号:

S = <e>

这可能仍然很令人困惑,但是在评估染色体时,以这种形式表示语法的原因变得很明显。

染色体

描述染色体最简单的方式是作为一个非负整数数组。值并不重要,但长度很重要(稍后会详细介绍)。

举个例子,我们称我们的染色体为:

C: [4, 15, 75, 8, 41, 12]

将染色体映射到语法

现在一切都在一起了。记得我们的开始符号是:

<e>

现在,根据我们的生产规则P,当遇到一个<e>时,要么用<e><o><e>替换,要么用<v>替换。但是我们怎么知道是哪一个呢?染色体告诉我们。染色体的第一个值是4,产生式规则中有<e>2选项。4 mod 20,所以我们从产生式规则<e><o><e>中取第0 -th(零索引,所以真的是1 -st 条目)选项。

所以现在我们的表达式已经扩展到了<e><o><e>,我们正在评估第一个条目<e>(因为它不是终端集的成员,所以我们一直评估每个条目,直到它被终端集的成员替换)。

我们知道在产生式规则中有<e>2选项,所以我们取染色体中的第二个条目15,并且15 mod 2给出了1,所以我们从产生式规则<v>中取第一个(零索引,所以实际上是第二个条目)选项。

我们继续以下步骤:

  • 完整表达式:<v><o><e>
    当前表达式:<v>
    语法中<v>选项个数:2
    染色体值:75``75 mod 2 = 1
    y替换<v>
  • 完整表达式:y <o><e>
    当前表达式:<o>
    语法中<o>选项个数:4
    染色体值:8
    8 mod 4 = 0
    +替换<o>
  • 完整表达式:y + <e>
    当前表达式:<e>
    语法中<e>选项个数:2
    染色体值:41
    41 mod 2 = 1
    <v>替换<e>
  • 完整表达式:y + <v>
    当前表达式:<v>
    语法中<v>选项个数:2
    染色体值:12
    12 mod 2 = 0
    x替换<v>

最终表情:y + x

所以我们已经用我们的语法表示把我们的染色体(数组)变成了一个函数!请随意重读几遍,因为理解表达式和运算符的来源需要一些时间。

评估适应度函数

现在我们有了一个语法上正确的函数,我们可以根据一些适应度函数来评估这个函数的性能。那些表现良好的功能有更大的机会将它们的 DNA 传递给下一代染色体。从这一点来看,GE 与其他遗传算法没有太大的不同,因为染色体被交叉和变异以产生下一代染色体,然后这些染色体被映射到语法并根据适应度函数进行测试。

这将持续用户指定的代数,最后将最有效的(适应度函数的最佳分数)算法返回给您。

通用电气公司分析

现在你(希望)对语法进化有了更多的了解,你可能会问为什么它这么好?

首先是快,真的快。通过代代相传信息,它大大改进了随机搜索。

其次,因为语法是你写的,你可以很容易地将领域知识编码到函数中。你可能会经常听到这种说法,并问“这到底是什么意思?”(我知道我有)。以下是一些例子:

  • 允许访问你所有的信息,不管它是否有用。这可以通过在语法中使用一个<v>表达式来实现,并且包含你想要的所有变量。
  • 根据需要使程序尽可能复杂或简单。在<e>中包含许多选项(包括重复的选项,以改变特定操作符被选中的机会)允许容易地操纵进化程序的复杂性。
  • 通过设置<n> ::= 0|1|2|3|4|5|6|7|8|9然后<const> ::= <n><n><n>.<n><n><n>来定义常量的精度等级,设置精度为 3 位小数的 0 到 999 之间的常量。
  • 包含表达式包含<fn>(<e>)<fn> ::= sin | max的函数

这一切都很酷,但通用电气也有一些缺点。首先,如上所述,染色体的长度确实会导致程序无效。对于上面的例子,如果染色体中的倒数第二个条目是 42 而不是 41,那么<e>将被替换为<e><o><e>,但是没有留下染色体数据来评估这些表达式。由于该染色体无效,因此不能根据适应度函数对其进行评估。因此,虽然一条染色体可能包含接近好的解决方案,但它永远不会为人所知。

与此相反的是,程序进化时没有使用整个染色体。剩余的数据称为尾部,可以忽略。因此,通常最好将染色体构造为长尾,因为这可以减少无效解出现的机会。

然而,可能最大的缺点是,语法必须非常非常仔细地构建,为问题构建适当的语法和适应度函数需要一点艺术。除此之外,“大”语法可能需要很长时间才能进化。包括单级 for 循环、if 语句、列表函数和字典操作的语法可能需要 12 个小时以上才能完成。希望这在未来会有所改善,但这是阻止语法进化取代人类代码优化器的主要原因吗…

所以现在你有希望对语法演变有更多的了解,我们可以尝试在 PonyGE2 中实现一个简单的例子。

PonyGE2

PonyGE2 可以从这里克隆或者分叉。不需要任何设置,演化将从带有适当参数的命令行运行。

研究这个包的最好方法是通过一个例子来完成。我们将尝试开发一个函数来查找列表中的最大值。这很容易在 Python 中用max()或函数实现:

for val in list:
    if val >= current_max:
        current_max = val

第一步是创建一个适应度函数,或者我们想要最大化或最小化的函数。这里的术语有点混乱,因为我们正在进化一个函数,其结果将优化适应度函数。目前我们只是在讨论适应度函数。

这些例子的所有代码都包含在 https://github.com/Padam-0/NC-GA 的中

PonyGE2/src/fitness中有很多例子,要运行你自己的,在那个文件夹中创建一个名为max_in_list.py的文件,结构如下:

*from* fitness.base_ff_classes.base_ff *import* base_ff
import random
import time*class* max_in_list(base_ff):
    *def* __init__(self):
        # Initialise base fitness function class.
        super().__init__() *def* evaluate(self, *ind*, ***kwargs*):
        p = *ind*.phenotype print("\n" + p) fitness = 0 for trial in range(50):
            self.test_list = generate_list()
            m = max(self.test_list) d = {'test_list': self.test_list} *try*:
                t0 = time.time()
                exec(p, d)
                t1 = time.time() guess = d['return_val'] fitness += len(p) v = abs(m - guess)
                if v <= 10**6:
                    fitness += v
                else:
                    fitness = self.default_fitness
                    break if t1 - t0 < 10:
                    fitness = self.default_fitness
                    break
                else:
                    fitness += (t1 - t0) * 1000 *except*:fitness = self.default_fitness
                break return fitness *def* generate_list():
    return [random.randint(0, round(random.random() * 90 + 10, 0)) for i in range(9)]

让我们一行一行地来。

第 1–3 行:

  • 进口。base-ff是我们将要继承的类,random 用于生成随机列表,time 用于跟踪执行时间

第 5 行:

  • 定义类,max_in_list,继承自base_ff。这需要与您正在处理的文件同名(在本例中是max_in_list.py)。

第 6–9 行:

  • 该类的实例初始化信息。

第 10 行:

  • 创建带有三个参数的evaluate函数,self、ind 和 kwargs。

到目前为止,这是每个健身功能的标准配置。下一步是独立于每一个正在进化的算法。

第 11–13 行:

  • 从进化中返回当前算法作为p。我们可以将它打印到命令行(如我们在第 13 行中所做的那样),并查看它。

第 15 行:

  • 将适应性初始化为0

第 17 行:

  • 将 for 循环设置为运行 50 次。如果我们不这样做,每个算法将运行在同一个“随机”列表上,并可能演化出一行,如随后返回的m=4949可能恰好在那个列表里,而且是最大值,所以计算机认为找到了完美的算法。短、快、准!但是对于这个例子来说。在任何其他列表中,如果49不在其中(或者不是最大值),那么算法就是错误的。因此,我们给出了适应度函数的 50 个列表,每个列表都有不同的值(实际上是最大可能值),以避免过度适应。

第 18 行:

  • 从函数generate_list()创建随机列表self.test_list
  • 跳到最后几行,这个函数在0之间生成 10 个随机整数,以及 10 到 100 之间的某个数字。这是避免过度拟合的最好方法。

第 19 行:

  • 找出当前使用列表的最大值。重要的是在这里完成,而不是在算法执行之后,因为在执行过程中列表可能会改变(如果语法中已经包含列表操作),所以可能不会返回正确的结果。
  • 此时你可能(正确地)会问,如果我们已经有了一个函数来寻找列表的最大值,那么做这些有什么意义呢?这是一个很好的问题,通用电气的重点是找到一种潜在的更有效的方法来做到这一点。对于简单的函数来说,这并不值得,但却是一个很好的学习练习。

第 21 行:

  • 创建一个字典d,其中有一个条目test_list,用于保存当前列表。这在我们写语法的时候会更有意义。

第 23/45–47 行:

  • Try/Except 语句。一般来说,拥有一个开放式 Except 语句不是一个好主意,因为你永远不会捕捉到错误,但在这种情况下,所有错误都可能发生在进化的算法中(因为它只是半随机地将单词放在一起,所以它们不可能都是完美的代码),所以该语句是合理的。
  • 如果返回一个错误,该算法的适合度被设置为默认值(NA ),循环被中断,下一个算法被测试。

第 24 行:

  • 获取开始时间。

第 25 行:

  • 执行算法p并在d内传递参数,以便可以访问它们。这是实际评估算法的地方。返回的值作为return_val写入字典d(我们在语法中定义了这一点)。

第 26 行:

  • 获取结束时间。

第 28 行:

  • 从当前算法中检索最大值猜测。

第 30 行:

  • 将当前适应度分数增加算法的长度。这是为了避免臃肿和不必要的 if 语句。进化试图让事情尽可能的短。

第 32 行:

  • 求列表的实际最大值和猜测值之差。最好的情况是这是0,但如果不是,这是一个算法如何接近得到正确答案的代理。

第 33–37 行:

  • 有一些算法可能会产生完全超大的猜测,这将破坏进化,所以最好保留一个 if 语句来检查值是否高于某个永远不可行的大(但不太大)数。
  • 同样,如果该检查失败,则将适应度设置为 NA,并继续下一个算法。否则,将猜测值和正确值之间的差加到当前的适应性分数上。

第 39–43 行:

  • 一些算法(具有多层 for 循环,或for i in range(1000)语句)需要很长时间来评估。除非这是预期的,否则这表示有错误,因此建议使用 if 语句来捕获那些花费了更多时间(在本例中为 10 秒)的错误。
  • 如果算法花费的时间少于此,则可以将该时间添加到适应度分数中,这样,工作更快的算法将获得较低的适应度。由于时间尺度很小,建议将这部分分数放大 100 或 1000 倍。

第 49 行:

  • 还健身,就完事了!

有很多东西需要理解,有一些可能没有意义,但我们会继续写语法,希望有了完整的描述,会更清晰一些。

语法

这是困难的部分,因为你必须对你写的东西非常精确和深思熟虑。我们将逐步介绍发展 max 函数所需的基本语法,但是包括附加逻辑、列表函数和字典函数的语法扩展可在https://github.com/Padam-0/NC-GA获得。

同样,PonyGE2 在 PonyGE2/grammars 目录中提供了语法示例。在那里创建你的(它可以被称为任何东西,但是给它扩展名.pybnf)。

第一行包含程序的起点:

<fc> ::= <deff>{::}<callf>

用英语来说,这表示:

  • <fc>是起始符号,包含一个选项:<deff>后面跟一个换行符({::}代表换行符,{:是缩进(tab 或 4 个空格):}关闭缩进),后面跟<callf>

下一行,我们定义<deff>:

<deff> ::= def fun(li):{:m = 0{::}<code>{::}return m:}

这看起来有点像 Python。我们可以看到我们有一个名为fun()的函数的函数定义,有一个参数li

接下来我们打开一个缩进(像 Python 要求的那样),初始化我们的变量m=0,开始一个新行,写一些<code>,开始一个新行,返回m,然后关闭缩进。

还是那句话,<deff>只有一个选项,所以这个肯定会写。接下来,<callf>:

<callf> ::= return_val = fun(test_list)

同样,这看起来更像 Python。而且只有一个选项,所以不管染色体如何,我们的算法看起来总是这样:

def fun(li):
    m = 0
    <code>
    return m
return_val = fun(test_list)

<code>部分是进化完成的地方,但是在大多数情况下,我们现在将有一个工作函数。酷嘿!天气变凉了。

还记得在我们的健身函数中,我们给了字典d一个名为test_list的键吗?嗯,因为我们调用了exec(p, d),所以程序可以看到那个字典d的内容,所以当它在算法中看到test_list的时候,就用字典dtest_list对应的值来替换它,或者在我们的例子中,就是我们想要找到的最大值的随机列表!很酷吧,现在我们有办法将数据从我们的适应函数传递到我们的进化函数中。

同样,在我们的适应度函数中,我们设置guess = d['return_val']?事实证明,我们不仅可以从d读取,还可以向它写入,从fun(test_list)返回的值作为return_val传递给d,这样我们就可以在适应度函数中访问进化算法的返回值,这样我们就可以访问它的适应度了!

因此,我们现在可以双向发送数据,我建议重新阅读适应度函数部分,看看这是否更有意义。对我来说绝对是。

至于我们剩下的语法:

<code> ::= <stmt> | <stmt>{::}<code>

代码可以是一条语句,也可以是一条语句后在新的一行上跟随更多的代码。这样我们就可以给自己多线功能了!这种语法的递归性质是非常有用的,将会出现很多,使我们能够增加进化的复杂性。

<stmt> ::= <var> = <expr> | <for> | <if>

然后,语句要么将表达式赋给变量,要么赋给 for 循环,要么赋给 if 语句。让我们以相反的顺序来看这些:

<if> ::= if <cond>:<if-opt>
<if-opt> ::= {:<code>:} | {:<code>:}else:{:<code>:} | {:<code>:}elif <cond>:{:<if-opt>:}<cond> ::= <expr> <c-op> <expr>
<c-op> ::= ">=" | "<=" | ">" | "<"

所以 if 语句接受一个条件,然后是一个选项。条件采用表达式、运算符和表达式的形式。

为了使这一点更清楚,现在有必要讨论一下<expr>标签:

<expr> ::= <number> | <var> | <expr> <op> <expr>

所以一个表达式要么是一个数字,要么是一个变量,要么是一个操作(后面会详细介绍)。

回到我们的 if 语句,我们的条件采用形式if <cond>:,它扩展为:

if <expr> <c-op> <expr>:

然后可以扩展为:

if <var> >= <number>:

我们有一个我们认可的 if 语句。<if-opt>稍微复杂一点,因为它们必须包括elifelse功能,但是它们都归结为一个 if 语句、一个条件,然后一些<code>被写入其中。

接下来,对于循环:

<for> ::= for i in <list-var>:{:<fl-code>:}
<fl-stmt> ::= <var> = <expr> | <fl-if>
<fl-code> ::= <fl-stmt> | <fl-stmt>{::}<fl-code>

因此,for 循环采用形式for i in list:,然后为某个语句创建一个缩进(在新的一行上)。语句本身可能只是我们上面的<stmt>,但是这将允许嵌套 for 循环,这会成倍地增加计算时间。除非您认为嵌套的 for 循环是绝对必要的,否则请避免使用它们(一般来说,这是一个非常好的编程规则)。

所以我们的<fl-stmt>只包括变量赋值,和一个特殊的 if 语句,<fl-if>:

<fl-if> ::= if <cond>:<fl-if-opt>
<fl-if-opt> ::= {:<fl-code>:} | {:<fl-code>:}else:{:<fl-code>:} | {:<fl-code>:}elif <cond>:{:<fl-if-opt>:}

这实际上与上面的 if 语句语法相同,但是它不调用<code>,而是调用<fl-code>,基本上是为了避免 for 循环内部的 if 语句内部出现 for 循环。有点麻烦,但比允许嵌套 for 循环要好!

最后,变量赋值。我们已经看过<expr>,所以让我们看看组成它的零件:

<var> ::= m | i
<list-var> ::= li<number> ::= <num><num><num> | <num><num> | <num>
<num> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9<op> ::= + | - | * | / | // | %

这应该很简单。我们的变量是开始时初始化的m和运行 for 循环时初始化的i。数字可以从 0 到 999,我们有所有的 python 运算符(除了指数运算符,它会导致整数溢出和一大堆执行非常慢的算法。像嵌套的 for 循环一样,只在需要时才包含它)。

信不信由你,这就是我们的语法!让我们看看如何从一个<code>标签到我们的最终函数。像这样的染色体:

[0, 1, 0, 1, 0, 1, 1, 2, 1, 0, 0, 0, 0, 1, 1]

绘制出来后,我们可以得到:

def fun(li):
    for i in li:
        if i > m:
            m = i
return_val = fun(test_list)

太棒了。现在我们有了适应度函数和语法,我们如何用 PonyGE2 运行它呢?

好吧,如果 fitness 函数在 PonyGE2/src/fitness 中(并且与它保存的类具有相同的文件名,在本例中是 max_in_list),并且语法在 PonyGE2/grammars 中,我们可以从命令行运行:

python ponyge.py --fitness_function max_in_list --grammar_file max_in_list.pybnf

这将运行您的语法和健身功能的演变,与其他选项的默认参数。有很多,值得一读参考文献,但两个真正重要的是人口规模和世代数。

群体大小是在开始时产生的染色体的数量,并且在每一代进化。这个数字越大,搜索范围越广,但进化时间越慢。

代数是染色体进化的次数。同样,它扩大了搜索范围,但以进化速度为代价。

您可以通过以下方式设置这些参数:

python ponyge.py --fitness_function max_in_list --grammar_file MIL_e2.pybnf --population_size 500 --generations 100

现在,对于简单的语法,这些参数的值在 100-500 的范围内就足够了,但是随着语法变得更加复杂,它们需要更多的群体和世代来确保进化出足够的算法。一个好的测试是给你的语法增加复杂性,用和上面一样的适应度函数来运行它。如果你得到一个在列表中找到最大值的函数,你可以确信你的参数是合适的,然后把它转换到你要解决的问题的另一个适应度函数上。

不幸的是,运行时间变得很快。对我来说,2000 代和 750 代的人口需要大约 6 个半小时,这不足以用上面的语法进化出一个合适的算法(但也包括列表和字典操作)。

这就是通用电气的问题所在。承诺是,如果你能写一个适应度函数,和一个包含大量 Python 操作的健壮语法,那么 ge 将能进化出一种更有效的做事方式。不幸的是,目前这种处理能力和时间在公共机器上是不可行的。

不管怎样,这是一个值得关注的领域,就像我们要教机器编码一样,很有可能语法进化与此有关。

其他示例

UCD 自然计算研究和应用集团的团队是这项研究的前沿,他们发表了许多展示通用电气力量的伟大论文(尽管是在超级计算机上)。其中包括:

  • 寻找正则表达式的改进性能;
  • 用语法进化优化复杂的桥塔结构;和
  • 结合结构分析和多目标标准的进化建筑设计。

如果你喜欢这篇文章,请点击❤按钮让你的追随者知道,或者让我知道你的想法。

Python 中的功耗分析简介

原文:https://towardsdatascience.com/introduction-to-power-analysis-in-python-e7b748dfa26?source=collection_archive---------2-----------------------

Source: unsplash.com

了解概念的重要性,如显著性水平、效应大小、统计功效和样本大小

如今,许多公司——网飞(T1)、亚马逊(Amazon)、T2()、优步(T3),但也有一些规模较小的——不断进行实验(A/B 测试),以测试新功能并实现那些用户认为最好的功能,最终带来收入增长。数据科学家的角色是帮助评估这些实验,换句话说,验证这些测试的结果是否可靠,是否可以/应该在决策过程中使用。

在本文中,我介绍了功耗分析。简而言之,权力是用来报告从实验结果中得出的结论的可信度。它还可以用于估计实验所需的样本量,,即,在给定的置信度下,我们应该能够检测到一个效应的样本量。实际上,人们可以理解许多事情,例如,在一个组内更频繁的转换,以及在网上商店中经历某一注册流程的顾客的更高的平均花费,等等。

首先,我介绍了一些理论,然后用 Python 实现了一个功耗分析的例子。你可以在文末找到我回购的链接。

简介

为了理解功效分析,我认为理解三个相关概念是很重要的:显著性水平、I/II 类错误和效应大小。

在假设检验中, 显著性水平 (通常表示为希腊字母 alpha)是拒绝零假设(H0)的概率,当它实际上为真时。与显著性水平密切相关的指标是p-值,它是在 H0 为真的情况下,获得至少是极端结果(离零假设更远的结果)的概率。这在实践中意味着什么?在从总体中随机抽取样本的情况下,观察到的效应可能仅仅是由于抽样误差而产生的。

当相关的p-值小于所选的α时,实验结果(或例如线性回归系数)在统计上是显著的。显著性水平应在设置研究之前指定,并取决于研究领域/业务需求。

第二个值得一提的概念是在统计测试假设时我们可能犯的种错误。当我们拒绝一个真正的 H0 时,我们谈论的是一个I 型错误(假阳性)。这是与显著性水平相关的误差(见上文)。另一种情况发生在我们未能拒绝假 H0 时,这被认为是一个II 型错误(假阴性)。你可以从混乱矩阵中回忆起这些概念!

Types of error in a nutshell 😃

最后要考虑的是 效应大小 ,这是一种现象在人群中出现的量化幅度。根据具体情况,可以使用不同的指标来计算效果大小,例如:

  • 皮尔逊相关
  • 回归系数
  • 两组之间均值的差异,例如 Cohen 的 d

我在另一篇文章的中描述了效果大小的各种度量。

统计能力

现在我们已经修改了与功效分析相关的关键概念,我们终于可以谈论统计功效了。假设检验的统计功效简单来说就是当备选项事实上为真时,给定检验正确拒绝零假设(这意味着与接受 H1 相同)的概率。

更高的实验统计能力意味着犯第二类错误的概率更低。这也意味着当存在要检测的效应时,检测到效应的概率更高(真阳性)。这可以用下面的公式来说明:

Power = Pr(拒绝 H0 | H1 为真)= 1 - Pr(拒绝 H0 失败| H0 为假)

在实践中,功率太小的实验结果会导致错误的结论,进而影响决策过程。这就是为什么只能考虑具有可接受功率水平的结果。设计 80%功效水平的实验是很常见的,这相当于犯第二类错误的概率为 20%。

功率分析

功耗分析基于以下构建模块:

  • 显著性水平
  • 效果大小
  • 力量
  • 样本量

我以前没有讨论过样本大小,因为这是不言自明的。唯一值得一提的是,一些测试联合考虑两组的样本量,而对于另一些测试,样本量必须单独指定(在它们不相等的情况下)。

这四个指标是相互关联的。例如:降低显著性水平会导致功效降低,而较大的样本会使效果更容易检测。

功率分析的思想可以归结为以下几点:通过四个度量中的三个,我们估计缺少的一个。这在两个方面很方便:

  • 当我们设计一个实验时,我们可以假设什么样的显著性水平、功效和效果大小是我们可以接受的,并且——因此——估计我们需要收集多大的样本来进行这样的实验以产生有效的结果。
  • 当我们验证一个实验时,我们可以看到,在给定所用样本大小、效应大小和显著性水平的情况下,从商业角度来看,犯第二类错误的概率是否可以接受。

除了为给定指标计算一个值之外,我们还可以通过多次执行功效分析(针对组件的不同值)并在图上显示结果来执行一种敏感性分析。这样我们可以看到——例如——必要的样本量是如何随着显著性水平的增加或减少而变化的。这自然可以扩展到 3 个度量的 3D 平面。

Python 中的例子

在本例中,我对独立双样本 t 检验(样本大小和方差相等)的情况进行了功效分析。库statsmodels包含对一些最常用的统计测试进行功耗分析的函数。

让我们从一个简单的例子开始,假设我们想知道我们的实验需要收集多大的样本,如果我们接受 80%的功效水平,5%的显著性水平和预期的效应大小为 0.8。

首先,我们导入所需的库。

然后,我们需要运行以下命令,并达到所需的样本大小 25。

做了这些之后,是时候更进一步了。我们希望看到当我们修改其余的构建模块时,功率如何变化。为此,我们绘制了功率与其他参数的关系。我从检查样本大小如何影响功效开始分析(同时将显著性水平和效应大小保持在特定水平)。我已经选择了[0.2,0.5,0.8]作为考虑的效果大小值,因为它们对应于小/中/大的阈值,如在科恩的 d 的情况中所定义的。

从图中,我们可以推断,样本/效果大小的增加会导致功效的增加。换句话说,样本越大,功率越高,保持其他参数不变。下面,我还在 x 轴上展示了两个剩余构建模块的图,结果不言自明。

Power vs. effect size

Power vs. significance level

最后,我想把分析扩展到三个方面。为此,我将显著性水平固定在 5%(这是实践中经常使用的),并创建一个可能的样本和效应大小组合的网格。然后我需要获得每个组合的功率值。为此,我使用 NumPy 的meshgridvectorize

为了创建 3d 情节,我选择了plotly,因为它很容易快速获得好的,互动的情节,然后可以嵌入到这个帖子中。在代码中,我使用plotly的离线模式,不需要注册。如果你想创建可以共享/嵌入的图形,你必须在这里创建一个免费账户来获得一个 API 密匙。

结论

总的来说,功耗分析现在主要用于 A/B 测试,在计划实验/研究或评估结果时都可以使用。由于许多公司使用频率主义方法进行假设检验,知道如何进行权力分析以及如何展示其含义无疑是件好事。

一如既往,我们欢迎任何建设性的反馈。可以在 Twitter 或者评论里联系我。文章的代码可以在这里找到。

喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要你额外付费。提前感谢,再见!

SQL 中的过程和游标介绍

原文:https://towardsdatascience.com/introduction-to-procedures-and-cursors-in-sql-f9d9b9ea1fe7?source=collection_archive---------6-----------------------

Photo by Caspar Rubin on Unsplash

学习如何为一个 RDBMS 编写程序和游标。

如果你想从数据科学的角度了解更多关于 SQL 的知识,你可以参加 DataCamp 的免费课程“数据科学的 SQL 介绍”。

SQL 是任何现代软件工程师的必备技能。因为大多数软件依赖于某种类型的数据,并且与 RDBMS(关系数据库管理系统)集成得很好。无论是 web 应用程序、API 还是内部应用程序,RDBMS 都在那里。SQL 是查询 RDBMS 的语言。

作为一名数据科学家,了解 SQL 及其相关技术是非常初级的。为了能够查询 RDBMS 并获得关于您正在处理的数据的特定问题的答案,SQL 是最低要求。

在他与 DataCamp 的最新视频中,大卫·罗宾逊(首席数据科学家@ DataCamp) 向我们展示了他如何在一个数据科学问题中使用 SQL。请检查一下,他的工作流程非常有趣。

在本教程中,您将学习编写过程和游标;SQL 的另一个重要方面。您是否曾经希望 RDBMS 在执行特定操作时自动执行某些操作?例如,假设您已经在名为Employees的表中创建了一个新的雇员记录,并且您希望它反映在其他相关的表中,如Departments。好吧,你将选择正确的教程。

在本教程中,您将学习:

  • RDBMS 中的过程是什么?
  • 如何编写一个过程呢?
  • 不同类型的程序
  • RDBMS 中的游标是什么?
  • 如何编写不同类型的游标?
  • 不同类型的光标

听起来很刺激?让我们开始吧。

RDBMS 中的过程是什么?

在继续学习过程和游标之前,您需要了解一些关于PL/SQL的知识,它是一种块结构语言,使像您这样的开发人员能够将 SQL 的强大功能与过程语句结合起来。但是你不会以传统的方式学习,你会随着你的前进和需要而学习。

所以如果你有一个 SQL 查询,你想多次执行它。程序是解决方法之一。通常在这种情况下调用过程,因为它们保持存储状态,并在特定操作或一系列操作时被触发。程序也被称为Procs

现在您将看到如何编写一个过程。

写作程序:

编写过程的一般语法如下:

**CREATE** **PROCEDURE** procedure_name
**AS**
sql_statement
**GO**;

请注意,这些语法适用于几乎所有 RDBMS,无论是 Oracle、PostgreSQL 还是 MySQL。

创建过程后,您必须执行它。下面是它的语法。

**EXEC** procedure_name;

现在让我们写一个简单的程序。考虑下面来自 RDBMS 的快照,它包含一个名为Customers的表。

Source: W3Schools

您将编写一个名为SelectAllCustomers的程序,它将从Customers中选择所有的客户。

**CREATE** **PROCEDURE** SelectAllCustomers
**AS**
**SELECT** * **FROM** Customers
**GO**;

执行SelectAllCustomers的人:

**EXEC** SelectAllCustomers;

过程也可以是独立的语句块,这使得它们独立于任何表,不像前面的表。下面的示例创建了一个显示字符串“Hello World!”的简单过程作为执行时的输出。

**CREATE** **PROCEDURE** welcome
**AS**
**BEGIN**
dbms_output.put_line('Hello World!');
**END**;

有两种执行独立过程的方法。

  • 使用EXEC关键字
  • 从 PL/SQL 块调用过程名

可以使用关键字EXEC调用上述名为“welcome”的过程,如下所示:

**EXEC** welcome;

现在您将看到下一个方法,即从另一个 PL/SQL 块调用过程。

**BEGIN**
welcome;
**END**;

程序也可以被替换。你只需要在创建程序时添加REPLACE关键字。这将替换已经存在的过程(如果),否则将创建一个新的过程。

**CREATE** **OR** **REPLACE** **PROCEDURE** welcome
**AS**
**BEGIN**
dbms_output.put_line('Hello World!');
**END**;

删除存储过程没什么大不了的:

**DROP** **PROCEDURE** **procedure**-name;

根据参数的不同,程序也会有所不同。可以有单参数过程,也可以有多参数过程。现在你将研究这些变体。

为此,您将使用同一个表Customers。为了方便起见,下面的部分再次给出了快照。

Source: W3Schools

您将编写一个存储过程,从表中选择特定城市的客户:

**CREATE** **PROCEDURE** SelectAllCustomers @City nvarchar(30)
**AS**
**SELECT** * **FROM** Customers **WHERE** City = @City
**GO**;

让我们在这里剖析一下共同的原则:

  • 您编写了第一个@City,并将其类型和大小定义为程序执行时将给出的参数之一。
  • 第二个@City被分配给条件变量City,它只是Customers表中的一列。

该过程执行如下:

**EXEC** SelectAllCustomers City = "London";

现在让我们看看另一个变体。

多参数的编写程序与前面的完全相同。你只需要添加它们。

**CREATE** **PROCEDURE** SelectAllCustomers @City nvarchar(30), @PostalCode nvarchar(10)
**AS**
**SELECT** * **FROM** Customers **WHERE** City = @City **AND** PostalCode = @PostalCode
**GO**;

按照以下方式执行程序:

**EXEC** SelectAllCustomers City = "London", PostalCode = "WA1 1DP";

上面的代码可读性不是很好吗?当代码可读时,做起来更有趣。手续到此为止。现在您将学习光标。

RDBMS 中的游标是什么?

Oracle 等数据库创建了一个内存区域,称为上下文区域,用于处理 SQL 语句,其中包含处理该语句所需的所有信息,例如处理的行数。

光标是指向该上下文区域的指针。PL/SQL 通过一个光标控制上下文区域。游标是执行 SQL 语句时在系统内存中创建的临时工作区。游标包含有关 select 语句及其所访问的数据行的信息。因此,游标用于加快大型数据库中查询的处理时间。您可能需要使用数据库游标的原因是,您需要对单独的行执行操作。

光标有两种类型:

  • 隐式光标
  • 显式光标

现在您将看到如何编写不同类型的游标。

写入光标:

您将从理解什么是隐式游标开始这一部分。

当没有为 SQL 语句定义显式游标时,每当执行该语句时,Oracle 都会自动创建隐式游标。程序员不能控制隐式光标和其中的信息。每当发出 DML(数据操作语言)语句(INSERT、UPDATE 和 DELETE)时,都会有一个隐式游标与该语句相关联。对于插入操作,光标保存需要插入的数据。对于更新和删除操作,光标标识将受影响的行。

您可以将最近的隐式游标称为 SQL 游标,它始终具有如下属性:

  • 找到%个,
  • %ISOPEN,
  • %未找到,
  • %ROWCOUNT

下图简要描述了这些属性:

Source: TutorialsPoint

让我们考虑一个数据库的快照,它包含一个名为Employee的表:

现在,您将编写一个游标,将年龄小于 30 岁的人的薪水增加 1000 英镑。

**DECLARE**
total_rows number(2);**BEGIN**
**UPDATE** Employee
**SET** salary = salary + 1000
**where** age < 30;
**IF** **sql**%notfound **THEN**
    dbms_output.put_line('No employees found for under 30 age');
**ELSIF** **sql**%**found** **THEN**
    total_rows := **sql**%rowcount;
    dbms_output.put_line( total_rows || ' employees updated ');
**END** **IF**;
**END**;

现在让我们回顾一下你所写的一切:

  • 您定义了一个名为total_rows的变量,用于存储将受光标操作影响的雇员数量。
  • 您用BEGIN开始了 cursors 块,并编写了一个简单的 SQL 查询来更新那些年龄小于 30 岁的人的工资。
  • 如果数据库中没有雇员年龄小于 30 岁的条目,您可以处理输出。您为此使用了%notfound属性。注意,这里的隐式光标sql存储了所有相关信息。
  • 最后,您使用%rowcount属性打印出受游标影响的记录数。

太好了!你做得很好!

当在 SQL 提示符下执行上述代码时,它会产生以下结果:

更新了 2 名员工(假设有 2 条记录,其中年龄< 30)

现在,您将学习显式游标。

显式光标对上下文区域进行更多定义的控制。它是在返回多行的 SELECT 语句上创建的。

创建显式游标的语法是

**CURSOR** **cursor_name** **IS** select_statement;

如果您正在使用显式游标,您需要遵循如下一系列步骤:

  • 在内存中声明用于初始化的光标
  • 打开光标分配内存区域
  • 获取用于检索数据的光标
  • 关闭光标以释放内存

下图表示典型显式游标的生命周期:

现在,您将进一步了解这些步骤。

声明光标:

您声明了一个游标和一个SELECT语句。例如:

**CURSOR** **C** **IS** **SELECT** id, name, address **FROM** Employee **where** age > 30;

打开光标:

当您打开游标时,CPU 会为游标分配内存,并准备好获取 SQL 语句返回的行。例如,我们将打开上面定义的光标,如下所示:

**OPEN** **C**;

获取光标:

获取游标涉及到从游标所需的 SQL 中的关联表中一次访问一行。

**FETCH** **C** **INTO** C_id, C_name, C_address;

关闭光标:

关闭游标意味着释放分配的内存。您将关闭上面打开的光标,如下所示:

**CLOSE** **C**;

你现在要以一种有意义的方式把所有这些部分组合在一起。

组装这些零件:

**DECLARE**
C_id Employee.ID%**type**;
C_name Employee.NAME%**type**;
C_address Employee.ADDRESS%**type**;
**CURSOR** **C** **is**
**SELECT** id, name, address **FROM** Employee **where** age > 30;
**BEGIN**
**OPEN** **C**;
LOOP
**FETCH** **C** **INTO** C_id, C_name, C_address; 
dbms_output.put_line(ID || ' ' || NAME || ' ' || ADDRESS); 
EXIT **WHEN** **C**%notfound;
**END** LOOP;
**CLOSE** **C**;
**END**;

您还学习了声明游标变量 C_id、C_name 和 C_address。C_id Employee.ID%type; -这确保了创建 C_id 的数据类型与在Employee表中 id 的数据类型相同。

通过使用LOOP,您可以通过光标循环读取记录并显示出来。如果光标没有找到记录,您也可以处理这种情况。

当在 SQL 提示符下执行代码时,它会产生

结论:

恭喜你。你已经坚持到最后了。您讨论了数据库世界中最流行的两个主题——过程和游标。这些在处理大量事务的应用程序中很常见。是的,你猜对了!银行自古以来就在使用这些。您学习了如何编写一个过程,它有哪些不同的类型以及为什么会这样。您还学习了游标及其几种变体,以及如何编写它们。

太神奇了!

以下是撰写本教程的一些参考资料:

  • Oracle PL/SQL 编程
  • 光标上的 TutorialsPoint 博客
  • SQL 存储过程— W3Schools

Q 学习简介

原文:https://towardsdatascience.com/introduction-to-q-learning-88d1c4f2b49c?source=collection_archive---------1-----------------------

想象自己在迷宫中寻宝。游戏如下:

你从一个给定的位置开始,起始状态。从任何状态你都可以向左、向右、向上或向下走,或者停留在同一个地方,只要你不穿过迷宫的前提。每个动作将带你到网格的一个单元(不同的状态)。现在,在其中一个州(目标州)有一个宝箱。此外,迷宫在某些位置/状态有一个蛇坑。您的目标是沿着一条没有蛇的路径从起始状态行进到目标状态。

Grid outline of the maze

当您将一个代理放入网格(我们称之为我们的环境)时,它将首先探索。它不知道什么是蛇,也不知道宝藏在哪里。所以,为了给它蛇和宝箱的概念,我们会在它完成每个动作后给它一些奖励。它每踏上一个蛇穴,我们将给予它-10 的奖励。对于宝藏,我们将给予+10 的奖励。现在我们希望我们的代理尽快完成任务(走最短的路线)。为此,我们将给予其他州-1 的奖励。然后我们会告诉它最大化分数。现在,随着代理探索,它了解到蛇对它是有害的,宝藏对它是有益的,它必须尽快得到宝藏。图中的'-'路径表示奖励最大的最短路径。

Q-Learning 试图了解处于特定状态的价值,并在那里采取特定的行动。

我们要做的是开发一个表格。其中行是状态,列是它可以采取的动作。因此,我们有一个 16x5 (80 个可能的状态-动作)对,其中每个状态是迷宫网格的一个单元。

我们首先将该表初始化为统一的(全零),然后当我们观察到我们从各种行为中获得的奖励时,我们相应地更新该表。我们将使用 贝尔曼方程来更新表格。

eqn.1

“s”代表当前状态。‘a’表示代理从当前状态采取的动作。s”表示该操作产生的状态。“r”是你采取行动得到的奖励,“γ”是折扣系数。所以,采取行动 a 的状态的 Q 值是即时奖励和未来奖励的折扣之和(结果状态的值)。折扣系数‘γ’决定了你对未来奖励的重视程度。比方说,你去了一个离目标州更远的州,但是从那个州开始,遇到有蛇的州的机会就更少了,所以,这里未来的奖励更多,尽管即时奖励更少。

我们将每次迭代(代理所做的尝试)称为一个情节。对于每一集,代理将试图达到目标状态,并且对于每个转换,它将继续更新 Q 表的值。

让我们看看如何计算 Q 表:

为此,为了方便起见,我们将采用一个较小的迷宫网格。

最初的 Q 表看起来像这样(状态沿着行,动作沿着列) :

Q Matrix

上、下、左、右

奖励表应该是这样的:

R Matrix

这里,E 表示零,即,不可能有这样的转变。

算法:

  1. 用全零初始化 Q 矩阵。设置“γ”的值。填写奖励矩阵。
  2. 每集。选择一个随机的起始状态(这里我们将起始状态限制为 state-1)。
  3. 从当前状态的所有可能操作中选择一个。
  4. 作为动作(a)的结果,移动到下一个状态(S’)。
  5. 对于状态中所有可能的动作,选择具有最高 Q 值的一个。
  6. 使用公式 1 更新 Q 表。
  7. 将下一个状态设置为当前状态。
  8. 如果达到目标状态,则结束。

例如:假设我们从状态 1 开始。我们可以选择 D 或 r。比如说,我们选择了 D。然后我们将到达 3(蛇坑)。因此,我们可以选择 U 或 R,取γ = 0.8,我们有:

Q(1,D) = R(1,D) + γ*[max(Q(3,U) & Q(3,R))]

Q(1,D) = -10 + 0.8*0 = -10

这里,max(Q(3,U) & Q(3,R)) = 0,因为 Q 矩阵尚未更新。-10 代表踩蛇。因此,新的 Q 表看起来像:

现在,3 是起始状态。从 3 开始,假设我们去 r。所以,我们去 4。从 4 开始,我们可以去 U 或 L。

Q(3,R) = R(3,R) + 0.8*[max(Q(4,U) & Q(4,L))]

Q(3,R) = 10 + 0.8*0 = 10

所以,现在我们已经达到了目标状态 4。所以,我们终止和更多的传递,让我们的代理理解每个状态和动作的值。继续传递,直到值保持不变。这意味着您的代理已经尝试了所有可能的状态-动作对。

python 中的实现:

最后一个 q_matrix 的输出:

在下一篇文章中,我将介绍使用神经网络进行 Q 学习,以及使用表格方法的缺点。此外,我们将致力于开放人工智能健身房的游戏测试。在那之前,再见。

量化金融导论:资产回报的程式化事实

原文:https://towardsdatascience.com/introduction-to-quantitative-finance-part-i-stylised-facts-of-asset-returns-5190581e40ea?source=collection_archive---------6-----------------------

作为一名具有定量金融背景的数据科学家,我一直对探索两个领域结合的可能性感兴趣。我认为这是一个令人着迷的探索领域,这就是为什么我想开始一系列的文章来描述量化金融的基础知识。

在本系列的最后,我打算提出一个简单的分配策略,并希望表明,通过使用数据科学/量化金融知识,有可能超越基本的基准策略。当然,没有人在谈论建立一个完美的模型,准确预测未来的股票价格,并使我们——潜在的投资者——赚取数百万美元。

有一个理论解释了为什么这是不可能的,即有效市场假说(EMH)。它指出,资产价格充分反映了所有可用的信息。这意味着持续跑赢市场是不可能的,因为市场价格只会对新信息做出反应。你可以在这里了解更多关于的信息。但是我们仍然可以尝试一下,看看短期内是否有可能赚到一些钱,至少在理论上是这样的:)

在直接进入机器学习和建立资产配置策略之前,我认为花一些时间在基础知识上并理解我们试图建模的过程是至关重要的。在本文中,我研究了资产回报的程式化事实,并展示了如何使用 Python 来验证它们的存在。一些统计学的基础知识会有所帮助,但是当我试图直观地解释正在发生的事情时,不要气馁。

回报以及我们为什么与他们合作

我首先使用 Python 的quandl库下载历史股票价格。这非常简单,你只需要创建一个免费账户来获得 API 密匙。

在本文中,我使用调整后的收盘价,因为它们说明了可能的公司行为,如股票分割等。

我选择微软(股票代码:MSFT)作为例子,以数据帧的形式下载时间序列。然后,我将价格转换成对数回报,以便进一步分析:

其中 P_t 表示资产在时间 t 的价格,log 函数代表自然对数(有时也称为 ln )。

有一篇很棒的文章描述了简单返回和日志返回之间的区别,因此您可以在那里找到使用这两种方法的优缺点。

但是当我们已经有了价格,为什么还要处理退货呢?原因是价格通常是非平稳的,即均值和方差(数学矩)等统计数据随时间变化。这也可能意味着在我们的价格序列中观察一些趋势或季节性。正如你所想象的,通过处理回报率,我们使时间序列稳定,这是统计建模中的一个期望属性。现在,就让它这样吧。

Decomposition of a time series into trend/seasonal components.

下面我展示了微软价格和回报随时间的演变。

在图中可以直接观察到的一个重要事实是“波动聚集”的存在——大回报周期与小回报周期交替出现,表明波动不是恒定的。我稍后会回来。

一般来说,程式化的事实是出现在许多经验资产回报(跨时间和市场)中的统计属性。了解它们是很重要的,因为在构建代表资产价格动态的模型时,模型必须能够捕捉/复制这些属性。

事实 1:收益分布不正常

Standard Normal (Gaussian) distribution

据观察,回报表现为:

  • 负偏度(三阶矩)——大的负回报比大的正回报更常见。目测:左尾较长;分布的质量集中在分布图的右侧。
  • 超额峰度(四阶矩)——大(和小)回报比预期的更经常发生。目测:厚尾、尖峰分布。

下面,我展示了一个直方图,直观地显示了微软的对数回报的分布,以及一条代表正态概率密度曲线的线(平均值和标准偏差等于样本平均值)。我们看到,回报确实呈现出更高的峰值,而且更多的质量位于尾部(比正常情况下预期的要多)。

为了进一步检验,我还看了 Q-Q 图。红线代表标准的正态分布。在收益服从高斯分布的情况下,这两条线会对齐。然而,我们看到有差异,主要是在尾部。这进一步证实了上述发现。

关于如何创建和解释 Q-Q 图的更多细节,你可以阅读本文。

最后,我查看了所考虑的回报的描述性统计数据(它们以日价值表示,实际上,通常以年价值表示)。 Jarque-Bera 正态性检验证实了我们的怀疑,p 值小到足以拒绝声称数据遵循高斯分布的零假设。

Descriptive statistics of MSFT’s log returns

事实 2:回报没有(或几乎没有)显著的自相关性

自相关测量给定时间序列与连续时间间隔内同一序列的滞后版本之间的相似程度。这类似于两个时间序列之间的相关性:第一个是原始形式,另一个滞后了 n 个周期。

例如:当某种资产的回报表现出历史上的正自相关性,并且在过去几天里价格正在上涨,人们可能会合理地预期进一步的正运动(当然,预测股票价格并不那么简单,否则成为百万富翁将是一件相当容易的事情……EMH 再次出击)。

事实 3:平方收益和绝对收益的自相关性小且缓慢下降

在对回报建模时,考虑波动性在决策(买/卖)过程中可能是至关重要的。波动性通常被理解为回报的标准差(方差的平方根)。

现在,让我们考虑误差,而不是回报,即实际值——由某个模型预测/解释的值。方差基本上是误差平方的平均值,而绝对偏差是绝对误差的平均值。通过绘制随时间变化的平方/绝对误差,我们可以看到方差(或绝对偏差,也是波动性的一种度量)是否随时间保持不变。在资产回报的情况下,情况并非如此,我们可以观察到高/低波动的时期。这被称为“波动聚类”,可以在对数收益的时间序列图上观察到。

另一方面,长期短期(每日)平均回报预计为零(EMH)。这就是为什么通过查看平方和绝对回报,我们可以有效地测量与预期均值的偏差,而不用查看误差的方向——平方和绝对函数都会抵消误差的方向。

下面我展示了 MSFT 对数收益的自相关图,以及平方值和绝对值(检验事实 2 和 3)。蓝色区域表示 95%的置信区间,超出该区间的点具有统计学意义。我们看到,对于对数回报,只有几个重要的点(这与事实 2 一致)。至于事实 3,我们看到相关性是显著的,平方收益比绝对收益更容易观察到相关性的下降。总之,这让我们相信,我们可以尝试利用自相关结构来进行波动建模。

ACF Plots of returns, squared and absolute returns

结论

在本文中,我简要介绍了资产回报的程式化事实。当然,这仅仅是触及了话题的表面。还有更多的东西需要学习,不同的资源也增加了更多的程式化事实。如果你感兴趣,我在参考资料中添加了一些额外的资源。

需要注意的一件重要事情是,不能保证所有的事实在每个收益序列中都清晰可见。这很容易受到分析中考虑的时间范围的影响。在这种情况下,我从 2000 年开始收集数据。但是没有严格的规定。使用提供的代码,您可以轻松地调查不同的时间范围和资产。

介绍完之后,在下一篇文章中,我将介绍一些预测资产回报的常用方法(也许还有它们的波动性)。在最后一篇文章中,我将试图说明,通过(或多或少准确的)预测,我们可以尝试建立资产配置策略,并调查我们是否在历史上赚了一些钱!

一如既往,我们欢迎任何建设性的反馈。你可以在推特上或评论中联系我。用于调查程式化事实的代码可以在我的 GitHub 上找到。

我最近出版了一本关于使用 Python 解决金融领域实际任务的书。如果你感兴趣,我在贴了一篇文章介绍这本书的内容。你可以在亚马逊或者 Packt 的网站上买到这本书。

参考资料:

[1]https://orfe.princeton.edu/~jqfan/fan/FinEcon/chap1.pdf

[2]资产回报的经验属性:程式化的事实和统计问题—http://finance . martinse well . com/typed-facts/dependency/cont 2001 . pdf

推荐系统介绍。第 2 部分(神经网络方法)

原文:https://towardsdatascience.com/introduction-to-recommender-system-part-2-adoption-of-neural-network-831972c4cbf7?source=collection_archive---------1-----------------------

1.介绍

在我本系列的上一篇博文: 推荐系统介绍。第一部分(协同过滤,奇异值分解) ,我谈到了协同过滤(CF)和奇异值分解(SVD)如何用于构建推荐系统。随着神经网络的兴起,你可能会好奇我们如何利用这种技术来实现推荐系统。这篇博文将介绍由 PyTorch 支持的推荐系统框架 Spotlight,以及我借用单词嵌入的思想创建的 Item2vec。最后,我将比较我讨论过的模型的性能。

2。聚光灯

Spotlight 是一个实现良好的 python 框架,用于构建推荐系统。它包含两大类模型,因子分解模型和序列模型。前者利用了 SVD 背后的思想,将效用矩阵(记录用户和项目之间交互的矩阵)分解成用户和项目矩阵的两个潜在表示,并将它们馈入网络。后者是用长短期记忆(LSTM)和一维卷积神经网络(CNN)等时间序列模型建立的。由于 Spotlight 的后端是 PyTorch,所以在使用之前,请确保您已经安装了正确版本的 PyTorch。

相互作用

效用矩阵被称为聚光灯下的交互。为了创建隐式交互,我们为所有用户-项目交互对指定用户和项目的 id。额外的评级信息将这种交互转变为明确的交互。

因子分解模型

因式分解模型包含隐式或显式的交互。为了便于说明,我们将使用隐式方法。

Implicit Feedback (https://github.com/maciejkula/netrex/)

它的思想与 SVD 非常相似,在 SVD 中,用户和项目被映射到一个潜在的空间中,这样它们就可以直接进行比较。本质上,我们使用两个嵌入层来分别表示用户和项目。目标是我们传入的交互(效用矩阵)。为了计算用户-项目对的分数,我们获取该用户和项目的潜在表示的点积,并将其传递给 sigmoid 激活函数。通过计算所有用户-项目对相对于真实交互的损失(稍后将详细介绍),我们可以反向传播并优化嵌入层。网络结构如下图所示。

Neural Network Structure (https://github.com/maciejkula/netrex/)

我们只需要几行代码来用 Spotlight 训练这样的模型,它看起来非常类似于 scikit-learn toolkit:

顺序模型

顺序模型将推荐问题视为顺序预测问题。给定过去的交互,我们想知道在下一个时间步骤中用户最有可能喜欢哪个项目。例如,假设用户 A 与 id 顺序为[2,4,17,3,5]的项目进行交互。那么我们将有下面的扩展窗口预测。

[2] -> 4
[2, 4] -> 17
[2, 4, 17] -> 3
[2, 4, 17, 3] -> 5

左边的数组存储过去的交互,而右边的整数表示用户 A 接下来将要交互的项目。

为了训练这样的模型,我们简单地将原始交互对象转换成顺序交互对象。剩下的都一样。

注意 to_sequence() 函数在长度不够长的序列前面填充零,以确保每个序列都具有相同的长度。

因此,id 为 0 的项目应该被更改为其他任意未使用的 id 号,以便此功能能够工作。

损失函数的选择

当指定模型时,我们可以灵活地改变损失函数。不同损失函数的模型在性能上可能有显著差异。我将简要描述 Spotlight 中定义的两种主要类型的损失函数。

  • “逐点”:与其他形式的损失函数相比,这是最简单的形式。由于样本的稀疏性(效用矩阵中有很多 0),将所有项目都考虑进去在计算上是不可行的。因此,不是计算给定用户的所有项目的损失,我们只考虑随机选择的一部分否定样本(用户没有与之交互的项目)和所有肯定样本。
  • “bpr”:贝叶斯个性化排名(BPR)给每个用户的每个项目一个排名。它试图确保正样本的等级高于负样本的等级,公式如下。

ranking loss

现在,您已经了解了如何使用 Spotlight 构建推荐系统。它使用起来非常简单,并且有足够的灵活性来满足你的需求。虽然对于大多数问题,序列模型优于因式分解模型,但训练序列模型需要更长的时间。此外,在应用序列模型时,如果数据没有明确的序列相关性,也不会有很大帮助。

3.项目 2Vec

Item2Vec 的想法是上个月我参加一个竞赛时产生的,国际数据分析奥林匹克 (IDAO)。它提出的挑战要求参与者为 Yandex 建立一个推荐系统。因为那时我正在学习 Word2Vec,所以我想类似的概念也可以用在推荐系统中。我不确定是否有论文或文章指出过这个想法,但是我没有看到 Word2Vec 的概念在这个领域有类似的应用。Word2Vec 背后的大致思想是,我们利用分布式表示来编码每个单词。也就是说,每个单词由该单词周围的其他单词所确定的向量来表示。如果你想了解更多关于 Word2Vec 的内容,可以参考我之前的博文: Word2Vec 和 FastText 用 Gensim 进行单词嵌入。类似地,我试图使用分布式表示,根据用户在交互之前和之后交互的项目,对每个项目进行编码。

对于每个用户,我首先按照时间顺序创建了一个条目列表。然后,在这些项目列表上训练 Gensim 的 Word2Vec 模型。经过训练的项目向量存储在磁盘中,以便我们可以加载它供以后使用。

之后,我们将训练好的项目向量加载到嵌入矩阵中。

然后,我们定义了预测用户未来交互的模型。基本上,它是由 CuDNN 加速的 GRU 模型。如果你没有英伟达 GPU,也不用担心。你可以简单的把 CuDNNGRU 换成 GRU。

请注意,at 我将预训练的嵌入矩阵加载到模型的嵌入层中,并通过将 trainable 设置为 false 来冻结它。

4.表演

我已经在 IDAO 的公共电路板测试集上测试了我在本系列的两个部分中提到的一些模型。下表显示了它们各自的公开委员会分数。

Public Board Score

看起来基于神经网络的模型不一定能打败传统的推荐系统构建方法。虽然易于理解和实现,但 SVD 的得分与需要更长时间训练的 Spotlight 序列模型相当。令人惊讶的是,Item2Vec 是我测试过的所有型号中最好的型号。诚然,我们不能只用一个测试集来判断所有这些模型。这让你大致了解每个模型有多好。

5.结论

我已经讨论了在 Spotlight toolkit 中实现的两种类型的模型和我自己创建的依赖于 Word2Vec 概念的 Item2Vec。我还基于 IDAO 的公共电路板测试集比较了我提到的模型。事实证明,SVD 是推荐系统的有效解决方案,Item2Vec 已经证明了它能够更准确地推荐项目。如果你对这篇文章有任何问题,请不要犹豫,在下面留下你的评论或者给我发电子邮件:khuangaf@connect.ust.hk。如果你喜欢这篇文章,请确保你在 twitter 上关注我,以获得更多机器学习/深度学习博文!

递归神经网络导论

原文:https://towardsdatascience.com/introduction-to-recurrent-neural-network-27202c3945f3?source=collection_archive---------2-----------------------

有许多专门解决许多任务的深度学习模型。这里我们讨论深度学习模型处理序列的能力。

什么是顺序数据?

如果相关事物之间有特定的顺序,我们称之为序列。

《我是个好孩子》****《我是个好孩子吗》

你认为两个句子意思相同吗?不!也就是说单词的位置很重要!它们是一系列单词。

想象一个正在播放的视频。如果你已经看过了,你可以很容易地预测下一个场景。但是考虑到你困了,不记得框架的位置了(脑子里全是冗杂的框架)。那你能预测下一个场景吗???当然不是!!!

递归神经网络

他们和我们一样!!!他们能记住序列。如果你让 RNN 预测下一个场景,它会告诉你。

当前馈神经网络仅基于当前输入做出决策时,RNN 基于当前和先前输入做出决策。

Recurrent Neural Network

绿框代表一个神经网络。箭头表示记忆或简单地反馈到下一个输入。

第一张图显示了 RNN。第二幅图展示了同一幅 RNN 在时间中的展开。考虑一个序列【我是个好孩子】。我们可以说序列是按时间排列的。t = 0 时,X0 =“I”作为输入给出。t=1 时,X1 =“am”作为输入给出。第一时间步的状态被记忆,并作为第二时间步的输入,与该时间步的当前输入一起给出。

在前向神经网络中,网络每个样本仅向前传播一次。但是在 RNN,网络正向传播等于每个样本的时间步数。

与 RNN 解决了不同的问题

生成文本

给定一个单词序列,我们希望在给定前一个单词的情况下预测每个单词的概率。

机器翻译

机器翻译类似于语言建模,因为我们的输入是源语言(例如德语)中的单词序列。我们希望输出目标语言(例如英语)的单词序列。

语音识别

给定来自声波的声学信号的输入序列,我们可以预测语音片段序列及其概率。

生成图像描述

与卷积神经网络一起,RNNs 已经被用作模型的一部分来为未标记的图像生成描述。

聊天机器人

聊天机器人可以回答你的问题。当给定一个单词序列作为输入时,将在输出端生成单词序列。

你需要知道的数据科学概念!第一部分

原文:https://towardsdatascience.com/introduction-to-statistics-e9d72d818745?source=collection_archive---------0-----------------------

这是 5 篇系列文章的第一篇,将概述数据科学中的一些核心概念:

值得注意的是,我们将涵盖上图中的统计桶,并试图使其尽可能直观和数学化。

我的背景是南部和东部非洲的大型制药公司、学术界(牛津大学物理和理论化学系的博士)和“为社会公益服务的数据科学”行业。

这一系列帖子旨在介绍并快速发展数据科学和数据分析中的一些核心概念,并特别关注我觉得在其他材料中被忽略或简单处理的领域。因此,这些帖子将适合希望重温统计理论的数据科学家,希望获得全面培训材料的数据分析师,以及希望从数据和员工那里提出更好问题的数据经理。

我们将在本系列中讨论的一些主题包括:

  • 功率和样本量计算的非参数方法
  • A/B 测试(又名随机试验)的设计和分析
  • 如何有效探索数据趋势
  • 如何实施、评估和改进线性模型

这些帖子改编自我为国际非政府组织 One Acre Fund 开发的一系列培训材料,One Acre Fund 为东非的小农提供小额贷款。

这篇文章的目的(#1):

  • 理解是什么决定了分布的形状。
  • 理解非正态性如何影响假设检验和功效计算
  • 了解如何使用蒙特卡罗方法进行非参数样本容量/功效计算

这些帖子是用 R-markdown 制作的,它允许在一个地方呈现 R 代码、文本写作和结果。R-markdown 对于编写报告特别有用,因为它使分析透明且可重复。

动机:

统计学本质上是对分布的研究。分布是将一个值的频率与观察到的实际值联系在一起的一种方式。你可以想象一下,例如,如果我们在测量员工的身高,我们可能会发现大多数人的身高在 1.5 到 1.8 米之间,但也会有一些人比这更高或更矮。当我们谈论这样的数据时,我们实际上是在谈论分布:

set.seed(111)
hist(rnorm(1000, mean=1.75, sd=0.5), xlab="Employee height (m)", main="Employee height", breaks=c(0,0.5,1,1.5,2,2.5,3,3.5,4),col="black")

上面的柱状图是我们用图形的方式表述的;我们有沿 X 轴的观察值(这些值被分组为“箱”)和沿 Y 轴的计数或频率(即我们观察该值的次数)。有时我们也可以绘制沿 Y 轴的观察的概率。

阅读上面的直方图,我们可以说最常见的身高是 1.5 到 2 米,在更极端的值下频率会降低(例如,0.5-1 米和 2.5-3 米的人比 1.5-2 米的人少)。更具体地说,通过阅读 X~Y 轴,我们可以说大约有 400 人身高 1.5 到 2 米,大约有 200 人身高 2 到 2.5 米。

每一项分析都必须从理解底层数据及其分布开始。分布的形状将决定:

  • 我们使用的分析方法(我们应该使用 T 检验,还是韦尔奇检验?)
  • 样本量(我们需要多少个人才能发现一个效应?)
  • 我们的误差大小(数据有多分散?)
  • 统计显著性(即干预/产品是否成功,其效果有多大)

最终,这种分布将决定我们是否能为我们测试的干预赋予意义和因果关系。

正态分布

上面的直方图来自正态分布,这是你将看到的最常见的分布之一。让我们更深入地研究一下这个分布。在正态分布中(也只有正态分布),我们期望我们的均值中值位于分布的中心(最高点),我们同样期望分布关于均值大致对称,如下所示:

#lets generate some example normal distributions 
set.seed(111)# by setting a seed we can make sure that R draws random numbers reproducibly
#simulate a random normal distribution
norm1 <- rnorm(20000, mean=0,sd=1)

normdf <- data.frame("val"=norm1, "flag"=0)

#which is a logical, it will evaulate a condition: here "which val is greater than 1sd of norm OR less than -1sd of norm"
# note that | means OR and & means and
sd2 <- which( normdf$val > 1* sd(norm1) | normdf$val <  -1*sd(norm1) )
sd3 <- which( normdf$val > 2*sd(norm1) | normdf$val <  -2*sd(norm1) )
sd1 <- which( normdf$val < 1*sd(norm1) & normdf$val > -1*sd(norm1) )

#now lets use the index made above to reset the values in flag to the following
normdf$flag[sd1] <- "Within 1 SD"
normdf$flag[sd2] <- "Within 2 SD"
normdf$flag[sd3] <- "Within 3 SD"
normdf$flag <- as.factor(normdf$flag)

#lets plot these...
#as a histogram
ggplot(normdf, aes(x=val, fill=flag)) + geom_histogram(binwidth=.5, bins=100, alpha=1, breaks=c(-Inf,min(subset(normdf, flag=="Within 3 SD")$val),min(subset(normdf, flag=="Within 2 SD")$val),min(subset(normdf, flag=="Within 1 SD")$val), max(subset(normdf, flag=="Within 1 SD")$val), max(subset(normdf, flag=="Within 2 SD")$val),max(subset(normdf, flag=="Within 3 SD")$val), Inf)) + geom_vline(aes(xintercept = mean(val), colour="Mean & Median"),color='black',size=2) + geom_text(aes(x=mean(norm1)-0.6,y=15000,label="Mean & \n Median")) + xlab("Value of observation") + ylab("Number of observations")

正态分布由两个指标定义,均值和标准差。对于正态分布,我们预计 68%的值位于 1 个标准差内,95%位于 2 个标准差内,99.7%位于 3 个标准差内(如上)。

请注意,分布的标准偏差与分布的宽度成比例。

当我们展示分布时,我们的目标是使图表尽可能简单,同时仍然忠实于数据

呈现数据

我们可以用其他格式呈现分布,而不仅仅是直方图:

#
#histo
p1 <- ggplot(normdf, aes(x=val)) +  geom_histogram(binwidth=.5, colour="black", fill="white") + ggtitle("Histogram")

#density
p2 <-ggplot(normdf, aes(x=val)) + geom_density() + ggtitle("Density plot") 

#boxplot
#the theme argument removes the x-axis as we have no information to show here
p3 <- ggplot(normdf, aes(x=1, y=val)) + geom_boxplot() + ggtitle("Boxplot") + xlab("")  + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())
#p3 <- ggdraw(add_sub(p3, "Boxplot"))

#finally a beeswarm plot
library(ggbeeswarm)

p4 <- ggplot(normdf) +  geom_beeswarm(aes(x=1,y=val)) + ggtitle("Beeswarm") + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

#this is a funtion defined in the first block which allows us to put more than one graph on the same page
multiplot(p1,p2,p3,p4, cols=2)

我们以不同的方式展示了上述完全相同的数据:

  • 我们熟悉的直方图(左上)。请注意,改变直方图的条柱数量(即我们需要多少条柱)会极大地改变我们对数据的理解。
  • 盒状图(右上)在 Y 轴上有我们的值,粗中心线代表中间值,上下盒边界代表第一和第三个四分位数(分别),从盒中伸出的“胡须”代表最大值和最小值,最后点是(假定的)异常值。箱形图信息丰富,但可能隐藏聚类数据。
  • 密度图类似于我们的直方图。但是,密度图被平滑,y 轴现在表示总计数的分数(从 0 到 1 ),而不是实际计数。密度图下的面积总和为 1。
  • 蜂群图显示了数据框中的每个数据点。图的宽度与观察值的数量成正比,我们可以知道分布的正态性,因为图在 0(我们的平均值)附近较厚,然后在平均值的北部和南部对称地变小。虽然箱线图可以隐藏聚类,密度和直方图依赖于良好的箱宽度,但蜂群可以清楚地显示聚类数据,但看起来有点难看。

为了说明这一点,让我们展示一些聚类数据(也称为二项式分布,注意这不同于正态分布):

#
#lets make two seperate distributions and join them:
set.seed(122)
nor1 <- rnorm(200, mean=0,sd=0.8)
nor2 <- rnorm(50, mean=4,sd=0.7)

clusterdf <- data.frame("val"=c(nor1,nor2), "flag"=0)

# a beeswarm plot

p4 <- ggplot(clusterdf) +  geom_beeswarm(aes(x=1,y=val)) + ggtitle("Beeswarm") + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

#histo
p1 <- ggplot(clusterdf, aes(x=val)) +  geom_histogram(binwidth=.5, colour="black", fill="white") + ggtitle("Histogram")

#density
p2 <-ggplot(clusterdf, aes(x=val)) + geom_density() + ggtitle("Density plot") 

#boxplot
#the theme argument removes the x-axis as we have no information to show here
p3 <- ggplot(clusterdf, aes(x=1, y=val)) + geom_boxplot() + ggtitle("Boxplot") + xlab("")  + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())
#p3 <- ggdraw(add_sub(p3, "Boxplot"))

#this is a funtion defined in the first block which allows us to put more than one graph on the same page
multiplot(p4,p1,p2,p3, cols=2)

从蜂群中我们可以看到,在~0 附近有一个很大的数据集群,但在~4 附近也有一个较小的集群。密度图和直方图显示了这一点,但如果我们只检查箱形图,我们将无法清楚地看到这一点。

最后,改变密度图或直方图的条块也可以改变我们对数据的解释:

#density
p1 <-ggplot(clusterdf, aes(x=val)) + geom_density(bw=0.05) + ggtitle("Density plot 1") 
p2 <-ggplot(clusterdf, aes(x=val)) + geom_density(bw=0.2) + ggtitle("Density plot 2") 
p3 <-ggplot(clusterdf, aes(x=val)) + geom_density(bw=2) + ggtitle("Density plot 3") 
p4 <-ggplot(clusterdf, aes(x=val)) + geom_density(bw=6) + ggtitle("Density plot 4") 

multiplot(p1,p3,p2, p4, cols=2)

即使数据是相同的,我们对数据的解释也会根据我们检查的图而发生巨大的变化!我们如何从图 4 中了解我们的数据?图 1 可能太详细,而图 3 和图 4 太不详细(注意图 4 完全隐藏了第二组数据)。

剧情 2 既简单又符合数据。因此,这是这里最好的情节。请注意,找出最佳图的唯一方法是检查基础数据。因此,我建议在制作数据的简化版本之前,使用蜜蜂群或具有小区间宽度(或高区间数)的密度图,首先尽可能详细地检查数据。

有效地比较分布

通常我们会想要比较分布,看看是否有明显的差异,例如当比较治疗组和对照组时。我的首选方法是使用密度图或箱线图。让我们看看下面的一些例子,在这些例子中,我们测量了一种处理方法对卢旺达农民采用化肥的影响:

 #lets make some data
set.seed(122)
nor1 <- data.frame("val"=rnorm(50, mean=0.6,sd=0.15), "Group"="Control")
nor2 <- data.frame("val"=rnorm(50, mean=0.8,sd=0.1), "Group"="Treated")

#bind the data by rows (e.g. stack one ontop of the other)
dat <- rbind(nor1,nor2)

#Density plots with semi-transparent fill
g1 <- ggplot(dat, aes(x=val, fill=Group)) + geom_density(alpha=.3, bw=0.1) + xlab("Fertilizer adoption")

# boxplot and remove redundant legend. 
g2 <- ggplot(dat, aes(x=Group, y=val, fill=Group)) + geom_boxplot() +
    guides(fill=FALSE) + ylab("Fertilizer adoption")

g3 <- ggplot(dat, aes(x=val, fill=Group)) + geom_histogram(alpha=.3, bw=0.1) + xlab("Fertilizer adoption")

g4 <- ggplot(dat, aes(x=val, fill=Group)) + geom_beeswarm(aes(x=0, y=val, colour=Group)) + ylab("Fertilizer adoption") + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

multiplot(g1,g2,g3,g4, cols=2)

我们可以看到,密度图和箱线图对于观察组间差异非常有用。然而,蜂群图和直方图过于繁忙,无法快速得出结论(尽管它们在其他场景中很有用,例如查看异常值)。因此,这些数据应该以密度图或箱线图的形式呈现,以满足我们的标准,即易读但真实的数据

显著和非显著差异

所以我们现在有了治疗组和对照组的描述图。

ggplot(dat, aes(x=val, fill=Group)) + geom_density(alpha=.3, bw=0.1) + xlab("Fertilizer adoption")

这两组看起来不同,但是我们怎么能更确定,我们怎么能量化我们的不确定性呢?

假设检验

统计测试的存在是因为我们只有一个人口样本(见词汇表)。例如,我们可以在随机试验中测量东非农民样本的肥料使用情况。但是我们正试图推断出一些关于所有东非农民的情况(即从我们的样本中归纳出全部人口)。我们希望能够了解对实际人群的影响,这样我们就可以对项目干预做出决定;因此我们想要比较人口,但是我们只有样本。假设检验允许我们在给定一些关键假设的情况下检验潜在人群的差异。

假设检验有某些潜在的假设。常用测试的一些示例假设如下:

  • T 检验:假设正态分布。该测试是在 20 世纪 50 年代针对小样本量进行的,现在有了更可靠的测试,应该使用
  • 配对 T 检验:T 检验(同上),但用于测量治疗前后的同一受试者(例如,在一次散发传单活动前后测量农民种植依从性)
  • 双样本 T 检验:用于两个不同组的 T 检验,例如比较接受治疗的农民和对照农民的玉米产量。
  • Welch 检验:对 T 检验的改进,对不等方差更稳健(例如,对密度图宽度不同的样本更稳健)。我们可以在 t.test() R 函数中调用带有参数“var.equal=FALSE”的 Welch 测试。请注意,韦尔奇检验仅对正态分布数据有效(如 T 检验)。

我们如何知道何时使用每个测试?我们如何检验这些测试的假设?

常态假设

许多假设检验和样本量计算都假设数据是正态分布的(记住,这意味着数据关于平均值是对称的)。然而,我们经常希望对非正态数据进行假设检验。我们将很快检查非正态数据的假设检验,但是首先,我们如何知道我们的数据是否正态分布?这里有许多方法,我将介绍两种比较常见的方法。

让我们来看看下面的数据集:

#
#lets make some data
set.seed(122)
dat <- data.frame("val"=rnorm(100, mean=0.6,sd=0.15))

#this lets us plot graphs next to each other
par(mfrow = c(1, 2))

#this is a simple histogram
# i call the column named "val" from dataframe named "dat" with the $val addition
hist(dat$val, main="Data A", xlab="values")

hist(log(dat$val), main="Data B",xlab="values")

希望很明显,数据 A 可能是正常的,但数据 B 看起来肯定是非正常的(注意明显的不对称)!

为了更彻底地检验正态性,我们可以绘制一个理想的正态分布,然后将我们的数据放在上面(这被称为 QQ 图),然后计算关系之间的 R 平方:

#
#plot data against ideal normal
#note that the subset command means we will only take the val column of data with Group=="Control"
# subset(dat, Group=="Treated") would return the whole dataframe where the column "Group" is equal to "Treated", adding the $val allows us to access the val column directly
par(mfrow = c(1, 2))

qqnorm(dat$val, main="QQ plot A")
qqline(dat$val)

qqnorm(log(dat$val), main="QQ plot B")
qqline(log(dat$val))

#get Rsquared
qn=qqnorm(log(dat$val), plot.it=FALSE)
rsq_B <- cor(qn$x,qn$y)

#get Rsquared
qn=qqnorm(dat$val, plot.it=FALSE)
rsq_A <- cor(qn$x,qn$y)

QQ 图将完美的正态分布绘制为一条实对角线,然后将我们的实际数据作为标记(圆圈)放在其上。

从图中我们可以看出,我们的数据 A 很好地遵循了正态(实斜线)分布。然而,检查图 B 中的数据,我们可以看到与正常线的实质性偏差,这些偏差显然不是随机的,而是遵循一个趋势(随机偏差在线的任一侧出现的次数相同)。

为了量化这一点,我们可以提取 R 平方(我们将在后面的课程中了解更多关于 R 平方的内容,但它本质上是在 0 到 1 的范围内测量我们的点与对角线的接近程度)。A 和 B 的 R 平方值分别为 0.997 和 0.974。查看数据就足以认识到曲线 B 是非正态的,但是我们也可以选择一个截止值,例如 R 的平方为 0.975,并将低于这个值的任何值称为非正态,将高于这个值的任何值称为正态。

另一种方法是使用夏皮罗检验,它将对我们的数据是否正常进行假设检验:

shapiro.test(dat$val)

这里的关键部分是 P 值,数据 a 的 P 值为 0.84 值越高,分布越正态。通常我们会使用 0.1 的 P 值临界值来确保正态性。因此,任何 p 值为<0.1 we would class as non-normal. This approach is complementary to the above, and I would recommend both plotting a QQ-plot (as above) 的数据都要进行夏皮罗检验(并在任何报告中报告这两个值)。

让我们看看一些非正态(特别是对数正态)数据的 QQ 图和夏皮罗测试:

non_norm <- log(rnorm(75, mean=5,sd=3))

par(mfrow = c(1, 2))
hist(non_norm, main="Histogram of log-normal data", xlab="Values")
qqnorm(non_norm, main="QQ plot for log-normal data")
qqline(non_norm)

上述分布的夏皮罗测试 P 值为 2.4e-09,QQ 图显示了与正常线的系统偏差。这强烈表明我们的数据 B 是非正态的。

假设检验正态分布

一旦我们确信我们的数据是正态分布的(我们稍后将处理非正态数据),我们就可以进行一些假设检验。T-test 通常被用作“go-to”假设检验,但这里我想说服您使用 Welch 检验(记住,要访问 R 中的 Welch 检验,我们调用 t.test()函数,但添加参数 var.equal=FALSE )。韦尔奇检验更适合于我们在现实世界中经常遇到的不等样本量和不等方差的情况。

下面,我运行了一个模拟来演示在方差数据不相等的情况下使用 T-test 优于 Welch tests 的危险性:

#set up vars
nSims <- 20000 #number of simulations
p1 <-c()
p2 <- c()

#create variables for dataframe
catx<-rep("x",38)
caty<-rep("y",22)
condition<- c(catx,caty)

#run simulations
for(i in 1:nSims){ #for each simulated experiment
  sim_a<-rnorm(n = 38, mean = 0, sd = 1.11) #simulate participants condition a
  sim_b<-rnorm(n = 22, mean = 0, sd = 1.84) #simulate participants condition b
  p1[i]<-t.test(sim_a,sim_b, alternative = "two.sided", var.equal = TRUE)$p.value #perform the t-test and store p-value
  p2[i]<-t.test(sim_a,sim_b, alternative = "two.sided", var.equal = FALSE)$p.value #perform the Welch test and store p-value
}

par(mfrow = c(1, 2))
hist(p1, main="Histogram of t-test p-values ", xlab=("Observed p-value"))
hist(p2, main="Histogram of Welch's p-values", xlab=("Observed p-value"))

我们在这里绘制了多次运行模拟后从两次测试中得出的 P 值直方图。我们会记得 p 值是组间差异纯粹是偶然观察到的概率(即组间没有真正的差异)。这里的两个总体具有相同的均值,这意味着我们应该接受零假设,拒绝替代假设(见术语表)。

正如我们所知,人群之间没有真正的差异,我们应该接受零假设,并看到一个平坦的 p 值分布(我们应该看到一个 p 值为<0.05 5% of the time by definition, as a p-value of 0.05 implies a 5% chance of a false result in frequentist statistics). Note that in a real situation we wouldn’t already know if there was or was not a difference between populations!

We see that the right hand histogram of the Welch test results is flat (this is good, it matches what we know about the data). However, the T-test (left hand histogram) performs very poorly here and reports more smaller p-values. This means the chances of us wrongly concluding that 那里 )组之间的显著差异要高得多。准确地说,如果我们在这里使用 T 检验而不是韦尔奇检验,我们有 72 %的可能做出不正确的结论!!!这可能导致接受实际上没有效果的程序或产品创新,浪费时间和金钱。

这个故事的寓意是在正确的时间使用正确的测试。如果数据是正常的,那么我们应该总是使用韦尔奇检验(忽略 T 检验),因为韦尔奇检验比 T 检验有更少的假设。如果数据是非正常的,那么我们需要一个非常不同的测试。

假设检验非正态分布

以上适用于正态分布的数据。但是非正态数据呢?

在现实生活中,我们经常会遇到非正态数据。任何我们的值接近 0 或 100%的情况都可能是非正常的。例如,如果我们观察一家老牌银行的贷款偿还情况,或者如果我们观察一种非常受欢迎(或不受欢迎)的产品的采用情况。

卢旺达农民的非正态分布示例如下(贷款偿还百分比和太阳能灯采用率):

df <- read.csv("./Sample_data.csv")
df$X..Repaid <- df$TotalRepaid/df$TotalCredit * 100
df$solar_A <- df$solar_A *100
d1 <- ggplot(df, aes(x=X..Repaid)) + geom_density(alpha=0.3, fill="red") + ggtitle("% repaid density plot")  + xlab("% repaid") + xlim(75,100)
d2<- ggplot(df, aes(x=solar_A)) + geom_density(alpha=0.3, fill="red") + ggtitle("Solar adoption density plot")  + xlab("% solar adoption") 

multiplot(d1,d2,cols=2)

我们可以从密度图中清楚地看到,我们的数据在两种情况下都是非正态的。但是让我们使用上面概述的诊断来确保:

par(mfrow = c(1, 2)) qqnorm(df$X..Repaid, main="QQ plot for % repaid") qqline(df$X..Repaid) qqnorm(df$solar_A, main="QQ plot for solar adoption") qqline(df$solar_A)#Shapiro test has an upper limit of 5000, so we will randomly take a subset of data to test instead shapiro.test(sample(df$X..Repaid, size=1000))Shapiro-Wilk normality test data: sample(df$X..Repaid, size = 1000) W = 0.54519, p-value < 2.2e-16shapiro.test(sample(df$solar_A, size=1000))Shapiro-Wilk normality test data: sample(df$solar_A, size = 1000) W = 0.87404, p-value < 2.2e-16

哇!这些是一些看起来很糟糕的 QQ 图,和一些非常低的 P 值!数据远非正常。

然而,我们仍然希望对这些数据进行假设检验。

如何检验非正态数据

现在让我们比较一下测试增加 1.5%太阳能利用率的干预措施的方法。我们将使用 T 检验(对非正态数据不正确)、韦尔奇检验(对非正态数据也不正确)和威尔科森检验(对非正态数据的适当检验)。

#load data
norm1 <- df$solar_A
norm2 <- norm1 *1.015

T 检验:

#t test
t.test(norm1,norm2, alternative = "two.sided", var.equal = TRUE)

P 值= 0.1048

韦尔奇试验:

#welch test
t.test(norm1,norm2, alternative = "two.sided", var.equal = FALSE)

P 值= 0.1048

威尔科克森试验:

wilcox.test(norm1 , norm2 ,paired=FALSE, correct=TRUE)

P 值= 1.55e-06

我们可以看到我们得到了非常不同的结果!T 检验和 Welch 检验报告 p 值为 0.105 和 0.105,这表明在典型的 p 值阈值 0.05 下无显著性。而 Wilcoxon 试验表明 p 值为 1.55e-06。

你可以看到,根据我们使用的测试,我们会得出完全不同的结果。T 检验和 Welch 检验会使我们相信干预是没有用的,而 Wilcoxon 检验清楚地表明干预似乎有效果。因此,对正确的数据使用正确的测试非常重要。想象一下,如果我们一直在测试一种对农民有害的干预措施,但使用了错误的测试方法,因此得出干预措施是安全的结论!

我们现在可以将 Wilcoxon 测试添加到我们的库中:

  • Wilcoxon-test :对假设很少的非正态数据的良好测试。我们正在测试两个数据集具有不同分布的假设。这里的主要假设是:1)样本随机代表总体,2)样本相互独立,3)值有顺序(如 3 大于 1,但不能说真大于假)。

报告数据

我们现在已经了解了如何计算数据的稳健 P 值。然而,我们报告数据的方式也取决于分布的形状。对于正常数据,我们可以简单地报告平均值和置信区间,例如平均值为每英亩 4.5(CI:1.5–7.5)千克(您也可以报告带有标准误差的平均值,只要您报告的内容清晰明了)。非正态数据有点复杂,我们通常应该报告中位数、第一和第三四分位数,例如中位数 4.5 (Q1 2.5 & Q3 6)

我们将记住,正态分布是对称的,正是非正态分布的不对称性阻止了我们报告 CIs、SEMs 或 StDevs(因为这些都是基于对称性的)。

与上述假设检验思想相关的一个概念是统计功效。幂用于计算样本量,也用于解释试验后 RCT 的结果。低功率意味着我们的结果不太可靠,我们可能会对干预做出错误的结论。

我们使用正确的功率计算非常重要,就像我们使用正确的假设检验一样重要。功率计算取决于数据分布,R 中最常用的功率计算器适用于正态分布的数据。这个计算器需要一个“效果大小”,这是一个简单的方法来衡量治疗的效果。效应大小基本上是样本间平均值的差异除以样本的标准差。这意味着单位是标准偏差。因此,效应大小为 1 意味着数据移动了等于 1 个标准差的量。我在下面加入了一个函数,使用科恩的 D 方程计算效应大小:

cohen_d <- function(d1,d2) {  

  m1 <- mean(d1, na.rm=TRUE)
  m2 <- mean(d2, na.rm=TRUE)
  s1 <- sd(d1, na.rm=TRUE)
  s2 <- sd(d2, na.rm=TRUE)
  spo <- sqrt((s1**2 + s2**2)/2)
  d <- (m1 - m2)/spo
  rpb <- d / sqrt((d**2)+4)
  ret <- list("rpb" = rpb, "effectsi" = d)
  return(ret)  }

现在我们有了一种计算效果大小的方法,让我们用它来计算一项有正常数据和 100 名参与者的研究的功效。我们将使用 pwr 库中的函数“pwr.t.test”。该函数需要以下参数:

  • h —这是由上面的科恩 D 方程计算出的效应大小。我们用对象后面的“$effectsi”来调用它(详见代码)。
  • n——每个样本的样本量
  • sig.level —这是我们希望在分析中使用的 p 值临界值。这通常是 0.05 或 0.1。
  • power —我们希望将此设置为 NULL,以获得将电源返回给我们的功能。

我们一起将这个库称为“pwr”。

其中“length()”参数返回名为“norm”的列表中元素的数量。

norm <- rnorm(200,40,10)
norm2 <- norm*1.1
inp <- cohen_d(norm, norm2)

这里我们看到我们有一个 0.97 的幂。理想情况下,我们希望功效高于 0.75–0.8,以获得准确检测效果的良好概率。

请注意,我们可以通过填写幂参数并将 n 设置为空来计算 0.8 的幂所需的样本量,如下所示(这是一个略有不同的等式,因为我们假设对照组和治疗组的大小相等):

*pwr.t.test(n= NULL, d= inp$effectsi, power=0.8, alternative="two.sided")*

我们可以循环查看不同样本大小的功效,然后用一条线标出功效为 0.8 的位置。

power_out <- c() # initialise this empty so we can append to it
sample_sizes <- c(2,4,6,10,20,30,40,50,70,90,110,130)
for(i in sample_sizes){
  x <- pwr.t.test(n= i, d= inp$effectsi, power=NULL, alternative="two.sided")$power
  power_out <- c(power_out, x)

}

p <- ggplot() + geom_line(aes(x=sample_sizes, y= power_out)) + geom_hline(yintercept = 0.8, color="red", size=2) + ggtitle("Example power curve")
p

像上面这样的图可以帮助你了解什么样的样本大小和功效是合理的。我强烈建议绘制功效曲线的下限(即你可能看到的最小功效)和上限(即你可能看到的最大功效)。

运行一个完整的例子:让我们想象我们想要运行一个 RCT(或 A/B 测试),检查一个新的利率对肥料使用的影响。我们有两组,一组是对照组,利率和之前一样。以及利率降低 3 个点(例如 15%的利息而不是 18%)的治疗组。我们对客户的了解意味着,我们认为通过这种处理方式,化肥的使用量将增加 15%至 25%。我们绘制如下的功率曲线(请检查代码并确保您理解了代码):

control <- rnorm(100, 0.5,0.2)
treat_lower_estimate <- control *1.15
treat_upper_estimate <- control *1.25

power_lw <- c() # initialise this empty so we can append to it
power_hi <- c() # initialise this empty so we can append to it
sample_sizes <- c(10,20,30,40,50,70,90,100,125,150,175,200,250,300,350,400,450,500,550,600,700)
for(i in sample_sizes){

  lower_cohen <- cohen_d(control, treat_lower_estimate)
  a <- pwr.t.test(d = lower_cohen$effectsi , n=i,  sig.level = 0.05, power = NULL)$power
  power_lw <- c(power_lw, a)

  upper_cohen <- cohen_d(control, treat_upper_estimate)
  b <- pwr.t.test(d = upper_cohen$effectsi , n=i,  sig.level = 0.05, power = NULL)$power
  power_hi <- c(power_hi, b)

}

marker <- pwr.t.test(d = lower_cohen$effectsi , n=NULL,  sig.level = 0.05, power = 0.8)$n
marker2 <- pwr.t.test(d = upper_cohen$effectsi , n=NULL,  sig.level = 0.05, power = 0.8)$n
ggplot() + geom_ribbon(aes(x=sample_sizes, ymin= power_lw, ymax=power_hi), alpha=0.2, colour="blue", fill="blue")  + xlab("Sample size") + ylab("Power") + geom_vline(xintercept = marker, linetype="dotted" ) + geom_hline(yintercept=0.8, linetype="dotted", size=2) + geom_vline(xintercept = marker2 , linetype="dotted") + labs(title="Power curve example", caption="Power curve indicating sample sizes needed for a 0.8 power (dotted lines)") + theme(plot.caption = element_text(hjust = 0.5))

上面的图让我们看到它需要一个大的样本量(n 大约是。200,所以我们在这个试验中需要 400 个参与者——200 个控制组和 200 个治疗组)来检测 15%的采用变化,其功效为 0.8。像这样绘制数据允许更灵活的决策,强烈建议这样做。

非正态分布数据和样本大小/功效

对于正常的功率计算来说,以上都没问题。但是非正常力量呢?

我们对此也有解决方案!

我在下面做了一个函数(“MCpower”),它将计算非正态分布的功率。它需要样本 1 和 2(处理和对照)的数据(或预期数据)和样本大小(“大小”参数)。

请确保你理解这个代码,并舒适地使用它

MCpower = function(sample1, sample2, size) {

  reps = 1000
    results  <- sapply(1:reps, function(r) {
        resample1 <- sample(sample1, size=size, replace=TRUE) 
        resample2 <- sample(sample2, size=size, replace=TRUE) 
        test <- wilcox.test(resample1, resample2, alternative="two.sided",paired=FALSE, correct=TRUE)
        test$p.value
    })
    sum(results<0.05)/reps
}

#we use it like this
Non_norm_power <- MCpower(control, treat_upper_estimate, 100)

我们可以比较这些方法来理解为什么我们需要对正确的数据使用正确的测试。让我们进行一些模拟实验。下面的数据是非正态,样本之间是有差异的。因此,我们期望看到统计上的显著差异。请注意,虽然正常的功效测试或假设测试将测试均值,但这里的功效计算将测试分布的总体相似性。

让我们运行一个模拟,计算用不同方法测试两个总体之间的差异所需的功效:

#set up vars
nSims <- 500 #number of simulations

#initialise empty vectors for appending to
x1 <- c()
x2 <- c()
p1 <- c()
p2 <- c()

#run simulations
for(i in 1:nSims){ #for each simulated experiment
  set.seed(i)
  sim_a <- c(rnorm(150, mean=130,sd=20) )**2
  sim_b <- c(rnorm(150, mean=120,sd=35) )**2
  sim_b[which(is.nan(sim_b)==TRUE)] <- 1
  sim_a[which(is.nan(sim_a)==TRUE)] <- 1
  inp <- cohen_d(sim_a, sim_b) # effect size
  x1[i] <- pwr.t.test(d= inp$effectsi , n =length(sim_a), sig.level = 0.05, power = NULL)$power
  x2[i] <- MCpower(sim_a, sim_b,  size=150) 
  p1[i] <- t.test(sim_a,sim_b)$p.value
  p2[i] <- wilcox.test(sim_a,sim_b, paired=FALSE, correct=TRUE)$p.value
}

#hist(sim_b, bins=20)
#shapiro.test(sim_b)
par(mfrow = c(1, 2))
hist(x1, main="Histogram of normal powers ", xlab=("Observed power"), xlim =c(0,1))
hist(x2, main="Histogram of MC powers", xlab=("Observed power"), xlim =c(0,1))

数百次 t 检验模拟的平均 p 值为 0.133,MC 检验的平均 p 值为 0.0305(参见上述分布直方图)。我们现在知道 T-检验假设正态分布,这在这里是不正确的,而 MC 方法只需要满足很少的假设。我们可以看到,MC 方法通常具有更高的功效,并且经常正确地识别出这些样本之间存在显著差异,不像 T 检验表现不佳。

注意,对于正常数据,正常功率计算的结果和我的 MC 方法非常相似。比较效应大小为 1 的两种分布,标准方法和 MC 方法的 P 值分别为 0.012 和 0.014,功效分别为 0.86 和 0.85。

摘要

我们现在已经了解了如何绘制和呈现数据,以使其简单且真实地反映基础数据,我们还了解了如何计算 RCT 中正常和非正常数据的 p 值和乘方,以及当我们的假设有误时会发生什么。我附上了一个简短的流程图来说明需要作出的决定:

分析 RCT 的最佳实践:

  • 即使您在 RCT 前计算样本量,计算 RCT 后的功效(与样本量相关)也很重要,以确保我们的研究有足够的功效。请记住,低功率意味着我们不太可能检测到干预的效果,通常会使我们的结果不太可靠。我希望每一次 RCT 分析都从关键变量的功效计算开始
  • 我们还必须绘制关键变量的分布图。在 RCT 中,我们通常会观察 2 个或更多组(例如对照组和治疗组)。因此,我建议在分析开始时为每个关键变量绘制密度图或箱线图。R-Markdown(这是本课的内容)在这里非常有用,将成为 AMP 的重点。
  • 检验我们的假设。在决定使用什么方法之前,我们应该对我们的数据进行 Shapiro 测试,以确保它是正常的(例如 T-测试或 Wilcoxon 测试)。
  • 对于正态分布数据,始终报告 p 值的平均值和置信区间,对于非正态数据,报告中位数和第一个及第三个四分位数。
  • 确保图表简单,但真实的数据

统计测试概述

  • T 检验:假设正态分布。该测试是在 20 世纪 50 年代针对小样本量进行的,现在有了更可靠的测试,应该使用
  • 配对 T-检验:T-检验(如上),但用于测量治疗前后的同一受试者(例如,测量发传单活动前后的农民种植依从性)
  • 双样本 T 检验:用于两个不同组的 T 检验,例如比较接受治疗的农民和对照农民的玉米产量。
  • Welch 检验:对 T 检验的改进,对不等方差更稳健(例如,对密度图宽度不同的样本更稳健)。我们可以在 t.test() R 函数中调用带有参数“var.equal=FALSE”的 Welch 测试。请注意,韦尔奇检验仅对正态分布数据有效(如 T 检验)。
  • Wilcoxon-test :对假设很少的非正态数据的良好测试。我们正在测试两个数据集具有不同分布的假设。这里的主要假设是:1)样本随机代表总体,2)样本相互独立,3)值有顺序(如 3 大于 1,但不能说真大于假)。

资源

  • 设置/安装说明 R
  • 互动 R 基础教程——强烈推荐
  • Base R cheatsheet —强烈推荐,打印出来放在办公桌上!
  • 非互动教程(如果那是你的事)
  • Youtube 教程
  • 备忘单 —仅推荐给更高级的 R 用户
  • StackOverFlow —针对具体的技术问题

词汇表

  • 观察:在统计学中,这是一个变量在特定时间的值。我们也可以把观察看作数据帧中的数据行
  • 变量:可以观察到的特性。这也可以被称为一个特性,可以被认为是数据帧中的一列(例如:性别、糖价或收成)。
  • 正态:正态分布是近似对称的,均值一定等于中位数。数据点离平均值越远,发生的可能性就越小。正常数据也称为“钟形数据”。
  • 方差和标准差:方差是正态分布的宽度。标准差是方差的平方根。我们可以认为这是数据的分布,高方差意味着大量的可变性,低方差意味着大多数观测值将具有非常相似的值。
  • 四分位数:四分位数是另一种数据度量。如果我将一个变量的所有值按顺序排列,那么第一个四分位数就是总长度的四分之一。同样,第三个四分位数将是四分之三长度的值。例如,数据 1,3,6,8,10,14,15,18,20,22,25,26 的第一个四分位数为 6 ,第三个四分位数为 20
  • 人口:从大量潜在数据中抽取样本。
  • 样本:我们有数据的总体的子集。例如,我们可能正在研究一个由 1000 名肯尼亚农民组成的样本,但是想要推广到整个肯尼亚农民人口
  • P 值:观察结果完全随机产生的概率(即群体之间没有真正差异的概率)
  • 功效:在给定样本量、分布和误差率的情况下,我们能够检测出两个总体之间差异的概率。请注意,功率也会影响我们的结果的稳健程度。
  • 效果大小:2 组之间的标准化差异。它有单位 stdev 。因此,1 的效应大小等于 1 stdev 的差值。群体之间。
  • 假设检验:统计检验。每个假设检验有两个部分,一个是零假设,表示两个群体是相同的(即没有差异),另一个是替代假设,表示两个群体之间有差异。通常,零假设被称为 H0,替代假设被称为 H1。
  • 标准形式/科学记数法:我们可以用标准形式写出有很多零的数字。例如 0.001 变成 1e-3,1000 变成 1e+3(意思是 1 *10 的 3 次方)。
  • 直方图:矩形图(也称为条柱),条柱的高度与观察值的数量成比例,宽度与包含的值的范围成比例。

下一篇文章:

  • 最小可检测影响
  • 计划 A/B 测试
  • 集群内效应
  • 还有更多!

最初发布于Michael-bar . github . io

如果你在这些帖子中看到任何错误,请留下评论!同样,如果任何事情需要进一步的解释,然后评论!

文本表示和相似性介绍

原文:https://towardsdatascience.com/introduction-to-text-representation-and-similarity-b5dd3fd71737?source=collection_archive---------0-----------------------

机器学习和数据挖掘任务中最基本的就是比较对象的能力。我们必须在聚类、分类、查询和其他方面比较(有时是平均)对象。文本也不例外,在这篇文章中,我想探索文本的不同表示/嵌入以及一些最流行的距离/相似度函数。

首先,我想谈谈我们希望文本表示和距离/相似性函数具有什么样的属性:

  1. 相同的文本必须具有相同的表示和零距离(最大相似度)。
  2. 当我们有多个文本 t1、t2 和 t3 时,我们希望能够说 t1 比 t3 更类似于 t2。
  3. 相似度/距离应该表达文本之间的语义比较,文本长度应该影响不大。

那么让我们开始,考虑这三句话:

s1 = “David loves dogs”
s2 = “Dogs are ok with David”
s3 = “Cats love rain”

现在假设我们想把这些句子分成两组。很明显,句子 1 和句子 2 属于同一组。但是我们如何通过编程来比较它们呢?

为此,我们将定义 2 个函数:1)向量函数,它获取某个句子并返回表示该句子的向量。以及 2)距离函数,其接收两个向量并返回它们如何远离或相似。

最基本的表达句子的方式是使用一组单词。在大多数情况下,我们会希望预处理我们的文本,以减少噪音。预处理可能包括小写、词干、删除停用词等。在我们的例子中,我们将把单词转换成它的基本形式,并去掉无用的单词。所以句子是:

s1 = (“david”, “love”, “dog”)
s2 = (“dog”,”ok”,”david”)
s3 = (“cat”,”love”,”rain”)

比较这些句子,我们可以用 Jaccard 相似度。Jaccard 相似度是两个句子的常用词数量(交集)和总词数量(并集)之间的比例。句子 1 和 2 的并集是(“大卫”、“爱”、“狗”、“好”),交集是(“大卫”、“狗”),所以 Jaccard 相似度将是 2/4 = 0.5。

另一方面,句子 1 和 3 之间的 Jaccard 相似度是 1/6 = 0.166,句子 2 和 3 之间的相似度是 0/6 = 0。

虽然这种方法解决了我们的问题,但也有一些缺点。概括这些缺点的最佳方式是表示和距离函数都不是“数学的”,即我们不能进行句子平均,例如,使用其他数学函数操纵距离函数(如求导)。

为了解决这个问题,我们必须用一种更科学的方式来表达我们的句子:向量。

这非常简单:我们将使用语料库中的所有单词(所有句子)构建一个词汇表,每个单词都有一个索引。在我们的示例中,它看起来像这样:

{'cat': 0, 'david': 1, 'dog': 2, 'love': 3, 'ok': 4, 'rain': 5}

我们将把每个句子表示为一个 6 维向量,并在索引中为每个单词存储 1,在其他地方存储 0。以下是我们的句子:

s1 = [0, 1, 1, 1, 0, 0]     
s2 = [0, 1, 1, 0, 1, 0]    
s3 = [1, 0, 0, 1, 0, 1] 

现在,每个句子只是 6 维空间中的一个点(或一个向量)。以下是我们使用主成分分析法在二维空间中将其可视化后的效果:

Sentence 1 and 2 — Blue, Sentence 3 — Red

你可以看到第一句和第二句的观点都比第三句更接近。有很多种方式来表达他们之间的距离。最直观的是“欧几里德距离”(也叫 L2 范数)其中计算这条线:

当然,没必要自己实现;有很多实现(例如 python 中的 numpy.linalg.norm)。

这是欧几里德距离的值:

 ╔══════╦════════╦════════╦════════╗
                 ║      ║   **S1**   ║   **S2**   ║   **S3**   ║  
                 ╠══════╬════════╬════════╬════════╣
                 ║ **S1**   ║    0   ║  1.41  ║    2   ║
                 ╠══════╬════════╬════════╬════════╣
                 ║ **S2**   ║  1.41  ║   0    ║  2.44  ║
                 ╠══════╬════════╬════════╬════════╣
                 ║ **S2**   ║    2   ║  2.44  ║    0   ║
                 ╚══════╩════════╩════════╩════════╝

它看起来不错,但还是有一些缺点。很多时候,文本语义是由某个词出现的次数决定的。例如,如果我们阅读一篇关于“向量”的文章,那么“向量”这个术语会出现很多次。在这种情况下,在我们的文本向量中只使用二进制值将忽略文本的真正语义。最简单的解决方案是将单词出现的次数存储在向量的正确位置。

考虑这些句子:

s1 = “David loves dogs dogs dogs dogs”
s2 = “Dogs are ok with David”
s3 = “Cats love rain”

当然,第一句话在语法上是不正确的,但是我们可以说它是关于狗的。让我们看看相应的向量:

s1 = [0, 1, 5, 1, 0, 0]     
s2 = [0, 1, 1, 0, 1, 0]    
s3 = [1, 0, 0, 1, 0, 1]

这几个向量和前面的唯一区别是,这一次,我们在第一个句子向量的“狗”位置存储 5。

让我们再次使用 PCA 绘制这些向量:

Sentence 1 — Blue, Sentence 2 — Green, Sentence 3 — Red

看看发生了什么;现在,句子 2(绿色)和 3(红色)比 1(蓝色)和 2(绿色)更接近。这对我们非常不利,因为我们不能表达句子的语义。

这个问题最典型的解决方案是,我们可以比较两个向量之间的角度,而不是计算两点之间的距离,例如,这些值:

你可以看到句子 1 和 2 的角度比 1 和 3 或者 2 和 3 更近。实际的相似性度量被称为“余弦相似性,它是两个向量之间角度的余弦。0 的余弦是 1(最相似),180 的余弦是 0(最不相似)。

这样,我们能够更好地表示文本的语义,以及比较文本对象。

结论

我们看到了表示文本和比较文本对象的不同方法。没有更好或最好的方法,在文本机器学习和数据挖掘相关任务中有许多类型的问题和挑战,我们应该了解并选择适合我们的选项。

还有许多其他的表示和距离/相似性函数,包括 TfIdf 和 Word2Vec,它们是非常常见的文本表示(我希望我会再写一篇文章)。

电报 API 简介

原文:https://towardsdatascience.com/introduction-to-the-telegram-api-b0cd220dbed2?source=collection_archive---------0-----------------------

用程序分析你的电报通话记录

T elegram 是一种即时通讯服务,就像 WhatsApp、Facebook Messenger 和微信一样。近年来,它因为各种原因而广受欢迎:它的非盈利性质、跨平台支持、安全承诺 ,以及它的开放 API。

在这篇文章中,我们将使用 Telethon ,一个用于 Telegram API 的 Python 客户端库,来统计我们每个 Telegram 聊天中的消息数量。

电报 API

Telegram has an open API and protocol free for everyone.” — Telegram homepage

Telegram 的 API 中最著名的是它的 Bot API,这是一个基于 HTTP 的 API,供开发人员与 Bot 平台进行交互。Bot API 允许开发者控制电报机器人,例如接收消息和回复其他用户。

除了 Bot API,还有 Telegram API 本身。这是 Telegram 应用程序使用的 API,用于您在 Telegram 上的所有操作。仅举几个例子:查看您的聊天记录、发送和接收消息、更改您的显示图片或创建新群组。通过 Telegram API,你可以用编程的方式做你在 Telegram 应用程序中能做的任何事情。

Telegram API 比 Bot API 复杂得多。您可以使用标准 JSON、表单或查询字符串有效负载通过 HTTP 请求访问 Bot API,而 Telegram API 使用自己的自定义有效负载格式和加密协议。

电报 API

Diagram for MTProto server-client flow

MTProto 是定制的加密方案,支持 Telegram 的安全承诺。它是一种应用层协议,直接写入底层传输流,如 TCP 或 UDP,以及 HTTP。幸运的是,在使用客户端库时,我们不需要直接关心它。另一方面,为了进行 API 调用,我们确实需要理解有效载荷的格式。

类型语言

Telegram API 是基于 RPC 的,因此与 API 的交互包括发送表示函数调用的有效载荷和接收结果。例如,读取一个对话的内容包括用必要的参数调用messages.getMessage函数,并接收一个messages.Messages作为返回。

类型语言或 TL 用于表示 API 使用的类型和函数。TL 模式是可用类型和函数的集合。在 MTProto 中,TL 构造在作为 MTProto 消息的有效载荷嵌入之前将被序列化为二进制形式,但是我们可以将此留给我们将使用的客户端库。

一个 TL 模式的例子(首先声明类型,然后声明函数,函数之间用分隔符隔开):

auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;auth.sentAppCode#e325edcf phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;---functions---auth.sendCode#768d5f4d phone_number:string sms_type:int api_id:int api_hash:string lang_code:string = auth.SentCode;

使用上述 TL 模式中的函数和类型的 TL 函数调用和结果,以及等效的二进制表示(来自官方文档):

(auth.sendCode "79991234567" 1 32 "test-hash" "en")
=
(auth.sentCode
  phone_registered:(boolFalse)
  phone_code_hash:"2dc02d2cda9e615c84"
)

d16ff372 3939370b 33323139 37363534 00000001 00000020 73657409 61682d74 00006873 e77e812d
=
2215bcbd bc799737 63643212 32643230 39616463 35313665 00343863 e12b7901

TL-模式层

电报 API 使用 TL 模式层进行版本控制;每一层都有一个唯一的 TL 模式。Telegram 网站包含当前的 TL 模式和 https://core.telegram.org/schema的先前层。

看起来是这样,事实证明,虽然 Telegram 网站上最新的 TL-Schema 层是第 23 层,但在撰写本文时,最新的层实际上已经是第 71 层了。你可以在这里找到最新的 TL-Schema。

入门指南

创建电报应用程序

您将需要获得一个api_idapi_hash来与电报 API 交互。请遵循官方文档中的说明:https://core.telegram.org/api/obtaining_api_id。

您必须访问https://my.telegram.org/,使用您的电话号码和确认码登录,确认码将通过电报发送,并在“API 开发工具”下的表格中填写应用标题和简称。之后,你可以在同一个地方找到你的api_idapi_hash

或者,相同的说明提到您可以使用电报源代码中的样本凭证进行测试。为了方便起见,我将在这里的示例代码中使用我在 GitHub 上的 Telegram 桌面源代码中找到的凭证。

安装天线

我们将使用 Telethon 与 Telegram API 通信。Telethon 是用于 Telegram API 的 Python 3 客户端库(这意味着您必须使用 Python 3 ),它将为我们处理所有特定于协议的任务,因此我们只需要知道使用什么类型和调用什么函数。

您可以使用pip安装 Telethon:

pip install telethon

使用与您的 Python 3 解释器相对应的pip;这可能是pip3代替。(随机:最近 Ubuntu 17.10 发布了,它使用 Python 3 作为默认的 Python 安装。)

创建客户端

在开始与 Telegram API 交互之前,您需要用您的api_idapi_hash创建一个客户端对象,并用您的电话号码对其进行认证。这类似于在新设备上登录 Telegram 你可以把这个客户端想象成另一个 Telegram 应用。

下面是创建和验证客户端对象的一些代码,修改自 Telethon 文档:

from telethon import TelegramClient
from telethon.errors.rpc_errors_401 import SessionPasswordNeededError

# (1) Use your own values here
api_id = 17349
api_hash = '344583e45741c457fe1862106095a5eb'

phone = 'YOUR_NUMBER_HERE'
username = 'username'

# (2) Create the client and connect
client = TelegramClient(username, api_id, api_hash)
client.connect()

# Ensure you're authorized
if not client.is_user_authorized():
    client.send_code_request(phone)
    try:
        client.sign_in(phone, input('Enter the code: '))
    except SessionPasswordNeededError:
        client.sign_in(password=input('Password: '))

me = client.get_me()
print(me)

如前所述,上面的api_idapi_hash来自电报桌面源代码。将您自己的电话号码放入phone变量中。

Telethon 将在其工作目录中创建一个.session文件来保存会话细节,就像你不必在每次关闭和重新打开 Telegram 应用程序时重新验证它们一样。文件名将以username变量开始。如果您想使用多个会话,您可以决定是否要更改它。

如果没有之前的会话,运行此代码将通过电报向您发送授权代码。如果您在电报帐户上启用了两步验证,您还需要输入您的电报密码。认证一次并保存.session文件后,即使您再次运行脚本,您也不必再次重新认证,直到您的会话到期。

如果成功创建并验证了客户机,应该会在控制台上打印出一个代表您自己的对象。它看起来类似于(省略号表示跳过了一些内容):

User(is_self=True … first_name='Jiayu', last_name=None, username='USERNAME', phone='PHONE_NUMBER' …

现在,您可以使用这个客户机对象开始向 Telegram API 发出请求。

使用电报 API

检查 TL 模式

如前所述,使用 Telegram API 包括调用 TL 模式中的可用函数。在这种情况下,我们对messages.GetDialogs函数感兴趣。我们还需要注意函数参数中的相关类型。下面是我们将用来发出这个请求的 TL 模式的一个子集:

messages.dialogs#15ba6c40 dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;---functions---messages.getDialogs#191ba9c5 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int = messages.Dialogs;

这并不容易理解,但请注意,messages.getDialogs函数将返回一个messages.Dialogs,它是一个抽象类型,用于包含DialogMessageChatUser向量的messages.dialogsmessages.dialogsSlice对象。

使用 Telethon 文档

幸运的是,Telethon 文档给出了关于如何调用这个函数的更多细节。从https://lonamiwebs.github.io/Telethon/index.html,如果您在搜索框中键入getdialogs,您将看到一个名为GetDialogsRequest的方法的结果(TL-Schema 函数由 Telethon 中的*Request对象表示)。

GetDialogsRequest的文档陈述了方法的返回类型以及关于参数的更多细节。当我们想要使用这个对象时,“复制导入到剪贴板”按钮特别有用,就像现在。

https://lonamiwebs.github.io/Telethon/methods/messages/get_dialogs.html

messages.getDialogs函数以及GetDialogsRequest的构造函数接受一个InputPeer类型的offset_peer参数。在 GetDialogsRequest 的文档中,单击InputPeer链接可以看到一个页面,其中描述了获取和返回该类型的构造函数和方法。

https://lonamiwebs.github.io/Telethon/types/input_peer.html

因为我们想创建一个InputPeer对象作为GetDialogsRequest的参数,所以我们对InputPeer的构造函数感兴趣。在这种情况下,我们将使用InputPeerEmpty构造函数。再次点击进入InputPeerEmpty页面,复制它的导入路径来使用它。InputPeerEmpty构造函数没有参数。

提出请求

下面是我们完成的GetDialogsRequest以及如何通过将它传递给我们授权的客户端对象来获得它的结果:

from telethon.tl.functions.messages import GetDialogsRequest
from telethon.tl.types import InputPeerEmpty

get_dialogs = GetDialogsRequest(
    offset_date=None,
    offset_id=0,
    offset_peer=InputPeerEmpty(),
    limit=30,
)dialogs = client(get_dialogs)
print(dialogs)

在我的例子中,我得到了一个包含对话、消息、聊天和用户列表的DialogsSlice对象,正如我们基于 TL-Schema 所期望的:

DialogsSlice(count=204, dialogs=[…], messages=[…], chats=[…], users=[…])

收到一个DialogsSlice而不是Dialogs意味着不是我所有的对话框都被返回,但是count属性告诉我我总共有多少个对话框。如果您的对话少于某个数量,您可能会收到一个Dialogs对象,在这种情况下,您的所有对话都被返回,您拥有的对话的数量就是向量的长度。

术语

Telegram API 使用的术语有时可能会有点混乱,尤其是在缺少类型定义以外的信息的情况下。什么是“对话”、“消息”、“聊天”和“用户”?

  • dialogs代表您的对话历史中的对话
  • chats代表与您的对话历史中的对话相对应的群组和频道
  • messages包含发送给每个对话的最后一条消息,就像您在 Telegram 应用程序的对话列表中看到的那样
  • users包含您与之进行一对一聊天的个人用户,或者向您的某个群组发送最后一条消息的人

例如,如果我的聊天记录是我从 Play Store 中的 Telegram 应用程序获取的截图:

dialogs将包含截图中的对话:老海盗,新闻发布室,莫妮卡,吉安娜…

将包含老海盗、新闻发布室和 Meme 工厂的条目。

messages将包含消息“请上车!”来自老海盗,“哇,提得好!”从新闻发布室,一条代表发给莫妮卡的照片的消息,一条代表吉安娜的回复的消息等等。

users将包含自从 Ashley 向新闻发布室发送最后一条消息以来的条目,以及自从他向 Meme 工厂发送最后一条消息以来的 Monika、Jaina、Kate 和 Winston 的条目。

(我还没有通过 Telegram API 处理过秘密聊天,所以我不确定它们是如何处理的。)

计数消息

我们的目标是统计每次对话中的消息数量。要获得一个会话的消息数量,我们可以使用 TL-Schema 中的messages.getHistory函数:

messages.getHistory#afa92846 peer:[InputPeer](https://lonamiwebs.github.io/Telethon/types/input_peer.html) offset_id:[int](https://lonamiwebs.github.io/Telethon/index.html#int) offset_date:[date](https://lonamiwebs.github.io/Telethon/index.html#date) add_offset:[int](https://lonamiwebs.github.io/Telethon/index.html#int) limit:[int](https://lonamiwebs.github.io/Telethon/index.html#int) max_id:[int](https://lonamiwebs.github.io/Telethon/index.html#int) min_id:[int](https://lonamiwebs.github.io/Telethon/index.html#int) = [messages.Messages](https://lonamiwebs.github.io/Telethon/types/messages/messages.html)

按照与前面使用messages.getDialogs类似的过程,我们可以使用GetHistoryRequest来解决如何使用 Telethon 调用它。这将返回一个MessagesMessagesSlice对象,或者包含一个count属性,告诉我们一个对话中有多少条消息,或者一个对话中的所有消息,这样我们就可以计算它包含的消息数。

然而,我们首先必须为我们的GetHistoryRequest构建正确的InputPeer。这一次,我们使用InputPeerEmpty,因为我们想要检索特定对话的消息历史。相反,我们必须根据对话的性质使用InputPeerUserInputPeerChatInputPeerChannel构造函数。

操纵响应数据

为了统计每个对话中的消息数量,我们必须为该对话创建一个GetHistoryRequest,并为该对话创建相应的InputPeer

所有相关的InputPeer构造函数都采用相同的idaccess_hash参数,但是根据对话是一对一聊天、群组还是频道,这些值出现在GetDialogsRequest响应的不同位置:

  • dialogs:我们希望对其中的消息进行计数的会话列表,包含一个peer值,以及对应于该会话的对等方的类型和id,但不包含access_hash
  • chats:包含idaccess_hash以及本集团和频道的标题。
  • users:包含我们个人聊天的idaccess_hash和名字。

在伪代码中,我们有:

let counts be a mapping from conversations to message countsfor each dialog in dialogs:
    if dialog.peer is a channel:
        channel = corresponding object in chats
        name = channel.title
        id = channel.id
        access_hash = channel.access_hash
        peer = InputPeerChannel(id, access_hash)
    else if dialog.peer is a group:
        group = corresponding object in chats
        name = group.title
        id = group.id
        peer = InputPeerChat(id)
    else if dialog.peer is a user:
        user = corresponding object in users
        name = user.first_name
        id = user.id
        access_hash = user.access_hash
        peer = InputPeerUser(id, access_hash) history = message history for peer
    count = number of messages in history counts[name] = count

转换成 Python 代码(注意上面的dialogschatsusers是我们的GetDialogsRequest的结果的成员,也称为dialogs):

counts = {}

# create dictionary of ids to users and chats
users = {}
chats = {}

for u in dialogs.users:
    users[u.id] = u

for c in dialogs.chats:
    chats[c.id] = c

for d in dialogs.dialogs:
    peer = d.peer
    if isinstance(peer, PeerChannel):
        id = peer.channel_id
        channel = chats[id]
        access_hash = channel.access_hash
        name = channel.title

        input_peer = InputPeerChannel(id, access_hash)
    elif isinstance(peer, PeerChat):
        id = peer.chat_id
        group = chats[id]
        name = group.title

        input_peer = InputPeerChat(id)
    elif isinstance(peer, PeerUser):
        id = peer.user_id
        user = users[id]
        access_hash = user.access_hash
        name = user.first_name

        input_peer = InputPeerUser(id, access_hash)
    else:
        continue

    get_history = GetHistoryRequest(
        peer=input_peer,
        offset_id=0,
        offset_date=None,
        add_offset=0,
        limit=1,
        max_id=0,
        min_id=0,
    )

    history = client(get_history)
    if isinstance(history, Messages):
        count = len(history.messages)
    else:
        count = history.count

    counts[name] = count

print(counts)

我们的counts对象是一个聊天名称到消息计数的字典。我们可以对它进行排序和漂亮的打印,以查看我们的热门对话:

sorted_counts = sorted(counts.items(), key=lambda x: x[1], reverse=True)
for name, count in sorted_counts:
    print('{}: {}'.format(name, count))

示例输出:

Group chat 1: 10000
Group chat 2: 3003
Channel 1: 2000
Chat 1: 1500
Chat 2: 300

图书馆魔术

Telethon 有一些帮助功能来简化常见操作。实际上,我们可以用其中的两个帮助器方法来完成上面的工作,client.get_dialogs()client.get_message_history(),取而代之:

from telethon.tl.types import User

_, entities = client.get_dialogs(limit=30)

counts = []
for e in entities:
    if isinstance(e, User):
        name = e.first_name
    else:
        name = e.title

    count, _, _ = client.get_message_history(e, limit=1)
    counts.append((name, count))

message_counts.sort(key=lambda x: x[1], reverse=True)
for name, count in counts:
    print('{}: {}'.format(name, count))

然而,我觉得首先直接调用 Telegram API 方法是一种更好的学习体验,特别是因为没有一个助手方法适用于所有情况。然而,有一些事情使用 helper 方法要简单得多,比如我们如何在开始时认证我们的客户端,或者上传文件之类的动作,否则这些动作会很乏味。

包扎

这个例子的完整代码可以在这里找到一个要点:https://Gist . github . com/yi-Jiayu/7b 34260 cfbfa 6 CB C2 b 4464 edd 41 def 42

使用 Telegram API 可以做更多的事情,尤其是从分析的角度来看。在想到我的一个老项目后,我开始研究这个项目,试图从导出的 WhatsApp 聊天记录中创建数据可视化:https://github.com/yi-jiayu/chat-analytics。

使用 regex 解析通过电子邮件发送的纯文本聊天记录,我可以生成一个类似于 GitHub punch card 存储库图表的图表,显示一周中的哪些时间聊天最活跃:

然而,使用“电子邮件聊天”功能来导出是相当粗糙的,你需要手动导出每个聊天的对话历史,一旦你收到新消息,它就会过时。我并没有继续这个项目,但是我一直认为可以从聊天记录中获得其他见解。

通过编程访问聊天记录,Telegram 聊天可以做更多的事情。像messages.search这样的方法对我来说非常有用。也许是动态生成高峰和低谷对话的统计数据,或者是持续活跃的对话,或者是找到你最喜欢的表情符号或最常见的 n 字母组合?天空是极限(或 API 速率极限,以较低者为准)。

更新

(2017–10–25 09:45 SGT)修改了消息计数以跳过意外对话框

  1. ^ 就我个人而言,我不能对 Telegram 的安全性发表评论,只能指出 Telegram 的对话在默认情况下不是端到端加密的,并提到 Telegram 的加密协议是自行开发的,与 Signal Protocol 等更成熟的协议相比,它受到的审查更少。

各种强化学习算法介绍。第一部分(Q-Learning,SARSA,DQN,DDPG)

原文:https://towardsdatascience.com/introduction-to-various-reinforcement-learning-algorithms-i-q-learning-sarsa-dqn-ddpg-72a5e0cb6287?source=collection_archive---------0-----------------------

强化学习(RL)是指一种机器学习方法,在这种方法中,智能体在下一个时间步接收延迟奖励,以评估其先前的行为。它主要用于游戏(如雅达利、马里奥),性能与人类相当甚至超过人类。最近,随着算法随着神经网络的结合而发展,它能够解决更复杂的任务,例如钟摆问题:

Deep Deterministic Policy Gradient (DDPG) Pendulum OpenAI Gym using Tensorflow

虽然有大量的 RL 算法,但似乎没有对它们中的每一个进行全面的比较。在决定将哪些算法应用于特定任务时,我很难抉择。本文旨在通过简要讨论 RL 设置来解决这个问题,并介绍一些著名的算法。

1.强化学习 101

通常,RL 设置由两个组件组成,代理和环境。

Reinforcement Learning Illustration (https://i.stack.imgur.com/eoeSq.png)

那么环境是指智能体所作用的对象(例如 Atari 游戏中的游戏本身),而智能体则代表 RL 算法。该环境首先向代理发送一个状态,然后代理根据它的知识采取行动来响应该状态。之后,环境发送一对下一个状态和奖励给代理。代理将使用环境返回的奖励更新其知识,以评估其最后的动作。循环继续,直到环境发送一个终端状态,结束于 epset。

大多数 RL 算法都遵循这种模式。在下面的段落中,我将简要地谈谈 RL 中使用的一些术语,以便于我们在下一节中进行讨论。

定义

  1. 动作(A):代理可以采取的所有可能的动作
  2. 状态:环境返回的当前情况。
  3. 奖励(R):从环境中发送回来的对上次行为进行评估的即时回报。
  4. 策略(π):代理用来根据当前状态确定下一步行动的策略。
  5. 价值(V):相对于短期回报 R. Vπ(s) 贴现的预期长期回报定义为当前状态下的预期长期回报。
  6. Q-value 或 action-value (Q): Q-value 类似于 value,除了它需要一个额外的参数,即当前动作 aQπ(s,a) 指长期返回当前状态 s ,在策略π下采取行动 a

无模型 vs .基于模型

该模型代表对环境动态的模拟。即,模型学习从当前状态 s 0 和动作 a 到下一状态 s 1 的转换概率 T(s1|(s0,a)) 。如果成功学习了转移概率,代理将知道在给定当前状态和动作的情况下进入特定状态的可能性有多大。然而,随着状态空间和动作空间的增长,基于模型的算法变得不切实际。

另一方面,无模型算法依靠试错法来更新其知识。因此,它不需要空间来存储所有状态和动作的组合。下一节讨论的所有算法都属于这一类。

保单与非保单

策略上的代理基于其从当前策略导出的当前动作 a 学习该值,而其策略外的对应部分基于从另一个策略获得的动作 a*学习该值。在 Q-learning 中,这样的策略就是贪婪策略。(我们将在 Q-learning 和 SARSA 中详细讨论这一点)

2.各种算法的说明

2.1 Q-学习

Q-Learning 是一种基于著名的贝尔曼方程的非策略、无模型 RL 算法:

Bellman Equation (https://zhuanlan.zhihu.com/p/21378532?refer=intelligentunit)

上式中的 e 指的是期望值,而ƛ指的是折现因子。我们可以把它改写成 Q 值的形式:

Bellman Equation In Q-value Form (https://zhuanlan.zhihu.com/p/21378532?refer=intelligentunit)

用 Q*表示的最佳 Q 值可以表示为:

Optimal Q-value (https://zhuanlan.zhihu.com/p/21378532?refer=intelligentunit)

目标是最大化 Q 值。在深入研究优化 Q 值的方法之前,我想先讨论两种与 Q 学习密切相关的值更新方法。

策略迭代

策略迭代在策略评估和策略改进之间循环。

Policy Iteration (http://blog.csdn.net/songrotek/article/details/51378582)

策略评估使用从上次策略改进中获得的贪婪策略来估计值函数 V。另一方面,策略改进用使每个状态的 V 最大化的动作来更新策略。更新方程基于贝尔曼方程。它不断迭代直到收敛。

Pseudo Code For Policy Iteration (http://blog.csdn.net/songrotek/article/details/51378582)

值迭代

值迭代只包含一个分量。它基于最佳贝尔曼方程更新值函数 V。

Optimal Bellman Equation (http://blog.csdn.net/songrotek/article/details/51378582)

Pseudo Code For Value Iteration (http://blog.csdn.net/songrotek/article/details/51378582)

在迭代收敛之后,通过对所有状态应用 argument-max 函数,直接导出最优策略。

注意,这两种方法需要转移概率 p 的知识,表明它是基于模型的算法。然而,正如我前面提到的,基于模型的算法存在可扩展性问题。那么 Q-learning 是如何解决这个问题的呢?

Q-Learning Update Equation (https://www.quora.com/What-is-the-difference-between-Q-learning-and-SARSA-learning)

α指的是学习率(即我们接近目标的速度)。Q-learning 背后的思想高度依赖于价值迭代。然而,更新等式被替换为上述公式。因此,我们不再需要担心转移概率。

Q-learning Pseudo Code (https://martin-thoma.com/images/2016/07/q-learning.png)

注意,选择下一个动作a’来最大化下一个状态的 Q 值,而不是遵循当前策略。因此,Q-learning 属于非政策范畴。

2.2 国家-行动-奖励-国家-行动

SARSA 非常类似于 Q-learning。SARSA 和 Q-learning 之间的关键区别在于,SARSA 是一种基于策略的算法。这意味着 SARSA 基于由当前策略而不是贪婪策略执行的动作来学习 Q 值。

SARSA Update Equation (https://www.quora.com/What-is-the-difference-between-Q-learning-and-SARSA-learning)

动作 a(t+1)是在当前策略下在下一个状态 s(t+1)中执行的动作。

SARSA Pseudo Code (https://martin-thoma.com/images/2016/07/sarsa-lambda.png)

从上面的伪代码中,您可能会注意到执行了两个操作选择,它们总是遵循当前策略。相比之下,Q-learning 对下一个动作没有约束,只要它最大化下一个状态的 Q 值。因此,SARSA 是一个基于策略的算法。

2.3 深 Q 网(DQN)

虽然 Q-learning 是一个非常强大的算法,但它的主要缺点是缺乏通用性。如果您将 Q-learning 视为更新二维数组(动作空间*状态空间)中的数字,实际上,它类似于动态编程。这表明对于 Q 学习代理以前没有见过的状态,它不知道采取哪种动作。换句话说,Q-learning agent 不具备估计未知状态值的能力。为了处理这个问题,DQN 通过引入神经网络摆脱了二维数组。

DQN 利用神经网络来估计 Q 值函数。网络的输入是电流,而输出是每个动作的相应 Q 值。

DQN Atari Example (https://zhuanlan.zhihu.com/p/25239682)

2013 年,DeepMind 将 DQN 应用于雅达利游戏,如上图所示。输入是当前游戏情况的原始图像。它经历了几层,包括卷积层以及全连接层。输出是代理可以采取的每个操作的 Q 值。

问题归结为:我们如何训练网络?

答案是我们根据 Q 学习更新方程来训练网络。回想一下,Q 学习的目标 Q 值是:

Target Q-value (https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf)

ϕ相当于状态 s,而𝜽代表神经网络中的参数,这不在我们讨论的范围内。因此,网络的损失函数被定义为目标 Q 值和从网络输出的 Q 值之间的平方误差。

DQN Pseudo Code (https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf)

另外两个技巧对训练 DQN 也很重要:

  1. 经验回放:由于典型 RL 设置中的训练样本高度相关,数据效率较低,这将导致网络更难收敛。解决样本分布问题的一种方法是采用经验回放。本质上,样本转换被存储,然后从“转换池”中随机选择以更新知识。
  2. 分离目标网络:目标 Q 网络与估值的结构相同。每 C 步,根据上面的伪代码,将目标网络重置为另一个。因此,波动变得不那么剧烈,导致更稳定的训练。

2.4 深度确定性政策梯度(DDPG)

虽然 DQN 在更高维度的问题上取得了巨大的成功,比如雅达利游戏,但是动作空间仍然是离散的。然而,许多感兴趣的任务,尤其是物理控制任务,动作空间是连续的。如果你把行动空间划分得太细,你最终会有一个太大的行动空间。例如,假设自由随机系统的程度是 10。对于每个度数,你把空间分成 4 个部分。你最终有 4 个⁰ =1048576 个动作。这么大的行动空间也极难收敛。

DDPG 依靠演员和评论家两个同名元素的演员-评论家架构。参与者用于调整策略功能的参数𝜽,即决定特定状态的最佳动作。

Policy Function (https://zhuanlan.zhihu.com/p/25239682)

一个批评家被用来评估由行动者根据时间差异(TD)误差估计的策略函数。

Temporal Difference Error (http://proceedings.mlr.press/v32/silver14.pdf)

这里,小写的 v 表示参与者已经决定的策略。看起来眼熟吗?是啊!它看起来就像 Q 学习更新方程!TD 学习是一种学习如何根据给定状态的未来值来预测值的方法。Q 学习是用于学习 Q 值的 TD 学习的特定类型。

Actor-critic Architecture (https://arxiv.org/pdf/1509.02971.pdf)

DDPG 还借鉴了 DQN 经验重演分众目标网的理念。DDPG 的另一个问题是它很少探索行动。对此的解决方案是在参数空间或动作空间上添加噪声。

Action Noise (left), Parameter Noise (right) (https://blog.openai.com/better-exploration-with-parameter-noise/)

OpenAI 写的这篇文章声称在参数空间上加比在动作空间上加好。一种常用的噪声是奥恩斯坦-乌伦贝克随机过程。

DDPG Pseudo Code (https://arxiv.org/pdf/1509.02971.pdf)

3.结论

我已经讨论了 Q-learning、SARSA、DQN 和 DDPG 的一些基本概念。在下一篇文章中,我将继续讨论其他最新的强化学习算法,包括 NAF、A3C 等。最后,我将简单地比较一下我所讨论的每一种算法。如果你对这篇文章有任何问题,请不要犹豫,在下面留下你的评论,或者在 twitter 上关注我。

各种强化学习算法介绍。第二部分(TRPO、PPO)

原文:https://towardsdatascience.com/introduction-to-various-reinforcement-learning-algorithms-part-ii-trpo-ppo-87f2c5919bb9?source=collection_archive---------3-----------------------

本系列的第一部分 介绍各种强化学习算法。第一部分(Q-Learning,SARSA,DQN,DDPG) I 讲述了强化学习(RL)的一些基本概念,并介绍了几种基本的 RL 算法。在本文中,我将继续讨论两种更高级的 RL 算法,这两种算法都是去年刚刚发表的。最后,我将对我所讨论的每种算法做一个简单的比较。

1.入门指南

定义:

  • 优势(A): A(s,a) = Q(s,a)- V(s)

优势是许多高级 RL 算法中常用的术语,如 A3C、NAF 和我将要讨论的算法(也许我会为这两种算法写另一篇博文)。为了以一种更直观的方式来看待它,可以把它想成一个动作与特定状态下的平均动作相比有多好。

但是我们为什么需要优势呢?Q 值不够好吗?

我将用这个论坛中发布的一个例子来说明优势的想法。

你玩过一个叫“接球”的游戏吗?在游戏中,水果会从屏幕上方落下。你需要向左或向右移动篮子来抓住它们。

Catch (https://datascience.stackexchange.com/questions/15423/understanding-advantage-functions)

上图是游戏的草图。上面的圆圈代表一种水果,而下面的小矩形是一个篮子。有三个动作,a1、a2 和 a3。显然,最好的动作是 a2,不要动,因为水果会直接掉进篮子里。现在,假设任何行为都没有负回报。在这种情况下,代理人没有选择最优行动的动机,即上面场景中的 a2。为什么?让我们用 Q*(s,a)来表示状态 s 和动作 a 的最佳 Q 值,那么我们将得到:

(https://datascience.stackexchange.com/questions/15423/understanding-advantage-functions)

假设贴现因子𝛾仅略小于 1。我们可以得到

(https://datascience.stackexchange.com/questions/15423/understanding-advantage-functions)

由于没有负回报,r(a3)和 r(a1)都大于或等于 0,暗示 Q(s,a3)和 Q(s,a2)差别不大。因此,在这种情况下,代理人对 a2 比对 a3 只有很小的偏好。

为了解决这个问题,我们可以将每个动作的 Q 值与它们的平均值进行比较,这样我们就可以知道一个动作相对于另一个动作有多好。回想一下上一篇博客,一个州的平均 Q 值被定义为 Value (V)。本质上,我们创造了一个名为 advantage 的新操作符,它是通过用该状态的值减去每个动作的 Q 值来定义的。

2.算法图解

2.1 信任区域策略优化(TRPO)

上一篇文章中讨论的深度确定性策略梯度(DDPG)是一个突破,它允许代理在连续空间中执行操作,同时保持下降性能。然而,DDPG 的主要问题是你需要选择一个合适的步长。如果太小,训练进度会极其缓慢。如果它太大,相反,它往往会被噪音淹没,导致悲剧性的表现。回想一下,计算时差(TD)误差的目标如下:

Target for TD error (https://arxiv.org/pdf/1509.02971.pdf)

如果步长选择不当,从网络或函数估计器中导出的目标值 yi 将不会很好,导致更差的样本和更差的价值函数估计。

因此,我们需要一种更新参数的方法来保证政策的改进。也就是说,我们希望预期贴现长期回报η 总是增加。

Expected Discounted Long-term Reward (https://arxiv.org/pdf/1509.02971.pdf)

警告:这部分会有无数的数学方程式和公式。如果您对此不满意,可以直接跳到这一部分的末尾。

与 DDPG 类似,TRPO 也属于政策梯度的范畴。它采用了actor-critical架构,但是修改了 actor 的策略参数的更新方式。

对于新政策π',η(π')可以看作是政策π'相对于旧政策π'的优势的期望收益。(由于我在键盘上找不到带曲线的π,我将在以下段落中使用π’)

η For New Policy π’ (https://arxiv.org/pdf/1509.02971.pdf)

你可能想知道为什么使用 advantage。直觉上,你可以把它看作是衡量新政策相对于旧政策的平均表现有多好。新政策的η可以改写为以下形式,其中 打折的就诊频率

η Rewrite & ⍴ (https://arxiv.org/pdf/1509.02971.pdf)

然而,由于⍴对新政策π'的高度依赖,上述公式很难进行优化。因此,本文介绍了η(π′),lπ(π′)的一种近似:

Approximation of η (https://arxiv.org/pdf/1509.02971.pdf)

请注意,我们将⍴π替换为⍴π',假设新旧政策的州访问频率没有太大差异。有了这个等式,我们可以结合众所周知的策略更新方法:

.

CPI (https://arxiv.org/pdf/1509.02971.pdf)

这里π_{old}是当前策略,而π'是使 L_{πold}最大化的策略的自变量 max。然后我们将得到下面的定理(让我们用定理 1 来表示它)。

Theorem 1 (https://arxiv.org/pdf/1509.02971.pdf)

c 表示惩罚系数,而 D^{max}_{KL}表示每个状态的两个参数的最大 KL 散度。KL 散度的概念源于信息论,描述了信息的损失。简单来说,你可以把它看成π和π'这两个参数有多大的不同。

上式暗示,只要右手边的项最大化,预期的长期回报η就单调提高。为什么?让我们把不等式的右边定义为 M_{i}。

(https://arxiv.org/pdf/1509.02971.pdf)

然后我们可以证明下面的不等式。

(https://arxiv.org/pdf/1509.02971.pdf)

第一行可以简单地把 M_{i}的定义代入定理 1 得到。第二条线成立,因为π_{i}和π_{i}之间的 KL 散度为 0。将第一条线和第二条线结合起来,我们将得到第三条线。这表明,只要 M_{i}在每次迭代中最大化,目标函数η总是在改进的。(我认为第三行末尾的最后一个词应该是 Mi 而不是 m。不确定这是否是论文的打印错误)。因此,我们现在试图解决的复杂问题归结为最大化 Mi。即,

Objective Function 1 (https://arxiv.org/pdf/1509.02971.pdf)

下图直观地说明了η与 L 的近似值:

Visual Illustration of The Approximation (https://www.youtube.com/watch?v=xvRrgxcpaHY&t=363s)

在实践中,如果目标函数中包含惩罚系数,步长会很小,导致训练时间很长。因此,对 KL 散度的约束用于允许更大的步长,同时保证稳健的性能。

Objective Function 2 (https://arxiv.org/pdf/1509.02971.pdf)

KL 散度约束施加在状态空间中的每个状态上,其最大值应该小于一个小数值𝜹.不幸的是,它是不可解的,因为有无限多的状态。该论文提出了一种解决方案,该解决方案提供了一种启发式近似,该近似具有状态上的预期 KL 散度,而不是找到最大 KL 散度。

KL Divergence With State Visitation Frequency ⍴ (https://arxiv.org/pdf/1509.02971.pdf)

现在,当我们展开第一行时,目标函数变成如下:

Objective Function 3 (https://arxiv.org/pdf/1509.02971.pdf)

通过用期望代替状态上的σ,用重要抽样估计量代替动作上的σ,如果采用单路径方法,这等同于旧的策略,我们可以将上述重写为:

Final Objective Function (https://arxiv.org/pdf/1509.02971.pdf)

目标函数也称为“替代”目标函数,因为它包含当前策略和下一个策略之间的概率比。TPRO 成功地解决了 DDPG 提出的性能不能单调提高的问题。位于约束内的区域子集称为信赖域。只要政策变化相当小,这个近似值与真实的目标函数就不会有太大的不同。通过选择满足 KL 散度约束的最大化期望的新政策参数,保证了期望长期回报η的下界。这也暗示你不需要太担心 TRPO 的步长。

2.2 近似策略优化(PPO,OpenAI 版本)

虽然 TRPO 已经取得了巨大且持续的高性能,但是它的计算和实现是极其复杂的。在 TRPO 中,对代理目标函数的约束是新旧策略之间的 KL 差异。

Fisher 信息矩阵是 KL 散度的二阶导数,用于近似 KL 项。这导致计算几个二阶矩阵,这需要大量的计算。在 TRPO 论文中,共轭梯度(CG)算法被用于解决约束优化问题,从而不需要显式计算 Fisher 信息矩阵。然而,CG 使得实现更加复杂。

PPO 消除了由约束优化产生的计算,因为它提出了一个剪裁的代理目标函数。

让 rt(𝜽)表示新旧政策之间的比率。用于近似 TRPO 的长期回报η的替代目标函数变成如下。注下标描述了 TRPO 所基于的保守策略迭代(CPI)方法。

TRPO Objective Function (https://arxiv.org/pdf/1707.06347.pdf)

TRPO 的约束思想是不允许政策改变太多。因此,PPO 没有添加约束,而是稍微修改了 TRPO 的目标函数,并对过大的策略更新进行了惩罚。

Clipped Objective Function (https://arxiv.org/pdf/1707.06347.pdf)

在右边你可以看到概率比 rt(𝜽)被限制在[1- 𝜖,1+𝜖].这表明,如果 rt(𝜽)导致目标函数增加到一定程度,其有效性将下降(被修剪)。让我们讨论两种不同的情况:

  • 情况 1:当优势ȃt 大于 0 时

如果ȃt 大于 0,则意味着该动作优于该状态下所有动作的平均值。因此,应通过增加 rt(𝜽来鼓励该行动,以便该行动有更高的机会被采纳。由于分母 rt(𝜽)不变,旧政策增加 rt(𝜽)也意味着新政策增加π𝜽(a(s)。也就是说,增加在给定状态下采取行动的机会。然而,由于修剪,rt(𝜽)只会增长到和 1+𝜖.一样多

  • 情况 2:当优势ȃt 小于 0 时

相比之下,如果ȃt 小于 0,那么这个动作应该被阻止。因此,rt(𝜽)应该减少。同样,由于修剪,rt(𝜽)只会减少到和 1-𝜖.一样少

Illustration of The Clip (https://arxiv.org/pdf/1707.06347.pdf)

本质上,它限制了新政策与旧政策的差异范围;因此,消除了概率比 rt(𝜽移出区间的动机。

在实践中,损失函数误差和熵加成也应在实施过程中加以考虑,如下所示。然而,我不打算详细介绍它们,因为最具创新性和最重要的部分仍然是裁剪后的目标函数。

PPO Objective Function (https://arxiv.org/pdf/1707.06347.pdf)

比较 L^{CPI}和 L^{CLIP}的目标函数,我们可以看到 L^{CLIP}实际上是前者的一个下界。它还消除了 KL 发散约束。因此,优化该 PPO 目标函数的计算量比 TRPO 少得多。经验上也证明了 PPO 的表现优于 TRPO。事实上,由于其轻便和易于实现,PPO 已经成为 open ai(https://blog.openai.com/openai-baselines-ppo/)的默认 RL 算法。

3.所讨论算法的比较

Various RL Algorithms I Have Discussed

所有讨论的 RL 算法都是无模型的。也就是说,他们都没有试图去估计目标函数。相反,他们基于反复试验来更新他们的知识。在所有这些公司中,只有 SARSA 是在政策上,根据其当前的行动学习价值。从离散的观察空间到连续的观察空间,DQN 是一个巨大的进步,允许代理处理看不见的状态。DDPG 是另一个突破,它使智能体能够执行具有策略梯度的连续动作,将 RL 的应用扩展到更多的任务,如控制。TRPO 改进了 DDPG 的性能,因为它引入了代理目标函数和 KL 散度约束,保证了长期回报不减少。PPO 通过修改代理目标函数进一步优化 TRPO,提高了性能,降低了实现和计算的复杂度。

结论

总之,我介绍了两种更高级的 RL 算法,并对我讨论过的所有 RL 算法进行了比较。然而,在 TRPO 中,数学公式非常复杂。虽然我已经尽力解释了,但我相信对你们中的一些人来说,这可能仍然是令人困惑的。如果您有任何问题,请随时在下面发表评论,或者在推特上关注我。

单词嵌入和 Word2Vec 简介

原文:https://towardsdatascience.com/introduction-to-word-embedding-and-word2vec-652d0c2060fa?source=collection_archive---------0-----------------------

单词嵌入是最流行的文档词汇表示之一。它能够捕捉文档中单词的上下文、语义和句法相似性、与其他单词的关系等。

到底什么是单词嵌入?不严格地说,它们是特定单词的矢量表示。说到这里,接下来是我们如何生成它们?更重要的是,他们如何捕捉上下文?

Word2Vec 是使用浅层神经网络学习单词嵌入的最流行的技术之一。它是由谷歌的托马斯·米科洛夫于 2013 年开发的。

让我们一部分一部分地解决这个问题。

我们为什么需要它们?

考虑下面类似的句子:过得愉快过得愉快。它们几乎没有什么不同的意思。如果我们构造一个穷举词汇表(姑且称之为 V),那就有 V = {Have,a,good,great,day}。

现在,让我们为 V 中的每个单词创建一个独热码编码向量。我们的独热码编码向量的长度将等于 V (=5)的大小。除了索引处代表词汇表中相应单词的元素之外,我们将有一个零向量。这个特殊的元素就是。下面的编码可以更好地解释这一点。

Have = [1,0,0,0,0];a=[0,1,0,0,0];good=[0,0,1,0,0];great=[0,0,0,1,0];day=[0,0,0,0,1](代表转置)

如果我们试图将这些编码可视化,我们可以想象一个 5 维空间,其中每个单词占据一个维度,与其余维度无关(没有沿其他维度的投影)。这意味着“好”和“伟大”就像“天”和“有”一样不同,这是不正确的。

我们的目标是让具有相似上下文的单词占据相近的空间位置。从数学上来说,这些向量之间的角度余弦应该接近 1,即角度接近 0。

Google Images

产生分布式表示的想法来了。直观地说,我们引入了一个单词对另一个单词的一些依赖性。该单词的上下文中的单词将获得这种依赖性的更大份额。在一个热编码表示中,所有的字都是彼此独立的**,如前所述。

word 2 vec 是如何工作的?

Word2Vec 是一种构建这种嵌入的方法。它可以使用两种方法获得(都涉及神经网络):Skip Gram 和 Common Bag Of Words (CBOW)

CBOW 模型: 该方法以每个单词的上下文为输入,尝试预测上下文对应的单词。考虑我们的例子:祝你有美好的一天。**

让神经网络的输入是单词,棒极了。注意,这里我们试图使用单个上下文输入单词来预测一个目标单词( d ay )更具体地说,我们使用输入单词的一个热编码,并测量与目标单词的一个热编码相比的输出误差( d ay)。在预测目标词的过程中,我们学习目标词的向量表示。

让我们更深入地看看实际的架构。

CBOW Model

输入或上下文单词是大小为 V 的一个热编码向量。隐藏层包含 N 个神经元,输出也是长度为 V 的向量,其元素是 softmax 值。

让我们把图中的术语对了:
- Wvn 是将输入 x 映射到隐藏层的权重矩阵(VN 维矩阵)
- W`nv 是将隐藏层输出映射到最终输出层的权重矩阵(NV 维矩阵)**

我不会涉足数学。我们就能知道发生了什么。

隐藏层神经元只是将输入的加权和复制到下一层。没有类似乙状结肠、tanh 或 ReLU 的激活。唯一的非线性是输出层中的 softmax 计算。

但是,上述模型使用单个上下文单词来预测目标。我们可以使用多个上下文单词来做同样的事情。

Google images

以上模型取 C 上下文单词。当 Wvn 用于计算隐藏层输入时,我们取所有这些 C 上下文单词输入的平均值。

因此,我们已经看到了单词表示是如何使用上下文单词生成的。但是我们还有一种方法可以做到。我们可以使用目标单词(我们想要生成它的表示)来预测上下文,在这个过程中,我们产生表示。另一个变体,称为跳过克模型做这个。

跳格模型:

这看起来像是多上下文 CBOW 模型被翻转了。在某种程度上,这是真的。

我们把目标词输入网络。模型输出 C 个概率分布。这是什么意思?

对于每个上下文位置,我们得到 V 个概率的 C 个概率分布,每个单词一个。

在这两种情况下,网络都使用反向传播来学习。详细的数学可以在这里找到

谁赢了?

两者各有利弊。根据 Mikolov 的说法,Skip Gram 可以很好地处理少量数据,并被发现可以很好地表示罕见的单词。

另一方面,CBOW 更快,对更频繁的单词有更好的表示。

前方有什么?

上面的解释是一个非常基本的解释。它只是让您对什么是单词嵌入以及 Word2Vec 如何工作有一个高层次的概念。

还有很多事情要做。例如,为了提高算法的计算效率,使用了分层 Softmax 和 Skip-Gram 负采样等技巧。所有这些都可以在这里找到。

感谢阅读!我已经开始了我的个人博客,我不打算在媒体上写更多令人惊叹的文章。订阅的帮助空间,支持我的博客

单词嵌入简介

原文:https://towardsdatascience.com/introduction-to-word-embeddings-4cf857b12edc?source=collection_archive---------3-----------------------

什么是单词嵌入?

单词嵌入的一个非常基本的定义是一个单词的实数向量表示。通常,如今,具有相似意思的单词在嵌入空间中会有接近的向量表示(尽管情况并不总是如此)。

当构建单词嵌入空间时,通常目标是捕获该空间中的某种关系,无论是意义、形态、上下文还是某种其他类型的关系。

通过对密集空间中的单词嵌入进行编码,我们可以用一种方式用数字表示单词,这种方式可以在几十或几百维而不是几百万维的向量中捕获它们(就像一次性编码向量)。

许多单词嵌入都是基于 Zellig Harris 的“分布假设”所引入的概念而产生的,这可以归结为一个简单的想法,即彼此靠近使用的单词通常具有相同的含义。

美妙之处在于,不同的单词嵌入是以不同的方式或使用不同的文本语料库来创建的,以映射这种分布关系,因此最终结果是帮助我们完成 NLP 世界中不同下游任务的单词嵌入。

为什么我们使用单词嵌入?

单词不是计算机自然理解的东西。通过将它们编码成数字形式,我们可以应用数学规则并对它们进行矩阵运算。这使得他们在机器学习领域特别令人惊叹。

以深度学习为例。通过以数字形式编码单词,我们可以采用许多深度学习架构,并将它们应用于单词。卷积神经网络已经应用于使用单词嵌入的 NLP 任务,并且已经为许多任务设置了最先进的性能。

更好的是,我们发现我们实际上可以预先训练适用于许多任务的单词嵌入。这是我们将在本文中讨论的许多类型的焦点。因此,人们不必为每个任务、每个语料库学习一组新的嵌入。相反,我们可以学习通用的表示法,然后在不同的任务中使用。

单词嵌入的具体例子

现在,简单的介绍结束了,让我们来简单地看看我们可以用数字表示单词的一些不同的方法(稍后,我将对每种方法进行更复杂的分析,以及如何在下游任务中实际使用它们)。

一键编码(计数矢量化)

我们可以用数字表示单词的最基本的方法之一是通过一键编码方法(有时也称为计数矢量化)。

想法超级简单。创建一个向量,其维数与你的语料库中唯一的单词数一样多。每个唯一的单词都有一个唯一的维度,在该维度上用 1 表示,在其他维度上用 0 表示。

这样的结果?非常巨大和稀疏的向量,完全没有关系信息。如果你没有其他选择,这可能是有用的。但是如果我们需要语义关系信息,我们还有其他选择。

我现在也有一个关于如何在真实文本数据上使用计数矢量化的帖子!如果你感兴趣,可以在这里查看:自然语言处理:用 scikit-learn 计算矢量化

TF-IDF 变换

TF-IDF 矢量与独热码编码矢量相关。然而,它们不仅仅以计数为特征,而是以数字表示为特征,其中单词不仅仅在那里或者不在那里。相反,单词由它们的术语频率乘以它们的逆文档频率来表示。

简单来说,经常出现但随处可见的单词应该被赋予很小的权重或重要性。我们可以认为这是英语中类似于theand的单词。他们没有提供大量的价值。

然而,如果一个单词出现得很少或很频繁,但只出现在一两个地方,那么这些可能是更重要的单词,应该这样加权。

同样,这也有非常高维度表示的缺点,不能捕捉语义相关性。

共生矩阵

同现矩阵就像它听起来的那样:一个和词汇量一样长和一样宽的巨大矩阵。如果单词一起出现,它们被标记为阳性条目。否则,他们有一个 0。它归结为一个数字表示,simple 提出了“单词是一起出现的吗?如果有,那就数这个。”

我们已经看到什么正在成为一个大问题?超大表示!如果我们认为独热编码是高维的,那么同现是高维的平方。内存中要存储大量数据。

神经概率模型

现在,我们可以开始进入一些神经网络。神经概率模型通过完成一些任务(如建模或分类)来学习嵌入,并且是这些嵌入的其余部分或多或少所基于的。

通常,你清理你的文本,并创建一个热点编码向量。然后,您定义您的表示大小(300 维可能是好的)。从那里,我们初始化嵌入到随机值。这是进入网络的入口点,反向传播用于根据我们的目标任务修改嵌入。

这通常需要大量数据,并且可能非常慢。这里的权衡是,它学习一种嵌入,这种嵌入对于网络被训练的文本数据以及在训练期间共同学习的 NLP 任务是有益的。

word2vec

Word2Vec 是神经概率模型更好的继承者。我们仍然使用统计计算方法从文本语料库中学习,然而,其训练方法比简单的嵌入训练更有效。这或多或少是现今训练嵌入的标准方法。

这也是第一个演示经典矢量算法来创建类比的方法:

有两种主要的学习方法。

连续词袋

该方法通过基于上下文预测当前单词来学习嵌入。上下文由周围的单词决定。

连续跳跃图

这种方法通过预测给定上下文的周围单词来学习嵌入。上下文是当前单词。

这两种学习方法都使用本地单词使用上下文(具有相邻单词的定义窗口)。窗口越大,通过嵌入学习到的主题相似性就越多。强迫一个更小的窗口导致更多的语义、句法和功能相似性被学习。

那么,有什么好处呢?嗯,高质量的嵌入可以非常有效地学习,特别是在与神经概率模型进行比较时。这意味着低空间和低时间复杂度来生成丰富的表示。更重要的是,维度越大,在我们的表现中就有越多的特征。但是,我们仍然可以保持比其他方法低得多的维数。它还允许我们有效地生成十亿个单词的语料库,但包含一堆概括性的内容,并保持较小的维度。

手套

GloVe 是 word2vec 的扩展,而且是一个更好的扩展。有一组用于自然语言处理的经典向量模型擅长捕捉语料库的全局统计数据,如 LSA(矩阵分解)。他们非常擅长全球信息,但他们不能很好地捕捉含义,而且肯定没有内置的很酷的类比功能。

GloVe 的贡献是在语言建模任务中添加了全局统计来生成嵌入。本地上下文没有窗口功能。相反,有一个词-上下文/词共现矩阵,它学习整个语料库的统计数据。

结果呢?比简单的 word2vec 学习更好的嵌入。

快速文本

现在,有了 FastText ,我们进入了一个非常酷的新单词嵌入的世界。FastText 所做的是决定合并子词信息。它通过将所有单词拆分成一个 n 元字符包(通常大小为 3-6)来实现这一点。它会将这些子单词加在一起,以创建一个完整的单词作为最终特征。这个功能真正强大的地方是它允许 FastText 自然地支持词汇表之外的单词!

这很重要,因为在其他方法中,如果系统遇到一个它不认识的单词,它只需将它设置为未知单词。使用 FastText,如果我们只知道单词 navigate,我们就可以给单词 circuit navigate 赋予意义,因为我们对单词 navigate 的语义知识至少可以帮助我们提供更多的语义信息来 circuit navigate,即使它不是我们的系统在训练期间学习的单词。

除此之外,FastText 使用负采样的 skip-gram 目标。所有的子词都是正例,然后从语料库中的词典中随机抽取样本作为负例。这些是 FastText 培训中包含的主要内容。

另一件很酷的事情是,脸书在开发 FastText 的过程中,用 294 种不同的语言发布了预先训练好的 FastText 向量。在我看来,这是一件非常棒的事情,因为它允许开发人员以非常低的成本使用通常没有预先训练的单词向量的语言来制作项目(因为训练他们自己的单词嵌入需要大量的计算资源)。

如果你想看所有 FastText 支持的语言,点击这里查看。

庞加莱嵌入(分层表示)

庞加莱嵌入非常不同,非常有趣,如果你有雄心壮志,你绝对应该给看看论文。他们决定使用双曲几何来捕捉单词的等级属性。通过将它们嵌入到双曲空间中,它们可以使用双曲空间的性质来使用距离来编码相似性,并且使用向量的范数来编码等级关系。

最终结果是需要更少的维度来编码层级信息,他们通过用非常低的维度重新创建 WordNet 来证明这一点,尤其是与其他单词嵌入方案相比。他们强调了这种方法对于像 WordNet 或像计算机网络这样等级森严的数据是非常有用的。看看这一潮流会产生什么样的研究(如果有的话)将会很有趣。

工程与后勤管理局

ELMo 是我个人的最爱。它们是最先进的上下文单词向量。这些表示是从整个句子的函数中生成的,以创建单词级表示。嵌入是在字符级生成的,因此它们可以利用像 FastText 这样的子词单元,并且不会受到词汇表之外的词的影响。

ELMo 被训练成一个双向、两层的 LSTM 语言模型。一个非常有趣的副作用是,它的最终输出实际上是其内层输出的组合。已经发现的是,最低层适合于像词性标注和其他更多语法和功能任务这样的事情,而较高层适合于像词义消歧和其他更高级、更抽象的任务这样的事情。当我们组合这些层时,我们发现我们实际上在开箱即用的下游任务上获得了令人难以置信的高性能。

我脑子里唯一的问题?我们如何减少维数,并扩展到不太流行的语言上的训练,就像我们对 FastText 的训练一样。

概率快速文本

概率快速文本是最近的一篇论文,它试图更好地处理意思不同但拼写相同的单词的问题。以单词 rock 为例。它可能意味着:

  • 摇滚乐
  • 一块石头
  • 来回移动的动作

我们遇到这个词怎么知道自己在说什么?通常情况下,我们不会。当学习一个嵌入时,我们只是把所有的意思混在一起,然后抱最好的希望。这就是为什么像 ELMo 这样使用整个句子作为上下文的东西,在需要区分不同意思时往往表现得更好。

这也是概率快速文本做得很好的地方。不是将单词表示为向量,而是将单词表示为高斯混合模型。现在,我仍然没有真正理解数学,但许多训练模式仍然类似于 FastText,只是我们不是学习向量,而是学习一些概率性的东西。

我非常好奇这种趋势是否会产生未来的研究,因为我认为远离载体是一种非常好奇的方式。

包扎

如果你喜欢读这篇文章,给我留言或者给我的 GoFundMe 捐款来帮助我继续我的 ML 研究!

敬请关注即将推出的更多单词嵌入内容!

最初发表于T5【hunterheidenreich.com】

人工智能入门指南

原文:https://towardsdatascience.com/introductory-guide-to-artificial-intelligence-11fc04cea042?source=collection_archive---------2-----------------------

本指南的主要目标是为想学习人工智能的人提供关于理论、技术和应用的直觉。它包括简短的描述和解释性文章和讲座的链接。每一部分都包含基本的材料来了解它是如何工作的。在最后一部分,你可以找到额外的书籍,课程,播客和其他材料。你也可以去游乐场玩互动游戏。让我们开始吧!

内容:

  1. 起源
  2. 先决数学
  3. 没有免费的午餐定理
  4. 方法和算法
  5. 发展
  6. 现实世界的应用
  7. 额外资源

起源

人工智能诞生于模仿人类智能的尝试中。看看它的简史。目前还不清楚是否有可能模仿人类的思维,但我们肯定可以再造它的一些功能。与此同时,认知科学的整个领域受到了广泛的关注。

与此同时,它在社会上引起了很多关注。机器接管世界的问题有些言过其实,但工作岗位的转移现在是一个真正的问题。看一看人工智能与自然智能来更好地了解计算机在哪些方面优于我们。

从某种意义上说,所有的计算机甚至计算器都代表了一种 AI。正如该领域的创始人之一所说:

“它一工作,就没人再管它叫 AI 了。” 约翰·麦卡锡

随着计算机变得越来越快,方法越来越先进,人工智能将变得越来越聪明。最近的研究表明,在未来 5-10 年内,多达 50%的工作岗位受到威胁。不管我们能否完全模拟我们的思维,人工智能都将对我们的生活产生重大影响。

先决数学

事实上,数学不是严格要求的,但是你需要它来更深入地理解这些方法。我建议在深入之前,至少在每个小节中获得基本的直觉。我假设你已经熟悉了学校代数。如果没有,你可以看看这本指南或者在 openstax 上找到免费的高质量教材。

首先值得注意的是,我们都熟悉的古典逻辑不能代表大多数现代技术。由此,你应该理解模糊逻辑的思想。

第二个重要的话题是图表。这个温和的介绍会帮助你理解主要思想。

线性代数

线性代数将概念和运算从普通代数扩展到数的集合。它们通常代表输入、输出和操作参数。我推荐从这本指南开始。

接下来是张量。张量是标量、向量和矩阵对高维对象的概括。这个视频会给你直观的解释这个概念。

可能性

由于我们通常没有关于任何事情的准确信息,我们不得不处理概率。这篇文章解释了非常基础的东西,而这个系列会让你对概率、统计和贝叶斯逻辑有更完整的理解。我建议至少看完这个系列的前三部分。

目标函数

也称为目标函数、成本函数或损失函数。它们代表了我们方法的主要目的。通常目标函数衡量我们的算法完成工作的好坏。此外,通过优化这个函数,我们可以改进我们的算法。

最重要的是均方误差和交叉熵。你可以在这篇文章中找到关于 MSE 和平均绝对误差的描述,在这篇文章中找到关于交叉熵和 Kullback-Leibler 散度的描述。

有时我们不能直接计算目标函数,需要评估算法的性能。但是这些评估服务于相同的目标。

最佳化

在我们建立了目标函数之后,我们需要优化它的参数来提高我们算法的性能。优化的常用方法是梯度下降。你可以在这里找到直觉,在这里找到更详细的描述。

GD 有很多种。其中之一是随机梯度下降,它只需要训练数据的子集来计算每次迭代的损失和梯度。另一类重要的 GD 算法包括动量,它迫使参数在一个共同的方向上移动。

没有免费的午餐定理

我专门用了一个独特的章节来讲述它,因为这个定理传达了一个非常重要的思想:没有普遍有效的人工智能方法。简而言之,这个定理表明,每个问题解决过程对于每个任务都有一些计算成本,并且这些过程中没有一个比其他过程平均更好。虽然这个定理还没有在最一般的情况下得到证明,但实践已经表明了它的重要性。

Some methods may look particularly wonderful, but you still can’t eat them 😃

所以,我们必须为每个问题选择合适的方法。

常用方法和算法

每种方法的主要目的是为特定问题构建一个良好的输入到输出映射模型。此外,它们的组合导致甚至更好的解决方案。并行搜索、堆叠和提升等技术有助于利用简单模型的混合来构建更好的模型。

虽然搜索方法通常只需要问题规范,但大多数深度学习算法需要大量数据。因此,可用数据在方法选择中起着重要作用。

我将按照发展的大致历史顺序来描述主要的技术类别。

经典编程

虽然编程不再被认为是人工智能技术,但这是很多年前的事了。一个单独的程序可以执行简单的输入加法,这看起来不像是一个智力活动。然而,它可能控制机器人的运动并执行复杂的操作。

You heard me right. Even HTML pages are a kind of AI.

这种方法的可解释的和严格的规范允许在一个结构中组合数百甚至数千个不同的程序。然而,这种方法在大多数复杂的现实场景中都失败了。预测复杂系统中所有可能的输入输出组合是极其困难的。

基于规则的专家系统

典型的专家系统由一组 if-then 规则的知识库和一个推理机制组成。这个教程会给你大概的思路。现代知识图一般用于问答和自然语言处理。在这里你可以得到它们的直观解释。虽然这些方法今天仍在使用,但专家系统的受欢迎程度正在稳步下降。

搜索

如果你能定义可能的解决方案,搜索将帮助你找到一个好的。这个演示介绍将会给你常见搜索算法背后的直觉,以及它们是如何应用在游戏开发中的。另外,本教程会提供更正式的描述。尽管表面上很简单,但如果使用得当,这些方法可以在许多领域取得优异的效果。

遗传算法

遗传或进化算法是一种受生物进化启发的搜索。这篇文章将帮助你理解这个想法。

机器学习

一般来说,ML 方法也使用一种搜索,通常是梯度下降,来寻找解决方案。换句话说,他们使用训练示例来学习/拟合参数。实际上有几十种 ML 算法,但大多数都依赖于相同的原理。

回归、支持向量机、朴素贝叶斯和决策树是最受欢迎和使用最广泛的。

剩下的小节将描述机器学习最突出的领域。

概率图形模型

这些模型以图表的形式学习变量之间的统计相关性。这篇文章将提供 PGMs 的一般概念。如今,它们在现实世界的应用中被神经网络积极地取代,但对于复杂系统的分析仍然有用。

深度学习

简而言之,深度学习是 ML 方法的子集,包括许多层的表示。本帖提供总体概述。NN 最漂亮的特性之一就是你可以任意组合堆叠不同的层。组成层的高级描述通常称为网络架构。

神经网络的基本类型:

  • 前馈
  • 经常性
  • 卷积(以及不同类型的卷积

在更专门化的模块中,神经注意力机制在许多应用中显示出巨大的成果。其他即插即用模块,如长短期存储器或这种用于关系推理的模块在架构设计中提供了很大的灵活性。通过这种方式,你可以很容易地用注意力和其他东西创建循环卷积网络。

受限波尔兹曼机器是无监督学习网络的一个流行例子。

一些技术旨在改善神经网络和其他 ML 模型的泛化,这反过来积极地影响准确性。其中最受欢迎的是辍学和批量正常化。

另一类成功的网络是自动编码器。他们最著名的应用——word 2 vec。此外,它们还用于创建文档、知识图实体、图像、基因和许多其他事物的表示。

另一个有趣的例子是生成对抗网络,它可以学习生成令人信服的图像、视频和任何其他类型的数据。

许多其他类型的神经网络在文献中很受欢迎,但实际应用相对较少:自组织映射、波尔兹曼机器、脉冲神经网络、自适应共振网络等。

强化学习

RL 背后的直觉受到行为心理学家的启发,他们观察到动物从奖励中学习如何行为。这导致了寻找能带来最大回报的政策的方法的发展。本帖包含强化学习的概述。

在历史的进程中发展了许多 RL 方法。最先进的技术包括进化策略、深度强化学习、异步优势行动者-批评家(A3C) 等等。

发展

由于大多数现代系统或多或少使用相同的硬件(GPU 和 TPU),在这一节中,我将重点介绍软件开发。

基础

对于初学者来说,Python 可能是最好的编程语言。对于当前的人工智能方法来说,它是相当通用的,并且与第一种成功的人工智能语言 Lisp 有许多相似之处。Python 有直观的语法和一个巨大的社区,其中有大量的包、教程和培训材料。

我推荐从多伦多大学的这些课程开始:第一部分和第二部分。它们涵盖的主题从编程的基础到 Python 的最佳实践。

数据科学

因为人工智能方法高度依赖数据,所以你需要能够分析和操纵数据。

这个用 Python 和 Pandas 系列的数据分析将帮助你更深入地理解数据集,而这个面向编码人员的数值线性代数课程将帮助你掌握重要的运算。

这些备忘单包含了流行 Python 库的常用函数的描述。编码的时候有那些很方便。

机器学习

我强烈推荐从吴恩达的机器学习课程开始。它涵盖了所有必要的数学和基本方法:线性和逻辑回归,支持向量机,主成分分析,简单的神经网络和其他。本课程中唯一缺少的重要内容是决策树。这个决策树教程和更高级的渐变提升树教程将填补这个空白。

现在你可以更深入了。这个程序员实用深度学习课程教授如何使用最先进的 DL 技术。此外,这个来自伯克利的深度强化学习课程将向你介绍现代 RL 方法。

也有自动设计机器学习模型的方法。但是要得到好的结果,AutoML 需要比手工构建的模型多得多的资源,所以它还没有普及。此外,在进行人工智能项目时,你应该考虑可能的安全问题。

浏览课程和教程是很棒的,但是要真正理解整个过程,你应该获取一些真实世界的数据并使用它。这些资源将帮助您开始:

开源项目

一些有趣的简单例子可供学习:

  1. 数据科学 IPython 笔记本 —大量收集 DS、ML、DL 和其他示例
  2. TensforFlow 示例 —针对初学者的带示例的 TF 教程
  3. Kaggle 内核 —数千台用于 Kaggle 比赛的开放式笔记本

数据集

您可以使用这些开放数据集来训练您使用不同类型数据的技能:

  1. Kaggle 数据集 — 700 多个开放数据集
  2. 超赞的公共数据集 — 400 多个开放数据集
  3. DeepMind 开放数据集—deep mind 研究中使用的独特数据集

现实世界的应用

本节主要是为开发人员提供启发性的演示。你可以看看人工智能系统现在是如何改变世界的,以及在不久的将来哪些方向将特别相关:医学,军事,教育,科学,物理学,经济学以及许多其他领域。

额外资源

除非另有说明,下面列出的一切都是免费的。此外,大多数课程为学生和工人提供付费证书,通常费用约为 50-100 美元。

谷歌永远是你最好的助手。此外, Quora 是一个寻找答案的好地方。例如,这里的人们已经为 AI 的研究提出了很多材料。

书单

  1. 人工智能:现代方法作者斯图尔特·拉塞尔和彼得·诺维格(不免费!)—领先的人工智能教材
  2. 大卫·l·普尔和艾伦·k·马克沃斯的《人工智能:计算代理的基础》
  3. 深度学习书籍(pdf、mobi 和 epub )作者:伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔——最佳 DL 教材
  4. 安德森·霍洛维茨的《人工智能行动手册》——以实践为导向的人工智能书籍
  5. 神经网络和深度学习迈克尔·尼尔森著——专注于神经网络的书
  6. 吴恩达的《机器学习向往》——一本关于如何构建一个生产就绪的 ML 项目的书
  7. 马文·明斯基的情感机器(不免费!)—伟大的 AI & CogSci 书籍,由 AI 领域的一位父亲撰写,侧重于理论

你还可以在这个资源库中找到更多关于机器学习的电子书。

在线课程

作为人工智能的第一门课程,我会推荐吴恩达的机器学习和安萨夫·萨莱博-奥乌伊西的人工智能。

  1. 彼得·诺维格和巴斯蒂安·特龙的《人工智能导论》
  2. 机器学习简介作者凯蒂·马龙和巴斯蒂安·特龙 Python 中的 ML 算法简介
  3. 深度学习作者吴恩达——神经网络及其在实际项目中应用的 5 门专业课程
  4. Vincent Vanhoucke 和 Arpan Chakraborty 的《深度学习》Python 中的 DL 算法简介
  5. 用于机器学习的神经网络作者 Geoffrey hint on——关于神经网络的综合性理论导向课程
  6. 杰瑞米·霍华德程序员实用深度学习—面向实践的 DL 课程
  7. 杰瑞米·霍华德《程序员的前沿深度学习》—本课程的第二部分,介绍数字图书馆的最新发展
  8. 用于视觉识别的卷积神经网络Andrej kar pathy——斯坦福关于卷积网络的讲座(2017 年春季)
  9. 深度自然语言处理,牛津 2017 —自然语言处理深度学习综合课程
  10. 深度学习暑期学校,蒙特利尔( 2016 , 2017 ) —许多深度学习主题的讲座
  11. Parag Mital 的深度学习与 TensorFlow 的创造性应用——DL 在艺术中的应用课程
  12. 自动驾驶汽车的深度学习,麻省理工学院 2017-自动驾驶汽车深度学习实践的入门课程

博客

  1. 开放 AI 博客 —关注 AI 安全问题
  2. DeepMind 博客——“解决智能。用它让世界变得更美好。”是 DeepMind 的座右铭
  3. 谷歌研究博客——谷歌研究的最新消息
  4. 脸书研究博客——脸书研究的最新消息
  5. 微软下一篇博客 —微软技术和研究的最新消息
  6. BAIR 博客 —伯克利人工智能研究平台
  7. 直觉机器 —深度学习模式、方法论和策略
  8. LAB41 博客 —数据分析研究的发现、实验结果和思考
  9. 提炼 —最清晰的机器学习研究期刊

频道和播客

  1. send ex—各种 Python 教程
  2. 深度学习。电视 —简化的深度学习
  3. Siraj Raval——寓教于乐
  4. 两分钟论文——最新研究的简要概述
  5. 人工智能播客——英伟达关于不同主题的播客
  6. 本周在机器学习& AI —每周有趣访谈