TowardsDataScience 博客中文翻译 2019(三十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

现代世界的金融

原文:https://towardsdatascience.com/a-sign-of-the-times-finance-in-the-modern-world-9a98a3366cca?source=collection_archive---------30-----------------------

“别哭了,这是时代的标志……”一点不错,哈里·斯泰尔斯,一点不错。

金融——认识你的小兄弟,金融科技 金融科技,通常被称为 Fintech,是科技创新发展最快的领域之一。预计它将呈指数级增长,并在未来几年内显著重塑金融格局。根据 Fintech Global 的数据,2018 年全球金融科技行业筹集了惊人的 417 亿美元投资。根据普华永道 2017 年全球金融科技报告,“82%的现任者预计在未来 3-5 年内增加金融科技合作。”因此,即使你不倾向于转行,了解你在不久的将来可能要合作和接触的玩家也是很重要的。

“你必须……重新想象如何管理和转移资金,因为未来 5 年金融服务业的变化将超过过去 30 年。”—PayPal 首席执行官丹·舒尔曼

目前,合格的金融科技工作者的需求远远大于供应,在这个市场上,潜在候选人很有可能继续在雇主面前占据上风。区块链、数据科学和机器学习等领域对知识工作者的需求很高。这些现代工作要求金融专业人士采用新技能,并熟练掌握技术语言。谁掌握了这一组合,谁就会加入少数幸运者的行列,他们的职业生涯将充满希望、挑战和利润。

随着金融科技的进步,对合格工人的需求预计将保持高位,而供应将保持低位。因此,工资将反映这一差异。

随着现有工作开始消失,新的工作到来,了解金融就业市场的走向非常重要。随着金融科技的进步,预计需求将保持高位,供应将保持低位。因此,工资将反映这一差异。出于上述原因,我们在下面介绍了一些薪酬最高的金融科技角色。

1。区块链专家和开发者 区块链技术在金融领域前景广阔。例如,基于区块链网络的智能合同允许在没有第三方参与的情况下进行可信的交易。这有可能取代和淘汰许多中介角色,如经纪人和银行机构。
在普华永道进行的 2017 年全球金融科技报告中,提出“77%的金融机构预计到 2020 年将采用区块链作为生产系统或流程的一部分”。区块链开发人员是与区块链技术公司合作的软件开发人员。他们负责区块链应用程序从研究到执行的整个生命周期。这一领域的人才稀缺,导致工资比正常工作至少高出 10-20%。平均每个区块链开发者有 14 个工作机会,我想他们的胜算更大。

2。应用专家(开发人员和架构师) 应用专家的主要角色是应用和软件设计,因为应用专家从头到尾指导产品生命周期。这包括设计流程以及创建、测试和介绍应用程序。应用专家还会修改现有软件,并对可能出现的任何软件相关问题进行故障排除。

3。数据科学家
如今,财务部门在很大程度上依赖数据科学来简化决策并为各种问题提供更好的解决方案。数据科学家帮助连接成千上万的信息源之间的点,并反过来为客户提供更好、通常更有效的解决方案。

今天,有了大量的现有数据,数据科学家告诉我们这一切意味着什么。因此,对数据科学家、数据分析师和分析专家的需求很大,并相应地要求高报酬。

根据 Glassdoor 的数据,数据科学家被列为 2019 年美国排名第一的工作。Glassdoor 的排名考虑了职位平均工资、空缺职位数量以及该职位员工的平均工作满意度。

4。网络安全专家
随着越来越多的金融数据以数字化方式存储和传输,网络攻击和黑客攻击也越来越多。不幸的是,网络技能安全缺口很大,而且还在扩大。因此,组织愿意花费大量的金钱来引进能够保护他们的在线资产和数据的人。据《福布斯》(Forbes)报道,“网络安全专业人员的平均工资为 11.6 万美元,是全职工资和薪水工人全国平均收入的近三倍。”

改旧迎新

许多长期存在的金融角色将继续存在,但会有所改变。例如,合规和风险管理这两个重要的金融领域将变得越来越重要,因此也越来越有利可图。鉴于技术的影响,这些高薪职位所需的技能将包括现代元素。我们解释如下:

6。风险控制经理
风险经理分析和控制企业的财务风险。评估和确定风险程度是金融界的基石。在现代世界中,数据科学是一项关键资产,可帮助金融机构构建更快、更好的风险决策流程和评估。

像 FICO 这样的信用评级机构和信用评分公司已经依靠数据科学和机器学习来获得借款人的即时数据。例如,他们使用逻辑回归来预测客户的风险,并区分好的借款人和坏的借款人。更新技术世界的长期角色是必要的,以确保它们继续存在。

7。合规专家 技术的作用越大,就越需要合规专家。随着技术对规则和法规提出新的挑战,监管的必要性和重要性与日俱增——新的法规越来越多,更严格的法规是必要的。

新平台已经在挑战做事的方式。

除了金融科技的角色,许多金融科技平台和技术已经在改变金融工作的方式。以下是您可能很快就会看到的集成、改变或取代财务工作场所流程的几个平台:

区块链平台
共生体是领先的智能合约平台。有了 Symbiont,机构可以依靠统一的分类帐来获取商业信息和市场数据。区块链平台可以用来创建数字形式的金融工具,包括贷款和证券。通过构建数据共享网络来降低风险、保护数据并节约成本。

支付平台
Payoneer 的跨境支付平台帮助企业在全球范围内支付和收款,就像在自己的城市一样轻松。使用 Payoneer,您可以轻松管理多个供应商,向供应商付款,并轻松获得来自世界各地的营运资金,从而超越您所在国家的边界。Payoneer 等平台为银行和传统贷款机构带来了新的竞争。

自动化平台
DataRails 通过自动化基于 Excel 的数据的繁琐合并流程,彻底改变了 FP &完成工作的方式。凭借其专利技术,DataRails 将所有基于 Excel 的数据整合并存储在基于云的集中式数据库中。节省时间、金钱和精力,而无需改变您的工作方式。DataRails 改进了财务部门,尤其是财务专业人员的工作方式和获取见解的方式。

借贷平台 Kabbage 是一个新颖的借贷平台,与 Payoneer 等支付平台一起,与传统金融服务相抗衡。Kabbage 提供了一种更简单的企业融资方式,允许个人在 10 分钟内获得高达 25 万美元的信贷。通过消除获取信贷的令人疲惫的过程,Kabbage 为小型和新兴企业提供了发展和繁荣的机会。

准备好,准备好,开始!不管喜欢与否,比赛已经开始了。

传统金融需要适应,否则就会被创新超越。
最后,我想引用“不同思考”小组的合伙人 David M. Brear 的话。尽管他专门谈到了银行业,但他的话引起了整个金融业的共鸣。

“技术创新将是未来许多年银行业的心脏和血液,如果大银行不能充分利用这一点,金融科技和大型科技公司的新参与者肯定会。”
-David M . Brear,合伙人,不同思维小组

最小 k 路切割问题的简单快速确定性算法

原文:https://towardsdatascience.com/a-simple-and-fast-deterministic-algorithm-for-the-minimum-k-way-cut-74d7ee2a521a?source=collection_archive---------4-----------------------

用一个例子逐步解释 m .托鲁普的“通过确定性贪婪树包装的最小 k 路切割”中的算法。

最小 k 向切割

G= ( V,E,c: E →R+ ) 是一个有容量限制的图,其中 |V|=n 个节点, |E|=m 个边。一个 k 路切割是将节点划分成 k 组。切割边是连接不同组中的节点的边。最小 k 路切割问题的目标是找到最小化切割边总容量的 k 路切割。

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

In the left, a capacitated graph. In the right, a minimum 3*-way cut. The weight of the cut is the sum of the capacities of the edges that are not in the right subgraphs, which is 52.*

最小路割问题在网络出现的不同领域都有应用,例如,在社交网络中划分兴趣组。它还用于查找电信网络甚至流量网络中最弱的连接。

解决问题

如果 k 是输入的一部分,那么为有容量限制的图寻找最小 k 路割的问题是 NP 难的,参见[1]。在 k 固定的情况下,问题是多项式可解的。

M. Thorup 在[2]中提出的算法解决了soft-o(n^(2k)*,*参见 soft-O wikipedia

算法:通过确定性贪婪树包装的最小 K 路切割,由 m .托鲁普提出

该算法建立在 m .托鲁普在[2]中提出的以下定理的基础上:

对于 0 < a < 9/10,设 T 是一个至少有 3 个m(k/a)ln(nmk/a)树的贪婪树包装。然后,平均起来, T 的树交叉每条最小k-路割不到 2( k- 1+2 a )次。特别地,对于 a =1/4,每个最小 k 道切口被 T 中的某棵树最多穿越 2 k -2 次。

考虑到 a =1/4 的特殊情况,寻找最小 k 路径切口的过程如下:

  • 构建贪婪树包装。
  • 对于至少一棵树的包装,收集每个 k 道切口不超过 2k2 次。
  • 从集合中选择最小的 k 向切削,也就是最小的 k 向切削。

逐步解释

在这个解释中,目标是找到以下容量限制图的最小 3 路截

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

Capacitated graph.

第一步:生成贪婪树包装

贪婪树打包是图的生成树的集合,其通过将关于利用率的最小生成树添加到集合中来构建。

一条边的利用率是该边在包装的当前树中的次数与其容量的商。因此,每次将一棵树添加到包装中,这些边的利用率都会随着其容量的倒数而增加。

贪婪树打包获得的第一个生成树如下:

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

First nine spanning trees (left-right by row) of the greedy tree packing. Edge labels are the capacities.

步骤 2:建造每一个 k 道切口,该切口被树穿过少于 2k2 次

如果对于每棵树,我们得到所有没有被该树交叉超过 2 次的 k 个方向切口,则最小的 k 个方向切口必须在最终集合中。那么,如何列出给定树木的采伐量呢?现在对包装的第一棵树进行解释,并且必须对它们中的每一个进行解释。有两个步骤:

  • 考虑从树上切割 2 条 k 条 -2 条边所产生的所有可能的图形。这些切割中的每一个都有 2 个 k -1 块。

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

Sample of cuts generated by cutting 2k-2 edges from the first tree of the packing. Pieces of the first cut would be 1:[0, 1, 6, 7], 2:[2, 5], 3:[3], 4:[4], 5:[8]

  • 对于每个切割,以各种可能的方式将 2 个 k -1 件分成 k 组。在这样的分组中,被分成 k 块的节点诱导出一个 k 路割(在不同组的节点之间没有边的原始图),该图满足被考虑的生成树交叉不超过 2 k -2 次的条件。

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

All 3-way cuts extracted from the first cut (previous figure’s first) of the first tree.

这样做的关键是,对于给定的树,删除 2 条 k -2 条边相当于确保我们只允许这些边穿过 k 路切割,因为剩余的边将节点保留在一个片段中,这些节点必须属于将片段分成 k 组的每个可能分组中的同一组。

这 25 个作为最小 k 路切割的候选是从贪婪树包装的第一棵树的第一次切割中提取的。必须对包装中每棵树的 2 个 k -2 个边缘的所有可能切割进行收集。

第三步:选择最小k-路切

最小 k 路切削是生成的 k 路切削集合的最小值。

时间复杂度

算法的时间复杂度是找到定理所有可能的 k 路割的时间。有关更多详细信息,请查看算法参考。因此,

  1. 贪心树包装:3 棵m(k/a)ln(nmk/a)=soft-O(MK)树,每棵在 O(n) 。对于每棵树:
  2. 树的 2 k -2 条边的所有可能切割: Binom ( n- 1,2k-2)=soft-o((en/(2k-2))^)2k-2)可能性。对于每次切割:
  3. 将 2 个 k -1 块分割成 k 套:最多k^(2k-1)/k!= 软-o((ek)^(k-1))不同的方式。

每个分区可以在固定的时间内生成分区,因此,时间复杂度变为soft-o(n^(2k)。

结论

在这篇文章中,解释了一个寻找有容量限制的图的最小 k 路割的算法。接下来是一个例子,看看它是如何工作的,最后起草了一个简单的复杂性分析。

图形操作和数字是用 Python 的 NetworkX 包创建的,见[3]。

参考

  1. O.戈德施密特和 D. S .霍赫鲍姆。固定 kk 割问题的多项式算法。数学。操作。第 61 号决议,1994 年。
  2. 米(meter 的缩写))托鲁普。经由确定性贪婪树包装的最小 k 路切割。第四十届 ACM 计算理论年会会议录, 2008。
  3. NetworkX,https://NetworkX . github . io

附录

算法的 Python 代码

在本附录中,有在 python 中运行算法的代码。该代码不是为最佳体验而优化的,它旨在阐明所描述的算法的定义和结构。

预测性维护的简单且可解释的基线

原文:https://towardsdatascience.com/a-simple-and-interpretable-baseline-for-predictive-maintenance-3f94736ed99a?source=collection_archive---------14-----------------------

不久前,我在数据科学工作中遇到了一个预测性维护问题。高度不平衡的类(因为破损的数量通常小于 1%),大量不可解释的传感器——好吧,但下一步是什么?由于我缺乏这方面的经验,我开始搜索和阅读所有我能找到的关于“项目管理的数据科学”的资料。

令我失望的是,我发现的大多数文章都没有给我提供有价值的见解——它们要么是一些复杂的 Arxiv 论文,在不可用的数据上测试新的理论方法,要么是一些高水平的博客帖子,缺乏可重用的想法。

经过几个月用机器学习解决预测性维护(进一步设置为 PM)问题的实践经验,我厌倦了辛劳,决定分享我迄今为止开发的基线方法。对于像我几个月前一样,不知道该做什么,希望附近有某种灯塔的人来说,这可能是富有成效的。

在帖子中,我将解释问题的业务方面,并列出客户端对算法的典型要求,这可能会极大地限制可用的数据科学工具集。接下来,我将详细解释我的方法,并强调其利弊。最后,我将分享一些实用的技巧和代码片段,对实现它有所帮助。

业务问题

如果你只对技术感兴趣,你可以跳过这一部分。

安装在业务流程中的每个 ML 算法都应该以某种方式增加利润。在项目管理中,我们通常有一台大型机器,消耗昂贵的资源,通过复杂的多阶段过程产生某种最终输出。随着时间的推移,这些机器会意外损坏,导致闲置时间增加和宝贵资源的损失,因为发生故障的机器通常会浪费这些资源。

这就是 ML 算法可以进入场景的地方——它可以使用安装在机器上的传感器的数据,提前预测故障(我在全文中交替使用停止、损坏、停止)。然而,即使我们能够提前预测这些停止,在不知道原因的情况下,我们预测的财务价值将是适度的。

首先,如果我们向工程师报告的唯一信息是在接下来的 20 分钟内破损的可能性很高,他们就不能做太多。也许,他们可以停止机器,做一些深度维护,但这是昂贵的。此外,对于大型机器,他们不一定会在如此短的时间内发现故障原因,因此,我们预测的价值是无效的。第二,我们的算法会有一定的误报。由于假阳性的存在,客户端很少会批准停止机器来检查不明显的故障。

因此,我们的算法,除了预测停止的概率,应该在某种程度上暗示可能的原因。它将为技术人员在预防性维护过程中查找故障提供一定的指导。在这种情况下,我们的 ML 算法真正解决了客户的痛苦。

数据准备

现在让我们仔细看看一个典型的预测性维护数据。下面是完成数据准备后,结果变量的样子。 Y = 1 如果即将停止,而 Y = 0 如果在接下来的 K 分钟内没有停止。

你可以看到,类是不平衡的,机器学习模型应该给稀有类更高的权重,以便用更强的注意力来区分导致停止的异常。

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

Outcome variable

但是要获得这个时间序列,你必须做一些繁重的工作。通常,它们会为您提供两个数据集-一个包含有关停靠点的信息(它们的性质、原因和时间戳),另一个包含来自传感器的所有数据。

我们需要合并这两个文件来创建数据集。我建议当机器坏了时,停止观察(下面是数据处理的代码样本),因为这些信息可能有噪音。例如,可以丢弃到下一站的时间少于 5 分钟的所有观测。

接下来,让我们将到达下一站的时间超过 20 分钟的所有观察值标记为零,而将到达下一站的时间小于 20 分钟的所有观察值标记为一(您可以根据您的数据改变这个临界值)。这个操作稍微改善了你的职业平衡。

通常在机器的不同部分有不同类型的停止。我建议筛选数据,选择最常见的一个,然后将解决方案推广到其他止损点。不同类型的停车有不同的原因,因此,关于每次停车的信息将包含在不同的传感器组中。因此,一个通用模型不太可能表现良好。

一些可能有助于您完成上述操作的代码:

https://gist.github.com/ikleni/fa9421f23852459e166f14a5f4edb584

第二,要处理好解释变量( Xs )。在我们将它们与一个结果变量合并后,我们应该尝试降低维度,以便得出有意义的结论。在没有任何行业细节的先验知识的情况下,我们无法根据我们的直觉选择哪些对应于重要的预测因素。就看一些 Xs 的剧情:

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

Examples of sensors

然而,我们有很多技术可以降低维度:

  • 超低方差跌落传感器
  • 根据传感器在机器中的位置/角色对传感器进行分组和聚合(通过 PCA 或其他类似技术)(此信息可从其标签中获得)
  • 变量的总体变化(有多少传感器刚刚改变了它们的状态)

根据与结果变量的原始相关性选择变量不是一个好主意

在我的任务中,变量变化的汇总很有帮助,因为它既包含了机器不稳定的信息,又减少了变量的数量。

这里有一个这样的聚合变量:

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

Aggregated variable and Y

我们可以进一步限制我们的传感器空间。

让我们反复挑选每个传感器,并尝试根据其分位数预测止损点。如果传感器的当前时间序列分位数在某种程度上指示停止,则传感器包含关于机器异常行为的信息。我建议选择大约 5-15 个(这个范围适用于我的特殊问题)传感器,它们的分位数模型具有最强的预测能力。

这一步预测能力的丧失取决于止损的数据和性质,因为有时某一顺序的复杂相互作用可能对预测至关重要。然而,我们的主要目标是简单的基线可解释性和对客户的可解释性。

另一个有用的事情是在停止之前和稳定工作期间检查所选传感器的行为。如果你注意到你的时间序列图在停止之前有异常,你就有很好的机会解决这个问题。

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

Sensors just prior to the stop (look for simultaneous jumps in certain variables)

生成此类图的代码:

https://gist.github.com/ikleni/95d93442f1042d1c7e3bf392d4322a30

建模

思绪

给定行为良好的( X,Y )(我假设你已经做了其他标准的数据预处理,比如处理缺失值)数据我们就可以开始建模阶段了。

在测试一些模型之前,我们可以假设信号包含在哪里。机器是为了正常运转而设计的。此外,它们还规定了一个稳定的工作状态,指示每个传感器的值的区间。如果由于某种原因(工程师没有顺利改变某个参数),机器偏离了规定的运行状态,它可能会发生故障。随着时间的推移,机器变得越来越不稳定,操作制度应考虑到这种转变。这种情况很少发生——这可能是我们完成这项任务的面包和黄油。

我希望通过每个传感器与一些新值范围的偏差,可以很好地预测止损。此外,我预计几个传感器之间的相互作用将预测停机。例如,如果一个传感器偏离其正常间隔,而另一个传感器的值为 w ,则不会发生停机。但是,如果同一个传感器出现偏差,而另一个传感器的值为 z ,则停止是不可避免的。

我不期望(这个假设对我的任务有好处)大量传感器之间的交互对这个任务有帮助。特别是,如果我们量化当前超出其标准值范围的传感器总数。这种整体机器稳定性应该是该模型的关键特征之一。

接近

考虑到这一点,我选择用基于 2-3 个传感器和集合特征的小模型的多数投票集合来预测停靠点。这种方法允许识别哪些传感器发出停止信号。这些信息可以在以后提供给工程师,工程师可以根据他们的知识找出原因并解决问题。

首先,我使用具有特定调整参数的基本 LGBM 模型,从我们的受限集合中选择一组传感器对(三元组)。根据 k 倍时间序列交叉验证的 AUC 分数,通过对成对的迭代搜索进行选择。除了传感器数据,这些小型模型还包括聚合功能和一些基于传感器的直观功能,例如:

  • 平均
  • 趋势
  • z 分数
  • 标准

变量生成代码:

在确定了小模型的集合之后,它们的预测通过基本集合被组合。发现 0.5 分位数,如果它高于预定义的边界,我预测 Y = 1,止损应该很快出现。报警!

上述方法略有简化,还可以做更多的工作来提高其精度,例如:

  • 其他组装技术(RNN 和其他…)
  • 其他初级学习者
  • 搜索剩余的传感器,并将它们添加到一些小模型中
  • 为每个生产体系建立一个单一模型(夏季/冬季在传感器值的分布上有很大不同,这可以通过 Kolmogorov-Smirnov 测试进行检查)

结果

在我看来,图像比文字或指标更能说明问题,如果你看到算法很少预测停止,但当机器确实发生了一些事情时——我们很好:

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

Good performance of the baseline

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

Bad performance

在我的数据中,所描述的框架能够以大约 40%的精度和大约 40%的召回率预测停止,这对于预测性维护中的基线来说是一个好结果。此外,它为工程师提供了特定传感器的参考,因为他们知道哪些传感器发出停车的可能性较高。因此,他们可以进行有针对性的预防性维护。

最后,我将简要总结一下这种方法的利弊:

优点

  • 简单性和可解释性(由于每个型号的传感器数量如此之少,您可以强调机器的哪个部分驱动了停止的威胁)
  • 对 GPU 使用和内存的低限制

缺点

  • 在准确性方面次优(具有所有特征的训练有素的神经网络可能优于该基线)
  • 计算时间限制(所有这些迭代搜索都需要时间)
  • 人的时间限制(这种方法需要人的指导)

稍后我会添加链接到省略的代码。此外,我要感谢 Kaggle Bosch 竞赛,我用它创作了所有这些图像…

Python 中模板化 SQL 查询的一种简单方法

原文:https://towardsdatascience.com/a-simple-approach-to-templated-sql-queries-in-python-adc4f0dc511?source=collection_archive---------1-----------------------

加速和自动化您的分析

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

在许多情况下,人们都希望在 SQL 查询中插入参数,并且有许多方法可以在 python 中实现模板化的 SQL 查询。在不比较不同方法的情况下,这篇文章解释了一种使用 JinjaSql 参数化 SQL 的简单而有效的方法。除了 Jinja2 的许多强大功能,如条件语句和循环,JinjaSql 还提供了一种简单明了的方法,不仅可以参数化代入wherein子句的值,还可以参数化 Sql 语句本身,包括参数化表和列名,以及通过组合整个代码块来组合查询。

基本参数替代

假设我们有一个保存金融交易记录的表transactions。该表中的列可以是transaction_iduser_idtransaction_dateamount。要计算给定用户在给定日期的交易数量和总金额,直接对数据库的查询可能如下所示

**select**
    user_id
    , count(*) as num_transactions
    , sum(amount) as total_amount
**from**
    transactions
**where**
    user_id = 1234
    and transaction_date = '2019-03-02'
**group by**
    user_id

这里,我们假设数据库会自动将日期的字符串表示形式的YYYY-MM-DD格式转换成适当的日期类型。

如果我们想要为任意用户和日期运行上面的查询,我们需要参数化user_idtransaction_date值。在 JinjaSql 中,相应的模板将简单地变成

**select**
    user_id
    , count(*) as num_transactions
    , sum(amount) as total_amount
**from**
    transactions
**where**
    user_id = {{ uid }}
    and transaction_date = {{ tdate }}
**group by**
    user_id

这里,值被占位符替换,python 变量名用双花括号{{ }}括起来。注意,选择变量名uidtdate只是为了证明它们是变量名,与列名本身没有任何关系。存储在 python 变量中的同一模板的一个可读性更好的版本是

**user_transaction_template** = '''
**select**
    user_id
    , count(*) as num_transactions
    , sum(amount) as total_amount
**from**
    transactions
**where**
    user_id = {{ user_id }}
    and transaction_date = {{ transaction_date }}
**group by**
    user_id
'''

接下来,我们需要为查询设置参数。

params = {
    'user_id': 1234,
    'transaction_date': '2019-03-02',
}

现在,从这个模板生成 SQL 查询非常简单。

**from** jinjasql **import** JinjaSql
j = JinjaSql(param_style='pyformat')
query, bind_params = j.prepare_query(user_transaction_template, params)

如果我们打印querybind_params,我们会发现前者是一个参数化的字符串,而后者是一个参数化的OrderedDict:

>>> print(query)
**select**
    user_id
    , count(*) as num_transactions
    , sum(amount) as total_amount
**from**
    transactions
**where**
    user_id = %(user_id)s
    and transaction_date = %(transaction_date)s
**group by**
    user_id>>> print(bind_params)
**OrderedDict**([('user_id', 1234), ('transaction_date', '2018-03-01')])

运行参数化查询

许多数据库连接都可以选择将bind_params作为参数传递给在连接上执行 SQL 查询的方法。对于数据科学家来说,在 Pandas 数据框中获得查询结果可能是很自然的事情。一旦我们有了连接conn,就像运行read_sql一样简单:

**import** pandas **as** pd
frm = pd.read_sql(query, conn, params=bind_params)

其他示例参见 JinjaSql 文档

从模板到最终的 SQL 查询

通常希望在运行查询之前用所有参数完全展开查询。例如,记录完整的查询对于调试批处理过程非常重要,因为可以将查询从日志中直接复制粘贴到 interactive SQL 界面中。使用 python 内置的字符串替换将bind_params替换到query中是很诱人的。然而,我们很快发现字符串参数需要加引号才能产生正确的 SQL。例如,在上面的模板中,日期值必须用单引号括起来。

>>> print(query % bind_params)
​
**select**
    user_id
    , count(*) as num_transactions
    , sum(amount) as total_amount
**from**
    transactions
**where**
    user_id = 1234
    and transaction_date = 2018-03-01
**group by**
    user_id

为了处理这个问题,我们需要一个助手函数来正确地引用字符串参数。我们通过调用来检测参数是否是字符串

**from** six **import** string_types
isinstance(value, string_types)

这对 python 3 和 2.7 都适用。字符串参数被转换为str类型,名称中的单引号被另一个单引号转义,最后,整个值被括在单引号中。

**from** six **import** string_types**def** quote_sql_string(value):
    '''
    If `value` is a string type, escapes single quotes in the string
    and returns the string enclosed in single quotes.
    '''
    **if** isinstance(value, string_types):
        new_value = str(value)
        new_value = new_value.replace("'", "''")
        return "'{}'".format(new_value)
    **return** value

最后,为了将模板转换成正确的 SQL,我们循环遍历bind_params,引用字符串,然后执行字符串替换。

**from** copy **import** deepcopy**def** get_sql_from_template(query, bind_params):
    **if** **not** bind_params:
        **return** query
    params = deepcopy(bind_params)
    **for** key, val **in** params.items():
        params[key] = quote_sql_string(val)
    **return** query % params

现在我们可以很容易地得到最终的查询,我们可以记录或交互运行:

>>> print(get_sql_from_template(query, bind_params))**select**
    user_id
    , count(*) as num_transactions
    , sum(amount) as total_amount
**from**
    transactions
**where**
    user_id = 1234
    and transaction_date = '2018-03-01'
**group by**
    user_id

将所有这些放在一起,另一个 helper 函数包装 JinjaSql 调用,简单地获取模板和一个dict参数,并返回完整的 Sql。

**from** jinjasql **import** JinjaSql
​
**def** apply_sql_template(template, parameters):
    '''
    Apply a JinjaSql template (string) substituting parameters (dict) and return
    the final SQL.
    '''
    j = JinjaSql(param_style='pyformat')
    query, bind_params = j.prepare_query(template, parameters)
    return get_sql_from_template(query, bind_params)

计算列的统计信息

无论是在第一次浏览数据时还是在生产中进行数据验证时,对存储在特定数据库列中的值计算统计数据都很方便。因为我们只想演示模板的一些特性,为了简单起见,让我们只使用integer列,比如上面表transactions中的user_id列。对于整数列,我们感兴趣的是唯一值的数量、最小值和最大值以及空值的数量。有些列可能有一个默认值,比如说,-1,它的缺点超出了本文的范围,但是,我们确实想通过报告默认值的数量来捕获它。

考虑下面的模板和函数。该函数将表名、列名和默认值作为参数,并返回用于计算统计数据的 SQL。

**COLUMN_STATS_TEMPLATE** = '''
**select**
    {{ column_name | sqlsafe }} as column_name
    , count(*) as num_rows
    , count(distinct {{ column_name | sqlsafe }}) as num_unique
    , sum(case when {{ column_name | sqlsafe }} is null then 1 else 0 end) as num_nulls
    {% if default_value %}
    , sum(case when {{ column_name | sqlsafe }} = {{ default_value }} then 1 else 0 end) as num_default
    {% else %}
    , 0 as num_default
    {% endif %}
    , min({{ column_name | sqlsafe }}) as min_value
    , max({{ column_name | sqlsafe }}) as max_value
**from**
    {{ table_name | sqlsafe }}
'''
​
​
**def** get_column_stats_sql(table_name, column_name, default_value):
    '''
    Returns the SQL for computing column statistics.
    Passing None for the default_value results in zero output for the number
    of default values.
    '''
    params = {
        'table_name': table_name,
        'column_name': column_name,
        'default_value': default_value,
    }
    **return** apply_sql_template(COLUMN_STATS_TEMPLATE, params)

这个函数很简单而且非常强大,因为它适用于任何表中的任何列。注意模板中的{% if default_value %}语法。如果传递给函数的默认值是None,SQL 将在num_default字段中返回零。

如果default_value设置为 None,上面的函数和模板也可以处理字符串、日期和其他数据类型。然而,为了更智能地处理不同的数据类型,有必要扩展该函数,以将数据类型作为参数,并构建特定于不同数据类型的逻辑。例如,可能想知道字符串长度的最小值和最大值,而不是值本身的最小值和最大值。

让我们看看transactions.user_id列的输出。

>>> print(get_column_stats_sql('transactions', 'user_id', None))**select**
    user_id as column_name
    , count(*) as num_rows
    , count(distinct user_id) as num_unique
    , sum(case when user_id is null then 1 else 0 end) as num_nulls
    , 0 as num_default
    , min(user_id) as min_value
    , max(user_id) as max_value
**from**
    transactions

请注意,空行出现在{% %}子句的位置,可以被删除。

摘要

有了上面的帮助函数,用 python 创建和运行模板化的 SQL 查询就非常容易了。因为参数替换的细节是隐藏的,所以可以专注于构建模板和参数集,然后调用单个函数来获得最终的 SQL。

一个重要的警告是代码注入的风险。对于批处理来说,这应该不是问题,但是在 web 应用程序中使用sqlsafe构造可能会有危险。sqlsafe关键字表明用户(您)确信不可能进行代码注入,并负责将参数中传递的任何字符串直接放入查询中。

另一方面,在查询中放入任意字符串的能力允许将整个代码块传递到模板中。例如,可以不通过上面的table_name='transactions',而是通过'(select * from transactions where transaction_date = 2018-03-01) t',查询仍然可以工作。

要探索 SQL 模板更强大的特性,也可以参考关于使用 JinjaSql 的 Python 中的高级 SQL 模板教程

本帖中的代码获得了麻省理工学院许可的许可。这篇文章最初出现在生活数据博客上。

Sergei Izrailev 的照片和图片

一个简单而有效的面试准备技巧

原文:https://towardsdatascience.com/a-simple-but-effective-interview-prep-trick-3efb0f017c62?source=collection_archive---------25-----------------------

尝试这种实用的方法来准备数据科学面试

正好逢年过节,各位求职者,我送给你的礼物是一个非常实用的面试准备方法。如果你也这么做,保证你有 100 万的工作机会!不过说真的,这样做了之后,在面试的时候谈自己和自己的工作就会轻松很多。回忆关于你技能的信息越容易,面试就越容易。

方法?在你的简历中标注#$%。

制作一份简历的副本,并保存为一个单独的文件。然后,花一到三个小时对这份文件进行评论,每项技能、项目或角色都与你面试的角色相关(简称“TRYIF”)。面试官可能会把你的简历作为他们会问你的问题的指南,无论是文化问题还是技术问题,所以你可以在评论中同时关注这两个问题。

如果你有一份过去几周一直在申请工作的“通用”简历,这尤其有帮助。这是一个通过 TRYIF 的镜头唤起你对每个主题的记忆并思考它的练习。最近你对这些事情想得越多,谈论它们就越容易。

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

Google docs is a good way to organize your resume thoughts

你的评论应该至少涵盖其中的一个方面,你涵盖的越多,你的准备就越充分。每一个后面都有一个我今天早些时候准备的简历注释的例子:

a) 定义用你自己的话或从其他来源对项目的解释,还是那句话对你最有利。Seaborn:“Python 数据可视化库,它提供了一个高级接口,用于绘制有吸引力且信息丰富的统计图形。”(来自其网站)或 Seaborn:让 matplotlib 更漂亮。

