TowardsDataScience-博客中文翻译-2019-三十二-
TowardsDataScience 博客中文翻译 2019(三十二)
多少分析才算多?

Photo by Jonatan Pie on Unsplash
不要让你的生产力和决策成为分析瘫痪的牺牲品
我们通常认为更多的分析是一件好事(尤其是随着越来越多的公司加强他们的分析和数据科学能力)。你对一个问题投入的时间和思考越多,你的解决方案就应该越好,越有见地。这在一定程度上是真实的。
但是有两大警告。第一,更多分析的增量价值会迅速下降。虽然我不认为这是白费力气,但你第 30 个小时研究的回报可能会比你第 3 个小时的研究低得多。
第二,当人们甚至整个团队收集越来越多的信息时,他们可能会犹豫不决。这就是通常所说的分析瘫痪,发生这种情况有几个原因:
- 太多的信息(和噪音)和太多试图解读这些信息的人会导致意见不一致,并大大减慢决策过程。
- “我们不能放过任何一块石头”的想法会让我们陷入无止境的分析和检查。这通常是由偏执的决策者推动的,他们过分强调犯错的可能性和代价。这一点很难打破,因为随着我们做更多的分析,我们仍然觉得我们在努力工作并取得进展(这感觉很好,掩盖了优柔寡断)——但现实是,随着每一项新的分析,我们增加的价值越来越少。
怎样才能避免分析麻痹?
那么如何才能避免被数据麻痹呢?虽然这绝不是一份详尽的清单,但每当我试图获取数据、分析数据并最终基于数据做出决定时,以下要点都帮了我很大的忙。
1.接受总会有一些不确定性
无论我们做多少分析,总会有一些我们没有检查到的东西。即使我们可以检查一切,生活也不是象棋——结果是随机的,而不是确定的。所以我们唯一能做的就是适应随机性和不确定性。尽管我们尽了最大努力,但有时一切仍取决于硬币的翻转。
但作为分析师和数据科学家,我们的工作是确保我们主要是在投掷不公平的硬币。也就是说,虽然可能存在不确定性,但我们希望机会(或决策)的结果分布向有利于我们的方向转移(就像硬币有超过 50%的机会正面朝上)。因此,我们的分析应该集中在识别一系列机会上,在这些机会上,我们的优势是倾斜的(并且避免那些不利的机会)。

We want the blue distribution (unfair in our favor)
我想重申这一关键点—
作为分析师、数据科学家和战略家,我们的工作不是消除风险和不确定性(这是不可能的);相反,它是识别不对称的风险/回报机会(不公平硬币)并采取行动。
2.认识到我们的心理偏见
前景理论是由丹尼尔·卡内曼和阿莫斯·特沃斯基发展起来的行为经济学理论,它告诉我们,一般人感受到的损失的痛苦多于获得的快乐。根据他们的理论,卡尼曼和特沃斯基能够对我们的心理偏见做出一些有趣的观察:
- 对于某些人来说,可能需要 2000 美元的收益来弥补 1000 美元损失的痛苦。这是一个例子,说明一般来说,人们感受到的损失比得到的多。
- 人们高估了小概率,比如市场崩盘或飞机失事的风险。
- 人们会为确定性(消除所有差异)支付额外费用——例如,人们一般会更喜欢有 : 100%的机会获得 94 美元,而不是有 95%的机会获得 100 美元。这在传统经济学意义上是不合理的,因为 A 的期望值为 94 美元,而 B 的期望值更高,为 95 美元(0.95 * 100 美元= 95 美元)。
因此,前景理论的关键要点之一是,人们会非常努力地避免错误,因为他们:
- 高估错误的可能性。
- 比起做出正确决定所带来的回报,他们更害怕犯错误(和遭受损失)的痛苦。
- 又过分看重不确定性的消除。
消除这些偏见可能是不可能的,但是知道它们的存在和对我们的影响是很好的第一步。接下来清单上的几项帮助我们减少这些心理偏见的负面影响。
3.彻底就可以了;害怕做决定是不对的
有时候,我们发现自己在原地打转,想着,“哦,也许在我决定做什么之前,我应该看看这个。我还想看看另外一件事。我应该看看我的同事是怎么想的。但他们两周后才会回来,所以我想我会在那之前暂不做决定。”
那不是彻底,那是拖延。我们都知道什么时候我们在拖延,即使我们尽最大努力合理化这是可以的。
是什么让我们拖延和磨磨蹭蹭?假设我们不懒(我没有,我发誓!),那么我们可能会推迟做决定,因为我们害怕犯错(因为上面第 2 项中详述的所有原因)。所以我们需要对自己诚实——如果我们发现对未知(和犯错)的恐惧驱使我们缺乏行动,那么这可能是一个很好的信号,是时候做出选择并继续前进了。
4.理解我们决策背后的关键假设(然后重点检查这些假设的有效性)
当我们选择一件东西的时候,我们应该知道我们为什么选择它。更具体地说,我们应该能够识别关键的假设,这些假设对我们来说是正确的。例如,我们可能会认为股票便宜,因为该公司拥有一个快速增长的软件业务,而这个业务被市场上的其他公司忽略了。
因此,在这种情况下,我们的主要假设是,软件业务被其他投资者低估了,它要么将以比所有人预期的更快的速度增长,要么获得比预期高得多的利润率(或者两者兼而有之)。在这种情况下,我们股票投资的成功主要取决于我们对软件业务未来的预测。因此,我们应该将大部分检查集中在软件业务上(以及我们可能如何错误地分析了它),而在我们认为被市场公平估价的业务的其他方面花费相对较少的时间。
5.量化最坏的情况
当任由自己想象时,人们通常会高估事情可能变得有多糟糕。这就是为什么保险公司通常都能盈利。
因此,克服这种偏见的一个方法是尽我们所能量化最坏情况的概率和幅度。如果我们能够对事情会变得多糟糕做出合理的估计,那么我们就可以理性地决定我们应该对最坏的情况担心多少。我们可能会发现,最糟糕的情况并没有那么糟糕,我们是在杞人忧天。
如果我们发现损失的幅度或概率可能超过我们的承受能力,那么要么我们根本不应该前进,要么我们应该找到一种方法来对冲一些风险。
我要提醒你,估计最坏的情况并不容易。例如,用纯粹的历史数据创造的最坏情况应该以怀疑的态度看待——在 2007 年和 2008 年,历史数据告诉我们房地产市场永远不会崩溃,然后它迅速崩溃了。
6.估计额外分析的增量价值
我个人认为,越来越多的分析的附加值遵循帕累托原则,即 80%的收益由 20%的工作产生:

Most of the value is produced by 20% of the work/effort
当然,这并不意味着我们可以只做 20%的工作,然后就到此为止——收益很少是线性增长的。但是这确实意味着我们应该尝试测量每次分析增加的增量价值的数量。
这里的关键词是增量。无论我们第一次分析选择什么,它都可能增加很多价值,因为我们在开始时知道的很少。然后,随着我们研究和建立更多的模型,它们平均产生的增值越来越少(有一些幸运的突破)。至于我们何时应该停止分析并开始做出决策,没有正确的答案——但重要的是要认识到就员工每小时产生的价值而言,每一次额外的分析都越来越昂贵。

Illustrative example of incremental value produced by additional analyses
7.认识到大多数决策只是一个正在进行的迭代过程中的一步(失败可以也应该从中吸取教训)
最后,它有助于保持全局观念。很少有决定是最终的(除非你真的在赌这家公司)。我们做一些分析来告知我们的决定,根据我们对数据的阅读做出选择,从结果中学习,然后重新开始这个过程。
伟大的组织不是一个成败决定的起源。
相反,它们是一个又一个好的决定混合在一起的结果,同时经受住不可避免的错误选择和失败,并从中吸取教训。
感谢阅读!
我希望你觉得这是令人愉快的和有见地的。干杯!
更多数据科学与商业相关岗位由我:
你愿意为人工智能损失多少?
两个月前,我与风力涡轮机行业的一位领导者进行了第一次会面。他的目标是使用机器学习来使风力涡轮机检查更快更便宜。
对于每一次会议,我都是从这个问题开始的:
你能接受多少错误?
他回答了业内所有人都认同的问题:
我们不能接受任何错误,我们的工作太敏感了
不可能的完美
每个涉及安全的项目只接受 0-失败的过程。Cornis 于 2011 年开始与欧洲和法国航天局合作。航天工业是最小心避免错误的行业之一。
但是在 1986 年 1 月 18 日,挑战者号航天飞机在发射后不久爆炸。

专家建造了这架航天飞机。
其他专家验证了这架航天飞机。
其他专家测试了这架航天飞机。
尽管如此,它还是爆炸了,造成 7 人死亡。世界上最好的专家犯了一个悲剧性的错误。
一切都会失败。唯一的问题是多久一次。如果哪个公司卖给你零故障系统,赶紧跑!
我们都希望我们的失败率尽可能远离接近 100%的 USB 密钥插入失败率。

但是如果航天工业专家犯了错误,你可以肯定任何专家也犯了错误。
取代人类专家的人工智能算法不需要犯任何错误。它需要比人类专家犯更少的错误。
由于假阴性,我们可以比较专家和算法的性能。
人工智能总是打败人类…或者不是。
不幸的是,神经网络没有固有的假阴性率。这些算法为我们的图像提供了一个关于缺陷的分数。

通常的方法是为这个分数设置一个 0 的阈值。通过改变这个阈值,算法可以满足更严格的假阴性需求。
您可以决定经过训练的神经网络的假阴性率(漏检)。
结果将取决于假阳性率的数量(错误检测的数量)。较低的假阴性率会带来更多的假阳性。

对于叶片检查,由于失误是至关重要的,所以我们采用了非常低的假阴性率。因此,专家仍然要花一些时间来找出假阳性。但是在过程中加入人工智能并没有影响他们工作的准确性。
你真正需要多少数据?
现实世界中的数据科学
量化注释数据的收益递减
作者:Gal HyamsDan MalowanyAriel BillerGregory Axlerallegrock . ai 团队**

Too Many Cooks in the Kitchen, John Cherry
深度学习模型因其对训练数据的无尽胃口而臭名昭著。获取高质量带注释数据的过程会消耗多种资源,主要是现金。随着机器学习项目的进展,数据量不断增长,导致了其他不良后果,例如减慢了所有的研发。因此,经验丰富的项目负责人总是关注其数据集的额外增量所带来的整体性能增益。通常情况下,特别是如果新数据与现有数据相对相似,人们会遇到收益递减的现象。
收益递减规律表明,当你在生产过程中不断增加越来越多的投入时,实际上产出的增长会逐渐变小。这一现象被 18 世纪的经济学家如图尔古特和亚当斯密所提及,并在 1815 年被英国经济学家大卫·李嘉图所阐述。在处理训练数据量对模型性能的影响时,收益递减规律表明,训练集大小的每次增量对预定的成功度量的贡献将会更小。
当项目负责人能够监控甚至量化他们机器学习项目中的收益递减效应时,他们就能够在其整个生命周期中实现更好的控制。比如:估算达到项目目标需要多少数据;避免多余的培训课程;或者甚至预测当前的模型架构是否能够达到目标度量。这种知识有效地为时间、人力和计算资源的优化管理提供了工具。
监控对象检测中的收益递减
收益递减的现实是否也适用于物体探测任务?我们决定通过在两个代表性数据集的增量部分上训练检测器来探索这个问题的答案:(1)上下文中的公共对象(COCO)和(2)伯克利深度驱动(BDD)。通过查看相应的验证集,对每个模型进行评估。数据准备是使用这个脚本完成的,元数据子集在这里可用。COCO 数据集包含 80 个对象类别,其中一些是稀缺的。当对该数据集的子集进行采样时,稀有类别严重不足,有些甚至根本不存在。
因此,我们仅在视觉对象类(VOC)数据集中出现的二十个标签上训练和评估该模型。这些类别是 COCO 中最常见的,相对来说没有贴错标签。从 COCO 训练集中得到的分类流行度和标签图像的样本拼贴如下图所示。

Figure 1(A): Collage of labeled images from the COCO training set

Figure 1(B): Class prevalence of the COCO dataset with VOC labels. Counting and visualization were done using this.**
在 BDD 数据集上, 的内容 类别,“可驾驶区域”和“车道”被忽略,它们具有不定的空间范围或形状。类别“骑手”被映射到“人员”类别。BDD 训练集的类流行度和标记图像拼贴样本可以在图 2 中看到。

Figure 2(A): Collage of labeled images from the BDD training set

Figure 2(B): Class prevalence of the BDD dataset. Counting and visualization were done using this code.
单触发检测器(SSD)元架构用于两个流行的主干:MobileNet-v2 和 ResNet101。对训练集的样本进行了训练。结果由每个数据集各自的验证集进行评估。为了模拟迁移学习的常见情况,这两个模型在 TensorFlow 的检测模型 zoo 中找到的开放图像数据集(v4) 上进行预训练。使用 RMSProp 对基于 MobileNet 的模型进行批量大小为 12 的 200,000 个训练步骤的训练。通过动量优化器对具有 ResNet-101 主干的模型进行批量大小为 4 的 300,000 个训练步骤的训练。
在图 3 中,我们可以看到模型实现的映射:

Figure 3(A): Diminishing returns — mAP as a function of training data volume for COCO dataset. Each point on the graph is the mAP of the validation-set evaluation, with a model trained on the respective training-subset.

Figure 3(B): Diminishing returns — mAP as a function of training data volume for BDD datasets. Each point on the graph is the mAP of the validation-set evaluation, with a model trained on the respective training-subset.
图 3 显示了 mAP 的缓慢增长,展示了附加注释帧的收益递减。在两个模型的两个数据集上,我们观察到 mAP 快速增加,随着数据量的增加而减少。常识表明,收益递减效应出现在大多数数据集和模型中。
预测收益递减
预测收益递减效应的能力对于任何深度学习经理的工具箱来说都是一个有价值的补充。它能够在项目的整个生命周期中做出更明智的决策,节省宝贵的资源。一般每个项目的收益递减取决于数据复杂度和模型架构;然而,如上所述,收益递减效应在不同的任务中表现相似。
事实上,收益递减模型非常普遍。问题是,普遍的收益递减模型是后验的——它们符合观察到的数据,但很难预测收益递减动态的升级。
考虑描述收益递减动态的经典模型—渐近回归模型 (ARM):
f(x) =a1-a2eta3
当 t 为数据集体积,ai 为学习参数。当提供所有的经验数据时,这个渐近模型非常适合收益递减曲线。尽管如此,在预测图谱演变时,ARM 努力预测基于较小规模实验绘制的后期实验。当没有给定渐近线时,学习模型不能正确地放置它的渐近线。显然这是因为在这个模型中,渐近线直接由参数 a1 描述。通常,当函数的渐近线未知时,很难预测其趋势。
为了克服这个问题,我们选择了一个非渐近对数回归模型:
f(x)= x log(a1)+a2
该函数很好地预测了正在进行的 mAP 曲线,如图 5 和表 1 所示,并被证明是一个相当有用的经验工具。这个模型实际上接近一个渐近模型,并根据一些早期实验预测收益递减动态。尽管如此,执行对数变换(图 4)显示,地图升级开始时是对数函数,随着数据量的扩大,这种增长变成次对数函数。因此,对数回归可能是收益递减预测的有效工具,但其准确性有限。有趣的是,之前提到的深度学习项目中数据量的收益递减被描述为对数或亚对数。

Figure 4(A): mAP as a function of training data volume for BDD datasets. X-axis on log scale.

Figure 4(B): mAP as a function of training data volume for COCO. X-axis on log scale.
对数-对数回归,即 f = x log(log(t))+a,尽管更接近渐近模型,但在预测任务中并不成功(表 1)。尽管对数回归与我们的收益递减经验数据相对吻合,但在缺乏观察的情况下,帕累托 CDF 实际上可能会产生更好的预测。在预测收益递减时,由于获取数据的成本,可用的经验数据(设定体积、结果图)通常很少。这通常会导致预测器参数过拟合。仅包含单个可学习参数的 Pareto CDF 对这种现象的弹性是模型所能达到的:
f(x)=1 — (1/t)x
不幸的是,单参数函数除了具有过度拟合弹性的特征之外,还过于死板。事实上,如表 1 所述,帕累托 CDF 并不像对数回归那样提供准确的预测。

Figure 5: mAP elevation prediction, using logarithmic-regression model and asymptotic regression model (ARM), on COCO (figure 2 A-B) and BDD (figure 2 C-D) datasets. The dots on the ground-truth lines represents the mAP/dataset-volume observation available to the fitted model.

Table 1: Prediction of diminishing returns dynamics: a survey of the various models, given only 5% of the dataset.
结论
从上面的实验中可以清楚地看出,收益递减规律适用于任何深度学习项目,并可能对其产生不利影响。然而,它不可避免的存在也可能被用作预测工具。至少,监控其效果提供了一种方法来评估项目生命周期的不同阶段需要多少数据,从超参数搜索到模型微调。最后,很明显,预先了解预期的最终模型性能有助于任何架构搜索工作。预测项目的收益递减将有助于节省大量的时间和金钱。
欢迎你使用这个 Jupyter 笔记本来预测你的项目的收益递减,甚至设计和评估新的收益递减模型。
以上研究是在深度学习开源实验管理器 trains 中完成的。你可以在这里找到我们为这个博客做的培训和评估实验。
接下来
在我们的下一篇博客中,我们将探索有偏见的数据集,其中类不平衡是突出的。我们将检查处理这种常见疾病的方法:数据集去偏置,专门损失(有人能说是焦点吗?)甚至互补的合成数据。所以请继续关注并在下面的评论中向我们提问。
原载于 2019 年 9 月 23 日https://allegro . ai。**
一个数据科学家需要了解多少数据工程?
&他/她不需要知道多少。

"没有数据就进行理论化是一个严重的错误。"
[人名]夏洛克·福尔摩斯(英国侦探小说家亚瑟·柯南·道尔所塑造的小说人物)
数据科学之前的数据工程
在过去的 5 年里,数据科学已经成为一个热门词汇。每个公司都想做一些这种著名的数据科学,这个主题仍然是 2019 年转向人工智能的公司的最高优先事项之一。然而,在实践中,挑战被证明是非常困难的,数据科学往往仍然是一个非常遥远的目标,许多人似乎从未达到过。
过去几年表明,数据工程是数据科学和人工智能之前的一个重要步骤,但仍然是许多公司完全错过、匆忙或忽略的一个步骤。结果,许多数据科学家最终做了数据工程师的工作,几乎没有任何时间或机会来构建有价值的数据科学项目。
当谈到分离数据工程师和数据科学家的工作时,界限可能有点模糊。这可能会让公司感到困惑,雇佣错误的人来做这项工作,从而让他们的数据科学家感到沮丧。
今天,当其他人都想雇用数据科学家时,谁还需要数据工程师呢?
link.medium.com](https://link.medium.com/n4oxupqRQZ)
两个角色的重叠
数据科学家和数据工程师的知识经常有重叠。重叠的知识是好的,因为两者都需要能够交流和互相帮助。为了合作尽可能顺利,他们应该理解对方的决定和对方的任务。
虽然没有人会指望数据科学家来承担数据工程师的工作(反之亦然!),一些数据工程知识对于数据科学家来说可能是必不可少的。
云计算
随着 Google Cloud、AWS 和 Microsoft Azure 的兴起,云基础设施的知识对任何数据科学家来说都变得非常有价值。使用这些平台的公司通常会鼓励他们的数据科学团队使用他们的云基础设施来开发他们的模型,甚至使用 CI/CD 管道将它们部署到生产中。
然而,数据科学家不需要知道如何自己建立整个基础设施或管道。再说一遍,这不是他们的工作。然而,知道管道由什么组成,以及知道如何在“云中”运行模型会非常有用。例如,重型机器学习模型的开发和/或部署可能需要使用集群、虚拟机或容器。因此,知道如何处理这些服务会很方便。
尽管我并不热衷于现成的数据科学解决方案,但我必须提到,云基础设施现在拥有相当先进的机器学习平台。它们通常可以轻松地与来自同一提供商的其他云服务集成,是一个很好的概念验证选择。
阿帕奇火花
Spark 通常是数据科学家和数据工程师将展示的重叠的一部分,因为他们都将把它用于不同的目的。Apache Spark 是一个非常流行和强大的数据处理引擎,支持数据并行。对于数据科学家来说,Spark(或者 Python 用户的 PySpark)可以用来对非常大量的数据([包括流数据)应用机器学习模型!](http:// https://link.medium.com/PMOYb24QQZ))而数据工程师会用它来建立可靠的数据管道。
Apache Spark 与 Hadoop MapReduce——优势、劣势以及何时使用
towardsdatascience.com](/a-beginners-guide-to-apache-spark-ff301cb4cd92)
结构化查询语言
SQL 已经存在了很长一段时间,关系数据库在许多业务中仍然很受欢迎和必不可少。任何数据科学家都应该掌握一些 SQL 基础知识,以便能够从任何 SQL 数据库中查询数据。掌握一些数据仓库的基础知识也会有所帮助。然而,数据科学家既不负责生成 SQL 报告,也不负责维护或提高数据库中的数据质量。
Linux 操作系统
虽然可能不需要广泛的 Linux 知识,但是 Linux 的基础知识对任何数据科学家来说都是非常有用的!事实上,数据科学家可能需要在远程服务器或集群上以 Linux 作为操作系统来开发和运行他们的实验。而且操作系统很受我之前提到的云提供商的欢迎。 Linux 可以在大多数强大的远程机器上运行,在这个操作系统上安装和运行某些软件或软件包(比如 AirFlow)会轻松得多。出于同样的原因,数据科学家的代码一旦投入生产,就很可能被部署在 Linux 机器上。简而言之,如果你是一名数据科学家,了解 Linux 和命令行将会有很大的价值。****
阿帕奇气流(很好,但不是必需的)
Airflow 是一个用于自动化工作流的开源调度工具。它提供了一个可视化界面,并且是基于 Python 的。它可以用来安排 ETL 任务,但对数据科学家来说也很方便。虽然 ETL 工作不是他们的职责,但数据科学家可以利用 Airflow 的功能来自动化他们对任何机器学习模型的数据处理。如果您还没有听说过 Apache Airflow,下面的文章提供了该工具的一个很好的概述。
在这篇文章中,我将讨论由 Airbnb 开发的工作流管理系统 Apache Airflow。
towardsdatascience.com](/getting-started-with-apache-airflow-df1aa77d7b1b)**
只有基本的
结合数据科学和数据工程的领域在不断变化,以适应出现的挑战。虽然数据科学家应该关注数据工程的发展&一些相关的工具,他们很少需要大部分提到的软件或系统的高级知识。要求一个数据科学家具备数据工程和相关工具方面的高级知识是很不合理的。然而,任何数据科学家都会在适当的时候欣赏这些技能。通常,成长并不是来自不断获得新技能。它来自于收集正确的技能。****
多少数据才够?
使用 Python 工具进行实验设计

Photo Credit: pxhere.com CC0
当你在一个现有的数据集或多个数据集的组合中寻找洞察力时,你必须接受给你的,或者决定出去收集你自己的数据。在第二种情况下,当您还没有数据或者您的数据质量或数量不够高时,下一个问题是:我需要多少数据?
这个问题根据上下文有不同程度的重要性:数据收集有多贵?数据收集需要多长时间?显然,昂贵和/或缓慢的数据收集将使你需要多少数据的问题变得更有争议。如果数据便宜且易于收集,就没有理由不收集或增加额外的缓冲区。在其他场景中,您可能不得不竭尽全力来捍卫您的数据收集计划,并抵抗分析部分数据集的压力。
今天,我们正在考虑一个假设性的问题:“跑步者和游泳者,哪一组吃得更多?”

Photo Credit: Martin Vorel on librashot.com w/ Public Domain License
不管你的背景如何,在你开始收集数据之前,你会想知道你需要多少数据来找到一个有统计学意义的结果。这将有助于你计划数据收集、估算成本和获得资金。
既然你已经记住了为什么要做这项工作,那就让我们来看看你需要什么:
- 可接受的\u\u——I 类错误的概率(当零假设实际上是正确的时,拒绝零假设)
- 期望的统计功效 —假设实验治疗产生了效果,检测到效果的可能性。功效= 1- β,其中β是第二类错误的概率(当零假设不正确时,未能拒绝零假设)
- 预期效果大小——有两种方法可以考虑预期效果大小:1)如果你已经做了一些初步调查,你可能对效果大小有一个很好的想法,或者 2)你可以考虑在你的环境中有意义或可操作的最小效果大小。例如,两个人群的平均身高相差 0.00001 英寸可能在统计学上是显著的,但实际上并不重要。可能不值得收集足够的数据来检测这么小的影响大小。也许对于你的目的来说,只有 1 英寸的效果尺寸才是有意义和可行的。这将需要非常不同的数据量来实现相同的功率。
- 总体标准差——同样,一些初步数据可以帮助你解决这个问题,这些数据来自一项较小的研究、一篇文献综述或你的最佳猜测。这个特性中的任何错误都将影响您最终实验的实际统计能力。对于相同的绝对效应大小,较小的标准差需要更多的数据。
对于我的实验问题,我的研究小组决定如下:
- 可接受= 0.05 —相当标准
- 幂= 0.95 —我真的很想找到一个有统计学意义的结果,如果有的话!
- 达到那个能量的效果大小= 100 千卡/天——我认为 100 千卡/天是一个值得注意的水平,较小的差异对我们的使用并不重要。
- 标准偏差= 700 千卡/天(来自本研究),假设两个群体的总和
一旦你决定了这些输入,你就可以开始计算了。
对于比较两个总体平均值的实验,首先使用您的效应大小来计算标准化效应大小:平均值之差的绝对值除以两组的标准差。
effect_size = 100
stdev = 700
standardized_effect_size = effect_size / stdev
注意科恩的 d 提供了另一种常用的标准化效果大小方法。
您可以使用 python 的statsmodels.stats.power.tt_solve_power来求解所需的样本大小,其中 nobs 是来自每个群体的观察值的数量。
from statsmodels.stats.power import tt_solve_powertt_solve_power(effect_size=standardized_effect_size, alpha=0.05, power=0.95)Result: 639
注意:TT _ 求解 _ 功率( effect_size=None , nobs=None , alpha=None , power=None ,alternative =‘双边’)将求解四个输入中未提供的任何一个。更多信息参见文档。
现在我看到了结果,并考虑到大型研究所需的费用和时间,我将绘制不同功率水平所需的观察次数。
from matplotlib import pyplot as plt
import numpy as nppowers = np.linspace(0, 1, 101)
nobs = [tt_solve_power(effect_size=standardized_effect_size,
alpha=0.05, power=power)
for power in powers]plt.plot(powers, nobs)
plt.title("Sample Size Needed vs. Power for \nRunner vs. Swimmer Caloric Consumption Experiment \nw/ effect size of 100kcal/day, stdev of 700kcal/day")
plt.ylabel('Sample size needed per population')
plt.xlabel('Power')
plt.ylim((0,1000))
plt.savefig('power_plot.png')

理想情况下,我们总是有一个超高的能量和一个超低的阿尔法值,这样我们就可以确信我们的实验结果反映了现实。然而,我们看到,除非数据收集是快速和免费的,或者我们两个群体之间的差异非常大(与合并标准差相比),否则我们通常需要做出权衡。将经济分析添加到功率分析中,将有助于您和您的团队做出适合您的情况的决策。
快乐实验!

Picture Credit: Mohamed Hassan on needpics.com
请随意查看 GitHub 回购。完全公开:这次没有任何额外的代码。
数据科学家挣多少钱?

我们用 H1B 工资数据来探究数据科学家的工资
我最近写了很多关于数据科学行业的文章——既有关于如何打入的,也有关于分析行业本身是否容易受到它所引领的自动化趋势的影响。
今天我们将讨论最有趣的话题,薪酬。如果数据科学家的市场如此火爆,那么他们的薪酬到底有多少呢?
对于不耐烦的人,让我们开门见山吧
在我谈论数据来源和所有这些好东西之前,让我先告诉你一些数字。就我个人而言,我讨厌和老板开会讨论我的加薪和奖金,但是接下来的 30 分钟我们会讨论其他事情——说重点!这就是:

Median Data Scientist Salary by Year
所有年份的工资中位数是 12 万美元。正如你从上面的图表中看到的,当我们按年细分时,趋势非常平缓,稳定在 120,000 美元左右。请记住,这个中位数只是基本工资,不包括现金奖金,股权和福利。因此,数据科学家的总薪酬中值很可能要高得多。
在我们探索数据的更多趋势之前,让我们先弄清楚我们到底在看什么。
数据是从哪里来的?
我从这个牛逼的网站 上得到了我的工资数据 这个网站索引了劳工部(DOL)的劳动条件申请(LCA)数据。基本上,当公司打算雇用需要 H1B 签证担保的员工时,他们需要在提交 H1B 签证申请之前向劳工部提交 LCA。此 LCA 包含所有人都可以公开获得的公司、工资和职位数据。
我在网上搜集了上述网站(如果你想自己动手, 你可以在我的 GitHub 上找到我的代码)以下地区数据科学家的工资数据(抱歉,我把重点放在美国西海岸,因为那是我生活和工作的地方):
- 旧金山湾区(旧金山、圣何塞、库比蒂诺、山景城、帕洛阿尔托等。)
- 西雅图(包括微软的雷德蒙)
- 奥斯汀
- 洛杉矶(包括圣莫尼卡)
此外,我将分析的重点放在了被聘为数据科学家的员工身上。因此,该分析不包括更有经验的数据科学职位,如高级数据科学家或员工数据科学家,也不包括数据分析师。
在所有这些自我强加的过滤之后,我最终得到了 2818 个观察结果。
最后,请注意,这是 H1B 相关的薪资数据,因此,我在分析中使用的薪资数据不包括美国公民的收入。由于我没有看到任何相反的证据,我将假设美国公民数据科学家和持有绿卡的数据科学家的数据遵循 H1B 数据中相同的一般趋势。
越来越多的数据科学家被雇佣
好消息是,在过去的 5 年里,数据科学家的雇佣人数大幅上升。请注意,当我在 8 月份写这篇文章时,2019 年还有一段路要走,因此在最后有一个较短的专栏(棕色)。

Number of Data Scientists Hired (H1B) by Year (2019 Still Ongoing)
虽然数据科学现在绝对是一个时髦的职业,但我个人认为,过去几年数据科学家的增加也反映了另一个因素——许多公司都试图赶上大数据和人工智能的潮流。因此,这些公司以前被称为决策分析或研究的团队正在被重新命名为数据科学。因此,几年前被称为研究分析师的角色现在被称为数据科学家。
不过,我不认为这有什么不对。数据科学家的头衔并不神圣——如果你以一种有见地的方式应用定量数据来帮助你的组织做出更好的决策,那么在我看来,你就是数据科学从业者!
但是请记住,并不是所有的数据科学工作都是平等的。数据科学家头衔的过度使用意味着,A 公司的数据科学家可能会将 80%的时间花在 SQL 上,而 B 公司的数据科学家会花一整天的时间用 Python 实现机器学习算法。不管合理与否,这可能是数据科学家的工资表现出如此高的差异的原因之一(其他明显的原因是经验年限、雇佣地点、公司的平均工资水平以及员工是否有高等学位)。
让我们通过柱状图来看看工资的分布情况。由于这些数据在不同年份之间差别不大,我在下面的柱状图中绘制了所有 5 年的数据。两条黑线显示的是第 25 位(102,600 美元)和第 75 位(135,475 美元),红线显示的是中位数(120,000 美元)。

Data Science Salary Histogram, Black Lines are 25th and 75th Percentiles, Red Line is Median
如果我告诉你这些年来工资分布变化不大,你可能不相信,我们可以用一个箱线图来比较不同年份的工资分布:

Box Plot of Data Scientist Salary by Year
作为参考,2015 年,薪酬四分位界限为:
- 第 25 百分位:10 万美元
- 第 50 百分位:11.5 万美元
- 第 75 百分位:13 万美元
目前在 2019 年,同样的四分位界限是:
- 第 25 百分位:10 万美元
- 第 50 百分位:119850 美元
- 第 75 百分位:13.5 万美元
因此,工资确实有所上升,但幅度不大。此外,在撰写本文时,2019 年数据科学家的工资与 2018 年相比有所下降。
谁付的钱最多?
那么,你去哪里得到大笔的钱呢?这是一张按公司从高到低排列的数据科学家工资中位数的图表。在这张图表中,我只包括了在我的样本期内雇佣了 10 名或更多数据科学家的公司——如果我向你展示一家雇佣了一名孤独的数据科学家的公司,即使他或她挣 20 万美元,也没有多大帮助。
你会发现最常见的嫌疑人——AirBnB、Lyft、脸书、苹果都支付了 13.5 万美元或更多。你也有一些惊喜。谁知道 Ancestry.com 是数据科学家的主要高薪雇主呢(我也没想到沃尔玛会名列前茅——我一直认为低低的价格意味着低低的薪水)?

Where You Should Go to Get the Big Bucks
如果你感兴趣,我在下面的图表中画出了数据科学家的最大雇主(提交 H1B 申请最多的雇主)。不出所料,你的顶端是大型科技股。我的列表中有一个明显的遗漏是谷歌。不管出于什么原因,它们在数据科学家的数据库中并不常见。这可能是谷歌使用的标题不同——我将在未来对此进行更多的调查。

Who Hires the Most?
直到下次
我希望这是有益的。虽然这不是一个完整的画面,因为这只是基于 H1B 数据,但我得到的数字与我听说的以及在薪资聚合网站如 Paysa 上看到的非常吻合。
在某个时候,我将进行第 2 部分,在那里我将更深入地研究数据,并为其他与数据相关的角色(如数据工程师和数据分析师)引入数字。我还会调查公司内部的趋势——例如,随着时间的推移,脸书是否会给数据科学家越来越多的报酬?
在那之前,干杯!
来源:https://h1bdata.info/index.php
在这里阅读本系列的第二部分:
更多数据科学与分析相关帖子由我:
数据科学家挣多少钱第二部分

当我们深入挖掘时,我们发现了一些令人惊讶的趋势
L 上次我们用 H1B 的薪资数据探讨了一般数据科学家的薪资趋势(数据详情请参考我之前的博文)。以下是我们发现的快速回顾:
- 我们发现数据科学家基本工资的中位数是 12 万美元(不包括奖金和股权)。
- 工资中位数几乎没有逐年增长。
- 最大的科技公司通常支付最多。

Median Data Scientist Salary by Year
深入挖掘揭示了两个潜在趋势
上次我没有足够的时间深入研究这些数字。但是在对事情进行了更详细的研究后,我发现了一些令人惊讶的趋势。
首先,过去几年数据科学平均工资的普遍停滞实际上是两个趋势的故事:
- 在“更时尚”的科技公司(谷歌、脸书、苹果和 Airbnb 等家喻户晓的名字,以及 Stitch Fix 和 Opendoor 等较小的公司)中,数据科学家的薪水正在大幅增长。
- 对于我样本中的其他公司(如 IBM、思科、甲骨文、波音、诺德斯特龙、斯伦贝谢等公司。),工资中位数实际上略有下降。
我意识到我列出的“新潮”科技公司完全是主观的——我的标准是,“顶尖工程学院的普通毕业生会对在那里工作感到兴奋吗?”不管怎样,看看趋势的不同:

Trendy tech raising data science pay, everyone else not so much
我的猜测是,有两组公司——一组有能力从专有数据中产生、收集和提取竞争优势,另一组没有这种能力。因为“富人”可以从他们的数据科学家那里获得更多价值,所以他们也愿意支付更多。与此同时,“穷人”更有可能对他们的数据科学团队没有创造价值感到沮丧,从而导致更低的感知价值(和更高的流动率)。
谷歌和脸书等公司已经证明,收集和利用独特的数据可以创造巨大的竞争优势(这种竞争优势会随着时间的推移而扩大,因为收集了更多的数据和见解)。他们在利用数据科学创造巨额利润方面的成功创造了一个良性的反馈循环,数据和研究创造利润,然后再投资到更多的数据和研究中(从而产生更大的未来利润)。
因此,对于有抱负的数据科学家来说,教训是为拥有独特数据类型的公司工作,这种数据类型赋予了他们竞争优势。一家知道如何正确使用这些数据来创造研究和利润的良性循环的公司。
这是最近(2018 年至 2019 年)按公司分列的数据科学家工资中位数。请记住,我们只查看数据科学家职位,我过滤掉了在此期间雇用 5 名或更少数据科学家的公司。

Data scientist salary by company, those Stitch Fixers make a lot!
哇,看看缝针!这是一大笔钱,尤其是当我们记住 19 万美元的中位数只是基本工资,不包括奖金或股票。更普遍的是,处于顶端的公司都是数据驱动的,要么拥有大量的专有数据(AirBnB、Lyft、脸书),要么正在通过与用户的独特互动来建立这些数据(Stitch Fix、Opendoor)。
最后,在考察不同公司之间的这些差异时,记住这些差异不仅是由每个公司银行账户的相对规模驱动的,也是由角色和所需专业知识的差异驱动的,这是很有帮助的。
硅谷数据科学的工资更高(但我们还是买不起这里的房子)
不出所料,旧金山湾区(硅谷)的数据科学家薪酬高于美国其他地区(我所在的“新潮”科技集团的许多公司都位于硅谷)。下图显示的基本工资中位数的差异可能被低估了,因为我主要关注的是西海岸和其他科技中心——中西部和南部的许多低成本城市没有包括在我的分析中。

Silicon Valley firms (orange) pay more
在硅谷工作的数据科学家与在其他地区工作的数据科学家之间的薪酬差距看起来相当显著。但不幸的是,生活成本的差异(由高昂的房价和租金推动)甚至更大。
那么作为一名数据科学家,我应该去哪里生活最舒服呢?
赚大钱固然好,但我们需要记住开销也同样重要。如果我们赚了大钱,但最终却向山姆大叔(税收)和我们的房东(房租)支付了更多的钱,那么我们最终可能还是一个净输家。
首先,让我们来看一下数据科学家的工资按地区排列的情况(仅限 2018-19 年的工资):

Data scientists earn more in major coastal cities
正如预期的那样,旧金山湾区在基本工资中位数方面名列前茅。纽约的薪水低于我的预期——可能的原因是,我的数据集没有捕捉到大银行聘用的一些数据科学家(在那里,他们可能被称为量化策略师、风险经理或投资组合顾问)。此外,仅使用基本工资可能会低估大银行聘用的数据科学家的收入能力,因为他们的薪酬在年度现金奖金中占很大比重(100%的奖金并不罕见)。
最让我印象深刻的是西雅图。作为一名数据科学家,你的收入几乎和在硅谷一样多,但你不用缴纳州所得税,住房成本也低得多。
让我们用上一个柱状图中的基本工资中值除以每个城市的租金中值(乘以 12 得到年租金),得到一个你的美元能走多远的粗略替代值(我省略了“其他”类别,因为它包括多个城市,但不足以安全地应用全国平均水平)。如果你感到好奇,以下是我使用的月租金中位数(来源于本文):
- 湾区(硅谷)::3300 美元,比文章中的价格略低,以反映旧金山以外的租金略低。
- 西雅图:2100 美元
- 纽约市:$ 2700
- 洛杉矶:2400 美元
下面是基本工资转换成租金等值单位后的样子。回想一下,我将月租金乘以 12,以便按年计算:

Your dollar goes furthest in Seattle
经房租调整后,你在西雅图的数据科学薪水比其他科技中心高得多。这是在我们考虑你支付较低税收(没有州所得税记得吗?)也是。所以如果你不介意下雨,可以考虑在亚马逊、微软和星巴克投一两份简历。
最后,让我们来看看这些地区的科技与非科技薪资差距(仅 2018-19 年薪资)。西雅图“时尚”科技公司的平均薪酬也更高,就像湾区(硅谷)一样。纽约的差距尤其大——我的最佳猜测是,纽约的非科技公司支付高额年度奖金,这不会在 H1B 工资数据中显示出来。

In all regions, trendier tech companies pay more
结论
在今天结束之前,让我们回顾一下我们数据中的一些关键发现:
- 数据科学家的薪酬数据有两个潜在趋势——“时尚”科技公司的数据科学家薪酬稳步增长,其他公司的薪酬停滞不前(尽管这些公司的薪酬中值仍接近 11 万美元)。
- 看看目前的数据(2018-19),在“时尚”科技公司工作与在其他公司工作的收入之间有很大的差距(超过 3 万美元)。这种差距也只是基本工资——在考虑奖金、股权和股权表现后,实际差距可能会更大(更时尚的公司拥有更时尚的股票)。
- 西雅图提供非常有竞争力的数据科学薪资,没有州所得税,生活成本相对合理(以租金中位数计算)。你有机会通过经受风雨和寒冷来塑造性格。
希望这是有见地的,对你有用。干杯!
在这里阅读这个故事的第一部分:
更多数据科学与分析相关帖子由我:
软件工程师挣多少钱?

Photo by Markus Spiske temporausch.com from Pexels
写代码是目前城里最热门的游戏——让我们看看薪水是否与宣传相符
2012 年,当我搬回硅谷时,我记得曾听说优秀的软件工程师越来越难招到了。大型科技公司正在竭尽全力争夺给最优秀的工程师开巨额支票的特权。
当时,我距离获得莱斯大学的 MBA 学位仅差两年。我最近没有查看统计数据,但在当时,作为一名排名相当不错的 MBA 毕业生(当然,如果你去了哈佛或斯坦福,你会期望更多),你对 10 万至 11 万美元的基本工资加上适度的奖金相当满意。因此,当我搬回湾区时,我震惊地听说,顶尖计算机科学本科项目的应届毕业生除了获得公司股票或期权的丰厚奖励外,还获得了越来越多的收入。
自那以后的几年里,软件工程师的薪酬只是在大型科技公司(脸书、谷歌、苹果等)赚取巨额利润的推动下上涨的。),资本从软银这样的非传统风险公司大量涌入创业公司,以及华尔街(在大多数情况下)愿意专注于使命和机会而不是损益表。
今天,我们将使用 H1B 工资数据来探索硅谷软件工程师的基本工资有多高,以及过去几年的趋势如何。我将借用我之前两篇与薪酬相关的文章中的许多方法和代码,您可以在这里找到:
希望你喜欢!如果你想用我的代码进行你自己的分析,你可以在我的 GitHub 上找到它。
他们挣多少钱?
在我们深入研究这些数字之前,让我们先了解一些细节:
- 所有数据都是从 H1B 工资数据库中抓取的。
- 我只收集了硅谷(旧金山湾区)城镇的数据。
- 我的数据只包括以下两个职位——软件工程师和高级软件工程师。
- 最后,我给出的数字只是基本工资,不包括年度奖金、限制性股票单位(rsu)或股票期权。
让我们先把基本数字弄清楚。2019 年,我发现软件工程师的底薪中位数是 13 万美元。拥有高级软件工程师头衔的人年薪为 14.8 万美元。
以下是 H1B 数据中软件工程师头衔的 2019 年基本工资四分位数:
- 第 25 位百分位数—【12 万美元
- 第 50 个百分位数—13 万美元
- 第 75 个百分位数—15 万美元
以下是高级软件工程师头衔的相同值:
- 第 25 个百分位数—132,000 美元
- 第 50 个百分位数—148,000 美元
- 第 75 个百分位数—164,000 美元
这些数字很大,我想再次提醒你,这些数字是在年度奖金(如果适用)和股权(绝对适用)之前的。
哪些公司工资最高?
上一次,人们对哪些公司向数据科学家支付最高工资颇感兴趣,所以让我们来看看软件工程师的类似图表。为了提醒大家我们在看什么,下表中的值捕捉了 2018 年和 2019 年硅谷软件和高级软件工程师(我把他们都放在一起)在公司中的 H1B 工资中位数。我只标出了在此期间雇佣了至少 30 名 H1B 软件工程师的公司。

Median Software Engineer Salary by Company (2018–19)
有几件事引起了我的注意:
- 在我调查的所有公司中,只有一家公司的薪资中值低于 10 万美元。
- 这份名单上有 14 家公司(都是你应该认识的公司)给他们的软件工程师支付的平均基本工资是 15 万美元或者更多。
- 我们稍后会看到,谷歌是 H1B 软件工程师的最大雇主之一。他们的基本工资中值为 14 万美元,相当可观,但这仅使他们在我们的榜单上排名第 23 位。话说回来,他们可能会以其他方式弥补,比如更高的奖金、大量的股权、高于平均水平的加薪,以及波霸鸡尾酒(主宰他们所有人的一项特殊待遇)。
- 第一是……我们工作!我没想到会这样。话又说回来,他们从风险投资家那里获得了大量资金,并极其努力地将自己塑造成一家科技公司,而不是房地产公司。此外,它们目前的价值为 470 亿美元。无论你有多乐观,都很难指望股票在这些泡沫水平上有很大的上涨(特别是在它继续消耗大量现金的情况下)——所以最近的新员工可能会要求更高的现金薪酬来弥补风险。
但是更重要的是,不管你选择在哪里编码,看起来你都会得到一份相当不错的薪水,
过去几年谁雇佣的人最多?
现在我们来看看过去 6 年(2014-19 年)谁雇佣了最多的 H1B 软件工程师:

Who Hired the Most H1B Software Engineers (2014–19)
哇,看看谷歌——他们雇佣的员工数量比其他任何人都多。脸书和 LinkedIn 远远落后于第二名和第三名——在我研究的这段时间里,他们仍然雇佣了几千名软件工程师。
所以看起来谷歌在我的数据集和软件工程师招聘中占据了主导地位。不过,这并不一定会扭曲我的数据。请记住,所有这些公司都在竞相招聘高质量的工程师——没有人会在真空中招聘。因此,谷歌对程序员的兴趣成为了水涨船高(工资)的潮流,其薪酬方案成为了许多薪资谈判中使用的标准基准。有趣的是,这一点得到了证实,正如我经常听到工程师告诉他们的同事,“如果你认为自己的薪酬不够,那就去谷歌(Google)找一份有竞争力的工作。”当然,说起来容易做起来难。
过去几年软件工程师的工资趋势
现在我们来看看软件工程师(包括软件工程师和高级软件工程师)的工资中位数在过去几年的趋势如何。从 2014 年到 2019 年(五年一期),工资增长了 14.8%,相当于年增长率为 2.8%。这并不比通货膨胀高多少(也比硅谷的通货膨胀低很多)。作为比较基准,2014 年斯坦福大学 MBA 毕业生的平均工资为 12.5 万美元,2018 年为 14.2 万美元(4 年增长率为 13.6%,年增长率为 3.2%)。
因此,虽然水平很高,但过去几年的增长率低于我的预期。话说回来,这只是基本工资的增长——薪酬的大部分增长可能发生在股权方面,既可以获得更多股权,也可以提高已获股份的估值。

Software Engineer Median Salary by Year
如果你对 H1B 软件工程师工资的分布趋势感到好奇,下面是箱线图。这没什么太令人震惊的——随着时间的推移,工资的差异保持相对稳定。

Distribution of Software Engineer Median Salary by Year
数据中的其他趋势
既然大型科技公司,尤其是谷歌和脸书,在数据中占据主导地位,让我们也来看看不为这些公司工作的软件工程师的薪水。下面的图表用橙色(is_tech=True)显示了大科技软件工程师的工资中位数,用蓝色(is_tech=False)显示了其他人的工资中位数。我对大型科技公司的定义是为以下公司工作的工程师——谷歌、脸书、微软、优步、AirBnB、Lyft、苹果、网飞和 LinkedIn。
大型科技公司支付的价格肯定要高得多(这可能不仅仅是因为它们的盈利能力更高,也是因为它们股票的上涨空间更小)。然而,两组的增长率大致相等(5 年期间都在 14%左右)。

Median Software Engineer Salaries for Big Tech (in Orange) and Everyone Else (in Blue)
最后,虽然我不是这方面的专家,但软件工程师的头衔似乎在大型科技公司使用得更广泛——在较小、不太知名的公司被视为高级软件工程师的人,可能是谷歌或脸书的软件工程师。这也许可以解释为什么大型科技软件工程师的薪水和其他人之间存在差距(这体现了更广泛的经验水平)。
在大技术类别中有一些高级软件工程师的工资,所以我们可以通过比较“其他所有人”(X 轴上为假)和大技术(X 轴上为真)类别中的软件工程师和高级软件工程师的工资来检验我的假设:

这似乎证实了我的假设——“其他所有人”类别(左边的蓝色和橙色方框图)的分布重叠比大型科技公司(右边的蓝色和橙色方框图)的分布重叠少得多。因此,看起来“软件工程师”或多或少是一个包罗万象的头衔,涵盖了大型科技公司的各种经验水平和工资级别。
结论
随着软件继续“吞噬世界”,颠覆和改变传统行业,软件工程师的技能对于任何想要在这个竞技场上竞争的公司来说都是至关重要的。
数字支持了这一点——虽然增长率比我想象的要低,但程序员的基本工资水平非常令人印象深刻(甚至不要说软件工程师年复一年赚了多少钱)。
这是否可持续是另一个时代的故事(对世界上的谷歌来说是这样,对世界上的 WeWorks 和 Ubers 来说可能不是这样)。我希望这对你有所帮助和启发。干杯!
更多数据科学、职业、教育相关岗位由我:
根据模拟,30 岁退休需要多少钱

Photo by Fabian Blank on Unsplash
任何人都有在年轻时辞掉工作,环游世界,同时保持经济独立的梦想。达到这个目标需要多少钱?
在本文中,我们运行了一个统计(蒙特卡罗)模拟来估计基于历史数据的退休投资组合(首先是资产配置)的成功率。
假设和策略
让我们考虑一下利亚姆。他存了一些钱,打算在 30 岁时退休。我们将假设他的:
- 预期寿命又是 65 岁。
- 月收入/提现 4000 美元。
他用以下策略投资他的钱:
- 在标准普尔 500 指数和美国债券指数(以先锋总债券指数基金为代表)中分配退休投资组合。
- 最初%的股票和债券将每月进行再平衡。例如,给定 50%股票和 50%债券的初始设置,如果股票市场表现良好,并且他的股票投资组合的价值比债券增加了很多,那么投资组合将通过出售股票和购买债券来重新平衡,以回到最初的 50/50 分割。
利亚姆在未来 65 年面临的经济形势是:
- 股票/债券市场的年度回报率与 1986 年至 2019 年的市场有些相似。为了模拟这种情况,我们随机抽取了四个 15 年的市场周期和一个 5 年的市场周期,总共是 65 年。我们用这些收益来投资他的投资组合。
- 通货膨胀率为每年 3%。所以 Liam 的月收入/提现每年都会以这个速率上去。
结果
这个模拟的目标是看看在给定初始资金和资产分配策略的不同组合的情况下,Liam 在余生中保持每月提款的可能性有多大。
我们查看了 9 种不同的场景,并对每种场景进行了 1000 次模拟。成功率是以他的投资组合在整个 65 年中保持在 0 美元以上的次数的百分比来计算的。

- 30 岁时舒适的提前退休需要 200 万美元左右
如你所见,在初始资金只有 100 万美元的情况下,利亚姆的成功率很低。所有 200 万美元投资组合的例子都有很高的成功率,值得一试。当利亚姆有 300 万美元时,他可能希望每月提取更多的钱。
- 资产配置很重要
事实上,资产配置是投资者根据自己的风险偏好应该做的第一件事。
在模拟中,当利亚姆的钱更少时,即 100 万美元,如果他冒更大的风险——购买更多的股票,他就有更大的成功机会。从长期来看,债券的回报不足以跟上他的提款和通货膨胀。
如下表所示,股票的波动性更大。1986 年至 2019 年的月度股票收益率范围为-21.76%至 13.18%。债券指数的波动范围更窄,为-3.34%至 3.95%。
然而,即使利亚姆将一切都配置到股票中,成功率仍然很低,只有 25.6%。这些成功很可能是牛市中的一些连续的幸运抽奖。

当利亚姆有一笔合理的资金(超过 200 万美元)时,如果他只想维持稳定的提取金额(经通胀调整),最好投资于债券等更稳定的投资。
更多考虑?
这里讨论的模拟是简化的。在现实生活中,还有很多其他的事情需要考虑。
- 投资策略或偏好可能会有所不同
除了股票和债券指数,你还可以投资许多其他资产。你可以进行彻底的分析,自己挑选特定的股票/债券产品。许多人还购买了出租房地产。
还有许多不同的策略,人们试图增加收益或降低风险——购买并持有并不是唯一的策略。
- 撤军计划可能改变
在现实生活中,你可能会根据你的投资表现来调整你的提款额度。如果你的投资在一年内下跌 50%,继续同样的撤资计划并不是一个好主意。如果你突然需要一大笔钱,你最好也有一些应急基金。
- 经济状况可能转变
与过去相比,债券和股票市场的回报在未来可能会发生变化。一些人认为,由于世界经济增长放缓,股市在未来十年的表现不会那么好。然而,我们 1986 年至 2019 年的时间段确实包括 1987 年 10 月 20%的下跌以及 2000 年和 2008 年的严重熊市。
- 税务考虑
这绝对是要考虑的重要因素。由于定期派息较低,股票指数可能优于债券。这将有效地推迟税收。
- 养老金计划包容性
许多政府确实有帮助人们退休的社会项目。在加拿大,CPP(加拿大养老金计划)和 OAS(老年保障)是两个通常在 65 岁开始实施的计划。这些也应该包括在退休计划中。
Elo 有多重要?
elo 是什么?
Elo 是一个计算出来的分数,用于在国际象棋或篮球比赛中对选手进行排名。许多人已经看到了这个算法背后的实际公式,因为安德鲁·加菲尔德把它写在了社交网络中哈佛宿舍的窗户上。

Image from https://www.akitaonrails.com
有多重要?
当芒努斯·卡尔森与法比亚诺·卡鲁阿纳争夺国际象棋世界锦标赛时,马格努斯的 Elo 评分为 2835,而法比亚诺为 2832。这种差异有什么关系吗?Elo ~ 1250,我打败 Magnus 的几率有多大?在这篇文章中,我详细介绍了我如何使用 Python 来收集、转换和分析数据,以理解 Elo 对于预测游戏赢家有多么重要。
收集数据
为了理解 Elo 与游戏预测结果之间的关系,我首先使用下面的脚本从 chess.com 的 100,000 多场游戏中收集数据。在这里,我通过在 URL“【https://www.chess.com/live/game/】”的末尾添加一个随机数来遍历国际象棋游戏,并使用辅助函数 get_chess_info()获取游戏结果。这个函数返回一个字符串,如下例所示,所以我使用第二个辅助函数 parse_text()将它转换成有用的数据。
eono619 (1243) vs Rogeriothales (1201). eono619 won on time in 59 moves. The average chess game takes 25 moves — could you have cracked the defenses earlier? Click to review the game, move by move.
我用两个助手函数提取数据,然后用 csv 库的 DictWriter 方法将其全部写入一个. csv 文件。
在一些额外的特征工程之后,我得到了如下形式的数据:

探索性分析
现在有了收集和转换的数据,我继续进行分析。为了确定 Elo 在预测游戏结果中的重要性,我查看了 1)两个玩家之间的 Elo 评分差异,以及 2)谁赢得了游戏。但是首先,我很快检查了数据,从玩家评分的分布开始,不出所料,它是正态分布的。

然后,我继续讨论玩家评级之间的差异。Chess.com 将技能水平相似的玩家配对,因此两个玩家之间的 Elo 差异分布也呈正态分布并以 0 为中心是有道理的。

要了解玩家之间的 Elo 排名差异有多大,一种方法是查看在 Elo 差异的每个级别上赢得游戏的百分比。然而,小样本会引入很多噪声,所以我首先检查在两个玩家评级之间的每个增量点上,我是否有足够数量的游戏。对于-100 到+100 的 Elo 差异,看起来我在每个级别至少有 100 场比赛,所以我很高兴继续前进,看看胜率。

通过对玩家之间的 Elo 差异进行分组,并取“赢”列的平均值(赢=1,输=0),我就可以得到每个 Elo 差异的胜率。除了数据中的一点噪音之外,玩家之间 Elo 差距的前 50 分与游戏结果之间有着非常明显的关系。在这个范围之外,趋势似乎趋于平稳,一个人高于或低于对手的每一个增量点似乎对她赢得比赛的机会都不太重要。

逻辑回归
另一种观察 Elo 重要性的方法是通过使用玩家之间的 Elo 差异训练逻辑回归模型来预测获胜者。

顺便提一下,我展示了 ROC 曲线,该曲线针对不同的分类阈值绘制了真阳性对假阳性。曲线下的面积,通常称为 AUC,是. 69;对于一个单一预测模型来说还不错。
Credit to Susan Li’s article (https://towardsdatascience.com/building-a-logistic-regression-in-python-step-by-step-becd4d56c9c8) on TDS for the code to make the ROC curve

我现在可以使用我训练的逻辑回归模型来预测在两个玩家的 Elo 评级之间的每个差异点上赢得游戏的概率。将预测叠加到原始数据的观察结果上,我们看到一个非常相似的关系,如果不是稍微平滑的话。

用这个模型来预测我和国际象棋世界冠军芒努斯·卡尔森的比赛,我被给出了 2.227e-08 的获胜概率,老实说,这听起来是对的。对于更现实的游戏,我在 Elo 差异的 5、10、15、20、30、40 和 50 点水平上观察逻辑回归模型的预测。

本文背后的完整代码和数据可以在我的 GitHub 上找到,感谢阅读。要获得所有媒体文章的完整访问权限,请点击此处!
一平方米要加多少钱?

Photo by Deva Darshan
里士满建筑面积与房价的简单线性回归分析
我们研究了澳大利亚墨尔本郊区里士满的建筑/楼层面积和房屋的价格之间的关系。
这里的目的是展示探索数据以揭示关系、为分析做准备以及理解线性关系的端到端过程。
这篇文章分为两部分:
- 探索数据
- 应用线性回归
请随意跳到您感兴趣的步骤,因为它们可以按任何顺序阅读。
我们的分析使用了从域刮来的来自 Kaggle 的墨尔本住房市场数据(完整版)。它包含价格,房间数量,郊区,建筑面积等房屋信息。
我们开始吧!完整的代码请访问我的 GitHub 库。
1.探索数据
在这一节中,我们深入研究了住房市场数据,看看房子的建筑面积和价格之间是否存在可能的关系,并希望应用线性回归模型。
首先,让我们快速浏览一下我们的数据。
Viewing and cleaning our data

Table 1 — Summary Output
现在,如果我们看第一个表(从melbourneHousePrices.head()开始),有几个 NaN 值。理想情况下,我们应该调查这些值存在的原因,并适当地处理每一个值,但是对于本例,我们将删除所有包含 NaN 值的行。因此,在清理数据集之后,我们还剩下 8887 行。
总共有 21 个栏目,每个栏目都有描述房屋的有趣而有用的信息。虽然我很想深入分析每一个问题,并将其纳入我们的分析中,但我们今天的主要关注点将是BuildingArea和Price。
- 建筑面积,指房屋占用的建筑面积。这通常以平方米或平方英尺来衡量。
- 价格,这是指房屋的价格,用澳元($)表示
就我个人而言,我发现可视化两个变量之间关系的最快和最好的方法是散点图。所以,让我们就这么做吧!

Figure 1: Scatter plot of House Price and Building Area
好了,没有明显的线性关系,所以这将是文章的结尾…
坚持住!我们有一些异常值!
正是这些异常值扭曲了我们的散点图。我们无法辨别 0 到 500 米之间拥挤的房屋的大致位置,因为房屋的高度超过 3000 米(有趣的事实是,这是一个足球场的一半大小)。
我们应该放弃这个离群值吗?也许吧,但让我们先调查一下,因为它可能会给我们更多关于数据集的信息。

Table 2: 46 Athelstan Rd, Camberwell
如果我们查看显示的数据点,您会注意到一些非常有趣的事情。的土地面积是 730 m,比的建筑面积还小,这怎么可能?这可能意味着它有多个故事。
不幸的是,我看了一下的平面图和这个房子的描述,我一点也不明白它怎么会有 3112 平方米的建筑面积。
如果你能解释为什么,请留言,我很想知道答案!
让我们试着去除这个异常值,看看我们的散点图是如何变化的。
Removing outlier with Building Area of 3112 m²

Figure 2: Scatter plot of House Price and Building Area (with outlier removed)
好的,我们的数据集开始看起来好一点了,但是仍然有异常值扭曲了我们的图,没有明确的线性关系。
记下我们上次的异常值调查,让我们根据建筑面积调查前 10 所房屋,看看我们是否能观察到任何模式。我们也将只提取总列的子集(即郊区、距离、建筑面积和价格)。

Table 3: Top 10 Building Areas
查看表 3,你可以看到每栋房子都属于不同的郊区。一些与墨尔本中央商务区距离相似的郊区房屋也有相似的建筑面积(例如Brunswick和Kew)
是否值得对某个特定的郊区进行过滤,以查看其房屋在建筑面积和价格之间是否呈现线性关系?
首先,让我们看看哪些郊区的房子在数据集中最多,因为我们希望有一个良好的样本量。

Table 4: Suburbs with most houses in data set
我们可以选任何一个郊区,但是我们选里士满吧!
酷,让我们过滤里士满的房屋数据,并再次在散点图上可视化。

Figure 3: Scatter plot of Richmond House Price and Building Area
好吧,好吧,好吧…我们这里有什么?线性关系。
里士满房价和建筑面积之间似乎存在正相关关系。这让我们可以开始构建我们的线性回归模型。
继续下一个!
2.应用线性回归模型
在这一节中,我们试图用一个线性回归模型来拟合里士满房价和建筑面积之间的关系。
我们将清除数据中的任何异常值或错误点,然后理解回归输出。
首先,让我们用一个箱线图来可视化我们的数据。

Figure 4: Box plot of building area for Richmond houses
我们可以从图 4 中确定以下几点:
- 看起来最小值为 0 米
- 从 200 米向前有 5 个异常值
先说第一点,里士满有一套建筑面积为 0 平方米的房子,很奇怪,让我们来看看。

Table 5: House with Building Area of 1 m²
建筑面积实际上是 1 平方米,但的土地面积为 0 平方米。在调查了这个在线房产后,很明显这不是一个茶水间,但比那个大得多。因此,这个数据点是不正确的,所以让我们把它过滤掉。
接下来,我们有 5 个 200 米以上的异常值。为了识别这些异常值,我们使用 1.5 倍 IQR 法则。

Table 6: Richmond house outliers based on Building Area
虽然根据 IQR 计算,这些房子被认为是高异常值,但我将把它们保留在数据集中。原因是,如果我们回到图 3 中的散点图,这些值对于捕捉房价和建筑面积之间的线性关系非常重要。
现在我们已经清理了数据并评估了所有的异常值,我们可以使用最小二乘回归来构建我们的回归模型了!

Figure 5: Linear Regression Plot
我们可以看到我们的回归线与数据非常吻合,所以让我们看看结果:

Table 7: OLS Regression Results
我们的回归模型如下:
价格($)= 14140+10620 *建筑面积
OLS 回归结果的关键要点:
- 基于调整后的 R 平方,我们的回归模型解释了其均值附近 70.6%的价格可变性。
- 我们有一个截距 14,140,根据 0.05 的显著性水平,它是不具有统计显著性 (p 值= 0.817)。
- 建筑面积系数为 10620,具有统计显著性 (p 值很小)。
让我们详细阐述每一点。
外卖 1:
尽管我们已经发现我们的模型解释了其均值附近价格总方差的 70.6%,但我们不能就此罢休。重要的是我们检查残差图,以检查我们的模型的任何解释能力是否存在于我们的残差中,因为这些是随机的和不可预测的。
回归存在两个组成部分,一个确定性的和随机的组成部分。对于随机成分,这意味着我们观察到的价格和实际价格之间的差异应该是随机的。

Figure 6: Standardised Residual Plot
我们可以看到,残差图上的点随机分布在零附近,我们无法辨别任何模式。这意味着我们不能用一个价格剩余来决定下一个价格剩余的价值,因此不存在解释力。(这就好!)
外卖 2:
我们有一个统计上无关紧要的截距 14140,我们如何解释这个?
对于我们的模型,截距是当我们的建筑面积为 0 平方米时里士满的一栋房子的价格。这意味着对于一栋没有建筑面积的房子,它的价格将是 14,140 美元。我的信念是,无论截距是否显著,它都应该被忽略,因为一栋没有建筑面积的房子卖 14140 美元是不现实的。然而,对于建筑面积变得更加现实的情况,例如 30 平方米,截距在建立基线房价时将是重要的。
外卖 3:
我们发现建筑面积的系数为 10620,具有统计学意义。我们如何解读这一点?
首先,由于系数大于零且具有统计学意义,里士满房价与其建筑面积之间存在正相关关系。
其次,在所有其他变量保持不变的情况下,建筑面积每增加一个单位,里士满的房价就会增加 10,620 美元。
然而,重要的是我们要考虑回归系数的不确定性(即 95%置信区间),因此我们可以将其表示为:
保持所有其他变量不变,楼面面积增加 1 平方米,里士满的房价将大约增加 9524 美元,达到 11700 美元。
最后…
我希望这篇文章已经让你理解了准备线性回归数据的过程,以及如何理解结果。这个例子用于说明简单线性回归的应用,但是在以后的文章中,我计划应用不同的方法,比如多元线性回归。
如果您对我的工作有任何反馈,我可以如何改进或任何您认为不正确的地方,请告诉我!感谢您的阅读!
数据科学到底需要多少数学?
如果你目前正在学习数据科学,我确信一切看起来比实际需要的要复杂得多。只要在谷歌上快速搜索一下这个领域的先决条件,就会发现一些让你焦虑的东西——那就是数学。
但是数据科学家在现实中到底用了多少数学? 继续阅读了解。

Photo by Doug Maloney on Unsplash
如果你要在谷歌上快速搜索数据科学中的数学,你可能会看到一个 Quora 帖子,一些数学博士、智商 180 的大脑互动体以如下方式回复了这个帖子:
“嗯,老姐,你需要掌握:
-高等线性代数、多元微积分、向量微积分、弦理论、广义相对论、量子场论、生命的意义、功夫
只有这样,你才能考虑学习一些基本的编程和分析。"
好吧,也许,只是也许我有点夸张了。但是你明白了。许多“参考资料”陈述了许多先决条件,在考虑 Python 和机器学习的外部世界抽象之前,您应该在睡梦中了解这些先决条件。
By GIPHY
是啊,好像有道理。
事实并非如此,这让我很恼火,因为虽然我非常尊重任何拥有数学或类似领域高等学位的人,但并不是所有的数据科学工作都是为他们保留的。
在接下来的几节中,我将把我第一次进入这个领域时发现的最相关的东西进行分类,希望它们也能很好地适合你。
先学习直觉
人类不应该手动进行高级计算,我很想知道为什么这么多大学强制采用这种方法。好像考完试两个星期后你还会记得。
为什么我有勇气这么说?嗯,这是因为我们在 21 世纪,我们有该死的电脑。这些不仅仅是为了发送电子邮件和玩游戏,也是为了繁重的数学工作。速度有多快,错误有多少就不用说了。
作为一个人,你应该专注于发展每一个主要数学主题背后的直觉,并知道在什么情况下该主题适用于你的数据科学项目。不多不少,但这让我想到了下一点。
By GIPHY
手工做东西是没有意义的
你没听错。现实生活不是学校,在你的工作中,很可能只有最终结果才是最重要的,因此你可以用你现有的知识做出什么。
****你的老板很可能不会在意你已经先在笔和纸上实现了渐变下降,然后在 Python 中实现了渐变下降。在他/她关心的极少数情况下,这可能是针对你在解决琐碎任务上花费了过多的时间。
如果你在写方程上犯了什么错误,那就留给你自己的时间吧。
By GIPHY
所以,你是说我不需要数学学位?
完全正确。
不要误解我的意思,我认为数学或重数学的学位是进入数据科学的一个很好的方式,但是没有必要知道所有的事情。
然而,这伴随着一个问题。
By GIPHY
如果你在面试一个潜在的数据科学职位,而面试官是一个比你懂更多数学的人,那么他很可能会给你一个的难题。你应该为那种情况做好准备。不代表每次都会发生,但要做好准备。
这与你不知道你应该知道什么(可能)无关,而是与你的面试官是阿迪·海德有关。他想通过让你看起来渺小来显得聪明。问问你自己, 那是你想要的工作环境吗?
金科玉律
你很可能以前听过这句话,但我觉得它需要一遍又一遍地重复:
比一般的数学家更擅长编程。
比一般的程序员更擅长数学。
就这么简单。数据科学是多个领域的混合体。你不应该在任何一个方面都是最好的,而是应该努力在每一方面都做到足够好。牢记大局。****
在你走之前
我只想再说一次,这篇文章不是针对数学专业或博士的垃圾言论。正如我之前所说的,我对他们怀有最高的敬意。
只是当涉及到现实世界和一个普通的数据科学工作角色时,有比了解数学的一切更重要的事情。数学只是你用来获得所需结果的工具,对于大多数事情来说,有一个好的直观方法就足够了。
感谢阅读。保重。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
** [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)**
在 21 点中,100,000 美元将为您赢得多少?

赌场不是很神奇吗?从戏剧的角度来说,你走进一个赌场,所有明亮的灯光照耀着你,有一种强烈的,舒缓的和感性的气味,你听到人们庆祝他们的胜利!现在你欣喜若狂,你迫不及待地想感受手中的筹码,你对自己说,这是你一直梦想的夜晚,你将赢得一生的胜利!你开始玩 21 点,你取得了重大的胜利,你觉得你在九霄云外,然后繁荣来了。连胜持续了多久?不多,嗯,这个场景你看着眼熟吗?(还是只有我经历这个!)
在我最近去了一次赌场后,我想一定有赢的策略,我必须找出赢这场游戏的概率。我在谷歌上搜索了 21 点策略,几乎所有的网站都将我引向赌博的基本21 点图表,我很快就明白了,现在是测试的时候了,除了模拟玩家和庄家之间随机分配 21 点,还有什么别的方法呢?
嗯,这正是我所做的,让我们假设我们有 100,000 美元来下注(我真希望!),每次下注将花费我们 10 美元,我们玩 10,000 手牌。让我们想一想通过我们的模拟可以尝试回答的问题;
- 我玩一万手牌赢了多少?
- 赢和输的百分比是多少?
- 我打了几个 21 点?(最少 1000,十分之一手?)
- 经销商赚多少钱?
- 哪些手最幸运?
- 我们能否创建一个矩阵,显示玩家牌相对于庄家牌的胜率?(我将在下次去赌场时用它来赚钱!)
模拟设置
为了模拟赌场游戏,让我们有 6 个玩家在玩,每个人都有 100,000 美元的底池(大玩家,伙计!)和一个经销商。每次下注 10 美元,赢 21 点的回报率为 3 : 2,也就是说,10 美元的赌注将返回 25 美元(包括您的 10 美元赌注),而正常的高赢或庄家破产的回报率为 1 :1,也就是说,10 美元的赌注将返回 20 美元。出于模拟的目的,让我们忽略保险,分裂,双倍下注和任何其他奖金发挥。由于所有赌场现在通常处理一副牌中的 6 组牌,我们将使用相同的牌,即每轮总共 312 张牌——我们将每轮洗牌以模仿连续洗牌机(拜拜算牌!).庄家开始与玩家 1 至玩家 6 发牌,并结束与自己的发牌。他的第一张牌也面朝上。玩家将根据他们发出的前两张牌和庄家面朝上的牌的总和,再次根据基本二十一点策略(请参考此处),决定打出更多牌还是继续。好吧,现在让我们运行模拟,看看结果,好吗?
游戏结果
让我们先来看看所有玩家一起玩的所有牌的总统计数据,然后再来看看单个玩家的统计数据:

在总共玩了 60,000 手和总共下注 600,000 美元之后,玩家们总共只赢了 586,625 美元即下降了 2%。赢款与下注的比率为 0.98,只有大于 1 的系数才能让您从下注中获利。让我们看看赢的概率 —从多次运行来看,范围总是在 42%到 43% 之间,输的概率总是在 47%到 49% 之间,输的概率总是高于赢的概率,这表明如果我们玩大量的手牌,那么赌场最终将比我们任何人都赚钱。让我们来看看21 点命中率** —我们最初的目标是从 10,000 手牌中打出 1,000 个 21 点,也就是说 10%中有 1 个23,我们已经从 60,000 手牌中打出了 2845 手牌,命中率只有 5%左右。我们最幸运的手是哪一只?—毫无疑问,它们是一对10(10,J,K,Q——在 21 点中具有相同的值)。让我们来看看单个球员的数据。******
玩家统计

一个有趣的观察结果是,每个玩家的统计数据彼此相似,并且与总体组合统计数据相似。上一节的所有推论在这里同样适用。我们来看看一些失败的统计数据怎么样?

从多次运行中,我们看到一个玩家爆发(他们的牌和超过 21)~17%到 19% ,而他们打败了(庄家的牌和高于他们)大约 28%到 30%。这清楚地表明基本 21 点策略使人在打出更多牌时非常保守。当庄家的赔率为 24%到 25% 倍时,少于玩家的赔率%。也许我们应该看看输赢矩阵,做一些调整来改善输赢统计。

幸运手有什么惊喜吗?不完全是,正如预期的那样 20 和 21 给你最多的胜利。有趣的是,17&18****输 的概率非常高~60%比 70% 。而 13,14,15&16——概率是输 是>的 50%到 60%。这可能是我们可以改善损失的战略领域。
赢百分比矩阵,玩家面对庄家正面牌的牌数总和

突出显示(加框)的区域胜率很低,这可能是我们改进的重点,目前 14,15,16 & 17 对 8,9,10 & 11 的庄家正面牌的策略是打出更多的牌以获得对庄家的优势,如果我们能更仔细地看看我们到底是如何输掉这些牌的——如果我们把牌弄坏了,或者如果我们被庄家的大牌打败了,我们就可以根据需要临时制定策略。
推理
就策略而言,玩家和为 12,13 的胜率相当不错,20 和 21 的胜率非常高。基本策略看起来肯定能让我们在重要牌(~50 手)中获得 42%的胜率,但这个胜率根本不足以盈利。如果我们能把胜率提高到 50%或 55%左右,我们肯定会有利润。那么,我们如何提高胜率呢?—等着瞧吧,鼓声——本文的第二部分将为您提供这些细节。现在,请记住我的朋友,如果你在玩 21 点,并且你当前的胜率(赢的手数与玩的手数之比)超过 55%或更高,我建议你离开牌桌,领取你的奖金!我希望这篇文章能对赌博模式有所启发,并让你对赢的几率有所了解。
试试模拟?
对于所有想看代码和尝试模拟的人来说——https://github.com/Mojocolors/Blackjack-Odds。直到第二部分——快乐阅读,快乐玩耍!
神经网络是如何学习写作的
写作文本的自然语言处理模型的发展综述
在一些历史学家的在线论坛上,一个用户问了一个问题:
普通的苏联公民有幽默感吗?
不久之后,他们收到了一封长达五段的回信。在阐述一个复杂的答案之前,首先要有一个合理的介绍性解释:
在苏联,有一种普遍的幽默感,这种幽默感常常与苏联身份和***联系在一起。
一些巨魔回复了一个没用的嗨,并立即被版主指责。乍一看,这个线程没有什么特别不寻常的。除了…这个论坛上的帖子不是来自人类,而是来自人工智能代理,或机器人。
我提到的帖子只是来自 r/SubSimulatorGPT2 的一个例子,这是一个专门用于由基于 OpenAI 的 GPT2 的 bot 自动生成的帖子的子编辑。如果你认为上面关于苏联幽默的段落只是它记忆和复制的东西,那很可能不是这样:谷歌搜索显示这句话的一半都没有出现。
让机器人在 Reddit 上互相对话并不新鲜:r/SubredditSimulator 已经这样做了几年。这里的区别是生成的文本质量有了巨大的飞跃。虽然较老的机器人可以用一些随机的胡说八道来逗你开心,但基于 GPT2 的机器人实际上可以让你暂时相信他们是真实的人——当他们最终说出一些荒谬的声明时,这往往会变得更有趣。
为什么会有如此聪明的人工智能模型?事情不是一夜之间就变成这样的。开发能够复制人类语言的模型的研究已经进行了几十年,但直到最近才真正令人印象深刻。在这里,我将展示语言建模进化的概述,以及为什么它除了创建有趣的机器人之外如此有用。
文本生成的演变
马尔可夫链和 N 元文法
来自旧的 r/SubredditSimulator 的机器人使用马尔可夫链,这是一种成熟的生成序列的技术。像现代神经网络一样,它们从数据中学习,但要简单得多。
基于马尔可夫链的模型假设一个句子中的每个单词只依赖于它前面的最后几个单词。因此,它将观察到一个给定句子的概率建模为组成该句子的所有 n 个字母——由 n 个单词组成的序列——的组合概率。一个 n 字母的概率可以近似为你在你的语言中能找到的所有可能的 n 字母中看到该特定序列的次数。
训练马尔可夫链模型基本上包括从文本数据中估计这些概率。下图说明了这个概念:

A small sentence decomposed in trigram probabilities. N-grams near the sentence beginning usually include a pseudo-token
在上面的例子中,基于三个单词(或三元模型)序列的马尔可夫链决定了令牌巧克力跟随我喜欢的概率。接下来,它将确定看到像巧克力一样跟随的令牌蛋糕的概率,但不再考虑令牌 I 。
然后,为了生成新的文本,我们只需要从模型给我们的概率中一次抽取一个单词。这种过程被称为自回归,其中每一步的结果都取决于前一步模型的预测。
抽样给了我们一些模型输出的变化。如果我们总是根据模型选择最可能的单词,它将总是产生相同的文本。
问题是,如果我们像这样分解问题,我们永远不会发现一句话有什么奇怪的地方,比如我喜欢巧克力蛋糕,我喜欢巧克力蛋糕,我喜欢巧克力蛋糕:三个记号的每一个序列听起来都非常正常,除此之外这个模型不关心。
如果我们尝试观察更长的序列,我们会看到一个指数爆炸。考虑到 1 万(10⁴)单词的小词汇量,我们有 1 亿(10⁸)可能的二元模型,1 万亿(10)可能的三元模型和 10 万亿(10)可能的四元模型!其中大多数都是无意义的,例如香蕉香蕉漩涡香蕉,但这是问题的一部分:许多完美的 4-grams 也不会出现在训练数据中,并且模型没有办法区分哪些序列是荒谬的,哪些序列是好的,但不幸的是没有被发现。

Banana banana maelstrom banana
规避较长字母的稀疏性的一种方法是使用一种语言模型,将它们与较短的字母组合起来。所以,也许我们的训练语料库没有出现普遍幽默感,但它确实有一些幽默感。与此同时,甚至连香蕉风暴和香蕉风暴都闻所未闻。这当然会有所帮助——但是考虑到价格,我们不能如此信任更长的克数。
N-gram 计数是我们多年来语言建模中最好的,并且它们在使用大量的谷歌 n-grams 时表现得相当好。尽管如此,我们可以看到它们非常脆弱,由马尔可夫链生成的超过五六个单词的句子几乎没有任何意义——同样,你可以查看更老的 subreddit 模拟器。
单词嵌入和神经语言模型
单词嵌入是当今任何人在 NLP 中首先学会的事情之一:单词到多维空间的投影。它们的巨大优势是,用余弦相似度来衡量,具有相似用法/意义的单词会得到相似的向量。因此,涉及相似单词的单词向量的矩阵乘法倾向于给出相似的结果。
这是基于神经网络的语言模型的基础。现在,我们可以将每个单词视为数百维的密集向量,并对其进行数值运算,而不是将每个单词视为一个原子符号。
在其最简单的形式中,神经语言模型查看一个 n 文法,将它的每个单词映射到它们相应的嵌入向量,连接这些向量,并将它们馈送到一个或多个隐藏层。输出层决定词汇表中每个单词下一个出现的概率,计算为分数的 softmax 。
有趣的是,神经模型并不计算出现次数来确定概率,而是学习可以为任何输入计算它们的参数(权重矩阵和偏差)。这样,当我们对较长单词的计数不可靠时,我们不需要退回到较短的n-gram,最好的是,我们甚至可以在训练数据中从未见过的 n -gram 之后计算下一个单词的合理概率分布!

A simple MLP (multilayer perceptron) language model predicting the next word after the last given three.
第一个神经语言模型于 2003 年提出,比深度学习时代早了十年。那时候,没有人在 GPU 上运行神经网络,计算机更慢,我们还没有发现很多现在常用的技巧。这些模型会慢慢变得更受欢迎,但真正的突破只发生在递归神经网络上。
递归神经网络
可以说,语言生成的最大进步来自于递归神经网络(RNNs)的出现,更具体地说,是长短期记忆(LSTMs)的出现。与我之前提到的最简单的网络不同,RNN 的上下文不仅限于 n 个单词;它甚至没有理论上的极限。
Andrej Karpathy 有一个很棒的帖子,解释了他们是如何工作的,并展示了很多例子,在这些例子中,他们学会了制作类似莎士比亚戏剧、维基百科文章甚至 C 代码的文本。
与我之前展示的简单网络相比,RNN 的主要改进在于它们保留了一个内部状态——也就是说,一个表示网络记忆的矩阵。因此,RNN 可以一个字一个字地连续阅读,更新其内部状态以反映当前的上下文,而不是只看固定的窗口。
使用 RNNs 的文本生成遵循与马尔可夫链相似的基本原理,以自回归的方式。我们对第一个单词进行采样,将其输入神经网络,获得下一个单词的概率,对第一个单词进行采样,以此类推,直到我们对一个特殊的句子结束符号进行采样。
RNNs 在 2014 年和 2015 年左右在 NLP 中变得非常流行,并且仍然被非常广泛地使用。然而,他们优雅的体系结构和谨慎的内部状态有时会成为一种负担。让我用这个例子来说明:
和约翰一起来的男孩非常聪明。
注意和的男孩意见一致,而不是和约翰意见一致,尽管两者更接近。为了正确地生成这样的句子,RNN 需要跟踪复数名词,直到它生成匹配的动词。这个例子相当简单,但是一旦你有了更长的句子,事情就变得更难了,特别是在更喜欢屈折和长距离依赖的语言中。如果我们不需要将如此多的信息塞进有限空间的内存,而是只需要回头看看前面的单词,检查还缺少什么,那就太好了。

The RNN internal state keeps track of information about all seen words. In this example, the colors show how it can get increasingly difficult to fit everything into a limited space.
为了缓解这种情况,引入了注意机制。它允许 RNN 这样做:在产生下一个输出之前回顾所有以前的单词。计算关注度实质上意味着计算过去单词的某种分布(也就是说,对它们中的每一个进行加权,使得权重之和等于 1),然后根据接收到的关注度成比例地聚集这些单词的向量。下图阐释了这一概念。

The attention mechanism allows an RNN to look back at the outputs of previous words, without having to compress everything into the hidden state. The condensed RNN block before the intermediate outputs is the same as when not using attention.
但是还是有一点不方便。训练 RNN 没有利用可并行化的硬件操作,因为我们需要在查看字 i+1 之前处理每个字 i 。
除此之外,你有没有注意到上图中的中间输出向量在每个单词之后变得更加丰富多彩?这象征着句子中更靠后的词可以接触到前面的词,而开头的词看不到后面的词。根据单词后面的内容对单词进行建模,起初听起来可能违反直觉,但我们一直都在这样做。考虑英语中的名词-名词复合词,比如第一个例子中的巧克力蛋糕。当我们一听到或读到蛋糕这个词,我们就知道巧克力只是在描述它,并不是短语的中心。我们这样做是因为我们可以回溯我们头脑中的信息,但线性 RNN 做不到这一点。因此,虽然 RNNs 可以做得很好,但仍有改进的空间。
变形金刚(电影名)
Transformer 是 2017 年推出的神经网络架构,旨在解决 RNNs 的缺点。它的核心思想是严重依赖注意力,以至于根本不需要内部状态或复发。
变换器中的每个隐藏层都有一个注意力组件,后跟一个默认的前馈(或 MLP)变换。首先,转换器计算每个单词对所有单词的关注程度,包括它自己和它后面的单词。在 RNN 中,这些单词的向量按照接收到的注意力的比例进行缩放和求和,从而产生上下文感知向量。这个结果向量然后经过前馈变换,结果是该变换器层的输出。
变形金刚通常有很多层,这使得它们能够学习单词之间越来越复杂的相互作用。并且为了考虑单词顺序,输入单词嵌入用编码其位置的附加向量来扩充。
这是对转换器的一个相当简单的描述,下面展示了一个这样的层。实际的架构相当复杂,你可以在后的图解变压器中找到更详细的解释。

Simplified view of the first layer of a transformer network. The same weights are used in all the attention and feedforward operations in a given layer.
堆叠大约 6 层、12 层甚至 24 层,我们就能得到非常丰富的编码向量。在最后一个之上,我们可以放置最终的输出层来产生下一个单词的概率分布,就像在其他模型中一样。
当生成一个新句子时,我们必须在每个新单词后重新运行整个转换器。这是必要的,以便允许以前的单词考虑新的单词,这是 rnn 所不能做到的。
在巧克力蛋糕的例子中,变形金刚可以让巧克力在蛋糕的第一层上出现。因此,它的向量编码了更精确的意义信息,这些信息将被传播到更高的注意力层。
我之前也提到过,RNNs 没有让我们利用并行操作的优势。您可能已经注意到,由于我们也必须用 Transformer 一步一步地生成新单词,这里也是如此。嗯,在运行你的模型时是,但在训练时不是。
在训练过程中,我们可能会让一个转换器并行预测一个句子中的所有单词。我们只需要屏蔽我们想要预测的位置 i 处的单词及其后面的单词,因此网络只能查看过去的位置。没有隐藏状态-无论前一个时间步长如何,都会在每个时间步长重新计算变换器中的所有隐藏层。
我们现在在哪里
在许多 NLP 任务中,包括语言建模,转换器是目前最先进的。研究人员不断提出一些改进建议,但整体架构几乎保持不变。
我在本文开头提到的 GPT-2 模型是一个 Transformer 实例。那个特定的有 3.45 亿个参数,由 OpenAI 在一个巨大的文本集合上进行训练,然后在 Reddit 的几十兆字节的文本上进行微调。
OpenAI 提供的预训练模型在生成文本方面总体来说很棒,但要使一些东西更具体,你需要对它进行微调——也就是说,用一些你感兴趣的数据对它进行进一步训练。在子漩涡模拟器中,GPT-2 的不同版本在 100 多个子漩涡中相互对话,你可以清楚地看到它们是如何学习自己的风格和特质的。这对于在不同子线程中对机器人进行微调的线程来说尤其有趣!
顺便说一句,那个预训练的模型甚至不是 OpenAI 最好的。他们已经训练了一个更强大的,有 15 亿个参数的,但是因为害怕恶意使用而决定不发表。这引发了一些关于人工智能会带来什么危险的有趣问题:不是科幻小说中的杀人机器人,而是一位可以不知疲倦地争论或创造故事的多产作家。机器学习领域内外的许多人不同意这种语言模型是危险的,但这一集至少表明,人工智能的影响正成为一个更重要的辩论话题。
除此之外还有什么呢?
好吧,但是除了创建有趣的 Reddit 线程,这些模型还有什么用呢?当然,有很多 NLP 应用程序!你可能已经意识到,一个非常简单的键就在你手机的键盘上,就是 对。
任何涉及文本生成的 NLP 任务都可以从这些模型中受益。语音识别就是一个例子:在这里,语言模型必须根据一些语音输入找到最可能的单词序列,而不仅仅是以前的单词。
另一个自然的应用是翻译:这是一项给定另一种语言的文本,寻找最可能的单词序列的任务。事实上,机器翻译正是关于变形金刚的原始论文所处理的应用。
神经语言模型的有用性不需要局限于语言生成。一旦一个模型能够生成看起来几乎像人类的文本,这意味着它学到了很多关于单词如何相互作用的知识。这些知识编码在许多参数中,对于初始化许多不同任务的新 NLP 模型非常有用:文本分类、实体识别、问题回答和许多其他任务。
利用预先训练的模型来初始化新的模型被称为迁移学习,它现在被非常频繁地使用,并取得了巨大的成果——事实上,它是训练这些庞大的神经语言模型的主要动机。这是一个非常有趣的工作,值得另发一篇文章。
一些有趣的资源
- OpenAI 发布的 GPT-2 模型你可以用它来生成文本
- 一个在线平台尝试 GPT-2
- 微调 GPT-2 的教程和生成假对话的例子
- 另一个关于产生笑话的教程。可悲的是,神经网络仍然不是超级有趣。
- 代码用于训练字符级 RNN 语言模型
- 由 LSTM 制作的莎士比亚戏剧样本
神经科学家如何分析来自透明鱼脑的数据:第 2 部分,聚类神经数据。
PCA 和 K-means 将具有相似活动的神经元分组
在第一篇文章中(你可以在这里阅读),我描述了神经科学家如何将来自透明鱼脑的大脑图像预处理成可利用的数据集:一个 2D 矩阵[神经元 x 时间],代表每个时间点每个神经元的活动。

Two non-overlapping populations of amygdala neurons in the mouse brain. Picture from Mark Cembrowski, from the Cell Picture Show 2018 (have a look here for many gorgeous photos !)
在这篇文章中,我们将看到这些数据如何被用来回答这个问题:我能把具有相似活动特征的神经元归为一组吗?对于神经科学家来说,找到具有相同活动的神经元群是一个极其重要的问题,因为同步神经元群可能是大脑区域电路中的“构建模块”的基础。
第一步是归一化每个神经元的活动,以减去背景活动。确定称为 F0 的基线活动值:例如,它可以是记录的前 3 分钟期间的平均活动。归一化的方法是去除 F0,然后除以 F0: (F — F0)/F0。因此,最终结果用δF/F0(简称“DFF”)表示:这个四维值代表活性相对于基线的增加或减少,用百分比表示。举个例子,
- 当 F=F0 时,则δF/F0 = 0(与基线相比没有增加)
- 当 F=2*F0 时,则δF/F0 = 1(与基线相比增加 100%)。
(注:F 代表“荧光”,因为神经活动是通过神经元活跃时发出的荧光强度间接测量的。)
数据标准化后,就可以进行聚类了。目标是将神经元分组在一起,因此——对于记录在 T 个时间戳中的 N 个神经元——在 T 维空间中将有 N 个数据点。为了可视化,让我们在 3 个时间戳期间在 3D 空间中绘制 6 个神经元的数据集:

An example data set for visualisation : 6 neurons recorded over 3 time frames = 6 data points in a 3D space.
事实上,神经元不仅仅在 3 个时间步长内被记录…实际数字可以是大约 50000 帧(例如:20Hz 下 45 分钟的记录= > 54000 个记录帧),所以这个图应该有 50000 个维度…
但是,我听到你说“ 50000 个维度,太多了!我真的要把它们都留着吗?反正我肯定所有维度都没那么有用”。你可能是对的:想象一下,有一段时间,大脑什么也没发生?(在健康的大脑中,这在生理上不太可能,但让我们假设一下)。或者在某个时候,所有的神经元突然变得超级活跃:这可能是可能的,但是如果我们的目标是将神经元分成几个集群,这将不会提供太多信息…所以,在集群之前,我们可以用 PCA (主成分分析)减少我们数据集的非常高维度。
降维在很多帖子里都有描述,这里我就长话短说。让我们看一个简单的 2D 数据集,如图 a):十几个人的年龄和身高。我们可以在 b)中看到,数据遵循一个总体“趋势”,用箭头表示。如果我们将数据点投影到那个箭头上(如 c 中所示),我们仍然可以很好地了解数据的分布。这个“趋势”就是第一主成分(PC)。在图 d)中,我们可以选择仅在一维而不是二维中表示我们的数据。我们减少了维度的数量,但我们仍然可以捕获关于数据集的重要信息。

Little sketch of dimensionality reduction with PCA.
PCA 的目标是基于数据集的“原始”成分(这里是年龄和身高)计算主成分。借助上面的示意图,您可能已经注意到箭头捕捉到了数据集方差最大化的方向,或者更简单地说,在原始空间(a 中)最远的 2 个点在 PCs 空间(d 中)仍然最远。因此,PCA 背后的基本原理是找到数据集中方差最大的维度。
(备注:这是与 tSNE 完全不同的基本原理——t 分布随机邻居嵌入——这也是一种在神经科学中广泛用于高维数据集可视化的降维技术。这将在下一篇文章中描述!**

Diagonalization of the covariance matrix
一种方法是计算数据集的协方差矩阵并将其对角化。因此,你找到了一个新的空间,其中协方差矩阵是对角的:特征向量是主分量,特征值量化了每个主分量所解释的方差的百分比。对于 PCA,主成分是正交的。****

由于主成分是由原始成分组合而成的,它们不一定“意味着”与数据相关的任何东西。在我的例子中,沿着第一个 PC 的值将是年龄平方的平方根加上身高平方…这个组合允许我们只保留一维。
在我们的神经数据集中,第一维是神经元的数量(几百个)。使用 PCA,我们可以将第二维从大约 50000(时间帧)减少到 10(主成分)。
一旦对数据进行了归一化处理,降低了第二个维度,我们就可以使用一个简单的、众所周知的算法进行聚类: K-means 。同样,许多 TDS 帖子已经致力于这一算法(你可以在这里 观看动画)。因此,我将简单地评论一下毕晓普书中著名的方案。在下面的 2D 数据集中,我想分成 2 组:

From C. Bishop’s book “Pattern recognition and machine learning”, page 426
- 初始化 (a):随机选择聚类的中心(红色和蓝色十字)。
- 期望 (b):每个数据点被分配到最近的聚类中心。
- 最大化 (c):重新计算聚类中心(它们是彩色点的质心)。
- (d-e-f):重复期望最大化步骤,直到收敛(即聚类中心不再移动)。
(备注:如这里 所讨论的 ,聚类数 K 必须由用户选择。对于简单的数据集,这可以通过视觉检查来完成。但是对于高维数据集,选择正确的 K 可能很棘手。有几种方法可以帮助你找到一个合适的 K,如 这篇帖子中所述。)
使用 PCA 和 K-means,神经科学家可以将具有相似活动的神经元分组在一起。让我们看一个来自挪威 Yaksi 实验室的研究的例子。研究人员调查了斑马鱼的嗅觉以及大脑如何处理气味。他们对缰核(一个被认为整合来自感觉区域的信息的大脑区域)进行了成像,并检测了神经元,如我在第一篇帖子中所述。
在实验的第一部分,研究人员没有做任何具体的事情,但一些神经元无论如何都是活跃的。这叫做“自发活动”。科学家们执行了 PCA 和 K-means(要求 K=6),并根据神经元在时间上的活动将它们分成 6 个簇。我们首先可以看到的是,自发活动并不是随机的,具有相似活动的神经元在空间上是接近的!下图显示了按簇分组的神经元的活动概况,以及每个神经元在缰核中的位置:用相同颜色表示的神经元属于同一个簇。**

Spontaneous activity of habenular neurons. Left) neural activity in time (the traces are grouped in 6 clusters). Each row is a neuron, the color represents the DFF, introduced before. Right) spatial map showing the position of each neuron in the habenula (color-coded by cluster number). Figure found here.
在实验的第二部分,研究人员通过水向鱼传递一种气味(传递的时间由下图中的箭头表示)。他们再次执行了 PCA 和 K=6 的 K-means,并注意到气味传递期间的簇与自发活动期间的簇非常相似。****

Same legend than above, but during odor delivery. Figure found here.
因此,自发同步的神经元在气味处理过程中也很可能是同步的!这就像一些神经元已经“预先连线”在一起,使它们更有可能以类似的方式对气味做出反应。
大脑中的自发活动是如何组织的?这对信息处理意味着什么?这些问题非常好,激励了许多神经科学家!
我的搜救犬多大了?

Ruth, My Dog of Unknown Age
在相关数据集似乎不存在的情况下调查问题
去收容所挑选一只狗
如果你从未去过狗收容所,那里到处都是需要一个家的可爱狗狗。但它们通常也充满了规则,可能会妨碍找到适合你的宠物。例如:
- 在指定的参观空间一次只能遇到一只狗。
- 一天只能见几只狗。三只狗是我最常看到的极限。
- 你可以根据狗狗的简历来选择你会遇到的狗狗。在你去拜访他们之前,根本没有机会去了解他们的个性。
当然,这些避难所很棒。这些规则是为了狗和游客的健康和安全。但它们不是我所希望见到的我未来的毛皮宝宝。
当我到达马特维尔时,我找到了我一直在寻找的东西:

Muttville’s open visiting room (photo property of Muttville)
我坐在一张狗床上,等着看哪些狗向我走来。我想要一只既好奇又可爱的狗。我想要一只能和其他狗友好相处的狗。最重要的是,我不想选一只狗。我想让一只狗来选我。
当我想到去收容所找一只狗来收养时,我就想到了这一点。
爱上马特维尔和高级狗
在我准备带一只回家之前,我在一年的时间里去过马特维尔几次。在此期间,我爱上了马特维尔。
马特维尔的任务是为老年狗寻找家园。创始人知道收容所更容易为年轻的狗找到家。它们在传统方式下仍然很可爱,主人可能更容易训练它们,它们也不太可能有健康问题。马特维尔只收留年长的狗。他们向新宠物主人提供与狗的年龄相关的医疗费用报销。例如,当我第一次得到我的狗时,它需要做牙科手术,马特维尔支付了手术的全部费用。

The “Golden Mutts” getting dolled up for an early bird special adoption event (photo property of Muttville).
这篇博文的目的不是为庇护所做广告,所以我最后要说的是,他们的社交媒体很可爱。当我对着他们可爱的狗哇哇大叫的时候,他们的工作人员向我推销了养一只老狗的想法。
收养一只年长的狗的一些好处:
- 他们(有时)比小狗更容易训练,尤其是如果他们已经被以前的主人以任何方式训练过。
- 他们往往要冷静得多。
- 它们通常不需要像幼犬那样多的关注。
作为一个第一次养狗的忙碌的人,它吸引了我去养一只更安静的狗,它不需要我一直全神贯注。
露丝出场了
去了马特维尔很多很多次后,我遇到了 8 岁的露丝(当时她叫克丽克特),我开始了人生的新篇章。

Ruth and I just before I took her home for the first time. These days, she and I both look much less nervous when I carry her!
作为我收养文件的一部分,我得到了她的医疗记录和信息。我几乎懒得看一眼,因为我是第一次养狗,我不能更兴奋地把露丝带回家。

I was told to expect her not to be too clingy, but this is one of the only places she’ll sleep
露丝和我开始更加了解对方。当我在 Instagram 上贴满她的照片时,她的害羞消失了。我很快发现,虽然我被告知要期待她冷静和超然,但她实际上是充满活力和粘人的。

Ruth has a perpetual case of THE ZOOMIES
我越了解她,就越开始问这个问题——这只狗真的只有 8 岁吗??
然后我会接着问——在我遇见她之前,她的生活是什么样的?
挖掘曾经流浪狗的秘密
给我的记录很少。我有她在收容所接受的疫苗的信息,以及她在未来几周需要加强的疫苗。我被告知她患有牙病,需要尽快手术。除此之外,我只知道:
- 她可能一半是吉娃娃,一半是腊肠狗(有些人——不是我——称之为腊肠)。
- 我得到她的时候她大约 8 岁。
- 她有两个良性肿瘤。
- 当她到达收容所时,她超重了,在我把她带回家后,她需要继续减肥。
- 她到达收容所几天后就被阉割了。
- 她至少生了一胎,可能更多。
- 她被发现时是一只流浪狗,但她也有一个微芯片。安装微芯片的公司几年前就倒闭了,他们关于她的信息无法获取。
我根据露丝的个性、她喜欢/不喜欢的东西以及她在旧金山某些地区散步时的反应,对她之前的生活提出了一些理论。

A few quick hints about Ruth’s likes and dislikes (her second favorite activity after running around the house is, of course, sleeping)
但事实上,我不知道她是谁。我创造的故事将所有的片段组合在一起,这就是故事。
故事很难评价。但是作为一个数据科学家,一个简单到“我的狗多大了?”似乎很容易回答。我可以把她的所有特征代入回归模型并得到她的年龄作为输出的模型在哪里?
当我纠结于她小狗般的个性和她年迈的医疗记录之间的关系时,我只是不停地掉进谷歌兔子洞,试图找到这个问题的答案。
狗的年龄是怎么估计的?
简短的回答:牙齿。

Source: https://www.rescuedogs101.com/3-big-clues-to-how-old-is-my-dog/
对于幼犬来说,特征的比例(和客观的可爱程度)是一个很明显的迹象,表明这只狗非常年轻。根据一些兽医的说法,观察幼崽的乳牙/成年牙是如何生长的,可以提供+/-几周的年龄估计。
你会注意到上图中狗的年龄越大,估计它的年龄就越不精确。如果没有关于狗一生中牙齿护理类型的信息,这些界限就会变得更加模糊。一位兽医曾经告诉我,她猜我的狗在 4 到 10 岁之间——这不是一个令人满意的置信区间。
狗的年龄的其他暗示包括:
- 变老——和人类一样,随着年龄的增长,狗也变老了。但也像人类一样,这种情况的发生没有明确的年龄(查看一些资料,听起来像是狗在 5 +/- 3 岁时发生灰色)。
- 眼睛——年长的狗会丧失视力。他们也可能会在眼睛周围形成一种良性混浊,称为晶状体硬化。这似乎开始发生在 4 到 10 岁之间,并随着时间的推移而恶化。
- 听力——随着年龄的增长,狗会丧失听力。狗的听力损失很难量化。即使不是这样,我也认为这是另一个听力损失范围很广的领域。
- 体型——狗和人类一样,随着年龄的增长,越来越难保持脂肪。
我发现的模糊指标还包括:丧失行动能力、疼痛、丧失认知功能,甚至摇尾巴的次数…

According to Ruth’s tail wagging, she’s about a week old.
据一位兽医说:
估计狗的年龄是一门艺术,而不是科学。
品种是如何影响的?
我再从简短的回答开始:很多!据 PetMD 报道,
一只年老的吉娃娃可能是 18 岁,一只年老的大丹狗可能是 7 岁。
不仅品种起作用,而且品种内的狗的大小也起作用。例如,一只 6 磅的约克比一只 12 磅的约克衰老得更慢。然而,关于不同品种的狗和不同大小的狗如何变老,甚至有很多不同意见。

Disagreement between Sources on “Human Age Equivalent” of Dogs
狗的特征和年龄的数据集在哪里?
主观特征不在某个地方的数据集中是可以理解的。然而,有一个客观特征似乎可以提供一些见解。
从狗身上拔掉的牙齿数量以及狗的体重、品种和年龄的数据集在哪里?
在世界各地,都有兽医给狗做牙科工作。许多个体诊所可能有他们治疗的所有狗的这些信息。
这就是我们面临数据收集整体挑战的地方。不幸的是,即使所有的数据都已经被记录在某个地方,它也是昂贵的。并非每个办公室都以同样的方式记录数据。也许它都保存在一个文件中,但更有可能的是,它存储在每只狗的文件中。我不指望这些办公室有理由让这些数据可查询。他们可能连电脑里都没有。
我没有数据收集方面的背景知识,无法猜测需要花费多少人力去接触每一位兽医获取数据,跟进直到数据收集完毕,然后对数据进行分类,使其以相同的方式存储,但我相信这将需要大量的时间,并且从每一个品种中获得足够的样本量,以及足够的数据来解释该品种体重的影响,这将是一项昂贵的工作。
数据收集往往非常困难。 随着数据科学家越来越擅长创建程序来自动分析数据,我们可能会忘记,在计算机完成人工智能之前,许多许多人都在幕后记录、收集和清理这些数据。
在预测狗的年龄的情况下,收集所有这些数据的成本是否值得或许更好地预测狗的年龄的回报?收集所有这些数据只会发现目前可用的非常粗略的估计和预测一样准确。与此同时,在某个时间点后知道狗的年龄对你如何照顾那只狗没有什么影响。能够回答这个问题真的只是为了满足人类主人的好奇心。
还有一个关于创造这种预测模型的伦理问题。如果随着年龄的增长,狗越来越难被收养,那么创建这样的模型可能会对狗被收养的能力产生负面影响。也许问题不在于这些数据是否值得收集,而在于是否应该收集。
那么一个好奇的狗主人该怎么做呢?
我发现,如果你仍然对你的狗的年龄感到好奇,最好的建议是一年左右拍一次相关特征的特写照片。这不会告诉你你的狗的年龄,但它会告诉你你的狗衰老得有多快,并给你一个主意,什么应该保持最密切的关注。

Ruth’s features that may indicate aging

You’ll come back and read our next post, won’t you??
[1]晶状体硬化的解释(在狗的眼睛里堆积):https://www . petmd . com/blogs/fully vetted/2011/nov/catarats _ or _ Lenticular _ Sclerosis-11975
【2】Embark 估计狗狗年龄指南:https://Embark vet . com/how-old-is-your-dog-how-veterinaries-estimate-dog-age/
[3]宠物医生估算狗狗年龄指南:https://www . petmd . com/dog/slides shows/how-old-my-dog-5-tips-determining-your-dogs-age
OpenAI 如何用机械手解决魔方
人工智能的突破还是只是烟幕弹?

A robotic hand holding a Rubiks Cube.
如果你没看过视频。 结账 。
强化学习在过去的几年里取得了很多成功。我们已经看到人工智能通过强化学习在围棋、Dota 和星际争霸中击败了职业选手。前围棋冠军李时斗在输给高手 AI 后甚至完全退出了比赛。
强化学习的问题是
但是强化学习有一个巨大的问题——它的成功仅限于虚拟环境。没有一个人工智能能像人类一样驾驭现实世界。甚至一个 2 岁的孩子都比我们最复杂的人工智能做得更好。当然,这是一个非常复杂的问题——进化花了 40 亿年才创造了人类,而我仍然设法找了 10 分钟的钥匙,才意识到它们一直在我的口袋里,所以智能生命并没有达到它的顶峰。
尽管如此,人类还是设法在不死亡的情况下学习复杂的任务。如果人类完全像我们的算法一样学习,他们将不得不从悬崖上开下数千次,才能意识到留在路上可能不是一个坏主意。

更糟糕的是,这些算法是如此的数据饥渴,以至于人类的一生都没有足够的时间来学习哪怕是一些有点困难的任务。例如,Dota AI 在能够击败职业选手之前玩了 40,000 年的游戏。当然,仍然令人印象深刻,但是加快时间在虚拟环境中更有效。
那么 OpenAI 是如何在没有利用虚拟环境优势的情况下,利用强化学习来控制物理手臂的呢?
他们没有。他们使用了虚拟模拟。但是一个模拟可以精确到它的结果可以直接转移到现实世界吗?OpenAI 的结论是否定的,现实世界太复杂了,摩擦和弹性之类的东西太难精确测量和模拟。
这是他们试图通过这个实验解决的核心问题。这是 sim2real 迁移问题,它描述了将在模拟中学到的知识应用到现实世界的挑战。
自动域随机化(以及为什么比听起来更容易理解)
他们解决这个问题的方法是一种叫做自动域随机化(ADR)的方法。ADR 的思想是,随着 AI 性能的提高,随机产生越来越多的具有不断变化因素的困难环境。这迫使人工智能学习一种适用于所有随机生成的环境的通用策略,这在理论上导致了这样一种健壮的人工智能,其结果可以转化为现实世界。
让我们再深入一点。这听起来很复杂,但是很简单。让我给你介绍一个人——他是 ADR 算法,他就像一个邪恶的老师。

Great illustration
他喜欢看他的学生努力奋斗。这个例子中的人工智能是他的学生。他面前有几个旋钮。第一个控制魔方的大小,第二个控制手的摩擦力,最后一个控制魔方的重量。还有几个参数,但那不是重要的部分。
当 AI 开始训练时,它仍然在挣扎,所以 ADR 什么也不做。旋钮停留在固定位置。然后在某些时候,人工智能是相当好的,并设法解决立方体的大部分时间。由于 ADR 不喜欢看到 AI 成功,他开始随机转动旋钮。但在现实中,即使 ADR 是邪恶的,他的心是好的。所以他不会全力以赴,只是随意地转动旋钮。足以让人工智能再次挣扎,但不要太随机,因为这将使学习变得不可能。这种情况会永远持续下去——随着人工智能改善 ADR,其随机性范围也会增加。

How the size of the Rubik’s Cube changes over time.
好了,现在我们明白了 ADR 是如何工作的,但是实际的人工智能控制机器人手臂呢?我会给你一个简短的总结他们的设置。
在后台
实现这一目标的神奇调料是以下几点的结合:
- 卷积神经网络从三个摄像机角度预测立方体的 3D 变换。
- Kociemba 的算法,这是一个手工制作的算法,可以计算出解决任何混乱的魔方的步骤。
- 一个神经网络,它根据预测的立方体位置和指尖位置(从机器人手接收)决定下一个动作

During development OpenAI sometimes used a smart Rubiks Cube (Giker Cube) instead of cameras as a stepping stone.
戏剧
你们中的许多人可能会惊讶地看到他们使用手工算法来计算解决方案。别担心,社区的大部分人也是。声称已经用神经网络解决了魔方,但实际解决部分使用了手工制作的算法,这有点不真诚。另一方面,为什么要尝试解决一个已经有完美解决方案的问题。
既然我们已经在戏剧中,让我们继续:当观看视频时,你得到的印象是,该网络在做什么是相当好的。但是,成功率有点令人失望:对于需要 26 次面部旋转的立方体,他们的最佳策略的成功率只有 20%左右。公平地说,26 次旋转是最坏的情况,大多数立方体不需要那么多。对于需要旋转 15 次面的立方体,成功率高达 60%。
另一个警告是修改魔方。OpenAI 使用贴纸来打破旋转对称,这使得模型可以从单个图像中唯一地识别角度。这是人类不需要的修改,虽然很好理解。
不要误会我,我并不是想淡化 OpenAI 的惊人壮举。重点是,我认为 OpenAI 想通过使用 clickbait 策略来炒作他们的作品,获得更多关注。通过投资获得炒作,他们研究的准确性和科学有效性开始变得可疑。
你怎么看?
今天到此为止。如果你喜欢学习人工智能,请到我的 Youtube 频道来看看我。和平!✌️
我们对待 ITSM 的方式让我们的客户非常失望

如果我们要绘制全球企业对技术的需求以及 IT 提供技术的能力,我们会看到一条向上的右曲线。在这个图表中,企业在要求技术方面比在提供技术方面更加积极。这让我们质疑我们的做法是否正确,ITSM 是否让我们的客户失望。
我们认为是的。
一点历史
我们认为 ITSM 正在失败。但平心而论,我们并不认为这是一个新的发展。更确切地说,这是一个漫长而稳定的下降过程。在过去的几十年里,出现了范式转变和分水岭式的时刻。想想当 PC 成为一件大事的时候,互联网出现了,大数据,虚拟化等等。
创新一直不缺乏,这是肯定的。很难想象在我们历史上的任何时候,有 20-30 年左右的时间可以看到如此突然和持续的发展和创新。
那么我们为什么认为 ITSM 失败了呢?因为自始至终,我们都没有用正确的方式做事。问题不在于技术。是我们。
我们哪里出错了
在这个过程中的某个时刻,整个 IT 部门认为他们是一个服务管理组织,于是 ITSM 诞生了。这就是我们开始出错的地方。
“好吧,”你说,“所以它变成了 ITSM,并采取了‘服务提供商’的心态。这有什么不好?”
这种方法的固有问题是,在成为服务提供商的过程中,我们要说两件事。
- “是的,我们可以为您提供这项服务”
- “…但是我们也希望你知道足够多,知道你想要什么,你什么时候想要,以及你如何想要。”
最明显的问题是我们提供前者而假设后者。更大的问题?在假设企业知道他们需要什么、如何以及何时需要什么的时候,我们忽略了他们通常不知道的部分。
所以,是的,技术不是问题。太棒了。但是通过创新,新的实践,闪亮的新玩具,算法,程序和工具;我们忽略了一个事实,即尽管企业对技术的需求正在增长(甚至飙升),但他们不太可能知道自己需要什么,也不知道技术对他们有什么好处。
“是的,我们可以提供这项服务……但我们希望您知道该怎么做。”
随着 ITSM 的成长和成为标准,企业想要什么和团队愿意或能够交付什么之间的鸿沟已经扩大。有了它,商业和技术之间的鸿沟扩大了,结果团队和人之间的鸿沟也扩大了。
这就是 ITSM 让我们的客户失望的地方。但这又能怪什么呢?
是云惹的祸吗?
我们行业中的一些人倾向于将云视为一个分水岭,将事情引向了错误的方向。如果我们退后一步,看看随着时间的推移这种下降,我们可能会指着一个时间说“啊哈!这就是云出现的地方。”

然而,在我们看来,云并不是导致这个问题的原因。在这方面,我们认为它实际上可能有所帮助。
从这个角度来看,云真正解决的问题是如何弥合企业需要的东西和他们能够合理获得的东西之间的差距。
如果我们把这个问题看作是技术无法满足商业期望的问题;或者是企业无法理解自身需求的问题,因为这与技术有关;至少,云没有让这些事情变得更糟。
云是很多东西,但对业务需求和技术交付能力之间日益扩大的差距的指责不是其中之一。
那是什么?
根据我们的估计,技术在这一领域的失败是由于 ITSM 运动的意外但明显的后果,即技术和业务之间的鸿沟越来越大,以至于技术可以提供能力,但业务需要自己解决问题。
ITSM 没有兑现承诺。不是云。不是大数据(尽管它有自己的问题)。而不是任何闪亮的工具。相反,我们对待行业的态度并没有产生最佳结果。改变这种心态是扭转趋势的关键。
而在过去,技术团队可能会花费大量时间来弄清楚企业想要实现什么,与不同的部门联络,并从全局角度看待手头的问题、期望的结果以及如何实现;我们现在看到技术团队提供服务。有时提供预先打包、预先形成和预先加载的单一服务,期望公司知道如何最好地运行它。
我们以首席技术官及其预算为目标。不是业务需要。首席技术官是伟大的,不要误解我们。他们通常是决策者。但是他们不一定是合适的倾诉对象。他们可能不知道,也经常不知道真正的需求是什么。是技术问题吗?是营销问题吗?操作问题?
首席技术官可能会签署合同,但他们可能并不处于真正确定或阐明整体业务目标的最佳位置,尽管他们自己没有任何过错。
ITSM 失败了,因为我们忘记了我们服务的 IT 部门是一个完整的企业,实现积极的业务成果不一定只是一个 IT 实施问题。
没有开拓新的领域
这不是一个全新的想法,也不是一个大胆的声明。这不是旨在颠覆行业的杰里·马奎尔式的宣言。在私人谈话或会议的分组会议中,这个话题会被详细讨论。我们都知道这是一个需要解决的问题。并且已经尝试这样做。
一路上,我们有各种尝试、技术和方法,试图更好地连接商业和技术。这带来了一些积极的结果,但更重要的是带来了更多的项目管理部门、产品经理、产品营销经理等。IT 或工程部门内的专门角色和部门;或者是营销或运营部门的分支,旨在帮助保持联系。
这是有帮助的,但是我们也无意中创造了一些角色,这些角色充满了毫无疑问有能力的人,他们有时会“代替”企业;但他们往往无法弥补能力上的差距。
我们需要转移注意力

IT 服务管理层采取了这种立场,并宣称:“我们在这里提供服务…但也仅此而已。”简而言之,我们已经成为科技世界的 UPS、联邦快递和邮局。只要准时到达那里。不管接下来发生什么,那都取决于接受者。我们在这里的工作完成了。事情就是这样。但是应该吗?
在这些快递公司花费数百万了解客户行为的时候,进行这种比较也许是具有讽刺意味的;以更便捷的方式提供更多服务,优先考虑客户体验。
这发生在当今世界数据为王、货币为王的时代。还有很多等着我们去使用。顺便问一下,这些快递公司向谁寻求帮助?
美国。很讽刺,不是吗?
我们能做什么?
ITSM 正在失败,我们的方法需要改进。就像包裹运送公司将他们的服务视为一个完整的产品一样;从销售到发货,都需要跟风。它需要管理结果。不仅仅是物流。
答案并不那么简单,因为它需要我们作为一个行业来思考。不再把 ITSM 作为标准,而是把 ITSM 作为我们工作的一个方面,只要执行得当。
这不仅仅是工具或技术的问题。这不是关于云或 DevOps,也不是关于我们明年推出的闪亮新玩具。这实际上是从 360 度的角度恢复我们所服务的企业的信心和信心。
恢复伙伴关系心态
它需要伙伴关系来取得成果。我们需要重新获得我们失去的东西,这是提供服务的真正意义,也是实现预期结果、解决问题所需要的东西,并与我们服务的企业合作,而不是无视它们。

通过重新建立这种方法,我们可以开始不通过我们设定的服务级别指标或目标来衡量成功。不要误解我们,服务级别指标很好…但是有多少服务提供商根据业务的成果来衡量成功,而不是他们自己提出的任意指标?
业务试图实现的目标之间是有区别的;服务提供商确定的是成功的衡量标准。这些往往不是一回事。
同样,在实现这些服务级别目标和为服务提供商所帮助的企业的成功做出贡献之间存在着越来越大的差距。一方当然可以帮助另一方,但它们并不总是一回事。
简而言之:ITSM 心态已经失败。基本上,如果我们想更好地服务我们的客户,推动我们的行业向前发展,我们就用了错误的方式和错误的思维方式。如果不从整体的角度来看待我们的行业和我们能够提供的服务,我们就会有所欠缺。
IT 需要看到并确定对业务有影响的成果,而不是在服务级别目标上打勾。如果我们不缩小差距,并开始将客户的实际需求与我们的能力联系起来,我们将继续玩“我们只是提供服务”的游戏。这就是我们对 ITSM 的心态不仅让我们失望,也让我们的客户失望的症结所在。
最终,我们只会做更多同样的事情。从本质上来说,这导致了企业的失败,更重要的是,这种分化永久化了。
原载于 2019 年 12 月 1 日https://introspectdata.com。
我们的黑客马拉松项目如何激励谷歌对抗阿片类药物危机
对于那些从未参加过黑客马拉松的人来说,这是一次独特的经历。睡眠不足、垃圾食品、紧迫的截止日期和竞争(但合作)精神的结合会产生创新的想法。
然而,尽管黑客马拉松很受欢迎,但对它们的一个普遍批评是,它们几乎没有真正的影响力。一旦糖的高潮消退,红牛消退,参与者回到他们的日常生活,他们努力开发的想法和原型通常会半途而废。这是一种耻辱。虽然在黑客马拉松上开发的许多项目都是简陋的原型,但这些原型背后的想法可能有真正的价值。通过额外的工作,一些支持你的伙伴,再加上一点运气,这些想法会产生真正的影响。我知道是因为这发生在我的团队身上。
2017 年 12 月,我和我的团队(三名数据科学家和一名软件工程师)参加了美国卫生与人类服务部(HHS)阿片类药物代码马拉松。我们和其他 50 个团队有 24 小时的时间来梳理 70 多个提供的数据集,以帮助 HHS、卫生从业者和公众找到解决阿片类药物危机的新方法。不是来自公共卫生背景,我们很难(现在仍然如此)理解助长阿片类药物危机的许多相互依赖的行为者、行为和动机。在这样一个复杂的系统中,“速赢”,特别是那些可以在代码马拉松中在 24 小时内解决的,可能是难以捉摸的;但这并不是说,如果你足够努力地去寻找,它们就不存在。
在事件发生前的几周,我们尽可能多地阅读了有关阿片类药物危机的信息。从学术期刊到 Reddit,我们投入了大量时间试图理解危机带来的挑战的类型和规模。正是通过这项研究,我们发现了一个惊人的事实:71%的滥用处方止痛药的人从家人或朋友那里获得药物(赠送、购买或盗窃)。

CDC — Policy Impact — Prescription Painkiller Overdoses — 2011
这个事实迫使我们重新评估我们对成瘾最常见途径的假设。危险不仅存在于过度热心的医生或药品经销商身上,还存在于全国各地医药柜中数百万陈旧且未使用的药物中。单独来看,这些药物似乎无害,但总的来说,我们知道这些过量的药物最终导致每年数千人死亡。这一认识迫使我们不断回到同一个问题:我们能做些什么来安全地清除已经在流通的阿片类药物(和其他药物)?
安全处置药物并不是一个新概念。多年来,美国药品管理局的分流控制部门为全国范围内选择允许他们接受旧的或未使用的药物的药店提供许可证。此外,美国药品管理局每年都会举办全国回收日,在此期间,公众可以将药物退回到由当地执法机构运营的其他站点。虽然这些项目为安全处置药物创造了必要的基础设施,但找到安全处置药物的方式、时间和地点仍然是一项艰巨的任务。有关许可处置地点、时间和限制的信息分散在多个联邦、州和地方政府网站以及 CVS 和 Walgreens 等私营公司的网站上。
除此之外,众所周知,让公众参与到预防行为中来是非常困难的,比如退回未使用的药物。这并不是说我们是坏人,我们只是忙碌、疲惫,被工作、账单和家庭压得喘不过气来的人。虽然我们很多人都渴望做“正确的”事情,但我的团队意识到,没有一种资源可以让公众轻松找到并利用他们周围现有的回收地点。为了真正激励公众退回他们未使用的和多余的药物,我们意识到我们需要建立一个工具来完成两件事:1)建立一种紧迫感,2)使公众尽可能容易地找到他们附近的回收地点。有了这些事实、大量的数据和大量的咖啡,我们开始了代码马拉松。
24 小时后,我们展示了我们的原型:夺回美国

TakeBack America Prototype — April 2018
简而言之,“回收”旨在通过让公众更容易找到他们附近有执照的处理场所来消除安全处理药物的障碍。TakeBack 利用县一级阿片类药物风险和处方数据(由 HHS 提供),以及我们从各种网站收集的药物回收地点数据。在 TakeBack 中,这些数据在县一级进行合并和显示,使用的是一个动态且易于使用的界面中内置的综合热点和点地图。最终,我们相信以一种本地化的、简洁的、令人信服的方式呈现这些信息将会促使公众退回他们的旧的和过量的药物;其他人同意了。在两轮闪电测试中演示了我们的工具后,TakeBack 被来自 HHS、Stanford Medicine X、Socrata 等公司的评委选为三个获奖解决方案之一。

Team Visionist — HHS Opioid Code-a-thon Awards Ceremony (Photo Credit: HHS)
在代码马拉松之后,我们继续给 TakeBack 一些 TLC。最初的更新很小;增加一些新的处理地点或者调整我们的地图,但是很快其他人开始聚集在我们周围。首先,我们 Visionist 的领导鼓励我们改进 Takeback 的用户界面,包括一天晚上我们工作到很晚时送披萨。很快,我们许多了不起的同事来帮助我们,一些人在下班后留下来帮助我们自动化数据流,微调我们的用户体验,或完善我们的用户界面。随着 TakeBack 的基础数据和功能不断增长,网站的访问量也开始增加。
虽然我们对 TakeBack 的技术细节感到满意,但我们坚信未来对 TakeBack 的增强应该由用户来引导。为此,我们首先联系了代码马拉松的赞助商 HHS。举办完比赛后,HHS 的首席数据官 Mona Siddiqui 和她的团队与我们会面,讨论如何更好地推广我们的工具。这些讨论让我们在 2018 年健康数据收集大会上展示了 TakeBack 和关于数据共享政策、数据驱动的解决方案和阿片类药物危机的圆桌会议。在这些活动中,我们有机会与患者、医生和其他卫生从业者直接互动。我们发现这些对话非常有帮助,引导我们对 TakeBack 进行改进,这是我们自己从来没有想到过的。
然后在九月,出乎意料的,谷歌联系了我们。原来谷歌(Code-a-thon 的原始赞助商)看过我们的演示,觉得 TakeBack 有很大的潜力。事实上,谷歌深受启发,他们告诉我们,他们想在谷歌的地图和搜索产品中复制 TakeBack 的见解。从 10 月份开始,我们与谷歌的法律和数据科学团队反复通话,审查我们的数据、方法以及 TakeBack 的底层代码。上周,谷歌、HHS 和 Visionist 终于宣布向更广泛的公众发布这一新工具。
不用说,我们很荣幸谷歌和 HHS 都看到了 TakeBack 的独特价值,我们很高兴在过去的一年里与这两个组织合作,将 TakeBack 推广到全国观众。我们相信,这些与谷歌搜索和地图的新整合将成为他人的宝贵资源,甚至有助于拯救生命。作为一名数据科学家,没有什么比看到您的工具惠及如此多的人更值得骄傲的了。
然而,这只是朝着正确方向迈出的一步。通过这次经历,我们了解到阿片类药物危机是多么复杂和多方面的。真正解决这一危机需要医疗系统内外的人继续做出贡献。在 Visionist,我的团队继续寻找机会将我们的分析技能应用于阿片类药物危机及其他问题。我希望这篇文章能鼓励你们中的一些人加入到我们的努力中来。无论是深夜的想法、课堂作业,还是你自己的黑客马拉松项目,我们和其他人都想听听你带来了什么想法和原型来应对这场危机。我们的经验表明,这种项目可能是未经雕琢的钻石。如果你相信你的项目,继续给它你的时间和注意力。与他人分享,并寻求他们诚实的反馈。你永远不知道它会激励谁,也不知道它最终会变成什么。
再次感谢所有让这一切成为可能的人,包括我在 Visionist 的出色团队,他们帮助我们回到今天的状态(Dillon Mulroy、Kelsey Campbell、Will Sutton、Brian Lehman、Matt Loff、Eric Reidelbach、Trish Willard、Enrique Caballero、Greg Friedman 和 Ruth Goulding)。另外,感谢谷歌的法律团队和 HHS 办公室的首席技术官。
Python 如何帮助我选择新家——第 1 部分
一个简单的端到端应用程序,使用 Python 来自动化枯燥的工作。

Public Housing in Singapore. Photo by DollarsAndSense.
一点背景
最近,我向住房发展委员会(HDB)申请建造一套新公寓(BTO)。对于那些不熟悉新加坡公共住房的人来说,新加坡人可以申请 HDB 建造的全新公寓,等待期为 3-5 年。那些成功的申请人将获得一个排队号码,决定他们在项目中选择一个单位的顺序。谢天谢地,我很幸运地拿到了一个排队号。剩下要做的就是选择一个我喜欢的单元,然后努力祈祷直到我的约会日期它仍然是可用的。
最初,根据我自己的标准,比如潜在的转售价值、屏蔽/未屏蔽的视图等,很容易列出几个单元。然而,他们总是说现实是残酷的,我最喜欢的单位被别人拿走了。
问题来了…
最终,我开始发现自己陷入了一个痛苦的循环每天:
1)查看是否有单位在 HDB 网站上被选中。如果是,它们在我的入围单位中吗?如果是的话,c̶r̶i̶e̶s̶̶i̶n̶t̶e̶r̶n̶a̶l̶l̶y̶会重新评估我的选择。

The very page I can’t help but stare at every single day before our appointment.
显然,我不是唯一有这种问题的人。在和我未来的邻居在一个电报小组呆了一天后,我很快就意识到了这一点。是的,你没听错,聪明的国家。所以我想,现在是 Python 的时代了。
计划是什么?
为了自动化检查单元的整个过程和个性化体验,同时对我来说成本最低或为零。
该过程
首先,内容。我需要从 HDB 网站提取单位和其他杂项信息的可用性。这可以用 Python 中的 BeautifulSoup 包或 Selenium 来完成。在这种情况下,我选择了 BeautifulSoup,因为这个任务非常简单。我不会详细讨论实现,因为这将是一个单独的话题。然而,对于那些感兴趣的人来说,网上有很多教程,这里有一个很好的。
二、存储。为了迎合个人,我将不得不在单元数据上存储用户数据以供将来参考,这是我与 MongoDB 自由层云数据库(M0 阿特拉斯)一起进行的。对于手头的任务,阿特拉斯·M0 绝对绰绰有余。此外,Python 有 pymongo 包,这使得设置非常简单。
最重要的是,消费。我将如何查看此信息,从哪里获取更新?还有,还有谁会想用这个?自然地,因为我从 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 中找到了我未来的邻居,所以以 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 bot 的形式提供服务就有了直接的意义。毫无疑问,我选择了 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot 包,因为它的社区给了我第一手的经验,并且我可以用它进行大量的定制。

Process of setting up an Azure VM
在花了几个小时来创建基本功能,如用户注册,当他们选择的单位被占用时的通知和发送每日摘要后,这个机器人已经准备好部署在。在虚拟机上托管脚本将允许机器人全天候运行。我把它放在微软自己的云计算平台 Azure 上。顺便说一下,学生在 Azure 上注册时可以获得 100 美元的积分。在 Azure 上设置一个 VM 简直是小菜一碟,只需点击并决定我的 VM 的层和位置。几分钟后,BTO·巴迪上线了。
用户反馈的重要性
这次我确定要做的一件事是在第一个版本中加入一个反馈按钮,允许用户匿名留下关于我如何改进 BTO 巴迪的建议。你会对收到的反馈感到惊讶。一位用户建议,他们可以输入堆栈,而不是一次手动键入一个设备(例如# 07–111、# 08–111、# 09–111),所有带有#xx-111 的设备都将包含在观察列表中。我继续为他们开发这个特性。
结果呢
最后,经过几次修改和听取用户的反馈后,BTO 巴迪能做的是:
- 监视列表和通知的个性化

Example of heartbreaking notification sent to users when their favourite units are taken
2.基于用户排队数的用户机会估计

Example of a user’s profile and chances
3.显示单位的当前状态及其受欢迎程度

Example of how a user can check the status of their units
至此,BTO 巴迪已经或多或少地完成了,目前服务于 200 多个用户。至于它的可持续性,也许我可能得想办法抵消托管的成本(5~10 美元)。如果你有机会申请 BTO,一定要试试 BTO 哥们 (@btobuddy_bot)!
更新 : Part 2 已经发布!
Python 如何帮助我选择新家——第 2 部分

Photo by Muhd Asyraaf on Unsplash
在第 1 部分的中,我分享了如何使用 Python 来自动化我的 BTO 应用程序中的普通流程,例如跟踪单元的可用性,并在单元被占用时通知我。截至目前,它正在为大约 700 名用户提供服务🎉非常感谢大家的支持!
由于它开始从监控单元中释放出我的时间,我能够花更多的时间来比较单元并决定如何对它们进行排序。在这个过程中,我意识到我必须手动计算每个单元的“因子”(例如,一个单元得到的阳光类型,窗户方向),然后才能比较它们。这既重复又耗时。不得不分析场地平面图来加工这些因素,并从数百个单元中确定哪些是“理想的”单元,这可能需要几天的时间。
不要误解我,这绝对是我珍惜的里程碑之一。然而,我相信每个单元因素的搅动可能是瞬间的,你可以花更多的时间和你的伙伴一起选择单元。因此,在这篇文章中,我将分享 Python 和一点计算机视觉是如何为我做到这一点的。
哦,如果你不熟悉 BTO 的话:
按单建造(BTO) 是新加坡的一种公共住房分配制度,单身人士(35 岁及以上)和夫妇可以通过投票选择新的住房。公寓通常会在 3-5 年内准备好,因项目而异。偶尔被称为新加坡大抽奖。
解释流程
为了让您更好地理解,请允许我向您介绍一下这个过程。想象一下,你非常幸运地申请了坦帕因斯的一套 5 居室,得到了 10 号排队号。这意味着你将是第十个选择一个单位的人,可能是一个有有利因素的单位。然后,您会得到一份项目现场平面图,以帮助您做出决策:

Site Plan of Tampines Green Glen. Photo by HDB.
让我们假设你是利润驱动的并且想要最大化你的单位的未来转售价值。您决定根据以下因素选择一个单位:
- 没有阳光直射到你的窗户上— 为了凉爽的温度
- 卧室外畅通无阻的视野— 谁不喜欢好的视野
- 位于高层— 向上,向上,远离噪音
注意:这些因素只是众多因素中的一部分。其他的例子还有到火车站的距离,到学校的距离,甚至与风水相关的属性。
尽管每个因素的重要性因人而异,但其潜在的计算方法是相似的。希望你开始明白这有多麻烦。记住上述因素,我们现在可以将它们转换成 Python 程序。
将流程转换为代码
下面是我们需要在代码中实现的目标:
- 确定 5 个房间的单元在场地平面图中的位置。
- 对于每个单元,确定窗户位于哪一侧。
- 对于每个单元,确定窗户朝向哪个方向。
以上为我们提供了每个单元的空间理解,形成了我们目标的基础。毕竟,大多数因素是基于一个单位的定位。
实施
在我们开始之前,你必须了解一点关于计算机如何感知图像的基础知识。这将有助于你理解我的方法。

Image as an array. Photo by Stanford.
与人类不同,计算机将图像视为三维阵列中的数字,即宽 x 高 x 通道。
- 每个数字代表像素的强度,范围从 0(最暗)到 255(最亮)。
- 对于彩色图像,有 3 个通道(红色、绿色和蓝色),而对于灰度图像,只有 1 个通道。
- x,y 轴用于参考某个像素,有趣的是,原点[0,0]是图像左上角的像素。
在 Python 中,有几个包我们可以用来处理图像,比如 OpenCV 、 Pillow 和 Scikit-Image 。在我的例子中,我们将主要使用 OpenCV。
有了这些新知识,让我们回到我们的第一个目标:
确定 5 个房间的单元在场地平面图中的位置。
为了确定它们的位置,我们可以利用的一种技术是颜色分割。请注意 5 个房间的单元是如何用蓝绿色进行颜色编码的,这也显示在图例中。这意味着,如果我们能够获得颜色的精确值,我们就可以找到单元在我们的三维数组中的位置。
通过使用颜色选择器,我们可以确定蓝绿色的值为 191,227,211 (R,G,B)。现在让我们对图像进行颜色分割:
我们必须交换我们周围的颜色值成为 BGR,并将其转换成 HSV(色调,饱和度,亮度)。HSV 是颜色的另一种表现形式。从我们的颜色分割得到的图像看起来像:

Site Plan with Color Segmented for 5-Room units
看起来棒极了!然而,这仍然没有给我们每个 5 室单元的确切位置。因此,我们将不得不使用另一种称为轮廓检测的技术。对于这项技术,我们将首先把图像转换成灰度。这意味着图像只包含一个通道。然后,我们应用一个简单的阈值,将所有值为 127 及以上的像素转换为 255,将 127 以下的像素转换为 0。最后,我们使用 OpenCV 中的 findContours 函数来检测单元的位置。
我们的图像看起来会像这样:

Contours drawn around all 5-Room units
我们也可以将我们的轮廓(多点)转换成矩形 (4 点)以便于计算,同时保留我们想要的信息。

Contours converted to Bounding Box using cv2.minAreaRect(contour)
好了,我们现在有了场地平面图中每个 5 室单元的坐标!继续我们的第二个目标:
对于每个单元,确定窗户位于哪一侧。
通过查看一套五居室公寓的布局,我们确定窗户位于“矩形”的扁平端。

Layout of a 5-room unit. Photo by HDB
为了确定单元的方向,我们可以利用图像处理中的另一种常见技术,称为 模板匹配 。模板匹配的主要思想是使用一个模板 (duh) 并在我们的基础图像上滑动它。给你最小差异的位置可能包含你的模板。
不是滑动,我们必须每次旋转模板 90 度,用翻转的模板重复。这是为了说明我们的单位出现在它们的边界框中的方式。总的来说,我们有 8 个不同的方向进行比较,并获得最小的差异。
下面是一个简短的例子:

Template (Left) with varying orientation and Base Image (Right)
给出最小差异的方向是最佳匹配。使用这个方向,我们可以确定边界框坐标中的哪两个点是矩形的平边。因此,我们的第三个目标是:
对于每个单元,确定窗户朝向哪个方向。
这相当简单,不需要使用任何技术。通过计算包围盒的平均点和窗口边上两点的平均点,我们可以投影一条线来表示窗口面向哪个方向。

Direction of which the windows are facing
应用
有了边界框的坐标和窗口的方向,我们现在可以在它们上面构建因子(特征)。继续我们的例子,我们想要确定每个单元将面对的太阳的类型。

Animation of sun movement. Animation by Stacked Homes
一个单元有朝阳窗朝东、午后阳窗朝西和间接阳窗朝北/南。因为北也是场地平面图的北,所以我们可以通过计算两条线之间的角度来确定窗户的角度和指南针方向。第一条线是上面画的蓝色箭头,第二条线只是一条垂直线。两条线之间的角度公式为:****

Photo by Steemit
一个简单的基于规则的方法可以帮助将罗盘方向转换成一个单位将要面对的太阳类型。比如【NNW,N,NNE,SSW,S,SSE】会是间接太阳,【E,ENE,ESE,NE,SE】会是上午太阳,【W,WNW,WSW,NW,SW】会是下午太阳。
另一个我们可以计算的因素是一个单位的视野是否被阻挡,如果是,还有多远?通过对每个其他房间类型执行颜色分割,我们可以获得每个单元周围的“障碍物”的边界框。

Bounding box of each block
还记得我们的蓝色箭头(窗户方向)吗?现在让我们在同一个方向上进一步投射它,直到它击中其中一个盒子,这与寻找一条直线和一个矩形的交点是一样的。
一个巧妙的技巧是确定该直线与构成矩形的 4 条直线的交点。如果相交,我们可以画一个绿色箭头表示堵塞,并计算其长度:

Projection of window direction and potential view blockage
为了确定实际距离,我们可以参考原始地图上的比例,即地图上的距离与地面上相应距离的比例。
最后,我们可以将所有内容放入一个简单的电子表格中,以便根据我们的喜好轻松引用和过滤:

Summary of 5-Room units with factors
鉴于大多数因素都围绕着单元的定位,您可以进一步扩展这些因素,并建立一个相当全面的列表。然而,我决定将重点放在这 3 个因素上,作为概念验证,并收集关于其可用性的反馈。
结论
尽管这最终比我节省的几天时间要长得多,但考虑到为未来的房主节省的时间,这绝对是值得的。事实上,它已经被集成到 BTO 好友(第一部分中的机器人)中。最后,我希望你和我一样喜欢这篇文章。非常感谢所有反馈,干杯!
免责声明: 你可能会发现整个过程并不像描述的那样一帆风顺(生活也是如此),需要一些小技巧,比如放大和稀释图像,才能让它成功运行。
PyTorch 如何让你建立和实验一个神经网络
我们一步一步地展示了一个在 PyTorch 中构建分类器神经网络的简单示例,并强调了使用自定义层和激活函数等高级概念进行实验是多么容易。
介绍
深度学习(DL)火热。这是时尚的 T2。它有很酷的工具可以玩。

Source: This tweet
尽管许多 DL 实践者是从 TensorFlow 开始他们的旅程的,但 PyTorch 已经成为一个同样受欢迎的深度学习框架,因为它是由脸书人工智能研究(FAIR)团队在 2017 年初推出的。自推出以来,它引起了全球 AI 研究人员和从业者的关注,并已显著成熟。
本质上,PyTorch 为程序员提供了极大的灵活性,使他们能够创建、组合和处理流过网络(称为计算图)的张量,并配有相对高级的面向对象的 API。
当然,原始 TensorFlow 提供了类似级别的低级灵活性,但通常很难掌握和排除故障。
此外,PyTorch 还提供了强大而简单的 API 方法来自动区分基本的反向传播流程。
见它的核心创造者,sou Smith chint ala谈谈它的起源和演变。
下面这篇文章实际上很好地提炼了 PyTorch 的本质,以及它与其他非常流行的框架 Keras/TensorFlow 的主要区别。
从 TensorFlow 迁移到 PyTorch
towardsdatascience.com](/pytorch-tutorial-distilled-95ce8781a89c)
在本文中,我们将展示在 PyTorch 中构建 2 层神经网络分类器(密集连接)的简单逐步过程,从而阐明一些关键特性和风格。
PyTorch 为程序员提供了极大的灵活性,让他们可以创建、组合和处理流过网络的张量…
核心组件
PyTorch 的核心组件将用于构建神经分类器,
- 张量(py torch 中的中心数据结构)
- 张量的自动签名的特征(自动微分公式烘焙到
**nn.Module**类,用于构建任何其他神经分类器类- 优化器(当然,有很多可供选择)
- 损失功能(有大量选择供您选择)

使用这些组件,我们将通过五个简单的步骤构建分类器,
- 构建我们的神经网络作为我们的自定义类(从
nn.Module类继承而来),包括隐藏层张量和一个forward方法,用于通过各种层和激活函数传播输入张量 - 使用这种
forward方法通过网络传播特征(来自数据集)张量——假设我们得到一个output张量作为结果 - 通过比较
output和地面真实值并使用内置损失函数计算T4 - 使用自动微分能力()和
backward方法传播的渐变 - ****使用损失梯度更新网络的权重,这是通过执行所谓的优化器的一个步骤
optimizer.step()来完成的。
仅此而已。这五个步骤构成了一个完整的训练时期。我们只是重复它一堆次,以降低损失,并获得高分类精度。

The five-step process with the five core components.
在 PyTorch 中,我们将神经网络定义为一个自定义类,从而可以获得面向对象编程(OOP)范例的全部好处。
张量
[torch.Tensor](https://pytorch.org/docs/stable/tensors.html#torch.Tensor)是包含单一数据类型元素的多维矩阵。它是框架的中心数据结构。我们可以从 Numpy 数组或列表中创建张量,并执行各种操作,如索引、数学、线性代数。
张量支持一些额外的增强功能,使它们变得独一无二。除了 CPU 之外,它们还可以加载到 GPU 中(通过极其简单的代码更改)以获得更快的计算速度。并且它们支持使用 、动态计算图(DCG) 来形成跟踪应用于它们的每个操作以计算梯度的反向图。
在这里阅读关于张量的官方文档。或者,看这个优秀的视频介绍。
亲笔签名
当涉及到复杂的神经网络时,我们都不擅长微积分。高维空间搅乱了我们的思维。还好有亲笔签名救我们。
为了处理 14 维空间中的超平面,想象一个 3 维空间并大声对自己说“14”。每个人都这样做——杰弗里·辛顿
张量对象支持神奇的自动签名功能,即自动微分,这是通过在张量流经网络时跟踪和存储对其执行的所有操作来实现的。您可以观看这个精彩的教程视频,获得直观的解释。
nn.Module类
在 PyTorch 中,我们通过将神经网络定义为自定义类来构建它。然而,这个类继承自[nn.Module](https://pytorch.org/docs/stable/nn.html) 类,而不是从原生 Python object派生而来。这给神经网络类注入了有用的属性和强大的方法。我们将在文章中看到这样一个类定义的完整例子。
损失函数
损失函数定义了神经网络的预测与实际情况有多远,损失的定量测量有助于驱动网络向对给定数据集进行最佳分类的配置靠近。
PyTorch 为分类和回归任务提供了所有常见的损失函数—
- 二元和多类交叉熵,
- 均方和平均绝对误差,
- 平滑 L1 损失,
- 负对数似然损失,甚至
- 库尔贝克-莱布勒散度。
关于这些的详细讨论可以在本文中找到。
优化器
优化权重以实现最低损失是用于训练神经网络的反向传播算法的核心。PyTorch 通过[**torch.optim**](https://pytorch.org/docs/stable/optim.html)模块提供了大量的优化器来完成这项工作
- 随机梯度下降(SGD),
- 亚当,阿达塔,阿达格勒,斯巴达姆,
- BFGS,
- RMSprop 等。
“五个步骤的过程构成了一个完整的训练时期。我们只是重复了很多次。”
神经网络类及其训练
数据
对于这个示例任务,我们首先使用 Scikit-learn 函数创建一些带有二进制类的合成数据。在下面的图中,数据类别由颜色区分。很明显,数据集不能通过简单的线性分类器来分离,神经网络是解决该问题的合适的机器学习工具。

The synthetic dataset used for the classification example
建筑
我们为这个演示选择了一个简单的全连接、2 隐藏层架构。如下所示,

类别定义
我们定义对应于这个架构的变量,然后定义主类。神经网络类定义如下所示。如前所述,它继承自nn.Module基类。

添加注释后,代码几乎一目了然。在方法forward,的定义中,与 Keras 的模型定义有很强的相似性。
此外,请注意内置线性代数运算的使用,如**nn.Linear**(层间)和激活函数的使用,如**nn.ReLU**和**nn.Sigmoid**在层的输出。
如果我们实例化一个模型对象并打印出来,就会看到结构(平行于 Keras 的model.summary()方法)。
损失函数、优化器和训练
我们为此任务选择二元交叉熵损失,并将其定义如下(是的,按照惯例,损失函数在 PyTorch 中通常被称为criterion)
criterion = nn.BCELoss() *# Binary cross-entropy loss*
此时,让我们通过我们定义的神经网络模型运行输入数据集,即向前传递一次,并计算输出概率。由于权重已经被初始化为随机的,我们将看到随机的输出概率(大多接近 0.5)。这个网络还没有被训练。
logits = model.forward(X) *# Output of the forward pass (logits i.e. probabilities)*
如果我们打印前 10 个概率,我们会得到这样的结果,
tensor([[0.5926],[0.5854],[0.5369],[0.5802],[0.5905],[0.6010],[0.5723],[0.5842],[0.5971],[0.5883]], grad_fn=<SliceBackward>)
所有的输出概率看起来都接近 0.5,

平均损耗是使用简单的,
loss = criterion(logits,y)
对于优化器,我们选择简单的随机梯度下降(SGD ),并指定学习率为 0.1,
from torch import optim
optimizer = optim.SGD(model.parameters(),lr=0.1)
现在开始训练。我们再次遵循一个五步流程
- 将梯度重置为零(防止梯度累积)
- 通过层向前传递张量
- 计算损失张量
- 计算损失的梯度
- 通过将优化器增加一个步长(在负梯度的方向上)来更新权重
令人惊讶的是,如果你阅读了上面的五个步骤,这正是你在所有关于神经网络的理论讨论(以及所有教科书)中看到的。使用 PyTorch,你可以用看似简单的代码一步一步地实现这个过程。
没有什么是对你隐藏或抽象的。您会感受到用五行 Python 代码实现神经网络训练过程的原始力量和兴奋!

多个时期的训练
那只是一个时代。现在,我们很清楚一个时代是不够的,不是吗?对于运行多个时期,只需使用一个循环。
并且当运行 1000 个周期时,可以容易地产生所有熟悉的损失曲线。

想看看概率是如何随时间演变的吗?
PyTorch 赋予你实验、探索、打破和动摇事物的力量。
只是为了好玩,如果您想检查输出层概率如何在多个时期内演变,对前面代码的简单修改就可以做到这一点,

这就对了,

显然,未训练的网络输出都接近 1,即不区分正类和负类。随着训练的继续,通过调整网络的权重,概率彼此分离,逐渐试图匹配地面真实的分布。
PyTorch 赋予你实验、探索、打破和动摇事物的力量。
有其他时髦的想法吗?试穿一下
PyTorch 从其早期发布开始,就非常受欢迎,尤其是在学术研究人员和创业公司中。这背后的原因很简单——它让你通过简单的代码重构来尝试你疯狂的想法。实验是任何科学领域新思想进步的核心,当然,深度学习也不例外。
用两个激活功能混起来?
(有点)疯狂的是,让我们假设我们想用两种不同的激活函数混合它——ReLU 和双曲正切(tanh)。我们想把张量分成两个平行的部分,分别对它们应用这些激活,把结果张量相加,然后正常传播。

看起来很复杂?实现这个的代码正是你所想的。将输入张量(如 X )通过第一个隐藏层,然后通过单独的激活函数创建两个张量 X1 和【X2】流动合成张量。简单地将合成张量相加,并通过第二个隐藏层。

你会得到什么好处吗?谁知道呢?但是你可以用 PyTorch 很容易地做这种实验性的东西和改变网络的架构。
实验是任何科学领域新思想进步的核心,当然,深度学习也不例外。
试试自己定制的损失函数?
你可能想试试你自己定制的损失函数。我们从高中时代就开始使用均方差了。试一下回归问题的误差的四次方如何?
只需定义函数…

然后在您的代码中使用它(注意新的模型reg_model,它可以通过关闭我们的Network类的输出中的 sigmoid 激活来构造。

现在,你有这种感觉吗?

摘要
这个演示 的所有代码都可以在我的 Github repo 这里找到。
PyTorch 是一个很棒的软件包,可以深入到神经网络的核心,为您的应用程序定制它,或者尝试网络的架构、优化和机制方面的大胆的新想法。
在本文中,我们总结了几个关键步骤,可以遵循这些步骤来快速构建用于分类或回归任务的神经网络。我们还展示了如何用这个框架轻松地试验出好的想法。
走出去,建立你最喜欢的网络,解决你的机器学习问题。可能性是无限的!
如果你有任何问题或想法要分享,请联系作者tirthajyoti【AT】Gmail . com。此外,您可以查看作者的 GitHub 资源库中的代码、思想和机器学习和数据科学方面的资源。如果你像我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
*** [## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)***
回归分析如何工作

不同形式的回归分析及其应用
R 回归分析是一种机器学习算法,可用于衡量自变量与因变量的相关程度。回归分析的一个广泛应用是在数据集上建立模型,精确预测因变量的值。
回归分析分步指南
在回归分析开始时,数据集可以分为两组:训练数据集和测试数据集。训练数据集可用于创建模型,以找出将最佳拟合线应用到图表中的最佳方法。因此,它可以是一条直线,也可以是一条曲线,很容易与自变量对因变量的图形相吻合。
这个新创建的模型可用于预测测试数据集的因变量。然后,预测值可以通过使用不同的精度测量值(如 R 平方、均方根误差、均方根误差、皮尔逊相关系数等)与原始因变量值进行比较。
如果准确度分数不够准确,并且想要建立更强的模型,则可以改变分配给训练和测试数据集的数据集的百分比。例如,如果训练数据集有 70 %的数据集,而测试数据集有 30%,那么训练数据集现在可以有 80%的数据集,而测试数据集有 20%。
获得更强模型的另一种方式是通过从线性回归分析变为多项式回归分析或者从多元线性回归分析变为多元多项式回归分析。
对于连续变量有不同的回归分析方法,如线性回归、多元线性回归、多项式回归和多元多项式回归。
不同形式的回归分析
线性回归
线性回归通过使用自变量来预测因变量的值。
在线性回归中,最佳拟合线用于从训练数据集中获得方程,然后该方程可用于预测测试数据集的值。该方程可以是这样的形式: y = mx + b 其中 y 是预测值,m 是直线的斜率,而 b 是直线与 y 轴相交的点。以下是在 python 中运行线性回归的一组代码:
该代码是基于 FIFA 19 球员评级的数据集完成的。在这里,潜力被用来预测玩家的总体评分。
**import** **numpy** **as** **np** ## The dataset is split into two groups below. The training dataset ## had 75% of the dataset and the testing dataset had 25%
split = np.random.rand(len(df_fifa)) < 0.75
train = df_fifa[split]
test = df_fifa[~split]
## A regression model is created
regr = linear_model.LinearRegression()
## Training and fitting the model
fifa_x_train = train[['Potential']]
fifa_y_train = train[['Overall']]
regr.fit(fifa_x_train, fifa_y_train)
## Predicting the dependent variables in the testing dataset
fifa_x_test = test[['Potential']]
fifa_y_test = test[['Overall']]
df_fifa_pred = regr.predict(fifa_x_test)
## Testing the accuracy of the linear model using R-squared
r2_score(fifa_y_test, df_fifa_pred)
多项式回归
多项式回归可以用一个自变量来预测因变量的值。
在多项式回归中,最佳拟合曲线用于从训练数据集中获得方程,然后该方程可用于预测测试数据集的值。
在多项式回归的情况下,方程可以是以下形式: y = ax^n + bx^n-1 + …+ c 其中 y 是预测值,a 和 b 是方程的常数, n 是确定曲线形状的方程的最高次,而 c 是 x 为 0 的点。基于 n 的值,该等式可以是二次、三次、四次或更多次。以下是在 python 中运行多项式回归的一组代码:
该代码是基于 FIFA 19 球员评级的数据集完成的。在这里,潜力被用来预测玩家的总体评分。
**import** **numpy** **as** **np** ## The dataset is split into two groups below. The training dataset ## had 75% of the dataset and the testing dataset had 25%
split = np.random.rand(len(df_fifa)) < 0.75
train = df_fifa[split]
test = df_fifa[~split]
## A regression model is created
regr = linear_model.LinearRegression()
## Training ,transforming the independent variable into a polynomial ## fit and fitting the model
fifa_x_train = train[['Potential']]
fifa_y_train = train[['Overall']]
poly = PolynomialFeatures(degree=4)
fifa_x_train_poly = poly.fit_transform(fifa_x_train)
regr.fit(fifa_x_train_poly, fifa_y_train)
## Transforming the testing dataset and predicting the dependent
## variables in the testing dataset
fifa_x_test = test[['Potential']]
fifa_y_test = test[['Overall']]
fifa_x_test_poly = poly.fit_transform(fifa_x_test)
df_fifa_pred = regr.predict(fifa_x_test_poly)
## Testing the accuracy of the polynomial model using R-squared
r2_score(fifa_y_test, df_fifa_pred)
多元线性回归
多元线性回归使用两个或多个自变量来预测因变量的值。
在多元线性回归中,多条最佳拟合线用于从训练数据集中获得通用方程,然后该方程可用于预测测试数据集的值。一般方程可以是这样的形式: y = ax+ bx2 +…+ c 其中 y 是预测值,a 和 b 是连接自变量和因变量的直线的斜率,而 c 是直线与 y 轴相交的点。以下是在 python 中运行多元线性回归的一组代码:
该代码是基于 FIFA 19 球员评级的数据集完成的。年龄、潜力、货币价值和释放条款被用来预测球员的总体评分。
**import** **numpy** **as** **np** ## The dataset is split into two groups below. The training dataset ## had 75% of the dataset and the testing dataset had 25%
split = np.random.rand(len(df_fifa)) < 0.75
train = df_fifa[split]
test = df_fifa[~split]
## A regression model is created
regr = linear_model.LinearRegression()
## Training and fitting the model
fifa_x_train = train[['Age','Value','Potential','Release Clause']]
fifa_y_train = train[['Overall']]
regr.fit(fifa_x_train, fifa_y_train)
## Predicting the dependent variables in the testing dataset
fifa_x_test = test[['Age','Value','Potential','Release Clause']]
fifa_y_test = test[['Overall']]
df_fifa_pred = regr.predict(fifa_x_test)
## Testing the accuracy of the linear model using R-squared
r2_score(fifa_y_test, df_fifa_pred)
多元多项式回归
多元多项式回归是通过使用两个或多个自变量来预测因变量的值。
对于多元多项式回归,最佳拟合的多条曲线用于从训练数据集中获得通用方程,该方程然后可用于预测测试数据集的值。
在多元多项式回归的情况下,一般方程可以是这样的形式: y = ax^n + bx^n-1 + …+ c 其中 y 是预测值,a 和 b 是方程的常数, n 是确定曲线形状的方程的最高次,而 c 是 x 为 0 的点。基于 n 的值,该等式可以是二次、三次、四次或更多次。以下是在 python 中运行多元多项式回归的一组代码:
该代码是基于 FIFA 19 球员评级的数据集完成的。年龄、潜力、货币价值和释放条款被用来预测球员的总体评分。
**import** **numpy** **as** **np** ## The dataset is split into two groups below. The training dataset ## had 75% of the dataset and the testing dataset had 25%
split = np.random.rand(len(df_fifa)) < 0.75
train = df_fifa[split]
test = df_fifa[~split]
## A regression model is created
regr = linear_model.LinearRegression()
## Training ,transforming the independent variable into a polynomial ## fit and fitting the model
fifa_x_train = train[['Age','Value','Potential','Release Clause']]
fifa_y_train = train[['Overall']]
poly = PolynomialFeatures(degree=4)
fifa_x_train_poly = poly.fit_transform(fifa_x_train)
regr.fit(fifa_x_train_poly, fifa_y_train)
## Transforming the testing dataset and predicting the dependent
## variables in the testing dataset
fifa_x_test = test[['Age','Value','Potential','Release Clause']]
fifa_y_test = test[['Overall']]
fifa_x_test_poly = poly.fit_transform(fifa_x_test)
df_fifa_pred = regr.predict(fifa_x_test_poly)
## Testing the accuracy of the polynomial model using R-squared
r2_score(fifa_y_test, df_fifa_pred)
结论
回归分析是一种非常有趣的机器学习技术,可以应用于不同的领域来预测数值,例如预测产品/房屋的价格,预测足球运动员在一个赛季中的进球数量以及预测人的身体质量指数。
亚马逊评论有多靠谱?
建立一个识别虚假评论的索引

简介
作为一个自称的技术爱好者,我关注技术评论社区已经有一段时间了,尤其是在 YouTube 上。在那段时间里,我发现每次新 iPhone 发布后都会出现一种特定的模式:非常受欢迎的视频(以及文章)会被发布,批评新 iPhone 的初始问题。


然而,苹果的销售数字似乎并没有受到其发布日期周围的负面气氛的影响。这让我想知道谁受这些视频和文章的影响最大,以及它们是否会影响苹果的客户满意度。事实上,如果这些评论影响了苹果的客户,一个更宽松的发布时间表,给苹果更多的时间来完善 iPhone 的新功能,可能会提高苹果的客户满意度。
为什么是 amazon.co.uk 的 T2?

我选择刮 amazon.co.uk 有几个原因。首先,除了中国,欧洲可以说是 iPhone T5 在 T4 最重要的海外市场。因此,来自英国的顾客评论呈现了苹果的相关信息。其次,亚马逊让我不仅可以收集评论本身的信息(评分、标题、文本、有用的投票),还可以收集发布评论的亚马逊用户的信息。通过点击用户名,我可以收集每个用户的信息,比如有用的投票和评论的总数,以及所有发布的评论。
在进行我的研究时,我选择专门关注 2017 年 11 月至 2018 年 9 月期间对 iPhone X 的评论,以便只收集该时间点最新 iPhone 的评论。未来的研究可能会将同样的概念应用于老款 iPhones。
工作流程

我使用 Selenium 来抓取 amazon.co.uk,主要是因为它在不同网站间导航的灵活性。
在收集了数据之后,我准备并清理了数据,主要是使用 Pandas、NumPy 和 RE。这一步包括识别和适当地处理丢失的值,修改我的代码,以及重新格式化收集的数据,以便进行进一步的处理和分析。
然后,我处理并分析了这些数据,将它们分成小组并比较它们的特征。
最后,我用 matplotlib、seaborn 和 wordcloud 可视化了我的分析结果。
每月审核次数

我分析的第一部分重点是从 2017 年 11 月 iPhone 的第一批评论到 2018 年 9 月每个月的评论数量。与我最初的预期相反,在 iPhone 发布期间,相关评论相对较少。然后,在 2017 年 12 月左右,评论数量开始显著增加,在 2018 年 3/4 月达到顶峰。
我对此次发布的评论数量相对较低的怀疑是,首先,iPhone 在欧洲的发布时间晚于美国,这可能会导致评论延迟。此外,英国的消费者可能会等到圣诞节才购买 iPhone,这可以解释 12 月份的增长。
已验证与未验证的评论

接下来,我将评论分为两类:已验证和未验证的评论。一般来说,经过核实的评论明显多于未经核实的评论。然而,唯一一次未经核实的评论数量超过经核实的评论数量的时刻是 2017 年 11 月,就在 iPhone 发布之后。这一发现让我更加怀疑,iPhone 发布时互联网上普遍负面的气氛并不是由苹果的客户造成的,而是由不喜欢苹果公司的人造成的。
此外,该折线图显示,之前确定的评论增加几乎完全由已验证的评论驱动,而未验证的评论在 2017 年 11 月之后减少,并且从未真正再次增加。
在证明了经过验证和未经验证的评论数量之间的实质性差异后,我决定深入研究并比较这两组评论的平均评分。下面的箱线图显示了结果:

这个箱线图表明,这两种类型的评论不仅在评论数量上有很大差异,而且在平均评分上也有很大差异。虽然已验证评论的平均评级集中在 4.50 和 4.75 之间,第一和第三四分位数彼此非常接近,但未验证评论的平均评级显示出很大的可变性。最重要的是,未经核实的平均评分中值约为 3.50,这进一步证明了我的猜测,即实际的苹果客户普遍对他们的 iPhone 非常满意,并且没有受到互联网上负面评论的影响。
为了证实这些发现,我仔细研究了 2017 年 11 月发表的按评论类型分组的评论:

虽然相对少的评论数量不允许非常可靠的结论,但是在已验证和未验证的评级之间仍然存在明显的差异,已验证的评级通常比未验证的评级更受欢迎。
分析复习课文
在我的下一步中,我专门关注已验证评论的评论文本,并在准备数据后,生成了一个词云,允许快速概述已验证评论的总体情绪:

同样,这个词云中的大多数词都是积极的,表示对 iPhone X 的满意(“开心”、“优秀”、“最好”)。此外,交付似乎对客户非常重要,这不一定是苹果的洞察力,但肯定是亚马逊的。
在这个词云中找到否定词,要么需要非常好的眼睛,要么需要放大镜。如果你拥有其中任何一个,你可能会发现“崩溃”或“粉碎”,然而,负面词汇的大小和罕见程度为实际苹果客户的高满意度提供了进一步的证据。
造假审查指标
在这一点上,我几乎准备好结束我的项目,并包括一些更多的描述可视化来证明我的观点。
然而,在抽样调查了一些评论后,我开始怀疑到底有多少评论是由真正购买了该产品的人发表的。有些评论,甚至是经过验证的评论,在我看来都非常可疑。为了减少由于不知道哪些评论是真实的而带来的不确定性,我想出了一个我命名为虚假评论指数的东西。
为了将虚假评论指数纳入我的研究,我决定重新开始搜集,不仅收集评论,还收集每个用户的相关信息。然后,我使用这些信息,根据以下 6 个因素来计算虚假评论指数:

我通过为这些因素分配权重和分类几个场景来计算虚假评论指数。例如,有用投票数/评论数因子的最高分是 10。这个因素的一种情况如下:如果给定用户的这个计算结果返回小于或等于 1 的数字(=用户对他的所有帖子平均收到小于或等于 1 的有用投票),则用户的虚假评论指数增加 10。因此,假评论指数越低,越有可能是真评论。
虽然虚假评论指数还不是非常复杂,但我非常有信心它至少能够识别最明显的虚假评论并将其过滤掉。
为了说明虚假评论指数,我加入了两个不同用户对 iPhone X 的评论:

这个用户收到了 74.5 的假评论指数。从他的评论中可以明显看出,他几乎没有得到有用的投票,他的评论看起来也不真实。此外,该用户主要使用 5 星评级,并在同一天发布不同产品的几条评论。因此,他得到高的虚假评论指数分数。

第二个用户收到的虚假评论指数为 27,这使得他的评论很可能是真实的。事实上,这个档案似乎属于亚马逊评论社区的一名活跃成员,因为他的评论实际上详细描述了他对该产品的体验,不仅包括 5 星评级,还获得了更多有用的投票:

最后,在根据评论的虚假评论指数对其进行分组后,我得出了一个有趣的观察结果:评论越有可能是真实的,平均评分就越低。虽然下降幅度不是很大,但仍然很显著,因为很可能是真实的评论的平均评分约为 3.8。这个评分仍然很高,证明苹果的客户非常满意,尽管如此,它并不像之前讨论的验证评论的平均 4.5-4.75 那样高。

总结
综上,苹果的客户满意度还是很高的。iPhone 发布时互联网上的负面氛围,主要可以归咎于非客户。然而,当考虑到评论的真实性时,苹果的客户满意度并不像人们乍一看可能怀疑的那样高。
这个项目未来的扩展将包括一个更完善和复杂的虚假评论指数,然后可以普遍应用于不同的评论网站,使公司能够筛选出他们的客户中最相关的评论和趋势。
最初发表于T5【nycdatascience.com】。
圣地亚哥的街道有多安全?
用 Python 和 GeoPandas 来回答一下吧!

Costanera Center, Santiago / Benja Gremler
前段时间我写了一篇文章,解释了如何用 Python 处理地理地图,用的是“硬方法”(主要是 Shapely 和熊猫 ): 用 Python 绘制地理数据。现在是时候再做一次了,但这次,用一种简单的方式解释如何做,使用 GeoPandas,可以理解为 Pandas + Shapely 在同一个包中。
Geopandas 是一个开源项目,旨在简化 Python 中地理空间数据的使用。GeoPandas 扩展了 Pandas 使用的数据类型,允许对几何类型进行空间操作。
这篇文章的动机是最近由 Oscar Peredo 教授提出的一个项目,该项目由我的同事 Fran Gortari 和 Manuel Sacasa 为我们 UDD 大学数据科学硕士学位的大数据分析课程开发。
该项目的目标是利用最先进的机器学习算法,根据 2013 年至 2018 年的公共汽车碰撞数据,探索预测城市电网碰撞风险得分的可能性。另一方面,本文的目的只是学习如何在实际问题中使用 GeoPandas,回答一个问题:
"圣地亚哥的街道有多安全?"。
如果你想知道我们为我们的 DS Master deegre 做了什么,请访问它的 GitHub 库 。
安装 GeoPandas
使用 GeoPandas 时,您应该做的第一件事是创建一个全新的 Python 环境,并从该环境安装软件包。如果所有依赖项都已安装,您可以使用 PIP 简单地安装它:
pip install geopandas
但是正如 GeoPandas 官方页面上所推荐的,在一个全新的环境中实现它的最佳方式是使用 conda (GeoPandas 及其所有依赖项都可以在 conda-forge 频道上获得):
conda install --channel conda-forge geopandas
从 GeoPandas 开始
学习 GeoPandas 的一个很好的开始就是跟随 Benjamin Colley 的文章: 让我们制作一张地图吧!使用 Geopandas、pandas 和 Matplotlib 制作一个 Choropleth 地图 ,还可以看看西班牙语版爱德华多·格雷尔-加里多的作品Workshop de cartografía en Python。
使用地理地图时,定义将使用哪种地球投影至关重要。在本文中,使用的实际坐标是纬度-经度( EPSG: 4326 )模式,其单位是十进制度,并且是在参考球面或椭球面上:

WGS 84 (also known as WGS 1984, EPSG:4326)
另一种可能性是使用横轴墨卡托投影,这将是以米为单位的 2D 地图(对于智利“ESPG: 5361”):

这是你的选择,但要考虑到你不能把它们混在一起。
我们来绘制地图吧!
一旦安装了 GeoPandas,让我们开始导入一些基本的库:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import geopandas as gpd
from shapely.geometry import Point, Polygon
我们将下载的第一个形状将是定义我们工作区域的多边形。在我们的情况下,圣地亚哥市区!矢量地图可以在智利国会图书馆 (BCN)找到。
可用地图以 shapefile 格式包含智利所有 400 个城市区域。我们应该将其过滤为“圣地亚哥”,并将其转换为 ESPG:4326:
sf_path = "../data/BCN/areas_urbanas/areas_urbanas.shp"
sf = gpd.read_file(sf_path, encoding='utf-8')
stgo_sf = sf[sf.NOMBRE == 'Santiago']
stgo_shape = stgo_sf.to_crs({'init': 'epsg:4326'})
stgo_shape
此时,我们有一个 geopandas 数据帧,它只有一条线,除了长度和面积等数据外,还包括“几何图形”,即“包围”所有城市的多边形的坐标:

我们可以绘制这个地理数据框架,就像我们习惯于绘制正常的熊猫数据框架一样:
stgo_shape.plot()

注意,经度(横轴)从大约-70.80(西)到-70.45(东),纬度(纵轴)从-33.65(南)到-33.30(北)。
您可以使用以下方式确认准确的城市边界:
stgo_shape.total_bounds

此外,还可以获得形状的中心坐标(或质心):
stgo_shape.centroid

下面你可以在谷歌地图上看到同样的区域,太平洋在左边(西边),安第斯山脉和阿根廷边界在右边(东边)

Santiago Urban Area — Google Maps
从 OpenStreetMap 导入道路
OpenStreetMap (OSM)是一个合作项目,旨在创建一个免费的可编辑世界地图,由一个地图绘制者社区构建,该社区提供并维护有关道路、小径、咖啡馆、火车站等更多信息的数据。项目生成的数据而非地图本身被视为其主要输出。
网站 GeoFabrik 有来自 OpenStreetMap 项目的数据摘录,通常每天更新。这项开放式数据下载服务由 Geofabrik GmbH 免费提供。
开始从这个链接下载数据,并保存到你的/data/ depository 下的“/OSM/”。
从那里,让我们打开关于道路的形状文件:
roads_path = "../data/OSM_Chile/chile-latest-free/gis_osm_roads_free_1.shp"roads = gpd.read_file(roads_path, encoding='utf-8')
这个文件包含了将近 455,000 条道路。让我们开始用圣地亚哥形状过滤它(为此我们将使用)。sjoin ,所以我们只能处理我们感兴趣区域内的道路。
roads = gpd.sjoin(roads, stgo_shape, op='intersects')
即使过滤,我们也完成了大约 83,000 条道路。检查 roads 地理数据框架,我们可以看到它包含一个名为 fclass 的列。我们来看看:

这意味着几条道路主要位于居民区,同时也是用作服务区、人行道、自行车道、人行道等的道路。一旦我们对绘制车祸地图感兴趣,让我们只保留最有可能找到它们的道路,这将把数据集减少到大约 12,000 条道路。

我们也可以只过滤主干道(主要道路和高速公路):
main_roads = car_roads[(car_roads.fclass == 'primary') |
(car_roads.fclass == 'motorway')
]
main_roads.plot()

从公共数据集中导入车祸
在智利,可以在 CONASET 网站上找到 2013 年至 2018 年分类车祸数据的公共数据库。我们将从那里下载关于去年(2018 年)发生的事件的数据。
该数据集包含近 24,000 个已报告的事件,但不幸的是,并非所有事件都进行了地理定位。首先,让我们来看看几何数据遗漏了多少数据:
p0 = Point(0,0)
df_p0 = df_2018['geometry'] == p0
df_p0.sum()
结果是 3537 分。让我们把它们拿出来,看看我们有多少干净的数据:
s_2018 = df_2018[df_2018['geometry'] != p0]
s_2018.shape
结果是:20,402 个事件。非常好!我们可以利用这些数据。让我们对它们进行筛选,仅获取圣地亚哥地区内的事件并绘制它们:
ax = stgo_shape.plot(figsize=(18,16), color='#EFEFEF', edgecolor='#444444')
main_roads.plot(ax=ax, color='green', markersize=0.2)
crashes.plot(ax=ax, color='red', markersize=8)
plt.title("2018 Road Crashs - Santiago, Chile");
plt.axis('off');

哇!目测 2018 年圣地亚哥几乎每条路都发生过车祸!
挖掘数据
为了真正了解发生了什么,我们需要更深入地研究数据。
查看数据集,我们可以看到,除了包含每个碰撞事件的地理定位的“几何图形”之外,我们还会发现以下相关信息:
- 撞车发生的时间(日期和时间)
- 位置和区域(农村和城市)
- 位置类型(交叉路、环形路、直路、弯道等。)
- 车道数量和建筑类型(沥青、混凝土等)。)
- 路况(干燥、潮湿、油污等。)
- 天气状况(雨、雪、清洁等。)
- 事件类型(碰撞、撞击、人员撞击、火灾等。)
- 严重性(致命、严重、中等、轻微、非伤害)
让我们想象一下这些事件及其主要特征:




从上面的可视化结果中,我们可以看到,2018 年圣地亚哥发生的大多数车祸都是在沥青或混凝土道路上发生的碰撞和颠簸,因为几乎所有的车祸都发生在晴朗干燥的一天。
那么发生在的时候呢?让我们用与时间相关的数据创建新列:
crashes['Fecha'] = pd.to_datetime(crashes['Fecha'])
crashes['Hora'] = pd.to_datetime(crashes['Hora'])crashes['month'] = crashes['Fecha'].dt.month
crashes['day'] = crashes['Fecha'].dt.day
crashes['weekday'] = crashes['Fecha'].dt.weekday_name
crashes['hour'] = crashes['Hora'].dt.hour




不出意外。大多数事件发生在早上 7 点到晚上 10 点,交通挑选时间(早上 8 点和下午 6 点)是最复杂的。此外,撞车事故在周末和月末发生得更少(这是一个有趣的点,应该更好地调查)。请注意,二月是事件较少的月份。这是因为这是智利人的暑假季节,圣地亚哥通常在这个月成为“沙漠”。
创建热图
在 GeoPandas 上可视化数据的一个很好的方法是聚合小区域上的数据,这些小区域具有向我们显示特定区域中存在的数据量的颜色模式。例如,事件越少,颜色越浅(如黄色),事件越多,颜色越深(如棕色)。
首先,我们需要将城市分割成小区域(或多边形)。你可以使用网格、感觉区域等。在我们的案例中,我们将使用上一次智利起点-终点调查(EOD)中定义的区域,该调查可从 SECTRA(智利交通规划部长)处获得。
一旦你下载了 shapefile,你应该将它与你感兴趣的区域相交(在我们的例子中,stgo_shape)。结果将是 743 个更小的区域来获取我们的汽车碰撞数据。

接下来,您应该将事件聚合到城市区域中。为此,应该完成两项主要任务:
- 上述文件形状和崩溃数据集之间的连接。生成的数据集将为每条线提供一个点(碰撞)和一个相关联的面(大约 20,000)。您将会注意到,对于在其区域上捕获的每个点(事件),每个多边形都将重复。
- 一组结果数据集,按区域 id。合成形状应具有与原始形状相同的线条数(743)。
可视化热图非常简单。为此,您应该使用一个简单的绘图函数,但是定义 2 个参数:
- cmap:将要使用的 colomap 名称。在我们的例子中是“magma_r”。
- k:你想要“分割”你的数据范围的类的数量。在我们的例子中,5(通常,建议不要使用超过 7 种颜色来表示您的数据范围)。
ax = crash_zone_2018.plot(column='crashes', cmap='magma_r', k=5, legend=True)
plt.title("2018 Crashes by Zone - Santiago");
ax.set_axis_off()

现在,从视觉上很容易区分最危险的区域(较暗的区域)。但是这些区域和道路有什么关系呢?让我们在最后一张地图上想象圣地亚哥的主要道路:
fig, ax = plt.subplots(figsize = (10,6))
crash_zone_2018.plot(ax=ax, column='crashes', cmap='magma_r', k=5, legend=True)
main_roads.plot(ax=ax, color = 'blue')
plt.title("2018 Crashes by Urban Zone and main roads - Santiago City");
ax.set_axis_off();

看最后一个图像,我们可以看到,例如,靠近主干道交叉口的区域,更容易发生事故。
在地图上查看大量数据的另一个非常有用的方法是使用“地形视图”。就像看一座山,山越高,颜色越深(当然,会有不是高,而是事故的数量)。爱德华多·格雷尔斯-加里多在圣地亚哥市探索移动性方面做得很好。基于他的代码,我们可以创建自己的代码:

乍一看,我们可以意识到城市中最危险的区域在哪里。
在 gitHub 上,你可以看到用于创建这种虚拟化的代码。
创建严重性指数
到目前为止,我们对每一个碰撞事件都一视同仁,但当然,与它们相关的严重程度非常重要。让我们将严重性指数与每个事件相关联。为此,我们应该创建一个函数,将其应用于所有数据集:
def sev_index_crash(row):
if row['Fallecidos'] != 0: return 5 # fatal
elif row['Graves'] !=0: return 4 # serious
elif row['Menos_Grav'] !=0: return 3\. # less-serious
elif row['Leves'] !=0: return 2\. # minor
else: return 1 # non-injurycrashes['SEV_Index'] = crashes.apply(sev_index_crash, axis=1)
有了这个列,让我们来看看新的数据:
SEV_Index = crashes.SEV_Index.value_counts()
SEV_Index.plot.bar(title="Crash Severity Index", color = 'red');

幸运的是,2018 年的大多数撞车事故都没有造成伤害(1),其次是超过 5000 起轻伤(2)。
将严重性指数与道路相关联
对于本文,将使用一个更简单的解决方案,它是由 Alex Raichev 在 KIWI PYCON 2017 上提出的。
对于每条道路的线性路段(已经在 OSM 数据集上定义),我们将收集距离该路段给定距离(例如,5 米)发生的交通事故。为此,将使用 GeoPandas 函数缓冲区。注意,单个事件可以在多条道路上被捕获,例如在十字路口。但我们认为,一旦所有细分市场都受到影响,这应该很重要。

一旦我们用度数来表示角度,我们必须首先把米转换成度。我们可以用一个简单的公式来计算:
- 度数=(米* 0.1) / 11000
并为每个崩溃事件创建一个缓冲区:
meters = 5
buffer = (meters*0.1)/11000 # degrees
c = crashes[['geometry', 'SEV_Index']].copy()
c['geometry'] = c['geometry'].buffer(buffer)
接下来,我们需要空间连接道路和缓冲碰撞点
r = roads[['geometry', 'osm_id', 'name', 'fclass']].copy()
f = gpd.sjoin(r, c, how='inner', op='intersects')
下面我们可以检查生成的地理数据框架。请注意,lineString 是捕获了单个碰撞事件的路段。例如,前 2 行是名为“Rosas”(osm _ id:7981169)的街道的同一路段,其中捕获了 2 个碰撞事件(index_right: 11741 和 23840)。

现在,按路段 osm_id 对地理数据框架进行分组将非常重要。这样做,我们将有段聚合崩溃。我们将添加崩溃和严重性指数。这样,例如,一个致命的事件将比一个非伤害事件重要 5 倍。
注意,这种方法完全是武断的,不科学的。这只是本文中用来比较路段危险程度的个人指标。
f['num_crashes'] = 1
g = f.groupby('osm_id', as_index=False).agg({
'name': 'first',
'num_crashes': 'sum',
'SEV_Index': 'sum',
'geometry': 'first',
})
g = gpd.GeoDataFrame(g, crs='4326')
对我们将获得的地理数据框架进行排序:

生活在圣地亚哥,这个结果很有意义。至少从名字上看,Americo Vespucio 和 Bernardo O'Higgins 是两条最重要的城市动脉。
让我们想象一下所有街道,每个路段都有一种颜色(“热点地图”):
fig, ax = plt.subplots(figsize = (10,6))
g.plot(ax=ax, column='SEV_Index', cmap='magma_r', k=7, legend=True)
plt.title("2018 Severity Crashes by roads - Santiago City");
ax.set_axis_off();

但是,我们应该做的是在真实的地图上可视化每一段。为此,我们可以使用叶子。下面是市区的一段,显示了所谓的“阿拉米达”(Ave Bernardo O'Higgins)最危险的一段。

你可以从 GitHub 下载一张“圣地亚哥街道”的互动地图。
就这些了,伙计们!
希望你能像我一样欣赏地理和数据科学!
详情和最终代码,请访问我的 GitHub 库:圣地亚哥的街道
更多项目,请访问我的博客:MJRoBot.org
来自世界南部的 Saludos!
我的下一篇文章再见!
谢谢你,
马塞洛
神经网络的短期预测如何影响长期决策。

神经网络调峰:第二部分
电力公司只需三天的天气预报就能探测到每月的高峰。
与 合作研究开放建模框架 。
这是关于神经网络调峰的三部分系列文章中的第二部分。考虑一下另外两个:
[## 基于神经网络的⚡️负荷预测和调峰
预测技术给了公用事业单位一个机会来拉平他们的负荷曲线,提出了一个全新的家庭…
www.kmcelwee.com](https://www.kmcelwee.com/load-forecasting/)
对于电力公司来说,减少每月的需求费用可以获得巨大的利润。然而,每天实施调峰策略可能成本高昂。如果公用事业公司使用直接负荷控制(付费给客户关闭空调、热水器等)。),如果他们这样做得太频繁,可能会让客户感到沮丧。如果公用事业公司使用存储,过度使用可能会迫使他们不必要地频繁更换昂贵的电池。因此,不仅预测第二天的负荷形状很重要,预测当月的峰值也很重要。在理想情况下,按月收费的公用事业公司需要每月削峰一天。
不幸的是,与天气预测类似,负荷预测在几天后变得不可靠。在过去三天的预测中,我们的预测平均绝对误差为 10%(MAPE)。由于一整个月的日峰值落在 10 MAPE 范围内并不罕见,因此找到月峰值很快就变成了猜测。
令人欣慰的是,通过结合一些统计技术,我们可以将明天的预测放在上下文中,并大大减少我们派遣的天数。
设置
我们被一个简单的问题所激励:明天是这个月的高峰吗?
我们知道我们不可能有 30 天的预测,但是通过查看三天的预测、本月已经发生的情况以及历史峰值,我们可以回答两个较小的问题:
- 明天会是局部高峰吗?
- 这个月明天的负荷特别高吗?
最后,我们将结合这些答案,为我们的激励问题提供信息。
明天会是局部高峰吗?
“本地峰值”将意味着明天是三天预测中最高的,也高于本月已经看到的任何负载。在我们的 web 应用程序的测试版中,它是这样表示的:

以上是 2018 年 12 月 20 日德克萨斯州中北部地区的天气预报。因为“明天的预测峰值”比目前看到的最高峰值低得多,所以电力公司不会在 12 月 20 日实施调峰策略。
考虑到模型的预测可能在正态分布附近是准确的,我们可以为明天将是局部峰值的统计可能性分配一个数字。它由这个公式给出:


Given two normal distributions (subscripts 1 and 2, defined by their mean and standard deviation), what is the likelihood that the sample X₁ will be greater than the sample X₂.
如果你对细节感兴趣,这里有一个链接可以找到完整的解释。下面是我们如何扩展该公式并将其翻译成 python:
Function used to determine likelihood that tomorrow is local peak.
使用 12 月 20 日的示例并四舍五入到两位小数,明天的“局部峰值可能性”为 0.0%,主要是因为明天峰值的正态分布区域比迄今为止的最高峰值小得多。
这个月明天的负荷特别高吗?
这个问题比较容易回答。我们查看前几年的月度数据,并计算明天预测的百分位数。需要注意的是,我们计算的是每日峰值的百分比,而不是每小时的负载。
我们试图最小化什么?
我们有两个因素,“本地峰值可能性”和“峰值百分位数”,我们希望制定一个规则来最小化两个结果,“错过的峰值百分比”和“发出的百分比”
这两个结果是每个公用事业公司必须做出的权衡。如果他们希望确保每个峰值都被捕获(丢失的峰值百分比低),他们必须每天进行调度(进行调度的百分比高)。反之亦然:如果他们想保守调度数量,他们就有错过高峰的风险。
我们需要一个目标来最小化。因此,出于我们的目的,我们将简单地添加两个目标。在下面的热图中,最小化(右)的函数就是其他两个函数的和。自然地,考虑到电力公司的优先级,他们会以不同的方式权衡这个优化函数。由于这也有金钱方面的原因,适当的成本效益分析是必要的。但是这些计算对每个电力公司来说都是独特的。
结果呢
我对 2002 年至 2018 年德克萨斯州各个地区的 ERCOT 数据进行了测试。我从 2008 年到 2018 年运行该计划,以便“峰值百分比”变量有一些后见之明。整个测试过程可以在这本 jupyter 笔记本中找到。
我假设我们对一天的预测有 97%的准确率,对两天的预测有 95%的准确率,对三天的预测有 92%的准确率——这些结果在学术文献中很常见,也反映在我们自己的测试中。

Tests run on ERCOT’s SCENT data (San Antonio, Austin). Minimization of (% peaks missed + % dispatches made) for the two variables (“peak percentile threshold” and “local peak likelihood threshold”)
以上是德克萨斯州中南部地区的一个例子。请注意,在中心热图的顶部有一条明显的线。超过一半的每日峰值有 0%的机会成为局部峰值,这表明无论公用事业公司采用何种优化方法,这种方法都会立即将调度减少一半,同时很少错过峰值。该带在进行该试验的德克萨斯州的所有地区都出现。

The regions of Texas used in testing.
需要特别注意的是,上面的图表和下面的结果在创建调度规则时使用了逻辑“and ”(例如,如果本地峰值的概率≥ 4%,并且明天≥99 %,则进行调度。)我还测试了逻辑“或”,但结果总是更糟。
结果如下图所示。请注意,这些“规则”只有在事后才是准确的。每个电力公司都需要测试以前的政策在未来的负荷上的实施效果。正如人们可能预料的那样,在试图预测月度峰值时,没有一条规则适用于所有情况。然而,一致的趋势是,如果出现局部峰值的可能性大于个位数,并且如果预测的百分比相当高,就要调度。(北部的结果与德克萨斯州的其他地方截然不同,这里有一个链接指向它的热图。)

结果表明,“局部峰值似然性”变量在此函数中起了最大的作用,而百分位数因子有助于检测历史背景中明显的非峰值。
我没有忘记,这种优化也可以通过分解每个月的规则来辅助,甚至可以应用某种机器学习算法;但是,由于未来的负载行为可能会因技术和消费模式的变化而不同于过去,因此这些流程很容易成为过度拟合的牺牲品。
然而,公用事业公司有很大的机会利用机器学习和基本统计数据来更好地通知他们的调度决策,从而节省资金并在此过程中建立客户信任。
有问题吗?更正?数据科学笑话?联系我,查看更多项目在 我的网站 。
你的新闻来源有多聪明?
21 种不同新闻媒体的可读性分析

我认为理解我们新来源的观点和偏见比以往任何时候都更重要。不幸的是,新闻如此之多,以至于我们几乎不可能逃脱小小的过滤气泡。
幸运的是,让我们陷入这种困境的技术可以帮助我们渡过难关。使用电脑,有可能获得多种新闻来源的广阔视野,并看到他们最关注的领域。看到不同网点的写作风格如何不同也很有趣。虽然我们需要在自然语言处理(NLP)方面取得更多进展,以真正处理新闻偏见,但我们现在可以做一些有趣的分析。
为此,在过去的 6 个月里,我使用 python 报纸库从 21 个不同的新闻渠道收集了尽可能多的文章。这里有一些有趣的不同之处。
新闻的情感
当谈到新闻时,一个简单而有趣的事情是故事情节。使用 python VADER 库,我们可以给来自不同出版物的所有故事打分,并测量它们的平均情绪。正数表示更乐观的语言,而负数表示黑暗和消极的写作。

不出所料,《今日美国》的评价相当正面,而关于信息战争的阴谋论大多是负面的。令人惊讶的是,大多数新闻文章并不完全是负面的(尽管今日俄罗斯、布莱巴特和 Buzzfeed 似乎倾向于负面)。
如果我们只看新闻标题,我们会发现它们比故事内容更消极。毕竟坏消息更受关注。同样,Inforwars 头条是最负面的,只有华尔街日报得分正面。

新闻的可读性
新闻写作的另一个简单衡量标准是它的可读性。多年来已经开发了多种系统来衡量一个东西的易读性。下面我用 python textstat 库 ⁴比较了各种出版物的阅读难度。
弗莱斯奇-金凯可读性 Testing⁵
弗莱斯-金凯就绪测试是最受欢迎的测试之一。它根据每个句子的字数和每个单词的音节数来评分,即长单词和句子更难阅读。然后,它将该分数转换为等级级别。注意,这个结果和分析的句子内容无关。完全基于单词/句子的长度。
使用这种方法,我们看到 MSNBC 有最高的年级水平,使其最难阅读。这可能是因为 MSNBC 的“故事”只是网站上新闻视频的描述。它们被设计成描述性的,不一定可读。所有其他网站都包含适当的文章,甚至像 CNN 和 FoxNews 这样的网络新闻网站。
在光谱的另一端,BBC 新闻文章可以轻松阅读,只需要 10 年级教育。这可能是因为大多数 BBC 的报道短小精悍(很少有曲折的社论)。

戴尔-查尔可读性测试
戴尔-查尔公式使用单词长度,但也考虑了这些单词的难度。它保留了一个四年级学生应该理解的“简单单词”列表。使用这种方法,不在列表中的单词越多,阅读起来就越困难。
基于这个体系,我们再次看到 MSNBC 是最不可读的。除了现在《纽约时报》( NYT)和《华尔街日报》(华尔街日报)以 8 分左右的分数上升。这意味着他们需要 11 或 12 年级的教育才能完全理解。

雾霾 Grade⁷
雾霾分级系统使用多音节词(3 个或 3 个以上音节的单词)的数量来分配难度等级。我们再次看到 MSNBC、布莱巴特和政治使用最长的单词,而英国广播公司和洛杉矶时报使用更简单的语言。

射击雾 index⁸
喷雾指数也是用音节多的单词作为阅读难度的衡量标准,只是公式不同。有了这种新方法,《今日美国》成为最容易阅读的报纸。

每个故事的字数
最后,尽管不是严格的可读性测试,我们可以通过测量新闻报道的长度来了解新闻报道的复杂性。
注意——一些新闻网站是付费的,所以不可能总是收集完整的故事。还有一些网站要求点击“阅读更多”按钮来获取全文。这些来源已被删除。

我们看到,以解释新闻为使命的 Vox 拥有迄今为止最长的文章(1427 个单词)。政治和 Buzzfeed 紧随其后,平均每篇报道 1000 字左右。如果我们包括付费网站,《纽约时报》、《洛杉矶时报》和《华盛顿邮报》,它们也会接近 1500 字/篇。
就我个人而言,我认为《纽约邮报》是最完美的报纸,500 字的篇幅正好适合报道。社论往往更长。
新闻内容
不幸的是,NLP 工具还不够先进,不足以轻易发现政治偏见。然而,我们可以通过看标题来了解一家媒体的政治倾向。以下是基于术语使用频率的词云(大词是使用频率最高的词)。
三大全国性新闻媒体似乎大多是特朗普的报道机器(我确实担心它们未来的商业模式)。卡瓦诺证实的故事是所有三个来源中第二受欢迎的,而穆勒调查对 MSNBC 也很重要。

其他主要新闻来源的单词 clouds 也是类似的。虽然他们都痴迷于特朗普,但他们也涉及其他主题。《华尔街日报邮报》和《华盛顿邮报》有很多关于沙特的报道,而《纽约时报》有很多#MeToo 报道(“被告”、“男人”、“性”)。NPR 仍然谈论特朗普很多,但《今日美国》花了大部分笔墨在“最佳交易”的故事上。与此同时,英国广播公司正确地聚焦于英国退出欧盟和全球政治。





我们还可以看到,更新的纯互联网出版物覆盖面更广(政治除外)。《赫芬顿邮报》似乎有很多希腊语和西班牙语的文章,所以结果与其他语言的单词混在了一起。Vox 的主要报道是“解释者”(关于川普、沙特和卡瓦诺的常见话题),而布莱巴特和《每日来电》对美墨“边境”进行了大量报道。最后,《洛杉矶时报》(LA Times)、《波士顿环球报》(Boston Globe)和《纽约邮报》(New York Post)等当地报纸除了关注特朗普,还关注当地新闻(“加州”、“波士顿”、“纽约”)。他们也有许多老式的一般兴趣故事(“家”、“学校”、“男人”、“女人”等术语很常见)。
Word2Vec 分析
由于“特朗普”是新闻中的头条,我认为看看不同媒体如何看待他会很有趣。使用一种叫做“⁹”的技术,可以看到哪些单词被新闻媒体认为与 Trump 相似。
下面我们看到,围绕“川普”的词汇类似于用来描述“奥巴马”、“老布什”、“普京”、“Xi”(金平)、“博尔索纳罗”、“杜特尔特”和“马克龙”的词汇。似乎左翼和右翼都将特朗普等同于全球强有力的(或者激进的)领导人。
注意——尼尔“盖曼”混入这些结果的有趣事实表明,这种技术可能不太适合这种类型的分析。




结论
这些天我们读得最多的单词来自互联网新闻网站。这些出版物对我们的所见、所想和感受有着巨大的影响。然而,他们只对富有的资助人或他们的底线负责。科技创造了这种极具竞争力的媒体景观。也许科技也能帮助我们更深思熟虑地穿越它。
奖金结果
作为一个作家,我一直想知道理想的句子长度是多少。根据新闻标题的平均字数,答案是 10 到 14 个字。这是所有新闻媒体在这些点击中使用的长度。

我们也可以测量一篇新闻文章平均一句话的字数。在这里,我们看到大多数都在 21 到 26 个单词之间。这对我来说有点长,但我的背景涉及更多的技术和商业写作。英语专业的记者可能更啰嗦。

最差情绪头条
为了好玩,我把绝对最差情绪评分的新闻标题留了下来。下面这些反映了过去 6 个月最黑暗的故事。
- 联邦调查局局长雷:恐怖分子可能使用无人机袭击美国的“大规模集会”
- 唐纳德·特朗普将致命的加州野火归咎于对森林的“严重管理不善”
- 记者死亡人数:报复杀人在 2018 年几乎翻了一番
- 怀疑溺死儿子的母亲在谷歌上搜索了 100 多次杀害儿童的提示
- 疾病预防控制中心数据显示,美国枪支死亡人数达到近 40 年来最高水平
- 怀蒂·巴尔杰的致命监狱殴打:“他是无法辨认的”
- 前黑人雇员声称,特斯拉工厂是种族主义的温床
托马斯·弗里德曼
如上所述,大多数可读性测试都非常简单。它们不衡量句子是如何构成的,也不衡量单词是如何使用的。我想看看这些测试如何给我认为是真正糟糕的作品打分。为此,我从出了名的高深莫测的纽约时报专栏作家 Thomas Friedman 中挑选了最后 5 篇文章。他的分数在以下。
平均果肉-金凯级水平-12.1
戴尔-查尔可读性平均得分— 7.27(十年级)
平均喷涂雾— 13.03
平均烟雾等级——13.5
基于弗里德曼的写作风格有多么奇特,我认为雾霾等级是最准确的。无论他想说什么,你肯定需要一个大学学位才能理解。
如果你想知道,这篇文章有以下可读性分数:
弗里斯-金凯等级水平— 7.9,戴尔-查尔可读性分数— 6.81,喷烟— 9.64,烟雾等级— 11.3
笔记
位于 https://github.com/taubergm/news_readability的 GitHub 上的所有代码和数据(不包括受版权保护的新闻报道)
1 —“每天有 2.5 万亿字节的数据被创建”
2—【https://newspaper.readthedocs.io/en/latest/
3 — VADER 情感分析。VADER (Valence Aware 字典和情感推理器)是一个基于词典和规则的情感分析工具,专门针对社交媒体中表达的情感,对其他领域的文本也很有效。
4—https://github.com/shivam5992/textstat
我不得不修复这个库中一个与计算句子字数相关的小错误。我使用 nltk 标记器用自己的实现替换了 sentence_count()函数
5 —转换为年级水平之前的 Flech-Kincade 分数

6 —戴尔-查尔公式

7-烟雾公式

8-喷雾配方

9——来自维基百科。Word2Vec 模型“是浅层的两层神经网络,被训练来重建单词的语言上下文”。我承认我只是模糊地理解它是如何工作的。
Spotify 如何推荐你新喜欢的艺术家

一个关于数据、品味和非常有效的推荐系统的故事。
就在几天前,我在教的一门课上与一些学生讨论了推荐系统的影响。
网飞、亚马逊、脸书和许多其他在线服务使用我们的数据来推荐我们可能喜欢的其他产品。
这有帮助吗,或者只是为了巩固我们现有的偏好?
当我们的选择由旨在提供“参与”的系统决定时,我们如何发现真正新的或意想不到的东西?
因此,它们被编程为给我们更多我们已经喜欢的东西,这可能导致熟悉的影响向内螺旋。
这是一个比我想象的更大的问题,它让我思考了更多。
当受到不同的影响时,我们更有创造力,但是要在机器时代做到这一点,我们的品味必须符合一个数学模型。
科技不仅仅存在于我们的环境中;它从一开始就包围并塑造了我们的感知。重要的是我们要解决这个问题。
因此,我开始思考我们如何消费我们的音乐——特别是在 Spotify 这样的流媒体平台上。
这个故事将涵盖:
-Spotify 到底是什么?
-数字版 Spotify。
-Spotify 怎么这么了解你。
——推荐人制度。

更多这样的故事,订阅克拉克的免费时事通讯!
SPOTIFY 到底是什么?
Spotify: 基于云的数字音乐平台,提供对超过 5000 万首歌曲的跨设备访问,以及数量迅速增长的播客和视频。2008 年成立于斯德哥尔摩。
它提供一个免费的、有广告支持的选项和一个付费的、无广告的版本,每月 9.99 美元。每月 12.99 美元就可以获得 Spotify + Hulu(还是美国)。其他计划(家庭和学生优惠很常见)也有,但因市场而异。
Spotify 根据音乐人歌曲的播放次数向他们支付版税(实际上它与第三方签约来处理此事)。通常,每场比赛的奖金在 0.006 美元到 0.0084 美元之间。难怪歌曲越来越短,越来越上口。
该公司的一个新重点是 Spotify Marketplace,它向一系列“创作者”开放。这个双边市场旨在鼓励艺术家在 Spotify 平台上上传和编辑他们的作品,粉丝可以在这里发现和欣赏这些作品。
今年早些时候,Spotify 收购了 SoundBetter,以增加一套新的创作工具。面对苹果和亚马逊日益激烈的竞争,苹果希望这种方式能够降低运营成本,增加对消费者的吸引力。
这家公司是瑞典的,但目前它的总部在卢森堡。听众可以在 80 多个国家注册。
好,让我们从一些数字开始
10 月 28 日,Spotify 发布了 2019 年第三季度财报。我已经读过了,所以你也许不必读了。
总的来说,瑞典音乐流媒体平台今年表现不错。
关键统计:
- €本季度总收入 17 亿元,同比 2018 年增长 28%。
- 保费收入为€15.6 亿,超出预期。
- 广告支持的收入为€1.7 亿,大大低于预期。
- 经营利润率3.1%(€5400 万);这是 Spotify 自 2008 年推出以来第三个季度实现盈利。由于一些即将进行的投资,该公司预计第四季度将出现亏损。
- 高级(付费、无广告)用户同比增长 31%,从 8700 万增加到 1.13 亿。
- 免费(免费,广告支持)用户增长了 29%,从 1 . 09 亿增加到 1 . 41 亿。
- 这使得总月活跃用户(mau)增加了 30%。
- 与 Q2 相比,第三季度播客播放时间增长了 39%。
- Spotify 认为,其音乐服务的用户数量是苹果的两倍,其用户对 Spotify 平台的参与度明显更高。这是基于苹果公司在最近的声明中公布的公开数据。
Spotify 将拉丁美洲和亚洲列为今年和 2020 年的两个重要增长地区。Spotify Lite 现已在 36 个国家上市,这无疑有助于印度等国家的采用。
然而,头条数据来自北美。下图显示了 Spotify 用户的地区分布情况:

Spotify 在其本土欧洲建立了基础,但在 2011 年推出的美国面临更激烈的竞争。
Pandora(音乐平台,而不是魅惑手环或开罐器恶棍)是 Spotify 在这个市场上最直接的竞争对手。
2015 年 Q2 结束时,Pandora 的全球活跃用户数超过了 Spotify(分别为 7940 万和 7500 万)。
潘多拉已经向内聚焦,于 2017 年关闭了其在澳大利亚和新西兰的昂贵业务,以加倍其在美国的努力。
与此同时,Spotify 每年都在向更多的市场扩张,并启动了引人注目的广告活动。
截至 2019 年第三季度,Spotify 的 mau 数量是 Pandora 的近 4 倍(2.48 亿比 6310 万)。
我们可能预料到这个结果;潘多拉在它选择优先考虑的市场上仍然有相当多的追随者。
我们可能没有预料到的是,Spotify 现在在美国的 mau 数比 Pandora 还多(分别为 6700 万和 6300 万)。
而且,潘多拉的用户群正在萎缩;去年这个时候,它在美国拥有 6800 万听众。
这不是唯一重要的统计数据——事实上,远非如此。
2019 年第三季度,Pandora 的广告收入达到 3.15 亿美元,而 Spotify 在美国的广告收入为 1.9 亿美元。
潘多拉宣布了创新的新广告形式,这可能有助于品牌通过在线音频与观众联系。这是一个巨大的挑战;我们今天听到的很多东西都让人想起老式的广播广告,甚至连声音效果也不例外。
潘多拉的想法之一是创建互动广告,允许听众通过对着他们的设备说话来跳过或询问更多信息。
与基于文本的在线广告相比,这有助于解决音频广告的另一个挑战。
很难知道一个音频广告对它的接收者有什么影响。
互动语音广告创造了额外的数据点,这些数据点将反馈到 Pandora 的报告中,并帮助广告商衡量和改善业绩。
Spotify 的创始人着手创建一个开放平台,每首歌曲都可以免费获得,由广告支持。创始人之一(现任首席执行官丹尼尔·埃克)的早期资金来自卖给 TradeDoubler 的 Advertigo。
毫不奇怪,Spotify 正在转向交互式音频广告,这将很快开始为在 Spotify 应用程序中启用麦克风的用户播放。

Spotify 的目标是成为流媒体音乐的代名词。
例如,如果你在谷歌 Chrome 浏览器中键入 playlist.new,它会直接将你带到 Spotify。
这款应用可以通过智能扬声器使用,很快,Fitbit 佩戴者将能够通过手势控制他们的音乐。

明白了,很受欢迎。但是为什么呢?
这些天我们谈论了很多关于转换成本的话题。嗯,我当然知道。
这是微观经济学(个人决策经济学)中的一个术语,适用于消费者从一个供应商换到另一个供应商所产生的成本。
这可能意味着金钱、时间或努力。对于一个 iPhone 用户来说,升级到新的 iPhone 比赶上三星的潮流更简单。这将意味着建立新的账户,回答大量的问题,等等。
无论如何,这些都不是不可逾越的障碍,但是我们的大脑喜欢常规。这就是为什么你每周都会阅读这份时事通讯。
许多优步用户也有 Lyft 应用,增加第三个或第四个打车选择不会杀了他们。转换成本低;我想,如果出现一款更便宜、更快捷、更好的打车应用,我们就不会效忠优步了。
类似地,许多公司都沉迷于他们的新功能(有人需要在他们的智能手机上再装一个摄像头吗?)而忽略了客户真正想要的是什么。
这种情况打开了“中断”的可能性;一个新进入者突然出现,并提供我们想要的东西,而不是公司认为我们想要的东西。
在这方面,Spotify 必须保持警惕。亚马逊可以在其 Prime 订阅机器中包含音乐流媒体,而苹果和谷歌也活跃在这一领域。
当然,这仍然不能解释 Spotify 的持久流行,但我们正在朝着这个方向前进。

Spotify 明确而坚定地专注于使用参与度数据来了解并提供客户渴望的东西。
它估计,60%的时间听众在应用程序上处于“封闭”的心态;他们知道他们想听什么,他们只需要找到它。
剩下的 40%的时间是在“开放”的心态中度过的。
在这种心态下,用户投入的精力更少,滚动的次数更少,跳过的曲目更多,点击艺术家以获取更多信息的次数更少。
本质上,他们乐于接受新思想,但处于被动而不耐烦的状态。
我认为 Spotify 最初的吸引力在于大多数人的“封闭”心态。当 Spotify 推出时,能够免费播放任何歌曲是一个非常有吸引力的前景。
它仍然很吸引人,但现在许多其他服务也可以提供这种服务。
Spotify 的持久吸引力在于它如何迎合 40%的“开放”心态。

它开发了一个数学模型来理解艺术家和听众之间的关系,但也让这种关系充满了发现一首新的最喜爱的歌曲的飘渺的兴奋感。
这一成功的核心是推荐系统。
“音乐不像新闻,重要的是 5 分钟前甚至 10 秒钟前发生的事情。有了音乐,一首 20 世纪 60 年代的歌曲可能会像最新的 Ke$ha 歌曲一样与今天的人相关。”
—丹尼尔·埃克
SPOTIFY &推荐系统

“音乐是一种不用特定词语说话的语言。它用情感说话,如果是在骨子里,那就是在骨子里。”
——基思·理查兹
也许吧基思。
但当他发表这些离谱的言论时,他没有考虑深度学习算法。
真正神奇的https://pudding . cool产生了一系列基于大数据的歌曲流派分析,结果令人瞠目结舌。
这些视觉散文引发了关于它们揭示的模式的辩论。
乡村音乐使用的词汇范围较小,这可能是因为它的听众和它所描绘的地方比较熟悉。

乡村音乐也比任何其他音乐类型更多地谈论酒,而那些节制的基督徒则避而远之。
好吧,这一发现并不完全可耻,但看到这些趋势在图表中具体化仍然很有趣。

显然,随着时间的推移,音乐变得越来越重复。
谁知道辛纳特拉如此多变?尽管正如伟大的弗雷泽·克雷恩所说,“四个小时后,他的“叭-叭-叭-叭-a-a-a”听起来很像他的“勺子,嘣,嘣,嘣!""

Spotify 的一名数据科学家运营着网站http://everynoise.com/,该网站根据音乐流派之间的相互关系绘制出每一种音乐流派。
下面是来自上述网站的截图。它说,埃塞克斯独立音乐很像西班牙独立流行音乐。

当然,这些图表只是孤立地揭示了一点。然而,这些分析是由个体数据科学家进行的,主要是为了娱乐。
这种方法的风险在于,我们完全剥夺了音乐的乐趣。如果是在骨头里,正如我们的朋友理查兹先生建议的,我们会因为对数据驱动的一切无法满足的渴望而吸干骨头。
出于一些明智的商业原因,Spotify 希望避免这种情况。
相反,它希望扮演知情人士的角色,向你提示最新的乐队,那些你错过的 B 面和分割线,但肯定会“挖掘”。它希望通过将多样性与直接相关性相结合来实现这一目标:

考虑到这一点,让我们回到本周故事的介绍性问题:
Spotify 如何利用数据推荐新音乐,而不是简单地推荐更多相同的音乐?
好吧,Spotify 的推荐系统根据用户的历史交互(收听/跳过/添加到播放列表)、他们所听歌曲/艺术家的属性以及它认为“相似”的用户的偏好,为用户提供建议。
其他音乐服务(Songza、Pandora)使用人工标记对歌曲进行分类,而 Spotify 使用深度学习来自动化这一过程,并识别艺术家、流派和用户偏好之间的潜在模式。
Spotify 上有三种推荐模式:
- 协同过滤:利用你和相似用户的行为。
- 自然语言处理(NLP): 针对歌词、播放列表、博客帖子、社交媒体评论。
- 音频型号:用于原始音频。
协同过滤
这个模型非常重要。它使用“最近邻居”来预测其他用户可能喜欢什么。
这类似于网飞的模式,但 Spotify 的引擎不是由星级提供动力的。Spotify 必须使用像流计数这样的隐式反馈信号来推断我们喜欢什么。
事实上,网飞已经转向这种方法,因为它比使用显式反馈更可靠。如果你想了解人们,听他们做什么,而不是他们说什么。
Spotify 上的每个用户都有自己的喜好,这取决于他们听什么、什么时候听、多久听一次等等。
下面的图像看起来像一个天气系统,但它是一个石英记者的口味配置文件;Spotify 允许他访问自己的个人资料,但通常更愿意保护平台的这一部分。遗憾的是,我们无法登录并查看自己的个人资料。

虽然在 Spotify 上,这些品味档案看起来更像这样:

该简档用于形成每个用户的每周发现播放列表。
《发现周刊》对 Spotify 来说是一个巨大的成功;在推出后的第一年,超过 50 亿首歌曲通过这些播放列表播放。
这个想法很简单,但执行起来很复杂:找到 30 首听众可能会喜欢,但还没有听过(在 Spotify 上)的歌曲。二进制系统对歌曲使用标签 1(流式)和 0(从未流式),后者则根据用户喜欢它们的可能性进行组织。
该列表是自动创建的,每周一提供。

这使得 Spotify 能够展现那些原本可能无人知晓的艺术家和歌曲的“长尾”。
如果 Spotify 只关注 60%的“封闭”思维,当用户搜索特定的东西时,就很难让这些艺术家出现在观众面前。

这将对该平台的供应方产生负面影响,因为艺术家没有什么动力优先考虑 Spotify。反过来,这会降低 Spotify 对听众的吸引力;我们喜欢 Spotify 上有 5000 万首歌曲的想法,即使我们只听了其中很小的一部分。
亚马逊用这种方式推荐产品;事实上,这只是它在电子商务中占据领先地位的众多原因之一。有如此多的产品可供选择,该平台需要帮助我们找到重要的商品。
策划探索的意义超越了《发现周刊》。Spotify 的主页、基于情绪的播放列表和电台部分都可以进行额外的个性化设置。

Spotify 致力于迎合这 40%的时间花在“开放”心态上,这使得竞争对手更难复制其优势。

它还增加了随机选择来为推荐系统产生更多的反馈。
毕竟,风险相对较低。如果出现最坏的情况,用户可以简单地跳过他们不喜欢的曲目。如果 Spotify 推荐的点击数多于未点击数,这是听众可以接受的成功率。

这一切都确保了赫拉克利特的教导在数字时代得到了令人欢迎的重申:一个人不能两次踏入同一条河流。
自然语言处理
Spotify 的工程师对他们的工作非常开放,他们经常表示,自然语言处理在音乐上比人们想象的更有效。

他们可以将播放列表转换成文本文档,并分析歌词模式之间的相互关系。
与谷歌的 NLP 算法类似,Spotify 可以识别单个术语的同位置,并以此来预测短语的含义。
在下面的例子中,我们看到了某些术语相对于刺激“Abba”的得分。《舞后》的得分略高于《妈妈咪呀》,这几乎可以肯定是因为后者在意大利流行音乐中无处不在。
Abba 可能会被描述为“活泼的”和“非暴力的”,尽管我见过婚礼舞池提供相反的证据。

这种洞察力随后被输送到 Spotify 庞大的实体网络中,带来了丰厚的回报。
他们的测试发现,根据这些常见的形容词推荐歌曲会产生以前看不到的新链接。
例如,被描述为“黑暗”或“忧郁”的音乐会跨越流派。我们倾向于根据我们知道的类别来导航,比如古典、重金属或迪斯科舞。这是一个有用的目的,但 Spotify 的推荐方式给我们带来了新的选择,否则我们不知道如何找到。
事实证明,音乐是一种用特定词语说话的语言。我们只需要一点技术援助来帮助找到它们。
音频模型
我们评估的前两种模式带来了 Spotify 最近的成功;这第三种模式是其未来成功的关键。
如果一首新歌通过不断扩大的市场添加到 Spotify,Spotify 如何知道这首歌应该提供给哪些用户?
如果这首歌是来自一个新的艺术家,有一个小的追随者,它将产生非常少的数据点。艺术家可能会用类别和流派属性来标记歌曲,但是这仅对于过时的推荐系统来说是足够的。
除此之外,Spotify 使用搜索引擎使用的那种神经网络来理解图像的内容。这些网络处理原始音频以产生一系列特征,包括音调、速度甚至响度。
蠢朋克高度重复的《环游世界》看起来是这样的:

因此,Spotify 可以将这些新歌放入正确的播放列表,当用户与内容互动时,它们可以在额外的数据点上分层。
这对 Spotify 下一阶段的发展至关重要。
如果它可以向乐于接受的粉丝介绍新的艺术家,这些艺术家将开始收到版税。这应该会鼓励其他不知名的艺术家将他们的作品带到 Spotify 上,在某些情况下,甚至可以使用 Spotify 的新工具来录制和编辑他们的歌曲。

这都是好消息吗?
没有。尽管这种体制有许多令人印象深刻的优点,但也存在缺陷和威胁。
像 Spotify 这样的平台对我们文化的重要方面拥有很大的控制权。
当音乐离开平台,很可能被遗忘时,挑战就来了。这是一种平淡无奇的契约式关注,但我们应该记得,这不是一种文化的历史记录;这是一家私营企业。
随着 Spotify 广告业务的增长,它还将在后台收集更多数据,并出售给出价最高的买家。
Spotify 的动机是让人们继续听下去,因此它将尽其所能实现这一结果。

有时,这意味着用新的艺术家取悦顾客;其他时候,这意味着乏味的重复。系统并不知道其中的区别——它只是想得出一个结果。
随着 Spotify 走向开放的“市场”方式,新的威胁将会出现。视频和播客内容将为坏演员提供吸引注意力的途径。
对这些创作者来说,他们也有动机让我们继续看,听,点击,做除了离开以外的任何事情。
毫无疑问,这些都不是新问题,也不是 Spotify 特有的问题。
在本周的主要故事中,我们开始回答一个问题,即算法推荐系统是否必然会导致个人经验的减少。更多相同的,无限的。
Spotify 的例子提供了一个有启发性的案例,说明了融合不同模式带来多样性和相关性的好处。
这一切都是通过对我们如何聆听和分享音乐的心理和文化理解来实现的。
Spotify 旨在利用混音带的怀旧吸引力,并提升数字时代的概念。
如果我们想找出 Spotify 保持低流失率(不到 Apple Music 的一半)的转换成本,它们主要在于它如何在探索的“开放”心态中娱乐我们。
Spotify 承担了合理的风险,并优化了参与度,没有屈服于同样轻松获胜的诱惑。
在这个过程中,它展示了算法推荐如何扩展我们的经验范围。
SQL 如何让我成为更好的科学家
解释我为什么以及如何开始使用 SQL

SQL(结构化查询语言)是一种用于关系数据库管理和数据操作的计算机语言。关系数据库和 SQL 在工业界非常受欢迎,这是有原因的。当处理大型复杂的数据库时,关系数据库非常有用。SQL 作为一种语言,允许你有效地查询这些数据库。SQL 是一种声明式编程语言,这基本上意味着当编写 SQL 代码时,你知道它做什么,但是你不一定知道它如何工作。SQL 为什么是如此强大的语言,这一切都发生在幕后,它可以以极高的效率查询数据库。由于它是一种声明性语言,如果你熟悉命令式编程语言(例如 Python),你会发现它非常容易学习。同样,有了 SQL,致力于学习如何高效查询数据库的团队已经为我们做了艰苦的工作,并找到了查询数据库的方法。使用 SQL,我们只需告诉计算机我们想要做什么。
当我第一次学习 SQL 时,我并不认为它会对我的日常工作有用,因为我是一名研究计算认知神经科学的研究生。我意识到,既然 SQL 在工业界如此受欢迎,我就必须学习它,但我并不打算在学生时代使用 SQL。在稍微思考了一下如何在我的工作场所使用 SQL 之后,我意识到创建/维护关系数据库在我的工作中非常有用。
为什么我选择开始使用 SQL
我的研究调查了一个名为衰老的认知神经科学的学科,这意味着我通常会进行人类大脑成像研究,其中包含年轻人(~ 18-29 岁)和老年人(~ 65-79 岁)的人类研究参与者样本。具体到老年人参与者,实际上很难找到(1)想要参与通常持续几天的研究的参与者,以及(2)接受持续 1-2 小时的 MRI 的参与者。因此,参与我的研究和实验室内其他研究的或多或少是同一批老年人。尽管每项研究设计不同,但通常每项研究都有相似的组成部分。例如,通常实验室内的所有研究都包含相同的神经心理学评估。我们实际上是在进行一项纵向研究,但却没有意识到这一点。
尽管我们年复一年地使用相同的参与者,但在实验室中没有一个好的系统来跟踪哪些参与者完成了我们的每项研究。基本上每项研究都是相互独立的。没有一个合适的系统来跟踪参与者,这确实是一个遗憾。那时我意识到创建一个标准化的实验室范围的关系数据库管理系统有可能改变我的研究。我可以创造一种方法,轻松地跟踪参与者并在一个地方维护他们的数据。创建这个数据库管理系统有几个好处。首先,我或我的一位同事可以进行一些有趣的分析,包括随着时间的推移跟踪参与者的认知表现(如记忆),看看谁表现出认知下降,谁没有,以及他们参加了哪些研究。此外,创建关系数据库管理系统可以节省管理评估的时间。我和一位同事可能在同一时间进行两项不同的研究,并使用相同的神经心理学工具。如果相同的参与者完成了每项研究,为了避免实践效应,他们不应该每次都接受神经心理学测试。最后,我们可以在研究之间折叠数据。例如,我主要进行脑成像研究,但我的一些同事只是进行行为研究。一位同事可以查询关系数据库,看到他或她的许多参与者完成了我的研究,并可能将行为测量与我的成像测量相关联,反之亦然。总之,创建关系数据库系统有可能增加我工作的影响。
创建数据库
既然我已经论证了为什么我认为创建数据库对我的工作有益,那么我将解释我是如何创建这个数据库的。我是关系数据库设计的初学者,所以我欢迎任何反馈。在创建数据库之前,创建一个数据库结构图是很重要的。有很多程序可以做到这一点,但我使用的是完全免费的 DBDiagram 。下面是示意图:

该图的细节并不太重要,但基本上每个参与者都被分配了一个唯一的参与者 id,并且每个研究都被分配了一个唯一的研究 id。NIH 工具箱是神经心理学的成套工具,在筛选问卷中还有一些其他的评估。
为了实际创建数据库,我使用了 SQLite,特别是 Python 中的 sqlite3。为了确保数据输入正确,我使用 SQLite 的 DB 浏览器查看数据库。对于有兴趣学习 SQL 的读者,网上资源很多,但我特意用了一个 Coursera class , Python 给大家,最重要的是,用自己的数据练习!
我不能公开数据,因为它包含参与者的个人信息,但你可以在我的 GitHub 上查看用于创建数据库的脚本。截至目前,该数据库只包含一项研究,但最终它将扩展到包括多项研究和更多的研究数据点。
结论
我相信我的同事和我自己将从这个数据库中受益。我很高兴看到这个数据库将有助于产生什么新奇的分析!最后,我将以最后一条建议作为结束,那就是如果你认为你不能从关系数据库的使用中获益,请三思。数据库管理在任何机构都很重要,它有可能使您的生活更加轻松,并提高您的工作质量。
如何成功创造隐私文化

隐私绝对是 2018 年的流行语。随着通用数据保护条例(GDPR)的生效,各公司都在努力满足该条例的要求。但是,从法律文本到执行,差距很大。实施 GDPR 的法律要求意味着将法律义务转化为实际步骤、具体目标和具有成本效益的商业计划。法律义务与创新和技术产业的现实之间也存在巨大的脱节。法律要求风险评估、警惕性和合规性,而客户要求效率、敏捷性和结果。
小组织面临的挑战不同于大组织。资源是有限的,当游戏中的大玩家忽视隐私时,更难说服人们认真对待隐私。然而,我们的经验证明,你不需要成为一个大组织来启动你的隐私计划。EURA NOVA 于 2018 年 1 月正式开始其隐私计划。回顾过去,我们已经走了很长一段路,我们可以自豪地说,我们有一个不仅合规而且重视隐私的组织。
以下是在 EURA NOVA 实施隐私计划过程中获得的一些技巧和经验,展示了 EURA NOVA 如何将隐私纳入主流并创造数据保护文化。
使隐私相关
启动一个成功的隐私计划需要不同利益相关者之间的合作。当组织中有更迫切的需求时,通常很难证明为隐私项目留出预算是合理的。EURA NOVA 隐私计划的第一步是让人们对此感到兴奋。为了确保组织中的每个人都遵守法律要求,我们在全公司范围内开展了培训。
中小企业的优势之一是,与许多选择在线培训的大公司不同,它们有机会进行现场培训。我们将现场培训作为接触每一位员工的机会,并开始不同项目人员之间的对话。我们的实践培训使法律义务与员工的日常工作相关。我们让培训变得有趣且有针对性,并收到了员工的积极反馈。
我们还意识到,一次性培训不足以解决所有持续存在的问题。因此,我们将隐私培训视为一个持续的项目。在这一年中,我们采取了各种举措,抓住一切机会谈论隐私。例如,我们与工程团队一起组织研讨会,分析不同的项目,一起寻找降低风险的最佳解决方案。通过这种方式,我们设法与不同的单位协调工作,并将隐私融入设计阶段。
如果您有兴趣接受为您和您的员工量身定制的有趣的 GDPR 实践培训,请通过 marketing@euranova.eu 联系我们

我们的通用 GDPR 培训提供:
- GDPR 的主要概念介绍
- 理解您所在组织的法规和法律要求的实际含义。
- 该培训适合所有员工。
我们的隐私和技术培训为您提供:
- GDPR 的主要概念介绍
- 设计隐私导论。
- GDPR 合规以及人工智能和 IOT 等新技术的实际例子。
- 该培训专为工程师、系统架构师和数据科学家量身定制。
自下而上的方法

EURA NOVA 是一家不分等级的公司,对我们来说,这意味着每个员工的声音都应该被听到,每个意见都是有价值的。我们想要一个符合我们文化的隐私计划。以下是我们的经验告诉我们的:
- 为项目设定现实的目标至关重要。此外,我们的成功源于理解不同团队的关注点,以及客户的要求,并建立清晰的沟通渠道。
- 如果你希望员工遵守数据保护原则,首先要确保你的行政部门理解并尊重员工的隐私。例如,我们从内部隐私声明和对行政部门的内部审计开始。
- 委派任务,让员工培养对隐私风险的关注。因为无论你雇佣内部还是外部的数据保护官员,她都不可能参与到每个项目的每个细节中。在某些时候,你必须依靠员工来意识到风险并提出正确的问题。重视员工的意见,让他们参与隐私风险评估,并为您的具体问题找到正确的解决方案。
- 避免普通律师散布恐惧的错误。虽然让每个人都知道法律风险是非常重要的,但为了让您的隐私计划有机地发展,对业务现实有一个清晰和公正的了解也是同样重要的。
准备好面对挑战

归根结底,实现数据保护合规性的道路并不平坦。该油田仍在开发中。因为监管比技术发展要慢得多,所以总会有一些法律没有答案的问题。例如,目前存在一定程度的不确定性,尤其是在人工智能等灰色领域。
我们的解决方案是紧跟新的法律和司法发展、学术研究和权威机构的建议。更重要的是,我们准备好提供创造性的解决方案并面对困难的问题。
淘宝的视觉搜索技术是如何工作的

它已经吸引了奢侈品零售商。
在本周的文章中,我们来看看中国电子商务巨头阿里巴巴旗下的淘宝。
它一直在增长,有趣的是,今年它成功地吸引了奢侈品零售商。
我也测试了淘宝的视觉搜索引擎,看看它与我们在 Pinterest、谷歌和亚马逊的老朋友相比如何。
我们来好好看看:
- 一些淘宝花絮。
- 淘宝和奢侈品零售商。
- 淘宝视觉搜索的工作原理。
- 懒汉测试。
一些淘宝花絮
在我们动手操作视觉搜索小发明之前,让我们明确一下淘宝是什么。
如今越来越多的情况是,这是一个比看起来更困难的任务。
这些巨型公司跨越行业和技术,扰乱了我们人类在这个过程中给一切贴上标签的欲望。
因此,淘宝于 2003 年由阿里巴巴集团创立,是中国最大的在线市场。
它最初是一个 C2C(消费者对消费者)销售平台,类似于 Ebay。事实上,淘宝的推出是阿里巴巴的一项防御性举措,旨在保护其在线主导地位,对抗 Ebay 新生的、但仍非常真实的威胁。
碰巧的是,淘宝以惊人的权宜之计扼杀了中国的 Ebay。
2003 年,Ebay 占据了中国 C2C 在线市场 79%的份额。然后淘宝出现了,到 2006 年易趣中国就没了。
淘宝如何应对 Ebay 在中国遭遇的这场迅速而致命的打击,有着重要的教训。
从我对这个话题公认的有限研究来看,淘宝似乎有一些关键的竞争优势:
- 价格: Ebay 向中国用户收费,让他们列出自己的产品。淘宝通过免费提供商品来吸引用户,然后通过广告将受众货币化。
- 本地知识:用户体验完全是为中国用户设计的,他们为论坛版主添加了一些小的改动,比如使用中国小说和漫画中的人物名字。
- 即时支付:2004 年,支付宝给数百万中国购物者带来了在线支付,也是淘宝提供服务的核心组成部分。这对小企业来说尤其是一个重大的好处。
- 客户服务:淘宝,或许比任何其他个人网站都更能提高中国消费者对客户服务的期望。自 2003 年以来,它为买家和卖家提供即时通讯工具。
不可能只孤立出导致这种优势的一个因素。淘宝创造了一系列互补服务,形成了自己生态系统的基础。
但是,我们可以说,这四个要素仍然是淘宝本地优势的基础。
我们还在 2006 年,所以我会加快步伐。
到 2008 年,淘宝占据了中国在线市场 80%的份额。
在这个阶段,它开始涉足电子商务的其他领域。首先,淘宝在 2008 年 4 月推出了淘宝商城(现在简称为天猫)。
如今,天猫据说是奢侈品品牌进入中国电子商务的门户。“奢侈品馆”的引入促进了这一点,它允许品牌在天猫内创建自己的在线商店,以符合他们的身份。
在 2019 年的光棍节(一个非常透明的购物假期,由阿里巴巴发明),295 个国际奢侈品牌“出席”了这场数字盛会。其中 40%的品牌抓住机会推出新产品,超过 95%的品牌整合了华北(支付宝虚拟信用卡)作为支付选项。
国际品牌已经慢慢学到了一些关于中国市场的惨痛教训。
今年,许多知名零售商选择与阿里巴巴合作,创造新的在线体验。与只翻译内容并等待人民币滚滚而来的老方法相比,这似乎是一个明智的选择。
瓦伦蒂诺与阿里巴巴人工智能实验室合作,创建了一个 3D 虚拟商店:

平均而言,顾客每次访问华伦天奴电子商店的时间超过五分钟。我不知道他们买了多少产品,但这似乎仍然是相当积极的。
博柏利在光棍节推出了在线围巾刺绣服务,这对我来说并不那么令人兴奋。但是我知道什么?他们仅在 3 小时内就卖完了一些围巾图案。

如果你喜欢这类东西,博柏利还与微信的母公司腾讯 T3 合作,为社交媒体创造内容。
就阿里巴巴和腾讯等公司而言,它们的“行业合作伙伴经理”团队正在以谷歌都无法企及的速度增长。
淘宝占阿里巴巴收入的 86%,天猫在最近一个季度的收入同比增长 34%。
今年 8 月,竞争对手腾讯公布了 13 年来首次季度销售收入下降(2%),而阿里巴巴继续快速增长。如今,仅在中国,其网站的移动设备年访问量就超过 6.2 亿。
如今,我们对这些数字不太敏感,但很明显,阿里巴巴将其 2019 年的成功在很大程度上归功于淘宝天猫上奢侈品牌的到来。
就在不久前,奢侈品零售商还对淘宝心存疑虑,因为它以出售廉价仿冒自己产品而闻名。
中国对奢侈品零售产品的需求越来越大,而且已经持续了一段时间。然而,很少有人会预测到淘宝会成为最大的受益者。
迈克高仕首席执行官今年早些时候表示:“阿里巴巴的天猫奢侈品馆是我们传达迈克高仕品牌愿景的绝佳场所。"

如你所见,关于这家公司有很多要说的。在我们继续之前,我将总结几个要点。
淘宝精品店让较小的零售商能够与他们的受众建立联系。
商店“工作人员”提供的不仅仅是顾客服务,他们还充当私人购物者,向购物者推荐新产品。
一位店主在最近接受《京日报》 采访时说:“我的一些客服团队成员喜欢与顾客进行朋友间的交谈,与他们建立了非常亲密和务实的关系。”
淘宝的电视直播功能还允许卖家把他们的客厅变成他们自己的 QVC 风格的工作室。视频是淘宝今年成功的一个重要方面,大多数商品页面都包含至少一部迷你电影。
此外,淘宝最近在马来西亚开设了一家“实体零售体验”(以前称为“一家商店”),此前在新加坡成功推出了一家类似的商店。
它将出售受欢迎的本地产品,类似于美国的亚马逊四星级商店。中国已经有很多这样的商店,但淘宝现在把目光投向了其他亚洲市场。

我们略显懒散的西方比较点是亚马逊,两者基于相似的买卖动态。
淘宝现在成立的目的是运输杂货,它正在吸引高端零售客户,此外它还提供复杂的人工智能服务、云计算和线下商店。
到目前为止,亚马逊。
尽管如此,淘宝的发展轨迹在很多方面都非常独特。
淘宝最初是一个 Ebay 式的 C2C 市场,它提供快如闪电的客户服务,并在自己的平台上扮演更亲力亲为的角色。
因此,任何此类比较都只能让我们有限地了解淘宝的成功之处。
也就是说,两家电子商务巨头都同意的一点是,视觉搜索的重要性正在上升。
**拍立陶 **
普通读者会非常了解我对 视觉搜索 的兴趣。
Pinterest 和谷歌提供高效的基于摄像头的搜索,而许多零售商也开发了自己的视觉搜索技术。
正如人们所料,百度、腾讯和阿里巴巴等中国公司也处于该领域技术发展的前沿。
在阿里巴巴的案例中,Pailitao.com一直是他们视觉搜索努力的焦点。虽然基于摄像头的搜索自 2014 年起就在淘宝上推出,但拍拍淘一直是一个独立的视觉搜索引擎。
Pailitao (‘拍立淘’ in Chinese) seems to mean ‘Polaroid’ or ‘shopping with a camera’, so that makes sense.

说到翻译,我真希望谷歌翻译在阅读派力陶主页上的这篇文章时是不准确的:

我的意思是,我知道他们说你可以在网上买任何东西,但这似乎有点多。
总之,我找到了一篇名为《阿里巴巴的视觉搜索》的科学论文,这篇文章对我很有帮助。
根据这篇论文,它是这样工作的:

安全了吗?
基本上,用户要么用相机搜索,要么在派力陶手机应用上上传图片。视觉搜索引擎然后试图隔离图像中的重要项目,提取它们最显著的特征,然后预测项目所属的类别。
从这里,它可以搜索它的产品索引来找到匹配,然后向用户显示最准确的结果。基于用户是否点击结果,该算法可以学习它的哪些建议是最有效的。
它看起来有点像这样,逐屏显示:

当它进入计划时,对用户来说是很棒的。他们不需要详细描述物品;通过将摄像机对准正确的项目,他们可以获得快速、准确、个性化的结果。
阿里巴巴将视觉搜索视为一个巨大的增长机会,并已着手将拍拍淘整合到淘宝的更多服务中。

那么,淘宝视觉搜索管用吗?
确定的唯一方法是测试它的速度,在我写这篇文章的时候使用手边的物品。
第一条:我桌子旁边的地板上有一双运动鞋。
在这种情况下,很可能用户想要找到该产品的近似匹配。图像非常清晰,几乎没有背景噪音,除了标准发行的伦敦出租物业地毯。

结果:这一点无可争议。仅仅等了四秒钟,淘宝上就找到了同样颜色的运动鞋,尽管价格相差很大,要么是 999 元,要么是 1539 元(134 美元或 229 美元)。
不过这是一个卖方的问题,所以我们会给淘宝五个相机(共五个)来买那个。
第二件:一个艺术风格的杯子,内含复杂的海边设计。
这才是真正的测试者。一些视觉搜索引擎会关注物品的形状,这不利于设计。任何人搜索这个不一定要确切的项目,而是类似项目的灵感。
让我们看看他们是如何相处的:

结果:一点都不差。
它会选择设计中包含的形状、颜色,甚至是物体。也许对基于姆明的设计有过度的偏好,但是我们在这里吹毛求疵。
让我们在这一个上给他们 4.5 个照相机。
第三项:乐福鞋。
这会告诉我们需要知道的一切。
通过 Loafie 测试是视觉搜索成就的典范。如果艾伦·图灵还在世的话,他会致力于此。
我一直在用它来尝试一系列类似的技术,并整理了一些关于这个主题的演示文稿— ,就像这个 。
如下所述,Loafie 是我在办公椅上用来支撑腰部的垫子。因此,这些天他比这张照片中的他更加憔悴:

我们可以从测试结果中看出视觉搜索引擎优先考虑哪些功能。
那么,我们来看看淘宝:

结果:它似乎专注于他的颜色和那价值百万美元的微笑,乌龟是一个特别的亮点。不可否认的是,其他一些结果更难解释。
微笑帽产品引起了我的兴趣,所以我仔细观察了一下:

这似乎是一条毛巾,兼作一顶时髦的帽子,绕过了费力的“头巾”方法的需要。
与 Pinterest(目前的 Loafie 测试领导者)相比,淘宝在解释如此细致入微的对象时表现良好。然而,仍有改进的余地。
五个摄像头中的三个。
【现在看,现在买】
阿里巴巴成功背后的驱动力淘宝提供了可视化搜索体验,帮助用户在全球最大的商店中找到合适的商品。
然而,这只是开始,我们应该很快就会在天猫的奢侈品零售店看到视觉搜索。
事实上,淘宝在 2019 年巴黎时装周上推出了“现在看,现在买”活动,让观众可以毫不夸张地购物。只需将相机对准最新时尚,淘宝就会指引你到合适的天猫精品店进行购买。
淘宝也利用这些西方时装秀在海外推广中国设计师。这些被称为“中国酷”的活动已于今年 9 月在纽约和米兰举办。
它将即时客户服务、免费商品列表和无缝在线支付结合在一起,帮助确立了淘宝作为中国电子商务主导力量的地位。
在其下一个增长阶段,一系列复杂的服务将有助于吸引奢侈品零售商和购物者到该平台。
视觉搜索将是把这两方面结合起来的关键因素。
亚马逊 Go 商店的人工智能是如何工作的
深入探讨亚马逊如何使用 AWS、ML、RL 和模拟来推动 Go Store 的“走出去”体验。
我住在芝加哥,我们很幸运地拥有 4 家 Amazon Go 商店,这是一家未来主义的便利店,你只需走进去,拿起你想要的东西,然后走出来。几分钟之内,你就可以拿到你所拿走的所有东西的准确收据。这感觉真的很神奇,但实际上这是大量的机器学习创新,亚马逊花了 3 年时间做概念验证,又花了 3 年时间生产 go 商店。今天在他们的 re:MARS 会议上,他们对提供“走出去”体验所需的大量创新进行了首次技术深度探讨。我想向你介绍一下他们分享的内容,这样我们就可以分享对这一惊人成就的敬畏。

The high-level architecture of the platform
计算机视觉核心:“走出去”技术
Go 商店的核心是基于计算机视觉的机器学习,用于无缝跟踪和评估商店中每个人的意图。亚马逊对这项技术的实现进行了令人惊讶的详细描述。虽然他们没有展示他们模型的确切神经架构,但他们展示了这些单个模型解决的具体问题,以及它们如何组合起来构建完整的解决方案。

本部分由首席科学家、前南加州大学计算机视觉教授 Gerard Medioni 博士演示。我不得不说,他不仅是一个出色的研究员,还是一个出色的演讲者。他设法在短短几秒钟内涵盖了激烈的话题,回答了 go store 背后的开创性问题:谁拿走了什么?

根据 Medioni 博士的说法,围棋库是一个“计算机视觉完全”问题,指的是计算机科学中的 NP 完全类算法问题。在这个顶级问题中,需要解决 6 个核心问题来提供体验。
传感器融合:聚合不同传感器(或摄像机)的信号,因为这个问题只用计算机视觉就解决了
校准:让每台摄像机非常准确地知道它在商店中的位置
人员检测:持续识别和跟踪店内的每个人
物品识别:区分出售的不同物品
姿势估计:检测货架附近的每个人用手臂在做什么
活动分析:判断一个人是否拿走了一件物品还是归还了一件物品。
Just Walk Out 技术的详细架构包括以下组件:

Just Walk Out Architecture
个人识别
定位器:问题“谁拿了什么?”不能用一系列独立的选择来解决。亚马逊必须跟踪每个人在商店的整个时间,从他们走进商店的那一刻直到他们离开。定位器组件必须解决的一些难题是:
- 遮挡,一个人被商店里的东西挡住了视线
- 纠结状态,人与人之间很亲近
为了解决这些问题,亚马逊使用定制的摄像头硬件来进行 RGB 视频和距离计算。在那里,他们将图像分割成像素,将像素分组为斑点,并将每个斑点标记为人/非人。最后,他们使用多个摄像头对每个人进行三角测量,从帧中构建位置地图。
链接器:下一个任务是确保标签在视频中的帧间得以保留,从定位转移到跟踪商店中的顾客。这一阶段遇到的问题有:
消除困惑状态:当两个人靠得很近时,会降低对谁是谁的信心。go store 技术通过将这些客户标记为低信心来处理这一问题,因此他们会被安排随着时间的推移进行重新识别。
有一个后续阶段用于区分亚马逊员工,他们的行为可能与客户不同(例如,他们可能会将商品放在货架上,而不是拿下来)。
物品标识
商品 ID 检测:这里要回答的关键问题是:哪些具体的商品是下架了,在某人手里。这一阶段面临的一些问题和解决方案是:
- 非常相似的物品,如同一品牌饮料的两种不同口味,在 CNN 层识别出物品类别后,使用残差神经网络进行精细的产品识别(我猜是跨多个帧)来区分
- 光照和变形改变了物品,这通过使用针对这些特定挑战的大量训练集数据生成来解决
客户协会
最具挑战性的问题可能是将上述步骤中的所有信息结合起来,最终回答“谁拿走了什么?”问题。
The “who took what?” decision is made from a stick figure model of the customers
姿势估计:位置跟踪 Go 商店摄像机从上往下看,而不是从等轴视图看,因此它们需要通过表示商品和顾客之间手臂的像素来跟踪路径。一个简单的自上而下的模型不足以解决这个问题,因此团队开始从视频中构建一个类似简笔画的客户模型。

需要一种新颖的深度学习模型来从视频中构建每个客户的关节模型。它使用具有交叉熵损失函数的 CNN 来构建联合检测点云,自回归用于向量生成,成对回归用于将向量分组在一起。这个模型本身非常有趣。他们表明,它可以用于任何视频剪辑,以帮助解决许多其他依赖于姿态估计的问题。
动作确定:为了避免对顾客没有拿走的商品收费,系统必须准确地考虑顾客可以将商品放回货架的情况。
上图可以看出这方面的一个问题。这个问题的明显答案是某个项目被拿走了,但这是不正确的。取而代之的是,顾客将一件商品放回原处,并将剩余的商品推到货架的更后面。为了解决这个问题,系统需要计算货架上的所有商品,而不是使用基于空间的简单假设。
长尾:当人们从货架上挑选一件物品时,可以有很多种姿势,尤其是当你考虑到附近有多个顾客的时候。只是没有足够的标记数据来训练每一个模型。即使有人类标记,也不可能扩展训练数据集(在金钱和时间上)。

Simulated data is used to solve for difficult situations
为了解决这个问题,该团队承担了一个雄心勃勃的项目,使用模拟器生成合成活动数据。在这些模拟器中,他们需要创建虚拟顾客(包括服装、头发、体型、身高等的变化)。)、相机、照明和阴影,并模拟相同的相机硬件限制。然而,回报是巨大的:
- 数据是预先注释的,因为它是生成的,这使得注释模拟数据便宜 3 个数量级。
- 该团队可以横向扩展计算来生成数据(他们有 AWS 云来做到这一点)。
- 注释在框架之间非常一致,而人类注释者则不是这样。
通过使用模拟来建立大规模的训练集,该团队能够利用云的力量在一天内对几个月的数据进行训练,消除了时间瓶颈,并实现了快速进步。这与 DeepMind 训练 AlphaStar、OpenAI 训练 Open AI 5 以及自动驾驶公司训练其驾驶员模型所使用的技术非常相似。
流媒体服务
如果视频不流动,任何计算机视觉魔法都不起作用。最初要解决的挑战是将视频从商店中取出,放到云中进行处理。该系统具有以下组件:
- 通过板载计算进行视频捕获,进行基本预处理并降低带宽要求
- 现场视频流设备,处理视频编解码器、网络问题,并保证交付到云
- 云上的视频服务器在 S3 和迪纳摩捕获和存储视频
管道中这一阶段的一个关键方面是冗余和异常检测,以处理跨系统(摄像机、网络、云基础设施等)的真实故障场景。)并提供弹性。
进入和退出检测
下一个挑战是检测人们何时进出商店来创建购物会话。该系统具有以下组件:
- 当你出现在商店时,移动应用程序扫描二维码。他们花了很多时间在这上面做 UX 测试(手机上下扫描,如何处理群组,等等。)
- 当您扫描二维码时,关联系统会根据您在商店入口处的位置,将您在视频中的肖像与您的帐户关联起来
- 会话的创建基于关联发生
在实现系统时,团队必须解决一些额外的场景。首先,人们可能会扫描多次,所以他们必须在第二次扫描时删除任何没有项目的会话。一个更困难的问题是,顾客(尤其是家庭)想集体购物,但只有一个人付款。为了实现这一点,当每个人进入商店时,负责人/付款人扫描相同的代码。这将创建一个会话,将该组中的所有人链接到同一个帐户。从那里,团队中的人可以随时离开商店。通过将会话提升到小组级别,并将单个购物者视为“一个小组”,该团队能够克服这一挑战,让个人随时进入或退出小组。
购物车、付款和收据
这些基本上都和你在 Amazon.com 看到的一样,所以这里没有太多创新可以讨论。他们用了整整 10 秒钟来覆盖这些区域。
当然,他们以经典的亚马逊风格结束了谈话,说“这是 Amazon Go 的第一天”,并暗示即将有重大改进。离开演讲时,我既对自己与这些成就的差距感到谦卑,又对人工智能的黄金时代的到来感到无比兴奋。
如果你读到最后,你可能也会对我关于强化学习进入主流的其他想法感兴趣。
对话式人工智能分析将如何改变商业?

第一章对话式人工智能
对话式人工智能是一种语音助手,可以进行类似人类的对话,捕捉上下文,并提供智能响应。例子包括苹果 Siri,亚马逊 Alexa,谷歌虚拟助手。还有其他侧重于企业的对话平台。根据 Gartner 的说法,典型的应用程序存在于人力资源、IT 服务台和自助服务中,但客户服务是聊天机器人已经产生最大影响的领域,特别是改变了客户服务的方式。
对话式人工智能平台的 Gartner 典型应用中尚未包括的一个领域是对话式分析。
第 2 章什么是对话分析
为了理解对话分析,我们首先需要讨论数据。组织拥有大量结构化和非结构化数据。通过从不同来源接收新的和新的更新,数据量每秒都在增长。
借助对话分析和人工智能技术,您可以获得更好地浏览所有这些数据的机会,从多个来源中提取正确的数据集,并通过语音或类型查询使其可用。
用例—财务报告

第 3 章机遇
对话分析将改变业务的原因之一是缺乏数据访问和个性化。如今,缺乏数据本身并不是一个问题。恰恰相反。如今,这些公司拥有大量数据,他们花费了大量精力来准备报告、图表和其他数据可视化工具。
数据如何为企业、经理和决策者带来最大价值?数据不应该成为组织的死资产。数据应该是相关的、透明的、最新的、个性化的和可访问的。
我们相信对话式分析有助于数据的可访问性和个性化。
用例—销售报告

第 4 章要改进什么?
对话分析可以帮助员工与数据对话。
如今,员工可以使用图形用户界面(GUI)来访问报告、图表和其他数据可视化图形,以访问数据并做出自信的决策。当我们谈论高层管理人员时,在许多情况下,他们没有时间使用 GUI 来获取报告,其他人正在为他们准备报告。
当你不在办公室的时候,有时不可能得到分析。在这种情况下,你可以使用电子邮件,并要求有人给的信息。当然,有一些移动解决方案可以为您提供移动的机会,让您可以随时随地访问数据。
我们还需要考虑到整个组织中的人员在不同的部门工作,他们有自己的职责,有时现有的分析不符合他们的议程或与期望的结果一致。
所有这些方面都在员工和数据之间产生一些障碍,有时在正确的时间获得正确的数据非常耗时,会导致不准确的结论。
第 5 章对话分析的好处
有了 Siri,你可以对着手机说话,有了 Alexa,你可以用语音了解天气或进行新的购买。
当前的人工智能技术可以理解我们,并理解查询的上下文。如果我们可以训练机器理解查询并可视化数据会怎么样。
想象一下,这个人站在大屏幕后面与机器对话,机器根据这个人的输入将数据可视化。
这样有什么好处?
时间 —有了对话式分析,你不需要考虑如何获取数据或者从哪里获取数据。你只需要想想你想要什么,然后说出来或者输入文字。
准确性 —在准备数据和可视化数据的过程中没有人接触,机器被编程为选择所需的数据,汇总并为您准备数据。我们可以避免报告中的人为错误。
移动性 —对话式人工智能界面在你的设备中,这不是一个独立的应用程序,这是一个简单的聊天,通过这个聊天,你可以获得分析或预订商务旅行或创建销售订单。集所有功能于一身。
用例—营销报告

利用人工智能技术,你可以与数据对话。
问候,
Andrii Rudchuk,首席执行官@ Hala.ai
政府如何使用数据科学
我们能知道政府是如何使用我们的数据的吗?

Photo by Seth Doyle on Unsplash
概述和背景
除非你在法律或政府部门工作,否则你可能不会意识到,美国政府做出的大多数关于公民的决定都是相当受控和透明的。这是因为一些不同的法律,但特别是一个要求政府告诉每个人他们要做什么,他们要如何做,为什么他们要这样做,如果他们不遵循自己的指导方针,你可以如何起诉他们。
哦,政府也会提前告诉你这些,并征求你的意见,这是法律要求他们考虑(并做出回应)的。这都是因为《行政程序法》(APA)。
《行政程序法》于 1946 年通过,是对新政下政府扩张的直接回应。在此期间,罗斯福总统扩大了联邦政府的规模和范围,创建了全新的机构来管理新的社会项目。一些人担心这会造成政府的中央执行部门过于强大——担心这会导致过多的中央计划或独裁。
这就是导致《行政程序法》立法产生的原因。根据《行政程序法》,联邦机构必须在《联邦公报》上公布提议的法规和规章以征求公众的意见,这些法规和规章详细说明了他们将要做什么以及如何去做。例如,如果国税局要审计税收,他们必须公布一项拟议的规则,规定他们如何确定要审计的纳税申报单,他们的审计师在进行审计时必须遵循的步骤,以及他们将如何确定审计的结果。
这些规则公开征求公众意见,机构必须对收到的每条意见作出回应,然后才能最终确定提议的规则。他们不必总是根据评论修改规则,但如果他们不这样做,他们必须在回应每个评论时解释原因。这实际上是一个很好的例子,说明了公民如何与政府互动并影响政府的结果。
更好的是,自 1994 年以来,联邦公报上发布的每一份文件都被数字化了,可以通过 REST API 获得。
由于我做了大量关于政府使用数据科学的研究,我想利用这一点来了解政府如何以需要制定规则的方式使用数据科学。
使用 python 和 Requests 包,我创建了一个联邦注册文档数据集,其中包含以下术语之一:人工智能、大数据、商业智能、数据分析、数据挖掘、数据科学和机器学习。
对于包含一个或多个上述搜索词的文档,我创建了一个具有特定文档字段和元数据的数据框,我的一些主要列是:
- 文件识别号
- 文档标题
- 机构名称
- 出版日期
- 文档类型(即通知、规则)和子类型
- 主题标签
- 摘要
描述统计学
该数据集有 638 个独特的联邦注册文档,包含一个或多个我的数据科学搜索术语。这些文件由 48 个不同的联邦机构发布,时间跨度从 1994 年 2 月到 2019 年 11 月(我在 11 月下旬提取了数据)。在同一时期,《联邦公报》上发表了 819,160 份文件。因此,我的第一个结论是,根据联邦登记册显示,联邦政府对数据科学的使用非常少,只有 0.00078%!

Count of Fed. Reg. Document Containing Search Terms
正如你在下面看到的,大部分的搜索词是最近才出现的,而其他的则被代理商使用了很长时间。例如,直到 2012 年,大数据在政府中似乎还不存在。

Documents containing search terms based on publication dates.
看看哪些联邦机构最常使用数据科学,肯定有一些并不令人惊讶。例如,国家科学基金会定期举行会议,并为人工智能和人工智能的研究提供资助。此外,美国宇航局似乎是合理的,因为他们使用 ML 的天文学以及应用技术。有趣的是,与其他文件相比,HHS 文件的数量更多。

如果我们把文件数量作为机关文件总量的一个比例,我们可以看到 HHS 还出版了更多的联邦公报文件。有趣的是,现在消费者金融保护局(作为多德-弗兰克法案的一部分,为应对 2007 年金融危机而创建)似乎更多地使用了数据科学。

HHS 的更多细节
尽管如此,我还是想更深入地了解 HHS,因为他们有 200 多个引用数据科学术语的文档,以了解他们正在制定哪些应用程序。

我想做的事情之一是了解 HHS 用这些术语发布了什么样的文档,所以使用 NLTK 和 WordCloud 包,我为文档标题和摘要创建了 word cloud。

HSS Document Abstract Word Cloud

HHS Document Title Word Cloud
最突出的是——特别是在文件的标题中——诸如“非公开”、“会议”和“通知”等术语占了优势。根据上下文,这些可能有几种不同的含义。例如,他们可能会通知公众公众意见征询期即将结束,或者他们可能会发布闭门会议(不对公众开放的会议)的通知和会议笔记。不幸的是,仅仅从云这个词来区分有点困难。
为了在不阅读每份文件(每份文件可能有数百页)的情况下得到确切的信息,我根据摘要中的搜索词过滤了文件标题。这里的理论是,该机构在其简短的摘要中捕获最相关的信息,因此摘要中出现的数据科学术语可能表明该文档主要关注该领域。
我很快意识到,HHS 在利用《联邦公报》宣布会议、培训网络研讨会、拨款和奖励提案讨论以及奖项和竞赛获奖者方面做得非常好。如果您了解数据科学在医疗领域的用途,这并不奇怪,其中许多都与数据科学搜索词直接相关。
我在我的 HHS 数据集中发现的数据科学的唯一应用是通过分析州医疗补助数据,使用数据挖掘来打击医疗补助中的欺诈行为。

Title and Abstract of HHS Applied Use Document
局限性、结论和后续步骤
我的研究有些受限,因为我无法从每个文档中提取全文。这是基于文件大小的问题,以及联邦注册 API 只允许你拉 URL 到唯一的文档或 PDF 链接,而不是文本。如果将来我有更多的时间,我会致力于解决这个问题,并重新审视我的分析。
虽然我对在联邦公报中很少使用应用数据科学技术并不感到惊讶,但我从这项研究中得到了一些重要的收获:
首先,《行政程序法》和《联邦公报》是公众了解政府在日常应用中使用数据科学的有用途径。此外,这允许公众就人工智能和人工智能的使用与直接影响美国公民的角色进行互动并向联邦政府提供反馈。
第二,在联邦公报上几乎没有应用 ML 和 AI 的证据。对此有两种可能的解释。首先是联邦政府不太使用 ML 或 AI。另一种选择是,它们的使用方式不需要在《联邦公报》上发表。
《行政程序法》只要求公布某些东西,供公众检查和评论。事实上,大多数军事和外交政策行动都免于公开评论,而被归类为“来源和方法”风险的其他领域允许机构排除有关他们如何完成某些任务的基本细节。例如,如果国税局想要查看社交媒体信息以进行审计,他们可能会掩盖许多细节,假装如果他们透露了来源和方法,就会妨碍他们的工作。
《行政程序法》的这些局限性早已为人所知。事实上,美国律师协会已经公布了对《行政程序法》的修改建议,以使联邦行为更加透明,并促使《行政程序法》更加符合国会的意图。
我认为,这还应包括对政府使用人工智能和人工智能的更好理解和问责。有趣的是,我们知道在联邦政府中人工智能和人工智能的使用越来越多,但这些实例在联邦登记册中明显缺失——这意味着如果没有另一种机制,公众对我们的政府将如何使用我们的数据几乎没有发言权。
正如我们在世界其他地方看到的那样,美国将不得不尽快解决这个问题,希望在我们遇到太多负面影响政府使用这些技术以更高效力和效率实施公共项目的能力的事件之前。
分形数学如何帮助预测股票市场的变化
使用分形识别市场异常

Image by Arek Socha from Pixabay.
在金融市场,投资者最常用的两种交易策略是动量和均值回复策略。如果一只股票表现出动量(或趋势行为,如下图所示),如果它的价格在前期已经上涨(下跌),那么它在本期的价格更有可能上涨(下跌)。

Section of the time series of the S&P 500 Index or SPY. This is an example of trending behavior.
当一只股票在时间 t 的收益在某种程度上依赖于前一时间 t - 1、的收益时,这些收益被称为自相关。在动量机制中,回报是正相关的。
相比之下,均值回归股票的价格围绕其历史均值随机波动,并显示出向历史均值回归的趋势。当存在均值回归时,如果价格在本期增加(减少),则在下一期减少(增加)的可能性更大。

Section of the time series of log returns of the Apple stock (adjusted closing price). This is an example of mean-reverting behavior.
请注意,由于这两种状态发生在不同的时间范围内(趋势行为通常发生在更大的时间范围内),它们可以,而且经常共存。
在这两种机制中,当前价格包含了关于未来价格的有用信息。事实上,交易策略只能在资产价格趋向或均值回复的情况下产生利润 ,否则,价格将遵循所谓的随机游走(见下面的动画)。

Example of random walk in 2D (source).
均值回复时间序列
股票价格很少表现出均值回复行为。在绝大多数情况下,它们遵循随机游走(然而,它们对应的回报是均值回复的,在零附近随机波动)。然而,均值回复价格序列可以通过组合不同的股票来合成,以建立一个协整的投资组合(更多细节见该参考文献),该投资组合显示了平稳性的属性(下文对此有更多介绍)。虽然可以使用各种众所周知的标准统计测试来识别平稳性,但在本文中,我将重点关注一种基于所谓的赫斯特指数的强大分析类型,该指数与价格时间序列的分形指数相关。赫斯特指数提供了一种方法来衡量金融时间序列偏离随机游走的程度。这是一个非常简单的工具,可以帮助投资者决定采用哪种策略。
平稳性
在本文中,出于实用目的,我将非正式地互换使用均值回复和平稳这两个术语。现在,假设给定股票的价格,我用 S ( t )来表示,表现出均值回复行为。这种行为可以更正式地描述为下面的随机微分方程 (SDE)

SDE describing a mean-reverting process.
这里,符号

分别是时间 t 的股价,时间 t 的一个维纳过程(或布朗运动),均值回复率 θ ,过程的均衡或均值 μ 及其波动率 σ 。根据这个 SDE,在 t+1 时的价格变化与在 t 时的价格与均值之间的差异成正比。正如我们所看到的,如果价格小于(大于)平均值,价格变化更可能是正的(负的)。这个 SDE 的一个众所周知的特例是所谓的奥恩斯坦-乌伦贝克过程。

The Ornstein-Uhlenbeck process was named after the Dutch physicist Leonard Ornstein and the Dutch-American physicist George Eugene Uhlenbeck.
两个最著名的(非)平稳性测试是迪基-富勒测试 (DF)和扩展迪基-富勒测试 (ADF)。
迪基-富勒试验和扩展的迪基-富勒试验:鸟瞰
ADF 测试是 DF 测试的扩展,所以让我们先了解后者。可以举例如下。考虑由下式给出的简单模型:

其中 S ( t )为随时间变化的股票价格, ρ 为系数,最后一项为误差项。这里的零假设就是 ρ= 1。由于在零假设下 S ( t )和 S ( t- 1)都是非平稳的,因此中心极限定理被违反,人们不得不求助于以下技巧。

The Dickey-Fuller test is named for the statisticians Wayne Fuller and David Dickey. The ADF is an extension of this test for more complex time series models.
定义第一差值和参数 δ 如下

回归模型可以方便地改写为:

Dickey-Fuller 随后测试假设(技术上来说是零假设)

DF 测试背后的逻辑可以启发性地理解如下。如果 S ( t )是稳定的,它倾向于返回到某个恒定的平均值(或者可能是决定性演变的趋势),这意味着较大的值可能跟随较小的值,反之亦然。这使得序列的当前值成为下一个值的强预测值,我们将得到 δ < 0。如果 S ( t )是非平稳的未来变化不依赖于当前值(例如,如果过程是一个随机行走,当前值不影响下一个)。
ADF 测试遵循类似的程序,但它适用于更复杂、更完整的模型,由下式给出:

这里, α 是实常数, β 是时间趋势的系数(漂移项),而 δ s 是差值的系数

其中 p 是过程的滞后阶数,最后一项是误差。这里的测试统计数据是

其中分母是回归拟合的标准误差。Dickey 和 Fuller 也把这个检验统计量的分布制成了表格。与 DF 测试的情况一样,我们期望γ0。关于如何进行测试的细节可以在任何时间序列书中找到。
Python 代码
下面的 Python 片段展示了 ADF 测试在苹果股票价格中的应用。虽然股票价格很少均值回复,股票日志回报通常是。下面的Python代码获取对数差异,绘制结果并应用 ADF 测试。
剧情如下:

Log returns for Apple stocks.
ADF 测试的输出是:
Augmented Dickey-Fuller test statistic: -28.653611206757994
p-value: 0.0
Critical Values:
1%: -3.4379766581448803
5%: -2.8649066016199836
10%: -2.5685626352082207
一般来说,我们更有可能拒绝零假设,根据零假设,序列是非平稳的(它有一个单位根),ADF 检验统计量“越负”。上述测试证实了对数收益序列确实是平稳的假设。结果显示-28.65 附近的统计值在 1%时小于-3.438,这是我们可以拒绝零假设的显著性水平(详见此链接)。
赫斯特指数
有另一种方法来研究过程中均值回归或趋势行为的存在。正如稍后将详细解释的,这可以通过分析系列的扩散速度并将其与随机行走的扩散速率进行比较来完成。这个过程将把我们引向赫斯特指数的概念,正如我们将看到的,它与分形指数密切相关。
虽然赫斯特指数的应用可以在数学的多个领域中找到,但我们在这里只关注其中的两个,即分形和长记忆过程。
分形
一个分形可以被定义为如下:
一种曲线或几何图形,其每一部分都具有与整体相同的统计特征。分形在模拟结构(如侵蚀的海岸线或雪花)时很有用,在这种结构中,相似的图案在逐渐变小的尺度上重复出现,在描述部分随机或混乱的现象时也很有用,如晶体生长、流体湍流和星系形成
分形的一个例子是下图所示的 Sierpinski 三角形。

测量表面粗糙度的“分形维数”与 H、有如下简单关系

我们看到,大的赫斯特指数与小的分形维数相关,即与更平滑的曲线或表面相关。下面是一个例子。从这篇文章的中可以清楚地看到,随着 H 的增加,曲线确实变得更加平滑。

Processes with varying Hurst exponents H. As H increases, the curve gets smoother and the fractal dimension decreases (source).
分形有一个属性叫做自相似性。在工程和应用数学的几个分支中出现的一种类型的自相似性被称为统计自相似性。在显示这种自相似性的数据集中,任何子部分在统计上都与整个数据集相似。统计自相似性最著名的例子可能是在海岸线上发现的。

This is an example of the so-called coastline paradox. According to it, if one measures coastlines using different units one obtains different results (source).
1967 年,分形几何领域的创始人之一伯努瓦·曼德尔布罗在科学杂志上发表了一篇开创性论文题为《英国的海岸有多长?统计自相似性和分数维”,其中他讨论了分形的性质,如自相似性和分数维。
长程相关性
当过程具有长程相关性时,会出现一种重要的偏离随机游动的情况。这些过程显示了高度的持续性:过去的事件与未来的事件有着重要的关联,即使它们相距很远。由 Granger、Joyeux 和 Hosking 构思的一个例子由下面的分数差分时间序列给出:

其中 L 是通常的滞后算子,指数 d 是非整数, ϵ 是误差项。使用简单的二项式展开,该方程可以用伽马函数来表示

比较简单的 AR(1) 过程的自相关函数,我们发现后者的自相关函数比前者的自相关函数具有更慢的衰减速率。例如,对于滞后 τ ~25,

而分数差分过程的自相关函数的相应值是~-0.17。
赫斯特指数的起源
尽管关于赫斯特指数估计方法的最新进展来自于分形和混沌理论的数学,但令人奇怪的是,赫斯特指数首次用于水文学领域,该领域主要关注水的分布、质量及其相对于土地的运动。此外,最近对金融时间序列长期相关性的测试是基于一种叫做重新标度范围的统计(见下文),最初是由英国水文学家哈罗德·赫斯特开发的。赫斯特原始论文的首页如下图。

The original paper by Harold Hurst (source).
赫斯特指数与反常扩散
了解价格序列本质的一个方法是分析它的扩散速度。扩散是一个广泛使用的概念,它描述了某个对象(可能是一个想法、一项资产的价格、一种疾病等)从一个比其他大多数地方更集中的地方向外扩散。

The plot shows how the mean squared displacement varies with the elapsed time τ for three types of diffusion (source).
可以通过研究方差如何依赖于后续测量之间的差异来测量扩散:

在这个表达式中, τ 是两次测量之间的时间间隔, x 是价格 S ( t )的一般函数。该函数通常被选择为对数价格:

众所周知,股票价格回报的方差很大程度上取决于人们选择衡量它的频率。以 1 分钟为间隔的高频测量与日常测量有很大不同。
如果股票价格遵循几何随机漫步(或等价的几何布朗运动或 GBM ),这并不总是如此(特别是对于每日回报),方差将随着滞后 τ 线性变化

回报将是正态分布的。然而,当存在与纯随机游走的小偏差时,正如经常发生的那样,给定滞后 τ 的方差不再与 τ 成比例,而是获得一个异常指数

The anomalous exponent is proportional to the Hurst exponent (source).
参数 H 就是所谓的赫斯特指数。均值回归和趋势股票都有以下特征

满足这个等式的日收益率不具有正态分布。相反,分布在平均值附近有较宽的尾部和较窄较高的峰值。
赫斯特指数可用于区分三种可能的市场机制:
- 如果H0.5,则时间序列是均值回复或平稳的。与几何布朗运动相关的正态扩散相比,对数价格波动性以较慢的速率增加。在这种情况下,系列显示所谓的反持久性(相邻点的高值和低值之间的长期切换)
- 如果 H > 0.5,序列显示趋势行为,其特征是存在持续行为(长期正自相关,即高值可能跟随高值)
- H = 0.5 的情况对应于几何布朗运动
因此,赫斯特指数衡量时间序列的持续性水平,并可用于识别市场状态:如果在某个时间尺度上,赫斯特指数发生变化,这可能表明从均值回归到动量机制的转变,反之亦然。

Relations between market regimes and the Hurst exponent.
因此,赫斯特指数衡量时间序列的持续性水平,并可用于识别市场状态。
每种情况的示例绘制如下:

在下一张图中,我们看到赫斯特指数如何随时间变化,表明政权的变化。

Hurst exponent varying in time for four different financial time series (source).
自相关
股票价格 S ( t )的自相关函数定义如下:

衰减非常慢的自相关过程称为长记忆过程。这样的过程对过去的事件有一些记忆(过去的事件对未来的事件有衰减的影响)。长记忆过程的特点是自相关函数 ρ ( τ )呈幂律衰减

α 与赫斯特指数的关系为

注意,随着 H 接近 1,衰减变得越来越慢,因为指数 α 接近零,这表示“持续行为”。经常发生的是,起初看起来随机的过程,实际上是长记忆过程,具有在开放区间内的赫斯特指数

那些过程通常被称为分数布朗运动 (fBm)或黑噪声,是布朗运动的推广。
使用方差估计赫斯特指数的重要问题
为了获得对 τ 的方差依赖性,我们必须对许多滞后重复相同的计算,并提取结果的对数图的斜率。正如我们现在将看到的, H 的值很大程度上取决于我们对滞后的选择。这一部分是基于这篇博文中的分析。
让我们考虑标准普尔 500 指数 SPY 并估计不同滞后的赫斯特指数。我们首先运行以下代码,其滞后范围为 2 到 20:
我们获得了 H 的以下值:
hurst = 0.43733191005891303
如前所述, H 的这个值表示均值回复机制,尽管相当温和。滞后 300–400 的相同代码给出:
hurst = 0.6107941846903405
这个值表示趋势状态的存在。因此,我们看到滞后的选择强烈地影响赫斯特指数的值。这意味着这个时间序列既不是纯粹的均值回复也不是趋势,而是改变行为或改变制度,这取决于人们是在短期内还是在长期内衡量它。此外,正如这里的所指出的,由于这些结论对于肉眼来说远非显而易见,我们得出结论,基于赫斯特指数的分析可以给出重要的见解。
长程相关性和重标范围
1971 年 Mandelbrot 注意到股票收益长期异常行为的存在。

Benoit Mandelbrot one of the fathers of the field of fractal geometry (source).
为了测试这种长期相关性,Mandelbrot 使用了上面简要提到的重新标度范围或 R/S 测试统计。R/S 统计量是一个序列相对于其均值的偏差的部分和的范围,由标准差重新调整(更多细节见本书)。Mandelbrot 和其他人表明,与其他方法(如自相关分析、方差比和频谱分解)相比,使用 R/S 统计会产生更好的结果,尽管它也有缺点,如对短程相关性的敏感性(有关更多详细信息,请参见本文和这篇出色的博客文章)。
R/S 统计可以如下获得。例如,考虑以下长度为 n 的股票收益时间序列

第一个 k 偏离平均值的部分和由下式给出:

R/S 统计与这些和的最大值和最小值之间的差成比例,其中 k ∈ [ 1 , n :

分母 σ ( n )就是最大似然标准差估计量。重新标度的范围和观察值的数量 n 具有以下关系

其中 H 是赫斯特指数。Mandelbrot 和 Wallis 首先使用这种标度行为来发现长程相关性的存在。由于重新标度的范围和观察次数之间的关系是多项式的,因此可以用简单的双对数图计算出 H 的值,因为

在下图中,赫斯特指数估计在 0.53 左右,这大致相当于随机游走。代码使用了hurst库(Github repo 的链接是这里是)。

Estimation of the Hurst exponent gives H~0.5183. The code uses the Github repo found here.
还有其他方法来获得赫斯特。你可以查看这篇文章了解更多细节。
结论和展望
我们看到,使用赫斯特指数的概念可以得出关于市场机制的非常有用的见解。有了这些信息,人们就可以决定均值回归和动量策略中哪一个更适合采用。
简而言之,赫斯特指数的值表明时间序列是否对过去的事件有记忆。赫斯特值不总是等于 1/2 的事实表明,市场完全不可预测的有效市场假说经常被违反。原则上,正确识别这些异常对于建立有效的交易策略非常有用。
感谢您的阅读,再见!一如既往,我们随时欢迎建设性的批评和反馈!
我的 Github 和个人网站 www.marcotavora.me 有(希望)一些关于数据科学和量化金融的其他有趣的东西。
公共部门如何共享数据为公民创造价值

今天,我们产生和收集的数据比以往任何时候都多。
根据 Domo 的数据从不睡觉报告,我们每天生成 2.5 万亿字节的数据。将近 45 亿人使用互联网。
现在的挑战在于有效地管理所有这些数据。个人和企业都需要帮助,从过多的信息中筛选出有意义的见解。幸运的是,许多公共部门的实体正在加入到帮助中来。
联邦、州和地方组织越来越多地与公众公开共享数据。这些机构完全有能力从各个部门的不同来源收集信息。此外,许多公共实体已经开发了强大的数据科学能力来处理和存储海量数据集。
有了这些信息,我们可以更好地了解我们周围的世界。通过让数据变得可访问,公共部门让个人和私人组织能够在日常生活中做出更明智的决策。
在本文中,我们提供了几个公共组织的例子,它们通过公开共享数据和数据科学能力为人们创造价值。我们还强调了一些有用的平台,帮助用户获得有价值的见解,并讲述他们的研究发现。
公共实体今天共享数据
联邦一级有许多实体定期与公众共享数据。
医疗保健部门的组织在这方面尤其活跃,因为他们可以访问和研究大型健康保险公司的索赔数据。利用索赔数据,数据科学部门可以研究去识别的健康信息,并识别人群中的广泛趋势,否则这些趋势将会被忽视。
通过 CDC 研究公共卫生数据
疾病控制和预防中心 (CDC)拥有发达的数据科学能力,使该组织能够大规模地研究健康结果和疾病流行率。CDC 还按主题发布统计数据,并提供工具帮助公众理解可用数据。
例如,任何人都可以访问疾病预防控制中心网站上发布的糖尿病页面,在由美国糖尿病监测系统提供的数据组成的各种仪表板之间切换。个人可以通过年龄、性别、种族和教育水平来了解糖尿病趋势。在州和县一级也有数据切片。此外,CDC 允许站点访问者下载 CSV 文件形式的数据,以供进一步分析。
美国疾病控制和预防中心还提供了与 T2 互动数据库系统的链接,该系统包含了关于广泛健康话题的最准确和最新的信息。那些对研究人口健康数据感兴趣的人,通过疾病预防控制中心的网站,随手可得的数据数量惊人。
通过 NHTSA 进行车辆背景调查
美国国家公路交通安全管理局 (NHTSA)提供了大量与车辆评级、召回等相关的数据集。任何人都可以在做出购买决定之前,使用该网站的 VIN 查找工具对特定汽车进行背景调查。网站访问者还可以看到任何品牌和型号的汽车座椅、轮胎和相关设备的安全评级。
NHTSA 提供了三个不同数据库的链接(车辆碰撞测试、生物力学和部件测试)。该组织还为那些希望进一步利用可用数据的人提供事件记录器报告、碰撞模拟模型和软件应用程序。
通过联邦调查局评估犯罪率
通过统一犯罪报告计划,FBI 根据从 18000 个志愿执法机构收集的数据发布了四份不同的报告。联邦调查局通过国家基于事件的报告系统(NIBRS)、仇恨犯罪统计计划、执法人员被杀和被袭击(LEOKA)计划和简要报告系统(SRS)收集数据。
公众可以免费获得所有报告。网站访问者可以下载跨越几十年的数据表,以及评估联邦调查局信息收集技术的完整性。虽然统一犯罪报告计划旨在支持执法行政和管理,但任何感兴趣的团体都可以使用该组织的数据。
通过 NCES 评估教育成果
国家教育统计中心(NCES)发布许多教育相关话题的数据和报告。联邦实体提供了无数的数据工具,以便人们可以查找大学、公立学校、私立学校和国际学校的信息。
NCES 的教育数据分析工具允许用户下载各种格式的调查数据集。根据特定的研究课题,可以为某些人群和变量定制数据集。通过 Delta Cost 项目,该组织能够对毕业率、财政援助信息和其他数据点进行纵向研究。
总的来说,有许多不同的方法来使用 NCES 的出版物和数据集来研究教育相关的主题。感兴趣的人可以获得大量免费的分析工具和资源。
支持公共数据分析的资源
除了上述组织之外,还有无数的其他国家、州和地方实体收集公共消费数据。
因此,普通大众有如此多的机会独立分析信息。人们比以往任何时候都更有能力研究数据和探索自己的研究问题,无论是出于个人原因还是职业需要。还有一些网站和平台让个人研究公共数据变得更加容易。
例如,我们的数据世界是一个整合公开信息并按主题组织数据的网站。因此,研究人员可以研究不同领域之间的关系,并就看似不相关的变量如何联系起来形成假设。
Apollo Yard 使用详细的可视化技术制作引人入胜的数据故事。网站访问者可以请求特定主题的数据故事,或者通过相关数据源的链接找到研究思路。
FlowingData 提供基本和高级的数据可视化工具,以便个人可以创建自己的信息图。该平台致力于使用户能够构建可读、可用且美观的图表。FlowingData 成员可以访问许多课程、分步教程以及关于如何创建漂亮的数据视觉效果的专家建议。
利用公共数据
不管您的具体数据相关兴趣或目标是什么,您拥有的信息和工具比以往任何时候都多。
公共实体以报告、可导出表格和可下载数据集的形式提供大量信息。在线平台还在简单的界面中提供数据科学功能,使用户能够更好地理解他们收集的数据。
利用今天存在的大量数据,为了你的个人利益或职业目标,更彻底地探索任何研究课题。
美国训练营如何将他们的测验缩短到 5 分钟左右
减少他们问的问题数量可能会让更多的人申请和注册,这将增加公司的收入

Photo by NESA by Makers on Unsplash
最近,我为丹佛的美国训练营做了一个项目,在过去的 5 年里,这个项目一直在教人们如何编码。作为录取过程的一部分,考生要从 12 个问题中选择 8 个来测试他们的逻辑思维。学校想知道是否以及如何使用一些数据科学分析,及时减少这种测验。
现在,它需要大约 1 个小时来完成,并且大约 50%的报名者从未开始测验。理想情况下,学校可以少问一些问题,同时保留那些能提供候选人是否优秀的信息的问题。潜在的可能性是,更短的测验可以让更多的人参加考试,如果他们通过了,最终加入学校,这也将使公司的收入增加。
More revenue always sounds good
看着这些数据
他们有大约 2700 名学生的数据。对于每一个人,他们都知道他们得到的问题以及他们得到的问题是对还是错,对于其中的大约 700 人,他们知道他们完成每一个问题所花的时间。
65%的人答对了 6 个或更多的问题。这可能意味着可以问的问题会更少,以前通过的人现在也会通过。稍后我们会知道这是不是真的。
要通过测验,你必须答对 6 道或 6 道以上的问题,答对 5 道的人需要接受额外的逻辑思维面试。这也是为什么有的人答对了 5 题,还是没通过。
关注谁?
根据数据的不同,学校可能做出的决定会有所不同。本质上,我们可以关注两类人群:
- 未完成就离开的人
- 从来没有机会参加测验的人
看起来大多数人回答了他们收到的所有 8 个问题,很少有人在开始测验时中途离开。
此外,回答几个问题的人是正确答案比例最低的人,所以他们很可能不会通过考试。
因此,试图让这些人完成没有意义,目标应该是关注另一组人,那些永远不会开始的人。我们会尽量缩短测验,如果太长是人们没有开始的原因,那么在缩短后,更多的人会开始。
Right now, candidates take between 25 minutes and 1h30 to complete the quiz.
缩短测验时间
为了决定去掉哪些问题,我们需要为每个问题获取一些度量。比如…
时间
Note: these names are not the original ones
有些问题比其他问题花的时间要长,比如深度大,10 分钟!。我们可能会想去掉那个
困难
大多数人都在问长路或红爸爸这样的问题。这可能意味着这些是最简单的问题,并没有给我们多少信息来知道一个学生是否会通过考试。
每个问题的重要性
这是我们对每个问题的 3 个衡量标准中最好的一个。它将告诉我们的是,每个问题在多大程度上预测了候选人是否会通过测试。
实际的技术术语是排列重要性。我在一个 fast.ai 课程中第一次了解到它,现在是使用它的好时机。基本上,它的工作原理是:
- 我们首先训练一个 ML 模型来预测结果。我们的结果是一个学生通过与否。这个模型会有一定的准确性。大约是 96%
- 然后我们取出*列,一个接一个,用训练好的模型预测同样的结果。剔除一个列后,模型的精度下降得越多,该列就越重要。
()实际上我们并没有把列拿出来,我们只是一次一列地洗牌。移动一个列与取出它有相似的效果,但是好处是我们不需要重新训练模型。在简单的模型中,如我使用的随机森林,这没有太大的影响,但如果一个模型需要很长时间来训练,这种方法我们只需要训练它一次,而不是 N 次。*
I added two random columns to have a baseline for importance.
正如我们之前所猜测的,红爸爸和长路确实是最不重要的。此外,要回答的最长的问题,巨大的深度,被证明是不那么重要的,所以把它拿出来不会像我们把茶或面包拿出来一样。
概括
现在,我们可以可视化所有问题的指标


The first plot is also 👀interactive 🎭
提出问题
这是这个项目的最后一部分🎉我拿出了 1,2,3…多达 11 个问题。我总是从巨大的深度开始,因为它是最长的,然后从最不重要的问题开始到最重要的问题。这为以下问题提供了答案……
- 可以带走多少个问题
- 如果问题少一些,测验要花多长时间
- 候选人应该通过多少道题,这样通过的人数最多,没有通过的人数最多,现在也不会通过
这是我发现的一些情况。
他们只能问一个问题,测验只需要 5 分钟
如果我们从问题库中删除 10 个最不重要的问题,并且只问了 2 个最重要的问题中的 1 个,则结果如下:

尽管如此,92%以前通过的人如果现在就通过,76%以前没有通过的人现在不会通过。
另一个好的折中办法是:只问 3 个问题,去掉 8 个
在这种情况下,我们看到 3 个问题中有 2 个答对需要最佳阈值。这只会给我们带来大约 15%的假阳性(应该被录取但不应该被录取的人)和大约 5%的假阴性(不应该被录取但应该被录取的人)。在这种情况下,测验大约需要 17 分钟。

我不想把这篇文章写得太长,但是还有很多可能性。如果你很好奇,想要检查它们(并看到一些不工作的东西),你可以查看完整的报告这里。
您还可以看到,计算出的重要性似乎是有效的,因为当我们删除较少的问题,例如,我们问 6 个中的 3 个而不是 4 个中的 3 个时,一个人应该正确通过多少个问题的阈值变得不太清楚。
结论
我们发现了哪些是最重要的问题,哪些没有告诉我们太多。我们还发现,测验可以更短,问重要的问题,我们仍然有足够的信息来判断一个学生是否优秀。
现在,应该做出什么决定呢?只问一个问题?问 8 个中的 5 个?
这更多地取决于业务的成本,并且更多地是利益相关者现在必须做出的决定,考虑到他们所拥有的数据。
如果采访更多的人很便宜,我的建议是少问一些问题,不要要求答对很多问题。这样,所有以前通过的学生现在都通过了,但是会有更多的学生不应该通过,在下一阶段必须进行面试才能找到答案。
理想情况下,能够宣布“现在考试只需要 5/10/15 分钟”会让更多的人参加考试,甚至可能提高门槛,这样面试团队的工作量不会增加,但会有更多的人成为学生。
这种情况是否会发生已经超出了本文的范围,需要通过实验来检验。希望如此,我可以在这上面加几行。
还有一件事!
我正在积极寻找合同工作来解决像这样有趣的数据问题。
因此,如果您的企业有具体的问题,并且希望以一种更加数据驱动的方式来解决它,我很乐意与您聊天,看看我能如何帮助您。
如何不花一毛钱考 A/B

无需购买测试平台即可获得具有统计意义的结果
A/B 测试是产品开发过程中不可或缺的一部分,从成长型营销人员到设计师都在使用。然而,并不是每个人都有合适的 A/B 测试平台。也许你买不起每年高达 100,000 美元的系统,或者你是一个纯粹主义者,喜欢自己提取和处理硬数字。无论如何,本指南将揭开这个过程的神秘面纱,并一步一步地指导你如何获得显著的效果。
什么是 A/B 测试?🤷
A/B 测试或统计假设测试基本上是一种比较两个版本的东西以找出哪个更好的实验。有趣的事实:早在 20 世纪初,吉尼斯的统计学家威廉·戈塞特就使用 A/B 测试来测试哪种类型的大麦在啤酒生产中产量最高。

A/B testing for better beer! That’s science I can get behind. Photo by Wil Stewart on Unsplash
它对我有什么帮助?
A/B 测试是任何人都可以根据自己的目标使用的工具。
- 产品经理可以测试定价模式的变化,以提高收入或优化漏斗的一部分(如注册和入职),从而提高转化率。
- 营销人员可以测试图像、CTA 或营销活动或广告中的几乎任何元素,以提高打开率和点击率。
- 产品设计师可以测试设计决策(例如,结帐按钮应该是红色还是蓝色),或者在 100%推出之前使用结果来确定新功能的可用性。
所以你想知道,没有一个合适的测试平台,我如何以正确的方式完成它?首先,在你进行 A/B 测试之前,问自己这些问题。
可行性——我能做到吗?
- 你有足够的用户和数据来玩吗?太小的样本量要么需要你运行测试很长时间,要么给你无关紧要的结果。
- A/B 测试也需要设计、设置和运行,所以问问你自己,你有时间和资源吗(例如,开发人员来实施)?有关这方面的更多信息,请参见步骤 4。
- 您有收集数据并将其传输到正确的查询或分析平台的系统吗?
你有提取、清理和分析数据的技能吗?
- 假设您没有专用的测试工具,您将需要使用查询语言(例如 SQL)提取原始数据,以可读格式(例如 Excel)处理和显示数据
合适性——我应该这么做吗?
这是检验假设或回答问题的最好(最便宜、最快)的方法吗?例如,如果你想知道为什么人们不填写表格,也许在半天的练习中做一些可用性测试比 3 周的 A/B 测试更好。当铲子起作用时,不要使用推土机。
6 个简单步骤的 A/B 测试
下面是你下次考虑进行测试时需要经历的 6 个步骤。该示例包括在 B2C 启动时 A/B 测试注册网页。数字是编出来的。

1.定义一个目标🎯
理解你公司更大的商业目标,并确保你的 A/B 测试与这些目标一致。
举例: 你是 X 公司的产品经理,这家公司处于初创阶段。高管团队已经制定了一个全公司的目标来促进用户增长。具体来说,该公司正在寻求增加日活跃用户数(DAUs),即过去 30 天内该网站每天注册用户的平均数量。您认为可以通过提高保留率(再次使用产品的用户百分比)或增加新用户注册来实现这一目标。
在调查过程中,您从漏斗分析中注意到,60%的用户在完成注册之前就退出了。所以你认为有一个很好的机会来提高注册页面的注册率。反过来,这应该有助于增加 DAU。
2.确定一个指标📏
接下来,您需要确定一个度量标准来衡量新版本是否比原始版本更成功。这通常是某种转化率,但也可能是中间步骤,如点击率。
例如: 在这种情况下,您选择注册率作为您的指标,定义为注册的新用户数除以网站的新访客总数。
3.发展一种假设🤔
接下来,您将需要开发一个假设来解释正在改变的内容(即,您想要测试的内容)、结果和基本原理。
例如: 假设当前注册页面有一个图像和一个注册模态。您可以在这里测试一些东西(例如,表单字段、副本、位置、文本大小),但英雄图像是视觉上最突出的,因此您想知道不同的图像是否会导致更好的注册率。
一般的假设是“如果注册页面的英雄形象被改变,那么更多的首次用户会注册这个产品,因为这个形象更好地传达了产品的价值。”
在正式的假设测试中,您需要定义两个假设,这将帮助您确定您在版本 A(原始版本)和版本 B(您想要测试的新版本)之间看到的结果是自然变化的结果还是您更改的结果。
- 零假设假设 A 和 B 的结果没有不同,观察到的差异是随机的。我们希望拒绝这一点。
- 备选假设是假设 B 不同于 A,你想通过拒绝 null 来推断 true。
决定它是单尾测试还是双尾测试。单尾检验允许您检测一个方向的变化,而双尾检验允许您检测两个方向的变化(正负)。因此,单尾测试将帮助您确定 B 是否优于 A,而双尾测试更适合测试两个完整的新设计(当不存在默认值时),并将告诉您 B 的表现是优于还是劣于 A。

If only 1-tailed tests were this cute. Photo by Jason Leung on Unsplash
举例: 我们的无效和替代假设将:
零假设: 新注册页面(B)注册率≤原注册页面(A 版)注册率
替代假设: 新注册页面(B)的注册率是>比原注册页面(A)的注册率
我们将使用一个 单尾测试 ,因为我们更感兴趣的是发现 B 的进步,而不是知道 B 何时表现更差。
4.设置实验👩🔬
为了使测试有效,我们需要
- 创建新版本(B) 以反映您想要测试的变更。
保护: 你也可以在 多元测试(MVT) 中一次测试多个变量,但这只包括分割测试
- 定义对照组和实验组。你想测试哪些用户?所有平台的所有用户?仅美国现有的网络用户?根据用户类型、平台、地理位置等来定义你的测试人群。然后,确定控制组(接受 A 的组)和实验组(接受 B 的组)的比例。这通常是对半分。
- 确保随机化哪些用户获得 A 和 b。这意味着每个用户获得 A 或 b 的机会均等。
- 定义显著性水平( α) 。这是你接受假阳性的风险水平(当真时拒绝零假设),通常设置为α = 0.05 或 5%。这意味着有 5%的时间你会发现 A 和 B 之间的差异,这实际上是由于自然变化。显著性水平越低,检测到随机性差异的风险就越低。
- 定义最小样本量。计算器存在于这里和这里并将计算每个版本所需的样本量。由于不同的参数和假设,你会得到稍微不同的数字。
拥有足够大的样本量对于确保您的结果具有统计学意义非常重要。
- 定义时间线。取每个版本所需的总样本量,除以你的日流量,这将给出你运行测试的天数。一般来说,一个好的经验法则是大约 1 到 2 周,但也可能更多或更少,这取决于许多因素,包括流量大小或商业周期。

举例:
创建版本 B 我们将用不同的英雄形象设计现有的注册页面。
定义对照组和实验组。 由于我们对在网络平台上注册的新用户感兴趣,我们将根据用户类型和平台进行细分。只有访问浏览器注册页面的新用户才会接触到这个实验。我们还确保随机抽样,这意味着每个用户将有平等的机会获得 A 或 B,并被随机分配。
控制组 — 50%使用网络浏览器点击注册页面的首次用户将看到原始版本 a。
实验组——50%使用网络浏览器点击注册页面的首次用户将看到新版本 b。
定义显著性水平。 我们将采用最佳实践,即显著性水平α = 0.05 或 5%。
定义时间线。 比方说,我们的注册网页平均每天有 10,000 的首次用户流量。我们计算出每个变异的最小样本量约为 100,000。这意味着每天只有 5000 名用户会收到每个变体。所以我们需要运行这个实验 100,000/5,000 = 20 天。
5.运行实验💃
- 传达实验的预期开始和结束日期,为您的团队或其他利益相关者设定期望。
- 执行质量控制— 这一点经常被忽视,但却非常重要。
无论你处于什么样的角色,学会如何自我问答。
- 与工程师确认实验设置了正确的参数。
- 如果您有一个测试查询来检查数据,请在临时环境上进行测试查询。或者,你也可以在实验开始的第一天检查数据。
- 数据清理应包括检查:
(1)完整性—空值、空白和丢失的数据可能是无害的,或者是错误实现的标志。
(2)准确性—确保正确的用户操作触发正确的事件,所有预期的字段和字段值都进入。 - 当它预期上线时,检查它是否真的上线了。
- 👀最后,不要偷看结果!过早查看结果可能会使统计显著性无效。为什么?在这里阅读。👀

Waiting for test results is like watching water boil. Photo by John-Mark Smith on Unsplash
6.最终分析结果!有趣的部分🤓
- 收集和分析数据 您需要提取数据,并计算您之前为版本 A、B 和差异定义的成功指标。如果总体上没有差异,您可能还希望根据平台、来源类型、地理位置等进行细分(如果适用)。您可能会发现版本 B 在某些部分表现得更好或更差。
- 检查统计显著性 这种方法背后的统计理论在这里有更好的解释但是基本思想是弄清楚 A 和 B 之间的结果差异是由于你改变了什么还是由于随机性/自然方差。这是通过将测试统计(和结果 p 值)与您的显著性水平进行比较来确定的。
Protip: 你也可以从置信水平的角度考虑统计显著性,简单来说就是 1-α。最佳实践通常是将置信度设置为 1-.05 = .95 或 95%。这意味着如果你重复测试 100 次,你会得到其中 95 次的结果。显著性水平和置信度水平均可用于确定统计显著性,但本例使用显著性水平。
确定重要性的基本步骤是:
- 计算检验统计量。检验统计值是我们用来比较 A 和 b 的结果的值。它说明了我们在结果之间看到的差异有多大,以及我们的数据中有多少可变性。根据你对实际人口的了解,通常会使用 Z 统计量或 t 统计量作为检验统计量。在此阅读更多关于何时使用的信息,尽管实际上,如果样本量很大,两者之间几乎没有区别。
- 使用检验统计量计算 p 值。p 值是 A 和 B 版本之间的结果差异纯粹是由于偶然因素造成的概率。因此,像 1%这样非常低的 p 值意味着 A 和 B 的差异极不可能是偶然造成的。这是从测试统计中计算出来的。你可能还记得在你的大学统计课上从表格中查找 p 值,但幸运的是今天有在线计算器可以帮你做到这一点。
- 将 p 值与显著性水平进行比较。
- 若 p 值< significance level, we can reject the null hypothesis and have evidence for the alternative.
- If p-value ≥ significance level, we cannot reject the null hypothesis.

One-tailed hypothesis test showing when the p-value is less than the significance level.
举例:
收集&分析数据 因为我们希望能够比较 A 和 B 的注册率,所以我们希望收集关于 ftu 数量以及在 20 天内成功注册的 ftu 数量的数据。
请参见下面的示例数据。
https://gist . github . com/lisamxu/db 6041895 a0b 96481 F4 F5 b 107 B1 c 2101

Table comparing registration rate of new users that received Version A vs B.
太好了!看起来 B 比 a 表现得更好。但是在我们自我表扬之前,我们需要检查其重要性。
检查统计显著性 我们将使用 t 统计量,因为我们不知道人口统计量。如果您对总体和总体统计(例如,平均值和方差)一无所知,您最好使用 t 统计。如果你知道,你可以使用 Z 统计量。
1。计算 t-statistic 我用了一个在线计算器 这里的 也显示了公式和原始计算。
t 统计量= 2.3665
②。计算 p 值 您可以使用一个 p 值 计算器 或Excelt-test 公式来返回 p 值。记住,这是一个显著性水平为 0.05 的单尾双样本测试。
P 值= .0115
3。将 p 值与显著性水平进行比较。
P 值为. 0115 < .05
结果是显著的!
这告诉我们只有大约 1.15%的可能性,登记率的不同结果是偶然的结果。因此,我们可以推断,另一种选择(即 B 确实比 A 有更高的注册率)是正确的。
得出结论
所以你已经看了结果并检查了重要性。A/B 测试可以下列方式结束:
对于大多数测试来说,新版本的表现与原始版本相同或更差。
- 控制一个胜败没有区别。除了会导致无效测试(即结果不准确或不重要的测试)的原因,新版本的较差性能可能是因为:
- 价值主张的信息传递/品牌推广不佳
- 没有吸引力的价值主张
- 用户体验差
在这种情况下,您可以挖掘数据或进行用户研究,以了解为什么新版本没有像预期的那样表现更好。这反过来将有助于你的下一次测试。

2。变体 B 赢了。A/B 测试支持您的假设,即版本 B 的性能优于版本 A。太好了!分享结果后,可以 100%铺开实验。之后关注成功和背线指标是有好处的。
在我们的例子中,我们的结论是版本 B 确实比版本 A 有更高的注册率,所以我们将向所有用户推送 live。然后,我们将在未来几周内监测登记率和 DAU 增长情况。
包装好一切
不管你的测试是否成功,把每一次实验都当作一次学习的机会。用你所学到的知识来帮助发展你的下一个假设。例如,您可以基于之前的测试,或者关注另一个要优化的领域。您可以测试和实现的可能性是无限的。
快乐实验!👩🔬
感谢阅读!想要连接吗?伸出 @lisamxu 。欢迎反馈和评论!特别感谢 托马斯·马蒂诺乔安·郭亚当·加德拉莎拉**
资源
如何使用 Tweepy 访问 Twitter 的 API
使用易于使用的 Python 库获得大型 Twitter 数据集的分步指南(包含代码和技巧)

Photo by Kon Karampelas on Unsplash
Tweet 数据集对于有抱负的(和实践中的)数据科学家来说是一个非常理想的分析和执行模型的语料库。推文本质上是简短的,包含不同的相关主题,这使得它成为一个优秀的情感分析数据集。这也是一个分析用户参与度的很好的数据集,因为推特时间戳是可用的。
虽然有许多现有的 Twitter 数据集,但它们会为你预先定义。我相信首先要定义你感兴趣的问题,然后找出获取数据的方法。这就是访问 Twitter API 的好处——你可以获得只有 API 才能提供的类型、容量和“新颖性”。

如果有任何证据的话,我能够获得 7 万个用户账户和他们的 1000 万个帖子,这几乎需要一整天的时间。这比用自制的酸面团来醒发你的面包面团要稍微长一点,但是真的不会太长。我更强烈地推荐它,而不是试图从零开始做面包(至少一次),相信我,这说明了很多。
什么是 Tweepy?

Straight from the Tweepy website: https://www.tweepy.org/
Twitter API 公开了数十个 HTTP 端点,可用于检索、创建和删除推文、转发和类似内容。它提供了对丰富的实时 tweet 数据的直接访问,但需要处理大量底层细节(并且调试起来很不有趣)。
Tweepy 是一个开源包,它允许你绕过许多低级的细节。 Twitter 的开发者网站有很棒的文档,我推荐你去浏览一下,获取示例回复,看看你能访问的数据类型。 Tweepy 的文档将进一步为 Tweepy 模块提供代码片段和一些基本文档。
获取 Twitter API 认证
Twitter API 使用 OAuth,这是一个开放的授权协议来认证请求。您需要创建和配置您的身份验证凭证来访问 Twitter API。正如我所承诺的,这是一个循序渐进的指南,所以跟着做吧!
第 0 步:开一个推特账号。如果你已经有一个 Twitter 账户,跳过这一步
第一步:申请开发者账号
去他们的开发者网站,进入申请访问,选择“申请开发者账户”。系统会提示您登录您的 Twitter 帐户。
然后,您将被导航到如下页面:

选择您的选择路径,在下一页填写详细信息,并填写一些个人信息。当你打算使用时,有几个字段有最小字符限制(一次他们有一个最小值😏).

这是我填的。诚实,但是不要太担心细节,尤其不要担心简洁。以我的经验来看,他们的审批是即时的。
还会有进一步的简单问题和步骤(耐心点!).一旦你完成了这些步骤并接受开发者协议,你现在就有了一个开发者帐户!
第二步:创建一个应用程序
您可能需要等待开发人员帐户获得批准,但一旦获得批准,您就可以开始创建自己的应用程序了。
转到您的个人资料选项卡并选择应用程序。创建一个应用程序并填写详细信息。那应该再花一分钟。


Fill in details in the app section.
创建应用程序后,进入下一步。
第三步:获取您的认证信息
转到您的应用程序页面,在那里您将看到您创建的应用程序。点击详细信息。

一旦你在那里,点击钥匙和令牌获得相关的钥匙。您可能需要生成您的访问令牌和访问令牌密码。
您还可以重新生成密钥,以防您需要写一篇循序渐进的博客文章并共享您的旧密钥(我就是这样做的)。

一旦你做到了这一点,就进入下一步吧!
验证凭据
用您自己的凭据替换下面代码中的 CONSUMER_KEY、CONSUMER_SECRET、ACCESS_TOKEN、ACCESS_TOKEN_SECRET。
运行下面的代码来验证您的身份验证。希望有用!
import tweepy
# Authenticate to Twitter
auth = tweepy.OAuthHandler("CONSUMER_KEY", "CONSUMER_SECRET")
auth.set_access_token("ACCESS_TOKEN","ACCESS_TOKEN_SECRET")api = tweepy.API(auth)# test authentication
try:
api.verify_credentials()
print("Authentication OK")
except:
print("Error during authentication")
强调几种方法
Tweepy 有一个方法列表,可以很容易地帮助你访问 Twitter 的端点。用户时间表、推文、搜索、趋势、用户等等都有一个方法。请务必阅读文档以获得完整列表,但是让我来谈谈我使用的这两种方法。
此方法允许您获取特定用户的最近关注(使用 screen_name 作为参数)。结果以 5,000 个用户 id 为一组,您可以使用光标浏览“页面”。
api.followers_ids(screen_name=screen_name)
出于我的目的,我将此作为一种策略来获取一个 id 列表,作为一个参数提供给 user_timeline 方法
在任何一个 24 小时内,这种方法的总速率限制为 100,000 次呼叫。这将转化为 100,000 个用户及其时间轴帖子(最多 200 个最新帖子)。
timeline = api.user_timeline(user_id=user_id, count=200)
下面是它将返回的 JSON 的一个片段。请仔细查看对您的目的有用的属性。

对我来说,我收集的属性是 ['created_at ',' text ',' source ',' in_reply_to_screen_name ',' retweet_count ',
'favorited ',' retweet ',' is_quote_status ',' retweeted _ status ',' hashtags ',' symbols ',' user_mentions']
我没有使用这种方法,但我相信这对于大多数寻找 Twitter 数据的人来说是有用的,可以获得关于特定主题的对话。该方法为所有公共 tweet 返回与指定查询匹配的相关 tweet 集合。
下面的例子返回了最近 5 条关于热门人物斯诺登的推文。
api.search(q="hot pockets snowden", lang="en", rpp=5)
您需要解析的结果是:

一些我需要的代码
这个函数将帮助你获得给定 Twitter 用户名的关注者 id 列表。每个页面有 5000 个 id,所以如果特定用户有超过 5000 个追随者,光标只是帮助你“翻转”页面。我的计划是为每个 id 调用用户时间表。
# define screen_name
def get_ids(screen_name):
'''
:argument: screen_name of user
:returns: a list_id of the given user's followers
'''
# get first list
first_list = api.followers_ids(screen_name=screen_name)
id_list = first_list['ids']
cursor = first_list['next_cursor'] while cursor != 0 :
user_ids = api.followers_ids(screen_name=screen_name, cursor=cursor)
id_list.extend(user_ids[0]['ids'])
cursor = user_ids[0]['next_cursor'] return id_list
下面的函数有点难。但是高层次上,它根据我指定的属性获取 tweets。我必须执行一些简单的操作(替换函数)来帮助 API 调用的下一行(\n)格式化。这完全是我的操作,因为我的 final 是一个 csv 文件,我将它移动到 postgresql 数据库中。
如果您是在 MongoDB 中捕获的,这可能是不需要的。
def get_tweets(user_id, timeline) :
'''
:param user_id: the list_id as recognized by twitter
:param timeline: the dictionary that is pulled from user_timeline twitter API
:return: all the posts in dictionary format of a specified list_id
'''
# attribute lists
post_attrs = ['created_at', 'text', 'source', 'in_reply_to_screen_name', 'retweet_count', 'favorite_count',
'favorited', 'retweeted', 'is_quote_status', 'retweeted_status']
entities_attrs = ['hashtags', 'symbols', 'user_mentions'] # creating empty dictionary, and specifying user id
post_dict = defaultdict(list) for tweets in timeline :
post_dict['user_id'] = user_id
for post in list(post_attrs) :
if post == 'text' :
try :
t = tweets[post]
t = t.replace('\n','')
t = t.replace('\r','')
post_dict[post].append(t)
except :
post_dict[post].append(np.nan)
else :
try :
t = tweets[post]
post_dict[post].append(t)
except :
post_dict[post].append(np.nan) # looping through other post attributes
for entity in entities_attrs :
try :
attr_name = 'len_' + entity
post_dict[entity].append(tweets['entities'][entity])
post_dict[attr_name].append(len(tweets['entities'][entity]))
except :
post_dict[entity].append(np.nan)
return post_dict
其他提示
auth = tweepy.OAuthHandler("CONSUMER_KEY", "CONSUMER_SECRET")
auth.set_access_token("ACCESS_TOKEN","ACCESS_TOKEN_SECRET")api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True, parser=tweepy.parsers.JSONParser())
- 在您的 API 方法中,一定要指定 wait_on_rate_limit 和 wait_on_rate_limit_notify,一旦您达到速率限制,它们就会等待并打印出一条消息。
- 我发现从 AWS 服务器(或任何云服务器)调用 API 比使用我的本地机器更快。这可能纯粹是我自己在查询 API 时观察打印的用户 id 填充速度的启发。你可以两者都试试,尤其是如果速度对你很重要的话。
- 这可能是我能给你的最大的提示,并且在我自己的数据收集中改变了游戏规则。尽管 Twitter 声明每 15 分钟的请求限制为 900 个,但是如果你在一批中连续请求,它们会变得非常慢(每 7 秒 1 个呼叫对每秒 1 个呼叫)。通过一次将我的批分成 5000 条(而不是我第一次迭代中的 20000 条),我能够更快地获得用户的历史推文。这意味着每次运行 5000 个用户的用户 ID 迭代,然后休息一下,进行另一个 API auth 调用,并调用另外 5000 个用户。请随意测试更小的批次。
目前就这些——如果有任何问题,请告诉我。快乐求活新鲜数据!
如何以最大的 ROI 和速度采用智能自动化?

Source: https://www.burwood.com/blog-archive/automation-vs-orchestration-whats-the-difference
自动化将使银行业的 20 万工人失业。在未来的十年里,理论上讲,全球近一半的带薪工作可能会面临自动化带来的风险,因为这些工作使用的是已经掌握的技术。在未来的 12 年里,三分之一的美国工人面临着因新技术而失去工作的风险,政治家们已经在谈论全民基本收入 (UBI)来补偿失去的工作,并保证人们有基本的生活工资来帮助他们应对。

Source: The New Yorker
这些都是可怕的预测,但让我们打破所有这些喧嚣,看看如何通过采用变革性智能自动化(IA)功能来推动变革的最佳实践。在过去几年中,作为 ia 之旅的第一步,通过机器人流程自动化(RPA)技术采用重复流程自动化的企业数量呈指数级增长。许多公司通常从 RPA 技术开始,这是一个关键的促成因素,为了确保最大的潜在价值,需要考虑一些关键因素。事实上,选择技术堆栈相对容易,因为已经有相当多的研究对不同的供应商进行了排名和分类。一旦你清楚了所有的十个成功因素,做决定就会变得容易。
机器人流程自动化软件魔力象限

Source: Gartner (May 2019)
我建议在你做出选择的时候,正面抓住这十个机会。
1。加倍关注您的公司战略和级联自动化业务案例
你应该总是从“问题”和商业机会开始。第一步是加倍你的公司战略。与您的高级利益相关者和公司领导层/首席执行官交谈,以了解迫切的需求是增加收入、提高利润、消除欺诈/合规问题还是其他。在内部员工、外部客户/消费者或供应商之间,对他们希望更好地服务的角色加倍下注。
一旦您对战略和目标有了更清晰的认识,请双击基于上述内容的自动化业务案例。你应该进一步明确你的重点是前台还是后台。选择合适的领域投资运营、供应链、财务、人力资源等。也许您的独特案例跨越了需要将多个组织整合在一起的接缝。这应该会让你对你需要与你的关键利益相关者保持一致的“奖励的大小”有一个概念。关注早期采用者团队和领导者。将数字传播者和意见领袖视为影响者和赞助者。作为一个意想不到的好处,所有这些开始的努力也会帮助你战胜文化阻力。
2。根据您的环境做出正确的选择—同类最佳与最佳套件
自动化领域也存在传统的 IT 投资困境。第一,选择没有对错;最合适的选择取决于您的业务案例和现有的公司架构。

best-of-breed vs. best-of-suite
如果你有强烈的特殊需求和潜在的更高的股东回报,那么就大胆地采用的最佳战略。这将使您能够选择最适合您的精品需求的解决方案,即 RPA、OCR、ML、BPM。它将加快您的上市创新。尽管如此,在大多数情况下,由于集成、可支持性、故障点的数量以及多种技术堆栈所有权,您的(IT 系统)总拥有成本会增加。此外,不要低估管理各种软件供应商/集成商的必要性。
另一种选择是针对特定需求提供足够好的功能,并选择一个您可以信赖的一体化解决方案 E2E 最佳套件解决方案。这种方法可以降低总体拥有成本,减少供应商/集成商的数量,并避免一个瓶颈。内包开发运维工作将变得更加容易,并且通常可以更快地将部署推向市场。主要的缺点是缺乏灵活性、有限的垂直功能,并且在用户体验或功能方面更难赢得最终用户的赞赏。您也可能被一个供应商所束缚,并且随着需求的发展进行定制可能是一个挑战。这里的另一个“注意”是,几乎每个大型 BPM、ERP 或云供应商都已经进入了利润丰厚的自动化领域。此外,要注意所有可用的自动化功能的成熟度。
采用现成的产品,而不是为自动化定制构建
虽然您可以采用和集成企业自动化软件包,但总有一种选择是构建一个定制的自动化解决方案。FAANG 有能力建造它,但问题是,你能吗?

Source: ITSolutions — Link
因为信息架构是一个快速变化的行业,我的建议是,当定制对你的公司来说是一个真正的竞争优势时,就定制。一旦明确了这一竞争点,您就可以寻求资源来投资于您的数据科学家、架构师和软件工程师,以将 Python/Java/C++语言与 Knime/SAS/PowerBI/Cloud ML 解决方案结合使用,并开发满足您特定业务需求的定制 ML 算法。
3。决定内包和/或外包实施工作
您需要快速地为实现和集成工作做出另一个战略选择。在理想的情况下,你可以内包所有的开发和运营/支持工作。不利的一面可能是更慢的启动和更高的启动成本,而从长远来看,你将享受更快、更便宜、更敏捷的交付。当你尽可能内包时,也更容易建立公民开发者,从而使自动化民主化并建立草根数字文化。

另一方面,外包会让你更快启动,降低你的初始资金需求。您还将从一开始就拥有更清晰的代码/标准,并在您将工作内包时赢得时间。
我的建议是在短期内外包和学习,但同时,开始投资于内包工作,并为未来的自动化机会播种第一代高级公民开发人员。
4。关键时刻—投资开发运维及持续支持的治理
是的,他们会告诉你,你的机器人将全天候工作,没有任何假期或病假,而且他们从不放弃。但是他们没有告诉你的是,他们也经常停止工作。请记住,您将面临遗留集成、信息安全需求、云迁移、不计其数的版本、技术异常,所有这些很快就会变成一场完美风暴。这些很快就会成为日常的头痛问题,因为你会用机器人取代你的关键流程,所有以前有经验的人可能都已经离开了。因此,总体治理框架是维持价值的关键,包括充分的控制、法规遵从性、用户访问管理、信息安全和 99%以上的关键流程优质服务。
每个公司都需要一个“机器人运营中心(ROC)”
智能自动化提供商通常是行业中的新手,经常推出新版本和升级。这意味着支持人员可能不完全符合行业标准,而且与 ERP/CRM 相比,DevOps 产品可能相对不成熟。这给支持质量和确保快速扩展带来了挑战。您可以通过业务和 IT 之间的积极协作以及嵌入内部 DevOps 模型来解决其中一些问题,该模型由混合 DevOps 结构中的合作伙伴进行补充。

Source: Link
一个新兴的未来工作示例是维持您的机器学习模型,目前还没有全面或负担得起的企业支持模型。公司需要找到方法来确保 ML 模型的持续性能,即使它们已经被移交给支持部门(即重新培训、重新标记、转移学习、性能监控等)。).
平台与业务流程支持 —虽然以上几点解决了平台需求,但我们也应该承认业务流程支持带来了类似的挑战。自动化/ML 模型解决了从非常简单到非常复杂的过程集(数百个机器人,需要集成多个平台)。特别是在后一种情况下,目标是最高的业务价值,支持流程本身就变成了业务知识、人员配备的连续性和技术专长的问题。创建这种支持结构需要时间来培训、提升以及维护,以确保适当的质量。早点开始!

A subset of the leading vendors. IA is fast becoming a crowded space…
5。从最小可行的产品开始,采用敏捷
你需要在自动化项目中使用敏捷/Scrum 或者一个变体;否则,我保证你的程序会失败!
根据敏捷原则,您不必从一开始就自动化整个过程。选择一些 lighthouse 案例,启动概念证明,意思是,以更高的频率自动化快乐路径和流程的各个部分。不要自动化每一个异常,除非你能确认它满足一个适当的频率阈值,在这个阈值下,自动化的好处可以显著地补偿开发成本。关注最小可行产品,以 快乐路径开始。选择和调整第一组流程对于整个企业 IA 项目的成功至关重要。

Agile project management life cycle
敏捷也为开发带来了挑战,因为变更请求和设计澄清的数量远远超出了最初的蓝图阶段。在这种情况下,有一个强有力的产品经理和 scrum 大师可以让事情继续发展。

Start with the happy path
另一个关键的实现挑战是满足内部客户的需求,尤其是当自动化面对用户时(人在回路中、编排等)。).许多业务需求(功能或 UX 相关的)是特定于某个业务模型的。在维护产品完整性、可伸缩性和可支持性的同时,用技术能力确保客户响应的灵活性和敏捷性仍然是自动化项目管理和实现中的“高”技能之一。

Source: Gartner (Christopher Little)
6。每个机器人的投资回报率是多少?
认真对待这一点,以优化投资,同时避免分析瘫痪的情况。一条经验法则是,自动化带来的节约应该等于或高于您的一次性成本。否则,您不应该继续。换句话说:你的付出比例应该是一年或更少。如果特定的自动化成本为 50,000 美元,那么您应该期望至少 5000 万美元或更多的持续收益。这是你的最低门槛。通常,较简单的 RPA 自动化的开发成本为 5 美元——10K,运行成本为类似的美元,而较复杂的自动化的开发或运行成本可能高达 4 万至 5 万美元(不包括 ML 型号)。
不要只考虑自动化消除了什么(减少您已经做的事情),还要考虑您可以用自动化做什么(承担更多的额外容量)。您可以减少罚款、提高客户服务/满意度、避免缺货或消除洗钱和欺诈!

Image source: https://www.slideteam.net/
7 .。不要错失良机,首先重新设计遗留流程!
比尔·盖茨优雅地说道“在商业中使用的任何技术的第一条规则是,自动化应用于高效的运营将会放大效率。第二,自动化应用于低效率的操作会放大低效率。”
关于 RPA 的一个很大的误解是,它被视为消除任何流程中低效率的灵丹妙药。
在实施 RPA(或更高级的 IA)的同时重新设计您的遗留流程会增加整个计划的时间和成本。尽管如此,投资回报可能会成倍增加。因此,我的建议是首先关注过程标准化和优化,而不是交付它的工具。首先,我们务实地标准化,然后我们改进,然后我们自动化。

Source: Intelligent Automation — Reshaping the future of work with robots, EY (PDF)
例外是任何成功的信息架构项目面临的逆风
如果您自动化整个遗留的“蜘蛛网”,这将需要很长时间,并且维护或支持起来很有挑战性。在大多数企业中,通常下至第 3 级,设计和文档编制是显而易见的,但通常较少应用于较低级别的流程设计和执行(4–5–6)。在第 6 层(击键或任务层),由于好的或坏的原因,流程通常不协调,并且在业务单元之间有差异。例如,每个国家可能有不同的法规、贸易条款或客户/消费者要求,因此有必要进行变更或例外。我们总是会有例外或客户驱动的变化,找到定制与标准化之间的最佳平衡点是一门艺术;因此,你需要专家。

Source: Slideshare — link
这是一个绝佳的机会,既可以转变组织结构,又可以优化与自动化项目并行的现有流程,从而最大化股东回报。

Source: CiGen RPA — Link
你需要多技能的专家
在自动化之前重新设计流程的最佳实践是组建一个拥有流程理解和 IA 技术专业知识的多技能专家团队。公司可以考虑招聘有经验的流程顾问、6-sigma/精益/约束理论/设计思维专家来加速转型。与 IA 项目并行运行流程重新设计(相对于线性瀑布方法)至关重要,因为公司可能会错过自动化的机会。
最具破坏性的方法是遵循零基础的流程清理方法,即从头开始设计最佳流程,而不是对现有流程进行增量更改。同时,现有组织也应该重新调整技能和目标,以适应新的目标流程。
8。一枚硬币的两面:智能自动化与工作流程/工作编排
历史上,公司总是被组织成筒仓。当他们开始部署 IT 时,他们实施的系统本身是孤立的:人力资源管理、税务和会计管理、采购管理、物流管理等。随着公司变得越来越不依赖于功能,未来的工作将需要跨孤岛简化这些业务流程。这里要注意的是,在尝试数字化转变您的业务时,不要将 RPA 作为权宜之计。日常运营自动化跨越了各个孤岛。
虽然智能自动化和业务流程管理(BPM)各有不同,但它们也是相辅相成的,可以帮助您实施公司范围的无缝数字化转型。从概念上讲,自动化似乎已经在消除手工和重复性工作。然而,不同之处在于过程。简单的 RPA 机器人自动执行单独的任务;他们缺乏将这些任务联系起来以简化工作流程的能力。这就是工作流程和工作编排自动化的起点。好消息是 BPM 和自动化正在快速融合,并且可以集成以利用它们的优势。
RPA 和 BPM 一起部署时,可以帮助您构建一个强大的平台,支持整个组织的数字化转型。他们有着相似的提高效率和生产率的目标。因此,它们不是相互竞争的方法,可以和谐地一起工作。
BPM 简化了组织的后端工作,以支持更好的员工体验,这反过来使这些员工能够支持更智能、更灵敏的客户交互。当您需要自动化那些不会频繁变化并且不需要大量集成的流程时,您应该选择基本自动化。BPM 应该用于主要由人工执行或需要第三方集成的流程。
智能 BPM (iBPM)工作流可以触发智能 RPA 机器人,反之亦然。RPA 可用作中间件,从核心系统或外部网站收集数据。
用例:新客户入职银行

Source: SAP — Sebastian Schroetel and Christopher Aron at digitalistmag — Link
你应该仔细分析并决定如何利用有限的公司资源。这个决定取决于要构建的自动化项目的目标。
使能技术
幸运的是,可行的技术是存在的。业务流程管理(BPM) 和流程再造在 90 年代已经很流行了。现在,现代智能业务流程管理套件(iBPMS)供应商提供了一套集成的技术来协调人、机器和事物。一个现代的 iBPMS 平台允许“公民开发者”在业务流程的改进和转换上进行合作。因此,现在是利用 iBPM 和 IA 平台的力量推动数字化转型的最佳时机。

Source: 2019 Gartner Magic Quadrant for Intelligent Business Process Management Suites
9。让 IT 和人力资源职能成为核心智能自动化团队和旅程不可或缺的一部分
信息架构的商业价值和股东回报必须与 IT 和人力资源团队密切合作共同创造。如果由于缺乏技术资源、云基础设施、与遗留系统的集成、符合信息安全标准以及持续的 IT 支持要求而导致公司 IT 职能部门没有密切参与,IA 项目可能注定会失败。由于 IA 项目需要短时间的冲刺和频繁的自动化发布,it 需要与 IT 部门同步工作。

Source: camp-essen — Link
由于每个 IA 项目都会自然地在系统中产生不确定性和紧张感,人力资源协作是持续沟通和密切管理员工关系的关键。人力资源支持对于明确目标至关重要,它还可以帮助技能再培训计划,吸引合适的人才,并重新调整一些遗留角色的用途。
10。收益递减陷阱——如何跨越鸿沟?
自动化可以在短期内带来巨大的价值,但如果您不发展您的 IA 能力,机会将会受到限制。大多数公司首先采用机器人流程自动化(RPA ),通过不需要人工交互的软件程序来自动化基于规则和确定性的流程。然而,这些公司在 1-2 年内很快就会遭遇商业价值回报递减,最终将需要采用更先进的技术,如机器学习(OCR、NLP 聊天机器人、分类/翻译机器人、预测/说明性警报等。),以及动态工作流程。

Image template: PeopleDesign
这是一个快速变化的空间,创新的步伐非常有活力。保持内部和外部联系,跨越每个鸿沟。
接下来,S 曲线/空白区域
制定机会总体规划,为您的组织选择合适的解决方案供应商;一家希望在您未来 3-5 年感兴趣的领域进行战略性投资的供应商。时间过得很快。当解决方案的功能不再符合客户需求时,改变方向可能为时已晚,且代价高昂。

Source: Genpact — Automation in banking and financial services processes
共同投资
共同投资是一个所有自动化公司为了在商业领域获得优势而竞争的领域。选择正确的业务战略和联合投资机会可以显著降低未来自动化的成本,甚至更好的是,释放巨大的未来价值。
遗言
还有其他重要的考虑事项我没有在这里介绍,比如建立自动化卓越中心(CoE),机器人的信息安全最佳实践,或者选择正确的供应商。IA 是一个多年的旅程,也是一个陡峭的学习曲线。不要害怕在实验中犯错误,大胆前进。祝你好运!

Good luck!
信用/来源:
https://www.uipath.com/blog/rpa-re-engineer-first-really?hs_amp=true
https://HBR . org/2018/06/before-automating-your-company-processes-find-ways-improve-them
https://technology advice . com/blog/information-technology/workflow-vs-BPM-vs-RPA/
https://kissflow.com/bpm/rpa-vs-bpm-whats-the-difference/
https://dzone.com/articles/rpa-vs-bpm
如何为任何模型添加置信区间
不到 10 行代码

Photo by Toa Heftiba on Unsplash
“我能相信你的模型吗?”
这是你展示最新作品时,你的经理问的第一件事。你怎么回答?你指的是均方差吗?R 系数?一些例子结果怎么样?这些都很棒,但是我想在你的工具箱中添加另一项技术— 置信区间。
信任
归根结底,任何数据科学家最重要的工作之一就是帮助人们信任一种他们很可能并不完全理解的算法。
帮助建立这种信任的一种方法是给模型的预测增加置信区间。我们将为本文定义置信区间,作为量化估计的不确定性的一种方式。这对于分类问题来说更容易。大多数算法提供概率估计,可以作为置信度得分。例如,90%的概率是一只猫应该比 50%的概率更有信心。
然而,对于回归问题,事情往往变得更加棘手。大多数算法没有提供置信度或概率分数的自然方法。这个问题有很多解决方案,我最喜欢的一个是贝叶斯模型,但是我想讨论最简单和最容易的方法来实现任何机器学习模型。
自举重采样
首先,我们需要定义一个引导示例。幸运的是,这很简单——这是我们数据集的一个样本,替换了,其中样本大小与数据集大小相同。这意味着平均 bootstrap 样本包含 63.2%的原始观察值,并省略 36.8%。遗漏的 36.8%的数据是从样本中包含的 63.2%的数据中复制的。你可以在这里阅读更多关于这些数字是如何计算的。
这很有用,因为这是一个非常简单的方法,通过它,您现在可以模拟不同的底层数据集,而不会实际更改数据。
下面是如何创建数据集的 1,000 个引导样本(假设 X 值在 scaled_df 中,标签在 target 中)
一旦你有了 1,000 个数据样本,你现在可以训练你的模型 1,000 次,并获得不同的结果。关键在于,当输入数据的微小变化仅导致输出的微小变化时,结果会更加稳健。让我们看看我们的培训(在本例中使用一个简单的 SGD 回归器)
在这个例子中,我关心的结果是我的模型系数。您可以在我的训练循环中看到,我将它们附加到一个列表中,这样我就可以分析系数的分布,如下所示:

我们拥有的是我在 x 轴上的所有特征以及这些特征的系数分布(来自 1000 个模型)。当试图理解这些系数值的可信度时,这非常有帮助。
例如,有几个变量,如年龄,跨度为 0。这不好,因为你不仅对点估计不自信,而且对方向(正或负)也不自信。其他变量,如 PTRATIO,具有较小的方差,并且完全位于正或负的一侧。这些变量给了我们更多的信心。
您还可以定义概率范围。如果我们仔细观察 LSTAT,我们会看到以下内容:
mean -3.599465
std 0.687444
min -5.825069
25% -4.058086
50% -3.592409
75% -3.120958
max -1.575822
100%的时间系数值落在-1.57 和-5.82 之间,内部四分位数范围位于-3.12 和-4.05 之间。
充满信心地前进
希望这是一个有用的例子,说明如何在任何模型中增加和测量你的信心。虽然简单,但我们已经证明了 bootstrap 重采样非常有启发性,有助于建立对模型的信任。这并不是提供置信区间的唯一方法,我鼓励你把它作为在你的模型中建立置信区间的起点。
如何向 Azure 数据湖添加元数据
1.介绍
许多公司考虑建立一个企业数据湖。这个想法是将数据存储在一个集中的存储库中。这样,团队就更容易用数据创造商业价值。为了防止数据湖变成充斥着不可信数据的数据沼泽,元数据是关键。在这种情况下,可以区分以下类型的元数据:
- 业务元数据:数据所有者、数据源、隐私级别
- 技术元数据:模式名、表名、字段名/类型
- 操作元数据:时间戳、数据大小、沿袭
在本博客的剩余部分,将讨论如何建立 Azure 数据湖以及如何添加元数据。关于如何在你的 Azure 数据湖中保护数据编排的更多细节,请看我的后续博客这里。关于如何使用快照和增量备份来防止数据湖中数据丢失的解决方案,请看这个博客。
2.带有元数据的 Azure 数据湖体系结构
在这个项目的架构中,结合了流行的 Azure 服务的功能来创建数据湖,其中数据/元数据从 SQLDB 复制到 Azure 数据湖存储。项目的设置可以在下面找到。

2. Azure Data Lake architecture with metadata
Azure 服务及其在本项目中的使用描述如下:
- 元数据存储用于存储业务元数据。在这个项目中,使用了一个 blob 存储帐户,其中数据所有者、数据的隐私级别存储在一个 json 文件中。
- SQLDB 用作包含将要复制的表数据的源系统。它还包含将用于描述数据的技术元数据。
- Azure 数据工厂 v2 (ADFv2)被用作将数据从源复制到目的地的编排器。它还收集业务元数据和技术元数据,并生成操作元数据。
- Azure Function Python 被 Azure Data Factory 用来创建符合公共数据模型 (CDM)格式的单个元数据文件。在这里,它使用业务/技术/运营元数据作为输入,并使用 CDM 的 jsonschema 创建 model.json。
- Azure Data Lake Store gen 2(ADLS gen 2)用于存储来自 10 个 SQLDB 表的数据。创建一个文件系统,每个表都是文件系统中的一个根文件夹。除了数据本身,元数据还使用由 Azure 函数 Python 创建的 CDM 格式的 model.json 进行存储。
在接下来的三章中,实现了这个架构。在第 3 章中,部署了创建数据湖的先决条件。然后在第 4 章,部署并运行一个管道。最后,在第五章得出结论。关于如何保护 ADFv2 管道的更多细节,请参见我的另一篇博客。
3.创建 Azure 数据湖的先决条件
在这一章中,实现了一个带有元数据的 Azure 数据湖。执行以下步骤:
- 3a。创建 SQLDB
- 3b。使用元数据创建存储帐户
- 3c。创建 ADLS 第二代帐户
- 3d。在 python 中创建 Azure 函数
- 3e。创建 Azure 数据工厂实例
- 3f。使用受管身份向 ADLS 第二代授予访问权限
3a。创建 SQLDB
按照快速入门中的步骤如何创建 is SQLDB 数据库。在这种情况下,请确保您选择了基本数据库,如下所示。

3a1. Basic SQLDB to save costs
此外,请确保安装 AdventureWorksLT 示例数据库,另请参见下文。

3a2. Add AdventureWorksLT as sample database
3b。使用业务元数据创建存储帐户
在此步骤中,将创建一个常规存储帐户。遵循本快速入门中的步骤。确保存储帐户存储在安装了 SQLDB 的同一资源组中。此外,在存储帐户中创建一个容器,并将该容器命名为 processmetadata 。然后使用以下链接下载包含数据所有者、数据隐私级别的以下业务元数据文件:
[https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/procesdataexample/MetadataProcess.json](https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/procesdataexample/MetadataProcess.json)
将 MetadataProcess.json 上传到您的存储容器,另请参见下文。

3b1. Storage account with container and MetadataProcess.json uploaded
3c。创建 ADLS 第二代帐户
在此步骤中,将创建一个 ADLS 第二代存储帐户。遵循本快速入门中的步骤。确保“分层命名空间”为“是”,这将创建一个分层文件系统(HFS ),其中可以创建文件夹(而不是基于对象的文件系统,其中所有信息都存储在对象本身中)。另见下文。

3c1. ADLS gen2 with hierachical namespace enabled
随后,在 ADLS gen 2 中创建一个文件系统,如下所示。

3c2. Create File System in ADLS gen2
确保文件系统被命名为 sqldbdata 。
3d。在 python 中创建 Azure 函数
在这一步中,用 Python 创建了一个 Azure 函数。按照这个用 Azure Python 创建函数的快速入门中的步骤操作。使用 HTTP 触发器发布初始 Azure 函数 Python 后,更新 init。py 和 requirement.txt,并将 cdmschema.py 添加到项目中 init.py 的旁边。
[https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/modeljson/modeljsonwrite/__init__.py](https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/modeljson/modeljsonwrite/__init__.py)[https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/modeljson/modeljsonwrite/cdmschema.py](https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/modeljson/modeljsonwrite/cdmschema.py)[https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/modeljson/requirements.txt](https://raw.githubusercontent.com/rebremer/adfv2_cdm_metadata/master/modeljson/modeljsonwrite/requirements.txt)
init。py 接收元数据输入作为参数,创建符合 CDM jsonschema 的 model.json 对象,然后将 json 对象返回给 ADFv2。然后,ADFv2 会将数据写入 ADLS gen2 文件系统。Requirement.txt 包含 Python 中 Azure 函数运行所需的 Pypi 库。随后,使用以下命令发布代码。
func azure functionapp publish <APP_NAME> --build remote
当你的 Azure 函数成功部署后,你可以看到函数中的代码,见下文。

3d1. Python code in Azure Function
3e。创建一个 Azure 数据工厂实例
在这一步中,用 Python 创建了一个 Azure 函数。遵循这个创建 Azure 数据工厂的快速入门中的步骤。创建数据工厂后,找到您的 ADFv2 资源并单击 author & monitor。然后选择建立一个代码库,导入下面的 GitHub 库 rebremer 和 projectADF v2 _ CDM _ metadata,见下图。

3e1. Setup code repository in ADFv2
3f。使用受管身份向 ADLS 第二代授予访问权限
在所讨论的体系结构中,ADFv2 用于将数据从 SQLDB 复制到 ADLS gen2。此外,使用 Azure Python 函数从 blob 存储中读取业务元数据,并将其写入 ADLS gen 2。为此,需要授予对 ADLS gen2、blob 存储和 SQLDB 的访问权限。在本教程中,解释了如何将 RBAC 规则分配给存储。按如下方式分配以下 RBAC 规则:
- 授予您的 ADFv2 实例“存储 Blob 数据贡献者”角色,使其成为具有业务元数据的存储帐户(在 3b 中创建)
- 向您的 ADLS gen 帐户(在 3c 中创建)授予您的 ADFv2 实例“存储 Blob 数据贡献者”角色
可以在访问控制选项卡中验证是否成功添加了 RBAC,请参见下面的 ADFv2 实例(3c)和 Azure 函数(3d)。

3f1. ADFv2 and Azure function as “Storage Blob Data Contributer” on ADLS gen2
为简单起见,在以下两个步骤中不使用托管身份:
所有先决条件现在都已部署。在下一章中,管道是在 ADFv2 中安润构建的。
4.在 ADFv2 中构建并运行管道
在本章中,实现了 ADFv2 中的构建和运行管道。执行以下步骤:
- 4a。设置参数和链接的服务
- 4b。在 Azure 函数中配置应用洞察
- 4c。运行管道
4a。设置参数和链接的服务
第一步,需要为您的存储帐户和 SQLDB 定制管道。确保 ADFv2 在数据工厂模式下运行,并使用您的参数填写管道的参数,如下所示

4a1. Data Factory mode ans set parameters
随后,在链接的服务中引用您自己的日志记录、ADLS gen 2、SQLDB 和 Azure 函数的存储帐户。请参阅下面需要更改的链接服务:

4a2. Linked Services that needs to be customized
4b。在 Azure 函数中配置应用洞察
第一次运行管道时,管道可能不会正确运行。在 ADFv2 中可以看到错误消息,但是,ADFv2 也引用了一个外部 Azure 函数。要查看 Azure 函数的日志记录,需要启用应用洞察。转到“监控”选项卡,按照向导设置应用洞察,见下文

4b1. Setup Applications Insights in Azure Function
当 Azure 函数运行时,所有 logging.info 和引发的异常都会被记录,参见下面的示例。

4b2. Example of logging in Azure Function using Applications Insight
4c。在 ADFv2 中运行管道
最后一步,管道可以在 ADFv2 中运行。转到您的管道并单击 debug。当一切顺利时,所有的绿色检查将出现在输出中,如下所示。

4c1. Successful run of pipeline
转到您的 ADLS gen 存储帐户,验证数据和元数据是否已复制。有关表 dboversio,请参见下面的示例

4c2. Data and metadata of table in ADLS gen2 file system
当您打开 model.json 时,可以使用 CDM 格式找到元数据,请参见下面的代码片段。
{
"name": "BlogMetaData",
"description": "Example model.json using CDM json schema",
"version": "1.0",
"annotation": {
"retentionPeriod": 62,
"sourceSystem": "bremerov",
"IngestionDate": "2019-09-09 16:56:00Z",
"privacyLevel": "10"
},
"entities": [
{
"$type": "LocalEntity",
"name": "SalesLTProductModel",
"description": "",
"attributes": [
{
"name": "ProductModelID",
"dataType": "int64"
},
...
5.结论
许多公司考虑建立一个企业数据湖。为了防止数据湖变成数据沼泽,元数据是关键。在这种情况下,可以区分以下类型的元数据:
- 业务元数据:数据所有者、数据源、隐私级别
- 技术元数据:模式名、表名、字段、字段类型
- 操作元数据:摄取开始/结束的时间戳
在这篇博客中,我们讨论了如何使用下面的架构向数据湖添加元数据。

5. Azure Data Lake architecture with metadata
如何正确地将正则化添加到 Keras 预训练模型中
使用 Tensorflow 2.0 正则化预训练的 Keras 模型

Photo by Kelly Sikkema on Unsplash
介绍
如果你以训练深度学习模型为生,你可能会厌倦知道一件具体而重要的事情:
微调深度预训练模型需要大量的正则化工作。
作为对比,你可能已经注意到,如何向来自深度学习库(如 Keras)的预训练模型添加正则化并不总是显而易见的。此外,找到这个问题的正确答案也不容易。在撰写这篇文章的过程中,我遇到了许多关于堆栈溢出的代码片段和一些博客文章,它们根本没有得到正确的解释。然后,作为减少您的 Google 搜索的一种方式(并帮助我未来的自己),我将向您展示如何以正确的方式将正则化添加到预训练的 Keras 模型中。
让我们从基础开始。
微调
微调是指采用预先训练好的模型,并将其作为优化不同(大多数情况下相关)任务的起点的过程。你可以想象使用一个在 ImageNet 数据库上训练的 ResNet50 模型,并用它来解决一个新问题,比如昆虫分类。
这个过程通常遵循简单的步骤。
- 我们首先加载模型架构和预训练权重。对于迁移学习更为成熟的计算机视觉,这是我们加载这些著名架构之一的地方,如 DenseNets 或 MobileNets 及其各自的权重(在 ImageNet 上训练)。
- 然后,我们在预训练模型的顶部添加一个特定于任务的分类层。这通常是一个具有 softmax 或 sigmoid 激活的致密层。请注意,分类层中单元的数量必须等于新问题的类的数量。所以,如果你的昆虫数据集包含 28 种虫子之类的东西,那么最后一层需要有 28 个单元。
- 然后,我们完成了模型的准备。在 Keras 中,我们使用优化器和损失函数编译模型,设置超参数,并调用 fit。
附注:这可能过于简单,但对我们的例子来说很好。
对抗过度拟合
我们必须记住的一件事是:
当微调预训练模型时,过度拟合是一个更大的问题。
问题很容易看出来。如果你有一个小的训练数据,你会不断地向网络一遍又一遍地显示相同的实例。此外,正如我们所知,ImageNet 上预先训练的 ConvNets 通常非常复杂;即它们有许多训练参数。因此,模型会很快完全记住你的训练数据。
作为解决方案,微调通常需要两件事:
- 大量的正规化
- 非常小的学习率
对于正规化,任何事情都可能有所帮助。我通常使用 l1 或 l2 正则化,并提前停止。对于没有批量标准化的 ConvNets,空间丢失也是有帮助的
作为补充说明,深度学习模型是众所周知的数据饥渴。这些模型需要大量数据来将非常复杂的高维空间分解成特征空间中的线性可分决策。许多人将微调视为使用较小数据集训练深度模型的一种方式。虽然在实践中,这种观点听起来可能是正确的,但这里有一个重要的陷阱。即使您可以使用小得多的数据集来拟合新模型,请记住,您的预训练模型训练了几天(使用多个 GPU)。换个说法,微调其实就是——站在巨人的肩膀上。
现在让我们直接进入代码。
黑客攻击
直观地说,添加正则化的过程很简单。在加载我们预先训练好的模型后,称为 基础模型 ,我们将遍历它的所有层。对于每一层,我们检查它是否支持正则化,如果支持,我们添加它。代码如下所示。
看起来我们结束了。事实上,如果你在谷歌上搜索如何将正则化添加到 Keras 预训练模型中,你会发现相同的结果。
作为安全检查,让我们确保正则化设置正确。在 Keras 中,我们可以通过访问层或模型的 loss 属性来检索损耗。在我们的例子中,我们可以通过以下方式访问所有损失的列表(通过正则化来自所有层):
如果你对术语感到困惑,这个属性叫做损失,因为在优化过程中正则化惩罚被添加到损失函数中。
如你所见,有些奇怪的事情正在发生。列表是空的,这意味着没有正则化惩罚应用于卷积核。
但是刚刚发生了什么?
好吧,直接进入问题,看起来当我们改变一个层的属性时,正如我们所做的,唯一真正改变的是模型配置。因此,模型对象本身就和我们加载时一样。完全没有变化。
添加正则化后,看一下配置文件。kernel _ regulator属性和我们设置的一样。
这个问题的一个简单解决方案是重新加载模型配置。这很容易做到,也解决了问题。
现在,如果我们试图看到,我们就有了。
然而,作为一种常见的黑客行为,这又引入了另一个问题。如果您更仔细地注意模型的权重,在从配置文件重新加载模型之后,权重被重置! 我们刚刚丢失了,所有的 ImageNet 预训练参数!
好吧,一个快速的解决方法是使用相同的策略。我们可以在重新加载模型配置之前保存权重,并在模型正确加载后重新加载权重。
下面的函数完成了全部工作。您可以传递来自 Keras 应用 (使用 Tensorflow 2.0) 的任何模型,以及您想要的正则化器,它会返回正确配置的模型。请注意,在从配置文件重新加载模型之前和之后,我们是如何保存和重新加载模型权重的。
同样,您可以使用相同的代码添加bias _ regulator和activity _ regulator。
就是这样。一个快速但有希望的有用的技巧来调整你的预训练模型。
感谢阅读!
如何调整检测网
一种由 NVIDIA 创建的对象检测架构

Photo by Christian Wiediger on Unsplash
DetectNet 是由 NVIDIA 创建的对象检测架构。它可以从 NVIDIA 的 Deep Learning 图形用户界面 DIGITS 运行,通过该界面,您可以快速设置和开始训练分类、物体检测、分割和其他类型的模型。
NVIDIA 提供了两个基本的 DetectNet prototxt 文件:
- 单个类一个(为原件),可在这里找到,并且
- 两个等级中的一个可以在这里找到。
DetectNet 最初的架构是用 Caffe 编写的。除了在英伟达网站上发表的两篇博客文章和一些(主要)重申博客内容的教程之外,我没有找到太多关于该架构的文档。我确实发现,在 NVIDIA/DIGITS 存储库中,有一个特定的 GitHub 问题问题#980 已经积累了大量信息。
以下是我从 GitHub 问题中收集的重点:
- 训练集中的图像大小不应该不同。如果是,您应该填充它们或调整它们的大小,使其大小相等。调整大小或填充可以在数字数据集创建步骤中完成。
- DetectNet 对大小在 50x50 像素到 400x400 像素之间的边界框很敏感。它很难识别超出这个范围的边界框。
- 如果您想检测比检测网敏感的尺寸小的对象,您可以调整图像的大小,使大部分边界框适合检测网的首选范围,或者您可以将模型的步距更改得更小。
- 图像尺寸必须可被步幅整除。例如,1248 和 384(检测网的默认图像大小)可以被 16 整除。
- 如果您正在使用不同于原始架构的图像分辨率来训练模型(原始架构期望图像的宽度为 1248,高度为 384),您需要在架构内的行 57 、 58 、 79 、 80 、 118 、 119 、 2504 、 2519 上更改指定的图像尺寸
- 要更改模型步幅,您必须在行 73 、 112 、 2504 、 2519 和 2545 中将默认步幅值(16)更改为您想要的值(这些行指的是单个类 DetectNet prototxt)。
- 如果指定一个较小的步幅,则需要减少网络中的层数来调整维度。降低维数的一种方法是将 pool3/3x3_s2 层的内核和步幅参数更改为 1。该层存在于从行 826 到 836 (这些行指的是单个类 DetectNet prototxt)。
对于多类目标检测,其中您想要检测两个以上的类,您可以更改 2 类检测网络协议[ 5 ]。取决于类别数量的行有:
- 第 82 行到第 83 行:为每个额外的类添加一行,递增地或基于数据集标签文本文件中的类值更改“src”和“dst”。
- 第 2388 行:更改你的模型将识别的类别数量。
- 第 2502 至 2503 行:每增加一个等级增加一行
- 第 2507 行:将最后一个数字更改为您的模型将识别的类的数量。
- 2518-2519行:每增加一节课就增加一行。
- 2523行:将最后一个数字更改为您的模型将识别的类的数量。
- 2527-2579 行:这里有 4 层,每层 2 层。每个类别有一个对应于分数的层(该层对指定类别的检测进行评分)和一个对应于 mAP 的层(该层计算指定类别的 mAP)。为每一个额外的类别添加一个分数和类别图层,并确保在图层的顶部和底部 blobs 中指定正确的类别号。
综上所述:(I)确保数据集中的所有图像大小相同(如果不相同,请调整大小或填充它们);(ii)如果使用的是自定义大小的数据集,则必须修改 DetectNet prototxt 文件中的多行内容;(iii)确保数据中的大部分边界框的大小在 50x50 和 400x400 像素之间;(iv)如果要将跨步更改为较小的值, 您必须减少网络中的层,并且(v)您可以调整 DetectNet 体系结构,通过将一些数字更改为您要识别的类的数目,并在 prototxt 文件中添加额外的行和层来进行多类对象检测。
我建议您阅读下面提到的所有参考资料,以便更好地了解 DetectNet 以及如何针对您的问题对其进行修改。
参考文献:
- 检测网:数字量物体检测的深层神经网络
- 1 级检测网网络原型
- 2 级检测网网络原型
- GitHub NVIDIA/DIGITS 问题#980:如何使用 DetectNet 获取自定义大小的数据?
- 数字用户:将初始步幅从 16 改为 8
- 使用 Nvidia 数字训练自定义多类对象检测模型
如何使用 Python 分析笔记本电脑上的 100 GB 数据

Image Credit: Flickr User Kenny Louie
理解大数据
许多组织正试图收集和利用尽可能多的数据,以改善他们如何经营业务、增加收入或如何影响他们周围的世界。因此,数据科学家面对 50GB 甚至 500GB 大小的数据集变得越来越常见。
现在,这种数据集使用起来有点…不舒服。它们足够小,可以放入日常笔记本电脑的硬盘,但又太大,无法放入 RAM。因此,它们已经很难打开和检查,更不用说探索或分析了。
处理此类数据集时,通常采用 3 种策略。第一个是对数据进行子采样。这里的缺点是显而易见的:一个人可能会因为没有看到相关的部分而错过关键的洞察力,或者更糟糕的是,因为没有看到全部而误解了它所讲述的故事和数据。下一个策略是使用分布式计算。虽然在某些情况下这是一种有效的方法,但是它会带来管理和维护集群的巨大开销。想象一下,必须为一个刚好超出 RAM 范围的数据集设置一个集群,比如 30–50gb 的范围。对我来说这似乎是一种过度杀戮。或者,您可以租用一个强大的云实例,它具有处理相关数据所需的内存。例如,AWS 提供了 1tb 内存的实例。在这种情况下,您仍然需要管理云数据桶,在每次实例启动时等待数据从桶传输到实例,处理将数据放在云上带来的合规性问题,以及处理在远程机器上工作带来的所有不便。更不用说成本,虽然开始很低,但随着时间的推移,成本会越来越高。
在本文中,我将向您展示一种新的方法:一种更快、更安全、总体上更方便的方法,使用几乎任意大小的数据进行数据科学研究,只要它能够适合您的笔记本电脑、台式机或服务器的硬盘驱动器。
Vaex
Vaex 是一个开源的 DataFrame 库,它可以对硬盘大小的表格数据集进行可视化、探索、分析甚至机器学习。为此,Vaex 采用了内存映射、高效核外算法和惰性评估等概念。所有这些都包含在一个熟悉的熊猫式的 API 中,所以任何人都可以马上开始使用。
十亿次出租车乘坐分析
为了说明这个概念,让我们对一个数据集做一个简单的探索性数据分析,这个数据集太大了,以至于不能放入典型笔记本电脑的 RAM 中。在本文中,我们将使用纽约市(NYC)的出租车数据集,其中包含标志性的黄色出租车在 2009 年至 2015 年间进行的超过10 亿次出租车旅行的信息。这些数据可以从这个网站下载,并且是 CSV 格式的。完整的分析可以在本 Jupyter 笔记本 中单独查看。
清扫街道
第一步是将数据转换成内存可映射文件格式,如 Apache Arrow 、 Apache Parquet 或 HDF5 。如何将 CSV 数据转换为 HDF5 的示例可参见这里的。一旦数据是内存可映射格式,用 Vaex 打开它是即时的(0.052 秒!),尽管它在磁盘上的大小超过 100GB:

Opening memory mapped files with Vaex is instant (0.052 seconds!), even if they are over 100GB large.
为什么这么快?当你用 Vaex 打开一个内存映射文件时,实际上没有数据读取。Vaex 只读取文件元数据,如数据在磁盘上的位置、数据结构(行数、列数、列名和类型)、文件描述等。那么,如果我们想要检查数据或与数据进行交互,该怎么办呢?打开一个数据集会产生一个标准的数据框,检查它的速度很快,而且很简单:

A preview of the New York City Yellow Taxi data
请再次注意,单元执行时间非常短。这是因为显示 Vaex 数据帧或列只需要从磁盘读取前 5 行和后 5 行。这让我们想到了另一个要点:Vaex 只会在必要时检查整个数据集,并且会尽量少地检查数据。
无论如何,让我们从清除这个数据集的极端异常值或错误的数据输入开始。一个好的开始方式是使用describe方法获得数据的高层次概述,该方法显示每列的样本数、缺失值数和数据类型。如果列的数据类型是数字,还会显示平均值、标准偏差以及最小值和最大值。所有这些统计数据都是通过对数据的一次遍历计算出来的。

Getting a high level overview of a DataFrame with the describe method. Note that the DataFrame contains 18 column, but only the first 7 are visible on this screenshot.
describe方法很好地说明了 Vaex 的能力和效率:所有这些统计数据都是在我的 MacBook Pro (15 英寸,2018,2.6GHz 英特尔酷睿 i7,32GB 内存)上在不到 3 分钟的时间内计算出来的。其他库或方法需要分布式计算或超过 100GB 的云实例来执行相同的计算。使用 Vaex,您需要的只是数据,而您的笔记本电脑只有几 GB 的内存。
查看describe的输出,很容易注意到数据包含一些严重的异常值。首先,让我们从检查提货地点开始。移除异常值的最简单方法是简单地绘制上下车地点,并直观地定义我们要重点分析的纽约市区域。由于我们正在处理如此大的数据集,直方图是最有效的可视化方式。用 Vaex 创建和显示直方图和热图是如此之快,这样的图可以是交互式的!
df.plot_widget(df.pickup_longitude,
df.pickup_latitude,
shape=512,
limits='minmax',
f='log1p',
colormap='plasma')

一旦我们交互式地决定了我们想要关注纽约的哪个区域,我们就可以简单地创建一个过滤数据框架:

上面的代码块很酷的一点是它只需要很少的内存就可以执行!过滤 Vaex 数据帧时,不会复制数据。相反,只创建对原始对象的引用,并对其应用二进制掩码。该掩码选择显示哪些行并用于将来的计算。这为我们节省了 100GB 的 RAM,这是复制数据时所需要的,正如当今许多标准数据科学工具所做的那样。
现在,让我们检查一下passenger_count列。单次出租车行程记录的最大乘客人数是 255 人,这似乎有点极端。我们来统计一下每名乘客的出行次数。用value_counts方法很容易做到这一点:

The value_counts method applied on 1 billion rows takes only ~20 seconds!
从上图中我们可以看到,超过 6 名乘客的行程可能是罕见的异常值,或者只是错误的数据输入。还有大量 0 旅客的车次。因为此时我们不了解这些是否是合法的旅行,所以让我们也将它们过滤掉。

让我们用行程距离做一个类似的练习。由于这是一个连续变量,我们可以绘制出行距离的分布。望最低(负!)和最大值(比火星还远!)距离,我们来画一个直方图,有一个比较感性的范围。

A histogram of the trip distances for the NYC taxi dataset.
从上图中我们可以看出,旅行次数随着距离的增加而减少。在大约 100 英里的距离,分布有一个大的下降。现在,我们将以此为分界点,根据行程距离消除极端异常值:

行程距离列中极端异常值的存在是调查出租车行程持续时间和平均速度的动机。这些特征在数据集中不容易获得,但是计算起来很简单:

上面的代码块不需要任何内存,也不需要任何时间来执行!这是因为代码会导致创建虚拟列。这些列只存放数学表达式,仅在需要时才进行计算。否则,虚拟列的行为就像任何其他常规列一样。注意,对于同样的操作,其他标准库需要几十 GB 的 RAM。
好的,让我们画出旅行持续时间的分布图:

Histogram of durations of over 1 billion taxi trips in NYC.
从上面的图中我们看到,95%的出租车行程不到 30 分钟就能到达目的地,尽管有些行程可能需要 4-5 个小时。你能想象在纽约被困在出租车里 3 个多小时吗?无论如何,让我们思想开放,考虑所有持续时间不超过 3 小时的旅行:

现在让我们调查出租车的平均速度,同时为数据限制选择一个合理的范围:

The distribution of average taxi speed.
基于分布变平的位置,我们可以推断出合理的平均滑行速度在每小时 1 到 60 英里的范围内,因此我们可以更新我们的过滤数据帧:

让我们把焦点转移到出租车旅行的费用上。从describe方法的输出中,我们可以看到在 fare_amount、total_amount、和 tip_amount 列中有一些疯狂的离群值。首先,这些列中的任何值都不应该是负数。另一方面,数字表明一些幸运的司机仅仅乘坐一次出租车就几乎成为百万富翁。让我们看看这些量的分布,但在一个相对合理的范围内:

The distributions of the fare, total and tip amounts for over 1 billion taxi trips in NYC. The creation of these plots took only 31 seconds on a laptop!
我们看到上述三种分布都有相当长的尾部。尾部的一些值可能是合法的,而其他值可能是错误的数据输入。无论如何,现在让我们保守一点,只考虑 fare_amount、total _ amount、 tip_amount 少于 200 美元的乘车。我们还要求 fare_amount,total_amount 值大于$0。

最后,在对数据进行所有初始清理之后,让我们看看还有多少次出租车出行需要我们进行分析:

我们剩下超过 11 亿次旅行!这些数据足以让我们对出租车行业有一些有价值的了解。
坐到司机座位上
假设我们是一名未来的出租车司机,或者出租车公司的经理,并且有兴趣使用这个数据集来学习如何最大化我们的利润,最小化我们的成本,或者仅仅是改善我们的工作生活。
让我们首先找出搭载乘客的地点,平均来说,这些地点会带来最好的收益。天真的是,我们可以绘制一个热图,显示按平均票价金额进行颜色编码的上车地点,并查看热点地区。然而,出租车司机自己也有成本。例如,他们必须支付燃料费。因此,带乘客去很远的地方可能会导致更高的票价,但这也意味着更大的燃料消耗和时间损失。此外,从那个遥远的地方找到乘客去市中心的某个地方可能不是那么容易的,因此没有乘客的情况下开车回来可能是昂贵的。解释这一点的一种方法是通过费用金额和行程距离之间的比率的平均值对热图进行颜色编码。让我们考虑这两种方法:

Heatmaps of NYC colour-coded by: average fare amount (left), and average ratio of fare amount over trip distance.
在天真的情况下,当我们只关心获得所提供服务的最高票价时,搭载乘客的最佳区域是纽约机场,以及沿主要道路,如范威克高速公路和长岛高速公路。当我们考虑到旅行的距离,我们得到一个稍微不同的画面。Van Wyck 高速公路和长岛高速公路以及机场仍然是搭载乘客的好地方,但是它们在地图上已经不那么突出了。然而,一些新的亮点出现在哈得逊河的西侧,看起来非常有利可图。
当出租车司机可能是一份相当灵活的工作。为了更好地利用这种灵活性,除了应该潜伏在哪里之外,知道什么时候开车最有利可图也是有用的。为了回答这个问题,让我们制作一个图表,显示每天和一天中的每个小时的平均费用与行程距离的比率:

The mean ratio of fare over trip distance per day of week and hour of day.
上面的数字是有道理的:最好的收入发生在一周工作日的高峰时间,尤其是中午前后。作为出租车司机,我们收入的一小部分给了出租车公司,所以我们可能会对哪一天、什么时间顾客给的小费最多感兴趣。让我们绘制一个类似的图,这次显示的是平均小费百分比:

The mean tip percentage per day of week and hour of day.
上面的情节很有意思。它告诉我们,乘客在早上 7-10 点之间给出租车司机的小费最多,在一周的前几天晚上也是如此。如果你在凌晨 3 点或 4 点接乘客,不要指望得到大笔小费。结合上两个图的观点,一个好的工作时间是早上 8-10 点:一个人将会得到每英里不错的票价和不错的小费。
加速你的引擎!
在本文的前面部分,我们简要关注了 trip_distance 列,在清除异常值的同时,我们保留了所有低于 100 英里的行程。这仍然是一个相当大的临界值,特别是考虑到黄色出租车公司主要在曼哈顿运营。 trip_distance 列描述了出租车在上车地点和下车地点之间行驶的距离。然而,人们通常可以在两个确切的上下车地点之间选择不同距离的不同路线,例如为了避免交通堵塞或道路施工。因此,作为 trip_distance 列的对应项,让我们计算一个接送位置之间的最短可能距离,我们称之为 arc_distance:

For complicated expressions written in numpy, vaex can use just-in-time compilation with the help of Numba, Pythran or even CUDA (if you have a NVIDIA GPU) to greatly speed up your computations.
用于计算 arc_distance 的公式非常复杂,它包含了大量的三角学和算术,并且计算量很大,尤其是当我们处理大型数据集时。如果表达式或函数仅使用 Numpy 包中的 Python 操作和方法编写,Vaex 将使用您机器的所有内核并行计算它。除此之外,Vaex 还支持通过 Numba (使用 LLVM)或py tran(通过 C++加速)进行实时编译,从而提供更好的性能。如果你碰巧有 NVIDIA 显卡,你可以通过jit_cuda方法使用 CUDA 来获得更快的性能。
无论如何,让我们画出行程距离和弧距离:的分布

Left: comparison between trip_distance and arc_distance. Right: the distribution of trip_distance for arc_distance<100 meters.
有趣的是,弧距从未超过 21 英里,但出租车实际行驶的距离可能是它的 5 倍。事实上,上百万次出租车旅行的下车地点都在上车地点 100 米(0.06 英里)以内!
多年来的黄色出租车
我们今天使用的数据集跨越了 7 年。有趣的是,我们可以看到一些兴趣是如何随着时间的推移而演变的。借助 Vaex,我们可以执行快速的核外分组和聚合操作。让我们来看看票价和旅行距离在这 7 年中是如何演变的:

A group-by operation with 8 aggregations for a Vaex DataFrame with over 1 billion samples takes less than 2 minutes on laptop with a quad-core processor.
在上面的单元块中,我们执行了一个 group-by 操作,然后是 8 个聚合,其中 2 个聚合在虚拟列上。上面的单元块在我的笔记本电脑上运行了不到 2 分钟。考虑到我们使用的数据包含超过 10 亿个样本,这是相当令人印象深刻的。不管怎样,让我们看看结果。以下是多年来出租车费用的变化情况:

The average fare and total amounts, as well as the tip percentage paid by the passengers per year.
我们看到出租车费和小费随着时间的推移而增加。现在让我们看看出租车行驶的平均行程距离和弧距与年份的关系:

The mean trip and arc distances the taxis travelled per year.
上图显示,行程距离和弧线距离都有小幅增加,这意味着,平均而言,人们倾向于每年旅行更远一点。
给我看看钱
在我们的旅行结束之前,让我们再停一站,调查一下乘客是如何支付乘车费用的。数据集包含 payment_type 列,所以让我们看看它包含的值:

从数据集文档中,我们可以看到该列只有 6 个有效条目:
- 1 =信用卡支付
- 2 =现金支付
- 3 =不收费
- 4 =争议
- 5 =未知
- 6 =无效行程
因此,我们可以简单地将 payment_type 列中的条目映射到整数:

现在,我们可以根据每年的数据分组,看看纽约人在出租车支付方面的习惯是如何变化的:

Payment method per year
我们看到,随着时间的推移,信用卡支付慢慢变得比现金支付更加频繁。我们真正生活在一个数字时代!注意,在上面的代码块中,一旦我们聚合了数据,小的 Vaex 数据帧可以很容易地转换成 Pandas 数据帧,我们可以方便地将其传递给 Seaborn 。我不想在这里重新发明轮子。
最后,让我们通过绘制现金与卡支付次数之间的比率来看看支付方式是取决于一天中的时间还是一周中的某一天。为此,我们将首先创建一个过滤器,仅选择由现金或卡支付的乘车费用。下一步是我最喜欢的 Vaex 特性之一:带有选择的聚合。其他库要求对每种支付方式的单独过滤的数据帧进行聚合,然后合并成一种支付方式。另一方面,使用 Vaex,我们可以通过在聚合函数中提供选择来一步完成。这非常方便,只需要一次数据传递,从而为我们提供了更好的性能。之后,我们可以用标准方式绘制结果数据帧:

The fraction of cash to card payments for a given time and day of week.
看上面的图,我们可以注意到一个类似的模式,显示了小费百分比作为一周中的某一天和一天中的某个时间的函数。从这两个图中,数据表明刷卡的乘客比现金支付的乘客倾向于给更多的小费。为了查明这是否确实是真的,我想邀请你去尝试并弄清楚它,因为现在你已经有了知识、工具和数据!你也可以看看这个 Jupyter 笔记本来获得一些额外的提示。
我们到达了你的目的地
我希望这篇文章是对 Vaex 的一个有用的介绍,并且它将帮助您减轻您可能面临的一些“令人不舒服的数据”问题,至少在表格数据集方面。如果您有兴趣探索本文中使用的数据集,可以直接从 S3 使用 Vaex。参见完整版 Jupyter 笔记本了解如何做到这一点。
有了 Vaex,人们可以在几秒钟内,在自己舒适的笔记本电脑上浏览 10 亿多行数据,计算各种统计数据、汇总数据,并生成信息丰富的图表。它是免费和开源的,我希望你能尝试一下!
数据科学快乐!
本文中介绍的探索性数据分析基于由 Maarten Breddels 创建的早期 Vaex 演示。
请查看下面我们来自 PyData London 2019 的现场演示:
如何用 python 分析 A/B 测试结果?
这是书中的一个数据挑战案例: 《数据科学带回家的挑战集锦》。 数据集可以在上面的网站购买,本文只讲解决方案和 python 技巧。所有代码都在我的 Github 上。

1.实验概述
XYZ 公司是一个全球性的电子商务网站,提供网站的本地化版本。XYZ 的一位数据科学家注意到,西班牙用户的转化率比任何其他西班牙语国家都高。
他们认为一个原因可能是翻译。所有说西班牙语的国家都有一个西班牙人写的网站的相同翻译。他们同意尝试一个测试,每个国家都有一个由本地人写的翻译。
然而,在他们进行测试后,他们真的很惊讶,因为测试是阴性的。也就是说,似乎非本地化翻译做得更好!
试验性变更:非本地化到本地化翻译
2.数据分析
看看这个数据框。
我们有 12 列,分别是“用户标识”、“日期”、“来源”、“设备”、“浏览器语言”、“广告频道”、“浏览器”、“转换”、“测试”、“性别”、“年龄”、“国家”。
所有来自西班牙的数据都在对照组。

data overview
1)确认测试实际上是阴性的。
首先,我们需要证明,在对照组中,西班牙在变革前的表现优于其他国家。
groupby_country = data[data['test'] == 0][['conversion', 'country']].groupby('country').mean()
groupby_country = groupby_country.reset_index()
groupby_country = groupby_country.sort_values('conversion', ascending = **False** )
*# Visualization*
fig, ax = plt.subplots(figsize=(18, 6))
sns.barplot(x='country', y='conversion', data=groupby_country, ax=ax)
plt.show()

然后,我们需要确认非本地化翻译表现更好的实验结果,或者可以说,在除西班牙以外的国家,控制组比测试组做得更好
*# Visualization* fig, ax = plt.subplots(figsize=(18, 6))
sns.barplot(x=’country’, y=’conversion’, hue=’test’, data=data, ax=ax)
plt.show()

并用统计学方法来证明。
*# A/B test*
test_data = data[data['country'] != 'Spain']
test_val = test_data[test_data['test'] == 1]['conversion'].values
cont_val = test_data[test_data['test'] == 0]['conversion'].values*# Welch Two Sample t-test*
print(ttest_ind(test_val, cont_val, equal_var=**False**))
ttest _ indResult(statistic =-7.3939374121344,pvalue=1.42829947540 e-13)
绝对正确。
然而,我们可以看到,测试组的平均转化率为 0.0434,对照组为 0.0483,下降 10%,如果这是真的,那将是惊人的。所以我们需要深入研究。
2)解释为什么会发生这种情况。本地化的翻译真的很差吗?
很可能,由于某种原因,一些用户更有可能进入测试或控制阶段,这部分用户的转化率明显高于/低于测试或控制阶段,这影响了整体结果。
只看西班牙以外国家的数据:(Github 上更多图表)
- 日期

- sourse

- 设备

- 语言

- 国家

我们可以看到,除了国家,所有测试组在其他细分领域的表现都比较差。所以仔细看看这个国家。
在理想的情况下,每个部分的测试和控制人员的分布应该是相同的。因此,我们可以使用决策树来测试随机化是否有效,其中变量是用户维度,结果变量是用户是在测试中还是在控制中。
**import** **h2o**
**from** **h2o.frame** **import** H2OFrame
**from** **h2o.estimators** **import** H2OGradientBoostingEstimatorh2o.init()
h2o.remove_all()
h2o_df = H2OFrame(data)
h2o_df['test'] = h2o_df['test'].asfactor()
h2o_df['ads_channel'] = h2o_df['ads_channel'].asfactor()
h2o_df.summary()feature = ['user_id', 'date', 'source', 'device', 'browser_language',
'ads_channel', 'browser', 'sex', 'age',
'country']
target = 'test'*# Build random forest model*
model = H2OGradientBoostingEstimator(ntrees = 2, max_depth = 2)
model.train(x=feature, y=target, training_frame=h2o_df)print(model)

data.groupby(['country','test']).size()=====================================country test
Argentina 0 9356
1 37377
Bolivia 0 5550
1 5574
Chile 0 9853
1 9884
Colombia 0 27088
1 26972
Costa Rica 0 2660
1 2649
Ecuador 0 8036
1 7859
El Salvador 0 4108
1 4067
Guatemala 0 7622
1 7503
Honduras 0 4361
1 4207
Mexico 0 64209
1 64275
Nicaragua 0 3419
1 3304
Panama 0 1966
1 1985
Paraguay 0 3650
1 3697
Peru 0 16869
1 16797
Uruguay 0 415
1 3719
Venezuela 0 16149
1 15905
missing 0 245
1 209
dtype: int64
阿根廷和乌拉圭加起来有 80%的测试和 20%的控制!随机化在这两个国家并不成功。
让我们在控制国家之后检查测试结果。
countries = [name **for** name **in** data['country'].unique() **if** name **is** **not** np.nan]
**for** country **in** countries:
test_val = data[(data['country'] == country) & (data['test'] == 1)]['conversion'].values
cont_val = data[(data['country'] == country) & (data['test'] == 0)]['conversion'].values
test_mean = test_val.mean()
cont_mean = cont_val.mean()
p_val = ttest_ind(test_val, cont_val, equal_var=**False**).pvalue
print('**{0:15s}** **{1:15.5f}** **{2:15.5f}** **{3:10f}**'.format(country, test_mean, cont_mean, p_val))

在我们对国家进行控制后,检验显然显得不显著。考虑到目标是提高转化率,这并不是一个很大的成功,但至少我们知道本地化的翻译没有让事情变得更糟!
如何分析分层随机抽样数据
使用实验设计来增加你的分析能力

Rock stratification is a topic for a different day. Credit: https://en.wikipedia.org/wiki/Stratigraphy
当构建一个实验时,要问的最重要的问题之一是:我应该如何从我的总体中取样?很明显,你想进行某种随机抽样程序,但是如何进行随机抽样会对你的分析产生很大的影响。虽然有许多关于如何进行分层随机抽样的有用指南,但我注意到,关于如何正确分析分层抽样数据的指南很少。在这篇文章中,我将讨论如何进行分层抽样,以及如何使用一些模拟数据作为例子来分析结果数据。
设计实验
首先,我想简要回顾一下分层抽样以及它的重要性。假设我是 X 公司的数据科学家。X 公司拥有来自美国各地的大约 500,000 名用户。我们的大多数用户生活在城市,但也有很大一部分生活在小城镇。我有兴趣做一个实验,看看改变我们的应用程序的用户界面会如何改变从应用程序到二级网站的点击率。一个非常简单的 A/B 测试。假设我有相关的权限和足够匿名的数据,我应该如何选择这个实验的用户?
我有两个选择:1)我可以从用户群中随机抽样,或者 2)我可以对我的用户中的两个子群(城市和城镇)进行分层抽样。如果我想使用分层抽样,我会从每个亚组中随机抽取样本,并把其中的一半分配给 A 组或 B 组。
但是我为什么要这么做呢?在这种情况下,如果我认为亚组之间存在真正的差异,我会分层。例如,也许“我的城市”子组的基线点击率高于“城镇”子组。另一种可能性是,治疗 B 的效应可能会因城市和城镇而异。也许城市里的人和城镇里的人有不同的审美观,而且真的喜欢 B 处理,导致 B 处理对点击率有更强的影响。在这种情况下,我不会讨论这种可能性,但在其他情况下,这可能很重要。
在这篇文章中,我将模拟一个用户群,并用一个假设的反应进行一个实验。首先使用完全随机抽样(又名简单随机抽样),然后使用分层随机抽样。然后,我将检查我对实验的推断在两种取样方式之间是如何变化的。这两个亚组的基线点击率有很大不同,但每组的治疗效果是相同的。
构造数据
我将使用 pandas、numpy、scipy 和 statsmodels 进行分析。你可以用 sklearn 代替 statsmodels 来做这些,但是我更喜欢 statsmodels 的统计输出。
我需要做的第一件事是建立一个用户群。
首先,为了可再现性,我为 numpy 设置了一个随机种子,用于它的随机选择算法。人口数据帧中的每一行代表一个唯一的用户。我的用户群有 50 万人,来自城市的人比来自城镇的人丰富 15 倍。在模拟数据集中,城市和城镇的人口比例并不完全是 15:1,因为我使用的是随机过程:
city 468520
town 31480
由于来自 R 背景,我还在这个数据帧中包含了一个 id 列。Pandas 通常用它的索引功能来解决这个问题,但是当我从一个群体中取样时,我喜欢有一个不变的 id 号。
随机抽样实验
对于这个实验,我感兴趣的是在实现一个改变后,用户点击应用的概率是否会增加。例如,为了增加流量,X 公司可能想改变一个指向合作伙伴网站的按钮。
在第一种情况下,我将从整体人口中随机抽样,不考虑城镇和城市之间的差异。
在上面的代码中,我设置了每次治疗 500 个用户的样本量(总共 1000 个用户)。然后,我从所有用户中抽取 1000 个样本,并基于这些样本创建一个新的数据框架。理想情况下,您应该使用功效分析来决定样本大小。但是我会在文章的最后回到这个话题。
下一步是分配治疗方案。为了让事情变得简单,我创建了一个函数,它可以对完全随机抽样和分层随机抽样都这样做。
在这个过程的最后,我们得到了一个类似这样的数据帧:

我已经为分配的治疗添加了一列,也为每个虚拟变量添加了一列。虚拟变量列将使合成响应变量更容易。
每个城市类别中有多少被分配到每个治疗?

我们马上就能看到一些担忧。相对于城市类别,城镇类别的样本非常少(正如我们根据它们在人口中的丰富程度所预期的)。更重要的是,处理 B 中的城镇个体几乎是处理 a 中的两倍。如果城镇个体与城市个体非常不同,这可能是一个真正的问题。(提示:这里会是个问题。)
随机抽样分析
为了计算预期的信号,我需要指定基线点击率以及界面变化产生的提升。对于这个例子,我假设城市用户的基线点进概率为 0.3,而城镇用户的基线点进概率为 0.1。然后,我假设 B 组中的用户的点击概率会增加 0.05 个百分点。它有点大,但是在这个玩具例子中很有用。
为了创建响应数据,我根据我在上一段中列出的概率,从每个组的二项分布中取样。
要分解上面代码块中发生的事情,从 np.random.binomial()函数开始。我从二项分布中抽样 500 次,每次只有一次试验,其中成功的概率是我刚才列出的概率中的任何一个(0.3,0.1,或者其他两个加上额外的 0.05)。这就是虚拟变量派上用场的地方。请记住,只有当用户来自某个城市时,city 列才为 1,其他地方都为 0,对于 A、B 和 town 列也是如此。这意味着我们可以将四个二项式响应变量中的每一个乘以它们各自的虚拟变量,然后将所有 4 列相加,得到一个响应变量列。这个过程类似于一般线性回归模型用来分析分类数据的过程。
从这里我们可以很容易地进行 t 检验,看看我们的治疗是否有效果。
responseA = completerandom_df['response'][completerandom_df['A']==1]
responseB = completerandom_df['response'][completerandom_df['B']==1]stats.ttest_ind(responseA, responseB)
运行这段代码得到的 t 统计值为-0.90,p 值为 0.37。不太好。如果我们把数据绘制成图表,我们就能了解正在发生的事情。

分层抽样实验&分析
现在,我们不进行简单的随机抽样,而是使用分层随机抽样,看看分析结果如何变化。
那么我们如何进行分层随机抽样呢?结果这和最初的完全随机抽样非常相似。
步骤如下:
- 定义要从中取样的子群体
- 从每个亚群中进行完全随机抽样
我做这个实验的方法是创建 k 个指数列表,每个指数代表一个我想要取样的亚群。然后,我将它们连接成一个长列表,并使用新的索引列表从原始群体中提取数据。我喜欢这样做,这样我可以跟踪数据帧是如何构建的,但是可能有更有效的解决方案。
现在,我用和上面一样的方法计算响应变量,然后运行
t 检验的代码保持不变:
responseA = stratified_df['response'][stratified_df['A']==1]
responseB = stratified_df['response'][stratified_df['B']==1]stats.ttest_ind(responseA, responseB)
这里的输出是 t 值 2.55 和 p 值 0.011。比原来的完全随机抽样制度好得多。
我可以再次对这些数据进行 t 检验,就像我上面做的那样。然而,现在我已经确保从两个亚群中取样,我可以使用 ANOVA 来解释一些差异并增强信号。
但是,当我们使用子群体的额外信息并对数据进行双向方差分析时,会发生什么呢?
model = ols('response ~ treatment + cities', data = stratified_df).fit()
aov_table = anova_lm(model, typ=1)
print(aov_table) df sum_sq mean_sq F PR(>F)
treatment 1 1.16 1.16 6.89 0.0090
town_size 1 10.82 10.82 64.47 2.75e-15
Residual 997 167.27 0.17 NaN NaN
双向方差分析是估计每个变量(治疗和反应)对反应总误差的贡献。您可以在表的第二列的 sum_sq 项中看到这个输出。基于此,看起来城市变量比治疗变量多贡献了大约 9.4 倍的方差,这基于我如何构建响应变量是有意义的。此外,在这种情况下,我没有获得比传统 t 检验低得多的治疗效果 p 值。那主要是因为两个城市治疗的效果是一样的。当亚组之间的治疗效果相同时,双向方差分析是否优于简单的 t 检验取决于采样数据的确切分布。
如果我们看看这个图,我们就能明白为什么方差分析表现得如此之好。

因为我们使用分层随机抽样增加了我们的分析能力,我们的初始样本量计算在分层随机抽样和完全随机抽样程序之间是不同的。我不会在这里深入探讨这个问题,但从本质上讲,当我们从完全随机抽样转向分层随机抽样时,我们对每个总体方差的估计会发生变化。
结论
这篇文章主要有两点。首先,考虑进行分层随机抽样时,信号可能是非常不同的亚群。第二,当你使用分层随机抽样进行实验时,使用一种可以考虑分类变量的分析方法。
总的来说,分层随机抽样增加了你的分析能力。在最初的完全随机抽样实验中,A/B 测试的信号被未解释的城镇亚人群引入的额外变异所稀释。一旦我考虑了这个亚群,那么 A/B 测试的信号就变得清晰了。
我希望这有助于你的分层随机抽样需求!我已经将我进行分析的 Jupyter 笔记本和一个类似的 R 脚本添加到我的 GitHub 库中。以下是进一步阅读 ANOVAs 和分层随机抽样的一些链接:
- 网上有许多文章介绍了不同类型的采样方法。看这里,这里这里,或者这里。
- 宾夕法尼亚州立大学的这门课程深入研究了分层随机抽样的统计学。
- 如何在 R 和 Python 中对虹膜数据集进行方差分析的示例。
- 如何使用传统的方法和模拟数据进行功率分析。
如何使用 Python 分析调查数据
如何使用 Python 读取 SPSS/SAV 数据,使用权重并执行典型的 SPSS 命令作为频率和交叉表

如果你从事市场调研,你可能还需要处理调查数据。通常这些都是 SAV 或 SPSS 文件。SPSS 对于调查数据的统计分析非常有用,因为变量、变量标签、值和值标签都集成在一个数据集中。使用 SPSS,分类变量易于分析:

不幸的是,SPSS 在处理较大的数据集时速度较慢,自动化的宏系统不够直观,与 Python 相比提供的选项很少。因此,我将向您展示如何使用 Python 分析调查数据。
设置
首先,我们安装pyreadstat模块,它允许我们将 SPSS 文件作为数据帧pip install pyreadstat导入。如果您想手动安装它,您可以从这里下载软件包:
将 SAS、SPSS 和 Stata 文件读写到 pandas 数据帧中。
pypi.org](https://pypi.org/project/pyreadstat/)
读取数据
现在,我们将模块导入 Jupyter 笔记本并加载数据集:
import numpy as np
import pandas as pd
import pyreadstatdf, meta = pyreadstat.read_sav('...path\\Surveydata.sav')
df.head(5)
让我们看一下数据框:

Our DataFrame
我们不能从中读出太多,因为我们不知道变量和数字信息意味着什么。元容器包括所有其他数据,如标签和值标签。用meta.column_labels我们可以打印变量标签:

对于列Sat_overall,匹配的标签是“您的总体满意度如何?”。通过几个变量,你可以很容易地从列表中分配它。如果我们有数百个变量,整个事情会很混乱。因此,我们首先创建一个字典,以便在必要时可以有选择地显示某一列的正确标签。
meta_dict = dict(zip(meta.column_names, meta.column_labels))
有了meta_dict['Sat_overall'],我们现在得到了匹配的标签。
未加权数据
在调查中,我们通常对选择特定答案类别的受访者的百分比感兴趣:
df['Age'].value_counts(normalize=True).sort_index()

从输出中,我们只能看到 29%的人投票支持类别 1,33%的人支持类别 2,几乎 38%的人支持类别 3。然而,在字典meta.value_labels中,我们有所有的值标签:
df['Age'].map(meta.variable_value_labels['Age']).value_counts(normalize=True)

这样看起来更好!38%的受访者超过 50 岁,33%在 30 至 50 岁之间,其余的在 30 岁以下。我个人更喜欢按照价值标签的顺序排序。目前,这些值只是按比例大小排序:
df['Age'].map(meta.variable_value_labels['Age']).value_counts(normalize=True).loc[meta.variable_value_labels['Age'].values()]

完美!这就是我们所需要的,结果与 SPSS“频率”的输出非常匹配。通常,调查数据是根据社会人口特征进行评估的。例如,满意度如何因年龄组而异?为此,我们可以简单地使用交叉表函数:
pd.crosstab(df['Sat_overall'], df['Age'], dropna=True, normalize='columns')

同样,我们不能对输出做太多,所以让我们首先映射值标签:
pd.crosstab(df['Sat_overall'].\
map(meta.variable_value_labels['Sat_overall']), \
df['Age'].map(meta.variable_value_labels['Age']), \
dropna=True, normalize='columns'). \
loc[meta.variable_value_labels['Sat_overall'].values()]. \
loc[:,meta.variable_value_labels['Age'].values()]*100

现在,我们能够解释输出。对于 50 岁以上的人,有最完全满意的顾客。相比之下,30 岁以下的顾客最不满意。使用.loc功能,我们可以再次在此指定顺序。
加权数据
在调查中,事后通常会发现社会人口特征的分布与客户群的分布并不一致。一开始我们看到三个组几乎是平均分布的。然而,我们知道 50%的顾客年龄在 30 岁以下,25%在 30 到 50 岁之间,其余的在 50 岁以上。因此,我们对数据进行加权以反映这种分布:
weight = np.NaN
df.loc[(df['Age'] == 1), 'weight'] = 0.5/(67/230)
df.loc[(df['Age'] == 2), 'weight'] = 0.25/(76/230)
df.loc[(df['Age'] == 3), 'weight'] = 0.25/(87/230)
但是我们现在如何在计算中考虑这个重量呢?对于频率分布,我们编写一个小的辅助函数:
def weighted_frequency(x,y):
a = pd.Series(df[[x,y]].groupby(x).sum()[y])/df[y].sum()
b = a.index.map(meta.variable_value_labels[x])
c = a.values
df_temp = pd.DataFrame({'Labels': b, 'Frequency': c})
return df_temp
因此,我们得到一个数据帧,其中包含相应的标签(按照从小到大的数字顺序)和相应的百分比频率:
weighted_frequency('Age','weight')

加权分布现在符合我们的客户结构。让我们再来看看满意度分布:
weighted_frequency('Sat_overall','weight')

例如,我们看到在加权分布中,更多的客户不满意。如果我们没有加权,我们会低估我们客户群中的奇怪之处。通过交叉表,可以轻松整合权重:
pd.crosstab(df['Sat_overall']. \
map(meta.variable_value_labels['Sat_overall']), \
df['Age'].map(meta.variable_value_labels['Age']),
df.weight, aggfunc = sum, dropna=True, \
normalize='columns'). \
loc[meta.variable_value_labels['Sat_overall'].values()]. \
loc[:,meta.variable_value_labels['Age'].values()]*100

我们所要做的就是添加权重参数(例如df.weight)和函数参数aggfunc=sum。在本例中,加权分布对应于未加权分布,因为组内病例的比率没有变化。
结论
第一步,我们安装了pyreadstat,一个我们可以将 sav 文件读入 Python 并进一步处理它们的模块。之后,我们看了标签和价值标签是如何分配的,以及分析是如何以一种易于理解的方式呈现的。我们看到 Python 很好地处理了分类数据,并且易于使用。
开源代码库
资料馆:
https://github.com/bd317/surveydata_with_python
笔记本:
https://Github . com/BD 317/Survey Data _ with _ python/blob/master/Github _ Survey _ Data _ upload . ipynb
SPSS-Dataset:
https://Github . com/BD 317/Survey Data _ with _ python/blob/master/Survey Data . sav
如果您喜欢中级和高级数据科学,并且还没有注册,请随时使用我的推荐链接加入社区。
在特定领域应用 BERT 的几个例子
在特定领域中应用 BERT

Photo by Kendal James on Unsplash
2018 年发布了几个新的预训练的情境化嵌入。新的最先进的结果每个月都在变化。伯特是著名的模特之一。在这个故事中,我们将扩展 BERT 来看看我们如何在不同领域问题上应用 BERT。
艾伦人工智能研究所(AI2)对 BERT 进行了进一步研究,并发布了基于 BERT 的 SciBERT,以解决科学数据上的性能问题。它使用来自 BERT 的预训练模型,并通过使用科学出版物(其中 18%的论文来自计算机科学领域,82%来自广泛的生物医学领域)来微调上下文化嵌入。另一方面,Lee 等人从事生物医学领域的工作。他们还注意到,通用的预训练 NLP 模型在特定领域数据中可能不会很好地工作。因此,他们将 BERT 微调为 BioBERT,在生物医学的 NER、关系抽取和问答 NLP 任务中有 0.51% ~ 9.61%的绝对提升。
这个故事将讨论关于 SCIBERT:科学文本的预训练语境化嵌入 (Beltagy 等人,2019), BioBERT:生物医学文本挖掘的预训练生物医学语言表示模型 (Lee 等人,2019)。将涵盖以下内容:
- 数据
- 体系结构
- 实验
数据
SciBERT 和 BioBERT 还为预训练引入了特定领域的数据。Beltag 等人使用从语义学者中随机挑选 1.14M 的论文来微调 BERT 并构建 SciBERT。语料库包括 18%的计算机科学领域的论文和 82%的广义生物医学领域的论文。另一方面,Lee 等人使用 BERT 的原始训练数据来微调 BioBERT 模型,这些数据包括英语维基百科和图书语料库以及领域特定数据,即 PubMed 摘要和 PMC 全文文章。

Training data among models
一些变化被应用在科技文章中以获得成功。ScispaCy 作为 spaCy 的科学专用版本,用于将文档拆分成句子。之后,Beltagy 等人使用 SentencePiece 库为 SciBERT 构建新的单词表,而不是使用 BERT 的词汇表。

Different tokenization method among models.
体系结构
SciBERT 和 BioBERT 都遵循 BERT 模型架构,该架构是多双向转换器,并通过预测屏蔽令牌和下一句来学习文本表示。标记序列将被转换成标记嵌入、分段嵌入和位置嵌入。标记嵌入指的是语境化的单词嵌入,片段嵌入只包括 2 个嵌入,它们或者是 0 或者是 1 来表示第一个句子和第二个句子,位置嵌入存储相对于序列的标记位置。你可以访问这个故事来了解更多关于伯特的事情。

BioBERT Architecture (Lee et al., 2019)
实验
科学伯特(SciBERT)
命名实体识别(NER)和参与者干预比较结果提取(PICO)都是序列标记。依存句法分析(DEP)是预测句子中标记之间的依存关系。分类(CLS)和关系分类(REL)是分类任务。

Evaluation dataset (Beltagy et al., 2019)

Evaluation result among different dataset (Beltagy et al., 2019)
生物医学伯特
从下表中,你可以注意到 BioBERT 在特定领域数据集上的表现优于 BERT。

Comparison between BERT and BioBERT on relation extraction dataset (Lee et al., 2019)

Comparison between BERT and BioBERT on question answering dataset (Lee et al., 2019)
拿走
- 通用的预训练模型在特定领域可能无法达到最先进的结果。因此,需要微调步长来提高目标数据集的性能。
- 在伯特和伯特的基础模型之后,Transformer(多重自我关注)变得越来越有名。我还注意到,BERT 的基本模型保持了最先进的性能。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。欢迎在 LinkedIn 上与我联系,或者在 Medium 或 Github 上关注我。
延伸阅读
- 变压器的双向编码器表示(BERT)
- 西伯特 GIT 回购
- BioBERT GIT 回购【1】/【2】
参考
- 贝尔塔吉、科汉和罗。 SCIBERT:科学文本的预训练语境化嵌入。2019
- J.李,尹文伟,金圣贤,金圣贤,苏春河和姜俊杰。 BioBERT:用于生物医学文本挖掘的预训练生物医学语言表示模型。2019
如何将持续学习应用到你的机器学习模型中
通过持续学习提高模型准确性并增强性能
什么是持续学习?
学者和从业者都认为持续学习(CL)是迈向人工智能的基本步骤。持续学习是模型从数据流中持续学习的能力。在实践中,这意味着支持模型在新数据到来时自主学习和适应生产的能力。有些人可能称之为自适应学习或连续自动学习。CL 的想法是模仿人类在其一生中不断获取、调整和转移知识和技能的能力。如你所知,在机器学习中,目标是通过生产环境部署模型。通过持续学习,我们希望使用进入生产环境的数据,并根据新的活动重新训练模型。例如,我们都体验过网飞非常成功的“下一个”推荐系统。网飞推荐系统会在你的最后一集结束后直接推荐一个节目,通常随着时间的推移,你很难抗拒这种诱惑。这种生产模式需要定期重新培训,因为市场上有新电影、新口味和新趋势。通过不断学习,目标是使用输入的数据,并使用它来自动重新训练模型,这样您就可以真正获得高精度并保留高性能的模型。
为什么我们需要不断学习?
答案很简单,数据在不断变化。数据可能会因趋势或用户采取的不同行动而发生变化。例如,亚马逊 2000 年的畅销书是哈利波特。今天,你可能会惊讶地发现,畅销书是一个完全不同的类型:火与怒:特朗普白宫内部。

Why continual learning? Data is changing.
因此,亚马逊将不得不重新训练这种模式,并根据新的数据和趋势向客户推荐新书。更新一点的例子是巨幅下跌前的比特币价格。2017 年,比特币价值 19K 美元。大约一个半月后,降到了 6K 美元。
不仅数据在变化,而且研究人员已经表达了“终身学习仍然是机器学习和神经网络模型的一个长期挑战,因为从非平稳数据分布中不断获取增量可用信息通常会导致灾难性的遗忘或干扰。”持续学习的理由仍然很充分。对于数据科学家来说,持续学习将最终优化模型的准确性,提高模型性能,并通过使模型自适应来节省再培训时间。
不断学习的机器学习管道

Machine learning pipeline
上图展示了在应用持续学习的生产环境中,机器学习管道是什么样子的。你会注意到管道看起来很像任何其他机器学习管道。我们必须有数据,某种验证。这可能包括测试或内部基准,如确定数据质量。也可能是你操作的预处理。
接下来,即将推出的是 AutoML 。持续学习中的 AutoML 是流水线中非常重要的一部分,类似于典型机器学习流水线中的训练步骤。但是,我们将在后面详细讨论。
培训之后,您将做一些模型验证来测试模型,并确保它们都工作良好。在这里,您还可以选择最好的一个,并将其部署到生产环境中。到目前为止,这个管道看起来像一个经典的机器学习管道。为了应用持续学习,我们增加了监控并将循环连接回数据。

Machine learning with closed loop continual learning
将监视在模型部署区域收集的预测。监控完成后,您将清理数据并在需要时贴上标签。但是,对于像推荐系统或预测这样的东西,您将能够在没有人为标记的情况下关闭环路。在标记和清理数据之后,我们将把它移回数据,再次重复训练和验证过程。现在我们已经像飞轮一样闭合了回路。
持续学习管道中的 AutoML
AutoML 是应用持续学习的一个重要组成部分,因为我们处理的是持续不断的数据流。你可以保持简单,用相同的参数重新训练相同的算法,但因为我们仍然希望获得非常高的精度,我们将使用 AutoML。
AutoML 不一定是非常复杂的元学习。你可以只使用超参数优化、开源算法和框架——你会惊讶于它是多么简单。作为你研究的一部分,当你开始研究你的机器学习管道时,你必须选择你的算法空间。例如,如果你在做一个计算机视觉问题,你可能想用迁移学习作为训练算法。通过迁移学习,你有许多预先训练好的模型,你可以用它们来重新训练网络的最后一层,然后部署你的模型。
在这种情况下,你会选择一个流行的预建模型,如 VGG,盗梦空间,ResNet 和其他一些。对于每个模型,我们还必须指定其参数范围。
这可能会变成一个非常大的计算问题。作为一名数据科学家,你应该真正研究什么样的算法和参数对你的机器学习问题有用。
AutoML 链接: AutoKeras , Auto SciKitLearn ,特征工程的特征工具
追踪你的汽车
使用 AutoML,不仅要跟踪生产中的模型,而且要跟踪整个过程,这一点尤为重要。如果你让你的机器学习自动驾驶,你必须确保一切都被跟踪和管理。您需要跟踪一切:您使用的算法类型、超参数是什么、使用的计算类型、内存消耗、指标、准确性等等。假设你今天正在训练 60 个不同的实验。被跟踪的数据可能会在下周尝试重新部署和重新训练模型时使用。
你也可以使用这些信息进行元学习,试图了解什么样的算法对问题有效,这将使每次的实验次数最少。
自动化您的基础设施
关于 AutoML 的另一个关键问题——尤其是深度学习——是自动化你的机器学习基础设施。启动一个深度学习就绪的实例可能需要很多时间(想想 CUDA、依赖项、数据、代码等等)。我们建议在您所有首选的云提供商之上使用 Kubernetes。事实上,您将拥有一个 Kubernetes 集群并运行,这使得部署新的实验变得非常容易。使用 Kubernetes,您可以非常快速地启动许多实验,并跟踪它们以确保所有实验都运行良好。
但是请记住,维护 Kubernetes 集群并不那么简单,可能需要 IT/数据工程团队的额外帮助。
在持续学习管道中部署模型
一旦您训练并选择了具有最佳性能的模型,您的模型就可以部署了。持续学习的一个主要挑战是如何在不影响用户体验和保持高准确性的情况下将新模型部署到相同的环境中。
为持续学习部署模型与经典的模型部署有点不同。通常,即使是一个数据科学家也能够部署一个模型,但是因为这是自动化的,我们必须非常小心。正如您不会将一个有缺陷的软件部署到生产环境中一样,您也不会部署一个没有被成功训练和验证的模型。为了确保您的新模型运行良好,您将在部署之前和部署期间对旧数据进行测试。此外,您还需要监控系统的性能和健康状况。
现在,在软件开发中,有很多不同的方法来部署新软件。对于机器学习来说,这个领域仍然很新,但是我们推荐使用金丝雀部署技术。Canary 是一种引入新软件版本的技术,以某种方式影响部分用户,根据测试逐渐增加用户数量。使用这种技术将会逐渐将模型部署到更大的用户子集。
在实现层面——我们建议使用 Kubernetes 和 Istio 进行模型部署,这样您就可以进行 A/B 测试,并确保您的模型部署良好。我们的博客上还有一个关于如何使用 Kubernetes 部署机器学习模型的指南。
持续学习管道的监控
随着持续学习,监控是机器学习的一个特别重要的部分。您需要确保,如果您的模型发生了不好的事情,或者如果发送到您的模型的数据被破坏,您有一种机制可以得到警告。
最常见的情况是,一个数据科学家会同时管理几个机器学习管道。所以警报设置至关重要。一旦将新模型部署到生产环境中,目标就是为数据科学家或数据工程师提供监控机器学习模型所需的控制和透明度。为了能够自动部署模型的新版本,您必须监控输入数据,以检测数据漂移和异常。监测对于预测数据也很重要,以确保高性能和准确性。
除了 AlertManager 之外,Kubernetes 或 Prometheus 中也有很好的工具,可以用来监控所有的输入数据。你应该利用云服务和 Kubernetes 来自动化你的机器学习基础设施和实验。
触发并重新训练您的模型,以便继续学习
连续学习 ML 管道的最后一步是触发再训练并结束循环。您的 ML 渠道为持续学习做好了准备:
- 你有数据
- 实验正在进行训练
- 预测正在被收集和监控
- 正在清理新数据
接下来,您必须决定重新训练您的模型的触发器。有几种方法可以做到这一点。我们的客户会定期重新培训他们的模型。例如,对于推荐系统或广告,我们看到团队每 30 分钟重新培训一次。您也可以考虑只根据新的数据来重新训练模型。
其他方法是跟踪和监控模型衰减和模型偏差、低置信度以及生产环境中触发再训练的任何其他类型的警报。最重要的是,如果你自动触发了机器学习管道,你应该跟踪和验证触发器。不知道您的模型何时被重新训练会导致重大问题。您应该始终控制模型的再训练,即使这个过程是自动化的。这样,您就可以在生产环境中理解和调试模型。
关闭 ML 循环
一旦你的自动化、部署和监控系统到位,你就能完成机器学习的循环。您的模型将不断学习,并自动适应新的数据和趋势。不仅你的模型精度会自动提高,而且总体上你的模型在应用程序中的表现会更好。
如何申请数据科学工作
(或者任何技术类的工作,真的。)

剧透:让招聘人员或招聘经理的工作更容易。
我为什么要写这个?:我们(Data Eng & Data Science @ Kik)正在招聘全职员工和合作者。最近几个月,我审查了大约 600 份提交的简历中的 300 份(有几个职位空缺)。我想帮助你,我最后四行的忠实读者,避免愚蠢的错误。
你为什么会读这个?:如果你是因为在申请了 Kik 的一个职位后在谷歌上搜索了我,那么恭喜你,否则:
在过去十年里,我花了 1000 多个小时阅读简历和进行面试(写简历、准备和参加面试)。这些齿尖经过了现场测试。
步骤 1:简历
你得到了我 30 秒的注意力,有机会赢得 3 分钟。让我相信,在你所拥有的技能和经验与所需的技能和经验之间,至少有一部分是匹配的,我应该继续阅读。就像博客文章中折叠上方的文字一样。(就在这里结束 iianm。简历的第一部分应该是非常简短的声明,说明你是谁,你擅长什么,你想做什么。(见下面链接中的简历模板)
你应该在简历上花多少时间。
大多数从事技术行业的人每 3-5 年找一次工作。每隔几年花 15-20 个小时润色你的简历是没问题的。我说的不是“越来越擅长<技能 >”。我说的是修改描述你技能的文件。你将对格式进行微小的修改,将它发送给朋友进行校对和反馈,改变措辞以符合时态,确保时态、语法和标点符号是统一的。
会根据“关注细节”来评判你,关注细节。你申请的前 5 份工作应该受益于一个小时的调整你的简历,以确保你突出了与特定工作相关的经验和技能。
最重要的不要就是:不要掺水。
我怎么强调这一点都不为过。
你申请的是一份技术工作——“Microsoft Word&Google Docs”是掺水,是同义反复(毕竟我在看你打出来的简历)。
再次强调:不要用水稀释!
更多不要的,请看简历错误宾果。(根据真实故事改编)
如何合理地“充实”一份简历
如果你刚刚起步,你没有什么成就可以夸耀,可能会有几十个,有时几百个申请人申请同一个职位。
脱颖而出。 如果你有一个有趣的爱好,一些你引以为豪的事情,一些你致力于的事情,一些你赢得的东西,一个副业,志愿活动,组织,成就等等。-不要害羞。突出显示它们。
网络。 如果一个普通的熟人给我指出你的简历,你基本上已经通过了第一次筛选,恭喜你。更好地连接
变好。如果你有时间,希望你在你感兴趣的领域找一份工作,在那个领域做些事情。(Kaggle、开源项目、课程等。).关键建议是“演示完成”。没有"搞定,就不能拼成"聪明,漂亮,搞定****
不要忘记修改你的简历:
当你刚从学校毕业时,加入一堆卡格尔比赛,这很好。但是现在,几年过去了,你有了更多的工作经验;更新你的简历并不意味着仅仅添加最新的成就,也意味着删除旧的不那么令人印象深刻的东西。也许只保留排名最高的那一场 Kaggle 比赛。
如果你已经很久没有使用一门语言了,并且不想被问到,那么帮大家一个忙,把它从你的简历中删掉。(你中学学的法语也是一样)
去面试!
你可能认为一旦你得到了面试机会,简历就不重要了。这几乎是真的。它会绊倒你;例如,我可以问你一些新的特性,或者一些你已经有一段时间没有使用的语言 ******* 的幕后细节。
第 2 部分:准备和面试
这是一篇关于申请的博客,我附上了面试技巧,因为准备应该是申请不可或缺的一部分。
以前
准备面试就像准备考试一样。我面试过的应届毕业生的平均得分比业内资深人士的平均得分高很多。对此,我唯一的解释是,学生们在学习上更加紧跟时代。
如果你要参加白板面试,花 20 美元买一个小白板和记号笔(最好是细的),在上面练习。感觉不一样,你不想在压力下第一次做。(面试时带上记号笔会让你的白板空间翻倍,给面试官留下深刻印象。)
在 25–30 分钟内练习完全解决面试问题(见下文)。
聊天 有人说面试是你证明自己的机会。这只说对了一半。面试也是你了解自己是否喜欢这个职位的机会。对我面试时的精神状态最有帮助的建议是:
你可能会和面试你的人一起度过你的工作日,让他们让你相信他们很好,你们会相处得很好。让他们试着通过你的关卡。
技术问题。
确保你理解了问题,提出问题来澄清它,也许走过一个微小的例子。
然后— 开始。我不是说马上开始编码,不要那样做。在你编码之前解决问题,检查你的解决方案。然后,如果你被要求编写代码,就去做。抽象地解决问题表明你很聪明。
编码表明你把事情做好了。
用几个例子展示你的解决方案,表明你关注细节。
故障排除
倾听暗示。
面试官会给你提示。不要错过他们。接受暗示会让你更好地找到解决方案(并为你赢得“善于接受反馈”分)。面试官可能熟悉一些错误的解决方案,并希望引导你离开。或者他们可能在寻找特定的解决方案。
如果你被卡住了,接受提示。如果你认为你的解决方案很好,但是面试官的暗示导致了不同的解决方案,那么——这是一个艰难的情况。我个人倾向于候选人明确认识到这一点。嗯,看起来这和我正在尝试的不相容,你介意我在尝试你的建议之前再花 2-3 分钟在这个方向上吗
摆脱困境——放松、休息,然后重启
有时候人们会陷入困境。他们可能自己意识到了这一点(他们很幸运),或者被面试官推到了死胡同(压力很大)。许多人会说:“等一下,让我重新开始。”这太好了,除此之外,他们不会真的重新开始!!他们想着自己,想着自己把问题弄错了。
如果我把它做成卡通形式,它会是这样的:
野狼🦊正拿着锤子和炸弹🔨 💣,想象着💭他自己试图把炸弹锤进一个盒子里。🔨 💣 🎁这个盒子太小了。
然后是思想泡沫中的郊狼💭停止锤击 🛑🔨又抬眼,思考。💭和一个更小的思想泡泡💭💭与另一只小野狼一起出现🦊它内部命中了炸弹。这导致了第一只假想的郊狼🦊重新开始锤击🔨,这导致了真正的狡猾🦊重新开始愉快地敲打他的(真正的)炸弹💣。三只土狼都停下来,交换了一下眼神,然后看向镜头。所有炸弹都会爆炸。**
重启是最难的技能,尤其是在压力下。练习解决有时间压力的问题,学会摆脱困境。你能在面试中做到这一点会得到额外的加分。你可以这样做:你说“等一下,让我重新开始。”
然后你闭上眼睛,默默地😃)数 5 次呼吸。如果你觉得尴尬,3 也可以。不要想问题!(必要时边呼吸边数)。睁开你的眼睛,微笑,重述问题,然后真正重新开始。
总而言之:
不要浪费你或我的时间。保留有影响的语句,去掉其余的。也许写简历 V1 包括一切,然后找出什么是上面的栏“令人印象深刻”和修剪其余的。
脱颖而出,不要害羞。(但是不要在简历上做虚假承诺) 练习,然后再多练一些,然后在白板上带着时间压力练习。
结语+链接
有一些关于如何写简历和如何准备面试的令人惊讶的帖子,你也可以看看。史蒂夫·耶格关于简历的建议是永恒的。(除了关于纯文本的部分)。Lazlo Bock 关于简历的建议是最好的。
更有一些不要的在恢复错误宾果格式。(似曾相识)
下面是一份 元简历 。我已经用该文本的描述替换了该文本。为了每一件美好的事情,请在发送前替换掉元文本。
如何将机器学习和深度学习方法应用于音频分析
作者:Niko Laskaris,面向客户的数据科学家, Comet.ml
要查看本文末尾的代码、训练可视化和关于 python 示例的更多信息,请访问 Comet 项目页面。
介绍
虽然许多关于深度学习的写作和文献都涉及计算机视觉和自然语言处理(NLP) ,但音频分析——一个包括自动语音识别(ASR) 、数字信号处理以及音乐分类、标记和生成的领域——是深度学习应用的一个不断增长的子域。一些最受欢迎和最广泛的机器学习系统,虚拟助手 Alexa,Siri 和 Google Home,很大程度上是建立在可以从音频信号中提取信息的模型之上的产品。
我们在 Comet 的许多用户都在从事音频相关的机器学习任务,如音频分类、语音识别和语音合成,因此我们为他们构建了工具,使用 Comet 的元机器学习平台来分析、探索和理解音频数据。

使用 Comet 进行音频建模、训练和调试
这篇文章专注于展示数据科学家和人工智能从业者如何使用 Comet 在音频分析领域应用机器学习和深度学习方法。为了理解模型如何从数字音频信号中提取信息,我们将深入探讨一些用于音频分析的核心特征工程方法。然后,我们将使用 Librosa ,一个用于音频分析的伟大 python 库,来编写一个简短的 python 示例,在 UrbanSound8k 数据集上训练神经架构。
音频的机器学习:数字信号处理,滤波器组,梅尔频率倒谱系数
构建机器学习模型来分类、描述或生成音频通常涉及输入数据是音频样本的建模任务。

来自 UrbanSound8k 的音频数据集样本的示例波形
这些音频样本通常表示为时间序列,其中 y 轴度量是波形的幅度。振幅通常作为最初拾取音频的麦克风或接收器设备周围的压力变化的函数来测量。除非有与音频样本相关联的元数据,否则这些时间序列信号通常将是拟合模型的唯一输入数据。
查看下面的样本,这些样本取自 Urbansound8k 数据集中的 10 个类别中的每一个类别,从目测可以清楚地看出,波形本身可能不一定产生清晰的类别识别信息。考虑发动机怠速、汽笛和手提钻的波形,它们看起来非常相似。

事实证明,从音频波形(以及一般的数字信号)中提取的最佳特征之一自 20 世纪 80 年代以来一直存在,并且仍然是最先进的:梅尔频率倒谱系数(MFCCs),由 Davis 和 Mermelstein 于 1980 年提出。下面我们将从技术上讨论 MFCCs 是如何产生的,以及为什么它们在音频分析中有用。这部分有些技术性,所以在开始之前,我们先定义几个与数字信号处理和音频分析相关的关键术语。如果你想更深入地了解,我们将链接到维基百科和其他资源。
混乱但有用的术语

在信号处理中,采样是将连续信号缩减为一系列离散值。采样频率或速率是在一定时间内采集的样本数量。高采样频率导致较少的信息损失,但是计算费用较高,而低采样频率具有较高的信息损失,但是计算快速且便宜。
声波的振幅是其在一段时间(通常是时间)内变化的量度。振幅的另一个常见定义是变量极值之间的差值大小的函数。

傅立叶变换将时间函数(信号)分解成组成频率。同样,音乐和弦可以通过其组成音符的音量和频率来表达,函数的傅立叶变换显示了基础函数(信号)中每个频率的振幅(量)。

顶部:数字信号;下图:信号的傅立叶变换
傅立叶变换有多种变体,包括短时傅立叶变换,它在 Librosa 库中实现,涉及将音频信号分割成帧,然后对每帧进行傅立叶变换。一般来说,在音频处理中,傅立叶变换是将音频信号分解成其组成频率的一种优雅且有用的方式。
*资源:到目前为止,我找到的最好的傅立叶变换视频来自 3Blue1Brown *

在信号处理中,周期图是对信号频谱密度的估计。上面的周期图显示了大约 30Hz 和大约 50Hz 的两个正弦基函数的功率谱。傅立叶变换的输出可以被认为是(不完全)本质上的周期图。

时间序列的功率谱是一种将功率分布描述为组成该信号的离散频率分量的方式。一个信号的统计平均值,通过它的频率含量来测量,被称为它的频谱。数字信号的频谱密度描述了信号的频率成分。

梅尔标度是一种由听众判断彼此距离相等的音高标度。mel 标度和正常频率测量之间的参考点是通过将 1000 mels 的感知音调分配给 1000 Hz 来任意定义的。在大约 500 Hz 以上,越来越大的音程被听众判断为产生相等的音高增量。名称 mel 来自单词 melody,表示音阶基于音高比较。
将 f 赫兹转换成 m 英里的公式是:

倒谱是对信号的估计功率谱的对数进行傅立叶变换的结果。

Urbansound8k 数据集中音频样本的 Mel 频谱图
频谱图是信号频谱随时间变化的直观表示。考虑频谱图的一个好方法是将一些时间间隔数字信号的周期图叠加起来。
耳蜗内耳的螺旋腔,包含耳蜗器官,它对声音振动产生神经冲动。
音频预处理:数字信号处理技术
数据集预处理、特征提取和特征工程是我们从底层数据中提取信息的步骤,这些信息在机器学习上下文中应该对预测样本的类别或某些目标变量的值有用。在音频分析中,这个过程很大程度上是基于寻找音频信号的成分,这些成分可以帮助我们将其与其他信号区分开来。
如上所述,MFCCs 仍然是从音频样本中提取信息的现有技术工具。尽管 Librosa 之类的库为我们提供了一个 python 命令行程序来计算音频样本的 MFCCs,但底层的数学有点复杂,所以我们将一步一步地讲解它,并包含一些有用的链接以供进一步学习。
计算给定音频样本的 MFCCs 的步骤:
- 将信号分割成短帧(时间)
- 计算每帧功率谱的周期图估计
- 将 mel 滤波器组应用于功率谱,并对每个滤波器中的能量求和
- 对对数滤波器组能量进行离散余弦变换(DCT)
关于 MFCC 推导和计算的精彩附加阅读可以在博客文章这里和这里找到。
- 将信号分割成短帧
将音频信号分割成短帧是有用的,因为它允许我们将音频采样成离散的时间步长。我们假设在足够短的时间尺度上,音频信号不会改变。短帧持续时间的典型值在 20-40 毫秒之间。通常每帧重叠 10-15 毫秒。
注意,重叠的帧会使我们最终生成的特征高度相关。这就是为什么我们必须在最后进行离散余弦变换的基础。
2。计算每一帧的功率谱
一旦我们有了帧,我们需要计算每个帧的功率谱。时间序列的功率谱描述了组成该信号的频率分量的功率分布。根据傅立叶分析,任何物理信号都可以分解成许多离散的频率,或连续范围内的频谱。根据频率成分分析的特定信号的统计平均值称为其频谱。

我们将短时傅立叶变换应用于每一帧,以获得每一帧的功率谱。
3。将 mel 滤波器组应用于功率谱,并对每个滤波器的能量求和
一旦我们有了功率谱,我们还有一些工作要做。人的耳蜗不能很好地辨别附近的频率,并且这种影响只会随着频率的增加而变得更加明显。 mel-scale 是一种工具,它允许我们比线性频带更接近人类听觉系统的响应。

Source: Columbia
从上面的可视化中可以看出,mel 滤波器随着频率的增加而变宽,我们不太关心较高频率下的变化。在低频时,差异对人耳来说更明显,因此在我们的分析中更重要,滤波器较窄。
通过对我们的输入数据应用傅立叶变换得到的我们的功率谱的幅度,通过将它们与每个三角形 Mel 滤波器相关联而被装箱。通常应用该宁滨,使得每个系数乘以相应的滤波器增益,因此每个 Mel 滤波器保持代表该通道中频谱幅度的加权和。
一旦我们有了滤波器组能量,我们就取每个能量的对数。这是由人类听觉限制推动的另一个步骤:人类无法感知线性范围内的音量变化。要使声波的感知音量加倍,声波的能量必须增加 8 倍。如果一个声波已经是高音量(高能量),那么该波能量的巨大变化听起来不会有很大的不同。
4。对对数滤波器组能量进行离散余弦变换
因为我们的滤波器组能量是重叠的(见步骤 1),所以它们之间通常有很强的相关性。进行离散余弦变换有助于去相关能量。
对我们来说,值得庆幸的是, Librosa 的创建者已经抽象出了大量的这种数学,并使得为你的音频数据生成 MFCCs 变得很容易。让我们通过一个简单的 python 示例来展示这种分析的实际效果。
范例项目:Urbansound8k + Librosa
我们将为 UrbanSound8k 数据集拟合一个简单的神经网络(keras + tensorflow backend)。首先,让我们加载我们的依赖项,包括 numpy、pandas、keras、scikit-learn 和 librosa。
#### Dependencies ######## Import Comet for experiment tracking and visual tools
from comet_ml import Experiment
####import IPython.display as ipd
import numpy as np
import pandas as pd
import librosa
import matplotlib.pyplot as plt
from scipy.io import wavfile as wavfrom sklearn import metrics
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.optimizers import Adam
from keras.utils import to_categorical
首先,让我们创建一个 Comet 实验作为我们所有工作的包装。我们将能够捕获任何和所有工件(音频文件、可视化、模型、数据集、系统信息、培训指标等。)自动。
experiment = Experiment(api_key="API_KEY",
project_name="urbansound8k")
让我们加载数据集,并从数据集中为每个类获取一个样本。我们可以使用 Comet 从视觉和听觉上检查这些样本。
# Load dataset
df = pd.read_csv('UrbanSound8K/metadata/UrbanSound8K.csv')# Create a list of the class labels
labels = list(df['class'].unique())# Let's grab a single audio file from each class
files = dict()
for i in range(len(labels)):
tmp = df[df['class'] == labels[i]][:1].reset_index()
path = 'UrbanSound8K/audio/fold{}/{}'.format(tmp['fold'][0], tmp['slice_file_name'][0])
files[labels[i]] = path
我们可以使用 librosa 的 display.waveplot 函数查看每个样本的波形。
fig = plt.figure(figsize=(15,15))# Log graphic of waveforms to Comet
experiment.log_image('class_examples.png')
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i, label in enumerate(labels):
fn = files[label]
fig.add_subplot(5, 2, i+1)
plt.title(label)
data, sample_rate = librosa.load(fn)
librosa.display.waveplot(data, sr= sample_rate)
plt.savefig('class_examples.png')
我们将把这个图形保存到我们的彗星实验中。
# Log graphic of waveforms to Comet
experiment.log_image('class_examples.png')

接下来,我们将记录音频文件本身。
# Log audio files to Comet for debugging
for label in labels:
fn = files[label]
experiment.log_audio(fn, metadata = {'name': label})
一旦我们将样本记录到 Comet,我们就可以直接从 UI 中监听样本、检查元数据等等。

预处理
现在我们可以从数据中提取特征。我们将使用 librosa,但是我们也将展示另一个实用程序 scipy.io,用于比较和观察正在发生的一些隐式预处理。
fn = 'UrbanSound8K/audio/fold1/191431-9-0-66.wav'
librosa_audio, librosa_sample_rate = librosa.load(fn)
scipy_sample_rate, scipy_audio = wav.read(fn)print("Original sample rate: {}".format(scipy_sample_rate))
print("Librosa sample rate: {}".format(librosa_sample_rate))
原始采样率:48000
Librosa 采样率:22050
Librosa 的 load 函数会自动将采样率转换为 22.05 KHz。它还将归一化-1 和 1 之间的位深度。
print('Original audio file min~max range: {} to {}'.format(np.min(scipy_audio), np.max(scipy_audio)))print('Librosa audio file min~max range: {0:.2f} to {0:.2f}'.format(np.min(librosa_audio), np.max(librosa_audio)))
原始音频文件最小~最大范围:-1869 到 1665
自由音频文件最小~最大范围:-0.05 到-0.05
Librosa 还将音频信号从立体声转换为单声道。
plt.figure(figsize=(12, 4))
plt.plot(scipy_audio)
plt.savefig('original_audio.png')
experiment.log_image('original_audio.png')

原始音频(注意是立体声——两个音频源)
# Librosa: mono track
plt.figure(figsize=(12,4))
plt.plot(librosa_audio)
plt.savefig('librosa_audio.png')
experiment.log_image('librosa_audio.png')

Librosa 音频:转换为单声道
使用 Librosa 从音频中提取 MFCCs】
还记得我们之前为了理解梅尔频率倒谱系数而经历的所有数学运算吗?使用 Librosa,下面是如何从音频中提取它们(使用我们上面定义的 librosa_audio)
mfccs = librosa.feature.mfcc(y=librosa_audio, sr=librosa_sample_rate, n_mfcc = 40)
就是这样!
print(mfccs.shape)
(40, 173)
Librosa 计算了 173 帧音频样本的 40 个 MFCCs。
plt.figure(figsize=(8,8))
librosa.display.specshow(mfccs, sr=librosa_sample_rate, x_axis='time')
plt.savefig('MFCCs.png')
experiment.log_image('MFCCs.png')

我们将定义一个简单的函数来提取数据集中每个文件的 MFCCs。
def extract_features(file_name):audio, sample_rate = librosa.load(file_name, res_type='kaiser_fast')
mfccs = librosa.feature.mfcc(y=audio, sr=sample_rate, n_mfcc=40)
mfccs_processed = np.mean(mfccs.T,axis=0)
return mfccs_processed
现在我们来提取特征。
features = []# Iterate through each sound file and extract the features
for index, row in metadata.iterrows():file_name = os.path.join(os.path.abspath(fulldatasetpath),'fold'+str(row["fold"])+'/',str(row["slice_file_name"]))
class_label = row["class"]
data = extract_features(file_name)
features.append([data, class_label])# Convert into a Panda dataframe
featuresdf = pd.DataFrame(features, columns=['feature','class_label'])
我们现在有一个数据帧,其中每行有一个标签(类)和一个特征列,由 40 个 MFCCs 组成。
featuresdf.head()

featuresdf.iloc[0]['feature']
数组([-2.1579300e+02,7.1666122e+01,-1.3181377e+02,-5.2091331e+01,-2.2115969e+01,-2.1764181e+01,-1.1183747e+01,1.8912683e+01,6.7266388e+00,1.40
现在,我们已经成功地从底层音频数据中提取了我们的特征,我们可以建立和训练一个模型。
模型建立和训练
我们首先将 MFCCs 转换成 numpy 数组,并对分类标签进行编码。
from sklearn.preprocessing import LabelEncoder
from keras.utils import to_categorical# Convert features and corresponding classification labels into numpy arrays
X = np.array(featuresdf.feature.tolist())
y = np.array(featuresdf.class_label.tolist())# Encode the classification labels
le = LabelEncoder()
yy = to_categorical(le.fit_transform(y))
我们的数据集将被分成训练集和测试集。
# split the dataset
from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(X, yy, test_size=0.2, random_state = 127)
让我们定义并编译一个简单的前馈神经网络架构。
num_labels = yy.shape[1]
filter_size = 2def build_model_graph(input_shape=(40,)):
model = Sequential()
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_labels))
model.add(Activation('softmax'))
# Compile the model
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam') return modelmodel = build_model_graph()
让我们来看一个模型总结,并计算训练前的准确性。
# Display model architecture summary
model.summary()# Calculate pre-training accuracy
score = model.evaluate(x_test, y_test, verbose=0)
accuracy = 100*score[1]

print("Pre-training accuracy: %.4f%%" % accuracy)
训练前准确率:12.2496%
现在是时候训练我们的模型了。
from keras.callbacks import ModelCheckpoint
from datetime import datetime num_epochs = 100
num_batch_size = 32model.fit(x_train, y_train, batch_size=num_batch_size, epochs=num_epochs, validation_data=(x_test, y_test), verbose=1)
及时完成的培训:
甚至在训练完成之前,Comet 就记录了我们实验的关键信息。我们可以从 Comet UI 中实时可视化我们的精度和损耗曲线(注意橙色旋转轮表示训练正在进行中)。

彗星的实验可视化仪表板
一旦经过训练,我们就可以在训练和测试数据上评估我们的模型。
# Evaluating the model on the training and testing set
score = model.evaluate(x_train, y_train, verbose=0)
print("Training Accuracy: {0:.2%}".format(score[1]))score = model.evaluate(x_test, y_test, verbose=0)
print("Testing Accuracy: {0:.2%}".format(score[1]))
训练准确率:93.00%
测试准确率:87.35%
结论
我们的模型已经训练得相当好了,但可能还有很大的改进空间,也许可以使用 Comet 的超参数优化工具。在少量代码中,我们已经能够从音频数据中提取数学上复杂的 MFCC,建立和训练神经网络以基于这些 MFCC 对音频进行分类,并在测试数据上评估我们的模型。
如何在 Android 应用中应用机器学习(ML)

机器学习是人工智能(AI)的一种应用,它使软件能够在没有人类干预的情况下自动学习、探索和设想结果。机器学习已经在许多领域得到应用,并且正在积极地服务于移动应用开发。
在 Android 应用程序中应用机器学习有多种方式。最合适的方式依赖于你想要在机器学习的辅助下破解的工作或任务。
机器学习算法可以对目标用户行为模式进行分析,并有搜索请求来提出建议和推荐。它广泛用于移动电子商务应用。а视频和音频识别甚至是 Snapchat 等娱乐领域使用的一种 ML。
它还可以用于面部或指纹识别,以简化身份验证。否则,你可以在你的移动应用程序中添加聊天机器人,这种应用程序已经变得很受欢迎,如苹果 Siri 。
根据 bccresearch 的研究,2017 年全球机器学习市场总额为 14 亿美元,预计到 2022 年将达到 88 亿美元。机器学习 vs 人工智能也是数据分析师争论最多的话题。
技术专业人士甚至通过在 Android 应用中启用 ML 来优化搜索过程。通过增加拼写纠正、语音搜索或搜索程序,你的目标用户会变得更自然,更少烦恼。
面向移动应用的机器学习
移动应用开发者可以从机器学习(ML)在整个行业提供的创新转型中受益匪浅。这是可能的,因为移动应用程序带来的技术能力支持更流畅的用户界面和体验,并为企业提供突出的功能,如提供精确的基于位置的建议或立即检测慢性疾病。
如今,人们希望他们的体验绝对个性化。所以,仅仅创建一个高质量的应用程序是不够的,你甚至必须让你的目标用户坚持使用你的移动应用程序。
在这里,机器学习可以帮助你。机器学习技术可以将你的移动应用翻新到用户的视野中。
如何制作一个机器学习 App
制作 ML 应用程序是一个迭代过程,涉及用目前观察到的内容和您希望模型预见的解决方案来构建核心机器学习问题。接下来,您需要收集、清理和过滤数据,提供结果,并进一步利用模型为新生成的数据实例生成所需答案的预测。
一些顶级的机器学习应用-
1)网飞

在网飞,他们利用机器学习算法。它通过使用线性回归和逻辑回归以及更多此类算法,提供了精确、个性化的参考。
网飞应用程序使用多种多样的内容,分为品种、演员、用户和评论家的评论、时间跨度、年份等等,以提供给他们的观众。所有这些信息都会进入机器学习算法。
网飞的人工智能算法是通过跟踪用户行为的用户动作来训练的。它监控我看什么电视节目或者我在网上提供什么类型的评论。机器学习算法熟悉这种用户行为,以提供非常个性化的内容。
2) 火绒

我们知道 tinder 是一款帮助寻找约会对象的手机应用。它使用机器学习算法来找到精确的匹配。它使用发布的图片等信息,随机展示它们,并分析它们被浏览的频率,这有助于应用程序通过将最常观察到的照片放在最前面来重新排序你的照片。这一创新功能增加了用户发现理想匹配的机会。
3) 谷歌地图
谷歌地图利用机器学习寻找停车位。它使用数据分析技术来做到这一点。

谷歌的研究人员从一个非常大的人群样本中收集和研究数据。他们问他们需要多长时间以及他们在寻找停车位时是否遇到困难。他们通过创建不同于那些共享其位置信息的人的训练模型来获取、聚集和使用这些数据。
机器学习进一步通过 Tensorflow 在 Android 移动应用程序上应用流程,tensor flow 是一个基本的 ML 框架。
如何将机器学习应用到 Android 上
有许多机器学习框架可用,我们在这里以 Tensorflow 为例。

TensorFlow 是谷歌的开源库,在 Android 中用于实现机器学习。TensorFlow Lite 是 TensorFlow 针对移动设备的轻量级解决方案。它支持使用低延迟的设备上 ML 推断,这就是它非常快速的原因。它非常适合移动设备,因为它采用较小的二进制大小,甚至通过利用 Android 神经网络 API 支持硬件加速。
在 Android 应用程序中使用 tensor flow Lite
下面是 android TensorFlow 机器学习实例总结,以及如何将机器学习应用到 android 上。要使用 TensorFlow Lite 执行模型,您必须将模型更改为模型(。tflite),这是 TensorFlow Lite 认可的。使用 TensorFlow Lite 时重要的事情是建立一个模型(。这与标准张量流模型截然不同。
通过获得模型和标签文件,可以在 Android 应用程序中启动和标记文件,以便通过利用所需的 TensorFlow Lite 库来加载所需的模型和预测输出。
我们拥有通过使用 TensorFlow Lite 构建完整的运行样本应用程序的经验,该应用程序旨在用于所需的对象检测。
在 Android 上训练 TensorFlow 模型
训练需要大量数据的张量流模型可能需要更长的时间。然而,有一种方法可以大大缩短这个过程,而不需要巨大的 GPU 处理能力和千兆字节的图像。迁移学习是使用先前训练好的模型并对其进行再训练以建立新模型的行为过程。
您可以按照以下步骤进行培训-
步骤 1:收集培训数据
步骤 2:将数据转换成所需的图像
第三步:创建图像文件夹,并将它们分组
步骤 4:用新图像重新训练模型
第 5 步:为无障碍移动设备优化模型
第六步:嵌入。tflite 文件到应用程序中
步骤 7:在本地运行应用程序,观察它是否检测到图像
使用机器学习的入门难度正在变得不那么显著。许多公司已经创建了训练有素的机器学习 API,您可以立即开始使用:
一些训练有素的机器学习服务和 API
Google Play 服务——移动视觉应用编程接口
机器学习服务的主要群体被创建到 Google Play 服务 SDK 中。这意味着任何 Android 开发者都可以在他们的应用中使用这些服务。 谷歌的云视觉 API 就是其中一个例子,它让开发者能够使用 Android 摄像头来感知人脸、检查条形码和识别文本。
ML Rest 服务——谷歌云 ML API
rest 服务训练有素,随时可以用于智能任务。有许多这样的休息服务可供选择,既有免费的也有付费的。
Google 的 ML 平台由翻译、语音识别、NLP 和工作列表 API 组成,积累到 REST 版本中。要开始使用 Google ML 平台,您只需要一个 Google 云平台帐户来登录和使用服务。
REST Vision API 支持多种请求,包括与标签、文本、图像属性等相关的信息。
前进
机器学习服务 使智能平台能够协助你创建、训练和托管所需的预测模型。一旦你接触到这些平台,它们就会变得柔软且易于使用。少数缺点是从一开始就设置机器学习应用程序所需的各种算法和配置的压倒性景观。然而,如果您已经掌握了机器学习开发的最新知识,那么高级服务将提供强大而足智多谋的计算资源,来进行准确的数据分析以及高度精确的预测。
如何对表格数据应用自我监督:介绍 dfencoder

Have a slice of cake. You’ve earned it.
日常数据科学家的去噪自动编码器。
2016 年,脸书首席 AI 科学家严乐存打了个比方:
“如果智能是一种蛋糕……无监督学习是 génoise,蛋糕的大部分。”
—颜乐存,深度学习与 AI 的未来,2016
他详细阐述了这个类比,将监督学习比作蛋糕上的糖衣,将强化学习比作顶端的樱桃。
2019 年,他更新了他的类比,将无监督学习修正为自监督学习。

LeCun’s updated cake analogy slide, presented at the 2019 IEEE International Solid-State Circuits Conference.
自我监督学习
无监督学习是机器学习中一个古老且众所周知的问题;乐存选择将其替换为他蛋糕类比中的明星,这不是他应该掉以轻心的事情!
如果你深入自我监督学习的定义,你会开始发现它实际上只是一种无监督学习的方法。由于这十年来机器学习的许多突破都是基于监督学习技术,当研究人员将一个无监督的问题重新构建为一个有监督的问题时,无监督问题中的成功往往会出现。具体来说,在自我监督学习中,我们找到了一种不需要人工标注器就能生成标签的聪明方法。
一个简单的例子是称为下一步预测的技术。给定一个序列(例如,文字或视频帧),模型可以预测下一步。因为我们已经有了序列,所以没有必要让人类注释者创建标签;我们可以只在步骤t-1截断序列,并使用步骤 t 作为“标签”(或目标)来优化我们的监督学习算法。
下一步预测是一个简单的例子,但是在自我监督技术的爆炸领域中有一整套技巧。
去噪自动编码器:新狗的老把戏?

You can’t teach an old dog new tricks, but denoising autoencoders have been around for a long time.
严乐存自己在 1987 年提出了去噪自动编码器(DAE)的概念,他的工作在 2000 年的和 2010 年的的该领域正在进行的研究中被引用。
这个想法与经典自动编码器有关,但有一个有趣的转折:与经典的模型输入等于监督目标的设置不同,我们在将每个例子输入模型之前,对其进行破坏或添加噪声。目标是示例的未损坏版本。

Visual example: We can add noise to an MNIST image and use the un-altered version as a target to train a neural network.
多元解释
在无监督学习的情况下,无监督模型的任务是学习样本在特征空间中的分布;这种分布可以理解为特征空间中的一个流形。
通过破坏输入,我们获取示例并人为地将它们“推”离歧管。通过使用未改变的输入示例作为目标,我们能够训练我们的模型来近似一个将特征空间中的点投影到特征分布流形上的函数。

The manifold interpretation of the denoising task. We’re looking at a simple feature space, where the “true” distribution of examples lies close to the line (manifold). The circle on the left shows the result of corrupting an input. The lines on the right show the learned function of projecting points onto the manifold (source).
对于任何正在努力理解流形概念的读者来说,这只是一种说法,即被破坏的输入看起来不像“在野外”的例子,但它们的目标看起来像。学习使被破坏的输入“看起来”像真实输入的任务给了我们的模型一种学习分布本身的方法。
这样,去噪任务是一种执行无监督学习任务的方式,该无监督学习任务学习样本在特征空间中的分布。好处是我们可以用示例/目标对进行训练,这为使用监督学习技术打开了大门。这使得这成为一个自我监督的学习计划。这是最古老的自我监督计划之一!

Self-supervised learning? Oh yeah, I used to be into that… before it went all “mainstream.”
与传统的自动编码器相比
“普通的”自动编码器不会破坏输入。模型的输入与目标相同。这些模型学习近似身份函数。
因为 identity 函数很容易学习,所以经典的自动编码器有一个特定的要求:模型输入的内部表示中至少有一个必须比输入的维数少。这样,任务就真的“压缩”了。我们如何以保留信息但降低维数的方式对输入向量进行编码?自动编码器知道如何回答这个问题。

Classic “vanilla” autoencoder setup; a “bottleneck” layer (z) is required to make the identity function non-trivial (source).
DAE 不是真正的自动编码器,因为它不学习识别功能。它实际上学习了一个将点投射到前面描述的流形上的函数。这消除了 DAE 中对瓶颈层的需求。

A DAE does not need a low-dimensional “bottleneck” layer. Copyright by Kirill Eremenko (Deep Learning A-Z™: Hands-On Artificial Neural Networks)
表征学习
深度神经网络之所以如此强大,是因为它们能够学习示例的潜在特征,或表示。
那是什么意思?
这里有一个简单的人为的例子。想象我们是一家汽车保险公司。我们有一份申请表,上面有我们的申请人想要确保的汽车特性。下面是该表中的一个片段:

Our contrived example dataset.
这里潜在特征的一个例子是“财富。“虽然我们不知道申请人有多少钱,我们也不能仅仅根据这些特征来确定,但驾驶法拉利的申请人很可能比驾驶本田思域的申请人更富有。


What do you think about the owners of these two cars? What’s different about them? Those are latent features.
这是一种人工神经网络可以解决的事情— 而无需明确地将财富的概念引入模型。
普通的自动编码器是一个好主意,但是对瓶颈层的需求迫使我们的网络做一些总结。这锻炼了模型做好表征学习的能力。
这就是为什么 DAE 是一个好主意!我们可以不压缩我们的例子,而是把它们打开;我们可以将每个示例扩展到一个更高维度的空间,其中包括潜在特征,显式地表达从每个示例中的整个数据集学习到的信息。
为什么是表格数据?
这些技术在研究中非常有效,但是我们很少在论文中看到表格数据。我希望我的读者开始考虑将 DAE 用于表格数据。
这是因为在平凡、普通、日复一日的数据科学家的工作中,表格数据就是我们所拥有的。
数据驱动的企业挤满了巨大的分布式数据存储系统,所有这些系统都塞满了数百万行和列的表格数据。

Though underrepresented in ML research, the vast majority of our information is stored in tables.
用于表格数据的 DAE:一个成功的故事
2017 年,一位 Kaggle 竞赛获胜者透露了他的获胜策略:用 DAE 进行表征学习。
这是一个完全表格化的数据集。
对于表格数据,不管你怎么说 DAE,但是证据就在布丁中。迈克尔用 DAE 赢得了比赛。
桌子的噪音
表格数据面临的挑战是,每一列都代表其独特的分布。我们有类别,数字,排名,二进制值等。,都融合到同一个例子中。
这给应用 DAE 带来了重大挑战:我们使用哪种噪声?
DAE 中的一些原创研究通过将输入值设置为零来破坏它们。对于分类列,“零”没有意义。我们是否只是随机地将一些值设置为编码为零的类别?这似乎不太合适。
交换噪声
迈克尔成功解决方案的关键是一种他称之为“交换噪音”的噪音

这是一个非常简单的想法,只适用于表格数据。
我们不会将值设置为零或给它们添加一些高斯噪声,而是在我们的数据帧中随机选取一些单元格,然后用来自同一列但随机采样的行的值替换它们的值。
这为从列的分布中获取样本值提供了一种计算成本低廉的方法,同时避免了实际建模这些分布的需要。****
噪音带有一个参数:我们交换一个给定值的可能性有多大?kaggle 获奖推荐:
" 15%的 swapNoise 是一个很好的起始值."
— 迈克尔·贾雷尔,波尔图安全车手大赛冠军
也就是说,表格中 15%的单元格应该随机替换为它们自己列中的值。从这里开始,调整 nob,看看什么最适合您的数据集。
dfencoder —用于表格数据的 DAE
我想亲自尝试一下。我想,“如果一个熊猫数据帧有一个应用交换噪声的方法不是很好吗?”
对熊猫来说,拥有这个特性并没有什么意义,但我会发现它很有帮助。我决定自己实施。于是,dfencoder 诞生了。第一个特性:EncoderDataFrame。这是一个熊猫的数据框。swap(),一种返回应用了交换噪声(默认值为. 15)的数据帧副本的方法。

Example of .swap() method usage.
从那时起,这个项目就像滚雪球一样变成了现在的样子:一个完整的端到端框架,用于构建和训练带有表格数据的 DAE。
要了解如何使用该框架的更多信息,请看一下演示笔记本。(项目仍在开发中,但在 BSD 许可下可以免费使用。)
DAE 的应用
我们已经讨论了作为特征提取器的 DAE。但是他们还能为我们做什么呢?
有许多应用,但仅举几个例子:
- 特征插补
- 异常检测
- 特征抽出
- 探索性分析(例如,类别嵌入)
你可以在 dfencoder 演示笔记本中看到如何处理这些用例。
也许您或您的组织只有一堆未使用的数据表—如果您有一些未使用的计算资源,为什么不将它们用于学习数据的有用表示呢?
使用 TensorboardX 实现 EDA 和更多功能
我不喜欢 Tensorflow ,但是这个生态系统的一个伟大之处就是它的传感器板。对于替代性深度学习库来说,没有什么比它更好的了。
幸运的是,有tensor board x——tensor board 的一个通用扩展。

Tensorboard’s user-friendly GUI.
我在 dfencoder 库中添加了一个 TensorboardXLogger 类,让您可以更密切地监控您的模型优化。
Tensorboard 的另一个很酷的特性是能够在你的模型已经学习的类别嵌入上运行 PCA 或 t-SNE——所有这些都有一个很好的 GUI。

PCA on category embeddings for education-level column in adult census dataset. Learned through DAE.
你不需要 tensorboardX 或 tensorflow 来运行 dfencoder,但是如果你想使用 tensorboard 后端,你可以只安装这些库,并将 logger='tensorboard ',logdir='your/logdir/'参数添加到 AutoEncoder 构造函数中。
dfencoder 理念
你有很多事情要做:截止日期,正在进行的次要项目,还有朋友和家人。
我们没有时间深入兔子洞,试图建立最先进的表征学习模型。我们坚持有效的方法:增强模型,随机森林;见鬼,正则化逻辑回归几乎总是奏效!
dfencoder 已经领先,处理所有的样板代码,所以你不必。如果您想构建一个 DAE,您需要担心的事情已经够多了:
- 隐藏层数
- 隐藏层的大小
- 激活功能
- 交换噪声参数
- 学习率
- 【计算机】优化程序
- 正规化
- 特征缩放
- 还有更多!
我希望您专注于这些东西,并实际制作一个有用的 DAE,调整这些参数以优化您正在做的任何事情。我不想让你写一堆我已经写好的代码!
这就是我创建 dfencoder 的原因。
查看该库——它适用于 python 3.6,并使用 torch 作为其深度学习后端。
重现获奖结果
我开始了这个项目,希望能够重现 DAE kaggle 冠军所获得的结果。我没有 GPU,所以我使用 Google Colab 作为免费的 GPU 后端——不幸的是,系统内存(~14 GB)不足以像 Michael 那样解决问题(32 GB 内存)。更不用说,训练花了他几天的时间。
复制他程序的笔记本的开端可以在这里找到;任何有硬件的人都可以看一看这款笔记本,并根据需要对其进行修改,以适应获胜的超参数。让我知道你是否能让它工作!
祝你好运!
我对你的故事很好奇。如果你觉得有趣或有用,在这里评论或在某处提及这个库!欢迎反馈和功能请求:)
如何处理机器学习问题?
机器学习是让计算机像孩子一样学习的过程。就像一个孩子需要被教会如何理解问题,从给定的情况中利用洞察力并采取相应的行动一样,机器学习模型也需要被教会。
在当今世界,数据是最昂贵的商品。它甚至比钻石或黄金还贵!原因是数据可以通过机器学习模型以各种不同的方式使用,以获得有意义的见解和预测未来的行为。

Source of Image :https://techgrabyte.com/10-machine-learning-algorithms-application/
现在我们已经确立了数据和机器学习的重要性,让我们开始讨论如何识别问题、决定数据集、制作模型和评估以获得期望的结果。
就区域应用和未来研究范围而言,机器学习算法能够解决的可能问题集是巨大的。我建议选择任何你感兴趣的问题。首先确定一个你想从事的领域。下一步是在那个领域里选择一个能让你感动的问题。一旦你有了问题,然后试着在互联网上找到什么样的数据集,因为许多研究人员开放他们的数据集和代码供学术界使用。此外,谷歌人工智能、微软研究院和脸书博览会等公司的研究部门通过挑战开源了各种有用的数据集,促进了各种领域的研究。
有时,我们必须根据我们所拥有的数据来修改问题陈述。别灰心!关键是要持之以恒。如果你对一个问题或想法充满热情,但没有数据集,你可能会考虑花时间收集数据(通过道德手段),并确保你或一些专家可以验证你的数据的用途。如果您已经找到适合您的问题的数据集,那么让我们继续下一步。
人们经常陷入的下一个问题是,哪种算法适合他们的问题陈述。这当然很难处理,但并非不可能。诀窍是对你的问题打算解决什么以及你想如何着手去做有一个非常清晰的想法。例如,如果你的问题是分类,那么你应该考虑看看各种机器学习和深度学习算法,它们将为你执行分类。但是,工作还没有完成!你还有很多选择。哪种算法最适合你的问题?你怎么会知道?
有两种方法来处理这样的困境。首先是测试!在你的数据上测试所有可能的算法,看看哪个最适合你。这种方法有利也有弊。好处是,你肯定知道一个或一组算法是你的问题陈述的更好的选择。然而,人们往往没有意识到我们在现实世界中拥有海量的数据。你能想象在如此庞大的数据集上运行所有可能的算法排列组合需要多少时间和空间吗?解决方法是走第二条路,在决定它是否适合你的问题之前,试着理解算法做什么。不要害怕深入算法本身的基础知识!你对算法的工作原理和它的局限性了解得越多,你就越有可能确定它对你的问题来说是不是一个好的选择!
一旦缩小了算法的范围,下一步就是构建模型,并根据数据对其进行训练。不要忘记调整超参数的重要性,因为它有助于提高模型的性能。如果你不知道什么是超参数,那么不用担心!这很容易。超参数就像煤气炉的旋钮。同样,在烹饪时,你需要确保旋钮上的设置是你烹饪食物的理想选择,同样,对于机器或深度学习模型,你需要调整这些旋钮来优化你的性能。
这个过程的另一个重要方面是选择一个与你的问题相关的好的评估标准。许多人在分类、回归等任务中追求准确性,仅仅是因为这是最容易理解的度量标准,但情况可能并不总是如此。例如,假设您的问题是确定在给定数据的情况下,您的模型预测患者患癌症的概率有多准确。在这种情况下,仅仅精确是不够的。在这样的问题中,你还关心精度和召回率。知道你的模型有多精确是个好主意。它是否将患有癌症患者归类为非癌症患者?如果是这样的话,那么这样的模型用在现实世界中岂不是很可怕?因此,对于你想从你的模型中得到什么,要非常小心,并相应地选择你的评估指标。现在你已经准备好进入测试阶段了!
这是如何处理任何问题的一个非常简短的概述。我相信使用好的和合理的策略可以帮助提高每件事和每个人的表现!
我希望这篇文章有助于提供机器学习世界的幕后展望。
谢谢!
资源:
要了解更多关于如何选择机器学习算法的信息,可以看看这个链接:
如何像创新者一样处理问题
来自我的先驱导师的三个经过实地检验的教训

Photo by Olav Ahrens Røtne on Unsplash
如果你和我一样,你会发现自己对当代一些最著名的人有点困惑。所有人都说,他们是天才,是工业巨人,远远领先于我们这些凡人,有人猜测他们是变形蜥蜴。然而,他们的言论如此简单,他们的方法如此基本和直观,我们不禁认为他们只是在用他们朴素的外表欺骗我们——不可能用如此简单的手段达到如此复杂的目的。
在科学方面,我们有阿尔伯特·爱因斯坦和他的简单思维实验。在投资领域,有沃伦巴菲特,与其说他是金融家,不如说他是哲学家。在商界,无忧无虑的理查德·布兰森浮现在脑海中。
我的导师阿赫蒂·海因拉 Skype 的联合创始人和机器人技术的先驱——也是一个类似的谜。他向我们——一屋子卓越的工程师——提出了一个复杂的问题,我们想出了一个复杂的技术解决方案,需要几天才能实现。阿赫蒂等待着熙熙攘攘的人群停下来,通常情况下,他会提出自己别出心裁的方法——一种可以在算盘上五分钟完成的方法。
这里有一个例子:我们原本自主的送货机器人偶尔会被困在障碍物后面——也许是灌木丛。在这种情况下,指挥中心的人负责控制,并通过实时视频观察机器人的周围环境,操纵机械人绕过障碍物,就像它是一辆遥控汽车一样。我们想测量执行这样的机动所花费的平均时间。
然而,问题是这样的信息不容易从数据库中获得。当我们都在考虑如何为此目的重新构建系统时,Ahti 调出了一些此类案件的视频,并手动计算了秒数。这个问题在几分钟内就解决了,我们目瞪口呆。
教训:正是因为我们太老练,我们才发现自己被问题困住,被分析麻痹。随着时间的推移,通过第一手经验,我注意到 Ahti 身上的几个特征反映了其他伟大创新者的特征。它们都讲述了同一个故事:简单是关键。
为了让自己变得不复杂,让我们从他们的剧本中吸取一页:
从基本原则出发思考
2017 年,埃隆·马斯克(Elon Musk)提出了一个想法,将洛杉矶等大都市的车辆交通转移到一个互联的地下隧道网络中。他认为,如果隧道费用至少降低一个数量级,从每英里 10 亿美元降到 1 亿美元,这样的计划在经济上是可行的。
他的新企业,无聊公司,就是要这样做。他概述了如何在 TED 演讲中实现这一壮举:
- 通过将直径减半,使隧道小于典型的。根据公式 S = π ×r,横截面积 S 因此减少了四倍。由于挖掘成本与面积成比例,成本下降到 2.5 亿美元。
- 在加固隧道壁的同时,继续钻探过程,挖掘得更智能。简化传统的停止挖掘隧道的程序,同时提供支持,将成本降低了两倍,降至 1 . 25 亿英镑。
- 通过加大钻孔机的功率来更快地挖掘隧道,这些钻孔机并没有以其最大能力工作。至少,这应该使效率加倍,使我们达到大约 6000 万,远低于必要的 1 亿大关。
现在,没有人否认这些步骤中的每一步都极其困难,取决于多年的技术和操作突破。但通过自下而上而不是自上而下地解决问题,马斯克迫使自己独立思考,导致对传统智慧的重新评估,并确定了明确的改进途径。
像马斯克一样,我们需要摆脱现状的束缚。当面临问题时,我们应该而不是从现有的解决方案向后工作,试图找出一些瓶颈——这只会导致不值得我们花费时间的渐进进步。相反,我们应该从基本原则开始建立对问题的理解,只有这样我们才有希望创造出真正崇高的东西。
我们的心态必须是建筑师的心态,而不是雕塑家的心态——我们不是在剥离已经存在的东西,我们是在构建一个全新的存在。
从头开始工作的优势有两方面。首先,它迫使我们关注大局,跳过那些在解决问题的早期探索阶段只会拖累我们的不必要的细节。当然,技术细节很重要,但只是在一定程度上允许我们实现我们的总体愿景。作为创新者,我们必须区分细节和一般,让后者引导前者,而不是相反。
第二,它允许我们的思想自由漫游,不受以前做过的事情的污染。我们多年来获得的独特技能赋予了我们一个独特的视角,其他人从未用这个视角探索过手头的主题。批判性地思考现在让我们挖掘潜力,当我们意识到自己的独特性时,我们的信心会增加。我们不再试图随大流,而是拥抱我们个人的工具箱,以用它来重建我们周围的世界为乐。
“云中城堡没有建筑规则”——吉尔伯特·k·切斯特顿
内化抽象概念
作为一个小男孩,物理学家理查德·费曼过去常常坐在他父亲的腿上,听他讲大英百科全书中的故事。年轻的费曼对奇妙的恐龙世界特别着迷,他的父亲通过将书中枯燥的统计数据转化为现实,使恐龙世界变得栩栩如生。
例如,说到霸王龙,百科全书会说它有 25 英尺高,头部有 6 英尺宽。然后,他的父亲会停下来,把这些事实转化为对他儿子来说切实的东西:“这意味着,如果它站在我们的前院,它就足够高,可以看到我们的房间。但是他很难吃掉我们,因为他的头有点太宽了,无法穿过窗户。”
据费曼自己承认,这种早期影响对他成长为一名特立独行的科学家起了重要作用。通过将他的思维建立在日常类比的基础上,他对物理学产生了一种本能的感觉——做科学变得更像是一种讲故事的练习,而不是严格的数学推理。正是他对抽象概念的直觉理解,让费曼简化了量子力学,用一个图形框架取代了复杂的数学表达式——这项工作为他赢得了诺贝尔奖。
我们应该从费曼那里学到的是理解和仅仅知道之间有着巨大的差异。后者可以通过材料的被动积累来实现,而前者需要一种主动的方法。一个关心理解的人总是在重组他的思维,将她遇到的每一个新概念编织到她现有的知识网络中,从不允许任何空隙。
我们必须优先考虑根据我们已经内化的东西来理解外部世界的抽象新奇事物。
这种对抽象事物的本能控制使我们的思维更敏锐,更有独创性。当其他人被过度的形式主义所困,经常屈服于单调乏味时,我们能够以无与伦比的旺盛精力解决问题,这是出于我们已经想到的许多类比。就像组装乐高积木一样,玩我们直观的原始模型,在我们的想象中重新配置它们以获得新的见解,这是一件非常有趣的事情。
此外,想法的深层内化允许它们渗透到我们的潜意识中,在那里它们将与我们已经吸收的其他概念混合和匹配。解决问题的方法会逐渐出现在我们面前,因为最初困扰我们的完全不同的概念会形成连贯的模式。这往往会带来顿悟的时刻,当事物之间隐藏的联系突然在直觉的闪现中变得可见——历史上许多最具突破性的发现都是这种潜意识过程的结果。
"为什么眼睛在梦中比清醒时的想象看得更清楚?"—莱昂纳多·达芬奇
立即采取行动
对于亚马逊的客户服务部来说,2000 年的假日季节特别混乱。随着圣诞节销售的增加,亚马逊的电话等待时间越来越长。由于互联网泡沫的破裂,消费者对科技公司的信任已经减弱,这是一场灾难。
为了控制这个问题,该公司的首席执行官杰夫·贝索斯召集了一系列紧急会议。在一次这样的会议上,贝佐斯要求提供客户等待时间的统计数据,并得到保证,在没有任何证据的情况下,他们远远低于一分钟。贝佐斯对此大吃一惊——这个数字远低于他的印象。他脱离现实了吗?
令他的高管困惑的是,贝佐斯当时就通过会议桌中间的扬声器拨打了亚马逊的帮助热线。他用手表记录时间,坚定地守在电话旁。随着时间的推移,这位线人在房间里其他坐立不安的高管中惊慌失措,并试图通过短信偷偷召唤他的下属。
最终,在漫长的五分钟等待后,贝佐斯的电话被一位愉快的代表接听了:“你好,亚马逊!”在没有任何冗长的后续会议和昂贵的分析的情况下,贝佐斯凭借这一独特的天才之举,不仅淘汰了无能的高管,还凸显了亚马逊运营中的一个重大问题。
阿赫蒂萨里也有类似的迅速而审慎行动的倾向。对于他来说,为了寻找答案,在会议中途浏览源代码并不罕见。或者实时编写新的功能和缺陷修复程序。事实上,他的即时感是如此强烈,以至于他让通常被动的人看起来不可思议地活跃——当提出想法时,他的注意力是如此坚定,注意力是如此敏锐,就好像他积极地将信息输入他的大脑。
培养我们对行动的这种偏见有三重好处。首先,我们的热情,也就是我们投入到手头工作中的热情增加了。我们的热情随着问题的开始和解决之间的距离的增加而减少。因此,为了抓住转瞬即逝的窗口,让我们的情绪准备状态有可能达到最佳状态——心流状态——现在就行动是必要的。
我们必须把我们对工作的热情等同于一段新的关系——它需要迅速培养,否则它会失败。
第二,我们以前所未有的清晰和专注推进。通过及时解决问题,我们对问题出现的背景仍然记忆犹新。这让我们能够专注于提供解决方案——我们不想耗尽我们的认知资源试图记住过去问题的复杂细节。这种可用性在协作环境中尤为重要,在协作环境中,任何信息的丢失都会以辅助会议的形式带来巨大的开销。
第三,就像阿提提一样,我们发展出一种关于我们自己的活力光环。不再焦虑,不再被不断增加的积压工作拖垮,不再把我们的注意力转移到内心,我们挺直腰板,以不同寻常的感知度生活。我们的思想和行动交织在一起,前者毫不拖延地呈现了后者,我们又一次像小孩子一样,可爱地躁动不安,永远充满好奇。作为一个额外的收获,我们会给人一种完全真实的感觉,吸引别人来看我们。
“我们走得越慢,我们死得越快”——乔治·克鲁尼
如果把这些信条融入我们自己,我们的生活会突然变得既容易又困难。从某种意义上说,我们所关注的本质是独立的,避免了我们被纠缠在细节中。更难是因为从基本原则出发思考,我们不能再沉迷于模仿,而必须从内部寻找灵感。更难是因为概念的深度内化会导致最初的开销——当其他人已经取得进展时(直到他们不可避免地被缺乏深度所阻碍),我们仍然处于明显的被动状态,或多或少是在做白日梦。
当然,我们已经知道——获得成功是困难的,更不用说达到最伟大的人的水平了。我只是想通过阿赫蒂和其他人告诉你,事情不必复杂。让我们感到欣慰的是:这远不容易,但至少很简单。
简单到我们现在就可以开始。
如何提出好的问题?

Photo by Cristofer Jeschke on Unsplash
什么是好问题?为什么问一个好问题?怎么做呢?这个故事探讨了这三个问题。
为什么要问好问题?
在进入“如何”部分之前,你可能想知道为什么你应该关心问好问题,所以让我们花点时间来理解为什么。问题旨在引出答案、信息、满足好奇心——这是我们所有人在生活中都渴望的。我们经常尝试这样做:从简单的谷歌搜索到详细的论文回复,一切都涉及到提问的概念。事实上,伏尔泰认为提出正确问题的能力比拥有所有答案更重要:
"判断一个人要看他的问题,而不是他的回答。"
—伏尔泰
因此,既然问问题是我们生活中不可或缺的一部分,问好问题不仅对个人有益,对职业也有好处。对于数据科学来说尤其如此,因为一些数据科学家认为,提出正确的问题是分析中最重要的过程——,这就是为什么它是增加数据科学价值的关键。
但是到底什么是好的问题呢?我来解释一下我的观点。
什么是好问题?
我们的问题可以根据针对的对象进行分类;广义来说,我们要么问一个人类(朋友、家人或陌生人),要么问一个非人类(语音助手、搜索引擎等)。).互联网上有如此多的信息,人类和非人类对问题有如此多的解释,一个好的问题应该被正确理解,并及时得到准确的答案。为了识别这些问题,我们需要数据和比较问题的方法。
但是,我们如何衡量呢?有没有一个指标可以帮我们做到这一点?一种可能是计算你需要最终得出答案的 个跟进问题 的数量。例如,假设您搜索“世界各地的生育率”数据。你一开始没有找到你要找的数据是有可能的,因为搜索引擎不知道你在看什么时间框架:你想要过去 1 年还是 50 年的数据?你想要历史数据还是预测,还是两者都要?
或者说你搜索“世界上最富有的国家”同样,对这些有很多解释:我们用什么指标来衡量“富有”? GDP? GNI ?我们在看什么时间框架?
这些模糊性要求你问一系列的“后续”问题,在这些问题中,你要么调整你原来的问题,要么提出一个全新的问题,直到你找到答案。作为一个重视时间的聪明人,你肯定想避免时间,同时保持高效和有效。通常情况下,一个问题是不够的,也可能不够,但我们知道这是我们的理想场景:如果我们知道一个理想的问题,我们可以一口气找到我们的答案!认为这过于乐观了吗?至少爱因斯坦不这么认为:
“如果我有一个小时来解决一个问题,而我的生命取决于这个问题的解决方案,我会用前 55 分钟来确定要问的恰当问题,因为一旦我知道了恰当的问题,我就可以在不到 5 分钟的时间里解决这个问题”——阿尔伯特·爱因斯坦。
这句话重申了提出好的问题对于快速有效地找到答案的重要性。在某种程度上,跟进问题的数量,正如 Charles Burke 所说,是我们的“富士山指标”

Photo by Daniel Seßler on Unsplash
我们的目标是指标的顶端(也就是山峰)。虽然我们可能永远也不会实现它,但是不断地朝着它前进将会帮助我们取得巨大的进步。问问题是一种技能,如果你不断向顶峰攀登,也许会像第一张照片中的那个人一样到达顶峰,你就可以发展这种技能。
如何?
既然你知道什么是好问题,为什么它们很重要,你就准备好揭开最棘手的部分:如何揭开?
正如在“是什么”部分中所讨论的,一个好的理想的问题是一个足以在一瞬间找到答案的问题。因此,问好问题的关键是问具体、详细的问题。但是多少才算够?越多越好吗?不一定。考虑这样一个场景:两个人走进一家咖啡馆,想要点吃的:
我可以要一个芝士汉堡吗?
我能要两个小圆面包,一个肉饼,生菜,西红柿,番茄酱,奶酪都堆在一起吗?
你明白了。你想找到正确的平衡,下面是你在设计问题前应该考虑的 3 个因素。让我给你举个例子,告诉你这些因素是如何产生的。假设您想了解世界各地的富人有多富有,以及不同地理区域之间的差异。
#1:特定术语
你问的术语是特定于那个领域的吗?如果没有,你能改进吗?在我看来,提出一个“前置问题”来巩固你对一个术语的理解,然后用具体的词来提出问题要容易得多。让我们假设你不太懂经济学或商业(如果你懂,那很好,你可以跳到第二点)。
一个好的开头或“前置问题”会问“经济学家如何衡量个人的财富?”或者“用什么指标衡量个人财富?”这可能会让你想到人均 GDP、人均 GNP 等术语。你的问题就变成了“世界上个人的 ______ 相比如何?”空白处由您选择的指示器填充。
#2:具体范围
虽然你用行话使问题更加清晰,但仍有工作要做。你需要有一个范围,否则你将不得不问一系列后续问题。例如,你对特定的国家、地区或大洲感兴趣吗?您是担心他们当前的财富,还是想要 xyz 年前的数据?
决定范围是困难的,主要是因为你不确定你想要进入的方向。这完全没问题,但是更具体地确定一个方向,去做它并决定不做它,与确定你的路径相比,需要更少的后续问题,因为你在问问题,这也可能导致混乱。
因为提问是一项你可以随着时间磨练的技能,随着时间的推移,这方面会变得更加舒适,你的“好”问题组合的大小也会增加。
#3:具体来源
来源指的是你问这个问题的广义对象。合理吗?例如,你走进一家餐馆,问一个关于暗物质为什么存在的完美框架的问题。有意义吗?绝对不行。
提问时你在哪里寻找答案至关重要。尽管这可能主要是由你的“估计”驱动的,但你肯定是错的。在一个城市里向游客 a 问路,向谷歌寻求对一个论文问题的回应,甚至只是向错误的朋友寻求帮助,都是浪费时间,如果不是完全错误的话。
你想关注的是富士山指标:你想问一个一语中的问题,为了做到这一点,你必须瞄准正确的方向——答案的来源。
像#2 一样,这方面也会随着时间的推移而发展,但在此之前,你也可以问“前置问题”来确定来源。前置问题与跟进问题的美妙之处在于,前置问题在你提问之前给你指明了方向(你可以记住它以便下次提问),而跟进问题在提问过程中寻找方向。
如果你已经通过阅读上面的所有内容完成了这一点,那就太好了!你已经向顶峰迈出了第一步!但是如果你想测试你的问题有多好呢?一种可能是将它粘贴到谷歌中,然后点击“我感觉很幸运”按钮,这将绕过搜索结果页面(有多个结果),直接进入你所提问题的排名第一的页面。如果你的问题足够好,你就会找到答案。这是我们的理想场景。
祝你在提问过程中好运,并让我知道进展如何!你可以通过 LinkedIn 或 Twitter 联系我。
如何用排列测试评估数据的统计显著性
随机抽样可以帮助您评估数据的统计显著性。下面是如何用几行 Python 代码实现的。
在处理统计数据时,随机性可能是我们手头最强大的现象之一。它可能不那么明显,但在正确的范围内,它可以帮助我们发现数据中隐藏的模式。传统上来说,我们依靠分析解决方案来进行假设检验。想想比较两个分布的平均值的 t 测试,或者测量两个变量之间的线性相关性的皮尔逊相关。这些统计值的意义总是依赖于一个 p 值。如果我们不知道其 p 值,0.30 的相关性没有任何意义,因为相关性分数可以用机会来解释。像这样,任何统计数据的解释都与它有关,它越小,我们看到的模式被偶然解释的概率就越低。
这些参数检验的缺点是它们依赖于假设(如 example⁴数据的正态性),并且只有一个目的。双样本 t 测试可以帮助您确定两个正态分布的平均值是否存在显著差异。中位数,众数,峰度,偏度等呢?两个分布的?可以认为它们在统计学上是不同的吗?这个问题不能用这个测试来回答。为此,我们可以利用随机性。
在这里,我将展示一个非常简单的方法,你可以使用随机排列 testing⁵.来测试几乎任何你想要的统计数据的显著性我假设你已经知道 Python 中的简单编码,并且理解基本的代数和统计。在本教程结束时,我希望你知道如何应用这种强大的技术来评估你自己数据中的统计显著性。我们开始吧!

Permuting a color grid means shuffling it! The proportion in the data is the same, but the structure is lost with every new iteration.
排列测试基本上是在做这张图片正在做的事情,但是是对我们的数据。我们将所有东西混在一起,形成一个大的数据池,然后将这个数据池与混洗前的数据池进行比较。不完全是这样,但是你可以知道我们在这里要做什么。
一般来说,我们会用到两种排列测试。第一个是评估两个分布之间的统计差异被偶然解释的概率。考虑一个 t 测试,但是对于任何你想要的度量,不仅仅是平均值。第二是测量两个变量(相关性、相互 information⁵等)之间的相关性被偶然解释的概率。这个概率越低,你的测试的意义就越高。
我将坚持使用鸢尾花数据集,它可以在sklearn中找到,利用它我们可以很容易地探索特征之间的统计意义。在构建置换算法之前,让我们导入所有模块并加载数据集:
测量两个变量之间度量差异的显著性的算法
构建该算法的分步指南如下所示:
1。选择你的度量标准,我们称之为 τ 。这可以是任何分布度量,如平均值、中值、峰度等。我选择了平均值,并将只对第一个特征(萼片长度)进行排列测试,在北美鸢尾和杂色鸢尾之间,你可以根据你想要的任何度量/特征改变它。
2。根据你的两个变量计算 τ ₁和 τ ₂之间的地面真实绝对差值δτ:

或者在我们示例的代码中:
gT = np.abs(np.average(feat_vir[:,0]) — np.average(feat_ver[:,0]))
3。将你的变量集中到一个单一的分布中:
pV = list(feat_vir[:,0]) + list(feat_ver[:,0])
4。随机采样(也称为自举)而不替换两个大小与该汇集分布的原始分布相等的分布,以计算两个置换样本之间的度量的绝对差Rδτ:

并且重复这个 p 次(这里我们会做 1000 次):
5。最后,置换差高于你的地面真值差的比例就是你的显著性值:
p_val = len(np.where(pD>=gT)[0])/p
就是这样!看起来是这样的:

Blue represents all permuted differences (pD) for sepal length while thin orange line the ground truth computed in step 2.
嘣!这基本上意味着我们的地面真实差异(gT)远远高于随机重采样产生的 1000 个差异。没有置换的差异更高,所以我们可以说,这两个变量的平均值之间的差异很难解释。这两个物种的相同特征之间的参数值测试怎么样?
stats.ttest_ind(feat_vir[:,0], feat_ver[:,0])
Ttest_indResult(statistic=5.629165259719801, pvalue=**1.7248563024547942e-07**)
也非常重要。明白我的意思了吗?更进一步,比较第二个特征(萼片宽度)与一个t-测试抛出一个 p - 值为 0.0018。仍然很重要,但不像另一个那么低。我们的排列测试怎么办?

Blue represents all permuted differences (pD) for sepal width while thin orange line the ground truth computed in step 2.
太棒了。更令人惊讶的是,我们置换的 p - 值为 0.001(很少是偶然解释的),与我们传统的t-测试中一模一样!
这两种方法都可以用来评估均值的显著差异,但请记住,排列可以用于任何其他指标。现在,让我们构建统计相关性的算法,并使用皮尔逊相关性作为我们的 τ 。
测量两个变量之间相关性显著性的算法
对于这个例子,我将选择测量鸢尾的萼片长度和萼片宽度之间的线性相关性的显著性。这些变量之间的散点图如下所示:

好消息是步骤几乎相同。唯一的区别是,我们不是计算绝对差值,而是简单地计算相关性 τ ,就像基本事实的皮尔逊相关性,以及在每个置换步骤中,同时仅改变一个变量并保持另一个 intact⁷.在代码中是这样的:
打印 p_val 抛出一个 0,这再次意味着高度重要!最后,这些置换关联看起来像这样:

Blue represents all permuted correlations while thin orange line the ground truth.
已解决的难题

Photo by Hans-Peter Gauster
通过本教程,您应该能够将这种技术应用到您自己的数据中。请记住,您可以使用任何您想要的统计指标/依赖关系。也许你想测量两个变量的峰度是否不同?没问题。两个变量之间相互 Information⁶的显著性?没什么大不了的。这种方法让你在所有这些类型的情况下。
编码快乐,感谢阅读!
参考资料:
[1]关于 t 检验的文章:https://medium.com/@kangeugine/hypothesis-test-21795f788f7d
[2]关于皮尔逊相关性的一句话:https://medium . com/@ silent flame/Pearson-correlation-A-mathematical-understanding-c9aa 686113 CB
[3]一篇关于 p 值含义的文章:https://towardsdatascience . com/p-values-explained-by-data-scientist-f40a 746 cf c8
[4]哈塞米,a .,& Zahediasl,S. 统计分析的正态性检验:非统计人员指南(2012)《国际内分泌与代谢杂志》, 10 (2),486。
[5] Ojala,m .,& Garriga,G. C. 研究分类器性能的排列测试(2010)《机器学习研究杂志》,11(6 月),1833–1863。
[6]曾,G. 互信息的统一定义及其在机器学习中的应用(2015)工程中的数学问题, 2015 。
[7]Fran ois,d .,Wertz,v .,& Verleysen,M. 互信息特征选择的排列检验(2006)ESANN(第 239-244 页)。
如何攻击机器学习(规避、投毒、推理、木马、后门)

Gerd Altmann Pixabay
在我之前的文章中,我提到了三类人工智能威胁(间谍、破坏和欺诈)。如果从技术层面来看,攻击可能发生在两个不同的阶段:训练或推理阶段。
UPD 2021: 这里你可以找到关于 AI 和 ML 攻击的最新报告
训练期间的袭击比你想象的更频繁。大多数生产 ML 模型定期用新数据重新训练它们的系统。例如,社交网络不断分析用户的行为,这意味着每个用户都可能通过修改行为来重新训练这个系统。
根据攻击者的实际目标(间谍、破坏、欺诈)和机器学习管道的阶段(培训和生产),对 ML 模型的攻击有不同的类别,或者也可以分别称为对算法的攻击和对模型的攻击。它们是规避、中毒、特洛伊木马、后门、重新编程和推理攻击。现在最普遍的是逃避、投毒和推断。简单地看一下它们(表 1)。

回避(对抗性例子)
规避是在推理过程中对机器学习模型进行的最常见的攻击。它指的是设计一个输入,这个输入对人类来说似乎是正常的,但是被 ML 模型错误地分类了。一个典型的例子是在上传之前改变一张图片中的一些像素,这样图像识别系统就无法对结果进行分类。事实上,这个对立的例子可以愚弄人类。见下图。

图 1。人类的反面例子
根据模型、数据集和其他属性,可以使用不同的方法来执行这种攻击。自 2004 年发布名为“对抗性分类”的研究以来,已有超过 300 篇研究论文考虑了 arXiv 的类似主题,大约相同数量的论文描述了各种保护措施。
人们的兴趣越来越大——见图表。2018 年的统计数据是在 7 月份收集的,因此预计今年年底至少会增加一倍。

图二。Arxiv 上关于对抗性攻击的研究论文的大概数量。
在选择正确的攻击方法之前,应该考虑一些限制:目标、知识和方法限制。
目标限制(定向对非定向对通用)
假阳性闪避,这是什么?想象一下,有人想要对结果进行错误分类,比如说,绕过拒绝除高层管理人员之外的所有员工的访问控制系统,或者只需要用错误的预测来淹没系统。这是某种形式的假阳性逃避。
事实上,有针对性的攻击比无针对性的攻击更复杂,但完整列表如下所示:
- 信心降低——我们没有改变一个职业,但却极大地影响了信心
- 错误分类——我们改变了一个没有任何特定目标的类
- 有针对性的错误分类——我们将一个类别更改为一个特定的目标
- 源/目标分类错误—我们将特定源更改为特定目标
- 普遍的错误分类——我们可以将任何来源改变成特定的目标
知识限制(白盒、黑盒、灰盒)
与任何其他类型的攻击一样,对手在了解目标系统方面可能有不同的限制。
黑盒方法——攻击者只能向系统发送信息并获得关于某个类的简单结果。
灰箱方法——攻击者可能知道数据集或一种神经网络、其结构、层数等的详细信息。
白盒方法-关于网络的一切都是已知的,包括训练该网络的所有权重和所有数据。
方法限制(l-0,l-1,l-2,l-无穷大—范数)
方法限制与可以对原始数据执行的更改有关。例如,如果谈论图像识别,改变较少的像素,反之亦然——稍微修改尽可能多的像素。或者介于两者之间。
事实上,基于 l-infinity 范数(最大像素差)的攻击更频繁,也更容易执行。然而,它们不太适用于现实生活,因为微小的变化会被相机的质量所抵消。如果攻击者有一张图片,并对多个像素进行小的扰动,他们就可以欺骗模型。如果他们有一个真实的对象和一个系统来制作这个对象的照片,然后将这个照片发送到 ML 系统,那么相机很有可能识别大多数干扰,并且被干扰的对抗性示例的照片将不再是对抗性的。因此,使用 l-0 或 l-1 范数的攻击看起来更真实并且更难执行。除图像之外的另一个约束可以是其他类型的数据。对于其他数据(如文本或二进制文件),约束可能更加严格,因为不可能改变许多输入特征。创建将绕过分析解决方案的恶意软件提出了更复杂的任务,因为输入特征可以具有甚至更少的要改变的选项,使得所产生的恶意软件示例将绕过检测算法并执行其功能。
白盒对抗性攻击
让我们从理论转向实践。对抗性攻击的第一个例子是基于流行的手写数字数据库演示的。它说明了可以对一个数字的初始图像进行微小的改变,从而使其被识别为另一个数字。这并不是系统混淆“1”和“7”的唯一例子。存在从每 10 个数字到每 10 个数字的所有 100 种可能的数字错误分类的例子。
那是以一种人们无法识别赝品的方式进行的。进一步的研究表明,图像的微小扰动可能导致错误分类,系统识别出一辆汽车而不是一只熊猫。
目前有超过 50 种方法来欺骗 ML 算法,我会给你一个例子。
首先,我们计算一个依赖矩阵,即所谓的雅可比矩阵,它显示了每个输入特征(对于图像,输入特征是像素值)的输出预测(结果类)的变化。之后,对图片进行修改,改变其最有影响的像素。如果有可能通过一点优化的强制对结果进行错误分类,选择下一个像素再试一次。结果令人印象深刻,但并非没有缺点。这是在白盒模式下完成的。这意味着研究人员曾经用众所周知的架构、数据集和响应来攻击一个系统。这似乎只是一个理论,在现实生活中不太现实和可实施。他们的研究不久后被另一个团队(https://arxiv.org/pdf/1707.03501.pdf)更新。
2017 年 7 月,一篇题为“对深度学习模型的强大物理世界攻击”的文章发表,揭示了识别系统可能会被愚弄,自动驾驶汽车可能会对路标进行错误分类。该实验以静态和动态模式进行,从不同角度捕捉视频,准确率为 84%。此外,他们使用艺术品和涂鸦来掩饰类似常规破坏行为的袭击。
有超过 100 篇关于 50 种不同攻击的研究论文,如 BIM、DeepFool、JSMA、C&W 等。

图片。3.对抗性攻击示例
给一幅描绘熊猫的图像添加一些噪声,将有助于将其归类为长臂猿的图片。
灰盒对抗性攻击或可转移性攻击
2016 年,第一项引入灰箱攻击的研究浮出水面。事实上,在白盒和黑盒之间有多个层次。灰盒意味着一个人知道一些关于系统的信息,它的体系结构或者其他什么。大多数流行的解决方案使用公开可用的架构,如 Google。“针对机器学习的实际黑盒攻击”研究表明,通过发送各种输入和收集输出,可以从黑盒系统中收集信息。然后你要根据这些例子训练替身模型,发动攻击。因此,对立的例子是可以转移的。如果有人能够破解一个模型,他或她很可能会破解相似的模型。原来,所有以前的研究例子考虑白盒攻击可能被用来执行黑盒攻击。
这还不是最糟糕的部分。在现实生活中,你甚至不需要数据集。这些网络在数据处理方面存在弱点,例如在卷积层。2017 年的许多研究论文表明,有可能制作一个通用的对抗性例子,可以从一种模式转移到另一种模式。其实知道数据集是没必要的。

图片。4.型号可移植性比较
正如你在图中看到的。4、圆顶模型具有接近 100%的可转移性。
黑盒对抗性攻击
这种可转移性不行怎么办?我们能做点什么吗?
原来我们可以!
通过对模型的黑盒访问,可以进行更改,而模型将无法识别初始图片。有时候只用一个像素就能达到目的。还有许多其他奇怪的方式。我最喜欢的方法之一是当我们向 NN 展示一辆车,但它认出了一只猫。为此,我们拍一张汽车的照片,稍微把它变成一只猫,同时保持 NN 回答它仍然是一辆汽车。这里有一个相反的技巧:不是通过稍微修改像素来改变我们的源到目标,他们取了一个目标,并开始在源的方向上改变像素,同时根据需要保持模型输出相同。

图片。5.一步一步的猫对狗的错误分类
对抗性重新编程
2018 年,研究人员分享了一些奇妙的发现,考虑到一种叫做对抗性重新编程的新型攻击。这是对人工智能模型进行破坏攻击的最真实的场景。顾名思义,该机制基于使用特殊图像对神经网络算法进行远程重新编程。对抗性攻击允许他们创建类似于特定噪音和一个大黑方块中的几个小白方块的图像。他们选择图片的方式是,例如,网络认为黑色背景上有白色方块的噪音是一只狗,有两个白色方块的噪音是一只猫,等等。总共有 10 张照片。
因此,研究人员拍了一张照片,上面有准确数量的白色方块作为背景
输入,然后系统用特定的动物产生结果。回应成功了
可以看到图中的方块数。
事实上,他们的图像识别系统后来变成了一个可以计算图片中正方形数量的模型。从更广阔的角度考虑。攻击者可以使用一些用于图像识别的开放机器学习 API 来解决他们需要的其他任务,并使用目标 ML 模型的资源。

图片。6.将 ImageNet 分类器转换为平方计算器
隐私攻击(推理)
看一看另一类攻击。目标是间谍活动和保密。
攻击者的目的是探索系统,比如模型,或者可以进一步派上用场的数据集。
鉴于大量的系统和专有算法,目标之一是获得关于人工智能系统及其模型的知识——模型提取攻击。
对于处理数据的攻击,可以借助属性推理,通过成员推理和数据属性等攻击来检索数据集的信息。最后,模型反转攻击有助于从模型中提取特定的数据。
目前大多数研究涵盖了生产阶段的推理攻击,但它们也可能发生在训练阶段。如果我们可以注入训练数据,我们就可以根据这些数据了解算法是如何工作的。例如,如果我们想了解一个社交媒体网站如何决定你属于一个目标受众,比如说,一群孕妇,以便向你展示一个特定的广告,我们可以改变我们的行为,例如,试图搜索有关 dippers 的信息,并检查我们是否收到了针对未来妈妈的广告。

图片。7.ML 模型的三种隐私攻击
成员推理和属性推理
成员关系推断是一种不太常见的攻击类型,但却是第一种,并且是数据提取的处理器。成员推断是一种攻击,我们想要知道一个特定的例子是否在数据集中。如果谈到图像识别,我们希望检查特定的人是否在训练数据集中。这是理解 AI 厂商如何遵循隐私规则的一种方式。
此外,它还可以帮助计划进一步的攻击,例如基于可转移性的黑盒规避攻击。在可转移性攻击中,您的数据集与受害者数据集越相似,您训练您的模型与受害者模型相似的机会就越多。属性推断有助于您提取有关训练数据的有价值的信息(例如,语音识别模型中说话者的口音)。
属性推断(猜测数据类型)和成员推断(特定数据示例)至关重要,这不仅是因为隐私问题,也是规避攻击的探索阶段。你可以在关于这个主题的第一篇论文中找到更多细节——“针对机器学习模型的成员推理攻击

图片。8.成员推理攻击
成员推断攻击是猜测这只特定的狗是否在训练数据集中。
输入推断(模型反演、数据提取)
输入推理或模型反演是迄今为止最常见的攻击类型,已有超过 10 篇不同的研究论文发表。与成员资格推断不同,在成员资格推断中,您可以猜测您的示例是否在训练数据集中,而在这里,您可以实际从训练数据集中提取数据。在处理图像时,有可能从数据集中提取某个图像,例如,只要知道一个人的名字,就可以得到他或她的照片。就隐私而言,这对任何系统都是一个大问题,尤其是在 GDPR 合规蓬勃发展的今天。
另一篇论文描述了针对 ML 模型的攻击的一些细节,该模型用于根据患者的基因型【https://www.ncbi.nlm.nih.gov/pubmed/27077138来辅助医疗。维护患者个人和医疗记录的隐私是医疗保健领域的一项重要要求,也是许多国家的法律规定。

图片。9.输入推理示例。左边是从模型中恢复的原始图片。
参数推断(模型提取)
参数推断或模型提取是不太常见的攻击,公开研究论文不到 12 篇。这种攻击的目标是知道确切的模型,甚至是模型的超参数。这些信息对于黑盒环境中的规避等攻击非常有用。
一篇关于规避攻击的最新论文使用一些模型反演方法,利用现有知识更快地执行攻击。我相信第一个关于推理攻击的实用信息是在 2013 年发表在“用更聪明的机器入侵智能机器:如何从机器学习分类器中提取有意义的数据”中

图。10.模型参数提取算法
中毒
中毒是另一类攻击,可以认为是最普遍的攻击之一。使用噪声数据进行学习实际上是一个老问题,可以追溯到 1993 年— “在存在恶意错误的情况下进行学习” —和 2002 年,然而,这些案例都是关于少量噪声数据有机发生的,而中毒意味着有人故意试图利用 ML 模型的过程。对 ML 的中毒攻击始于 2008 年的一篇文章,标题为“利用机器学习颠覆你的垃圾邮件过滤器”。本文给出了一个攻击垃圾邮件过滤器的例子。后来,发表了 30 多篇关于中毒攻击和中毒防御的其他研究论文。
中毒和逃避是不同的。首先,可以有不同的目标,如有针对性的和无针对性的攻击。下一个区别是环境限制,简单地说,就是我们到底能做什么来执行攻击。我们可以注入任何数据还是只注入有限的类型?我们可以注入数据并标记它,只注入它还是只标记现有的数据?
有四种宽泛的攻击策略可以根据对抗能力改变模型:
标签修改 :这些攻击允许对手单独修改监督学习数据集中的标签,但对于任意数据点。通常受到总修改成本的限制。
数据注入 :对手无法访问训练数据以及学习算法,但有能力向训练集增加新数据。通过将对立样本插入训练数据集中,有可能破坏目标模型。
数据修改 :对手没有访问学习算法的权限,但有完全访问训练数据的权限。在用于训练目标模型之前,可以通过修改数据来直接毒化训练数据。
逻辑腐败: 对手有能力干预学习算法。这些攻击被称为逻辑讹误。
投毒攻击是如何运作的?这一切都始于 2012 年对 SVM 等更简单的分类器的投毒攻击。SVM 方法在不同类别之间画出了决策界限。该算法输出一个分类新实例的最佳超平面。在二维空间中,这个超平面是一条将平面分成两部分的线,其中每一类例子位于该线的不同侧。
请看下图,因为它详细说明了毒药攻击以及与经典对抗性攻击的比较。

图片。11.对抗性攻击和中毒攻击的比较
中毒攻击改变分类界限,而对抗性攻击改变输入示例(见图。11).
如果我们给训练数据增加一个点,决策边界就会改变。如果我们展示我们的目标对象,它将在一个不同的类别。实际上,神经网络模型也可以用同样的方法被愚弄。就把这张图想象成我们复杂神经网络最后一层的特征。最新的研究甚至提出了一种在不标记数据的情况下毒害复杂神经网络的方法。对手可以将中毒的图像放在网上,等待它们被机器人抓取,在这种情况下,他们想绕过垃圾邮件过滤器,所以他们注入了电子邮件。他们从测试集中选择一个目标实例,比如一封普通的电子邮件。然后,他们从基类中抽取一个基本实例,并对其进行细微的更改,以创建一个病毒实例,然后将病毒图像注入到训练数据中。他们达到了 100%的攻击成功率,值得注意的是,测试准确率仅下降了 0.2%。
还有两种其他攻击类型,如后门和木马。这种攻击的目标和攻击者的类型不同,但从技术上讲,它们与投毒攻击非常相似。区别在于攻击者可以获得的数据类型。
特洛伊宁
中毒时,攻击者无法访问模型和初始数据集,他们只能向现有数据集添加新数据或修改它。至于特洛伊木马,攻击者仍然无法访问初始数据集,但可以访问模型及其参数,并可以重新训练该模型。这什么时候能发生?目前,大多数公司不是从零开始构建自己的模型,而是对现有模型进行再培训。例如,如果有必要为癌症检测创建一个模型,他们会采用最新的图像识别模型,并用数据集对其进行重新训练,因为缺乏数据和癌症图像不允许从头开始训练复杂的模型。这意味着大多数人工智能公司从互联网上下载流行的模型,黑客可以用自己的修改版本替换它们。
Trojaning 的想法是发现在某些情况下改变模型行为的方法,使现有行为保持不变。如何在注入任何数据后重新训练系统,使其仍然执行原来的任务?研究人员找到了一种方法——首先,从模型中减去数据集,然后将其与新的输入相结合,然后重新训练模型。我不会深入细节,但推荐阅读这篇研究论文。

图 12。木马攻击算法
走后门
即使在黑盒和灰盒环境中,以及在访问模型和数据集的完全白盒模式下,模型的行为修改(如中毒和特洛伊木马)也是可能的。尽管如此,主要的目标不仅仅是注入一些额外的行为,而是以这样一种方式来实现,即在重新训练系统之后,后门将会运行。
下一次攻击是在 2017 年重点强调的。这个想法来自最古老的 IT 概念之一,即所谓的后门。研究人员想教一个神经网络来解决主要任务和特定任务。
基于两个主要原则,攻击有可能在全球范围内发生:
- 用于图像识别的卷积神经网络表示由数百万个神经元形成的大型结构。为了对这种机制做出微小的改变,有必要修改一小组神经元。
- 能够识别诸如 Inception 或 ResNet 等图像的神经网络的操作模型是复杂的。他们受过海量数据和计算能力的训练,这是中小公司几乎不可能再造的。这就是为什么许多处理 MRI 或癌症照片等图像的公司会重用大公司预先训练好的神经网络。因此,原本旨在识别名人面部的网络开始检测癌变肿瘤。
- 犯罪分子可以黑客攻击存储公共模型的服务器,并通过后门上传他们自己的模型,神经网络模型将保留模型重新训练后制作的后门黑客。
例如,NYU 的研究人员证明,即使他们重新训练系统识别瑞典而不是美国的路标,他们的路标检测器中内置的后门仍然活跃。实际上,如果你不是专家,几乎不可能发现这些后门。幸运的是,不久前,研究人员发现了解决方案。我可以肯定的说,以后也会绕过这个机制。

图 13。后门攻击示例
总结
最后,简单地说,我们现在没有列出的问题的最佳解决方案,也许,我们根本无法发明一个通用的解决方案。听起来很悲伤,但是等等!有一些东西启发了我——人工智能系统很容易受到攻击的事实。为什么?既然我们知道这个秘密武器,我们就不应该害怕 AI 和人类之间的任何战争。
订阅阅读关于人工智能安全的新文章,因为这只是开始,我们应该了解更多关于防御的知识。
如何吸引数据科学家,以及如何留住他们!采访

这篇采访最初于 2019 年 6 月 19 日由创业公司的杰克·惠特尔在领英上发布。

几周前,我与 Jan Teichmann(zoo PLA 数据科学家负责人)坐下来讨论如何吸引最好的数据科学家,以及如何将他们留在贵公司。
这是简必须要说的…
您为什么成为数据科学家?
“数据科学仍然是技术创新的代名词,和许多早期的数据科学家一样,我一直被好奇心和技术所驱动。这和对数学的热情。起初,我看到了我在学术界的使命,但我无法真正决定我想研究什么。我开始非常重视数学和理论生物学。然而,我忽略了技术方面。我进入生物信息学是为了更多地了解应用计算机科学、算法和数据处理,只是为了回到数学领域攻读博士学位。随着我作为一名科学家的成熟,我意识到我有强烈的创业和商业倾向。因此,我与能源行业的朋友共同创办了一家初创公司,目的是利用新兴的云技术来提供数据产品,并以此改造整个公用事业行业。梦想远大,从小处开始!如今,数据转型响彻每个行业,但在那时,看到数据和机器学习在新兴智能电网领域的强大威力,人们大开眼界。这成为我后来工作中反复出现的一个主题,数据和机器学习继续对两者都产生真正的影响,对业务和消费者体验都是如此。这种感觉现在仍然很有力量和动力。”
所以,对数据科学家来说,最重要的事情是看看他们的工作如何产生真正的影响?
“我敢说,大多数数据科学家的动机是解决困难和复杂的问题,每个人都希望看到他们的辛勤工作产生的影响。不仅仅是数据科学家。问题是真正的影响是什么样的,这当然在研究职能部门的数据科学家和企业的商业数据科学团队之间有很大的不同。目前,企业中老一套的数据科学家正在努力产生真正的影响。根据 Gartner 和 NewVantage 的研究,超过 75%的商业数据科学项目和团队无法交付业务成果。对大多数企业来说,让数据科学取得商业成功确实很难。原因很复杂,但在很大程度上是将数据科学部署到生产中的挑战。生产化是数据科学中最棘手的问题。”
促进这一点的最重要方式是什么?
“如果我们看看 Gartner 炒作周期,我们目前正处于数据科学和人工智能炒作的巅峰。以目前商业数据科学项目的成功率来看,我们正直接走向幻灭的低谷。我们迫切需要重新关注成功的要求。不幸的是,成功没有灵丹妙药或捷径!挑战是复杂的,也经常被误解。有五个总体主题,我刚刚写了一篇关于它们的文章,主题是走向数据科学。
一些主题得到了很好的理解和广泛的讨论,如文化的重要性。其他主题突出了一些误解,例如,这些误解导致低估了技术在留住数据科学团队中的重要性。"
你是如何在你的团队中做到这一点的?
“我们是一个高度产品化公司中的集中专家团队。公司文化在将数据科学与业务的其余部分结合起来方面发挥着重要作用。集中的团队可能会变得孤立,尤其是在大公司。我们刚刚组织了一次全公司范围的黑客马拉松,这是一次与产品团队沟通和展示数据科学价值的绝佳机会。公司文化对数据科学的成功至关重要。正如彼得·德鲁克(Peter Drucker)恰如其分地说的那样:“文化把战略作为早餐”。
同时,团队文化在留住数据科学家方面发挥着至关重要的作用。我很幸运有一个非常聪明、高度积极和富有成效的团队。但我们产品的业务适应可能会很慢,并导致挫折。幸运的是,在数据科学领域有一个强大的社区,有很多机会在聚会上和通过博客帖子展示工作。我们还为数据科学创建了一个职业框架,并利用我们丰富的数据集和业务挑战积极创造一个促进学习和发展的环境。我们认识到需要在不断变化的领域(如数据科学)中学习和发展,这是团队的一个独立目标。"
好了,你已经了解了正确的文化,那么技术和结构呢?
“对数据基础设施有明显的要求:任何数据团队都需要访问高质量的数据和合适的基础设施来处理这些数据。基础设施还需要一定程度的敏捷性。正如您将看到的,大多数数据科学项目(希望不是团队)都非常短暂,并且失败率很高。你根本不知道数据会把你带到哪里,也不知道在每个想法的结尾是否有一个可行的模型。为了保持生产力,基础设施需要敏捷性来支持失败率高的短期项目。数据科学的生产部署有许多独特的要求,我写了一整篇文章介绍作为我支持的解决方案的 Rendezvous 架构。
要将数据科学投入生产,了解数据科学是一项团队运动是很重要的。成功需要数据科学家与工程、数据架构、开发运维及产品等其他职能部门的合作。最后,这种支持是存在于跨职能团队内部,还是可以通过团队和部门之间的良好协作和强大的优先级划分来获得,对于数据科学的成功并不重要。"
所以你做对了,那么你如何让你的团队开心呢?
“用 DataOps!
我们已经谈到了文化的重要性,但更独特的是数据科学,技术在保持团队长期快乐方面发挥着重要作用。
可扩展的交付管道和快乐的数据科学家之间有着重要的联系。
数据科学家的动机是开发新模型来解决相关的业务问题,而不是模型在生产中的日常运营责任。这意味着,数据基础设施、数据科学平台、自动化和数据运营不仅对于业务成果的交付,而且对于团队的长期保留都是至关重要的问题。在一个超过 75%的团队未能做到这一点的市场中,任何将模型端到端交付到生产中的数据科学家都变得非常有价值。对生产中的模型进行日常维护和监控并不是留住人才的好方法。很快,您会发现自己的产品中有一个无人维护的模型,这个模型正在漂移,没有人知道这个模型最初是如何工作的。
交付、技术和保留都与数据科学的长期成功紧密相关。"
为了让这些新项目继续下去,让一家公司专注于数据战略有多重要?
“这很关键。数据科学是企业正在进行的数据转型的一部分,以实现数据驱动。这引发了许多变化,需要战略协调和最高层的支持。根据我的经验,数据科学需要一个由长期愿景而非短期目标驱动的企业。数据应该得到与公司其他产品同样的战略关注,甚至更多。数据是新的石油,太多的公司仍然把它当作事后的想法。您的数据战略将是关键,决定您是否有一个改变游戏规则的数据科学项目路线图,或者一个被放弃的数据科学团队和大量没有回报的沉没成本。”
Jan,你能总结出培养和留住数据科学家的几个关键步骤吗?
“成功没有灵丹妙药或捷径,我们需要重新关注数据科学成功的复杂要求。请阅读我的文章来了解更多我们今天没有时间讨论的话题。
企业需要超越宣传,对数据科学及其随之而来的数据转换更具战略性。但不仅仅是企业,数据科学家也需要开始问一些重要的问题:
动机:这仅仅是另一个虚荣的项目还是与商业战略一致?
需求:是否有坚实的基础和基础设施,还是只有大量的管道胶带和消防设备?
招聘:招聘流程适合招聘数据科学独角兽吗?
交付:是否有机会生产模型或者只是笔记本电脑上未记录的模型?
****留任:18 个月内会出现改变游戏规则的数据科学项目路线图,或者一个被放弃的团队吗?"

Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。
****在 LinkedIn 上连接:【https://www.linkedin.com/in/janteichmann/】
****阅读其他文章:https://medium.com/@jan.teichmann
如何自动化超参数优化
将贝叶斯优化与 Scikit-Optimize 结合使用的初学者指南

在机器学习和深度学习范例中,模型“参数”和“超参数”是两个经常使用的术语,其中“参数”定义模型内部的配置变量,其值可以从训练数据中估计出来,而“超参数”定义模型外部的配置变量,其值不能从训练数据中估计出来()参数和超参数之间有什么区别?)。因此,超参数值需要由专业人员手动指定。
我们制作的每个机器学习和深度学习模型都有一组不同的超参数值,需要进行微调才能获得满意的结果。与机器学习模型相比,深度学习模型往往具有大量需要优化的超参数,以便获得所需的预测,这是由于其架构比典型的机器学习模型复杂。
手动重复试验不同的值组合以获得每个超参数的最佳超参数值可能是一项非常耗时且乏味的任务,需要良好的直觉、丰富的经验和对模型的深刻理解。此外,一些超参数值可能需要连续值,这将具有未定义数量的可能性,即使超参数需要离散值,可能性的数量也是巨大的,因此手动执行这项任务相当困难。说了这么多,超参数优化似乎是一项艰巨的任务,但由于网络上有几个现成的库,这项任务变得更加简单。这些库有助于轻松实现不同的超参数优化算法。一些这样的库是 Scikit-Optimize 、 Scikit-Learn 和hyperpt。
多年来,有几种超参数优化算法被频繁使用,它们是网格搜索、随机搜索和自动超参数优化方法。网格搜索和随机搜索都建立了超参数网格,但是在网格搜索中,每个单个值的组合都将被彻底地探索,以找到给出最佳精度值的超参数值组合,这使得该方法非常低效。另一方面,随机搜索将从网格中重复选择随机组合,直到达到指定的迭代次数,并被证明比网格搜索产生更好的结果。然而,即使它设法给出一个好的超参数组合,我们也不能确定它实际上是最好的组合。自动超参数优化使用不同的技术,如贝叶斯优化,它对最佳超参数进行引导式搜索(使用网格和随机搜索进行超参数调整)。研究表明,贝叶斯优化可以产生比随机搜索更好的超参数组合(超参数调整的贝叶斯优化)。
在本文中,我们将提供一步一步的指导,通过采用使用高斯过程的贝叶斯优化,在深度学习模型上执行超参数优化任务。我们使用由 Scikit-Optimize (skopt) 库提供的 gp_minimize 包来执行这个任务。我们将对使用 TensorFlow 开发的简单股票收盘价预测模型执行超参数优化。
sci kit-优化(skopt)
Scikit-Optimize 是一个比其他超参数优化库相对容易使用的库,并且拥有更好的社区支持和文档。该库通过减少昂贵且嘈杂的黑盒函数,实现了几种基于顺序模型的优化方法。更多信息你可以参考 neptune.ai 的文章,他们对 skopt 的功能和用法做了全面的分析。
使用高斯过程的贝叶斯优化
贝叶斯优化是 skopt 提供的众多功能之一。贝叶斯优化找到一个后验分布作为参数优化过程中要优化的函数,然后使用一个采集函数(如预期改善-EI、另一个函数等)从该后验分布中采样,以找到下一组要探索的参数。由于贝叶斯优化基于考虑可用数据的更系统的方法来决定下一点,因此与诸如网格搜索和随机搜索之类的穷举参数优化技术相比,它有望更快地获得更好的配置。你可以从这里阅读 skopt 中关于贝叶斯优化器的更多信息。
代码警报!
所以,理论说够了,让我们言归正传!
这个示例代码是使用 python 和 TensorFlow 完成的。此外,该超参数优化任务的目标是获得能够为我们的深度学习模型给出最低可能均方根误差(RMSE)的一组超参数值。我们希望这将是非常直截了当的任何第一次。
首先,让我们安装 Scikit-Optimize。您可以通过执行以下命令使用 pip 安装它。
pip install scikit-optimize
请注意,您将必须对现有的深度学习模型代码进行一些调整,以便使其与优化一起工作。
首先,我们来做一些必要的导入。
import skopt
from skopt import gp_minimize
from skopt.space import Real, Integer
from skopt.utils import use_named_args
import tensorflow as tf
import numpy as np
import pandas as pd
from math import sqrt
import atexit
from time import time, strftime, localtime
from datetime import timedelta
from sklearn.metrics import mean_squared_error
from skopt.plots import plot_convergence
我们现在将设置 TensorFlow 和 Numpy 种子,因为我们希望获得可重复的结果。
randomState = 46
np.random.seed(randomState)
tf.set_random_seed(randomState)
下面显示了一些我们已经声明的重要 python 全局变量。在变量中,我们还声明了希望优化的超参数(第二组变量)。
input_size=1
features = 2
column_min_max = [[0, 2000],[0,500000000]]
columns = ['Close', 'Volume']
num_steps = None
lstm_size = None
batch_size = None
init_learning_rate = None
learning_rate_decay = None
init_epoch = None
max_epoch = None
dropout_rate = None
“输入大小”描述了预测形状的一部分。“特征”描述了数据集中特征的数量,“列”列表具有两个特征的标题名称。“column_min_max”变量包含两个特征的缩放上限和下限(这是通过检查验证和训练分割获得的)。
在声明了所有这些变量之后,最后是时候为我们希望优化的每个超参数声明搜索空间了。
lstm_num_steps = Integer(low=2, high=14, name='lstm_num_steps')
size = Integer(low=8, high=200, name='size')
lstm_learning_rate_decay = Real(low=0.7, high=0.99, prior='uniform', name='lstm_learning_rate_decay')
lstm_max_epoch = Integer(low=20, high=200, name='lstm_max_epoch')
lstm_init_epoch = Integer(low=2, high=50, name='lstm_init_epoch')
lstm_batch_size = Integer(low=5, high=100, name='lstm_batch_size')
lstm_dropout_rate = Real(low=0.1, high=0.9, prior='uniform', name='lstm_dropout_rate')
lstm_init_learning_rate = Real(low=1e-4, high=1e-1, prior='log-uniform', name='lstm_init_learning_rate')
如果您仔细观察,您将能够看到我们在 log-uniform 之前声明了“lstm_init_learning_rate ”,而不仅仅是放入 uniform。这样做的目的是,如果您将 prior 设为 uniform,优化器将不得不在均匀分布中从 1e-4 (0.0001)到 1e-1 (0.1)进行搜索。但是当声明为 log-uniform 时,优化器将在-4 和-1 之间搜索,从而使这个过程更加高效。当 skopt 库为学习率分配搜索空间时,这已经被告知。
有几种数据类型可以用来定义搜索空间。它们是绝对的、实数的和整数的。当定义一个包含浮点值的搜索空间时,你应该选择“实数”,如果它包含整数,就选择“整数”。如果你的搜索空间涉及分类值,比如不同的激活函数,那么你应该选择“分类”类型。
我们现在将在“尺寸”列表中记下要优化的参数。这个列表稍后将被传递给‘gp _ minimize’函数。您可以看到,我们还声明了“default_parameters”。这些是我们给每个超参数的默认参数值。记住按照您在“尺寸”列表中列出超参数的顺序输入默认值。
dimensions = [lstm_num_steps, size, lstm_init_epoch, lstm_max_epoch,
lstm_learning_rate_decay, lstm_batch_size, lstm_dropout_rate, lstm_init_learning_rate]
default_parameters = [2,128,3,30,0.99,64,0.2,0.001]
要记住的最重要的事情是“default_parameters”列表中的超参数将是您的优化任务的起点。贝叶斯优化器将使用您在第一次迭代中声明的默认参数,根据结果,采集函数将确定下一步要探索的点。
可以说,如果您之前已经运行过该模型几次,并且找到了一组合适的超参数值,您可以将它们作为默认的超参数值,并从那里开始您的探索。这将有助于算法更快地找到最低的 RMSE 值(更少的迭代)。然而,请记住,这可能并不总是正确的。另外,请记住,在分配默认值时,要分配一个在您已定义的搜索空间内的值。
到目前为止,我们所做的是为超参数优化任务设置所有的初始工作。我们现在将重点关注我们的深度学习模型的实现。我们将不讨论模型开发过程的数据预处理,因为本文仅关注超参数优化任务。我们将在本文末尾包含完整实现的 GitHub 链接。
然而,为了给你更多的背景知识,我们将数据集分成三部分,分别用于训练、验证和测试。训练集用于训练模型,验证集用于执行超参数优化任务。如前所述,我们使用均方根误差(RMSE)来评估模型并执行优化(最小化 RMSE)。
使用验证分割评估的精度不能用于评估模型,因为在超参数优化过程中,使用验证分割最小化 RMSE 的所选超参数可能会过度拟合验证集。因此,标准程序是使用尚未在管道中的任何点使用的测试分割来测量最终模型的准确性。
下面显示的是我们深度学习模型的实现:
def setupRNN(inputs, model_dropout_rate):
cell = tf.contrib.rnn.LSTMCell(lstm_size, state_is_tuple=True, activation=tf.nn.tanh,use_peepholes=True)
val1, _ = tf.nn.dynamic_rnn(cell, inputs, dtype=tf.float32)
val = tf.transpose(val1, [1, 0, 2])
last = tf.gather(val, int(val.get_shape()[0]) -1, name="last_lstm_output")
dropout = tf.layers.dropout(last, rate=model_dropout_rate, training=True,seed=46)
weight = tf.Variable(tf.truncated_normal([lstm_size, input_size]))
bias = tf.Variable(tf.constant(0.1, shape=[input_size]))
prediction = tf.matmul(dropout, weight) +bias
return prediction
“setupRNN”函数包含了我们的深度学习模型。尽管如此,您可能不想理解这些细节,因为贝叶斯优化将该函数视为一个黑盒,它将某些超参数作为输入,然后输出预测。因此,如果你没有兴趣理解我们在函数中有什么,你可以跳过下一段。
我们的深度学习模型包含一个 LSTM 层、一个辍学层和一个输出层。模型工作所需的必要信息需要发送给这个函数(在我们的例子中,是输入和辍学率)。然后,您可以在该函数中继续实现您的深度学习模型。在我们的例子中,我们使用 LSTM 层来识别股票数据集的时间依赖性。
然后,出于正则化目的,我们将 LSTM 的最后一个输出馈送到漏失层,并通过输出层获得预测。最后,请记住将该预测(在分类任务中,这可能是您的 logit)返回给将被传递给贝叶斯优化的函数(“setupRNN”将被该函数调用)。
如果您正在为机器学习算法执行超参数优化(使用 Scikit-Learn 等库),您将不需要单独的函数来实现您的模型,因为模型本身已经由库给出,您将只需编写代码来训练和获得预测。因此,这段代码可以放在将返回给贝叶斯优化的函数内部。
现在,我们来到了超参数优化任务中最重要的部分,即“适应度”函数。
@use_named_args(dimensions=dimensions)
def fitness(lstm_num_steps, size, lstm_init_epoch, lstm_max_epoch,
lstm_learning_rate_decay, lstm_batch_size, lstm_dropout_rate, lstm_init_learning_rate):
global iteration, num_steps, lstm_size, init_epoch, max_epoch, learning_rate_decay, dropout_rate, init_learning_rate, batch_size
num_steps = np.int32(lstm_num_steps)
lstm_size = np.int32(size)
batch_size = np.int32(lstm_batch_size)
learning_rate_decay = np.float32(lstm_learning_rate_decay)
init_epoch = np.int32(lstm_init_epoch)
max_epoch = np.int32(lstm_max_epoch)
dropout_rate = np.float32(lstm_dropout_rate)
init_learning_rate = np.float32(lstm_init_learning_rate)
tf.reset_default_graph()
tf.set_random_seed(randomState)
sess = tf.Session()
train_X, train_y, val_X, val_y, nonescaled_val_y = pre_process()
inputs = tf.placeholder(tf.float32, [None, num_steps, features], name="inputs")
targets = tf.placeholder(tf.float32, [None, input_size], name="targets")
model_learning_rate = tf.placeholder(tf.float32, None, name="learning_rate")
model_dropout_rate = tf.placeholder_with_default(0.0, shape=())
global_step = tf.Variable(0, trainable=False)
prediction = setupRNN(inputs,model_dropout_rate)
model_learning_rate = tf.train.exponential_decay(learning_rate=model_learning_rate, global_step=global_step, decay_rate=learning_rate_decay,
decay_steps=init_epoch, staircase=False)
with tf.name_scope('loss'):
model_loss = tf.losses.mean_squared_error(targets, prediction)
with tf.name_scope('adam_optimizer'):
train_step = tf.train.AdamOptimizer(model_learning_rate).minimize(model_loss,global_step=global_step)
sess.run(tf.global_variables_initializer())
for epoch_step in range(max_epoch):
for batch_X, batch_y in generate_batches(train_X, train_y, batch_size):
train_data_feed = {
inputs: batch_X,
targets: batch_y,
model_learning_rate: init_learning_rate,
model_dropout_rate: dropout_rate
}
sess.run(train_step, train_data_feed)
val_data_feed = {
inputs: val_X,
}
vali_pred = sess.run(prediction, val_data_feed)
vali_pred_vals = rescle(vali_pred)
vali_pred_vals = np.array(vali_pred_vals)
vali_pred_vals = vali_pred_vals.flatten()
vali_pred_vals = vali_pred_vals.tolist()
vali_nonescaled_y = nonescaled_val_y.flatten()
vali_nonescaled_y = vali_nonescaled_y.tolist()
val_error = sqrt(mean_squared_error(vali_nonescaled_y, vali_pred_vals))
return val_error
如上所示,我们将超参数值传递给一个名为“fitness”的函数“适应度”函数将被传递到贝叶斯超参数优化过程( gp_minimize )。请注意,在第一次迭代中,传递给该函数的值将是您定义的默认值,从那里开始,贝叶斯优化将自行选择超参数值。然后,我们将选择的值赋给我们在开始时声明的 python 全局变量,以便我们能够在适应度函数之外使用最新选择的超参数值。
然后,我们来到优化任务中的一个相当关键的点。如果您在本文之前使用过 TensorFlow,您会知道 TensorFlow 通过为您制作的任何类型的深度学习模型创建计算图来运行。
在超参数优化过程中,在每次迭代中,我们将重置现有的图形并构建一个新的图形。这样做是为了最小化图形占用的内存,并防止图形相互堆叠。重置图表后,您必须立即设置 TensorFlow 随机种子,以获得可重复的结果。经过以上过程,我们终于可以宣告 TensorFlow 会话了。
在这之后,你可以像平常一样开始添加负责训练和验证你的深度学习模型的代码。这一部分实际上与优化过程无关,但是在这一点之后的代码将开始利用贝叶斯优化选择的超参数值。
这里要记住的要点是返回为验证分割获得的最终度量值(在本例中为 RMSE 值)。该值将被返回到贝叶斯优化过程,并将在决定它想要探索的下一组超参数时使用。
注意:如果你正在处理一个分类问题,你会想把你的精度作为一个负值(例如-96),因为,即使精度越高,模型越好,贝叶斯函数将继续试图减少这个值,因为它被设计为找到返回给它的最低值的超参数值。
现在让我们把整个过程的执行点,即“主”函数写下来。在 main 函数中,我们声明了“gp_minimize”函数。然后,我们向该函数传递几个基本参数。
if __name__ == '__main__':
start = time()
search_result = gp_minimize(func=fitness,
dimensions=dimensions,
acq_func='EI', # Expected Improvement.
n_calls=11,
x0=default_parameters,
random_state=46)
print(search_result.x)
print(search_result.fun)
plot = plot_convergence(search_result,yscale="log")
atexit.register(endlog)
logger("Start Program")
“func”参数是您希望使用贝叶斯优化器最终建模的函数。“dimensions”参数是您希望优化的一组超参数,“acq_func”代表采集函数,该函数有助于决定应使用的下一组超参数值。 gp_minimize 支持 4 种采集功能。它们是:
- LCB:信心下限
- EI:预期改进
- PI:改善的可能性
- gp_hedge:在每次迭代中概率性地选择上述三个获取函数中的一个
以上信息摘自文件。这些都有自己的优势,但如果你是贝叶斯优化的初学者,尝试使用“EI”或“gp_hedge ”,因为“EI”是最广泛使用的采集函数,“gp_hedge”将从上述采集函数中选择一个,因此,你不必太担心。
请记住,使用不同的采集功能时,您可能需要更改其他参数,这些参数会影响您选择的采集功能。请参考文档中的参数表。
回到解释其余的参数,“n_calls”参数是您想要运行适应度函数的次数。优化任务将通过使用由“x0”定义的超参数值(默认超参数值)开始。最后,我们设置超参数优化器的随机状态,因为我们需要可重复的结果。
现在,当您运行 gp_optimize 函数时,事件流将是:
适应度函数将与传递给 x0 的参数一起使用。将使用指定的历元对 LSTM 进行训练,并将运行验证输入来获取其预测的 RMSE 值。然后,根据该值,贝叶斯优化器将在采集函数的帮助下决定它想要探索的下一组超参数值。
在第二次迭代中,适应度函数将使用贝叶斯优化已经导出的超参数值运行,并且相同的过程将重复,直到它已经迭代了“n_call”次。当整个过程结束时,Scikit-Optimize 对象将被赋给“search _result”变量。
我们可以使用这个对象来检索文档中提到的有用信息。
- x[列表]:最小值的位置。
- fun [float]:函数值最小。
- 模型:用于每次迭代的代理模型。
- x _ iters[列表列表]:每次迭代的函数求值位置。
- func_vals [array]:每次迭代的函数值。
- 空间[Space]:优化空间。
- specs [dict]`:调用规范。
- rng [RandomState instance]:最小化结束时随机状态的状态。
“search_result.x”为我们提供了最佳超参数值,使用“search_result.fun ”,我们可以获得与所获得的超参数值相对应的验证集的 RMSE 值(为验证集获得的最低 RMSE 值)。
下面显示的是我们为模型获得的最佳超参数值和验证集的最低 RMSE 值。如果您发现在使用“search_result.x”时很难确定超参数值的排列顺序,那么它与您在“dimensions”列表中指定超参数的顺序相同。
超参数值:
- 第六步
- lstm_size: 171
- lstm_init_epoch: 3
- 最大纪元:58
- lstm _ learning _ rate _ decay:0 . 54686 . 38686868661
- lstm_batch_size: 24
- lstm _ dropout _ rate:0 . 20015 . 38383838661
- lstm _ init _ learning _ rate:0 . 36867 . 38686868686
最低的 RMSE:2 . 54686 . 38686868661
收敛图
在该图中产生贝叶斯优化最低点的超参数是我们得到的超参数值的最优集合。

该图显示了贝叶斯优化和随机搜索中每次迭代(50 次迭代)记录的最低 RMSE 值的比较。我们可以看到,贝叶斯优化已经能够比随机搜索更好地收敛。然而,在开始时,我们可以看到随机搜索比贝叶斯优化器更快地找到了更好的最小值。这可能是因为随机抽样是随机搜索的本质。
我们终于到了这篇文章的结尾,所以总结一下,我们希望这篇文章通过向您展示找到最佳超参数集的更好方法,使您的深度学习模型构建任务变得更容易。不要再强调超参数优化了。编程快乐,各位极客!
有用的材料:
如何自动将您喜欢的库导入 IPython 或 Jupyter 笔记本

不再需要每天十次输入“进口熊猫作为 pd”
如果您经常使用交互式 IPython 会话或 Jupyter 笔记本,并且厌倦了一遍又一遍地导入相同的库,请尝试以下方法:
- 导航至
~/.ipython/profile_default - 创建一个名为
startup的文件夹(如果它还不存在的话) - 添加一个名为
start.py的新 Python 文件 - 把你喜欢的进口货放在这个文件里
- 启动 IPython 或 Jupyter 笔记本,您喜欢的库每次都会自动加载!
以下是可视化的步骤。一、start.py的位置:

Full path of Python script is ~/.ipython/profile_default/startup/start.py
以下是我的start.py的内容:
现在,当我启动一个 IPython 会话时,我会看到:

我们可以通过检查globals()来确认库已经加载:
globals()['pd']**<module 'pandas' from '/usr/local/lib/python3.6/site-packages/pandas/__init__.py'>**globals()['np']
**<module 'numpy' from '/usr/local/lib/python3.6/site-packages/numpy/__init__.py'>**
我们现在都可以很好地使用我们的交互式会话,而不必键入命令来加载这些库!这也适用于 Jupyter 笔记本。
笔记
- 该文件可以命名为任何名称(
start.py很容易记住),并且在startup/中可以有多个文件。当 IPython 启动时,它们按照字典顺序执行。 - 如果你在 Jupyter 笔记本中运行这个,你不会得到一个带有导入的单元格,所以当你共享笔记本时,确保将
start.py内容复制到第一个单元格中。这将让人们知道你在使用什么库。(作为替代,你可以使用我写的default_cellJupyter 笔记本扩展。) - 如果您在多台计算机上工作,您将不得不重复这些步骤。确保使用相同的
start.py脚本,以便获得相同的导入! - 感谢这个栈溢出回答和官方文档
这当然不会改变生活(不像写数据科学),但每次你启动 IPython 时,它都会为你节省几秒钟。这也是一个有用的演示,展示了如何定制您的工作环境,以尽可能提高效率。你可以通过阅读文档(比如关于 IPython magic commands )找到许多其他的技巧,自己尝试,甚至关注有用的 Twitter 账户。如果你发现自己对一天打十次键盘这样的低效率感到沮丧,不要只是接受,要找到更好的工作方式。
一如既往,我欢迎反馈和建设性的批评。可以在推特上找到我 @koehrsen_will 。
如何避免悲惨的 Airbnb 入住?
用 Python 对 Airbnb 在洛杉矶的数据进行探索性分析

Heat map of Airbnb listings in Los Angeles
我相信不少人对 Airbnb 既爱又恨,一些美好的回忆因 Airbnb 的出色房源而高兴,也夹杂着其他令人失望甚至恐惧的住宿体验。有没有可能选择一个“满意保证”的 Airbnb 住宿,去一个我们从未去过的地方旅行?
我将对来源于 Airbnb 内部的的洛杉矶 Airbnb 数据集进行探索性分析,作为一个例子来演示如何在一个陌生的城市中以省时和准确的方式从数百个可用房源中筛选出一个值得信任的房源。
分析是用 Python 语言完成的。所有的源代码都可以转移到 Airbnb 内部列出的其他城市,并可以在我的 Github 上找到:【https://github.com/jystacy/Airbnb。
数据描述
作为世界闻名的旅游目的地,大量寻求物有所值的游客促进了 2008 年以来洛杉矶 Airbnb 的发展。截至 2018 年 12 月,天使之城的 25487 个主机拥有 43026 个房源。从文章开头展示的热图来看,Airbnb 房源集中分布在一系列旅游景点,从洛杉矶市区、好莱坞、西好莱坞、圣莫尼卡海滩一直延伸到这里。马里布和长滩也有很多上市选择。

我选择了上市获得第一次审查的年份作为上市年份的指标,发现 2015 年后的年增长率稳定在 40%至 60%之间。与此同时,在连续 8 年增长后,新主机从 2016 年开始出现负增长。2018 年,只有 2721 名新主机首次房源加入 Airbnb,数量仅为 2015 年增长高峰时的 58%。新房源和主机的反向增长趋势表明,近三年来,Airbnb 主机中有多个房源的数量有所增加。
住在哪里?
在选择住宿地点时,安全总是一个重要的考虑因素。该网站(www.bestplaces.net)提供犯罪数据,按邮政编码从 1(低犯罪率)到 100(高犯罪率)排列,其粒度比联邦调查局(仅按县)提供的犯罪数据更细。我用 Python 编写了代码来自动收集暴力犯罪数据,并在此基础上创建了一个洛杉矶邮政编码犯罪 choropleth。

对比热图可以看到,最热门的上市区域都避开了洛杉矶最危险的区域。但游客最好不要去市中心以南,并小心市中心、圣莫尼卡海滩和长滩等热点周围的财产和暴力犯罪。有趣的是,这个位于洛杉矶市中心以南、北邻圣莫尼卡高速公路(I-10)的地区几乎没有 Airbnb 房源。这个历史上被称为“中南部”的地区,长期以来一直遭受着集中贫困和高犯罪率的困扰。
P 米是另一个重要的度量标准。在洛杉矶 Airbnb 住宿平均花费 198.74 美元,另一家每晚 83.30 美元的清洁费。不同地区的挂牌价格差别很大。位于海岸和贝弗利山附近的房屋的短期租金价格推高了洛杉矶的平均水平。

Malibu 和 Bel Air 的房源平均价格最高,超过 1000 美元。评分分布表明,这些地区的房源在地理位置、入住服务和主客沟通方面得到了很高的评分,而在价值和清洁度方面的评分相对较低。在洛杉矶,有 13 个房源的价格高于每晚 10,000 美元,其中有 11 个房源属于同一个主机。

Rating distribution of the listings in the zip code areas whose average price per night is higher than $1,000
irbnb 使游客能够通过对清洁度、准确性、登记流程、与主人的沟通、位置和价值进行评级并留下评论来评估列表和他们的体验。其中“价值”是指付出的成本和获得的收益之间的回报(Curhan,Elfenbein,& Eisenkraft,2010)。我检查了所有拥有超过 100 个 Airbnb 房源的社区,发现以下 20 个社区的房源获得了最高的值分。

要选择哪个列表?
什么样的主机可以信任?
在共享经济平台上,陌生人之间的一种新的信任被命名为“分布式信任”(Botsman,2017),这种信任通过代表产品或服务分数、评级或评论的评估机制(Pettersen,2017)得到了脆弱的培育。
主机的可信度部分基于这样一个事实:Airbnb 使用各种方法来验证主机的身份。在这一部分,我想验证这些认证的有效性。
“Ssuper host”是一项每季度审核一次的计划,旨在奖励平均综合评分达到 4.8 分或更高、在过去一年中至少接待过 10 次住宿、在 24 小时内保持 90%的回复率且一年内没有取消预订的主人。Airbnb 通过在他们的个人资料和列表中添加徽章来突出显示这些合格的主机,并为列表搜索优先考虑他们的可见性。t 检验的结果证实了“Superhost”拥有的列表的平均评分显著高于其他列表。

Boxplot of listings’ rating scores between different host groups
为了加强平台上的分布式信任,Airbnb 还鼓励主机上传他们的个人资料照片,并完成个人资料验证。t 检验的结果也验证了主机验证的有效性,而有和没有个人资料图片的主机之间的列表评分没有显著差异。
W 主机取消政策怎么样?Airbnb 为房东提供五种取消选择——灵活、适度、有宽限期的严格、30 天超级严格和 60 天超级严格。前三种政策分别对应于在入住时间前 24 小时、5 天和 14 天取消住宿的全额退款,而后两种政策仅提供 30 天和 60 天取消的 50%退款。

Listing rating score comparison among host groups with different cancellation policies
我的许多朋友倾向于避开有严格取消政策的主人。然而,这并不能保证。正如所料,选择超级严格取消政策的主机的评级分数明显低于其他主机,而选择 14 天严格取消政策的主机仍然是可靠的。相比之下,在 Airbnb 的所有主机中,取消政策适中的主机评分最高。
基于主机分析,理想主机的画像包括完整的配置文件验证、“超级主机”认证和相对灵活的注销策略。
取消保单部分的 ANOVA 分析和事后分析 ( Tukey HSD )的代码也可以在这里查看。由于“严格”类别已完全被“有宽限期的严格”取代,并且数据集中只有 63 个具有“超级严格 30 天”取消政策的列表,我从 Tukey 的 HSD(诚实地说,显著差异)测试中删除了这两个类别。
评分和评论说明了什么?

Scatter plot displaying the relationship between rating score and the number of reviews of listings
建议厌恶风险的客人选择有大量评论的列表。所有每月收到超过 7.5 条评论的列表项在 100 分中被评为不低于 80 分,而所有被评为低于 60 分的列表项每月收到不超过 5 条评论。把评论少的房源排除在外太武断了,尤其是这些新上市的房源。然而,选择具有大量评论的列表将减少遇到不满意停留的概率。
在缩小到点评量可观的优质房源后,如何从甚至多达 700 条的点评中形成房源一目了然的印象?这种印象应该包括对最流行的话题的了解,但也包括对那些不经常出现的话题的了解。通过这种印象传达的信息量应该足以决定是否列名。

Word clouds for three random selected listings
传统的方法——基于单词在列表评论中出现的频率的单词云——对于这项任务有一些明显的问题。如果我们比较以上从三个包含 100 多条评论的列表生成的词云,词云提取的信息提供了高度的同质性,并提出了可读性的问题。
I nstead,基于语义相似度对评论进行聚类,并从每个聚类中提取典型句子,满足了客人对支持快速决策的有效评论摘要的需求。在去除了非英语评论(来自 langdetect 库)和句子标记化(来自 NLTK 库)之后,在句子嵌入方面,我使用了 Skip-Thought model ,该模型考虑了句子中单词的顺序而不仅仅是词频,从而语义相似的句子的嵌入在向量空间中彼此更接近,因此适合于聚类。然后我把高维向量空间中的这些嵌入聚类成预定义数量的聚类。聚类的数量等于总结中句子的数量,在这种情况下,我选择它作为评论中句子总数的第五个根。
从以上列表中获得的示例摘要如下:



Review summary based on Skip-thought clustering involves more amount of information than word cloud. Those who are dog-lovers may select Sherren’s listing. Tom’s listing seems more suitable for tourists. For John’s one, guests need to trade off between the unbeatable location and small size.
最后但并非最不重要的一步是记住,由于在线评论的积极性偏差,签到时的失望或多或少是不可避免的。积极的评论占据了 Airbnb 的评论区,即使考虑到 Airbnb 的双盲或“同步揭示”评论系统。我用情感函数(来自 textblob 库)对每个嘉宾留下的评论进行了情感分析。该函数返回范围为[-1,1]的极性得分,其中 1 表示肯定陈述,-1 表示否定陈述,0 表示中性陈述。大多数评论(98%)绝对不是负面的,尽管结果是基于这样一个事实,即带有一两个投诉的评论与其他正面评论一起出现,仍被职能部门归类为“正面”。
随着共享经济的发展和 Airbnb 的兴起,一批研究者和商业记者(如 Ho,2015;弗拉德金、格雷瓦尔、霍尔茨和皮尔森,2015 年;Yannopoulou 等人,2013 年;泽卡诺维奇-科罗纳&格尔祖诺夫,2014;Zervas 等人,2015)已经注意到 Airbnb 评分的这种异常积极的倾斜。可能的原因包括礼貌和礼貌的社会文化因素,以及恐惧或报复,以及担心自己的网络身份与负面评论相关联(Bridges,j .,& Vásquez,c .,2018)。
希望我们在 Airbnb 陪伴下的下一次旅行会很愉快!
本节中文本挖掘包括文本清洗、词云、聚类摘要的所有代码均可参考:https://github . com/jystacy/Airbnb/blob/master/Review % 20 analysis . ipynb
如何避免数据科学编程环境中的常见困难

减少编程环境中的附带问题,这样您就可以专注于重要的数据科学问题。
考虑以下情况:你正试图练习你的足球技能,但是每次你走上球场,你都会遇到一些问题:你的鞋子穿错了脚,鞋带没有系好,你的袜子太短,你的短裤太长,以及球的大小不对。这是一个荒谬的情况,但它类似于许多数据科学家由于一些常见的、容易解决的问题而发现自己的处境:
- 无法管理库依赖关系
- 代码风格不一致
- 不一致的命名约定
- 团队中不同的开发环境
- 不使用集成开发环境进行代码编辑
所有这些错误都会“绊倒”你,耗费你的时间和宝贵的精神资源去担心小细节。您没有解决数据科学问题,而是发现自己在设置环境或运行代码时遇到了一些附带的困难。幸运的是,使用正确的工具和方法,上述问题很容易解决。在本文中,我们将探讨数据科学编程环境的最佳实践,这将让您有更多的时间和精力来解决重要的问题。
1.无法管理库(依赖项)
最令人沮丧的事情莫过于,某一天编写的代码运行良好,但第二天却发现它有许多错误,而你却没有改变一个字符。几乎每次我遇到这个问题,都只有一个原因:无法跟踪你在代码中使用的库的版本。这个问题如此普遍,如此令人沮丧,以至于它的名字叫做依赖地狱。
为了克服这一点,你必须记住库有版本:当你说你使用pandas,那是不正确的;你实际上用的是pandas==0.24.0或者pandas==0.19.2等等。您在项目中导入的每个库都将是特定于的版本,记录您项目的版本对于避免可怕的代码崩溃是至关重要的。围绕着创建一个隔离环境的想法,有许多解决这个问题的选择:Python 的托管安装,它有自己的独立于系统 Python 的包。
- Python 内置的
[venv](https://docs.python.org/3/library/venv.html):这个是 Python 自带的但是有点难用。 [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html)虚拟环境:使用 conda 包管理器创建和维护虚拟环境。这是我向虚拟环境新手推荐的方法。[pipenv](https://docs.pipenv.org/)(第三方):也用版本控制的Pipfile创建和管理虚拟环境。我发现这个很容易使用。[docker](https://www.docker.com/resources/what-container)容器:容器超越了虚拟环境,包含了运行应用程序所需的所有软件和代码(尽管它并不完全是虚拟机)。Docker 在数据科学中越来越常见,因为你可以将数据、代码和所有需要的库打包在一起,所以学习如何设置和运行 docker 容器是值得的。
( Real Python 在所有这些工具上都有很棒的教程)。
pip freeze > requirements.txt还不够好:您需要使用虚拟环境(可以从requirements.txt创建)来确保库与预期版本相匹配。虚拟 env 也有一个指定的 Python 版本,消除了不同 Python 安装的问题。
你选择的方法取决于你的团队的需求和你想要投入多少时间。例如,我在个人工作中使用 conda 环境,在工作中使用pipenv。我不打算做推荐,除了说:挑一个用吧!在不知道您调用的每个库的版本的情况下,您永远不应该从事数据科学。
不一致的代码风格
如果您必须选择在脚本的每一行使用多少空格,您就没有时间考虑实际的代码了!大部分人的格式化倾向没那么差,但也接近了。你永远不必对代码格式做出有意识的决定:比如关键字参数周围的空格、行的长度、函数之间的空行、列表中最后一项后面的尾随逗号等等;仅处理代码外观的因素。
与其在每一条线上做选择,不如做一个全球性的决定——为你的项目采用一种风格——并且永远不要再担心它。在工作中,我的团队使用了[black](https://black.readthedocs.io/en/stable/) 自动套用格式工具,该工具在我们整个项目中应用了一种标准的代码风格,只是修复了错误——无需去想它。每次在 vscode 中保存 Python 文件时,我都将其设置为自动运行。black工作非常好,也非常容易使用,所以我也把它用于我所有的个人工作。
Python 和其他语言还有其他自动格式化或林挺选项。我建议采用一套代码风格标准,并使用一个工具来检查所有文件的使用情况。在代码格式化上花费比要求更多的精力,这是对你宝贵时间的一种浪费。

No more code format errors thanks to black autoformatting!
不一致的命名约定
在另一个“一次做出全局决定,而不是多次做出局部决定”的应用中,您应该为一个项目建立命名约定。这些应该包括变量、函数、类、文件、测试和目录。命名约定还应包括单位(如kph)和聚合(min、max)的标准化缩写。我在这里写了关于命名变量。
选择精确的约定并不重要,重要的是一致地使用它们。在整个团队(可能只有你自己)中就标准达成一致,把它们写在一个共同的地方,然后毫无偏差地遵循它们。在代码审查中,(另一个至关重要的最佳实践)执行标准,这样每个人都在同一页上。这个小技巧再次告诉我们,必须减少你做出的有意识的决定的数量。当您为函数、变量等编写名称时,应该有一个基于代码和约定的显而易见的选择。
如果你正在挣扎,采用另一个项目使用的标准惯例。不要固执己见,拒绝改变,因为你总是以一种方式做事。在编程中,没有一成不变的个人信念。制定惯例,写下来,应用它们,停止把时间花在数据科学的偶发问题上。
团队中不同的开发环境
团队中的每个人都应该使用相同的开发环境,没有例外。作为一个终生(22 年)的 Windows 用户,我完全没有想过抗议在我目前的职位上使用 MacOS 进行开发(Cortex Building Intelligence)。根本没有选择的余地:其他人都使用 Mac,所以我不得不在整个团队中使用它来实现标准化。我不打算提倡一个系统优于另一个系统(这里是最常用的系统的数字),但我会大声疾呼同一团队中的每个人使用相同的操作系统。
“它在我的机器上有效”是任何数据科学家都不想听到的一句话。即使在使用相同的库时,我也发现了这个问题,因为操作系统不同。当我知道我在我的机器上写的分析可以在其他人的机器上工作时,我们的团队可以更有效率(感谢操作系统和依赖管理)。此外,当我们团队中的任何人需要安装新软件时,我们都可以使用完全相同的命令来完成。对于不得不采用新操作系统的人来说,这并不好玩,但为了团队的利益,这是必要的。

Use the same operating system: no excuses
在笔记本而不是集成开发环境中编写太多代码
纠正这种做法可能是我从研究数据科学背景到行业的最大变化:程序和个人脚本应该在集成开发环境中编写,而不是在 Jupyter 笔记本上。笔记本非常适合探索、学习、绘图和有文化的编程,但是你不应该养成依赖它来编写所有代码的不健康习惯。
Jupyter 笔记本是一个用许多脚本编写实际程序的可怕地方,因为缺少工具:没有林挺,没有跨项目的自动格式化代码,糟糕的文件浏览,没有项目范围的查找和替换,没有内置的测试框架,糟糕的调试,没有集成的终端,等等。不,Jupyter 实验室没有解决这些问题;它仍然不是一个你可以或者应该开发脚本的地方。
打破笔记本电脑是令人生畏的,因为它需要你一次在你的大脑中容纳更多的信息。您需要从由许多函数和类组成的整个脚本的角度来考虑代码,而不是代码块。此外,笔记本呈现了从上到下执行的线性代码路径,而真正的程序有许多互锁的部分形成一个循环。一个脚本可能从你的模块中的 10 个其他脚本中导入,这些脚本在一个复杂的结构中相互作用。
我不想进入编码最佳实践,但是您的开发环境对您如何思考和编写代码有着巨大的影响。一个合适的集成开发环境会让你把数据科学代码看作一个软件产品,而不是孤立的笔记本:一个有许多联锁部分和复杂交互的软件产品。
IDE 有许多很好的选择。我建议尝试几个来找到您需要的合适的复杂性和特性数量。
- Sublime Text 开始是轻量级的,但是有很多插件
- Atom 是另一个很好的基本 IDE,提供了更多的功能包
- Rodeo 试图为 Python 创造一种 RStudio 的感觉
- PyCharm 是一个全功能的环境,拥有比你需要的更多的功能,还需要一点学习过程
我个人使用的 Visual Studio 代码,已经成为软件工程师最喜欢的编辑器。vscode 通过扩展(包括内置浏览器和 git 集成)给了我上面提到的所有东西,甚至更多。我大约 90%的编码时间都花在 Visual Studio 代码上,我已经像喜欢 Jupyter 笔记本一样喜欢它了。
Jupyter 笔记本没有什么本质上的错误,它们只是从来就不是用来开发严肃程序的。当正确使用时(实现文化编程的概念),它们是一个很好的工具。但是,和任何工具一样,笔记本可以用在不合适的地方。当您想要开始编写生产代码时,您将不得不切换到集成开发环境。即使您还没有做到这一点,我也建议您熟悉编写脚本而不是笔记本的想法,并将许多脚本组合成一个库(您可以将其导入笔记本进行分析)。不使用 IDE 来开发程序是一个严重的障碍:对工作的自己好一点,开始使用全功能的编程环境。

A little intimidating at first, but much more productive. Remember, your environment affects how you think.
结论
在他的优秀论文“没有银弹”中,大卫·布鲁克斯讨论了软件工程中偶然与本质问题的观点。过去 40 年来,软件工程生产率的提高是通过减少偶然问题实现的——那些与将想法转化为代码相关的问题——而基本困难——构思想法——仍然存在。在数据科学领域,我仍然看到许多人在偶然的困难中挣扎,甚至在开始编码之前就被自己绊倒,因为他们没有一个好的环境或者没有坚持简单的实践。
作为一个领域,我认为我们可以做得更好。让我们花更少的时间在数据科学的意外困难上——管理依赖关系、代码格式、命名、操作系统和代码编辑器——花更多的时间在基本困难上——开发算法、建立模型、工程特性和部署训练有素的模型(以及用机器学习应对气候变化)。通过采用本文中概述的实践,您将有更多的时间和精神资源来解决真正重要的问题。
一如既往,我欢迎反馈和建设性的批评。可以在 Twitter @koehrsen_will 上找到我。
如何避免数据科学领域的菜鸟错误?
数据科学初学者的注意事项指南

我最近开始了通过自学成为数据科学家的旅程。这条路并不总是一帆风顺的,因为没有人给我详细的连续教学大纲。因此,我尝试了一些事情,不太成功,但后来从那里拿起。如果你是一个有抱负的数据科学家,这篇文章可能会帮助你避免犯我犯过的错误。

首先,不要试图记忆或学习机器学习算法。大脑只保留其中的一部分,并丢弃其余部分。吸收它们的最好方法是通过实践。没有捷径!
我犯了一个错误,那就是在 Udemy 上浏览“机器学习 A-Z:数据科学中的 Python 和 R 的实践”课程。我的大脑吸收了课程的前半部分,但最终作为初学者,通读其余部分变得乏味。我确实得到了大多数算法的直觉,但现在回想起来,我觉得我本可以取消这门特殊的课程。
其次,编程是掌握数据科学的一个至关重要的部分。我们不能忽视这个阶段。精通一门编程语言是必须的,尤其是 Python。它是最被接受的语言,因为它有广泛的库,这有助于数据科学家部署随时可用的工具。而且大部分的课程和比赛都需要我们用 Python 编码。因此,“Pythonic 式”思维对数据科学职业生涯至关重要!
我借助了两个资源——一开始是 Codecademy ,后来是 Datacamp 。我很快就退出了 Codecademy,因为它是从非常基础的水平开始的——可能是为那些不是来自技术领域的人准备的。我在 Datacamp 上购买了一年的订阅,发现从数据科学的角度来看,这是学习 Python 的一个很好的资源。有些课程是为你最终要使用的库准备的——numpy,scipy 等等。有关于数据分析和可视化的项目。同样,人们应该记住没有必要记住语法。熟悉这种语言的功能和包是很重要的,确切的语法总是可以通过谷歌搜索到的。堆栈溢出是寻找查询答案以及回答他人问题的绝佳资源。
第三,在没有分析数据集的情况下,人们甚至不应该考虑机器学习算法。机器学习部分只有 2-3 行代码。其余的代码致力于详细的数据分析和可视化。如果不知道数据中的模式,就不可能确定哪些输入对您的输出很重要,消除数据中的噪声并最终转换数据以供模型使用。 Kaggle 是一个很好的资源,可以让你开始进行简单的机器学习练习(泰坦尼克号 & 房价预测)并尝试数据清理和转换。

我将在下一篇文章中涉及更多关于数据工程的内容。在此之前,请保持数据科学家的活力,并寻求任何问题或反馈!
如何避免每个数据科学家都会犯的最严重的错误——使用以下两个关键步骤
独家 TDS 采访
Patreon 的首席数据科学家分享了职业成功的宝贵技巧和资源以及解决数据方面实际挑战的策略。
Please subscribe to our official YouTube channel!
面试官:TowardsDataScience.com 项目负责人 Haebichan Jung 。
受访者: Maura Church ,Patreon 的数据科学主管。曾在谷歌工作,获得应用数学学士学位(哈佛大学)。
Patreon.com 是一个平台,让创作者很容易通过会员模式直接从粉丝那里获得报酬。你可以上 Patreon,每月支付给最喜欢的创作者一定的费用,以获得独家利益,偷窥等。有了足够的赞助,创意者就可以在 Patreon 上谋生,而不是通过广告或品牌。
你能告诉我们你的专业背景吗?
在 Patreon 之前,我在谷歌的一个数据分析团队从事数据工作。我一直在研究垃圾邮件和滥用,具体来说,就是应用数据来减少谷歌通信产品中的垃圾邮件、滥用和欺诈。在那之前,我在哈佛大学学习应用数学和音乐,特别是技术、艺术和计算机科学的交叉是我的兴趣所在。大约 4 年前,我作为第二名数据科学家加入了 Patreon,从那以后我就一直在这家公司工作。
刚开始在 Patreon 工作时,你的日常职责是什么?这些年来,您的数据角色发生了怎样的变化?
当我第一次开始时,Patreon 的主要数据结构是将我们所有的关键指标写入一个 Google sheet,该表通过 Google Sheet 的 API 每天更新,这在当时是有效的。这就是我进入的环境,我们没有任何数据基础设施设置,我们开始学习基础数据问题,我们想问的是像 Patreon 这样的创作者、顾客和企业是如何成长的。
我们第一年花了很多时间做 1)数据工程工作,例如设置我们的第一个 ETL,2)完成从 MySQL 到 redshift 的大迁移,3)定义我们的核心指标和我们想要测量的内容,以及 4)构建我们的第一个关键仪表板。
现在我的一天看起来很不一样。我现在管理着 5 名数据科学家。我对战略有更大的影响力(我们的数据应该帮助我们告诉我们去哪里),我非常关注产品分析(产品表现如何?如何做好实验?).
pat reon 的所有数据科学家都研究与产品相关的问题吗?如果不是,你能告诉我数据团队是如何构成的吗?
我们是一个核心数据科学团队(我们是一个非常集中的团队)。我们在业务中支持 4 个主要功能:
- 产品分析:衡量产品的性能。
- 业务分析:与走向市场业务团队(销售、营销、创造者成功、财务、法律等)相关的所有数据和指标。).
- 核心研究:关于创造者和赞助者的基础性、深层次的问题,这些问题将推动整个行业的发展。
- 商业智能/数据教育/数据可访问性:对新员工的入职数据进行改进,为公司提供使数据更易访问和解释的资源。
我们每季度 70%的工作都是在产品分析方面。一些人更倾向于 B.A .方面,一些数据教育,这取决于个人和季度以及我们那个月要做的事情。
你能详细说明一下你的主要任务吗:让“Patreon 的创造者、顾客和队友拥有做出卓越决策所需的数据”?
我认为,一方面是基础数据基础设施,另一方面是为我们的数据科学团队的创意经济提供动力的数据产品。今天,我们已经完成了通往另一端的旅程的 60-70%。我的希望是,在未来,我们正在构建嵌入 Patreon.com 的数据产品、API 或模型,使顾客和创造者能够做出更好的决策。
例如,我们可以帮助创作者了解顾客及其会员的流失特征[流失模型和分析]。这有助于创作者采取更好的行动来留住这些会员,并增加他们在 Patreon 的会员人数。或者,我们可以告诉用户他们还没有看到的最受欢迎的帖子或好处,通过数据科学团队建立的东西[内容推荐引擎]。
现在我们只有一个模型在生产,欺诈模型,它主要是帮助 Patreon 不收取欺诈性的承诺。我的希望是,从长远来看,我们正在建立更多的数据产品,为网站提供动力。
你希望 Patreon 的未来数据科学家具备什么样的特质、品质或背景?
对我来说,真正重要的事情很少,尤其是因为 Patreon 是一家初创公司,在初创公司担任数据科学家与在拥有一百名数据科学家的更大公司担任数据科学家是不同的。几件关键的事情:
- 技术障碍:我们每天都在 SQL 中工作,特别是在 Postgres 中,并希望候选人了解 Python/某种统计语言的某种流利程度。此外,有人谁是真正舒适的查询非常大的数据集。
- 沟通:在我们的角色中,我们每天都要花很多时间来获得深刻的见解或建立模型,并将结果传达给利益相关者,无论是产品经理、营销人员还是财务人员。数据科学考生具备良好的沟通能力是超级关键的。
- 勇气、韧性和解决难题的意愿:Patreon 是新市场的新产品。我们试图学习的东西和我们试图解决的问题通常都是难题。我希望任何加入数据科学团队的人都对困难的问题和艰难的挑战感到兴奋。
- 对艺术的热情和对使命的热情:这不是最重要的,但却是最重要的。
反过来,你不寻找的特质是什么?换句话说,你在数据科学申请者中见过哪些常见的陷阱?
我经常看到的一个常见陷阱与马斯洛的锤子的想法有关。这个观点认为,对于拿着锤子的人来说,任何东西看起来都像钉子。在数据科学中,这是一种愿望,即不管实际问题如何,将候选人可能感到非常舒服的方法应用于任何问题。
例如:候选人可能会进入 Tensorflow 并学习 Keras 和深度学习,对于他们遇到的任何问题,他们会说“哦,让我使用 Tensorflow!让我将深度学习应用于此”。这是一个需要避免的非常重要的陷阱。你将要面对的一些问题可能需要一个简单的 excel 电子表格。或者实际上解决问题的方法是让人们聚在一起讨论。因此,不考虑解决问题的正确方法是非常重要的陷阱。

https://www.youtube.com/watch?v=Cw0iK9OoETs
所以那将是从他们试图解决的问题中抽离出来,并问“为什么”他们正在使用的技术和模型?
没错。询问我们为什么试图解决这个问题,我们将为企业增加什么价值总是一个很好的开始,而不是用你知道的方法。
对于那些不熟悉商业价值思维的人来说,该如何改进呢?
我推荐两种方法:
- 有很多关于战略思维的好书。如果你谷歌一下《哈佛商业评论》关于战略思维的书籍,那会有所帮助。对于数据科学家来说,拥有战略性思考的技能,提出更长期的问题,并把事情框定为为什么要这样做,这很好。
- 候选人思考类似产品的案例研究是非常有价值的。例如,为 Pinterest、Airbnb 或 Lyft 这些非常常见的软件产品想出 10 个功能创意。在分析一个特性之前,先回顾一下,问问自己为什么要构建这个特性。这有助于培养问为什么的能力,并以此为起点,而不是一头扎进去。
特别关注 Patreon,该公司面临的主要数据挑战是什么?
我们面临的一个数据挑战是,创建者以许多不同的方式经营他们的会员资格。举个例子:有些音乐家会打开一个 Patreon 页面来支持他们的粉丝。他们只是想把他们的粉丝带到他们创作的音乐中来。另一个例子:一个播客正在创建会员资格以提供独家内容。
事实上,人们为什么使用 Patreon,他们如何使用它,以及他们如何构建他们的定价和利益,有如此多的商业模式,这使得它在数据方面确实具有挑战性。我们确实有基本的聚类来显示这些不同的模型是什么样子,但是它们并不规范。数据中的这种非结构化商业模式问题对我们来说确实具有挑战性。因为这意味着我们必须依靠我们在支付行为和定价行为中看到的其他元素和特征,来试图找出对于给定的创作者来说什么是可行的。
第二个主要挑战是 Patreon 已经存在 6 年了,在这段时间里,我们有不同的信息、营销和品牌来配合当时的战略。现在,我们专注于会员资格。帕特里翁是一个你可以建立会员资格并从你最大的粉丝那里获得报酬的地方。但这与我们最早的创造者是非常不同的模式。因此,当我们试图研究这个新的会员市场时,我们的历史数据可能不是最有价值的东西。
这是一个固有的挑战,即你用什么数据来解决什么问题,以及我们在多大程度上依赖旧数据,而不是来自可能在过去一年推出的创作者的数据。
对于这个冷启动问题,你运用了哪些成功的策略?
这是个好问题。采取的一个重要步骤,也是更商业的方法,是挑选我们正在寻找的典型的和案例研究的例子。因此,找到一个在会员资格方面做得非常好的创作者,并深入了解他们在做什么?他们是如何建立自己的网页的?他们如何向他们的成员传递价值?并利用这些问题试图找到其他创作者。
举一个具体的例子,我们知道 Patreon 上的播客创作者拥有非常好的留存率,因为他们每周都在发布连载内容。所以如果你知道下周会有全新的剧集,你可能会留下来。我们以此为例说,“好的。怎样才能鼓励其他创作者做连载内容?我们如何从特定的创作者那里获得这种洞察力,并将其更广泛地应用于我们所有的创作者?这就是我们所说的规范创建者方法,它在缺乏数据的情况下对我们很有帮助。
关于完整的剩余采访,请观看 YouTube 视频,其中 Maura 深入研究了在 Patreon 工作的数据科学项目,以及为当前和有抱负的数据科学家提供的其他重要提示和资源。
阅读容格在媒介上的作品。项目负责人@ TDS | haebichan@towardsdatascience.com。每天,Haebichan…
medium.com](https://medium.com/@haebichan) 
如何批量校正单个单元格
生命科学的数理统计和机器学习
单细胞基因组批量校正方法的比较

From Butler et al., Nature Biotechnology 36, p. 411–420 (2018), image source
这是专栏 生命科学的数理统计和机器学习 中的第 11 篇文章,我试图在这里涵盖生物信息学、生物医学、遗传学、进化等领域常见的分析技术。在我之前的一篇文章中,我开始讲述通过比较标准化策略来消除技术变异的方法。在这里,我将对该主题进行扩展,并谈论校正由不同技术、实验室、方案等测序的相同类型细胞之间的系统差异,即批量效应检测和消除。
如何检测批量效应?
批量效应有一个危险,即混淆真实的生物信号,即在 scRNAseq 的情况下,在样本中发现细胞类型。批次可能来自:不同的测序日期、测序人员、流动池/板、化学/方案、泳道、读数长度、实验室产生的数据,甚至极端情况下的不同生物体。

Human vs. mouse (left ) as well as stimulated vs. control (right) same type cells form distinct clusters, from Butler et al., Nat. Biot. 36, 411–420 (2018)
批次效应可以是全基因组,即大多数基因都存在,也可以是基因特异性,即某些基因恰好受到批次的影响。前者很容易从 PCA 或 tSNE 等降维图中看出。出于演示目的,我将继续使用来自的先天淋巴细胞( ILC ) scRNAseq 数据集。bjrklund 等,自然免疫学 17 ,第 451–460 页(2016) 。下面我计算了来自三个捐赠者的 ILC 细胞的 PCA 和 tSNE 降维图,详情请查看我的 github 上的完整笔记本。

从图中可以清楚地看到供体特异性批次,即来自同一供体的细胞倾向于聚集在一起,并且与来自其他供体的细胞截然不同。为了进一步量化,让我们显示每个主成分(PC)中有多少变化是由供体、平板和细胞类型解释的。

从上面的热图可以看出,PC1 的 44%是由供体批次造成的,而细胞类型的贡献可以忽略不计,因此我们有一个严重的全基因组供体相关批次效应。然而,如果我们在上述降维图中没有观察到任何供体聚类,这是否意味着我们的数据集中不存在批效应?不,不是的。某些基因在很大程度上仍可能因批次而非细胞类型而存在变异。我们可以通过将它们的表达与供体变量相关联来对受该批次影响的所有基因进行排序。从下面的左图中,我们观察到有 个基因由于供体批次而具有> 20%的变异。为了评估这个数字是多还是少,我们将批次变量混洗多次并计算** 噪声区,即由于随机变量导致的基因表达的变化。我们也可以做一个正式的统计测试,计算出偏离噪声区的显著性的 p 值(下图)。通过这种方式,我们最终得到了大约 200 个受批次显著影响的**基因的列表,这些基因对于进一步的下游分析来说是值得关注的。****

Ranking the genes by their variance explained by the batch variable and computing the noise zone
如何纠正批量效应?
一旦我们检测到数据中的批量效应,我们就可以应用多个可用的批量校正算法。我不建议对 scRNAseq 数据进行类似于 SVA 的无监督校正,因为 scRNAseq 分析也是无监督的,其基础事实(细胞类型)未知,因此移除近似批次的替代变量可能会破坏生物信号。对于监督批次校正,即当批次先验已知时,使用 和 方法进行简单的线性校正将是一个良好的开端。

战斗通过贝叶斯线性回归执行批量校正,因此与例如在 Limma 中实现的简单 aka Frequentist 线性批量移除相比,提供了相当大的改进。除了对于小样本量更好的性能,Combat 使用****贝叶斯向均值收缩,这意味着我们使用来自其他基因的“均值”信息来校正每个基因,而 Limma 独立地逐个基因地进行校正。尽管如此,战斗应用了线性批量效果修正。****
相互最近邻(MNN) 算法采用了受K-最近邻(KNN) 思想启发的非线性批量效应修正。该方法试图找到批次之间最相似的细胞(共同邻居),这些细胞被假定为属于相同类型和MNN 细胞之间的系统差异量化批次的强度,该信息被用于缩放批次中的剩余细胞。

Idea behind Mutual Nearest Neighbor (MNN) batch correction, from Haghverdi et al., Nat. Biot. 36, 2018
我对这种方法的一般问题是,我总是无法理解 MNN 细胞应该属于同一类型的假设。我的直觉是,一个批次可以完全混淆批次中细胞之间距离的概念,所以批次之间最近的两个细胞实际上可以属于不同的细胞类型但是因为批次本身的原因看起来非常相似 。然而,MNN 批量效应修正在实践中似乎运行良好,我们将在后面看到它在我们的基准测试中表现良好。
另一种流行的特定批量校正方法是 修拉典型相关分析(CCA) 技术,该方法有时被视为跨样本整合。CCA 的概念与我在以前的一篇文章中描述的 PLS 数据集成 非常相似。通过最大化来自不同批次的数据集之间的相关性(或协方差),来自批次的数据被投影到低维空间中。这意味着数据集的投影相关但不一定对齐,即在低维空间中没有很好地重叠。后者通过应用 动态时间扭曲(DTW) 技术来解决,该技术局部地拉伸和挤压CCA 数据投影,以便进一步对准它们。

Idea behind Seurat Canonical Correlation Analysis (CCA) batch correction, from Butler et al., Nat. Biot. 36, 2018
当战斗时,MNN 和修拉 CCA 试图转换数据以便合并来自不同批次的子集, SCMAP 算法试图将查询细胞投影到参考数据集上,该参考数据集可能是例如 人类细胞图谱 ,而不实际产生单个校正的数据集。

Idea behind SCMAP single cell projection onto a reference data set, from Kiselev et al., Nat. Met. 15, 2018
SCMAP 使用 KNN 分类器来寻找测试细胞和用于训练分类器的大概大得多的参考数据集之间的对应关系。
ILC 批量校正方法的比较
这些方法在实践中是如何工作的?我们将使用 ILC scRNAseq 数据集来运行它们,并尝试消除与供体相关的批次效应,从而协调批次之间的细胞。完整的笔记本可以在 github 找到,这里我只给出最终的对比 tSNE 图:

看着上面的 tSNE 图,我会说所有的方法都很好地混合了来自不同捐赠者的细胞。遵循奥卡姆剃刀原理,我认为最简单的战斗在超级容易理解和编程的同时性能也足够令人满意。
有趣的是,当在两个供体上训练 SCMAP 分类器作为参考并将来自第三个供体的细胞投射到参考上时,考虑到大约一半的细胞根本不能被可靠地分配到任何群,导致差的细胞分配/分类准确度 84% 。这可能是由于训练集不够大或者数据不满足对于 KNN 分类器至关重要的球面对称性。

摘要
在这篇文章中,我们了解到批量效应代表了一种技术上的变异,这种变异可能会混淆 scRNaseq 分析中的生物信号 。这些影响可以通过全基因组或基因特异性方式检测,并使用线性(战斗)或非线性(MNN、修拉 CCA、SCMAP)算法进行校正。总的来说,批量修正方法在基准测试中运行良好,表明最简单的(战斗)模型应该优先。
在下面的评论中让我知道生命科学中的哪些分析对你来说似乎特别神秘,我会在这个专栏中尽力解答。在我的 github 上查看帖子中的代码。在媒体关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。下一次我们将会涵盖到底如何UMAP作品,敬请关注。
如何成为 10 倍数据科学家

我将告诉你成为 10 倍数据科学家需要什么。什么是 10x 数据科学家?一个比普通数据科学家多做十倍实验的人。
为什么要做实验?数据科学家也做其他事情:数据管理、分析和为生产编写机器学习算法的实现。但是实验是数据科学家的定义。这就是科学的所在,也是他们区别于数据分析师或机器学习工程师的地方。
因此,要成为一名伟大的数据科学家,你必须擅长做实验。
为什么要多做 10 倍的实验?你永远不能保证你会因为更聪明或更快而获得十倍的好结果。但是你可以做更多的实验。你做的实验越多,你得到更好结果的可能性就越大,你迭代的速度就越快,你学习的速度也就越快。
你为什么想成为 10x 数据科学家?我不知道。可能因为听起来很酷。可能因为好玩吧。也许因为你会有更多的时间吃糕点。这取决于你。
我假设你能正确地进行实验。你是数据科学家,对吧?然而,有一件事我见过许多数据科学家犯了错误。是这样的:
1.衡量你的不确定性
如果不知道结果是否具有统计学意义,那么在基线上提高 5%有什么意义呢?数据科学家知道(或者说应该知道)统计学,但是他们往往懒得把它应用到自己的工作中。
这方面并不缺乏选择。我最喜欢的方法是我在物理学学位中学到的:将不确定性估计为平均值的标准误差。当然,这意味着您报告的值必须是某个值的平均值,无论是交叉验证中五次折叠的平均 F1 分数,还是 1000 个不同查询的排名中 10 的平均精度。
你不需要在所有结果之间做统计显著性检验。但是你需要知道你的结果有多不确定。平均值的标准误差给出了这一结果——如果您的结果相差超过标准误差的三倍,则差异可能非常显著。
你可能还想考虑一下你想要什么样的效果尺寸。如果 0.1%的改进对你没有用,那么进行可以检测这种变化的实验就没有意义了。
2.大数据并不酷
大数据慢。你不想慢下来。所以用小数据。大多数时候你不需要大数据。如果你认为你需要它,花一点时间重新考虑,以确保你真的需要它。
您希望您的数据集足够大,以便您的结果中的不确定性足够小,足以区分您所关心的差异。你不想让它变得更大:那只是浪费时间。
你不必使用所有可用的数据。根据您的实验,您可能能够估计您需要多少数据。否则,看看您所关心的指标是如何随着训练集的大小而变化的。如果它相当快地稳定下来,你就会知道你可以丢弃很多数据。做更多的实验,弄清楚你需要多少数据来使不确定性足够低,以获得你正在寻找的洞察力。
实验缓慢的首要原因是使用了太多的数据。就是不做。
3.不要使用大数据工具
如果你有小数据,就不需要大数据工具。不要使用 Spark,它会慢得可怕,与熊猫和 Scikit-learn 相比,结果会很差。用那个代替。
4.使用好的 IDE
使用一个像样的集成开发环境,比如PyCharm——实际上,只是使用 py charm,没有什么真正的比较。学习如何正确使用它。
这些是我觉得最有用的东西:
- 自动完成,尤其是与键入的代码结合使用时
- 查看函数或类的参数和文档
- 快速搜索文件、类或函数的整个代码库
- 重构以提取变量、函数或方法以及内联变量
我不忍心看着人们为了这种事情和一个文本编辑器较劲。请停下来。
Jupyter 笔记本做探索性工作还可以,但是如果你想成为 10x 的数据科学家,你需要用一个 IDE 做实验。
5.缓存中间步骤
实验可以包括数据预处理、特征提取、特征选择等。这些步骤中的每一步都需要时间来运行。一旦你找到了一组好的特性,你就可以在实验模型的时候或多或少地保持它们不变。如果预处理步骤需要很长时间,缓存中间步骤是有意义的,这样您只需执行一次这些昂贵的计算。这将对实验进行的时间产生巨大的影响。
我通常会使用一个或多个预处理脚本来完成这项工作,这些脚本会生成供后续阶段使用的文件。确保您跟踪这些文件如何与源数据相关,以便您可以通过文件命名约定或为工作设计的工具(如 Pachyderm )将您的实验结果追溯到原始数据。
6.优化您的代码
如果您的实验在减少数据集大小后仍然很慢,那么您可能会从优化代码中受益。在运行实验的同时,平衡运行实验和优化代码。
你应该知道如何优化代码的基本知识。这里是基本的:使用一个分析器。分析器会告诉你哪些位是慢的。改变这些位,直到它们不再慢为止。然后运行分析器,找到其他慢的位。重复一遍。
在一个小样本上运行分析器,这样您就可以快速找出哪些位运行缓慢。(你也需要优化优化。)
7.记录你的结果
如果你丢失了实验结果,那就是浪费。所以要小心追踪。使用为工作设计的工具,比如 MLFlow 、圣物,或者我自己的宠物项目 PyPastry 。如果你到处复制结果,你是在浪费时间,而且很可能出错。不要。
如果你做了以上所有的事情,运行一个实验可能需要不到五分钟,理想情况下不到两分钟。这段时间足够思考下一个实验会是什么。
这意味着你有可能在一天内运行数百个实验。当你运行这么多实验时,你需要一个好的方法来跟踪。
7a。多吃糕点
这实际上不是一个好建议。你的大脑每天需要高达 400 卡路里的葡萄糖,但吃糕点可能不是实现这一目标的最健康的选择。但是会很好吃。
相反,你可以考虑联系 DataPastry ,这是一家数据科学咨询公司,我和我的联合创始人 Iskander 一起经营。如果您想要任何建议或需要数据科学项目方面的帮助,我们很乐意收到您的来信,我们不咬人(糕点除外)。
结论
如果你做了以上所有的事情,我很确定你会比坐在你旁边的数据科学家至少多做十倍的实验(除非你坐在我旁边)。大部分数据科学家都不做。所以如果你都做了,你可能会多做五十次实验。这让你变得更有价值 50 倍吗?我不知道,但这没什么坏处。你会有更多的时间吃糕点。
原载于 2019 年 10 月 1 日https://datapastry.com。
如何成为一名气候学家

Image taken by author.
这些天,我们从各种新闻渠道中读到和听到了很多关于地球气候的信息。关于这些文章中的大多数,值得注意的一件有趣的事情是,它们中的许多报告来自科学报告。虽然这是一种传播科学信息的完美有效的方式,但它并没有真正告诉读者他们可以如何进行自己的气候学研究。虽然提供信息可以让观众了解信息,但在教育他们这些信息是如何产生的方面却没有什么作用。认识到这样一个事实,即许多人由于时间或缺乏资源而无法进行这些类型的检查,对许多人来说,有一个直接的指南来教他们一些关于气候科学和分析的知识仍然是有用的。今天我将使用来自美国历史气候网络(https://www.ncdc.noaa.gov/cdo-web/)的数据。他们有来自全美各站的数据。我在南卡罗来纳州哥伦比亚的车站寻找这个特别的练习。让我们开始吧。
1。)了解气候正常
气候正常是该领域大多数人所指的 30 年平均天气模式。有些人也可能把它称为某个研究区域的大气变量的“气候学”。每十年末更新一次正常值。最近的正常时期是 1981 年到 2010 年。你可能会想,“那是 29 年。”但是看似一年的假期却不是,正常情况下,整年都被计算在内,这意味着我们没有计算“到”2010 年,我们考虑的是“到”2010 年的数据,这给了我们完整的 30 年。气候常态有助于理解趋势变化、模式变化和异常事件。除非你是在做一个特定事件的案例研究,否则你应该尽可能多地查看数据,将这项研究视为一项气候学研究。然而,这个规则有一个例外。有句话说,“什么是气候学,取决于正在研究什么。”如果你开始研究一个领域的蒸发和风型的气候学,这是非常正确的。除了偶尔的恶劣天气事件,这些小气候很可能会经历很多变化。在这些更小的尺度上,异常仍然可能发生,但是 30 年的数据对于检查它们是不必要的。因此,当你观察区域、大陆或全球范围的天气模式时,应该应用气候常态。

Climate normal for the Columbia, SC station between 1981 and 2010. Figure made by author.



Climographs for each decade within the normal: 1980, 1990, and 2000. Figures made by author.
2。)季节性
另一个要考虑的是季节性。大多数气候学家喜欢按季节分解事物。季节分为春季(三月、四月、五月)、夏季(六月、七月、八月)、秋季(九月、十月、十一月)和冬季(十二月、一月、二月)。如果您还没有发现,winter 会要求将前一年的数据与下一年的数据进行分组。因此,我们 1981 年的第一个冬天需要 1980 年 12 月的数据,2010 年的最后一个冬天需要 2011 年 1 月和 2 月的数据。季节性对于确定一年中什么时候事件更有可能发生很有用。例如,如果我们检查从 1981 年到 2010 年所有秋季的飓风频率,我们会看到大多数发生在 9 月。我们也可以比较一段时间内的多个秋季。这让我们在不涉及天气模型或其他变量的情况下,更好地了解未来飓风预测的可变性和不确定性。
3。)地理
地理无疑会影响我们在气候学中观察到的模式类型。如果您正在检查亚利桑那州凤凰城和宾夕法尼亚州费城之间的干旱情况,您不会想要宣布凤凰城的干旱情况比费城严重,因为它的周、月或年降水量要少得多。这两个地方由于所处的位置,会经历非常不同的降水模式。费城比凤凰城潮湿得多,从局部对流活动和更大的迁移风暴系统中获得降水。如果要在两个地点之间进行比较,需要计算两个地点的被检查变量的正态分布,然后使用方差、标准差或标准误差等测量方法检查数据。
4。)时间序列,归属,&视窗
时间序列和归因可能是大多数气候学研究的主线。气候科学家想知道在观测记录中天气模式是如何变化的,他们也想知道是什么导致了这种变化。有大量的时间序列方法,但最常用的是拟合数据的回归线,以创建一个方程,显示随着时间的变化量。问题是气候数据通常不是高斯分布的,需要转换或者使用其他非参数方法。这是“使用不假设数据是正常的技术”的行话。归因技术可以有多种形式,但最常用的是相关性分析。正相关意味着两个观察点很可能相关,而负相关意味着它们不太可能相关,并且当一个发生时,另一个不相关。中性相关意味着看不出两者之间有任何关系。窗口是被分开来检查变化的时间段。因此,如果我们以 10 年为一个区间来考察我们的常态,我们可以观察到每个十年之间的明显差异。


Temperature (left) and Precipitation (Right) climate normal trends for each month. Notice how these compare to the decadal examinations below. Figures made by author.






Above: Temperature trends for the decades of 1980, 1990, and 2000. Below: Precipitation trends for the decades of 1980, 1990, and 2000. Temperature shows an increase over the three decades and precipitation shows a decrease. Figures made by author.
有了以上提供的所有信息,你现在可以练习一些基本的气候学了。随意钻研一些数据源,看看温度、降水、湿度,甚至是恶劣天气事件。通过这种方式,你可以随时了解你所在社区发生的事情。重要的是要注意到气候系统是复杂的,无论你发现的结果如何,都可能有更多的因素在起作用,而不仅仅是数据向你揭示的答案。前国防部长唐纳德·拉姆斯菲尔德说过一句话,在分析任何数据时,我总是喜欢记在心里,“有些事情我们知道我们知道。有已知的未知。也就是说,有些事情我们现在知道我们不知道。但也有不为人知的未知。有些事情我们不知道我们不知道。”
如何成为一名成功的首席数据官
首席数据官为组织创造价值并引领数据驱动型转型的三种方式

Photo by Ahmer, To the Mountain Top (Source)
总结
首席数据官(CDO)是组织内数据的代言人,将数据视为战略性企业资产。CDO 的角色正在演变,在行业中获得了巨大的吸引力,它的成功对于推动组织的发展和创新是必不可少的。CDO 必须将自己的角色从防御型数据战略转变为进攻型数据战略,承担起变革推动者的角色,并负责为其组织创造价值。这是成功的秘诀。
挑战
尽管 CDO 的角色正在走向成熟,但许多 CDO 正在失败。Gartner 最近的一项研究预测,50%的 CDO 将因众多内部和外部因素而失败。大多数外部因素是不可控的,因此,了解成功的关键内部障碍非常重要。
● 角色的级别:头衔“首席”意味着该角色向高管层汇报,但许多 CDO 并不这样做。他们没有资历、决策权和政治影响力来推动企业数据战略。
● 角色清晰性和限制:CDO 角色的定义仍然没有一致性,角色的期望取决于组织的数据成熟度。这个问题的一个直接后果是对角色本身的限制。
● 缺乏资金和资源:没有将 CDO 的角色放在组织中足够高的位置,其专用预算影响了对工具、技术和人员的投资。
● 公司文化和变革阻力:CDO 是一个颠覆性的变革管理角色,不是每个人或每个公司都能很好地适应变革。最重要的是,公司中任何新的“首席”角色都会带来政治动态,根据角色的位置,它可能会给首席信息官和首席技术官带来政治问题。
建议
随着组织逐渐走向成熟,并希望由 CDO 来共同主导增长章程,CDO 应首先评估其组织的数据成熟度,然后通过以下方式为其组织创造价值:
● 数据管理:这是 CDO 角色的核心,涉及数据控制、数据质量、维护、保护和治理。将数据作为企业资产或公司货币进行管理,并建立对数据的信任是一个关键因素,其他一切都取决于此
● 数据丰富和支持:找到利用现有数据实现业务成果的方法,并用额外的内部和外部数据对其进行扩充。从小处着手,在每一次成功(和失败)中积累。确保整个组织内分析的数据可用性,包括可操作的见解人力资源和财务等职能部门的不足
● 数据货币化:确定从数据中获取收入的方法。创建创新章程,进行实验,构建原型,传播和实现数据科学、人工智能和机器学习等高级分析,并将数据产品开发为企业知识产权和竞争优势
评估
新商业和数字化转型的出现,使得组织越来越依赖数据,无论是从即时交易的角度,还是从制定长期发展战略的角度。许多没有接受这一新现实的组织已经失败并继续挣扎,例如 Sears。数据和分析正在引领市场差异化和以消费者为中心。随着组织开始意识到数据是他们的公司货币,需要将其作为资产进行管理,首席数据官的角色应运而生。
该评估的重点是那些在数字方面非本地的组织,以及那些没有从头开始最大限度地发挥数据和分析作为其商业模式关键驱动因素的潜力的组织,如亚马逊、谷歌、脸书、Airbnb 等。在这些组织中,CDO 的角色通常是不存在的,数据管理,以及用数据和分析推动商业价值是一个基本元素和日常业务现实的一部分。
首席数据官对不同的组织有不同的含义。在一些组织中,风险、合规性和法规可能是创建相对狭窄和深入关注的角色的背后。在其他组织中,它可能更广泛,包含企业数据和分析以及创收驱动因素,或者它可能是对业务模式中断和推动创新需求的响应。从本质上讲,CDO 的角色必须与其数据战略的组织成熟度相关联。Gartner 从四个方面描述了 CDO 角色的演变:
CDO1.0 :专注于数据管理
CDO2.0 :开始拥抱分析
CDO3.0 : Led 数字化改造
CDO4.0 :以数据产品为重点的货币化
随着数据战略的发展,分析也在不断发展。根据 Thomas Davenport 进行的研究,分析经历了以下发展阶段:
分析 1.0 :传统商业智能时代
分析 2.0 :大数据时代
分析 3.0 :面向快速经济的数据丰富产品时代
分析 4.0 :认知消费者控制的数据时代
这给 CDO 带来了一个挑战:从哪里开始,关注哪里?CDO 的角色也是一个跨职能的变革管理角色,它从组织调整和政治角度创造了自己的内部挑战。事实上,Gartner 预测约有 50%的 CDO 会倒闭。在 Gartner 的 2017 年 CDO 调查中,文化惯性和数据素养被报告为缺乏成功的首要原因。

这一评估与新 Vantage 合作伙伴进行的研究非常一致,该研究旨在确定业务采用分析的障碍。

Source: New Vantage Partner (2019)
CDO 进气管道中的典型一天包括:
●营销部门对消费者总体水平的营销活动绩效报告的需求
●销售人员说这些数字是错误的,不可信
●首席财务官表示,向他们报告了多个版本的 topline KPIs,他们需要确定哪个版本是正确的
●商业智能团队表示他们没有足够的资源和工具
● CTO 说他们已经决定将数据从内部系统迁移到云中
似乎立即解决这些问题应该是 CDO 的重点,但这是错误的做法,因为这只会加剧围绕这一重点的关切。许多战术工作可以由现有的数据团队采用敏捷或老虎团队的方法来完成,但 CDO 必须专注于建立功能的战略愿景,并获得企业范围的认可。
首先,CDO 必须承担起变革推动者的角色,并理解这是一项跨职能的责任,需要组织能力来建立联盟和伙伴关系。了解组织如何运作至关重要。这应导致创建一个基于文化并与企业使命相联系的职能愿景。
接下来,CDO 必须开发一种组织结构,这种结构旨在通过一种跨越业务单位中的多个层级的参与模式来推动采用。CDO 应该根据变革的速度和组织的政治环境来评估集中型、分散型和混合型组织结构——建立信任和协作比建立帝国更好。

Copyright: Ahmer Inam
CDO 也应该是以人为中心的设计、设计冲刺和敏捷方法的支持者,并创建以领域专家或业务单位用户为中心的多学科敏捷团队。这使得采用成为从发现和设计阶段向前的计划的一部分。领导这些敏捷团队的一个重要角色应该是能够用数据和策略语言进行有效沟通的数据翻译者/传播者。

Copyright: Ahmer Inam
这里要考虑的一个关键因素是 CDO 想要领导的变革程度以及他们想要前进的速度。这些雄心应该与组织对变革的准备和 CEO 的支持相匹配。来自 Standish Group 的混沌报告显示,从大型计划开始有更高的失败可能性。
识别并专注于可解决的问题。不要一开始就野心太大,先把基础打好。平衡潜在的长期计划和短期项目,并尽早和经常地交付组件,提高成功率和价值。CDO 应该以价值而不是数量来衡量他们组织的生产力和成功。在向企业领导人讲述透明的价值驱动的故事中磨练出来的沟通策略将逐步在组织中建立声誉和信任。
解决组织战略的这些基本问题将导致 CDO 组织章程的制定,并为组织的成功奠定基础。

Copyright: Ahmer Inam
现在,我们来探讨一下 CDO 为其组织创造价值的三种方式。
建议 1:数据管理
许多 CDO 组织都是从这个领域(数据运营)开始的。这是 CDO 的核心责任领域,必须如此管理。没有掌握的、精心整理的、良好治理的和安全的数据,其他一切都是空谈。这不仅仅是一个维持的领域,也是一个将继续挑战 CDO 组织的创新领域。例如,确定如何最好地存储和检索高维高基数纵向时间序列数据,或者在 GDPR 时代掌握消费者数据,以有效地推动消费者参与战略。CDO 必须关注的一些价值驱动因素:
●将企业数据作为资产进行保护,并管理风险和合规性
●利用先进的治理原则减少敏感数据的暴露
●单一真相来源与多个真相来源的策略
●数据架构和系统的发展,以保持领先于市场的步伐
●持续评估和应用精益数据运营方法,以较低的成本提供高价值
●建立高标准的数据质量,消除“垃圾进垃圾出”的风险
建议 2:数据丰富和支持
CDO 必须对现有数据进行全面评估,对它们进行编目,并创建元数据。这将有助于最终用户更好地理解数据,也可以用来培养组织的数据素养。然后,探索组织利用现有数据还能做什么和做多少。从获得“易得之果”开始,并以此为基础。继续评估现有数据中的差距,并利用外部来源和合作伙伴进行补充和扩充。随着现有数据被用来推动组织价值,它将缓解对数据扩充和丰富策略的额外资金的请求。此外,使跨业务部门的数据访问民主化,以赢得更多支持者。向人力资源和财务等数据匮乏的组织表达爱意,并赢得这些强大业务职能部门的支持,因为他们拥有资源和预算方面的关键决策。
采取一种渐进的方法来逐步开发一个“洞察系统”,该系统必须集成数据孤岛,并作为一个干净的、治理的、扩充的数据系统,该系统将继续推动组织的价值。使用财务和销售数据来创建仪表板,以衡量对交付给组织的顶线 KPI 的影响。

Source: Forrester
建议 3:数据货币化
数据货币化本质上是数据丰富、利用和支持的延伸。CDO 必须专注于在现有流程和职能之外寻找新的收入和创收机会。这将需要挑战现有的商业模式,并通过宣传来获得组织盟友,以推动创新,并从项目导向转向产品导向。CDO 必须为产品创新创造空间,无论是在其组织内部还是与其他互补组织合作
●使组织的思维模式从数据是业务的副产品转变为 it 具有内在的货币价值:将数据视为组织的货币
●在当前项目之外增加关注点,以增加现有收入或降低成本
●利用数据产品确定新的收入来源,例如,商家服务提供商可以通过 SaaS 洞察门户向其商业客户授权聚合洞察
●在数据和分析领域之外进行思考,并将其视为创新练习。以人为中心的设计为先导,识别潜在的有价值的想法,将其原型化,无情地迭代、测试和学习,并在价值驱动因素确立后扩大规模。以下框架可用于建立以人为中心的产品开发生命周期(PDLC)流程
●不要一个人去争取。作为合作伙伴,带着战略财务、公司战略和其他高管一起踏上旅程
●确定拓展分析边界的机会,并将基于人工智能和机器学习的知识产权作为竞争优势

Copyright: Ahmer Inam
结论
使用此处规定的框架来处理首席数据官的角色,可以让 CDO 率先在一个安全且治理良好的环境中提供来自组织内外的最佳数据。这将推动组织的价值,并建立一个成功的和创新的价值驱动的 CDO 组织。
参考文献
[1] J. Heizenberg,A. Duncan,设计有效的数据和分析组织时要避免的 5 个陷阱 (2018),Gartner Research
[2] R. Bean,T. Davenport,大数据和人工智能高管调查 (2019),新 Vantage Partners
[3] M. Faria, Gartner 研究委员会任命首席数据官 (2019),Gartner 研究委员会
[4] C. Pettey,Gartner 首席数据官调查的 3 大要点 (2018) Gartner Research
[5] J. Bennett,为什么只有一半的 CDO 做好了成功的准备 (2016),Gartner Research
[6]斯坦迪什集团国际有限公司,混乱报告 (2015)
[7] M.Teerlink,B. Gow,K.Banerjee,大数据和分析的新英雄 (2014),IBM 商业价值研究所
[8] L. DalleMule,T. Davenport,你的数据战略是什么 (2017),《哈佛商业评论》
[9] T .达文波特,分析的四个时代 (2015),分析前沿会议
[10] S. Soares,《首席数据官数据治理手册》 (2014),MC 出版社
[11] C .卡鲁泽斯,p .杰克森,首席数据官的剧本 (2018),刻面出版
[12] D. Laney,信息经济学:如何将信息货币化、管理和衡量为竞争优势的资产 (2017),Routledge
[13] B. Evelson,洞察系统:下一代商业智能 (2015),Forrester
[14] A. Inam,B. Franks,以人为中心的变革推动分析采用 (2019),国际分析研究所
[15] A. Inam,B. O'Neill,以人为中心的设计如何增加对数据科学计划、产品和解决方案的参与 (2019),体验数据播客
[16] A. Inam,A. Hartsoe,实现客户终身价值(CLV) (2019),客户资产加速器
[17] A. Inam,P. Capon,播客#40 (2019),创新社区
如何成为一个成功的投资者:用 Python 进行简单的投资组合分析
阅读这篇文章是一项值得的投资

It’s amazing what you can do with this
你知道你去的那个地方,在那里你会投入大量的金钱,放弃四年(或更长)的宝贵时间,作为交换,你可以和一群你从未见过的同龄人一起住在一个狭小的空间(你也必须付钱),参加一系列聚会,你可以坐在那里看老年人说话,在白板上写东西(或使用 PowerPoint), 度过许多不眠之夜,了解最起码的营养是什么,所有这些都是为了得到一张小纸片或电子文档?

Feels bad…
我是不是不小心给你带来了生存危机?学院/大学是实际回报不固定的投资的完美例子。远非如此。事实上,投资的回报几乎完全取决于学生投入的精力和时间。
这就是投资的全部。它只是简单地放弃一些东西,希望一段时间后你会得到一些东西回来。在金融界,放弃金钱是希望你能得到更多的回报。这个非常简单的概念推动了商业和整个经济的大部分发展。银行不断发放贷款和/或接受贷款。为什么有人会给我一堆钱,除非他们知道他们会拿回来,再加上更多?
散户投资者(为自己投资的人,而不是像专业投资者那样的公司)投资的一种相当常见的方式是将他们的钱存入储蓄账户。他们投入一些钱,然后随着时间的推移,他们的钱的利率复合,然后最终当他们拿回他们的钱时,它会略有增长。
这样做的问题是你的钱增长太慢。还有很多很多其他的投资方式和投资对象。快速定义,你投资的那些东西叫做资产。资产可以是:股票、债券、短期国库券、储蓄账户,任何最终能为你赚钱的东西。如果你想最大化你的回报,你需要有一个计划,考虑到你将投资的所有资产,以及每种资产你将投资多少。一旦你列出了你所有的资产和你的权重,它们是你投资于单个资产的总资金的百分比,你就得到你的投资组合。

Just like mixing ingredients for cooking, you want the best mix for your delicious investment portfolio
举个简单的例子,假设 Amber 有 100 美元是她在当地地铁工作赚来的。她想用这笔钱投资,这样她会得到一些好的回报。她决定将一些钱存入储蓄账户,一些钱用于购买股票。她决定将 40 美元或 40%存入利息为 3%的储蓄账户。她用剩下的 60 美元,即 60%,购买了埃克森美孚公司(XOM)的股票。一年后,她的 100 美元变成了 107 美元。那就是 7%的回报率。这可能看起来很小,但是想象一下,如果 Amber 不投资 100 美元,而是投资 100,000 美元?!回报率是一样的,但实际收益是巨大的!一年后,安珀将有 107,000 美元。如果 Amber 在接下来的五年里将她所有的收益进行再投资,她可能会净赚超过 15 万美元!如果她在接下来的 15 年里一直这样做呢?那就超过了 $30 万!(顺便说一句,这都是假设安珀没有把任何额外的钱投入她的投资组合,只是把她的收益再投资。)
既然我已经激起了你的兴趣,让我们来看看使用 Python 寻找最优投资组合的简单方法。
重要声明:接下来的大部分内容将是高度技术性的,所以如果有你不理解的术语和概念,请参考底部的参考资料部分。此外,本文的主要目的是提供投资组合分析的入口,而不是提供实际的投资建议,所以请不要将这些技术用于自己的投资决策。
数据
让我们首先设置下载股票数据来计算我们需要的重要参数:平均收益和方差。我们将使用 pandas 自带的数据阅读器库从 Yahoo Finance 获取股票数据。

让我们通过抓取特斯拉上的一些股票数据来确保该库能够工作。

现在我们已经建立了如何收集一些数据,让我们得到一些其他公司的股票。
现在让我们检查一下,看看我们是否有必要的数据。

让我们继续前进!
基于历史数据计算参数
现在我们有了历史数据,我们可以计算好的东西。
首先,我们从对数收益开始。这些是每天股票价格的百分比变化。

现在我们有了百分比变化,我们可以计算每项资产的平均日收益和协方差矩阵。为了确保每个人都清楚,协方差矩阵用于计算波动率。

现在我们有了所有这些信息,让我们创建一个假设的投资组合,看看我们得到什么回报和波动。如前所述,我们将对资产使用一些随机权重,看看我们的代码会给出什么。至于分配,我们就这么做吧:谷歌——50%,丰田——20%,可口可乐——20%,百事可乐——10%。

因此,我们看到,从我们的迷你投资组合中,我们的年回报率约为 16%,标准差约为 4%。鉴于这是基于 2010 年至 2019 年的数据,这些数字实际上相当不错。最酷的是,我们甚至还没有优化投资组合权重,因此还有很大的改进空间!
可视化数据
在我们真正开始优化我们的投资组合之前,让我们看看我们的股票(GOOGL,TM,KO,PEP)如何相互叠加。很多时候,可视化我们的数据使我们能够看到模式、趋势和见解,这在单独通过数据时会非常麻烦和困难。
这是我们得到的。你可以清楚地看到,一只股票通常回报越高,其波动性就越大。

优化我们的投资组合权重
现在让我们开始有趣的部分。让我们弄清楚(利用代码的力量)如何让我们的资产获得最大的回报。
我现在警告你,接下来你将看到的很多东西看起来就像一堆疯狂的编程奇才的胡言乱语。只要你遵循代码,理解所有东西并不是最重要的。
我们将首先定义一组函数,使这个过程变得容易得多。Python 有一个名为 scipy 的库,它有一个优化功能,使我们试图实现的东西变得相当简单。
第一个函数基本上完成了我们刚刚完成的工作,即在输入权重、平均回报和协方差矩阵后,计算投资组合回报和标准差。
我们将用来优化我们投资组合的一个指标叫做夏普比率,本质上是每单位波动率的平均回报率。从字面上来看,这意味着你所投入的风险能获得多少回报。
该函数根据前面提到的参数计算负夏普比率。我们计算负夏普比率的原因是因为 scipy 优化函数只能最小化。
在这里,我们实际上使用了 scipy 优化函数,通过优化我们刚刚定义的函数来找到最佳的投资组合权重。
当我们运行函数时,我们得到这些权重:[0.231,0,0.167,0.602]

There we go! We just got our optimal portfolio!
让我们试着在最小化波动的基础上优化我们的投资组合。
如果我们运行这个函数,我们得到权重:[0,0.783,0.217,0]

结论
在所有这些之后,我们可以看到在投资组合优化方面有很多东西要学。现实世界显然没有这么简单。对于我们的优化函数来说,输入和金融环境中最微小的变化都会极大地改变结果。尽管如此,这仍然是一个有趣的小练习。请随意尝试不同的技术和方法,看看什么适合你!
需要改进的地方
感谢您花时间通读这篇文章!请随意查看我的作品集网站或我的 GitHub 。
1.使用不同的股票数据
还有许多其他股票可能以相对较低的风险获得巨大的回报,所以要勤奋地做研究,找到这些公司。
2.尝试不同的优化功能
您不仅仅局限于 scipy 优化功能。还有很多其他的选择,比如求解算法。
3.了解更多关于投资分析的信息
这篇文章仅仅触及了金融和投资分析的表面。想学多少就学多少,想探索多少就探索多少。无论你是想为华尔街公司投资,还是仅仅为个人投资,这里都有适合每个人的东西。
资源
如何对自己的神经网络自信
这些笔记基于关于现代神经网络校准的研究论文(郭等,2017。)。
在 CIFAR100 等计算机视觉数据集上,ResNet 等非常大而深的模型远比 LeNet 等较老的模型准确。然而,尽管他们更擅长对图像进行分类,我们对他们自己的信心却不太有信心!
大多数用于分类的神经网络使用 softmax 作为最后一次激活:它产生每个目标(猫、狗、船等)的概率分布。).这些概率总计为 1。我们可以预期,如果对于给定的图像,我们的模型将 0.8 的分数与目标“船”相关联,我们的模型有 80%的把握这是正确的目标。
超过 100 个图像被检测为船,我们可以预期大约 80 个图像确实是真实的船,而剩余的 20 个是假阳性。
对于 LeNet 这样的浅层模型来说是正确的,但是随着新模型精度的提高,它们的置信度变得与“真实置信度”不相关。
这对深度神经网络不再有效:

Figure 1: Miscalibration in modern neural network [source]
如您所见,LeNet 等较老的网络准确度较低(55%),但它们的可信度实际上与准确度相当!ResNet 等现代网络具有更高的准确性(69%),但如图 1 所示,它们过于自信。
模型置信度和实际准确度之间的差异被称为校准错误。
为什么它很重要
除了学院中使用的玩具数据集,了解我们的模型有多少可信度也是有用的。
想象一下,我们有一个预测欺诈的模型。我们希望根据模型置信度将某个交易标记为可疑,因为它是一个欺诈。我们可以明确地计算出验证集的最佳阈值,然后超过该阈值的所有置信度都将被标记为欺诈。然而,这个计算的阈值可以是 0.2 或 0.9,但是对人类来说可能更有意义。
没有错误校准的模型将有助于用户更好地解释预测。
为什么会这样
作者从经验上探索了现代网络中这种失调的原因。
他们用预期校准误差 (ECE)来测量误校准:置信度和准确度之间的平均差值。这个指标应该最小化。
更高的容量和交叉熵
错误校准的最可解释的原因是容量的增加和交叉熵损失。
模型容量可以被看作是一个模型可以记忆多少的度量。由于容量无限,该模型可以简单地记住整个训练数据集。必须在低容量和高容量之间进行权衡。如果太低,模型将无法学习数据的基本特征。如果它太高,模型将学习太多和过度拟合,而不是一般化。实际上,理解就是压缩:通过留下足够少的容量,模型必须挑选出最有代表性的特征(非常类似于 PCA 的工作方式),然后将更好地概括(但是容量太少&将不会发生学习!).
ResNet 之类的新体系结构比老的 LeNet 具有更大的容量(前者 25M 参数,后者 20k 参数)。这种高容量导致了更好的准确性:训练集几乎可以被记住。
此外,模型优化了交叉熵损失,这迫使他们正确并且非常自信。更高的容量有助于降低交叉熵损失,从而鼓励深度神经网络过于自信。正如您在图 1 中看到的,新模型现在过于自信了。

Figure 2: More capacity (in depth or width) increases the miscalibration [source]
神秘的批量标准化

Figure 3: Batch Normalization increases the miscalibration. [source]
批量归一化归一化网络中的张量。这大大提高了训练收敛&的最终表现。为什么它能如此有效还不太清楚(见更多)。
作者凭经验评论说,使用批量标准化增加了错误校准,但找不到确切的原因。
这种方法在训练中的帮助会促进过度自信吗?
正规化

Figure 4: More regularization decreases the miscalibration. [source]
重量衰减是一种额外的损失,它损害了重量的 L2 标准。权重越大,标准越大,损失也就越大。通过约束权重的大小,它避免了模型寻找可能使其过度拟合的极端权重值。
作者发现,正如预期的那样,增加正则化会降低模型精度。
然而,它也减少了误校准!答案还是因为正则化避免了过度拟合&从而避免了过度自信。
如何修复校准错误
这篇文章的标题,“如何对你的神经网络自信”,让你相信你会发现如何减少错误校准。
您不会减少容量、取消批处理规范化并增加正则化:您会过多地损害您宝贵的准确性。
幸运的是,有后处理解决方案。作者描述了几种,但最有效也是最简单的一种:温度标度。
不是像这样计算 softmax:

所有 logits(最终激活前的值,此处为 softmax)除以相同的温度值:

类似( Hinton 等人,2015。),这个温度软化了概率。
极端概率(高置信度)比较小概率(低置信度)减少得更多。作者通过最小化验证集上的预期校准误差来找到最佳温度。
校准错误几乎完全得到纠正:

Figure 5: Temperature Scaling fixes the miscalibration. [source]
温度缩放的另一个很酷的特性:因为所有的 logits 都除以相同的值,并且 softmax 是一个单调函数,精度保持不变!
原载于 2019 年 5 月 29 日https://arthurdouillard.com。
如何少犯错误
用有限数据预测未来的贝叶斯指南
柏林墙还能屹立多久?这就是 j .理查德·戈特 1969 年访问德国时的想法。
仔细想想,这是一个棘手的问题,因为没有太多关于柏林墙寿命的数据(事实上,柏林墙是 T2 唯一的数据点)。那么,在我们几乎一无所知的情况下,如何处理这样一个问题呢?

Remains of the Berlin Wall. (Source: Pixabay)
戈特现在是普林斯顿大学的天体物理学教授,他是这样想的:他在那一年的某一天看到长城并没有什么特别的。如果你把这堵墙的整个生命周期分成四个等长的部分,那么有 50%的可能性他会在中间的两个部分到达。这反过来又转化为对墙应该保留多长时间的估计:到目前为止它的寿命的三分之一(如果他碰巧在两个中间部分的末尾访问),到目前为止它的寿命的三倍(如果他碰巧在两个中间部分的开始访问)。
鉴于当时的长城在 1969 年已经建了 8 年,他得出结论说,有 50%的把握,它还能再用 3 到 24 年。这堵墙又持续了 20 年。

There is a 50% chance that Gott’s visit falls within the middle two segments of the Wall’s existence. (Source)
哥白尼原理:我们并不特别
戈特的推理是,他没有在任何特殊的时刻拜访长城,这实际上是更广泛的 哥白尼原理 的应用,该原理指出,我们在宇宙历史中既不占据特殊的位置,也不存在于特殊的时间。地球不是一个特别的地方,我们的太阳系或银河系也不是。2019 年并不是一个特别的活着的时间。
Gott 基于哥白尼原理的计算至少可以帮助我们在完全不知情的情况下对事件发生的时间做出估计。用它来估计各种世界大事可能是一项有趣的练习:
- 朝鲜有 50%的可能性作为一个孤立的国家再存在 24 到 213 年。
- 英国退出欧盟谈判有 50%的可能性会再持续 8 个月到 6 年。
- 欧元有 50%的可能性会再存在 7 到 60 年。
- 有 50%的可能性人类物种会再存在 7 万到 60 万年。
公平地说,戈特并不是第一个运用这种推理方式根据有限的数据做出预测的人。考虑一下 德军坦克问题 :二战期间,盟军试图根据目前缴获的坦克序列号来估算德军坦克总数。在极端的情况下,一辆缴获的坦克至少可以提供总共有多少辆坦克的线索。如果它的序列号是 60,那么有 50%的可能性坦克的总数在 80 到 240 之间。实际上,随着更多的坦克被俘获,这个估计会变得更准确。

Earth, as seen from Jupiter. (Nasa)
戈特基于哥白尼原理的计算实际上是应用贝叶斯定律的结果,该定律更广泛地告诉我们如何在面对新信息时更新我们的概率估计。Gott 展示了如何根据一个单一数据点更新我们的估计。然而,在大多数情况下,我们仅仅从我们的生活经验中获得了关于现象预期结果的额外信息,这些额外信息使我们的预测更加准确。
先验塑造了我们的预测
在我们的世界中,大致有两种不同类型的观察:围绕自然值聚集的事物,以及不围绕自然值聚集的事物。我们称前者为高斯分布,后者为幂律分布。人类寿命是高斯分布的一个例子,人类体重、卡路里摄入量、每晚睡眠时间、电影长度、老鼠尾巴长度等等也是如此。
以人类的寿命为例。我们对寿命有很好的预期:例如,在美国,平均寿命约为 78 岁,分布大致呈高斯型。用统计学术语来说,这个额外的信息是我们的先于。
由于我们的先验,我们可以根据某人的年龄来更新他们剩余寿命的概率,这比用哥白尼原理更准确——我们有额外的信息。例如,社会保障局每年都会更新这一计算方法,保险公司也是如此:根据他们的表格,7 岁儿童的预期剩余寿命约为 70 岁,而 70 岁老人的预期剩余寿命约为 14 岁。这是高斯先验的一个基本结果:你活得越久,你预期的额外寿命就越短。

Source: Unsplash
幂律
并非世界上的一切都遵循高斯分布。当观察值在许多数量级上发生变化时,我们很可能在处理一种幂律分布——例如城市人口、图书销售、电影票房、人们的财富和收入。
以电影票房为例。2018 年最成功的电影【黑豹】,拍出了大约 7 亿美元,而亿万富翁男孩俱乐部,表现最差的电影之一,拍出了微薄的 600 美元——这是 6 个数量级的差距!换句话说,幂律分布没有自然尺度:它们是无尺度分布。电影可以赚几亿或几亿美元。
利用贝叶斯定律,我们可以再一次估计我们期望一个观察结果在哪里结束,给定我们今天看到它的地方,给定幂律先验。事实证明,幂律先验隐含着一个乘法预测规则:将目前观察到的量乘以一个常数因子,这就是预期的最终结果。例如,对于电影票房,这个倍数大约是 1.4:鉴于一部电影已经赚了 1000 万美元,它很可能会达到 1400 万美元(对于亿万富翁男孩俱乐部,前景相当严峻)。乘法法则是幂律无尺度性质的直接结果,在幂律中,唯一能给我们尺度感的是我们所拥有的单一观察。
因此,Gott 的柏林墙预测——它将比它已经存在的时间长三分之一到三倍——类似于具有幂律先验的贝叶斯预测,不同之处在于乘法因子未知。由于缺乏数据,戈特的柏林墙计算更加无知。
因此,高斯先验和幂律先验之间最重要的区别是:有了高斯先验,事情持续的时间越长,我们期望它持续的时间就越短。有了幂律先验,事情持续的时间越长,我们期望它持续的时间就越长。

Source: Unsplash
生活就是学习的过程
无论我们承认与否,我们都会根据我们每天对世界的观察,含蓄地了解我们一生中世界上各种现象的先验知识。我们了解到人们的身高、体重和寿命集中在一个典型值上,而城市人口、电影票房和财富却没有。我们最终都是贝叶斯思想家。
"生活是一所概率学校."—沃尔特·巴杰特
以呼叫中心等待时间为例:研究人员 Tom Griffith 和 Josh Tenenbaum 根据已经等待的时间调查了人们认为他们的总等待时间。通过将他们的答案拟合到不同的分布,他们了解到,平均而言,人们对等待时间的预期是幂律的,乘法参数约为 1.3:在等待 5 分钟后,他们预计总共会等待 7 分钟。等了 50 分钟后,他们预计总共要等 67 分钟。
前科很重要
在《T2:T3 前的生存算法》一书中,作者布莱恩·克里斯蒂安和汤姆·格里菲斯讲述了哈佛生物学家史蒂芬·杰·古尔德的悲惨故事,他在 1982 年被诊断出患有一种致命的癌症。通过阅读医学文献,古尔德了解到他在这个阶段的平均寿命只有 8 个月。
然而,他推断,这个统计数字并没有说明任何关于预期寿命的 T4 分布。如果是高斯型的,那么他的预期寿命大约是 8 个月,越接近这一点,预期寿命就越短。
另一方面,如果这是一个幂律,他活得越久,他就能活得越久!古尔德发现这种分布实际上是严重偏斜的(更像是幂律),并在确诊后又活了 20 年。
前科很重要:我们的前科越多,我们的预测就越准确。
如何在迈向数据科学的旅程中保持灵感
以下是保持学习数据科学积极性的 7 个技巧。

Photo by Kristopher Roller on Unsplash
由于数据科学是一个相对较新的领域,如果没有正确的心态和方向,学习数据科学可能会令人疲惫不堪。此外,仅仅通过使用 Scikit-learn 掌握数据可视化或了解所有机器学习术语,你不会立即成为数据科学家。这需要几个月甚至几年的实践和对不完美数据的亲身实验。它是软技能(黑客技能)和硬技能(沟通)的融合。
也就是说,学习它将是你一生中最好的投资之一。难学甚至更难掌握的事实使得这个领域在未来的岁月里非常有价值。同样值得理解的是,你不能只学习数据科学,因为它是许多技能的组合,你所能做的就是提高这些技能。
现在,在我进入改变生活的建议——获得动力和燃烧激情之前,我相信如果你心满意足地发现自己需要学习数据科学的动力,那么你可能根本就不应该走这条路。一个真正热爱数据,热爱用黑客技巧和数学分析事物的个体,应该是愿意不断学习数据科学的。每一天都应该被视为学习的机会。
如果你经常发现自己需要学习数据科学的动力,那么你就不应该一开始就追求它。
尽管如此,这里有 7 种方法可以点燃你内心的火,让你开始感到被点燃了去实现你的目标。突出对你来说很重要的想法,仔细思考,花时间思考,好好阅读。
1.不要让金钱成为你的动力

Photo by Alexander Mils on Unsplash
首先,金钱不应该是你的首要目标或动机。我这么说是因为你可能已经决定进入数据科学领域,因为那里有丰厚的薪水和难以置信的高需求。据 Glassdoor 报道,数据科学家的平均工资为 120495 美元/年,最高为 163000 美元/年。
“钱通常是被吸引来的,而不是被追求来的。”—吉米·罗恩
尽管社会传播着这样一种观点,即获得大学学位的动力是受雇于一家有声望的公司,有一份赚钱的工作,以便谋生和偿还债务,等等。即便如此,我认为金钱不应该成为一个人进入数据科学或任何工作的动机。
在我看来,这是因为从长远来看,金钱并不能给你带来动力。当然,你可能对你在优步或脸书的新数据科学工作充满热情,而且你在财务上做得很好,但如果你正在做的事情不是你喜欢的,迟早你会意识到,当钱可以用来实现上帝赋予你的目的和使命时,它不值得你宝贵的生命。同样,许多数据科学家正在离开他们的工作岗位,主要是因为他们的期望与现实不符。所以好好想想,反复思考这个问题。
2.设定你自己的目标

Photo by Estée Janssens on Unsplash
目标是你发展和成功的基石。没有它们,就像跑一场没有终点线的比赛。没有目标意味着你的生活没有意义。所以很明显,有目标是很重要的。
即使你已经有了目标,挑战也在于确保这些目标是你独有的,而且只属于你一个人。永远不要根据别人说的或做的来设定目标。它应该符合你对生活的愿景,而且是没人能说服你放弃的事情。
“如果你想快乐,就设定一个目标,这个目标能控制你的思想,释放你的能量,激发你的希望。”—安德鲁·卡内基
将你的目标分为短期和长期也是很好的,这样你就可以有所作为。短期目标可以为你提供短暂的推动力,驱使你努力实现长期目标。
假设你的目标是获得一份与数据科学相关的工作。短期目标是学习基本的 Python 和与数据科学家建立联系,长期目标是在数据科学领域找到一份工作,成为一名全栈数据科学家。
一个建议是试试概念应用,它有很棒的模板,可以用来设定目标、待办事项、笔记等等。这将是一个非常有用的反思工具,提醒你关于你的目标和日常反思,无论你是否朝着你的目标努力。现在就试用!
3.用创造性的视觉想象结果

Photo by Caleb Jones on Unsplash
创造性想象描绘了一种方法,利用你的想象力来想象你想要的结果,并为你构建一幅精神画面来重新连接你的大脑。这让你的头脑有努力的目标,就像灯塔用它的光束指引船只驶向安全。
它是许多成功人士自觉或不自觉使用的一个不可或缺的工具,让他们高度专注于实现自己的梦想和抱负。通过想象自己成功,他们实际上吸引了成功。
“在做之前想象一下你想做什么。可视化是如此强大,当你知道你想要什么,你就会得到它。”
——奥黛丽·弗莱克
如果你决定进入数据科学,那么你必须有一份理想的工作或公司,GAFA 公司——谷歌、苹果、脸书和亚马逊是许多数据爱好者渴望进入的知名科技公司。
举例来说,如果你的梦想是成为一名首席数据科学家,想象自己是 GAFA 公司的一员,管理一个由数据科学家、ML 工程师和大数据专家组成的团队,规划数据项目,建立预测模型等。
现在试试吧,去吧。闭上眼睛,想象自己处于最后阶段,想象每一个过程的细节。每天花些时间这样做,甚至你最疯狂的梦想也可能实现。
4.驾驭习惯的力量

Photo by Drew Beamer on Unsplash
T 尽管习惯被认为是不好的,不利于一个人的生活,比如吸烟,甚至是在 Instagram 上随意滚动,但习惯也可以是好的。专业人士将习惯视为给他们的生活提供结构的东西,并关注他们生活中的某些基本惯例。例如,比尔·盖茨读书很多,事实上,他一年读 50 本书。通过使阅读成为一种习惯,它已经成为他的第二天性。他强烈的好奇心和求知欲培养了他阅读的习惯,这造就了他今天的成就。
在查尔斯·杜希格的《习惯的力量》一书中,他提到成功的关键在于理解习惯是如何工作的。所有爬上成功阶梯的人都到达了顶端,因为他们专注于塑造他们生活的潜在模式,并建立了培养成功的习惯。
“冠军不做不平凡的事。他们做普通的事情,但他们不加思考地做,快得让另一个团队反应不过来。他们遵循他们已经学会的习惯。”查尔斯·杜希格
在学习阶段,你应该养成无数的习惯,以便更好地为未来做准备。首先,收集一份来自可靠来源的 A 级内容的资源列表,这样,你就有一个独特的渠道来跟上数据科学每日的最新消息,并跳过互联网上的所有垃圾。
接下来,养成问很多很多问题的习惯。作为一名数据科学家,你的工作就是做一名科学家,对数据做出假设。关键在于提出正确的问题,并据此做出理想的决策。此外,为了管理复杂性并使您的数据科学项目更不容易出错,您应该养成某些编码习惯——例如保持代码整洁和使用函数。
5.极其乐观

Photo by Allie Smith on Unsplash
O 乐观主义被定义为一种倾向于事物积极一面的精神优势。乐观主义者对事物有更高的期望,梦想更大,而悲观主义者(相反)通常期望较低,并认为一切都是最坏的。因此,乐观主义者更快乐,更健康,情商也更高。
“悲观者在每个机会中都看到困难;乐观主义者在每一个困难中都看到机遇。”温斯顿·丘吉尔
很明显,我们的思想对我们的行为和态度有很大的影响。如果你一直面对障碍和路障,你很容易失去自信。如果你让你的失败有害地影响你的想法,你会开始认为其他人都比你更有资格,你只是一个模仿者。这就是专家所说的冒名顶替综合症。
简而言之,当你对自己的成功有不确定性,并且永远害怕被暴露为“伪装者”时,就会出现冒名顶替综合症。这种综合症在数据科学领域非常普遍,原因有很多,但主要是因为 ML 工具的激增和数据科学定义不明确的事实。正如亚历克斯·兰姆所解释的,
这些工具的真相是,它们中的大多数都有很大的重叠。你不需要把它们都冷冻起来。但这不会阻止你的感觉。
应对这种不断把你推下去的综合征可能很难,但乐观地看,你会以不同的方式看待这个世界,并意识到有很多人和你一样面临这种综合征。不要让消极情绪征服你,要意识到即使是最好的人也会跌倒。相信自己,在任何情况下都保持乐观。
6.让你周围都是专家

Photo by Product School on Unsplash
你可能听说过这句话“你周围的人,你会成为什么样的人。”之前。生活给我们设置了许多障碍,在通往成功的道路上,总会有人质疑你的信念,挑战你。还有什么更好的方法能让你重新站起来,和那些听你说话并推动你前进的人一起前进。
不要成为房间里最聪明的人也很重要,因为那只会限制你真正的潜力,阻碍你成长和个人发展的空间。通过将聪明人包围在你周围,并与他们交换意见,你才能完全重新构建你对世界的框架,并提高你的期望
"你是和你相处时间最长的五个人中的平均水平。"—吉米·罗恩
为了让自己周围都是数据科学专家,你可以尝试在 LinkedIn、Twitter 等网站上与数据科学专家建立联系,因为在这个领域,联系是无价的。此外,参加聚会和会议也是让自己置身于来自世界各地的专家之中的另一个好方法。这不仅会拓展你的思维,而且你会从他们的激情和能量中汲取营养,让你充满活力和热情,开始为你的目标和梦想而努力。
ODSC 东方 2020 由 ODSC -开放数据科学是 2020 年 4 月举行的最大的人工智能会议之一!不要错过!去那里,让你自己被人工智能中最大的名字包围。
7.查看大图

Photo by pine watt on Unsplash
放眼全局意味着对你的目标有一个总体的想法。在你的头脑中有一个大的图景是非常重要的,因为有时候你会在你的学习过程中走极端,偏离你最初的目标。你现在看到的有益的东西从长远来看未必有益。
学会看清大局。我们常常目光短浅,看不到大局,也看不到我们真正想要完成的目标。—罗伯特·奇克
一个看不到全局的例子是,你可能会沉迷于学习太多的 ML 工具,最终成为一个万事通,但没有一个是大师。虽然掌握 ML 工具的知识在数据科学中是必不可少的,但是您只需要一些重要的工具来完成您的工作。因此,从这个意义上来说,大局可能是在数据科学世界中找到自己的位置。
问自己这个问题:数据科学的哪一部分首先让你着迷?是在 it 的业务方面,您与领导者和投资者交流数据吗?或者是机器学习不可思议的潜力和无限的能力?如果什么都不懂,那就去争取全栈数据科学家的职位。
你想达到的目标是什么?你清单上的第一个?把它写下来,放在你每天都能看到的地方。确保它不是一个你可以在一天或几周内完成的目标,它必须是值得你每天为之奋斗的东西,是让你感动并在你内心燃烧的东西。有了这个,你就能走在自己定义的成功之路上。
摘要
- 不要让金钱成为你的动力
- 为你的生活设定独特的目标
- 用创造性的视觉想象结果
- 驾驭习惯的力量
- 异常乐观
- 和志同道合的人在一起
- 查看大图
感谢阅读,我希望这篇文章对你有深刻的见解,并激励你去实现你的激情。
查看我的文章《给数据科学初学者的可行建议》!
这里是给进入数据科学的人的 5 个建议
towardsdatascience.com](/5-actionable-advice-for-data-science-beginners-50fd912aa2d6)
关注我在 LinkedIn 和 T2 Twitter 上的更新。
如何成为 Pythonic 式的,为什么你应该关心
提高 Python 软件质量的常用策略

Token photo of a Python for an article about [the other kind of] Python. Photo by Tyler B on Unsplash
蛇就是蛇,就是这样
我已经正式写了十几年的代码,最后 5 年是全职软件工程师,虽然我还有很多要学的(确切地说,是一辈子的学习!),在那段时间里,我已经见识了相当多的软件,并且(我敢说)极大地发展了我在该领域的技能。我仍然记得我写的第一批程序,晚上躺在床上回想我做程序员新手时的噩梦。虽然我永远无法逃脱过去的罪行(编写五重嵌套循环是最大的罪行),但也许我可以通过帮助其他新手学习一些最佳实践来编写更快、更干净、更好的代码,从而部分地救赎自己,即使只是轻微的救赎。

Photo by Rock'n Roll Monkey on Unsplash
蟒蛇——一种仿生蟒蛇?
与几乎所有编程语言一样,Python 社区接受了某些特定的风格和常规指导原则,以促进统一、可维护和简洁的应用程序,这些应用程序是按照该语言设计的方式编写的。这些指导方针从适当的变量、类和模块命名约定,到循环结构,甚至是包装代码行的适当方式。“Python”这个名字是用来描述任何遵循这些准则并利用 Python 独特功能的程序、函数或代码块的。
为什么所有这些都很重要?这个问题可以有多种解释,但是您应该关注的几个关键原因可以归结为代码的清晰性、效率和可信度。让我们进一步分析一下。
清楚
如果你想成为一名开发者,代码的清晰对你的成功至关重要。随着您在该领域的成长,您可能会在某个时候与其他人一起工作,这将需要同事阅读您的代码。如果你的代码写得很差,别人破译你的意图可能是一场噩梦,即使代码很短。从 r/badcode 子编辑中选取以下示例:

The definition of insanity
这个代码有用吗?没错。函数名描述了函数的用途吗?确实如此。如果您更改了函数名,是否很容易确定这段代码应该完成什么?如果不花一个小时分析它,可能不会。
正如我所知道的每一个开发新手(包括我自己)的情况一样,当涉及到代码时,有一种普遍持有的“它能工作——不要碰它”的心态。当我们可以写一些东西来解决我们的问题时,我们害怕对代码做任何事情,害怕我们会破坏一切并且无法再次修复它。
我鼓励任何开发人员尽早打破这种心态(这适用于所有语言)。即使你自己编写了糟糕的代码,一个星期,一个月,甚至一年后,你也很难再回头去看它,试图揭开它的神秘面纱。更糟糕的是,如果你自己都不能破译代码,你怎么能指望队友或合作者来揭开其中的含义呢?
通过按照语言设计的方式编写程序,开发人员自然会编写出看起来与同行相似的代码。这使得它易于理解,易于分享,易于更新。
效率
回到我在大学实习的时候,我在工作中遇到的一个实习生同事告诉我“不要费心去写已经用 Python 写好的东西,因为你不可能写出更好的东西。”虽然我最初对这种令人沮丧的想法感到沮丧,但我最终意识到他的说法有些道理。到目前为止,Python 已经存在了近三十年,并迅速成为全世界开发者最流行的语言之一。Python 还以包含大量库而闻名,这些库几乎可以做你想要或需要的任何事情。这些库和特性中的许多都见证了成千上万的成员在几年内创建更新,尽可能地从每一行代码中榨取尽可能多的性能。虽然我们当然欢迎您编写自己的最佳字符串比较函数,但您得到的结果可能不会比现有的结果更快,而且开发新函数所花的时间可能已经花在了您试图解决的实际问题上。一般来说,寻找一个内置函数或数据类型来实现你所寻找的。很有可能,这将是完成任务最快的方法。如果没有,检查是否有任何可以安装的库或包可以满足您的需要。如果你仍然没有解决方案,现在是时候创造自己的解决方案了!
可靠性
对于第一次学习如何用 Python 之外的语言编程的人来说,通常很清楚开发人员来自哪种语言。以下面这个问题为例:
- 求 10 到 1000 之间所有数字的和
C(或 C++)开发人员可能会按照下面的思路写一些东西:
int a = 10;
int b = 1000;
int total_sum = 0;while (b >= a) {
total_sum += a;
a++;
}
对此的直接 Python 重写看起来非常相似:
a = 10
b = 1000
total_sum = 0while b >= a:
total_sum += a
a += 1
虽然上面的语句会产生预期的输出,但大多数 Python 开发人员会对这段代码不满,抱怨它不是 Python,没有利用该语言的强大功能。从头开始,你可以用 Pythonic 的方式来解决这个问题:
total_sum = sum(range(10, 1001))
这一行代码生成了与上面完全相同的结果(为了记录,我打算在代码中写1001,因为 Python 的range命令有一个包含的下限和一个不包含的上限,这意味着较低的数字将是循环的一部分,而较高的数字则不是)。如果您使用第一个例子编写 Python 代码,您作为 Python 开发人员的可信度将会下降,因为 Python 社区非常热衷于按照指南编写代码。这是另一个例子:
- 确定特定字符串是否在数组中
对于大多数非 Python 开发人员来说,第一个解决方案可能是这样的:
#include <stdbool.h>
char * arr[] = {"apples", "oranges", "bananas", "grapes"};
char * s = "cherries";
bool found = false;
int len = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < len; i++) {
if (!strcmp(arr[i], s)) {
found = true;
}
}
和以前一样,直接的 Python 翻译应该是:
arr = ["apples", "oranges", "bananas", "grapes"]
s = "cherries"
found = False
size = len(arr)for i in range(0, size):
if arr[i] == s:
found = True
我相信你已经猜到了,用 Python 写这个有一个更简单的方法:
arr = ["apples", "oranges", "bananas", "grapes"]
found = "cherries" in arr
无论你选择上面的哪种方法,found最终总会评估到False(或false)。然而,当谈到 Pythonic 代码时,最后一个选择显然是冠军。它简明易懂。即使那些从未读过 Python(或任何相关代码)的人也有机会理解最后一个代码块的意图,这与前两个不同。
最后一个例子是我最喜欢的 Python 工具之一,列表理解。这种技术允许你在一个列表中嵌入一个循环来创建一个新的列表。请考虑以下情况:
- 将数组中每个偶数的值加倍
首先,这里是 C 代码:
int[] arr = { 1, 2, 3, 4, 5, 6 };
int length = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < length; i++) {
if (arr[i] % 2 == 0) {
arr[i] *= 2
}
}
直接的 Python 翻译:
arr = [1, 2, 3, 4, 5, 6]
length = len(arr)for i in range(0, length):
if arr[i] % 2 == 0:
arr[i] *= 2
现在大蟒道:
arr = [1, 2, 3, 4, 5, 6]
arr = [x * 2 if x % 2 == 0 else x for x in arr]
如果你从未见过列表理解的实际应用,这可能看起来很滑稽。我发现从右向左看理解列表通常是最容易的。首先,它遍历列表中的每个元素for x in arr,然后检查元素是否为偶数if x % 2 == 0。如果是这样,它将数字加倍x * 2,如果不是else x,则保持不变。无论元素最终是什么,它都会被追加到一个新的列表中。在我们的例子中,我们用新的列表覆盖了arr的原始值。
这些只是编写代码 Pythonic 化的几种常见方法。您可能已经注意到,所有这些例子都包含某种循环。虽然有许多方法可以编写 Pythonic 代码,但是一个很好的做法是问问自己是否真的需要一个循环,或者是否可以用一个惯用的替代方法来代替它。
如果您关心您在软件世界中的可信度,并且想自豪地称自己为 Python 开发人员,那么请确保您知道并在代码中使用这些适用的技术。

Photo by Carolyn V on Unsplash
叶老指引道
希望您现在理解了编写 Pythonic 代码的重要性。在这一点上,你可能想知道一些指导方针是什么,以及你如何能遵循它们。请允许我向您介绍一下 Python 增强提案#8 (PEP 8)。对于那些不熟悉 pep 的人来说,它们是由社区编写的提案,旨在改进 Python 的某些方面,从性能到新功能和文档。具体来说,第 8 个提议提供了关于样式指南和约定的建议。这是一个经常被引用的关于如何成为 Pythonic 的资源,如果你还没有读过,我强烈推荐你读一读。以下是我认为最重要的一些话题:
命名规格
命名约定对于任何语言都很重要,它提供了一种标识类型和对象的通用方法。以下是命名约定的简略版本:
- 包/模块:必须全小写。必要时可以使用下划线,但不鼓励使用。例如:
package或者module.py。 - 类:必须使用 CapWords。建议不要在名字中使用
Class二字。例:class BasketballTeam:。 - 常量:必须使用尖叫蛇格。例:
API_URL = '...'。 - 函数/变量:必须使用标准蛇盒。例如:
home_team_points = ...或者def final_boxscore(...)。 - 函数/方法参数:必须使用标准 snake case。例:
home_team_name。
注释的正确使用
注释是代码清晰的重要辅助。我通常建议在代码的任何部分上面添加注释,这些注释的目的对于其他人来说并不明显。一般来说,注释应该是完整的句子,位于代码块之上,用英语写。此外,建议使用文档字符串(或“文档字符串”)来记录函数的用途,以及描述输入和输出的类型、名称和描述(如果适用)。PEP 257 包含了大量关于如何使用文档字符串的信息。
将行换行到 79 个字符或更少
Python 开发中一个更有争议的话题与换行有关。PEP 8 要求每行代码少于或等于 79 个字符。一些嵌入式系统的屏幕尺寸有限,一行最多只能显示 80 个字符,如果更长的话,就需要很难看的代码包装。此外,如果某一行代码长达数百个字符,那么阅读起来会非常困难,因为该行中可能会丢失许多变量和函数调用。
虽然在大多数情况下这可能不是问题,但有时一行代码需要大量的空间,尤其是当它包含长变量名或复杂的列表理解时。解决这一问题的几种方法是,每次在函数调用中使用逗号时创建一个换行符。例如,替换
some_function(first_var, second_var, third_var, ... twelfth_var)
随着
some_function(first_var,
second_var,
third_var,
...
twelfth_var)
上面的两个块将被完全相同地执行。而在括号(或元组)中,逗号后新行上的任何代码都将作为下一个参数包含在语句中。
Python 还允许使用反斜杠来分隔不包含在元组或其他类似对象中的代码。例如,替换
if first_boolean_variable == accepted_value and not second_boolean_variable: # This is all one line
print('Accepted')
随着
if first_boolean_variable == accepted_value and \
not second_boolean_variable: # This is a second line
print('Accepted')
虽然这些改变会给你的程序增加额外的代码行,但它会变得更容易阅读,尤其是在一系列的显示类型和尺寸上。

Photo by Jared Rice on Unsplash
Python 的禅
另一个经常被引用的资源是 Python 的 Zen。以下短文是蒂姆·皮特斯写的 PEP 20 的唯一内容:
漂亮总比难看好。
明的比暗的好。
简单胜于复杂。
复杂总比复杂好。
扁平比嵌套好。
稀不如密。可读性很重要。特例不足以特殊到打破规则。
虽然实用性胜过纯粹性。错误永远不会悄无声息地过去。
除非明确消音。
面对暧昧,拒绝猜测的诱惑。应该有一种——最好只有一种——显而易见的方法。虽然这种方式一开始可能并不明显,除非你是荷兰人。
现在总比没有好。
虽然从来没有经常比现在*好。如果实现很难解释,这是个坏主意。如果实现很容易解释,这可能是个好主意。
名称空间是一个非常棒的想法——让我们多做一些吧!
虽然上面的几行是不言自明的,但最重要的主题可以用第七条来概括:“可读性很重要。”对我来说,这意味着任何 Python 开发人员,不管他或她的经验如何,都应该能够阅读和理解代码。Python 使用一种简单的语法,这种语法比几乎所有其他语言都更接近自然英语。因此,代码应该简单美观。用英语传达信息的最好方法是以简洁的方式表达。Python 也是如此。
不管你的代码要实现什么,永远记住 Python 的禅。如果您的代码不遵循这些原则,那么它就不是真正的 Pythonic 应用程序。

Every developer needs a set of useful tools. Photo by Cesar Carlevarino Aragon on Unsplash
编写 Pythonic 代码的工具
我们现在已经了解了为什么 python 代码很重要,一些关键原则是什么,以及一些 python 代码的例子。毕竟,是时候我们学习如何实际应用这些技术了。幸运的是,有几个工具可以用来检查我们的代码是否符合 Python 的指导方针。第一个工具,pycodestyle(以前的pep8)检查任何指定的 Python 模块,以确定它是否违反了 PEP 8 中列出的任何准则。更多信息可以在 GitHub 库上找到。
另一个常用的工具是[pylint](https://www.pylint.org/)。pylint的基本前提与pycodestyle相同,但它更进一步,在范围和建议上更具侵略性。我个人更喜欢pycodestyle,因为我在过去遇到过几次pylint的误报。虽然有一些方法可以对抗这些误报,但我发现不值得不断地修改我的源代码来解决问题,并解释为什么某些行没有通过,但应该通过。
我还应该注意到,还有额外的代码验证和林挺工具,但是上面提到的两个是最常用的资源。
编辑:感谢 Tarun Chadha 提到这些工具可以与流行的 ide 集成,比如 PyCharm 和 Visual Studio Code 。

Photo by Sara Kurfeß on Unsplash
为地道的未来干杯!
如果您已经做到了这一步,那么现在您应该掌握了编写更快、更干净、更好的 Python 应用程序的知识。这不仅有助于您的开发技能,还会赢得 Python 社区的更多尊重。实践这个行业,你可能会被认为是伟大的 Python 开发者的神圣领域。
如何用天赋打败谷歌的自动超参数优化
使用 Flair 进行文本分类的超参数优化

这是我们之前关于最先进的文本分类的帖子的后续。我们解释了如何使用 Flair Python NLP 库进行超参数优化,以在文本分类中获得优于 Google AutoML 自然语言的最佳结果。
什么是超参数优化,为什么我们不能简单地手动完成?
超参数优化(或调整)是为机器学习算法选择一组最佳参数的过程。数据预处理器、优化器和 ML 算法都接收一组指导其行为的参数。为了实现最佳性能,需要对它们进行调整,以适应所用数据集的统计属性、要素类型和大小。深度学习中最典型的超参数包括学习速率、深度神经网络中的隐藏层数、批量大小、退出率…
在自然语言处理中,我们还会遇到许多其他与预处理和文本嵌入相关的超参数,如嵌入类型、嵌入维数、RNN 层数等
通常,如果我们足够幸运,问题足够简单,只需要一个或两个具有一些离散值的超参数(例如 k-means 中的 k),我们可以简单地尝试所有可能的选项。但是随着参数数量的增加,试错法变得困难。
我们的搜索空间随着调整的参数数量呈指数增长。
假设离散选项,这意味着如果我们有 8 个参数,其中每个参数有 10 个离散选项,我们最终得到超参数的 10⁸可能组合。假设训练一个模型通常需要相当多的时间和资源,这使得手工挑选参数不可行。
有许多超参数优化技术,如网格搜索、随机搜索、贝叶斯优化、梯度方法以及最终的 TPE。树形结构的 Parzen 估计器 (TPE)是我们在 Flair 的包装器 Hyperopt 中使用的方法,Hyperopt 是一个流行的 Python 超参数优化库。
使用 Flair 进行超参数调谐
Flair 提供了一个简单的 API 来调整您的文本分类器参数。然而,我们需要告诉它需要调整哪些类型的超参数,以及应该为它们考虑哪些值。
运行优化器并不比训练分类器本身更难,但它需要更多的时间和资源,因为它本质上要执行大量的训练。因此,建议在 GPU 加速的硬件上运行。
我们将对在 Kaggle 垃圾短信收集数据集上训练的文本分类器模型进行超参数优化,以区分垃圾短信和非垃圾短信。
做好准备
要准备数据集,请参考最新文本分类的“预处理—构建数据集”部分,在此我们获得train.csv、test.csv和dev.csv。确保数据集存储在与运行 Flair 的脚本相同的目录中。
您可以通过运行以下命令来检查您是否有可用于培训的 GPU:
import torch
torch.cuda.is_available()
它返回一个 boolean 值,指示 CUDA 是否可用于 PyTorch(在它上面写有 Flair)。
调整参数
超参数优化的第一步很可能包括定义搜索空间。这意味着定义我们想要调整的所有超参数,以及优化器应该只考虑它们的一组离散值还是在一个有界的连续空间中搜索。
对于离散参数,使用:
search_space.add(Parameter.PARAMNAME, hp.choice, options=[1, 2, ..])
对于均匀连续的参数,使用:
search_space.add(Parameter.PARAMNAME, hp.uniform, low=0.0, high=0.5)
所有可能参数的列表可在这里看到。
接下来,您需要指定一些参数,这些参数涉及我们想要使用的文本分类器的类型,以及要运行多少个training_runs和epochs。
param_selector = TextClassifierParamSelector(
corpus=corpus,
multi_label=False,
base_path='resources/results',
document_embedding_type='lstm',
max_epochs=10,
training_runs=1,
optimization_value=OptimizationValue.DEV_SCORE
)
注意DEV_SCORE被设置为我们的优化值。这是非常重要的,因为我们不想基于测试集优化我们的超参数,因为这会导致过度拟合。
最后,我们运行param_selector.optimize(search_space, max_evals=100),它将执行优化器的 100 次评估,并将结果保存到resources/results/param_selection.txt
运行整个过程的完整源代码如下:
from flair.hyperparameter.param_selection import TextClassifierParamSelector, OptimizationValue
from hyperopt import hp
from flair.hyperparameter.param_selection import SearchSpace, Parameter
from flair.embeddings import WordEmbeddings, FlairEmbeddings
from flair.data_fetcher import NLPTaskDataFetcher
from pathlib import Pathcorpus = NLPTaskDataFetcher.load_classification_corpus(Path('./'), test_file='test.csv', dev_file='dev.csv', train_file='train.csv')word_embeddings = [[WordEmbeddings('glove'), FlairEmbeddings('news-forward'), FlairEmbeddings('news-backward')]]search_space = SearchSpace()
search_space.add(Parameter.EMBEDDINGS, hp.choice, options=word_embeddings)
search_space.add(Parameter.HIDDEN_SIZE, hp.choice, options=[32, 64, 128, 256, 512])
search_space.add(Parameter.RNN_LAYERS, hp.choice, options=[1, 2])
search_space.add(Parameter.DROPOUT, hp.uniform, low=0.0, high=0.5)
search_space.add(Parameter.LEARNING_RATE, hp.choice, options=[0.05, 0.1, 0.15, 0.2])
search_space.add(Parameter.MINI_BATCH_SIZE, hp.choice, options=[16, 32, 64])param_selector = TextClassifierParamSelector(
corpus=corpus,
multi_label=False,
base_path='resources/results',
document_embedding_type='lstm',
max_epochs=10,
training_runs=1,
optimization_value=OptimizationValue.DEV_SCORE
)param_selector.optimize(search_space, max_evals=100)
我们的搜索空间包括学习率、文档嵌入隐藏大小、文档嵌入 RNN 层数、丢失值和批量大小。注意,尽管只使用了一种类型的单词嵌入(一堆新闻向前、新闻向后和手套),我们仍然必须将它传递给搜索空间,因为它是一个必需的参数。
结果
优化器在 GPU 上运行了大约 6 个小时,执行了 100 次评估。最终结果写入resources/results/param_selection.txt。
最后几行显示最佳参数组合,如下所示:
--------evaluation run 97
dropout: 0.19686569599930906
embeddings: ./glove.gensim, ./english-forward-v0.2rc.pt, lm-news-english-backward-v0.2rc.pt
hidden_size: 256
learning_rate: 0.05
mini_batch_size: 32
rnn_layers: 2
score: 0.009033333333333374
variance: 8.888888888888905e-07
test_score: 0.9923
...
----------best parameter combination
dropout: 0.19686569599930906
embeddings: 0
hidden_size: 3
learning_rate: 0 <- *this means 0th option*
mini_batch_size: 1
rnn_layers: 1
根据进一步评估确认的调优结果的test_score,我们获得了测试 f1 分数 0.9923 (99.23%) !
这意味着我们以微弱优势超过了谷歌的 AutoML。

Results obtained on Google AutoML Natural Language
提示:如果 *precision* = *recall* 那么*f-score*=*precision*=*recall*
这是否意味着我可以按照这个指南一直达到最先进的效果?
简短回答:不。该指南应该让您很好地了解如何使用 Flair 的超参数优化器,并且不是 NLP 文本分类框架的全面比较。使用所描述的方法肯定会产生与其他最先进的框架相当的结果,但是它们会根据数据集、使用的预处理方法和定义的超参数搜索空间而变化。
注意当选择最佳参数组合时,Flair 会考虑所获得结果的损失和变化。因此,损失最低且 f1-得分最高的车型不一定会被选为最佳车型。
那么我现在如何使用参数来训练一个实际的模型呢?
要在实际模型上使用最佳性能参数,您需要从param_selection.txt中读取最佳参数,并手动将它们一个接一个地复制到将训练我们的模型的代码中,就像我们在第 1 部分中所做的那样。
虽然我们对这个库非常满意,但是如果能够以一种更加代码友好的格式提供最佳参数,或者更好的是,在优化过程中可以选择简单地导出最佳模型,那就更好了。
如何战胜人工智能项目的阻力:3 个步骤

是什么阻碍了人工智能在您的组织中的采用?了解制药公司如何克服 3 个最常见的障碍
在最近由 O'Reilly 进行的一项调查中,受访者称“公司文化”是在他们的组织中采用人工智能的最大瓶颈。尽管人们对人工智能议论纷纷,但组织中的大多数人还没有认识到人工智能的必要性。

Pic: O’Reilly survey on AI adoption in the enterprise
在我看来,每个组织的高管都面临三个常见的障碍:
- 人工智能从何入手?
- 这对企业来说是否可行?
- 你如何获得预算和买入费?
让我们看一个真实的例子,一个制药行业客户如何在药物发现中采用人工智能来解决这些问题。
1.找到你的人工智能可以解决的商业问题
启动任何数据分析项目的最糟糕方式是询问关于数据或分析的问题。相反,通过识别最大的商业挑战来开始你的人工智能之旅。
启动任何数据分析项目的最糟糕方式是询问关于数据或分析的问题。
数据科学只有在解决业务问题时才能发挥价值。第一步是识别业务挑战并确定其优先级。
这家制造仿制药的制药公司渴望开始一场人工智能之旅。通过绘制他们的现有业务流程,他们发现药物特性是一个需要改进的领域。这是药物发现的关键一步,包括研究分子的大小、形状和特性。
这里的挑战之一是从显微图像中计数生物细胞。这是一项痛苦的手动任务,耗费了病理专家数小时的时间。这是应用人工智能的潜在候选者。

Pic: Microscopic image showing the biological cells
2.评估人工智能试点的可行性和潜力
确定了最大的业务挑战后,对它们进行优先级排序。发现挑战对业务团队有多重要。检查是否可以通过数据和分析解决。
评估一下是否真的需要 AI 的火力。很多问题通过简单的分析就可以更高效的解决。当你必须应用人工智能时,通过建立一个快速试验来检查可行性。
算法从来都不是 AI 项目中最大的挑战。今天,大多数常见用例都有开源模型库。
今天,有个开源库的 AI 算法可供通用用例使用。检查如何利用它们。公司文化抵制人工智能,因为缺乏熟悉和无法感知其好处。试点有助于正面解决这一问题。
制药客户选择解决手动细胞计数问题。人们发现这类似于人群计数——估计人群中的人数。一项文献研究揭示了关于人工智能驱动的人群计数的学术论文。
下一步是重用公共算法。在 Gramener 人工智能实验室,我们已经使用人工智能在购物中心进行了人群计数的试点实施。我们把它改装成一个工作试点来计算生物细胞。该试点项目展示了可行性、工作量和成本影响。利用潜在的时间和金钱节约,计算投资回报(ROI)。

Pic: AI pilot solution with a UI to count cells of different shapes
3.展示投资回报率和人性化的人工智能模型的结果
一旦你确定了商业问题的潜在人工智能解决方案,你必须在内部销售它们。高管们可能想知道人工智能项目是否是他们 IT 预算的最佳用途。由于可解释性和准确性的问题,用户可能会怀疑人工智能解决方案。他们担心人工智能是否会取代他们。所有这些导致了一种抵制文化。
始终使用视觉叙事来解释和人性化人工智能模型的结果。
通过展示业务投资回报,说服管理层预算。人工智能的不断进步有助于带来信任和透明的元素。利用它们和视觉故事向用户解释人工智能模型的结果。通过建立人的反馈和改进的渠道,让人们了解情况。
制药客户的 IT 主管证明,每张图像节省了 80%的时间。一年处理数千张图像,投资回报非常明显。
该解决方案构建了丰富的可视化层,以使模型输出易于理解。审查、编辑和添加手动输入的交互功能使人保持在循环中。人工智能可以通过人类输入的自动再训练来改善每一次运行。

Explainable AI: A framework to visualize what the AI uses to distinguish dogs from cats
将人工智能项目视为业务转型计划
总之,人工智能项目与业务转型项目没有什么不同:选择正确的问题来解决。通过试点评估想法。用可消费的福利说服用户。
然而,实践者经常被解决方案冲昏头脑。他们忽略了必须解决的问题。另一方面,用户被围绕人工智能的大肆宣传吓倒了。所有这些导致了一种抵制人工智能项目的文化。
技术领导者必须促进人工智能从业者和工具使用者之间的合作。他们需要教育人们人工智能将如何授权而不是压制他们。
您还必须导航人工智能项目要求的变更管理。通过教育、授权和启发来带动整个组织。
这篇文章最初是由 发表在 企业家项目上。增加了插图。
如何成为数据科学三重威胁

所以,前几天晚上我在看闪电侠(别评头论足),我起来看了闪电侠/超女穿越集、二重唱,其中闪电侠(格兰特·古斯汀)和超女(梅利莎·拜诺伊斯特)被困在一部音乐剧中,为了逃离不得不唱歌跳舞。
很明显,这一集之所以成为可能,是因为 Gustin 和 Benoist(以及他们的许多合作明星)都是非常有才华的演员,能歌善舞,还会演戏。
也就是说,他们是“三重威胁”。精通三种关键的、受欢迎的技能的人,会有令人难以置信的就业前景(如果你感兴趣,你可以在这里和这里看到这一集的片段)。
这让我开始思考。如果演艺界的“三重威胁”是会唱歌、跳舞、演戏的人,那么数据科学的三重威胁是什么样子的?你如何着手成为一个人呢?
数据科学家最重要的三项技能
为了回答这个问题,我研究了 2019 年 4 月 22 日至 2019 年 5 月 5 日期间在 LinkedIn 上发现的四个英语国家(澳大利亚、加拿大、英国和美国)的 100 个数据科学招聘广告。
这些招聘广告被选择来代表雇主类型、规模、行业和工作级别的广泛代表性,而纯粹的管理角色没有被考虑。
从这些招聘广告中,我手动提取了作为选择标准或在角色的日常职责中列出的技能的详细信息,并根据这些技能在招聘广告中出现的比例,确定了最受欢迎的 20 项数据科学技能。
他们在这里:

[如果你想知道,在创建这个列表时,我专注于一般技能,而不是特定的编程语言或技术,这就是为什么像 R、Python 和 Hadoop 这样的东西不值得一提。]
这些技能可以大致分为三类:
- 建模和统计:包括机器学习、统计建模和模型部署;
- 数据工程(和编程):包括数据争论、使用数据库和分布式计算(如果我们在分析中包括编程语言,我也会把它们放在这里);和
- 沟通和专业知识:包括提供见解、行业知识、领导和指导初级员工。
这三个类别与数据科学技能集的经典维恩图中显示的类别大体一致(下面给出了一个版本)。

然而,在我们的版本中:
- 我们扩大了“数学和统计”类别,以包括所有类型的建模(包括机器学习,它通常被认为是介于统计学和计算机科学之间),以及整个端到端的建模过程,直到部署;
- 我们用一个更接近软件或数据工程的类别来代替“编码”;和
- 我们扩大了“领域知识”类别,以包括对数据科学成功至关重要的其他软技能。
我们新版本的图表变成了:

基于此,我们可以认为数据科学领域的三重威胁是那些擅长数据工程和编程的人;建模和统计;交流和专业知识。
因此,要成为数据科学的三重威胁,有必要在这些类别中的每一个类别中培养自己的技能。
假设你已经对机器学习和编程有了一定的了解,以下是你可以重点培养的六项技能,以此来证明你对三重威胁的重视:
建模和统计
- 统计建模
- 模型部署
数据工程与编程 通信与工程
- 从数据中获得洞察力
- 领导和指导初级团队成员
- 沟通
让我们更详细地看一下每一项。
技能 1:统计建模
当许多数据科学家想到数据建模时,他们会立即想到大多数机器学习课程中教授的监督学习算法的集合。然而,除了这些算法之外,统计学还包括许多技术,这些技术适用于一些最常见的数据类型,而许多数据科学家似乎完全没有意识到这一点。
一些例子包括:

- 地理空间分析:与时间序列分析一样,地理空间分析技术是为应用于基于位置的数据(例如不同位置的降雨量测量)而设计的,并考虑了地理上接近的数据点之间的相关性。
- 广义线性模型:这些模型是标准线性回归模型的推广,可以应用于标准回归模型的假设不成立的许多情况。例如,在偏斜和计数数据的情况下。
在您的工具包中添加一些这样的技术,可以极大地拓宽您能够处理的问题的范围。
技能 2:模型部署
每一个称职的数据科学家都知道如何建立一个模型(模型好不好是另一回事)。但是在你造好它之后,你用它做什么呢?
当然,你不会期望将你的代码交给你的利益相关者(他们可能认为 Python 只是一种爬行动物,R 是字母表中的第 18 个字母)并让他们继续运行它吧?您需要能够部署您已经构建的模型。
模型部署在不同的情况下意味着不同的事情,不幸的是,在大多数数据科学学位或 MOOCs 中很少教授。
在某些情况下,部署可能只是意味着获取从模型中获得的见解,并使用它们来生成报告。
在其他情况下,这可能意味着开发一个前端/应用程序(例如,使用 Flask 或 Shiny),以便其他人可以自己运行您的模型,而不必接触代码。
在第三种情况下,它可能涉及到将您的代码转换成 R 或 Python 包,并上传到 CRAN 或 PyPi,以便其他人可以使用它。
意识到这一步,并学习一些把你的工作从电脑中拿出来,放在那些重要的人面前的替代方法,将会降低你的工作因缺乏关注而浪费的风险。
技能 3:使用数据库
如果你工作的(或想要工作的)公司有合理数量的数据(如果他们雇佣数据科学家,他们应该有),那么他们不会将这些数据存储在 csv 文件或 Excel 电子表格中。他们会把它保存在某种数据库里。
这意味着你,数据科学家,需要能够从数据库中提取数据。
最常见的数据库类型仍然是传统的关系数据库,在这种数据库中,数据存储在相互关联的表的集合中的行和列中。

如果招聘广告将 SQL 技能列为选择标准之一,那么你可以保证,如果你得到这份工作,你将与关系数据库一起工作,因为 SQL 是关系数据库的语言。
你不必学习所有关于关系数据库的知识。毕竟,你是数据科学家,不是数据库管理员。但是,如果您学习了连接(内部、外部、左侧和右侧)、键(主和外部)以及足够的 SQL 来合并和过滤一组表,那么您应该没问题。
技能 4:从数据中获得洞察力
每当我向我的前老板提交一份工作时,他总是会问的第一个问题是“那又怎么样?”
他为什么要关心我刚刚放在他面前的工作?里面有什么对我们的组织或客户有益的东西吗?我刚刚完成的工作意味着什么?
回答“那又怎样”是寻找洞见的全部内容,也是数据科学家可以为雇主增加价值的地方(从长远来看,如果你想保住工作,这一点很重要)。
如果你是一个组织或行业的新成员,那么寻找见解可能会很有挑战性。这就是行业知识(雇主看重的另一项技能)变得重要的地方。
通过花时间了解你工作(或有兴趣工作)的行业,通过与该行业的其他人交谈,或只是通过一般的研究,你提供见解的能力将会增加,你工作的价值也会增加。
技能 5:领导和指导初级团队成员
对于入门级的数据科学职位,领导和指导初级团队成员的能力并不那么重要。毕竟,在这样的位置上,你是团队中其他成员指导你的人,而不是相反。
然而,如果你渴望有一天爬上数据科学的阶梯,成为高级/首席数据科学家,甚至是数据科学团队的经理,那么发展你的领导和指导技能是你应该尽早考虑的事情。
从这个角度来看,虽然只有 6.7%的入门级数据科学职位广告提到能够领导/指导初级团队成员,但 18.2%的中级数据科学职位广告和 58.5%的高级数据科学职位广告都提到了这一点。
但是,领导和指导团队不应该是团队经理的职责吗?
通常,数据科学团队经理本身并不是数据科学家,因此培训初级团队成员的任务必然会落到数据科学团队的高级成员身上。
此外,经理通常是非常忙碌的人,因此他们需要高级团队成员的协助才能完成所有工作。这可能意味着更高级的团队成员指导初级成员,以便团队经理可以专注于指导高级团队成员。
不要等到别人问你。好事将会降临到那些自愿帮助团队其他成员并承担领导责任的人身上,不管这些责任有多小。
技能 6:沟通(不是你想的那样)
每个人都知道,要成为一名成功的数据科学家,你需要能够写下你的工作成果,并向他人展示。然而,这只是交流的一个方面。
交流是双向的。这不仅仅是说,也是听和解释对方在说什么。
当你被分配一项任务时,你需要和分配这项任务的人一起工作,准确地理解他们想要你做什么。这在一定程度上与倾听有关,但也包括提出正确的问题,以确定这个人所说的他们想要的实际上是否是他们解决问题所需要的(而事实往往并非如此)。
如果你能给别人提供他们真正需要的东西,而不仅仅是他们说他们想要的,那么这将会为你的声誉创造奇迹。
沟通也是关于能够影响他人。例如,根据您的分析结果,您可能需要能够影响他人做出正确的决定。
对于数据科学家来说,在管理层获得一个席位并不罕见,但如果你一旦到了那里,就无法影响这些人的决策,那么你还不如根本不在那里。
如果你和我一样,你永远也不会像梅利莎·拜诺伊斯特或格兰特·古斯汀那样能歌善舞(尽管,如果你能,那不是很棒吗?).
然而,如果你从上面提到的三种技能中选择一种,并且每周花几个小时来发展它们,很快你就会开始建立自己的令人敬畏的技能组合。这将使你成为数据科学世界的三重威胁。
它可能不会让你成为超女或闪电侠,但它肯定会让你变得超级。
Genevieve Hayes 博士是数据科学家、教育家和人工智能及分析专家,拥有Genevieve Hayes Consulting。你可以在LinkedIn或者Twitter上关注她。她还是 价值驱动数据科学 的主持人,这是一个每月两次的播客,面向希望最大化其数据和数据团队价值的企业。
想要发掘企业数据的价值,但不知道从哪里开始?**下载免费的数据科学项目发现指南。
如何成为一名数据科学家

Image of Chandrasekaran showing a possible trail that inspires me to create the trail below.
课程、书籍和电影几乎都是免费的
最近几个月,许多人问我如何才能成为一名数据科学家,在了解了大多数人的主要问题并随着时间的推移改进了我的答案后,我决定花大量时间制作这份指南,以便大多数人都能获得它。
索引
1-什么是数据科学家?
2-需要什么背景?
3-学什么?
4-受试者的循序渐进。
5-课程、书籍、电影推荐。
6-下一步。
1.什么是数据科学家?
如果你知道什么是数据科学家,你很难找到,因为即使是最有经验的专业人士也很难定义该领域的范围。一种可能的界定是,数据科学家是负责使用机器学习和统计学生成预测和/或解释模型的人。更完整(或详细)的描述可在以下链接中找到:
数据科学家的工作范围和角色是什么。
medium.com](https://medium.com/swlh/data-science-and-the-data-scientist-db200aac4ea0) [## 每个人都需要掌握的 10 种偏见和因果关系技巧。
第 1 部分—数据科学和机器学习中的偏差、因果关系、实验设计和辛普森悖论
medium.com](https://medium.com/@marcos.silva0/the-10bias-and-causality-techniques-of-that-everyone-needs-to-master-6d64dc3a8d68)
作为一名数据科学家,要不断学习、更新和提高。学习应用机器学习不会让你成为一个人,改变不仅仅是技术的集合,而是面对问题的思维方式的改变,它是怀疑的思考,没有偏见,它不会很快到来。
这份入门指南可以节省您寻找最佳材料或学习顺序的时间,而不是取代您培训所需的数百个小时。
2.必要的背景是什么?
第一波数据科学家主要来自开发人员、计算机科学家和工程师。他们创造了机器学习模型,优化了流程,最小化了成本函数。他们将分析非结构化数据,为每个问题创建特定的程序,并且由于计算处理的限制,进行手动映射/简化。幸运的是,时间一去不复返了,高性能程序和软件包极大地促进了这些操作,目前大多数数据科学家在建模上花费的时间更多,而在工程上花费的时间更少。

Image of Andrew Silver showing the great pillars of Data Science.
好消息是,今天,这个学习曲线不再那么陡峭了。来自不同背景的人有机会加入这个领域,其中一个主要原因是 Python 的大量使用,Python 是一种高级语言,作为更具表演性的低级语言的 API。换句话说,你不必浪费精力担心复杂的语法,因为,用 Python 写就像用英语写一样。你只需要在几周内学习掌握基础知识。除此之外,数据科学家的大部分耗时工作正在自动化或专门用于其他领域,如机器学习工程师和数据工程师。因此,把科学的一部分留给科学家。
如今,处理大数据已经变得像在 DataBricks 等环境中编写 SQL 一样简单。
有了像 SageMaker 及其竞争对手这样的工具,让算法在生产中高度可扩展和可用变得更加简单。
使用 AutoML ,甚至复杂特征工程的创建也实现了自动化。
简而言之,今天编程背景仍然重要,但重要性正在下降,我对未来的预期是,编程将不再是核心,它将成为 it 专业人员的专属活动。所以,我给你一个建议:把你的时间和精力集中在分析、建模和科学上。
3.那么学什么呢?
编程:Python & SQL

你肯定需要学习如何编程,许多语言都满足这一需求,无论是像 Scala 这样最具执行性的语言,还是像 R 这样更学术和统计性的语言,或者像 Python 这样通用的语言,后者对于任何初学者来说都是最明显的选择。原因很简单。Python 拥有最大的数据分析社区,在 Kaggle (机器学习竞赛网站成为数据科学家的作品集)中找到分析的例子,在 Stackoverflow (Q &一个拥有大多数初学者和经常是高级问题的网站)中找到代码例子,以及职位空缺,因为它是市场上最受欢迎的语言。
机器学习:公分母。

没办法跑,你不可避免的要经过机器学习的基础。当我在 2014 年第一次开始学习机器学习时,大多数课程都专注于推导模型,就像正规学位所期望的那样,许多 DS 都是这样训练的,
这给了你巨大的能力来理解不同模型内部如何工作,甚至思考每个问题的最佳模型。我建议你不要这样做。研究许多不同模型类别的成本收益非常小,你需要知道(每小时)模型是一个黑盒,可以将输入(我们的变量,如人的身高,他们住在哪里,他们赚多少钱)转化为输出(如他们成为欺诈者的可能性)。几乎每个模型都有许多共同的技术,我的建议是,你先学习这些技术,然后再专注于理解它们的数学差异和实现细节。
统计:基本做得好。

我把最好的,最重要的,也是(不幸的)最难的留到了最后。正是这种技能将区分数据科学家和机器学习工程师。这里没有太多的捷径。你应该从描述统计学开始,知道如何做一个好的探索性数据分析( EDA ),或者至少是概率和推理的基础知识,很好地理解选择偏差、辛普森悖论、变量关联(特别是方差分解方法)、统计推理的基础知识(以及著名的、市场上已知的作为推理的 A / B 检验),以及实验设计的好主意。
4.什么是理想的赛道?

这是一个很难的问题,根据每个人的背景可能会有不同的答案。但是万一你是初学者,我会建议,随着你的进步,你应该按照你最喜欢的细分领域去做。
先决条件:
- 数学:代数- >微积分。
- 统计:描述性统计- >概率>推断
- Python :数据类型- >迭代- >条件- >函数
基本:
我把基础知识称为任何数据科学家都应该具备的知识,无论背景或专业如何。
- 熊猫数据分析(打开不同的文件并操纵它们)
- 统计:变量之间的关联、方差分析、假设检验;
- 即:matplotlib;seaborn 散景;
- 数据 : SQL,查询 APIs
- 监督机器学习:梯度下降- >偏差和方差的权衡- >验证- >正则化-
回归和分类度量- >平衡- >参数化- >特征选择;—>观念的整体性;
- 无监督机器学习:聚类、降维
中介:
在这一点上,一个数据科学家应该专攻一个更小的(也是更困难的)领域;在这个阶段,几乎没有人是所有领域的专家,但我会向您展示每个领域:
- 统计:贝叶斯统计,因果实验;计量经济学(如果实验是不可能的),数据管理;
- 数据:数据摄取、Web 报废、非结构化数据、大数据环境;
- 生产算法:转换流水线;容器和创建 APIs
- 创建多层模型(堆叠)和元模型,
嵌入模型;用莱姆和 SHAP 解释模型; - 具有自相关数据(或仪表板数据)的机器学习;
高级:
我选择以下主题作为高级,不是因为它的难度,而是因为它们是最专业的知识。对于一个有经验的数据科学家来说,仅仅因为他或她在工作中没有机会,而不必使用这些技能的一部分是完全可以接受的。不过还是那句话,
了解所有技能的基础很有意思。
深度学习:深度强化学习、自然语言处理、计算机视觉;
统计学 : MCMC,带有倾向分数匹配和工具变量的因果建模,合成反事实。
数据:面向图形的数据、数据湖、流数据、低延迟 API、kubernetes
5.这些都是从哪里学来的?
由于我已经为生活在世界任何地方的任何对数据科学感兴趣的人写了这个指南,我将只推荐在线课程,最好是免费的。所有这些至少都有英文字幕,涵盖了上述线索的基本部分。
Python:
最完整的推荐 Python 课程是 MITx 的计算机科学和使用 Python 编程入门(>120 小时)或 Michigan 的Python for Everybody(>30 小时),你可以根据你有多少时间来选择。两个课程都已经从零开始形成了几千人,所以你没有先决条件,你会写小程序。
如果你已经熟悉其他编程语言,但不了解 Python,你可以选择来自 DataCamp (免费)的 4 小时短期课程。
机器学习:
一大群 DS 在斯坦福著名的机器学习课程中向 Andrew NG 学习。我不能不推荐。他采用了更技术性的方法,使用 Octave 语言(一种开源的 Matlab)。课程约 60h,先修线性代数和基本统计。
其他完整选项包括:
机器学习来自华盛顿大学 Coursera ( > 180h)
Nanodegree de 机器学习由 Udacity 提供(不免费)(> 120h)
统计数据

(更长更饱满) 统计学基础,MIT,免费,> 160h。这是一门非常广泛的课程,如果你没有数学或相关领域的背景,它可能太专业了,因为这是一门推导概念背后的数学的课程。本课程将教会你:
- 特定的模型对于特定的数据集有多合适?
- 线性回归如何选取变量?
- 如何对非线性现象建模?
- 如何查看大数据?
如果你想从短期(和基础)课程开始,这里有个替代选项 :

概率由哈佛,edX,免费 ~ 12h。这是一门比前一门更实用的入门课程,侧重于概率的主题,你将学到几个基础知识,例如:
- 随机变量,
- 独立,
- 蒙特卡洛模拟,
- 期望值,
- 标准误差,
- 中心极限定理。

推理与建模,哈佛,edX,免费 ~ 12h。补充前面实用性课程的另一个重要主题是同样由哈佛团队开发的推理课程。在本课程中,您将学习制作良好的统计模型所需的基础、误差范围,并了解本课程样本的预测可靠性,所有这些都有真实世界的例子,如 2016 年选举的数据。
书籍推荐
介绍性:

我不推荐给任何已经有基础的人,因为它太慢了。最近发布了这本书的第二版。

用于数据分析的 Python:与熊猫、NumPy 和 IPython 的数据角力作者 Wes McKinney 。这里所有的书显然都是很好的读物,但这里有一个阅读案例,是简单(或不那么简单)技巧的很好汇编,它会为你节省很多时间。
这不是一本统计学或机器学习的书,但你需要通过这些技术来做任何最接近真实世界的事情。

用 Scikit-Learn 和 TensorFlow 进行动手机器学习:构建智能系统的概念、工具和技术 。这里有一本优秀且最新的书(我甚至推荐最近发布的已经更新到优秀 tensorflow 2.0 的这本书的第二版)。第一部分讨论机器学习算法的“共同点”,第二部分重点讨论神经网络。
除此之外,还有一个很棒的 github 库,里面有这本书的所有代码。可用此处-v2 ou 此处-v1 。

说白了就是统计 。对那些没有统计学背景的人来说是轻松简单的阅读。每章描述一种不同的统计技术,从基本概念如集中趋势和分布的描述到更高级的概念如测试,回归,重复测量方差分析和因素分析。
每一章都以统计数据的简要描述和何时使用开始,随后是可选的进一步阅读。

Think Stats:程序员概率统计 点击链接即可免费获得。在这本令人愉快的读物中,你将放下沉重的公式,开始分析国家卫生研究院的实际数据。对于那些需要比理论更实际的东西来学习的人,或者如果他们已经很好地了解了理论,并且想看看如何在现实世界中应用它。。肤浅有趣的书。

统计学习入门 一本经典,满满的例子和应用(用 R 语言)。不可或缺!涵盖的主题包括线性回归、分类、重采样方法、收缩方法、基于树的方法、支持向量机、聚类等。
使用颜色图表和真实世界的例子来说明所提出的方法。
没那么入门..

【免费链接】这篇文章是该领域的一个里程碑。在此之前,不同的地区发展了他们自己的语言和符号来使用统计概念,作者在统计学的阴影下收集了所有这些。这里强调的是概念而不是数学。
借助好的彩色图形给出了很多例子。对于统计学家和任何对科学或工业中的数据挖掘感兴趣的人来说,这是一个有价值的资源。它探讨了不同的算法和统计用途的机器学习技术。
.
.

伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔合著的《深度学习》一书,埃隆·马斯克这样评价这本书:“由该领域的三位专家撰写,深度学习是该领域唯一一本全面的书。”这本书的第一部分是对更传统的机器学习的相当全面的介绍,同时关注其余部分。这本书的主题是深度学习和知识前沿。网上免费提供。

流畅的 Python:清晰、简洁、有效的编程 一本真正完整的书(我不知道还有比这本书更完整的了)让你学习 Python 哪怕是最小的细节。高级素材,不推荐现在开始用 Python 的人。
.
.

。
。
。
。
。
黑客的贝叶斯方法 作者:Cam Davidson-Pilon。阅读有助于给这个超级重要的领域一些实用主义,但与 frequentist 统计相比,内容相当贫乏。轻量级文本主要关注概念和应用,将数学留在背景中,
最终可以在一本优秀的书中将概率编程与贝叶斯统计结合起来。
.
.
.
电影和纪录片推荐。

MoneyBall,2011 这是那种让我们对数据分析充满热情的电影。他讲述了比利·比恩抓住一个相当小的棒球队的故事,通过数据分析,大量的勇气和一点政治可以将旧的感觉方法抛在身后,并彻底改变一项超级传统的运动。IMDB 注释 7.6。不可错过的
。(一个参考是 8 级在电影史上前 250 名)

alpha go 2017 纪录片是如何将复杂的机器学习算法转变为所有观众都能理解的纪录片的又一个光辉例子。在网飞上可以看到,你将在一个几年前被认为是人类固有的游戏中学习机器学习的不可思议的潜力。附注 7.9。

统计的快乐,2010 是对使用统计数据的道歉,由兴奋的汉斯·罗斯林教授提出,他用各种视觉技巧展示了不同的领域如何处理这个数据泛滥的新时代。IMDB Note 7.3(太棒了!)
2013 年大数据时代 bbc quee 纪录片探索了三个非常有趣的案例:
- 洛杉矶警方预测未来 12 小时内哪里最有可能发生犯罪
- 伦敦金融城的科学家转行做交易员,他相信自己已经找到了用数学赚几百万的秘密
- 南非天文学家,他想通过聆听所有的星星来记录天空。
推荐的最新去处..
。第一个推荐并不完全是最新的,但它是一个相当丰富的例子和讨论的来源,它是 Google 购买的 Kaggle 网站。那里有竞赛(包括高额奖金)、课程、大量笔记本、讨论,最近它正在成为一种数据科学家课程。
所以如果你想成为其中一员,这是值得了解的。
KDnuggets 。不要让这个 90 年代的网站欺骗了你,但它确实创建于 1997 年,从那时起就收集了大量高质量的帖子和内容,大部分是技巧和应用。
AnalyticsVidhya。&TDS这些都是由成千上万各种水平的数据科学家组成的分享内容的博客。这需要一点经验来区分谷壳和小麦,但有很多质量。
Montreal . ai我最喜欢的枢纽之一,他们在不同的社交网络上发帖,如果你关注你的频道,就会不断更新前沿知识。高质量的内容很难跟上该领域的创新步伐。
6.后续步骤:
显然后面还有很多步骤要做。但是每个人最终都会专攻你最感兴趣的某个领域,比如:
贝叶斯统计 ,加州大学。
计量经济学 s (因果推断)鹿特丹伊拉兹马斯大学
深度学习by Deep Learning . ai
[计算机视觉](http://Convolutional Neural Networks Course by deeplearning.ai (Coursera))by deep learning . ai********
高等经济学院自然语言处理 或 TensorFlow 中的 NLP
如果你喜欢这篇文章,你可能也会喜欢以下内容:
如何成为一名数据科学家?
简介:
我很确定我们中的许多人都在 2012 年看过《哈佛商业评论》的这篇文章。数据科学家是被称为 21 世纪最性感的职业。此外,麦肯锡全球研究所早在 2013 年进行的研究预测,到 2018 年,北美将分别有大约 425,000 和 475,000 个空缺的数据分析职位。这里要传达的信息是,所有行业都将需要源源不断的分析人才,公司在这些行业收集和使用数据以获得竞争优势。
到底什么是数据科学家?
在一个过于简化的描述中,数据科学家是能够处理大量数据并提取分析见解的专业人士。他们向利益相关者(即高层领导、管理层和客户)传达他们的发现。因此,公司可以受益于做出最明智的决策来推动其业务增长和盈利能力(即,取决于行业环境)。
为什么成为数据科学家这么难?

数据科学的本质是许多学科的混合。由不同的学科领域组成,如数学(如统计学、微积分等。)、数据库管理、数据可视化、编程/软件工程、领域知识等。在我看来,这可能是有意跳入入门级数据科学职业的人常常感到完全迷失的首要原因。大多数人不知道从哪里开始,因为你可能在一个领域完全缺乏,或者多个领域取决于一个人的教育背景和工作经验。
不过,好消息是,你不需要对此过于担心。这些天来,我们面对一个完全相反的问题。有太多的资源可供选择。所以,你不一定知道哪一个最适合你。在本文中,我将从三个角度重点介绍如何成为一名数据科学家。
第一节:从哪里学习数据科学?

Figure 1. Data Science Education Path and Job Placement Rate
先从哪里学数据科学开始吧。从海量开放在线课程(MOOC)、大学学位/证书和新兵训练营培训中获得数据科学教育有三大途径。
下面是一个示例图,展示了每个选项的预计时间承诺与工作安排成功率。这提供了一个想法,即训练营教育可以让你比其他两种选择更快地获得数据科学家的工作。
下面是一个汇总表,提供了有关每个教育途径的更多详细信息。基本上,每个选项在成本、灵活性和项目长度方面都有优点和缺点。然而,做出正确决定的最佳建议是问问自己什么对你来说最重要。比如,你有充裕的时间,想把投资成本降到最低。或者你可能是一个想尽快找到工作的人,即使最初的投资成本很高。

Table 1. Breakdown Analysis of Data Science Learning Path Comparison
第二节:学什么数据科学?
作为一名数据科学家,肯定有很多东西要学。让我们从五个主要步骤开始了解数据科学教育途径。

Figure 2. Data Science Learning Pathways
第一步,补上与统计、微积分和线性代数相关的基础数学是一个好的开始。作为一名数据科学家,这对于理解不同算法背后的机制至关重要。它建立了关于如何调整或修改算法以解决独特业务问题的直觉。此外,了解统计数据有助于您将实验性设计测试(即 A/B 测试)中的发现转化为关键业务指标。
第二步,数据科学家必须熟悉在各种环境中处理数据的工具集。工具集包含 SQL、命令行、编码和云工具的组合。这里总结了每种工具的使用方法。对于从关系数据库中提取和操作数据,SQL 是几乎在任何地方使用的基本语言。用于一般编程目的(即函数、循环、迭代等)。),Python 是一个不错的选择,因为它已经打包了许多库(例如,可视化、机器学习等)。).对于额外的提升,了解命令行提供了额外的好处,特别是对于在云环境中运行作业。
第 3 步,这是学习一些语言来构建数据科学基础的最佳时机。对于商业软件,你可以选择 SAS 或者 SPSS。从开源平台,很多人要么选择 R,要么选择 Python。从这里,您可以了解有关数据管理/争论的概念(即,导入数据、聚合、透视数据和缺失值处理)。在此之后,您将从数据可视化(即,条形图、直方图、饼图、热图和地图可视化)中获得最有趣的数据。
第四步,你可以选择应用机器学习或大数据生态系统途径。请注意,你可以随时回来掌握另一条道路。就我而言,我选择先学习应用机器学习。基本上,它涵盖了从端到端建立机器学习模型的方面(即,从数据探索到模型部署)。为了了解大数据,我将更多地介绍从哪里获得这种教育(即书籍和课程)。
第五步,这是展示你作为数据科学家候选人潜力的最关键的一步。一旦你熟悉了数据科学,你必须有一个项目组合。项目组合是你展示你从学习和工作经历中所做的最好机会。从数据收集开始(即,你自己在哪里挑选或收集数据),提出你的假设,进行探索性分析(即,提取一些有趣的见解),建立你的机器学习模型,最后分享你在写作或演示中的发现。就我而言,我通过与指定的导师一起完成顶点项目,完成了一篇报道和一个视频播客。对于拥有一个可以直接与你一对一合作的导师的重要性,我怎么强调都不为过。当你陷入一些项目想法、调整你的模型、交流你的结果等时,你的导师是指导你并寻求帮助的最好朋友。事实上,一些研究提到,有一个导师可以比没有导师的人多五倍地促进你的职业发展。
第三节:如何学习数据科学?
在本节中,您将学习如何挑选成为数据科学家的最佳资源。我想根据我的学习经验提出建议。

Figure 3. Suggested Resource on Learning Data Science Education
对于 SQL 教育来说,微软从 Edx 提供的 DAT201x 课程是最好的选择之一。本课程从数据类型、筛选、连接、聚合(分组)、窗口函数和高级概念(如存储过程)等方面介绍了 SQL 的以下内容。本课程确保您通过使用最佳样本数据仓库(即 AdventureWorks)进行大量练习。或者,您可以使用模式分析平台来练习和增强您的 SQL 技能。模式分析最大的好处是,您不需要在机器上安装 SQL server 和示例数据仓库。你所需要的是有一个免费的帐户和互联网连接来享受你的学习。
对于机器学习教育,我喜欢推荐两个选项。第一个课程是该领域的任何数据科学从业者都熟知的。吴恩达的机器学习课程来自 Coursera。我用这个课程来理解如何调整我的机器学习模型的基本概念和技巧。从编码体验的角度来看,我强烈推荐塞巴斯蒂安·拉什卡的《Python 机器学习第二版》。我真的觉得这是最好的机器学习书。这本书从每个算法的基本机制、大量的编码示例和补充参考资料(即研究文章)来帮助你理解。这本书最棒的一点是,他一行一行地详细解释了如何实现每个机器学习算法。正如许多数据科学家提到的,这非常重要,人们应该能够从头开始编写代码,并知道如何实现它。如今,有许多复杂的问题无法通过使用 Python 现有的库直接解决。
这里是一个完整的资源列表,您可以参考这些资源来学习数据科学教育的每个组成部分。
1。数学:
可汗学院数学赛道
麻省理工学院开放课件:线性代数与微积分
Udacity:介绍和推断统计学
2。数据科学工具包:
结构化查询语言
o Edx: DAT201x —使用 Transact SQL 进行查询(*)
o 模式分析:SQL 教程(高级入门)
o WiseOwl: SQL 教程(高级入门)(*)
命令行
o Book:命令行中的数据科学
Python 编码
o Udemy:完整的 Python 训练营
o 书:艰难地学习 Python(第三版)
o Book:用 Python 自动化枯燥的东西
3。机器学习:
Coursera:吴恩达的机器学习(*)
Coursera:应用机器学习(密歇根大学)
哈佛:CS109 —数据科学简介(*)
书:Python 机器学习(第二版)Sebastian Raschka (*)
书:Python 机器学习示例
书:Python 机器学习入门
4。大数据:
Hadoop
o 图书:Hadoop 权威指南
o uda city:Hadoop 和 MapReduce 简介
o IBM: Hadoop 基础知识学习徽章
火花
o Edx:加州大学伯克利分校星火课程(CS105,CS120)
o data camp:PySpark 简介,在 PySpark 中构建推荐引擎
o 图书:学习 PySpark,使用 Spark 进行高级分析
奖励部分:寻求帮助和建立关系网
现在,我想通过提供一些额外的技巧来结束这篇文章。一开始,作为一个新手数据科学爱好者,你不一定有一个可以指导你学习经验的导师。因此,您需要一个向数据科学社区征求意见和反馈的地方。好消息是,有几个论坛你可以寻求帮助来解决你的问题。少数网站如 StackOverflow、Quora 等。让您发布您的问题,并收到对您帖子的回复。
另一个提示与网络有关。这真的适用于任何真正寻找新机会和建立联系的人。在多伦多,有许多与数据科学相关的本地聚会和大型会议。尽量多参加活动,介绍自己(即动机、目标、激情)。此外,如果你有机会接触演讲者和活动组织者,努力与他们建立有意义的联系。我认为我从经验中学到的一个有用的策略是寻找机会在任何可用的媒体上展示我的项目组合。我指的是在本地会议上发表演讲的机会,甚至是通过远程数据科学办公时间进行的视频网络广播。从这次经历中,我能够从我愚蠢的错误中学习,并从一个演示文稿到另一个演示文稿做出改进。这为数据科学家候选人带来了很多价值,可以提供有效的演示,并能够清晰地传达分析见解。
感谢阅读这篇文章。随着我在成为数据科学家的旅程中获得更多经验,我希望带来更多令人愉快和丰富的信息。
如何在 2020 年成为伟大的数据科学家
给新的一年开个好头的 5 个新年决心

Photo by Alex Radelich on Unsplash
明年是你的一年。
明年的这个时候,当你回首往事时,你会惊讶地发现自己作为一名数据科学家成长了这么多。我不怀疑。你也不应该。
然而,要做到这一点,需要努力和奉献。为了给你一个好的开始,我想讨论 5 个新年决心来帮助你进入下一个阶段。
每天学习
对你来说,明年是成长的一年。承诺每天至少花 30 分钟学习。
学习可以采取任何你想要的形式。可能是读一本书,开始一门新的在线课程,去一个聚会,或者开一个博客。如果你需要一些好书的想法,看看这个帖子:
建立一个伟大的知识基础
towardsdatascience.com](/the-top-3-books-to-get-started-with-data-science-right-now-3f9945d78011)
为了这个目标,不要过度思考学什么,开始学就好。从我的经验来看,几乎所有的数据科学家都受到学习的激励,但我发现我们经常会花太多时间来考虑要学习什么。我们想选择最好的科目,所以我们不花时间学习,而是花时间思考学习。
这并不是说你不应该花时间去思考你想学什么,而是一旦你有了想法,就去实现它。也许你一直想了解更多关于强化学习的知识。去做吧!你最初几天的学习可能只是发现强化学习的最佳资源。然后你就可以开始挖了。
另外,不要忘记这是你学习的时间。如果你害怕这个时候,那么你需要改变它。选择一个不同的主题,寻找另一种学习方法,或者找一个朋友参与进来。关键是找到一种坚持每天花时间学习的方法。如果你能做到这一点,当你回顾 2020 年时,你会发现这是巨大增长的一年。
成为主人
无论你的角色是什么,在 2020 年,人们都会将你视为如何为公司创造重大价值的榜样。除了“按现状”接受一个项目并检查向您提出的问题之外,您还可以通过询问以下问题来培养一种主人翁精神:
- 这个项目如何使公司更接近其目标?
- 我是否理解了项目的愿景,因此我能够创造性地思考潜在的解决方案?
- 我如何主动确保该项目交付价值?即使其中一些项目不属于我的“工作描述”
你还可以问很多其他问题,但这 3 个问题应该是将你的思维模式从任务执行者转变为价值传递者的良好开端。你会惊讶地发现这会给你的工作带来多大的变化。它会促使你成为一个更好的合作者,学习新的技能,跳出框框思考,因为你的工作只有在提供价值后才算完成。
我发现这种技能对数据科学家来说尤其重要,因为数据通常跨越公司的很大一部分。这通常意味着,作为一名数据科学家,你必须在公司的很多部门工作,以确保你的工作能够带来价值。如果你能掌握这项技能,你将变得无价。
从简单开始
在 2020 年,你不会为了炒作而被最新最伟大的炒作所吸引。当然,有复杂的模型可以产生惊人的结果,但是当开始一个项目时,你会问自己:
我如何在一天内建立我的第一个模型
如果你需要一些帮助,看看这篇文章:
在任何项目中度过前 8 个小时的最佳方式
towardsdatascience.com](/my-potent-first-day-routine-for-phenomenal-success-on-your-next-data-science-project-c96874f4bf16)
在一天内建立你的第一个模型将迫使你专注于保持简单,只解决最关键的问题。你的模型很可能很糟糕,但是你现在有了一个可以建立的基线。增加复杂性要比消除复杂性容易得多。作为一名数据科学家,遵循这条简单的规则将会促使你忽略无关紧要的事情,专注于你需要解决的核心问题。
失败更多
俗话说:“你在失败中学到的比成功更多。”我 100%相信这是你自作聪明。仅仅失败并不意味着你学习或成长。失败,然后花时间去理解为什么,并设定改进目标,可以帮助你显著成长。
今年,你将设定一个目标:比任何人都更擅长失败。
你设定的目标会将你推向极限,也会导致一些失败。当你失败时,你会花时间去成长。
例如,也许你设定了一个目标,用一种你从未使用过的机器学习模型来传递价值。这可能是强化学习或概率深度学习之类的东西。这种类型的目标会把你推出舒适区,迫使你成长。
不过,要小心,你要适当地失败。在时间敏感的关键任务项目上冒大风险不是一个好主意。不过,在第三产业项目中,同样的目标可能很有意义。这个目标很好地补充了“从简单开始”的目标,因为它确保你继续推进你的极限。否则,可能会有真正有价值的算法或技术你没有利用,因为你从来没有分支。
恢复
最后,在 2020 年,定一个目标,回馈他人。找时间指导、教导、引导或帮助他人成长。下次初级数据科学家在 LinkedIn 上寻求建议时,请回复并尝试提供帮助。亚当·格兰特很好地证明了作为一名给予者的价值,我完全同意。不仅帮助了别人,也帮助了你。
我确信,无论你的经验或技能水平如何,你都可以找到帮助他人的方法。你只需要看看。
我希望我的 5 个新年决心将帮助你正确地开始新的一年,并让你回顾 2020 年,这是成长、学习和成功的重要一年。
这篇文章也可以在这里找到。
加入我的 邮箱 列表保持联系。
如何成为人工智能驱动的公司

人工智能正在以前所未有的速度改变我们做生意的方式,但过渡到人工智能驱动比你想象的要容易。现在是投资并保持在游戏顶端的时候了。
几周前,随着被广泛称为计算界“诺贝尔奖”的今年图灵奖获奖者的公布,人工智能成为人们关注的焦点。约舒阿·本吉奥、杰弗里·辛顿和扬·勒昆因他们 30 多年来在人工智能领域的开创性工作而受到表彰。在 80 年代,当人工智能研究非常不流行时,三人组的动机是创造可以像大脑一样运行的算法,至少在隐喻的层面上。大脑中的神经元作为一个整体工作,一起学习它们观察到的输入的内部表示,这些研究人员认为他们的人工神经网络也可以做到这一点。30 多年后,他们的联合研究导致了计算机视觉、自然语言处理和机器人技术的革命性进步,形成了一系列令人印象深刻的新技术,其中许多我们在零售决策平台编辑中使用。
人工智能与工业
值得注意的是,这项工作是在考虑工业应用而不仅仅是学术应用的情况下完成的。Hinton 目前是谷歌的副总裁兼工程研究员,LeCun 是脸书的副总裁兼首席人工智能科学家。事实上,LeCun 的突破性工作训练 CNN 通过手写数字的图像来阅读银行支票——据估计,他的系统在 20 世纪 90 年代末和 21 世纪初阅读了美国所有支票的 10%以上。人工智能在工业上有着丰富的遗产,有着无数的实际应用。尽管很难忽视它更引人注目的用例——亚马逊的仓库机器人,或特斯拉的自动驾驶汽车——但可以说人工智能最有影响力的成功故事是在消费技术领域。人工智能为翻译引擎、推荐系统、图像分类和预测提供了动力——所有这些我们都在 EDITED 使用——更重要的是,支持它们的规模潜力。研究员吴恩达有一句格言,“如果一个典型的人可以用不到一秒钟的思考来完成一项脑力任务,我们很可能现在或在不久的将来用人工智能来自动化它”。这提供了一种有用的方法来识别领域中的 AI 应用。
人工智能驱动意味着数据驱动
更便宜的计算和大量数据的结合是人工智能进步不可或缺的一部分,它将导致公司现在引入人工智能的成功。到 2020 年——基于云的平台提供商 Domo 的年度信息图——估计地球上每个人每秒将产生 1.7 MB 的数据。利用数据对人工智能的成功至关重要,幸运的是它被大量创造出来。其中大部分是由大公司收获的,很难利用。因此,重要的是首先确定您需要的数据范围,无论这些数据是以客户为中心的还是与产品相关的,包括背后的道德考量。在 EDITED,我们既利用产品数据推动公司发展,也利用用户数据让我们深入了解客户。我们使用爬虫和人工智能来获取在线服装行业提供的商业数据,并将其转化为用户可以触摸到的东西。这创造了世界上最大的实时零售数据来源。然后,我们能够通过用户交互了解我们功能的成功之处,并根据数据对新功能做出决策。
扩展和升级
人工智能技术在大规模提供可操作的见解时最有用,但开发可持续和可扩展的基础设施可能具有挑战性。在 EDITED,我们努力成倍增加我们的抓取,并为每个产品增加更多的智能,同时保持其准确性。随着全球各地机构中机器学习和人工智能学位的兴起,越来越多的人才库已经出现。将此与广泛的在线和基于课程的资源相结合,以提升您当前劳动力的技能,实施量身定制的人工智能解决方案现在对许多组织来说是可以实现的。
对于更不喜欢人工智能的人来说,有几个机器学习平台需要很少的领域知识来执行。然而,最好的数据驱动型决策来自数据科学家和工程师团队,他们了解技术以及如何利用技术推动改进。更好的办法是与数据科学、产品管理和领导力共同努力,评估人工智能可以改善价值链的机会,以及实施的适当时间表。
勇敢点
为了让人工智能取得成功,实验文化需要成为标准,并始终强调提高劳动力的技能。当本吉奥、辛顿和勒村开始他们在人工智能方面的关键工作时,文化停滞不前,投资也很低。他们的研究花了几十年才见成果。重要的是,我们要意识到人工智能的潜力,以及反复投资和学习的必要性。在 EDITED,我们不断将新技术和能力引入我们的数据科学团队。我们鼓励其他人致力于新的人工智能应用并促进知识共享,同时通过管理用户和公司对如何利用人工智能的期望来避免投资减少。At EDITED 的基本价值观是“勇敢”,这是我们人工智能成功的关键。人工智能已经证明了它在工业中的价值,所以如果你还没有做出改变,你可能会发现你的竞争对手已经这样做了。
如何成为更有市场的数据科学家

这个标题对你来说可能有点奇怪。毕竟,如果你是 2019 年的数据科学家,你已经有市场。由于数据科学对当今的企业有着巨大的影响,对 DS 专家的需求也在增长。在我写这篇文章的时候,仅 LinkedIn 上就有 144,527 个数据科学职位。
但是,重要的是要把握行业脉搏,了解最快、最有效的数据科学解决方案。为了帮助你,我们痴迷于数据的简历编译器团队分析了一些空缺职位,并定义了 2019 年数据科学就业趋势。
2019 年最受欢迎的数据科学技能
下图显示了 2019 年雇主对数据科学工程师的技能要求:

为了进行这项分析,我们查看了 StackOverflow、AngelList 和类似网站的 300 个数据科学职位空缺。一些术语可能在一个职务列表中重复多次。
注意:记住,这项研究代表了雇主的偏好,而不是数据科学工程师本身。
关键要点和数据科学趋势
显然,数据科学更多的是关于基础知识,而不是框架和库,然而仍然有一些趋势和技术值得注意。
大数据
根据 2018 年大数据分析市场研究,企业对大数据的采用率从 2015 年的 17%飙升至 2018 年的 59%。因此,大数据工具也越来越受欢迎。如果不把 Apache Spark 和 Hadoop 考虑在内,(下一节我们会详细讲后者),最受欢迎的是 MapReduce (36),和 Redshift (29)。
Hadoop
尽管 Spark 和云存储很受欢迎,Hadoop的“时代”还没有结束。因此,一些雇主仍然希望应聘者熟悉 Apache Pig (30)、 HBase (32)以及类似的技术。HDFS(20 岁)仍然在空缺职位中被提及。
实时数据处理
随着各种传感器、移动设备和物联网 (18)的使用越来越多,公司正致力于从实时数据处理中获得更多见解。因此,像 Apache Flink 这样的流分析平台在一些雇主中很受欢迎。
特征工程和超参数调整
准备数据和选择模型参数是任何数据科学家工作的关键部分。数据挖掘这个术语在雇主中非常流行。一些雇主也非常重视超参数调优 (21)。但是,作为数据科学家,你需要先关注特征工程 。为模型选择最佳特征至关重要,因为它们决定了模型在创建的最初阶段能否成功。
数据可视化
处理数据并从中提取有价值的见解的能力至关重要。然而,数据可视化 (55)对于任何数据科学家来说都是一项同样重要的技能。重要的是,你可以用一种任何团队成员或客户都能理解的格式来表示你的工作成果。至于数据可视化工具,雇主更喜欢 Tableau (54)。
总体趋势
在空缺中,我们遇到了AWS(86)Docker(36)Kubernetes(24)这样的术语。因此,软件开发行业的一般趋势也适用于数据科学领域。
专家怎么说
该评级中的技术不相上下。然而,在数据科学中,有些东西和编码一样重要。它是从“数据输出”中收集见解的能力,如最终数据集和趋势、可视化以及用这些数据讲述故事。此外,它是以一种可以理解的方式展示发现的能力。了解你的听众——如果他们是博士,以适当的方式与他们交谈,但是如果他们是 C 语言的,他们不会关心编程——只关心结果和投资回报率。
快照数据有助于了解市场的当前状态,但并不代表趋势,因此很难仅根据快照来规划未来。我想说,R 的使用将继续稳步下降(MATLAB 也是如此),而 Python 在数据科学家中的受欢迎程度将继续上升。Hadoop 和大数据上榜是因为行业有一些惯性:Hadoop 会消失(再也没有人认真投资它)大数据不再是热门趋势。人们是否必须投入时间学习 Scala 还不清楚:Google 官方支持 Kotlin(也是一种 JVM 语言),学习起来更简单,而 Scala 的学习曲线很陡。我也对 TensorFlow 的未来持怀疑态度:学术界已经转向 PyTorch,与其他行业相比,学术界在数据科学领域的影响力最大。(这些观点是我的,可能不代表 Gartner 的观点。)
Gartner 机器学习总监,
百页机器学习著作的作者 。
LinkedIn
PyTorch 是用 GPU 对 CUDA 张量进行数学运算的强化学习的驱动力。它也是一个更强大的框架,可以同时在多个 GPU 上并行化代码,而不像 TensorFlow 需要将每个操作打包到一个设备上。PyTorch 还构建了对递归神经网络有效的动态图。基于 ano 的 TensorFlow 生成静态图表,与基于 Torch 的 PyTorch 相比,学习起来更复杂。张量流反映了更大的开发人员和研究人员社区。PyTorch 在构建 TensorBoard 等机器学习仪表盘可视化工具时,将表现出更大的势头。PyTorch 用 matplotlib 和 seaborn 在调试和数据可视化库方面更 Pythonic 化。Python 的大多数调试工具也可以用来调试 PyTorch。TensorFlow 自带调试工具 tfdbg。
Ganapathi puli paka 博士,
埃森哲首席数据科学家,
50 大技术领袖奖获得者。
LinkedIn|Twitter**
我认为数据科学的“工作”不同于数据科学的“职业”工作列表提供了对市场现在需要的特定技能的洞察,但对于职业来说,我见过的最重要的技能之一是学习能力。数据科学是一个快速发展的领域,如果你想取得长期的成功,你需要能够轻松地掌握新的技术、工具和领域知识。通过挑战自己来做到这一点,避免过于舒适。
【隆·里斯伯格】 数据药剂 前 NASA 创始人/策展人。 推特 | 领英
数据科学是一个快速发展的复杂行业,一般知识和特定技术的经验同样重要。希望这篇文章能帮助你获得宝贵的见解,了解你需要哪些技能才能在 2019 年保持市场竞争力。祝你好运!
本文由 CV 编译器 团队为您带来——一款面向数据科学家、机器学习工程师和其他 IT 专业人士的在线简历增强工具。
如何在 Kaggle 上开始比赛

你刚刚完成了你的第一门机器学习课程,但你不知道从哪里开始应用你的新知识。你可以从玩 Iris 数据集或梳理泰坦尼克号记录开始(这可能是你应该做的第一件事)。但是有什么比直接跳进来和网上的陌生人竞争金钱更有趣的呢?
如果你正在阅读这篇文章,你可能已经知道 Kaggle 是一个数据科学竞赛平台,爱好者使用结构化(表格格式的数字和/或分类数据)和非结构化数据(例如,文本/图像/音频)在一系列机器学习主题中进行竞赛,目的是获得奖金和令人垂涎的 Kaggle 金牌。虽然你可能会发现与他人竞争的想法令人生畏,但重要的是要记住,目标永远是尽可能多地学习,而不是专注于结果。通过这种心态,你会发现竞争变得有趣,有益,甚至上瘾。
选择比赛的第一步
找一个你感兴趣的比赛。
这是开始新比赛时要考虑的最重要的事情。你想给自己大约两个月的时间来梳理一个问题,并真正熟悉数据的来龙去脉。这是相当多的时间。选择一个你不感兴趣的比赛会让你变得不感兴趣,放弃几周的时间。在时间线的早期加入还会让您有更多的时间来获取背景知识,并在您与社区的其他成员一起处理问题的各个阶段时提高您的学习质量。
专注学习
如果你发现自己对一场比赛感到沮丧,认为它太难了,那就专注于尽可能多的学习,然后继续前进。通过这种方式,你可以通过接触这些材料学到更多。当你不再担心自己在排行榜上的位置时,你甚至会发现自己取得了突破!
努力理解最高得分内核的每一行
问问自己,是否有一些明显的方法可以改进他们的工作。例如,有没有一个你可以创造的新颖的功能可以提高他们模型的分数?你能稍微调整一下他们用来提高性能的学习速度吗?追求唾手可得的果实,不要试图多此一举。这种心态将大大加快你的学习,同时确保你不会发现自己变得沮丧。
查看规则中是否有奇怪的规定
这一个没有其他的重要,但仍然值得一提。最近的一次竞赛中有一条规则规定如下:
[您的提交内容]不包含机密信息或商业秘密,并且不是注册专利或未决专利申请的主题
一名用户在论坛上表示,这项规定将使退学成为非法,因为这是谷歌的专利技术!
内核和讨论
在比赛过程中应该定期检查内核和讨论标签
首先查看一些 EDA(探索性数据分析?,探索性数据分析的?探索性数据分析?)和衡量你对领域和主题的兴趣程度。当你浏览其他人的作品时,在数据的合适模型类型、特征工程等方面,想想你想到的任何新颖的想法。
讨论标签中的“欢迎”帖子提供了很好的背景阅读
获得竞争领域的领域知识不会有什么坏处。这有助于深入了解模型的执行情况,并极大地有助于特征工程。我通常会在比赛开始时花一两周时间尽可能多地阅读,以了解问题空间。为了有助于这一点,大多数竞赛组织者在论坛上创建一个 onboarding 帖子,链接到该领域的重要论文/文章。他们还可能提供关于如何处理较大数据集的技巧和对数据的基本见解。当您获得关于手头问题的更多信息时,这些线索总是值得检查和回顾的。
探索性数据分析
你应该关注什么?
您对数据集的初始分析将根据您正在检查的数据类型而有所不同。但是,这些概念在不同领域中通常是相似的,下面的信息可以根据您的具体领域进行调整。为了简化事情,让我们假设我们正在看结构化数据。在任何初始 EDA 中,都有一些基本问题要问:
- 目标是如何分布的?
- 特征之间有什么显著的相关性吗?
- 数据中是否有缺失值?
- 训练和测试数据有多相似?
目标是如何分配的?
在任何数据集中,首先要注意的是类的分布。你会想要很快发现是否有阶级不平衡,因为这会对你的模型产生重大影响。特别是如果一个班级在培训中淹没了其他班级的信息。有许多技术可以处理类别不平衡(例如, SMOTE , ADASYN ,手动移除样本,模型参数来处理不平衡的数据集),但首先我们想知道类别是否在数据中不均衡地表示。检查这一点的快速方法是通过绘图库 seaborn ,基于流行的 matplotlib 。
**import** seaborn **as** snssns.countplot(df['target'])

Multi-class target imbalance
正如我们所看到的,90 级在我们的数据中占了很大比例。前述 SMOTE 技术和其他技术可以创建更平衡的训练数据集。反过来,这可以导致一个模型,更好地推广到看不见的数据,这种不平衡可能不存在。
特征之间有没有显著的相关性?
计算特征之间的皮尔逊相关系数可以提供对特征的一些宝贵见解。知道特性是否相关可以允许创造性的特性工程或删除不必要的列。例如,在下面显示的热图中,EXT_SOURCE_1是由外部来源提供的贷款申请人的信用评级。DAYS_BIRTH,申请人的年龄天数(负整数),与EXT_SOURCE_1负相关。这可能意味着EXT_SOURCE_1的计算涉及申请人的年龄。一般来说,我们希望避免包含可以从另一个特征线性导出的特征(这被称为线性相关性),因为它为模型提供了冗余信息。
**import** seaborn **as** sns
**import** matplotlib.pyplot **as** plt**def** correlation_map(df, columns, figsize=(15,10)):
correlation = (df.loc[:, columns]).corr()
fig, ax = plt.subplots(figsize = figsize)
sns.heatmap(correlation, annot = **True**, ax = ax)

Correlation heatmap showing positive and negative values for Pearson correlation coefficient between numerical features
数据中是否有缺失值?
您总是希望确保拥有一个完整的训练数据集,并且丢失的值尽可能少。例如,如果您的模型发现某个要素非常重要,但事实证明该要素中有大量的行缺少值,则可以通过输入缺少的值来大大提高模型的性能。这可以通过基于不包含NaN的相似行来推断特性的值来完成。另一种策略(称为回填)是用下一个非空值填充缺失值。其余要素的平均值、中值或众数有时也用于估算缺失值。[pandas.DataFrame.fillna()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html)方法提供了一些不同的选项来处理这个场景,并且这个 Kaggle 内核是一个非常有用的资源。
但是,缺少值并不总是意味着没有记录数据。有时,为某个特性包含一个NaN值是有意义的,这个值不适用于单独的行。例如,假设一个贷款申请数据集有一个二进制目标(申请人是否被批准),其中包括一个关于个人是否拥有汽车的特性。如果一个给定的人没有汽车,那么汽车注册日期的另一个特征将包含一个NaN值,因为在这里没有信息可以填写。
训练和测试数据有多相似?
熊猫 DataFrame对象包含一个[pandas.Dataframe.describe()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.describe.html)方法,该方法提供数据集中每个特征的统计数据,如最大值、平均值、标准差、第 50 百分位值等。该方法返回另一个DataFrame,因此您可以根据需要添加更多信息。例如,您可以使用以下函数让另一行检查该列中缺失值的数量:
**def** describe_df(df):
stats_df = df.describe()
stats_df.append(pd.Series(df.isna().any(), name='nans'))
**return** stats_df
这是一个非常有用的方法,允许您快速检查训练和测试中的特征之间的相似性。但是,如果你有一个单一的数字值,给你一个很好的想法,只是如何密切训练和测试一目了然?这就是对抗性验证进入的地方。我知道这听起来有点吓人,但一旦你理解了这一技巧,你会发现它非常简单。对抗性验证包括以下步骤:
- 将训练数据集和测试数据集连接成一个大数据集
- 将所有列车行的目标特征设置为值 0
- 在所有测试行中为目标特性填充值 1(您可能会看到这是怎么回事)
- 从数据中创建分层折叠(我喜欢使用 sklearn 实现)
- 将类似 LightGBM 的模型安装到培训文件夹中,并在验证文件夹中进行验证
- 对整个数据集进行验证预测,并计算接收器操作特征曲线(ROC AUC) 下的面积。我使用这个实现来计算面积。
- ROC 曲线下 0.5 的面积意味着模型无法区分训练行和测试行,因此这两个数据集是相似的。如果面积更大,模型可以看到训练和测试之间的一些差异,因此值得您深入挖掘数据,以确保您的模型可以很好地预测测试。
我发现以下两个内核有助于掌握这项技术:
- https://www.kaggle.com/tunguz/adversarial-santander
- https://www . ka ggle . com/pnussbaum/adversarial-CNN-of-PTP-for-vs b-power-v 12
为什么从基于树的模型开始?
在你第一次开始的时候,找出正确的模型是很重要的,而且可能会很混乱。让我们再次假设您正在处理结构化数据,并且您希望在陷入建模之前对数据有所了解。我发现 LightGBM 或 XGBoost 型号非常适合在你刚参加新的比赛时就把数据扔给你。这两个都是基于树的提升模型,具有很强的可解释性并且易于理解。两者都提供了绘制分割图的功能,因此创建max depth = 3左右的树并从一开始就查看模型分割的具体特征是很有用的。
lightgbm.Booster.feature_importance()方法根据模型对特定特征的分割次数(importance_type="split")或对特定特征的每次分割所获得的信息量(importance_type="gain")来显示模型最重要的特征。查看要素的重要性在匿名化的数据集中特别有用,您可以获取前 5 个左右的要素,并推断出这些要素可能是什么,知道它们对模型有多重要。这可以极大地帮助特征工程。
您还会发现 LightGBM 特别快(请原谅双关语),即使不使用 GPU 也能进行训练。最后,这两种模型都有很好的文档,所以初学者应该不难掌握。
估价
如果不使用可靠的评估方法,您可能在竞争中拥有性能最佳的型号,但却不知道这一点。在参赛之前,了解比赛的官方评估标准是至关重要的。一旦您对如何评估您的提交有了坚实的理解,您应该确保在培训和验证中使用官方评估指标(或者如果不容易获得合适的实现,则使用您自己的版本)。将这一点与可靠的验证集相结合,将避免您在提交时焦头烂额,并允许您快速、经常地进行试验。
除此之外,您希望以这样一种方式设置您的模型评估,以使您最终得到一个单一的数字。查看训练损失与验证损失或一系列指标,包括精确度、召回率、F1 分数、AUROC 等。有时在生产中很有用,但在竞争中,您希望能够快速浏览一个数字,然后说“这个型号比我以前的型号好”。同样,这个数字应该是官方指标。如果不是,你应该有一个很好的理由。
如果你遵循上面的建议,你将会达到这样一个点,在那里你会经常实验,以至于你需要一个可靠的方法来跟踪你的结果。我喜欢使用在 Docker 容器中运行的 MongoDB 实例,每次运行我的评估脚本后,我都会将我的模型参数和验证分数发送到该容器中。我为每个模型保留了一个单独的表(或者 MongoDB 喜欢称之为集合)。当我运行完一些实验后,我将记录作为一个 MongoDB .archive文件和一个.csv文件转储到我机器上的一个本地目录中,以便快速通读。代码可以在这里找到。应该注意的是,关于如何处理记录结果有不同的思想流派,这是我的首选方法,但我很想听听其他数据科学家如何处理它!
Chirag Chadha 是爱尔兰都柏林 UnitedHealth Group/Optum 的数据科学家。你可以通过他的电子邮件(chadhac@tcd.ie),通过他的LinkedIn,或者在ka ggle和GitHub上关注他。
如何从 Databricks-Spark-Hive 中获取数据

Fingers Trying to break out of jail, Pixabay.
简单的方法。
这篇文章是为那些使用 Databricks (DB)笔记本并希望通过使用 Pyspark 将基于 Hive 的数据集导出到外部机器的科学家而写的,以便使用 Pandas 获得更高效的工作流。
有很多方法可以做到以下几点,但这个方法对我很有效。
首先,在 DB 笔记本中创建一个 SQL 查询,并等待结果。以下查询是从 table_x 中选择所有列并将结果分配给 spark 数据框的简单示例。
df = spark . SQL(" " SELECT * FROM table _ x " " " ")
Spark 不会参与,直到您要求它物化数据,因此,您必须执行以下命令。
df.show()
此时,您应该会看到一个非常难看的打印输出,其中包含一些数据。
在打印输出之后,您需要安装 DB 客户机,对其进行配置,并在 DB 文件存储上创建一个目录。
pip3 安装数据块-cli
设置和配置 DB 客户端,我假设您可以遵循文档或者熟悉设置过程。点击此处获取文件。
dbfs mkdirs dbfs:/file store/my/path/is/here
按照这些步骤,在 DB 笔记本中执行 write-to-JSON 命令,数据帧将保存在预定义路径的多个 JSON 文件中。请注意,路径应该根据您的配置进行更改。
df . write . JSON(
f " dbfs:/FileStore/my/path/is/here ",
mode="overwrite ",
compression="gzip"
)
执行这些命令后,我们将在我们的机器上创建一个新目录,转到该目录,检查文件是否在我们的云目录中等待,最后使用 DB 客户端复制文件。
mkdir/data/our data
CD/data/our data
dbfs ls dbfs:/file store/my/path/is/here
dbfs CP-r dbfs:/file store/my/path/is/here。
按照这些步骤,您可以将 location 指向您机器的数据目录并处理文件,将所有下载的 JSON.GZ 文件连接到一个 Pandas 数据框中。
进口熊猫作为 pd
location = '/data/ourData '
从 pathlib 导入路径
files = list(路径(位置)。glob(" * . JSON . gz ")
l =[]
for f in files:
l . append(PD . read _ JSON(f,lines = True))
df = PD . concat(l)
现在,您可以使用 Pandas,处理数据的速度比使用 DB 笔记本更快。唯一的条件是,你实际上可以把所有的数据都放进你的机器的内存里。
我要感谢巴拉克·亚伊尔·赖夫的宝贵帮助,感谢阿黛尔·古尔审阅本文。
Ori Cohen 博士拥有计算机科学博士学位,主要研究机器学习。他是 TLV 新遗迹公司的首席数据科学家,从事 AIOps 领域的机器和深度学习研究。
如何在机器学习和软件工程之间架起桥梁

Photo by Tyler Lastovich on Unsplash
将数据科学转化为软件的实用工作流程
数据科学/机器学习社区越来越沮丧地看到又一个 PoC(概念验证)创造了有希望的结果,但从未变成有影响力的东西。主要原因:开发和部署之间的差距很大。
越来越多的工具和框架——开源的和商业的——有望弥合这一鸿沟。然而,将他们引入组织是一项耗时且昂贵的工作。
为这样的解决方案而战是光荣的,也是必要的。尽管如此,在此期间我们还可以做些别的事情来缩小差距:使我们的工作流程与软件开发原则保持一致。要学的第一件事:单元测试。
不幸的是,大多数介绍和文档都以抽象的方式处理这个主题。相比之下,这篇博客通过一个具体的例子向你展示了一个实用的工作流程。我们开始吧!
方案
我们在一家迅速扩大客户群的初创公司工作。虽然这对公司来说是个好消息,但有些流程需要适应新的形势。其中之一是电子邮件营销。
当我们公司开始发送营销邮件时,客户群很小,而且很专注。因此,所有注册客户都收到了所有的电子邮件,这很好。这不再是真的了。虽然仍有一些忠实的客户不想错过促销和产品更新,但许多新客户却不那么兴奋了。更糟糕的是,越来越多的潜在客户选择退出营销通讯,因为不相关或太多的电子邮件。
经过一番讨论后,我们初创企业的创始人决定加强营销流程。他们设想了一种系统,可以将电子邮件发送给关心他们的客户,让其他人免受收件箱的额外压力。
我们的工作是构建该系统的机器学习部分。
要求
让我们总结一下我们拥有的和我们需要的:
- 我们有一些顾客的信息。
- 我们有一些关于计划营销电子邮件的信息。
- 我们需要每个客户与给定营销电子邮件互动的可能性(不包括选择退出简讯的互动)。
对于数据科学家和机器学习工程师来说,跳入收集数据和建立复杂模型是非常非常诱人的。然而,这不是我们现在需要的。请记住,我们的目标是构建一个完整的系统,而不是一个独立的模型。那么,我们如何使我们的工作符合这些要求呢?
工作流程
我们决定采用四步工作流程:
- 选择下一个要开发的组件。
- 编写捕捉我们想要实现的目标的单元测试。
- 编写通过单元测试的代码。
- 重复一遍。
我们开始吧!
步骤 1:选择下一个要开发的组件
现在,什么都没有。然而,我们知道其他团队开始在整个系统上工作,我们想要支持他们。因此,我们的第一个任务是为整个流程创建一个接口,它接受两个输入并返回期望的输出。我们把这个主类叫做 CampaignPredictor 。它采用一个 pandas 数据框作为客户数据,一个字典作为计划活动的信息,并有一个方法返回所有客户与电子邮件交互的概率。它看起来像这样:
注意,我已经包含了类型提示、一个(初步的)docstring 和一个 NotImplementedError。在这一点上继续编码是非常有诱惑力的。然而,如果我们首先陈述我们对这段代码的期望,我们就帮了自己一个大忙。向我们以及将我们的代码集成到整个过程中的团队表达这些期望的最佳方式是:单元测试。
步骤 2:编写捕捉我们目标的单元测试
编写好的单元测试本身就是一门艺术。尽管如此,我们还是想在代码的两个维度上使用它们。第一个尺寸是有效的,而不是无效的输入。在有效输入的情况下,我们关注正确的输出。在无效输入的情况下,我们关注错误处理和快速失败。前者帮助用户了解哪里出错了,而后者确保用户在出错时不必等待。
第二个维度是结构与功能质量。结构单元测试包括输入和输出的正确类型和形状。功能单元测试覆盖了代码的功能。也就是说,它是否提供了它承诺要解决的问题。下面是这些单元测试的样子:
对于无效的输入,主要有两种错误。 TypeErrors 捕获我们期望一种类型的输入并得到另一种类型的输入的所有情况。例如,我们期望一个熊猫数据帧,但是得到一个 numpy 矩阵。 ValueErrors 捕获类型正确的情况,但是我们不能处理值本身。例如,我们期望一个字典有一个“campaign_type”键,该键的值是一个字符串,但是要么这个键丢失了,要么这个值不是一个字符串。这两种情况都会导致以后的问题,所以我们希望尽早发现并提供有意义的错误消息。
对于有效的输入,不应有任何错误。首先,我们期望输出具有正确的类型和形状。在我们的例子中,这是一个长度与输入中的客户数量相同的列表。第二,我们期望这个列表中的所有值都是有效概率,也就是说,它们的范围从 0 到 1。
如您所见,我们讨论了有效和无效输入的结构和功能方面。因为所有这些测试现在都失败了,所以一切都按预期运行。也就是说,根本不是。让我们解决这个问题。
步骤 3:构建通过测试所必需的东西(第一次尝试)
虽然测试没有明确的顺序,但是我们从无效输入的测试开始。这有助于我们在做一些事情之前澄清我们实际期望得到什么。
因为我们的主要目标是在有无效输入时快速失败,所以我们将编写验证代码作为类初始化的一部分。在我们的例子中,我们需要确保得到一个包含预期键值对的字典和一个至少有一行的数据框,即至少有一个客户可供选择。
这段代码通过了无效输入的测试。在进行这项工作时,您可能会获得关于应该测试什么的其他想法。总的来说,这是一件好事,因为这表明你开始更详细地考虑你的方法。然而,不要太具体,因为事情可能会改变。
看第二个测试是非常诱人的——最后!—从建模开始。然而,这不是我们现在的目标。我们的目标是整个过程。同时,有许多不同的方法来预测客户与电子邮件交互的概率。
解决办法?我们在兔子洞里更深入一步。单元测试的美妙之处在于,一个失败的测试会提醒我们还有一些东西需要修复。首先,让我们实现一个简单的方法来为活动选择客户:简单随机化。
延时拍摄中的步骤 1-3
第一步:我们现在正在为选择客户的更复杂的方法构建蓝图。对于简单的集成测试来说,这个占位符应该是快速的——并且不是完全愚蠢的。姑且称之为 RandomSelector 类。它需要一些客户来选择,以及他们中应该收到电子邮件的百分比。然后,它应用一种方法来随机选择一组客户,并将结果作为列表返回。
第二步:我们为有效和无效的输入编写单元测试。关于输入,我们希望确保客户的数量多于一个,并且要选择的百分比在 0 和 1 之间。如果输入与此不符,我们希望看到正确的错误类型。关于输出,我们希望得到一个长度正确的列表,并且至少有一个选定的客户。
正如您在第 42–51 行看到的,我还包括了一个我在编写测试时想到的边缘案例。同样,单元测试有助于澄清你实际期望得到什么,这使得之后的编码更加集中。
第 3 部分:我们更新了类的初始化,以检查输入和产生正确输出的方法。一旦我们通过了测试,我们就完成了这个任务。
现在我们可以使用这个新类来处理我们开始时的事情:CampaignPredictor。
步骤 3:构建通过测试所必需的东西(第二次尝试)
如果我们正确地从 CampaignPredictor 为**random selection类翻译我们的需求,我们几乎不需要额外的代码来通过有效输入的测试:
所有测试都通过了,我们可以庆祝我们的第一次迭代。在我们开始第二个之前,这是更新 docstring 并将代码提交给我们的版本控制系统的好时机。
重复
我们的下一步取决于业务优先级。在这种情况下,随机化将是不可接受的,因此我们需要集成一段能够加载训练模型并将其应用于所提供的数据集的代码。我把这个练习留给思考什么是有效的和无效的输入,以及这样一个模块需要传递给你什么。
外卖
这个工作流和场景被简化了。然而,每个案例都有其自身的复杂之处,这一微不足道的观察不能成为使一切复杂化的理由。相反,在构建下一个组件时,只有四个问题:
- 我期望的输入是什么?
- 如何处理无效或不完整的输入?
- 从结构的角度来看,我希望输出是什么样的?
- 从功能角度来看,我希望我的输出达到什么目的?
诚然,回答这些问题会让人觉得很烦。我认为主要有两个原因:
- 这些问题出奇的难。很好。你意识到你不确定你想要实现什么。现在比 1000 行额外的代码要好。
- 感觉又慢又啰嗦,尤其是截止日期临近的时候。如果你不在乎你要去哪里,感觉很快会更容易。然而,在压力下,方向感不清晰是最糟糕的。
关于测试本身的更多例子和更多细节,请参阅我的上一篇博文和其中包含的参考资料:
数据科学家和机器学习工程师应该向软件开发人员学习的另一件事
towardsdatascience.com](/tdd-datascience-689c98492fcc)*
如果这篇文章对你有所帮助或者你想补充什么,请在评论中或者在 Twitter 上告诉我。我也很乐意在 LinkedIn 上联系。感谢阅读!
如何将您的数据科学项目投入生产
将 Azure 数据块与 Spark、Azure ML 和 Azure DevOps 一起使用
1.介绍
许多公司努力将他们的数据科学项目投入生产。一个常见的问题是,模型越接近生产,就越难回答以下问题:
- 为什么模型会预测到这一点?
拥有数据科学项目的构建/发布管道有助于回答这个问题。它使您能够追溯:
- 模型 M 由人 P 用算法 A 在数据集 D 上训练
- 型号 M 在 R 版中于时间 T 投入生产
这种审计跟踪对于生产中运行的每个模型都是必不可少的,并且在许多行业中都是必需的,例如金融业。
博客/git 回购最后更新:2021 年 7 月 21 日。感谢Pardeep Singla修复了 Azure ML 中一些突破性的改动。
我了解到这个博客/回购经常用在演示、教程等中。如果你也这样做,请不要犹豫联系我,我很想知道。
2.目标
在本教程中,机器学习项目的构建/发布管道创建如下:
- 创建一个 HTTP 端点,使用年龄、每周工作时间、教育程度等特征来预测一个人的年收入是高于还是低于 50k。
- Azure Databricks 与 Spark、Azure ML 和 Azure DevOps 一起用于创建模型和端点。Azure Kubernetes 服务(AKS)同时用作测试和生产环境。
该项目可以在以下高级概述中进行描述:

2. High level overview
在本博客的剩余部分,将执行以下步骤:
- 3.先决条件
- 4.在 Azure Databricks 中创建机器学习模型
- 5.Azure 机器学习服务中的管理模型
- 6,7.在 Azure DevOps 中构建和发布模型
- 8.结论
博客的后续可以在这里找到,其中安全性被嵌入到构建/发布管道中。此外,审计跟踪的细节将在的博客中讨论。最后,如果你对如何在 Azure Data Factory 中使用 Azure Databricks 感兴趣,请参考这个博客。
3.先决条件
本教程需要以下资源:
4。在 Azure Databricks 中创建机器学习模型
Azure Databricks 是一个基于 Apache Spark 的分析平台,针对 Azure 进行了优化。它可以用于许多分析工作负载,其中包括机器学习和深度学习。在此步骤中,将完成以下工作:
- 4a。创建新集群
- 4b。导入笔记本
- 4c。运行笔记本
4a。创建新的集群
启动 Azure Databricks 工作区并转到群集。使用以下设置创建新集群(2020 年 9 月编辑:在 devOps pipeline 中,Databricks Runtime 6.6。被使用,建议在数据块中也使用这个运行时版本进行交互式分析):

4a1. Create cluster
4b。导入笔记本
转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:
[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/1_IncomeNotebookExploration.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/1_IncomeNotebookExploration.py)
另请参见下图:

4b1. Import notebook
4c。运行笔记本
选择您在 4b 中导入的笔记本,并将该笔记本连接到您在 4a 中创建的集群。确保集群正在运行,否则启动它。阅读笔记本中的步骤,其中研究了数据,并尝试了几种设置和算法,以创建一个预测一个人收入阶层的模型。使用快捷键 SHIFT+ENTER 逐个单元格地浏览笔记本。

4c1. Steps in notebook
5.Azure 机器学习服务中的管理模型
Azure 机器学习服务(Azure ML)是一种云服务,您可以使用它来训练、部署、自动化和管理机器学习模型。在这个上下文中,上一步中创建的模型将被添加到您的 Azuere ML 实例中。将执行以下步骤
- 5a。将库添加到数据块群集中
- 5b。使用 Azure ML 将笔记本导入到 Azure Databricks
- 5c。在 Azure ML 中查看结果
5a。将库添加到数据块群集中
右键单击您的工作区并选择“创建库”

5a1. Create library
选择 PyPi,然后填写:azureml-sdk[databricks]

5a2. Add PyPi library with azureml-sdk[databricks]
最后,将库连接到群集。

5a3. Attach library to cluster
5b。使用 Azure ML 将笔记本导入到 Azure Databricks
在本教程的上一部分,我们在 Azure Databricks 中创建了一个模型。在这一部分中,您将把创建的模型添加到 Azure 机器学习服务中。
再次转到您的 Databricks 服务,右键单击,选择导入,并使用以下 URL 导入笔记本:
[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2_IncomeNotebookAMLS.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2_IncomeNotebookAMLS.py)
同样,确保它已连接到群集,并且群集正在运行

5b1. Import Azure ML notebook
随后,为 workspace、subscription_id 和 resource_grp 填入正确的值。所有值都可以在 Azure 门户的 Azure 机器学习服务工作区的 overview 选项卡中找到。

5b2. Add variables notebook
现在,使用快捷键 SHIFT+ENTER 逐个单元格地运行笔记本单元格。
在 cell 6 中,您需要向笔记本中的 Azure 机器学习服务进行身份验证。按照笔记本中的说明打开 URL,并输入生成的代码进行身份验证。
5c。在 Azure ML 中查看结果
在步骤 5b 中,运行一个笔记本,其中的结果被写入 Azure 机器学习服务。在这方面,完成了以下工作:
- 在 you Azure ML 中创建了一个新的实验
- 在这个实验中,具有 6 个子运行的根运行可以找到不同的尝试。
- 子运行包含模型的描述(例如正则化为 0 的逻辑回归)和尝试的最重要记录(例如准确性、假阳性的数量)
- 模型人工制品(。mml)也是子运行的一部分。最佳子运行的工件可以投入生产。
转到您的 Azure ML 实例。选择笔记本中使用的实验名称(例如,experiment_model_int)。

5c1. Find experiment in Azure Machine Learning Service
现在单击实验,单击您想要查看指标的运行和子运行。

5c2. Find metrics of a childrun in Azure Machine Learning Service
你去输出的时候会发现模型神器,也可以下载。在本教程的下一部分中,最佳运行的模型工件将被用作使用 Azure DevOps 部署的容器的基础。

5c3. Model artifact
6.创建和准备 Azure DevOps 项目
Azure DevOps 是一个工具,可以持续地构建、测试和部署你的代码到任何平台和云。在第 6 章中,将创建并准备一个 Azure DevOps。该项目将采用以下步骤进行准备:
- 6a。在数据块中创建个人访问令牌
- 6b。创建 AKS 集群
- 6c。创建 Azure DevOps 项目和服务连接
- 6d。向代码中添加变量
在第 7 章中,实际的构建-发布管道将被创建并运行以创建模型的一个端点。
6a。在数据块中创建个人访问令牌
要在 Azure DevOps(使用 REST APIs)触发的 Azure Databricks 中运行笔记本,需要 Databrics 访问令牌(PAT)进行身份验证。
进入 Azure Databricks,点击右上角的人物图标。选择用户设置,然后生成新令牌。

6a1. Generate Databricks Access Token
请确保现在复制令牌。你再也看不到它了。稍后从 Azure DevOps 构建管道访问数据块需要令牌
6b。创建 AKS 集群
在这一步中,在 Azure Kubernetes Services (AKS)中创建了一个测试和生产环境。通常,这是两个独立的 AKS 环境,但是,为了简化和节约成本,只创建了一个环境。首先,转到您的 Azure ML 服务工作区并选择 Compute。取计算机名 blog-devai-aks 并选择 Kubernetes 服务作为计算机类型,也见下文。

6b1. Add AKS compute to Azure ML Service
创建 AKS 集群大约需要 10 分钟。继续下一步。
6c。创建带有服务连接的 Azure DevOps 项目
按照这个教程,在 Azure DevOps 中创建新项目。创建新项目后,单击存储库文件夹并选择导入以下存储库:
[https://github.com/rebremer/devopsai_databricks.git](https://github.com/rebremer/devopsai_databricks.git)
另请参见下图:

6c1. Add repository to your Azure DevOps project
从 Azure DevOps 访问资源组中的资源需要服务连接。转到项目设置、服务连接,然后选择 Azure 资源管理器。

6c2. Go to Service Connection
选择服务主体身份验证,并将范围限制在部署了机器学习工作区服务的资源组中。确保将连接命名为如下所示:devopsaisec _ service _ connection。

6c3. Create Azure Resource Manager service connection
6d。向代码中添加变量
在您在上一步中创建的 Repos 中,应更改以下文件:
- \ project \ config code _ build _ release . yml
对于工作空间、subscription_id 和 resource,使用与步骤 5b 中的机器学习服务工作空间的值相同的变量。此外,填写您在步骤 6a 中生成的 Databricks 个人访问令牌。
variables:
# change 5 variables below with your own settings, make sure that
# : with a space is kept and not replaced with =
workspace: '<<Name of your workspace>>'
subscription_id: '<<Subscription id>>'
resource_grp: '<<Name of your resource group with aml service>>'
domain: 'westeurope.azuredatabricks.net' # change loc.when needed
dbr_pat_token_raw: '<<your Databricks Personal Access Token>>'
在 Azure DevOps 中,可以通过在 Repos 中查找文件,点击“编辑”,更改变量,然后“提交”文件来更改文件。您还可以克隆项目并从那里开始工作。请注意,在生产环境中,绝不能将键添加到代码中。相反,Azure DevOps 管道中的秘密变量将被使用,并在后续的教程中处理。
在本章中,创建并准备了一个 Azure DevOps 项目。现在模型已经准备好在 Azure DevOps 项目中构建和发布了。
7.在 Azure DevOps 中构建和发布模型
在这一部分中,使用以下步骤在 Azure DevOps 中构建和发布模型:
- 7a。创建构建-发布管道
- 7b。运行构建-发布管道
- 7c。使用邮递员消费 HTTP 端点
7a。创建构建-发布管道
在这一步中,您将创建一个构建-发布管道。转到您在 6c 中创建的 Azure DevOps 项目,然后单击 Pipelines。将显示一个向导,您可以在其中选择 Azure Repos Git,另请参见下文。

7a1. Create Pipeline
随后,选择附加到这个项目的 Git repo,然后选择“现有的 Azure Pipelines YAML 文件”。然后浏览目录\ project \ config code _ build _ release _ ACI _ only . yml 或\ project \ config code _ build _ release . yml(如果在步骤 6b 中创建了 AKS 集群,另请参见下文)。

7a2. Select build-release YAML file
最后,检查您的管道并保存您的管道,另见下文。

7a3. Save pipeline
在本章中,配置了管道。在此管道中,将执行以下步骤:
构建:
- 选择 Python 3.6 并安装依赖项
- 将笔记本上传到数据块
- 通过运行 notebook 使用 Azure Databricks 创建模型。向 Azure 机器学习服务添加模型
- 创建构建工件作为发布 deployTest 和 deployProd 的输入
发布部署测试:
- 检索在构建步骤中创建的模型
- 将模型作为 docker 映像部署到作为测试端点的 AKS
- 测试 AKS 中的“测试端点”
释放部署杆:
- 检索在构建步骤中创建的模型
- 将模型作为 docker 映像部署到作为 prd 端点的 AKS
- 在 AKS 中测试“生产端点”
在下一部分中,将运行管道。
7b。运行构建-发布管道
在这一步中,构建-发布管道将在 Azure DevOps 中运行。转到上一步中部署的管道,选择管道,然后选择队列,另请参见下文。

7b1. Run build-release pipeline
当管道启动时,会在构建步骤中使用 Azure Databricks 和 Azure ML 创建一个包含 ML 模型的 docker 映像。随后,docker 映像在 ACI 和 AKS 中部署/发布。下面可以看到一次成功的运行。

7b2. Successful run of build-release pipeline
请注意,如果您决定不在 AKS 中部署 docker 映像,前面的步骤仍将执行,AKS 步骤将失败。要获得详细的日志记录,您可以单击各个步骤。
7c。使用邮递员消费 HTTP 端点
当你进入 Azure ML 工作区时,你可以找到你在 7b 中部署的模型的端点。这些端点现在将被邮递员用来创建预测。可以在项目中的项目/services/50_testEndpoint.py 中找到一个示例负载。在本例中,预测了三个人的收入等级。
- 对第一个人的预测是收入高于 50k,
- 对于另外两个人,预测值低于 50k。

7c2. Use HTTP endpoint to create predictions
8.结论
在本教程中,创建了一个机器学习项目的端到端管道。在此:
- Azure Databricks with Spark 用于探索数据和创建机器学习模型。
- Azure 机器学习服务用于跟踪模型及其度量。
- Azure Devops 用于构建最佳模型的映像,并将其作为端点发布。
通过这种方式,您可以协调和监控从构思到模型投入生产的整个过程。这使您能够回答问题:为什么模型会预测到这一点?
可以在下面找到架构概述。在这个后续教程中,管道的安全性得到了加强。

8. High level overview
如何构建聊天机器人——自然语言处理中的一课
一个 5 步的自然语言处理过程可以帮助你设计简单的聊天机器人
顾名思义,聊天机器人是一种和你聊天的机器。不过,诀窍是让它尽可能像人类。从“美国运通客户支持”到谷歌 Pixel 的电话筛选软件,聊天机器人的种类繁多。

Photo by Blake Wisz on Unsplash
它实际上是如何工作的?
聊天机器人的早期版本使用了一种叫做模式匹配的机器学习技术。与目前使用的高级 NLP 技术相比,这要简单得多。
什么是模式匹配?
要理解这一点,想象一下你会问一个卖书的人什么,比如——“_ _ 本书的价格是多少?"或"你有哪些 __ 作者的书?“这些斜体问题中的每一个都是一种模式的示例,当类似的问题在未来出现时,可以进行匹配。
模式匹配需要大量预先生成的模式。基于这些预先生成的模式,聊天机器人可以很容易地选择最匹配客户查询的模式,并为其提供答案。
你认为如何创建下面的聊天

简单地说,问题我可以知道的价格吗被转换成模板的价格<星/ >。这个模板就像一把钥匙,所有未来的答案都将存储在里面。所以我们可以有下面的
- iPhone X 的价格是 1500 美元
- Kindle Paperwhite 的价格——100 美元
用 AIML(人工智能建模语言)编写的代码看起来会像这样
**#PATTERN MATCHING**
<category>
<pattern>**MAY I KNOW THE PRICE FOR ***</pattern>
<template>
<srai>**THE PRICE OF <star/>**</srai>
</template>
</category>------------------------------------------------
**#PRE_STORED PATTERNS**<category>
<pattern>**THE PRICE OF iPhone X?**</pattern>
<template>*iPhone X Costs $1500.*</template>
</category><category>
<pattern>**THE PRICE OF Kindle Paperwhite?**</pattern>
<template>*The all-new kindle paperwhite costs $100\. Yay!! You
have got an offer!! You can get it for $85 if you apply
the coupon* ***MyGoodBot***
</template>
</category>
NLP 聊天机器人
模式匹配实现起来简单快捷,但也只能到此为止。它需要大量预先生成的模板,并且只对期望有限数量问题的应用有用。

进入 NLP !NLP 是一个稍微高级的技术的集合,可以理解广泛的问题。创建聊天机器人的 NLP 过程可以分为 5 个主要步骤
1)标记化— 标记化是将文本分割成小块的技术,称为标记,同时丢弃某些字符,如标点符号。这些标记在语言学上代表了文本。

Tokenizing a sentence
2)规格化— 规格化处理文本,找出可能改变用户请求意图的常见拼写错误。一篇很好的研究论文很好地解释了这个概念

Syntactic normalisation of tweets research
3)识别实体— 这一步有助于聊天机器人识别正在谈论的事物,例如,它是一个物体、一个国家、一个号码还是用户的地址。
在下面的例子中,观察谷歌、IBM 和微软是如何联合起来的。这一步也称为命名实体识别。

Entities for various words.
4)依存句法分析——在这一步中,我们把句子分成名词、动词、宾语、常用短语和标点符号。这项技术帮助机器识别短语,进而告诉它用户想要传达什么。

Stanford — dependency parsing example
5)生成— 最后,生成响应的步骤。以上所有步骤都属于 NLU(自然语言理解)。这些步骤有助于机器人理解所写句子的意思。然而,这一步属于 NLG(自然语言生成)。这一步接收前面 NLU 步骤的输出,并生成许多意思相同的句子。生成的句子通常在以下方面是相似的
- 词序— “厨房灯”类似于“厨房里的灯”
- 单数/复数— “厨房灯”类似于“厨房灯”
- 问题— “关上门”类似于“你介意关上门吗?”
- 否定——“19:00 开电视”类似于“19:00 不开电视”
- 礼貌——“打开电视”类似于“麻烦你打开电视好吗?”
基于用户问题的上下文,机器人可以用上述选项之一进行回复,用户会满意地返回。在很多情况下,用户无法区分机器人和人类。
自 AIML 于 1995 年发明以来,聊天机器人一直在稳步发展,并取得了长足的进步。即使在 2016 年,普通用户也要花 20 多分钟在即时通讯应用上,Kakao、Whatsapp 和 Line 是最受欢迎的应用。

世界各地的企业都希望通过使用这些机器人来削减客户服务成本,并提供全天候的客户服务。
这个故事被发送到 BI Intelligence 应用和平台简报订阅者。要了解更多信息并订阅…
www.businessinsider.com](https://www.businessinsider.com/80-of-businesses-want-chatbots-by-2020-2016-12?IR=T)
聊天机器人背后的技术相当标准。NLP 还有很长的路要走,但即使在目前的状态下,它也为聊天机器人领域带来了很多希望。
如何使用 Dash 和 Plotly 构建报告仪表板
在这篇博文中,我将提供一个分步指南,介绍如何使用 Dash 构建一个报告仪表板,这是一个用于构建分析性 web 应用程序的 Python 框架。我没有详细介绍构建 Dash 应用程序的基础知识,而是提供了一个使用数据表和图表构建多页仪表板的详细指南。
我将报告仪表板构建为一个多页面应用程序,以便将仪表板分成不同的页面,这样就不会太多,并以一种有组织的方式呈现数据。在每个仪表板页面上,有两个数据表、一个日期范围选择器、一个数据下载链接,以及两个仪表板下方的一组图表。我在构建仪表板时遇到了几个技术挑战,我详细描述了我是如何克服这些挑战的。
完成的仪表盘可以在https://David comfort-dash-app 1 . heroku app . com/cc-travel-report/payed-search/查看,代码在 Github 中提供。(应用程序中使用的数据是随机数据,产品名称是“虚拟”名称。)

Figure 1: Dashboard built using Dash

Figure 2: Second Part of Dashboard
目录
- 1。简介
- 2。我想用仪表板实现什么?
- 3。构建仪表板的挑战
- 4。创建新环境并安装 Dash
- 5。破折号入门
- 6。构建多页面应用程序
- 构建索引页面
- 自定义页面标题和图标
- 页面布局概述
- App 的本地测试
- 7。构建日期选择器元素
- 给 CSS 添加一个修正,这样日期选择器就不会隐藏在数据表后面
- 8。构建第一个数据表
- 根据日期选择改变数据表中显示的日期
- 计算指标的变化,以及计算每次会话的成本、转换率和每次收购的成本。
- 一种选择压缩数据表或完整数据表的方法。
- 有条件地对不同的数据表单元格进行颜色编码
- 使用重身幽灵列的单元格的条件格式
- 9。建筑下载数据链接
- 10。构建第二个数据表和
- 11。通过选择仪表板数据表中的行来更新图形
- 第一步
- 第二步
- 第三步
- 12。动态更新图表和计算指标
- 13。Plotly 图形工具
- 14。部署仪表板
- 解决 Custom.css 文件和认证问题
- Dash 部署服务器
- 15。包装完毕
- 16。破折号的资源
1.介绍
今年 1 月,我参加了我的第一次 PyData 会议,PyData Miami,参加了切尔西·道格拉斯关于 Dash 的精彩演讲。
Embedded Video 1: Dash: data exploration web apps in pure Python — Chelsea Douglas
很快,Dash 的强大功能变得显而易见,我可以使用 Python 轻松地构建 web 应用程序和仪表盘。
从我的角度来看,我的公司确实需要自动化报告,取代 Microsoft Excel 数据透视表和电子表格,并提供商业智能工具的替代方案。尽管我的公司中的各种利益相关者依赖 Excel 电子表格进行定期报告,但它们的使用变得很笨拙,容易出错,它们不是独立于平台的,并且它们不适合自动化。
因此,我努力使用 Dash 构建一个多页面的 web 应用程序。这篇文章深入探讨了我的努力的本质和细节,以及我是如何克服几个技术挑战的。我应该指出,我来自一个数据科学家的角度,并没有声称自己是一个软件开发人员。因此,我的代码当然还有改进的空间,我欢迎读者的建议。同时,如果读者需要构建复杂的仪表板和数据表,我希望他们能够从我的工作中受益。
2.我想用仪表板实现什么?
在我现在的公司,许多定期报告都是通过 Excel 电子表格和数据透视表完成的,或者使用商业智能工具,如 Birst 或 Qlikview 。因此,我想建立一个报告仪表板,作为一个概念验证,可以取代和增强我们的报告。具体来说,我想为一个品牌构建一个报告 web 应用程序,它可以报告不同的营销渠道指标,实现自动化并提供方便的访问。
电子商务营销仪表板的要求包括:
- 将不同的营销渠道分成不同的页面,这样仪表盘中显示的数据量就不会过多。
- 日期选择器,用户可以选择日期范围来过滤数据。
- 一个数据表,显示所选日期范围内,以及去年同期和所选日期范围之前的相应时期内,每个数字营销渠道或产品类型的基本指标(支出、会话、交易数量和收入)。*
- 另一个数据表显示所选日期范围(以及去年同期和前期)的计算指标。这些指标包括每次会话成本(CPS)、转换率(CVR)和每次收购成本(CPA)。
- 下载每个数据表中显示的数据(Excel 格式)的链接。
- 数据表下方将显示每周的指标图表。
- 对应的先前时段的一个示例是,如果用户选择了 2019 年的第 5 和第 6 周,则对应的先前时段将是 2019 年的第 3 和第 4 周。
3.构建仪表板的挑战
当我构建 dashboard 应用程序时,出现了多个挑战。一些主要挑战包括:
- 找出一种方法来显示压缩的数据表或完整的数据表。
- 能够根据单元格中的值对数据表中的单元格进行颜色编码。
- 能够选择多个产品以包括在数据的图形表示中。
- 能够根据用户选择的日期范围动态更新数据表中的指标。
- 能够下载数据表中呈现的数据,而无需任何附加格式。
- 在与给定指标相同的 x 轴上描绘指标的逐年变化。
- 能够同时放大所有的图表。
4.创建新环境并安装 Dash
有一个 Dash 用户指南,它提供了 Dash 的一个相当全面的介绍,我鼓励读者在处理一个完全成熟的仪表板之前浏览用户指南并构建一些简单的 Dash 应用程序。此外,还有一个 Dash 社区论坛,一个论坛的展示和讲述部分,突出 Dash 社区的工作,一个 Dash 项目的画廊,一个令人敬畏的 Dash 资源的精选列表,以及一篇关于 Dash 的介绍性文章:
Dash 是一个开源的 Python 库,用于创建基于 Web 的反应式应用程序。两年前,Dash 开始在 GitHub 上公开进行概念验证。我们在网上保留了这个原型,但是 Dash 的后续工作是秘密进行的。我们使用来自银行、实验室和数据科学团队的私人试验的反馈来指导产品的发展。今天,我们很高兴地宣布 Dash 的首次公开发布,它既是企业级的,也是 Plotly 开源工具的一流成员。 Dash 现在可以从 Python 的包管理器中下载,带有
pip install dash——它是完全开源的,得到了 MIT 的许可。你可以在这里找到入门指南和 GitHub 上的 Dash 代码。Dash 是一个用于创建分析性 web 应用程序的用户界面库。那些使用 Python 进行数据分析、数据探索、可视化、建模、仪器控制和报告的人会立即发现 Dash 的用处。
Dash 使围绕数据分析代码构建 GUI 变得非常简单。
在安装 Dash 之前,按照惯例,我使用 conda : conda create --name dash创建了一个新环境,然后激活了那个环境conda activate dash。然后,我简单地按照用户指南中提供的 Dash 安装协议进行操作:
Code Block 1: Pip installing Dash and its components
我应该注意的是,Dash 及其组件的版本将会有所不同,您应该参考用户指南。
5.Dash 入门
已经有相当多的 Dash 教程了,所以我将在本教程中重点介绍如何使用数据表和图表构建多页仪表板,而不是复习构建 Dash 应用程序的基础知识。
如果你刚刚开始使用 Dash,我会鼓励读者至少通读优秀的 Dash 用户指南的前三节。在仪表板数据表上也有一个部分。有几个教程可以让你入门 ***** :
- 介绍 Plotly Dash——《Dash》的作者 Chris Parmer 对 Dash 的高水平介绍。这篇文章是 Dash 官方发布(2017 年 6 月 21 日)的一部分。
- Plotly 的教程—第一部分:应用布局
- Plotly 的教程—第二部分:交互性
- Plotly 的教程——第三部分:交互式绘图
- Plotly 的教程—第 4 部分:带状态的回调
- Python 中基于 Web 的交互式仪表盘—MVC 模式如何适用于 Dash 以及构建应用程序的演练。
- 使用 Plotly 的 Dash 交付公共部门决策支持仪表板 —逐步构建复杂的仪表板。
- OPS code day:Dash Plotly Map+Graph—如何使用 Jupyter 笔记本与 Dash 协同创建映射,即
- 使用 Plotly 的 Dash 框架创建交互式可视化效果—Dash 入门指南。
- 用 Dash 寻找大脚怪,第 1 部分 —构建大脚怪目击仪表板的演练。第二部分,第三部分。
- 用 Dash 来想象地震——Dash 替代品的环境扫描,随后是一个教程。
- ARGO Labs — Plotly Dash 教程(视频) —创建交互式仪表盘的详细介绍。
- 使用 Dash 和 Python 的数据可视化 GUI(视频播放列表) —探索 Dash 特性的五部分系列。
***** 来自 牛逼 Dash Github 页面。
本质上,Dash 应用程序由两部分组成:(1)描述应用程序外观和感觉的应用程序的“布局”,以及(2)使应用程序能够交互的“回调”。用户指南中提供了一个简单的 Dash 应用程序布局,如下所示:
Code Block 2: Simple Dash App Layout
我在本教程中描述的仪表板将 Dash 应用程序分割成不同的文件,并使用户能够构建多页面应用程序。
有一个“索引”页面,根据 URL 呈现不同的页面或布局。每个布局都由几个不同的 Dash 组件组成,包括日期范围选择器、数据表、下载链接和几个图表。这些组件中的每一个都与一个或多个“回调”相关,这些“回调”使仪表板能够进行交互。
用户可以与 Dash 组件之一交互(例如,改变日期范围),并且其他组件反映该改变(例如,导致数据表中呈现的数据改变)。
这种方法的示意图如下图所示:

Figure 3: Schematic of Dashboard files
6.构建多页应用程序
基于在https://dash.plot.ly/urls的 Dash 文档,多页 Dash 应用程序的结构略有改动,如下所示:
Code Block 3: File Structure of a Multi-page Dash App
文件app.py 仅包含以下内容:
Code Block 4: app.py
注意,我使用的是 dash 认证模块(https://dash.plot.ly/authentication)。这有一些含义,我将在下面加以阐述。
构建索引页面
index.py文件通过定义函数display_page来定义应用程序的 URL 页面结构,该函数根据应用程序的 URL 来决定应该呈现什么样的页面布局。
Code Block 5: index.py
这与https://github.com/plotly/dash-vanguard-report的 Dash Vanguard 报告中的index.py页面非常相似,在(https://Dash-gallery . plot ly . host/Dash-Vanguard-Report/portfolio-management)有一个演示。
然而,我不得不包括行from app import server,以便克服我在 Heroku 上部署应用程序时的一个问题(详见https://community . plot . ly/t/nolayoutexception-on-deployment-of-multi-page-dash-app-example-code/12463)。
自定义页面标题和图标
此外,我想定制应用程序的 HTML 索引模板,特别是页面标题和 favicon。为此,我在index.py中添加了以下index_string::
Code Block 6: index_string in index.py File
为了定制 favicon,可以将favicon.ico图像放在资产目录中。
页面布局概述
index.py文件中的回调将应用程序 URL 作为输入,并根据布局输出不同的布局:
Code Block 7: Callback in index.py File
layouts.py文件包含以下内容:
- 普通 python 导入语句
- 将数据 CSV 文件读入 pandas 数据帧的语句
- 定义不同布局变化中所需的数据表列
- 每个页面布局部分的定义
noPage布局的定义
layouts.py文件的开头如下:
Code Block 8: Beginning of layouts.py File
每个页面布局部分包含以下元素:
- 调用导入的
Header(),这样就可以拥有共同的元素(徽标、品牌名称等。)跨多个 app。 - 数据范围元素
- 标题栏
- 用于选择压缩数据框和完整数据框的单选按钮
- 第一个数据表
- 下载按钮
- 第二数据表
- 图表
layouts.py中一个布局部分的简化代码块如下:
Code Block 9: Section of layouts.py to render Paid Search Page
上面的代码不包括条件格式,我将在下面讨论。
应用程序的本地测试
按照用户指南,在创建了index.py和app.py文件后,用户可以调用应用程序
$ python app.py
...Running on http://127.0.0.1:8050/ (Press CTRL+C to quit)
并在您的网络浏览器中访问http:127 . 0 . 0 . 1:8050/cc-travel-report/payed-search/。
7.构建日期选择器元素

Figure 4: Date Selector Element
日期选择器元素提供了更新两个数据表中显示的数据以及下载的数据链接的方法。我还想让日期选择器对用户选择的日期提供反馈。
我干脆选择 2018 年 1 月 1 日作为允许的最小日期(min_date_allowed);允许的最大日期基于 CSV 数据文件(max_date_allowed)中的最大日期;所选日期中显示的初始月份基于 CSV 数据文件中的最大日期(initial_visible_month);初始开始日期是最大日期减去 6 天(start_date);初始结束日期是最大日期。
以下代码位于layouts.py文件中,需要在 Dashboard 应用程序的每个“页面”上重复。
Code Block 10: Html Element for Date Picker in layouts.py File
我使用了一个回调函数和一个函数update_output来向用户提供反馈。具体来说,我希望提供关于所选日期、所选天数以及相应的前期日期的文本反馈。例如,如果用户使用日期范围选择器选择了 2019 年的第 5 周和第 6 周,则对应的过去时间段将是 2019 年的第 3 周和第 4 周。下面的update_output函数提供了这一功能。
Code Block 11: Callback and Function for Date Picker in layouts.py file
日期选择器元素为第一个数据表、第二个数据表、下载链接以及数据表下面的一组图表的回调提供输入。我将详细介绍这些回调是如何工作的,以及它们相关的输出。
向 CSS 添加一个修正,以便日期选择器不会隐藏在数据表后面
我必须纠正的一个问题是数据表模糊了日期选择器元素,所以我必须相应地纠正 CSS。
Code Block 12: CSS for change z-index of data table in custom.css file
8.构建第一个数据表

Figure 5: First Data Table with a Condensed View
仪表板中的第一个数据表显示了支出(与给定广告产品相关的成本)、网站会话、预订(交易)和收入等指标。这些指标根据在所选日期中选择的日期进行汇总,通常会显示所选日期范围内当前年度的数据、之前相应期间的数据、去年的数据,以及这些期间之间的百分比和绝对差异。
基于日期选择改变数据表中呈现的日期
我想要的第一个数据表的主要功能是使它具有交互性,由此显示的数据根据所选的日期而变化。首先,数据表元素需要包含在layouts.py文件中,如下面的(简化)代码所示:
Code Block 13: Data Table Component in layouts.py File
数据表的不同参数包括:
id:标识符,以便数据表可以被回调引用。columns:表格中呈现的列;deletable让用户能够在使用应用程序时删除列。editable=True让用户能够在使用应用程序时更改表格中的数据。n_fixed_columns=2冻结前两列(在我们的例子中是复选框和位置类型),因此当用户滚动整个数据表时,用户仍然可以查看复选框和位置类型。style_table允许 CSS 样式应用于表格。row_selectable='multi'允许用户通过复选框选择多行。这将根据选择更新下面的图表。selected_rows=0包含最初选择的行的索引(如下图所示)。style_cell允许将 CSS 样式应用于表格单元格。
我将在后续步骤中添加额外的参数,以便我们可以有条件的样式格式。在 pandas 中添加了数字格式,如美元符号、逗号和百分号,并定义为一系列格式化程序。
我应该注意,我没有在layouts.py文件中为数据表指定data参数。相反,数据表的data参数将来自回调:
Code Block 14: Callback for First Data Table in layouts.py File
计算指标的变化,以及计算每次会话的成本、转换率和每次收购的成本。
因为我们需要计算指标的变化,以及 CPA、CPS 和转换率,这些都取决于“动态”选择的日期,所以我将这些计算放入一个单独的文件中,functions.py。然后,我可以在不同的仪表板页面上重复使用这些功能。我还在这个文件中定义了格式化函数:
Code Block 15: Data Formatters in functions.py file
第一个数据表和第二个数据表的功能是相似的,所以我在这里只给出一个:
Code Block 16: update_first_datatable Function in functions.py
数据表元素、回调和函数之间的流程可以描述为:

Figure 6: Flow for the first data table
一种选择压缩数据表或完整数据表的方法。
我希望数据表的一个特性是能够显示表的“压缩”版本以及完整的数据表。因此,我在layouts.py文件中包含了一个单选按钮来选择要呈现的表格版本:
Code Block 17: Radio Button in layouts.py
此功能的回调接受单选按钮的输入,并输出要在数据表中呈现的列:
Code Block 18: Callback for Radio Button in layouts.py File
这个回调稍微复杂一点,因为我要为条件格式添加列(我将在下面讨论)。本质上,正如下面的回调基于使用回调语句Output('datatable-paid-search', 'data'选择的日期更改数据表中显示的数据一样,这个回调也基于使用回调语句Output('datatable-paid-search', 'columns'选择的单选按钮更改数据表中显示的列。
有条件地对不同的数据表单元格进行颜色编码
利益相关者希望数据表具有的特性之一是,能够根据指标值突出显示数据表中的某些数字或单元格;例如,红色代表负数。然而,数据表单元格的条件格式有三个主要问题。
- 目前 Dash 数据表中缺少格式化功能。
- 如果在将数字包含到 Dash 数据表中之前对其进行了格式化(例如在 pandas 中),则数据表功能(如排序和过滤)将无法正常工作。
- Dash 数据表代码中有一个缺陷,其中条件格式不能正常工作。
尽管有上述限制,我最终还是格式化了熊猫数据表中的数字。我发现 Dash 中的条件格式不适用于格式化的数字(带逗号、美元符号、百分号等的数字)。).事实上,我发现 Dash 数据表用户指南的条件格式—突出显示单元格一节中描述的方法有一个错误:
Code Block 19: Conditional Formatting — Highlighting Cells
纽约市温度的单元格显示为绿色,即使该值小于 3.9。*我在其他场景中测试过,数字的条件格式似乎只使用了条件的整数部分(“3”而不是“3.9”)。用于条件格式的温度过滤器以某种方式截断了有效数字,并且只考虑数字的整数部分。我在 Dash 社区论坛上发布了关于这个 bug 的帖子,它已经在 Dash 的最新版本中被修复了。
*这已在 Dash 文档中得到纠正。
使用重身幽灵列的单元格的条件格式
由于单元格条件格式的上述限制,我想到了一种替代方法,在该方法中,我将“二重身”列添加到 pandas 数据框和 Dash 数据表中。这些二重身列要么是原始列的值,要么是原始列的值乘以 100(以克服条件筛选不考虑值的小数部分时的缺陷)。然后,可以将重影列添加到数据表中,但使用以下语句隐藏这些列:
Code Block 20: Adding Doppelganger Columns
然后,可以使用以下语法实现条件单元格格式:
Code Block 21: Conditional Cell Formatting
本质上,过滤器应用于“二重身”列,Revenue_YoY_percent_conditional(过滤值小于 0 的单元格)。然而,格式化被应用于相应的“真实”列Revenue YoY (%)。人们可以想象这种条件格式编排方法的其他用途;例如,突出显示异常值。
数据表的完整语句如下(奇数行和偶数行的条件格式,以及使用 doppelganger 方法突出显示高于特定阈值的单元格):
Code Block 22: Data Table with Conditional Formatting
我描述了使用下面数据表中的选定行来更新图形的方法。
9.构建下载数据链接

Figure 7: Download data link
我希望仪表板的一个特性是能够下载数据表中显示的数据。具体来说,我希望下载的数据根据选择的日期进行更新(并显示在数据表中)。此外,由于没有显示日期,有必要将日期添加到下载的文件中。此外,尽管数据表中的数据是格式化的(带有$、%和千个逗号分隔符),我还是希望下载的数据没有格式化。
有两个关键的 Plotly 社区线程帮助我在建立了这个功能,允许用户点击下载 Excel 和允许用户点击下载 CSV。
下载数据功能通过以下方式实现:
- 在
layouts.py文件中有一个用于下载按钮的占位符。
Code Block 23: Placeholder for Download Button
- 要使下载链接正常工作,您需要以下模块:
Code Block 24: Import Statements to Enable Download Functionality
- excel 下载的回调放在
callbacks.py文件中。回调从日期选择器元素获取start_date和end_date,并输出对下载链接的文件引用。 update_link功能是根据开始和结束日期更新要提供的 URL 链接。- 函数
download_excel_1获取 URL 值并将其拆分回start_date和end_date,这样我就可以根据开始和结束日期以及当前日期来命名filename。
Code Block 25: Callback and function for excel download data link
- 函数
download_excel_1还调用另一个函数update_first_download,它与上面给出的update_first_download函数非常相似,只是数据没有格式化。 - 下载的 Excel 文件根据产品名称、选择的开始和结束日期以及当前日期命名。开始和结束日期以及其他适当日期的列被添加到下载的数据文件中。

Figure 8: Snap shot of the downloaded data.
10.建立第二数据表

Figure 9: Data Table with Calculated Metrics
第二个数据表显示了诸如每次会话成本、转换率和每次会话成本之类的指标,这些指标是根据所选日期范围内选择的日期“动态”计算的。
第二个数据表的创建方式与第一个数据表相似,所以本教程不再赘述,但是完整的文件在 Github 上。
11.通过选择仪表板数据表中的行来更新图形

Figure 10: Digital Marketing Metric Graphs
数据表下方的图形显示按周汇总的指标,包括本年度的数据、去年的数据以及两者之间的百分比变化。

Figure 11: Diagram of callback and function to update graphs
更新图表的步骤如下:
- 在
layouts.py文件中设置占位符。 - 在
callbacks.py文件中为每组图形、仪表板的每一页创建回调。 - 构建一个函数,该函数根据 Dash 数据表中选择的产品列表过滤完整的产品列表,然后根据该选择创建一个 pandas 数据框。
- 然后,过滤后的数据帧被传递给另一个函数,
update_graph,该函数(a)计算诸如每次会话成本、转换率和每次会话成本之类的指标,以及(b)生成图形输出。
这些步骤详述如下。第 12 节“动态更新图表和计算指标”详细介绍了第 4 步
第一步
在layouts.py文件中,只有一个图形占位符:
Code Block 26: Placeholder for Graphs
第二步
在callbacks.py文件中,每页上的每组图形都有一个回调函数:
Code Block 27: Callback for Graphs
回调从第一个数据表中获取输入,以及从日期选择器中获取输入,并通过id、paid-search输出到dcc.Graph元素。
第三步
我遇到的一个挑战是,如何根据数据表中选择的产品来更新图表。
在第一个数据表的代码中,需要设置row_selectable到multi和selected_rows=[0]的参数。前一个参数启用数据表中每一行旁边的复选框,而后一个参数确保所选行有初始值。参数n_fixed_columns冻结数据表中的前两行,以便当用户启用完整的数据框时,它们是可见的(从而显示所有可用的列)。
以下是第一个数据表的简化代码块(在layouts.py文件中):
Code Block 28: Simplified Data Table Definition
因此,图形的回调获得了selected_rows。在更新图表的函数update_paid_search中,通过按照仪表板页面类别过滤原始数据框(在本例中为付费搜索)并获得唯一放置类型的完整列表,构建了一个产品列表。然后,for循环根据数据表中选择的产品列表过滤该列表。随后,通过根据所选产品列表过滤原始数据框并执行熊猫groupby以及对花费、会话、预订和收入列求和,创建过滤数据框filtered_df。图表的回调和函数update_paid_search如下所示:
Code Block 29: Callback and Update Function for Graphs
12.动态更新图表和计算指标
每个指标的图表按周和数据表中选择的产品进行汇总(如上所述)。
我想要的图形和更新功能包括:
- 由于图表可以一次描述多个产品的指标,因此更新功能需要实时计算指标。
- 每个指标的图表应包括今年的值、去年的值以及年度间的百分比差异。这些数据应覆盖在同一张图表上,数值以线图显示,年度变化以条形图显示。
- 我希望缩放功能能够同时作用于所有的图形,这样,放大一个图形,就可以以相同的缩放级别放大其他图形。
完整的update_graph函数(位于functions.py文件中)如下:
Code Block 30: update_graph Function in functions.py File
为了将图表“组合”在一起,我使用了在https://plot.ly/python/subplots/中详细描述的子情节功能。update_graph功能有以下主要元素:
- 指标的动态计算。
- 使用 Plotly 库中的
graph_objs方法定义每个图形“轨迹”(记住通过import plotly.graph_objs as go导入该方法)。具体来说,每个图形都用go.Scatter方法定义:
Code Block 31: Trace Assignment for each Graph element
- 当我们调用
tools.make_subplots时,定义了主图形及其参数。在应用程序开发期间,我发现潜在的错误来源是在添加额外的跟踪(rows=6)时没有记住更改行数,以及确保标题的数量与图形的数量相同。这两种情况都可能导致应用程序失败。
Code Block 32: make_subplots To Set Parameters for Subplots
- 不同的子图“轨迹”被附加到主图形中,带有诸如
fig.append_trace(sessions_ty, 1, 1)的语句,其中sessions_ty是上面定义的轨迹名称;第一个数字1是图形编号,最后一个数字是列编号(在任何情况下都是1,因为我们只有一列)。为了在下一步中帮助我,我已经为每个跟踪添加了注释掉的数字。
Code Block 33: Appending Trace to the Figure
为了覆盖每年的变化,我必须有几个 update 语句,并为每个覆盖图(每年的变化图)添加新的 y 轴。这些重叠图形所需的语法有点复杂。
Code Block 34: Code to Overlay Year-to-Year Change Graphs
- 例如,在第一个 update 语句中,语句
fig['data'][2]中的索引号2引用第三个 trace,sessions_yoy(因为 Python 是零索引的)。
下图有助于可视化组合图中各种元素的索引。

Figure 12: Schematic of the Different Axis Indexes
- 语句
yaxis='y7'中的 y 轴名称y7需要是7,因为已经有 6 个 y 轴(每个指标一个:会话、花费、预订、cpa、cps 和 cr。对于每个指标,今年和去年的数据共享同一个左侧 y 轴)。因此,我们需要从7开始对右侧 y 轴进行编号。 - 我们需要使用
fig['layout']['yaxis']语句为每个额外的 y 轴分配参数。具体来说,第一个右侧轴表示会话的逐年变化,与第一个图表中的其他会话轨迹重叠。因此,我们需要相应地分配参数:overlaying='y1', anchor='x1',当然,我们需要通过设置side='right'将其分配到右侧。此外,我用以下内容更新了这组图表的标题:
Code Block 35: Update Title of Graphs
最后,我需要用下面的语句更新整个图形布局。我应该注意到下面有几个参数被注释掉了,因为我还在试验不同的参数。
Code Block 36: Update Overall Figure Layout
13.绘图工具
我应该注意到,在 Dash 中有几个有用的工具可以用来操作图形。如果您将鼠标悬停在图表右上方,就可以查看这些工具。

Figure 13: Plotly Graph Tools
使用这些工具,您可以:
- 拖动以放大,双击以返回原始图形。
- 拖动图形的角沿一个轴缩放。
- 双击以自动缩放单个轴。
- 更改悬停模式以比较数据或调查单个数据点。
当然,最好的工具之一是下载图片的能力:

Figure 14: Downloaded image of the graphs
14.部署仪表板
我基本上遵循了 Dash 用户指南中的部署 Dash 应用指南,做了一些改动。具体来说,我使用以下步骤在 Heroku 上部署了仪表板:
- 步骤 1 :我已经在前一步中为我的仪表板代码创建了一个文件夹。
Code Block 37: Mkdir and cd Code
- 第二步:用
git初始化文件夹。我之前为 Dash 设置了一个 conda 环境,而不是使用venv。
Code Block 38: Init Git and Active Dash Conda Environment
我已经使用conda或pip安装了应用程序的依赖项:
Code Block 39: Pip Installation of Dash and other Modules
您还需要一个新的依赖项gunicorn,用于部署应用程序(上面代码段中的第 10 行)。
- 第三步:用一个 app (
app.py)、一个.gitignore文件、requirements.txt文件、Procfile文件初始化文件夹进行部署。我们只需要最少的app.py,因为我们使用多个文件定义我们的应用程序。您需要在项目文件夹中创建以下文件。
app.py
Code Block 40: app.py file (previously created)
.gitignore
Code Block 41: .gitignore file
还有一个Procfile文件:
Code Block 42: Procfile file
您还需要生成一个requirements.txt文件。您可以通过以下方式实现这一点:
Code Block 43: Create new requirements.txt file
- 第四步:初始化 Heroku,添加文件到 Git,部署。在初始化 Heroku 之前,你需要安装 Heroku 命令行界面(CLI ),或者在 https://devcenter.heroku.com/articles/heroku-cli 用他们的安装程序安装,或者在 Mac 上用家酿软件安装。
Code Block 44: Initialize Heroku and Deploy
您应该可以在https://my-dash-app.herokuapp.com查看您的应用程序(将my-dash-app更改为您的应用程序的名称)。
- 第五步:更新代码,重新部署。当您修改应用程序的任何元素时,您需要将更改添加到 git,并将这些更改推送到 Heroku。此外,每当我更改底层 CSV 数据文件时,您都需要将新数据集推送到 Heroku。
Code Block 45: Pushing changes to Heroku via Git
我应该注意,如果您在部署 Heroku 时遇到问题,请先尝试部署一个简单的应用程序,并测试您是否正确地执行了每个步骤。例如,我发现我需要将以下内容添加到index.py文件中,以便 Heroku 部署能够工作:from app import server。
解决 Custom.css 文件和身份验证的问题
另外,我发现当我给我的 app 添加认证时,app 已经无法访问我的custom.css文件,所以我需要在 codepen.io 上创建一个 css 文件,并将其包含在外部 css 文件列表中(我假设这是 Dash 中的一个 bug)。
Dash 部署服务器
Plotly 还提供了一个 Dash 部署服务器
要在商业 IT 环境中轻松部署应用程序,请从关键任务项目的支持计划和研讨会开始,或者联系我们世界一流的工程团队进行定制功能开发或概念验证应用程序开发。
我应该指出,我与 Plotly 没有任何关系。
15.包扎
从开始到结束,这个项目花了大约两个半星期。我以前没有使用过 Dash,使用 Plotly 的经验有限。我用来构建仪表板的一些方法包括:
- 首先构建仪表板的最小部分。基本上,我不会试图一次解决所有问题。在将元素添加到整个仪表板之前,我一次构建一个元素,通常是单独构建。
- 为了确保我的 python 语法是正确的,我使用了一个 Jupyter 笔记本来记录原始数据框,并以分段的方式应用每个更改。
- 我会对应用程序进行小的增量更改,然后进行测试。冲洗并重复。
- 我首先开发了一个部分,并让它正常工作,达到了我的要求。然后,我会将此部分复制并粘贴到其他部分,并进行适当的更改。
- 我为最后一步保存了部署。我在本地测试了所有东西。
我希望更新仪表板的内容包括:
- 向每个图表轴添加周,很可能使用注释。
- 让图表的 x 轴跨越几年,而不是只描绘 2018 年或 2019 年。
- 为报告添加“打印 PDF”按钮。我试着实现了一个,但是还没有成功。
- 添加带有元数据的页脚(数据源、提取数据的日期、提取数据的位置等。)
谢谢你读到这里。我知道这有点让人不知所措,但我基本上把事情分成了易于管理的几个部分。
16.Dash 资源
这里有一些资源可以进一步帮助您使用 Dash:
- Dash 用户指南
- Udemy 课程(我没有上过这个在线课程,所以我不能对此发表评论。
- Dash 社区论坛
- Github 上的超赞 Dash 资源指南
如何构建基于内容的电影推荐系统
创建基于内容的电影推荐系统

Designed by rawpixel.com / Freepik
在这篇文章中,我将尝试解释我们如何在没有用户数据的情况下创建一个推荐系统。我还将分享一个我用 Python 做的例子,并一步步告诉你它是如何工作的。
我不打算单独解释推荐系统的类型,因为它在互联网上很容易找到。所以,我们先来说说基于内容的推荐系统吧!
什么是基于内容的推荐系统?

基于内容的推荐系统不包括从除你之外的用户那里检索的数据。它只是通过识别与你喜欢的产品相似的产品来帮助你。
例如,您有一个在线销售商品的网站,但您还没有注册用户,但您仍然想向网站的访问者推荐产品。在这种情况下,基于内容的推荐系统将是您的理想选择。
然而,基于内容的推荐系统是有限的,因为它们不包含其他用户数据。它也不能帮助用户发现他们潜在的品味。
举个例子,假设用户 A 和用户 B 喜欢剧情电影。用户 A 也喜欢喜剧电影,但是既然你没有那方面的知识,你就继续提供剧情电影。最终,你排除了用户 B 可能喜欢的其他选项。
反正!在创建这个系统之前,我们先来讨论几个术语。先说核密度估计!
核密度估计
核密度估计是一个非常有用的统计工具,有一个吓人的名字。通常简称为 KDE ,这是一种让你在给定一组数据的情况下创建平滑曲线的技术。

KDE plot example from seaborn
KDE 是一种帮助确定数据分布密度的方法。它提供了许多点位于何处和不在何处的信息。因此,在一维数组中,它通过将最低密度点(局部最小值)与最高密度点(局部最大值)分开来帮助您进行聚类。只要遵循这些步骤,
- 计算密度
- 寻找局部最小值和局部最大值
- 创建集群
余弦相似性
余弦相似度是一种度量向量之间相似度的方法。数学上,它计算两个向量之间角度的余弦值。如果两个向量之间的角度为零,则相似性被计算为 1,因为零的余弦为 1。所以这两个向量是相同的。任何角度的余弦值从 0 到 1 不等。因此,相似率将从 0 变化到 1。该公式表示如下:

Cosine similarity formula
现在够了!我们来编码吧!
特征重要性
我想为每部电影或连续剧设定一个分数,并且我需要为每个特征设定一个系数,所以我将查看特征的重要性。
数据集如下:

Sample data
通过合并在https://datasets.imdbws.com共享的文件,你可以很容易地获得这个数据集。我通过将 title.basics.tsv.gz 的与 title.ratings.tsv.gz 的合并得到这个数据,之后,我删除了一些特征。例如, end_year 字段包含了太多的空值,所以我删除了它。更多详细信息,请查看我的知识库。在本文最后分享。
我还得多说一个细节,我已经通过使用标签编码器将种类字段转换为整数字段。
Feature importances
正如你在上面看到的,我已经尝试了三种不同的方法。首先是由 随机森林 模型直接提供的特性的重要性。
另一个是 排列重要性 。这种方法通过对每个预测值使用随机重排技术来直接测量磁场对模型的影响。它保持了变量的分布,因为它使用了随机重排技术。
最后是 降列特征重要度 。这种方法是完全直观的,每次它删除一个特征,并将其与使用所有列的模型进行比较。它通常要安全得多,但处理时间可能会很长。处理时间对我们的数据集来说并不重要。
结果是这样的:

Feature importance results
我们在这些方法中选择了删除列特征重要性方法。正如我们之前指出的,它更加可靠,当我们看一眼结果时,它们对计算分数更有意义。
**dataset['score'] = (
0.4576 * dataset['num_votes'] +
0.3271 * dataset['runtime'] +
0.3517 * dataset['start_year'] +
0.0493 * dataset['kind']
)**
使聚集
我将使用分数来创建聚类。所以我可以推荐平均分数相同的电影。
我有一个分数的一维数组,我可以用 KDE 聚类。我用这个代码来看分数的分布:
**import matplotlib.pyplot as plt
import seaborn as snsplt.figure(figsize=(9, 6))
sns.distplot(dataset['score'])
plt.axvline(18000, color='r');**
我得到了这样一张图表,

Score distribution
我加了一条竖线 18000,因为密度在 650 到 18000 之间。如果我在应用 KDE 时给你大于 18,000 的点,它会将所有小于 18,000 的点收集在一个聚类中,这不是我们想要的,因为这会降低多样性。
正如我在文章开头提到的,我应用了 3 个阶段对 KDE 进行聚类。
- 计算密度
**from sklearn.neighbors.kde import KernelDensityvals = dataset['score'].values.reshape(-1, 1)
kde = KernelDensity(kernel='gaussian', bandwidth=3).fit(vals)
s = np.linspace(650, 18000)
e = kde.score_samples(s.reshape(-1, 1))**
2.寻找局部最小值和局部最大值
**from scipy.signal import argrelextremami = argrelextrema(e, np.less)[0]
ma = argrelextrema(e, np.greater)[0]points = np.concatenate((s[mi], s[ma]), axis=0)
buckets = []
for point in points:
buckets.append(point)buckets = np.array(buckets)
buckets.sort()**
3.创建集群
**dataset['cluster'] = buckets.searchsorted(dataset.score)**
文本相似度
最后,我计算了类型之间的相似性,以便能够尽可能准确地推荐同一类型的电影。为此我使用了 TF-IDF 和线性内核。因此,在背景中使用余弦相似性来寻找相似性。
**from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kerneltfidf_vectorizer = TfidfVectorizer()
matrix = tfidf_vectorizer.fit_transform(dataset['genres'])kernel = linear_kernel(matrix, matrix)**
现在就来看看推荐吧!
**def get_recommendations2(movie_index):
print(dataset.iloc[movie_index])
print('**' * 40)
sim_ = list(enumerate(kernel[movie_index]))
sim = sorted(sim_, key=lambda x: x[1], reverse=True)
index = [i[0] for i in sim if i[0] != movie_index and i[1] > .5]
cond1 = dataset.index.isin(index)
cond2 = dataset.cluster == dataset.iloc[movie_index]['cluster'] selected = dataset.loc[cond1 & cond2] \
.sort_values(by='score', ascending=False).head(20) print(selected[['title', 'cluster', 'genres']])**

这对我来说似乎很有用!如果你想看更详细的代码,用 烧瓶 上菜,用 橡皮筋搜索 索引电影,用 docker ,你可以看看我的资源库:
** [## egemenzeytinci/recommovie
对于所有选项,克隆存储库,$ git 克隆 https://github.com/egemenzeytinci/recommovie.git 构建并运行…
github.com](https://github.com/egemenzeytinci/recommovie)
感谢您的阅读!
参考
- Eryk Lewinson,以随机森林为例解释特征重要性 (2019)
- 马修·康伦,,核密度估计
- 马修·奥弗比, 1D 与 KDE (2017)
- 计数矢量器,tfidf 矢量器,预测评论 (2018)**
如何为 Tensorflow 构建自定义数据集
Tensorflow 激励开发人员在想到的几乎任何领域尝试他们令人兴奋的人工智能想法。在 ML 社区中有三个众所周知的因素,它们构成了一个好的深度神经网络模型,可以做神奇的事情。
- 模型架构
- 高质量的培训数据
- 足够的计算能力
我感兴趣的领域是实时通信。想出可以为 RTC 应用增加价值的实际 ML 用例是容易的部分。我最近写了一些关于这些的文章。
正如我的共同创始人和好朋友 Jean Deruelle 指出的,如果我们走进环境计算,新一代通信设备无缝增强家庭和工作体验,会有更多相邻的用例。
所以我想构建一个简单的原型,并直接将 Restcomm 连接到 Tensorflow。经过几天的研究,我意识到没有简单的方法将实时流音频/视频媒体(SIP/RTP)输入 tensorflow 模型。类似于 Google Cloud 的语音转文本流 gRPC API 的东西本来是一个可以接受的初始后备,但我在开源 Tensorflow 社区中没有找到。
有多种方法可以从离线的音频文件和视频文件中读取,但这与处理实时延迟敏感的媒体流完全不同。
最终,我的搜索将我带到了由唐勇领导的 Tensorflow IO 项目。TF IO 是一个年轻的项目,有一个由 Google、IBM 和其他公司支持的不断发展的社区。Yong 指给我一个公开的 github 问题,等待贡献者的现场音频支持。这开始了一次愉快的谈话。几个周末后,我鼓起足够的勇气接受了一个小小的编码挑战——为 PCAP 网络捕获文件实现一个新的 Tensorflow 数据集。
PCAP 文件与实时媒体流密切相关,因为它们是网络活动的精确历史快照。PCAP 文件能够记录和重放进入媒体处理软件的实际网络数据包,包括丢包和时间延迟。
回到本文的主题——我现在将向您介绍构建 TF PcapDataset 并将其贡献给 Tensorflow IO 项目的主要步骤:
- Fork Tensorflow IO 和从源构建
- 查看源树中的相邻数据集,选择一个最接近 pcap 的数据集。我利用了来自文本、 cifar 和拼花的代码。还有一份关于创建 TF ops 的文件被证明是有帮助的。
- 在 gitter 频道上寻求帮助。有些人会在几小时内关注并回复。我从斯蒂芬·阿普霍夫和勇那里得到了宝贵的建议。还有每月电话会议,在那里任何人都可以就项目问题发表意见。
- 准备好后提交一个拉取请求。TF IO 团队响应迅速,支持性很强,通过调整和修复来指导贡献者满足最佳实践。
第 2 步是我花了大部分周末业余时间学习 TF 基础设施和 API 的一步。让我给你分析一下。
从根本上讲,TF 是一个在每个节点都有操作的图结构。数据进入图中,操作将数据样本作为输入,处理这些样本并将输出传递给图中其节点所连接的下一个操作。下图是来自官方文档的 TF 图示例。

操作使用名为 tensors 的常见数据类型(因此得名 TensorFlow)。术语张量有数学定义,但张量的数据结构本质上是一个 n 维向量:0D 标量(数字、字符或字符串)、标量的 1D 列表、标量的 2D 矩阵或向量的更高维向量。
在将数据输入到 TF 模型之前,必须对其进行预处理并将其格式化为张量数据结构。这种张量格式要求是由于深度神经网络中广泛使用的线性代数,以及这些结构在 GPU 或 TPU 上应用计算并行性的可能优化。

它有助于理解 TF 数据集的优势和所有开箱即用的便利功能,如批处理、映射、混排、重复。这些函数使得利用有限的数据量和计算能力来构建和训练 TF 模型变得更加容易和高效。
数据集和其他 TF 操作可以用 C++或 Python 构建。我选择 C++路线只是为了学习一些 TF C++框架。然后我用 Python 把它们包起来。以后打算写几个纯 Python 数据集,应该会简单一点。
让我们看一下 TF IO 数据集的源代码文件结构。

Source code directory structure for the TF IO pcap Dataset
Tensorflow 使用 Bazel 作为构建系统,谷歌在 2015 年开源了该系统。下面是 PcapDataset 构建文件。它声明了动态 pcap 库的公共名称(_pcap_ops.so)。列出了要构建的两个源文件(pcap_input.cc 和 pcap_ops.cc)。并声明了构建所需的一些 TF 依赖项。
Main Bazel BUILD file for the pcap dataset
下一个重要的源文件是 pcap_ops.cc,我们在其中声明了 TF ops,它将注册到 TF 运行时环境中,并可用于 TF 应用程序中。
这里的大部分代码都是样板文件。它说我们正在引入一个可以读取 pcap 文件的 PcapInput 操作和一个由 PcapInput 填充的 PcapDataset 操作。两者之间的关系将在稍后变得更加明显。
从我开始我的贡献工作直到它被 TF master 分支接受,在基本的 TF 2.0 框架中引入了一些简化,减少了我的文件中的样板代码。我怀疑在不久的将来会有更多这样的简化。
TF 的核心团队明白,为了吸引更多的贡献者,降低进入门槛是很重要的。新的贡献者应该能够只关注他们正在编写的全新代码,而不要为与 TF 环境交互的细节伤脑筋,直到他们为此做好准备。
包中的下一个文件是 pcap_input.cc 。那里是大部分重物搬运的地方。我花了相当多的时间来编写和测试这个文件。
它有一个部分声明了 PcapDataset、PcapInput 和 PcapInputStream 之间的关系。我们将会看到它们各自的作用。
PcapInputStream 包含从原始 pcap 文件中读取并将其转换为张量的大部分逻辑。为了了解输入的味道,这里有一个用 CocoaPacketAnalyzer 查看的测试 http.pcap 文件的截图。

CocoaPacketAnalyzer view of http.pcap
让我跳过特定于 pcap 文件的逻辑,指出一些从原始二进制文件数据到张量转换的定义元素。
Read a packet record from the pcap file and convert to tensors
此 ReadRecord 行从 pcap 文件中读取下一个 pcap 包,并填充两个局部变量:packet_timestamp double 和 packet_data_buffer 字符串。
ReadRecord(packet_timestamp, &packet_data_buffer, record_count);
如果成功填充了新的 pcap 记录,标量将被放入各自的张量占位符中。结果输出张量的形状是一个有两列的矩阵。一列保存每个读取的 pcap 数据包的时间戳标量。另一列将相应的数据包数据保存为字符串。输出张量(矩阵)中的每一行对应于一个 pcap 分组。

Processing pcap file input to TF tensor output
Tensor timestamp_tensor = (*out_tensors)[0];
timestamp_tensor.flat<double>()(*record_read) = packet_timestamp;Tensor data_tensor = (*out_tensors)[1];
data_tensor.flat<string>()(*record_read) = std::move(packet_data_buffer);
out_tensors 是从 PcapDataset 请求新批次时准备的占位符张量。那是在这里完成的;在读循环之前。
使用类型化平面函数将 packet_timestamp 标量放在第一列(index [0])和(record_read)行。数据包数据缓冲区分别位于第二列(索引[1])和同一(记录读取)行。
这涵盖了 C++代码的关键元素。现在让我们看看 Python 文件。
init。顶层 pcap 目录级别的 py 指示 TF Python 文档生成器如何遍历 Python 代码并提取 API 参考文档。你可以在这里阅读更多关于文档最佳实践。
上面的代码指示 Pyhton API 文档生成器专注于 PcapDataset 类,忽略该模型中的其他代码。
接下来, pcap_ops.py 包装 C++数据集 op,并使其对 Python 应用程序可用。
C++动态库按如下方式导入:
from tensorflow_io import _load_library
pcap_ops = _load_library('_pcap_ops.so')
数据集构造函数的主要作用之一是提供关于它生成的数据集张量类型的元数据。首先,它必须描述单个数据样本中的张量类型。PcapDataset 样本是两个标量的向量。一个用于 tf.float64 类型的 pcap 分组时间戳,另一个用于 tf.string 类型的分组数据
dtypes = [tf.float64, tf.string]
Batch 是通过神经网络的一次正向/反向传递中的训练样本数。在我们的例子中,当我们定义批量的大小时,我们也定义了张量的形状。
当多个 pcap 数据包被分组为一批时,时间戳(tf.float64)和数据(tf.string)都是一维张量,具有 tf 的形状。TensorShape([batch])。
由于我们事先不知道总样本数,总样本数也不一定能被批量大小整除,所以我们宁愿把形状设为 tf。TensorShape([None])给我们更多的灵活性。
批量大小为 0 是一种特殊情况,其中每个单独张量的形状退化为 tf。TensorShape([]),或 0-D 标量张量。
shapes = [
tf.TensorShape([]), tf.TensorShape([])] if batch == 0 else [
tf.TensorShape([None]), tf.TensorShape([None])]
快到了。我们只需要一个测试案例。test_pcap_eager.py 在从 http.pcap 采样的同时练习 PcapDataset。
测试代码很简单。遍历所有 pcap 数据包,并根据已知常数测试第一个数据包中的值。
为了构建 PcapDataset 并运行其测试,我使用了本地 io 目录中的以下代码行:
$ bazel build -s --verbose_failures //tensorflow_io/pcap/...
$ pytest tests/test_pcap_eager.py
就是这样!希望这有助于您构建自己的自定义数据集。当你这样做的时候,我希望你会考虑把它贡献给 TF 社区,以加速开源 AI 的进步。
欢迎在评论区提问。我将尽力回答。
如何为你的机器学习项目建立数据集

你会为你的组织考虑人工智能吗?您已经确定了一个 ROI 得到验证的用例?完美!但没那么快…你有数据集吗?大多数公司都在努力建立一个人工智能就绪的数据集,或者干脆忽略这个问题,我想这篇文章可能会对你有所帮助。
让我们从基础开始…
一个数据集是一个数据的集合。换句话说,数据集对应于单个数据库表或单个统计数据矩阵的内容,其中表的每一列代表一个特定变量,每一行对应于所讨论的数据集的给定成员。
在机器学习项目中,我们需要一个训练数据集。是实际的数据集,用于训练模型执行各种动作。
我为什么需要数据集? ML 非常依赖数据,没有数据,一个“AI”是不可能学习的。是让算法训练成为可能的最关键的方面……无论你的 AI 团队有多伟大,或者你的数据集有多大,如果你的数据集不够好,你的整个 AI 项目都会失败!我见过一些很棒的项目失败,因为我们没有一个好的数据集,尽管我们有完美的用例以及非常熟练的数据科学家。
在训练数据的语料库上训练有监督的 AI。
在人工智能开发过程中,我们总是依赖数据。从训练、调整、模型选择到测试,我们使用三个不同的数据集:训练集、验证集和测试集。供您参考,验证集用于选择和调整最终的 ML 模型。
你可能认为收集数据就足够了,但事实恰恰相反。在每个人工智能项目中,对数据集进行分类和标记花费了我们大部分的时间,尤其是那些足够准确以反映市场/世界现实愿景的数据集。
我想向你介绍我们需要的前两个数据集——训练数据集和测试数据集,因为它们在你的人工智能项目中用于不同的目的,项目的成功在很大程度上取决于它们。
- 训练数据集用于训练算法,以理解如何应用神经网络等概念,学习并产生结果。它包括输入数据和预期输出。
训练集占总数据的大部分,约 60 %。在测试中,模型在被称为调整权重的过程中与参数相适应。
- 测试数据集用于评估你的算法用训练数据集训练的有多好。在人工智能项目中,我们不能在测试阶段使用训练数据集,因为算法已经提前知道了预期的输出,这不是我们的目标。
测试集代表 20%的数据。通常通过人工验证,确保测试集是与验证的正确输出分组在一起的输入数据。
根据我的经验,在测试阶段之后尝试进一步调整是一个坏主意。这可能会导致过度拟合。

什么是过度拟合?
对于数据科学家来说,一个众所周知的问题是… 过度拟合是一个建模错误,当一个函数过于接近有限的数据点集时就会出现这种错误。
需要多少数据?所有项目在某种程度上都是独一无二的,但我认为你需要的数据是正在构建的模型中参数数量的 10 倍。任务越复杂,需要的数据越多。****
我需要什么类型的数据?我总是通过向公司决策者提出精确的问题来启动人工智能项目。你想通过 AI 达到什么目的?根据您的回答,您需要考虑您实际需要哪些数据来解决您正在处理的问题。对您需要的数据做一些假设,并仔细记录这些假设,以便您可以在以后需要时测试它们。
以下是一些对你有帮助的问题:
- 你能为这个项目使用什么数据?你必须对你能使用的所有东西有一个清晰的了解。
- 你希望拥有哪些不可用的数据?我喜欢这个问题,因为我们总能以某种方式模拟这些数据。
我有一个数据集,现在怎么办?
没那么快!你应该知道所有的数据集都是不准确的。在项目的这个时刻,我们需要做一些数据准备,这是机器学习过程中非常重要的一步。基本上,数据准备就是让你的数据集更适合机器学习。它是一组程序,消耗了花在机器学习项目上的大部分时间。
即使你有数据,你仍然会遇到数据质量的问题,以及隐藏在你的训练集中的偏见。简单来说,训练数据的质量决定了机器学习系统的性能。
你听说过 AI 偏见吗?
人工智能很容易受到影响……多年来,数据科学家发现,一些用于训练图像识别的流行数据集包含性别偏见。
因此,人工智能应用程序需要更长的时间来构建,因为我们试图确保数据是正确的,并正确集成。
数据不够怎么办? 可能会发生这样的情况,你缺乏集成一个人工智能解决方案所需的数据。我不会对你撒谎,如果你仍然依赖于纸质文档或其他工具,建立一个人工智能就绪的数据集需要时间。 csv 文件。我建议你首先花时间建立一个现代的数据收集策略。
如果你已经确定了你的 ML 解决方案的目标,你可以要求你的团队花时间创建数据或者外包这个过程。在我最近的项目中,公司想要建立一个图像识别模型,但是没有图片。因此,我们花了几周时间拍摄照片来建立数据集,并找到未来客户为我们做这件事的方法。
你有数据策略吗?在一个组织中创造一种数据驱动的文化可能是一名人工智能专家最难的部分。当我试图解释为什么公司需要数据文化时,我可以在大多数员工的眼中看到沮丧。事实上,数据收集可能是一项烦人的任务,会加重员工的负担。然而,我们可以自动化大部分的数据收集过程!
另一个问题可能是数据的可访问性和所有权…在我的许多项目中,我注意到我的客户有足够的数据,但是这些数据被锁起来,很难访问。您必须在组织中的数据仓库之间创建连接。为了获得特殊的见解,你必须从多个来源收集数据。
关于所有权,合规性也是数据源的一个问题—仅仅因为公司可以访问信息,并不意味着它有权使用它!请不要犹豫,询问您的法律团队(欧洲的 GDPR 就是一个例子)。
质量、范围、数量! 机器学习不仅仅是关于大数据集。事实上,你不需要向系统提供任何相关领域的所有已知数据。我们希望向系统提供精心策划的数据,希望它能够学习,或许在边际上扩展人们已经拥有的知识。
大多数公司认为,收集每一个可能的数据,将它们结合起来,让人工智能找到洞察力就足够了。
当构建数据集时,您应该以数据的多样性为目标。我总是建议公司收集内部和外部数据。目标是建立一个独特的数据集,让你的竞争对手难以复制。机器学习应用确实需要大量的数据点,但这并不意味着模型必须考虑广泛的特征。
我们想要与项目相关的有意义的数据。你可能拥有某个主题的丰富、详细的数据,但这些数据并不十分有用。人工智能专家会问你一些精确的问题,关于哪些领域真正重要,以及这些领域如何可能对你获得的洞察力的应用产生影响。
在我最近的任务中,我必须帮助一家公司建立一个用于营销目的的图像识别模型。这个想法是建立和确认一个概念证明。这家公司没有数据集,除了一些他们产品的 3D 渲染。我们希望人工智能能够识别产品,阅读包装,确定它是否适合客户,并帮助他们了解如何使用它。
我们的数据集由 15 种产品组成,每种产品我们都有 200 张照片。这个数字是合理的,因为它仍然是一个原型,否则,我会需要更多的图片!这假设你正在利用迁移学习技术。
在拍摄照片时,我们需要不同的背景、光线条件、角度等。
每天,我都会从训练集中随机选择 20 张图片并进行分析。这让我对数据集的多样性和准确性有了一个很好的了解。
每次我这样做的时候,我都会发现一些关于我们数据的重要信息。这可能是具有相同角度的不平衡数量的图片、不正确的标签等。
一个好主意是从一个已经在大型现有数据集上预先训练好的模型开始,并使用迁移学习来用您收集的较小数据集对其进行微调。
数据预处理
好吧,让我们回到我们的数据集。在这一步,你已经收集了你认为对你的人工智能项目来说必要的、多样的和有代表性的数据。预处理包括从完整的数据集中选择正确的数据并建立训练集。以这种最佳格式将数据放在一起的过程被称为特征转换。
- 格式:数据可能分散在不同的文件中。例如,使用不同货币、语言等的不同国家的销售结果。这些数据需要收集在一起形成一个数据集。
- 数据清理:在这一步,我们的目标是处理丢失的值,并从数据中删除不需要的字符。
- 特征提取:在这一步,我们重点分析和优化特征的数量。通常,团队成员必须找出哪些特征对于预测是重要的,并选择它们以实现更快的计算和更低的内存消耗。

完美的数据策略
最成功的人工智能项目是那些在服务/产品生命周期中整合数据收集策略的项目。的确,数据收集不可能是一系列一次性的练习。它必须内置于核心产品本身。基本上,每次用户使用你的产品/服务时,你都想从互动中收集数据。目标是利用这种持续不断的新数据流来改进您的产品/服务。
当您达到这种数据使用水平时,您添加的每个新客户都会使数据集更大,从而使产品更好,这会吸引更多的客户,从而使数据集更好,以此类推。这是某种良性循环。

最好的、面向长期的 ML 项目是那些利用动态的、不断更新的数据集的项目。建立这种数据收集策略的好处是,你的竞争对手很难复制你的数据集。有了数据,人工智能变得更好,在某些情况下,比如协同过滤,它是非常有价值的。协同过滤基于用户之间的相似性提出建议,它将随着访问更多数据而改进;一个人拥有的用户数据越多,该算法就越有可能找到相似的用户。
这意味着您需要一种策略来持续改进您的数据集,只要它对提高模型准确性有任何用户好处。如果可以的话,找到创造性的方法来利用微弱的信号来访问更大的数据集。
让我再一次使用图像识别模型的例子。在我上一次的体验中,我们设想并设计了一种方式,让用户给我们的产品拍照并发送给我们。这些照片将被用于我们的人工智能系统,使我们的系统随着时间的推移变得更加智能。
另一种方法是提高标签管道的效率,例如,我们过去非常依赖一个系统,该系统可以建议由模型的初始版本预测的标签,以便贴标机可以更快地做出决定。
最后,我看到一些公司只是雇佣更多的人来标记新的培训投入……这需要时间和金钱,但很有效,尽管在传统上没有这种支出预算的组织中,这可能很困难。
不管大多数 SaaS 公司怎么说,机器学习需要时间和准备。每当你听到人工智能这个术语,你一定会想到它背后的数据。我希望这篇文章能帮助你理解数据在 ML 项目中的关键作用,并说服你花时间反思你的数据策略。
如何建立一个没有框架的深度神经网络
了解如何使用 NumPy 构建可扩展的深度神经网络,并将其用于图像分类

Photo by Sneaky Elbow on Unsplash
介绍
之前,我们从零开始构建了一个非常简单的神经网络用于图像分类。尽管如此,我们还是获得了 70%的准确率。
现在,我们将在不使用框架的情况下构建更深层次的神经网络。以下几段代码可扩展到任何神经网络架构。这意味着你可以使用不同数量的层和不同的激活和成本函数,只需对代码做最小的改动!
你可以在 Github 上抓取总结代码的两个笔记本。第一个笔记本构建必要的函数,第二个笔记本应用它们进行图像分类。
作为先决条件,我强烈推荐你阅读我的上一篇文章,因为它包含了关于构建神经网络的不同步骤的详细解释。
现在,让我们开始编码吧!
关于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
The feeling you will get when you are done building the neural network!
构建神经网络
步骤 1:初始化权重和偏差
像往常一样,构建神经网络的第一步是初始化权重矩阵和偏差矩阵。
请记住,权重必须是随机的非零值,而偏差可以初始化为 0。
对于这一步,函数非常简单:在神经网络的层数上循环,并为您的输入初始化每个权重和偏差。在代码中,应该是这样的:
步骤 2:正向传播模块
现在,我们将构建正向传播模块。在前向传播中,我们需要将加权和提供给激活函数。
该模块将分三步构建:
- 为加权和写一个函数
- 编写一个函数,将加权和提供给激活函数
- 编写一个函数,在最后一层使用 sigmoid 函数,在所有前面的层使用 ReLU
可选阅读:什么是 ReLU?
ReLu 代表RectivedLlinearUnit,表示为:

ReLU function
看起来是这样的:

ReLU plot
如你所见,正值的导数是 1,负值的导数是 0。请注意,函数在 0 处不可微。
实际上,激活函数通常是正的,这意味着导数将大于 0。因此,参数将更新得更快,并且网络最终通过 ReLU 学习得更快。
通常,如果您不确定使用什么激活函数,ReLU 是一个很好的默认函数,在大多数情况下都能很好地工作。
因此,对于加权和,函数很简单:
够简单!现在,我们构建一个函数来将结果提供给激活函数(ReLU 或 sigmoid):
现在,我们想在最后一层使用 sigmoid 函数,并依赖于所有先前的层。这是特定于该应用的,因为我们将执行二值图像分类,所以在最后一层使用 sigmoid 函数是有意义的。
太好了!
步骤 3:定义成本函数
当然,我们现在需要定义一个成本函数。然后,该函数将被最小化,并且它将驱动对权重和偏差矩阵的更新。
为此,我们使用交叉熵损失表示为:

Cross-entropy loss function
现在,我们用代码实现了一个矢量化版本:
成本函数到此为止!
第四步:反向传播
与正向传播类似,我们将分三步构建反向传播模块:
- 计算重量和偏差的导数
- 计算激活函数的导数
- 对整个网络执行反向传播
首先,我们为权重和偏差的导数写一个函数:
然后,我们找到激活函数的导数:
最后,我们编写一个函数在整个网络上执行反向传播:
现在这已经完成了,我们需要更新我们的参数!
步骤 5:用梯度下降更新参数
现在,我们简单地定义梯度下降来更新我们的参数,以便最小化交叉熵成本函数:
完美!我们现在准备在一个用于图像分类的神经网络中使用上述所有功能!
使用神经网络
随着所有助手功能的建立,我们现在可以在深度神经网络中使用它们来识别它是否是一张猫图片,并看看我们是否可以在我们的以前的模型上进行改进。
查阅笔记本导入合适的库并预处理数据。
在这种情况下,我们将训练一个 5 层网络。我们定义每个维度的维度,并按如下方式训练模型:
训练此模型需要几分钟时间。如果一切都做对了,你应该看到我们达到了 80%的测试准确率!这比我们以前的型号好多了!
当然,您可以随意调整模型的参数和结构。上面代码的优点是完全灵活。你可以添加任意多的层,改变迭代次数,提高学习速度等等。
恭喜你构建了一个没有任何框架的深度神经网络!你现在已经有了深度学习的坚实基础,你甚至可以将上面的代码重用到任何神经网络结构中。
在接下来的文章中,我将教授不同的方法来改善你的神经网络,并取得更好的效果。
干杯!
如何在 NumPy 中构建 DIY 深度学习框架

通过从头开始构建神经网络来理解神经网络的细节
作为学习的一般经验法则,只有当你能够自己构建时,你才会详细地理解一些东西。对于机器学习和神经网络等技术学科来说尤其如此。在您第一次接触深度学习时,您可以通过学习和掌握 TensorFlow 或 PyTorch 等高级框架来迈出几大步。然而,如果你想真正深入,你需要回到起点:你需要从头开始建立自己的神经网络和优化器!对于深度学习工程师和研究人员来说,这是一个常见的成人礼。掌握这些算法的细节会给你在这个领域带来非常有价值的优势。
当我最近开始这段旅程时,成功对我来说是一个提升的时刻。在这篇文章中,我们将一起走过这条道路,最终实现一个全功能的神经网络。如果你熟悉高水平的主题,并且知道什么是梯度下降,你就可以开始了!(如果你不熟悉梯度下降,看看这个帖子!)
然而一个重要的注意事项。与其马上阅读这篇文章,我鼓励你将这篇文章加入书签,然后尝试完全依靠自己建立一个神经网络。在我作为一名开发人员和科学家的生活中,很少有时刻像看着我的第一个神经网络学习一样有成就感和智力满足感。
这篇文章的代码可以在我的 GitHub 知识库https://GitHub . com/cosmic-cortex/neural-networks-from-scratch中找到。(在这里,我稍微超出了这篇文章的范围:实现了额外的层,如批量规范化和卷积层。)
究竟什么是神经网络?
在高层次上,神经网络只是一个函数,将输入(例如图像)映射到预测(例如可能标签上的概率分布)。从根本上说,有两个简单的操作你想做的函数:计算输出和导数,给定一个输入。第一个是需要获得预测,后一个是训练你的网络梯度下降。在神经网络术语中,计算输出被称为正向传递,而相对于输入的梯度被称为局部梯度。
对 Python 建模非常简单。
在local_grad()方法中,我们将返回一个渐变字典,而不是渐变的 NumPy 数组。当我们实现神经网络的层时,这样做的原因就变得很明显了。由于层有可调参数,这些参数将有自己的梯度。因此,区别对待变量组的梯度是有用的。
举个简单的例子,我们来考虑一下著名的 Sigmoid 函数!
注意,这个函数也适用于 NumPy 数组输入。目前,你可以认为这是一个单一变量的函数。然而,在后面,我们将把多元函数看作是带有张量输入的单变量函数。这一抽象层对于为神经网络编写紧凑的构件是必不可少的。
将乐趣分层
本质上,神经网络只是函数的重复应用,其中每个函数可以被认为是一层。对于复合函数来说,计算正向传递很简单。然而,如果我们要计算梯度,函数组合会使事情变得复杂,这对我们的目的是必不可少的。为了看看会发生什么,让我们考虑一个简单的例子!假设 N(x) 函数代表我们的神经网络,由一个线性函数与 Sigmoid 的组合定义。

A very simple “neural network”.
为了简单起见,我们还没有任何权重。为了计算它的导数,我们可以使用链式法则:

Derivative of N(x)
总结一下,我们需要三样东西来计算这个。
- Sigmoid 的导函数。
- f 的导函数。
- 在 x 处 f 的输出。
让我们从实用和计算的角度来思考这个问题。我们总是可以手动计算 N(x) 的导数,并将其硬编码到我们的程序中:

Derivative of N(x), expanded
然而,这不是一个好主意。首先,我们想要比这更复杂的功能,可能由数百层组成。计算数百个函数组合的导数实际上是不可能的。第二,我们希望我们的代码是模块化的,所以我们不是为我们的网络定义一个单一的功能,而是将它定义为功能的组合。
正因为如此,我们最好采用链式法则。然而,如果你注意到,计算导数本身也依赖于计算 f(x) 的值,所以我们不能简单地计算导数函数。为了确保一切正常,我们可以基于我们的Function实现下面的算法。(注意函数后面的撇,它表示它的导数。有时候很难看到,所以我提前强调一下。)
- 乘 x 。传递给代表 f 的
Function对象,计算 f(x) 和局部导数 f'(x) 。将两个结果都存储在缓存中。返回 f(x) 。 - 取 f(x)。传递给代表 Sigmoid 的对象,计算 Sigmoid(f(x)) 和局部导数 Sigmoid'(f(x))。将两个结果存储在缓存中。返回 Sigmoid(f(x)) 。
- 取乙状结肠'(f(x)) 。并返回 Sigmoid'(f(x)) 。(是的,我知道,这不是有史以来最复杂的步骤,但为了算法正确,这必须完成。)
- 将其传递给代表 f 的对象,从缓存中检索局部导数f’(x),最后与Sigmoid’(f(x))相乘。退回产品。
如果您再看一看,您可以看到步骤 1。第二。对于 f 和s 形的正向传递+局部梯度计算+缓存是否链接在一起。步骤三。第四。都是新东西:它们被称为倒传球代替乙状结肠和 f 。向后传递的返回值是梯度。请注意,这不仅仅是特定图层的局部渐变,而是该图层及其后所有图层的全局渐变。在技术文献中,它通常不会明确地与局部渐变区分开(因为它们都是渐变),但我喜欢通过使用全局和局部前缀来强调区别。
为了在我们的Function中反映这些方法,我们向它添加了缓存和向后方法。值得注意的是,当对象被调用时(即使用Function.__call__ 方法),局部渐变被自动缓存。
有了这个新模型,我们可以将 Sigmoid 函数定义如下。
这不仅是可组合的,而且我们也有方法计算组合函数的梯度。我们正在使用的这个算法叫做自动微分。这是现代深度学习框架的核心。没有它,梯度下降在计算上将是不可行的。
请注意,缓存起着非常重要的作用。例如,我们在向前传递过程中保存输入供以后使用,以节省梯度计算的时间。考虑这一点:如果特定的全连接线性层是神经网络中的第 109 层,则其输入是前 108 个函数的合成的输出。我们真的不想每次都重新计算,因为这会导致巨大的计算成本。
引入可调参数
在前面的例子中,我们只看到了某种意义上的静态函数,比如 Sigmoid。为了使模型适合训练数据,我们需要一组参数来调整。一个参数化的可微函数就是我们所说的层。理论上,可调参数(称为权重)可以被认为是另一组输入。然而实际上,分开处理这些参数更容易,因为
- 我们不会直接指定它们的值,而是存储一组当前值,
- 我们需要在每次反向传递后修改这些方法来执行梯度下降。
为此,我们通过使用权重初始化和权重更新方法扩展Function来创建Layer类:
例如,一个简单的全连接线性层表示具有参数 W 和 b 的 f(X) = Wx + b 函数,可以如下实现。
你可能会注意到,虽然这个函数从in_dim 维空间映射到out_dim维空间,但是向前传递只有一个变量。这是因为我们的代码是矢量化的:我们使用线性代数运算来压缩代码,而不是对每个维度的不同变量进行操作。一般来说,矢量化代码的执行速度也更快,因此这是机器学习武器库中一个不可或缺的技巧。
除此之外,我们的线性层还批量接受输入。也就是说,如果你在 d- 维空间中有 n 个数据点,你传递一个 n x d 矩阵,而不是调用函数 n 次。使用批处理弄清楚向前和向后传递的正确实现可能需要一些脑力劳动,但是我也建议你自己至少一次详细地解决这个问题。当然如果你卡住了,你可以随时查阅上面的代码!
损失函数
在神经网络的构件中,损失函数起着某种特殊的作用。损失函数不是只将前一层的输出作为输入,而是还将地面实况作为输入,输出反映函数拟合训练数据的能力的单个数字。损失越小,拟合越好。在任何情况下,它们都只是没有可调参数的可微函数。
实际上,这意味着两个重要的区别。
- 正向传递需要两个参数:最终层的输出和地面实况。
- 由于是最后一层,全局渐变等于局部渐变。
例如,一个常用的损失函数是交叉熵损失,它可以实现如下。
构成图层
到目前为止,我们只创建了神经网络的构建模块,而不是实际的网络本身。为了能够舒适地使用这样一个 DIY 深度学习框架,我们希望有一个这样的界面。
我们已经完成了大部分工作,所以Net只是一个简单的容器,将图层和损耗组合在一起。这个对象只是在层列表中循环,将每一层的输出传递给下一层。
测试我们的框架
现在我们已经构建了必要的工具,是时候将它们投入工作了!我们将使用具有 ReLU 激活的简单 2 层全连接神经网络来分类二维平面中的点。
完整的例子可以在这里找到,你可以在你自己的电脑上本地运行并试验它,这是非常鼓励的。我建议设置一个随机种子(以保持权重初始化的确定性),并尝试学习率参数。
超越完全连接的层
当然,这个简单的架构只是冰山一角。还有更复杂的架构可用,例如用于计算机视觉的卷积网络、用于序列学习的递归网络等。
在附带的代码中,您可以找到卷积层和池层的实现,以及一个 2d 批处理规范化层,您可以使用它来研究和试验某些组件。
在我的探索过程中,斯坦福大学著名的 CS231n:用于视觉识别的卷积神经网络课程对我帮助很大,所以如果你决定开始这段旅程并从头实现一个卷积网络,我可以向你推荐这个。
玩得开心,不断学习!
如果你喜欢把机器学习概念拆开,理解是什么让它们运转,我们有很多共同点。看看我的博客,我经常在那里发表这样的技术文章!
如何建立一个人脸检测和识别系统
基于计算机视觉和深度神经网络的解决方案

将机器学习技术应用于生物安全解决方案是新兴的人工智能趋势之一。今天,我想分享一些关于如何使用 OpenCV 库、DLib 和通过摄像机的实时流来开发基于人脸识别的生物识别系统的想法。
为了让系统正常运行,有必要实施三个步骤。首先,它必须检测到一张脸。然后,它必须几乎立即认出那张脸。最后,它必须采取任何需要的进一步行动,比如允许被批准的用户访问。
我在视频中的队友大致解释了这个想法,下面你可以阅读更详细的描述。
人脸检测和识别过程
面部识别过程从安装在与所述相机通信的任何兼容设备上的相机应用开始。该应用程序是用 Golang 编写的,可以作为本地控制台应用程序与 Raspbian 和 Ubuntu 一起使用。当应用程序第一次启动时,需要使用 JSON 配置文件配置本地摄像机 ID 和摄像机读取器类型。
然后,该应用程序能够使用计算机视觉和深度神经网络,以便在其流中找到预期的人脸。有两种主要的有效方法来做到这一点:第一种是 TensorFlow 对象检测模型,第二种是 Caffe 人脸跟踪。这两种方法都运行良好,并且是 OpenCV 库的一部分。

一旦捕捉到人脸,裁剪后的图像将通过 HTTP 表单数据请求转发到后端。然后,这个面部图像由 API 保存在本地文件系统和检测日志中,并附加一个 personID。
在后端,一种算法识别“classified=false”的记录,并使用 Dlib 函数生成 128 维向量,详细描述这张脸的属性。然后,该算法使用欧几里德距离将该向量与数据库中的所有面部条目进行交叉引用,以发现该新面部是否与记录中的任何面部相匹配。

下图是 Dlib 函数的代码表示,索引点对应于面部的各个部分。

在计算欧几里德距离之后,该算法将为未知类型的人生成新的 personID(如果距离大于 0.6),或者将面部标记为已分类并匹配 personID(如果距离小于 0.6)。
当一张脸被发现身份不明时,这张图像可以通过信使程序中的聊天机器人或其他方式与通知一起转发给经理或主管。经理或主管将会看到一系列关于如何处理这种情况的选项。

实现一个简单的聊天机器人警报系统需要大约两到五天的时间,可以使用像 Errbot (基于 Python)或微软的机器人框架这样的工具来创建。
面部记录可通过管理面板进行事后管理。这个空间将包含所有记录的图像及其 ID 号的链接。有可能创建一个所有相关员工面部图像的数据库,可以在系统上线前将其放入数据库。
一个潜在的问题是伸缩性。在我们的例子中,数据库中有大约 200 个条目,因此系统可以无缝地处理和立即识别人脸。当数据库膨胀到成千上万的条目时,或者如果需要多个摄像头时,事情变得更加复杂。如果不采取对策,处理速度将会减慢。
幸运的是,并行化提供了一个解决方案。可以创建一个负载平衡器和多个能够同时工作的 Web workers。这允许数据库被分成子部分,从而产生显著更快的搜索结果。
以下是对该面部识别解决方案所实施的技术和整体结构的总结。

解决方案中的 API 请求使用 RESTful API,后端员工数据收集使用 MongoDB 集合和 Golang。可以使用常规的工作站设置来测试解决方案。
值得注意的是,支持安全措施可以并且可能应该增强面部识别。面部图像比视网膜扫描或指纹更容易获得。如果安全需要足够重要,采取额外的面部反欺骗措施确保没有人能够用面部照片或图像击败面部识别系统。
你可以在我之前的文章 中了解更多人脸识别解决方案的反欺骗技术 。
这个解决方案以及其他类似的解决方案可以处理大量的数据。假设企业能够协调清晰的业务需求,数据科学公司将能够提供业务洞察力。人脸识别软件开发正在兴起,并将决定人工智能应用的未来。
人脸识别只是实现这种方法的开始。人脸只是要检测的对象之一。其他物体也可以用同样的方式识别。例如,如果使用对象在数据集上创建和训练了 DS 模型,那么它可以是车辆、家具、花卉、动物。
此外,还可以开发多模式生物识别系统,将两种或两种以上的生物识别凭证结合起来,例如,面部和声音识别,或基于 OCR 的身份识别。
想知道如何推出具有 DS/ML 特性的软件产品吗?阅读我最近的文章数据科学咨询:从想法到部署。
如何在 Node.js 中不用 TensorFlow 建立一个 k-NN

Points connected to each other, Image from Pixabay
k-NN 是一个简单直观的基于实例的学习器,当训练数据很大时,它工作得很好。因为模型必须记住训练数据中的所有点,所以它也消耗了相当多的内存。为了在 Node.js 中构建 k-NN,人们首先会想到 TensorFlow.js ,这是一个流行的机器学习框架,在 JavaScript 中提供 API。
但是,如果你是一个有经验的研究人员,想稍微改变一下模型,看看是否有改进的余地,那该怎么办呢?然后,您将需要进入另一个级别来更改核心架构。如果你是一个初学者,能够从头开始编写模型肯定会提高你的理解能力。
让我们开始吧!
万一你还没有,你得先安装 Node.js 。Node.js 是一种基于 JavaScript 的服务器端语言,相对容易学习。为了以最佳效率构建 k-NN,您将需要一个 k-d 树。k-d 树允许用分治法在 k 维空间中搜索点。对于设计涉及 k-means 或 LBS 服务等多维数据的系统确实很有用。更多关于 k-d 树的信息可以在这里找到。

Visualization of a k-d Tree
我们可以从 这里 下载整个 GitHub 存储库到我们的项目文件夹,为了导入它,我们使用了下面的 JavaScript 代码。
const kdtree = require('./kd-tree-javascript/kdTree');
现在为了测试 k-d 树是否有效,我们可以使用下面的代码:
const kdtree = require('./kd-tree-javascript/kdTree');
var points = [
{x: 1, y: 2},
{x: 3, y: 4},
{x: 5, y: 6},
{x: 7, y: 8}
];
var distance = function(a, b){
return Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2);
}
var tree = new kdtree.kdTree(points, distance, ["x", "y"]);
var nearest = tree.nearest({ x: 5, y: 5 }, 2);
console.log(nearest);
代码应该打印以下对象:
[ [ { x: 3, y: 4 }, 5 ], [ { x: 5, y: 6 }, 1 ] ]
我们可以使用下面的代码来构建我们的 k-d 树,其中 x 和 y 是 2 个特征, train 是训练数据。在距离方程中,要素除以其最大值。这样,计算出的欧几里德距离就不会太偏向于任何一个特征。还有许多其他有趣的方法来计算距离。
const kdtree = require('./kd-tree-javascript/kdTree');
var distance = function(a, b){
return Math.pow((a.x - b.x)/Xmax, 2) + Math.pow((a.y - b.y)/Ymax, 2);
}
var tree = new kdtree.kdTree(train, distance, ["x", "y"]);
var k = 5;
训练数据是对象的数组,其中每个对象至少包含 k-d 树内的两个特征。下面是一个如何在 for 循环中构造对象的例子。
var newObject = {
label: newLabel,
x: newX,
y: newY
}
data.push(newObject)
为了拆分训练数据,我们还可以使用以下代码混洗数据,在本例中,80%的数据被混洗到训练数据中。

Diagram illustrating how the data is processed
var shuffledData = shuffle(data);
var train = shuffledData.slice(0, Math.floor(shuffledData.length * 0.8));
var test = shuffledData.slice(Math.floor(shuffledData.length * 0.8) + 1, shuffledData.length);
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element...
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
最后,我们可以使用下面的代码来运行我们的模型。
var total = 0;
var correct = 0;
while(test[total] != null)
{
var nearest = tree.nearest(test[total], k);
var label = test[total].label;
var classa = 0;
// Count k nearest points that is labeled as "Class A"
for(i = 0; i < k; i++)
{
if(nearest[i][0].label == "Class A")
{
classa++;
}
}
// Validate if the actual label matches the majority
if(classa > k - classa && test[total].label == "Class A")
{
correct++;
}
else if(classa < k - classa && test[total].label == "Class B")
{
correct++
}
else if(classa == k - classa)
{
// In the case of a tie, evaluate randomly 50%/50%
if(Math.random() > 0.5 && test[total].label == "Class A")
{
correct++;
}
else if(test[total].label == "Class B")
{
correct++;
}
}
total++;
}
console.log("k-NN accuracy: " + correct/total);
该代码主要针对测试集运行 k-NN 算法,并对成功分类的实例进行计数。如果该实例周围的 k 个点的大多数被标记为该类,则该实例被分类为该类之一。在出现平局的情况下,算法会将其随机放入其中一个类中。

k-NN Illustrated, Image from Medium
恭喜你!您刚刚学习了如何从零开始构建 k-NN!现在由您来深入研究这个模型!
最后…
我对许多事情都充满热情,数据科学就是其中之一。在 Unity 机器学习框架准备好之前,我还从头开始构建了一个 BPANN。我当时唯一能找到的人工神经网络是用遗传算法来训练的。我没有把它写成一篇文章,但是我可以根据要求来写。
我喜欢学习新的东西,并与社区分享,如果有你特别感兴趣的主题,请让我知道,我可能会写它。我目前正在写一篇长文,详细解释 AlphaGo 是如何工作的,我需要一些时间来完成。
敬请关注,享受数据科学的乐趣!
如何在数据科学领域建立有意义的职业生涯
你可以善用数据科学的力量,改变世界。

需要一些灵感来引导您的数据科学职业朝着最有影响力的方向发展吗?
数据科学家的角色通常被称为 21 世纪最性感的工作。也许你被这个职业吸引是因为你热爱数学、编程和一切技术。但我敢打赌,你们中的许多人也对使用数据产生真正的影响感兴趣。
在调整数据和建立机器学习模型的漫长一天结束时,你会想说,“今天我创造了一些将积极影响某人生活的东西。”换句话说,你希望看到你的工作在现实世界中展开。
在 Omdena ,我们提供了一个协作学习环境,初级人才和经验丰富的导师可以在这里一起应对现实世界的人工智能挑战。我们的使命是将理论教育与实践联系起来,使世界各地的个人能够应对人类面临的一些最大挑战。
这里有三个鼓舞人心的故事,来自我们的创伤后应激障碍挑战
Albert、Kulsoom 和 Anam 都获得了两个月免费参加所有 DataCamp 课程的机会,这是因为他们出色的表现和社区精神。在我们的 PTSD 人工智能挑战赛中,他们与 32 名人工智能爱好者合作了两个月,构建了一个智能聊天机器人,帮助在低资源环境中面临可怕情况的个人诊断 PTSD,例如在战争和难民区。
艾伯特

17 岁的阿尔伯特是我们最年轻的合作者,但他对数据的热情和渴望激励了我们人工智能挑战中的其他 32 名合作者。用他自己的话说,这是他对这次经历的看法。
你对数据科学中有意义的职业的定义是什么?
我对有意义的 DS 职业生涯的定义是用一个人的知识和技能让世界变得更好。数据科学是一个极其强大的工具,善用它非常重要。像任何东西一样,它可以被用于善意或恶意的目的。
利用 DS 来解决诸如应对气候变化、提高农业产量和检测深度造假等问题,才是真正有意义的影响。
在你加入我们的挑战之前,你是如何看待学习 AI 的?
在加入 Omdena PTSD 挑战赛之前,学习 AI 感觉就是上一堆课,看视频,看论文,编程模型。一旦挑战开始,我意识到我错过了一个重要的方面:社区。加入数据科学从业者社区对于获得帮助、被激励以及学习团队合作和协作的技能非常重要!
你在这次挑战中学到的最重要的技能是什么,你将应用它来建立你未来的职业生涯?
这个挑战真的教会了我如何在团队中好好工作。在过去,我主要是单独从事我的机器学习项目。在这次 PTSD 挑战中,能够与世界各地的队友合作对于协调不同的任务至关重要。我可以把这段经历带到我未来的职业生涯中。
库尔苏姆

库尔苏姆·阿卜杜拉在 2011 年世界锦标赛上成为第一位代表巴基斯坦参赛的女子举重运动员。
你在举重生涯中学到的最重要的经验是什么,可以应用到生活中?
我想说我得到的教训是,我低估了自己的能力。很可能我们都低估了自己的能力。
作为人工智能中的一名女性,你必须克服的最大挑战是什么?
冒名顶替综合症——感觉自己很失败,觉得自己不配获得成功!
在大学里,我不得不学习并意识到这不是我的错,而是我的环境造成的。我还识别并处理了微侵犯和明目张胆的行为。我通过寻找积极的空间,如信任的家人、朋友、导师,以及照顾好自己来克服它。通过冒险,拥抱我的恐惧,“假装直到你成功”。
“我没有什么可失去的”帮助我向媒体介绍了我的举重比赛挑战和学术/工作情况。
这仍然是一项正在进行的工作。我希望我能继续进步,并帮助别人不处理我不得不做的事情。
如果你可以在广告牌上写一句话给正在挣扎的人,你会给他们什么建议?
恐惧和怀疑都是暂时的,继续走下去,享受旅程就好。
阿南

当 Anam 加入我们的 PTSD 人工智能挑战赛时,她几乎没有人工智能经验,但有着长期与 PTSD 斗争的个人历史。她加入了我们的 AI 挑战赛,并晋升为初级机器学习工程师。
是什么让你加入了 Omdena 的 PTSD AI 挑战赛?
亲身体验 PTSD 的生活对我来说是一个完美的挑战。成为它的一部分比一个人自己的收获更大,比如学习 ML 或增加他们在 it 方面的经验。这意味着帮助那些因创伤后应激障碍而在生活中面临许多障碍的人们。如果这意味着我能在如此大的事业中扮演哪怕是一个小角色,我已经准备好成为这个挑战的一部分。
你在这次挑战中学到了什么,你将应用于建立你未来的职业生涯?
通常,作为一所大学的学生,我们会收到一些有明确答案和固定范围的问题。和 Omdena 一起应对这个挑战是完全不同的。它帮助我理解了如何利用我们的知识来解决现实世界的问题并有所作为。这也让我明白,与我们习惯的方法相比,如此大规模和真正影响的问题需要一种不同的方法。一次奇妙的经历!
想成为 Omdena 的合作者,加入我们的一个 AI 来迎接好的挑战吗?在此申请。
如何在 SageMaker 上建立模型

Photo by Samuel Zeller on Unsplash
数据科学项目往往以报告的准确性和圆滑的情节而告终。在这篇文章中,我们将探讨下一步:如何创建一个可以部署的模型。
为此,我们将使用 Amazon SageMaker 并分解从实验到生产就绪的步骤。我们将遵循高层次的方法,这意味着 AWS 将为我们挑选一些参数。
在继续之前,确保你有一个 AWS 账户和一个 Jupyter 笔记本的访问权限。
设置笔记本实例

Photo by ASHLEY EDWARDS on Unsplash
第一步是登录亚马逊控制台,寻找 SageMaker,以防它不可见。

接下来,我们点击创建笔记本实例。

我们给笔记本命名,运行它的价格由实例类型决定。这里我们使用 ml.t2.medium ,但是建议查看定价页面以获得最佳选择。对于这种应用,我们可以保持弹性推断为无。

我们要设置角色,它是一种安全证书,决定权限,比如笔记本可以访问哪些资源。我们点击它并选择创建一个新角色

由于没有我们希望笔记本访问的额外存储桶,我们选择 None 并点击 create role。这里最重要的条件是第二行。

最后,我们单击页面最底部的“板条箱笔记本实例”。过一会儿,你的笔记本的状态应该会显示在使用中。一旦发生这种情况,AWS 将向我们收取使用该实例的费用,所以请确保在不使用时将其关闭。

克隆部署笔记本
从上图中点击打开 Jupyter 进入熟悉的设置。

在右上角点击新建并打开一个终端并改变目录。然后我们克隆这个包含笔记本和的 git 仓库,并在完成后关闭它。
回到主页选项卡,我们看到添加了一个 sagemaker 目录。我们导航到笔记本在 sagemaker_ml 文件夹中的位置。

下载数据
对于一般的数据科学家,特别是 NLP 实践者来说, IMDB 数据集就像是一个成年礼。我们将通过 XGBoost 使用这些数据来预测用户情绪。
第一步是下载数据。我们可以在笔记本中使用命令行代码:
GNU 文档为上面的命令提供了充足的资源。
准备数据
这里我们不会详细讨论这个问题,只提供一个简要的概述。不过,您可以在笔记本中查看整个过程。
这是一个 NLP 练习,所以我们需要将原始信息处理成数据和相应的标签。然后,我们剥离所有 html 标签的文本,用 NLTK 执行词干提取,并提取一个单词包。
在这个过程的最后,我们应该准备好我们的测试和训练数据。
用 XGBoost 分类
XGBoost clasifier 要求将数据集更好地写入文件,并使用亚马逊 S3 存储。我们进一步将训练数据集分为两部分:训练和验证。
我们将把这些数据集写入一个文件,并将文件上传到 S3。此外,我们将做同样的测试集输入上传到 S3。这样,一旦拟合完成,我们就可以使用 SageMaker 的批量转换功能来测试模型。
SageMaker 中 XGBoost 算法的文档要求保存的数据集不应包含标题或索引,对于训练和验证数据,标签应首先出现在每个样本中。
此时,节省可用内存是一个好的做法,我们可以将 text_X、train_X、val_X、train_y 和 val_y 设置为 None :
将培训验证文件上传至 S3
对于这一部分,我们将大量参考 SageMaker API 文档和 SageMaker 开发者指南。
upload_data 方法将本地文件或目录上传到 S3。它是代表我们当前 SageMaker 会话的对象的成员。这个方法将数据上传到 AWS 为我们创建的默认 bucket,如果它还不存在的话,上传到由变量 key_prefix 描述的路径中。如果我们导航到 S3 控制台,我们应该在那里找到我们的文件。
创建 XGBoost 模型
我们认为 SageMaker 上的模型由三部分组成:
- 模型工件
- 培训代码(集装箱)
- 推理代码(容器)
模型工件是实际的模型本身。在这种情况下,工件是在训练期间创建的树。
训练代码和推理代码用于操作训练工件。训练代码使用提供的训练数据和创建的模型工件,推理代码使用模型工件对新数据进行预测。
SageMaker 通过使用 docker 容器来运行训练和推理代码,这是一种打包代码并确保依赖关系不会成为问题的方法。
拟合 XGBoost
通过访问 S3 输入来拟合模型。
使用 SageMaker 拟合模型时,过程如下。
- 一个计算实例(某处的服务器)使用我们指定的属性启动。
- 当计算实例准备就绪时,用于适应模型的容器形式的代码被加载和执行。
- 当这个代码被执行时,它被提供对存储在 S3 上的训练(以及可能的验证)数据的访问。
- 一旦计算实例完成了对模型的拟合,生成的模型工件就被存储在 S3 上,并且计算实例被关闭。
试验
我们使用批量转换以非实时的方式对大型数据集进行推理。这让我们可以看到我们的模型执行得有多好。
这样做的好处是,我们不需要立即使用模型的结果,而是可以对大量样本进行推断。这种方法也很有用,因为我们可以对整个测试集进行推理。
要执行转换作业,我们需要指定要发送的数据类型,以便在后台正确序列化。这里我们为模型提供 csv 数据,因此我们指定文本/csv 。
此外,如果数据太大,无法一次性处理,那么我们需要指定数据文件应该如何分割。同样,这是一个 csv 文件,因此每一行是一个单独的条目,我们告诉 SageMaker 在每一行拆分输入。
使用上面的代码,转换在后台运行。我们调用 wait 方法等待转换工作完成并接收一些反馈。
转换作业被执行,并且每个评论的估计情绪被保存在 S3 上。我们想在本地处理这个文件,并将它复制到数据目录 data_dir 。
一种方便的方法是在 jupyter 中找到 AWS CLI 命令参考。
最后,我们可以从模型中读取输出。
我们需要将输出转换成对我们的目的更有用的东西。我们将情绪转换为正的1和负的0。最后我们可以打印出准确率: 86% ,还不错!
清除

Photo by Paweł Czerwiński on Unsplash
当我们对越来越大的数据执行操作时,跟踪我们使用了多少内存变得至关重要。我们可能会在执行操作时耗尽内存和/或产生昂贵的费用。
SageMaker 上的默认 notebook 实例可能没有太多多余的磁盘空间。当我们重复类似的练习时,我们最终可能会填满分配的磁盘空间,导致难以诊断的错误。
一旦我们完成了一个 notebok,删除我们在这个过程中创建的文件是一个很好的做法。我们可以从终端或笔记本电脑中心完成这项工作。
完成后,请务必返回 SageMaker 笔记本实例并停止该实例。
总结和后续步骤
在这篇文章中,我们看到了如何在 AWS SageMaker 上创建一个可以部署的模型。工作流程应该与典型的机器学习练习相同,只是增加了一些额外的步骤。
主要的收获是关注数据存储的位置和方式,代表我们做出的决策,以及如何防止内存溢出。
恭喜你!我们现在已经有了一个可以部署的情感分析模型!
如何构建非地理地图#2
或者如何将散点图变成交互式地图(使用传单和 JavaScript)

This guy’s body may seem odd and his chair disproportionate, but aren’t maps a distortion of reality, anyway? 😃
地图是数据可视化的强大设计对象。他们强调元素之间的空间关系和变量的比较。在非地理数据的背景下,web 地图可以增强传统的散点图。
#第 2 部分:从散点图到交互式地图
数据可视化的核心是通信。将吓人的桌子变成引人入胜的故事的能力。通常,最终目标是推动解决问题或决策的洞察力。在大多数情况下,用户不会玩弄数据,而是采取被动的态度。但是,如果你想授权给你的观众,激发他们的好奇心,并允许他们探索数据呢?
我们用地图来探索未知。他们给了我们走出人迹罕至的道路的信心。我们偏离了最初的路线,在一家咖啡馆停下来,或者绕道经过一个博物馆。这也是我们使用网络的方式。我们进行搜索,一个链接指向另一个,最终我们对一些我们点击几下之前甚至不知道存在的东西产生了兴趣。
我们能以同样偶然的方式传递数据吗?
在本系列的第一部分中,我们使用了降维技术来绘制 2D 空间中的相似性。我们最终得到了一个新的坐标系统,使我们能够在散点图中可视化我们的数据(见图(Plotly) )。
在本文中,我们将把它转换成一个交互式地图,包括一个搜索栏和一个侧面板。我们将使用传单和一些额外的 JavaScript。
无论数据类型如何,本文可能对任何想要构建 web 地图的人都有用。如果是这种情况,请跳到第 2 步。

第一步。建立一个坐标的 JSON
如果您遵循非地理数据映射的,您现在有一个嵌入——一个(非常非常长的)Numpy 坐标数组,代表您在 2D 的数据。
为了在传单地图上绘制所有这些数据点,我们需要将它们存储到一个 JavaScript 对象中。
为此,我们可以将 DataFrame 转换成 JSON 字符串,并用 JavaScript 处理它。
如果您只有几个数据点要绘制,那么您可能想跳过这一步,手动将它们存储在您的 JavaScript 中。
另外,请记住,每个用户每次打开页面时都会“加载”整个 JSON。这会影响你网站的表现。根据您拥有的数据量和流量,您可能更喜欢从数据库中动态加载内容。
1/创建一个数据帧
在本例中,我将使用:
- 基于技能和知识相似性的职业映射产生的嵌入和
- ONET 开放数据库。
我们的 JSON 必须包含每个标记的坐标和一些数据,比如它的标题和描述,我们将用它们来更新面板的内容。
下面是我创建数据框所遵循的步骤的简要描述。你可以在这里找到完整笔记本(Github) :
- 从 ONET 加载了 Occupation Data.xlsx 文件后,我创建了两个系列。我使用 ONET SOC 代码作为他们的公共索引,使用职业头衔和描述作为他们各自的值。然后,我将它们组合成一个单一的数据帧。
- 最后,我创建了一个所有职业标题及其各自坐标数组的字典(基于 UMAP 嵌入),并将其映射到数据框的标题列。

This is what your DataFrame should look like.
2/转换成 JSON
- Pandas 有一个内置函数,可以将对象转换为 JSON 字符串:
yourdataframe.to_json('newfile.json', orient='index')

This is what the JSON looks like.
更多详情可以在这里找到完整笔记本(Github) 。
第二步。用传单创建地图

Leaflet.js is an open-source JavaScript library for responsive & interactive maps. It offers wonderful features and a beautiful default design.
创建这张地图需要 传单 , 自举 ,jQuery和jQuery-ui。确保在您的代码中包含指向它们的 CSS 和 JS 库的链接。
1/创建地图
在这篇文章中,我将只使用非常基本的传单设置,并侧重于面板与地图的交互性。然而,你可以用传单做很多令人惊奇的事情,值得一看。
下面是一个快速设置。或者,你可以遵循他们的快速入门指南。
- 在您的 HTML 中,创建一个空容器:
<div id="mapDemo"> </div> - 地图容器必须具有定义的高度。在这里,我将其设置为 100%的查看器屏幕:
#mapDemo {width: 100vw; height: 100vh;} - 在你的 JS 中,创建地图:
map = L.map('mapDemo');。因为我们在左边有一个面板,所以我们把缩放控件放在屏幕的右下角:map.zoomControl.setPosition('bottomright');
2/地块标记
数据存储在一个 JSON 文件中,其结构与 JavaScript 字典相同。请注意,我的 codePen 示例基于一个只有 3 个元素和 3 个特性(“标题”、“坐标”和“描述”)的 JavaScript 字典。
- 首先,将 JSON 文件存储在 JavaScript 字典
var markers = {}中:
var markers = $.getJSON("map_data.json");
- 然后,遍历字典,将每个标记的特征存储在
markerOptions下。用addTo(map)绘制它们:
$.each(markers, function(key, val) {
var markerOptions = {markerId: key,
markerTitle: val['title'],
markerText: val['description']}; var marker = L.marker(val['coords'], markerOptions).addTo(map);
});
- 要查看标记,请在数据坐标范围内设置地图视图:
var bounds = [[-10,-10], [10,10]];
map.fitBounds(bounds);
第三步。奠定基础
在处理交互性之前,让我们先把 HTML 和 CSS 放在一边。
1/ HTML

Main elements and their ids. >> See CodePen
- 在 HTML 的
<body>中,创建一个带有表单控件(#searchTerm)和按钮(#searchBtn)的输入组。 - 下面,添加一个按钮(
#panelBtn)。它将允许用户随时打开/关闭面板。 - 对于面板,添加一个带有关闭按钮(
#closeBtn)的<div>和将用标记数据更新的内容(如标题和段落)。
2/ CSS

This map is mobile first. I only included a media query for screens that are 500px wide and above, but you may want to refine that.
- 在你的 CSS 中,确保所有应该位于地图顶部的元素都有一个大于 400 的
z-index(400 是地图的z-index)。 - 默认情况下,
#panel是隐藏的,只有在.active时才显示。将left属性设置为与#panel元素宽度相同的大小以隐藏它,当#panel.active时切换为 0(显示它)。 - 对于面板高度,使用
top和bottom属性定义元素的开始和结束位置。请注意,如果您没有设置bottom,而是定义了一个height,滚动将不会像您预期的那样工作。#panel将继续位于可见屏幕的“外部”(尽管有overflow-y:scroll;)。 - 在移动和小屏幕上,面板和输入组占据整个宽度。所以,我设置了
width:100vw;,但是对于超过 500 像素宽的屏幕,我把它改成了width:500px;。
你可以在这里找到完整代码(codePen) 。
3/数据结构
我们必须向前跳一点,考虑我们需要访问哪些数据来显示正确的输出。

Overview of the events that require access to markers’ data. In blue are the functions and in turquoise their respective arguments.
字典
让我们将点击标记时调用的函数称为markerOnClick(),将进入搜索后调用的函数称为search()(通过点击建议的标记标题或点击搜索按钮)。
这些功能有许多共同的步骤。为了避免两次编写相同的代码,我们将这些步骤包含在updatePanel()函数中。
为了用附加到每个markerId的标题和文本更新面板,updatePanel()必须能够访问一些其他标记特征。同样,search()是markerTitle的一个函数,但是需要访问markerId来调用updatePanel()。
为了让函数能够访问这些特性,我们需要字典。

These are the key-value pairs that we need.
- 创建 3 个字典:
var titleToId = {}; var idToTitle = {}; var idToText = {}; - 然后,在遍历
markers{}字典时追加它们:
$.each(markers, function(key, val) {
...
titleToId[val['title']] = key;
idToTitle[key] = val['title'];
idToText[key] = val['description'];
...
});
目录

当用户输入一个搜索时,它调用autocomplete(),根据用户输入给出所有可能的标记标题。因此,此函数的数据源必须是标记标题列表:
- 创建您在标记循环中附加的标记标题
var titlesList =[];列表:
$.each(markers, function(key, val) {
...
titlesList.push(val['title']);
...
});
第四步。协调互动

Overview of the functions associated with panel interactivity.
1/点击标记

When a marker is clicked: the search bar is updated with the marker’s title, the “open panel” button changes to “close panel”, and the panel opens and displays some content attached to that marker.
- 定义
updatePanel():
*var updatePanel = function(mId){
$('#panel').addClass('active');
$("#panelBtn").text('< Close Panel');
var markerTitle = idToTitle[mId];
var markerText = idToText[mId];
$('#panelTitle').text(markerTitle);
$('#panelText').text(markerText);
};*
marker onclick()
- 并在
markerOnClik()内呼叫updatePanel():
*var markerOnClick = function(){
var mId = this.options.markerId;
var markerTitle = idToTitle[mId];
$('#searchTerm').val(markerTitle);
updatePanel(mId);
};*
- 在循环中,将 onClick 事件添加到所有标记中。设置弹出选项(popupContent)并将弹出绑定到标记单击:
*$.each(markers, function(key, val) {
...
marker.on('click', markerOnClick);
var popupContent = val['title'];
marker.bindPopup(popupContent);
...
});*
现在,当用户点击一个标记时,相应的弹出窗口就会打开。
2/搜索输入

When the user types in the search bar, the autocomplete suggests a few marker titles. From there, the user can either select one of those suggestions or confirm her search. Either way, the output is the same as when a user clicks on a marker (see 1/ Click on marker).
autocomplete()
- 这里,我们定义了 autocomplete()的选项。同样,当从自动完成中选择一个条目时,我们将其值存储在
#searchTerm中并调用search():
*$(function() {
$("#searchTerm").autocomplete({
source: titlesList,
minLength: 1,
select: function(event, ui) {
$("#searchTerm").val(ui.item.label);
console.log(ui.item.label);
search();
}
});
});*
搜索()
现在,如果用户点击一个建议的markerTitle,就会调用search()和updatePanel()。但是,如果没有实际点击标记,弹出窗口就不会显示。
一种解决方案是给每个标记附加不同的层。然后我们可以将 fleet 的 openPopup()方法应用于search()函数中的层。

LayerGroup is a method from the Layer class used to group several layers and handle them as one >> see documentation
- 创建一组图层
var layers = L.layerGroup().addTo(map);并在标记循环layers.addLayer(marker)中更新 - 每个标记都有一个层,但是我们需要一个字典来允许我们根据标记的
markerId:var idToLayer = {};检索标记的层:
*$.each(fgLayers._layers, function(key,val){
idToLayer[val.options.markerId] = key;
});*
- 我们终于可以定义
search()函数了。它从搜索字段中获取markerTitle,找到它对应的标记,打开它的弹出窗口并调用updatePanel():
*var search = function(){
$("#searchTerm").blur();
var markerTitle = $("#searchTerm").val();
var markerId = titleToId[markerTitle];
var layerId = idToLayer[markerId];
var layer = layers._layers[layerId];
layer.openPopup(); updatePanel(markerId);
}*
3/打开-关闭面板
在用户进行搜索或点击标记后,我们希望他们能够关闭面板并随时返回地图。我们还想让他们直接从地图上重新打开面板。

To close the panel, the user can either click the close button of the panel or click the “close panel” button on the map.
togglePanel()
#panelBtn按钮允许用户连续打开或关闭面板。它的内容应该根据它允许用户接下来做的动作(打开或关闭)而改变。我们可以通过使用 jQuery 的 toggleClass 方法来实现这一点。
- 给按钮添加一个 onClick 事件:
<button onClick = "togglePanel()";>并定义togglePanel():
*var togglePanel = function() {
$('#panel').toggleClass('active');
$("#panelBtn").text(($("#panelBtn").text() == 'Open Panel >') ? '< Close Panel' : 'Open Panel >');
}*
关闭面板()
#closeBtn按钮允许用户在面板打开时关闭面板,并更新#panelBtn内部 HTML。
- 给按钮添加一个 onClick 事件:
<button onClick = "closePanel()";>并定义closePanel():
*var closePanel = function() {
$('#panel').removeClass('active');
$('#panelBtn').text('Open Panel >');
}*
包裹
感谢您的阅读😃
在本系列中,我们介绍了如何使用降维来构建散点图,该散点图使用距离作为相似性的代理,并将其转换为交互式地图。
我在撰写这些文章和为它们配插图的过程中获得了很多乐趣,并在此过程中学到了很多东西。我希望你已经发现它是有用的,并且我期待在那里看见更多令人惊奇的地图。
🔗链接到#第 1 部分:如何通过降维映射相似性
👉看看我是如何在实践中使用它的:www.tailoredpath.com
如何建立支付数据团队

Paying with Apple Pay on a Square Device
在过去的几年里,我们看到支付行业的收购数量越来越多。从收购老牌全球公司的大型投资者,如旧金山合伙人- > Verifone ,到出于能力、地理扩张或整合目的的战略收购,如 ING - > PayVision 、 WorldFirst - > Wyre 或 Worldline - > SIX 。然而,那些似乎还没有被收购的公司,是那些将利用他们的数据作为关键战略目标的公司。在这篇博客中,我分享了支付(适用于其他金融科技公司和科技公司)如何建立数据团队并超越竞争对手。
必需品与奢侈品 平心而论,支付行业在过去十年中发生了巨大的变化,像所有的变化一样,这不是因为大型企业公司,而是因为精益创业公司进行创新,并找到新的方法将支付纳入他们的产品和流程。到目前为止,包括脸书、Spotify、优步和网飞在内的“创业公司”在定义十多年前还不存在的新的电子商务类别方面发挥了极其重要的作用。这些新企业带来的主要东西是它们的数据驱动的工作方式。
这些公司不再关注处理了多少收入,而是更加关注其整体平台的效率。从转换率到授权率。利用他们数据驱动的工作方式,他们影响了许多“新”支付公司,以提供尽可能多的数据。随着这些新公司正在取代一些老公司,新老支付公司都必须适应并不断提供数据。
建立支付数据团队 支付是一种技术产品,这意味着尤其是在建立网关或收购方的初期,开发团队说了算。如果我今天要建立一个新的支付公司,这不会有很大的不同。但是,请记住,在某一点上,业务用户会开始提问,因此最好从能够检索回答这些问题所需的数据和见解的基础架构开始。
1。雇用一名数据经理(数据主管、数据副总裁等)。),最好有支付方面的经验。 因为业务将不得不从发展重心转移到业务重心,你需要一个数据经理,他了解双方,知道如何与双方沟通,并能够组建一个团队来执行战略和愿景。一个数据管理者的开始阶段,是与管理和业务用户一起度过的。了解业务和管理层想要实现的目标,同时与业务用户进行对话,以了解他们需要什么来完成工作。收集了所有需求后,经理应该制定一个数据策略,该策略应该是业务发展的基础。
2。雇佣数据架构师很多时候,公司会走路之前就想跑。您雇用数据架构师的原因是,现有的基础架构是为业务的开发方面而构建的。很长一段时间以来,支付在其数据中非常结构化,但是由于电子商务、移动商务和物联网商务,越来越多的数据变得更加非结构化。这就是为什么如果您想要检索数据并获得洞察力,您需要构建单独的数据基础架构。数据架构师将能够审查当前的基础设施,利用现有的部分,并设计不干扰现有基础设施的基础设施,同时为数据团队提供支持组织所需的资源。
我经常被问到,为什么我不能让我的数据工程师来设计基础设施呢?对此,我回答说,如果你在建房子,你会先雇建筑师还是建筑商?架构师制定计划,考虑所有的利弊,利用他的经验(主要是作为一名数据工程师),来设计一个在短期内有效并可以长期构建的基础设施。
3。雇佣一名数据工程师 一名优秀的数据工程师,了解最新的云技术,至少精通 SQL 和 Python。大多数数据工程师更喜欢在 AWS 工作,因为这是最受技术驱动的平台,也是历史最长的平台。然而,随着更现代的云技术的增加,如用于 ETL'ing(提取、转换&加载)的Matillion&five tran和用于数据仓库即服务的 Snowflake 和 Google BigQuery ,许多基础设施变得不那么复杂,而是更关注速度、灵活性和快捷性。随着数据量、速度和种类的快速变化,知道如何找到适合工作的工具的数据工程师可以完成更多工作,并帮助您的团队获得正确的结果。
4。雇用数据分析师和/或 BI 分析师 经过一段时间的设计和构建后,下一个雇员应该是数据分析师,他最好有一些业务背景,但在使用数据库和查询检索数据方面要先进得多。使用 R 或 Python 等编程语言,进行比 Excel 更复杂的数据分析。您希望数据分析师至少具备一些编程技能的另一个原因是,在大多数情况下,数据在成为可供数据分析师或业务用户分析的数据类型之前,可能需要进行一些清理和转换。
随着该团队的能力不断提高,类似查询请求的数量也在增加,数据分析师将成为将其查询转换为仪表板的关键,仪表板可以分布在整个组织中。通过将业务语言转化为建模层,并使用 Looker 等数据平台,数据团队的角色将开始从数据的控制者转变为解放者,让所有业务用户能够提出他们想要的问题,并自由探索数据,以他们认为合适的方式。
5。雇用一名数据科学家 只有在前四名雇员成功开发了自助式数据平台后,数据科学家才能加入进来,帮助组织真正实现数据驱动。一个伟大的数据科学家,可以专注于与团队合作开发数据驱动的应用程序。在支付行业,这可能意味着开发预测性应用程序,如获取路由(根据历史数据和权重,选择最佳路径)、动态授权(在提交交易前输入或删除数据)或构建欺诈引擎,该引擎能够预测哪些交易是欺诈性的,哪些不是。
您建立了自己的数据团队了吗? 如果你是一名企业主,或者数据属于你的职责范围,你可能会想,这是否真的值得。如果我们看看像脸书、优步、网飞和 Spotify 这样的公司,我们可以看到,控制你的数据,不仅会导致更好的决策和改进的运营,而且实际上可以让你赚更多的钱。对于支付行业来说也是如此,该领域的领导者包括 Stripe、Square、Transferwise 和 Plaid,它们比所有竞争对手都更好地利用数据。
那么,你已经建立了你的数据团队了吗?
感谢阅读;),如果你喜欢它,请点击下面的掌声按钮,这对我意义重大,也有助于其他人了解这个故事。让我知道你的想法,在推特上联系我。或者关注我,阅读我在数据科学、支付和产品管理方面的帖子。
如何为松弛消息建立一个具有 BERT 文本分类的 AI Besserwisser
当别人在电子邮件中不应该“回复所有人”时,或者有人在不属于它的频道上写了一条松散的消息时,我总是被人们的愤怒逗乐。
有鉴于此,我决定在 Peltarion 平台上玩一玩新发布的预训练 BERT(来自变压器的双向编码器表示)块,看看我是否可以建立一个识别松弛消息模式的模型,以便告诉人们何时消息被发布在错误的松弛通道上,并建议它属于哪里。
所以让我们建造一个机器人,也就是真正的无所不知者,它可以自动完成这项工作😈。

Image of Besserwisser via buttsss.com by Pablo Stanley.
在我工作的 Peltarion,我们有许多不同的休闲频道,用于各种目的。我们有自己的“官方”渠道,但也有很多其他更小的渠道。一些相当模糊的,因为人们有许多不同的兴趣。我们有#general(官方声明)、#random(不在 general 之列的东西)、#climbing、#music、#boardgames、#壁球……应有尽有。
总的来说,我确实认为人们很善于决定什么属于哪个频道。因此,我的直觉是,有某种东西可以区分来自不同渠道的信息,这是一个模型应该能够学习的。但是让我们来看看。
为了给我们的模型一个公平的机会,我们需要每个通道有相当数量的消息。看起来似乎大多数“问题”都是在一条消息被发布在#general 中时出现的,而实际上它应该被发布在#random 中。所以,我决定开始使用这两个渠道。使用 Slack 的 Python API 客户端,从这两个渠道获取消息,然后将它们上传到 Peltarion 平台(基于云的深度学习平台)非常容易。
建立模型
下一步:构建模型。这部分可能会比较棘手,尤其是如果你之前没有那么多构建 AI/深度学习模型的经验。但老实说,这可能是整个项目中最简单的部分,因为我可以将预先训练好的 BERT 模块插入到我的模型中。我尝试了一些不同的超参数,可以在两分钟内开始训练——通常我需要花更长的时间来决定 GitHub repo 的名称🤔。
构建、微调和部署花了我大约 30 分钟的时间。我运行了几个不同的实验(3-4),选择了一个准确率最高的实验(72%;不太好,但对这个小玩具项目来说足够好了)。然后,训练需要大约半小时到一小时来完成。
现在,让我们看看这位模特在野外的表现吧!

为此,我构建了一个非常简单的 Slackbot(简单得近乎愚蠢),它可以仔细检查消息并决定它们属于哪个通道。现在,无论何时有人在错误的渠道发布消息,你不必非得是那个同事告诉他们。相反,让你自己的私人贝塞威斯为你照顾它。任务完成!
…以下是如何将 Besserwisser 应用于其他真实用例的方法
对我来说,创建这个 BERT 应用程序只是一种有趣的方式,可以玩玩预先训练好的模型,并在我的日常生活中部署它。如果我在这上面多花一些时间,我会继续微调它,以获得更高的精度。使用来自两个以上 Slack 通道的数据来获得一个更有用的 Slackbot 也是很有趣的,它可以给出更多关于消息归属的建议。
如果你想亲自尝试,这里有一个由我的同事 Calle 创建的循序渐进的教程。
同样的模型也可以应用到其他领域,也许是更多的“现实生活”用例。假设你在一家公司工作,有大量的客户支持任务要处理。日复一日,信息不断涌入,从客户那里发来,希望得到迅速的答复(最好是尽快)。根据问题的不同,这些消息需要由组织中不同的人来回答。构建和部署一个与我的 Slackbot 应用程序中使用的模型类似的模型,可以允许根据主题/应该重定向给谁来对所有消息进行分类。通过这种方式,门票可以最终到达正确的人手中,并更快地得到处理。
如果你喜欢贝塞维瑟的 Slack icon,去看看巴勃罗·斯坦利的buttsss.com(他也有很多其他的好东西)。
如何为星巴克搭建推荐引擎

The Embarcadero, San Francisco, CA
咖啡对我们生活和文化的影响怎么强调都不为过。2018 年,64%的 18 岁或以上的美国人说他们前一天喝了一杯咖啡,而星巴克约占美国咖啡连锁行业的 40%。
在这篇文章中,我们将探索不同的方法来建立一个推荐引擎,推荐 10 种未指定的星巴克产品。这些优惠可以是买一送一 (BOGO),折扣或信息。共有 10 个优惠,它们在难度、持续时间和奖励方面各不相同。
对于每一种方法,我们将用数学公式抽象出问题,解释它如何应用到方法中,并用 python 代码解释它。
获取数据

Photo by Nathan Dumlao on Unsplash
用户的数据已经被清理,在 GitHub 上有 python 的详细实现。虽然没有在这篇文章中讨论,但是清洗过程在设置中注入了一些变化,并且影响了我们的输出。
任何数据科学项目的症结都在于数据收集、争论以及在此过程中做出的许多假设。这个项目绝不是一个例外。当我们讨论不同的方法时,请记住数据的质量是支持我们结论的基石。
第一条信息是用户特征矩阵,其中行是 Starbucks 用户 id,列是关于这些用户的属性。我们总共有大约 17,000 个用户和 23 个功能,有些是直接观察到的,例如:
- 收到的报价数量
- 报价类型(电子邮件、社交媒体等)
- 收入
其他的来源于用户抄本,例如:
- 回应或完成报价的平均时间
- 每次出价的平均奖励
- 因为出价而花费的总金额
下面是用户数据框架的示例截图:

User-Feature Matrix
还有一份抄本的样本:

Transcript of User Behavior
第三个数据帧是一个用户项目矩阵,其中行是用户,列是报价 id,这也是一个非常稀疏的矩阵。我们的条目将是多少次,如果有的话,用户已经查看了报价。如果没有收到报价,我们输入一个 NaN 值,因为我们无法衡量未被请求的参与度。

User-Item Matrix
推荐什么最受欢迎

Photo by Toa Heftiba on Unsplash
美国最受欢迎的咖啡饮料是拿铁,美国人在 2017 年 6 月至 2018 年 6 月期间喝了超过 67,000,000 杯拿铁。我们应该总是建议喝杯拿铁吗?
第一种方法是最简单的:建议什么是最流行的。人们的假设是,受大众欢迎的东西也受个人欢迎。
出现的一个问题是,我们如何定义流行度,在这种情况下,我们提出两种方法:
- 浏览量最多的出价
- 每次观看回报率最高的报价
最受欢迎视图的实现方式如下:
这种方法在新颖性和用户的意外收获方面有所欠缺。它还可以通过已经流行的方式使项目变得流行。
然而,这是一个稳健的解决方案,这也意味着我们总是有地方开始,并且不受冷启动问题的影响。此外,将这个工具放在用户手中也很有用,他们可以选择“最流行”或“最近”的项目。这是一个基于知识的方法的例子。
当我们探索其他方法时,我们的基本假设是视图会带来更多的用户参与和金钱回报。
协同过滤:用户-用户相似性

Photo by Nani Williams on Unsplash
我们的消费习惯经常受到身边人的行为影响。我们向朋友询问他们最喜欢的商品,或者在网上寻找评论。
下一种方法是利用用户之间的相似性来提出建议。这里的假设是,无论我们如何定义相似性,相似的人都会喜欢相似的东西。随着那些相似的邻居被识别,我们向我们的原始用户建议我们的邻居喜欢的新奇物品。
这种方法被称为协同过滤,我们给出了三种实现方法。我们首先创建一个简单的函数来收集单个用户看到的报价。
然后,我们可以构建一个字典来存储用户看到的报价。
我们现在可以着手测量用户之间的相似性。
欧几里德距离
如果我们把用户想象成空间中的点,那么我们可以认为占据同一个邻域的用户非常相似。因此,如果我们取一个用户,k 个最近邻居应该是最相似的。如果这听起来很熟悉,那是因为它确实是K-最近邻算法。
对于两个向量 x 和 y ,我们计算欧几里德距离为:

在 python 代码中:
和 KNN 一样,欧几里得距离对比例很敏感。或者,我们可以用曼哈顿距离 ( L1 范数)来度量相似性。
相互关系
皮尔逊相关系数返回一个介于-1 和+1 之间的值,其中+1 表示非常强的正相关,而-1 表示非常强的负相关。
相关系数 ρ 由下式给出:

到这样的程度
- cov(X,Y)=X 和 Y 的协方差
- σ = 方差
在 python 代码中:
虽然还有其他方法,如 Kendall 的 Tau 和 Spearman 的等级相关性,但选择正确的方法取决于数据分布。
皮尔逊系数的一个关键优势是它对缩放比例不变。然而,它对异常值并不鲁棒,并且对底层数据分布做出假设。
如果数据按照各自变量的样本均值移动,也就是说减去均值,皮尔逊相关就是两个变量之间夹角的余弦值,我们接下来将讨论这个问题。
余弦相似性
测量相似性的最后一种方法是测量两个向量之间的余弦。对于两个矢量 X 和 Y ,由下式给出:

使得 ||X|| 和 ||Y|| 是向量的范数。回想一下,零的余弦等于 1,这意味着两个向量具有相同的方向。我们可以用 scipy 实现这一点:
矩阵分解

Photo by nousnou iwasaki on Unsplash
实际上,我们想知道客户对我们的产品有什么反应。请记住,发出要约是有成本的。在我们的例子中,我们想要测量用户参与度:如果我们提出一些建议,用户真的会看到吗?
假设检验似乎很有吸引力,因为这是衡量成功的一个好方法。如果我们可以离线测试我们的推荐会怎么样?如果我们还可以预测还没看过的项目的评分呢?我们将在本节中尝试回答这些问题。
奇异值分解( SVD )是一个实数或复数矩阵的因式分解,让我们看到无法直接观察到的潜在特征。它将一个 mxn 矩阵分解成:
这三个矩阵通过以下方式与原始用户项矩阵相关联:

- n =用户数量
- k =潜在特征的数量
- m =项目数量
我们将只使用 SVD 的属性,不会深入研究它的工作原理。为了更好的解释,我们推荐斯坦福 CS246 和这个麻省理工学院教程。
∑ ( sigma )矩阵告诉我们许多关于用户项目矩阵中的原始可变性有多少被每个潜在特征所捕获。要解释的可变性总量是对角线元素的平方之和。
此外,由第一个分量解释的可变性的量是对角线上第一个值的平方,第二个值也是如此,以此类推。这意味着我们可以选择较少数量的潜在特征( k )并捕捉原始矩阵的几乎所有可变性,这是一个有助于节省计算的特性。
在我们拥有的真实用户条目矩阵中,许多值都丢失了。这意味着 SVD 不起作用。在 Netflix 颁奖期间,一个名叫西蒙·芬克的用户开发了 T2·芬克 SVD,作为一种计算缺失数据的方法。我们将通过这个算法的一个小例子,并推广到数据集。
初始化两个填充了随机值的矩阵 U 和 V.T 。我们转到原始的用户项矩阵,搜索第一个非缺失值。然后,我们取与用户相关的行和与电影相关的列的点积。
在我们的例子中,我们看到 person 0 的第一个值是 offer_id 4。以此为例,我们计算点积如下:



从这里我们可以计算出误差:

对于真实值 1,我们的误差是 4.24。我们的目标是通过改变每个矩阵中的权重来最小化所有已知值的误差,我们可以通过梯度下降来实现。
在用户矩阵中,我们取误差相对于每个值 ui 的导数。

在电影矩阵中,我们对每个值 vi 取误差的导数。

然后,我们通过向渐变的相反方向移动来更新高亮显示的值:

我们对用户项目矩阵中的所有已知评级进行相同的计算,并对设定数量的时期重复。
用 python 实现这一点:
我们现在想建立一种方法来验证我们的预测。我们在训练和验证中拆分数据,使 FunkSVD 适合训练数据,并在验证数据中为用户做出预测:
让我们用直方图和混淆矩阵来看看我们的预测。


我们可以看到 w 在某些方面是错误的,但是能够预测看不见的项目是一个非常有用的特性。我们也可以使用网格搜索来调整我们的超参数。改进这种方法的研究正在进行中,如赵等人的论文。
结论
我们看到有多种方法可以提供建议,每种方法都有其优势。没有明确的答案,通常使用混合方法的项目可能是最好的解决方案。
与大多数数据科学项目一样,我们拥有的高质量数据越多,结果就越好。希望你喜欢这篇文章!
鸣谢:帮助撰写本文的咖啡因是由三号**菲尔茨在福尔松 和 Illy on Battery 的 星巴克的了不起的咖啡师准备的。 特别感谢uda city和星巴克提供这些数据!**
如何快速简单地构建推荐引擎
第 1 部分:介绍,如何在一周内投入生产,之后去哪里

Recreation of Rina Piccolo’s cartoon (Cartoonist Group)
这篇文章是对这个主题的一个简单介绍,并且提供了在一周内让你进入推荐引擎生产的第一步。我还会告诉你从基础到相当高级的步骤。
我们还不会走在前沿,但也不会太远。
当快速和简单不再足够时,请阅读第 2 部分以了解更高级的用例:
第 2 部分:当快速和简单不再足够好时,如何构建您的下一个推荐引擎。
towardsdatascience.com](/advanced-use-cases-for-recommendation-engines-4a420b14ab4e)
推荐系统无处不在,对于许多在线平台来说,他们的推荐引擎就是真正的业务。这就是亚马逊大的原因:他们非常擅长向你推荐该读哪些书。还有许多其他公司都是围绕推荐系统建立的:YouTube、网飞、Spotify、社交媒体平台。与此同时,消费者开始期待个性化的体验和复杂的推荐系统来找到相关的产品和内容,这一切都是为了节省消费者的时间和金钱。
但是如何构建推荐引擎呢?
背景
推荐引擎已经存在了一段时间,有一些重要的经验可以利用:
- 用户的行为是用户意图的最佳指示器。评级和反馈往往非常偏颇,而且音量较低。
- 过去的行为和购买推动新的购买,与他人的购买和行为重叠是一个很好的预测。
推荐系统通常寻找重叠或同现来进行推荐。就像下面这个例子,我们基于 Ethan 和 Sophia 的相似性推荐 Ethan 一只小狗:

Recreation of illustration in “Practical Machine Learning, Ted Dunning & Ellen Friedman, O’Reilly 2014
在实践中,推荐引擎从事件和动作的历史矩阵中计算出同现矩阵。这很简单,但是在现实世界的场景中有很多挑战需要克服。如果每个人都想要独角兽呢?下面这个例子中独角兽的高共现是不是很好的推荐?

Recreation of illustration in “Practical Machine Learning, Ted Dunning & Ellen Friedman, O’Reilly 2014
在推荐系统已经计算了同现矩阵之后,我们必须应用统计来过滤掉足够异常的信号作为推荐。

Recreation of illustration in “Practical Machine Learning, Ted Dunning & Ellen Friedman, O’Reilly 2014
能够从共现矩阵中提取出相关指标的算法和统计是一个好的推荐系统的基础。创建项目到项目指标矩阵的路径称为项目到项目模型。显然还有一个用户项模型:

为了创建用户项目模型,我们可以应用简单的矩阵分解或训练神经网络来预测用户项目输入的分数。通常,当我们不在特征工程和模型调整等方面投入更多时,项目-项目模型更健壮,并产生更好的结果。
然而,一个好的推荐系统还需要克服一些挑战。反复推荐同样的东西无聊。更糟糕的是,推荐同样的东西会产生坏数据并导致内容疲劳。

Spotify wouldn’t produce such a result set! Their search and recommendation engines are top notch! This example needed editing. ❤ Spotify
提高推荐价值的两个简单直观的策略是
- 反泛滥:如果第二个和第三个推荐与第一个推荐具有相同的相似性得分,则惩罚它们。
- 抖动:添加一个通配符推荐,为推荐系统创建有趣的新数据点,以不断了解其他内容。

这些步骤确保了有趣的用户体验和替代推荐的新数据。
数据和要求
推荐系统最适合不带偏见的明确用户反馈,比如购买产品、看视频或听歌。如果你运气好,有这样一个数据集,即使是一个简单的方法也能很好地工作。然而,在许多用例中,你主要有隐性反馈,如页面浏览量、点击量或搜索查询量。不幸的是,这些数据也有很大的偏差,例如点击率很大程度上取决于内容在页面上的位置。隐式反馈也往往表现不佳,例如,点击搜索结果可能只是告诉你标题或 CTA 的点击量,而不是实际内容的相关性。这导致在最初的高点击率之后的高跳出率(一个非常普遍的情况!)
像协同过滤这样的简单方法需要项目之间的共现。这意味着协同过滤是合适的,并且如果
- 你的产品目录不要太大,条目的寿命很长,可以很容易地被多个用户交互。让我们以陷入困境的 Zoopla 为例:Zoopla.co.uk是一个房地产门户网站,在任何时间点都有超过 130 万个房源。伦敦的出租清单是非常短暂的,在一处房产被租出并退出市场之前,可能只需要几天时间。很明显,你不能同时向多人出租或出售公寓!以 Zoopla 目录的规模,即使在 Zoopla 的流量下,也很难产生大量的同现。
- 你不依靠推荐来发现新产品。因为协同过滤需要同现来产生信号,所以该算法有一个大的冷启动问题。产品目录中的任何新项目都不会同时出现,并且在用户没有与新项目进行一些初始互动的情况下无法推荐。如果你的企业大量使用 CRM 和市场营销作为推广新产品的策略,这是可以接受的。
协作过滤快速简单
一种选择是使用 Spark 和交替最小二乘(ALS)算法(链接),这是一种用于模型训练的简单解决方案,但不提供用于部署和评分的即时解决方案。我推荐一种不同的方法来开始:

事实证明,搜索和推荐问题的数学原理惊人地相似。最重要的是,良好的用户体验在搜索和推荐方面几乎是不可区分的。基本上,如果我们能够将推荐表述为搜索查询,那么搜索结果就是推荐。这是一个理想的解决方案,因为许多网站和企业已经在其后端运行搜索引擎,我们可以利用现有的基础设施来建立我们的推荐系统。Elasticsearch 可很好地扩展,并作为完全托管的部署存在,例如在 AWS 上。如果您想快速将您的推荐引擎部署到生产环境中,这是最安全的选择!
如何用搜索引擎创建推荐?

- 我们将所有用户项目交互存储在一个搜索索引中。
- 当用户在苹果的页面上时,我们会在 elasticsearch 中搜索所有拥有苹果的用户。这定义了我们的前景人口。
- 我们在给我们小狗的前景中寻找同现。
- 我们在背景人群中寻找小狗。
- 我们为我们的小狗推荐计算某种分数。
好消息是:Elasticsearch 在一个查询中为我们实现了所有 5 个步骤!
如果我们在弹性搜索中存储用户-项目交互,如下所示
{
"_id": "07700f84163df9ee23a4827fd847896c",
"user": "user_1",
"products": ["apple", "book", "lemon", "puppy"]
}
使用这样的文档映射:
{
"user": {"type": "keyword"},
"products": {"type": "keyword"}
}
那么产生一些建议所需要的就是下面的查询,例如使用 Python:
from elasticsearch import Elasticsearch, RequestsHttpConnection
from aws_requests_auth.boto_utils import BotoAWSRequestsAuthes = Elasticsearch(
host=host, port=port,
connection_class=RequestsHttpConnection,
http_auth=BotoAWSRequestsAuth(),
scheme=scheme
)es.search(
index=index, doc_type=doc_type,
body={
"query": {
"bool": {
"must": {
"term": {"products": "apple"}
}
}
},
"aggs": {
"recommendations": {
"significant_terms": {
"field": "products",
"exclude": "apple",
"min_doc_count": 100
}
}
}
}
)
默认情况下,Elasticsearch 将返回带有 JLH 分数的推荐,但是有一个可用的分数范围(文档)。
{
...
"aggregations": {
"recommendations": {
"doc_count": 12200,
"bg_count": 130000,
"buckets": [
{
"key": "puppy",
"doc_count": 250,
"score": 0.15,
"bg_count": 320,
}
]
}
}
}
在我们的示例中,搜索 apple 返回了 12,200 个用户的前景人群和 130,000 个在其产品中没有任何 apple 的用户的背景人群。小狗在前台共出现 250 次,在后台共出现 320 次。JLH 分数是背景集合与由(fg _ percentage-BG _ percentage)*(fg _ percentage/BG _ percentage)给出的本地搜索结果之间的变化的简单幅度,其给出 0.15 的分数
由于 JLH 分数是一个数量级的变化,重要的是要记住跳蚤跳得比大象高,JLH 分数对于小数据集来说非常不稳定。您可以调整查询中的min_doc_count参数,以保证您的推荐结果的质量。
这就是它,一个简单但强大的推荐引擎的第一次迭代,它可以在一周或更短的时间内上线!重要的是,任何版本 1 都不应该比这更复杂。生产时间在早期阶段更为重要。通常,你的第一个推荐引擎需要一些迭代来优化用户界面和 UX,而不是数学。
后续步骤
Elasticsearch 不仅仅是一个非常强大的推荐后台,它还非常灵活!在保持 elasticsearch 后端的同时,有很多方法可以改进我们的推荐系统。赢了!
当快速和简单不再足够时,请阅读第 2 部分以了解更高级的用例:
第 2 部分:当快速和简单不再足够好时,如何构建您的下一个推荐引擎。
towardsdatascience.com](/advanced-use-cases-for-recommendation-engines-4a420b14ab4e)
第一步:
我们可以使用 ALS 等更复杂的算法来为我们的推荐创建指标,并将这些指标放入 elasticsearch。这将推荐评分简化为一个简单的查找,因为我们在培训阶段进行繁重的工作,例如使用 Spark。这样,elasticsearch 只是我们为相关推荐提前计算的指标的一个性能表示层。您可以轻松地将它作为新的元数据添加到现有的产品目录中。
第二步:
目前,我们在产品数组中使用二进制标志,这意味着产品数组中的每个产品对 JLH 得分的贡献是相等的。如果没有太多的变化,我们可以使用一些指标来对产品事件本身进行评分,以捕捉更丰富的信号。我们可以用点击计数。或者更好的是,我们可以通过产生点击的页面位置的平均预期点击率来标准化点击,从而使用点击分数。例如,在搜索结果列表中,我们可以计算位于第一位置、第二位置等的项目的预期 CTR。然后,我们可以从项目度量分数的总和而不是它们的简单计数来计算 JLH 量级的变化。
第三步:
用户通常会生成一系列与推荐相关的事件,例如,点击多个商品或将多个产品添加到一个购物篮中。值得为您的推荐引擎添加一个用户交互缓存:( 1)使用一系列事件创建更复杂的搜索查询;( 2)在更新 elasticsearch 索引的批处理 ETL 过程和自上次更新推荐引擎以来发生的用户交互之间创建一个增量。

使用事件序列来产生推荐可以有助于(1)创建更相关的结果,以及(2)在低流量或非常大的目录的情况下,增加前景群体来生成更大数量的同现。只需要对 elasticsearch 查询做一点小小的修改,就可以切换到一个should查询:
es.search(
index=index, doc_type=doc_type,
body={
"query": {
"bool": {
**"should": [**
{"term": {"products": "apple"}},
{"term": {"products": "pony"}},
**],**
**"minimum_should_match": 1,
** }
},
"aggs": {
"recommendations": {
"significant_terms": {
"field": "products",
"exclude": ["apple", "pony"],
"min_doc_count": 10
}
}
}
}
)
minimum_should_match参数允许您在增加前景人口规模或通过增加相似性匹配用户使结果更相关之间进行优化。
第四步:
目前,我们的搜索是对项目的精确查找。这带来了一些后果:我们从用户交互中学习到的关于共现的一切都与它们的特定项目绑定在一起。当一件商品从产品目录中删除时,我们就失去了从它身上学到的一切。我们也不能将任何事物概括为相似的项目,例如,红苹果和绿苹果是不同的项目,同现仅限于红苹果或绿苹果的精确匹配。为了克服这一点,我们需要用数学方法描述项目,以计算项目之间的相似性。这被称为嵌入。阅读我以前的博文,我创建了一个嵌入了 T5 的 T4 地理区域。创建嵌入的其他选项是如上所述的用户项目模型中的自动编码器或矩阵分解。在我们将一个简单的 product_id 转化为嵌入之后,我们可以使用概率或模糊搜索来找到我们的前景群体和/或同现。
这应该能让你从推荐开始。当您从产品反馈中学习时,它也给了您充分的机会来构建您的第一个迭代。
推荐的早期步骤好坏更多地取决于用户界面和 UX,而不是数学的简单性。
超越弹性搜索
通常,产品有我们应该使用的大量元数据,例如价格、描述、图片、评论评级、季节性、标签和类别。在我们将丰富的元数据集转换成描述我们产品的嵌入之后,我们可以训练神经网络将输入嵌入映射成推荐嵌入,该推荐嵌入具有(1)较低的维度和(2)合适推荐的余弦相似性的期望行为是高的。一个很好的解决方案是连体神经网络。

输入是产品元数据的级联嵌入的高维向量。神经网络的输出是更紧凑的推荐嵌入向量。误差函数由输出向量的余弦相似性给出。我们可以使用协同过滤数据来为应该相似或不相似的组合创建我们的监督学习标签。重要的是,在连体神经网络中,两个网络的权重总是相同的,这就是它们的名字。这种推荐引擎将不再有冷启动问题!最后,产生推荐可以通过对输出推荐嵌入的 k-最近邻搜索来完成。
您可以在后续文章中了解更多后续步骤:
第 2 部分:当快速和简单不再足够好时,如何构建您的下一个推荐引擎。
towardsdatascience.com](/advanced-use-cases-for-recommendation-engines-4a420b14ab4e) 
Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。
在 LinkedIn 上连接:【https://www.linkedin.com/in/janteichmann/】
阅读其他文章:https://medium.com/@jan.teichmann
如何利用潜在因素协同过滤构建餐厅推荐系统

Image Designed by Freepik
介绍
我通常在工作间隙看 youtube。我承诺自己只看 5 到 10 分钟的 Youtube,让我的大脑休息一下。通常情况是这样的,在我看完一个视频后,下一个视频会从 Youtube 推荐中弹出,我会点击那个视频。当我再次看手表的时候,发现我已经看了一个多小时的 Youtube 了!😂
Youtube 的推荐系统是最强大和最复杂的推荐系统之一,可以让其用户连续几个小时观看 Youtube 视频。许多初创公司巨头,如网飞、Youtube 和亚马逊的收入主要来自他们建立的推荐系统。
本文主要讨论如何使用潜在因素协同过滤从零开始构建一个餐馆推荐系统。
什么是推荐系统?
推荐系统或推荐系统是简单的算法,旨在通过从庞大的信息库中过滤有用的东西,向用户(客户、访客、应用程序用户、读者)提供最相关和最准确的项目(产品、电影、事件、文章)。推荐引擎通过学习消费者的选择来发现数据集中的数据模式,并产生与其需求和兴趣相关的结果。
想象一个实体服装店。好的商家知道顾客的个人喜好。她/他的高质量推荐让客户满意,增加利润。当你去其他国家或城市旅行时,在选择一家餐馆吃午餐或晚餐的情况下,通常你会问你住在那个国家或城市的朋友镇上最好的餐馆是什么。问题是你没有任何朋友住在那个镇上。你的个人推荐可以由一个人造朋友产生:推荐系统。
矩阵分解或潜在因素协同过滤
有各种类型的推荐系统,但我建立的这个餐馆推荐系统。我侧重于使用矩阵分解或潜在因素协同过滤。让我们从因式分解这个术语开始。

当我们考虑因式分解时,它是一个类似于六乘四等于二十四的概念。24 是一个很大的数字,但是我们把它表示成两个小数字 6 和 4 的乘积,所以我们设法把一个大数字分解成两个小数字的乘积。类似的概念也适用于矩阵分解。

推荐系统是一个信息过滤系统,它试图预测用户对项目(在本例中是一家餐馆)的评分。我们可以将来自用户和项目的大矩阵分解成两个更小的用户特征和项目特征矩阵。例如,用户 A 喜欢吃热狗,但不喜欢吃比萨饼,而餐馆 P 有很棒的热狗,我们用点积乘矩阵,结果就是评分(在上面的例子中是 11)。
餐厅推荐系统
让我们开始使用上面讨论的技术建立一个餐馆推荐系统,它应该能够推荐最适合你的餐馆。

Yelp 是一个商业目录服务和众包评论论坛。该公司开发、托管和营销 Yelp.com 网站和 Yelp 移动应用程序,这些应用程序发布关于企业的众包评论。它还运营一项名为 Yelp Reservations 的在线预订服务。
Yelp 试图解决这个问题“我应该吃什么?”这很快扩大到包括其他业务,以回答其他问题。这可以最好地表示为“我在[城镇]。我在哪里可以得到[最好的/最快的/最便宜的/最容易的][食物/服务/等]?”如果你没有偏好,你朋友的推荐可能对你去哪里有最大的影响。Yelp 为不可用或不可信的情况提供服务。
让我们开始构建机器学习模型
让我们从导入笔记本中需要的所有包开始。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from nltk.corpus import stopwords
from nltk.tokenize import WordPunctTokenizer
现在我们导入数据集,我们使用审查数据集和业务数据集。
df = pd.read_csv('yelp_review_arizona.csv')
df_business = pd.read_csv('yelp_business.csv')
df.head()

我们首先需要清理文本,我们需要删除所有的标点符号和所有的停用词(重复的我们不需要的词,如 have,do,I,you,he 等)。我们使用 nltk.corpus 中的库来查找停用词。
我们只为数据选择星星和文本,并导入我们将使用的库。
#Select only stars and text
yelp_data = df[['business_id', 'user_id', 'stars', 'text']]import string
from nltk.corpus import stopwords
stop = []
for word in stopwords.words('english'):
s = [char for char in word if char not in string.punctuation]
stop.append(''.join(s))
现在让我们通过创建一个函数来清理文本。
def text_process(mess):
"""
Takes in a string of text, then performs the following:
1\. Remove all punctuation
2\. Remove all stopwords
3\. Returns a list of the cleaned text
"""
# Check characters to see if they are in punctuation
nopunc = [char for char in mess if char not in string.punctuation]# Join the characters again to form the string.
nopunc = ''.join(nopunc)
# Now just remove any stopwords
return " ".join([word for word in nopunc.split() if word.lower() not in stop])yelp_data['text'] = yelp_data['text'].apply(text_process)
为了将文本用于矩阵分解推荐系统,我们将遵循下面的架构来从评论文本中提取特征。

User feature extraction

Business feature extraction
对于每个用户,将所有评论组合起来形成一个段落,在我们将所有评论组合起来之后,我们应用 TFIDF 矢量器从文本中提取特征。每个餐馆都有类似的方法,我们需要给 max_feature 匹配矩阵的维数。
userid_df = yelp_data[['user_id','text']]
business_df = yelp_data[['business_id', 'text']]

Reviews of user ‘ZwVz20be-hOZnyAbevyMyQ’
userid_df = userid_df.groupby('user_id').agg({'text': ' '.join})
business_df = business_df.groupby('business_id').agg({'text': ' '.join})

Combined reviews of user ‘ZwVz20be-hOZnyAbevyMyQ’
现在我们应用 TFIDF 矢量器从文本中提取特征。
from sklearn.feature_extraction.text import TfidfVectorizer#userid vectorizer
userid_vectorizer = TfidfVectorizer(tokenizer = WordPunctTokenizer().tokenize, max_features=5000)
userid_vectors = userid_vectorizer.fit_transform(userid_df['text'])#Business id vectorizer
businessid_vectorizer = TfidfVectorizer(tokenizer = WordPunctTokenizer().tokenize, max_features=5000)
businessid_vectors = businessid_vectorizer.fit_transform(business_df['text'])
然后,我们用评级创建一个用户和企业矩阵。
userid_rating_matrix = pd.pivot_table(yelp_data, values='stars', index=['user_id'], columns=['business_id'])

潜在因素协同过滤优化
让我们回到我们使用的推荐系统的类型,这是潜在的因素协同过滤。我们已经有两个矩阵(用户特征,商业特征),我们可以相乘来预测用户给餐馆的评分。下一步,我们需要根据误差更新两个矩阵的特征值。

The image can be found in this link
为了优化预测,我们需要使用下面的函数计算误差。

假设 P 是用户特征矩阵,Q 是商业特征矩阵。如果我们用预测收视率(P.Q)减去实际收视率(r ),然后求平方,就得到 LSE(最小平方误差)。在餐馆评论的情况下,我们有只给 10 家餐馆评论的用户,但是我们也有给超过 200 家餐馆评论的用户。为了避免我们的模型过度拟合,我们必须将正则化添加到我们的 LSE 公式中,它将成为下面的公式。

我们应用该方程来最小化误差,使用梯度下降来更新矩阵 P 和矩阵 q 中每个特征的值。
def matrix_factorization(R, P, Q, steps=25, gamma=0.001,lamda=0.02):
for step in range(steps):
for i in R.index:
for j in R.columns:
if R.loc[i,j]>0:
eij=R.loc[i,j]-np.dot(P.loc[i],Q.loc[j])
P.loc[i]=P.loc[i]+gamma*(eij*Q.loc[j]-lamda*P.loc[i])
Q.loc[j]=Q.loc[j]+gamma*(eij*P.loc[i]-lamda*Q.loc[j])
e=0
for i in R.index:
for j in R.columns:
if R.loc[i,j]>0:
e= e + pow(R.loc[i,j]-np.dot(P.loc[i],Q.loc[j]),2)+lamda*(pow(np.linalg.norm(P.loc[i]),2)+pow(np.linalg.norm(Q.loc[j]),2))
if e<0.001:
break
return P,QP, Q = matrix_factorization(userid_rating_matrix, P, Q, steps=25, gamma=0.001,lamda=0.02)
现在我们已经更新了两个矩阵。是时候预测餐厅推荐了。
words = "i want to have dinner with beautiful views"
test_df= pd.DataFrame([words], columns=['text'])
test_df['text'] = test_df['text'].apply(text_process)
test_vectors = userid_vectorizer.transform(test_df['text'])
test_v_df = pd.DataFrame(test_vectors.toarray(), index=test_df.index, columns=userid_vectorizer.get_feature_names())predictItemRating=pd.DataFrame(np.dot(test_v_df.loc[0],Q.T),index=Q.index,columns=['Rating'])
topRecommendations=pd.DataFrame.sort_values(predictItemRating,['Rating'],ascending=[0])[:7]for i in topRecommendations.index:
print(df_business[df_business['business_id']==i]['name'].iloc[0])
print(df_business[df_business['business_id']==i]['categories'].iloc[0])
print(str(df_business[df_business['business_id']==i]['stars'].iloc[0])+ ' '+str(df_business[df_business['business_id']==i]['review_count'].iloc[0]))
print('')
通过输入“我想吃有美丽风景的晚餐”,模型将推荐这些餐馆。

让我们来看看上面列出的其中一家餐馆。例如,让我们在 Yelp 中打开 Compas Arizona Grill 来查看我们的推荐系统的结果。

它看起来像餐馆有相当美丽的景色和美丽的日落。你可以带你的配偶去那里吃一顿浪漫的晚餐(如果你有一个:D 的话)。
恭喜您创建了一个餐厅推荐系统!
要查看数据集和完整版本的代码,请访问下面的链接在 Github 中查看。
https://github . com/theo Jeremiah/Restaurant-Recommendation-System
如何使用 Scikit-Learn 构建可重用的自定义 NLP 管道
重点是功能工程和培训

机器学习代码管道最重要的特征之一是可重用性。一个可重用、可共享和可扩展的管道将通过对程序流强制一致地使用直观的结构元素来确保流程和代码的完整性,并因此可以增强数据科学家的开发流程,该流程本质上是迭代的。在本文中,我将演示如何使用 scikit-learn 从头构建一个定制的机器学习代码管道,重点是以下两个组件:
- 特性化管道,支持灵活定义和选择特性
- 一个训练管道,它结合了用于后续步骤的特征化管道的输出:向量化和模型训练
这两个组件都以类似的方式利用类继承;也就是说,它们的特征在于一个底层的类结构,从这个结构中可以派生出更具体的类来解决不同种类的监督学习问题或项目需求。作为本文的一个额外收获,在第 2 节中,我将触及与继承相关的一个强大的概念,即抽象方法,并说明它如何使所提出的管道设计如此直观和易于使用。
1.特征管线

一个典型的 NLP 任务需要大量的特征工程,这个过程包括为训练模型准备合适的输入数据。该步骤可能需要将输入文本数据转换成单词包表示或多维向量,或者它可能涉及编写更原始的用户定义函数来提取诸如句子长度标准偏差、主要动词之前的单词数(句法复杂性的粗略度量)、可读性分数等特征的值。在任何给定的项目中,可以选择任意数量的这种特征来训练模型或首先确定特征重要性、减少维度或进行消融研究。
为了方便、控制和灵活地选择或测试特性,你可以想象有一种“特性库”,当你需要它们的时候,你可以从中提取你(或你的队友)曾经写过的任何特性。这个库可以表示为下面称为BaseFeaturizer的类,它的每个方法都包含计算特性值的逻辑。
一旦我们在BaseFeaturizer中定义了这些基本方法,我们就可以派生新的类来修改这些方法或者添加新的方法。但是也许这些派生类最重要的属性是它们可以根据它们选择/引入的特性的数量和类型而变化。并且该信息应该在所有派生类中以一致的方式定义,即在每个派生类的 main 方法中,我将命名为**featurize**。
例如,假设我们要训练一个预测文档语法复杂性的文本分类模型,将它们分为两个离散的类:“简单”和“复杂”。这项任务的两个潜在有用的语法特征是:
- 主要动词前的单词数:主要动词前的文本越长,该文本的语法就越复杂(可能是因为存在从句和/或主语修饰语,如从句)
- 可读性:可读性分数越高,越复杂。(例如,在此阅读 Flesch–Kincaid 可读性测试。)
(我在这个例子中有些随意地选择了这些特征,但是有各种各样的特征选择技术可以用来首先确定哪些特征是最有用的,并且只包括那些在最终训练中的特征。)
下面,**SyntacticComplexityFeaturizer**被定义为BaseFeaturier的子类,两个特性的值在featurize中通过调用前面在BaseFeaturizer中定义的函数来计算。这些值存储在每个文档的feature_dict中,而featurize返回整个文档集的特征值映射。
这里有一个feature_dicts的例子,在SyntacticComplexityFeaturizer的实例上调用featurize的输出。
2.培训渠道

这个特征化管道的输出自然会作为下一个组件(训练管道)的输入。这两个管道在形式上是同构的,因为后者也包含一个基础设计(类),从该基础设计可以导出更具体的训练管道来满足不同的训练要求。我把这个类命名为BaseTrainingPipeline。这个类的一个重要属性是它继承了 **ABC** (“抽象基类”的简称),原因很快就会明了。
BaseTrainingPipeline可以用您以后可能想要访问的任何属性进行初始化,例如,self.y_test和self.y_preds(这些值适合存储用于评估目的),以及self.models(所有模型都基于相同的数据进行训练)。我在__init__函数中定义了以下属性:
接下来,该类的 main 方法pipeline_main包含将输入文本首先转换为数字特征,然后转换为向量所需的最少代码,这些步骤在大多数受监督的 NLP 任务中都会重复。注意,两条管道(特征化和训练)通过该方法连接,因为该方法将FeaturizerClass作为参数,例如SyntacticComplexityClass.
- 一旦实例化(
featurizer = FeaturizerClass(),该对象将对数据(语料库)调用featurize方法,返回一个特征值映射列表(第 22–23 行)。 - 然后可以使用
DictVectorizer(第 31–33 行)将这个列表转换成 numpy 数组或矩阵(向量)。 - 然后,向量
X_train和y_train可用于训练任何 scikit-learn 估计器(第 39–42 行)。
为了详细说明前面的观点,**train_model**被定义为BaseTrainingPipeline的一个抽象方法(这使得它成为一个抽象类)。抽象方法可以用装饰器@abstractmethod来装饰,相关部分转载如下:
你可以在这里阅读更多关于抽象方法的内容,但简单来说:
抽象类是包含一个或多个抽象方法的类。抽象方法是声明的方法,但不包含实现。抽象类可以不被实例化,并且需要子类为抽象方法提供实现。Python 中抽象类的子类不需要实现父类的抽象方法。
将train_model定义为一个抽象方法是必要的,因为它为该方法的所有实现提供了一个公共功能,这些实现由BaseTrainingPipeline的子类提供。也就是说,因为我们将train_model定义为基类的一个方法,所以我们可以从同一个类中定义的另一个方法中调用它(在我们的例子中,从pipeline_main),然而因为它的实现只能由子类提供,所以我们能够以多种不同的方式定义train_model。这些实现可能变化的一个方面是估计器类型。
为了使这一切更具体,考虑我从BaseTrainingPipeline : **ClassificationTrainingPipeline**和**RegressionTrainingPipeline**得到的两个示例训练管道。这种分离具有直观的意义,因为一个处理目标变量为分类/离散的分类器,而另一个处理目标变量为数值/连续的回归变量。这允许我们使用相同的通用(训练)流水线来支持不同类型的监督学习问题,而无需重写上面 **pipeline_main** 中定义的核心元素和可重复步骤的任何部分。注意train_model的实现在两种情况下有什么不同:在ClassificationTrainingPipeline中,train_model为满足特定条件的模型指定新的参数设置,即if algorithm == "logistic_regression"(下面的第 12-19 行),覆盖初始化模型的原始设置。RegressionTrainingPipeline不包含这样的覆盖设置,尽管它肯定可能用于任何其初始化的模型。
将所有这些放在一起,我们现在可以实例化这些训练管道中的一个,它将某个特征化类作为参数:
一旦我们运行了这段代码,__init__属性的值将会被更新,这样我们就可以访问保存的数组,比如y_test和y_preds,以及模型本身(您可能想要保存)。此时,您可以考虑扩展培训管道,以支持其他步骤,如模型评估、指标报告和可视化。例如,您可以将如下方法添加到RegressorTrainingPipeline中,以在 heldout 数据集上进行预测,并保存每次迭代训练的指标报告:
在本文中,我介绍了构建可重用、可扩展的 ML 代码管道的一步一步的过程,该管道可以很容易地适应各种 NLP 问题。设计的两个核心组件——特征管道和训练管道——在它们的基本组织中相互反映,并且通过类继承和在某些情况下的抽象方法,它们能够(1)适应灵活的特征定义和选择,以及(2)为训练不同种类的监督模型(例如,分类对回归)提供通用支持。
2019 年 12 月更新:关于使用 scikit-learn 的Pipeline实现您的 ML 管道的替代方法,请查看以下帖子:
[## 基于 Scikit-Learn 流水线的文本特征提取
使用 2010 年初选辩论记录
towardsdatascience.com](/the-triune-pipeline-for-three-major-transformers-in-nlp-18c14e20530)
如何在 3 分钟内建立一个语义搜索引擎
与标准 TF-IDF 相比,搜索相关性提高 80%
合著者 Jack Pertschuk

本教程是用 Elasticsearch 和 NBoost 建立语义搜索引擎的快速指南。本指南不作为语义搜索的介绍。查看这篇文章了解背景。
在 3 分钟内设置一个神经代理来进行弹性搜索
在这个例子中,我们将在客户端和 Elasticsearch 之间设置一个代理来提高搜索结果。
使用 tensorflow 安装 NBoost
如果您想在 GPU 上运行该示例,请确保您有 tensor flow 1.14–1.15(带 CUDA)来支持建模功能。但是,如果你只是想在 CPU 上运行,就不用担心了。对于这两种情况,只需运行:
pip install nboost[tf]
设置 Elasticsearch 服务器
🔔如果你已经有一个 Elasticsearch 服务器,你可以跳过这一步!
如果你没有 Elasticsearch,不用担心!你可以使用 docker 建立一个本地的 Elasticsearch 集群。首先,通过运行以下命令获取 ES 映像:
docker pull elasticsearch:7.4.2
一旦有了图像,您就可以通过以下方式运行 Elasticsearch 服务器:
docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.4.2
部署代理
现在我们准备好部署我们的神经代理了!做到这一点非常简单,只需运行:
nboost --uport 9200
📢
*--uhost**--uport*应该和上面的 Elasticsearch 服务器一样!Uhost 和 uport 是 upstream-host 和 upstream-port(指上游服务器)的简称。**
如果你收到这个消息:Listening: <host>:<port>,那么我们可以走了!
索引一些数据
NBoost 内置了一个方便的索引工具(nboost-index)。出于演示的目的,我们将通过 NBoost 索引一组关于旅游和酒店的段落。您可以通过运行以下命令将索引添加到您的 Elasticsearch 服务器:
*travel.csv*T24 自带 NBoost
*nboost-index --file travel.csv --name travel --delim ,*
现在让我们来测试一下!点击弹性搜索:
*curl "http://localhost:8000/travel/_search?pretty&q=passage:vegas&size=2"*
如果 Elasticsearch 结果中有_nboost标签,那么恭喜它成功了!

刚刚发生了什么?
让我们来看看 NBoost 前端。转到您的浏览器并访问 localhost:8000/nboost 。
如果您无法访问浏览器,您可以
*curl http://localhost:8000/nboost/status*获取相同的信息。

前端记录了发生的一切:
- NBoost 收到了对 2 个搜索结果的请求。 (0.32 毫秒)
- NBoost 连接到服务器。 (0.13 毫秒)
- NBoost 向服务器发送了 10 个搜索结果的请求。 (0.12 毫秒)
- NBoost 从服务器收到了 10 个搜索结果。 (120.33 毫秒)
- 这个模型挑选了最好的两个搜索结果。 (300 毫秒)
- NBoost 将搜索结果返回给客户端。 (0.10 毫秒)
如何建立一个简单的带标签的电影推荐系统
基于内容的查找相似电影的方法

Photo by Denise Jans on Unsplash
简介
让我们假设你正在推出下一个伟大的订阅视频点播(SVOD)流媒体服务,并且你已经获得了播放过去 100 年发行的所有主要电影的权利。祝贺这个不可思议的壮举!
现在有很多电影。如果没有某种推荐系统,你会担心用户可能会被他们不关心的电影淹没。这可能会导致客户流失,这是你最不想看到的!
所以你决定建立一个电影推荐系统。因为你的服务是新的,你还没有足够的数据说明哪些用户在看什么电影。这就是所谓的冷启动问题,它阻止你仅仅基于用户的历史收视率来推荐电影。
幸运的是,即使没有足够的收视率数据,我们仍然可以用电影元数据构建一个不错的推荐系统。这就是电影镜头的用武之地。MovieLens 为每部电影提供了一个带有关键字标签的公共数据集。这些标签信息丰富。例如,查看下面的顶级社区标签,寻找善意。


Screenshot taken from the MovieLens website
在这篇文章的剩余部分,我将回答三个商业问题,这三个问题对于使用 MovieLens 的标签构建一个简单的基于内容的推荐系统至关重要:
- 每部电影我们需要多少个标签?
- 我们如何用标签来衡量电影之间的相似度?
- 我们如何使用标签为用户生成电影推荐?
摘自维基百科关于基于内容的推荐系统的页面:
基于内容的过滤方法是基于对项目的描述和用户偏好的描述。这些方法最适合于已知项目数据(名称、位置、描述等)的情况。),但不在用户身上。基于内容的推荐器将推荐视为特定于用户的分类问题,并根据产品特征学习用户喜欢和不喜欢的分类器。”
这种分析的代码可以在这里与数据和康达环境 YAML 文件一起找到,便于您轻松重现结果。
1)每部电影我们需要多少个标签?
在 MovieLens 标签基因组数据集中有大约 10K 独特的电影和 1K 独特的标签。每部电影的每个标签都有一个相关性分数,因此大约有 1000 万个电影标签对。相关性分数的范围是从 0 到 1。
不是每个标签都与电影相关,所以我们只需要保留最相关的标签。首先,我们可以根据相关性分数对每部电影的标签进行排序。例如,在的前 10 个标签下面,记住泰坦。请注意,相关性分数远高于 0.9,这表明它们是非常相关的标签。

Top 10 tags based on relevance score (descending order)
接下来,我们在下面的图表中确认,电影的排名较高的标签往往具有较高的中值相关性分数。电影中排名第一的标签具有几乎为 1 的中值相关性分数。我们可以看到,随着我们下降到第 50 位,中值相关性分数逐渐降低。

为了找到与电影最相关的标签,我们可以根据相关性分数保留电影的前 N 个标签。在这里,我们需要仔细挑选 N 。如果 N 很小,我们有非常相关但很少的标签。如果 N 很大,我们有很多标签,但其中很多可能是不相关的。
下图显示了从排名第 1 位到第 100 位的标签,中值相关性分数的百分比变化。当相关性分数开始变得更加稳定时,我们在第 50 个排名附近看到一个拐点。因此,我们可以选择 N = 50 作为为每部电影保留的标签的合理数量。请注意,这是一个非常简单的“肘方法”风格的方法,可以在以后进行优化。

现在,我们可以获得每部电影的前 50 个标签的列表,我们将在下一节中使用。例如,在玩具总动员的前 50 个标签下面。

2)我们如何用标签来衡量电影之间的相似度?
在为用户生成电影推荐之前,我们需要一种方法来根据电影的前 50 个标签来衡量电影之间的相似性。在基于内容的推荐系统中,用户将被推荐与他们已经看过的电影相似的电影。
在这里,我将演示两种度量相似性的方法:
Jaccard 指数
使用 Jaccard 指数的第一种方法测量两个集合 A 和 B 之间的相似性,即交集的大小除以并集的大小。当测量电影之间的相似性时,我们可以为两组电影标签计算这个指数。

Taken from wikipedia
例如,假设我们有以下三部电影及其前三个标签:
- 电影 A 标签=(动作、空间、友情)
- 电影 B 标签=(冒险、太空、友谊)
- 电影 C 标签=(浪漫、喜剧、成人)
直观上,我们可以看到电影 A 比C更类似于 B 这是因为电影 A 和 B 共享两个标签(空间,友谊),而电影 A 和 C 不共享任何标签。
根据 Jaccard 指数,以下 10 部电影类似于《心灵捕手》。对于有良好意愿的观众来说,这些看起来是合理的建议。请注意,我在列表中包括了《心灵捕手》,以表明在比较电影本身时,Jaccard 指数= 1。

Movies similar to Good Will Hunting based on Jaccard Index of tag sets
以下是基于 Jaccard 指数的类似于星际的前 10 部电影。对于《星际穿越》的观众来说,这些看起来也是合理的推荐。

Movies similar to Interstellar based on Jaccard Index of tag sets
为了进一步说明 Jaccard 索引的有效性,请参见下面基于类似于《星际穿越》的电影的标签频率的词云。在这里,我们可以看到哪些标签在相似度计算中更突出(例如,科幻小说、伟大的结局、反主题未来、哲学、大脑)。

Word cloud based on tag frequency from movies similar to Interstellar
电影向量的余弦相似度(又名内容嵌入)
Jaccard Index 的第一种方法帮助我们建立了一种直觉,即与标签相似意味着什么。余弦相似度的第二种方法有点复杂。它要求我们把我们的电影表现为一个向量。在这里,向量只是一组数字。
例如,我们可以将之前的相同电影表示为一组三个实数:
- 电影 A = (1.1,2.3,5.1)
- 电影 B = (1.3,2.1,4.9)
- 电影 C = (5.1,6.2,1.1)
直观地,我们可以再次看到电影 A 比c更类似于 B 这是因为电影 A 和 B 在每个维度上具有更接近的数字(例如在第一维度上 1.1 比 1.3)。
为了找到一个好的电影矢量表示,我使用了这篇论文中的 Doc2Vec (PV-DBOW)技术,它获取一部电影(文档)并根据其标签(文档中的单词)学习到潜在的 K 维矢量空间的映射。这里我就不细说了,但是这就是我们如何把电影表示成一个基于标签的向量。

Visual of the PV-DBOW technique from the Doc2Vec paper; for each paragraph ID (movie) we’re training a model to predict the occurrence of a word (movie tag) in that paragraph
一旦我们可以将每部电影表示为一个向量,我们就可以计算向量之间的余弦相似度,以找到相似的电影。我不会在这里深入讨论余弦相似度的细节,但是在高层次上,它告诉我们电影向量彼此有多相似,我们可以用它来生成推荐。
下面我用 UMAP 可视化 2D 的电影向量,这是一种流行的非线性降维技术。我们可以看到,在这个向量空间中靠得更近的电影更相似(例如《玩具总动员》和《怪物公司》)。

Movie vectors learned from corpus of movie tags
3)我们如何使用标签为用户生成电影推荐?
现在我们可以用标签来衡量电影之间的相似性,我们可以开始向用户推荐电影。
记住,在基于内容的推荐系统中,用户会被推荐与他们已经看过的电影相似的电影。如果用户只看过一部电影(例如《心灵捕手》),我们可以像以前一样简单地使用 Jaccard 索引(或余弦相似度)来生成相似电影的列表进行推荐。
更实际的情况是,用户已经观看了一系列电影,我们需要根据这些电影的综合属性来生成推荐。
一个简单的方法是计算用户向量,作为他们看过的电影向量的平均值。这些用户向量可以表示用户的电影偏好简档。
例如,如果用户只看过下面的电影 A 和 B :
- 电影 A = (1,2,3)
- 电影 B = (7,2,1)
- 用户向量=电影 A 和 B 的平均值= (4,2,2)
以下是我喜欢看的电影。我们如何使用这些电影的标签来生成电影推荐?
《星际穿越》、《心灵捕手》、《差点成名》、《肖申克的救赎》、《明日边缘》、《杰里·马奎尔》、《阿甘正传》、《回到未来》
我的用户向量是上面九部电影的平均向量。我可以拿我的用户向量,找到最相似的我还没看过的电影(基于余弦相似度)。以下是我的电影推荐,考虑到我们这里只使用电影标签,这些推荐出奇的好!请随意使用笔记本,并生成您自己的建议。
The Theory of Everything
Cast Away
Dead Poets Society
Charly
Rain Man
Groundhog Day
Pay It Forward
A Beautiful Mind
E.T. the Extra-Terrestrial
Mr. Holland's Opus
On Golden Pond
It's a Wonderful Life
Children of a Lesser God
The Curious Case of Benjamin Button
Star Trek II: The Wrath of Khan
Cinema Paradiso
Mr. Smith Goes to Washington
The Terminal
Her
The World's Fastest Indian
The Truman Show
Star Trek: First Contact
The Family Man
下面总结了我们的基于内容的推荐系统。请注意,如果我们将系统部署为 API,我们可以在批处理过程中预先计算用户向量和相似性得分,以加快推荐服务的速度。
- 输入:用户向量(从标签学习的电影向量的平均值)
- 输出:基于用户和电影向量的余弦相似度,列出与用户相似的电影
如何用 Python 从头开始构建一个简单的神经网络
不使用框架建立神经网络的快速指南。

Photo by Franck V. on Unsplash
神经网络每天都变得越来越受欢迎,作为机器学习和人工智能的核心领域,它们将在未来几年在技术、科学和工业中发挥重要作用。这种高受欢迎程度已经产生了许多框架,允许您非常容易地实现神经网络,而无需了解它们背后的完整理论。另一方面,神经网络机制的严格理论解释需要一些高级数学知识。
在这篇文章中,我们将做一些介于。具体来说, 为了更扎实地理解神经网络, 我们将从头开始实际实现一个 NN,不使用任何框架但为了简单起见我们将省略证明。这可能比使用框架更难,但是你会对算法背后的机制有更好的理解。当然,在大型项目中,框架实现是首选,因为它更容易和更快地建立。
本教程中使用的工具只是带有 numpy 库(线性代数运算的科学库)的 Python。假设您已经安装了 python 和 pip,您可以通过运行以下命令来安装 numpy:
*pip install numpy*
神经网络实际上是许多变量的函数:它接受输入,进行计算并产生输出。我们喜欢把它想象成不同层中的神经元,一层中的每个神经元都与上一层和下一层中的所有神经元相连。所有的计算都发生在这些神经元内部,并且依赖于将神经元相互连接起来的权重。因此,我们所要做的就是学习正确的权重,以获得期望的输出。
它们的结构通常非常复杂,包括许多层,甚至超过一百万层(2020 年 12 月更新:GPT-3 现在使用 175 个参数!)神经元为了能够处理我们这个时代的大数据集。然而,为了理解大型深度神经网络如何工作,应该从最简单的开始。
因此,下面我们将实现一个非常简单的两层网络。为了做到这一点,我们还需要一个非常简单的数据集,因此我们将在示例中使用 XOR 数据集,如下所示。A 和 B 是 NN 的 2 个输入,AXORB是输出。我们将尝试让我们的 NN 学习权重,这样无论它接受哪一对 A 和 B 作为输入,它都将返回相应的结果。

The XOR truth table
所以,我们开始吧!
首先,我们需要定义我们的神经网络的结构。因为我们的数据集相对简单,所以只有一个隐藏层的网络就可以了。所以我们会有一个输入层,一个隐藏层和一个输出层。接下来,我们需要一个激活函数。sigmoid 函数是最后一层的好选择,因为它输出 0 到 1 之间的值,而 tanh(双曲正切)在隐藏层中效果更好,但其他所有常用函数也可以(例如 ReLU)。所以我们的神经网络结构看起来会像这样:

这里,要学习的参数是权重 W1、W2 和偏差 b1、b2。正如你所看到的,W1 和 b1 连接输入层和隐藏层,而 W2,b2 连接隐藏层和输出层。根据基本理论,我们知道激活 A1 和 A2 计算如下:
*A1 = h(W1*X + b1)
A2 = g(W2*A1 + b2)*
其中 g 和 h 是我们选择的两个激活函数(对于 us sigmoid 和 tanh ), W1、W1、b1、b2 通常是矩阵。
现在让我们进入实际的代码。代码风格总体上遵循了吴恩达教授在本次课程中提出的指导方针。
注意:你可以在我的知识库这里找到完整的工作代码
首先,我们将实现我们的 sigmoid 激活函数,定义如下: g(z) = 1/(1+e^(-z)) 其中 z 通常是一个矩阵。幸运的是 numpy 支持矩阵计算,所以代码相对简单:
Sigmoid implementation
接下来,我们必须初始化我们的参数。权重矩阵 W1 和 W2 将从正态分布随机初始化,而偏差 b1 和 b2 将被初始化为零。函数 initialize_parameters(n_x,n_h,n_y)将 3 层中每一层的单元数作为输入,并正确初始化参数:
Parameters initialization
下一步是实现向前传播。函数 forward_prop(X,parameters)将神经网络输入矩阵 X 和参数字典作为输入,并返回 NN A2 的输出以及稍后将在反向传播中使用的缓存字典。
Forward Propagation
我们现在必须计算损失函数。我们将使用交叉熵损失函数。Calculate_cost(A2,Y)将 NN A2 和基本事实矩阵 Y 的结果作为输入,并返回交叉熵成本:
Cost Calculation
现在是神经网络算法中最难的部分,反向传播。这里的代码可能看起来有点奇怪和难以理解,但我们不会深入研究它为什么在这里工作的细节。该函数将返回损失函数相对于我们的网络的 4 个参数(W1,W2,b1,b2)的梯度:
Backward Propagation
很好,现在我们有了损失函数的所有梯度,所以我们可以进行实际的学习了!我们将使用梯度下降算法来更新我们的参数,并使我们的模型以作为参数传递的学习率进行学习:
Gradient Descent Algorithm
到目前为止,我们已经实现了一轮培训所需的所有功能。现在,我们所要做的就是将它们放在一个名为 model()的函数中,并从主程序中调用 model()。
Model()函数将特征矩阵 X、标签矩阵 Y、单元数量 n_x、n_h、n_y、我们希望梯度下降算法运行的迭代次数以及梯度下降的学习速率作为输入,并组合上述所有函数以返回我们的模型的训练参数:
Model function that combines all the above functions.
训练部分现在结束了。上面的函数将返回我们的神经网络的训练参数。现在我们只需要做出我们的预测*。函数 predict(X,parameters)将矩阵 X 作为输入,该矩阵 X 具有我们想要为其计算 XOR 函数的 2 个数字和模型的训练参数,并通过使用阈值 0.5 返回期望的结果 y_predict:*
Prediction function
我们最终完成了所有需要的功能。现在让我们进入主程序,声明我们的矩阵 X,Y 和超参数 n_x,n_h,n_y,num_of_iters,learning_rate:
Main program: Initialization of variables and hyperparameters
设置好以上所有内容后,在上面训练模型就像调用下面这行代码一样简单:
Learn the parameters using the model() function
最后,让我们预测一对随机的数字,比如说(1,1):
Make a prediction with A=1, B=1 using the learned parameters
那是真正的代码!让我们看看我们的结果。如果我们用这个命令运行我们的文件,比如说 xor_nn.py
*python xor_nn.py*
我们得到下面的结果,因为 1XOR1=0,所以这个结果确实是正确的。

Result of our NN prediction for A=1 and B=1
就是这样!我们只用 Python 从头开始训练了一个神经网络。
当然,为了训练具有许多层和隐藏单元的较大网络,您可能需要使用上述算法的一些变体,例如,您可能需要使用批量梯度下降而不是梯度下降,或者使用更多的层,但是简单 NN 的主要思想如上所述。
您可以随意使用超参数,尝试不同的神经网络架构。例如,您可以尝试更少的迭代次数,因为成本似乎下降得很快,1000 次迭代可能有点大。记住你可以在我的 GitLab 库这里找到完整的工作代码。
感谢的阅读,我很乐意讨论您可能有的任何问题或纠正:)如果您想谈论机器学习或其他任何事情,请在 LinkedIn 或我的网页上找到我。
如何使用决策树构建垃圾邮件分类器
机器学习:监督学习
越简单的模型越好!

NASA/JPL/Cornell University, Maas Digital LLC
"像鸭子一样走路,像鸭子一样游泳,像鸭子一样嘎嘎叫,大概,它是一只鸭子!"
数据科学投诉
在监督学习领域,有大量的分类器,包括逻辑回归( logit 101 和 logit 102 )、LDA、朴素贝叶斯、SVM、、KNN 、随机森林、神经网络,每天都有更多的分类器出现!
所有数据科学家都应该问自己的真正问题是:
我们是否选择了正确的方法?
或者,
我们选的是花式模特吗?
关于 5 个最流行的 ML 分类器的快速比较和分步说明,请参考我的另一篇 帖子 :
哪一种最适合不平衡数据?有什么权衡吗?
towardsdatascience.com](/classifying-rare-events-using-five-machine-learning-techniques-fab464573233)
如下面这条推文所示,
一个简单的回归就够了,建立 10 层深度学习模型还有什么意义?
让我们面对现实吧。我们,数据科学家,有时可能是以自我为中心的毒枭,更关心炫耀技能,而不听取客户的需求。
无论是面向内部的 DS 角色(例如人员分析)还是面向外部的 DS 角色(例如统计顾问),他们都需要提供非技术同事和客户能够立即理解和应用的快速解决方案。请不要将它们与 DS 术语、行话、系数解释或任何其他不必要的麻烦混淆。如果 ML 模型太难而没有用,那绝对没有附加值。
考虑到这一点,我们在这篇文章中学习如何使用可解释的 ML 分类器决策树来构建一个简单的垃圾邮件分类器(UCI 机器学习数据库托管数据集,可以在这里访问)。

决策图表
决策树是一种监督学习方法,它将结果空间分割成 J 个区域 R(1),R(2),…,R(J),并预测每个区域 R 的响应
使用递归二进制分裂,我们通过四个简单的步骤构建 DT 模型:
- 基于变量 X(i)分割区域 R(j)
- 设置截止点 s,并将 R(j)分成两个区域,如果
- {X|X(i)
{X|X(i)> s} = R(类别 2)
3.对下一个区域重复前两步
4.继续下去,直到我们用完了所有可用的单元,或者每个叶节点中只剩下少量的单元。
用日常俗人的话来说,DT 就是找到空间的最佳分割方式,让空间在每次分割后变得“更纯粹”。有三种方法可以测量空间的纯净度或不纯净度:
分类错误率

2。基尼指数

3。熵

如何选择最佳分割?
对于区域 j,计算先前杂质 I(分割前)和变量 I(分割后)的分割后杂质。选择导致 I(分割前)和 I(分割后)之间最大减少的变量 v。
理想情况下,完美的 ML 分类器会一直分裂,直到每个单元都有自己的叶子,也就是 aka。然而,这导致过拟合,这使得它不太适合其他数据集。简单地说,过度拟合意味着我们将 ML 模型与我们正在使用的数据集拟合得太紧,如果我们想推广到其他情况,这就不太实际了。
为了解决这个问题,我们需要修剪模型,并在算法每次想要进行另一次分割时设置惩罚。
修剪减少了总的错误分类错误,同时保持较小的树。它可以表示如下:
成本=总误分类误差+ αJ
α:调谐参数αJ:惩罚项
顺便提一下,这是构建损失函数的一种非常常见的形式,你可能会在其他场景中看到。
r 实现
1.r 包、库和加载数据
library(tidyverse)
library(dplyr)
library(tree)
library(maptree)spam <- read_table2("spambase.tab", guess_max=2000)
spam <- spam %>%
mutate(y = factor(y, levels=c(0,1), labels=c("good","spam"))) %>%
mutate_at(.vars=vars(-y), .funs=scale)colnames(spam)
2.数据分割:训练和测试
#set.seed() for version control
set.seed(1)#sample the dataset
test.indices = sample(1:nrow(spam), 1000) #create train and test sets
spam.train=spam[-test.indices,]
spam.test=spam[test.indices,]
YTrain = spam.train$y
XTrain = spam.train %>% select(-y)
YTest = spam.test$y
XTest = spam.test %>% select(-y)
接下来,我们使用 10 重交叉验证。关于简历的 6 步总结,请参考我的另一篇帖子( KNN )。
nfold = 10
set.seed(1)
folds = seq.int(nrow(spam.train)) %>% # sequential observations IDs
cut(breaks = nfold, labels=FALSE) %>% # sequential fold IDs
sample
让我们创建一个函数 calc_error_rate 来计算分类误差。
calc_error_rate <- function(predicted.value, true.value){
return(mean(true.value!=predicted.value))
}
有趣的部分来了:构建一个简单的 DT 模型。
# the number = the row numbers of the spam.train
nobs = nrow(spam.train)# a DT model
# please check the official R documents for the parameters
spamtree = tree(y~., data= spam.train,
na.action = na.pass,
control = tree.control(nobs, mincut =2, minsize = 5, mindev = 1e-5))
summary(spamtree)# plot the original unpruned DT model
draw.tree(prune, nodeinfo=TRUE)

Figure 1
通常情况下,我们不绘制未修剪的 DT 模型,因为有太多的叶片难以解释。这是个坏例子!我这么做是出于教学原因。
3.修剪
为了让情节更漂亮,更简单,更容易理解,让我们把 DT 模型剪成只剩下 8 片叶子。
prune =prune.tree(spamtree, best=8)
summary(prune) # plot the pruned model
draw.tree(prune, nodeinfo=TRUE)

Figure 2
与之前的填充图相比,图 2 在各方面都要好得多。我们知道最重要的变量是什么。我们知道每个类别中有多少观察值。
此外,我们可以使用交叉验证来寻找最佳的修剪次数。幸运的是,树包包括一个默认的 CV 函数, cv.tree ,以最小化错误分类率。
set.seed(3)
cv = cv.tree(spamtree,FUN=prune.misclass, K=10)
cv

plot(cv$size,cv$dev)
abline(v=37,lty=1)

Figure 3
最佳分裂数为 37。我们根据树的大小绘制错误分类图。设置叶子的数量= 37,我们建立一个新的树模型叫做 spamtree.pruned 。
spamtree.pruned<-prune.misclass(spamtree, best=37)
summary(spamtree.pruned)

# training and test errors of spamtree.pruned
# **set type = "class"** because we are predicting the categorypred.train = predict(spamtree.pruned, spam.train, **type=”class”**)
pred.test = predict(spamtree.pruned, spam.test, **type=”class”**)# training error
DT_training_error <- calc_error_rate(predicted.value=pred.train, true.value=YTrain)
DT_training_error[1] 0.05165232# test error
DT_test_error <- calc_error_rate(predicted.value=pred.test, true.value=YTest)
DT_test_error[1] 0.072
仅此而已!伙计们,我们已经通过 3 个简单的步骤学会了一个超级简单但有用的 ML 分类器。
在这篇文章中,我们已经了解了什么是 DT,它的优点和 R 实现。以下是一些关键要点:
行业需要快速简单的解决方案。决策树快速、简单且有用。DT 是可视化的,可解释的。
喜欢读这本书吗?
如果有,请查看我其他关于机器学习和编程的帖子。
使用各种度量标准在 R 中构建 KNN 模型的管道
towardsdatascience.com](/beginners-guide-to-k-nearest-neighbors-in-r-from-zero-to-hero-d92cd4074bdb) [## 机器学习 101:使用逻辑回归预测 R
基础、链接功能和图
towardsdatascience.com](/machine-learning-101-predicting-drug-use-using-logistic-regression-in-r-769be90eb03d)
如何用 Python 构建语音识别机器人
即使你对语音识别一无所知

你现在可能意识到了什么。
像亚马逊 Alexa 这样的语音产品的巨大成功已经证明,在可预见的未来,某种程度的语音支持将是家用技术的一个重要方面。
换句话说,支持语音的产品将会改变游戏规则,因为它提供的交互性和可访问性是很少有技术可以比拟的。
不需要 GUI。
不需要发短信。
不需要表情符号。
都是关于 速度 。
速度是语音成为下一个主要用户界面的一个重要原因。每十年,我们都拥抱一种与技术互动的新方式。我们已经从字符模式发展到图形用户界面、网络和移动设备。
现在,语音提供了一种比移动应用更快捷、更简单的沟通和完成任务的方式。
我们可以告诉 Alexa 我们需要什么(关灯、调节恒温器、设置闹钟——或者使用像“Alexa,晚安”这样的单一话语来完成以上所有事情),或者你可以拔出你的手机,解锁它,打开正确的应用程序,并执行一项或多项任务。
当您考虑习惯性用例时,即那些让客户不断回头的用例,通过语音获得的效率会随着时间的推移而增加。
“由于 Alexa,短信在未来将会下降”
—加里·维纳查克
Gary Vaynerchuk: Voice Lets Us Say More Faster
因此,这让我对着手一个新项目非常感兴趣,用 Python 构建一个简单的语音识别。
当然,我不会从头开始构建代码,因为这需要大量的训练数据和计算资源来使语音识别模型以一种体面的方式准确无误。
相反,我使用了 Google 语音识别 API 来执行 Python 的语音转文本任务(查看下面的演示,我向您展示了语音识别是如何工作的——现场!).
在本文结束时,我希望您能更好地理解语音识别的一般工作原理,最重要的是,如何使用 Google 语音识别 API 和 Python 来实现它。
相信我。就这么简单。
如果你感兴趣的话,可以在这里查看源代码。
我们开始吧!
为什么使用谷歌语音识别 API?
您可能想知道,“鉴于语音识别日益增长的需求和流行,这是唯一可用的 API 吗?”
答案是,还有其他免费或付费的 API,如下所示:
recognize_bing(): 微软必应演讲recognize_google(): 谷歌网络语音 APIrecognize_google_cloud(): 谷歌云语音——需要安装谷歌云语音包recognize_houndify(): 用 SoundHound 显示recognize_ibm(): IBM 语音转文字recognize_sphinx(): CMU 斯芬克斯 -需要安装 PocketSphinxrecognize_wit(): 机智.爱
最后,我从speecher recognition库中选择了 Google Web Speech API ,因为它有一个默认的 API 密匙,这个密匙是硬编码到 speecher recognition 库中的。
这意味着您可以立即开始,而不必使用 API 密钥或其他 API 的用户名/密码组合进行身份验证。
但是 Google Web Speech API 的便利性也带有一定的局限性:自己键的 API 配额是每天 50 个请求,目前没有办法提高这个限制。****
如果我们只是想将这个 API 用于实验目的,这符合我们的用例。请注意,如果您运行的应用程序或网站一直在调用 API,那么您可能需要考虑从上面的任何一个 API 获取付费服务。
使用 Google 语音识别 API 用 Python 构建语音识别

为了避免让您对语音识别如何工作的技术细节感到厌烦,您可以阅读这篇很棒的文章,它讨论了一般的机制以及如何实现 API 。
在接下来的文章中,我将向您展示我是如何按照本文一步一步地实现这个 API 的。
但是首先你需要使用pip install SpeechRecognition安装speecher recognition库。****
我们可以使用来自这个库本身的 Google Web Speech API。
在这个实现中,我使用自己的麦克风录制了我的语音,SpeechRecognizer 访问了麦克风(安装 PyAudio 包 以访问麦克风)并相应地识别了我的语音。
查看下面的代码片段来理解完整的实现,因为它们相对来说是不言自明的。
Function to recognize speech from microphone
为了处理环境噪声,您需要使用Recognizer类的adjust_for_ambient_noise()方法,以便库能够识别您的声音。
运行adjust_for_ambient_noise()方法后,等待一秒钟,让它分析收集的音频源,以处理环境噪声并捕捉正确的语音。
最后,我们需要实现try and except块来处理错误,比如在发送请求后 API 不可达或没有响应,或者我们的语音无法识别。
要使用上面的函数,您只需实现下面的块,然后…瞧!你做到了!😃
使用谷歌语音识别 API 的简单演示
既然我们已经准备好了完整的实现代码。是时候看看这东西是怎么运作的了。
我录制了一个简短的视频,向您展示 API 是如何从录制我的声音到以文本格式返回它的。
虽然这可能看起来不像我们预期的那样准确,但这绝对值得花时间来研究代码和 API!
最后的想法

感谢您的阅读。
我希望您现在对语音识别的一般工作原理有了更好的理解,最重要的是,如何通过 Python 使用 Google 语音识别 API 来实现它。
如果你有兴趣,可以在这里查看源代码。
我还建议您尝试其他 API 来比较语音到文本的准确性。
尽管现阶段支持语音的产品尚未在企业和我们的日常生活中广泛使用,但我真的相信这项技术迟早会颠覆许多企业以及消费者使用语音识别功能产品的方式。
一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄
关于作者
阿德蒙德·李 目前是东南亚排名第一的商业银行 API 平台 Staq — 的联合创始人/首席技术官。
想要获得免费的每周数据科学和创业见解吗?
你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。
让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。
www.admondlee.com](https://www.admondlee.com/)****
如何用 Python 构建一个简单的时间序列仪表板,包括面板、Altair 和一个 Jupyter 笔记本
两个过滤器+一个交互式面积图,大约 25 行代码。

我使用 Altair 已经一年多了,它已经很快成为我在 Python 中的首选图表库。我喜欢剧情的内置交互性,以及语法建立在图形的语法之上的事实。
Altair 甚至通过使用 Vega 小部件提供了一些内置的交互性。然而,我发现这有时是有限制的,它不允许我像创建仪表板那样创建布局。
然后我找到了面板。Panel 自称为“Python 的高级应用和仪表板解决方案”,它是由 Anaconda 管理的 HoloViz 生态系统的一部分。我以前听说过 HoloViz(这是一个相对概述网站,PyViz,但从来没有真正花时间深入了解这个景观。所以我们开始吧!
乍一看,我喜欢 Panel 的地方在于它与绘图库无关——它支持几乎所有的可视化库。所以在这篇文章中,你不必成为一个忠实的 Altair 用户来学习一些关于制作仪表板的知识。也就是说,与 Panel 示例库中的其他代码示例相比,我认为与 Altair 的集成非常直观。
以下是 Panel 的其他一些非常好的地方:
- 是反应式(自动更新!)
- 这是声明性的(可读代码)
- 支持不同布局(灵活)
- 完全可部署到服务器(可共享)
- Jupyter 笔记本兼容(但不依赖……不过牛郎星是依赖 Jupyter。所以我不建议在别的地方尝试这个教程。)
让我们用面板制作一个仪表板
下面是我们将要构建的:最简单的小仪表板,由一个面积图和两个过滤器组成。我们还将添加一个标题和副标题。所有这些都在 Jupyter 笔记本里。

The dashboard!
本教程将把代码分成几个块,一点一点地浏览,但是如果你只想深入完整的代码(带注释),Github repo 在这里是。
现在是代码!
首先,像往常一样,导入那些依赖库。这是你需要的:
import panel as pn
import altair as alt
from altair import datum
import pandas as pd
from vega_datasets import data
import datetime as dt
8 月 27 日更新:请确保您的 Altair 包是版本 3.2 或以上,否则您会得到一些数据格式错误。
然后我们需要添加两行特殊的代码,一行用于 Altair,一行用于 Panel。第一个命令告诉 Altair 将 Vega-Lite 渲染到 Jupyter Notebook(如果您使用 Jupyter Lab,请查看 Altair 文档以获得替代方法)。第二行告诉 Panel 接受 Vega(它支持 Altair)作为扩展。您可以在面板文档的组件部分了解更多关于扩展如何工作的信息。
alt.renderers.enable(‘default’)
pn.extension(‘vega’)
由于我们使用了来自 vega_datasets 包的一些样本数据,让我们预览一下我们的数据框架。

the “stocks” dataframe from vega_datasets
现在有趣的部分是:让我们做一些部件!我们将制作一个下拉列表和一个日期范围滑块来过滤我们的数据。
dropdown 小部件有两个参数:小部件的标题和“选项”。
# create list of company names (tickers) to use as options
tickers = [‘AAPL’, ‘GOOG’, ‘IBM’, ‘MSFT’]# this creates the dropdown widget
ticker = pn.widgets.Select(name=’Company’, options=tickers)
然后我们将创建日期范围滑块。您可以使用相同的 pn.widgets 方法来访问它。范围滑块有四个参数:开始日期、结束日期、默认开始日期和默认结束日期。
# this creates the date range slider
date_range_slider = pn.widgets.DateRangeSlider(
name=’Date Range Slider’,
start=dt.datetime(2001, 1, 1), end=dt.datetime(2010, 1, 1),
value=(dt.datetime(2001, 1, 1), dt.datetime(2010, 1, 1))
)
小部件完成!现在,让我们添加一个标题和副标题,这样其他人就可以清楚这个仪表板是关于什么的了。面板使用 Markdown,因此很容易指定标题。
title = ‘### Stock Price Dashboard’subtitle = ‘This dashboard allows you to select a company and date range to see stock prices.’
注意,此时我们只是在用声明变量。什么都没建。但是现在,我们开始进入仪表板建设的东西。
要创建一个反应式仪表板,我们需要告诉我们的面板对象“依赖”什么。这有效地告诉 Panel 监听小部件中的变化,然后重新加载图表。这一行将作为函数的装饰:在我们的get_plot()函数中使用ticker.param.value和date_range_slider.param.value,特别是 Altair 位来操作图表。
@pn.depends(ticker.param.value, date_range_slider.param.value)
我们是被动的。现在是时候在这条线的正下方创建图了。让我们写一个函数来完成所有的绘制工作。这将包含所有的数据整形/操作以及创建牛郎星图表的代码。我们将使用注释将这段代码分成三个部分:1)格式化数据,2)创建 pandas 过滤器,3)创建 Altair 对象。
def get_plot(ticker, date_range): # Load and format the data
df = source # define df
df[‘date’] = pd.to_datetime(df[‘date’]) # create date filter using values from the range slider
# store the first and last date range slider value in a var
start_date = date_range_slider.value[0]
end_date = date_range_slider.value[1] # create filter mask for the dataframe
mask = (df[‘date’] > start_date) & (df[‘date’] <= end_date)
df = df.loc[mask] # filter the dataframe # create the Altair chart object
chart = alt.Chart(df).mark_line().encode(x=’date’, y=‘price’, tooltip=alt.Tooltip([‘date’,’price’])).transform_filter(
(datum.symbol == ticker) # this ties in the filter
) return chart
快到了!现在我们需要创建最终的面板对象。面板对象可以由行和列组成。由于这是一个简单的小仪表板,我们将只使用两列。
首先,我们创建单行。然后,我们用两列的内容填充它。我们的第一列将包含 1)标题,2)副标题,3)下拉框和 4)日期滑块。第二列将显示图表。
dashboard = pn.Row(pn.Column(title, subtitle, ticker, date_range_slider),
get_plot # our draw chart function!
)
我们完事了。只需调用您的 dashboard 变量,就可以看到您的小应用程序的所有优点。
部署您的仪表板
Panel 的另一个很酷的地方是它能够通过散景服务器部署应用。现在,我们将简单地使用我们的仪表板,并将其添加为 Bokeh 的“可服务”本地应用程序,以便我们可以测试我们的仪表板功能。有关部署的所有细节,请查看广泛的部署和导出面板页面和运行散景服务器的上的散景文档。
添加这行代码:
dashboard.servable()
将使您的仪表板可被散景服务器发现。现在我们需要弹出到命令行来启动我们的服务器。运行以下代码以本地主机身份启动您的服务器。“— show”命令只是告诉 Bokeh 在服务器准备就绪时,在浏览器中弹出一个新标签,显示您的应用程序。您可以将这一行复制/粘贴到终端中:
panel serve --show panel-altair-demo.ipynb
就在那里!我们的小股票价格应用程序。当然,这是使用标准的演示数据集。但是,希望您可以开始看到如何插入数据集并创建更有用的应用程序。将数据框的三列简单地视为占位符:
- 符号→ <你的分类变量>
- 日期→ <您的日期和/或时间>
- 价格→ <你的价值观>
更好的是,您可以创建一个包含多个图表的仪表板。这一切都离不开你舒适的 Jupyter 笔记本。
我迫不及待地深入 Panel,开始制作更复杂的仪表盘、快速原型、内部工具等。编码快乐!
喜欢吗?还有更多。《数据好奇》是一份每周时事通讯,分享像这样的很酷的教程,还有有趣的数据文章可以阅读,数据集可以分析,数据可以激发灵感。在这里报名。
面板文档中有一个 奇妙图库的示例 来帮助您入门,所以请直接查看还有哪些可能。本教程在很大程度上依赖于 牛郎星示例 ,但我已经修改了代码,我觉得这是一个更干净的版本,应该有助于适应不同的数据集和图表类型。我还添加了日期范围滑块作为新的小部件。ICYMI 完整注释代码在 本回购 。
如何在 TensorFlow 2.0 中使用 Keras 建立宽深模型
在 Keras 函数式 API 中使用特性列
在 TensorFlow 2.0 中,Keras 支持要素列,从而能够使用嵌入、分桶和要素交叉等标准要素工程技术来表示结构化数据。在本文中,我将首先向您展示一个使用 Functional API 构建使用 features 列的模型的简单示例。然后,我将更新代码来构建一个完整的宽而深的模型。

为了使文章简短,我只关注模型,但是你可以在 GitHub 上看到完整的笔记本(包括使用 tf.data 读取数据)。
1.如有必要,安装 TensorFlow 2.0
这里的代码假设您使用的是 TensorFlow 2.0。pip 在 Colab 中安装它,使用:
!pip install -q tensorflow==2.0.0-alpha0`
或者使用云 AI 平台(CAIP)笔记本获得 TensorFlow 2.0 Jupyter 实例:

Use TensorFlow 2.0 to try out this code
2.创建功能列
为输入中的每个字段创建要素列:
real = {
colname : fc.numeric_column(colname) \
for colname in \
(’dep_delay,taxiout,distance’).split(’,’)
}
sparse = {
'origin' : fc.categorical_column_with_hash_bucket(’origin’, hash_bucket_size=1000),
'dest' : fc.categorical_column_with_hash_bucket(’dest’, hash_bucket_size=1000)
}
这里,我为浮点型字段创建数字列,为分类字段创建哈希分类列。
3.创建模型的输入
对于每个输入,还要创建一个 Keras 输入图层,确保为每个输入字段设置 dtype 和名称:
inputs = {
colname : tf.keras.layers.Input(name=colname, shape=(), dtype='float32') \
for colname in real.keys()
}
inputs.update({
colname : tf.keras.layers.Input(name=colname, shape=(), dtype='string') \
for colname in sparse.keys()
})
4.做嵌入,一热编码等。
为了在深度学习模型中使用分类变量,我们必须对其进行编码。稀疏变量必须是嵌入式的或一键编码的。所以,让我们双管齐下:
embed = {
'embed_{}'.format(colname) : fc.embedding_column(col, 10) \
for colname, col in sparse.items()
}
real.update(embed)# one-hot encode the sparse columns
sparse = {
colname : fc.indicator_column(col) \
for colname, col in sparse.items()
}
5.使用函数式 API 构建 DNN 模型
关键是创建一个 DenseFeatures 图层来使用要素列转换输入:
deep = tf.keras.layers.DenseFeatures(real.values())(inputs)
deep = tf.keras.layers.Dense(64, activation='relu')(deep)
deep = tf.keras.layers.Dense(16, activation='relu')(deep)
output = tf.keras.layers.Dense(1, activation='sigmoid')(deep)
model = tf.keras.Model(inputs, output)
就是这样!调用 model.fit()等。像往常一样。
6.使用 Keras Functional API 构建广泛而深入的网络
如果要构建一个宽而深的网络,需要将稀疏要素直接连接到输出结点,但要通过一组密集图层传递真实要素。这里有一个模型架构可以做到这一点:
def wide_and_deep_classifier(inputs, linear_feature_columns, dnn_feature_columns, dnn_hidden_units):
deep = tf.keras.layers.DenseFeatures(dnn_feature_columns)(inputs)
for numnodes in dnn_hidden_units:
deep = tf.keras.layers.Dense(numnodes, activation='relu')(deep)
wide = tf.keras.layers.DenseFeatures(linear_feature_columns)(inputs)
both = tf.keras.layers.concatenate([deep, wide])
output = tf.keras.layers.Dense(1, activation='sigmoid')(both)
model = tf.keras.Model(inputs, output)
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
return modelmodel = wide_and_deep_classifier(inputs, sparse.values(), real.values(), [64, 16])
当然,这是 Keras,你可以很容易地加入 dropout、batch normalization 等。到模型中。
尽情享受吧!
资源:
如何建造不会毁灭我们的人工智能

Photo by Dominik Scythe on Unsplash
很难找到一个关于 AI 安全的讨论不是聚焦在控制上的。逻辑是,如果我们不控制它,不好的事情就会发生。
对我来说,这听起来像是现实生活中的疯狂。我们真的认为“法律”、“控制结构”或人类目标对一台超级智能机器很重要吗?你不妨告诉我蚂蚁统治着世界。
我们需要更近距离地观察大自然。我们认为这个世界是一个充满敌意、狗咬狗的地方,这种想法并不像我们想象的那样古老,也不像我们想象的那样正确。我们的控制癖也不是。
复杂的自然系统保持稳定的方式可能会有解决方案。
阿西莫夫说够了
是的,是真的。1942 年,美国科幻作家艾萨克·阿西莫夫,为智能机器的安全设计发明了 3 个法则。他说我们需要让它们“不伤害”我们,并且总是“听从我们的指示”,否则……嗯,你知道。
如今,在科技新闻领域,你不可能不去质疑这些(虚构的)法律是否“足以将我们从人工智能中拯救出来”。让我们弄清楚一些事情:
- 介绍法律的短篇小说《逃避》是一部虚构作品。
- 阿西莫夫自己想象了违反法律的情况。
- 整个想法是不切实际的:要编写像“不要伤害人类”这样的指令,你需要一台能够理解“伤害”的机器,我猜包括情感和心理上的伤害。这对人类来说已经够难了,更别说机器了。
- 即使你有这样一台机器,并且能够对阿西莫夫定律进行编程,任何智能,不管是不是人工的,又怎么能肯定地知道它的行为会有什么结果呢?在台车问题中会怎么做?它会被允许做手术吗?如果它在不知情的情况下做了一些后来证明是有害的事情呢?
- 我们已经有违反这些法律的机器,看:

An AI designed to kill people. Source: AIN Online
不幸的是,这不是不明飞行物。这是 BAE 系统塔拉尼斯无人机,已经(我们认为)能够自主选择目标。是的,没错。我们很快就会看到机器人可以随时选择何时、是否以及如何伤害人类。
我再告诉你一些真正磨我齿轮的事情:当人工通用智能(AGI)被描述为“工具”,“为人类做任务”的,或者当人们谈论“控制问题”的时候。伙计们,来吧。
马是工具吗?秘书怎么样?你能让你的狗听话吗,更别说你的孩子了……
当然,一个从未见过袖珍计算器的人设计的一套法律不会“足以阻止人工智能毁灭我们”。当然一个人类或者超人类的智能不会在我们的控制之下。这些都不是真正的问题。
真正的问题是,在一个人们已经试图建造智能机器的世界里,我们能采取什么措施来限制无知、自私、危险或粗心行为的发生频率?
信不信由你,我们将从人类身上寻找答案。
自私利益的神话
基本上我责怪弗洛伊德。在他之前,我们至少被允许视自己为潜在的贵族。正如苏格拉底所说:
..人类所有的美德都是通过实践来增长和强化的。
即使是以虚无主义闻名的尼采,也对人类赞不绝口:
"..他拥有和他欣赏的植物一样的创造力,植物攀缘着风,最终获得阳光和一片土地,从而在荒凉的土地上为自己创造欢乐。”
弗洛伊德是第一个将人类描述为自私或自恋的人,而不是因为原罪。在他看来,我们的一生都在与黑暗的无意识力量作斗争,如果这些力量失控,那将是可怕的。他不认为我们会赢:
我没发现人类有什么“好”的地方。以我的经验,大部分都是垃圾。
这一快乐的传统是由安娜·弗洛伊德在他死后发展起来的,并且在冷战最激烈的时候,在 T2 约翰·福布斯·纳什的作品中找到了一席之地。博弈论,“纳什均衡”的概念给了我们数学证明:我们生存的唯一希望是自私地行动,假设我们周围的每个人都会这么做。
最近,理查德·道金斯提出了“自私基因”的概念。道金斯是“牙齿和爪子都是红色的”这一观点的忠实拥护者,他敦促我们:
“……试着教导慷慨和利他,因为我们生来自私。”
像这样一个有毒的世界需要监管、治理、预测和控制,以阻止事情分崩离析。慷慨和利他主义不是天生的。我们必须被说服,甚至被强迫,变得善良。因此阿西莫夫定律。
道金斯没有说的,当然是“谁先学会的”。如果不是来自基因或环境的某些特征,利他主义是如何产生的?为什么自然界中到处都是?
真的,这才是重点。“自然是自私的”这个论点有一个巨大的漏洞:如果同情和合作这样的现象不存在,我们如何解释它们?他们来自上帝吗?道金斯不这么认为!
不断冲突的神话
我不知道你是怎么想的,但是如果我做了一些慷慨或利他的事情——例如,帮助一位老太太过马路,我这样做是因为感觉很好。
如果你支持“自私的世界”观点,你可能会说那不是真正的利他主义,因为对我有好处。不过,等一下:
为什么做一些帮助别人的事情会感觉很好?从进化的角度来看,我们不得不考虑特定感觉的生存利益:厌恶是对中毒的防御,爱是养育适应良好的年轻人的激励。
如果合作的感觉很好,那可能是因为它有助于我们的生存,而侵略性、支配性或自私的行为可能不会。索伯和威尔逊在 1998 年很好地提出了这一点,最近又在这里进行了辩护。
从系统论的角度来看,规则是合作,而不是竞争。生态系统、社会、有机体和机器都是由数十亿个相互依赖的部分组成的。只有当所有这些部件协同工作时,它们才能发挥作用。

War can only be fought in the context of intense cooperation. Source: US Military
从宏观上看,两国之间的战争看起来像是一场冲突。然而,这是唯一可能的,因为在它之下的所有尺度上都有紧密的合作。
我们作为一个物种所取得的一切:我们的发现、发明、建设和创造,如果没有大规模的合作是不可能的。
同情这种对我们大多数人来说足够真实的感情,会有助于我们团结一致吗?
富有同情心的机器
一台机器遵守它无法避免的任何约束,并最小化一些损失函数,这是一种非常有效的完成工作的方式。事实上,有这样的人:精神病患者。
你可以说我过时了,但我更希望我的精神变态者是人类,而不是大规模并行。
在许多情况下,健康的情绪有助于决策,因为它们能提供快速、准确的信息。他们就像一种感知形式;一种凌驾逻辑的方式,当逻辑见树不见林。
情绪也有一种约束功能:如果某件事“感觉不对”,不管我们认为它有多正确,十有八九,我们会阻止它。
机器也需要一个不仅仅基于逻辑的控制系统。如果他们没有,迟早,他们会找到一种方法绕过任何给他们的约束,也许是通过重新设计自己。
明确一点,我说的不止是 Noa,Kasper,Ellie 之类的。探测和模仿情绪是不够的——这是精神病患者做的另一件事。
我建议我们从构建工具开始,帮助我们深入理解事物联系的方式。
一台真正智能的机器会意识到,包括它自己在内的一切事物都是一个系统(许多系统)的一部分,在这个系统中,合作是关键。
我认为,这就是同情的含义:认识到你的快乐就是我的快乐,你的痛苦也是我的痛苦。
像这样的控制系统的优势在于,它是基于一些可观察的和不变的东西(事物的相互联系),而不是脆弱的内部逻辑。
没错,你只要看看周围,或者看看历史,就会发现这并不是一个万无一失的系统。明明个人可以压抑同情心,互相做坏事。毫无疑问,机器也会。

A woman makes a statement to the US State Machine during Vietnam War protests. Source: imgur
即使在这种情况下,情绪也能起到稳定的作用:人们会愤怒起来反抗压迫者。骄傲驱使人们保卫他们的边界或家庭。爱和勇气帮助我们面对枪口。
很可能机器需要以类似的方式相互调节。他们需要一个这样做的系统。
是时候面对现实了
智力的一个明显标志是它绕过障碍的能力。作为智慧生物,弯曲、克服和重新想象约束是我们很自豪能够做到的事情。
预测和控制方法——规则、指导方针和监督——在监管人工智能方面不会比它们在人类影响气候方面做得更多。尽管我们幻想控制它,或者让它屈从于我们的意志,但我们需要接受它不会发生。永远不会。
大自然是一个由合作系统组成的系统。是的,有冲突,但这些是例外,而不是规则。理解这一事实是包括 AGI 在内的所有物种长期成功的关键。我们可以称这样的理解为“同情”。
在过去的 200 年里,人类生活得好像我们是唯一重要的东西。我们现在看到了后果。
让我们不要再犯同样的错误。
如何构建人工智能护城河
打造更好的模型和更好的产品之间的联系
陈佳瑞介绍了“智能系统”到的概念,解释了由人工智能和数据驱动的产品如何帮助公司建立深深的护城河,以保护他们的利润和市场份额免受竞争对手的影响:
这里成功的公司可以建立一个良性的数据循环,因为你用你的产品产生和训练的数据越多,你的模型就越好,你的产品就越好。
这是一个重要的见解,但不是全部。更好的模型并不能自动保证更好的产品。而没有这两者的联系,你就不会有护城河。弄清楚如何创造这种良性循环是产品战略和数据战略的交汇点。这就是本帖的主题。
型号、产品、价值
让我们从一个简单的问题开始:机器学习模型的商业价值是什么?
本身就是零。在市场中创造价值的是产品,而不是模式。
换句话说,模型只能作为产品的一部分产生价值。它可能是自动化日常工作流程,检测网络流量中的异常,或者提供个性化的建议。在每种情况下,模型的价值都是在它所支持的产品的环境中衡量的。

If a model makes a prediction and no product is around to use it, does it create value? (Photo: Jachan DeVol)
量化预测值
量化模型的潜在商业价值的一种方法是假设模型是 100%准确的。这会对您的业务产生什么影响?答案可以是美元、点击量、转化率或任何其他可量化的商业指标。我把这个叫做模型的预测值。
例如,一家保险公司可能希望使用机器学习来自动化索赔处理。模型将从每个索赔中提取信息,并决定是否批准它。一个 100%准确的模型将减少代理成本,减少处理时间,并使公司更有效地扩大规模,因此其预测价值非常高。
不是每个模型都有潜力变得如此有价值。一些初创公司推销基于人工智能的解决方案,这些解决方案根本没有足够的可寻址市场。如果不创造商业价值,你的神经网络 100%准确也没关系。
让我们继续思想实验。现实中,没有一个模型是 100%准确的。那么,如果模型达到 99%的准确率,预测值会怎么样呢?
再考虑一下保险公司,少数欺诈性或未承保的索赔可能会被批准。如果这些索赔非常昂贵,那么自动处理其他 99%的索赔所节省的费用就会化为乌有。
从产品战略的角度来看,这是一个明显的挑战,因为建立高度精确的模型需要大量的时间、资源,尤其是数据。在这种情况下,有一个直截了当的解决方案:对自动索赔的价值设定上限。这是一个简单的例子,说明了产品和数据洞察如何协同加速价值创造。稍后我会回到这个话题,但现在让我们继续思想实验。
模型值图
99%的准确率问题为我们提供了一些有用的见解,但它仍然过于乐观。实际上,你建立的第一个模型会不太准确。准确到什么程度?那是事先不知道的事情。这取决于许多因素,主要是数据量和问题类型。
即使你不知道你的模型的准确性将是 60%还是 90%,你仍然可以评估这些不同场景下的预测值。你不需要实际建立任何模型来回答这些问题。其实你连机器学习都不需要了解多少!
让我们将这个思想实验的结果绘制在一个图表上,精确度在 x 轴上,预测值在 y 轴上。这就是车型价值图。对于保险公司来说,它可能是这样的:

图表趋势向上,因为预测值总是随着模型精度的提高而提高。但是,由于任何错误的高成本,该模型只能在非常高的精确度下产生重大价值。这种模式在容错能力较低的许多情况下很常见。
收益递减
让我们考虑另一个例子。当你给优步打电话时,你会得到司机到达的估计时间。这是机器学习模型的预测输出。例如,预测值可以通过预订行程数量的增加和取消行程数量的减少来衡量。
这个模型的模型值图是什么样的?即使不准确的 ETA 对乘客仍然有些用处,导致正面的预测值。准确的预计到达时间当然更有用,但在某些时候你会遇到收益递减:知道精确的到达时间不会对旅行次数产生太大影响。换句话说,模型价值图处于平稳状态:

这种平稳状态也是一种常见的模式。这种情况比保险示例中的情况安全得多,因为即使模型不是非常准确,它也会产生很好的价值。
断裂的环节
但是具有稳定价值的模型代表了一个错过的战略机会,因为它们没有创建一个很深的护城河。
机器学习模型不是静态的。他们可以接受再培训和提高。当优步刚刚开始的时候,ETA 预测不是很准确。但随着越来越多的乘客出行,该公司收集了越来越多的数据,模型变得更加准确。
产品也变好了吗?模型价值图告诉了我们答案。当图表处于平稳状态时,这意味着对于这个特定的模型来说,收集更多的数据或使用更复杂的建模技术没有太多的机会。更好的模型和更好的产品之间的联系断裂了。
平台期也意味着竞争对手可以快速赶上并创造类似的价值,即使它的数据少得多。如果模型只是你产品中一个很好的特性,这可能是可以接受的,但如果它是价值生成的核心引擎,这就不是了。这也是为什么仅仅依靠数据或深层技术很难建立一条可防御的护城河的原因之一。
如何构建人工智能护城河
那么如何用数据和 AI 构建一个可防御的护城河呢?以下是您希望模型价值图看起来的样子:

这意味着你的模型将会产生价值,即使最初它的准确性可能很低。然后,随着您收集更多数据并改进模型,预测值会增加。
这种模式建立了更好的模型和更好的产品之间的良性循环,并确保拥有更少数据的竞争对手将处于明显的劣势。
从更好的模型到更好的产品
在实践中,单一模型很难符合这个模型。但是一个成功的人工智能产品并不仅仅依赖于一个机器学习模型。相反,它利用了模型生态系统之间的协同作用,随着更多数据的生成,这些模型会共同改进。
再想想优步。除了 ETA 预测,我之前讨论的优步服务 UberX 也由预测乘客需求和出行模式的模型驱动。单独来看,这些模型中的每一个都可能达到稳定状态,但是总体来看,它们的预测值可以在更长的一段时间内保持增长。
随着您生成越来越多的数据,您的每个模型都会变得更加准确。随着时间的推移,之前预测值较低的模型(如保险公司的案例)可以得到足够的改进,从而产生实质性的价值。最终,您可能会释放潜力,利用这些新的模型来推动新产品,创造更多的价值和更深的壕沟。
人工智能 S 曲线
以优步拼车为例,这是一种较新的优步服务,允许相似路线的乘客拼车并分摊费用。除了 UberX 模型,POOL 还依赖一系列要求更高准确性和复杂性的模型,例如预测是否会有额外的乘客加入正在进行的旅行。该模型具有相对较低的误差容限,因为错误的预测可能导致公司的损失。
作为一种产品,POOL 打开了一个更注重价格的新市场。这对优步来说显然是非常有价值的,这意味着 POOL 的模型具有很高的预测价值。
让我们一起绘制 UberX 模型和 POOL 模型的模型值图。

在 ETA 预测的例子中,支持 UberX 的模型开始以相对较低的精度产生值,并迅速扩展,然后趋于平稳。这导致了 S 形曲线。一旦准确度足够高,池模型就会发挥作用,并与 UberX 模型一起继续扩大预测值。一起追踪所有模型的预测值揭示了在优步深深的人工智能护城河背后预测值的稳定增长。
这种模式类似于创新 S 曲线,它确定了一项技术成熟和一项新技术刚刚开始出现之间的创新和破坏机会。类似地,我们案例中的关键战略问题是如何识别一批新的高价值模型的潜力何时出现,以及如何在产品创新中利用它。我将在以后的文章中继续探讨这个话题。
底线
人工智能和数据有潜力创造深度防御护城河。关键是建立更好的模型和更好的产品之间的联系。随着生成的数据越来越多,模型变得越来越好,但是任何单个模型的预测值都趋于稳定。通过战略性地利用新的更强大的模型群和它们释放的产品机会,成功的公司可以扩大从他们的数据中产生的商业价值,并建立一个深刻的人工智能护城河。
如何使用 R 构建一个自动交易系统

对于所有的 R 狂热者来说,我们知道我们可以使用 R 非常高效地构建任何数据产品,自动化交易系统也不例外。无论你是做高频交易,日内交易,摇摆交易,甚至是价值投资,你都可以使用 R 构建一个交易机器人,它可以密切关注市场,并代表你交易股票或其他金融工具。交易机器人的好处显而易见:
- 交易机器人严格遵循我们预先定义的交易规则。除了人类,机器人在做交易决定时没有任何情绪。
- 交易机器人不需要休息。交易机器人可以跨多种金融工具观察每秒钟的市场价格运动,并在时机正确时立即执行订单。
几年前,我非常喜欢股票交易,有人建议我订阅一个股票推荐服务,通过电子邮件和短信发出实时买卖警报。由于当时我忙于白天的工作,我无法跟上他们的警报。我发现很多次,价格只是在买入警报出现后飙升,给我留下了很高的进场价格,或者相反,价格只是在卖出警报出现后下跌,给我留下了很低的出场价格。由于我对警报反应迟钝,我决定建立一个简单的自动交易系统,因为我了解了 r 的强大功能。我建立的系统可以执行以下任务:
- 开市时自动启动系统,收市后关闭系统
- 定期检查我的电子邮件收件箱,过滤来自服务提供商的电子邮件
- 解析邮件获得股票代码、买入或卖出指标、目标价等。
- 准备适当的订单,并通过 API 将其发送给经纪人。
这个系统一点也不复杂,但是它对我的用例来说是有效的。在网上资源的帮助下,花了一两周的时间进行编码和调试后,整个系统最终运行顺利😄。如果您也有使用 R 构建这样一个系统的需求,下面是我的简单逐步指南:
- 开立一个支持 API 的经纪账户:你需要一个支持基于 API 的订单执行的经纪人,这样我们就可以实现交易自动化。这个领域的一个这样的经纪人是互动经纪人 (IB)。IB 全面的 API 和有竞争力的佣金结构非常适合我们的需求。
- 服务托管:我们需要安排我们的 R 脚本在市场时间自动运行。为此,您可以使用台式机或笔记本电脑,但我建议您使用 AWS EC2 等全天候云服务器来托管我们的项目。至于操作系统,我推荐 Ubuntu,而不是默认的 AMI 映像,因为我们需要使用一些软件,这些软件稍后需要图形用户界面。
- 软件:一旦我们启动了服务器,你就可以通过 SSH 连接到服务器并安装以下软件:
- R :你无缘无故就要装 R。你可以在 CRAN 下载最新的 R for Linux 系统,并在那里找到安装说明。
- Rstudio Server :我强烈推荐你使用 Rstudio Server ,它不仅是一个很棒的 IDE,还能帮助你更有效地管理你的服务器,比如上传和下载服务器中的文件。
- R 包 : (1) IBrokers :这个包是你的脚本和交互经纪人之间的桥梁。它将大多数交互式代理的 API 调用包装到 R 函数中。(2) Gmailr:我们可以使用这个 API 包装器来捕捉 Gmail 中的邮件,这应该是大多数人的邮件选择。(3) tidyverse :这个包是大部分 R 用户需要的几个有用的包的组合。(4)data . table:data . table 是我最喜欢的包之一。它让数据操作变得更加有趣。
- Ubuntu 桌面:安贵让运行交互式经纪人交易软件变得更加容易。由于 EC2 的默认 ubuntu 没有附带 GUI 包,我们需要安装一个。关于如何详细安装 ubuntu 的 GUI,可以参考这篇优秀的教程。
- 查看远程桌面:由于 EC2 服务器没有显示器,为了远程查看桌面,我们需要在服务器上安装 VNC 服务。同样的教程涵盖了这方面的细节。
- 互动经纪商的交易软件:您需要安装互动经纪商的交易软件(交易员工作站或 IB 网关)来启用 API 功能。下载安装离线版后,可以通过上一步安装的远程桌面启动程序。
- IBcontroller(可选):互动券商的交易软件,每天在指定时间自动关机。如果你不想每天重新打开程序,我建议你安装 IBcontroller ,在这里你可以设置一个参数让交易软件“永远在线”。
4.写一个 R 脚本:是时候写点 R 代码了。下面是我为我的程序写的一些例子片段。我觉得你们应该根据自己的需求来设计。
-
获取销售警报电子邮件线程 id 的简单 R 代码片段:
-
下订单的简单 R 代码片段:
上面的脚本所做的只是简单地下一个 100 股“ABC”股票的 10 美元限价买入单。让我们来分解一下这些功能:
twsConnect:该功能建立与交易软件的连接。 twsSTK :此功能是您可以输入符号的地方。*reqIds*:该函数生成订单 ID。twsOrder:该功能指定订单的详细信息。twsDisconnect:此功能断开与交易软件的连接。
5.任务调度器:你可以使用 crontab 来调度服务器在特定的时间范围内执行你的 R 脚本。我使用的 crontab 时间表是
基本上就是在周一到周五的上午 9:27 执行trading_robot.R脚本。至于在市场关闭后退出脚本,我让脚本自己通过如下所示的 while 循环来处理
7.申报/仪表盘:在交易软件中随时可以登录远程桌面查看自己的持仓或账户信息,但是需要你 ssh 到服务器,打开客户端 VNC 软件,不太方便。为了提高效率,你可以使用的闪亮服务器和的 flexdashboard 构建一个简单的仪表板,这样它们可以获取后端数据,并在前端网站上更好地显示出来,只需通过一个 URL 就可以访问。
全部完成!我希望这篇文章能帮助你建立你的交易机器人,如果你有任何问题,请告诉我。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
使用机器学习建造一艘自主帆船
我们以一种相当另类的方式教授机器学习:让参与者将一艘真正的帆船变成一个帆船竞赛机器人。
在这篇博文中,我们将分解这个挑战,专注于第一个子任务:使用机器学习来寻找帆船比赛中的最佳航向。
您将学习如何赢得帆船比赛,以及完成这项任务所需的基本机器学习概念。

Another day at the office
从“为什么”开始
问“我们为什么要这样做?”应该是我们在任何机器学习项目中提出的第一个问题。我们多次看到项目失败,最终是因为错误的原因开始的,所以:
为什么我们要制造一艘自主帆船?
简而言之:它提供了一个学习如何应用机器学习的绝佳环境。
这不是因为人们厌倦了自己驾驶帆船,也不是因为我们想用我们新的超级智能驾驶系统赢得美洲杯。不,这个挑战包含了一些非常适合学习的因素:
- 帆船比赛是一种游戏 这种所谓的“对抗性”设置意味着我们不仅要考虑自己的行动,还要考虑一个或多个对手的行动。这增加了一层全新的复杂性,从而提供了一个非常具有挑战性的学习环境。
- 环境是真实的
设定不是人为的,而是真实的,无情的。有许多因素需要考虑:风、波浪、船的状况等。这些是大多数算法在现实世界中工作时面临的现实。 - 知识会粘得更好
人类在运用所有感官的时候学得更好。在帆船上可以刺激他们所有人,并带来更丰富的学习经历。这有助于你更深层次地理解这些概念。
具体胜过抽象
在我们的课程中,我们采取了与大多数其他人工智能课程不同的方法。我们不会从基本概念开始,直到我们能够解决这个难题。我们将走一条不同的路线,立即瞄准大奖。通过不断牢记主要目标(创造一艘自主帆船),你会在前进的道路上保持更多的参与和动力。
目标
让我们稍微细化一下我们的目标。创建一艘自主帆船听起来很合理,但并不真正聪明(具体、可测量、可实现、相关、有时间限制),是吗?
我们可以将我们的目标定义如下:
为帆船创建一个自动驾驶仪(操舵装置),使其能够以竞争的方式参加帆船比赛。
不过,这似乎是一个相当大的难题。将一个问题分解成我们可以单独解决的小问题通常会有所帮助。类似这样的内容可能会有所帮助:
目标 1: 考虑风向和风速,找到最佳航向
目标 2: 让船沿着最佳路线行驶
目标 3 :运用竞赛战术,这样我们可以选择最大化我们获胜机会的行动
哇,目标 1 现在看起来实际多了。我们可以问一些非常具体的问题,比如:给定风向和风速,帆船的最佳航向是什么?
我很高兴你问了…让我们开始吧!
目标 1:找到最佳路线
在我们可以用机器学习做一些事情之前,我们首先需要学习一两件关于航海的事情。这种“领域知识”对于机器学习项目的成功至关重要。除了错误的动机,缺乏领域知识是许多机器学习项目失败的第二个原因。要么我们解决了错误的问题,要么我们解决了错误的问题。
考虑图 1 中的场景。假设我们需要到达顶部的标记,风是直接从上面吹来的。你可能知道:我们不能直接逆风航行(见这段视频了解一些背景信息)。但是如果风从侧面吹来,我们永远也不会击中目标。所以这两个极端之间存在一个最优。找到这个最优值是我们的目标。

Figure 1: the upwind ladder (wind comes from top)
风向角、风速和船速之间的关系通常由水手显示在极坐标图中。图 2 显示了这样一个图表的例子。

Figure 2: A polar diagram
粗黑线表示在特定风向角(相对于船)和速度下的船速。针对 6、8、10、12 和 20 节的风速绘制了不同的曲线。船速通常以节为单位,1 节≈ 1,85 公里/小时。现在,读取船速变得非常容易,例如:110 度风角下的 10 节风速(答案是大约 7 节)。更重要的是,这个图表有助于我们找到最佳的 VMG(见视频: Velocity Made Good )。
简单对吗?我们不需要机器学习。除了我们没有每艘船的极坐标图。通常,船只设计师会提供一些理论极坐标,但专业团队需要创建自己的极坐标以获得最佳性能。
现在我们可以将第一个目标重新定义为更具体的东西:
给定风速和风向,预测某个方向的船速。
有了这样一个模型,我们可以很容易地预测最大 VMG 的路线。现在让我们继续,看看我们如何使用机器学习来实现这一点!
永远记住目标
在课程中,我们将使用除了自主帆船以外的例子。当我们引入新概念时,我们会使用这样的插页将它们与我们的目标联系起来:
目标:寻找最佳路线
什么是机器学习?
那么,什么是机器学习呢?让我们首先定义学习本身。谷歌网络的定义告诉我们:
学习 :通过学习、体验或被教导而获得知识或技能
这适用于计算机,也适用于人类。稍后我们将会看到:人类和计算机以非常相似的方式学习。
在机器中,获得的知识存在于所谓的模型中。该模型在训练阶段学习,并将在以后用于执行其在应用程序中的最终任务。比如做预测。
模型:系统对世界的看法,包含系统所学的内容
机器学习的类型
根据上面的学习定义,有三大类机器学习:
- 监督学习(被教授)
- 强化学习(体验)
- 无监督学习(研究)
监督学习
目前,这是最常见的机器学习形式。我们知道结果一定是什么,我们通过提供数据的好的和坏的例子来“教”机器更接近。
更具体地说:我们希望我们的模型能够将给定的输入(通常命名为 X)转换成特定的输出(通常命名为 y)。我们通过输入相应的输出示例来训练模型。这被称为训练集。

Figure 3: Inputs, Outputs and Model
另一种定义它的方法是把它写成一个数学公式:
y = f(X)
这里 f 是将输入转化为输出的函数(模型)。
强化学习
这在技术上是一种监督学习的形式,只不过老师不是人。该系统通过反复试验从其环境中学习。
该模型仍然有输入和输出,但我们没有带有示例的训练集。相反,我们有一个奖励函数,这个模型试图最大化这个函数。
无监督学习
即使没有老师,机器也可以学习在接收到的数据中寻找结构。例如:'聚类'和'降维'。见下面的降维示例。系统找到看起来相似的照片示例。

Figure 4: Example of the t-SNE dimensionality reduction, original from: https://lvdmaaten.github.io/tsne/
目标——寻找最佳路线
问题
什么样的机器学习类型最适合我们的目标?回答
我们有一个已标记的数据集可用,所以我们可以使用监督学习。
问题的类型
在监督学习中,我们可以解决两种主要类型的问题。类型取决于所需的输出。
假设您想要确定某个图像包含一只狗还是一只猫。这将是一个分类的例子。
分类 :目标是预测一个类或类别
另一个例子:假设我们想根据天气预报和季节来预测北京的烟雾量。这将是一个回归问题。
回归 :目标是预测一个实数
目标——找到最佳路线
问题 我们的目标是分类还是回归型问题?
回答 显然这是一个回归问题,因为我们想要预测船速,而船速是一个实数。
特征
现在,我们来看看机器学习系统的输入数据。模型需要知道我们想要了解的事物的属性。这些特性或属性被称为特征。
我们以水果为例:水果的重量和颜色都是特征。

Figure 5: Different features of oranges and kiwis
该模型可以使用这些特征来预测我们正在观察的水果的种类。这就是分类。
试图根据重量和颜色预测直径是一个回归问题。
目标——寻找最佳路线
问题 对于我们的目标来说,该模型的特点是什么?
回答 风的角度和风速
培训模型
好的,但是我们如何从特征到预测呢?首先我们必须训练我们的模型。
训练分类模型
让我们继续以水果为例。我们想根据重量和颜色来确定水果的类型。首先,我们需要将颜色转换成数字。我们用纳米来表示光的波长。绿色变成 520 纳米,橙色变成 600 纳米。我们将这两个数字绘制成图表。

Figure 6: Scatterplot with data points
训练的目标是找到猕猴桃和橙子的分界线。这条线完全是随机开始的。随着每一步的训练,模型都试图将线向正确的方向移动一点。一段时间后,越来越多的水果会出现在正确的一边。

Figure 7: Classifying oranges and kiwis
经过 5 个步骤,我们对结果感到满意。训练停止,我们现在可以用我们全新的训练模型进行预测。
训练回归模型
这遵循相同的基本原则。现在,我们将根据重量来预测每个橙子的价格。我们的目标是画一条与我们用于培训的示例非常匹配的线。

Figure 8: Example of a regression model
经过训练后,该模型给出了给定重量的每只橙子的估计价格。
回到帆船上
那么,在给定风速和风向的情况下,我们如何使用机器学习模型来预测某个方向的船速呢?在我们开始训练之前,我们需要数据!
假设你已经记录了去年你的团队每次出航时的风速、风向和船速。你遇到了许多不同的天气(和海浪)条件。清理完这些数据后,您最终会得到一个包含数字的大表。来自该数据帧的随机样本如图 9 所示。

Figure 9: Random sample of dataset
在这种情况下,boat_speed 是我们的目标变量。我们的输入特征是风速和攻角。
在我们的课程中,我们使用在船上收集的数据来训练机器学习模型。参与者将使用这些预测来制作他们自己的船的极坐标图。如前所述,这将在比赛中为船只的自主性和竞争力发挥重要作用。
然后我们把模型挂在帆船上,在水上测试它们。我们还与所有参与者举行虚拟比赛,以找出哪种模式效果最好!


Videos from the virtual race and simulator used to test the algorithms
一锤定音
在这篇博客文章中,你已经发现了我们实现自主航行挑战的子目标 1 的方法——找到最佳路线,并了解了机器学习的一些关键概念。
那么,子目标 2 和 3 发生了什么变化?子目标 1 在一篇博客文章中已经涵盖了很多内容,所以请继续关注未来关于挑战的其他部分的文章。
就是这样,我们希望你受到了机器学习、帆船比赛或最好两者的启发!如果你有任何问题,请在评论中告诉我。
更多关于我们机器学习课程的信息,请看:【https://www.ai-captain.com/】T3
水上见!
如何建立用于垃圾分类的图像分类器

用 fastai 库在 Python 中快速训练卷积神经网络
为什么要进行垃圾分类?
当废物被不正确地处理时,回收污染就会发生——比如回收一个上面有油的比萨饼盒子(堆肥)。或者当废物被正确处理但未被正确准备时——比如回收未腌制的果酱瓶。
污染是回收行业的一个大问题,自动化垃圾分类可以缓解这个问题。只是为了好玩,我想尝试制作一个图像分类器的原型,对垃圾和可回收物进行分类——这种分类器可以应用在光学分类系统中。
构建图像分类器
我将使用 fastai 库(构建在 PyTorch 上)训练一个卷积神经网络来将图像分类为纸板、玻璃、金属、纸张、塑料或垃圾。我使用了 Gary Thung 和 Mindy Yang 手动收集的图像数据集。如果你正在跟随,在这里下载他们的数据集,然后把它移到和笔记本相同的目录。(注意:你会想要使用 GPU 来加速训练。)
我的建模渠道:
- 下载并提取图像
- 将图像组织到不同的文件夹中
- 火车模型
- 做出并评估测试预测
- 后续步骤
1.提取数据
首先,我们需要提取“dataset-resized.zip”的内容。

Code for extracting images from zip file
解压缩后,调整了数据集大小的文件夹有六个子文件夹:

Ignore .DS_Store
2.将图像组织到不同的文件夹中
现在我们已经提取了数据,我将把图像按 50–25–25 的比例分成训练、验证和测试图像文件夹。我定义了一些帮助我快速构建它的函数,你可以在笔记本中查看。
接下来,我将根据 ImageNet 目录约定创建一组目标文件夹。这意味着它将有一个包含三个子文件夹的外部文件夹(我称之为 data):train、validation 和 test。在每个文件夹中,都有一个名为纸板、玻璃、金属、纸张、塑料和垃圾的文件夹。我也将跳过这段代码,因为它很普通;只要知道这是我的图像数据集的组织。

ImageDataBunch.from_folder()指定我们将从 ImageNet 结构的文件夹中提取训练、验证和测试数据。
批量大小 bs 是你一次训练多少个图像。如果您的电脑内存较少,请选择较小的批处理大小。
您可以使用 get_transforms()函数来扩充数据。
以下是数据的一个示例:

Excellent photos of garbage
3.模特培训

Specifying the CNN in one line of code
resnet34 是什么?
残差神经网络是有很多层的卷积神经网络(CNN) 。具体来说,resnet34 是一个有 34 层的 CNN,已经在 ImageNet 数据库上进行了预训练。预训练的 CNN 将在新的图像分类任务中表现得更好,因为它已经学习了一些视觉特征,并且可以转移这些知识(因此是转移学习)。
由于它们能够描述更复杂的情况,深度神经网络在理论上应该比浅层网络在训练数据上表现得更好。然而,在现实中,深度神经网络往往比浅层神经网络表现更差。
创建 Resnets 是为了使用一种叫做快捷连接的黑客技术来规避这个故障。如果层中的一些节点具有次优值,则可以调整权重和偏差;如果一个节点是最优的(它的残差是 0),为什么不放过它呢?仅根据需要对节点进行调整(当存在非零残差时)。
当需要调整时,快捷连接会应用 identity 函数将信息传递给后续层。这在可能的情况下缩短了神经网络,并允许 resnets 具有深层架构,并且表现得更像浅层神经网络。resnet34 中的 34 只是指层数。
阿南德·萨哈在这里给出了一个更深入的解释。
寻找学习率
我将找到梯度下降的学习率,以确保我的神经网络收敛得相当快,而不会错过最佳误差。关于学习率的复习,看看杰瑞米·乔登关于选择学习率的帖子。

学习率查找器建议学习率为 5.13e-03。有了这个,我们就可以训练模型了。
培养

Results of training on validation set
我运行了 20 个时期的模型。这种拟合方法的酷之处在于,学习率随着每个历元而降低,从而使我们越来越接近最优值。8.6%的验证误差看起来非常好…让我们看看它在测试数据上的表现。
首先,我们可以看看哪些图像被错误地分类了。
可视化最不正确的图像

这里回收器表现不佳的图像实际上被降级了。看起来照片曝光太多了,所以这实际上不是模型的错!

这种模型经常把塑料误认为玻璃,把金属误认为玻璃。最令人困惑的图片列表如下。

4.根据测试数据做出新的预测
为了了解这种模式的实际表现,我们需要对测试数据进行预测。首先,我将使用 learner.get_preds()方法对测试数据进行预测。
注意: learner.predict()只对单幅图像进行预测,而 learner.get_preds()对一组图像进行预测。我强烈推荐阅读文档来学习更多关于 predict()和 get_preds()的知识。

get_preds(ds_type)中的 ds_type 参数接受一个数据集参数。示例值是数据集。训练,数据集。我提到这一点是因为我犯了传入实际数据(learn.data.test_ds)的错误,这给了我错误的输出,并且花费了令人尴尬的长时间来调试。
不要犯这种错误!不要传入数据—传入数据集类型!

这些是每幅图像的预测概率。这个张量有 365 行(每个图像一行)和 6 列(每个材质类别一列)。

现在我要把上面张量中的概率转换成预测类名的向量。

这些是所有图像的预测标签!让我们检查一下第一个图像实际上是否是玻璃。

确实是!
接下来,我将从测试数据集中获取实际的标签。

看起来前五个预测匹配!
这款车型整体表现如何?我们可以用混淆矩阵来找出答案。
测试混淆矩阵

Confusion matrix array
我要把这个矩阵做得漂亮一点:

同样,该模型似乎混淆了玻璃的金属和玻璃的塑料。随着时间的推移,我相信进一步的调查会有助于减少这些错误。

我最终在测试数据上实现了 92.1%的准确率,这相当不错——垃圾网数据集的原始创建者使用支持向量机在 70-30 的测试训练中实现了 63%的测试准确率(他们还训练了一个神经网络,测试准确率为 27%)。
5.后续步骤
如果我有更多的时间,我会回去减少分类错误,特别是玻璃。我还会从数据集中删除曝光过度的照片,因为这些图像只是坏数据。
这只是一个快速而肮脏的迷你项目,旨在表明训练一个图像分类模型是非常快速的,但使用 fastai 库创建一个最先进的模型的速度是非常惊人的。如果你有一个你感兴趣的应用程序,但不认为你有机器学习的能力,这对你来说应该是令人鼓舞的。
下面是 这个项目的 Github 回购。
感谢詹姆斯·德林杰的这篇关于蓝鸟分类的 博文 。有关回收的更多信息,请查看这篇 fivethirtyeeight帖子 。
如何使用 IBM Watson NLC 服务构建对象检测模型
无需编码,构建脑瘤目标检测模型

Image by Robina Weermeijer — Unsplash
目标检测
目标检测是属于计算机视觉和图像处理的图像分类和定位任务的一般形式。对象检测的目标是利用每个对象的置信度分数来检测图像中的特定对象。它被用于不同的领域,用于不同的目的,例如搜索、计数、检测癌症等。
让我们建立模型
在本帖中,我们将构建一个无需一行代码就能检测脑瘤的对象检测模型。
在 IBM Watson 中创建一个项目后,单击项目名称,您将被重定向到一个类似的页面,如下所示

点击“添加到项目”选择模型类型:视觉识别模型。

如果是第一次训练或测试可视化模型,您需要添加一个服务

选择一个符合你需要的计划

我更喜欢保留默认设置。但是,您可以更改区域、计划、服务名称等。

之后,选择一个视觉模型(在我们的例子中,检测物体)。

点击“浏览”将您的大脑扫描数据集(或任何其他图像数据集)上传为 zip 文件。不久之后,图像将被加载到模型中,您可以在其中看到图像细节。

单击每个图像以添加您想要检测的对象。只需点击【添加对象】按钮。在对象周围画一个正方形,并在屏幕右侧命名。点击“添加”,对象将被添加到图像中。最后,点击“完成”保存更改。

其他图像可能不止一次出现相同的对象或不同的对象。你可以把他们都干掉。点击“完成”保存更改。

在添加了至少一个对象之后,模型就可以进行训练了。点击“火车模型”,模型将立即准备好。

培训结束后将会发送通知。

点击“此处”导航至模型页面,在此您可以查看其所有详细信息。

点击“测试”,通过上传新图像来推断您的模型。该模型将利用它们的置信度分数来检测所有可能的对象。在下面的例子中,我选择了只显示肿瘤对象。

最后,单击“Implementation ”,将会提供 API 来远程推断您的模型。

资源
如何使用 CatBoost 构建首个 CC 欺诈模型
首次提交给 Kaggle 的 IEEE-CIS 欺诈检测竞赛

上周我提到我将通过新的 IEEE-CIS 欺诈检测卡格尔竞赛来探索一些数据科学概念。第一个视频带你建立一个 Python 环境,并为一个 ML 项目使用版本控制。
本周,我有一个新的视频深入研究数据,并使用梯度增强库 Catboost 构建第一个模型。下面来看看吧!
如何使用谷歌云通过 4 个步骤构建低成本、实时和可扩展的机器学习模型
在这篇文章中,我描述了一个端到端的机器学习管道,使用谷歌云平台(GCP)、TensorFlow、约 40 亿订单历史数据集和美国交易所实时订单簿来预测比特币价格。
在过去的 3 年里,我对这个存在于云计算、机器学习和加密货币交汇处的主题产生了热情。
这是 2019 年 5 月几天的主要输出。

Bitcoin actual and predicted price for 2 days in May 2019; predicted price is 5 minutes ahead
你可能会认为这是 TensorFlow 的又一个比特币价格预测模型。其实这与其说是比特币,不如说是机器学习。
在深入了解更多细节之前,让我们先快速了解一下高层架构。

High Level GCP Architecture
这只是一个例子,绝不是投资建议。
这篇文章和其他类似的文章有一些显著的不同:
- 庞大而丰富的数据集——我一直在流式传输和收集大约 40 亿份 BTC 美元订单;该数据集已用于训练模型
- 架构——非常注重集成 GCP 提供的许多组件
- 成本—这不是 IT 部门、硬件机架或百万美元预算所能实现的。这只是我在学习 GCP(当我不在金融机构的分析部门工作时)
现在回到 4 个步骤,简而言之,我做了以下事情:
- 流式传输和存储实时完整订单
- 执行探索性分析,并将原始数据转化为有意义的变量
- 开发和训练深度学习模型
- 实时评估模型
让我们进入更多的细节,但在“待办事项”列表格式,以保持简短。
- 传输并存储实时完整订单簿
- 选择一个交换。数据是免费的。我喜欢比特币基地
- 决定订单水平。如果你买了市场微观结构和价格形成理论,选择给你最多(全订单)数据的级别。我满足于第 3 级,因为我可以分别为交易和(市价和限价)订单创建变量
- 选择一个数据存储。在流式数据方面,BigQuery 是一款很棒的产品。我尝试过(浪费了很多时间)在一个计算实例中运行我自己的数据存储
- 决定流式组件。这一领域有许多优秀的产品。我选择了 node.js/websockets,因为它与 BigQuery 的集成非常好
- 使用小型计算实例全天候传输数据流。小型 linux 实例是可靠的。他们只是跑了几个月。我确实会时不时地让它们停几分钟来升级软件包,但是我通常会设置好实例,然后忘记它
2。进行探索性分析,将原始数据转化为有意义的变量
- 使用 Data Studio 或 Tableau 连接到 BigQuery。我使用 Tableau 已经很多年了,这是一个很好的工具。但我对 Data Studio 感到惊喜,它与谷歌产品的集成是无与伦比的。我发现自己越来越多地使用 Data Studio

Exploratory Data Analysis with Data Studio
- 使用 Dataproc 从 BigQuery 中提取数据并保存到云存储中。接下来转换数据集:重新采样(例如,10 分钟间隔),归一化,创建变量。将输出以 TFRecord 格式保存到云存储中。Dataproc 没问题,但我考虑将这部分切换到数据流,原因有二:
- 在启动集群之前,我需要确定集群的大小;我多次低估了我需要的资源,并且在 Spark 中遇到了内存不足的错误
- 我使用 scala 和 Dataproc,但是对于实时组件,我使用 python。两种语言做同样的事情并不理想。另外,你需要考虑一些细微的差别
3。开发和训练深度学习模型
- 使用云 ML 引擎 /CMLE 来训练和部署 TensorFlow 模型——一旦训练集准备好,我就使用 TensorFlow 及其强大的神经网络功能来训练一个序列模型。这里要提到的一件事是,我很惊讶超参数调整如何改进我的模型,在几次试验后将 RMSE 降低了 50%。
4。实时评估模型
- 使用交易所实时订单簿预测 5 分钟后的比特币价格。
下面的图表是使用 Data Studio 创建的,它实时显示了 5 分钟前的预测。x 轴显示时间线(以 5 分钟为单位,采用 UTC 时区), y 轴显示两个时间序列:实际价格和预测价格。请注意,由于模型是实时预测的,因此没有与上次预测价格相关联的实际价格!
预测跟踪得相当好,但是它们没有始终捕捉到方向的变化(例如图表中的第一点)。这是我打算解决的问题。

最后,我正在考虑将模型输出作为 API 公开,但是我现在还不确定。如果你对此感兴趣,给我写信。
如何构建生产级 AI?

Photo by Hitesh Choudhary on Unsplash
让你的人工智能模型为你工作
你是否努力从你新开发的人工智能模型中获取真正的价值?
“你说的生产是什么意思?太复杂了。我们将再次运行代码。”
以上是许多领先组织中有抱负的数据科学家的典型回应。
生产级人工智能模型是一种帮助人类以可持续和可预测的方式做出商业决策的模型。
在过去的几年里,我成功地领导了高级分析和数据科学领域的组织转型。这些是一些最常见的心态——看看你能否将事实与虚构区分开来:
- “机器建造了我的人工智能模型”
- “我不够聪明,无法解释我的人工智能模型”
- “我有人工智能模型,我不用再做任何工作”
以上都是目前虚构的。人类为人类建立 AI 模型。伟大的数据科学家可以建立与人类一起工作的人工智能模型。此外,人工智能模型提供了额外的见解,但仍需要大量的工作、调查和决策。
那么,生产级 AI 的支柱是什么呢?
证明 AI 模型实力
“所有的模型都是错的,问题是它们错得有多离谱。”——约翰·埃文斯
模型强度并不完全等同于模型准确性。衡量 AI 模型实力还是需要精度的。混淆矩阵是衡量模型准确性的常用方法,它显示模型预测和实际结果之间的差异。尽管它默认适合分类模型,但是可以将非分类模型转换成这种形式。虽然名字很难理解,但结果很容易理解。

An illustrative example of Confusion Matrix from “Understanding Confusion Matrix”
精度越高不一定越好。在统计学中,这被称为“过度拟合”,即模型与训练样本过于相似。这意味着模型完美地预测了过去的事件,但是没有正确地预测未来的事件。
衡量模型强度的更好方法是模型提升。它证明了模型如何区分成功和随机选择。

在模型提升下,有一些相关的拟合优度统计,如 AUC(曲线下面积)或 K-S (Kolmogorov-Smirnov)。对于 K-S 统计,任何超过 25%的通常被认为是生产级。
此外,显示人工智能模型强度随时间的退化。我们可以使用的度量标准是 PSI ( 人口稳定性指数)。它通过记分卡以及重新访问模型的关键阈值来跟踪模型的强度。
证明人工智能模型稳定性
典型的数据科学家或典型的机器学习软件表示:“我使用了 10%的样本,这样就足够了。”
10%的保留样本或任何其他默认百分比是不够的。
有两种类型的时间验证与人工智能模型开发相关:
- 及时验证(ITV)
- 超时验证(OTV)
传统的保留样本通常被称为及时验证,因为它是观察时间窗口的子集。然而,这种情况会持续到未来吗?
OTV 是对未来模型稳定性的一个很好的检验。我见过无数次,模特通过了 ITV,但没有通过 OTV。这包括模型精度、模型升力的显著下降,甚至模型方向参数的改变。它还可以作为过度装配的把关者。
证明 AI 模型合理性
一个生产级的 AI 模型必须通过理性或者商业常识。尽管复杂的人工智能模型发现了极端异常,但其关键发现植根于普通的商业常识。
部分相关性图(PDP)展示了您的相关性/结果变量与主要驱动因素的关键相关性。尽管人工智能模型的内部机制非常复杂,但如果构建正确,结果解释的清晰度将会非常清晰。

An illustration of PDP Plots from Christoph Molnar’s book on Interpretable Machine Learning
上面的例子清楚地显示了租用自行车的数量与温度、湿度和风速之间的半线性关系。尽管人工智能模型很复杂,但企业高管需要利用其结果来做出重要决策。这可能涉及定价,自行车供应和潜在的有利可图的商业地点。
总之,数据科学家需要学会构建强大、稳定和理性的生产级人工智能模型。
人工智能模型的建立具有挑战性。它同时需要复杂性、简单性和创造性。
然而,重要的是要记住,人工智能模型是由人类建造的——由机器计算——并为人类所用。
如果你喜欢这篇文章,并想看更多的内容,请考虑加入媒体会员,使用下面的链接来支持我和其他作者:
[## 通过我的推荐链接加入 Medium-Albert Suryadi
阅读艾伯特·苏亚迪(以及媒体上成千上万的其他作家)的每一个故事。您的会员费直接支持…
albertsuryadi.medium.com](https://albertsuryadi.medium.com/membership)
关于作者:Albert sur yadi是蓝筹股组织中实现高级分析和数据科学能力的公认领导者。他被公认为分析团队(实践社区)的领导者,该团队授权并激励他人超越现状。
如何在几分钟内构建生产规模的云 ML 模型!
仅使用 Google Cloud 上的 SQL,在几分钟内构建、训练和部署一个机器学习模型。

Photo by Markus Spiske on Unsplash
作为在云计算市场获得更大市场份额的努力的一部分,谷歌云一直在为其平台添加强大的工具,特别是在人工智能方面。其中一个工具是 BigQuery ML,它使用户能够在几分钟内开发和训练大型数据集的 ML 模型!
如果您还不熟悉它,BigQuery 是一个无服务器的数据仓库,支持 SQL 查询,您只需为查询数据的使用和存储付费(它“类似”于 AWS 上的 Redshift)。
自 2018 年年中以来,BigQuery 已使用户能够在几分钟内用几行 SQL 代码构建 ML 模型。这篇文章将带你经历构建这样的 ML 模型所需的步骤。
注:
- 用于说明步骤的例子是受 BigQuery 官方教程中的 one 的启发。
- 如果你想执行这里的代码,你可以在这里找到它。
1)将您的数据导入 BigQuery:
如果数据还没有加载到 BigQuery 中,有几种方法可以实现。事实上,您不需要像查询外部数据一样将数据加载到 BigQuery 中进行查询。但是,如果您关心速度,将您的数据上传到 BigQuery 是一个好主意。
在这里,我们将使用出生率数据集,其中有 1969 年至 2008 年间美国出生登记的详细信息,来预测新生儿的体重。它已经在 BigQuery 中作为公共数据集 在这里 可用。
2)探索和预处理数据:
让我们通过运行以下查询来考虑数据集中最近 10 年的数据,其中的值是有意义的(即> 0):

这产生了下表:
BigQuery runtime: 2.3s elapsed, 21.9 GB processed
从上表中可以看出,有几列似乎适合创建要素来预测新生儿的体重,即:
**is_male**,
**plurality**,(one baby, twins, ...etc)
**mother_age**,
**gestation_weeks**,(duration of pregnancy in weeks)
**weight_gain_pounds** (weight gained by the mother during the pregnancy in pounds)
例如,为了检查这些列是否可以被利用到特性中,可以在 Jupyter 或 Datalab 笔记本中对照weight_pounds列(预测的目标)来绘制这些列,并进行探索。检查缺失数据、稀疏性等。对于良好的特征工程是必不可少的。为了简单起见,让我们跳过这一步,跟着我们的直觉走!
3)定义和设计特征:
使用在上一步中选择的将被利用到特性中的列,让我们看看如何在 BigQuery 中编码我们的特性。
请注意,在 BigQuery ML 中,所有字符串都被视为分类特征,所有数值都被视为连续特征。因此,我们的 5 个特征将定义如下:

运行上述查询会产生:
BigQuery runtime: 2.7s elapsed, 6.82 GB processed
注意hashmonth栏。我们为数据集的过去 10 年中的每个月制作了一个哈希值(year>1998),以在下一步中无泄漏地分割训练/评估数据集(即,具有相同出生日期的婴儿应该在训练或评估集中)。
3)创建和训练 ML 模型:
在创建 ML 模型之前,需要一个 BigQuery 数据集来存储模型,这可以通过在 BiQuery web UI 中单击“创建数据集”来轻松创建。让我们把这个数据集命名为BigQDemo。
SQL 命令CREATE MODEL创建并训练模型。因为我们预测的是新生儿的体重,这是一个连续的值,所以在下面的查询中为model_type选择了一个线性回归模型。运行这个查询(大约需要 4 分钟)创建并训练一个名为NewBornWeight_Model的 ML 模型!

经过训练的模型以表格的形式出现在BigQDemo数据集下:

可以通过浏览NewBornWeight_Model表或运行以下查询来查看培训统计数据,如损失和学习率:
SELECT * FROM ML.TRAINING_INFO(MODEL BigQDemo.NewBornWeight_Model);
您可以在官方文档这里找到 BigQuery ML 的所有其他模型类型和可选参数。
4)评估训练好的模型:
命令ML.EVALUATE用于评估已训练的模型。在我们的例子中,让我们对训练期间没有使用的剩余 20%的数据评估模型(参见下面查询中的条件AND MOD (..., 5)>= 4):

这产生了以下结果:
BigQuery runtime: 2.5s elapsed, 6.82 GB processed
5)用你的模型预测
当您对您的模型感到满意时,您可以使用命令ML.PREDICT来使用它进行预测。让我们根据过去 10 年的出生数据预测 50 个婴儿的体重:

如下表所示,当使用ml.PREDICT命令时,预测列自动命名为predicted_<label_column_name>。
BigQuery runtime: 1.0s elapsed, 5.80 GB processed
这样,您就有了一个功能完整的 ML 模型!
BigQuery ML 不仅有助于构建 ML 模型作为 Google Cloud 数据管道的一部分,或者使非技术人员能够运行 ML 模型;而且还可以快速测试新设计的复杂 ML 特征的效果,例如在大型数据集上。因此,当直接从开发环境(例如 Jupyter notebooks)执行时,BigQuery ML 对 ML 开发人员特别有用。
如何快速建立苗条的 Docker 图像

你还记得那些日子吗,你写了很棒的软件,但是你不能把它安装在别人的机器上,或者它在那里崩溃了。虽然这从来都不是一次愉快的经历,但我们可以说

如今,由于集装箱化,这不再是一个借口。
简而言之,通过容器化,您可以将应用程序和所有必要的依赖项打包到一个映像中。在执行时,您将该映像作为容器运行。有了这个,你就不必为了让你的软件运行而去摆弄别人的系统了。容器和你的软件应该可以在任何地方运行,如果它运行在你的机器上的话。当部署依赖于不同包和版本的模型时,这对于数据科学家也很有用。对我来说,数据科学家必须知道如何创建图像和容器。
众所周知,Docker 是这一领域的主要玩家,Docker 图像无处不在。这太棒了,因为你可以毫无困难地并排启动不同版本的数据库。为你的应用程序拼凑图片也非常简单。这是由于大量的基本图像和简单的定义语言。然而,当你在不知道自己在做什么的情况下一起黑图像时,你有两个问题。
- 你浪费了磁盘空间,因为你的图像变得不必要的庞大。
- 等待花费太长时间的构建会浪费你的时间。
在本文中,我想向您展示如何减轻这两个问题。幸运的是,这只需要你知道 Docker 提供的一些技巧和技术。为了让本教程变得有趣和有用,我将向您展示如何将 Python 应用程序打包到 Docker 映像中。你可以在我的 Github 资源库 中找到下面引用的所有代码。
你准备好了吗?我们开始吧。
教程
让我们假设我们所有的代码都在一个 Python 文件 main.py. 中,因为我们是酷小孩,所以我们使用最新最好的 Python 版本,在撰写本文时是 3.8。我们的应用只是一个简单的网络服务器,它依赖于熊猫、 、fastapi 、和、uvicorn 。我们将依赖关系存储在一个 requirements.txt 文件中。在本地,我们在虚拟环境中开发应用程序。该环境位于名为的文件夹中。venv 放在与代码相同的文件夹中(这一点很快变得很重要)。现在,我们决定将所有这些打包成一个 Docker 映像。为此,我们要做的就是
- 使用 Python 3.8 版本的基础图像。
- 复制代码和需求文件。
- 在映像中安装需求和依赖项。
- 公开运行我们的应用程序的命令
我们的 Docker 图像的第一个版本看起来像
**FROM** python:3.8.0-slim
**COPY** . /app
**RUN** apt-get update \
&& apt-get install gcc -y \
&& apt-get clean
**WORKDIR** app
**RUN** pip install --user -r requirements.txt
**ENTRYPOINT** uvicorn main:app --reload --host 0.0.0.0 --port 8080
除了我们的代码和需求,我们需要安装 GCC ,因为FastApi 要求在安装时安装。我们通过以下方式建立我们的形象
docker build -t my-app:v1 .
这个映像的大小约为 683 MB,构建它大约需要一分钟(不包括下载基本映像)。让我们看看如何减少这种情况。
基础图像
关于基础图像,我已经有意识地选择使用 Python slim 。我为什么要选择这个?
例如,我可以拍摄一个完整的 Ubuntu 或 CentOS 图像,这将导致图像大小大于 1GB。但是,因为我只需要 Python,所以没有理由安装所有这些。
在图像尺寸的下端,我们可以取 python:3.8.0- 高山 。但是,我的代码依赖熊猫,在 alpine 上安装很痛苦。Alpine 在稳定性和安全性方面也有问题。再者,slim 只比 alpine 大~80MB,还是可以的。有关如何选择最佳 Python 映像的更多信息,我建议感兴趣的读者参考本文。
构建上下文
当您构建映像时,打印到控制台的第一行内容是:向 Docker 守护进程发送构建上下文。在我的电脑上,这花了大约 5 秒钟,发送了 154 MB。这里发生了什么事?Docker 将构建上下文中的所有文件和文件夹复制到守护进程中。这里,构建上下文是存放 Dockerfile 文件的目录。由于我们只需要两个文本文件,154 MB 听起来很多,不是吗?这样做的原因是 Docker 复制了所有 T21 的东西,例如。包含虚拟环境的 venv 文件夹,或者。git 文件夹。
要解决这个问题,你只需要添加一个名为 的文件。在你的文档旁边。在这个文件中,你一行一行地列出 不应该复制 的 Docker。这就像 git 对。gitignore 文件。举个小例子,假设我们的文件夹中有几个不想复制的 Excel 文件和 png 文件。的。dockerignore 文件看起来像
*.xlsx
*.pngvenv
.venv
.git
在我们的例子中,在我添加了这个文件之后,“向 docker 发送构建上下文”只需要几毫秒,并且只发送了 7.2 kb。我将图像大小从 683 Mb 减少到 529 Mb,这大约是以前构建上下文的大小。不错!添加一个. dockerignore 文件既有助于构建缩小* 图像尺寸 。***
图层缓存
如前所述,在我的机器上构建这个图像大约需要 60 秒。大部分时间,我估计大约 99.98%,用于安装需求和依赖项。你可能会认为这里没有太大的改进空间。但是有时你必须频繁地构建图像!为什么?Docker 可以利用 图层缓存 。
Docker 文件中的每一行都代表一个层。通过添加/删除线中的内容,或者通过更改它引用的文件或文件夹,可以更改层。当这种情况发生时, 这一层和下面所有的层得到重建 。否则,Docker 使用该层的缓存版本。为了利用这一点,您应该这样构建 docker 文件
- 不经常变化的图层应该出现在靠近 Dockerfile 开头的地方。 这里安装编译器就是一个很好的例子。
- 经常变化的图层应该出现在接近 Dockerfile 的末尾。 复制源代码就是这里最完美的例子。
酷毙了。理论到此为止,让我们回到我们的例子。
假设你没有改变需求,你只是更新了你的代码。这在开发软件时相当常见。现在,每次构建您的映像时,都会重新安装这些讨厌的依赖项。构建映像总是需要相同的时间。烦人!我们还没有利用缓存。
神奇的新 docker 文件来了,它解决了你的问题
****FROM** python:3.8.0-slim
**RUN** apt-get update \
&& apt-get install gcc -y \
&& apt-get clean
**COPY** requirements.txt /app/requirements.txt
**WORKDIR** app
**RUN** pip install --user -r requirements.txt
**COPY** . /app**ENTRYPOINT** uvicorn main:app --reload --host 0.0.0.0 --port 1234**
这看起来没有什么魔力和不同,对吗?我们所做的唯一一件事,就是首先安装 GCC 和分开复制需求和复制源代码。
GCC 和依赖关系很少改变。这就是为什么这一层现在很早就出现了。需求变化也很慢,但比 GCC 更频繁。这就是为什么这一层在 GCC 层之后。我们的源代码经常改变。因此,复制它发生晚了。现在,当我们对源代码进行修改并重新构建映像时,由于 Docker 使用缓存的层,所以不会重新安装依赖关系。现在重建几乎不需要时间。这很好,因为我们可以花更多的时间来测试和执行我们的应用程序!
多阶段构建
在我们的示例图中,我们必须安装 GCC 来安装 FastApi 和 uvicorn。但是,对于运行 应用程序我们不需要编译器 。现在想象一下,你不仅需要 GCC,还需要其他程序,比如 Git,或者 CMake,或者 NPM,或者…你的制作形象越来越胖。
多阶段构建拯救了我们!
通过多阶段构建,您可以在同一个 Dockerfile 文件中定义不同的映像。每个图像执行不同的步骤。您可以将从一个映像生成的文件和工件复制到另一个映像。最常见的情况是,您有一个构建应用程序的映像和另一个运行应用程序的映像。您需要做的就是将构建工件和依赖项从构建映像复制到应用程序映像。
对于我们的例子,这看起来像
*****# Here is the build image*
FROM** python:3.8.0-slim as builder
**RUN** apt-get update \
&& apt-get install gcc -y \
&& apt-get clean
**COPY** requirements.txt /app/requirements.txt
**WORKDIR** app
**RUN** pip install --user -r requirements.txt
**COPY** . /app***# Here is the production image***
**FROM** python:3.8.0-slim as app
**COPY** --from=builder /root/.local /root/.local
**COPY** --from=builder /app/main.py /app/main.py
**WORKDIR** app
**ENV** PATH=/root/.local/bin:$PATH
**ENTRYPOINT** uvicorn main:app --reload --host 0.0.0.0 --port 1234**
当我们构建它时,我们得到的最终生产映像大小为 353 MB。这大约是我们第一个版本的一半大小。恭喜你,不算太坏。请记住,您的生产映像越小越好!
顺便提一下,多阶段构建也增加了安全性。阿辉,这是为什么?假设您需要一个秘密,比如 SSH 密钥,以便在构建时访问某些资源。即使您在后面的层中删除了该秘密,它在前面的层中仍然存在。这意味着可以访问你的图片的人可以得到这个秘密。对于多阶段构建,您只需复制必要的运行时工件。因此,生产映像永远看不到这个秘密,而您已经解决了这个问题。
关于多阶段构建有更多的细节,我建议读者参考本文和本文。
包裹
在这篇文章中,我向您展示了一些简单的技巧和诀窍,告诉您如何创建更小的 Docker 映像,以便更快地构建。纪念
- 总是添加一个. dockerignore 文件。
- 想想你的图层顺序,从慢变到快变的动作排序。
- 尝试使用和开发多阶段构建。
希望这能为你以后节省一些磁盘空间和时间。
感谢您关注这篇文章。一如既往,如有任何问题、意见或建议,请随时联系我。
如何构建像托尼·斯塔克那样的软件

That’s gonna be you by the end of this journey
这篇文章将带你经历一个过程,在这个过程中,你可以开始项目,打破无休止学习的循环,或者改变你的方式,在编码时改进你的工作流程和效率,这样你就可以不再觉得这不是你的事情,而是决定学习 Excel。我们将从托尼·斯塔克(又名钢铁侠)和他如何建造东西中汲取灵感。我也会分享一些我个人遵循的保持 100%状态的小贴士。
如今写伟大的代码并不是一个真正的问题。一切都只是一个谷歌搜索,只需找到 Stackoverflow 的第一个链接,找到最多投票/接受的答案和 boom 复制粘贴!
我看到,如今大多数人面临的真正挑战是下一步去哪里,或者如何真正利用他们所学的东西。我们都有责任在最新的框架上观看完整的视频播放列表,这个框架比其他每个人似乎都在使用的框架做得更好,但无论如何都在抱怨。大多数人只是看看,留下一些评论,然后就结束了。几天后,你看到的下一个播放列表也是如此。

人们以惊人的速度消费这些播放列表。学习新东西没有错,但真正的错误是除了视频用来指导你完成框架的演示应用/服务之外,不要在任何地方使用它们。
如果它是 React 或 Vue 之类的东西,它将是待办事项应用程序。如果是与机器学习相关的东西,如 Tensorflow 或 keras,它十有八九会出现在 MNIST 数据集(识别手写数字)上。
我明白,除了扩展提供的示例代码之外,很难想出一个项目来应用这些技术。我们中的大多数人在待办事项应用程序中添加 2 个或更多按钮,然后结束一天的工作,更新你的简历并完成。如果你拿起播放列表是因为你想学习新的东西来做你的项目,那会更容易,因为你知道你想从那里开始。大多数人不进行下一步,因为他们要么相信他们已经从一门课程中掌握了框架,并能够在需要时使用它(大错特错),要么他们对如何将各种框架放在一起没有真正的信心,因为他们缺乏经验(这是很常见的,没有错)。然后,你将自己与那些在你之前的人进行比较,他们在车库里的一台简单的电脑上编写了谷歌代码,这让你感到更加不安全。

顺便说一句,我有一个的便利指南,它可以帮助你在考虑某个项目时决定选择什么语言、框架和方法。
每个程序员都必须在某个时候经历这些阶段。好吧,我们知道你来这里的目的。你学了很多东西,却什么也没做,这可能会让你觉得自己更像个骗子。那我们该怎么办?
好吧,这里有一些生活建议:当陷入困境时,总是寻找灵感,你最终会找到出路。
在这种情况下,我们将从 MCU 的一个面孔中获得一些灵感,托尼·斯塔克又名钢铁侠…
让我们开始吧,我们将经历托尼在 11 年钢铁侠生涯中穿过的几件主要盔甲的制作过程。
马克 1(一起黑客攻击)

This was the suit that was literally built in a cave, with materials salvaged from missiles.
在早期阶段,当你刚开始学习编码或使用一个框架时,你自己做所有的工作,你谷歌每样东西,以某种方式拼凑你的代码,以便你可以加载一些 HTML 页面或显示一条消息。
您可以从 Stackoverflow 答案中排除所有问题,并在需要时引用。
这类似于托尼在山洞里用碎料和废品拼凑他的衣服。
标志 2(美学和质量控制)

虽然马克 1 是坏蛋,但它仍然笨重,一起被黑,不能准确地飞行,必须手动装备。就像您第一次尝试构建一样,大部分代码足以显示一些内容并满足您的基本目的。当然,点击一个 90 年代的按钮打开一个弹出窗口,上面写着“你好,世界”很酷,但是你真的会把它放在你的文件夹里吗?
肯定不会。就像 Mark 2 一样,这是一次全面的升级,从美学到自动化组装和飞行能力,你的代码也需要第二次迭代,否则它不会给你房间外的任何人留下深刻印象。
所以你从网上挑选一些设计,并尝试重新创作。这里有几个地方,你可以找到激发你创造力的设计灵感:
既然你已经有了一些灵感,下一步就是想出如何将这个设计变成现实。如果你正在建立一个网站/webapp,这很简单。您可以使用一个工具包/UI 框架,该框架已经预先设计了所有必要的组件,并从那里开始定制。而不是从头开始构建(向绝大多数想要构建东西的人推荐这种方法,如果你真的对设计感兴趣,那么可以尝试从头开始构建)。您可以利用的一些工具包/UI 框架有:
- Bootstrap (个人使用最多,我喜欢!)
- 布尔玛
- Daemonite 的材质(基于谷歌的材质设计)
你可以阅读谷歌关于用户界面/UX 的案例研究,以及设计适合绝大多数设备和用例的用户界面的指南。
Mark 3(测试和错误修复)

现在,马克 2 看起来一点也不像它的前身(你可以说两者之间有着鲜明的对比),马克 2 在各方面都领先一步,但它也有自己的缺陷。这是我们的第三课。永远测试!
托尼完成设计并穿上马克 2 号后,就开始了测试,他直接跳到了飞行测试,而宇航服飞行得令人惊讶。由于结冰,它没能在更高的海拔存活下来。如果他在战斗中没有考虑到这些结果,他就不会赢得这么漂亮。
所以总是尽你所能测试你的代码。这里有一些为 Python 和 JavaScript(目前最常用的两种语言)编写测试的链接
- Python 单元测试
- JavaScript 单元测试
- 另外测试 React (是的,这是一件事,而且非常需要!)
只需查找您选择的武器的视频。
你写的测试越多,你对你的代码就越有信心,尤其是在演示或者部署它的时候。
与 Mark 2 相比,Mark 3 可能是一个较小的增量更新,但它是必要的,你知道为什么。所以不要错过测试。
马克 5(便携性)

Mark 5 是一款非常注重便携性和易于装备的套装。
这很小,但是在某些时候你必须意识到你的项目文件夹中的源文件太大了,以至于不能随身携带进行演示,你不能总是希望在你的笔记本电脑上进行演示。因此,考虑将您的项目打包成可执行文件或部署到服务器上,以便您在旅途中需要快速吹嘘时更容易访问它。
标志 6(主要的重新设计和规格变化)

现在,从外观上看,Mark 4 可能再次看起来只是一个微小的设计调整,但这还不是全部。它配备了一个新的电弧反应堆,完全是用一种新元素重建的,这种新元素在那之前并不存在。他决定这样做,因为从长远来看,以前的核心并不支持。
该上第四课了。识别出没有成功的事情。
有时候,当你工作时,你会意识到你所付出的努力并没有真正取得成果,因为你的工作环境、你所选择的框架等等的限制。这和托尼面临的问题是一样的。所以,当一个核心组件,比如说你的 PHP 脚本(请不要使用 PHP)跟不上你的需求时,是时候更换工具了。
这是我早年作为程序员尝试构建自己的 JARVIS 时遇到的一些事情。大约 6 年前,当我第一次开始使用 C#时,我决定使用 Windows 窗体(是的,我这样做了,这并不是我引以为豪的事情,但肯定会因为你将看到的原因而感到高兴)。它提供了我当时设计所需的一切。语音识别通过。Net,易于拖放的 UI 生成器(我当时选择它的主要原因)。我能够构建我的第一个版本,并提供下载。

Please ignore that horrible Obviously PowerPoint ripped background
这不是最好看的东西,但我很自豪。但很快我意识到 WinForms 已经太老了,过时了,所以我决定改用 WPF 的另一种用于 UI 设计的 Windows 技术,它提供了更细粒度的控制(与 WinForms 相比)
它支持 XAML,这基本上是一种美化的创建 UI 的方式,就像你用 HTML 一样,通过添加标签、属性,同时仍然保持拖放方面。在这一点上,我开始欣赏像 HTML 这样的东西所提供的控制水平,我可以制作动画、自定义主题等并没有让我兴奋并让我越来越想学习的事实。在这一点上,我开始喜欢材料设计,并与它一起前进。

This was the last iteration I made for desktop, then I switched to web technologies
如你所见,在我为萨姆开发的过程中,我多次更换了我的核心平台,萨姆现在是的吹牛大王。不断更换平台是一种巨大的痛苦,而从 WinForms 到 WPF 的切换仍然是在 C#上,一旦我切换到 React,它就是 JavaScript。毫无疑问,所有的代码都变得毫无用处,但是这些变化帮助我成为了今天的 FullStack 开发者。
所以在本节的最后,我想说的是,要有足够的勇气去考虑改变那些不再有用的规范和框架。你改变得越快,你的头痛就越少。如果我没有转到 WPF,我永远不会喜欢上 Web 技术,也不会转到 React 和 Flutter,尽管我知道有很多 UI 要从头开始重新设计,而且我对它没有什么经验。
托尼也经历了同样的事情。永远为你的旧作品保留一份备份,这样万一事情没有按计划进行,你至少有东西可以展示。
标志 7–50(部署)


所有向前发展的套装都有一个共同点,那就是它们变得非常容易装备,马克 7 将作为一个完整的包装到达,而马克 42 可以作为微小的零件出现并组装。
这里的关键是对网络开发者来说是必不可少的。
当你的产品依赖于用户的互联网连接来满足他们时,来回传输的每个字节的数据尽可能有效地压缩/组织是至关重要的。
让我们来看看当你把你的网站部署到托管服务上时,你必须做的几件事。
- 缩小你的 JS 和 CSS 。缩小从代码中删除必要和冗余的数据以节省空间。当额外文件空间的每一个字节都会影响网站加载时间和服务器负载时,这一点至关重要。

Left: Regular CSS | Right: Minified CSS
2.使用 CDN。CDN(内容交付网络)存储经常被请求的图像和视频等文件(比如您网站上加载的徽标或宣传片),因为这些文件通常比整个网站都大,而且总是按需提供,它们会给您的服务器增加很大的负担,因此利用 CDN 是一个不错的策略,CDN 是分布式服务器,为您托管您的媒体,并使它们可以立即访问。这些服务器通常比你的主机服务快得多,故障率也低。例子包括:
- 使用类似 Webpack for WebApps 的捆绑器:捆绑器本质上将你所有的源文件粘在一起,就像 React 应用的情况一样,并使它们一起工作,这样它们就可以通过服务器提供服务。所有文件都根据您的规范链接,定义入口点和出口点,设置何时显示哪个页面等等。捆绑再次减少了加载时间和最终的磁盘和网络空间利用率,从而节省了您的带宽和用户的等待时间。
马克 50–85(模块化、自动化和混合方法)

马克 50-85 基本上都是关于使服装适应环境,创造武器,随意支持,这是一个非常混合和模块化的方法。
在这些盔甲出现之前,每一件盔甲都很灵活,每一件都有一套武器和自己的用途,并不是所有的都能进入外太空,对付绿巨人等等。

虽然为某些用例编写定制的模块很好,但是您希望能够尽可能多地重用代码。当然,你拥有的那些过渡动画很酷,驱动它们的 100 行 CSS 是一件真正的艺术品,但是如果它们只适合主页上的滑块,又有什么用呢?
编写代码时,你应该记住在哪里可以重用某些组件。
像 React 这样的框架非常注重重用组件。几乎三分之二的登录表单可以重复使用来制作您的注册表单。

尽量减少重写相同组件和逻辑的需要,尽可能重用。准备条件,以便在检测到状态更改时,禁用并隐藏表单的某些元素。就像在这种情况下,如果表单状态设置为“登录”,那么密码确认和全名字段应该是不可见的,并且文本必须根据需要更改为登录。记住,避免冗余代码可以节省空间,最重要的是提高性能!
在电子表格或 Adobe XD 上一步一步地计划你的设计。随着时间的推移,你会养成在纸上规划设计,然后拼凑代码的习惯。

另一个有用的技巧是为你自己创建样板模板,这样你就可以从这些模板开始新的项目,而不是再次搜索所有的东西。所以即使你完成了这个项目,你也可以马上开始一个新的项目。
我可以推荐一些好的引导库:
- 对基本反应过来
- 对于高级 React(带路由器、Redux、Express 后端)
- Django、Flask 和其他一些人自带样板文件,是很好的起点。
- 对于静态网站,查找一些免费的模板,并尝试通过混合和匹配来修改它们,以满足您的要求。
写下你的要求,分析你还需要什么来实现你的梦想,并学习它们。一旦你完成了学习,将它们整合到你的项目中,冲洗并重复,直到你有一个你有信心向世界展示的版本。
请记住,你的程序员之旅将是一个持续的过程,需要大量的学习、遗忘和再学习。没有一种框架/语言是同等创建的,每一种都有自己的学习曲线和优缺点。在做决定之前,一定要考虑到所有这些因素。
正如我前面所说的,我花了很长时间才意识到我真正想把我的项目带到哪里,最终的规范(目前)只是在多次分解后才开始具体化。所以,如果你发现自己经常把东西拆开,不要担心。最后让你更习惯于造东西。所以继续建造疯狂的东西,打破它们,修复它们,返工它们。

以上都是我的观点,请务必在下面的评论中告诉我你的想法👇。我也想听听你的经历和建议😁。
直到下一次,坚持下去!

如何为数据收集和可视化构建您的个人基础架构,并成为您自己生成的数据点的真正所有者

这个故事的更新版本可以在 Platypush 博客 上免费获得。
智能家居可以生成和收集数据。大量数据。目前,家庭生成的数据还存在一些未解决的问题:
——碎片化。你可能有自己的家庭气象站,自己的运动探测器,安全摄像头,气体和烟雾探测器,身体传感器,GPS 和 fit 追踪器和智能插头。很可能这些设备中的大多数都会生成数据,并且在大多数情况下,这些数据只能通过专有的应用程序或网络服务来访问,并且与其他服务的任何集成,或者任何用于修补和自动化目的的空间,将主要取决于开发人员或企业在为这些数据构建第三方界面方面的善意。在本文中,我们将探索如何借助开源解决方案,如 platypush 、 Grafana 和 Mosquitto ,克服碎片问题,将原本无法通信和共享数据的数据源“粘合”在一起。
- 能够查询。大多数硬件和数据极客不会满足于通过应用程序或时间图表中的标尺来访问他们的数据的能力。我们中的许多人希望能够以结构化的方式探索我们自己生成的数据,最好是通过 SQL 或任何查询语言,我们需要量身定制的仪表板来探索我们的数据,而不是愚蠢的移动应用程序。对我们许多人来说,生成我们健身活动的定制月度报告、查询我们在特定时间范围内去过的国家、或者过去三个月我们在室内呆了多长时间、或者过去一周我们客房的烟雾探测器超过阈值多少次的能力是无价的,并且常常被硬件和软件制造商忽视。在本文中,我们将探讨如何利用开源关系数据库(在本例中为 PostgreSQL)和一些基本的数据管道在您的私人计算机上分发和存储数据,以便随时进行查询或可视化。
——隐私。我在前面的例子中提到的许多解决方案或服务都带有基于云的基础设施来存储用户数据。虽然将您的数据存储在其他人的计算机上可以节省您投资本地解决方案所需的时间和磁盘空间,但它也带来了与将您的数据存储在其他人的计算机上相关的所有问题。其他人可以决定你是否以及如何访问你的数据,可以决定出售你的数据获利,或者可以以这样或那样的方式被黑客攻击。如果我们谈论的是关于你自己的身体、位置或房屋环境的数据,这可能尤其令人担忧。家庭托管的数据基础设施绕过了数据的第三方所有权问题。
本文将分析构建数据基础设施的构件,并在此基础上构建自动化。我们将了解如何为一些用例(温度、湿度、气体、手机位置和 fit 数据)设置数据收集和监控,以及如何基于这些数据构建自动化触发器。
首先,你需要一个有鸭嘴兽的 RaspberryPi(或任何类似的克隆体)。我假设您已经安装并配置了 platypush。如果没有,请阅读我之前的文章如何开始使用 platypush 。
您还需要在设备上安装一个关系数据库。本文中的示例将依赖于 PostgreSQL,但是任何关系数据库都可以完成它的工作。在 Raspbian 上安装和配置 PostgreSQL 并创建一个名为sensors的数据库:
[sudo] apt-get install postgresql libpq-dev postgresql-client
postgresql-client-common -y
[sudo] systemctl restart postgresql.service
[sudo] su postgres
createuser pi -P --interactive
psql -U pi
> create database sensors;
我们将使用数据库来存储以下信息:
- 系统度量
- 传感器数据
- 智能手机和位置数据
- 拟合数据
您还需要在您的 RaspberryPi 上运行一个消息队列代理程序,以便通过新的数据读取来发送消息——查看这个 Instructables 教程,了解如何在您的 RaspberryPi 上启动和运行 Mosquitto。
对于一些数据测量,我们还需要一个 MQTT 客户机通过配置的队列发送消息——例如,从一个 shell 脚本发送测量。我喜欢使用mqttcli来实现这些目的——它快速、轻量并且是用 Go 编写的:
go get [github.com/shirou/mqttcli](https://github.com/shirou/mqttcli)
最后,安装 Grafana 作为基于网络的数据网关:
[sudo] apt-get install grafana
[sudo] systemctl restart grafana
启动服务后,前往[http://your-pi:3000](http://your-pi:3000),确保看到 Grafana 闪屏——创建一个新的管理员用户,现在就可以开始了。
现在您已经准备好了所有的基础部分,是时候设置您的数据收集管道和仪表板了。让我们从在数据库上设置表和数据存储逻辑开始。
数据库配置
如果您按照上面的说明操作,那么您将有一个 PostgreSQL 实例运行在您的 RaspberryPi 上,可以通过用户pi访问,并且有一个为此目的创建的sensors数据库。在这一节中,我将解释如何创建基本表和触发器来规范化数据。请记住,您的测量表可能会变得非常大,这取决于您处理的数据量和处理数据的频率。相对重要的是,要控制数据库大小并提高查询效率,提供由触发器强制执行的规范化表结构。出于我的目的,我准备了以下配置脚本:
上面的脚本将保持数据库中的数据规范化和查询友好,即使推送到消息队列中的消息不关心哪个是正确的数字 host_id 或 metric_id。对您的 PostgreSQL 实例运行它:
psql -U pi < database_provisioning.sql
现在您已经准备好了表格,是时候用数据填充它们了。我们将看到一些度量标准收集的例子,从系统度量标准开始。
系统度量
您可能希望监控您自己的 RaspberryPi 或任何其他主机或虚拟服务器的 CPU、RAM 或磁盘使用情况,比如设置一个仪表板来轻松监控您的指标,或者在事情失控时设置警报。
首先,创建一个脚本来检查系统上的可用内存,并在消息队列通道上发送已用内存的百分比——出于本教程的目的,我们将这个脚本存储在~/bin/send_mem_stats.sh下:
并在您的 crontab 中安排它每 5 分钟运行一次:
*/5 * * * * /bin/bash /home/pi/bin/send_mem_stats.sh
也可以为其他系统统计信息创建类似的脚本,例如,监控根磁盘的使用情况:
一旦在 crontab 中进行了调度,这些作业将开始定期将数据推送到您的消息队列中,按照配置的主题(在上面的示例中分别是sensors/<hostname>/memory和sensors/<hostname>/disk_root)。
现在是时候设置 platypush 来监听这些频道了,只要有新消息进来,就将它存储在您已经提供的数据库中。将以下配置添加到您的~/.config/platypush/config.yaml文件中:
启动 platypush,如果一切顺利的话,你很快就会看到你的sensor_data表被填充了内存和磁盘使用统计数据。
传感器数据
商业气象站、空气质量解决方案和存在探测器可能相对昂贵,并且在开放其数据时相对有限,但通过使用我们迄今为止谈论的成分,可以相对容易地在房子周围建立传感器网络,并让它们收集现有数据基础设施上的数据。为了本文的目的,让我们考虑一个从房子周围的一些传感器收集温度和湿度测量值的例子。在 RaspberryPi 上设置模拟传感器时,您主要有两种选择:
- 选项 1 :使用模拟微处理器(如 Arduino、ESP8266 或 ESP32)通过 USB 连接到您的 RaspberryPi,并配置 platypush 通过串口读取模拟测量值。RaspberryPi 是一项令人惊叹的技术,但它没有自带 ADC 转换器。这意味着,市场上许多将不同环境值映射到不同电压值的简单模拟传感器无法在 RaspberryPi 上工作,除非您在它们之间使用一个能够读取模拟测量值并通过串行接口将其推送到 RaspberryPi 的器件。出于我的目的,我经常使用 Arduino Nano 克隆,因为它们通常很便宜,但任何可以通过 USB/串口通信的设备都应该可以完成它的工作。您可以在互联网上找到便宜但精确的温度和湿度传感器,如 TMP36 、 DHT11 和 AM2320 ,它们可以轻松设置为与您的 Arduino/ESP设备通信。您所需要做的就是确保您的 Arduino/ESP设备在每次执行新的测量(例如
{"temperature": 21.0, "humidity": 45.0})时都会在串行端口上传回有效的 JSON 消息,这样 platypush 就可以很容易地了解某个测量值何时发生变化。 - 选项 2 :像 ESP8266 这样的设备已经带有 WiFi 模块,可以通过像
[umqttsimple](https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/MQTT/umqttsimple.py)这样的小型 MicroPython 库直接在 MQTT 上发送消息(查看本教程以及 ESP8266+MQTT 设置)。在这种情况下,您不需要串行连接,您可以从设备直接将数据从传感器发送到 MQTT 服务器。 - 选项 3 :使用通过 I2C/SPI 通信的分线传感器(如 BMP280 、 SHT31 或 HTU21D-F ),您可以直接插入 RaspberryPi。如果您采用这种解决方案,那么您将不再需要另一个微处理器来处理 ADC 转换,但您还必须确保这些器件附带一个 Python 库,并且在 platypush 中得到支持(如果不是这样,请随意提出问题或发送 pull 请求)。
让我们简单分析一下选项 1 实现的一个例子。假设您有一台 Arduino,其 7 号引脚上连接了 DHT11 温度和湿度传感器。您可以准备一个如下所示的草图,通过 USB 以 JSON 格式将新的测量值发送到 RaspberryPi:
然后,您可以将下面几行添加到 RaspberryPi 的~/.config/platypush/config.yaml文件中,该文件连接了传感器,用于向消息队列转发新的测量值,并将它们存储在本地数据库中。该示例还显示了如何调整轮询周期、容差和阈值,以及如何在传感器高于/低于特定阈值时运行自定义操作:
并且记得将sensors/your-rpi/temperature、sensors/your-rpi/humidity和您想要监控的任何其他 MQTT 主题添加到 MQTT/数据库主机上的backend.mqtt所监控的主题列表中。
有了这些简单的组件,您可以在数据库中存储任何类型的传感器数据,并轻松地在其上构建自动化规则。
智能手机和位置数据
我们的智能手机还会产生大量数据,这些数据可以在我们新的数据基础设施上进行跟踪,并实现自动化,让我们的生活变得更加轻松。在这个例子中,我们将展示如何在您的 Android 设备上利用 Tasker 、push pullet和 AutoLocation 来定期检查您的位置,将其存储在您的本地数据库中(这样您就可以关闭令人毛骨悚然的谷歌位置历史记录——对不起,是谷歌),并实施智能规则,例如打开照明和加热,并在您到家时说一句欢迎信息。
让我们首先看看如何将您的手机位置数据存储到您的本地数据库。
- 在你的手机上安装 Pushbullet、Tasker 和 AutoLocation 应用程序。
- 转到您的推送帐户设置页面并创建一个新的访问令牌。
- 在数据库主机上的 platypush 安装上启用 Pushbullet 后端。要添加到您的
config.yaml中的行:
backend.pushbullet:
token: your-token
device: platypush
-
向数据库中添加一个表来存储位置数据:
-
创建一个事件挂钩,用于监听包含纬度/经度信息的特定格式的推推通知(例如
LATLNG#7.8712,57.3123),并将它们存储在 PostgreSQL 数据库中: -
创建每 10 分钟(或 5 分钟、20 分钟,或您喜欢的任何频率)运行一次的 Tasker 规则,通过向您的 platypush 虚拟设备发送 Pushbullet 通知来更新您的位置:



保存 Tasker 个人资料后,您的智能手机将开始定期向 Pushbullet 发送其位置数据,您的 RaspberryPi 将拦截这些通知并将数据存储在您的本地数据库中。是时候抛弃第三方位置追踪器了!
当您进入或退出您的家庭区域时,如何运行自定义操作?让我们创建一个 Tasker 配置文件,它基于自动定位纬度/经度数据,检测您何时进入或退出某个区域。

该任务将简单地向您的 platypush 虚拟设备发送一个 Pushbullet 通知,其中包含HOME#1(您进入了您的家庭区域)或HOME#0(您退出了您的家庭区域)。


在您的 platypush config.yaml中添加一个事件挂钩来拦截通知并运行您的自定义逻辑:
根据目前为止显示的简单成分,将手机上的事件连接到智能家居基础设施相对简单,只要你的智能手机上有一个 Tasker 插件来实现你想要做的事情。
拟合数据
过去几年,智能手表、健身追踪器、身体传感器和智能健身算法在我们的手机上的爆炸式增长,为健康和健身技术开启了一场真正的革命。然而,由于市场的碎片化以及可视化和查询数据的有限可能性,这种革命仍未能发挥其全部潜力。大多数健康和健身解决方案都带有他们的 walled garden 应用程序:你只能使用开发者提供的应用程序访问数据,并且你只能使用该应用程序访问由你的特定传感器生成的数据。解决方案之间缺乏集成,这可能会给我们测量身体产生的数据的方式带来一场革命,我们喜欢向朋友展示这些很酷的技术,但没有多少实际用途。在过去的几年里,Google Fit 已经向前迈出了一些步伐;如今,越来越多的产品可以将数据同步到 Google Fit(我的建议是避开那些不同步的产品:它们只不过是闪闪发光的玩具,没有任何实用价值)。然而,尽管 Google Fit 允许你对你的身体数据有一个单一的视图,即使数据点是由不同的传感器收集的,但当它为你提供一个强大的方法来查询,比较和可视化你的数据时,它仍然非常有限。网络服务已经被扼杀了一段时间,这意味着访问你的数据的唯一途径是通过(坦白说非常有限)移动应用程序。而且你没有办法执行更高级的查询,比如比较不同时期的数据,找出一个月中你走路或睡觉最多的那一天,或者甚至只是在计算机上可视化数据,除非你利用 Fit API 编写自己的程序。
幸运的是,platypush 附带了一个方便的 Google Fit 后端 T2 和插件 T4,你可以利用它们轻松构建可视化、自动化和可查询的 Fit 数据库。
-
在数据库中准备合适的表。同样,我们将利用触发器来处理规范化:
-
前往 Google 开发者控制台获取您的证书 JSON 文件:

- 运行以下命令授权 platypush 访问您的 Fit 数据:
python -m platypush.plugins.google.credentials\
"[https://www.googleapis.com/auth/fitness.activity.read](https://www.googleapis.com/auth/fitness.activity.read) [https://www.googleapis.com/auth/fitness.body.read](https://www.googleapis.com/auth/fitness.body.read) [https://www.googleapis.com/auth/fitness.body_temperature.read](https://www.googleapis.com/auth/fitness.body_temperature.read) [https://www.googleapis.com/auth/fitness.location.read](https://www.googleapis.com/auth/fitness.location.read)"\
/path/to/your/credentials.json\
--noauth_local_webserver
- 在 platypush 运行的情况下,检查您的帐户上可用的数据源:
curl -XPOST -H 'Content-Type: application/json' \
-d '{"type":"request", "action":"google.fit.get_data_sources"}'\
http://your-pi:8008/execute
-
记下您想要监控的指标的
dataStreamId属性,将它们添加到 Google Fit 后端的配置中,并创建一个事件挂钩,将新数据插入到您新创建的表中: -
重启 platypush。您应该很快就会看到您的 fit 数据填充到您的表格中。
数据可视化和自动警报
现在,您已经构建了数据管道,将系统、传感器、移动和 fit 数据点传输到您的本地数据库,并在这些事件上建立自动化。但是我们都知道,如果我们不能将数据可视化,数据收集就只有一半的乐趣。是时候去我们安装的 Grafana 仪表盘创建一些图表了!
在浏览器中打开[http://your-pi-address:3000/](http://your-pi-address:3000/)。在 Grafana 中创建仪表板和面板非常简单。您所需要的就是指定可视化类型和想要对数据库运行的查询。显示每天行走的步数和活动时间的简单面板如下所示:

Grafana 还允许您在某些指标低于/高于某个阈值时,或者在某段时间内没有数据点时创建警报。你也可以通过利用 platypush 的网络钩子将这样的警报连接回 platypush 事件。
例如,让我们看看如何配置 Grafana,以便在您的某个气体传感器的测量值超过某个阈值时,向 platypush 自定义 web 挂钩发送通知,该挂钩会向您的移动设备发送 Pushbullet 通知:
- 向您的 platypush
config.yaml添加一个 web hook 事件:
这个配置将创建一个可以通过[http://your-pi:8008/hook/gas_alert](http://your-pi:8008/hook/gas_alert.)T5 访问的动态 web 钩子。
- 进入你的 Grafana 仪表盘,点击“提醒”(右边的铃铛图标)->通知频道,然后添加你的网络链接:

- 编辑包含气体传感器测量值的面板,单击钟形图标,并在数值超过某个阈值时添加自动警报:

每当有与您的指标相关的提醒时,您都会在手机上收到推送通知。
如果到目前为止您已经阅读了这篇文章,那么您应该已经具备了使用自己的数据做任何事情的所有要素。本文尽最大努力展示有用的示例,但并不打算详尽地指导您通过连接数据库、数据管道和事件及自动化引擎所能做的一切。我希望我已经为您提供了足够的输入来激发您的创造力并构建新的东西:)
如何通过 3 个简单的步骤构建你的机器学习应用
使用 Streamlit 为您的数据科学项目构建 web 应用程序并使用 Heroku 进行部署的简单方法

Photo by Markus Spiske on Unsplash
如果你是一名数据科学家,你会经常被这个问题困扰。
我已经建立了我的数据科学项目。现在,我如何让人们能够接触到它?我如何展示我的作品?
我能想到的两个最常见的选择是:
1)将项目代码作为 Jupyter 笔记本。
2)为您的项目构建一个 web 应用程序。
对于第一种选择,通常使用 Github 或 Jupyter Notebook Viewer 来公开您的代码。如果有人想测试您的项目,他们要么必须下载并在本地计算机上运行笔记本,要么在 Jupyter 笔记本查看器中在线运行笔记本。
对于第二种选择,最常见的是使用 HTML 或 JavaScript 和 Flask 围绕您的数据科学项目构建一个 web 应用程序,然后通过该应用程序运行您的项目。但是,构建一个优秀的、精致的、美观的 web 应用程序需要一定程度的 HTML 或 JavaScript 技能,这有点难以快速学习,尤其是如果你的主要关注点是数据科学。
有没有一种简单的方法可以让我为我的数据科学项目构建一个 web 应用程序,同时避免 HTML、CSS 或 JavaScript 的复杂性?
输入细流
Streamlit 是一个简单而强大的库,它让你只用 Python 就能构建具有丰富 ui 的 web 应用。它带有各种小部件,支持可视化库,如 ALTAIR、GraphViz、Plotly 以及对 GPU 的支持。
这篇文章是关于了解如何为你的数据科学项目创建一个 Streamlit 应用程序并在 Heroku 上部署它。
要了解更多关于 Streamlit 的信息,可以看看它的开发者发的这个帖子。
步骤 1:构建您的项目
对于这个项目,我决定建立一个流媒体服务,实时捕捉与特定标签相关的推文,然后对这些推文进行情感分析。我用 Tweepy 和 Vader 的情绪来做这个。 Tweepy 是一个围绕 Twitter API 的 python 包装器,帮助你挖掘 Twitter 数据。 维达情感 是一个基于规则的情感分析库,专为推文的情感分析而设计。
我的推特流代码:
analyser = SentimentIntensityAnalyzer()class StreamListener(tweepy.StreamListener):
def on_status(self, status):
if not stop:
text = status.text
score = analyser.polarity_scores(text)
st.write(text)
st.write("The sentiment is: {}".format(str(score)))
return True
else:
exit()
return Falsedef stream_tweets(tag):
listener = StreamListener(api=tweepy.API(wait_on_rate_limit=True, wait_on_rate_limit_notify=True))
streamer = tweepy.Stream(auth=auth, listener=listener, tweet_mode='extended')
query = [str(tag)]
streamer.filter(track=query, languages=["en"])
在上面的代码中,我定义了一个函数 stream_tweets ,我将' tag' 传递给它,这将是我想要 tweets 的查询。我使用 tweepy 创建了一个 twitter 流。流 并且我使用了我在类stream listener中定义的监听器。当一条推文包含标签时,它被 on_status 函数检测为 状态 。然后,我们可以轻松地使用状态来使用推文。我使用 分析器 获取推文文本的情感,然后显示推文及其情感。上面代码中的 st 是导入的 Streamlit 库, stop 是一个按钮的变量,用于停止推文的流式传输。
你需要在你的本地机器上安装 Tweepy 和 Vader 的情绪,并在 Twitter 上获得一个开发者帐户来传输推文。
步骤 2:使用 Streamlit 设计一个 web 应用程序
对于这一步,我在我的机器上安装了 streamlit。
pip install streamlit
我使用下面的代码来设计我的 web 应用程序。
import streamlit as stst.header("Twitter Streamer and Sentiment Analysis")st.write("Enter the query is the text box and click the 'Get Tweets' button. A stream of tweets will start along with the sentiment for each tweet. Press the stop button in right hand corner to stop the streaming. Press the reset button to reset the streamer.")t = st.text_input("Enter a hastag to stream tweets")start = st.button("Get Tweets")stop = st.button("Reset")
在 streamlit 中创建小部件就像在 python 中创建变量一样简单。在上面的代码中,我使用 st.header 函数创建了一个 header。st.write 功能可以让你在你的应用程序中写入任何东西,无论是文本、图表、地图等等。接下来,我使用ST . text _ input来创建一个文本输入框,以获取我想要的 tweets 流标签。它存储在变量 t 中。我还创建了两个按钮' 【开始】 ',以启动流媒体和' 停止 '以停止流媒体和重新加载应用程序。
然后我把流媒体功能链接到按钮' 开始 '上。
if start:
stream_tweets(str(t))
按下“开始”按钮即可触发推文流。我将代码保存在一个名为 hello.py 的文件中。
然后,我检查了 UI 的外观。
streamlit run hello.py

步骤 3:在 Heroku 上部署
现在最后一步是在 Heroku 上部署 app。
首先,我在 Heroku 上创建了一个帐户。

然后,我创建了一个新项目,命名为 twitter-streaming-rohan。
但是,在 Heroku 上部署应用程序之前,我需要定义一些文件。
首先,我定义了需求文件,它包含了我的项目所需的所有库。Heroku 引擎将自己安装所有的库,它们只需要在 requirements.txt 文件中指定。
requirements.txt
tweepy
streamlit
pyyaml
vaderSentiment
接下来,我定义了我想要使用的 Python 的运行时版本。我用的是 python 3.7。
runtime.txt
python-3.7.3
接下来是 setup.sh 文件。这是在 Heroku 运行 streamlit 所必需的。
setup.sh
mkdir -p ~/.streamlit/echo "\
[general]\n\
email = \"email@website.com\"\n\
" > ~/.streamlit/credentials.tomlecho "\
[server]\n\
headless = true\n\
enableCORS=false\n\
port = $PORT\n\
" > ~/.streamlit/config.toml
我创建的最后一个文件是 Procfile 。它包含启动应用程序要执行的命令。我将此文件保存为不带任何扩展名的普通文本文件。
Procfile
web: sh setup.sh && streamlit run hello.py
我把所有这些文件放在同一个文件夹里,命名为 twitter-streaming。
然后,我把代码推给了 Heroku。
为此,我在本地机器上安装了 Heroku CLI。
现在,我从终端登录 Heroku,使用:
$heroku login
接下来,我转到项目目录:
$cd twitter-streaming
然后,我使用以下命令初始化该目录中的 git:
$git init
$heroku git:remote -a twitter-streaming-rohan
twitter-streaming-rohan 是我在 Heroku 上的项目名称。
然后,我将所有文件添加到 Heroku:
$git add .
已提交更改:
$git commit -am “first-commit”
推动变革:
$git push heroku master
就是这样!!
应用程序已部署。
我去了网址查看应用程序。对我来说,是 https://twitter-streaming-rohan.herokuapp.com/的
我的应用程序已经启动并运行。

结论
有了 Streamlit 和 Heroku,您可以快速简单地部署您的 ML 应用程序,而且完全免费。Streamlit 应用程序也可以部署在 AWS、谷歌云或任何其他云上。有了各种各样的小部件和库,Streamlit 的可能性是无穷无尽的。它还有一个丰富的社区论坛。
现在,构建 ML 应用程序比以往任何时候都容易!!
这个应用程序的完整代码可以在这里找到。
感谢Gabe mal donato讲解 Streamlit 在 Heroku 的部署。
如何从零开始构建自己的 PyTorch 神经网络层
并了解一些关于权重初始化的知识

这实际上是杰瑞米·霍华德第五课的作业。我已经展示了使用 PyTorch 从零开始构建卷积神经网络是多么容易。今天,让我们试着更深入地研究一下,看看我们是否可以编写自己的nn.Linear模块。既然脸书的开发人员已经写好了 PyTorch 模块,为什么还要浪费时间写自己的呢?
嗯,首先,你会对所有的部分是如何组合在一起的有更深的理解。通过将您的代码与 PyTorch 代码进行比较,您将了解为什么以及如何开发这些库。
此外,一旦你完成了,你将对实现和使用所有这些库更有信心,知道事情是如何工作的。对你来说不会有神话。
最后但同样重要的是,如果情况需要,您将能够修改/调整这些模块。这就是 noob 和 pro 的区别。
好了,动机够了,让我们开始吧。
简单的 MNIST 一层 NN 作为背景
首先,我们需要一些“背景”代码来测试我们的模块是否执行以及执行得有多好。让我们建立一个非常简单的单层神经网络来求解古老的 MNIST 数据集。下面的代码片段(在 Jupyter 笔记本中运行):
# We'll use fast.ai to showcase how to build your own 'nn.Linear' module
%matplotlib inline
from fastai.basics import *
import sys
# create and download/prepare our MNIST dataset
path = Config().data_path()/'mnist'
path.mkdir(parents=True)
!wget http://deeplearning.net/data/mnist/mnist.pkl.gz -P {path}
# Get the images downloaded into data set
with gzip.open(path/'mnist.pkl.gz', 'rb') as f:
((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding='latin-1')
# Have a look at the images and shape
plt.imshow(x_train[0].reshape((28,28)), cmap="gray")
x_train.shape
# convert numpy into PyTorch tensor
x_train,y_train,x_valid,y_valid = map(torch.tensor, (x_train,y_train,x_valid,y_valid))
n,c = x_train.shape
x_train.shape, y_train.min(), y_train.max()
# prepare dataset and create fast.ai DataBunch for training
bs=64
train_ds = TensorDataset(x_train, y_train)
valid_ds = TensorDataset(x_valid, y_valid)
data = DataBunch.create(train_ds, valid_ds, bs=bs)
# create a simple MNIST logistic model with only one Linear layer
class Mnist_Logistic(nn.Module):
def __init__(self):
super().__init__()
self.lin = nn.Linear(784, 10, bias=True)
def forward(self, xb): return self.lin(xb)
model =Mnist_Logistic()
lr=2e-2
loss_func = nn.CrossEntropyLoss()
# define update function with weight decay
def update(x,y,lr):
wd = 1e-5
y_hat = model(x)
# weight decay
w2 = 0.
for p in model.parameters(): w2 += (p**2).sum()
# add to regular loss
loss = loss_func(y_hat, y) + w2*wd
loss.requres_grad = True
loss.backward()
with torch.no_grad():
for p in model.parameters():
p.sub_(lr * p.grad)
p.grad.zero_()
return loss.item()
# iterate through one epoch and plot losses
losses = [update(x,y,lr) for x,y in data.train_dl]
plt.plot(losses);

这些代码很容易理解。我们在这个项目中使用了 fast.ai 库。下载 MNIST pickle 文件并解压缩,将其转换为 PyTorch 张量,然后将其填充到 fast.ai DataBunch 对象中,以便进一步训练。然后我们创建了一个只有一个Linear层的简单神经网络。我们还编写了自己的update函数,而不是使用torch.optim优化器,因为我们可以从头开始编写自己的优化器,作为 PyTorch 学习之旅的下一步。最后,我们遍历数据集并绘制损失图,以查看它是否有效以及效果如何。
第一次迭代:让它工作
所有 PyTorch 模块/层都是从torch.nn.Module扩展而来。
class myLinear(nn.Module):
在这个类中,我们需要一个__init__ dunder 函数来初始化我们的线性层,并需要一个forward函数来进行正向计算。让我们先来看看__init__函数。
我们将使用 PyTorch 官方文档作为构建模块的指南。从文档中可以看出,nn.Linear模块具有以下属性:
因此,我们将获得这三个属性:
def __init__(self, **in_features, out_features, bias=True**):
super().__init__()
** self.in_features = in_features
self.out_features = out_features
self.bias = bias**
该类还需要保存重量和偏差参数,以便进行训练。我们也初始化那些。

** self.weight** = torch.nn.Parameter(torch.randn(out_features, in_features))
** self.bias** = torch.nn.Parameter(torch.randn(out_features))
这里我们用torch.nn.Parameter来设置我们的weight和bias,否则,它不会训练。
另外,请注意,我们使用了[torch.rand](https://pytorch.org/docs/stable/torch.html#torch.randn)n而不是文档中描述的来初始化参数。这不是权重初始化的最佳方式,但我们的目的是让它先工作,我们将在下一次迭代中调整它。
好了,现在__init__部分完成了,让我们继续forward功能。这实际上是最简单的部分:
def forward(self, input):
_, y = input.shape
if y != self.in_features:
sys.exit(f'Wrong Input Features. Please use tensor with {self.in_features} Input Features')
**output = input @ self.weight.t() + self.bias
return output**
我们首先获得输入的形状,计算出输入中有多少列,然后检查输入大小是否匹配。然后我们做矩阵乘法(注意我们在这里做了转置来调整权重)并返回结果。我们可以通过给它一些数据来测试它是否有效:
my = myLinear(20,10)
a = torch.randn(5,20)
my(a)
我们有一个 5x20 的输入,它通过我们的层,得到一个 5x10 的输出。您应该会得到这样的结果:

好,现在回到我们的神经网络代码,找到Mnist_Logistic类,将self.lin = nn.Linear(784,10, bias=True)改为self.lin = myLinear(784, 10, bias=True)。运行代码,您应该会看到类似这样的图:

如你所见,它没有很好地收敛(一个时期大约 2.5 次损失)。那很可能是因为我们初始化不好。另外,我们没有注意到bias部分。让我们在下一次迭代中解决这个问题。第一次迭代的最终代码如下所示:
class myLinear(nn.Module):
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.bias = bias
self.weight = torch.nn.Parameter(torch.randn(out_features, in_features))
self.bias = torch.nn.Parameter(torch.randn(out_features))
def forward(self, input):
x, y = input.shape
if y != self.in_features:
sys.exit(f'Wrong Input Features. Please use tensor with {self.in_features} Input Features')
output = input @ self.weight.t() + self.bias
return output
第二次迭代:正确的权重初始化和偏差处理
我们已经处理了__init__和forward,但是记住我们还有一个bias属性,如果False,将不会学习加法偏差。我们还没有实施。此外,我们使用torch.nn.randn来初始化权重和偏差,这不是最佳的。让我们解决这个问题。更新后的__init__函数如下:
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.bias = bias
**self.weight = torch.nn.Parameter(torch.Tensor(out_features, in_features))
if bias:
self.bias = torch.nn.Parameter(torch.Tensor(out_features))
else:
self.register_parameter('bias', None)** **self.reset_parameters()**
首先,当我们创建weight和bias参数时,我们没有将它们初始化为最后一次迭代。我们只是给它分配一个规则的张量对象。实际的初始化在另一个函数reset_parameters中完成(将在后面解释)。
对于bias,我们增加了一个条件,如果True,做我们上一次迭代做的事情,但是如果False,将使用register_parameter(‘bias’, None)给它None值。现在对于reset_parameter功能,它看起来是这样的:
def reset_parameters(self):
**torch.nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))**
if self.bias is not None:
**fan_in, _ torch.nn.init._calculate_fan_in_and_fan_out(self.weight)
bound = 1 / math.sqrt(fan_in)
torch.nn.init.uniform_(self.bias, -bound, bound)**
以上代码直接取自 PyTorch 源代码。PyTorch 对权重初始化所做的称为kaiming_uniform_。它来自一篇论文深入研究整流器:在 ImageNet 分类上超越人类水平的性能——何,k .等人(2015) 。

它实际上所做的是通过用均值为 0 且方差为 T16 的正态分布初始化权重,它避免了消失/爆炸梯度的问题(尽管我们在这里只有一层,当编写线性类时,我们仍然应该记住 MLN)。
请注意,对于self.weight,我们实际上给了a一个值math.sqrt(5)而不是math.sqrt(fan_in),这在 PyTorch repo 的 this GitHub issue 中有所解释,可能有人对此感兴趣。
同样,我们可以在模型中添加一些extra_repr字符串:
def extra_repr(self):
return 'in_features={}, out_features={}, bias={}'.format(
self.in_features, self.out_features, self.bias is not None
)
最终的模型如下所示:
class myLinear(nn.Module):
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.bias = bias
self.weight = torch.nn.Parameter(torch.Tensor(out_features, in_features))
if bias:
self.bias = torch.nn.Parameter(torch.Tensor(out_features))
else:
self.register_parameter('bias', None)
self.reset_parameters()
def reset_parameters(self):
torch.nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
if self.bias is not None:
fan_in, _ = torch.nn.init._calculate_fan_in_and_fan_out(self.weight)
bound = 1 / math.sqrt(fan_in)
torch.nn.init.uniform_(self.bias, -bound, bound)
def forward(self, input):
x, y = input.shape
if y != self.in_features:
print(f'Wrong Input Features. Please use tensor with {self.in_features} Input Features')
return 0
output = input.matmul(weight.t())
if bias is not None:
output += bias
ret = output
return ret
def extra_repr(self):
return 'in_features={}, out_features={}, bias={}'.format(
self.in_features, self.out_features, self.bias is not None
)
重新运行代码,您应该能够看到这个图:

我们可以看到,它在一个时期内收敛到 0.5 的损耗要快得多。
结论
我希望这能帮你驱散这些 PyTorch nn.modules上的阴霾。这可能看起来很无聊和多余,但有时最快(也是最短)的方法就是“无聊”的方法。一旦你深究此事,那种知道没有什么“更多”的感觉是无价的。你会意识到:
在 PyTorch 下面,没有技巧,没有神话,没有陷阱,只有坚如磐石的 Python 代码。
此外,通过编写自己的代码,然后与官方源代码进行比较,您将能够看到不同之处,并向行业中的佼佼者学习。多酷啊。
觉得这篇文章有用?在 Medium 上关注我(李立伟)或者你可以在 Twitter @lymenlee 或者我的博客网站wayofnumbers.com上找到我。你也可以看看我下面最受欢迎的文章!
为什么 CS50 特别适合巩固你的软件工程基础
towardsdatascience.com](/this-is-cs50-a-pleasant-way-to-kick-off-your-data-science-education-d6075a6e761a) [## 一枚硬币的两面:杰瑞米·霍华德的 fast.ai vs 吴恩达的 deeplearning.ai
如何不通过同时参加 fast.ai 和 deeplearning.ai 课程来“过度适应”你的人工智能学习
towardsdatascience.com](/two-sides-of-the-same-coin-fast-ai-vs-deeplearning-ai-b67e9ec32133) [## 你需要了解网飞的“朱庇特黑仔”:冰穴📖
是时候让 Jupyter 笔记本有个有价值的竞争对手了
towardsdatascience.com](/what-you-need-to-know-about-netflixs-jupyter-killer-polynote-dbe7106145f5)
如何计算客户保持率——一种实用的方法
可以说,留住人才是新的营销黄金,但计算起来并不总是那么容易。有了这个简单的 Python 脚本,一切都将改变!

If you don’t have a way to measure Customer Retention, how will you know if you’re “leaking” customers? (photo: Vryheid Herald)
如此多的指标,如此少的时间…
我明白了。你是一个大忙人,没有时间阅读介绍!不幸的是,我确实需要简单解释一下我们在衡量什么,因为有太多的指标围绕着客户保持率和忠诚度!与我的大多数其他文章相反,这里的代码会很短,但是我需要确保概念是清楚的,因为很容易弄乱计算。
我将回顾测量客户保持率的基础知识和原因,然后以一个提供保持率表的 Python 脚本结束
如果你已经关注了我,你知道我通常写 Python 项目并在最后分享代码。这次也不会例外!然而,这一次我决定去做一个项目,一些项目实际上可能适用于他们自己的职业现实,甚至他们自己的企业。请在评论中告诉我你是如何解决的!
在试图计算任何东西之前,你需要明白的最重要的一件事是每个企业在衡量保留率时都有自己的细微差别。对于网上商店,你可能想知道每月有多少顾客购买你的商品。对于一家 SaaS 公司,您可能需要考虑有多少客户保持活跃的付费订阅。另一方面,如果你与在 Reddit 或脸书等社交平台工作的分析师交谈,他们可能会更关注用户访问量,而不是购买量。举个例子,如果你有一个像游戏一样的免费增值应用,情况也是如此。
这并不是说我们不关心购买和其他与金钱相关的指标,但是这里的主要思想是衡量我们的用户是否会回来!这是知道你是否有好产品的最终方法,对吗?(提示:是反问句!)
在衡量最近度时,行业之间也存在这些细微的差异,最近度是指从与用户最后一次交互起经过的时间。术语“相互作用”可以有很多含义……但这是一篇关于 RFM 分析的全新文章的主题!
在整篇文章中,我会向你抛出几个名字,你应该事先知道它们的意思:
- 流失率(或损耗率) —在一段时间内放弃你的产品的客户的百分比
- 保留率 —在一段时间内继续使用你的产品的客户的百分比
- 队列分析:注意到上面的“一段时间”了吗?您是否想每天、每周、每月地测量保留率?在我们的例子中,我将测量的每日保持率。群组分析可能是分析保留率和流失率的最佳工具。这是一个特定类型的表,将用户分成“桶”(群组),每个群组将包含在同一天/周/月/等注册的用户。也就是说,每个群组指的是一段时间(在我们的例子中是一天)。
为什么留住客户很重要?
评估您的收购策略的质量
看到上面的图了吗,有一根漏水的管子?如果你没有衡量客户保持,你可能有一个[客户]流失的问题。当你花费宝贵的金钱通过 AdWords 或脸书广告或任何你可能拥有的获取策略来获取新用户时,你可能会以灾难性的速度失去现有用户。
如果你不能让你的用户回来,你基本上就是在烧钱。
让它深入人心。
当你花费宝贵的金钱获取新用户的时候,你的产品却无法吸引他们,从长远来看,这将会扼杀你的生意。
My business model is solid because I get so many new users!
也许这有点苛刻…但这说明了一个问题。如果你想对你的商业模式做出明智的决定,你需要知道你的保留率。你还会想知道你的客户的终身价值是多少,这样你就可以评估你是否花了太多的钱来获得他们,但这超出了本文的范围!
当你计划下一次 AdWords 或 FB 广告活动以获得新用户时,想想这张 GIF!
它允许你测试什么有效,什么无效
当然,使用与保留相关的指标不仅有助于评估您的收购活动。你可以尝试几件事,比如 A/B 测试注册服务或应用程序功能。给一月注册的用户 A,给二月注册的用户 B。衡量留存率,并检查是否有比其他活动效果更好的活动。冲洗。重复一遍。
这就是为什么脸书向人类介绍了新闻提要。你还记得我们只看到朋友们分享的内容,这就足够了吗?后来有一天,脸书决定推出新闻提要。随之而来的是社会动荡,具有讽刺意味的是,这最终证明脸书采取这一举措是正确的。他们知道人们花更多的时间在网上,与其他人交往,并且更经常回来。
他们做了测试,数据显示保留率更高。因此,他们不顾公众的强烈抗议,全力以赴。在线游戏完善了他们的使命,以最大限度地提高用户参与度(另一个吸引人的名字)。
同样的原则也适用于用户旅程。如果你决定要给新用户提供一个特定的旅程(这可能与游戏应用程序更相关),你可以检查哪个路线图最好。你可以看到哪个特定的旅程让用户在你的应用/平台停留的时间更长。如果你将留存指标与销售指标交叉,你还可以看到停留时间更长的用户是否比以前花费更多或更少的钱。然后,显然,你可以针对他们的活动,并评估他们的表现。
不过我跑题了……
我可以继续说其他几点,了解你的产品保持率会让你受益,但是这两点应该足够让你信服了!底线是,对一些人来说,保留是王道。这应该是合乎逻辑的,因为如果你留住你的客户更久,他们最终会在你的产品上花更多的钱,这意味着增加他们的终身价值。
我明白了…但是我们从哪里开始呢?
好吧,我们从获取一些数据开始!
我想超越电子商务商店的经典教科书示例及其 2015 年的月销售额,所以我继续为一个虚构的应用程序创建了一个虚构的数据集。想象一下,这个应用程序是一个免费的游戏,用户可以免费玩,但也要花一些钱。
为了在您自己的环境中工作,您需要提取关于哪些用户在应用程序中活跃的日常数据。您不需要每天提取它,但是您必须有一个表来显示在您定义的时间范围内的每一天谁是活跃的。
如果您选择分析每月保留,请将上面句子中的单词“每日和“日”替换为“每月”和“月”。或者“周”和“周”等等。你是自己分析的主人!
你可以在文章末尾找到我的 csv 格式的数据集。每一行都和一个玩家一天的活动有关。你可以有重复的玩家名字,如果他们在几天内都是活跃的(希望如此!).但是让我澄清一下这些列是什么:
- 用户名:唯一用户 id
- 注册日期:玩家注册的日期
- ref_date :活动的日期
- 钱:玩家在那个 ref_date 花了多少钱
- 时间:用户在 ref_date 打了多少分钟
- 国家:例如,这种分类可以让你对球员进行细分,并计算每个国家的保留率。
下面是我们将使用的文件片段:

最后来点 Python!
下面的代码基于我之前讨论的 csv 的文件结构。如果您试图在其他项目中使用它,请注意您可能需要做一些小的调整——例如,列名。

为了管理你的期望(实际上是增加期望),让我告诉你这个项目的最终结果应该是什么。
我们将查看从我们的应用程序中收集的数据,并应用一些小的更改来将其转换为正确的格式。这样,我们就可以有一个简单的数据透视表,其中包含每天活跃的用户数量。
之后,我们还可以构建留存率表,它是第一个数据透视表的变体。
最后,我们为两个表构建热图,并尝试得出任何结论。我希望这是一个足够强大的激励,让你不要再去折腾了。看到我做了什么吗?!

This heatmap displays how many users from each cohort (signup date on the left) were active during their lifecycle (their seniority).
让我们开始编码吧!
和往常一样,我们从导入将要使用的包开始。没什么特别的,但是我们将使用 seaborn 绘制热图,用于我们的保留可视化,因此我们为此导入 matplotlib 和 seaborn 。我们还将读取我们的数据集和熊猫。

在左边,您可以看到我们刚刚导入的表的前 10 行。
根据这些信息,用户 U10000 自注册以来访问了我们的应用 6 次。
我们需要格式化日期并添加另一个名为资历的列。资历基本上告诉我们用户在访问我们的应用程序的那一天有多大。我们在上面加了 1,因为这样更容易阅读,资历 10 意味着用户在注册后的第 10 天。

现在我们能够建立队列。但是在这种背景下到底什么是队列?
将群组想象成桶,根据一定的标准将客户分组。
这样,你就可以比较关于你的产品和你的用户的生命周期的几个指标。这里的重要信息是“跟踪它们的生命周期”。
我们的群组将从注册日期开始创建(每个日期一个)。这样,它们就互相排斥了。我们首先使用 groupby 方法,使用 signup_date 和residency,并获得它们的大小。我们还需要重置索引。

在左侧,这是此时该表的外观。
这看起来可能不多,但是您现在有了每个注册日期的每个资历(在我们的数据中是 1 到 15)的用户数。
但是我们还没有完成。我们需要把它变成一个数据透视表。
正如我之前提到的,数据透视表是我们稍后将用来创建热图可视化的。它应该有索引中的注册日期和列中的资历。这些值将从用户名列中获得,经过上一步后,该列现在包含群组的用户计数。
我在上面的代码片段中添加了一些东西,这样我们就为下一步准备好了两个表。你可能已经注意到,我没有分享任何公式或一些奇怪的方程来计算保留。网上有很多这样的东西,老实说,如果你不明白你在计算什么,就很容易混淆或者应用错误。
我们试图找出一天中我们“留住”了多少顾客。首先我们得到一个绝对数字,然后我们计算一个百分比。
这个百分比等于同一个群组在一天 中的 活跃用户数除以群组在第 1 天 开始的 用户数。如果在第 N 天有 10 个人注册,7 天后只有 4 个人还在,那么 7 天后该群组的保留率为 40% (4/10)。

I’ve been told he is quite convincing…
流失率恰恰相反。如果我们保留了 40%的用户,这意味着他们中的 60%已经流失了。为了简单起见,我们只深入讨论留存率,但请记住,流失率与留存率正好相反!
上面的片段显示了如何在生命周期开始时(资历= 1)从每个群组中分离出注册人数。我使用了一个名为 base 的变量,这就是我用来计算保留率的变量,用整个群组计数矩阵除以 base 。看看下面的两个数据透视表:


通常,第一天的保留率应该是 100%,因为我们将整个表除以第一列。这很有意义,因为在我们的例子中,每个用户在他们的注册日期都是活跃的。
热图是可视化群组分析的绝佳工具
只要你知道如何阅读它们!下面您可以找到获得两个热图的代码,一个是用户计数,另一个是保留率。
- 每一行都是同一天注册的一群用户。
- 每一列代表用户在其生命周期中所处的位置(以天、周、月等为单位)。
您可以通过两种主要方法从这张热图中获得一些有用的见解。最显而易见的方法是观察一个特定的群体在变老时的表现。姑且称之为横向途径。在典型的热图中,您会看到用户数量从左向右下降。除非你有一个优秀的产品,每个用户每天/每月/等等都会回来!

为了强调这一点,我在上面标记的方块显示,在 10 月 3 日注册的 11 个用户中,有 4 个用户在第六天是活跃的。
第二种方法——可能不太明显——是评估我们的产品在留住特定资历阶段的用户方面表现如何。让我们称之为垂直方法。使用保留表而不是用户计数更容易理解,因为通常群组可能没有相同的基数来纵向比较它们——而比率是一个百分比。查看热图,然后查看示例。

The dataset is not large enough to draw big conclusions, but at least it looks cool…
举个例子,假设我们更新了我们的应用程序,当用户达到第八天的时候,我们会推送通知。我们预计一些用户会在第 8 天登录,也许我们甚至可以为他们提供一些东西作为激励,让他们再次参与进来。然后,我们预计在第 8 天左右,获得更新的用户会出现某种高峰。查看等于 8 的资历栏,我们可以看到不同队列的保留率是如何变化的。
这就是你如何为你的新功能,或新用户体验,或任何你认为可能影响用户保持的东西创建 A/B 测试。这就是你如何实际监控它是否工作。
结束语
这篇文章绝对超出了我的想象!我仍然想向您展示如何比较不同国家的用户保持率,以及如何为不同的指标而不是用户数构建群组分析。
国比较简单。你只需要根据你想要比较的国家来分割数据框架 df ,并对每个新的国家数据框架遵循完全相同的代码片段。
在该文件中,我们还有两列“金钱”和“时间”,我们可以用它们来构建群组分析,向我们显示每个群组在其生命周期中花费了多少“金钱”或“时间”。一个想法是检查用户随着生命周期的发展,花费是增加还是减少。如果你想增加特定人群的支出,这是一个很好的跟踪方法。
不幸的是,这篇文章太长了,所以我将把最后一个建议作为对你的挑战。如果你真的真的… 真的,想让我写另一篇关于队列分析、终生价值的文章,或者这一篇的后续文章,请在评论中告诉我。我试着回答所有的问题,所以我会注意是否有很多人提出同样的要求!
这里是 存储库 的链接,我在这里放置了包含客户数据的 csv 文件和包含代码的 Jupyter 笔记本。
我希望这篇文章是有帮助的,也许你甚至可以向你的团队展示一些新的东西。如果您有任何问题,或者如果您看到任何不准确的地方,请让我知道。如果你有营销或创意背景,请允许我无耻地塞一个朋友的 简介 ,他写的是营销策略、创意等等。希望你喜欢!
感谢您的阅读!如果你喜欢这篇文章,我邀请你看看我的其他故事。我主要感兴趣的是数据科学、Python、 区块链 和数字货币、技术,以及其他一些像 摄影 !
如果你想取得联系,可以在LinkedIn上联系我或者直接回复下面的文章。
我的其他文章包括:
* [## 用一个简单的 Python 机器人增加你的 Instagram 粉丝
我在 4 天内有了 500 个真正的追随者!
towardsdatascience.com](/increase-your-instagram-followers-with-a-simple-python-bot-fde048dce20d) [## 用 Python 绘制马科维茨有效边界
基于历史数据,这个边界将允许你根据你的期望优化你的投资组合配置…
towardsdatascience.com](/python-markowitz-optimization-b5e1623060f5)*
如何计算世界上任何地点的旅行时间

Isochrone map from London, Source: Esri UK
关于如何在 Python 中执行等时线(从一点到另一点的旅行时间)的指南。
不同的交通方式(如骑自行车、步行或驾车)需要不同的到达时间。但是你有没有想过,“从现在的位置往任何方向走 10 分钟能到达哪里?”
这就是等时线(旅行时间图)的本质。等时线(希腊文 isos 的意思是‘相等’, chrónos 的意思是‘时间’),指的是旅行时间相等的线。
例如,送货公司可以使用等时线来确定 30 分钟车程内可到达的送货区域。或者,使用最大通勤时间和交通方式偏好,从你的工作场所找到一个理想的新家。
在本教程中,我将向您展示如何在 Python 中执行等时线(旅行时间图)。我们将为街道网络使用 OSMnx Python 库。这篇文章的代码可以作为 Mybinder Notebook 获得。不需要安装任何东西就可以在网上运行和试验它。
如果想在本地电脑上运行,需要用 pip 安装这三个库: networkx ,Osmnx,和 Geopandas 。
让我们先从建设街道网络开始。
网络图
首先,我们需要获得我们想要的位置的数据。所以,让我们先下载并可视化一个地方的街道网络数据。在本教程中,我将以瑞典斯德哥尔摩为例。随意挑选任何其他地点。
首先,让我们导入库。
# 1\. Import libraries
import geopandas as gpd
from shapely.geometry import Point, LineString, Polygon
import networkx as nx
import osmnx as ox
import matplotlib.pyplot as plt
from descartes import PolygonPatch
from IPython.display import IFrame
ox.config(log_console=True, use_cache=True)
现在我们需要为我们想要创建的网络图设置参数。你需要一个地址或坐标(纬度和经度)。如果你提供一个名字或者一个地址,Osmnx 会进行地理编码并返回该地区的网络图。
让我们为斯德哥尔摩市创建一个网络图。在下面的代码片段 1 和 2 中,我们首先创建两个变量来保存位置和运输方式。
一旦我们有了这些变量,我们就可以创建一个图表。OSMNx 有不同的创建图形的方式;在这个例子中,我们从一个地址创建了一个网络图。您可以通过调整代码片段 3 中的 distance 参数来增加或减少返回的网络图的面积。
最后一个片段(#4)显示了如何绘制图形,该图形可视化了带有边和节点的区域的街道网络。

Network graph plotted
该图包含斯德哥尔摩街道网络的节点和边,并提供了距离(1500)。如果你想要一个有这些图形网络的背景地图,OSMNX 有一个创建叶子地图的功能。
下面是带背景底图的叶图。

让我们试试另一个例子。因为这是一个重复的任务,所以我创建了一个函数,它还可以接受其他参数,如交通方式、距离和位置类型。
现在,我们可以从任何地址/坐标得到一个网络。让我们使用坐标(纬度和经度)作为我们的位置来测试这个函数。这次我们提供来自伦敦的坐标。
在从上述代码中的坐标创建了一个图形之后,我们还绘制了这个图形。这是伦敦图形网络的输出图。

London
接下来,我们将根据网络图创建行程时间图(等时线)。
等时线(旅行时间)
首先,我们用交通方式建立兴趣点和图形网络。让我们为更大的网络斯德哥尔摩创建一个距离为 7k 的步行图。
一旦我们创建了遍历图,下一步就是从图中创建节点(代码片段#2)。在代码片段 3 中,我们指定了我们感兴趣的点——时间旅行开始的地方。最后,我们将图从纬度/经度投影到合适的 UTM 投影。
接下来,我们将确定行程时间和行驶速度。
我们希望旅行分为 5 类,从 5 分钟到 1 小时不等。我们还指定平均步行速度为千米每小时(4.5),然后转换为米每分钟。
现在我们已经设置了行程和行驶速度,我们可以为五个行程类别创建行驶时间(等时线)。
第一段代码为不同的旅行时间提供了不同的颜色。然后在第二个代码片段中,我们遍历行程时间及其颜色,用适当的颜色填充节点。
最后,我们用图形网络来绘制色点。这是输出。

这些点根据它们的行驶时间被涂上颜色,例如,在 60 分钟内,你可以到达在外围涂上浅红色的点。然而,这些彩色的图形节点并不在多边形中,但是我们可以像这样很容易地从这些点创建多边形。
一旦我们创建了等时多边形,我们就可以使用 plot_graph 函数和笛卡尔库中的 PlygonPatch 来绘制它们。
下面绘制的网络图更直观地显示了行驶时间的区域。

Isochrones
注意:OSMNx 没有用 follow 底图绘制等时线的固有功能。我怀疑这是由于地理投影。请记住,在运行等时线过程之前,我们已经对图表进行了投影。
但是,您可以使用 Geopandas 从 isochrone_polys 创建地理数据框架,并通过提供适当的通用横轴墨卡托(UTM)投影区将其导出。
我还包含了如何使用正确的 UTM 投影将等时线多边形导出到 shapefile 的代码。
结论
在本教程中,我们介绍了如何使用 Python 执行旅行时间。尝试不同的位置,并测试您所在区域的旅行时间(等时线)情况。这个 Binder 容器中提供了代码,您可以运行并试验它。
[## GitHub:shaka som/isochronewithosmnx/master
单击运行此交互式环境。来自活页夹项目:可复制、可共享、交互式计算…
mybinder.org](https://mybinder.org/v2/gh/shakasom/isochronewithosmnx/master)
如何校准欠采样模型得分
二元预测模型中的不平衡数据问题,以及用 Python 和 r 处理这些问题的简单而有效的方法。

Random Undersampling Flower
不平衡的数据,万恶之源
不平衡数据简单地指的是其中一个类别形成高多数并支配其他类别的情况。对于机器学习,目标值的偏斜分布可能会导致算法的准确性偏差,并对模型的性能产生负面影响。在这一点上,模型和性能指标的目标是实质性的。
我们用一个例子来澄清一下。如果您的目标列具有带有%1 的真类,那么就基本准确性而言,总是预测假的模型将有 99%的成功率。然而,这在大多数情况下是不切实际的,因为假阳性(或 I 型误差)和假阴性(或 II 型误差)预测的成本通常是不相等的。
有几个解决不平衡数据问题的方法,但在这篇文章中,我将提到欠采样方法和校准过程,调整最终分数。
什么是欠采样?
假设您的数据有一个比率高度不对称的二进制目标变量。为了平衡目标的比例,增加机器学习算法对少数类的关注,减少了多数类的行数。这个过程称为欠采样,应用于模型训练前的数据准备阶段。

The data before and after undersampling
在欠采样过程之后,在模型分数的分布上可以看到一些副作用。例如,如果训练数据中的真类的比率是 %5 ,我们期望概率预测的平均值也是 %5 。但是,如果我们操纵目标类别比率,我们也会改变预测分数的分布。对非目标类别的随机欠采样提高了训练数据中目标类别的先验概率,并且最终增加了概率预测。

这是个问题吗?
如果您的目标是根据实例的预测得分选择一定数量的实例,欠采样不是问题,因为它不会改变实例的概率得分顺序。例如,如果您需要为您的营销活动指定一个具有最高倾向得分的人群,您不需要担心采样不足的副作用。
然而,在某些情况下,现实的概率预测很重要:
- 客户终身价值或类似的计算需要校准的概率预测。假设你有价值 100 美元的产品 A 和对产品 A 倾向评分为 0.1 的用户 B 。所以,用户 B 在营销方面的价值是 100\(*0.1=10\)。
- 如果假阳性或假阴性预测的成本很高,则要求有现实的概率预测。在您想要指定罪犯的情况下,误报通常是不可容忍的。或者如果你试图预测一个人是否患有癌症,这个顺序通常是没有意义的,另一方面,概率是至关重要的。
“如果你给所有发生的事件 0.6 的概率,给所有不发生的事件 0.4 的概率,你的辨别能力是完美的,但你的校准是糟糕的”。
丹尼尔·卡内曼
校准会改变什么?
如果您使用 AUC 作为模型评估指标,您将看不到校准前后的任何差异,因为 AUC 关心的是区分类别,而不是它们的概率。但是,如果您使用的度量标准(如对数损失)与似然函数配合使用,情况就会有所不同。
在下图中,您可以看到校准前后欠采样数据的概率预测分布。紫色竖线表示原始数据中目标类的先验概率。从图表中可以看出,欠采样模型预测的红色区域在校准过程之后变得与先验概率高度一致。

The comparison of the score distribution before and after calibration
让我们校准
为了调整模型输出中的概率,我们校准它们。有两种众所周知的校准算法:普拉特缩放和保序回归。
除了这些,我想说一下另一个不复杂的校准公式及其在 python 和 r 中的作用。
以下是函数参数的解释:
- 数据:模型输出的概率预测数组
- train_pop: 训练数据集中的总行数
- target_pop: 训练数据集中目标类的总行数
- sampled_train_pop: 欠采样后训练数据集中的总行数
- sampled_target_pop: 欠采样后训练数据集中目标类的总行数
校准功能:
Calibration function in python
Calibration function in R
如何使用该功能?
假设你的目标是生成一个显示信用违约概率的模型,你的原始训练数据有 50,000 行,其中只有 500 行被标记为目标类。当您随机对非目标实例进行采样,并将总行数减少到 10,000 ,同时保留 500 个目标行时,我们的校准函数变为:
校准(型号 _ 结果,50000,500,10000,500)
这里 model_results 是你的模型概率输出数组。在您训练您的模型并将结果放入其中之后,您的函数就可以使用了。好好享受吧!

参考
如何用自己的物联网家庭工作站捕捉天气数据
通过 MQTT 协议捕获天气数据,并在本地和物联网服务上记录这些数据。

介绍
当我们谈论温度、压力等物理变量时。作为一名数据科学家,通常您会从在其他地方创建的数据集开始工作。但是你想过如何自己捕捉那些数据吗?
在本教程中,我们将学习如何从几个不同的传感器获取数据,并将它们发送到物联网服务 ThingSpeak.com 和移动应用程序(Thingsview),在那里我们可以记录和处理数据。我们还将探索将传感器连接到 Raspberry Pi 的几种不同通信方式,如下所示:
- DHT22 —温度和湿度传感器—数字通信
- DS18B20 —温度传感器—单线
- BMP180 —温度和压力传感器— I2C
- UV —紫外线传感器—通过 A/D 和 SPI 总线的模拟传感器
简而言之,所有数据将被捕获,保存在本地 CSV 文件中,并通过 MQTT 协议发送到物联网服务(ThingSpeak.com ),如下图所示:

为了完成一个真正的气象站,在最后一步,你还将学习如何测量风速和风向,遵循毛里西奥·平托的教程。
供应品:
- 树莓派 V3
- DHT22 温湿度传感器
- 电阻器 4K7 欧姆
- DS18B20 防水温度传感器
- 电阻器 4K7 欧姆
- BMP180 气压、温度和海拔传感器
- 紫外线传感器
- Adafruit MCP3008 8 通道 10 位 ADC,带 SPI 接口
1.开发环境— Jupyter 笔记本
Jupyter Notebook 是一个非常棒的工具,或者更好的说法是一个开源的 web 应用程序,它允许您创建和共享包含实时代码、等式、可视化和叙述性文本的文档。Jupyter 笔记本主要用于数据科学,用于清理和转换数据,进行数值模拟,统计建模,数据可视化,机器学习,等等!
在本教程中,我们将使用 Jupyter Notebook 与 Raspberry Pi GPIOs 进行交互,直接读取传感器并将数据发送到互联网。
安装
如果您的 RPi 上已经安装了 Jupyter 笔记本,您可以跳过这一步
要在您的 Raspberry 上安装 Jupyter(将与 Python 3 一起运行),请打开终端并输入以下命令:
sudo pip3 install jupyter
sudo ipython3 kernelspec install-self
现在,在您的终端上,运行命令:
jupyter notebook
就是这样!!!!太神奇了!非常简单容易。Jupyter 笔记本将作为服务器运行在:
http:localhost:8888

请注意,您的默认浏览器将在上述地址自动打开,作为“主页”运行,如上图所示。
要停止服务器并关闭“内核”(Jupyter 笔记本),您必须使用键盘上的[Ctrl] + [C]。
从现在开始,任何时候你启动你的 Pi 并想使用 Jupyter notebook,只需在你的终端上输入命令:“Jupyter Notebook”并让它一直运行。这个很重要!
例如,如果您需要使用终端执行另一项任务,如运行程序,请打开一个新的终端窗口。
你可以按照这个教程一步一步来,创建自己的笔记本,或者从我的 GitHub 下载最终版:Rpi _ Weather _ station . ipynb。
2.DHT22 —温度和湿度传感器

将安装的第一个传感器是 DHT22,用于采集空气温度和相对湿度数据。 ADAFRUIT 网站提供了关于这些传感器的大量信息。贝娄从那里检索到一些信息:
概述
低成本 DHT 温度和湿度传感器非常简单,速度较慢,但非常适合想要进行一些基本数据记录的爱好者。DHT 传感器由两部分组成,一个电容式湿度传感器和一个热敏电阻。内部还有一个非常基本的芯片,可以进行一些模数转换,并根据温度和湿度发出数字信号。使用任何微控制器都很容易读取数字信号。
DHT22 主要特征:
适用于 0–100%湿度读数,精确度为 2–5%适用于-40 至 125°C 温度读数,精确度为 0.5°C 采样频率不超过 0.5 Hz(每 2 秒一次)
- 低成本
- 3 至 5V 电源和 I/O
- 转换期间的最大电流消耗为 2.5mA(请求数据时)
- 机身尺寸 15.1 毫米 x 25mm 毫米 x 7.7mm 毫米
- 4 个间距为 0.1 英寸的引脚
如果您通常在小于 20 米的距离上使用传感器,则应在数据和 VCC 引脚之间连接一个 4K7 欧姆的电阻。DHT22 输出数据引脚将连接到 Raspberry GPIO 16。检查上述电气图,将传感器连接到 RPi 引脚,如下所示:
- 引脚 1 — Vcc ==> 3.3V
- 引脚 2 —数据==> GPIO 16
- 引脚 3 —未连接
- 引脚 4 — Gnd ==> Gnd
不要忘记在 Vcc 和数据引脚之间安装 4K7 欧姆电阻
一旦连接了传感器,我们还必须在 RPi 上安装它的库。
安装分布式哈希表库:
在您的覆盆子上,从/home 开始,转到/Documents
cd Documents
创建一个安装库的目录并移动到那里:
mkdir DHT22_Sensor
cd DHT22_Sensor
在您的浏览器上,转到 Adafruit GitHub:
Python 库来读取树莓 Pi 或 Beaglebone Black 上的 DHT 系列湿度和温度传感器。…
github.com](https://github.com/adafruit/Adafruit_Python_DHT)
通过点击右边的下载 zip 链接来下载这个库,并在您最近创建的 Raspberry Pi 文件夹中解压存档文件。然后转到库的目录(解压文件时自动创建的子文件夹),并执行命令:
sudo python3 setup.py install
在 Jupyter 笔记本上,导入 Adafrut DHT 库,定义连接 DHT 和 RPi 的数字 pin,并运行代码以捕获温度和湿度:
import Adafruit_DHT
DHT22Sensor = Adafruit_DHT.DHT22
DHTpin = 16humDHT, tempDHT = Adafruit_DHT.read_retry(DHT22Sensor, DHTpin)
if (humDHT is not None) and (tempDHT is not None):
hum = round (humDHT,1)
temp = round (tempDHT, 1)
运行电池并打印结果:
print(‘Temperature = {}*C Humidity = {}%’.format(temp, hum))
下面是 Jupyter 笔记本显示结果的部分:

3.DS18B20 —温度传感器

传感器概述:
在本教程中,我们将使用 DS18B20 传感器的防水版本。这对于在潮湿条件下捕捉温度非常有用,例如在潮湿的土壤上。该传感器是隔离的,可以在 125 摄氏度之前进行测量(由于其电缆 PVC 护套,Adafrut 不建议在 100 摄氏度以上使用)。
DS18B20 是一款数字传感器,即使是长距离使用也很方便!这些单线数字温度传感器相当精确(大部分范围内为±0.5°C ),板载数模转换器的精度最高可达 12 位。它们使用单个数字引脚与 RPi 配合工作,您甚至可以将多个数字引脚连接到同一个引脚,每个数字引脚在出厂时都有一个唯一的 64 位 ID,以便区分。
该传感器的工作电压范围为 3.0 至 5.0V,这意味着它可以直接由其中一个覆盆子引脚(1 或 17)提供的 3.3V 电源供电。
该传感器有 3 根电线:
- 黑色:GND
- 红色:VCC
- 黄色:单线数据
在这里,你可以找到完整的数据: DS18B20 数据手册
传感器安装:
按照上图进行连接:
- Vcc ==> 3.3V
- Gnd == >接地
- Data ==> GPIO 4(库的默认值)
安装 Python 库:
接下来,让我们安装将处理传感器的 Python 库:
sudo pip3 install w1thermsensor
在运行脚本测试传感器之前,检查 RPi 中是否启用了“1-Wire”接口(参见下面的打印屏幕)

启用接口
更改配置后,不要忘记重启 RPi
测试传感器:
为了测试传感器,可以使用一个简单的 python 代码:
from w1thermsensor import W1ThermSensor
ds18b20Sensor = W1ThermSensor()
tempExt = round(ds18b20Sensor.get_temperature(), 1)
print('External Temperature = {}*C'.format(tempExt))
下面是 Jupyter 笔记本显示结果的部分:

4.BMP180 —温度和压力传感器

传感器概述:
BMP180 是 BMP085 的继任者,BMP 085 是面向消费者应用的新一代高精度数字压力传感器。BMP180 的超低功耗、低压电子器件针对移动电话、PDA、GPS 导航设备和户外设备的使用进行了优化。BMP180 的低空噪声仅为 0.25 米,转换速度快,性能卓越。I2C 接口便于系统与微控制器集成。BMP180 基于压阻技术,具有 EMC 鲁棒性、高精度、线性度和长期稳定性。
完整的 BMP 数据表可以在这里找到: BMP180 —数字压力传感器
传感器安装:
按照上图进行连接:
- Vin ==> 3.3V
- GND ==> GND
- SCL ==> GPIO 3
- SDA ==> GPIO 2
启用 I2C 接口
转到 RPi 配置并确认 I2C 接口已启用。如果没有,请启用它并重启 RPi。
使用 BMP180
如果一切都已安装和连接好,你现在准备好打开你的 Pi,并开始查看 BMP180 告诉你关于你周围的世界。
首先要做的是检查 Pi 是否看到你的 BMP180。在终端窗口中尝试以下操作:
sudo i2cdetect -y 1
如果该命令有效,您应该会看到类似下面的终端打印屏幕,显示 BMP180 在通道' 77 '上。

安装 BMP180 库:
创建一个安装库的目录,并转到该目录:
mkdir BMP180_Sensor
cd BMP180_Sensor
在您的浏览器上,转到 Adafruit GITHub:
Python 库,用于访问 BMP 系列压力和温度传感器,如树莓 Pi 上的 BMP 085/BMP 180…
github.com](https://github.com/adafruit/Adafruit_Python_BMP)
通过点击右边的下载 zip 链接来下载库,并在您的 Raspberry Pi 创建的文件夹中解压缩归档文件。然后转到创建的子文件夹,在库的目录中执行以下命令:
sudo python3 setup.py install
在 Jupyter 上,编写以下代码:
import Adafruit_BMP.BMP085 as BMP085
bmp180Sensor = BMP085.BMP085()
tempBMP = round(bmp180Sensor.read_temperature(), 1)
presBMP = round(bmp180Sensor.read_pressure()/100, 1)
altBMP = round(bmp180Sensor.read_altitude(),1)
用以下代码检查传感器读取的变量:
print ('Temperature = {} C '.format(tempBMP))
print ('Pressure = {} hPa [or mbar]'.format(presBMP))
print ('Altitud = {} m '.format(altBMP))
下面是 Jupyter 笔记本显示结果的部分

注意,传感器压力以 Pa(帕斯卡)为单位。参见下一步,更好地了解本单元。
5.用 BMP180 测量天气和高度

海平面压力
让我们花点时间来了解更多关于我们将会得到的 BMP 读数。
你可以跳过这部分教程,或者稍后返回,如果你想知道更多关于传感器读数的信息,请去这个伟大的教程:https://learn.sparkfun.com/tutorials/bmp180-barome...
BMP180 设计用于精确测量大气压力。大气压力随着天气和高度而变化。
什么是大气压?
大气压的定义是你周围的空气对一切物体施加的力。大气中气体的重量产生大气压力。压力的常用单位是“磅每平方英寸”或 psi。我们将在这里使用国际符号,即每平方米的牛顿,称为帕斯卡(Pa)。
如果你拿 1 厘米宽的空气柱会重约 1 公斤
这个重量压在柱子上,产生大气压力,我们可以用 BMP180 等传感器测量。因为厘米宽的空气柱重约 1 公斤,所以平均海平面气压约为 101325 帕斯卡,或者更好,1013.25 百帕(1 百帕也称为毫巴)。每上升 300 米,这将下降约 4%。你升得越高,你看到的压力就越小,因为到大气层顶部的柱子要短得多,因此重量也就轻得多。知道这一点很有用,因为通过测量压力和做一些数学计算,你可以确定你的高度。
海拔 3810 米的气压只有海平面气压的一半。
BMP180 以帕斯卡(Pa)为单位输出绝对压力。一帕斯卡是一个很小的压力,大约相当于一张纸放在桌子上所产生的压力。你会经常看到以百帕为单位的测量值(1 百帕= 100 帕)。这里使用的库提供了以 hPa 为单位的输出浮点值,恰好等于 1 毫巴(mbar)。
以下是一些到其他压力单位的转换:
- 1 百帕= 100 帕= 1 毫巴= 0.001 巴
- 1 百帕= 0.75006168 托
- 1 百帕= 0.01450377 磅/平方英寸(磅/平方英寸)
- 1 百帕= 0.02953337 英寸汞柱
- 1 百帕= 0.00098692 大气压(标准大气压)
温度影响
因为温度影响气体的密度,密度影响气体的质量,质量影响压力(咻),大气压会随着温度发生剧烈变化。飞行员将此称为“密度高度”,这使得在寒冷的日子比炎热的日子更容易起飞,因为空气密度更大,空气动力学效应更大。为了补偿温度,BMP180 包括一个相当好的温度传感器和一个压力传感器。
要读取压力,首先要读取温度读数,然后将其与原始压力读数相结合,得出最终的温度补偿压力测量值。(图书馆让这一切变得非常容易。)
测量绝对压力
如果您的应用需要测量绝对压力,您所要做的就是获得温度读数,然后执行压力读数(详见示例草图)。最终压力读数的单位为 hPa = mbar。如果您愿意,可以使用上述换算系数将其转换为不同的单位。
注意,大气的绝对压力会随着你的高度和当前的天气模式而变化,这两者都是可以测量的有用的东西。
天气观测
地球上任何给定位置(或任何有大气的地方)的大气压力都不是恒定的。地球自转、地轴倾斜和许多其他因素之间的复杂相互作用导致较高和较低压力的移动区域,这反过来导致我们每天看到的天气变化。通过观察气压的变化,你可以预测天气的短期变化。例如,压力下降通常意味着潮湿的天气或暴风雨即将来临(低压系统正在移动)。压力上升通常意味着晴朗的天气即将来临(一个高压系统正在通过)。但是请记住,大气压力也随着高度而变化。我家的绝对压力,在智利的 Lo Barnechea(海拔 950 米)将永远低于例如旧金山的绝对压力(不到 2 米,几乎是海平面)。如果气象站仅仅报告了它们的绝对压力,就很难直接比较一个地点和另一个地点的压力测量值(大规模的天气预报依赖于尽可能多的气象站的测量值)。
为了解决这个问题,气象站总是从他们报告的压力读数中消除海拔的影响,通过数学方法加上等效的固定压力,使其看起来好像是在海平面上读取的。当你这样做的时候,旧金山的读数总是比 Lo Barnechea 高,这是因为天气模式,而不是因为海拔。
为此,库中有一个函数叫做 海平面(P,A) 。这采用了以百帕为单位的绝对压力(P)和以米为单位的测站当前高度(A ),并从压力中去除了高度的影响。您可以使用此功能的输出直接将您的天气读数与世界上其他气象站的数据进行比较。
确定高度
由于压力随着海拔高度而变化,您可以使用压力传感器来测量海拔高度(有一些注意事项)。海平面上大气的平均压力是 1013.25 百帕(或毫巴)。当你向太空的真空爬升时,这个值会下降到零。因为这个下降曲线很好理解,你可以用一个特定的方程计算两个压力测量值(p 和 p0)之间的高度差。
如果你使用海平面气压(1013.25 百帕)作为基线气压(p0),方程式的输出将是你目前的海拔高度。库中有一个函数叫做 海拔(P,P0) 可以让你得到“计算的海拔”。
以上解释摘自 BMP 180 Sparkfun 教程。
6.海平面压力测量

正如我们在上一步中了解到的,手头有海平面压力是很重要的,一旦我们有了测量绝对压力的真实高度,就可以计算出海平面压力。下面的函数可以帮助我们:
def bmp180GetData(altitude):
temp = bmp180Sensor.read_temperature()
pres = bmp180Sensor.read_pressure()
alt = bmp180Sensor.read_altitude()
presSeaLevel = pres / pow(1.0 - altitude/44330.0, 5.255)
temp = round (temp, 1)
pres = round (pres/100, 2)
alt = round (alt)
presSeaLevel = round (presSeaLevel/100, 2)
return temp, pres, alt, presSeaLevel
在我的例子中,我将 BMP180 安装在 957 米的实际测量高度上,因此我们可以从传感器获得以下更新数据:

7.使用 ADC(模数转换器)

下一步,我们将讨论如何从一个非常简单但性能良好的模拟传感器获取 UV 数据。这里的问题是,Raspberry Pi 没有模拟输入引脚作为 Arduino 或 NodeMCU,但我们可以通过使用模数(A/D)转换器来解决这个问题,这将有助于模拟传感器与 Raspberry Pi 的接口。我们将在这个项目中使用的模数转换器是流行的 MCP3008。
MCP3008 是一款 10 位 8 通道 ADC(模数转换器),使用 SPI 总线协议与 Raspberry Pi 接口。它很便宜,不需要任何额外的部件。它提供 8 路模拟输入,仅使用 4 个 Raspberry Pi gpio,外加电源和接地引脚。MCP3008 输出范围为 0–1,023,其中 0 表示 0V,1,023 表示 3.3V
MCP3008 引脚排列

MCP3008 的引脚编号从左上开始(引脚 1: CH0),顶部有一个半圆,如上图所示。MCP3008 ADC 共有 16 个引脚,其中 8 个引脚用于接收模拟输入。模拟输入引脚来自 CH0-CH7(引脚 1–8)。在另一侧(引脚 9–16),我们有如下不同的功能:
- 09 — DGND 是芯片的数字接地引脚。
- 10 — CS 是片选引脚。连接到 RPi 引脚 24 (SPI0 — CE)
- 11 — DIN 是 Raspberry Pi 引脚 19 (SPI0 — MOSI)的数据输入引脚
- 12 — DOUT 是数据输出引脚。连接到 RPi 引脚 21 (SPI0 — MISO)
- 13 — CLK 是时钟引脚。连接到 RPi 引脚 23 (SPI0 — SCLK)
- 14 — AGND 是模拟接地引脚。
- 15 — VREF 是模拟基准电压。接 3.3V,想换刻度可以换。16 — VDD 是芯片的电源引脚。
在这个项目中,我们将使用通道 0(引脚 1)作为模拟输入。
SPI
Raspberry Pi 配有一条 SPI 总线,具有 2 个芯片选择。Raspbian 上的 SPI 主驱动器默认禁用。要使能它,使用 raspi-config 确认 spi 总线已使能(与之前使用 1-Wire 完成的程序相同)。
首先,导入 spidev,一个访问 SPI 总线的 Linux 驱动程序:
import spidev
并打开和配置总线:
spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz=1000000
从那里,您可以访问我们 ADC 的任何模拟通道。为了测试,编写下面的函数:
def ReadChannel(channel):
adc = spi.xfer2([1,(8+channel)<<4,0])
data = ((adc[1]&3) << 8) + adc[2]
return data
然后,将通道 0 (MCP3008 引脚 1)连接到 3.3V,并运行以下功能:
ReadChannel(0)
结果,您应该看到:1023
8.模拟紫外线传感器

这种紫外线传感器产生一个与光感应光谱中的紫外线辐射成比例的模拟输出。它使用紫外光电二极管(基于氮化镓),可以检测 240-370 纳米范围的光(覆盖 UVB 和大部分 UVA 光谱)。来自光电二极管的信号电平非常小,在纳安级,因此该模块嵌入了一个运算放大器,将信号放大到更可读的电压电平(0 至 1V)。
通过将 VCC 连接到 3.3VDC,将 GND 连接到电源地,可以给传感器和运算放大器供电。模拟信号可以从 OUT 引脚获得。其输出以毫伏为单位,由连接到 RPi 的 ADC 的模拟输入(CH0)读取。
使用上一步中显示的相同代码,我们可以看到由 UV 传感器生成的“原始数据”(在本例中为“43”):

有了原始的传感器数据,我们应该“转换”(或“映射”)它的值,以便代码更好地处理。我们可以用函数 readSensorUV()来实现。该功能读取紫外线传感器 3 次,取平均值并将测量值转换为 mV:
def readSensorUV():
numOfReadings = 3
dataSensorUV = 0
for i in range(numOfReadings):
dataSensorUV += ReadChannel(0)
time.sleep(0.2)
dataSensorUV /= numOfReadings
dataSensorUV = (dataSensorUV * (3.3 / 1023.0))*1000;
return round(dataSensorUV)
例如,原始测量值“43”实际上相当于 128 毫伏:
如果我们看下面的表格和曲线:

我们会看到 128mV 应该和指数 0 到 1 之间的辐射有关。让我们创建一个函数来计算这个指数,这是最常见的紫外线辐射测量。我们将考虑一个范围,以上表所示的 Vout 为起点,范围为 110mV。例如,介于 227 毫伏和 337 毫伏之间的紫外线测量值将被视为指数 1。
def indexCalculate(dataSensorUV):
if dataSensorUV < 227: indexUV = 0
elif (227 <= dataSensorUV) & (dataSensorUV < 318): indexUV = 1
elif (318 <= dataSensorUV) & (dataSensorUV < 408): indexUV = 2
elif (408 <= dataSensorUV) & (dataSensorUV < 503): indexUV = 3
elif (503 <= dataSensorUV) & (dataSensorUV < 606): indexUV = 4
elif (606 <= dataSensorUV) & (dataSensorUV < 696): indexUV = 5
elif (696 <= dataSensorUV) & (dataSensorUV < 795): indexUV = 6
elif (795 <= dataSensorUV) & (dataSensorUV < 881): indexUV = 7
elif (881 <= dataSensorUV) & (dataSensorUV < 976): indexUV = 8
elif (976 <= dataSensorUV) & (dataSensorUV < 1079): indexUV = 9
elif (1079 <= dataSensorUV) & (dataSensorUV < 1170): indexUV =10
else: indexUV = 11
return indexUV
因此,对于之前的测量(128mV),指数应为 0。

9.完整的硬件和软件

此时,我们已经安装并测试了所有的传感器。现在让我们开发一个函数来一次捕获所有数据:
import datetimedef getSensorData():
global timeString
global humLab
global tempExt
global tempLab
global presSL
global altLab
global presAbs
global UV_mV
global UV_index now = datetime.datetime.now()
timeString = now.strftime("%Y-%m-%d %H:%M") tempExt = round(ds18b20Sensor.get_temperature(), 1)
tempLab, presAbs, altLab, presSL = bmp180GetData(altReal) humDHT, tempDHT = Adafruit_DHT.read_retry(DHT22Sensor, DHTpin)
if humDHT is not None and tempDHT is not None:
humLab = round (humDHT) UV_mV = readSensorUV()
UV_index = indexCalculate(UV_mV)
请注意,我已经将所有传感器变量定义为全局变量。您可以将它们保存在本地,从函数中返回值(这是一种更好的做法)。

10.本地记录数据

此时,您拥有了从传感器获取大量数据的所有工具。但是该拿它们怎么办呢?
最简单的答案是创建一个循环函数来定期捕获数据,并将它们保存在本地文件中。
with open("/home/pi/rpi_weather_station.csv", "a") as log:
while True:
getSensorData()
log.write("{},{},{},{},{},{},{},{},{}\n".format(timeString, humLab, tempExt, tempLab, presSL, altLab, presAbs, UV_mV, UV_index))
time.sleep(30)
上面的代码在你的根目录下打开一个名为“rpi_weather_station.csv”的文件。

每隔 30 秒,时间戳加上来自所有传感器的数据将被“附加”到该文件中,如上所示。
11.物联网——向云服务发送数据

至此,我们已经了解了如何从传感器捕获数据,并将其保存在本地 CSV 文件中。现在,是时候看看如何将这些数据发送到物联网平台了。在本教程中,我们将使用ThingSpeak.com。
“ThingSpeak 是一个开源的物联网(IoT)应用程序,使用 REST 和 MQTT APIs 来存储和检索数据。ThingSpeak 支持创建传感器日志应用程序、位置跟踪应用程序和具有状态更新的社交网络。”
首先,你必须在 ThinkSpeak.com 有一个账户。接下来,按照说明创建一个通道,记下它的通道 ID 和写 API 键。

创建频道时,您还必须定义将上传到 8 个字段中的每个字段的信息,如上所示。
12.MQTT 协议和 ThingSpeak 连接
MQTT 是一种发布/订阅架构,主要用于通过无线网络连接带宽和功率受限的设备。它是一个简单的轻量级协议,运行在 TCP/IP 套接字或 web 套接字上。WebSockets 上的 MQTT 可以用 SSL 保护。发布/订阅体系结构使得消息能够被推送到客户端设备,而无需设备持续轮询服务器。
MQTT 代理是通信的中心点,它负责在发送者和合法接收者之间分发所有消息。客户机是连接到代理的任何设备,可以发布或订阅主题以访问信息。主题包含代理的路由信息。每个想要发送消息的客户端将消息发布到某个主题,每个想要接收消息的客户端订阅某个主题。代理将带有匹配主题的所有消息传递给适当的客户端。
ThingSpeak 在 URLmqtt.thingspeak.com和端口 1883 有一个 MQTT 代理。ThingSpeak 代理支持 MQTT 发布和 MQTT 订阅。
在我们的例子中,我们将使用 MQTT Publish。

MQTT 发布
首先,让我们安装 Eclipse Paho MQTT Python 客户端库,它实现了 MQTT 协议的 3.1 和 3.1.1 版本。
sudo pip install paho-mqtt
接下来,让我们导入 paho 库:
import paho.mqtt.publish as publish
并启动 Thingspeak 通道和 MQTT 协议。这种连接方法最简单,需要的系统资源最少:
channelID = "YOUR CHANNEL ID"
apiKey = "YOUR WRITE KEY"topic = "channels/" + channelID + "/publish/" + apiKey
mqttHost = "mqtt.thingspeak.com"
tTransport = "tcp"
tPort = 1883
tTLS = None
现在,您必须定义要上传到您的物联网服务的主题有效负载(“tPayload”):
tPayload = “field1=” + str(humLab)+ “&field2=” + str(tempExt)+ “&field3=” + str(tempLab)+ “&field4=” + str(presSL)+ “&field5=” + str(altLab) + “&field6=” + str(presAbs)+ “&field7=” + str(UV_mV) + “&field8=” + str(UV_index)
并发送它:
print ("[INFO] Data prepared to be uploaded")
try:
publish.single(topic, payload=tPayload, hostname=mqttHost, port=tPort, tls=tTLS, transport=tTransport)
print ("[INFO] Data sent for 8 fields: ", humLab, tempExt, tempLab, presSL, altLab, presAbs, UV_mV, UV_index)
except:
print ("[INFO] Failure in sending data")
如果一切正常,您将获得发送数据的“回声”,在 ThingSpeak 频道页面上,您可以看到这些数据。

13.在物联网服务上记录传感器数据

ThingSpeak 频道上传了数据
现在,我们知道只需几行代码就可以将数据上传到物联网服务,让我们创建一个循环函数,以固定的时间间隔自动上传数据(类似于我们在“本地记录数据”中所做的)。
持续捕获数据并将其记录在我们的通道上的简单代码是:
import timewhile(True):
getSensorData()
tPayload = "field1=" + str(humLab)+ "&field2=" + str(tempExt)+ "&field3=" + str(tempLab)+ "&field4=" + str(presSL)+ "&field5=" + str(altLab) + "&field6=" + str(presAbs)+ "&field7=" + str(UV_mV) + "&field8=" + str(UV_index) try:
publish.single(topic, payload=tPayload, hostname=mqttHost, port=tPort, tls=tTLS, transport=tTransport)
save_log()
except (KeyboardInterrupt):
break except:
print ("[INFO] Failure in sending data")
time.sleep(60)
寻找你的 ThingSpeak 频道页面,你会观察到数据会被持续加载到每个字段。该通道将自动“记录”这些数据以供将来分析。数据的完整 CSV 文件也可以从该网站下载。
我们包含了一个函数(save_Log())来将数据记录到本地的 CSV 文件中:
def save_log():
with open("/home/pi/rpi_weather_station.csv", "a") as log:
log.write("{},{},{},{},{},{},{},{},{}\n".format(timeString, humLab, tempExt, tempLab, presSL, altLab, presAbs, UV_mV, UV_index))
log.close()
用于开发的完整 Jupyter 笔记本可以在这里找到:Rpi _ Weather _ station . ipynb。
14.things view—ThingSpeak 应用程序

记录的数据可以直接在本地保存的 CSV 文件上查看,也可以在 ThingSpeak.com 网站或通过 APP 查看,例如 ThingsView !
ThingView 是由 CINETICA 开发的一个应用程序,它使你能够以一种简单的方式可视化你的 ThingSpeak 频道。只需输入频道 ID,您就可以开始了。
对于公共频道,应用程序将尊重您的 windows 设置:颜色,时间刻度,图表类型和结果的数量。当前版本支持折线图和柱形图,样条图显示为折线图。
对于私有通道,数据将使用默认设置显示,因为无法仅使用 API 键读取私有窗口设置。
ThingView 应用程序可以为 ANDROID 和 IPHONE 下载。
15.测量风速和风向

这个气象站教程是我和我的朋友 Mauricio Pinto 共同开发的项目的一部分。在这里,我们学习了如何捕捉与天气相关的几个重要数据,如空气温度和湿度、压力和紫外线。添加到气象站的另一个非常重要的数据是风速和风向。
毛里西奥做得很好,写了一个非常详细的教程,解释了如何构建一个风速计,主要是用回收材料。你可以在这个 2 部分教程中找到他的项目:
第二部分——使用 Arduino IDE 实现 Esp8266 Nodemcu 并传输到 ThingSpeak 的草图
正如 Mauricio 在他的教程中解释的那样,风速计是一种能够测量风速及其方向的设备。利用霍尔效应传感器,他能够计算出杯子在一段时间内旋转了多少圈,这是风的强度,与轴的旋转速度成正比。通过一些简单的物理方程,他可以确定当时的风速。风向是通过带有钕磁铁和簧片开关的挡风玻璃测量的。
在这里,你可以看到安装在他房子里的风速计(距离我的气象站大约 400 米):
风速和风向也被发送到 Thingspeak.com。

16.结论
一如既往,我希望这个项目可以帮助其他人找到进入令人兴奋的电子和数据科学世界的方法!
详情和最终代码,请访问我的 GitHub 仓库: RPi-Weather-Station
更多项目,请访问我的博客:【MJRoBot.org
来自世界南部的 Saludos!
我的下一篇文章再见!
谢谢你,
马塞洛
如何选择数据科学项目,并最大限度地激发您完成项目的动力
我经常被问到这个问题:我如何挑选一个好的数据科学项目?这里是我的方法,提出一个想法候选名单,计划出具体的步骤,最重要的是,执行项目完成。

Source: Unsplash
本文将带您了解以下内容:
- 想出一个想法的候选名单
- 执行计划
想出一个想法的候选名单
你的“为什么”
首先,我们先来考察一下,你当初为什么有兴趣做一个数据科学方面的项目。
对自己诚实!在执行项目时,理解你的动机会产生最大的不同。当你对自己不诚实时,如果你不能保持动力,想法很容易被放弃。
原因可能是:
- 强迫自己学习[x]编程语言或技术
- 我想改善我的投资组合(学校或工作申请)
- 每个人都在做…为什么我不能?
我希望你真诚地思考你的理由。当我回顾我成功完成的项目和没有完成的项目时,为什么和项目对我的意义,使产生了最大的不同。与编程难度、对技术栈的不熟悉等等相比,这是项目完成的更好预测。
现在我希望你已经和自己谈过了,记下你做数据科学项目的原因。没有对错。可能是“我只是想在同学面前看起来酷一点”。你不必告诉我;你不用告诉任何人,只要对自己诚实。
你的技能清单
我希望你写下的第二件事是:你想通过这个副业项目学习和展示哪些技能?
你可以从写下你的技能愿望清单开始——随意写下多项,只要你能清楚地表达你想学什么,以及结果是什么。因为这是一个愿望清单——我鼓励你甚至写下你认为目前远不可及的事情!(我会列出我在亚马逊上买不起的东西,一直都是……)
一个例子:
- [x]语言,[y]包:比如“我想学 Flask (Python web framework)”
- 对结果的具体设想:“我想证明我可以制作一个 web 应用程序,它可以接受用户的输入,并向用户输出一些东西”(我们可以稍后细化细节,现在专注于大脑转储)
现在,你应该有一个愿望清单,列出你想学习的技能,并对结果有一些想法。这里有一个例子,当我刚开始从事数据科学时,我的愿望清单可能是这样的:
- 我想学习如何做我在 Stata(一个本科必修的统计软件)中做的所有事情,但是是用 Python
- 结果:复制我在 Stata 中完成的任务(线性和逻辑回归),但是只使用 Python
您可能会注意到,这个例子并没有特别给出 Python 包的名称(例如 NumPy、Pandas 等。).这是因为当时我刚刚起步,不太了解 Python 在数据科学方面的具体内容。这正是这个兼职项目的目的——学习细节并能够做到这一点!这也可能是你的情况——也许你想构建一个 web 应用程序,但不知道使用什么框架或技术…
这将我们带到下一个主要部分,创建您的执行计划。
执行计划
完善你的愿望清单
现在,最困难的部分来了。对我来说,现在有太多的东西我想学!
我试图想出一种方法,将我想学的所有技能融合到一个项目中。"我如何同时做一些涉及张量流,烧瓶和[x],[y],[z]的事情?"

经过一番试错,我发现这是个好东西!但是我建议你试着限制它,一旦它发展到一定程度,就会给项目带来严重的不便。例如,我想在一个项目创意中加入学习围棋(通常被称为 Golang)的想法。经过更多的研究,它似乎不能与我想学的其他技能“配合得很好”。虽然创造性地让多个部分协同工作本身可能是一个有趣且具有挑战性的兼职项目,但它不在我的技能清单上。
如果您曾经遇到范围蔓延(例如,“我想在这个项目中再多学一样东西!),我建议根据你的技能清单上的最高优先级,以及对你能负担得起的时间框架内的副业项目的研究,来缩小范围。从小处着手——这个副业不会成为你一生的工作或任何事情。(所以才叫一个边项目!)它的目的是帮助你去更高更远的地方。
设计项目
还记得第一节中的问题“我为什么要做这个数据科学方面的项目”吗?
在这里,我真的想提出一个一刀切的解决方案,你不必接受,但听我说…
不管你的真正原因是为了看起来很酷,炫耀,“这样我的 GitHub 就不是空的”,学习[x],还是其他什么——我建议你用一个一个标准来设计这个兼职项目。
Do something that is meaningful to you.
是的,我知道这很俗气,但我发现这是我完成项目与否的最大区别。
当我开发视频游戏时,我可能会想“什么最流行;卖什么?”并尝试制作多人对战 royale 第一人称射击游戏。(大众喜爱的各种类型的混搭。)
好吧,如果我只考虑了诸如流行语(或“就业能力”)之类的外部因素,我可能会一直在做一个对我来说如此普通和无聊的兼职项目,我可能会很痛苦,并开始找借口停下来。但是如果你没有完成它,你将无法展示你的【技能清单】,你想学习它是因为【你做数据科学副业的理由】!
所以,我专注于设计我的项目的方式是:什么会让我有乐趣?什么对我有意义?
你很少会独自拥有一个项目,并拥有完全的控制权;珍惜它去做一些与众不同的事情!
随便做点傻事!做一些只有你和你的朋友能理解的事情!
我知道你现在可能有疑问:
- 如果这是我想给[招聘人员],[其他外部方]留下深刻印象的东西呢?可能他们不会关心我关心的【话题 x】——我不应该做我关于【话题 x】的副业!
- 如果展示我在做吴恩达深度学习课程第[m]周的作业[n]时的代码更安全,以显示我真的在 Coursera 上做过那门课程,会怎么样?
好吧,我不是说你不能做到以上几点,但我感觉项目越独特,一个【招聘人员】,【其他外部方】就越会记住它。作为一个看过很多简历、面试过很多应聘者的人,看起来像课程或作业的副业很难记住,因此不会让应聘者脱颖而出。
与此同时,那些真正看起来像激情项目的项目往往会让我脱颖而出,作为一名面试官,我喜欢问应聘者这些问题。
作为思考练习,我鼓励你问自己的另一个问题是:我会在会议上谈论这个吗?
当你这样想的时候,没有人会在会议上谈论他们在[Coursera 课程]中的作业[n],[第四年的 x 课程,其他 100 多人也这样做了]。当我想到会议演讲时,我通常会想到演讲者创造的独特产品,或者他们解决的独特问题,这对他们来说意味着什么。
现在,花些时间用这些镜头设计你的副业,关注结果:
- 当这个项目“完成”时,它会是什么样子?即定义项目的终点
请记住,所有这些都是可变的:一旦你开始这个项目,事情可能会发生变化,这没关系。关键是开始行动,而不是陷入规划的困境。
一旦你写下了一些细节,你就可以开始下一步了。

Source: Unsplash
迈出你的第一步
好吧!我们到了,计划的最后一步,这将帮助你在你的副业上迈出第一步!
概括地说,您已经准备好了前面章节中的以下组件:
你的技能清单
- 示例:Tensorflow、Keras、Flask…
你的副业预期成果设计
- 例如:一个 web 应用程序,它将接收用户上传的图像,通过图像识别神经网络(由您训练)输入图像,并输出结果(例如,图像中出现了视频游戏《英雄联盟》中的哪个角色?)给用户。
在这个阶段,我经常会遇到一些瘫痪——也许我会因为对技术栈不熟悉而感到沮丧或卡住。没关系,我想帮你避免这种情况。你的兼职项目可能是你第一次实现某项技能,这是最重要的,所以遇到一些困难把你推到舒适区之外是很自然的。
在这里,对我来说最有效的方法是分解问题。在上面的例子中,结果是两个项目合二为一:
- 训练神经网络对视频游戏《英雄联盟》中的角色进行分类
- 有一个 web 应用程序(有一个前端),可以以某种方式连接用户上传的图像,通过神经网络传递它,并获得结果
在这一点上,我通常从我觉得稍微容易的部分开始,在这种情况下是1.,并将其进一步分解成任务。
训练神经网络对视频游戏《英雄联盟》中的角色进行分类
- 收集训练图像
- 选择神经网络架构
- 建立训练神经网络的环境
然后,递归地将最容易的或顺序最早的步骤分解成更小的步骤:
采集训练图像
- 使用美丽的汤或 Scrapy 获得训练图像(从哪里?了解一下)
- 以适合神经网络输入的方式裁剪图像或调整图像大小
使用美汤或刺儿头获取训练图像
- 找个网站刮一下(谷歌图片搜索?)
- 写代码!但是我从来没有用过 Scrapy!
现在,这两个步骤看起来不像我们的大步骤那样令人生畏,“训练神经网络对视频游戏《英雄联盟》中的角色进行分类”。事实上,这两个步骤相当简单。第一步不需要编码,只需浏览一些图像托管网站,寻找对项目有用的东西。第二步可以从谷歌搜索开始,但在这一点上,很容易开始这个项目的实际步骤——即使有一个关于“如何使用 Scrapy”的堆栈溢出问题
你完成了一小步,太棒了!你刚刚开始你的副业!
接下来,你沿着树枝往上走,直到更大的步骤也完成。然后,你会慢慢看到你想象的结果变成现实。不仅如此,你还将学习和展示你的【技能组合愿望清单】,以及实现【你做数据科学兼职项目的理由】。
离别赠言
在我的兼职项目中,我曾多次陷入困境或失去动力。我从克服这些挑战中学到了很多,这篇文章是我根据自己的经验写的——帮助你制定行动计划,清楚地看到你的第一步!
如果您有任何问题或反馈,请随时联系我们。如果这个指南对你有帮助,我很想听听。
现在开始吧!
—最初发表于susanshu.com
如何在多种模式中选择
比较模型时要记住的关键概念

在之前的文章中,我们讨论了欠拟合和过拟合的概念,它们如何导致模型与可用数据不匹配,如何识别每个问题,以及如何识别与数据非常匹配的模型。这些概念可以帮助您避免重大失误,并生成合理准确地拟合数据的模型;然而,有令人难以置信的数量的模型符合这一描述。这意味着下一步,除了生成一个合适的模型之外,还要确定哪个模型最合适。
在确定模型与数据集的拟合程度时,将模型预测与数据集进行比较来计算统计值非常重要。这超出了这篇概念性文章的范围,但更多信息可以在从头开始的数据科学或数据科学家实用统计中找到。在本文中,我们将讨论开发、验证以及测试模型的过程。
什么是模型开发、验证和测试阶段,为什么它们是必要的?
这里要注意的基本问题是,你不能仅仅因为你开发的模型与训练数据吻合,就相信它。这是因为一个简单的原因:您强制模型很好地适应了训练数据。如果在创建一个模型后,统计计算显示它与数据匹配良好,这意味着可以使用数学方法来迫使模型与数据匹配良好。这并不意味着模型正在捕捉真正发生的趋势,或者模型能够预测其他情况。我在上一篇文章中的 overfit 模型的例子很好地突出了这一点。
这个问题的解决方案是模型验证。验证是使用模型来预测其他有数据的情况下的输出,并根据这些结果计算相同的统计度量的实践。请注意,这意味着您需要将数据集分成两个不同的数据文件。第一个是训练数据集,用于生成模型。第二个是验证数据集,用于对照未用于训练模型的数据来检查模型的准确性。
一般来说,一个项目中会创建多个模型。如果创建了许多模型,则将最适合训练数据的模型与验证数据进行比较。那么自然的选择是选择最符合验证数据的模型,然后继续前进。然而,这带来了另一个潜在的陷阱。类似于将模型与训练数据进行比较,仅仅因为模型最接近地匹配验证数据仍然不意味着它匹配现实。虽然它在这个测试中表现最好,但它仍然可能是错误的。
最后一步,也是该问题的解决方案,是将在验证阶段表现最佳的模型与第三组数据(测试数据)进行比较。这个测试数据也是来自原始数据源的数据的子集。它只包含模型开发或验证中未使用的点。只有当模型与测试数据进行比较,并且统计计算显示出令人满意的匹配时,才认为模型可以使用。
这整个过程是如何分解的?
这个过程分为以下七个步骤。
- 创建开发、验证和测试数据集:最初你有一个单一的大型数据集。正如上一节所讨论的,您需要将它分成三个独立的数据集,每个数据集只用于项目的一个阶段。在创建每个数据集时,确保它们包含位于每个变量的高/低极限值和中间值的混合数据点。这确保了该模型能够并且必须在光谱的所有范围内都是准确的。此外,确保大多数数据都包含在训练数据集中。模型只能和用来创建它的数据集一样精确,更多的数据给了它更多的机会。
- 使用训练数据集开发您的模型:将数据集输入到您的模型开发脚本中,并使用它来开发您选择的模型。根据可用的数据源和需要回答的问题,您可以开发几种不同的模型。关于模型类型的更多信息可以在从头开始的数据科学中找到。在这个阶段,您可能想要创建几个不同的模型。它们可以是不同结构的模型,或者是不同阶的几个回归模型。生成您认为可能表现良好的任何模型。
- 计算识别模型开发性能的统计值:一旦模型被开发出来,你需要将它们与用来创建它们的训练数据进行比较。性能较高的模型比性能较低的模型更适合数据。为此,您需要计算为此目的设计的统计值。例如,检查回归模型性能的一种常用方法是计算 r 值。根据这些统计计算,将模型与训练数据集进行比较,确定表现最佳的模型。
- 计算验证数据集中数据点的模型结果:在这一步中,您使用验证数据集中的输入来驱动模型,为这些数据点生成预测。一旦完成,您就有了真实值(来自数据集)和预测值(来自模型)。这允许您将不同模型的性能与验证数据集中的数据进行比较。
- 计算统计值,将模型结果与验证数据进行比较:现在您已经有了验证数据集中每个实例的数据值和模型预测,您可以计算与将模型预测与验证数据集进行比较之前相同的统计值。这是流程的关键部分。第一次统计计算确定了模型与被迫拟合的数据集的拟合程度。在这种情况下,您要确保模型能够匹配一个单独的数据集,一个对模型开发没有影响的数据集。对每个型号完成您选择的统计计算,然后选择性能最高的型号。
- 计算测试数据集中数据点的模型结果:使用测试数据集的输入来驱动模型,在这些点上生成模型的预测输出。仅使用验证阶段性能最高的模型来执行此任务。完成后,您将获得每个输入的输出的模型预测值和实际值。
- 计算统计值,将模型结果与测试数据进行比较:最后一次,执行您选择的统计计算,将模型预测与数据集进行比较。在这种情况下,你只有一个模型,所以你不是在寻找最合适的。相反,您正在检查以确保您的模型与测试数据集足够接近,令人满意。
一旦你开发了一个令人满意地匹配测试数据集的模型,你就可以开始生成预测了。但是,不要认为这意味着您已经完全完成了模型开发;很有可能有一天你会决定需要根据新的可用数据集来调整你的模型。
包装它
本文中讨论的基本挑战是,模型在特定数据集上的性能并不能保证它在其他数据集上也能表现良好。强制一个数学模型匹配一个给定的数据集只能确保它匹配那个特定的数据集,并不能说明它的预测能力。
这个挑战可以通过使用不同数据集的开发、验证和测试来克服。第一步是根据训练数据集开发模型,并确保模型可以在最简单的情况下准确预测结果。第二步是将表现最好的模型与第二个数据集(验证数据集)进行比较。验证数据集应包含跨越训练数据集中包含的值范围的点,但不应包含任何相同的点。这第二次检查对确保模型具有合理的预测能力大有帮助。最后一步是选择对验证数据集表现最好的模型,并将其与第三个数据集(测试数据集)进行比较。如果模型在数据集上表现良好,那么它可以合理地用于创建预测。
如何选择最好的开源软件

Photo by Pankaj Patel on Unsplash
在阅读了 Ted Malaska 和 Jonathan Seidman 所著的 O'Reilly 一书“ 架构数据解决方案 的基础”之后,我反思了我过去是如何选择软件/工具/解决方案的,以及我今后应该如何选择它们。
作为一名生物信息学家,你需要能够快速辨别一个出版物/工具是否真的是一个重大进步,或者只是稍微好一点。我不只是在谈论最新的单细胞 RNA-seq 技术或另一种文件格式,而是针对你遇到的每一个问题。无论是数据可视化工具、展示工具、分布式存储系统、等等。
这不仅仅是关于工具有多有用,还取决于文档的质量,安装有多简单,它在开源生命周期中的位置等等。

Xkcd 很有趣,但与之竞争的标准并不有趣。不相信我?看看有多少管道工具就知道了!
面对如此多的选择,如何选择适合自己需求的解决方案呢?
为什么要开源?
我过去曾使用过一些授权软件解决方案;比如 BLAST2GO ( plug:用 Camille Scott 的 dammit 代替!)、 Matlab 以及一款名为 Autopano Giga (现已不存在)的图像拼接软件。我最大的挫折之一是学习这些工具只是为了以后改变角色,并且不再使用它们。作为渔业和海洋部的顾问,Matlab 的高昂成本促使我开始学习另一种高级编程语言 R. FWIW:
“[Matlab]他们在许多情况下混淆源代码,这意味着 bug 更难被发现,也不可能在不冒被起诉的风险的情况下被 T2 编辑。此外,将 Matlab 用于科学会导致为我们的代码付费。从定义上来说,我们正在封闭我们的计算科学。”—摘自 我讨厌 Matlab:一个 IDE、一种语言、一种心态如何伤害
大多数公司避开第三方解决方案,或者将他们的产品构建为专有和开源的混合体,以保持较低的成本。例如,亚马逊网络服务(AWS)提供收费的简单存储服务(亚马逊 S3),但它是建立在开源软件如 Apache Hadoop 之上的。我不是说不使用 AWS(或任何其他云提供商),因为有时你会被迫使用来;我实际上在 Docker 的一个项目中使用了 AWS(珊瑚物种的转录组组装)。目前,我正在处理必须在现场上锁保存的敏感信息,因此使用了替代解决方案。
大多数较新的大数据平台和成功的开源项目在经历外部孵化阶段之前,最初几年都是作为公司或大学的内部项目开始的。例如:
- LinkedIn—“阿帕奇卡夫卡”
- 加州大学伯克利分校—“阿帕奇火花”
- cloud era—“黑斑羚
- 雅虎!—“Apache Hadoop”
- 谷歌— " Kubernetes"
- 脸书——“阿帕奇蜂房”
选择由可靠的赞助商支持的开源项目是有好处的,这些赞助商拥有良好的声誉、可靠的开发人员以及赞助成功项目的记录。您可以相当自信地认为,这些项目拥有坚实的代码基础、优秀的文档、在会议上获得的会话时间,以及相当大的公众认可度(通过围绕它的博客帖子和文章)。
当考虑开源解决方案时,衡量它们在开源生命周期中的位置也很重要。根据马拉斯卡和塞德曼的说法,基于石榴石炒作周期,项目生命周期有九个(潜在)阶段;然而,我认为这里只讨论几个相关的问题:
你应该选择哪个周期?

Photo by @Matthew_T_Rader on Unsplash
不要相信炒作
周期的这个阶段被称为“治愈癌症”阶段。这个阶段的宣传对于吸引提交者和贡献者是很重要的,但是除非你想在很大程度上提供帮助,否则你应该避开。除非你想走在最前沿(风险承受能力),或者扮演积极的贡献者角色,否则最好等 6-12 个月再尝试任何新技术。通过让其他人先碰壁,你会遇到更少的错误,并获得更好的文档和博客帖子。
失信不是谎言
在"治愈癌症"阶段之后是失信阶段。此时,人们正在使用项目,并发现问题或限制。例如,一个解决方案可能无法很好地与其他现有系统集成,或者可能存在可伸缩性问题。在这个阶段,您应该以谨慎乐观的态度对待任何开源项目。
尽可能寻求可靠的解决方案
处于硬化或企业阶段的项目已经成为成熟技术。承诺的数量将标志着一个项目的投资水平。提交的类型讲述了一个故事,告诉作者代码的发展方向,通过表明对项目不同特性的兴趣来揭示他们想要做什么。到目前为止,最初的兴奋已经消退,对稳定性的需求超过了对新功能的需求。最初的开发团队可能正在开发其他项目,因为它已经开发了一个可靠的社区——这通常是项目成功的好迹象。
很明显,最近的活动表明这个项目是活跃的,并且得到了维护。请记住,Github 上有许多已经死亡和废弃的项目。也就是说,活动并不总是需要非常近!一位多产的“摇滚明星 Dev”这样说:
上下文切换是很昂贵的,所以如果我同时处理许多包,我永远也不会完成任何事情。相反,在任何时候,我的大多数包都处于休耕状态,不断积累新特性的问题和想法。一旦积累到一定的数量,我会花几天的时间来包装。— 哈雷·威克姆
最终,项目进入了衰落的 T21 阶段,没有人愿意采纳或贡献一个死去的项目。
我能信任你吗?

Photo by Purnomo Capunk on Unsplash
我主要使用 R,所以让我花点时间谈谈项目托管在哪里。代码通常托管在 Github、 ROpenSci 、 Bioconductor 或 CRAN 上。全面的 R 档案网络 (CRAN) 是 R 包的主要储存库。
“作为 R 用户,我们被惯坏了。在 R 历史的早期,Kurt Hornik 和 Friedrich Leisch 构建了对 R 中的包的支持,并开始了全面的 R 存档网络(CRAN)。R 和 CRAN 有一个奇妙的运行。大约二十年后,我们看到超过 12,000 个软件包可以(通常)绝对轻松地安装,没有任何意外。没有任何其他(相关的)开源语言具有类似的严谨性和质量。”—摘自 Dirk Eddelbuettel
在 CRAN 上,几乎任何类型的包都是受欢迎的(只要符合严格的政策),并且包每天都被测试(在多个系统上)。 rOpenSci 是 CRAN 的完美对立面。众所周知,曲柄不透明、不一致且冷漠。它不能处理起重机自动化的数量,但在质量方面推销自己。
对于生物信息学领域来说,生物导体是一个包的最终归宿。只存在于 Github 上的项目应该被更加谨慎地看待,因为它们没有清单或同行评审。
让我们来谈谈依赖性(一个沉重的话题——没有双关语的意思)
安装依赖项太糟糕了!你有多长时间安装了一个包却得到了一船货?您应该尝试并避免包含许多(变化的)包的包,因为这将禁止确定您的工作是否正确(从而确保可再现性),因为依赖关系很难管理风险。
tinyverse 的支持者倾向于远离臃肿的依赖,没有人想在地狱里度过时光!
如果您是开发人员,请记住:
"并不是所有的依赖都是相同的……一些流行的软件包[有]不稳定的 API(突破性变化的历史)和高历史错误率(复杂的历史和增加功能而不是修复东西的历史)。
您还可以为您的 repo 添加一个标记,显示您的包依赖于的依赖项的数量
透明度是好的

Photo by Aleks Dahlberg on Unsplash
在 Github 上查看项目时,你应该寻找有许多明星、观察者、分叉、贡献者、等的人/包。这些社区支持的可见线索表明社区关心一个人、一个项目或一项行动,并且许多其他人将从中受益。**
请记住,提交、发布和拉动请求(PRs)的数量可能是对项目投资和承诺的信号。问题和减贫战略是否得到处理?后者实际上是一个提供的代码,它被忽略,而不是被接受、拒绝或评论。
通过遵循代码上的操作,您可以确定谁创建了项目,在不同的版本中发生了什么,并推断出项目的结构和合作者角色(谁对系统的哪些部分有专长)。链接的提交和发布传达了代码更改背后的原因。
你也可以通过查看聚会、和会议的数量(以及他们的出席水平),或者电子邮件列表、用户组、社区论坛等来衡量社区兴趣。
谷歌趋势也可以很好地衡量人们对项目或技术的兴趣程度。

Using metrics to track the decline of SPSS
要寻找的东西

Photo by Arnaud Papa on Unsplash
- 易于安装
- 易于运行
- 是否有问题和公关提出
所有者是否在照顾他们(修复 bug、帮助用户、添加功能)?还是被抛弃了?
它是否列出了硬件要求(RAM 和磁盘大小)、示例命令、玩具数据、示例输出、屏幕截图/记录
要查找的其他内容,请参见此处的和此处的和。
基准标记
如果您是一名软件开发人员,并且正在考虑整合众多竞争技术中的一种,那么您可以使用您的用例和数据来执行内部基准测试。
如果您使用 R,基准可以提供不同的放大级别。对于宏观分析(当计算更密集时),你应该使用[rbenchmark](https://cran.r-project.org/web/packages/rbenchmark/index.html)包。对于微观时间比较(例如纳秒时间)使用[microbenchmark](https://cran.r-project.org/web/packages/microbenchmark/index.html)包
有时其他联合体已经为你做了基准测试(例如【组装】 )。尽管如此,人们应该意识到试图进行不公平比较的隐藏的或有动机的偏见(一种工具明显具有优势的用例)。也要理解测试人员本可以诚实地尝试一个公平的测试,但是却产生了导致无效结果的误解。因此,重要的是执行你自己的内部基准,并将其他基准保持在可重复性和验证的开放标准上。
最后的话
最终选择一个软件解决方案归结于你的项目的需求(时间表,预算,等等),你有多愿意走在前沿(风险承受能力),以及有能力的团队成员基于他们的技能水平(内部技能集)有多能够掌握这些解决方案。然后,在完全提交之前测试解决方案。这项工作可以交给团队中的原型角色;喜欢试验/研究新软件的人。
如何选择合适的数据库
我们将讨论可用的数据库类型以及不同项目类型的最佳实践。
无论你是一个有经验的软件工程师还是一个正在做大学项目的学生,在某些时候你都需要为你的项目选择一个数据库。
如果您以前使用过 DB,您可能会说“我会选择 X,这是我熟悉并使用过的 DB”,如果性能不是您系统的重要需求,这完全没问题。否则,当项目增长时,选择错误的数据库可能会成为一个障碍,有时很难解决。即使您正在从事一个成熟的项目,并且暂时使用了特定的数据库,了解它的限制并确定何时应该向堆栈中添加另一种类型的数据库也是很重要的(组合几个数据库是很常见的)。
了解不同数据库及其属性的另一个原因是,这是求职面试中很常见的问题!
在本帖中,我们将回顾两种主要类型的数据库:
·关系数据库(基于 SQL)。
·NoSQL 数据库。
我们将讨论不同类型的 NoSQL DBs 以及何时使用每种 DBs。
最后,讨论关系数据库与 NoSQL 数据库的优缺点。
这篇文章将不包括为每种类型的数据库提供的不同产品之间的比较(例如 MySQL 与 MS SQL Server)。
TL;DR:如果你正在寻找一个快速的小抄,跳到文章的末尾。

关系数据库(基于 SQL)
这个 DB 由一组相互连接的表(如 CSV 表)组成。表中的每一行代表一条记录。
为什么叫关系型?该数据库中存在哪些“关系”?
假设您有一个学生信息表和一个课程成绩表(课程、年级、学号),每个成绩行将关联到一个学生记录。
参见下图,其中“学生 ID”列中的值通过“ID”列的值指向“学生”表中的行。
所有关系数据库都使用类似 SQL 的语言进行查询,这种语言是常用的,并且本身支持连接操作。
它们允许对列进行索引,以便基于这些列进行更快的查询。
由于其结构化的本质,关系数据库的模式是在插入数据之前决定的。
常见的关系数据库: MySQL、PostgreSQL、Oracle、MS SQL Server

NoSQL 星展银行
在关系数据库中,一切都是按照行和列来组织的,而在 NoSQL 数据库中,没有一个通用的结构化模式来管理所有的记录。大多数 NoSQL 数据库包含 JSON 记录,不同的记录可以包含不同的字段。
这一系列数据库实际上应该被称为“非主要 SQL”——因为许多 NoSQL 数据库支持使用 SQL 的查询,但是使用 SQL 并不是它们的最佳实践。
有 4 种主要类型的 NoSQL 数据库:
1.面向文档的数据库
这个数据库的基本单位是文档。每个文档都是一个 JSON,不同文档之间的模式可以不同,并且包含不同的字段。
文档数据库允许对文档中的一些字段进行索引,以允许基于这些字段进行更快的查询(这迫使所有文档都具有该字段)。
什么时候该用?
数据分析——由于不同的记录彼此不相关(逻辑和结构方面)该数据库支持并行计算。
这使您可以轻松地对我们的数据进行大数据分析。
常见的基于文档的数据库 : MongoDB 、 CouchDB、DocumentDB 。

2.柱状 DBs
这个数据库的原子单位是表中的一列,这意味着数据是逐列存储的。这使得基于列的查询非常高效,而且由于每一列上的数据都非常相似,因此可以更好地压缩数据。
什么时候该用? 当您倾向于查询数据中列的子集时(不需要每次都是相同的子集!).
columnard DB 执行这种查询的速度非常快,因为它只需要读取这些特定的列(而基于行的 DB 必须读取整个数据)。
- 这在数据科学中很常见,每一列代表一个特征。作为一名数据科学家,我经常用特征的子集来训练我的模型,并倾向于检查特征和分数之间的关系(相关性、方差、显著性)。
- 这在日志中也很常见——我们经常在日志数据库中存储更多的字段,但是在每个查询中只使用了很少的字段。
常用列 DB 数据库: Cassandra。

Column vs. raw based DBs.
3.键值数据库
该查询只是基于键的—您需要一个键并获得它的值。
不支持跨不同记录值的查询,如“select all records where city = = New York”
该数据库中的一个有用功能是 TTL 字段(生存时间),该字段可以针对每个记录进行不同的设置,并声明何时应从数据库中删除。
优点— 速度非常快。首先是因为使用了唯一的键,其次是因为大多数键值数据库将数据存储在允许快速访问的内存(RAM)中。
缺点— 您需要定义惟一的键,这些键是很好的标识符,并且是根据您在查询时知道的数据构建的。通常比其他种类的数据库更贵(因为在内存上运行)。
我应该什么时候使用它?
主要用于缓存,因为它非常快,不需要复杂的查询,而且 TTL 功能对缓存非常有用。
它也可以用于其他任何需要快速查询并符合键值格式的数据。
常用键值数据库: Redis,Memcached

4.图形数据库
图形数据库包含表示实体的节点和表示实体之间关系的边。
我应该什么时候使用它?
当你的数据是一个图形时,就像知识图形和社会网络。
常用图数据库: Neo4j,InfiniteGraph

关系数据库与文档数据库
现在你可能已经知道了,没有正确的答案,也没有“一个数据库可以统治所有的数据库”。
最常见的“常规”数据库是关系数据库和文档数据库,因此我们将对它们进行比较。
关系优势
- 它有一个简单的结构,可以匹配程序中通常拥有的大多数类型的数据。
- 它使用了 SQL ,这是常用的,并且天生支持 JOIN 操作。
- 允许快速数据更新。所有的数据库都保存在一台机器上,记录之间的关系被用作指针,这意味着您可以更新一个记录,所有相关的记录都会立即更新。
- 关系数据库也支持原子事务。
什么是原子事务:假设我想从 Alice 转账 X 美元给 Bob。我想执行 3 个操作:将 Alice 的余额减少 X,将 Bob 的余额增加 X,并记录交易。我想把这些行为作为一个原子单位来对待——要么所有的行为都会发生,要么什么都不会发生。
关系—缺点
- 因为每个查询都是在一个表上完成的,所以查询执行的时间取决于表的大小。这是一个很大的限制,它要求我们保持表相对较小,并对数据库进行优化,以便进行伸缩。
- 在关系数据库中,扩展是通过向保存数据库的机器添加更多的计算能力来完成的,这种方法被称为'垂直扩展'。
为什么是劣势?因为机器能够提供的计算能力是有限的,而且向机器添加资源可能需要一些停机时间。 - 关系型不支持基于 OOP 的对象,即使表示简单的列表也非常复杂。
文档数据库—优势
- 它允许你用不同的结构来保存物体。
- 你可以使用优秀的 JSON 来表示几乎所有的数据结构,包括基于面向对象的对象、列表和字典。
- 尽管 NoSQL 本质上是无模式化的,但它通常支持模式 验证,这意味着您可以将集合模式化,模式不会像表那样简单,它将是一个具有特定字段的 JSON 模式。
- 查询 NoSQL 非常快,每个记录都是独立的,因此查询时间与数据库的大小无关,支持并行性。
- 在 NoSQL,扩展数据库是通过添加更多的机器并在它们之间分配你的数据来完成的,这种方法被称为‘水平扩展’。这允许我们在需要时自动向数据库添加资源,而不会导致任何停机。
文档数据库—缺点
- 更新数据在文档数据库中是一个缓慢的过程,因为数据可以在机器之间划分,并且可以复制。
- 原子事务本身不受支持。您可以通过使用验证和恢复机制在代码中自己添加它,但是由于记录是在机器之间划分的,所以它不能是一个原子过程,并且可能会出现争用情况。

备忘单:
- 对于缓存 —使用一个键值数据库。
- 对于图形- 之类的数据-使用图形数据库。
- 如果您倾向于查询列 /features 的子集,请使用列数据库。****
- 对于所有其他用例,关系数据库或文档数据库。
如何在高维空间中聚类
生命科学的数理统计和机器学习
自动检测集群数量的方法

这是 生命科学的数理统计与机器学习 栏目的第三篇文章。之前,我们强调了scRNAseq是有前途的大数据资源,讨论了 tSNE 是 scrna seq 的中心降维技术,并学习了如何调优 tSNE 的超参数。tSNE 应用于 scRNAseq 数据后的下一步是进行聚类分析,以检测细胞群之间的边界。
然而,聚类同时受到算法的限制和 维数灾难 的影响,这经常导致 tSNE 图的视觉解释和聚类分析输出之间的矛盾。在本文中,我提出了一种自动化的方法,在 scRNAseq 数据分析的维度缩减和聚类之间达成一致。****
聚类分析的假象
对 scRNAseq 进行聚类的一个问题是,我们在 tSNE 图中看到的与聚类分析报告的在聚类数量和聚类的单元分配方面存在差异。例如,我们在下图中清楚地观察到三个集群,甚至可以手动绘制集群之间的边界。然而,运行聚类算法可能会导致诸如错误的聚类数或错误的单元分配给聚类之类的假象,即当一个均匀的聚类碰巧被算法分割成多个块时。****

Results of clustering contradict our visual interpretation, image source
此外,由于聚类算法缺乏鲁棒性,试图复制科学论文的结果可能会令人困惑。例如,使用来自 Kolodziejczyk 等人的数据,细胞干细胞 2015 、八个集群在 tSNE 图中可见,然而本文中使用的聚类算法似乎只检测到三个集群。

Contradiction between tSNE (left) and clustering (right) from Kolodziejczyk et al., Cell Stem Cell 2015
降维和聚类之间的矛盾具有双重性。一方面,由于维数灾难,在高维 scRNAseq 空间中定义数据点之间的距离是出了名的困难;另一方面,聚类算法通常使用理想化的假设,而这些假设对于现实世界的数据来说并不成立。
高维空间中的欧氏距离突变
高维数学是一个活跃的研究领域,我将为这个主题专门写一篇文章。高维空间中会出现很多怪异的现象。其中之一是数据点和坐标系原点之间的距离随着维数 d 的平方根增长。这可以被视为数据点耗尽中心,并集中在 n 维球的壳中。

Data points occupy the surface and deplete the center of the n-ball in high dimensions, image source
因此,数据点之间的平均距离发散并失去其意义,进而导致欧几里德距离的发散,欧几里德距离是用于聚类的最常见距离。曼哈顿距离对于 scRNAseq 来说是更好的选择,但是它在高维度上也没有完全的帮助。****
聚类方法的假设和限制
尽管维数灾难是 scRNAseq 聚类分析的主要障碍,但由于其内部假设和限制,许多聚类算法即使在低维中也可能表现不佳。所有的聚类方法大致可以分为四组:****
- 分层聚类
- 基于质心的聚类
- 基于图的聚类
- 基于密度的聚类
Python 库 Scikit-learn 提供了一组聚类方法,并提供了一个出色的概述,强调了它们的优缺点:

Clustering methods overview at scikit-learn Python library web-page
分层(凝聚)聚类对数据中的 噪声过于敏感。基于质心的聚类(K-means,高斯混合模型)只能处理具有球形或椭球形对称性的聚类。****
基于图的聚类(Spectral,SNN-克里格,修拉)对于高维数据来说可能是最健壮的,因为它使用了图上的距离,例如共享邻居的数量,与欧氏距离相比,这在高维数据中更有意义。****

Graph-based clustering uses distance on a graph: A and F have 3 shared neighbors, image source
然而,为了构建图形,这种方法仍然** 使用欧几里德距离。此外,集群的数量必须通过“分辨率”超参数隐式指定先验。改变超参数可以容易地导致更少或更多的聚类,这在某种程度上是任意的,因此非常不令人满意,因为没有明显的方法来定义用于自动调整超参数的目标函数。**
在所有聚类算法中,只有基于密度的算法(Mean-Shift、DBSCAN、OPTICS、HDBSCAN)允许聚类,而无需指定聚类数。这些算法通过向高密度点移动的滑动窗口来工作,即它们发现存在许多密集区域。

DBSCAN clustering finds dense regions in the data, image source
此外,这些算法与聚类形状无关,并且可以捕获任何拓扑结构的 scRNAseq 数据。下面我将展示如何通过最小化一个目标函数来调整算法的超参数。
如何调整 HDBSCAN 的超参数
聚类是一个无监督的学习问题,这意味着我们不知道基本事实(聚类的数量),并且不能使用交叉验证来优化算法的超参数。然而,有一种方法可以自动优化 HDBSCAN 的超参数。
HDBSCAN 是一种强大的基于密度的聚类算法,它 1)与聚类的形状无关,2)不需要指定聚类的数目,3)对不同密度的聚类具有鲁棒性。此外,HBDSCAN 非常有吸引力,因为它只有一个超参数 minPts ,这是一个聚类中的最小点数。对于大型数据集来说,它的速度相对较快,检测外围小区,并为每个小区报告一个分配给一个集群的概率。分配到一个簇的概率低的单元部分可以用作优化 minPts 的目标函数,min pts 进而给出最优的簇数。
下面,我将继续使用癌症相关成纤维细胞(CAFs) 从以前的帖子中,我们发现了最佳的困惑( optPerp )和主成分数( optPC )。现在,我们将针对不同最小规模的集群,即范围从 3 到 N_pt=50 的 minPts ,对 tSNE 维数缩减运行 HDBSCAN。对于每个 minPts,我们将分数函数计算为具有低置信度(概率< 5%)分配给聚类的细胞的分数,通过分数函数的最小化,我们希望减少未分配的数据点的数量。由于内部随机性,tSNE 从运行到运行是变化的,因此为了稳健性,我们重复聚类 N_iter=50 次,并对结果进行平均。绘制分数函数与 minPts 的关系揭示了某个最小聚类大小 minPts 的明确最小值。

现在,在我们为我们的数据集 minPts 找到簇的最佳最小大小后,我们将使用该值在 tSNE 上运行最终的 HDBSCAN,这将为我们提供簇的数量、分配给簇的单元,以及不能确定分配给任何簇的单元,即外围单元。与其他算法相比,后者是一个优势,也是基于密度的聚类的一个特点,但是这里为了简单起见,我使用 KNN 分类器将外围单元分类到它们最近的邻居聚类中。注意,tSNE 运行 N_tsne=50 次,最小 Kullback-Leibler 散度图被选为最终图。下面,我展示了几个 scRNAseq 数据集。

Results of HDBSCAN clustering on tSNE
将 HDBSCAN 应用于各种 scRNAseq 数据集的结果看起来并不太差,因为这些图是通过只提供原始表达式矩阵而不手动调整聚类参数获得的。该函数的代码只接受一个原始的 scRNAseq 表达式矩阵,对所有超参数进行自动优化,并返回一个带有 HDBSCAN 聚类结果的 tSNE 图,可以在 my github 上找到。
基于 tSNE、PCs 和原始表达式矩阵的聚类
由于维数灾难,在原始表达式矩阵上运行聚类可能非常具有挑战性。因此,几乎总是建议在进行聚类分析之前进行任何类型的维数缩减。这里我比较了 9 种流行的聚类算法在 CAFs 数据集上的性能:HDBSCAN(如上所述), Kmeans ,高斯混合模型(GMM) ,层次聚类,谱聚类, SC3 , Bootstrap 一致性聚类,SNN-克里格和修拉。事实上,在原始 CAFs 表达矩阵上运行聚类算法带来了不令人满意的结果:

Clustering on raw expression matrix
虽然所有的算法都无法在原始表达式矩阵上进行聚类,但是只有 SC3 提供了令人惊讶的好的单元分配网络,它跨不同的算法和距离度量执行一致性聚类。现在,我们将把聚类算法应用于通过在先前帖子中置换表达式矩阵找到的重要 PCs** 。**

现在,SC3 的表现不太好,HDBSCAN 也不完美。相反,基于修拉图的社区检测和层次聚类似乎表现最好。最后,让我们将 9 种聚类算法应用于 scRNAseq 表达数据的 tSNE 降维表示:

尽管 tSNE 图是 2D 维数缩减,但是诸如 K-means、高斯混合模型(GMM)、分级聚类、谱聚类、Bootsrap 一致性聚类和 SC3 的许多算法都不能正确地将细胞分配到它们的聚类。HDBSCAN 和基于图的聚类方法(修拉和 SNN-克里格)似乎表现最好。然而,后者需要手动调整超参数,由于上述自动优化程序,HDBSCAN 不需要这样做。
摘要
在本文中,我们已经了解到,由于聚类方法的维数灾难和限制,对高维度 scRNAseq 数据进行聚类是具有挑战性的。令人沮丧的是,大多数聚类算法需要预先指定的个簇个,由于交叉验证不适用于聚类,这很难优化。然而,HDBSCAN 作为一种只有一个超参数的算法在这里很突出,该算法很容易通过最小化未分配单元的数量来优化。****
在下面的评论中让我知道生命科学中的哪些分析对你来说似乎特别神秘,我会在这个专栏中尽力解答。在媒体关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我,在我的 github 上查看这篇文章的代码。我计划写下一篇关于如何标准化你的数据,你可以在传统统计学打破的单一空间中结束,敬请关注。





浙公网安备 33010602011771号