b)项目的目标优点缺点Pandas:因为有表格,所以很容易使用,但不能处理大量数据(超过 10gb 时会非常慢)

c) 该物品在您过去项目中的重要用途烧瓶:部署 汇聚 以及使用它的 Doppel app

d) 您对项目用药过量 项目的意见:很难找到这个项目的数据集,了解了很多关于人口普查及其 API 和阈值的信息。

其中一些可能看起来“多余”,但有一些很好的理由来注释你的简历。通常面试官感兴趣的是听你如何向那些不知道你在说什么的人解释事情。也有可能面试官不熟悉你简历上的某件事,然后你可以很快回忆起你刚刚为他们创造的简单解释。最后,这些很容易写,因为除了你没有人会看到它们。你不必担心语法或让它们变得完美——这完全是你的大脑的事!

面试并不容易,但是把这种方法和一般的面试建议结合起来,做很多项目,你就在获得工作机会的路上了,我的朋友。你自己试试吧,并告诉我你的想法。

新年快乐!希望新工作也愉快!

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

Photo by Suhyeon Choi on Unsplash

一个简单但强大的人工智能机器人,用于六边形网格上的创/光骑士

原文:https://towardsdatascience.com/a-simple-but-strong-ai-bot-for-tron-lightriders-on-a-hexagonal-grid-2d7662ffcbf6?source=collection_archive---------17-----------------------

基于寻路的简单启发式算法如何找到通往排行榜顶层的路径。

新的学年,意味着新一批聪明的学生开始了他们工程生涯的第一步。和去年一样,我和我的三个课程助理同事(埃利亚斯彼得奥赞)为一个人工智能机器人竞赛创建了一个平台,将在根特大学的教授 Dhoedt 讲授的信息学课程(他们在该课程中学习 Python 编程)期间举办。今年,我们决定主办 Tron(有时称为连续蛇或 Lightriders)的游戏,如下所示。

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

A more advanced implementation of the game Tron, called Armagetron

既然谜语. ioCodinGame (如果你对 AI 机器人感兴趣的话绝对应该去看看!)也为 Tron 举办一场人工智能比赛,我们决定稍微修改游戏,让它在六边形网格上玩,而不是正方形。这可以避免学生只是复制粘贴那些平台的可用解决方案。游戏截图可以在下面找到。

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

A visualization of a match between two bots, which I lost. The darker colored tiles are starting positions.

和去年一样,我决定自己参加比赛,但没有那么多空闲时间。因此,我的解决方案不是很强。尽管如此,我最终在排行榜上名列前茅(第五名),拥有最少的代码基础和简单的启发式搜索,基于路径查找。

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

The top 10 of the final leaderboard. Again this year, we were amazed by the quantity and quality of many submitted agents by students. Notice how jvdhooft, my partner in crime of last year, regretted his decision of not collaborating this year 😉.

为了讨论我的解决方案,我不需要像去年那样多的时间/行数,因此我决定添加一些额外的内容。我把这篇博文分成几个部分:

目录

  1. 游戏和竞赛规则
  2. 我的强启发式的详细概述(附代码)
  3. 一些顶级竞争对手写的文章
  4. 竞赛平台制作概述(另文)

1.游戏和竞赛规则

1.1 游戏规则

游戏规则相当简单明了。两个玩家都从一个随机的位置(镜像在地图的中心)开始,并且有一个随机的方向(总共有 6 个方向)。每个玩家必须决定是否要旋转他们的蛇(120°或 60°顺时针/逆时针或 0°),然后向前移动(如下图所示)。每条蛇都会留下难以穿越的痕迹。第一条撞到墙壁或自己或对手的踪迹的蛇输掉游戏。

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

The five possible moves a player can make in each turn.

1.2 竞赛规则和代理界面

提交的代理必须遵循预定义的界面:

def **generate_move**(board, positions, orientations):
  """Generate a move.
     Args:
        board (np.array):    playing field
        positions (list):    list of positions `(x, y)`
        orientations (list): list of orientations (int in [0,5]) Returns:
        move (int):          integer in [-2,2]
    """
  return 0

此外,每个代理必须遵守以下限制:

  • 它不包含import语句,除了:numpy, functools, itertools, collections, operator, heapq, math, random, time
  • 文件大小不得大于 1 兆字节
  • generate_move的执行时间不得超过 1 秒

向我们的平台提交您的第一个代理后,您将每 30 分钟与另一名玩家配对一次。每场比赛结束后,双方玩家的排名( TrueSkillELO )会根据比赛结果进行调整,这些排名用于排行榜。关于排名系统的更多信息,请参考我的下一篇文章

1.3 定期比赛和附加赛

比赛持续了 1 个月左右。我们注意到运气对你的最终排名有很大的影响(由于匹配算法)。为了克服这一点,并尽可能客观地结束排名,我们在一段时间后从排行榜上剔除了排名靠前的竞争者(仅限一年级学生)。这些竞争者被挑选出来参加“附加赛”,每个代理人与所有其他代理人比赛四次。每赢一场,代理人被分配三分,而平局(有很多场)导致双方代理人被奖励一分。

2.我的基于寻路的强启发式算法

2.1 主回路

在实现更复杂的技术之前,比如强化学习、遗传算法和阿尔法-贝塔剪枝,首先实现一个基于启发式的代理总是一个好的实践。这些可以用来测试你对手的实力,但更重要的是你代理的后期版本的实力。不幸的是,由于时间不够,我今年没有实现更复杂的技术,只上传了我的基线代理,基于一个启发式的(结果非常强大)。我现在将彻底讨论我的实现。

我的代理人背后的主要推理相当简单:“总是选择导致你可以首先到达的牌的数量与你的对手可以首先到达的牌的数量之间的最大差异的移动。”很明显,会有很多情况下,每一个可能的走法的结果都是相同的分数(尤其是在游戏开始的时候)。我们通过最小化某一步后剩余合法走法的数量和最小化到中间的距离(如果还能到达的话)来打破平局。主游戏循环如下所示:

The main loop of our agent. In each turn, we iterate over all possible legal moves

2.2 获得所有合法移动

现在让我们把所有事情都分解开来,从(可能)代码中最简单的部分开始:获得所有合法的移动(get_legal_moves)。在这个函数中,我们迭代区间[-2,2]中的每个整数,这是五个可能的移动。我们将每个整数映射到一个偏移量元组(get_steps),该偏移量元组对应于我们的移动,并根据这些偏移量更新我们假设的位置和方向(_update_pos_orient)。然后,我们计算我们是否仍然居住在六边形网格中(_valid_position)以及我们是否没有撞上一个已经被占用的单元(_no_crash):

代码相当简单,可能不需要太多的阐述。为了检查我们是否仍然在六边形网格中,我们必须通过检查我们的xy坐标是否没有超出我们游戏区域的边界来确保我们没有得到IndexError。此外,由于棋盘表示是一个带有一些不可到达的单元格的正方形,我们需要确保我们的代理不会移动到这些单元格中的任何一个上。通过检查主页上描绘的较小(7x7)游戏场,我们注意到合法单元的xy之和以 3 和 9 为界。

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

The x and y coordinates of the allowed tiles on a 7x7 field are bounded by 3 and 9.

这适用于所有比赛场地,因此我们可以说:

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

k 是运动场的大小。此外,为了检查我们是否没有在已经被占用的单元上移动,我们可以只沿着我们的游戏板的最终轴进行求和(记住这个游戏板的最终轴包含每个玩家的位图),并检查我们想要移动到的坐标的值是否等于 0。此外,_get_steps中偏移的顺序是特定的顺序,这样我们可以使用我们新计算的方向(等于(orientation + action) % 6)直接索引它们。使用这个新的方向,我们可以得到相应的偏移量,并将它们添加到我们当前的坐标中,以计算我们的新坐标。

2.3 计算游戏状态的效用或分数

现在我们有了一个不会导致我们立即失败的所有移动的列表,我们可以根据启发式算法计算每个移动的分数。我们使用的试探法是基于到游戏区域中每个可能牌的距离。我们希望在比对手少走几步的情况下,尽可能多的拿到牌,同时尽可能少的先拿到牌。下面展示了一个不错的 GIF,取自谷歌 Tron 人工智能挑战赛中获胜解决方案的报道。

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

Maximizing the cells we (red) can reach first, while minimizing the cells our opponent (blue) can reach first results in a strong, but not optimal, heuristic.

为了计算从某个坐标到另一个单元的最小距离,我们可以使用 A*寻路算法Dijkstra 。但是因为我们需要计算到网格中所有单元的距离,所以我们使用一个稍加修改的版本。我们跟踪仍然需要访问的单元列表(以及到每个单元的距离),称为frontier。对于我们的边界中的每个单元,我们在所有可能的方向上扩展,并且如果它们还没有被探索或者如果我们发现了具有较小移动量的路径,则将这些新单元添加到我们的边界中(距离等于我们的旧距离+ 1)。一旦我们计算了两个玩家到所有单元的距离,我们就可以很容易地计算出两个玩家可以首先到达的牌的数量:

就是这样!就这么简单。简而言之,我们检索所有可能合法行动的列表,然后迭代这些合法行动并计算每个行动的得分。分数是基于我们在移动后可以从新的位置首先到达的牌的数量,以及我们的对手可以首先到达的牌的数量。还有一些额外的细节,例如,如果我们离对手太近,无法避免正面碰撞,则从分数中减去一个惩罚项,以及平局情况下的处理(平局的打破基于填满棋盘的剩余合法移动的数量以及到中间的距离,因为这在游戏开始时很重要)。

2.4 可能的改进和其他方向

如前所述,今年只花了有限的时间写我的经纪人。因此,许多可能的改进是开放的。最重要的列举如下:

  • 启发式函数的适应可以导致显著的收益。根据谷歌 Tron 人工智能挑战赛的报道,这导致作者赢得了比赛。在他的博客文章中,提供了一个很好的游戏状态示例,其中用于我的代理的启发式函数将分配一个负的分数,而我们(再次是红色的)实际上是赢的一方:

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

According to our heuristic, red has much less tiles he can reach first than blue. But no matter what move blue makes now, red can easily win the game since it is impossible for blue to fill up all his tiles.

  • 我们可以为每一步可能的棋计算分数,而不是为每一步可能的棋计算分数,从而预测不止一步棋。为了解决这个问题,我们通常使用诸如阿尔法-贝塔剪枝这样的技术,但是由于两个玩家同时移动,所以需要做一些额外的考虑。一个简单的方法是首先为你的对手检索所有合法的移动,然后迭代你所有的合法移动(改变游戏状态),然后递归地调用你的对手,传递这些移动。这确保了两个玩家都可以计算他们的合法移动,在递归过程中使用相同的游戏状态。
  • 使用蒙特卡罗模拟,而不是使用启发式函数,计算每个可能的移动(或移动序列)的分数。在这里,我们将模拟从某个游戏状态开始的大量游戏,其中每个代理人将进行随机但合法的移动。我们从这些模拟中赢得的游戏分数可以很好地表明某个游戏状态的实力。当然,需要注意的是,出招的最大时间只有一秒。我没有测试一个人在一秒钟内可以做多少次模拟。
  • 进化神经网络为你玩游戏,是一个非常通用的策略,不需要游戏本身的知识。为此编写一个框架(或者配置一个已经存在的框架)将需要相当多的工作,但是一旦编写好了(或者掌握了现有框架的窍门),它就可以很容易地适用于其他游戏。我发现很多单人贪吃蛇游戏的例子(比如这里的这里的这里的)但是连续贪吃蛇或者 tron 的例子非常少(比如这里的这里的)。
  • 阅读其他顶级竞争对手的评论,并结合所有人最重要的见解来创建一个超级机器人。

3.顶级竞争对手的报道

以下是一些最终排名高于我的代理的学生的答案:

3.1。Michiel Platteau(决赛排行榜第一,附加赛第二)

这个机器人是它所有前身的产物。每次我做了很多元函数,而不是重新编写新代码。很多更小的功能总是可以回收到下一代。这些功能包括确定移动是否合法,计算可用单元的数量以及到这些单元的距离。但是将所有这些功能结合起来会变得相当复杂。

代码首先计算对手是否和他在同一个领域,如果他不在,他用最大数量的可用单元进行最左边的移动(floodfill)。如果他们在同一个领域,这都是为了在未来拥有最好的防洪堤。它从去中心(6,6)开始。如果蛇从边界开始,他尽可能走得宽些,试图欺骗对手,否则他会走最中间的路线,试图把场地分成两半。比赛场地的中央是一个非常重要的位置。我为这个动作做了一个特殊的函数。他观察哪些位置可以给他优势而不给对手优势。如果他没有找到一个这样的位置,他就向中间移动,导致许多可能的选择。

一旦机器人完成了对中心的争夺,我已经定义了一个函数来模拟如果我的蛇在每个可能的方向上直线前进的情况。它分析我的机器人是否可以从那里利用优势(更大的洪水),以及到那个地点的距离是否更短。它分析了“成功”、“可能平局”或“成功但距离更远”的情况。对于我能做的移动,他也像对对手那样运行那个功能,并且不做可能导致对对手有利的移动。这可能需要一段时间,所以它在 0.7 秒后停止这样做,它只是假设对手不会有优势。如果没有成功的移动是可能的,他试着尽可能靠近中心和敌人。

3.2. Kristiaan Bogaerts (决赛排行榜第 2 名,附加赛第 3 名)

在每一回合开始时,代理根据它收到的数据生成几个变量,其中一些是长度和宽度等于棋盘长度和宽度的 2D 数组,其他的是单元素整数或布尔。这些变量作为输入用于最终决定邻近代理的哪个六边形是最适合下一个去的,并且因此代理应该如何旋转以到达那个六边形,这是输出

代理生成的前述变量包括:

*一个 2D 阵列,其中对应于一个六边形的每个元素表示未被两个代理之一或其轨迹占据的相邻六边形的数量

  • 2D 数组,其中对应于一个六边形的每个元素指的是从该六边形到棋盘边缘的最短可能距离(以六边形表示)

*一个布尔值,表示两个代理是否仍能相互联系

计算完这些变量后,代理根据单元素变量的值为 2D 数组分配权重。2D 阵列被乘以它们各自的权重,随后被加在一起以构建最终的 2D 阵列**。在这个最终数组中对应于棋盘上的六边形的每个元素都被分配了一个值,如果代理通过移动到该六边形估计赢得游戏的机会相对较高,则该值相对较高,如果代理估计的机会相对较低,则该值相对较低。最后,代理将检查其位置周围的每个六边形,寻找在最终数组中具有最高对应值的六边形,并将输出到达该六边形所需的旋转。**

3.3.马克西姆·德·克勒克( LinkedInGitHub )(最终排行榜第三,附加赛第一)

最终代理有两个主要版本,v8 和 v10,其中 v10 的策略几乎与 v8 完全相同,只是它的速度更快,因为它用图形表示棋盘(我将在后面解释)。

两个代理都有一大组实用函数,允许更快地编写代码,因为这些函数可以在版本之间复制,因为它们的实现保持不变(例如,位置 x 可以播放吗?代理从 x 位置可以到达多少个单元格?位置 x 和 y 之间的距离是多少?集合 s 中离位置 x 最近的位置是什么?).

代码的其余部分由算法组成,以确定最佳行动。这些算法中的大多数过滤可玩的棋步,并将它们传递给另一个算法来打破平局。第一种算法确定我们是否必须在两个或更多区域之间做出决定,并且只传递导致更大区域的移动。然后代理检查我们是否能到达对手,如果不可能,我们可以用填充算法填充剩余的区域。

在所有其他情况下,去棋盘的中心几乎总是最佳的。如果代理将要走到棋盘的中心,它首先检查对手是否也能到达中心。如果可以,那么代理人可以通过稍微向左或向右移动来切断对手,但前提是开始位置在棋盘的边缘,并且切断的区域比对手的区域大。

如果上述特殊情况都没有发生,代理就退回到它的通用洪泛算法,该算法使移动产生它能首先到达的最多的单元。如果对手能和代理同时到达一个单元格,则算作半个单元格。

如果泛洪在几个移动中得到相同的分数,它会将这些移动传递给多光线投射算法,这是一种相当古老的算法(v6 ),它从两个玩家的位置投射光线,并确定哪个移动会产生最大的区域。

v8 和 v10 最大的区别在于填充算法。v8 只从玩家的位置投射单条光线来确定最大可能的区域,而 v10 从网格中组成一个图形。这是通过将网格中的每个位置映射到一个从 0 到 126 的数字来实现的。因为光线投射仍然有用,所以我必须为图中的节点定义一个方向,所以我定义了一个 127×5 的网格,其中 get _ next _ nodes()[node][direction % 6]将为我提供代理在该方向上可以到达的节点。然后,一个相当复杂的转换函数会将网格转换成邻接表。代理现在可以确定图形中的关节点,而不是光线投射。代理现在可以通过在接下来的两个移动中产生最少关节点的移动来填充该区域。这导致任何区域的完美填充。

重要: Maxim 在他的 GitHub 上发布了代码。请务必查看比赛的获胜方案。你甚至可以模拟我和他经纪人之间的游戏!

结束语

这篇博文中讨论的所有代理代码都可以在 GitHub 上获得。我尽了最大努力清理和优化代码,但它肯定还不够完美。因此,我们非常欢迎您提交拉动请求或开放问题!

此外,和往常一样,如果这篇博文中有什么不清楚或者需要进一步澄清的地方,请随时发表评论,或者联系我!如果你对明年的游戏有任何酷的建议,请随时留下评论!

哇,你已经到达这篇博文的结尾了!向你致敬。第三届 AI 大赛明年见;),
张卫

一个简单的 CNN:多图像分类器

原文:https://towardsdatascience.com/a-simple-cnn-multi-image-classifier-31c463324fa?source=collection_archive---------0-----------------------

利用张量流和迁移学习,用卷积神经网络轻松制作一个有标签的图像分类器

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

Source

计算机视觉和神经网络是机器学习技术的新热点。随着神经网络的进步和将图像读取为像素密度数字的能力,许多公司都依赖这种技术来获取更多数据。例如,speed camera 使用计算机视觉来拍摄超速行驶的汽车的牌照,并将牌照号码与已知的数据库进行匹配,以发送罚单。虽然这与目标字符识别比图像分类更相关,但两者都使用计算机视觉和神经网络作为工作基础。

图像分类的一个更现实的例子是脸书标记算法。当你上传一个有人物的相册,并在脸书给他们加标签时,标签算法会分解人物照片的像素位置,并将其存储在数据库中。因为每张图片都有自己独特的像素位置,所以算法可以根据数据库中以前的图片相对容易地识别出谁是谁。当然,该算法可能会不时出错,但你纠正得越多,它就越能识别你的朋友,并在你上传时自动为你标记他们。然而,脸书标签算法是建立在人工智能的基础上的。这意味着标记算法能够基于我们的输入进行学习,并在未来进行更好的分类。

我们不会关注人工智能方面,而是关注制作图像分类算法的最简单方法。我们的模式和脸书的模式之间的唯一区别是,我们不能从它的错误中吸取教训,除非我们修正它。但是,对于一个简单的神经网络项目来说,这就足够了。

由于使用人的照片是不道德的,我们将使用动物来创建我们的模型。我的朋友文森特和我已经就此做了一个项目,所以我会以此为例继续下去。GitHub 链接在最后。

第一步是收集数据。在我看来,这将是该项目的最困难和最烦人的方面。请记住,数据必须有标签。谢天谢地,Kaggle 已经标记了我们可以轻松下载的图片。我们使用的数据集可以在这里找到: animal-10 dataset 。如果数据集未被标注,这可能会非常耗时,因为您必须为每类影像手动创建新的标注。另一种方法是创建新的标签,只将 100 张图片移动到它们适当的标签中,并创建一个类似我们将使用的分类器,并让该机器对图像进行分类。这将导致分类错误,因此您可能希望在每次运行后手动检查,这是耗时的地方。

现在,我们已经将数据集安全地存储在我们的计算机或云中,让我们确保我们有一个训练数据集、一个验证数据集和一个测试数据集。训练数据集将包含全部标记数据的 85–90%。这些数据将被用来训练我们的机器了解我们拥有的不同类型的图像。验证数据集将包含总标记数据的 5-10%。这将测试我们的机器对已知标签数据的表现。测试数据集将包含未标记格式的其余数据。这些测试数据将被用来测试我们的机器对从未见过的数据进行分类的能力。测试数据也可以只包含你从谷歌下载的图片,只要它对你分类的主题有意义。

我们先导入所有需要的库:

import pandas as pd
import numpy as np 
import itertools
import keras
from sklearn import metrics
from sklearn.metrics import confusion_matrix
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img 
from keras.models import Sequential 
from keras import optimizers
from keras.preprocessing import image
from keras.layers import Dropout, Flatten, Dense 
from keras import applications 
from keras.utils.np_utils import to_categorical 
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg
%matplotlib inline
import math 
import datetime
import time

定义尺寸和定位图像:

#Default dimensions we found online
img_width, img_height = 224, 224 

#Create a bottleneck file
top_model_weights_path = ‘bottleneck_fc_model.h5’# loading up our datasets
train_data_dir = ‘data/train’ 
validation_data_dir = ‘data/validation’ 
test_data_dir = ‘data/test’

# number of epochs to train top model 
epochs = 7 #this has been changed after multiple model run 
# batch size used by flow_from_directory and predict_generator 
batch_size = 50 

在这一步中,我们定义图像的尺寸。根据你的图像大小,你可以改变它,但我们发现 224,224 效果最好。然后我们创建了一个瓶颈文件系统。这将用于转换所有的图像像素到他们的数字(numpy 数组)对应,并存储在我们的存储系统中。一旦我们运行这个,它将需要半个小时到几个小时,这取决于分类的数量和每个分类有多少图像。然后我们简单地告诉我们的程序每个图像在我们的存储器中的位置,这样机器就知道哪里是什么了。最后,我们为我们的机器定义时期和批量大小。对于神经网络来说,这是关键的一步。我们发现,这组配对对于我们的机器学习模型来说是最佳的,但同样,这取决于需要调整的图像数量。

导入迁移学习模型 VGG16:

#Loading vgc16 model
**vgg16 = applications.VGG16(include_top=False, weights=’imagenet’)****datagen = ImageDataGenerator(rescale=1\. / 255)** 
#needed to create the bottleneck .npy files

这引入了卷积神经网络的迁移学习方面。迁移学习很方便,因为它带有预制的神经网络和其他必要的组件,否则我们将不得不创建这些组件。迁移学习模式有很多。我特别喜欢 VGG16,因为它只使用了 11 个卷积层,非常容易使用。但是,如果您正在处理较大的图像文件,最好使用更多的层,所以我推荐 resnet50,它包含 50 个卷积层。

对于我们的图像分类器,我们只处理了 6 个分类,因此对这些图像使用迁移学习并没有花费太长时间,但是请记住,图像和分类越多,下一步将花费越长的时间。但是值得庆幸的是,由于您只需要将图像像素转换为数字一次,因此您只需对每个训练、验证和测试执行一次下一步操作——除非您删除或损坏了瓶颈文件。

使用 VGG16 创建权重和特征:

#__this can take an hour and half to run so only run it once. 
#once the npy files have been created, no need to run again. Convert this cell to a code cell to run.__start = datetime.datetime.now()

generator = datagen.flow_from_directory( 
    train_data_dir, 
    target_size=(img_width, img_height), 
    batch_size=batch_size, 
    class_mode=None, 
    shuffle=False) 

nb_train_samples = len(generator.filenames) 
num_classes = len(generator.class_indices) 

predict_size_train = int(math.ceil(nb_train_samples / batch_size)) 

bottleneck_features_train = vgg16.predict_generator(generator, predict_size_train) 

np.save(‘bottleneck_features_train.npy’, bottleneck_features_train)
end= datetime.datetime.now()
elapsed= end-start
print (‘Time: ‘, elapsed)

因为我们正在制作一个简单的图像分类器,所以没有必要改变默认设置。对于我们在上面创建的培训、验证和测试目录,只需按照上面的步骤操作即可。但是,您可以添加不同的功能,如图像旋转、变换、反射和扭曲。

一旦文件被转换并保存到瓶颈文件,我们加载它们并为我们的卷积神经网络做准备。这也是确保所有数据都已经加载到瓶颈文件中的好方法。记住对验证和测试集也重复这个步骤。

为训练数据创建瓶颈文件。(验证和测试步骤相同):

#training data
generator_top = datagen.flow_from_directory( 
   train_data_dir, 
   target_size=(img_width, img_height), 
   batch_size=batch_size, 
   class_mode=’categorical’, 
   shuffle=False) 

nb_train_samples = len(generator_top.filenames) 
num_classes = len(generator_top.class_indices) 

# load the bottleneck features saved earlier 
train_data = np.load(‘bottleneck_features_train.npy’) 

# get the class labels for the training data, in the original order 
train_labels = generator_top.classes 

# convert the training labels to categorical vectors 
train_labels = to_categorical(train_labels, num_classes=num_classes)

创建我们的卷积神经网络代码:

#This is the best model we found. For additional models, check out I_notebook.ipynbstart = datetime.datetime.now()
**model = Sequential()** 
model.add(Flatten(input_shape=train_data.shape[1:])) 
model.add(Dense(100, activation=keras.layers.LeakyReLU(alpha=0.3))) 
model.add(Dropout(0.5)) 
model.add(Dense(50, activation=keras.layers.LeakyReLU(alpha=0.3))) 
model.add(Dropout(0.3)) 
model.add(Dense(num_classes, **activation=’softmax**’))model.compile(**loss=’categorical_crossentropy’**,
   optimizer=optimizers.RMSprop(lr=1e-4),
   metrics=[‘acc’])history = **model.fit**(train_data, train_labels, 
   epochs=7,
   batch_size=batch_size, 
   validation_data=(validation_data, validation_labels))model.save_weights(top_model_weights_path)(eval_loss, eval_accuracy) = model.evaluate( 
    validation_data, validation_labels, batch_size=batch_size,     verbose=1)print(“[INFO] accuracy: {:.2f}%”.format(eval_accuracy * 100)) 
print(“[INFO] Loss: {}”.format(eval_loss)) 
end= datetime.datetime.now()
elapsed= end-start
print (‘Time: ‘, elapsed)

现在我们创建我们的模型。第一步是用 Sequential()初始化模型。之后,我们平坦的数据,并添加我们额外的 3(或更多)隐藏层。这一步是完全可定制的你想要的。我们用不同的退出,隐藏层和激活制作了几个不同的模型。但是由于这是一个带标签的范畴分类,最终的激活必须总是 softmax。对于 loss 来说,最好是分类交叉相关的,但是 model.compile 中的其他内容都可以更改。然后,在我们创建并编译了我们的模型之后,我们用我们前面提到的规范使我们的训练和验证数据适合它。最后,我们创建一个评估步骤,来检查我们的模型训练集相对于验证集的准确性。

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

这是我们的模型,现在训练数据,然后验证它。一个时期是模型在我们整个数据集上训练的次数。批量可以解释为少量服用,训练后再服用一些。在进入下一个时段之前,每个时段必须完成所有批次。用太少的历元训练会导致数据拟合不足,而用太多的历元训练会导致数据拟合过度。你也希望损失尽可能低。下面的图片将显示我们的数据集的准确性和损失

代码为可视化的精度和损失:

#Graphing our training and validation
acc = history.history[‘acc’]
val_acc = history.history[‘val_acc’]
loss = history.history[‘loss’]
val_loss = history.history[‘val_loss’]
epochs = range(len(acc))
plt.plot(epochs, acc, ‘r’, label=’Training acc’)
plt.plot(epochs, val_acc, ‘b’, label=’Validation acc’)
plt.title(‘Training and validation accuracy’)
plt.ylabel(‘accuracy’) 
plt.xlabel(‘epoch’)
plt.legend()
plt.figure()
plt.plot(epochs, loss, ‘r’, label=’Training loss’)
plt.plot(epochs, val_loss, ‘b’, label=’Validation loss’)
plt.title(‘Training and validation loss’)
plt.ylabel(‘loss’) 
plt.xlabel(‘epoch’)
plt.legend()
plt.show()

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

Even though according to this graph, it showed that epoch 3 was the best as that was the point of intersection between accuracy and loss, when we ran the model on 3 epoch, it underperformed. So this graph is not an absolute indicator of how many epoch to run on your model.

下图显示了我们刚刚制造的机器对未知数据的预测能力。注意,它说它在 test_data 上进行测试。准确性是第二个数字。然而,这不是检查我们的机器性能的唯一方法

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

有两种很好的方法可以检验你的机器的预测和分类能力。其中一个是分类度量,另一个是混淆矩阵。

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

为了使用分类度量,我们必须将测试数据转换成不同的 numpy 格式,numpy 数组,以便阅读。这就是第一行代码所做的一切。第二个单元块接收转换后的代码,并通过内置的分类指标运行它,从而给出一个简洁的结果。请注意,除非您在这里手动标记您的类别,否则您将得到 0–5 作为类别,而不是动物。这里重要的因素是精确度和 f1 分数。分数越高,你的模型越好。这里有一个在 medium 上的很棒的博客,解释了这些都是什么。

现在来做一个混淆矩阵。网上有很多关于如何制作大混乱矩阵的教程。我们的是我们在网上找到的一些的变体

#Since our data is in dummy format we put the numpy array into a dataframe and call idxmax axis=1 to return the column
# label of the maximum value thus creating a categorical variable
#Basically, flipping a dummy variable back to it’s categorical variable**categorical_test_labels = pd.DataFrame(test_labels).idxmax(axis=1)
categorical_preds = pd.DataFrame(preds).idxmax(axis=1)**confusion_matrix= confusion_matrix(categorical_test_labels, categorical_preds) #To get better visual of the confusion matrix:def plot_confusion_matrix(cm, classes,
   normalize=False,
   title=’Confusion matrix’,
   cmap=plt.cm.Blues):

#Add Normalization Option
 ‘’’prints pretty confusion metric with normalization option ‘’’
   **if normalize:
     cm = cm.astype(‘float’) / cm.sum(axis=1)[:, np.newaxis]
     print(“Normalized confusion matrix”)
   else:
     print(‘Confusion matrix, without normalization’)**

# print(cm)

   plt.imshow(cm, interpolation=’nearest’, cmap=cmap)
   plt.title(title)
   plt.colorbar()
   tick_marks = np.arange(len(classes))
   plt.xticks(tick_marks, classes, rotation=45)
   plt.yticks(tick_marks, classes)

   fmt = ‘.2f’ if normalize else ‘d’
   thresh = cm.max() / 2.
   for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
      plt.text(j, i, format(cm[i, j], fmt), horizontalalignment=”center”, color=”white” if cm[i, j] > thresh else “black”)

   plt.tight_layout()
   plt.ylabel(‘True label’)
   plt.xlabel(‘Predicted label’) 

我们之前创建的 numpy 数组放在 dataframe 中。混淆矩阵最适合数据帧。具有多个迭代代码的第三单元块纯粹用于彩色视觉效果。唯一重要的代码功能是“if normalize”行,因为它标准化了数据。

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

正如我们在标准化数据中看到的,我们的机器非常擅长对动物进行分类。鸡被误归类为蝴蝶,很可能是因为蝴蝶身上有许多不同类型的图案。此外,蝴蝶也可能因为同样的原因被误归类为蜘蛛。大象和马都是相当大的动物,所以它们的像素分布可能相似。

最后一个阶段是对图像进行测试。下面的单元块将实现这一点:

def read_image(file_path):
   print(“[INFO] loading and preprocessing image…”) 
   image = load_img(file_path, target_size=(224, 224)) 
   image = img_to_array(image) 
   image = np.expand_dims(image, axis=0)
   image /= 255\. 
   return imagedef test_single_image(path):
  animals = [‘butterflies’, ‘chickens’, ‘elephants’, ‘horses’, ‘spiders’, ‘squirells’]
  images = read_image(path)
  time.sleep(.5)
  bt_prediction = vgg16.predict(images) 
  preds = model.predict_proba(bt_prediction)
  for idx, animal, x in zip(range(0,6), animals , preds[0]):
   print(“ID: {}, Label: {} {}%”.format(idx, animal, round(x*100,2) ))
  print(‘Final Decision:’)
  time.sleep(.5)
  for x in range(3):
   print(‘.’*(x+1))
   time.sleep(.2)
  class_predicted = model.predict_classes(bt_prediction)
  class_dictionary = generator_top.class_indices 
  inv_map = {v: k for k, v in class_dictionary.items()} 
  print(“ID: {}, Label: {}”.format(class_predicted[0],  inv_map[class_predicted[0]])) 
  return load_img(path)path = ‘data/test/yourpicturename’test_single_image(path)

第一个 def 函数是让我们的机器知道它必须加载图像,改变大小并将其转换为数组。第二定义函数使用迁移学习的预测模型和迭代函数来帮助正确预测图像。路径是我们定义图像位置的地方,最后 test_single_image 单元块将打印出最终结果,这取决于第二个单元块的预测。对于这一部分,我不会张贴一张图片,以便您可以找到自己的结果。然而,GitHub 链接就在下面,所以请随意下载我们的代码,看看它与您的代码相比如何。

[## 动物图像分类

基于 CNN 的不同类型动物图像分类。-动物图像分类

github.com](https://github.com/imamun93/animal-image-classifications) [## 动物-10

取自谷歌图片的 10 个不同类别的动物图片

www.kaggle.com](https://www.kaggle.com/alessiocorrado99/animals10) [## 准确度、精密度、召回率还是 F1?

当我与希望将数据科学应用到其流程中的组织交谈时,他们经常会问…

towardsdatascience.com](/accuracy-precision-recall-or-f1-331fb37c5cb9)

单词袋模型的简单解释

原文:https://towardsdatascience.com/a-simple-explanation-of-the-bag-of-words-model-b88fc4f4971?source=collection_archive---------5-----------------------

快速、简单地介绍单词袋模型以及如何用 Python 实现它。

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

Photo by Patrick Tomasso on Unsplash

单词袋 (BOW)模型是一种通过计算每个单词出现的次数将任意文本转换成固定长度向量的表示方法。这个过程通常被称为矢量化

我们用一个例子来理解这个。假设我们想要向量化以下内容:

  • 猫坐下了
  • 猫坐在帽子里
  • 戴帽子的猫

我们将每一个都称为文本文档

第一步:确定词汇

我们首先定义我们的词汇表,它是在我们的文档集中找到的所有单词的集合。在上述三个文档中唯一找到的单词是:thecatsatinthehatwith

第二步:计数

为了对我们的文档进行矢量化,我们所要做的就是计算每个单词出现的次数:

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

现在每个文档都有长度为 6 的向量了!

  • 猫坐着 : [1, 1, 1, 0, 0, 0]
  • 猫坐在帽子里
  • 戴帽子的猫 : [2, 1, 0, 0, 1, 1]

请注意,当我们使用 BOW 时,我们丢失了上下文信息,例如,单词在文档中出现的位置。这就像一个字面上的单词包:它只告诉你哪些单词出现在文档中,而不是它们出现在的什么地方。

在 Python 中实现 BOW

既然您已经知道了 BOW 是什么,我猜您可能需要实现它。下面是我的首选方法,它使用了 Keras 的 Tokenizer 类:

运行该代码会给我们带来:

Vocabulary: ['the', 'cat', 'sat', 'hat', 'in', 'with']
[[0\. 1\. 1\. 1\. 0\. 0\. 0.]
 [0\. 2\. 1\. 1\. 1\. 1\. 0.]
 [0\. 2\. 1\. 0\. 1\. 0\. 1.]]

注意,这里的向量长度是 7,而不是 6,因为在开头有额外的0元素。这是一个无关紧要的细节——Keras 储量指数0并且从来不把它分配给任何单词。

BOW 有什么用?

尽管是一个相对基本的模型,BOW 经常被用于自然语言处理任务,如文本分类。它的优势在于它的简单性:它的计算成本很低,有时当定位或上下文信息不相关时,越简单越好。

我已经写了一篇使用 BOW 进行亵渎检测的博文——如果你对 BOW 的实际应用感到好奇,就来看看吧!

最初发表于T5【https://victorzhou.com】

适用于 Github 初学者和其他人的简单 Git 工作流程

原文:https://towardsdatascience.com/a-simple-git-workflow-for-github-beginners-and-everyone-else-87e39b50ee08?source=collection_archive---------10-----------------------

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

成为 Git 大师

当我在我参加的数据分析编码营开始我的第一个小组项目时,我们必须挑选一个“Git 大师”为五个使用 git 和 Github 的没有经验的人协调工作流的想法有点令人畏惧。决定的时候到了,因为我在新兵训练营开始前有一点点使用它的经验,我被任命为团队的“g it 大师”这是我创建的备忘单,用于帮助我的队友将他们的代码分支并合并到 Github 存储库中。如果你已经熟悉 Git ,可以在页面底部找到命令行指令的原始文本备忘单。

如果你正在考虑进入数据科学领域,请查看我在该领域工作 90 天后的感想:

[## 我为什么会涉足数据科学?

我不是一个“数字迷”这是我在数据科学领域头 90 天的反思

towardsdatascience.com](/why-did-i-ever-get-into-data-science-aa69d3c74d19)

对 Git 和 Github 完全陌生?

GitHub 是一个 Git 存储库托管服务的用户界面。 Git 是一个可通过命令行访问的分布式版本控制系统。Git 是根据第二版 GNU 通用公共许可证的条款发布的免费开源软件。

Git 非常棒,因为它有助于跟踪代码的变化,并允许在各种规模的项目上进行协作。使用 Github,我可以与全世界分享我所有的编码项目。Github 有许多独特的特性,可以增强 git 体验,简化协作编码。任何人都可以打开我的用户页面,派生并克隆一个回购协议,然后玩代码。我不是 Git 或 Github 专家,但这是一个简短的指南,可以帮助你在 Github 上开始使用 Git:

创建一个 Github 帐户,如果你愿意的话,下载并安装 Git。这个例子是使用 Windows 10 机器完成的:

在 Github 上创建新的回购:

点击仓库选项卡上的绿色新建按钮。

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

将显示编辑器。

  1. 输入存储库名称。
  2. 选中复选框以使用自述文件初始化此存储库。
  3. 单击创建存储库。您的新回购显示。
  4. 单击绿色的克隆或下载按钮。
  5. 将地址复制到剪贴板。

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

  1. 复制完存储库地址后,切换到您的桌面。
  2. 右键单击并选择 Git Bash Here,在桌面上打开一个终端。终端将显示。
  3. 类型 git 克隆。
  4. 一个文件夹将出现在您的桌面上,它是克隆的存储库的副本。

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

通过克隆回购,您创建了它的本地副本。因为我们在桌面上使用了 Git Bash,所以副本出现在桌面上。现在我们有了本地 repo,我们可以在本地 repo 上添加文件和更新代码,然后使用备忘单中的命令将它推送到 Github!

将文件添加到您的存储库中

将文件添加到 repo 并推送到 Github 很容易。

  1. 打开将存储库克隆到桌面时创建的文件夹。
  2. 创建新的文本文件。
  3. 切换到终端。确保您在正确的目录中!
  4. 使用以下命令将文件推送到 Github,这样就可以将它们添加到存储库的主分支中:
Add the files to the branch:
 $ git add .

Commit the files:
 $ git commit -m "comment"

Add branch and files to the Remote Repo:
 $ git push -u origin main

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

注意新文件出现在 Github 上!

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

更多教程!

这个演练很简短,但是对于任何需要学习更多关于在平台上管理和共享代码的人来说,有很多好的 Git 和 Github 指南和教程。

如果您正在寻找编码项目,请查看我的一些教程:

[## 简单的情感分析为 NLP 初学者和其他人使用 VADER 和 TextBlob

无需训练模型,只需几行代码就能从 Panda 数据帧的文本中提取情感指标!

medium.com](https://medium.com/swlh/simple-sentiment-analysis-for-nlp-beginners-and-everyone-else-using-vader-and-textblob-728da3dbe33d) [## Python 中的仪表盘,适用于初学者和使用 Dash 的其他人

使用 Python 中的 Dash 初学者教程构建一个基本的和高级的仪表板

medium.com](https://medium.com/swlh/dashboards-in-python-for-beginners-and-everyone-else-using-dash-f0a045a86644)

工作流程备忘单

Common console commands: 
 cd - change directory
 mkdir - make directory
 ls - view the files/folders in directory

NOTE: Exit VIM if needed ctrl + c then type :qa! and push enter
NOTE: If file is not in local repo, manually move the file into 
       the correct folder (outside of console)

--------------------------------------------
 Managing your Local Repo
--------------------------------------------
NOTE: If you need to hard reset your local repo to match 
       the remote master use the following commands:
 $ git fetch origin
 $ git reset --hard origin/master

Undo the act of committing, leaving everything else intact:
 $ git reset --soft HEAD^:

Undo the act of committing and everything you'd staged, 
but leave the work tree (your files intact):
 $ git reset HEAD^

Completely undo it, throwing away all uncommitted changes,
 resetting everything to the previous commit:
 $ git reset --hard HEAD^

--------------------------------------------  
 BEGIN WORKFLOW
-------------------------------------------- 
Clone the Repo to local machine:
 $ git clone https://github.com/user_name/repo_name.git

Make sure the local master is up-to-date:
 $ git pull origin main

Create new branch:
 $ git banch branch_name

Move to branch:
 $ git checkout branch_name

Navigate file structure as needed:
 $ ls 
 $ cd folder_name

Add the files to the branch:
 $ git add .

Verify file: 
 $ git status

Commit the files:
 $ git commit -m "comment"

Add branch and files to the Remote Repo:
 $ git push -u origin branch_name

Go to the github website to manage pull request and merge. 

Switch back to local master so you can delete the local branch:
 $ git checkout main

Delete local branch: 
 $ git branch -d branch_name
 OR 
 $ git branch -D branch_name

 If you don't want to go to the website, you can merge your branch 
 to the master locally and push the new master to the remote repo:

Switch back to master branch:
 $ git checkout main

Merge the branch with the local master:
 $ git merge branch_name -m "comment"

Push the local master to the remote master:
 $ git push origin main

Delete local branch: 
 $ git branch -d branch_name
 OR 
 $ git branch -D branch_name

我的 Github

如果你是 Github 的新手,需要一些 repos 来玩,请点击这里查看我的 Github:

[## 弯曲游戏-概述

对游戏、金融、数据分析、技术写作和牛肉干感兴趣。阻止或报告 9 月 10 月 11 月 12 月 1 月…

github.com](https://github.com/bendgame/)

谢谢大家!

—埃里克·克莱本

在 Google Cloud 上部署垃圾邮件检测器的简单指南

原文:https://towardsdatascience.com/a-simple-guide-for-deploying-a-spam-detector-onto-google-cloud-ab1cd7163a21?source=collection_archive---------10-----------------------

谷歌云平台,Flask,分类合一

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

Photo by Samuel Zeller on Unsplash

你好👋!嗯,有很多关于建立各种用途的机器学习模型的指南,我最近看到了一个关于建立垃圾邮件检测器然后使用 Flask 部署它的指南。通过这一点,我决定通过部署到谷歌云平台上更进一步!当然,你也可以使用 Heroku,AWS 等,但这是另一天的另一个主题,我现在只关注 GCP。

项目的简要背景

这是一种机器学习模型,通过对现有的标有“垃圾”或“火腿”的短信集合进行训练,对垃圾短信进行分类。垃圾邮件检测器采用 scikit-learn 的多项式朴素贝叶斯分类器,该分类器基于朴素贝叶斯算法,用于多项式分布数据:

朴素贝叶斯方法是一组基于应用贝叶斯定理的监督学习算法,其“朴素”假设是在给定类变量的值的情况下,每对要素之间的条件独立性。

与更复杂的方法相比,朴素贝叶斯学习器和分类器可以非常快。类别条件特征分布的分离意味着每个分布可以被独立地估计为一维分布。这反过来又有助于缓解维数灾难带来的问题。

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

Flask Logo

同时,Flask 作为 web 框架,通过前端接收用户的输入(HTTP 请求)并实现其预测功能。诞生于 2010 年的 Flask 以大多数标准来看都是一个小框架,小到可以被称为“微框架”。Flask 提高了其源代码的可读性和易理解性。Flask 是一个用 Python 编写的轻量级 Web 框架,它已经成为初创企业最广泛使用的 Python web 框架之一,也是大多数企业快速简单解决方案的完美工具。

Flask 的目标是保持框架的核心小但高度可扩展,从而非常容易和灵活地编写应用程序或扩展,同时使开发人员能够为他们的应用程序选择自己的配置

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

在 Google 云平台上部署

我们将在标准环境中使用谷歌应用引擎。它允许我们“在完全托管的无服务器平台上构建高度可扩展的应用程序”。在继续之前,我将提出一些必要条件或假设:

  1. 我假设您已经安装了 Flask 和虚拟环境中涉及的库(如果没有,将在后面显示)。
  2. 您有一个可以访问谷歌云平台控制台的谷歌账户,并在上面创建了一个新项目。

确保为您的项目启用计费。为了将应用程序部署到 App Engine,需要将计费帐户链接到您的项目

3.已安装 Google Cloud SDK ,按照其说明进行安装。

4.您已经成功地在本地测试了您的应用程序。

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

Project Folder Structure

大致来说,您的主文件夹将具有这种结构,请注意“nlp”是我的虚拟环境,我们将在下面创建 app.yaml、appengine_config.py 和 requirements.txt:

app.yaml

示例 app.yaml 指定了应用程序应该运行的运行时,对于这个项目,它将在 Python 3.7 上运行。对于 Python 2.7,可以参考下面的代码:

Python 2.7 app.yaml

app_engine_config.py

requirements.txt

如果您没有将必要的库安装到虚拟环境中,您可以使用下面的代码。应该首先激活环境,并使用终端、命令提示符等来访问它,以便根据需求安装新的依赖项。

pip install -t lib -r requirements.txt

-t lib: 此标志将库复制到 lib 文件夹中,该文件夹在部署期间上传到 App Engine。

-r requirements.txt: pip 安装 requirements.txt 中的所有内容。

部署

在我们开始之前,最好(可选)更新已安装的云 SDK:

gcloud components update

然后,在根文件夹,我们将使用您的 cmd/终端部署它,代码如下:

gcloud app deploy --project [ID of Project]

或者你也可以在没有项目 ID 的情况下完成!

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

根据您的项目,选择最合适的区域并等待几分钟,它将为您提供一个链接,任何人都可以访问该链接来查看/使用您的 web 应用程序!

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

或者只使用下面的代码:

gcloud app browse --project=
#the link usually is "projectid".appspot.com

结论

瞧啊。GCP 使部署 web 应用程序的过程变得更快、更容易。我希望我可以尝试在不久的将来或其他项目的其他选择。如果有任何问题,请随时联系我!我的网站可以在这里找到:spamdetector.appspot.com

参考

  1. 存储库:https://github.com/georgeblu1/Spam-Detector-Web-App
  2. 用 Python 开发 NLP 模型&用 Flask 逐步部署:https://towardsdatascience . com/develop-a-NLP-Model-in-Python-Deploy-It-with-Flask-Step-Step-744 F3 BDD 7776
  3. 烧瓶框架食谱
  4. 砂箱网开发
  5. Python 机器学习

面向数据科学家的链表简单介绍

原文:https://towardsdatascience.com/a-simple-introduction-of-linked-lists-for-data-scientists-a71f0eb31d87?source=collection_archive---------17-----------------------

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

Image by WILLGARD from Pixabay

算法面试

或者说,什么是链表,为什么我需要了解它们?

算法和数据结构是数据科学不可或缺的一部分。虽然我们大多数数据科学家在学习时没有上过适当的算法课程,但它们仍然很重要。

许多公司在招聘数据科学家的面试过程中会询问数据结构和算法。

现在,许多人在这里问的问题是,问一个数据科学家这样的问题有什么用。 我喜欢这样描述,一个数据结构问题可以被认为是一个编码能力测试。

我们都在人生的不同阶段进行过能力倾向测试,虽然它们不是判断一个人的完美代理,但几乎没有什么是真的。那么,为什么没有一个标准的算法测试来判断人的编码能力。

但我们不要自欺欺人,他们需要像你的数据科学面试一样的热情,因此,你可能需要花一些时间来研究算法和数据结构问题。

这篇文章是关于快速跟踪这项研究,并以一种容易理解的方式为数据科学家解释链表概念。

什么是链表?

链表只是一个非常简单的数据结构,表示一系列节点。

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

每个节点只是一个包含值和指向下一个节点的指针的对象。例如,在这里的例子中,我们有一个包含数据 12 并指向下一个节点 99 的节点。然后 99 指向节点 37 等等,直到我们遇到一个空节点。

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

也有双向链表,其中每个节点包含下一个和前一个节点的地址。

但是我们为什么需要链表呢?

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

我们都使用过 Python 中的列表。 但是你想过列表数据结构的插入时间吗?

假设我们需要在列表的开头插入一个元素。在 python 列表的开头插入或删除元素需要一个 O(n) 复制操作。

如果我们面临这样的问题,有很多这样的插入,我们需要一个数据结构,实际上在常数 O(1)时间内做插入,怎么办?

有很多你可以想到的链表的实际应用。人们可以使用双向链表来实现一个系统,其中只需要前一个和下一个节点的位置。 例如 chrome 浏览器中的上一页和下一页功能。或者照片编辑器中的上一张和下一张照片。

使用链表的另一个好处是,我们不需要对链表有连续的空间要求,即节点可以驻留在内存中的任何地方,而对于像数组这样的数据结构,节点需要分配一个内存序列。

我们如何在 Python 中创建一个链表?

我们首先定义一个可以用来创建单个节点的类。

class Node:
    def __init__(self,val):
        self.val = val
        self.next = None

然后,我们使用这个类对象创建多个节点,并将它们连接在一起形成一个链表。

head = Node(12)
a = Node(99)
b = Node(37)head.next = a
a.next = b

我们有链表,从head开始。在大多数情况下,我们只保留变量head来定义我们的链表,因为它包含了我们访问整个链表所需的所有信息。

链接列表的常见操作或面试问题

1.插入新节点

在开始,我们说我们可以在一个常数 O(1)时间内在链表的开始插入一个元素。让我们看看我们能做些什么。

def insert(head,val):
    new_head = Node(val)
    new_head.next = head
    return new_head

因此,给定节点的头,我们只需创建一个new_head对象,并将其指针设置为指向链表的前一个头。我们只需创建一个新节点,并更新一个指针。

2。打印/遍历链表

打印链表的元素非常简单。我们只是以迭代的方式遍历链表,直到遇到 None 节点(或者末尾)。

def print(head):
    while head:
        print(head.val)
        head = head.next

3.反转单向链表

这更像是链表上一个非常常见的面试问题。如果给你一个链表,你能在 O(n)时间内反转这个链表吗?

**For Example:
Input:** 1->2->3->4->5->NULL
**Output:** 5->4->3->2->1->NULL

那么我们该如何应对呢?

我们从遍历链表开始,在将指针移动到下一个节点时反转指针方向,直到有下一个节点。

def reverseList(head):
    newhead = None
    while head:
        tmp = head.next
        head.next = newhead
        newhead = head
        head = tmp
    return newhead

结论

在这篇帖子里,我谈到了链表及其实现。

链表是数据科学面试中一些最常见问题的基础,很好地理解这些问题可能会帮助你找到理想的工作。

虽然您可以在不学习它们的情况下在数据科学中走得更远,但您可以为了一点乐趣而学习它们,也许是为了提高您的编程技能。

这里有一个小的笔记本给你,我把所有这些小概念都放在里面了。

我把这个问题留给你自己解决— 实现一个函数来检查一个链表是否是回文。

如果你想学习算法和数据结构,也可以看看我在系列的其他帖子。

继续学习

如果你想了解更多关于算法和数据结构的知识,我强烈推荐 UCSanDiego在 Coursera 上的 算法专门化。

谢谢你的阅读。将来我也会写更多初学者友好的帖子。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

K-最近邻算法简介

原文:https://towardsdatascience.com/a-simple-introduction-to-k-nearest-neighbors-algorithm-b3519ed98e?source=collection_archive---------0-----------------------

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

Photo by h heyerlein on Unsplash

什么是 KNN?

k 最近邻是一种简单的算法,它存储所有可用的案例,并基于相似性度量对新数据或案例进行分类。它主要用于根据相邻数据点的分类方式对其进行分类。

让我们以下面的葡萄酒为例。两种化学成分叫做芦丁和杨梅素。考虑用红葡萄酒和白葡萄酒这两个数据点来测量芦丁和杨梅素的含量。他们已经测试了葡萄酒中芸香素和杨梅黄酮的含量,并确定了它们在图表中的位置。

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

KNN 中的“k”是一个参数,指的是在多数投票过程中包括的最近邻的数量。

假设,如果我们在数据集中添加一杯新的葡萄酒。我们想知道这种新酒是红的还是白的?

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

所以,我们需要找出这种情况下的邻居是谁。假设 k = 5,并且新的数据点被来自其五个邻居的多数投票分类,并且新点将被分类为红色,因为五个邻居中有四个是红色的。

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

KNN 算法中 k 的值应该如何选择?

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

KNN 算法中的 K’是基于特征相似性的。选择正确的 K 值是一个被称为参数调整的过程,并且对于更好的准确性是重要的。求 k 的值并不容易。

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

关于“K”取值的几点想法

  1. 没有一个结构化的方法可以找到“K”的最佳值。我们需要通过反复试验来找出不同的值,并假设训练数据是未知的。
  2. 选择较小的 K 值可能会产生噪声,并对结果产生较大影响。

3)K 值越大,决策边界越平滑,意味着方差越低,但偏差越大。此外,计算成本很高。

4)选择 K 的另一种方法是通过交叉验证。从训练数据集中选择交叉验证数据集的一种方法。从训练数据集中取出一小部分,称之为验证数据集,然后使用它来评估 K 的不同可能值。这样,我们将使用 K 等于 1,K 等于 2,K 等于 3 来预测验证集中每个实例的标签…然后我们看看什么样的 K 值能让我们在验证集上获得最佳性能,然后我们可以取这个值,并将其用作我们算法的最终设置,这样我们就能最小化验证误差。

5)一般来说,实践中,选择 k 的值是 k = sqrt(N) 其中 N 代表你的训练数据集中的个样本数。

6)尽量保持 k 值为奇数,以避免两类数据之间的混淆

KNN 算法是如何工作的?

在分类设置中,K-最近邻算法本质上归结为在与给定的“看不见的”观察最相似的 K 个实例之间形成多数投票。相似性根据两个数据点之间的距离度量来定义。一种流行的方法是欧几里德距离法

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

其他方法有曼哈顿、闵可夫斯基和海明距离方法。对于分类变量,必须使用汉明距离。

我们举个小例子。年龄 vs 贷款。

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

我们需要预测安德鲁的违约状态(是或否)。

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

计算所有数据点的欧几里德距离。

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

K=5 时,五个最近邻居中有两个 Default=N,三个 Default=Y。基于 5 分中的 3 分的主要相似性,我们可以说 Andrew 的默认状态是“Y”。

K-NN 也是一个懒惰的学习者,因为它不从训练数据中学习判别函数,而是“记忆”训练数据集。

KNN 的优点

  1. 易于实施
  2. 灵活选择功能/距离
  3. 自然处理多类案件
  4. 在实践中可以做得很好,有足够的代表性数据

KNN 的缺点

  1. 需要确定参数 K 的值(最近邻的数量)
  2. 计算成本相当高,因为我们需要计算每个查询实例到所有训练样本的距离。
  3. 数据存储
  4. 必须知道我们有一个有意义的距离函数。

参考:

https://stack overflow . com/questions/11568897/value-of-k-in-k-nearest-neighbor-algorithm

张量流的简单介绍

原文:https://towardsdatascience.com/a-simple-introduction-to-tensorflow-d992eb2e3dbb?source=collection_archive---------20-----------------------

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

Don’t lie, this was you at some point

根据我的经验,学习任何对计算机科学有用的东西都落在了理论和实践的奇怪交叉点上。我们很容易忽略一些我们编码的东西的深度。机器学习将这一点发挥到了极致,如今每个人都想成为机器学习工程师。(包括我自己)

《统计学习要素》是一本很棒的书。如果你能熬过这一关,你会知道很多,但如果你不能将其中任何一点付诸实践,那就没什么意义了。TensorFlow 是一个用于构建、训练和部署机器学习模型的框架。Keras 是一个构建在 TensorFlow 之上的包装器,使它更容易访问,更容易使用,也更干净。

下面的代码块相当于 TensorFlow 中的“Hello World”。尽管这是使用 TensorFlow 的第一步,但这里还有很多东西要解开。所以让我们开始吧。

Full Code for this article

Python 令人惊奇的一点是,少量代码中可以包含如此多的内容。跟随教程并让代码做事情是非常容易的。对某些人来说,这就够了。其他人可能想知道每一行或每一个函数的作用。我属于后一类。

数据

import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()

MNIST 数据集由手写数字组成;60000 幅训练图像和 10000 幅测试图像。一个训练集是一个集合,在其中我们被给予我们正在观察的特征的结果。特征是可以测量的物体的特征。一个更熟悉的特性术语可能是变量或属性。

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

Digits in the MNIST Dataset

通过使用训练集中对象的特征,我们的模型将学习,然后对新的相似对象进行预测。

测试集是我们将(你猜对了)用来测试通过使用训练集创建的模型。

在上面的几行中,我们告诉 TensorFlow 我们想要 MNIST 数据集中的文件,然后我们将数据加载到训练和测试变量中。

print(x_train.shape)(60000, 28, 28)

我们已经知道我们的训练集有 60,000 张图片。28,28 指的是每个图像的尺寸,28 像素乘 28 像素。因此,让我们进一步探索这些数据。

import matplotlib.pyplot as plt
%matplotlib inlineplt.figure()
plt.imshow(x_train[5])
plt.colorbar()
plt.grid(False)
plt.show()

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

Result of plt.imshow(x_train[5])

对于图像的任何给定像素,分配给该像素的值可以在 0 到 255 之间。这就引出了下一行代码:

x_train, x_test **=** x_train **/** 255.0, x_test **/** 255.0

它标准化了我们训练和测试集中的所有值。

好了,酷的时候到了:

模型

model = tf.keras.models.Sequential([
 tf.keras.layers.Flatten(input_shape=(28, 28)),
 tf.keras.layers.Dense(512, activation=tf.nn.relu),
 tf.keras.layers.Dropout(0.2),
 tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])model.compile(optimizer=’adam’,
 loss=’sparse_categorical_crossentropy’,
 metrics=[‘accuracy’])

我们的第一行指定了我们正在使用的模型:

tf.keras.models.Sequential

顺序模型可以被认为是一堆煎饼。每一层都是煎饼。因为我们正在努力成为高级厨师,制作机器学习模型,所以我们的煎饼有馅料。馅料即使不比它们的成分更好,也尽量做得一样好。我们的原料是我们的训练装备。
第一层之后的层可以自动识别出模型的输入形状是连续的,这就是为什么只做一次的原因。

tf.keras.layers.Flatten(input_shape**=**(28, 28)),

我们现在把输入的图像“展平”成一个 2D 数组。输入形状是输入到图层中的图像的尺寸。可以把这看作是为模型重新格式化图像。

tf.keras.layers.Dense(512, activation**=**tf.nn.relu)

这就产生了一个紧密连接的神经层。层中的每个输入节点都连接到一个输出节点。它接收来自前一层的输入,这就是为什么它是密集。512 表示输出空间的维数,乍一看,这对大多数人来说意义不大。这意味着什么的答案是比这篇文章更深入的神经网络。
一个激活函数接受网络中一个节点的输入,并生成将被传递到下一层的输出。如果没有非线性激活函数,这将只是一个线性回归模型。这里使用的激活函数类型是 RELU 或整流线性单元,这是最常用的激活函数之一。

tf.keras.layers.Dropout(0.2),

丢弃层是一种正则化技术,其中随机选择的神经元在训练中被忽略。这里我们有一个 20%的比率集,它将在下一个训练周期中丢弃每五个输入中的一个。

tf.keras.layers.Dense(10, activation**=**tf.nn.softmax)

与上面的 RELU 层类似,这一层使用了一个 Softmax 激活函数。Softmax 激活函数的输出类似于分类概率分布,因此它表示类为真的概率。

model.compile(optimizer**=**'adam',
              loss**=**'sparse_categorical_crossentropy',
              metrics**=**['accuracy'])

现在我们编译这个模型。
首先,亚当到底是谁?不是一个人。显然它是从“自适应矩估计”中推导出来的。应该是一个叫亚当的人想出来的,应该能写出更好的段落。
无论如何,优化器确实做了它听起来做的事情。Adam 优化算法用于根据训练数据更新网络权重。
损失函数用于衡量预测值和实际值之间的差异。目标是最小化损失函数。

结果

model.fit(x_train, y_train, epochs**=**5)
model.evaluate(x_test, y_test)

最后,我们拟合和评估我们的模型。需要注意的是,一个纪元与一次迭代不是一回事。历元是训练数据的完整传递。让一个模型运行太少的时期,在性能方面会有很多不足之处。让一个模型运行太多的时期会有开始“记住”它可能想要的输出的风险,因此会损害它的准确性。

这个模型的训练无论如何都不是很好,但这只是来自 TensorFlow 教程。

model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)Epoch 1/5
60000/60000 [==============================]60000/60000 [==============================] - 8s 126us/step - loss: 9.9728 - acc: 0.3813

Epoch 2/5
60000/60000 [==============================]60000/60000 [==============================] - 8s 127us/step - loss: 10.1151 - acc: 0.3724

Epoch 3/5
60000/60000 [==============================]60000/60000 [==============================] - 8s 127us/step - loss: 10.0101 - acc: 0.3789

Epoch 4/5
60000/60000 [==============================]60000/60000 [==============================] - 8s 126us/step - loss: 10.0149 - acc: 0.3786

Epoch 5/5
60000/60000 [==============================]60000/60000 [==============================] - 8s 127us/step - loss: 10.0893 - acc: 0.3740

10000/10000 [==============================]10000/10000 [==============================] - 0s 32us/step[10.388112817382812, 0.3555]

现在你知道了!首次尝试 TensorFlow。虽然它只有几行代码,但还有很多要解开,但这将变成一本书。如果你读了所有这些,我希望你学到了一些东西!

一个简单的,外行人介绍人工智能

原文:https://towardsdatascience.com/a-simple-layman-introduction-to-ai-bcf793be7b4a?source=collection_archive---------28-----------------------

人工智能(AI)是什么,为什么要关心?

你一定听说过艾。那么什么是“人工智能(AI)”。为了理解,我们首先需要理解什么是计算机。

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

“计算机”这个词的意思是会“计算”的人或东西。多年前,在计算机出现之前,进行计算的人被称为计算机。现在,计算机可以根据我们的指令进行计算、数据处理或控制与计算机相连的设备。人类可以做所有这些事情,但计算机可以做得更快。计算机每秒可以处理超过 20-30 亿次交易,而我们却几乎不能。如果我们改变时间尺度,这种差异是明显的。如果计算机需要一秒钟来做一个复杂的计算,保持相同的速度比,人类需要 63 年才能完成同样的计算。此外,从长远来看,与人类相比,计算机要便宜得多。

如果你想在 10,000 个文档中找到包含“AI”这个词的文档,或者创建同一文档的 20 个副本,计算机可以非常快地完成。因此,计算机非常擅长计算、存储和整理数据,并在大量数据中找到相关信息。有了这些技能,计算机变得无处不在,并且已经改变了世界。

然而,有许多问题是计算机无法处理的。我们已经说过,如果我们能告诉计算机做什么,它就能做到。但是,有些问题,很难说该怎么办。

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

举个例子,我们来考虑一下开车。还记得你是怎么学会开车的吗?有人写下在所有情况下该怎么做了吗?如果你认为你能做到,试着写如何开车。你会发现这几乎是不可能的。这种情况太多了。相反,我们通过尝试和获得反馈来学习。

很多需要决策、复杂思考或智力的问题都有相同的表现。人工智能是一种可以解决这类问题的技术。你不必告诉 AI 做什么。相反,你必须给出很多例子来说明什么是对的,什么是错的,技术能够从中学习,就像人类一样。

当人工智能学会如何解决一个问题时,它可以更快地解决它,一次又一次。例如,它可以识别声音,找到图片中的内容,诊断疾病,检测欺诈行为。这些事情不能自动化,因为人们不能告诉计算机如何去做。人工智能比人类更快、更便宜地完成这些任务。

例如,假设你计划去日本旅行,但你会发现大部分细节都是用日语写的。你可以去谷歌翻译器(https://translate.google.com/)翻译信息。几年前,要做同样的事,要么你得找个懂日语的人,要么雇个翻译。然而,现在谷歌有能力免费给你。这就是 AI 的力量之一。

在过去的几年里,对于一些问题,人工智能已经接近超越人类的表现。著名的例子发生在 1997 年,当时国际象棋计算机“深蓝”打败了国际象棋世界冠军。其他例子还有 Alpha Go 击败世界围棋冠军,IBM Watson 击败自然语言问答比赛 jeopardy 的冠军。

这些例子来自游戏。现实世界中的例子包括自动驾驶汽车、谷歌照片搜索、语言翻译和疾病诊断。AI 正在接管大量用例。它不再只是数百万公司手中的工具。例如,大约一年前,一名青少年编写的人工智能程序帮助推翻了 375000 多张停车罚单。IBM 正试图将他们的沃森人工智能引擎应用到健康领域,如果成功,它可能会让每个人以很少的成本获得高质量的医疗建议。

此外,我们每天通过使用谷歌搜索或脸书等应用程序与人工智能互动。比如,麦肯锡估计,在未来 10—15 年内,约 14%的现有工作将实现自动化。

人工智能或我们生活的影响将比上述例子所暗示的更加广泛。让我们以自动驾驶汽车为例。让我们检查一些不明显的影响。如果大多数汽车都是自动驾驶的,这将减少大多数事故,因为如果发生一起事故,所有的汽车都会从事故中吸取教训。作为一个单独的车队,汽车将能够开得更快,从而大大减少交通流量。大部分停车位都可以被释放出来,因为你可以下车,并要求汽车停放。汽车看起来会很不一样。你可以在车里吃东西、睡觉或看电视。交通警察、保险和许多相关服务可能不需要。

然而,并非所有的影响都是有利的。一些工作将被取代。人们将不得不学习新技能。政府必须帮助人们转换工作。然而,人工智能并不意味着它们将永远取代人类。更常见的是,人工智能将帮助人类做出更好的决定,更有效地做事,并接管他们工作中重复的部分。

很可能你至少看过一部有杀手级 AI 的电影。事实上,这是可能的,尽管我们可能需要 50-100 年才能实现这种人工智能。例如,一个人可以从 2-3 个例子中学习,而人工智能需要数十亿个。

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

最后,在对人工智能做出判断之前,我们需要了解当前的低效率。例如,世界上许多人无法接触到顶级专业人士,如医生、教师、设计师和律师。因此,每天都有许多人死亡。人工智能有可能使专业知识无处不在,并每天拯救许多生命。这意味着不作为也要付出代价。否定 AI,让人们死亡或处于劣势,公平吗?我们必须衡量积极影响和消极影响。

这意味着我们所知道的世界正在快速变化。我们的孩子将生活在一个不同的世界,做非常不同的工作。他们面临的挑战将会非常不同。然而,我充满希望,人类已经适应了许多环境和技术的变化,我们也将适应这种变化。

解决普特南竞赛数学问题的简单蒙特卡罗模拟

原文:https://towardsdatascience.com/a-simple-monte-carlo-simulation-to-solve-a-putnam-competition-math-problem-28545df6562d?source=collection_archive---------19-----------------------

Python 中蒙特卡罗方法综述

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

Photo by Jonathan Petersson on Unsplash

介绍

高赌注赌博和高速赛车有两个共同点——高度的不确定性和蒙特卡洛城。这两者之间的联系导致了术语“蒙特卡罗模拟”的使用,该术语用于使用统计抽样来预测包含不确定性的过程的各种结果的概率的计算方法。迷茫?放心吧!我们将看看使用 Python 设计和执行一个简单的蒙特卡罗模拟。

当我的一个朋友挑战我解决久负盛名的普特南竞赛中的一个问题时,我通常无聊的火车通勤变得令人兴奋——这是一个甚至困扰最聪明的数学本科生的测试。

问题如下(转述):

如果你在一个球体上随机选择 4 个点并把它们连接起来,那么得到的四面体包含球体中心的概率是多少?

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

现在,通过应用一些几何和概率的概念来确定精确的解是完全可能的。我希望你们中的数学天才在你读完这句话之前就已经准备好答案了。对于那些不能理解的人(像我一样),YouTube 上 3Blue1Brown 的一个视频提供了一个关于分析解决方案的非常优雅的解释。

然而,问题中的“随机”一词在我的脑海中引发了另一种思路,最终导致了我将要提出的解决方案。我考虑了通过随机抽样获得答案的可能性。这个想法很简单——抽取大量四面体的随机样本,并计算考虑所有这些样本的概率。

该算法

模拟的大致算法如下:

  1. 将已知半径的球面定义为样本空间。
  2. 将合成概率定义为 num/den,其中 num=0,den=1。
  3. 从样本空间中绘制球体内部四面体的一个样本。
  4. 确定中心是否位于四面体内部。
  5. 分别基于当前试验的成功或失败,通过在 num 上加 1 或 0,并在任何情况下在 den 上加 1,计算得到的概率。
  6. 重复步骤 3 至 5,选择指定数量的随机样本。
  7. 显示结果概率。

代码

我们将一步一步地浏览代码,并详细检查每一步。

步骤 1:导入所需的模块

首先,我们在 Python 中导入所需的模块——即 ScipyMatplotlibScipy 有一个允许生成随机数的子模块。

import scipy as sci
import matplotlib.pyplot as plt

步骤 2:定义样本空间

下一步是创建一个由一定数量的点组成的样本空间。对于这个例子,让样本空间在半径为 1 单位的球体表面上有 10,000 个点

我们如何确保样本空间上的点位于球面上?三个简单的步骤:

  1. 使用sci.random.rand(1,3) *选择任意随机 3D 矢量。*这将产生一个以 0.5 为中心的三维矢量,每个坐标的值在 0 到 1 之间。
  2. 从每个坐标中减去 0.5,使其以 0 为中心。
  3. 计算向量的范数(或大小)并将向量除以其范数,确保其成为单位向量**。任何单位矢量都必然位于半径为 1 的球面上。**

为了安全起见,可以添加一个 if 条件,以确保范数等于 0 或大于 1 的向量不会经历这种变换。

This animation was created using matplotlib; the code for this is not given in the article. It is merely used for the purpose of representation of under-the-hood computations.

points=10000 #Number of points 
x=sci.zeros((points,3)) #To store x-coordinates of sample points
y=sci.zeros((points,3)) #To store y-coordinates of sample pointsfor i in range(points):
    vector=sci.random.rand(1,3)-0.5
    if(sci.linalg.norm(vector)!=0 and sci.linalg.norm(vector)<=1.0):
        x[i,:]=vector
        y[i,:]=x[i,:]/sci.linalg.norm(x[i,:])

为了绝对确保样本空间中的所有点都位于球体表面,我们可以添加另一个检查点。****

我们计算样本空间中向量的实际范数和期望范数(等于球体的半径;这里 1)并将其与一个公差(任意定义的;这里是 1×10⁻ ⁰).与所需规范不匹配的规范存储在danger_array中。如果danger_array的大小是 0(也就是说,不存在不需要的规范),那么我们显示“全部清除”消息并继续前进。

y_norms=sci.zeros(points) #Array to store norms of sample vectorsfor i in range(points):
    y_norms[i]=sci.linalg.norm(y[i,:])
    tol=1e-10 #Tolerance
    norm_diff=abs(y_norms-1) #Diff. between actual and desired norm
    danger_array=y_norms[norm_diff>tol]if(len(danger_array)==0): 
    print("All Clear")
else:
    print("Danger")

步骤 3:创建函数来确定中心是否位于四面体内部

一旦所有检查都通过了,我们就进入问题的核心——确定球体的中心是否位于随机四面体中。这可以通过使用两个函数来简化。

第一个检查球体的中心和四面体的第四个顶点是否位于由四面体的其余三个顶点形成的平面的同一侧。

第二个为四面体的所有四个面调用第一个函数,并推断中心是否位于四面体内部。

为了公式化CheckSide函数,我们依赖于以下线性代数原理:

  • 两个向量的叉积给出一个垂直于两个向量形成的平面的向量。****
  • 两个矢量的点积给出了一个矢量在另一个方向上的分量的大小。如果分量的方向与第二个向量相反,那么点积就是负的。****

我们使用第一个原理来寻找由任意三个顶点形成的平面的法线。

接下来,我们找到法线和一个向量的点积,该向量将第四个顶点与三个顶点中的任何一个连接起来——这个点积的符号被存储。

最后,我们找到法线和连接球体中心和三个顶点中的任何一个的向量的点积——将该点积的符号与前一个进行比较,如果它们匹配,则可以得出结论,第四个顶点和中心位于由剩余三个顶点形成的平面的同侧**。**

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

This schematic will make it easier for you to visualize the application of the two principles

def CheckSide(vertices,point):
    t1,t2,t3,t4=vertices
    p=point
    side_1=t2-t1
    side_2=t3-t1
    normal=sci.cross(side_1,side_2) ref_vector=t4-t1
    ref_sign=sci.dot(normal,ref_vector) point_vector=p-t1
    point_sign=sci.dot(normal,point_vector) if(sci.sign(ref_sign)==sci.sign(point_sign)):
        return 1
    else:
        return 0

如果我们将CheckSide函数应用于一个四面体的所有四个面,我们将能够准确地推断出中心是否位于其中。因此,我们定义了一个新函数CheckTetrahedron ,它调用了CheckSide 函数四次。

在每一次函数调用之间,我们的顶点数组滚动一个,这样CheckSide 函数在下一次调用时会在一个新的面上工作。

最后,将所有四个CheckSide 调用返回的值相加,如果它们等于 4 ,则断定中心位于四面体内部;如果没有,它就在外面。

def CheckTetrahedron(vertices,point):
    vert=sci.copy(vertices)
    check_1=CheckSide(vert,point) vert=sci.roll(vert,1,axis=0)
    check_2=CheckSide(vert,point) vert=sci.roll(vert,1,axis=0)
    check_3=CheckSide(vert,point) vert=sci.roll(vert,1,axis=0)
    check_4=CheckSide(vert,point) sum_check=check_1+check_2+check_3+check_4 if(sum_check==4.):
        return 1
    else:
        return 0

步骤 4:初始化

现在我们已经定义了所有必需的函数,是时候开始实际运行了。在开始运行之前,我们需要初始化一些参数,以便运行和绘图。

数组check_point将存储来表示每次迭代的成功失败**。我们将创建一个数组来存储每次迭代的值,而不是只存储结果概率的一个值,这样我们就可以绘制一条曲线来显示概率随迭代次数的变化。**

centre=[0,0,0]
number_of_samples=10000
sample_span=sci.arange(0,number_of_samples,1)
check_point=sci.zeros(number_of_samples) 
prob=sci.zeros(number_of_samples)

跑步

是时候运行模拟了!在每次迭代中,我们做以下三件事:

  1. 从样本空间中随机挑选 4 个不同的点。
  2. CheckTetrahedron 函数应用于这 4 个点和中心,以确定中心是否位于这 4 个点形成的四面体中。
  3. 根据试验的成功或失败,在check_point 中分别存储 1 或 0,并更新prob 数组中的合成概率值。

This animation was created using matplotlib; the code for this is not given in the article. It is merely used for the purpose of representation of under-the-hood computations.

for i in range(number_of_samples):
    indices=sci.random.randint(0,points,4)
    vertex_list=y[indices]
    check_point[i]=CheckTetrahedron(vertex_list,centroid)
    prob[i]=len(check_point[check_point==1.])/(i+1)

第六步:绘图

最后,在给定迭代次数下运行模拟后,绘制结果并找出结果概率的时间到了。我们给情节添加了一些花里胡哨的东西,让它看起来更有吸引力,同时也确保它清晰地传达了所有需要的信息。

#Plot blank figure
plt.figure(figsize=(15,10))#Plot resultant probability from simulation
plt.plot(sample_span,prob,color="navy",linestyle="-",label="Resultant probability from simulation")#Plot resultant probability from analytical solution
plt.plot(sample_span,[0.125]*len(sample_span),color="red",linestyle="-",label="Actual resultant probability from analytical solution (0.125)")#Plot value of final resultant probability in text
plt.text(sample_span[int(number_of_samples/2)],0.05,f"The final probability is {prob[-1]:.4f}",fontsize=16)#Display axis labels
plt.xlabel("Number of iterations",fontsize=14)
plt.ylabel("Probability",fontsize=14)#Display legend
plt.legend(loc="upper right",fontsize=14)#Display title of the plot
plt.title("Variation of resultant probability with increase in the number of iterations",fontsize=14)

最终的剧情如下。从图的性质来看,很明显随着迭代次数的上升,概率收敛到真值(即解析解)。****

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

Plot generated by matplotlib detailing the variation of probability with the number of iterations

总结想法

由于方法中相关的随机性,你的模拟可能无法在与我的模拟相同的迭代次数内收敛到真实值。在这种情况下,您可以不断增加迭代次数,直到您的解收敛到真实值。

解析解是 1/80.1250 ,蒙特卡罗模拟收敛到一个值 0.1248,,这个值足够接近。我们通过模拟从随机性中创造了一种明显的秩序——重复随机采样可以导致单一收敛解的事实令人震惊。这种方法可能看起来不优雅——几乎就像对计算能力的野蛮使用——但它非常有效,确实给出了准确的答案。

代码已经被记录在一个 Jupyter 笔记本中,可以在线查看。

我希望我已经清楚地解释了方法和代码。欢迎您在评论中做出回应,提出问题或提供您可能有的任何建议。

你也可以在 Twitter 上关注我。

一个简单的 Python 脚本来记录 SQLite 数据库

原文:https://towardsdatascience.com/a-simple-python-script-to-document-the-sqlite-databases-7932aa462cd8?source=collection_archive---------18-----------------------

自动生成降价文件以记录 SQLite 数据库

当我使用关系数据库时,这个问题一直困扰着我:文档。实体关系图是标准的,但是当列名不是自解释的或者模式变得太大而无法处理时,它就没有用了。 SchemaSpy 是一个开源工具,可以自动生成 ER 图,但它为用户提供了接近零的灵活性来增强文档。

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

SchemaSpy demo

对于小型数据集,SchemaSpy 可能是多余的。为了使数据集可用于协作,很好地记录每一列就足够了。我选择 markdown 作为这项工作的工具。事不宜迟,让我们看看解决方案是什么样子的。

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

After executing the script on the left, we obtain a documentation template on the right.

该脚本检索所有表和相应的列名。我们需要做的就是打开 markdown 文件,并填写每个字段的描述。

你可以在这里下载奇努克数据库并在你的电脑上运行演示。现在终于轮到我的食谱了。尽情享受,随心所欲地调节它:-)

sqlite_doc_template.py

你知道任何其他好的方法来记录数据库(SQL,NoSQL,图形数据库等)。)?请在下面评论或给我留言!

探索性数据分析的一个简单技巧

原文:https://towardsdatascience.com/a-simple-trick-for-exploratory-data-analysis-35f2fa05764b?source=collection_archive---------27-----------------------

如果您很难理解您的数据,您可以尝试使用这些超级基础的数据分析工具,例如 python、SQL 和 excel 数据透视表。最终的结果是类似仪表板的表格,使您能够通过切片和切块来挖掘可操作的洞察力。

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

那么首先要做什么呢?当然,获取数据。

本文中使用的数据源是来自 UCI 机器学习库的一个银行机构的直接营销活动(大约#41K 记录)。 然后,用 pandas 把 CSV 文件读入 DataFrame。
~https://archive.ics.uci.edu/ml/datasets/Bank+Marketing

import pandas as pd
bank_cust_df = pd.read_csv('../dat/bank-additional-full.csv', sep = ',')
bank_cust_df.head(10)

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

First 10 rows of bank_cust_df

根据数据集描述,我们知道银行客户数据与基于电话的电话营销活动有关,并且与定期存款的预订 的结果有关。(出于演示目的,我将仅使用人口统计相关数据,并跳过下面展示中的数据清理步骤。)

+---------------+--------------------------------------------+
| Features Name | Features Description                       |
+---------------+--------------------------------------------+
| age           | numeric                                    |
| job           | type of job (blue-collar, entrepreneur...) |
| marital       | marital status (married, singe...)         |
| education     | education (high school,university...)      |
| default       | has credit in default? (Y/N)               |
| housing       | has housing loan? (Y/N)                    |
| loan          | has personal loan? (Y/N)                   |
**| y             | has subscribed a term deposit?  (Y/N)      |**
+---------------+--------------------------------------------+

接下来,我们需要隔离必要的列,并了解数据的样子。

使用 SQL 将数据汇总成汇总格式

# pandasql needed to run SQL with the pandas DataFrame
# [https://pypi.org/project/pandasql/](https://pypi.org/project/pandasql/)from pandasql import sqldf
pysqldf = lambda q: sqldf(q, globals())

聚合字段的基本思想是创建您想要浏览的字段的汇总表。例如,下面的代码将婚姻状况和教育与婚姻状况计数相加。

sql = """
select 
--==================
-- Category Features
--==================
job
,education
,count(*) as cnt
--=============================
-- Summarized Category Features
--=============================
,sum(case when marital = "divorced" then 1 else 0 end) as m_divorced
,sum(case when marital = "married" then 1 else 0 end) as m_married
,sum(case when marital = "single" then 1 else 0 end) as m_single
,sum(case when marital = "unknown" then 1 else 0 end) as m_unknown
from bank_cust_df
--===============================================
-- in this case, there are 2 columns to summarize
--===============================================
group by 1,2
;
"""
agg_df = pysqldf(sql)
agg_df.head(20)

然后,您将得到一个汇总表 agg_df ,如下所示,包含工作和教育的所有可能组合。通过每种组合,您还可以拥有不同婚姻状况的客户数量。

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

Example on aggregated table

下面的全代码生成整个汇总表:

sql = """
select 
y as subscribed
,case when age <= 18 then "Below 18"
      when age <= 25 then "19 - 25"
      when age <= 35 then "26 - 35"
      when age <= 45 then "36 - 45"
      when age <= 55 then "46 - 55"
      when age >  55 then "55 +" end as age_group
,job
,education
,marital
,housing
,loan,count(*) as cnt,sum(case when y = "yes" then 1 else 0 end) as subscribed_y
,sum(case when y = "no" then 1 else 0 end) as subscribed_n,sum(case when age <= 18 then 1 else 0 end) as age_18
,sum(case when age <= 25 then 1 else 0 end) as age_25
,sum(case when age <= 35 then 1 else 0 end) as age_35
,sum(case when age <= 45 then 1 else 0 end) as age_45
,sum(case when age <= 55 then 1 else 0 end) as age_55
,sum(case when age > 55 then 1 else 0 end) as age_ge_55,sum(case when job = "admin." then 1 else 0 end) as job_ad
,sum(case when job = "blue-collar" then 1 else 0 end) as job_blue
,sum(case when job = "entrepreneur" then 1 else 0 end) as job_entre
,sum(case when job = "housemaid" then 1 else 0 end) as job_house
,sum(case when job = "management" then 1 else 0 end) as job_mgt
,sum(case when job = "retired" then 1 else 0 end) as job_reti
,sum(case when job = "self-employed" then 1 else 0 end) as job_self
,sum(case when job = "services" then 1 else 0 end) as job_serv
,sum(case when job = "student" then 1 else 0 end) as job_std
,sum(case when job = "technician" then 1 else 0 end) as job_tech
,sum(case when job = "unemployed" then 1 else 0 end) as job_unem
,sum(case when job = "unknown" then 1 else 0 end) as job_un,sum(case when marital = "divorced" then 1 else 0 end) as m_divorced
,sum(case when marital = "married" then 1 else 0 end) as m_married
,sum(case when marital = "single" then 1 else 0 end) as m_single
,sum(case when marital = "unknown" then 1 else 0 end) as m_un,sum(case when education = "basic.4y" then 1 else 0 end) as edu_4y
,sum(case when education = "basic.6y" then 1 else 0 end) as edu_6y
,sum(case when education = "basic.9y" then 1 else 0 end) as edu_9y
,sum(case when education = "high.school" then 1 else 0 end) as edu_high
,sum(case when education = "illiterate" then 1 else 0 end) as edu_illi
,sum(case when education = "professional.course" then 1 else 0 end) as edu_pro
,sum(case when education = "university.degree" then 1 else 0 end) as edu_ud
,sum(case when education = "unknown" then 1 else 0 end) as edu_un,sum(case when housing = "yes" then 1 else 0 end) as housing_y
,sum(case when housing = "no" then 1 else 0 end) as housing_n
,sum(case when housing = "unknown" then 1 else 0 end) as housing_un,sum(case when loan = "yes" then 1 else 0 end) as loan_y
,sum(case when loan = "no" then 1 else 0 end) as loan_n
,sum(case when loan = "unknown" then 1 else 0 end) as loan_un
from bank_cust_df
group by 1,2,3,4,5,6,7
;
"""agg_df = pysqldf(sql)
agg_df.head(20)

结果聚集表具有#3,980 条记录,共 45 列(45 列中的 7 列是特征列;其他为汇总栏)。创建这样的聚合表的一个优点是防止敏感的客户数据泄露,因为所有数据都已经汇总。

通过创建简单的 excel 数据透视仪表板实现数据可视化

接下来,将聚合表导出到 CSV。不直接导出到 excel 文件的原因是为了防止记录超出 Excel 限制(根据版本不同,是#65,536 还是# 1,048,576)。

# Export the csv file to out folder
agg_df.to_csv('..\out\summ.csv',index=False)

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

Exported summ.csv open in excel

再创建一个名为 summary.xlsx 的 excel 文件,使用 excel 内置函数(Data > From Text/CSV)添加与 summ.csv 的数据连接。数据导入后,使用导入的数据作为数据源创建数据透视表。

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

import summ.csv

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

Load the data with comma as the delimiter

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

Using summ table as a data source

根据特性类型放置字段,
-特性列>过滤区
-汇总列>值区
-订阅的>列
-σ值>行

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

Pivot Table fields setting

最后,将该字段重命名为有意义的标题,并对其应用条件格式,这样就完成了一个带有特色过滤器的清晰的仪表板,并且可以更容易地显示客户数据的分布。

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

Dashboard-like table

浏览数据的最简单方法

现在,您可以创建一个简单的仪表板表,以便更好地了解您的数据,而无需任何花哨的分析工具。

最后,如果您拥有的数据少于 100 万行,我建议您在您的任务中充分利用上面的探索方法。接下来你要做的只是简单地切片和切块,并搜索任何特殊的模式和见解。

部署任何机器学习模型的简单方法

原文:https://towardsdatascience.com/a-simple-way-to-deploy-any-machine-learning-model-106d463e9a4b?source=collection_archive---------4-----------------------

如何使用 Azure 函数来公开一个 REST API 端点,以服务可以在另一个服务器中计算的 ML 模型

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

Is there an easy way to deploy a powerful image segmentation model to a mobile app? The answer is yes.

当数据科学家开发机器学习模型时,无论是使用 Scikit-Learn、深度学习框架(TensorFlow、Keras、PyTorch)还是自定义代码(convex programming、OpenCL、CUDA),最终目标都是使其在生产中可用。

然而,很多时候我们只是想要一个简单的方法来调用 REST API 并使用当前的分类器获得预测。例如,我们可能只想展示模型如何与用户界面集成,而不用担心设置环境、扩展到生产、平衡负载或任何其他问题。

这篇文章将展示我发现的最简单的方法:

  • 建立机器学习模型;
  • 公开一个端点(REST API),以便网站/应用程序可以向http://myendpoint.com/predict发布消息并获得结果;
  • 所有源代码和安装说明可在 https://github.com/douglas125/AzureMLDeploy获得

我们不用担心导出模型、创建 Docker 图像、直接在浏览器中运行、安装软件包或任何类似的事情——有大量的资源可以处理这些问题(参见参考资料)。在本文中,机器学习服务器(MLServer)可以是本地计算机或云中的虚拟机。它将检索需要处理的数据,并将结果发送回来。

此外,无服务器架构是最便宜和最容易实现的架构之一:本质上,每个存储和执行时间都是收费的——如果我们不需要永远存储输入和输出,成本应该会非常低。

它是如何工作的?

Azure Function 应用程序充当中间人,接收并存储来自客户端的请求和来自 MLServer 的回答。当客户端返回来检索结果时,函数应用程序会将结果交付给客户端。

这看起来非常简单——确实如此。正是我们在这篇文章中寻找的。

示例 1:简单的 Ajax 页面

按照存储库中的安装说明,可以构建一个简单的 Ajax 页面来总结客户端和 MLServer 端的工作流。注意,虽然 HTML 页面非常简单,但它仍然演示了如何从客户端(发送作业和检索结果)和 MLServer(获取作业和发送结果)向端点发送数据。

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

Simple Ajax page to test Azure Function App. Sequence: 1 — client posts task, receives task_id; 2 — MLServer fetches task and processes it; 3 — MLServer sends results to Function App; 4 — Client retrieves results.

示例 2:将 DeepLabV3+作为服务运行

C#是为 Windows 构建用户界面的好工具。这个例子展示了如何使用 python(作为 MLServer)进行推理。同样,所有代码在这个库中都是可用的

下面的图像序列演示了客户端和 MLServer 端发生的情况。请注意,MLServer 可以是运行 Jupyter 笔记本中 Keras 模型的任何计算机或虚拟机。

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

Client C# application loads image, resizes it to 512x512 (DeepLabv3+ input size) and sends it to Azure Function App Server.

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

A local computer or a virtual machine could be used to make predictions. In this case, we used Google Colab as the MLServer

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

Client C# application receives predictions (a .png file with the masks) and displays results to the user in a friendly interface.

保持简单

像 Azure Functions 或 AWS Lambda 这样的无服务器架构是实现云计算的绝佳方式:它们处理扩展服务的问题,它们通常易于使用,并且在许多情况下,它们也是最便宜的选择,因为它们不需要专用服务器,用户按使用付费(消费计划)。选择 Azure 函数完全是因为我对 C#的熟悉。

我们将构建一个简单的无服务器架构,接收用户请求,允许远程机器读取并预测存储在云中的数据,并让用户接收最终结果。请注意,功能应用程序可以配置为要求身份验证,保存发出请求的用户(稍后向他们收费)和许多其他功能-这只是一个入门代码,应该用作简单的基础。

工作流程如下:

  • 用户通过向端点/预测发布消息来发出预测请求,该消息带有其有效载荷——文本、图像、音频或任何需要分析的数据;
  • 服务器接收用户请求,保存有效载荷并生成唯一的 task_id,返回给用户;
  • MLServer(机器学习服务器)查询服务器检索下一个作业;
  • 服务器向 MLServer 发送下一个作业的 task_id 和有效载荷;
  • MLServer 处理有效负载并将 task_id 的结果发送到服务器;
  • 服务器接收并存储 task_id 结果;
  • 用户使用 task_id 查询服务器并检索结果。

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

Client — Server — MLServer architecture

设置服务

我们已经讨论了客户端和 MLServer 是做什么的。现在是时候深入 Azure Function 应用服务器了。

服务器需要处理来自客户机和 MLServer 的请求。我们需要四个端点:

  • 预测—接收有效负载并创建 task _ id
  • getresult—接收 task_id 并返回该任务的结果(如果可用);
  • getnexttask —向 MLServer 发送 task_id 和有效负载;
  • puttaskresult —接收 task_id 并存储结果。

我们将使用 Azure Blob 存储来保存有效负载和结果。我们需要两个文件夹:收件箱(存储未完成任务的地方)和发件箱(存储结果)。如果我们想要使用多个服务器并行处理数据,我们可能会想要跟踪正在处理的任务(以便相同的任务不会被执行两次)。然而,这超出了本文的范围,并且会给我们的目标增加额外的、不必要的复杂性。

在函数 puttaskresult 中,我们将从 inbox 文件夹中删除有效载荷,并将结果保存在 outbox 文件夹中。如果我们愿意,我们可以在删除它之前将有效负载复制到一个“已处理”的文件夹中,但是这里我们将保持简单。

对于所有的实现细节,感兴趣的读者应该参考这个库。它有功能应用程序的所有源代码以及安装说明。

结论

本文演示了一种非常简单的方法,使用 Azure 函数存储和服务请求和预测结果,将机器学习模型部署到客户端应用程序。虽然这种方法不如 Tensorflow Serving 强大或不如 tensorflow.js 通用,但它具有重要的优势;

  • 部署起来非常简单;
  • 它允许程序员服务于任何机器学习模型——不仅仅是神经网络,以及任何预处理和后处理步骤;
  • 不需要转换或 dockerize 任何东西;
  • 不需要分配专用的 VM——推理可以在本地运行;
  • 由于推理可以在本地运行,功能应用程序按请求/存储收费,因此这是一个演示概念的廉价选项。

当然也有缺点:

  • 对于需要接近实时运行的模型(例如,有执行时间限制的模型),这不是最好的选择;
  • 不会像 tf.js 一样在客户端运行;
  • MLServers 的负载平衡必须手动完成。

请注意,在原型/开发的早期阶段,这些缺点通常不是开发人员所担心的——他们可以简单地让一台 PC 开着(或者甚至是 Google Colab ),让用户界面团队可以使用 REST API。

这是我发现的将当前状态的机器学习算法快速部署到客户端应用程序的最简单方法。

参考

Tensorflow.js 【https://js.tensorflow.org/

使用 Azure 机器学习服务部署模型。https://docs . Microsoft . com/en-us/azure/machine-learning/service/how-to-deploy-and-where

在生产中部署机器/深度学习模型的指南https://medium . com/@ maheshkkumar/a-guide-to-deploying-machine-deep-learning-model-s-in-production-e 497 FD 4b 734 a

如何使用 Tensorflow Serving 轻松将机器学习模型投入生产。https://medium . com/coin monks/how-to-easy-put-machine-learning-models-to-production-using-tensor flow-serving-91998 fa 4 B4 e 1

通过使用 AWS Lambda 服务机器学习模型,我们学到了什么。https://medium . freecodecamp . org/what-we-learn-by-serving-machine-learning-models-using-AWS-lambda-c70b 303404 a 1

图像分类——评分样本https://github . com/dot net/machine learning-samples/tree/master/samples/cs harp/getting-started/deep learning _ image classification _ tensor flow

ML.NET——一个开源、跨平台的机器学习框架https://dot net . Microsoft . com/apps/machine learning-ai/ml-dot net

使用 Python 训练和部署机器学习模型的初学者指南https://medium . freecodecamp . org/a-初学者指南-训练-部署-机器学习-模型-使用-python-48a313502e5a

部署机器学习模型作为 REST APIhttps://towards data science . com/deploying-a-machine-learning-model-as-a-rest-API-4a 03 b 865 c 166

部署机器学习模型很难,但不一定非得是https://www . anaconda . com/blog/developer-blog/deploying-machine-learning-models-is-hard-but-it-dont-have-to-be/

我们如何使用 FLASK 和 DOCKER 部署 SCIKIT-LEARN 模型https://blog . solutotlv . com/deployed-sci kit-learn-model-flask-docker/?UTM _ medium = How-do-I-deploy-Machine-Learning-Models-as-an-API&UTM _ source = quora

档案:波利贾·科纳·Poznań.jpghttps://commons . wikimedia . org/wiki/File:Policja _ konna _ Pozna % C5 % 84 . jpg

作者 LukaszKatlewa——自己的作品,CC BY-SA 4.0https://commons.wikimedia.org/w/index.php?curid=49248622

Keras 实现 Deeplabv3+https://github.com/bonlime/keras-deeplab-v3-plus

检测异常的简单方法

原文:https://towardsdatascience.com/a-simple-way-to-detect-anomaly-3d5a48c0dae0?source=collection_archive---------17-----------------------

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

Photo by Markus Spiske on Unsplash

当一个类中的观察值比另一个类中的观察值多得多时,很难训练一个普通的 CNN 分类器。CNN 分类器可以认为所有的观察值都来自主类,以实现高精度。

解决这个问题的一种方法是使用过采样或下采样来平衡数据。此外,调整类权重以强制分类器处理稀有类中的数据也是一个好主意。

然而,当数据极度不平衡时,使用上述方法有时可能导致模型过度拟合。因此,我们将研究另一种方法,称为异常检测,来处理这种情况。

我们将假设主类中的观察值为正常数据,并仅使用这些数据来训练我们的模型。然后,我们能够预测一个新的观察是否正常。您可能会问,当模型没有根据这些数据进行训练时,如何检测异常数据。下面是一个简单的例子来说明异常检测是如何工作的。

—实施—

我们可以使用 Keras 和 Scikit Learn 在几行代码内实现异常检测。

首先,导入库来构建模型。这四个库正是我们所需要的。

其次,我们可以使用预先训练的模型作为特征表示,将图像转换到更好的特征空间。

我们使用 Keras 得到一个在 ImageNet 上预训练的 VGG16 模型,并得到所选层的输出。然后,我们将输出通过一个全局平均池层来降低维度。

为了实现一类分类器,我们使用来自 Scikit Learn 的聚类模型,高斯混合模型(GMM)。所以,建造一个只有一个组件的 GMM。

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

figure 2. clustering examples from Scikit Learn documentation.

如图 2 所示。越靠近高斯分布中心的数据越可能是正态的。通过选择分布的范围,我们能够确定观察值是否正常。

是时候导入数据集来看看模型是如何工作的了。我们使用来自 Keras 的 MNIST 数据集。我们假设“1”为正常数据,“7”为异常数据。因此,我们只使用“1”作为训练数据,同时使用“1”和“7”作为测试数据。

reshape_x: according to Keras’s VGG pre-trained model, the minimum size of images is 30 * 30, so we have to resize our images and transform them into 3-channel images.

只有两行来训练我们的模型。首先,使用 VGG 模型从训练数据中提取特征。然后,使用结果作为 GMM 的输入数据。

—结果—

使用 GMM 的 score_samples 函数,我们可以很容易地计算数据的可能性。假设阈值是训练数据的平均可能性加上 3 倍的标准偏差,我们可以预测我们的测试数据。

我们使用 VGG 模型从测试数据中提取特征。然后,我们使用经过训练的 GMM 来计算结果的可能性。最后,如果观测值的可能性小于阈值,我们就可以检测到异常。

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

the output of svdd_part6.py

让我们来看看我们的结果吧!我们画散点图,x 轴是数据的指数,y 轴是分数。我们将“1”标为蓝点,将“7”标为粉红点,并将阈值标为黑线。我们可以看到,大部分的点都可以用阈值来分隔。我们就是这样检测异常数据的。

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

visualization of output, the score is negative since the output of score_samples is log likelihood.

我们还可以检查失败案例。下图显示,当“1”更复杂且“7”过细时,模型更容易出错。

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

These are predictions of ‘1’. the first row is incorrect predictions. The second row is correct predictions.

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

These are predictions of ‘7’. the first row is incorrect predictions. The second row is correct predictions.

为了获得更好的准确性,我们可以用自动编码器代替预先训练的模型,以获得更好的特征表示。虽然在 ImageNet 上预先训练的模型可以从图像中提取很好的特征,但 MNIST 的图像与 ImageNet 中的图像非常不同。如果我们使用与 ImageNet 大不相同的数据集,可能会得到更差的结果。此外,有很多方法可以实现异常检测,请随意尝试另一种方法。

—参考—

[1] ICML 2018 论文深一类分类

[3] Scikit 学习文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值